libdraw: added enter() and eenter() functions

This commit is contained in:
cinap_lenrek 2011-10-31 19:41:48 +01:00
parent 01a7c491fc
commit 278d4f8477
7 changed files with 472 additions and 4 deletions

View file

@ -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*);

View file

@ -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*);

View file

@ -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"

View file

@ -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

195
sys/src/libdraw/eenter.c Normal file
View file

@ -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;
}

219
sys/src/libdraw/enter.c Normal file
View file

@ -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;
}

View file

@ -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\