From 0d87cf12a37c8bba53376edb1f2cd1b869839acc Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Tue, 31 Mar 2015 22:45:02 +0200 Subject: [PATCH] Add combi viewer, where (selected) modi can be combined. - Add active window highlighter. --- Changelog | 5 +- config/config.def.c | 7 ++- include/rofi.h | 26 +++++---- include/textbox.h | 11 +++- source/dialogs/combi.c | 86 ++++++++++++++++++++++----- source/dialogs/dmenu.c | 8 ++- source/dialogs/run.c | 7 +++ source/dialogs/script.c | 6 ++ source/dialogs/ssh.c | 7 +++ source/dialogs/window.c | 14 +++++ source/rofi.c | 125 +++++++++++++++++++--------------------- source/textbox.c | 17 ++++-- source/xrmoptions.c | 3 +- 13 files changed, 220 insertions(+), 102 deletions(-) diff --git a/Changelog b/Changelog index 89cb7b7b..5873554d 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,8 @@ -0.15.3: (unreleased) +0.15.4: (unreleased) New feature: - Number mode for dmenu. allows user to get index back instead of content. + - Combi mode. Combine multiple views into one. + - Highlight current window. Bug fixes: - On a single item in list disable auto-select. Improvements: @@ -13,6 +15,7 @@ - Fix modi switcher boxes size+layout. - Reduce work on redraws (do not always calculate new size/position), set text, etc. - OO-ify the switchers. + - Remove unneeded filtered array. Cleanup: - Do not lug argc,argv around everywhere. diff --git a/config/config.def.c b/config/config.def.c index b79d35ea..7d21f11b 100644 --- a/config/config.def.c +++ b/config/config.def.c @@ -104,7 +104,10 @@ Settings config = { /** Lazy mode setting */ .lazy_filter_limit = 5000, /** auto select */ - .auto_select = FALSE, - .parse_hosts = FALSE + .auto_select = FALSE, + /** Parse /etc/hosts file in ssh view. */ + .parse_hosts = FALSE, + /** Modi to combine into one view. */ + .combi_modi = "window,run" }; diff --git a/include/rofi.h b/include/rofi.h index 1cb1947d..0054624b 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -37,6 +37,8 @@ typedef enum typedef SwitcherMode ( *switcher_callback )( char **input, void *data ); typedef void ( *switcher_free )( Switcher *data ); + +typedef const char * ( *get_display_value )( unsigned int selected_line, void *data, int *state ); /** * State returned by the rofi window. */ @@ -90,7 +92,7 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensi */ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, menu_match_cb mmc, void *mmc_data, - int *selected_line, int sorting ) __attribute__ ( ( nonnull ( 1, 3, 4, 7 ) ) ); + int *selected_line, int sorting, get_display_value mgrv, void *mgrv_data ) __attribute__ ( ( nonnull ( 1, 3, 4, 7 ) ) ); /** * @param sig The caught signal * @@ -203,6 +205,8 @@ typedef struct _Settings unsigned int auto_select; /** Hosts file parsing */ unsigned int parse_hosts; + /** Combi Switchers */ + char *combi_modi; } Settings; /** Global Settings structure. */ @@ -236,21 +240,23 @@ struct _Switcher /** * A switcher normally consists of the following parts: */ - void ( *init )( struct _Switcher *sw ); - char ** ( *get_data )( unsigned int *length, struct _Switcher *pd ); - int ( *match )( char **tokens, const char *input, int case_sensitive, int index, struct _Switcher *data ); - SwitcherMode ( *result )( int menu_retv, char **input, unsigned int selected_line, struct _Switcher *pd ); - void ( *destroy )( struct _Switcher *pd ); + void ( *init )( struct _Switcher *sw ); + char ** ( *get_data )( unsigned int *length, struct _Switcher *pd ); + int ( *match )( char **tokens, const char *input, int case_sensitive, int index, struct _Switcher *data ); + SwitcherMode ( *result )( int menu_retv, char **input, unsigned int selected_line, struct _Switcher *pd ); + void ( *destroy )( struct _Switcher *pd ); // Token match. - menu_match_cb token_match; + menu_match_cb token_match; + + get_display_value mgrv; // Pointer to private data. - void *private_data; + void *private_data; // Extra fields for script - void *ed; + void *ed; // Free SWitcher - switcher_free free; + switcher_free free; }; #endif diff --git a/include/textbox.h b/include/textbox.h index 6843d0ef..d75eb8b0 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -17,6 +17,7 @@ typedef struct XIM xim; XIC xic; PangoLayout *layout; + int tbft; } textbox; @@ -34,11 +35,15 @@ typedef enum typedef enum { // Render font normally - NORMAL, + NORMAL = 1, // Alternating row. - ALT, + ALT = 2, // Render font highlighted (inverted colors.) - HIGHLIGHT, + HIGHLIGHT = 4, + + STATE_MASK = ( NORMAL | ALT | HIGHLIGHT ), + + BOLD = 8, } TextBoxFontType; textbox* textbox_create ( Window parent, diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 6d6518f3..a171777f 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -29,8 +29,11 @@ #include #include -extern unsigned int num_switchers; -extern Switcher **switchers; +#include +#include +#include +#include + /** * Combi Switcher */ @@ -45,28 +48,64 @@ typedef struct _CombiModePrivateData // List of switchers to combine. unsigned int num_switchers; Switcher **switchers; + char *cache; } CombiModePrivateData; -static void combi_add_switcher ( Switcher *sw, Switcher *m ) +static void combi_mode_parse_switchers ( Switcher *sw ) { - CombiModePrivateData *pd = sw->private_data; - pd->switchers = g_realloc ( pd->switchers, ( pd->num_switchers + 2 ) * sizeof ( Switcher * ) ); - pd->switchers[pd->num_switchers] = m; - pd->switchers[pd->num_switchers + 1] = NULL; - pd->num_switchers++; + CombiModePrivateData *pd = sw->private_data; + char *savept = NULL; + // Make a copy, as strtok will modify it. + char *switcher_str = g_strdup ( config.combi_modi ); + // Split token on ','. This modifies switcher_str. + for ( char *token = strtok_r ( switcher_str, ",", &savept ); + token != NULL; + token = strtok_r ( NULL, ",", &savept ) ) { + // Resize and add entry. + pd->switchers = (Switcher * *) g_realloc ( pd->switchers, + sizeof ( Switcher* ) * ( pd->num_switchers + 1 ) ); + + // Window switcher. + if ( strcasecmp ( token, "window" ) == 0 ) { + pd->switchers[pd->num_switchers++] = &window_mode; + } + // SSh dialog + else if ( strcasecmp ( token, "ssh" ) == 0 ) { + pd->switchers[pd->num_switchers++] = &ssh_mode; + } + // Run dialog + else if ( strcasecmp ( token, "run" ) == 0 ) { + pd->switchers[pd->num_switchers++] = &run_mode; + } + else { + // If not build in, use custom switchers. + Switcher *sw = script_switcher_parse_setup ( token ); + if ( sw != NULL ) { + pd->switchers[pd->num_switchers++] = sw; + } + else{ + // Report error, don't continue. + fprintf ( stderr, "Invalid script switcher: %s\n", token ); + token = NULL; + } + } + // Keybinding. + } + // Free string that was modified by strtok_r + g_free ( switcher_str ); } + static void combi_mode_init ( Switcher *sw ) { if ( sw->private_data == NULL ) { CombiModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; - for ( unsigned int i = 0; i < num_switchers; i++ ) { - if ( switchers[i] != sw ) { - combi_add_switcher ( sw, switchers[i] ); - } - } + combi_mode_parse_switchers ( sw ); pd->starts = g_malloc0 ( sizeof ( int ) * pd->num_switchers ); pd->lengths = g_malloc0 ( sizeof ( int ) * pd->num_switchers ); + for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { + pd->switchers[i]->init ( pd->switchers[i] ); + } } } static char ** combi_mode_get_data ( unsigned int *length, Switcher *sw ) @@ -101,8 +140,13 @@ static void combi_mode_destroy ( Switcher *sw ) g_free ( pd->cmd_list ); g_free ( pd->starts ); g_free ( pd->lengths ); + // Cleanup switchers. + for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { + pd->switchers[i]->destroy ( pd->switchers[i] ); + } g_free ( pd->switchers ); g_free ( pd ); + g_free ( pd->cache ); sw->private_data = NULL; } } @@ -138,6 +182,21 @@ static int combi_mode_match ( char **tokens, const char *input, abort (); return 0; } +static const char * combi_mgrv ( unsigned int selected_line, void *sw, int *state ) +{ + CombiModePrivateData *pd = ( (Switcher *) sw )->private_data; + for ( unsigned i = 0; i < pd->num_switchers; i++ ) { + if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { + g_free ( pd->cache ); + pd->cache = g_strdup_printf ( "(%s) %s", + pd->switchers[i]->name, + pd->switchers[i]->mgrv ( selected_line - pd->starts[i], (void *) pd->switchers[i], state ) ); + return pd->cache; + } + } + + return NULL; +} Switcher combi_mode = { @@ -151,6 +210,7 @@ Switcher combi_mode = .result = combi_mode_result, .destroy = combi_mode_destroy, .token_match = combi_mode_match, + .mgrv = combi_mgrv, .private_data = NULL, .free = NULL }; diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index c019f421..0ad32c99 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -64,6 +64,12 @@ static char **get_dmenu ( int *length ) return retv; } +static const char *get_display_data ( unsigned int index, void *data, G_GNUC_UNUSED int *state ) +{ + char **retv = (char * *) data; + return retv[index]; +} + int dmenu_switcher_dialog ( char **input ) { char *dmenu_prompt = "dmenu "; @@ -84,7 +90,7 @@ int dmenu_switcher_dialog ( char **input ) do { int mretv = menu ( list, length, input, dmenu_prompt, - token_match, NULL, &selected_line, FALSE ); + token_match, NULL, &selected_line, FALSE, get_display_data, list ); // We normally do not want to restart the loop. restart = FALSE; diff --git a/source/dialogs/run.c b/source/dialogs/run.c index fc3cd039..ec3d7c30 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -331,6 +331,12 @@ static void run_mode_destroy ( Switcher *sw ) } } +static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +{ + RunModePrivateData *rmpd = ( (Switcher *) sw )->private_data; + return rmpd->cmd_list[selected_line]; +} + Switcher run_mode = { .name = "run", @@ -343,6 +349,7 @@ Switcher run_mode = .result = run_mode_result, .destroy = run_mode_destroy, .token_match = token_match, + .mgrv = mgrv, .private_data = NULL, .free = NULL }; diff --git a/source/dialogs/script.c b/source/dialogs/script.c index 96334ed1..576dee6d 100644 --- a/source/dialogs/script.c +++ b/source/dialogs/script.c @@ -163,6 +163,11 @@ static void script_mode_destroy ( Switcher *sw ) sw->private_data = NULL; } } +static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +{ + ScriptModePrivateData *rmpd = ( (Switcher *) sw )->private_data; + return rmpd->cmd_list[selected_line]; +} Switcher *script_switcher_parse_setup ( const char *str ) { @@ -189,6 +194,7 @@ Switcher *script_switcher_parse_setup ( const char *str ) sw->result = script_mode_result; sw->destroy = script_mode_destroy; sw->token_match = token_match; + sw->mgrv = mgrv; return sw; } diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 675ffa10..a848de0e 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -321,6 +321,12 @@ static void ssh_mode_destroy ( Switcher *sw ) } } +static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +{ + SSHModePrivateData *rmpd = ( (Switcher *) sw )->private_data; + return rmpd->cmd_list[selected_line]; +} + Switcher ssh_mode = { .name = "ssh", @@ -333,6 +339,7 @@ Switcher ssh_mode = .result = ssh_mode_result, .destroy = ssh_mode_destroy, .token_match = token_match, + .mgrv = mgrv, .private_data = NULL, .free = NULL }; diff --git a/source/dialogs/window.c b/source/dialogs/window.c index a3e727e4..8b01ed1a 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -286,6 +286,9 @@ typedef struct _SwitcherModePrivateData winlist *ids; int config_i3_mode; int init; + // Current window. + unsigned int index; + char *cache; } SwitcherModePrivateData; static int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input, @@ -496,11 +499,21 @@ static void window_mode_destroy ( Switcher *sw ) winlist_free ( rmpd->ids ); i3_support_free_internals (); x11_cache_free (); + g_free ( rmpd->cache ); g_free ( rmpd ); sw->private_data = NULL; } } +static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +{ + SwitcherModePrivateData *rmpd = ( (Switcher *) sw )->private_data; + if ( window_client ( display, rmpd->ids->array[selected_line] )->active ) { + *state = BOLD; + } + return rmpd->cmd_list[selected_line]; +} + Switcher window_mode = { .name = "window", @@ -513,6 +526,7 @@ Switcher window_mode = .result = window_mode_result, .destroy = window_mode_destroy, .token_match = window_match, + .mgrv = mgrv, .private_data = NULL, .free = NULL }; diff --git a/source/rofi.c b/source/rofi.c index a36b4ce1..f8e322d4 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -272,51 +272,52 @@ static Window create_window ( Display *display ) typedef struct MenuState { - unsigned int menu_lines; - unsigned int max_elements; - unsigned int max_rows; - unsigned int columns; + unsigned int menu_lines; + unsigned int max_elements; + unsigned int max_rows; + unsigned int columns; // window width,height - unsigned int w, h; - int x, y; - unsigned int element_width; + unsigned int w, h; + int x, y; + unsigned int element_width; // Update/Refilter list. - int update; - int refilter; - int rchanged; - int cur_page; + int update; + int refilter; + int rchanged; + int cur_page; // Entries - textbox *text; - textbox *prompt_tb; - textbox *case_indicator; - textbox *arrowbox_top; - textbox *arrowbox_bottom; - textbox **boxes; - char **filtered; - int *distance; - int *line_map; + textbox *text; + textbox *prompt_tb; + textbox *case_indicator; + textbox *arrowbox_top; + textbox *arrowbox_bottom; + textbox **boxes; + int *distance; + int *line_map; - unsigned int num_lines; + unsigned int num_lines; // Selected element. - unsigned int selected; - unsigned int filtered_lines; + unsigned int selected; + unsigned int filtered_lines; // Last offset in paginating. - unsigned int last_offset; + unsigned int last_offset; - KeySym prev_key; - Time last_button_press; + KeySym prev_key; + Time last_button_press; - int quit; - int init; + int quit; + int init; // Return state - int *selected_line; - MenuReturn retv; - char **lines; - int line_height; + int *selected_line; + MenuReturn retv; + char **lines; + int line_height; + get_display_value mgrv; + void *mgrv_data; }MenuState; /** @@ -337,7 +338,6 @@ static void menu_free_state ( MenuState *state ) } g_free ( state->boxes ); - g_free ( state->filtered ); g_free ( state->line_map ); g_free ( state->distance ); } @@ -575,15 +575,9 @@ static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned in } else if ( key == XK_Tab ) { if ( state->filtered_lines == 1 ) { - if ( state->filtered[state->selected] ) { - state->retv = MENU_OK; - *( state->selected_line ) = state->line_map[state->selected]; - state->quit = 1; - } - else{ - fprintf ( stderr, "We should never hit this." ); - abort (); - } + state->retv = MENU_OK; + *( state->selected_line ) = state->line_map[state->selected]; + state->quit = 1; return; } @@ -636,7 +630,7 @@ static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned in } else if ( key == XK_space && ( modstate & ControlMask ) == ControlMask ) { // If a valid item is selected, return that.. - if ( state->selected < state->filtered_lines && state->filtered[state->selected] != NULL ) { + if ( state->selected < state->filtered_lines ) { textbox_text ( state->text, state->lines[state->line_map[state->selected]] ); textbox_cursor_end ( state->text ); state->update = TRUE; @@ -753,13 +747,6 @@ static void menu_refilter ( MenuState *state, char **lines, menu_match_cb mmc, v if ( sorting ) { qsort_r ( state->line_map, j, sizeof ( int ), lev_sort, state->distance ); } - // Update the filtered list. - for ( unsigned int i = 0; i < j; i++ ) { - state->filtered[i] = lines[state->line_map[i]]; - } - for ( unsigned int i = j; i < state->num_lines; i++ ) { - state->filtered[i] = NULL; - } // Cleanup + bookkeeping. state->filtered_lines = j; @@ -767,7 +754,6 @@ static void menu_refilter ( MenuState *state, char **lines, menu_match_cb mmc, v } else{ for ( unsigned int i = 0; i < state->num_lines; i++ ) { - state->filtered[i] = lines[i]; state->line_map[i] = i; } state->filtered_lines = state->num_lines; @@ -841,9 +827,10 @@ static void menu_draw ( MenuState *state ) ex + x_offset, ey + y_offset, element_width, element_height ); { - TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; - char *text = state->filtered[i + offset]; - TextBoxFontType tbft = ( i + offset ) == state->selected ? HIGHLIGHT : type; + TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; + int fstate = 0; + const char *text = state->mgrv ( state->line_map[i + offset], state->mgrv_data, &fstate ); + TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type ); textbox_font ( state->boxes[i], tbft ); textbox_text ( state->boxes[i], text ); } @@ -855,8 +842,10 @@ static void menu_draw ( MenuState *state ) else{ // Only do basic redrawing + highlight of row. for ( i = 0; i < max_elements; i++ ) { - TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; - TextBoxFontType tbft = ( i + offset ) == state->selected ? HIGHLIGHT : type; + TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; + int fstate = 0; + state->mgrv ( state->line_map[i + offset], state->mgrv_data, &fstate ); + TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type ); textbox_font ( state->boxes[i], tbft ); textbox_draw ( state->boxes[i] ); } @@ -924,7 +913,8 @@ static void menu_paste ( MenuState *state, XSelectionEvent *xse ) } MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, - menu_match_cb mmc, void *mmc_data, int *selected_line, int sorting ) + menu_match_cb mmc, void *mmc_data, int *selected_line, int sorting, + get_display_value mgrv, void *mgrv_data ) { int shift = FALSE; MenuState state = { @@ -940,11 +930,13 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom .filtered_lines = 0, .max_elements = 0, // We want to filter on the first run. - .refilter = TRUE, - .update = FALSE, - .rchanged = TRUE, - .cur_page = -1, - .lines = lines + .refilter = TRUE, + .update = FALSE, + .rchanged = TRUE, + .cur_page = -1, + .lines = lines, + .mgrv = mgrv, + .mgrv_data = mgrv_data }; unsigned int i; workarea mon; @@ -1036,7 +1028,6 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom config.padding + state.max_rows * element_height + LINE_MARGIN ); // filtered list - state.filtered = (char * *) g_malloc0_n ( state.num_lines, sizeof ( char* ) ); state.line_map = g_malloc0_n ( state.num_lines, sizeof ( int ) ); if ( sorting ) { state.distance = (int *) g_malloc0_n ( state.num_lines, sizeof ( int ) ); @@ -1212,7 +1203,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom // Special delete entry command. else if ( ( ( ev.xkey.state & ShiftMask ) == ShiftMask ) && key == XK_Delete ) { - if ( state.filtered[state.selected] != NULL ) { + if ( state.selected < state.filtered_lines ) { *( state.selected_line ) = state.line_map[state.selected]; state.retv = MENU_ENTRY_DELETE; state.quit = TRUE; @@ -1226,7 +1217,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom shift = ( ( ev.xkey.state & ShiftMask ) == ShiftMask ); // If a valid item is selected, return that.. - if ( state.selected < state.filtered_lines && state.filtered[state.selected] != NULL ) { + if ( state.selected < state.filtered_lines ) { *( state.selected_line ) = state.line_map[state.selected]; if ( strlen ( state.text->text ) > 0 && rc == -2 ) { state.retv = MENU_CUSTOM_INPUT; @@ -1836,7 +1827,9 @@ SwitcherMode switcher_run ( char **input, Switcher *sw ) input, prompt, sw->token_match, sw, &selected_line, - config.levenshtein_sort ); + config.levenshtein_sort, + sw->mgrv, + sw ); SwitcherMode retv = sw->result ( mretv, input, selected_line, sw ); diff --git a/source/textbox.c b/source/textbox.c index 190fa0d1..78632559 100644 --- a/source/textbox.c +++ b/source/textbox.c @@ -78,10 +78,6 @@ textbox* textbox_create ( Window parent, tb->layout = pango_layout_new ( p_context ); - PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font ); - pango_layout_set_font_description ( tb->layout, pfd ); - pango_font_description_free ( pfd ); - unsigned int cp; switch ( tbft ) { @@ -104,6 +100,8 @@ textbox* textbox_create ( Window parent, InputOutput, vinfo->visual, CWColormap | CWBorderPixel | CWBackPixel, &attr ); // need to preload the font to calc line height + // Force update of font descriptor. + tb->tbft = ~tbft; textbox_font ( tb, tbft ); textbox_text ( tb, text ? text : "" ); @@ -129,7 +127,15 @@ textbox* textbox_create ( Window parent, // set an Xft font by name void textbox_font ( textbox *tb, TextBoxFontType tbft ) { - switch ( tbft ) + if ( ( tbft & BOLD ) != ( tb->tbft & BOLD ) ) { + PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font ); + if ( ( tbft & BOLD ) == BOLD ) { + pango_font_description_set_weight ( pfd, PANGO_WEIGHT_BOLD ); + } + pango_layout_set_font_description ( tb->layout, pfd ); + pango_font_description_free ( pfd ); + } + switch ( ( tbft & STATE_MASK ) ) { case HIGHLIGHT: tb->color_bg = color_hlbg; @@ -145,6 +151,7 @@ void textbox_font ( textbox *tb, TextBoxFontType tbft ) tb->color_fg = color_fg; break; } + tb->tbft = tbft; } // set the default text to display diff --git a/source/xrmoptions.c b/source/xrmoptions.c index c7a3f4fe..9e1116bb 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -105,7 +105,8 @@ static XrmOption xrmOptions[] = { { xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL }, { xrm_SNumber, "eh", { .snum = &config.element_height }, NULL }, { xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL }, - { xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL } + { xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL }, + { xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL } }; // Dynamic options.