]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libcontrol/scribble.c
libmp: use portable mpdigdiv routines for mips (causes invalid instruction trap on...
[plan9front.git] / sys / src / libcontrol / scribble.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 #include <control.h>
8 #include <scribble.h>
9
10 typedef struct Scrib Scrib;
11
12 struct Scrib
13 {
14         Control;
15         int             border;
16         CImage  *image;
17         CImage  *color;
18         CImage  *bordercolor;
19         CFont   *font;
20         int             align;
21         int             lastbut;
22         char            lastchar[8];
23         Scribble        *scrib;
24 };
25
26 enum{
27         EAlign,
28         EBorder,
29         EBordercolor,
30         EFocus,
31         EFont,
32         EHide,
33         EImage,
34         ELinecolor,
35         ERect,
36         EReveal,
37         EShow,
38         ESize,
39 };
40
41 static char *cmds[] = {
42         [EAlign] =              "align",
43         [EBorder] =     "border",
44         [EBordercolor] ="bordercolor",
45         [EFocus] =      "focus",
46         [EFont] =               "font",
47         [EHide] =               "hide",
48         [EImage] =      "image",
49         [ELinecolor] =  "linecolor",
50         [ERect] =               "rect",
51         [EReveal] =     "reveal",
52         [EShow] =               "show",
53         [ESize] =               "size",
54         nil
55 };
56
57 static void     scribshow(Scrib*);
58 static void scribchar(Scrib*, Rune);
59
60 static void     resetstroke(Scrib *w);
61 static void     displaystroke(Scrib *w);
62 static void     displaylast(Scrib *w);
63 static void     addpoint(Scrib *w, Point p);
64
65 static void
66 scribmouse(Control *c, Mouse *m)
67 {
68         Scrib *b;
69         Rune r;
70
71         b = (Scrib*)c;
72         if (m->buttons & 0x1) {
73                 if ((b->lastbut & 0x1) == 0) {
74                         /* mouse went down */
75                         resetstroke(b);
76                 }
77                 /* mouse is down */
78                 if (ptinrect(m->xy,b->rect))
79                         addpoint(b, m->xy);
80         } else if (b->lastbut & 0x1) {
81                 /* mouse went up */
82                 if (ptinrect(m->xy,b->rect)) {
83                         r = recognize(b->scrib);
84                         scribchar(b, r);
85                         scribshow(b);
86                         if (r) chanprint(b->event, b->format, b->name, r);
87                 }
88         }
89         b->lastbut = m->buttons;
90 }
91
92 static void
93 scribfree(Control *c)
94 {
95         Scrib *b;
96
97         b = (Scrib*)c;
98         _putctlimage(b->image);
99         _putctlimage(b->color);
100         _putctlimage(b->bordercolor);
101         _putctlfont(b->font);
102 //      scribblefree(b->scrib);
103 }
104
105 static void
106 scribchar(Scrib *b, Rune r)
107 {
108         if(r == 0)
109                 b->lastchar[0] = '\0';
110         else if(r == ' ')
111                 strcpy(b->lastchar, "' '");
112         else if(r < ' ')
113                 sprint(b->lastchar, "ctl-%c", r+'@');
114         else
115                 sprint(b->lastchar, "%C", r);
116 }
117
118
119 static void
120 scribshow(Scrib *b)
121 {
122         Image *i;
123         Rectangle r;
124         char *mode;
125         Scribble *s = b->scrib;
126         char buf[32];
127
128         if (b->hidden)
129                 return;
130         if(b->border > 0){
131                 r = insetrect(b->rect, b->border);
132                 border(b->screen, b->rect, b->border, b->bordercolor->image, ZP);
133         }else
134                 r = b->rect;
135
136         i = b->image->image;
137         draw(b->screen, r, i, nil, i->r.min);
138
139         if (s->ctrlShift)
140                 mode = " ^C";
141         else if (s->puncShift)
142                 mode = " #&^";
143         else if (s->curCharSet == CS_DIGITS)
144                 mode = " 123";
145         else if (s->capsLock)
146                 mode = " ABC";
147         else if (s->tmpShift)
148                 mode = " Abc";
149         else
150                 mode = " abc";
151
152         snprint(buf, sizeof buf, "%s %s", mode, b->lastchar);
153
154         string(b->screen, r.min, b->color->image, ZP, b->font->font, buf);
155         flushimage(display, 1);
156 }
157
158 static void
159 scribctl(Control *c, CParse *cp)
160 {
161         int cmd;
162         Rectangle r;
163         Scrib *b;
164
165         b = (Scrib*)c;
166         cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
167         switch(cmd){
168         default:
169                 abort();
170                 ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
171                 break;
172         case EAlign:
173                 _ctlargcount(b, cp, 2);
174                 b->align = _ctlalignment(cp->args[1]);
175                 break;
176         case EBorder:
177                 _ctlargcount(b, cp, 2);
178                 if(cp->iargs[1] < 0)
179                         ctlerror("%q: bad border: %c", b->name, cp->str);
180                 b->border = cp->iargs[1];
181                 break;
182         case EBordercolor:
183                 _ctlargcount(b, cp, 2);
184                 _setctlimage(b, &b->bordercolor, cp->args[1]);
185                 break;
186         case EFocus:
187                 break;
188         case EImage:
189                 _ctlargcount(b, cp, 2);
190                 _setctlimage(b, &b->image, cp->args[1]);
191                 break;
192         case ELinecolor:
193                 _ctlargcount(b, cp, 2);
194                 _setctlimage(b, &b->bordercolor, cp->args[1]);
195                 break;
196         case ERect:
197                 _ctlargcount(b, cp, 5);
198                 r.min.x = cp->iargs[1];
199                 r.min.y = cp->iargs[2];
200                 r.max.x = cp->iargs[3];
201                 r.max.y = cp->iargs[4];
202                 if(Dx(r)<0 || Dy(r)<0)
203                         ctlerror("%q: bad rectangle: %s", b->name, cp->str);
204                 b->rect = r;
205                 break;
206         case EReveal:
207                 _ctlargcount(b, cp, 1);
208                 b->hidden = 0;
209                 scribshow(b);
210                 break;
211         case EShow:
212                 _ctlargcount(b, cp, 1);
213                 scribshow(b);
214                 break;
215         case EFont:
216                 _ctlargcount(b, cp, 2);
217                 _setctlfont(b, &b->font, cp->args[1]);
218                 break;
219         case EHide:
220                 _ctlargcount(b, cp, 1);
221                 b->hidden = 1;
222                 break;
223         case ESize:
224                 if (cp->nargs == 3)
225                         r.max = Pt(0x7fffffff, 0x7fffffff);
226                 else{
227                         _ctlargcount(b, cp, 5);
228                         r.max.x = cp->iargs[3];
229                         r.max.y = cp->iargs[4];
230                 }
231                 r.min.x = cp->iargs[1];
232                 r.min.y = cp->iargs[2];
233                 if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
234                         ctlerror("%q: bad sizes: %s", b->name, cp->str);
235                 b->size.min = r.min;
236                 b->size.max = r.max;
237                 break;
238         }
239 }
240
241 static void
242 resetstroke(Scrib *w)
243 {
244         Scribble *s = w->scrib;
245
246         s->ps.npts = 0;
247         scribshow(w);
248 }
249
250 static void
251 displaystroke(Scrib *b)
252 {
253         Scribble *s = b->scrib;
254
255         poly(b->screen, s->pt, s->ps.npts, Endsquare, Endsquare, 0, b->color->image, ZP);
256         flushimage(display, 1);
257 }
258
259 static void
260 displaylast(Scrib *w)
261 {
262         int         npt;
263         Scribble *s = w->scrib;
264
265         npt = s->ps.npts;
266         if (npt > 2)
267                 npt = 2;
268         poly(w->screen, s->pt + (s->ps.npts - npt), npt, Endsquare, Endsquare,
269                 0, w->color->image, ZP);
270         flushimage(display, 1);
271 }
272
273 static void
274 addpoint(Scrib *w, Point p)
275 {
276         pen_point       *ppa;
277         Point   *pt;
278         int             ppasize;
279         Scribble        *s = w->scrib;
280
281         if (s->ps.npts == s->ppasize) {
282                 ppasize = s->ppasize + 100;
283                 ppa = malloc ((sizeof (pen_point) + sizeof (Point)) * ppasize);
284                 if (!ppa)
285                         return;
286                 pt = (Point *) (ppa + ppasize);
287                 memmove(ppa, s->ps.pts, s->ppasize * sizeof (pen_point));
288                 memmove(pt, s->pt, s->ppasize * sizeof (Point));
289                 free (s->ps.pts);
290                 s->ps.pts = ppa;
291                 s->pt = pt;
292                 s->ppasize = ppasize;
293         }
294         ppa = &s->ps.pts[s->ps.npts];
295         ppa->Point = p;
296
297         pt = &s->pt[s->ps.npts];
298         *pt = p;
299
300         s->ps.npts++;
301         
302         displaylast(w);
303 }
304
305 Control*
306 createscribble(Controlset *cs, char *name)
307 {
308         Scrib *b;
309
310         b = (Scrib*)_createctl(cs, "scribble", sizeof(Scrib), name);
311         b->image = _getctlimage("white");
312         b->color = _getctlimage("black");
313         b->bordercolor = _getctlimage("black");
314         b->align = Aupperleft;
315         b->format = ctlstrdup("%q: value 0x%x");
316         b->font = _getctlfont("font");
317         b->scrib = scribblealloc();
318         b->lastbut = 0;
319         b->bordercolor = _getctlimage("black");
320         b->border = 0;
321         b->ctl = scribctl;
322         b->mouse = scribmouse;
323         b->exit = scribfree;
324         return (Control*)b;
325 }