git: 9front

Download patch

ref: cb5f68eac22880caa39dc94811c8a442e7a15c15
parent: c79f966b290d86c31bf0df0043bcd9e66b10e909
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Mon Oct 31 15:41:48 EDT 2011

libdraw: added enter() and eenter() functions

--- a/sys/include/event.h
+++ b/sys/include/event.h
@@ -64,3 +64,4 @@
 extern void		edrawgetrect(Rectangle, int);
 extern int		ereadmouse(Mouse*);
 extern int		eatomouse(Mouse*, char*, int);
+extern int		eenter(char*, char*, int, Mouse*);
--- a/sys/include/mouse.h
+++ b/sys/include/mouse.h
@@ -4,6 +4,7 @@
 typedef struct	Cursor Cursor;
 typedef struct	Menu Menu;
 typedef struct 	Mousectl Mousectl;
+typedef struct	Keyboardctl Keyboardctl;
 
 struct	Mouse
 {
@@ -44,3 +45,4 @@
 extern void		drawgetrect(Rectangle, int);
 extern Rectangle	getrect(int, Mousectl*);
 extern int	 		menuhit(int, Mousectl*, Menu*, Screen*);
+extern int		enter(char *, char *, int, Mousectl*, Keyboardctl*, Screen*);
--- a/sys/man/2/event
+++ b/sys/man/2/event
@@ -1,6 +1,6 @@
 .TH EVENT 2
 .SH NAME
-event, einit, estart, estartfn, etimer, eread, emouse, ekbd, ecanread, ecanmouse, ecankbd, ereadmouse, eatomouse, eresized, egetrect, edrawgetrect, emenuhit, emoveto, esetcursor, Event, Mouse, Menu \- graphics events
+event, einit, estart, estartfn, etimer, eread, emouse, ekbd, ecanread, ecanmouse, ecankbd, ereadmouse, eatomouse, eresized, egetrect, edrawgetrect, emenuhit, eenter, emoveto, esetcursor, Event, Mouse, Menu \- graphics events
 .SH SYNOPSIS
 .nf
 .PP
@@ -69,15 +69,16 @@
 .B
 int	emenuhit(int but, Mouse *m, Menu *menu)
 .PP
-.PP
 .B
 int	emoveto(Point p)
 .PP
-.PP
 .B
 int	esetcursor(Cursor *c)
 .PP
 .B
+int	eenter(char *ask, char *buf, int len, Mouse *m)
+.PP
+.B
 extern Mouse    *mouse
 .PP
 .B
@@ -374,6 +375,35 @@
 If
 .B c
 is nil, it restores the image to the default arrow.
+.PP
+.I Eenter
+provides a simple way of text input in graphical programs. It displays
+a box at the current position of the mouse cursor (passed in the
+.B Mouse *m
+argument) in wich text can be
+typed and edited.
+If the string argument
+.B ask
+is not
+.B nil,
+it is displayed as a static label before the input string.
+The
+.B buf
+parameter contains the null-terminated input string to be edited. The
+.B len
+argument specified the length of
+.B buf
+in bytes including the terminating null byte.
+If
+.B buf
+or
+.B len
+is zero, no text can be entered.
+On success,
+.I eenter
+returns the number of bytes in the edited string
+.B buf
+or -1 on error.
 .SH SOURCE
 .B /sys/src/libdraw
 .SH "SEE ALSO"
--- a/sys/man/2/mouse
+++ b/sys/man/2/mouse
@@ -1,6 +1,6 @@
 .TH MOUSE 2
 .SH NAME
-initmouse, readmouse, closemouse, moveto, getrect, drawgetrect, menuhit, setcursor \- mouse control
+initmouse, readmouse, closemouse, moveto, getrect, drawgetrect, menuhit, setcursor, enter \- mouse control
 .SH SYNOPSIS
 .nf
 .B
@@ -42,6 +42,11 @@
 .PP
 .B
 int		menuhit(int but, Mousectl *mc, Menu *menu, Screen *scr)
+.PP
+.B
+int		enter(char *ask, char *buf, int len,
+.B
+			Mousectl *mc, Keyboardctl *kc, Screen *scr)
 .fi
 .SH DESCRIPTION
 These functions access and control a mouse in a multi-threaded environment.
@@ -238,6 +243,20 @@
 .IR emenuhit ,
 creating backing store for the menu, writing the menu directly on the display, and
 restoring the display when the menu is removed.
+.PP
+.I Enter
+is a multithreded version of the
+.I eenter
+function described in
+.IR event(2).
+Like
+.I menuhit,
+it has a optional
+.B scr
+argument to create a window. Keyboard input is read from the channel in the
+.B Keyboardctl *kc
+argument (see
+.IR keyboard (2)).
 .PP
 .SH SOURCE
 .B /sys/src/libdraw
--- /dev/null
+++ b/sys/src/libdraw/eenter.c
@@ -1,0 +1,195 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+int
+eenter(char *ask, char *buf, int len, Mouse *m)
+{
+	int done, down, tick, n, h, w, l, i;
+	Image *b, *save, *backcol, *bordcol;
+	Point p, o, t;
+	Rectangle r;
+	Event ev;
+	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;
+
+	while(ecankbd())
+		ekbd();
+
+	if(m) o = m->xy;
+
+	if(buf && len > 0)
+		n = strlen(buf);
+	else {
+		buf = nil;
+		len = 0;
+		n = 0;
+	}
+
+	k = -1;
+	b = screen;
+	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(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 = 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);
+
+		i = Ekeyboard;
+		if(m != nil)
+			i |= Emouse;
+		switch(eread(i, &ev)){
+		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;
+				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+tick);
+					if(i+l >= tick){
+						tick = i;
+						break;
+					}
+				}
+				continue;
+			}
+			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 Emouse:
+			*m = ev.mouse;
+			if(!ptinrect(m->xy, r)){
+				down = 0;
+				continue;
+			}
+			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;
+		}
+
+		draw(b, save->r, save, nil, save->r.min);
+		freeimage(save);
+		save = nil;
+	}
+
+	freeimage(backcol);
+	freeimage(bordcol);
+	flushimage(display, 1);
+
+	return n;
+}
+
--- /dev/null
+++ b/sys/src/libdraw/enter.c
@@ -1,0 +1,219 @@
+#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;
+	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;
+
+	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);
+
+		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+tick);
+					if(i+l >= tick){
+						tick = i;
+						break;
+					}
+				}
+				continue;
+			}
+			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;
+				continue;
+			}
+			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;
+		}
+	}
+
+	freeimage(backcol);
+	freeimage(bordcol);
+	flushimage(display, 1);
+
+	return n;
+}
--- a/sys/src/libdraw/mkfile
+++ b/sys/src/libdraw/mkfile
@@ -18,9 +18,11 @@
 	defont.$O\
 	draw.$O\
 	drawrepl.$O\
+	eenter.$O\
 	egetrect.$O\
 	ellipse.$O\
 	emenuhit.$O\
+	enter.$O\
 	event.$O\
 	fmt.$O\
 	font.$O\
--