shithub: eesp

Download patch

ref: f94021cad309874252753f9ac7b49b9efe9b04be
author: sirjofri <sirjofri@sirjofri.de>
date: Sat Jul 20 10:48:07 EDT 2024

adds files (lib* files are to copy from libdraw)

--- /dev/null
+++ b/eenter.c
@@ -1,0 +1,41 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+void
+eresized(int)
+{
+	draw(screen, screen->r, display->white, nil, ZP);
+}
+
+void
+main(int argc, char **argv)
+{
+	USED(argc, argv);
+	
+	int e;
+	Event ev;
+	char buf[512];
+	
+	if (initdraw(nil, nil, "eenter") < 0)
+		sysfatal("error: %r");
+	
+	einit(Emouse|Ekeyboard);
+	
+	for (;;) {
+		e = event(&ev);
+		switch (e) {
+		case Emouse:
+			if (ev.mouse.buttons == 0)
+				break;
+			snprint(buf, sizeof(buf), "hello world");
+			if (eenter("Ask:", buf, sizeof(buf), &ev.mouse) > 0)
+				fprint(2, "entered: %s\n", buf);
+			break;
+		case Ekeyboard:
+			if (ev.kbdc == 'q')
+				exits(nil);
+		}
+	}
+}
--- /dev/null
+++ b/enter.c
@@ -1,0 +1,65 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+enum {
+	Emouse,
+	Eresize,
+	Ekeyboard,
+};
+
+void
+threadmain(int argc, char **argv)
+{
+	Mouse m;
+	Rune k;
+	Mousectl *mctl;
+	Keyboardctl *kctl;
+	char buf[512];
+	USED(argc, argv);
+	
+	Alt a[] = {
+		{ nil, &m, CHANRCV },
+		{ nil, nil, CHANRCV },
+		{ nil, &k, CHANRCV },
+		{ nil, nil, CHANEND },
+	};
+	
+	if (initdraw(nil, nil, "enter test") < 0)
+		sysfatal("initdraw: %r");
+	
+	mctl = initmouse(nil, screen);
+	if (!mctl)
+		sysfatal("initmouse: %r");
+	
+	kctl = initkeyboard(nil);
+	if (!kctl)
+		sysfatal("initkeyboard: %r");
+	a[Emouse].c = mctl->c;
+	a[Eresize].c = mctl->resizec;
+	a[Ekeyboard].c = kctl->c;
+	
+	for (;;) {
+		switch (alt(a)) {
+		case Emouse:
+			if (m.buttons == 0)
+				break;
+			snprint(buf, sizeof(buf), "hello world");
+			if (enter("Ask:", buf, sizeof(buf), mctl, kctl, nil) > 0)
+				fprint(2, "entered: %s\n", buf);
+			break;
+		case Eresize:
+			if (getwindow(display, Refnone) < 0)
+				sysfatal("cannot reattach: %r");
+			draw(screen, screen->r, display->white, nil, ZP);
+			break;
+		case Ekeyboard:
+			if (k == Kdel || k == 'q')
+				threadexitsall(nil);
+			break;
+		}
+	}
+}
--- /dev/null
+++ b/libeenter.c
@@ -1,0 +1,371 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+static void
+sorttick(int *t1, int *t2)
+{
+	int i;
+	if(*t1 <= *t2)
+		return;
+	i = *t1;
+	*t1 = *t2;
+	*t2 = i;
+}
+
+static Point
+drawstring(Image *b, char *buf, Point p, int s, int e, Image *bg, int h)
+{
+	sorttick(&s, &e);
+	p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, s));
+	if(s == e){
+		draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP);
+		draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP);
+		draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP);
+	} else {
+		p = stringnbg(b, p, display->black, ZP, font, buf+s, utfnlen(buf+s, e-s), bg, ZP);
+	}
+	p = string(b, p, display->black, ZP, font, buf+e);
+	return p;
+}
+
+static void
+enterselection(char *buf, int len, int s, int e, int *sp, int *ep)
+{
+	int l, i;
+	Rune k;
+	sorttick(&s, &e);
+	*sp = *ep = -1;
+	for(i = 0; i < len; i += l){
+		l = chartorune(&k, buf+i);
+		if(*sp >= 0 && i >= e){
+			*ep = i;
+			break;
+		}
+		if(*sp < 0 && i >= s)
+			*sp = i;
+	}
+}
+
+static int
+delsubstring(char *buf, int len, int s, int e, int *nlen)
+{
+	int l, i, sp, ep;
+	Rune k;
+	if(s == e)
+		return s;
+	if (s < 0)
+		s = 0;
+	enterselection(buf, len, s, e, &sp, &ep);
+	memmove(buf+sp, buf+ep, len - ep);
+	buf[len-ep+sp] = 0;
+	if (nlen)
+		*nlen = sp+len-ep;
+	return sp;
+}
+
+static int
+entersnarf(char *buf, int len, int s, int e, int *nlen)
+{
+	int fd, sp, ep;
+	fd = open("/dev/snarf", OWRITE|OTRUNC);
+	if(fd < 0){
+		fprint(2, "error: %r\n");
+		return s;
+	}
+	enterselection(buf, len, s, e, &sp, &ep);
+	if(sp < 0 || ep < 0){
+		close(fd);
+		return sp < 0 ? ep : sp;
+	}
+	pwrite(fd, &buf[sp], ep-sp, 0);
+	close(fd);
+	return delsubstring(buf, len, s, e, nlen);
+}
+
+static void
+enterpaste(char *buf, int len, int max, int s, int e, int *nlen, int *ns, int *ne)
+{
+	char *str;
+	int fd, sp, ep, n, newlen;
+	
+	fd = open("/dev/snarf", OREAD);
+	if(fd < 0){
+		fprint(2, "error: %r\n");
+		return;
+	}
+	str = mallocz(max*sizeof(char), 1);
+	n = pread(fd, str, max-1, 0);
+	str[n] = 0;
+	close(fd);
+
+	newlen = len;
+	enterselection(buf, len, s, e, &sp, &ep);
+	s = entersnarf(buf, len, s, e, &newlen);
+
+	memmove(buf+n+s, buf+s, newlen-s);
+	memcpy(buf+s, str, n);
+
+	free(str);
+	if (nlen)
+		*nlen = newlen+n;
+	if (ns)
+		*ns = s;
+	if (ne)
+		*ne = s+n;
+}
+
+int
+eenter(char *ask, char *buf, int len, Mouse *m)
+{
+	int done, down, tick, n, h, w, l, i;
+	int tick2, mb, ti;
+	Image *b, *save, *backcol, *bordcol;
+	Point p, o, t;
+	Rectangle r, sc;
+	Event ev;
+	Rune k;
+
+	mb = 0;
+	o = screen->r.min;
+	backcol = allocimagemix(display, DPurpleblue, DWhite);
+	bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue);
+	if(backcol == nil || bordcol == nil)
+		return -1;
+
+	while(ecankbd())
+		ekbd();
+
+	if(m) o = m->xy;
+
+	if(buf && len > 0)
+		n = strlen(buf);
+	else {
+		buf = nil;
+		len = 0;
+		n = 0;
+	}
+
+	k = -1;
+	tick2 = tick = n;
+	save = nil;
+	done = down = 0;
+
+	p = stringsize(font, " ");
+	h = p.y;
+	w = p.x;
+
+	b = screen;
+	sc = b->clipr;
+	replclipr(b, 0, b->r);
+
+	while(!done){
+		p = stringsize(font, buf ? buf : "");
+		if(ask && ask[0]){
+			if(buf) p.x += w;
+			p.x += stringwidth(font, ask);
+		}
+		r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
+		p.x = 0;
+		r = rectsubpt(r, p);
+
+		p = ZP;
+		if(r.min.x < screen->r.min.x)
+			p.x = screen->r.min.x - r.min.x;
+		if(r.min.y < screen->r.min.y)
+			p.y = screen->r.min.y - r.min.y;
+		r = rectaddpt(r, p);
+		p = ZP;
+		if(r.max.x > screen->r.max.x)
+			p.x = r.max.x - screen->r.max.x;
+		if(r.max.y > screen->r.max.y)
+			p.y = r.max.y - screen->r.max.y;
+		r = rectsubpt(r, p);
+
+		r = insetrect(r, -2);
+		if(save == nil){
+			save = allocimage(display, r, b->chan, 0, DNofill);
+			if(save == nil){
+				n = -1;
+				break;
+			}
+			draw(save, r, b, nil, r.min);
+		}
+		draw(b, r, backcol, nil, ZP);
+		border(b, r, 2, bordcol, ZP);
+		p = addpt(r.min, Pt(6, 6));
+		if(ask && ask[0]){
+			p = string(b, p, bordcol, ZP, font, ask);
+			if(buf) p.x += w;
+		}
+		if(buf){
+			t = p;
+			p = drawstring(b, buf, p, tick, tick2, bordcol, h);
+		}
+		flushimage(display, 1);
+
+nodraw:
+		i = Ekeyboard;
+		if(m != nil)
+			i |= Emouse;
+
+		replclipr(b, 0, sc);
+		i = eread(i, &ev);
+
+		/* screen might have been resized */
+		if(b != screen || !eqrect(screen->clipr, sc)){
+			freeimage(save);
+			save = nil;
+		}
+		b = screen;
+		sc = b->clipr;
+		replclipr(b, 0, b->r);
+
+		switch(i){
+		default:
+			done = 1;
+			n = -1;
+			break;
+		case Ekeyboard:
+			k = ev.kbdc;
+			if(buf == nil || k == Keof || k == '\n'){
+				done = 1;
+				break;
+			}
+			if(k == Knack || k == Kesc){
+				done = !n;
+				n = tick2 = tick = 0;
+				buf[n] = 0;
+				break;
+			}
+			if(k == Ksoh || k == Khome){
+				tick2 = tick = 0;
+				continue;
+			}
+			if(k == Kenq || k == Kend){
+				tick2 = tick = n;
+				continue;
+			}
+			if(k == Kright){
+				if(tick2 < n)
+					tick2 = tick += chartorune(&k, buf+tick);
+				continue;
+			}
+			if(k == Kleft){
+				for(i = 0; i < n; i += l){
+					l = chartorune(&k, buf+i);
+					if(i+l >= tick){
+						tick2 = tick = i;
+						break;
+					}
+				}
+				continue;
+			}
+			if(k == Ketb){
+				l = tick;
+				while(tick > 0){
+					tick--;
+					if(tick == 0 ||
+						strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))
+						break;
+				}
+				memmove(buf+tick, buf+l, n-l);
+				buf[n -= l-tick] = 0;
+				break;
+			}
+			if(k == Kbs){
+				if(tick <= 0 && tick2 <= 0)
+					continue;
+				if (tick == tick2)
+					for(i = 0; i < n; i += l){
+						l = chartorune(&k, buf+i);
+						if(i+l >= tick){
+							memmove(buf+i, buf+i+l, n - (i+l));
+							buf[n -= l] = 0;
+							tick2 = tick -= l;
+							break;
+						}
+					}
+				else
+					tick = tick2 = delsubstring(buf, n, tick-1, tick2, &n);
+				break;
+			}
+			if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
+				continue;
+			if((len-n) <= (l = runelen(k)))
+				continue;
+			tick = delsubstring(buf, n, tick, tick2, &n);
+			memmove(buf+tick+l, buf+tick, n - tick);
+			runetochar(buf+tick, &k);
+			buf[n += l] = 0;
+			tick2 = tick += l;
+			break;
+		case Emouse:
+			*m = ev.mouse;
+			if(mb&1 && !m->buttons&1) {
+				sorttick(&tick, &tick2);
+				mb = m->buttons;
+			}
+			if(m->buttons&1 && mb&6){
+				if (m->buttons != mb)
+					goto Mchecks;
+				continue;
+			}
+			if(m->buttons&1 && mb&6){
+				continue;
+			}
+			if(!ptinrect(m->xy, r)){
+				down = 0;
+				goto nodraw;
+			}
+			if(m->buttons&1){
+				down = 1;
+				if(buf && m->xy.x >= (t.x - w)){
+					down = 0;
+					for(i = 0; i < n; i += l){
+						l = chartorune(&k, buf+i);
+						t.x += stringnwidth(font, buf+i, 1);
+						if(t.x > m->xy.x)
+							break;
+					}
+					if(mb & 1){
+						tick2 = i;
+					}else
+						tick = tick2 = i;
+				}
+				if(!((m->buttons&2) || (m->buttons&4))){
+					mb = m->buttons;
+					continue;
+				}
+			}
+Mchecks:
+			if(!(mb&2) && (m->buttons&3) == 3){
+				tick = tick2 = entersnarf(buf, n, tick, tick2, &n);
+				mb = m->buttons;
+			}
+			if(!(mb&4) && (m->buttons&5) == 5){
+				enterpaste(buf, n, len, tick, tick2, &n, &tick, &tick2);
+				mb = m->buttons;
+			}
+
+			done = down;
+			break;
+		}
+		if(save){
+			draw(b, save->r, save, nil, save->r.min);
+			freeimage(save);
+			save = nil;
+		}
+	}
+
+	replclipr(b, 0, sc);
+
+	freeimage(backcol);
+	freeimage(bordcol);
+	flushimage(display, 1);
+
+	return n;
+}
+
--- /dev/null
+++ b/libenter.c
@@ -1,0 +1,237 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+int
+enter(char *ask, char *buf, int len, Mousectl *mc, Keyboardctl *kc, Screen *scr)
+{
+	int done, down, tick, n, h, w, l, i;
+	Image *b, *save, *backcol, *bordcol;
+	Point p, o, t;
+	Rectangle r, sc;
+	Alt a[3];
+	Mouse m;
+	Rune k;
+
+	o = screen->r.min;
+	backcol = allocimagemix(display, DPurpleblue, DWhite);
+	bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue);
+	if(backcol == nil || bordcol == nil)
+		return -1;
+
+	sc = screen->clipr;
+	replclipr(screen, 0, screen->r);
+
+	n = 0;
+	if(kc){
+		while(nbrecv(kc->c, nil) == 1)
+			;
+		a[n].op = CHANRCV;
+		a[n].c = kc->c;
+		a[n].v = &k;
+		n++;
+	}
+	if(mc){
+		o = mc->xy;
+		a[n].op = CHANRCV;
+		a[n].c = mc->c;
+		a[n].v = &m;
+		n++;
+	}
+	a[n].op = CHANEND;
+	a[n].c = nil;
+	a[n].v = nil;
+
+	if(buf && len > 0)
+		n = strlen(buf);
+	else {
+		buf = nil;
+		len = 0;
+		n = 0;
+	}
+
+	k = -1;
+	b = nil;
+	tick = n;
+	save = nil;
+	done = down = 0;
+
+	p = stringsize(font, " ");
+	h = p.y;
+	w = p.x;
+
+	while(!done){
+		p = stringsize(font, buf ? buf : "");
+		if(ask && ask[0]){
+			if(buf) p.x += w;
+			p.x += stringwidth(font, ask);
+		}
+		r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
+		p.x = 0;
+		r = rectsubpt(r, p);
+
+		p = ZP;
+		if(r.min.x < screen->r.min.x)
+			p.x = screen->r.min.x - r.min.x;
+		if(r.min.y < screen->r.min.y)
+			p.y = screen->r.min.y - r.min.y;
+		r = rectaddpt(r, p);
+		p = ZP;
+		if(r.max.x > screen->r.max.x)
+			p.x = r.max.x - screen->r.max.x;
+		if(r.max.y > screen->r.max.y)
+			p.y = r.max.y - screen->r.max.y;
+		r = rectsubpt(r, p);
+
+		r = insetrect(r, -2);
+		if(scr){
+			if(b == nil)
+				b = allocwindow(scr, r, Refbackup, DWhite);
+			if(b == nil)
+				scr = nil;
+		}
+		if(scr == nil && save == nil){
+			if(b == nil)
+				b = screen;
+			save = allocimage(display, r, b->chan, 0, DNofill);
+			if(save == nil){
+				n = -1;
+				break;
+			}
+			draw(save, r, b, nil, r.min);
+		}
+		draw(b, r, backcol, nil, ZP);
+		border(b, r, 2, bordcol, ZP);
+		p = addpt(r.min, Pt(6, 6));
+		if(ask && ask[0]){
+			p = string(b, p, bordcol, ZP, font, ask);
+			if(buf) p.x += w;
+		}
+		if(buf){
+			t = p;
+			p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick));
+			draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP);
+			draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP);
+			draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP);
+			p = string(b, p, display->black, ZP, font, buf+tick);
+		}
+		flushimage(display, 1);
+
+nodraw:
+		switch(alt(a)){
+		case -1:
+			done = 1;
+			n = -1;
+			break;
+		case 0:
+			if(buf == nil || k == Keof || k == '\n'){
+				done = 1;
+				break;
+			}
+			if(k == Knack || k == Kesc){
+				done = !n;
+				buf[n = tick = 0] = 0;
+				break;
+			}
+			if(k == Ksoh || k == Khome){
+				tick = 0;
+				continue;
+			}
+			if(k == Kenq || k == Kend){
+				tick = n;
+				continue;
+			}
+			if(k == Kright){
+				if(tick < n)
+					tick += chartorune(&k, buf+tick);
+				continue;
+			}
+			if(k == Kleft){
+				for(i = 0; i < n; i += l){
+					l = chartorune(&k, buf+i);
+					if(i+l >= tick){
+						tick = i;
+						break;
+					}
+				}
+				continue;
+			}
+			if(k == Ketb){
+				l = tick;
+				while(tick > 0){
+					tick--;
+					if(tick == 0 ||
+						strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))
+						break;
+				}
+				memmove(buf+tick, buf+l, n-l);
+				buf[n -= l-tick] = 0;
+				break;
+			}
+			if(k == Kbs){
+				if(tick <= 0)
+					continue;
+				for(i = 0; i < n; i += l){
+					l = chartorune(&k, buf+i);
+					if(i+l >= tick){
+						memmove(buf+i, buf+i+l, n - (i+l));
+						buf[n -= l] = 0;
+						tick -= l;
+						break;
+					}
+				}
+				break;
+			}
+			if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
+				continue;
+			if((len-n) <= (l = runelen(k)))
+				continue;
+			memmove(buf+tick+l, buf+tick, n - tick);
+			runetochar(buf+tick, &k);
+			buf[n += l] = 0;
+			tick += l;
+			break;
+		case 1:
+			if(!ptinrect(m.xy, r)){
+				down = 0;
+				goto nodraw;
+			}
+			if(m.buttons & 7){
+				down = 1;
+				if(buf && m.xy.x >= (t.x - w)){
+					down = 0;
+					for(i = 0; i < n; i += l){
+						l = chartorune(&k, buf+i);
+						t.x += stringnwidth(font, buf+i, 1);
+						if(t.x > m.xy.x)
+							break;
+					}
+					tick = i;
+				}
+				continue;
+			}
+			done = down;
+			break;
+		}
+
+		if(b != screen) {
+			freeimage(b);
+			b = nil;
+		} else {
+			draw(b, save->r, save, nil, save->r.min);
+			freeimage(save);
+			save = nil;
+		}
+	}
+
+	replclipr(screen, 0, sc);
+
+	freeimage(backcol);
+	freeimage(bordcol);
+	flushimage(display, 1);
+
+	return n;
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,18 @@
+</$objtype/mkfile
+
+TARG=enter eenter
+
+</sys/src/cmd/mkmany
+
+prep:V: libenter.c libeenter.c
+
+instlib:V: /sys/src/libdraw/enter.c /sys/src/libdraw/eenter.c
+
+libenter.c:
+	cp /sys/src/libdraw/enter.c $target
+
+libeenter.c:
+	cp /sys/src/libdraw/eenter.c $target
+
+/sys/src/libdraw/%.c: lib%.c
+	cp $prereq $target