ref: 0d843ac836b5afb166eb6b9b8a6590f1548af4ee
parent: d89778bebd8de5942141b9d8db5510e23f9885e2
author: phil9 <telephil9@gmail.com>
date: Wed Feb 9 12:07:00 EST 2022
import libdraw enter() and adapt it to Kbdctl
--- /dev/null
+++ b/enter.c
@@ -1,0 +1,240 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include "kbd.h"
+
+int
+kbdenter(char *ask, char *buf, int len, Mousectl *mc, Kbdctl *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;
+ Key key;
+ 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 = &key;
+ 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:
+ k = key.k;
+ 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;
+}