Add more rendering functions

This commit is contained in:
adnano 2024-02-26 16:44:23 -05:00
parent f9167689dc
commit 96b3c0ef26

118
main.c
View file

@ -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) {