X-Git-Url: https://git.xinqibao.xyz/dmenu.git/blobdiff_plain/518c9b72d1c84bde7de49c2fb04c0d0a7cbe725b..851672cadcd8e07533d9afa757186f58df7f92f2:/dmenu.c?ds=sidebyside diff --git a/dmenu.c b/dmenu.c index f93407d..2966954 100644 --- a/dmenu.c +++ b/dmenu.c @@ -19,6 +19,7 @@ #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80)) /* enums */ enum { ColFG, ColBG, ColLast }; @@ -42,8 +43,8 @@ typedef struct { typedef struct Item Item; struct Item { char *text; - Item *next; /* traverses all items */ - Item *left, *right; /* traverses items matching current search pattern */ + Item *next; /* traverses all items */ + Item *left, *right; /* traverses items matching current search pattern */ }; /* forward declarations */ @@ -85,8 +86,8 @@ static unsigned int numlockmask = 0; static Bool running = True; static Display *dpy; static DC dc; -static Item *allitems = NULL; /* first of all items */ -static Item *item = NULL; /* first of pattern matching items */ +static Item *allitems = NULL; /* first of all items */ +static Item *item = NULL; /* first of pattern matching items */ static Item *sel = NULL; static Item *next = NULL; static Item *prev = NULL; @@ -212,12 +213,12 @@ drawmenu(void) { dc.h = mh; drawtext(NULL, dc.norm); /* print prompt? */ - if(promptw) { + if(prompt) { dc.w = promptw; drawtext(prompt, dc.sel); + dc.x += dc.w; } - dc.x += promptw; - dc.w = mw - promptw; + dc.w = mw - dc.x; /* print command */ if(cmdw && item && lines == 0) dc.w = cmdw; @@ -241,14 +242,13 @@ drawmenuh(void) { dc.w = spaceitem; drawtext(curr->left ? "<" : NULL, dc.norm); dc.x += dc.w; - /* determine maximum items */ for(i = curr; i != next; i=i->right) { dc.w = MIN(textw(i->text), mw / 3); drawtext(i->text, (sel == i) ? dc.sel : dc.norm); dc.x += dc.w; } - dc.x = mw - spaceitem; dc.w = spaceitem; + dc.x = mw - dc.w; drawtext(next ? ">" : NULL, dc.norm); } @@ -256,10 +256,8 @@ void drawmenuv(void) { Item *i; - dc.x = 0; - dc.w = mw; + dc.w = mw - dc.x; dc.y += dc.font.height + 2; - /* determine maximum items */ for(i = curr; i != next; i=i->right) { drawtext(i->text, (sel == i) ? dc.sel : dc.norm); dc.y += dc.font.height + 2; @@ -340,13 +338,11 @@ initfont(const char *fontstr) { if(missing) XFreeStringList(missing); if(dc.font.set) { - XFontSetExtents *font_extents; XFontStruct **xfonts; char **font_names; dc.font.ascent = dc.font.descent = 0; - font_extents = XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); - for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { + for(i = 0; i < n; i++) { dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent); xfonts++; @@ -365,7 +361,7 @@ initfont(const char *fontstr) { void kpress(XKeyEvent * e) { char buf[sizeof text]; - int i, num; + int i, num, off; unsigned int len; KeySym ksym; @@ -480,13 +476,19 @@ kpress(XKeyEvent * e) { break; case XK_BackSpace: if(cursor > 0) { - memmove(text + cursor - 1, text + cursor, sizeof text - cursor + 1); - cursor--; + off = 1; + while(cursor > off && !IS_UTF8_1ST_CHAR(text[cursor - off])) + off++; + memmove(text + cursor - off, text + cursor, sizeof text - cursor + off); + cursor -= off; match(text); } break; case XK_Delete: - memmove(text + cursor, text + cursor + 1, sizeof text - cursor); + off = 1; + while(cursor + off < sizeof text - 1 && !IS_UTF8_1ST_CHAR(text[cursor + off])) + off++; + memmove(text + cursor, text + cursor + off, sizeof text - cursor); match(text); break; case XK_End: @@ -522,9 +524,11 @@ kpress(XKeyEvent * e) { calcoffsets(); } } - else if(cursor > 0) - cursor--; - else + else if(cursor > 0) { + do { + cursor--; + } while(cursor > 0 && !IS_UTF8_1ST_CHAR(text[cursor])); + } else return; break; case XK_Next: @@ -549,9 +553,11 @@ kpress(XKeyEvent * e) { break; case XK_Right: case XK_Down: - if(cursor < len) - cursor++; - else if(sel && sel->right) { + if(cursor < len) { + do { + cursor++; + } while(cursor < len && !IS_UTF8_1ST_CHAR(text[cursor])); + } else if(sel && sel->right) { sel=sel->right; if(sel == next) { curr = next;