mirror of https://github.com/davatorium/rofi.git
Add combi viewer, where (selected) modi can be combined.
- Add active window highlighter.
This commit is contained in:
parent
56a888da6f
commit
0d87cf12a3
|
@ -1,6 +1,8 @@
|
||||||
0.15.3: (unreleased)
|
0.15.4: (unreleased)
|
||||||
New feature:
|
New feature:
|
||||||
- Number mode for dmenu. allows user to get index back instead of content.
|
- 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:
|
Bug fixes:
|
||||||
- On a single item in list disable auto-select.
|
- On a single item in list disable auto-select.
|
||||||
Improvements:
|
Improvements:
|
||||||
|
@ -13,6 +15,7 @@
|
||||||
- Fix modi switcher boxes size+layout.
|
- Fix modi switcher boxes size+layout.
|
||||||
- Reduce work on redraws (do not always calculate new size/position), set text, etc.
|
- Reduce work on redraws (do not always calculate new size/position), set text, etc.
|
||||||
- OO-ify the switchers.
|
- OO-ify the switchers.
|
||||||
|
- Remove unneeded filtered array.
|
||||||
Cleanup:
|
Cleanup:
|
||||||
- Do not lug argc,argv around everywhere.
|
- Do not lug argc,argv around everywhere.
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,10 @@ Settings config = {
|
||||||
/** Lazy mode setting */
|
/** Lazy mode setting */
|
||||||
.lazy_filter_limit = 5000,
|
.lazy_filter_limit = 5000,
|
||||||
/** auto select */
|
/** auto select */
|
||||||
.auto_select = FALSE,
|
.auto_select = FALSE,
|
||||||
.parse_hosts = FALSE
|
/** Parse /etc/hosts file in ssh view. */
|
||||||
|
.parse_hosts = FALSE,
|
||||||
|
/** Modi to combine into one view. */
|
||||||
|
.combi_modi = "window,run"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ typedef enum
|
||||||
typedef SwitcherMode ( *switcher_callback )( char **input, void *data );
|
typedef SwitcherMode ( *switcher_callback )( char **input, void *data );
|
||||||
typedef void ( *switcher_free )( Switcher *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.
|
* 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,
|
MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt,
|
||||||
menu_match_cb mmc, void *mmc_data,
|
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
|
* @param sig The caught signal
|
||||||
*
|
*
|
||||||
|
@ -203,6 +205,8 @@ typedef struct _Settings
|
||||||
unsigned int auto_select;
|
unsigned int auto_select;
|
||||||
/** Hosts file parsing */
|
/** Hosts file parsing */
|
||||||
unsigned int parse_hosts;
|
unsigned int parse_hosts;
|
||||||
|
/** Combi Switchers */
|
||||||
|
char *combi_modi;
|
||||||
} Settings;
|
} Settings;
|
||||||
|
|
||||||
/** Global Settings structure. */
|
/** Global Settings structure. */
|
||||||
|
@ -236,21 +240,23 @@ struct _Switcher
|
||||||
/**
|
/**
|
||||||
* A switcher normally consists of the following parts:
|
* A switcher normally consists of the following parts:
|
||||||
*/
|
*/
|
||||||
void ( *init )( struct _Switcher *sw );
|
void ( *init )( struct _Switcher *sw );
|
||||||
char ** ( *get_data )( unsigned int *length, struct _Switcher *pd );
|
char ** ( *get_data )( unsigned int *length, struct _Switcher *pd );
|
||||||
int ( *match )( char **tokens, const char *input, int case_sensitive, int index, struct _Switcher *data );
|
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 );
|
SwitcherMode ( *result )( int menu_retv, char **input, unsigned int selected_line, struct _Switcher *pd );
|
||||||
void ( *destroy )( struct _Switcher *pd );
|
void ( *destroy )( struct _Switcher *pd );
|
||||||
// Token match.
|
// Token match.
|
||||||
menu_match_cb token_match;
|
menu_match_cb token_match;
|
||||||
|
|
||||||
|
get_display_value mgrv;
|
||||||
|
|
||||||
// Pointer to private data.
|
// Pointer to private data.
|
||||||
void *private_data;
|
void *private_data;
|
||||||
|
|
||||||
// Extra fields for script
|
// Extra fields for script
|
||||||
void *ed;
|
void *ed;
|
||||||
// Free SWitcher
|
// Free SWitcher
|
||||||
switcher_free free;
|
switcher_free free;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@ typedef struct
|
||||||
XIM xim;
|
XIM xim;
|
||||||
XIC xic;
|
XIC xic;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
|
int tbft;
|
||||||
} textbox;
|
} textbox;
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,11 +35,15 @@ typedef enum
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
// Render font normally
|
// Render font normally
|
||||||
NORMAL,
|
NORMAL = 1,
|
||||||
// Alternating row.
|
// Alternating row.
|
||||||
ALT,
|
ALT = 2,
|
||||||
// Render font highlighted (inverted colors.)
|
// Render font highlighted (inverted colors.)
|
||||||
HIGHLIGHT,
|
HIGHLIGHT = 4,
|
||||||
|
|
||||||
|
STATE_MASK = ( NORMAL | ALT | HIGHLIGHT ),
|
||||||
|
|
||||||
|
BOLD = 8,
|
||||||
} TextBoxFontType;
|
} TextBoxFontType;
|
||||||
|
|
||||||
textbox* textbox_create ( Window parent,
|
textbox* textbox_create ( Window parent,
|
||||||
|
|
|
@ -29,8 +29,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <rofi.h>
|
#include <rofi.h>
|
||||||
|
|
||||||
extern unsigned int num_switchers;
|
#include <dialogs/run.h>
|
||||||
extern Switcher **switchers;
|
#include <dialogs/ssh.h>
|
||||||
|
#include <dialogs/window.h>
|
||||||
|
#include <dialogs/script.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combi Switcher
|
* Combi Switcher
|
||||||
*/
|
*/
|
||||||
|
@ -45,28 +48,64 @@ typedef struct _CombiModePrivateData
|
||||||
// List of switchers to combine.
|
// List of switchers to combine.
|
||||||
unsigned int num_switchers;
|
unsigned int num_switchers;
|
||||||
Switcher **switchers;
|
Switcher **switchers;
|
||||||
|
char *cache;
|
||||||
} CombiModePrivateData;
|
} CombiModePrivateData;
|
||||||
|
|
||||||
static void combi_add_switcher ( Switcher *sw, Switcher *m )
|
static void combi_mode_parse_switchers ( Switcher *sw )
|
||||||
{
|
{
|
||||||
CombiModePrivateData *pd = sw->private_data;
|
CombiModePrivateData *pd = sw->private_data;
|
||||||
pd->switchers = g_realloc ( pd->switchers, ( pd->num_switchers + 2 ) * sizeof ( Switcher * ) );
|
char *savept = NULL;
|
||||||
pd->switchers[pd->num_switchers] = m;
|
// Make a copy, as strtok will modify it.
|
||||||
pd->switchers[pd->num_switchers + 1] = NULL;
|
char *switcher_str = g_strdup ( config.combi_modi );
|
||||||
pd->num_switchers++;
|
// 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 )
|
static void combi_mode_init ( Switcher *sw )
|
||||||
{
|
{
|
||||||
if ( sw->private_data == NULL ) {
|
if ( sw->private_data == NULL ) {
|
||||||
CombiModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
|
CombiModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
|
||||||
sw->private_data = (void *) pd;
|
sw->private_data = (void *) pd;
|
||||||
for ( unsigned int i = 0; i < num_switchers; i++ ) {
|
combi_mode_parse_switchers ( sw );
|
||||||
if ( switchers[i] != sw ) {
|
|
||||||
combi_add_switcher ( sw, switchers[i] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pd->starts = g_malloc0 ( sizeof ( int ) * pd->num_switchers );
|
pd->starts = g_malloc0 ( sizeof ( int ) * pd->num_switchers );
|
||||||
pd->lengths = 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 )
|
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->cmd_list );
|
||||||
g_free ( pd->starts );
|
g_free ( pd->starts );
|
||||||
g_free ( pd->lengths );
|
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->switchers );
|
||||||
g_free ( pd );
|
g_free ( pd );
|
||||||
|
g_free ( pd->cache );
|
||||||
sw->private_data = NULL;
|
sw->private_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,6 +182,21 @@ static int combi_mode_match ( char **tokens, const char *input,
|
||||||
abort ();
|
abort ();
|
||||||
return 0;
|
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 =
|
Switcher combi_mode =
|
||||||
{
|
{
|
||||||
|
@ -151,6 +210,7 @@ Switcher combi_mode =
|
||||||
.result = combi_mode_result,
|
.result = combi_mode_result,
|
||||||
.destroy = combi_mode_destroy,
|
.destroy = combi_mode_destroy,
|
||||||
.token_match = combi_mode_match,
|
.token_match = combi_mode_match,
|
||||||
|
.mgrv = combi_mgrv,
|
||||||
.private_data = NULL,
|
.private_data = NULL,
|
||||||
.free = NULL
|
.free = NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,6 +64,12 @@ static char **get_dmenu ( int *length )
|
||||||
return retv;
|
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 )
|
int dmenu_switcher_dialog ( char **input )
|
||||||
{
|
{
|
||||||
char *dmenu_prompt = "dmenu ";
|
char *dmenu_prompt = "dmenu ";
|
||||||
|
@ -84,7 +90,7 @@ int dmenu_switcher_dialog ( char **input )
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int mretv = menu ( list, length, input, dmenu_prompt,
|
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.
|
// We normally do not want to restart the loop.
|
||||||
restart = FALSE;
|
restart = FALSE;
|
||||||
|
|
|
@ -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 =
|
Switcher run_mode =
|
||||||
{
|
{
|
||||||
.name = "run",
|
.name = "run",
|
||||||
|
@ -343,6 +349,7 @@ Switcher run_mode =
|
||||||
.result = run_mode_result,
|
.result = run_mode_result,
|
||||||
.destroy = run_mode_destroy,
|
.destroy = run_mode_destroy,
|
||||||
.token_match = token_match,
|
.token_match = token_match,
|
||||||
|
.mgrv = mgrv,
|
||||||
.private_data = NULL,
|
.private_data = NULL,
|
||||||
.free = NULL
|
.free = NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,6 +163,11 @@ static void script_mode_destroy ( Switcher *sw )
|
||||||
sw->private_data = NULL;
|
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 )
|
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->result = script_mode_result;
|
||||||
sw->destroy = script_mode_destroy;
|
sw->destroy = script_mode_destroy;
|
||||||
sw->token_match = token_match;
|
sw->token_match = token_match;
|
||||||
|
sw->mgrv = mgrv;
|
||||||
|
|
||||||
return sw;
|
return sw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 =
|
Switcher ssh_mode =
|
||||||
{
|
{
|
||||||
.name = "ssh",
|
.name = "ssh",
|
||||||
|
@ -333,6 +339,7 @@ Switcher ssh_mode =
|
||||||
.result = ssh_mode_result,
|
.result = ssh_mode_result,
|
||||||
.destroy = ssh_mode_destroy,
|
.destroy = ssh_mode_destroy,
|
||||||
.token_match = token_match,
|
.token_match = token_match,
|
||||||
|
.mgrv = mgrv,
|
||||||
.private_data = NULL,
|
.private_data = NULL,
|
||||||
.free = NULL
|
.free = NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -286,6 +286,9 @@ typedef struct _SwitcherModePrivateData
|
||||||
winlist *ids;
|
winlist *ids;
|
||||||
int config_i3_mode;
|
int config_i3_mode;
|
||||||
int init;
|
int init;
|
||||||
|
// Current window.
|
||||||
|
unsigned int index;
|
||||||
|
char *cache;
|
||||||
} SwitcherModePrivateData;
|
} SwitcherModePrivateData;
|
||||||
|
|
||||||
static int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input,
|
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 );
|
winlist_free ( rmpd->ids );
|
||||||
i3_support_free_internals ();
|
i3_support_free_internals ();
|
||||||
x11_cache_free ();
|
x11_cache_free ();
|
||||||
|
g_free ( rmpd->cache );
|
||||||
g_free ( rmpd );
|
g_free ( rmpd );
|
||||||
sw->private_data = NULL;
|
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 =
|
Switcher window_mode =
|
||||||
{
|
{
|
||||||
.name = "window",
|
.name = "window",
|
||||||
|
@ -513,6 +526,7 @@ Switcher window_mode =
|
||||||
.result = window_mode_result,
|
.result = window_mode_result,
|
||||||
.destroy = window_mode_destroy,
|
.destroy = window_mode_destroy,
|
||||||
.token_match = window_match,
|
.token_match = window_match,
|
||||||
|
.mgrv = mgrv,
|
||||||
.private_data = NULL,
|
.private_data = NULL,
|
||||||
.free = NULL
|
.free = NULL
|
||||||
};
|
};
|
||||||
|
|
125
source/rofi.c
125
source/rofi.c
|
@ -272,51 +272,52 @@ static Window create_window ( Display *display )
|
||||||
|
|
||||||
typedef struct MenuState
|
typedef struct MenuState
|
||||||
{
|
{
|
||||||
unsigned int menu_lines;
|
unsigned int menu_lines;
|
||||||
unsigned int max_elements;
|
unsigned int max_elements;
|
||||||
unsigned int max_rows;
|
unsigned int max_rows;
|
||||||
unsigned int columns;
|
unsigned int columns;
|
||||||
|
|
||||||
// window width,height
|
// window width,height
|
||||||
unsigned int w, h;
|
unsigned int w, h;
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned int element_width;
|
unsigned int element_width;
|
||||||
|
|
||||||
// Update/Refilter list.
|
// Update/Refilter list.
|
||||||
int update;
|
int update;
|
||||||
int refilter;
|
int refilter;
|
||||||
int rchanged;
|
int rchanged;
|
||||||
int cur_page;
|
int cur_page;
|
||||||
|
|
||||||
// Entries
|
// Entries
|
||||||
textbox *text;
|
textbox *text;
|
||||||
textbox *prompt_tb;
|
textbox *prompt_tb;
|
||||||
textbox *case_indicator;
|
textbox *case_indicator;
|
||||||
textbox *arrowbox_top;
|
textbox *arrowbox_top;
|
||||||
textbox *arrowbox_bottom;
|
textbox *arrowbox_bottom;
|
||||||
textbox **boxes;
|
textbox **boxes;
|
||||||
char **filtered;
|
int *distance;
|
||||||
int *distance;
|
int *line_map;
|
||||||
int *line_map;
|
|
||||||
|
|
||||||
unsigned int num_lines;
|
unsigned int num_lines;
|
||||||
|
|
||||||
// Selected element.
|
// Selected element.
|
||||||
unsigned int selected;
|
unsigned int selected;
|
||||||
unsigned int filtered_lines;
|
unsigned int filtered_lines;
|
||||||
// Last offset in paginating.
|
// Last offset in paginating.
|
||||||
unsigned int last_offset;
|
unsigned int last_offset;
|
||||||
|
|
||||||
KeySym prev_key;
|
KeySym prev_key;
|
||||||
Time last_button_press;
|
Time last_button_press;
|
||||||
|
|
||||||
int quit;
|
int quit;
|
||||||
int init;
|
int init;
|
||||||
// Return state
|
// Return state
|
||||||
int *selected_line;
|
int *selected_line;
|
||||||
MenuReturn retv;
|
MenuReturn retv;
|
||||||
char **lines;
|
char **lines;
|
||||||
int line_height;
|
int line_height;
|
||||||
|
get_display_value mgrv;
|
||||||
|
void *mgrv_data;
|
||||||
}MenuState;
|
}MenuState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,7 +338,6 @@ static void menu_free_state ( MenuState *state )
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free ( state->boxes );
|
g_free ( state->boxes );
|
||||||
g_free ( state->filtered );
|
|
||||||
g_free ( state->line_map );
|
g_free ( state->line_map );
|
||||||
g_free ( state->distance );
|
g_free ( state->distance );
|
||||||
}
|
}
|
||||||
|
@ -575,15 +575,9 @@ static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned in
|
||||||
}
|
}
|
||||||
else if ( key == XK_Tab ) {
|
else if ( key == XK_Tab ) {
|
||||||
if ( state->filtered_lines == 1 ) {
|
if ( state->filtered_lines == 1 ) {
|
||||||
if ( state->filtered[state->selected] ) {
|
state->retv = MENU_OK;
|
||||||
state->retv = MENU_OK;
|
*( state->selected_line ) = state->line_map[state->selected];
|
||||||
*( state->selected_line ) = state->line_map[state->selected];
|
state->quit = 1;
|
||||||
state->quit = 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
fprintf ( stderr, "We should never hit this." );
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +630,7 @@ static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned in
|
||||||
}
|
}
|
||||||
else if ( key == XK_space && ( modstate & ControlMask ) == ControlMask ) {
|
else if ( key == XK_space && ( modstate & ControlMask ) == ControlMask ) {
|
||||||
// If a valid item is selected, return that..
|
// 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_text ( state->text, state->lines[state->line_map[state->selected]] );
|
||||||
textbox_cursor_end ( state->text );
|
textbox_cursor_end ( state->text );
|
||||||
state->update = TRUE;
|
state->update = TRUE;
|
||||||
|
@ -753,13 +747,6 @@ static void menu_refilter ( MenuState *state, char **lines, menu_match_cb mmc, v
|
||||||
if ( sorting ) {
|
if ( sorting ) {
|
||||||
qsort_r ( state->line_map, j, sizeof ( int ), lev_sort, state->distance );
|
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.
|
// Cleanup + bookkeeping.
|
||||||
state->filtered_lines = j;
|
state->filtered_lines = j;
|
||||||
|
@ -767,7 +754,6 @@ static void menu_refilter ( MenuState *state, char **lines, menu_match_cb mmc, v
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for ( unsigned int i = 0; i < state->num_lines; i++ ) {
|
for ( unsigned int i = 0; i < state->num_lines; i++ ) {
|
||||||
state->filtered[i] = lines[i];
|
|
||||||
state->line_map[i] = i;
|
state->line_map[i] = i;
|
||||||
}
|
}
|
||||||
state->filtered_lines = state->num_lines;
|
state->filtered_lines = state->num_lines;
|
||||||
|
@ -841,9 +827,10 @@ static void menu_draw ( MenuState *state )
|
||||||
ex + x_offset, ey + y_offset,
|
ex + x_offset, ey + y_offset,
|
||||||
element_width, element_height );
|
element_width, element_height );
|
||||||
{
|
{
|
||||||
TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT;
|
TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT;
|
||||||
char *text = state->filtered[i + offset];
|
int fstate = 0;
|
||||||
TextBoxFontType tbft = ( i + offset ) == state->selected ? HIGHLIGHT : type;
|
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_font ( state->boxes[i], tbft );
|
||||||
textbox_text ( state->boxes[i], text );
|
textbox_text ( state->boxes[i], text );
|
||||||
}
|
}
|
||||||
|
@ -855,8 +842,10 @@ static void menu_draw ( MenuState *state )
|
||||||
else{
|
else{
|
||||||
// Only do basic redrawing + highlight of row.
|
// Only do basic redrawing + highlight of row.
|
||||||
for ( i = 0; i < max_elements; i++ ) {
|
for ( i = 0; i < max_elements; i++ ) {
|
||||||
TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT;
|
TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT;
|
||||||
TextBoxFontType tbft = ( i + offset ) == state->selected ? HIGHLIGHT : type;
|
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_font ( state->boxes[i], tbft );
|
||||||
textbox_draw ( state->boxes[i] );
|
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,
|
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;
|
int shift = FALSE;
|
||||||
MenuState state = {
|
MenuState state = {
|
||||||
|
@ -940,11 +930,13 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
||||||
.filtered_lines = 0,
|
.filtered_lines = 0,
|
||||||
.max_elements = 0,
|
.max_elements = 0,
|
||||||
// We want to filter on the first run.
|
// We want to filter on the first run.
|
||||||
.refilter = TRUE,
|
.refilter = TRUE,
|
||||||
.update = FALSE,
|
.update = FALSE,
|
||||||
.rchanged = TRUE,
|
.rchanged = TRUE,
|
||||||
.cur_page = -1,
|
.cur_page = -1,
|
||||||
.lines = lines
|
.lines = lines,
|
||||||
|
.mgrv = mgrv,
|
||||||
|
.mgrv_data = mgrv_data
|
||||||
};
|
};
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
workarea mon;
|
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 );
|
config.padding + state.max_rows * element_height + LINE_MARGIN );
|
||||||
|
|
||||||
// filtered list
|
// filtered list
|
||||||
state.filtered = (char * *) g_malloc0_n ( state.num_lines, sizeof ( char* ) );
|
|
||||||
state.line_map = g_malloc0_n ( state.num_lines, sizeof ( int ) );
|
state.line_map = g_malloc0_n ( state.num_lines, sizeof ( int ) );
|
||||||
if ( sorting ) {
|
if ( sorting ) {
|
||||||
state.distance = (int *) g_malloc0_n ( state.num_lines, sizeof ( int ) );
|
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.
|
// Special delete entry command.
|
||||||
else if ( ( ( ev.xkey.state & ShiftMask ) == ShiftMask ) &&
|
else if ( ( ( ev.xkey.state & ShiftMask ) == ShiftMask ) &&
|
||||||
key == XK_Delete ) {
|
key == XK_Delete ) {
|
||||||
if ( state.filtered[state.selected] != NULL ) {
|
if ( state.selected < state.filtered_lines ) {
|
||||||
*( state.selected_line ) = state.line_map[state.selected];
|
*( state.selected_line ) = state.line_map[state.selected];
|
||||||
state.retv = MENU_ENTRY_DELETE;
|
state.retv = MENU_ENTRY_DELETE;
|
||||||
state.quit = TRUE;
|
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 );
|
shift = ( ( ev.xkey.state & ShiftMask ) == ShiftMask );
|
||||||
|
|
||||||
// If a valid item is selected, return that..
|
// 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];
|
*( state.selected_line ) = state.line_map[state.selected];
|
||||||
if ( strlen ( state.text->text ) > 0 && rc == -2 ) {
|
if ( strlen ( state.text->text ) > 0 && rc == -2 ) {
|
||||||
state.retv = MENU_CUSTOM_INPUT;
|
state.retv = MENU_CUSTOM_INPUT;
|
||||||
|
@ -1836,7 +1827,9 @@ SwitcherMode switcher_run ( char **input, Switcher *sw )
|
||||||
input, prompt,
|
input, prompt,
|
||||||
sw->token_match, sw,
|
sw->token_match, sw,
|
||||||
&selected_line,
|
&selected_line,
|
||||||
config.levenshtein_sort );
|
config.levenshtein_sort,
|
||||||
|
sw->mgrv,
|
||||||
|
sw );
|
||||||
|
|
||||||
SwitcherMode retv = sw->result ( mretv, input, selected_line, sw );
|
SwitcherMode retv = sw->result ( mretv, input, selected_line, sw );
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,6 @@ textbox* textbox_create ( Window parent,
|
||||||
|
|
||||||
tb->layout = pango_layout_new ( p_context );
|
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;
|
unsigned int cp;
|
||||||
switch ( tbft )
|
switch ( tbft )
|
||||||
{
|
{
|
||||||
|
@ -104,6 +100,8 @@ textbox* textbox_create ( Window parent,
|
||||||
InputOutput, vinfo->visual, CWColormap | CWBorderPixel | CWBackPixel, &attr );
|
InputOutput, vinfo->visual, CWColormap | CWBorderPixel | CWBackPixel, &attr );
|
||||||
|
|
||||||
// need to preload the font to calc line height
|
// need to preload the font to calc line height
|
||||||
|
// Force update of font descriptor.
|
||||||
|
tb->tbft = ~tbft;
|
||||||
textbox_font ( tb, tbft );
|
textbox_font ( tb, tbft );
|
||||||
|
|
||||||
textbox_text ( tb, text ? text : "" );
|
textbox_text ( tb, text ? text : "" );
|
||||||
|
@ -129,7 +127,15 @@ textbox* textbox_create ( Window parent,
|
||||||
// set an Xft font by name
|
// set an Xft font by name
|
||||||
void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
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:
|
case HIGHLIGHT:
|
||||||
tb->color_bg = color_hlbg;
|
tb->color_bg = color_hlbg;
|
||||||
|
@ -145,6 +151,7 @@ void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
||||||
tb->color_fg = color_fg;
|
tb->color_fg = color_fg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
tb->tbft = tbft;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the default text to display
|
// set the default text to display
|
||||||
|
|
|
@ -105,7 +105,8 @@ static XrmOption xrmOptions[] = {
|
||||||
{ xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL },
|
{ xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL },
|
||||||
{ xrm_SNumber, "eh", { .snum = &config.element_height }, NULL },
|
{ xrm_SNumber, "eh", { .snum = &config.element_height }, NULL },
|
||||||
{ xrm_Boolean, "auto-select", { .num = &config.auto_select }, 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.
|
// Dynamic options.
|
||||||
|
|
Loading…
Reference in New Issue