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