commit - 844addbb3803e8f077087ce69fdaaf32b0ea4395
commit + c392d7270046bfa46e5891c9b6f4c731fbd56a4d
blob - e4558fc6d4f892c6bb22a6710c205cdb3ced7dcd
blob + 637c9fc52c07bdb82eb7c29d6845deb53a0982a0
--- mymenu.c
+++ mymenu.c
# define strcasestr strstr
#endif
+// The initial number of items to read
#define INITIAL_ITEMS 64
+// Abort if a is nil
#define check_allocation(a) { \
if (a == nil) { \
fprintf(stderr, "Could not allocate memory\n"); \
TOGGLE_FIRST_SELECTED
};
+// A big set of values that needs to be carried around (for drawing
+// functions). A struct to rule them all
struct rendering {
Display *d; // connection to xorg
Window w;
struct completion *next;
};
+// Wrap the linked list of completions
struct completions {
struct completion *completions;
int selected;
return cs;
}
+// Return a newly allocated (and empty) completion
struct completion *compl_new() {
struct completion *c = malloc(sizeof(struct completion));
if (c == nil)
}
}
+// Delete the wrapper and the whole list
void compls_delete(struct completions *cs) {
if (cs == nil)
return;
(*p)[len] = c;
(*p)[len+1] = '\0';
return maxlen;
-}
-
-// return the number of character
-int utf8strnlen(char *s, int maxlen) {
- int len = 0;
- while (*s && maxlen > 0) {
- len += (*s++ & 0xc0) != 0x80;
- maxlen--;
- }
- return len;
}
-// remove the last *glyph* from the *utf8* string!
-// this is different from just setting the last byte to 0 (in some
-// cases ofc). The actual implementation is quite inefficient because
-// it remove the last byte until the number of glyphs doesn't change
-void popc(char *p, int maxlen) {
- int len = strnlen(p, maxlen);
+// remove the last rune from the *utf8* string! This is different from
+// just setting the last byte to 0 (in some cases ofc).
+void popc(char *p) {
+ int len = strlen(p);
if (len == 0)
return;
- int ulen = utf8strnlen(p, maxlen);
- while (len > 0 && utf8strnlen(p, maxlen) == ulen) {
- len--;
- p[len] = 0;
- }
+ char *e = p + len - 1;
+
+ do {
+ char c = *e;
+ *e = 0;
+ e--;
+
+ // if c is a starting byte (11......) or is under U+007F (ascii,
+ // basically) we're done
+ if (((c & 0x80) && (c & 0x40)) || !(c & 0x80))
+ break;
+ } while (e >= p);
}
// If the string is surrounded by quotes (`"`) remove them and replace
// by default the first completion isn't selected
bool first_selected = false;
+ // our parent window
char *parent_window_id = nil;
// first round of args parsing
}
}
+ // read the lines from stdin
char **lines = calloc(INITIAL_ITEMS, sizeof(char*));
readlines(&lines, INITIAL_ITEMS);
if (XrmGetResource(xdb, "MyMenu.font", "*", datatype, &value) == true) {
fontname = strdup(value.addr);
check_allocation(fontname);
- }
- else
+ } else {
fprintf(stderr, "no font defined, using %s\n", fontname);
+ }
- if (XrmGetResource(xdb, "MyMenu.layout", "*", datatype, &value) == true) {
+ if (XrmGetResource(xdb, "MyMenu.layout", "*", datatype, &value) == true)
horizontal_layout = !strcmp(value.addr, "horizontal");
- }
else
fprintf(stderr, "no layout defined, using horizontal\n");
if (XrmGetResource(xdb, "MyMenu.prompt", "*", datatype, &value) == true) {
free(ps1);
ps1 = normalize_str(value.addr);
- } else
+ } else {
fprintf(stderr, "no prompt defined, using \"%s\" as default\n", ps1);
+ }
if (XrmGetResource(xdb, "MyMenu.width", "*", datatype, &value) == true)
width = parse_int_with_percentage(value.addr, width, d_width);
}
case DEL_CHAR:
- popc(text, textlen);
+ popc(text);
update_completions(cs, text, lines, first_selected);
break;