]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/enter.c
python: arm64 support
[plan9front.git] / sys / src / libdraw / enter.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7
8 int
9 enter(char *ask, char *buf, int len, Mousectl *mc, Keyboardctl *kc, Screen *scr)
10 {
11         int done, down, tick, n, h, w, l, i;
12         Image *b, *save, *backcol, *bordcol;
13         Point p, o, t;
14         Rectangle r, sc;
15         Alt a[3];
16         Mouse m;
17         Rune k;
18
19         o = screen->r.min;
20         backcol = allocimagemix(display, DPurpleblue, DWhite);
21         bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue);
22         if(backcol == nil || bordcol == nil)
23                 return -1;
24
25         sc = screen->clipr;
26         replclipr(screen, 0, screen->r);
27
28         n = 0;
29         if(kc){
30                 while(nbrecv(kc->c, nil) == 1)
31                         ;
32                 a[n].op = CHANRCV;
33                 a[n].c = kc->c;
34                 a[n].v = &k;
35                 n++;
36         }
37         if(mc){
38                 o = mc->xy;
39                 a[n].op = CHANRCV;
40                 a[n].c = mc->c;
41                 a[n].v = &m;
42                 n++;
43         }
44         a[n].op = CHANEND;
45         a[n].c = nil;
46         a[n].v = nil;
47
48         if(buf && len > 0)
49                 n = strlen(buf);
50         else {
51                 buf = nil;
52                 len = 0;
53                 n = 0;
54         }
55
56         k = -1;
57         b = nil;
58         tick = n;
59         save = nil;
60         done = down = 0;
61
62         p = stringsize(font, " ");
63         h = p.y;
64         w = p.x;
65
66         while(!done){
67                 p = stringsize(font, buf ? buf : "");
68                 if(ask && ask[0]){
69                         if(buf) p.x += w;
70                         p.x += stringwidth(font, ask);
71                 }
72                 r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
73                 p.x = 0;
74                 r = rectsubpt(r, p);
75
76                 p = ZP;
77                 if(r.min.x < screen->r.min.x)
78                         p.x = screen->r.min.x - r.min.x;
79                 if(r.min.y < screen->r.min.y)
80                         p.y = screen->r.min.y - r.min.y;
81                 r = rectaddpt(r, p);
82                 p = ZP;
83                 if(r.max.x > screen->r.max.x)
84                         p.x = r.max.x - screen->r.max.x;
85                 if(r.max.y > screen->r.max.y)
86                         p.y = r.max.y - screen->r.max.y;
87                 r = rectsubpt(r, p);
88
89                 r = insetrect(r, -2);
90                 if(scr){
91                         if(b == nil)
92                                 b = allocwindow(scr, r, Refbackup, DWhite);
93                         if(b == nil)
94                                 scr = nil;
95                 }
96                 if(scr == nil && save == nil){
97                         if(b == nil)
98                                 b = screen;
99                         save = allocimage(display, r, b->chan, 0, DNofill);
100                         if(save == nil){
101                                 n = -1;
102                                 break;
103                         }
104                         draw(save, r, b, nil, r.min);
105                 }
106                 draw(b, r, backcol, nil, ZP);
107                 border(b, r, 2, bordcol, ZP);
108                 p = addpt(r.min, Pt(6, 6));
109                 if(ask && ask[0]){
110                         p = string(b, p, bordcol, ZP, font, ask);
111                         if(buf) p.x += w;
112                 }
113                 if(buf){
114                         t = p;
115                         p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick));
116                         draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP);
117                         draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP);
118                         draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP);
119                         p = string(b, p, display->black, ZP, font, buf+tick);
120                 }
121                 flushimage(display, 1);
122
123 nodraw:
124                 switch(alt(a)){
125                 case -1:
126                         done = 1;
127                         n = -1;
128                         break;
129                 case 0:
130                         if(buf == nil || k == Keof || k == '\n'){
131                                 done = 1;
132                                 break;
133                         }
134                         if(k == Knack || k == Kesc){
135                                 done = !n;
136                                 buf[n = tick = 0] = 0;
137                                 break;
138                         }
139                         if(k == Ksoh || k == Khome){
140                                 tick = 0;
141                                 continue;
142                         }
143                         if(k == Kenq || k == Kend){
144                                 tick = n;
145                                 continue;
146                         }
147                         if(k == Kright){
148                                 if(tick < n)
149                                         tick += chartorune(&k, buf+tick);
150                                 continue;
151                         }
152                         if(k == Kleft){
153                                 for(i = 0; i < n; i += l){
154                                         l = chartorune(&k, buf+tick);
155                                         if(i+l >= tick){
156                                                 tick = i;
157                                                 break;
158                                         }
159                                 }
160                                 continue;
161                         }
162                         if(k == Ketb){
163                                 while(tick > 0){
164                                         tick--;
165                                         if(tick == 0 ||
166                                            strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))
167                                                 break;
168                                 }
169                                 buf[n = tick] = 0;
170                                 break;
171                         }
172                         if(k == Kbs){
173                                 if(tick <= 0)
174                                         continue;
175                                 for(i = 0; i < n; i += l){
176                                         l = chartorune(&k, buf+i);
177                                         if(i+l >= tick){
178                                                 memmove(buf+i, buf+i+l, n - (i+l));
179                                                 buf[n -= l] = 0;
180                                                 tick -= l;
181                                                 break;
182                                         }
183                                 }
184                                 break;
185                         }
186                         if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
187                                 continue;
188                         if((len-n) <= (l = runelen(k)))
189                                 continue;
190                         memmove(buf+tick+l, buf+tick, n - tick);
191                         runetochar(buf+tick, &k);
192                         buf[n += l] = 0;
193                         tick += l;
194                         break;
195                 case 1:
196                         if(!ptinrect(m.xy, r)){
197                                 down = 0;
198                                 goto nodraw;
199                         }
200                         if(m.buttons & 7){
201                                 down = 1;
202                                 if(buf && m.xy.x >= (t.x - w)){
203                                         down = 0;
204                                         for(i = 0; i < n; i += l){
205                                                 l = chartorune(&k, buf+i);
206                                                 t.x += stringnwidth(font, buf+i, 1);
207                                                 if(t.x > m.xy.x)
208                                                         break;
209                                         }
210                                         tick = i;
211                                 }
212                                 continue;
213                         }
214                         done = down;
215                         break;
216                 }
217
218                 if(b != screen) {
219                         freeimage(b);
220                         b = nil;
221                 } else {
222                         draw(b, save->r, save, nil, save->r.min);
223                         freeimage(save);
224                         save = nil;
225                 }
226         }
227
228         replclipr(screen, 0, sc);
229
230         freeimage(backcol);
231         freeimage(bordcol);
232         flushimage(display, 1);
233
234         return n;
235 }