tfixed insert segfault, added nextrune - dmenu - Dmenu fork with xft fonts.
 (HTM) git clone git://r-36.net/dmenu
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 849f1dd7a3ac1fc6d6a88a9e2b7d7dedbcd0befc
 (DIR) parent 402dc2bc951a27924c963e7227932194616559f4
 (HTM) Author: Connor Lane Smith <cls@lubutu.com>
       Date:   Thu, 12 Aug 2010 15:35:51 +0100
       
       fixed insert segfault, added nextrune
       Diffstat:
         dmenu.c                             |      72 +++++++++++++++----------------
       
       1 file changed, 35 insertions(+), 37 deletions(-)
       ---
 (DIR) diff --git a/dmenu.c b/dmenu.c
       t@@ -15,7 +15,6 @@
        #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 UTF8_CODEPOINT(c)       (((c) & 0xc0) != 0x80)
        
        typedef struct Item Item;
        struct Item {
       t@@ -32,7 +31,8 @@ static void grabkeyboard(void);
        static void insert(const char *s, ssize_t n);
        static void keypress(XKeyEvent *ev);
        static void match(void);
       -static void paste(Atom atom);
       +static size_t nextrune(int incr);
       +static void paste(void);
        static void readstdin(void);
        static void run(void);
        static void setup(void);
       t@@ -52,7 +52,7 @@ static unsigned int lines = 0;
        static unsigned int promptw;
        static unsigned long normcol[ColLast];
        static unsigned long selcol[ColLast];
       -static Atom clip, utf8;
       +static Atom utf8;
        static Bool topbar = True;
        static DC *dc;
        static Item *items = NULL;
       t@@ -159,7 +159,9 @@ grabkeyboard(void) {
        
        void
        insert(const char *s, ssize_t n) {
       -        memmove(text + cursor + n, text + cursor, sizeof text - cursor - n);
       +        if(strlen(text) + n > sizeof text - 1)
       +                return;
       +        memmove(text + cursor + n, text + cursor, sizeof text - cursor - MAX(n, 0));
                if(n > 0)
                        memcpy(text + cursor, s, n);
                cursor += n;
       t@@ -169,7 +171,6 @@ insert(const char *s, ssize_t n) {
        void
        keypress(XKeyEvent *ev) {
                char buf[32];
       -        int n;
                size_t len;
                KeySym ksym;
        
       t@@ -217,38 +218,31 @@ keypress(XKeyEvent *ev) {
                                ksym = XK_Up;
                                break;
                        case XK_u:  /* delete left */
       -                        insert(NULL, -cursor);
       +                        insert(NULL, 0 - cursor);
                                break;
                        case XK_w:  /* delete word */
       -                        if(cursor == 0)
       -                                return;
       -                        n = 0;
       -                        while(cursor - n++ > 0 && text[cursor - n] == ' ');
       -                        while(cursor - n++ > 0 && text[cursor - n] != ' ');
       -                        insert(NULL, 1-n);
       +                        while(cursor > 0 && text[nextrune(-1)] == ' ')
       +                                insert(NULL, nextrune(-1) - cursor);
       +                        while(cursor > 0 && text[nextrune(-1)] != ' ')
       +                                insert(NULL, nextrune(-1) - cursor);
                                break;
                        case XK_y:  /* paste selection */
       -                        XConvertSelection(dc->dpy, XA_PRIMARY, utf8, clip, win, CurrentTime);
       +                        XConvertSelection(dc->dpy, XA_PRIMARY, utf8, utf8, win, CurrentTime);
                                return;
                        }
                }
                switch(ksym) {
                default:
                        if(isprint(*buf))
       -                        insert(buf, MIN(strlen(buf), sizeof text - cursor));
       -                break;
       -        case XK_BackSpace:
       -                if(cursor == 0)
       -                        return;
       -                for(n = 1; cursor - n > 0 && !UTF8_CODEPOINT(text[cursor - n]); n++);
       -                insert(NULL, -n);
       +                        insert(buf, strlen(buf));
                        break;
                case XK_Delete:
                        if(cursor == len)
                                return;
       -                for(n = 1; cursor + n < len && !UTF8_CODEPOINT(text[cursor + n]); n++);
       -                cursor += n;
       -                insert(NULL, -n);
       +                cursor = nextrune(+1);
       +        case XK_BackSpace:
       +                if(cursor > 0)
       +                        insert(NULL, nextrune(-1) - cursor);
                        break;
                case XK_End:
                        if(cursor < len) {
       t@@ -274,15 +268,13 @@ keypress(XKeyEvent *ev) {
                        break;
                case XK_Left:
                        if(cursor > 0 && (!sel || !sel->left || lines > 0)) {
       -                        while(cursor-- > 0 && !UTF8_CODEPOINT(text[cursor]));
       +                        cursor = nextrune(-1);
                                break;
                        }
                        else if(lines > 0)
                                return;
                case XK_Up:
       -                if(!sel || !sel->left)
       -                        return;
       -                if((sel = sel->left)->right == curr) {
       +                if(sel && sel->left && (sel = sel->left)->right == curr) {
                                curr = prev;
                                calcoffsets();
                        }
       t@@ -306,15 +298,13 @@ keypress(XKeyEvent *ev) {
                        exit(EXIT_SUCCESS);
                case XK_Right:
                        if(cursor < len) {
       -                        while(cursor++ < len && !UTF8_CODEPOINT(text[cursor]));
       +                        cursor = nextrune(+1);
                                break;
                        }
                        else if(lines > 0)
                                return;
                case XK_Down:
       -                if(!sel || !sel->right)
       -                        return;
       -                if((sel = sel->right) == next) {
       +                if(sel && sel->right && (sel = sel->right) == next) {
                                curr = next;
                                calcoffsets();
                        }
       t@@ -370,14 +360,23 @@ match(void) {
                calcoffsets();
        }
        
       +size_t
       +nextrune(int incr) {
       +        size_t n, len;
       +
       +        len = strlen(text);
       +        for(n = cursor + incr; n >= 0 && n < len && (text[n] & 0xc0) == 0x80; n += incr);
       +        return n;
       +}
       +
        void
       -paste(Atom atom) {
       +paste(void) {
                char *p, *q;
                int di;
                unsigned long dl;
                Atom da;
        
       -        XGetWindowProperty(dc->dpy, win, atom, 0, sizeof text - cursor, False,
       +        XGetWindowProperty(dc->dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
                                   utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
                insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p));
                XFree(p);
       t@@ -396,8 +395,8 @@ readstdin(void) {
                                eprintf("cannot malloc %u bytes\n", sizeof *item);
                        if(!(item->text = strdup(buf)))
                                eprintf("cannot strdup %u bytes\n", strlen(buf)+1);
       -                inputw = MAX(inputw, textw(dc, item->text));
                        item->next = item->left = item->right = NULL;
       +                inputw = MAX(inputw, textw(dc, item->text));
                }
        }
        
       t@@ -415,8 +414,8 @@ run(void) {
                                keypress(&ev.xkey);
                                break;
                        case SelectionNotify:
       -                        if(ev.xselection.property != None)
       -                                paste(ev.xselection.property);
       +                        if(ev.xselection.property == utf8)
       +                                paste();
                                break;
                        case VisibilityNotify:
                                if(ev.xvisibility.state != VisibilityUnobscured)
       t@@ -437,7 +436,6 @@ setup(void) {
                screen = DefaultScreen(dc->dpy);
                root = RootWindow(dc->dpy, screen);
                utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
       -        clip = XInternAtom(dc->dpy, "_DMENU_STRING", False);
        
                normcol[ColBG] = getcolor(dc, normbgcolor);
                normcol[ColFG] = getcolor(dc, normfgcolor);