mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-03 04:23:42 -05:00
Refactor to make dmenu use Switcher, and make menu func use this.
This commit is contained in:
parent
ae26c13daf
commit
13203c9de7
3 changed files with 159 additions and 106 deletions
|
@ -79,6 +79,7 @@ typedef enum
|
|||
typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensitive, unsigned int index, Switcher *data );
|
||||
|
||||
/**
|
||||
* @param sw the Switcher to show.
|
||||
* @param lines An array of strings to display.
|
||||
* @param num_lines Length of the array with strings to display.
|
||||
* @param input A pointer to a string where the inputted data is placed.
|
||||
|
@ -93,10 +94,9 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensi
|
|||
*
|
||||
* @returns The command issued (see MenuReturn)
|
||||
*/
|
||||
MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt,
|
||||
menu_match_cb mmc, void *mmc_data, int *selected_line,
|
||||
get_display_value mgrv, void *mgrv_data, int *next_pos, const char *message ) __attribute__ ( ( nonnull ( 1, 3,
|
||||
4, 7 ) ) );
|
||||
MenuReturn menu ( Switcher *sw, char **input, char *prompt,
|
||||
int *selected_line,
|
||||
unsigned int *next_pos, const char *message ) __attribute__ ( ( nonnull ( 1, 2, 3, 4 ) ) );
|
||||
/**
|
||||
* @param sig The caught signal
|
||||
*
|
||||
|
|
|
@ -36,8 +36,28 @@
|
|||
#include "dialogs/dmenu.h"
|
||||
#include "helper.h"
|
||||
|
||||
struct range_pair
|
||||
{
|
||||
unsigned int start;
|
||||
unsigned int stop;
|
||||
};
|
||||
typedef struct _DmenuModePrivateData
|
||||
{
|
||||
char *prompt;
|
||||
int selected_line;
|
||||
char *message;
|
||||
char *format;
|
||||
struct range_pair * urgent_list;
|
||||
unsigned int num_urgent_list;
|
||||
struct range_pair * active_list;
|
||||
unsigned int num_active_list;
|
||||
// List with entries.
|
||||
char **cmd_list;
|
||||
unsigned int cmd_list_length;
|
||||
} DmenuModePrivateData;
|
||||
|
||||
static char **get_dmenu ( int *length )
|
||||
|
||||
static char **get_dmenu ( unsigned int *length )
|
||||
{
|
||||
char buffer[1024];
|
||||
char **retv = NULL;
|
||||
|
@ -64,16 +84,17 @@ static char **get_dmenu ( int *length )
|
|||
return retv;
|
||||
}
|
||||
|
||||
struct range_pair
|
||||
static char ** dmenu_mode_get_data ( unsigned int *length, Switcher *sw )
|
||||
{
|
||||
unsigned int start;
|
||||
unsigned int stop;
|
||||
};
|
||||
DmenuModePrivateData *rmpd = (DmenuModePrivateData *) sw->private_data;
|
||||
if ( rmpd->cmd_list == NULL ) {
|
||||
rmpd->cmd_list_length = 0;
|
||||
rmpd->cmd_list = get_dmenu ( &( rmpd->cmd_list_length ) );
|
||||
}
|
||||
*length = rmpd->cmd_list_length;
|
||||
return rmpd->cmd_list;
|
||||
}
|
||||
|
||||
struct range_pair * urgent_list = NULL;
|
||||
unsigned int num_urgent_list = 0;
|
||||
struct range_pair * active_list = NULL;
|
||||
unsigned int num_active_list = 0;
|
||||
|
||||
static void parse_pair ( char *input, struct range_pair *item )
|
||||
{
|
||||
|
@ -113,14 +134,16 @@ static void parse_ranges ( char *input, struct range_pair **list, unsigned int *
|
|||
|
||||
static const char *get_display_data ( unsigned int index, void *data, G_GNUC_UNUSED int *state )
|
||||
{
|
||||
char **retv = (char * *) data;
|
||||
for ( unsigned int i = 0; i < num_active_list; i++ ) {
|
||||
if ( index >= active_list[i].start && index <= active_list[i].stop ) {
|
||||
Switcher *sw = (Switcher *) data;
|
||||
DmenuModePrivateData *pd = (DmenuModePrivateData *) sw->private_data;
|
||||
char **retv = (char * *) pd->cmd_list;
|
||||
for ( unsigned int i = 0; i < pd->num_active_list; i++ ) {
|
||||
if ( index >= pd->active_list[i].start && index <= pd->active_list[i].stop ) {
|
||||
*state |= ACTIVE;
|
||||
}
|
||||
}
|
||||
for ( unsigned int i = 0; i < num_urgent_list; i++ ) {
|
||||
if ( index >= urgent_list[i].start && index <= urgent_list[i].stop ) {
|
||||
for ( unsigned int i = 0; i < pd->num_urgent_list; i++ ) {
|
||||
if ( index >= pd->urgent_list[i].start && index <= pd->urgent_list[i].stop ) {
|
||||
*state |= URGENT;
|
||||
}
|
||||
}
|
||||
|
@ -177,65 +200,57 @@ static void dmenu_output_formatted_line ( const char *format, const char *string
|
|||
fputc ( '\n', stdout );
|
||||
fflush ( stdout );
|
||||
}
|
||||
|
||||
int dmenu_switcher_dialog ( void )
|
||||
static void dmenu_mode_free ( Switcher *sw )
|
||||
{
|
||||
char *input = NULL;
|
||||
char *dmenu_prompt = "dmenu ";
|
||||
int selected_line = -1;
|
||||
int retv = FALSE;
|
||||
int length = 0;
|
||||
char **list = get_dmenu ( &length );
|
||||
int restart = FALSE;
|
||||
char *message = NULL;
|
||||
if ( sw->private_data == NULL ) {
|
||||
return;
|
||||
}
|
||||
DmenuModePrivateData *pd = (DmenuModePrivateData *) sw->private_data;
|
||||
|
||||
find_arg_str ( "-mesg", &message );
|
||||
|
||||
g_strfreev ( pd->cmd_list );
|
||||
g_free ( pd->urgent_list );
|
||||
g_free ( pd->active_list );
|
||||
|
||||
g_free ( pd );
|
||||
sw->private_data = NULL;
|
||||
}
|
||||
|
||||
static void dmenu_mode_init ( Switcher *sw )
|
||||
{
|
||||
if ( sw->private_data != NULL ) {
|
||||
return;
|
||||
}
|
||||
sw->private_data = g_malloc0 ( sizeof ( DmenuModePrivateData ) );
|
||||
DmenuModePrivateData *pd = (DmenuModePrivateData *) sw->private_data;
|
||||
|
||||
pd->prompt = "dmenu ";
|
||||
pd->selected_line = -1;
|
||||
|
||||
find_arg_str ( "-mesg", &( pd->message ) );
|
||||
|
||||
// Check prompt
|
||||
find_arg_str ( "-p", &( pd->prompt ) );
|
||||
find_arg_int ( "-selected-row", &( pd->selected_line ) );
|
||||
// By default we print the unescaped line back.
|
||||
char *format = "s";
|
||||
pd->format = "s";
|
||||
|
||||
// Allow user to override the output format.
|
||||
find_arg_str ( "-format", &format );
|
||||
// Check prompt
|
||||
find_arg_str ( "-p", &dmenu_prompt );
|
||||
find_arg_int ( "-selected-row", &selected_line );
|
||||
find_arg_str ( "-format", &( pd->format ) );
|
||||
// Urgent.
|
||||
char *str = NULL;
|
||||
find_arg_str ( "-u", &str );
|
||||
if ( str != NULL ) {
|
||||
parse_ranges ( str, &urgent_list, &num_urgent_list );
|
||||
parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) );
|
||||
}
|
||||
// Active
|
||||
str = NULL;
|
||||
find_arg_str ( "-a", &str );
|
||||
if ( str != NULL ) {
|
||||
parse_ranges ( str, &active_list, &num_active_list );
|
||||
}
|
||||
|
||||
int only_selected = FALSE;
|
||||
if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) {
|
||||
only_selected = TRUE;
|
||||
if ( length == 0 ) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/* copy filter string */
|
||||
input = g_strdup ( config.filter );
|
||||
|
||||
char *select = NULL;
|
||||
find_arg_str ( "-select", &select );
|
||||
if ( select != NULL ) {
|
||||
char **tokens = tokenize ( select, config.case_sensitive );
|
||||
int i = 0;
|
||||
for ( i = 0; i < length; i++ ) {
|
||||
if ( token_match ( tokens, list[i], config.case_sensitive, 0, NULL ) ) {
|
||||
selected_line = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev ( tokens );
|
||||
parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) );
|
||||
}
|
||||
|
||||
// DMENU COMPATIBILITY
|
||||
find_arg_uint ( "-l", &( config.menu_lines ) );
|
||||
|
||||
/**
|
||||
|
@ -250,11 +265,63 @@ int dmenu_switcher_dialog ( void )
|
|||
if ( find_arg ( "-i" ) >= 0 ) {
|
||||
config.case_sensitive = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Switcher dmenu_mode =
|
||||
{
|
||||
.name = "dmenu",
|
||||
.keycfg = NULL,
|
||||
.keystr = NULL,
|
||||
.modmask = AnyModifier,
|
||||
.init = dmenu_mode_init,
|
||||
.get_data = dmenu_mode_get_data,
|
||||
.result = NULL,
|
||||
.destroy = dmenu_mode_free,
|
||||
.token_match = token_match,
|
||||
.mgrv = get_display_data,
|
||||
.private_data = NULL,
|
||||
.free = NULL
|
||||
};
|
||||
|
||||
int dmenu_switcher_dialog ( void )
|
||||
{
|
||||
dmenu_mode.init ( &dmenu_mode );
|
||||
DmenuModePrivateData *pd = (DmenuModePrivateData *) dmenu_mode.private_data;
|
||||
char *input = NULL;
|
||||
int retv = FALSE;
|
||||
int restart = FALSE;
|
||||
unsigned int cmd_list_length = 0;
|
||||
char **cmd_list = dmenu_mode.get_data ( &( cmd_list_length ), &dmenu_mode );
|
||||
|
||||
|
||||
int only_selected = FALSE;
|
||||
if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) {
|
||||
only_selected = TRUE;
|
||||
if ( cmd_list_length == 0 ) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/* copy filter string */
|
||||
input = g_strdup ( config.filter );
|
||||
|
||||
char *select = NULL;
|
||||
find_arg_str ( "-select", &select );
|
||||
if ( select != NULL ) {
|
||||
char **tokens = tokenize ( select, config.case_sensitive );
|
||||
unsigned int i = 0;
|
||||
for ( i = 0; i < cmd_list_length; i++ ) {
|
||||
if ( token_match ( tokens, cmd_list[i], config.case_sensitive, 0, NULL ) ) {
|
||||
pd->selected_line = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev ( tokens );
|
||||
}
|
||||
|
||||
do {
|
||||
int next_pos = selected_line;
|
||||
int mretv = menu ( list, length, &input, dmenu_prompt,
|
||||
token_match, NULL, &selected_line, get_display_data, list, &next_pos, message );
|
||||
unsigned int next_pos = pd->selected_line;
|
||||
int mretv = menu ( &dmenu_mode, &input, pd->prompt,
|
||||
&( pd->selected_line ), &next_pos, pd->message );
|
||||
// Special behavior.
|
||||
// TODO clean this up!
|
||||
if ( only_selected ) {
|
||||
|
@ -262,8 +329,8 @@ int dmenu_switcher_dialog ( void )
|
|||
* Select item mode.
|
||||
*/
|
||||
restart = 1;
|
||||
if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && list[selected_line] != NULL ) {
|
||||
dmenu_output_formatted_line ( format, list[selected_line], selected_line, input );
|
||||
if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && cmd_list[pd->selected_line] != NULL ) {
|
||||
dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input );
|
||||
retv = TRUE;
|
||||
if ( ( mretv & MENU_QUICK_SWITCH ) ) {
|
||||
retv = 10 + ( mretv & MENU_LOWER_MASK );
|
||||
|
@ -274,54 +341,51 @@ int dmenu_switcher_dialog ( void )
|
|||
// In no custom mode we allow canceling.
|
||||
restart = ( find_arg ( "-only-match" ) >= 0 );
|
||||
}
|
||||
selected_line = next_pos - 1;
|
||||
pd->selected_line = next_pos - 1;
|
||||
continue;
|
||||
}
|
||||
// We normally do not want to restart the loop.
|
||||
restart = FALSE;
|
||||
// Normal mode
|
||||
if ( ( mretv & MENU_OK ) && list[selected_line] != NULL ) {
|
||||
dmenu_output_formatted_line ( format, list[selected_line], selected_line, input );
|
||||
if ( ( mretv & MENU_OK ) && cmd_list[pd->selected_line] != NULL ) {
|
||||
dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input );
|
||||
if ( ( mretv & MENU_SHIFT ) ) {
|
||||
restart = TRUE;
|
||||
// Move to next line.
|
||||
selected_line = MIN ( next_pos, length - 1 );
|
||||
pd->selected_line = MIN ( next_pos, cmd_list_length - 1 );
|
||||
}
|
||||
retv = TRUE;
|
||||
}
|
||||
// Custom input
|
||||
else if ( ( mretv & ( MENU_CUSTOM_INPUT ) ) ) {
|
||||
dmenu_output_formatted_line ( format, input, -1, input );
|
||||
dmenu_output_formatted_line ( pd->format, input, -1, input );
|
||||
if ( ( mretv & MENU_SHIFT ) ) {
|
||||
restart = TRUE;
|
||||
// Move to next line.
|
||||
selected_line = MIN ( next_pos, length - 1 );
|
||||
pd->selected_line = MIN ( next_pos, cmd_list_length - 1 );
|
||||
}
|
||||
|
||||
retv = TRUE;
|
||||
}
|
||||
// Quick switch with entry selected.
|
||||
else if ( ( mretv & MENU_QUICK_SWITCH ) && selected_line >= 0 ) {
|
||||
dmenu_output_formatted_line ( format, list[selected_line], selected_line, input );
|
||||
else if ( ( mretv & MENU_QUICK_SWITCH ) && pd->selected_line >= 0 ) {
|
||||
dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input );
|
||||
|
||||
restart = FALSE;
|
||||
retv = 10 + ( mretv & MENU_LOWER_MASK );
|
||||
}
|
||||
// Quick switch without entry selected.
|
||||
else if ( ( mretv & MENU_QUICK_SWITCH ) && selected_line == -1 ) {
|
||||
dmenu_output_formatted_line ( format, input, -1, input );
|
||||
else if ( ( mretv & MENU_QUICK_SWITCH ) && pd->selected_line == -1 ) {
|
||||
dmenu_output_formatted_line ( pd->format, input, -1, input );
|
||||
|
||||
restart = FALSE;
|
||||
retv = 10 + ( mretv & MENU_LOWER_MASK );
|
||||
}
|
||||
} while ( restart );
|
||||
|
||||
g_strfreev ( list );
|
||||
g_free ( urgent_list );
|
||||
g_free ( active_list );
|
||||
|
||||
g_free ( input );
|
||||
|
||||
dmenu_mode.destroy ( &dmenu_mode );
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
|
|
@ -233,6 +233,7 @@ static Window create_window ( Display *display )
|
|||
|
||||
typedef struct MenuState
|
||||
{
|
||||
Switcher *sw;
|
||||
unsigned int menu_lines;
|
||||
unsigned int max_elements;
|
||||
unsigned int max_rows;
|
||||
|
@ -278,8 +279,6 @@ typedef struct MenuState
|
|||
MenuReturn retv;
|
||||
char **lines;
|
||||
int line_height;
|
||||
get_display_value mgrv;
|
||||
void *mgrv_data;
|
||||
}MenuState;
|
||||
|
||||
/**
|
||||
|
@ -815,7 +814,7 @@ static void menu_draw ( MenuState *state )
|
|||
{
|
||||
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 );
|
||||
const char *text = state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate );
|
||||
TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type );
|
||||
textbox_font ( state->boxes[i], tbft );
|
||||
textbox_text ( state->boxes[i], text );
|
||||
|
@ -830,7 +829,7 @@ static void menu_draw ( MenuState *state )
|
|||
for ( i = 0; i < max_elements; i++ ) {
|
||||
TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT;
|
||||
int fstate = 0;
|
||||
state->mgrv ( state->line_map[i + offset], state->mgrv_data, &fstate );
|
||||
state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate );
|
||||
TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type );
|
||||
textbox_font ( state->boxes[i], tbft );
|
||||
textbox_draw ( state->boxes[i] );
|
||||
|
@ -902,18 +901,18 @@ 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,
|
||||
get_display_value mgrv, void *mgrv_data, int *next_pos, const char *message )
|
||||
MenuReturn menu ( Switcher *sw, char **input, char *prompt,
|
||||
int *selected_line,
|
||||
unsigned int *next_pos, const char *message )
|
||||
{
|
||||
int shift = FALSE;
|
||||
MenuState state = {
|
||||
.sw = sw,
|
||||
.selected_line = selected_line,
|
||||
.retv = MENU_CANCEL,
|
||||
.prev_key = 0,
|
||||
.last_button_press = 0,
|
||||
.last_offset = 0,
|
||||
.num_lines = num_lines,
|
||||
.distance = NULL,
|
||||
.quit = FALSE,
|
||||
.skip_absorb = FALSE,
|
||||
|
@ -924,11 +923,10 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
.update = FALSE,
|
||||
.rchanged = TRUE,
|
||||
.cur_page = -1,
|
||||
.lines = lines,
|
||||
.mgrv = mgrv,
|
||||
.mgrv_data = mgrv_data,
|
||||
.top_offset = 0
|
||||
};
|
||||
// Request the lines to show.
|
||||
state.lines = sw->get_data ( &( state.num_lines ), sw );
|
||||
unsigned int i;
|
||||
if ( next_pos ) {
|
||||
*next_pos = *selected_line;
|
||||
|
@ -1086,7 +1084,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
state.selected = 0;
|
||||
|
||||
state.quit = FALSE;
|
||||
menu_refilter ( &state, lines, mmc, mmc_data, config.levenshtein_sort, config.case_sensitive );
|
||||
menu_refilter ( &state, state.lines, sw->token_match, sw, config.levenshtein_sort, config.case_sensitive );
|
||||
|
||||
for ( unsigned int i = 0; ( *( state.selected_line ) ) >= 0 && !state.selected && i < state.filtered_lines; i++ ) {
|
||||
if ( state.line_map[i] == *( state.selected_line ) ) {
|
||||
|
@ -1114,7 +1112,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
// If not in lazy mode, refilter.
|
||||
if ( state.num_lines <= config.lazy_filter_limit ) {
|
||||
if ( state.refilter ) {
|
||||
menu_refilter ( &state, lines, mmc, mmc_data, config.levenshtein_sort, config.case_sensitive );
|
||||
menu_refilter ( &state, state.lines, sw->token_match, sw, config.levenshtein_sort, config.case_sensitive );
|
||||
menu_update ( &state );
|
||||
}
|
||||
}
|
||||
|
@ -1122,7 +1120,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
// When timeout (and in lazy filter mode)
|
||||
// We refilter then loop back and wait for Xevent.
|
||||
if ( state.refilter ) {
|
||||
menu_refilter ( &state, lines, mmc, mmc_data, config.levenshtein_sort, config.case_sensitive );
|
||||
menu_refilter ( &state, state.lines, sw->token_match, sw, config.levenshtein_sort, config.case_sensitive );
|
||||
menu_update ( &state );
|
||||
}
|
||||
}
|
||||
|
@ -1301,6 +1299,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
void error_dialog ( const char *msg, int markup )
|
||||
{
|
||||
MenuState state = {
|
||||
.sw = NULL,
|
||||
.selected_line = NULL,
|
||||
.retv = MENU_CANCEL,
|
||||
.prev_key = 0,
|
||||
|
@ -2065,19 +2064,9 @@ int main ( int argc, char *argv[] )
|
|||
|
||||
SwitcherMode switcher_run ( char **input, Switcher *sw )
|
||||
{
|
||||
char *prompt = g_strdup_printf ( "%s:", sw->name );
|
||||
int selected_line = -1;
|
||||
unsigned int cmd_list_length = 0;
|
||||
char **cmd_list = NULL;
|
||||
|
||||
// get the list and get its length, before passing the length to menu
|
||||
cmd_list = sw->get_data ( &cmd_list_length, sw );
|
||||
|
||||
int mretv = menu ( cmd_list, cmd_list_length, // List data.
|
||||
input, prompt, // Input and prompt
|
||||
sw->token_match, sw, // token match + arg.
|
||||
&selected_line, // Selected line.
|
||||
sw->mgrv, sw, NULL, NULL );
|
||||
char *prompt = g_strdup_printf ( "%s:", sw->name );
|
||||
int selected_line = -1;
|
||||
int mretv = menu ( sw, input, prompt, &selected_line, NULL, NULL );
|
||||
|
||||
g_free ( prompt );
|
||||
return sw->result ( mretv, input, selected_line, sw );
|
||||
|
|
Loading…
Reference in a new issue