fixed insert segfault, added nextrune
							parent
							
								
									402dc2bc95
								
							
						
					
					
						commit
						849f1dd7a3
					
				
							
								
								
									
										72
									
								
								dmenu.c
								
								
								
								
							
							
						
						
									
										72
									
								
								dmenu.c
								
								
								
								
							|  | @ -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 { | ||||
|  | @ -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); | ||||
|  | @ -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; | ||||
|  | @ -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; | ||||
|  | @ -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; | ||||
| 
 | ||||
|  | @ -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) { | ||||
|  | @ -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(); | ||||
| 		} | ||||
|  | @ -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(); | ||||
| 		} | ||||
|  | @ -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); | ||||
|  | @ -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)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -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) | ||||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue