Add support for msg string with pango markup.

This commit is contained in:
QC 2015-05-23 20:06:06 +02:00
parent 48d8d09831
commit a93aec02bd
7 changed files with 117 additions and 18 deletions

View File

@ -529,6 +529,10 @@ The following options are further explained in the theming section:
Preset user filter to *filter* in the entry box and pre-filter the list.
`-mesg` *str*
Add a message line beneath filter. Supports pango markdown.
### Message dialog
`-e` *message*

View File

@ -695,6 +695,14 @@ Default: 's'
Preset user filter to *filter* in the entry box and pre\-filter the list.
.fi
.RE
.PP
\fB\fC\-mesg\fR \fIstr\fP
.PP
.RS
.nf
Add a message line beneath filter. Supports pango markdown.
.fi
.RE
.SS Message dialog
.PP
\fB\fC\-e\fR \fImessage\fP

View File

@ -87,6 +87,7 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int case_sensi
* @param mmc Menu menu match callback, used for matching user input.
* @param mmc_data data to pass to mmc.
* @param selected_line pointer to integer holding the selected line.
* @param message Extra message to display.
*
* Main menu callback.
*
@ -94,8 +95,8 @@ 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,
get_display_value mgrv, void *mgrv_data, int *next_pos ) __attribute__ ( ( nonnull ( 1, 3,
4, 7 ) ) );
get_display_value mgrv, void *mgrv_data, int *next_pos, const char *message ) __attribute__ ( ( nonnull ( 1, 3,
4, 7 ) ) );
/**
* @param sig The caught signal
*

View File

@ -18,6 +18,8 @@ typedef struct
XIC xic;
PangoLayout *layout;
int tbft;
int markup;
int changed;
} textbox;
@ -29,6 +31,7 @@ typedef enum
TB_RIGHT = 1 << 17,
TB_CENTER = 1 << 18,
TB_EDITABLE = 1 << 19,
TB_MARKUP = 1 << 20,
} TextboxFlags;
@ -240,4 +243,7 @@ void textbox_delete ( textbox *tb, int pos, int dlen );
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
int textbox_get_estimated_char_height ( void );
void textbox_text_markup ( textbox *tb, const char *text );
#endif //__TEXTBOX_H__

View File

@ -186,6 +186,10 @@ int dmenu_switcher_dialog ( char **input )
int length = 0;
char **list = get_dmenu ( &length );
int restart = FALSE;
char *message = NULL;
find_arg_str ( "-mesg", &message );
// By default we print the unescaped line back.
char *format = "s";
@ -238,7 +242,7 @@ int dmenu_switcher_dialog ( char **input )
do {
int next_pos = selected_line;
int mretv = menu ( list, length, input, dmenu_prompt,
token_match, NULL, &selected_line, config.levenshtein_sort, get_display_data, list, &next_pos );
token_match, NULL, &selected_line, config.levenshtein_sort, get_display_data, list, &next_pos, message );
// Special behavior.
if ( only_selected ) {
/**

View File

@ -280,6 +280,7 @@ typedef struct MenuState
unsigned int w, h;
int x, y;
unsigned int element_width;
int top_offset;
// Update/Refilter list.
int update;
@ -290,6 +291,7 @@ typedef struct MenuState
// Entries
textbox *text;
textbox *prompt_tb;
textbox *message_tb;
textbox *case_indicator;
textbox *arrowbox_top;
textbox *arrowbox_bottom;
@ -798,7 +800,7 @@ static void menu_draw ( MenuState *state )
}
int element_height = state->line_height * config.element_height;
int y_offset = config.padding + state->line_height;
int y_offset = state->top_offset;
int x_offset = config.padding;
// Calculate number of visible rows.
unsigned int max_elements = MIN ( a_lines, state->max_rows * columns );
@ -850,6 +852,9 @@ static void menu_update ( MenuState *state )
textbox_draw ( state->case_indicator );
textbox_draw ( state->prompt_tb );
textbox_draw ( state->text );
if ( state->message_tb ) {
textbox_draw ( state->message_tb );
}
menu_draw ( state );
menu_set_arrow_text ( state->filtered_lines, state->selected,
state->max_elements, state->arrowbox_top,
@ -859,6 +864,13 @@ static void menu_update ( MenuState *state )
state->line_height + ( config.padding ) + ( LINE_MARGIN ) / 2,
state->w - ( ( config.padding ) ) - 1,
state->line_height + ( config.padding ) + ( LINE_MARGIN ) / 2 );
if ( state->message_tb ) {
XDrawLine ( display, main_window, gc,
( config.padding ),
state->top_offset + ( LINE_MARGIN ) / 2,
state->w - ( ( config.padding ) ) - 1,
state->top_offset + ( LINE_MARGIN ) / 2 );
}
if ( config.sidebar_mode == TRUE ) {
XDrawLine ( display, main_window, gc,
@ -904,7 +916,7 @@ 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,
get_display_value mgrv, void *mgrv_data, int *next_pos )
get_display_value mgrv, void *mgrv_data, int *next_pos, const char *message )
{
int shift = FALSE;
MenuState state = {
@ -919,13 +931,14 @@ 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,
.mgrv = mgrv,
.mgrv_data = mgrv_data
.refilter = TRUE,
.update = FALSE,
.rchanged = TRUE,
.cur_page = -1,
.lines = lines,
.mgrv = mgrv,
.mgrv_data = mgrv_data,
.top_offset = 0
};
unsigned int i;
if ( next_pos ) {
@ -986,6 +999,9 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
entrybox_width, state.line_height,
NORMAL,
*input );
state.top_offset = config.padding + state.line_height;
// Move indicator to end.
textbox_move ( state.case_indicator,
config.padding + textbox_get_width ( state.prompt_tb ) + entrybox_width,
@ -998,11 +1014,25 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
textbox_show ( state.case_indicator );
}
state.message_tb = NULL;
if ( message ) {
state.top_offset += config.menu_bw;
state.message_tb = textbox_create ( main_window, &vinfo, map, TB_AUTOHEIGHT | TB_MARKUP,
( config.padding ),
state.top_offset,
entrybox_width, -1,
NORMAL,
message );
textbox_show ( state.message_tb );
state.top_offset += textbox_get_height ( state.message_tb );
state.top_offset += config.menu_bw;
}
int element_height = state.line_height * config.element_height;
// filtered list display
state.boxes = g_malloc0_n ( state.max_elements, sizeof ( textbox* ) );
int y_offset = config.padding + state.line_height;
int y_offset = state.top_offset;
int x_offset = config.padding;
for ( i = 0; i < state.max_elements; i++ ) {
@ -1022,7 +1052,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
"" );
textbox_move ( state.arrowbox_top,
state.w - config.padding - state.arrowbox_top->w,
config.padding + state.line_height + LINE_MARGIN );
state.top_offset + LINE_MARGIN );
// TODO calculate from top.
textbox_move ( state.arrowbox_bottom,
state.w - config.padding - state.arrowbox_bottom->w,
@ -1036,7 +1066,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
// resize window vertically to suit
// Subtract the margin of the last row.
state.h = state.line_height + element_height * state.max_rows + ( config.padding ) * 2 + LINE_MARGIN;
state.h = state.top_offset + element_height * state.max_rows + ( config.padding ) + LINE_MARGIN;
// Add entry
if ( config.sidebar_mode == TRUE ) {
@ -1936,7 +1966,7 @@ SwitcherMode switcher_run ( char **input, Switcher *sw )
&selected_line,
config.levenshtein_sort,
sw->mgrv,
sw, NULL );
sw, NULL, NULL );
SwitcherMode retv = sw->result ( mretv, input, selected_line, sw );

View File

@ -89,6 +89,9 @@ textbox* textbox_create ( Window parent,
tb->layout = pango_layout_new ( p_context );
tb->markup = FALSE;
tb->changed = FALSE;
unsigned int cp;
switch ( tbft )
{
@ -115,7 +118,12 @@ textbox* textbox_create ( Window parent,
pango_font_description_free ( pfd );
textbox_font ( tb, tbft );
textbox_text ( tb, text ? text : "" );
if ( ( flags & TB_MARKUP ) == TB_MARKUP ) {
textbox_text_markup ( tb, text ? text : "" );
}
else{
textbox_text ( tb, text ? text : "" );
}
textbox_cursor_end ( tb );
// auto height/width modes get handled here
@ -180,6 +188,32 @@ void textbox_text ( textbox *tb, const char *text )
}
tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
}
// set the default text to display
void textbox_text_markup ( textbox *tb, const char *text )
{
g_free ( tb->text );
const gchar *last_pointer = NULL;
if ( g_utf8_validate ( text, -1, &last_pointer ) ) {
tb->text = g_strdup ( text );
}
else {
if ( last_pointer != NULL ) {
// Copy string up to invalid character.
tb->text = g_strndup ( text, ( last_pointer - text ) );
}
else {
tb->text = g_strdup ( "Invalid UTF-8 string." );
}
}
tb->markup = TRUE;
pango_layout_set_markup ( tb->layout, tb->text, strlen ( tb->text ) );
if ( tb->flags & TB_AUTOWIDTH ) {
textbox_moveresize ( tb, tb->x, tb->y, tb->w, tb->h );
}
tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
}
@ -274,7 +308,14 @@ void textbox_draw ( textbox *tb )
int cursor_x = 0;
int cursor_width = MAX ( 2, font_height / 10 );
pango_layout_set_text ( tb->layout, text, text_len );
if ( tb->changed ) {
if ( tb->markup ) {
pango_layout_set_markup ( tb->layout, text, text_len );
}
else{
pango_layout_set_text ( tb->layout, text, text_len );
}
}
if ( tb->flags & TB_EDITABLE ) {
PangoRectangle pos;
@ -443,6 +484,9 @@ void textbox_insert ( textbox *tb, int pos, char *str )
memmove ( at + slen, at, len - pos + 1 );
// insert new str
memmove ( at, str, slen );
// Set modified, lay out need te be redrawn
tb->changed = TRUE;
}
// remove text
@ -460,6 +504,8 @@ void textbox_delete ( textbox *tb, int pos, int dlen )
else if ( tb->cursor >= ( pos + dlen ) ) {
tb->cursor -= dlen;
}
// Set modified, lay out need te be redrawn
tb->changed = TRUE;
}
// delete on character