180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <draw.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include <mouse.h>
680ee5cbfSDavid du Colombier #include <keyboard.h>
780ee5cbfSDavid du Colombier #include <control.h>
880ee5cbfSDavid du Colombier #include <scribble.h>
980ee5cbfSDavid du Colombier
1080ee5cbfSDavid du Colombier typedef struct Scrib Scrib;
1180ee5cbfSDavid du Colombier
1280ee5cbfSDavid du Colombier struct Scrib
1380ee5cbfSDavid du Colombier {
1480ee5cbfSDavid du Colombier Control;
1580ee5cbfSDavid du Colombier int border;
1680ee5cbfSDavid du Colombier CImage *image;
1780ee5cbfSDavid du Colombier CImage *color;
1880ee5cbfSDavid du Colombier CImage *bordercolor;
1980ee5cbfSDavid du Colombier CFont *font;
2080ee5cbfSDavid du Colombier int align;
2180ee5cbfSDavid du Colombier int lastbut;
2280ee5cbfSDavid du Colombier char lastchar[8];
2380ee5cbfSDavid du Colombier Scribble *scrib;
2480ee5cbfSDavid du Colombier };
2580ee5cbfSDavid du Colombier
2680ee5cbfSDavid du Colombier enum{
2780ee5cbfSDavid du Colombier EAlign,
2880ee5cbfSDavid du Colombier EBorder,
2980ee5cbfSDavid du Colombier EBordercolor,
3080ee5cbfSDavid du Colombier EFocus,
3180ee5cbfSDavid du Colombier EFont,
329a747e4fSDavid du Colombier EHide,
3380ee5cbfSDavid du Colombier EImage,
3480ee5cbfSDavid du Colombier ELinecolor,
3580ee5cbfSDavid du Colombier ERect,
369a747e4fSDavid du Colombier EReveal,
3780ee5cbfSDavid du Colombier EShow,
389a747e4fSDavid du Colombier ESize,
3980ee5cbfSDavid du Colombier };
4080ee5cbfSDavid du Colombier
4180ee5cbfSDavid du Colombier static char *cmds[] = {
4280ee5cbfSDavid du Colombier [EAlign] = "align",
4380ee5cbfSDavid du Colombier [EBorder] = "border",
4480ee5cbfSDavid du Colombier [EBordercolor] ="bordercolor",
4580ee5cbfSDavid du Colombier [EFocus] = "focus",
4680ee5cbfSDavid du Colombier [EFont] = "font",
479a747e4fSDavid du Colombier [EHide] = "hide",
4880ee5cbfSDavid du Colombier [EImage] = "image",
4980ee5cbfSDavid du Colombier [ELinecolor] = "linecolor",
5080ee5cbfSDavid du Colombier [ERect] = "rect",
519a747e4fSDavid du Colombier [EReveal] = "reveal",
5280ee5cbfSDavid du Colombier [EShow] = "show",
539a747e4fSDavid du Colombier [ESize] = "size",
5480ee5cbfSDavid du Colombier nil
5580ee5cbfSDavid du Colombier };
5680ee5cbfSDavid du Colombier
5780ee5cbfSDavid du Colombier static void scribshow(Scrib*);
5880ee5cbfSDavid du Colombier static void scribchar(Scrib*, Rune);
5980ee5cbfSDavid du Colombier
6080ee5cbfSDavid du Colombier static void resetstroke(Scrib *w);
6180ee5cbfSDavid du Colombier static void displaystroke(Scrib *w);
6280ee5cbfSDavid du Colombier static void displaylast(Scrib *w);
6380ee5cbfSDavid du Colombier static void addpoint(Scrib *w, Point p);
6480ee5cbfSDavid du Colombier
6580ee5cbfSDavid du Colombier static void
scribmouse(Control * c,Mouse * m)669a747e4fSDavid du Colombier scribmouse(Control *c, Mouse *m)
6780ee5cbfSDavid du Colombier {
6880ee5cbfSDavid du Colombier Scrib *b;
6980ee5cbfSDavid du Colombier Rune r;
7080ee5cbfSDavid du Colombier
719a747e4fSDavid du Colombier b = (Scrib*)c;
729a747e4fSDavid du Colombier if (m->buttons & 0x1) {
7380ee5cbfSDavid du Colombier if ((b->lastbut & 0x1) == 0) {
7480ee5cbfSDavid du Colombier /* mouse went down */
7580ee5cbfSDavid du Colombier resetstroke(b);
7680ee5cbfSDavid du Colombier }
7780ee5cbfSDavid du Colombier /* mouse is down */
78*da79363fSDavid du Colombier if (ptinrect(m->xy,b->rect))
799a747e4fSDavid du Colombier addpoint(b, m->xy);
8080ee5cbfSDavid du Colombier } else if (b->lastbut & 0x1) {
8180ee5cbfSDavid du Colombier /* mouse went up */
82*da79363fSDavid du Colombier if (ptinrect(m->xy,b->rect)) {
8380ee5cbfSDavid du Colombier r = recognize(b->scrib);
8480ee5cbfSDavid du Colombier scribchar(b, r);
8580ee5cbfSDavid du Colombier scribshow(b);
869a747e4fSDavid du Colombier if (r) chanprint(b->event, b->format, b->name, r);
8780ee5cbfSDavid du Colombier }
88*da79363fSDavid du Colombier }
899a747e4fSDavid du Colombier b->lastbut = m->buttons;
9080ee5cbfSDavid du Colombier }
9180ee5cbfSDavid du Colombier
9280ee5cbfSDavid du Colombier static void
scribfree(Control * c)939a747e4fSDavid du Colombier scribfree(Control *c)
9480ee5cbfSDavid du Colombier {
959a747e4fSDavid du Colombier Scrib *b;
969a747e4fSDavid du Colombier
979a747e4fSDavid du Colombier b = (Scrib*)c;
9880ee5cbfSDavid du Colombier _putctlimage(b->image);
9980ee5cbfSDavid du Colombier _putctlimage(b->color);
10080ee5cbfSDavid du Colombier _putctlimage(b->bordercolor);
10180ee5cbfSDavid du Colombier _putctlfont(b->font);
10280ee5cbfSDavid du Colombier // scribblefree(b->scrib);
10380ee5cbfSDavid du Colombier }
10480ee5cbfSDavid du Colombier
10580ee5cbfSDavid du Colombier static void
scribchar(Scrib * b,Rune r)10680ee5cbfSDavid du Colombier scribchar(Scrib *b, Rune r)
10780ee5cbfSDavid du Colombier {
10880ee5cbfSDavid du Colombier if(r == 0)
10980ee5cbfSDavid du Colombier b->lastchar[0] = '\0';
11080ee5cbfSDavid du Colombier else if(r == ' ')
11180ee5cbfSDavid du Colombier strcpy(b->lastchar, "' '");
11280ee5cbfSDavid du Colombier else if(r < ' ')
11380ee5cbfSDavid du Colombier sprint(b->lastchar, "ctl-%c", r+'@');
11480ee5cbfSDavid du Colombier else
11580ee5cbfSDavid du Colombier sprint(b->lastchar, "%C", r);
11680ee5cbfSDavid du Colombier }
11780ee5cbfSDavid du Colombier
11880ee5cbfSDavid du Colombier
11980ee5cbfSDavid du Colombier static void
scribshow(Scrib * b)12080ee5cbfSDavid du Colombier scribshow(Scrib *b)
12180ee5cbfSDavid du Colombier {
12280ee5cbfSDavid du Colombier Image *i;
12380ee5cbfSDavid du Colombier Rectangle r;
12480ee5cbfSDavid du Colombier char *mode;
12580ee5cbfSDavid du Colombier Scribble *s = b->scrib;
12680ee5cbfSDavid du Colombier char buf[32];
12780ee5cbfSDavid du Colombier
1289a747e4fSDavid du Colombier if (b->hidden)
1299a747e4fSDavid du Colombier return;
13080ee5cbfSDavid du Colombier if(b->border > 0){
13180ee5cbfSDavid du Colombier r = insetrect(b->rect, b->border);
13280ee5cbfSDavid du Colombier border(b->screen, b->rect, b->border, b->bordercolor->image, ZP);
13380ee5cbfSDavid du Colombier }else
13480ee5cbfSDavid du Colombier r = b->rect;
13580ee5cbfSDavid du Colombier
13680ee5cbfSDavid du Colombier i = b->image->image;
13780ee5cbfSDavid du Colombier draw(b->screen, r, i, nil, i->r.min);
13880ee5cbfSDavid du Colombier
13980ee5cbfSDavid du Colombier if (s->ctrlShift)
14080ee5cbfSDavid du Colombier mode = " ^C";
14180ee5cbfSDavid du Colombier else if (s->puncShift)
14280ee5cbfSDavid du Colombier mode = " #&^";
14380ee5cbfSDavid du Colombier else if (s->curCharSet == CS_DIGITS)
14480ee5cbfSDavid du Colombier mode = " 123";
14580ee5cbfSDavid du Colombier else if (s->capsLock)
14680ee5cbfSDavid du Colombier mode = " ABC";
14780ee5cbfSDavid du Colombier else if (s->tmpShift)
14880ee5cbfSDavid du Colombier mode = " Abc";
14980ee5cbfSDavid du Colombier else
15080ee5cbfSDavid du Colombier mode = " abc";
15180ee5cbfSDavid du Colombier
15280ee5cbfSDavid du Colombier snprint(buf, sizeof buf, "%s %s", mode, b->lastchar);
15380ee5cbfSDavid du Colombier
15480ee5cbfSDavid du Colombier string(b->screen, r.min, b->color->image, ZP, b->font->font, buf);
15580ee5cbfSDavid du Colombier flushimage(display, 1);
15680ee5cbfSDavid du Colombier }
15780ee5cbfSDavid du Colombier
15880ee5cbfSDavid du Colombier static void
scribctl(Control * c,CParse * cp)1599a747e4fSDavid du Colombier scribctl(Control *c, CParse *cp)
16080ee5cbfSDavid du Colombier {
16180ee5cbfSDavid du Colombier int cmd;
16280ee5cbfSDavid du Colombier Rectangle r;
16380ee5cbfSDavid du Colombier Scrib *b;
16480ee5cbfSDavid du Colombier
16580ee5cbfSDavid du Colombier b = (Scrib*)c;
1669a747e4fSDavid du Colombier cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
16780ee5cbfSDavid du Colombier switch(cmd){
16880ee5cbfSDavid du Colombier default:
1699a747e4fSDavid du Colombier abort();
1709a747e4fSDavid du Colombier ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
17180ee5cbfSDavid du Colombier break;
17280ee5cbfSDavid du Colombier case EAlign:
1739a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
1749a747e4fSDavid du Colombier b->align = _ctlalignment(cp->args[1]);
17580ee5cbfSDavid du Colombier break;
17680ee5cbfSDavid du Colombier case EBorder:
1779a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
1789a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
1799a747e4fSDavid du Colombier ctlerror("%q: bad border: %c", b->name, cp->str);
1809a747e4fSDavid du Colombier b->border = cp->iargs[1];
18180ee5cbfSDavid du Colombier break;
18280ee5cbfSDavid du Colombier case EBordercolor:
1839a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
1849a747e4fSDavid du Colombier _setctlimage(b, &b->bordercolor, cp->args[1]);
18580ee5cbfSDavid du Colombier break;
18680ee5cbfSDavid du Colombier case EFocus:
18780ee5cbfSDavid du Colombier break;
18880ee5cbfSDavid du Colombier case EImage:
1899a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
1909a747e4fSDavid du Colombier _setctlimage(b, &b->image, cp->args[1]);
19180ee5cbfSDavid du Colombier break;
19280ee5cbfSDavid du Colombier case ELinecolor:
1939a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
1949a747e4fSDavid du Colombier _setctlimage(b, &b->bordercolor, cp->args[1]);
19580ee5cbfSDavid du Colombier break;
19680ee5cbfSDavid du Colombier case ERect:
1979a747e4fSDavid du Colombier _ctlargcount(b, cp, 5);
1989a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
1999a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
2009a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
2019a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
20280ee5cbfSDavid du Colombier if(Dx(r)<0 || Dy(r)<0)
2039a747e4fSDavid du Colombier ctlerror("%q: bad rectangle: %s", b->name, cp->str);
20480ee5cbfSDavid du Colombier b->rect = r;
20580ee5cbfSDavid du Colombier break;
2069a747e4fSDavid du Colombier case EReveal:
2079a747e4fSDavid du Colombier _ctlargcount(b, cp, 1);
2089a747e4fSDavid du Colombier b->hidden = 0;
2099a747e4fSDavid du Colombier scribshow(b);
2109a747e4fSDavid du Colombier break;
21180ee5cbfSDavid du Colombier case EShow:
2129a747e4fSDavid du Colombier _ctlargcount(b, cp, 1);
21380ee5cbfSDavid du Colombier scribshow(b);
21480ee5cbfSDavid du Colombier break;
21580ee5cbfSDavid du Colombier case EFont:
2169a747e4fSDavid du Colombier _ctlargcount(b, cp, 2);
2179a747e4fSDavid du Colombier _setctlfont(b, &b->font, cp->args[1]);
2189a747e4fSDavid du Colombier break;
2199a747e4fSDavid du Colombier case EHide:
2209a747e4fSDavid du Colombier _ctlargcount(b, cp, 1);
2219a747e4fSDavid du Colombier b->hidden = 1;
2229a747e4fSDavid du Colombier break;
2239a747e4fSDavid du Colombier case ESize:
2249a747e4fSDavid du Colombier if (cp->nargs == 3)
2259a747e4fSDavid du Colombier r.max = Pt(0x7fffffff, 0x7fffffff);
2269a747e4fSDavid du Colombier else{
2279a747e4fSDavid du Colombier _ctlargcount(b, cp, 5);
2289a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
2299a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
2309a747e4fSDavid du Colombier }
2319a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
2329a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
2339a747e4fSDavid du Colombier 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)
2349a747e4fSDavid du Colombier ctlerror("%q: bad sizes: %s", b->name, cp->str);
2359a747e4fSDavid du Colombier b->size.min = r.min;
2369a747e4fSDavid du Colombier b->size.max = r.max;
23780ee5cbfSDavid du Colombier break;
23880ee5cbfSDavid du Colombier }
23980ee5cbfSDavid du Colombier }
24080ee5cbfSDavid du Colombier
24180ee5cbfSDavid du Colombier static void
resetstroke(Scrib * w)24280ee5cbfSDavid du Colombier resetstroke(Scrib *w)
24380ee5cbfSDavid du Colombier {
24480ee5cbfSDavid du Colombier Scribble *s = w->scrib;
24580ee5cbfSDavid du Colombier
24680ee5cbfSDavid du Colombier s->ps.npts = 0;
24780ee5cbfSDavid du Colombier scribshow(w);
24880ee5cbfSDavid du Colombier }
24980ee5cbfSDavid du Colombier
25080ee5cbfSDavid du Colombier static void
displaystroke(Scrib * b)25180ee5cbfSDavid du Colombier displaystroke(Scrib *b)
25280ee5cbfSDavid du Colombier {
25380ee5cbfSDavid du Colombier Scribble *s = b->scrib;
25480ee5cbfSDavid du Colombier
25580ee5cbfSDavid du Colombier poly(b->screen, s->pt, s->ps.npts, Endsquare, Endsquare, 0, b->color->image, ZP);
25680ee5cbfSDavid du Colombier flushimage(display, 1);
25780ee5cbfSDavid du Colombier }
25880ee5cbfSDavid du Colombier
25980ee5cbfSDavid du Colombier static void
displaylast(Scrib * w)26080ee5cbfSDavid du Colombier displaylast(Scrib *w)
26180ee5cbfSDavid du Colombier {
26280ee5cbfSDavid du Colombier int npt;
26380ee5cbfSDavid du Colombier Scribble *s = w->scrib;
26480ee5cbfSDavid du Colombier
26580ee5cbfSDavid du Colombier npt = s->ps.npts;
26680ee5cbfSDavid du Colombier if (npt > 2)
26780ee5cbfSDavid du Colombier npt = 2;
26880ee5cbfSDavid du Colombier poly(w->screen, s->pt + (s->ps.npts - npt), npt, Endsquare, Endsquare,
26980ee5cbfSDavid du Colombier 0, w->color->image, ZP);
27080ee5cbfSDavid du Colombier flushimage(display, 1);
27180ee5cbfSDavid du Colombier }
27280ee5cbfSDavid du Colombier
27380ee5cbfSDavid du Colombier static void
addpoint(Scrib * w,Point p)27480ee5cbfSDavid du Colombier addpoint(Scrib *w, Point p)
27580ee5cbfSDavid du Colombier {
27680ee5cbfSDavid du Colombier pen_point *ppa;
27780ee5cbfSDavid du Colombier Point *pt;
27880ee5cbfSDavid du Colombier int ppasize;
27980ee5cbfSDavid du Colombier Scribble *s = w->scrib;
28080ee5cbfSDavid du Colombier
28180ee5cbfSDavid du Colombier if (s->ps.npts == s->ppasize) {
28280ee5cbfSDavid du Colombier ppasize = s->ppasize + 100;
28380ee5cbfSDavid du Colombier ppa = malloc ((sizeof (pen_point) + sizeof (Point)) * ppasize);
28480ee5cbfSDavid du Colombier if (!ppa)
28580ee5cbfSDavid du Colombier return;
28680ee5cbfSDavid du Colombier pt = (Point *) (ppa + ppasize);
28780ee5cbfSDavid du Colombier memmove(ppa, s->ps.pts, s->ppasize * sizeof (pen_point));
28880ee5cbfSDavid du Colombier memmove(pt, s->pt, s->ppasize * sizeof (Point));
28980ee5cbfSDavid du Colombier free (s->ps.pts);
29080ee5cbfSDavid du Colombier s->ps.pts = ppa;
29180ee5cbfSDavid du Colombier s->pt = pt;
29280ee5cbfSDavid du Colombier s->ppasize = ppasize;
29380ee5cbfSDavid du Colombier }
29480ee5cbfSDavid du Colombier ppa = &s->ps.pts[s->ps.npts];
29580ee5cbfSDavid du Colombier ppa->Point = p;
29680ee5cbfSDavid du Colombier
29780ee5cbfSDavid du Colombier pt = &s->pt[s->ps.npts];
29880ee5cbfSDavid du Colombier *pt = p;
29980ee5cbfSDavid du Colombier
30080ee5cbfSDavid du Colombier s->ps.npts++;
30180ee5cbfSDavid du Colombier
30280ee5cbfSDavid du Colombier displaylast(w);
30380ee5cbfSDavid du Colombier }
3049a747e4fSDavid du Colombier
3059a747e4fSDavid du Colombier Control*
createscribble(Controlset * cs,char * name)3069a747e4fSDavid du Colombier createscribble(Controlset *cs, char *name)
3079a747e4fSDavid du Colombier {
3089a747e4fSDavid du Colombier Scrib *b;
3099a747e4fSDavid du Colombier
3109a747e4fSDavid du Colombier b = (Scrib*)_createctl(cs, "scribble", sizeof(Scrib), name);
3119a747e4fSDavid du Colombier b->image = _getctlimage("white");
3129a747e4fSDavid du Colombier b->color = _getctlimage("black");
3139a747e4fSDavid du Colombier b->bordercolor = _getctlimage("black");
3149a747e4fSDavid du Colombier b->align = Aupperleft;
3159a747e4fSDavid du Colombier b->format = ctlstrdup("%q: value 0x%x");
3169a747e4fSDavid du Colombier b->font = _getctlfont("font");
3179a747e4fSDavid du Colombier b->scrib = scribblealloc();
3189a747e4fSDavid du Colombier b->lastbut = 0;
3199a747e4fSDavid du Colombier b->bordercolor = _getctlimage("black");
3209a747e4fSDavid du Colombier b->border = 0;
3219a747e4fSDavid du Colombier b->ctl = scribctl;
3229a747e4fSDavid du Colombier b->mouse = scribmouse;
3239a747e4fSDavid du Colombier b->exit = scribfree;
3249a747e4fSDavid du Colombier return (Control*)b;
3259a747e4fSDavid du Colombier }
326