29 #define G_LOG_DOMAIN "Dialogs.DMenu"
41 #include <gio/gunixinputstream.h>
42 #include <sys/types.h>
58 static cairo_surface_t *
dmenu_get_icon (
const Mode *sw,
unsigned int selected_line,
int height );
61 static inline unsigned int bitget ( uint32_t *array,
unsigned int index )
63 uint32_t bit = index % 32;
64 uint32_t val = array[index / 32];
65 return ( val >> bit ) & 1;
68 static inline void bittoggle ( uint32_t *array,
unsigned int index )
70 uint32_t bit = index % 32;
71 uint32_t *v = &array[index / 32];
108 static void async_close_callback ( GObject *source_object, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data )
110 g_input_stream_close_finish ( G_INPUT_STREAM ( source_object ), res, NULL );
111 g_debug (
"Closing data stream." );
116 gsize data_len = len;
127 while ( end < data + len && *end !=
'\0' ) {
130 if ( end != data + len ) {
131 data_len = end - data;
142 GDataInputStream *stream = (GDataInputStream *) source_object;
145 char *data = g_data_input_stream_read_upto_finish ( stream, res, &len, NULL );
146 if ( data != NULL ) {
148 g_data_input_stream_read_byte ( stream, NULL, NULL );
158 GError *error = NULL;
161 g_data_input_stream_read_byte ( stream, NULL, &error );
162 if ( error == NULL ) {
172 g_error_free ( error );
175 if ( !g_cancellable_is_cancelled ( pd->
cancel ) ) {
177 g_debug (
"Clearing overlay" );
183 static void async_read_cancel ( G_GNUC_UNUSED GCancellable *cancel, G_GNUC_UNUSED gpointer data )
185 g_debug (
"Cancelled the async read." );
190 while ( sync_pre_read-- ) {
193 if ( data == NULL ) {
210 if ( data == NULL ) {
229 return g_strdup ( input );
232 char ** splitted = g_regex_split_simple ( pd->
column_separator, input, G_REGEX_CASELESS, 00 );
234 for (; splitted && splitted[ns]; ns++ ) {
238 unsigned int index = (
unsigned int ) g_ascii_strtoull ( pd->
columns[i], NULL, 10 );
239 if ( index < ns && index > 0 ) {
240 if ( retv == NULL ) {
241 retv = g_strdup ( splitted[index - 1] );
244 gchar *t = g_strjoin (
"\t", retv, splitted[index - 1], NULL );
250 g_strfreev ( splitted );
251 return retv ? retv : g_strdup (
"" );
254 static inline unsigned int get_index (
unsigned int length,
int index )
259 if ( ( (
unsigned int) -index ) <= length ) {
260 return length + index;
266 static char *
get_display_data (
const Mode *data,
unsigned int index,
int *state, G_GNUC_UNUSED GList **list,
int get_entry )
304 g_cancellable_cancel ( pd->
cancel );
313 g_object_unref ( pd->
cancel );
339 .cfg_name_key =
"display-combi",
347 ._get_completion = NULL,
348 ._preprocess_input = NULL,
350 .private_data = NULL,
352 .display_name =
"dmenu"
411 int fd = STDIN_FILENO;
415 fd = open ( str, O_RDONLY );
417 char *msg = g_markup_printf_escaped (
"Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr, g_strerror ( errno ) );
426 if ( !( fd == STDIN_FILENO && isatty ( fd ) == 1 ) ) {
427 pd->
cancel = g_cancellable_new ();
429 pd->
input_stream = g_unix_input_stream_new ( fd, fd != STDIN_FILENO );
432 gchar *columns = NULL;
434 pd->
columns = g_strsplit ( columns,
",", 0 );
447 pango_parse_markup ( rmpd->
cmd_list[index].
entry, -1, 0, NULL, &esc, NULL, NULL );
456 for (
int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) {
460 if ( test == tokens[j]->invert && rmpd->
cmd_list[index].
meta ) {
480 return g_strdup ( pd->
message );
487 g_return_val_if_fail ( pd->
cmd_list != NULL, NULL );
501 if ( retv == FALSE ) {
504 else if ( retv >= 10 ) {
528 const char *cmd = input;
557 restart = (
find_arg (
"-only-match" ) >= 0 );
669 find_arg (
"-selected-row" ) >= 0 ) {
674 if ( pd->
cancel != NULL ) {
676 unsigned int pre_read = 25;
690 if (
find_arg (
"-multi-select" ) >= 0 ) {
694 if (
find_arg (
"-markup-rows" ) >= 0 ) {
699 if ( cmd_list_length == 0 ) {
707 if (
find_arg (
"-password" ) >= 0 ) {
715 if ( select != NULL ) {
718 for ( i = 0; i < cmd_list_length; i++ ) {
729 for ( i = 0; i < cmd_list_length; i++ ) {
742 if (
find_arg (
"-keep-right" ) >= 0 ) {
746 if ( async && ( pd->
cancel != NULL ) ) {
757 int is_term = isatty ( fileno ( stdout ) );
758 print_help_msg (
"-mesg",
"[string]",
"Print a small user message under the prompt (uses pango markup)", NULL, is_term );
759 print_help_msg (
"-p",
"[string]",
"Prompt to display left of entry field", NULL, is_term );
760 print_help_msg (
"-selected-row",
"[integer]",
"Select row", NULL, is_term );
761 print_help_msg (
"-format",
"[string]",
"Output format string",
"s", is_term );
762 print_help_msg (
"-u",
"[list]",
"List of row indexes to mark urgent", NULL, is_term );
763 print_help_msg (
"-a",
"[list]",
"List of row indexes to mark active", NULL, is_term );
764 print_help_msg (
"-l",
"[integer] ",
"Number of rows to display", NULL, is_term );
765 print_help_msg (
"-window-title",
"[string] ",
"Set the dmenu window title", NULL, is_term );
766 print_help_msg (
"-i",
"",
"Set filter to be case insensitive", NULL, is_term );
767 print_help_msg (
"-only-match",
"",
"Force selection to be given entry, disallow no match", NULL, is_term );
768 print_help_msg (
"-no-custom",
"",
"Don't accept custom entry, allow no match", NULL, is_term );
769 print_help_msg (
"-select",
"[string]",
"Select the first row that matches", NULL, is_term );
770 print_help_msg (
"-password",
"",
"Do not show what the user inputs. Show '*' instead.", NULL, is_term );
771 print_help_msg (
"-markup-rows",
"",
"Allow and render pango markup as input data.", NULL, is_term );
772 print_help_msg (
"-sep",
"[char]",
"Element separator.",
"'\\n'", is_term );
773 print_help_msg (
"-input",
"[filename]",
"Read input from file instead from standard input.", NULL, is_term );
774 print_help_msg (
"-sync",
"",
"Force dmenu to first read all input data, then show dialog.", NULL, is_term );
775 print_help_msg (
"-async-pre-read",
"[number]",
"Read several entries blocking before switching to async mode",
"25", is_term );
776 print_help_msg (
"-w",
"windowid",
"Position over window with X11 windowid.", NULL, is_term );
777 print_help_msg (
"-keep-right",
"",
"Set ellipsize to end.", NULL, is_term );