]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/eenter.c
libdraw: added enter() and eenter() functions
[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;
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         b = screen;
38         tick = n;
39         save = nil;
40         done = down = 0;
41
42         p = stringsize(font, " ");
43         h = p.y;
44         w = p.x;
45
46         while(!done){
47                 p = stringsize(font, buf ? buf : "");
48                 if(ask && ask[0]){
49                         if(buf) p.x += w;
50                         p.x += stringwidth(font, ask);
51                 }
52                 r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
53                 p.x = 0;
54                 r = rectsubpt(r, p);
55
56                 p = ZP;
57                 if(r.min.x < screen->r.min.x)
58                         p.x = screen->r.min.x - r.min.x;
59                 if(r.min.y < screen->r.min.y)
60                         p.y = screen->r.min.y - r.min.y;
61                 r = rectaddpt(r, p);
62                 p = ZP;
63                 if(r.max.x > screen->r.max.x)
64                         p.x = r.max.x - screen->r.max.x;
65                 if(r.max.y > screen->r.max.y)
66                         p.y = r.max.y - screen->r.max.y;
67                 r = rectsubpt(r, p);
68
69                 r = insetrect(r, -2);
70                 if(save == nil){
71                         save = allocimage(display, r, b->chan, 0, DNofill);
72                         if(save == nil){
73                                 n = -1;
74                                 break;
75                         }
76                         draw(save, r, b, nil, r.min);
77                 }
78                 draw(b, r, backcol, nil, ZP);
79                 border(b, r, 2, bordcol, ZP);
80                 p = addpt(r.min, Pt(6, 6));
81                 if(ask && ask[0]){
82                         p = string(b, p, bordcol, ZP, font, ask);
83                         if(buf) p.x += w;
84                 }
85                 if(buf){
86                         t = p;
87                         p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick));
88                         draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP);
89                         draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP);
90                         draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP);
91                         p = string(b, p, display->black, ZP, font, buf+tick);
92                 }
93                 flushimage(display, 1);
94
95                 i = Ekeyboard;
96                 if(m != nil)
97                         i |= Emouse;
98                 switch(eread(i, &ev)){
99                 default:
100                         done = 1;
101                         n = -1;
102                         break;
103                 case Ekeyboard:
104                         k = ev.kbdc;
105                         if(buf == nil || k == Keof || k == '\n'){
106                                 done = 1;
107                                 break;
108                         }
109                         if(k == Knack || k == Kesc){
110                                 done = !n;
111                                 buf[n = tick = 0] = 0;
112                                 break;
113                         }
114                         if(k == Ksoh || k == Khome){
115                                 tick = 0;
116                                 continue;
117                         }
118                         if(k == Kenq || k == Kend){
119                                 tick = n;
120                                 continue;
121                         }
122                         if(k == Kright){
123                                 if(tick < n)
124                                         tick += chartorune(&k, buf+tick);
125                                 continue;
126                         }
127                         if(k == Kleft){
128                                 for(i = 0; i < n; i += l){
129                                         l = chartorune(&k, buf+tick);
130                                         if(i+l >= tick){
131                                                 tick = i;
132                                                 break;
133                                         }
134                                 }
135                                 continue;
136                         }
137                         if(k == Kbs){
138                                 if(tick <= 0)
139                                         continue;
140                                 for(i = 0; i < n; i += l){
141                                         l = chartorune(&k, buf+i);
142                                         if(i+l >= tick){
143                                                 memmove(buf+i, buf+i+l, n - (i+l));
144                                                 buf[n -= l] = 0;
145                                                 tick -= l;
146                                                 break;
147                                         }
148                                 }
149                                 break;
150                         }
151                         if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
152                                 continue;
153                         if((len-n) <= (l = runelen(k)))
154                                 continue;
155                         memmove(buf+tick+l, buf+tick, n - tick);
156                         runetochar(buf+tick, &k);
157                         buf[n += l] = 0;
158                         tick += l;
159                         break;
160                 case Emouse:
161                         *m = ev.mouse;
162                         if(!ptinrect(m->xy, r)){
163                                 down = 0;
164                                 continue;
165                         }
166                         if(m->buttons & 7){
167                                 down = 1;
168                                 if(buf && m->xy.x >= (t.x - w)){
169                                         down = 0;
170                                         for(i = 0; i < n; i += l){
171                                                 l = chartorune(&k, buf+i);
172                                                 t.x += stringnwidth(font, buf+i, 1);
173                                                 if(t.x > m->xy.x)
174                                                         break;
175                                         }
176                                         tick = i;
177                                 }
178                                 continue;
179                         }
180                         done = down;
181                         break;
182                 }
183
184                 draw(b, save->r, save, nil, save->r.min);
185                 freeimage(save);
186                 save = nil;
187         }
188
189         freeimage(backcol);
190         freeimage(bordcol);
191         flushimage(display, 1);
192
193         return n;
194 }
195