summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-10-31 19:41:48 +0100
committercinap_lenrek <cinap_lenrek@centraldogma>2011-10-31 19:41:48 +0100
commit278d4f8477a5f35a17ef9f01cf06849963f31e38 (patch)
tree0e839a781ea42040ecb8cd5c92851b151141cefb
parent01a7c491fc2a2b826e9944dc6418325f052fb11c (diff)
libdraw: added enter() and eenter() functions
-rw-r--r--sys/include/event.h1
-rw-r--r--sys/include/mouse.h2
-rw-r--r--sys/man/2/event36
-rw-r--r--sys/man/2/mouse21
-rw-r--r--sys/src/libdraw/eenter.c195
-rw-r--r--sys/src/libdraw/enter.c219
-rw-r--r--sys/src/libdraw/mkfile2
7 files changed, 472 insertions, 4 deletions
diff --git a/sys/include/event.h b/sys/include/event.h
index 03679f8f2..86e6ca6a4 100644
--- a/sys/include/event.h
+++ b/sys/include/event.h
@@ -64,3 +64,4 @@ extern Rectangle egetrect(int, Mouse*);
extern void edrawgetrect(Rectangle, int);
extern int ereadmouse(Mouse*);
extern int eatomouse(Mouse*, char*, int);
+extern int eenter(char*, char*, int, Mouse*);
diff --git a/sys/include/mouse.h b/sys/include/mouse.h
index 14d26de6d..5f91f11a3 100644
--- a/sys/include/mouse.h
+++ b/sys/include/mouse.h
@@ -4,6 +4,7 @@ typedef struct Channel Channel;
typedef struct Cursor Cursor;
typedef struct Menu Menu;
typedef struct Mousectl Mousectl;
+typedef struct Keyboardctl Keyboardctl;
struct Mouse
{
@@ -44,3 +45,4 @@ extern void setcursor(Mousectl*, Cursor*);
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*);
diff --git a/sys/man/2/event b/sys/man/2/event
index 11324a9af..8027f2b91 100644
--- 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 @@ void edrawgetrect(Rectangle r, int up)
.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 @@ changes the cursor image to that described by the
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"
diff --git a/sys/man/2/mouse b/sys/man/2/mouse
index 76625b683..72981dd50 100644
--- 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 @@ void drawgetrect(Rectangle r, int up)
.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.
@@ -239,6 +244,20 @@ behaves like
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
.SH SEE ALSO
diff --git a/sys/src/libdraw/eenter.c b/sys/src/libdraw/eenter.c
new file mode 100644
index 000000000..d1434eacc
--- /dev/null
+++ b/sys/src/libdraw/eenter.c
@@ -0,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;
+}
+
diff --git a/sys/src/libdraw/enter.c b/sys/src/libdraw/enter.c
new file mode 100644
index 000000000..54c7ba702
--- /dev/null
+++ b/sys/src/libdraw/enter.c
@@ -0,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;
+}
diff --git a/sys/src/libdraw/mkfile b/sys/src/libdraw/mkfile
index 86f275bd0..0a70c3a48 100644
--- a/sys/src/libdraw/mkfile
+++ b/sys/src/libdraw/mkfile
@@ -18,9 +18,11 @@ OFILES=\
defont.$O\
draw.$O\
drawrepl.$O\
+ eenter.$O\
egetrect.$O\
ellipse.$O\
emenuhit.$O\
+ enter.$O\
event.$O\
fmt.$O\
font.$O\