Add more rendering functions
This commit is contained in:
parent
f9167689dc
commit
96b3c0ef26
1 changed files with 64 additions and 54 deletions
118
main.c
118
main.c
|
@ -87,7 +87,7 @@ struct menu {
|
|||
uint32_t promptbg, promptfg;
|
||||
uint32_t selectionbg, selectionfg;
|
||||
|
||||
char text[BUFSIZ];
|
||||
char input[BUFSIZ];
|
||||
size_t cursor;
|
||||
|
||||
int repeat_timer;
|
||||
|
@ -199,15 +199,15 @@ static void match_items(struct menu *menu) {
|
|||
menu->matches_end = NULL;
|
||||
menu->sel = NULL;
|
||||
|
||||
size_t len = strlen(menu->text);
|
||||
size_t len = strlen(menu->input);
|
||||
|
||||
struct item *item;
|
||||
for (item = menu->items; item; item = item->next) {
|
||||
if (!menu->strncmp(menu->text, item->text, len + 1)) {
|
||||
if (!menu->strncmp(menu->input, item->text, len + 1)) {
|
||||
append_item(item, &lexact, &exactend);
|
||||
} else if (!menu->strncmp(menu->text, item->text, len)) {
|
||||
} else if (!menu->strncmp(menu->input, item->text, len)) {
|
||||
append_item(item, &lprefix, &prefixend);
|
||||
} else if (fstrstr(menu, item->text, menu->text)) {
|
||||
} else if (fstrstr(menu, item->text, menu->input)) {
|
||||
append_item(item, &lsubstr, &substrend);
|
||||
}
|
||||
}
|
||||
|
@ -242,13 +242,13 @@ static void match_items(struct menu *menu) {
|
|||
}
|
||||
|
||||
static void insert(struct menu *menu, const char *s, ssize_t n) {
|
||||
if (strlen(menu->text) + n > sizeof menu->text - 1) {
|
||||
if (strlen(menu->input) + n > sizeof menu->input - 1) {
|
||||
return;
|
||||
}
|
||||
memmove(menu->text + menu->cursor + n, menu->text + menu->cursor,
|
||||
sizeof menu->text - menu->cursor - MAX(n, 0));
|
||||
memmove(menu->input + menu->cursor + n, menu->input + menu->cursor,
|
||||
sizeof menu->input - menu->cursor - MAX(n, 0));
|
||||
if (n > 0 && s != NULL) {
|
||||
memcpy(menu->text + menu->cursor, s, n);
|
||||
memcpy(menu->input + menu->cursor, s, n);
|
||||
}
|
||||
menu->cursor += n;
|
||||
}
|
||||
|
@ -256,8 +256,8 @@ static void insert(struct menu *menu, const char *s, ssize_t n) {
|
|||
static size_t nextrune(struct menu *menu, int incr) {
|
||||
size_t n, len;
|
||||
|
||||
len = strlen(menu->text);
|
||||
for(n = menu->cursor + incr; n < len && (menu->text[n] & 0xc0) == 0x80; n += incr);
|
||||
len = strlen(menu->input);
|
||||
for(n = menu->cursor + incr; n < len && (menu->input[n] & 0xc0) == 0x80; n += incr);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ static void calc_widths(struct menu *menu) {
|
|||
|
||||
// Calculate prompt width
|
||||
if (menu->prompt) {
|
||||
menu->promptw = text_width(cairo, menu->font, menu->prompt);
|
||||
menu->promptw = text_width(cairo, menu->font, menu->prompt) + menu->padding + menu->padding/2;
|
||||
} else {
|
||||
menu->promptw = 0;
|
||||
}
|
||||
|
@ -293,6 +293,7 @@ static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
|
|||
(color >> (0*8) & 0xFF) / 255.0);
|
||||
}
|
||||
|
||||
// Renders text to cairo.
|
||||
static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
|
||||
int x, int y, int width, uint32_t bg_color, uint32_t fg_color,
|
||||
int left_padding, int right_padding) {
|
||||
|
@ -316,6 +317,34 @@ static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
|
|||
return width;
|
||||
}
|
||||
|
||||
// Renders the prompt message.
|
||||
static void render_prompt(struct menu *menu, cairo_t *cairo) {
|
||||
if (!menu->prompt) {
|
||||
return;
|
||||
}
|
||||
render_text(menu, cairo, menu->prompt, 0, 0, 0,
|
||||
menu->promptbg, menu->promptfg, menu->padding, menu->padding/2);
|
||||
}
|
||||
|
||||
// Renders the input text.
|
||||
static void render_input(struct menu *menu, cairo_t *cairo) {
|
||||
render_text(menu, cairo, menu->input, menu->promptw, 0, 0,
|
||||
0, menu->foreground, menu->padding, menu->padding);
|
||||
}
|
||||
|
||||
// Renders a cursor for the input field.
|
||||
static void render_cursor(struct menu *menu, cairo_t *cairo) {
|
||||
const int cursor_width = 2;
|
||||
const int cursor_margin = 2;
|
||||
int cursor_pos = menu->promptw + menu->padding
|
||||
+ text_width(cairo, menu->font, menu->input)
|
||||
- text_width(cairo, menu->font, &menu->input[menu->cursor])
|
||||
- cursor_width / 2;
|
||||
cairo_rectangle(cairo, cursor_pos, cursor_margin, cursor_width,
|
||||
menu->line_height - 2 * cursor_margin);
|
||||
cairo_fill(cairo);
|
||||
}
|
||||
|
||||
// Renders a single menu item horizontally.
|
||||
static int render_horizontal_item(struct menu *menu, cairo_t *cairo, struct item *item, int x) {
|
||||
uint32_t bg_color = menu->sel == item ? menu->selectionbg : menu->background;
|
||||
|
@ -362,41 +391,22 @@ static void render_vertical_page(struct menu *menu, cairo_t *cairo, struct page
|
|||
}
|
||||
}
|
||||
|
||||
static void render_to_cairo(struct menu *menu, cairo_t *cairo) {
|
||||
// Draw background
|
||||
// Renders the menu to cairo.
|
||||
static void render_menu(struct menu *menu, cairo_t *cairo) {
|
||||
// Render background
|
||||
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_u32(cairo, menu->background);
|
||||
cairo_paint(cairo);
|
||||
|
||||
int x = 0;
|
||||
|
||||
// Draw prompt
|
||||
if (menu->prompt) {
|
||||
x += render_text(menu, cairo, menu->prompt, 0, 0, 0,
|
||||
menu->promptbg, menu->promptfg, menu->padding, menu->padding/2);
|
||||
}
|
||||
|
||||
// Draw input
|
||||
render_text(menu, cairo, menu->text, x, 0, 0,
|
||||
0, menu->foreground, menu->padding, menu->padding);
|
||||
|
||||
// Draw cursor
|
||||
{
|
||||
const int cursor_width = 2;
|
||||
const int cursor_margin = 2;
|
||||
int cursor_pos = x + menu->padding
|
||||
+ text_width(cairo, menu->font, menu->text)
|
||||
- text_width(cairo, menu->font, &menu->text[menu->cursor])
|
||||
- cursor_width / 2;
|
||||
cairo_rectangle(cairo, cursor_pos, cursor_margin, cursor_width,
|
||||
menu->line_height - 2 * cursor_margin);
|
||||
cairo_fill(cairo);
|
||||
}
|
||||
// Render prompt and input
|
||||
render_prompt(menu, cairo);
|
||||
render_input(menu, cairo);
|
||||
render_cursor(menu, cairo);
|
||||
|
||||
// Render selected page
|
||||
if (!menu->sel) {
|
||||
return;
|
||||
}
|
||||
// Draw matches
|
||||
if (menu->vertical) {
|
||||
render_vertical_page(menu, cairo, menu->sel->page);
|
||||
} else {
|
||||
|
@ -417,7 +427,7 @@ static void render_frame(struct menu *menu) {
|
|||
cairo_paint(cairo);
|
||||
cairo_restore(cairo);
|
||||
|
||||
render_to_cairo(menu, cairo);
|
||||
render_menu(menu, cairo);
|
||||
|
||||
int scale = menu->output ? menu->output->scale : 1;
|
||||
menu->current = get_next_buffer(menu->shm,
|
||||
|
@ -537,7 +547,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
XKB_MOD_NAME_SHIFT,
|
||||
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
|
||||
|
||||
size_t len = strlen(menu->text);
|
||||
size_t len = strlen(menu->input);
|
||||
|
||||
if (ctrl) {
|
||||
// Emacs-style line editing bindings
|
||||
|
@ -588,7 +598,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
|
||||
case XKB_KEY_k:
|
||||
// Delete right
|
||||
menu->text[menu->cursor] = '\0';
|
||||
menu->input[menu->cursor] = '\0';
|
||||
match_items(menu);
|
||||
render_frame(menu);
|
||||
return;
|
||||
|
@ -600,10 +610,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
return;
|
||||
case XKB_KEY_w:
|
||||
// Delete word
|
||||
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] == ' ') {
|
||||
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
|
||||
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
||||
}
|
||||
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') {
|
||||
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') {
|
||||
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
||||
}
|
||||
match_items(menu);
|
||||
|
@ -643,10 +653,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
case XKB_KEY_Left:
|
||||
case XKB_KEY_KP_Left:
|
||||
// Move to beginning of word
|
||||
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] == ' ') {
|
||||
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
|
||||
menu->cursor = nextrune(menu, -1);
|
||||
}
|
||||
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') {
|
||||
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') {
|
||||
menu->cursor = nextrune(menu, -1);
|
||||
}
|
||||
render_frame(menu);
|
||||
|
@ -654,10 +664,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
case XKB_KEY_Right:
|
||||
case XKB_KEY_KP_Right:
|
||||
// Move to end of word
|
||||
while (menu->cursor < len && menu->text[menu->cursor] == ' ') {
|
||||
while (menu->cursor < len && menu->input[menu->cursor] == ' ') {
|
||||
menu->cursor = nextrune(menu, +1);
|
||||
}
|
||||
while (menu->cursor < len && menu->text[menu->cursor] != ' ') {
|
||||
while (menu->cursor < len && menu->input[menu->cursor] != ' ') {
|
||||
menu->cursor = nextrune(menu, +1);
|
||||
}
|
||||
render_frame(menu);
|
||||
|
@ -676,11 +686,11 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
case XKB_KEY_Return:
|
||||
case XKB_KEY_KP_Enter:
|
||||
if (shift) {
|
||||
puts(menu->text);
|
||||
puts(menu->input);
|
||||
fflush(stdout);
|
||||
menu->run = false;
|
||||
} else {
|
||||
char *text = menu->sel ? menu->sel->text : menu->text;
|
||||
char *text = menu->sel ? menu->sel->text : menu->input;
|
||||
puts(text);
|
||||
fflush(stdout);
|
||||
if (!ctrl) {
|
||||
|
@ -767,9 +777,9 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
if (!menu->sel) {
|
||||
return;
|
||||
}
|
||||
menu->cursor = strnlen(menu->sel->text, sizeof menu->text - 1);
|
||||
memcpy(menu->text, menu->sel->text, menu->cursor);
|
||||
menu->text[menu->cursor] = '\0';
|
||||
menu->cursor = strnlen(menu->sel->text, sizeof menu->input - 1);
|
||||
memcpy(menu->input, menu->sel->text, menu->cursor);
|
||||
menu->input[menu->cursor] = '\0';
|
||||
match_items(menu);
|
||||
render_frame(menu);
|
||||
break;
|
||||
|
@ -908,7 +918,7 @@ static const struct wl_registry_listener registry_listener = {
|
|||
};
|
||||
|
||||
static void read_stdin(struct menu *menu) {
|
||||
char buf[sizeof menu->text], *p;
|
||||
char buf[sizeof menu->input], *p;
|
||||
struct item *item, **end;
|
||||
|
||||
for(end = &menu->items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) {
|
||||
|
|
Loading…
Add table
Reference in a new issue