diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-10-31 19:41:48 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-10-31 19:41:48 +0100 |
commit | 278d4f8477a5f35a17ef9f01cf06849963f31e38 (patch) | |
tree | 0e839a781ea42040ecb8cd5c92851b151141cefb /sys/src/libdraw/enter.c | |
parent | 01a7c491fc2a2b826e9944dc6418325f052fb11c (diff) |
libdraw: added enter() and eenter() functions
Diffstat (limited to 'sys/src/libdraw/enter.c')
-rw-r--r-- | sys/src/libdraw/enter.c | 219 |
1 files changed, 219 insertions, 0 deletions
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; +} |