/* xmenu * a simple fuzzy-selection menu made with Xlib */ #include #define ARENA_IMPL #define STR_IMPL #include "arena.h" #include "dynarr.h" #include "str.h" #include "ui.h" typedef DYNARR(char) DynStr; int umod(int a, int b) { if (a < 0) { return b + a % b; } else { return a % b; } } int txt_insert(DynStr *s, int i, Str ins) { DA_FIT(s, s->n + ins.n); if (i < s->n) { memmove(s->v + i + ins.n, s->v + i, s->n - i); } memcpy(s->v + i, ins.s, ins.n); s->n += ins.n; return i + ins.n; } int txt_delete(DynStr *s, int i, int n) { if (n > i) n = i; if (n > 0) { memmove(s->v + i - n, s->v + i, s->n - i); s->n -= n; } return i - n; } int main(int argc, char **argv) { ui_init(argc, argv); DynStr input = { 0 }; int inpi = 0; int seli = 0; Str optv[] = { S("she shit on my thang until i vomit"), S("what"), S("who are you"), S("why are you"), S("where'd you come from") }; int optc = sizeof optv / sizeof *optv; if (!optc) goto done; for (UiEvent ev; ui_wait_event(&ev); ) { switch (ev.type) { case UI_KEY_DOWN: switch (ev.key.key) { case UIK_ESCAPE: goto done; case UIK_BACKSPACE: inpi = txt_delete(&input, inpi, 1); goto draw; case UIK_RETURN: { Str o = optv[seli]; printf("%.*s\n", (int)o.n, o.s); } goto done; case UIK_DOWN: seli = umod(seli + 1, optc); goto draw; case UIK_UP: seli = umod(seli - 1, optc); goto draw; case UIK_LEFT: if (inpi > 0) inpi--; goto draw; case UIK_RIGHT: if (inpi < input.n) inpi++; goto draw; case UIK_HOME: inpi = 0; goto draw; case UIK_END: inpi = input.n; goto draw; default: if (!ev.key.strn) break; inpi = txt_insert(&input, inpi, (Str) { ev.key.str, ev.key.strn }); seli = 0; goto draw; } break; case UI_REDRAW: draw: ui_draw( (Str) { input.v, input.n }, inpi, seli, optv, optc ); break; default: break; } } done: ui_fini(); return 0; }