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 addpoint(b, m->xy); 79 } else if (b->lastbut & 0x1) { 80 /* mouse went up */ 81 r = recognize(b->scrib); 82 scribchar(b, r); 83 scribshow(b); 84 if (r) chanprint(b->event, b->format, b->name, r); 85 } 86 b->lastbut = m->buttons; 87 } 88 89 static void 90 scribfree(Control *c) 91 { 92 Scrib *b; 93 94 b = (Scrib*)c; 95 _putctlimage(b->image); 96 _putctlimage(b->color); 97 _putctlimage(b->bordercolor); 98 _putctlfont(b->font); 99 // scribblefree(b->scrib); 100 } 101 102 static void 103 scribchar(Scrib *b, Rune r) 104 { 105 if(r == 0) 106 b->lastchar[0] = '\0'; 107 else if(r == ' ') 108 strcpy(b->lastchar, "' '"); 109 else if(r < ' ') 110 sprint(b->lastchar, "ctl-%c", r+'@'); 111 else 112 sprint(b->lastchar, "%C", r); 113 } 114 115 116 static void 117 scribshow(Scrib *b) 118 { 119 Image *i; 120 Rectangle r; 121 char *mode; 122 Scribble *s = b->scrib; 123 char buf[32]; 124 125 if (b->hidden) 126 return; 127 if(b->border > 0){ 128 r = insetrect(b->rect, b->border); 129 border(b->screen, b->rect, b->border, b->bordercolor->image, ZP); 130 }else 131 r = b->rect; 132 133 i = b->image->image; 134 draw(b->screen, r, i, nil, i->r.min); 135 136 if (s->ctrlShift) 137 mode = " ^C"; 138 else if (s->puncShift) 139 mode = " #&^"; 140 else if (s->curCharSet == CS_DIGITS) 141 mode = " 123"; 142 else if (s->capsLock) 143 mode = " ABC"; 144 else if (s->tmpShift) 145 mode = " Abc"; 146 else 147 mode = " abc"; 148 149 snprint(buf, sizeof buf, "%s %s", mode, b->lastchar); 150 151 string(b->screen, r.min, b->color->image, ZP, b->font->font, buf); 152 flushimage(display, 1); 153 } 154 155 static void 156 scribctl(Control *c, CParse *cp) 157 { 158 int cmd; 159 Rectangle r; 160 Scrib *b; 161 162 b = (Scrib*)c; 163 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 164 switch(cmd){ 165 default: 166 abort(); 167 ctlerror("%q: unrecognized message '%s'", b->name, cp->str); 168 break; 169 case EAlign: 170 _ctlargcount(b, cp, 2); 171 b->align = _ctlalignment(cp->args[1]); 172 break; 173 case EBorder: 174 _ctlargcount(b, cp, 2); 175 if(cp->iargs[1] < 0) 176 ctlerror("%q: bad border: %c", b->name, cp->str); 177 b->border = cp->iargs[1]; 178 break; 179 case EBordercolor: 180 _ctlargcount(b, cp, 2); 181 _setctlimage(b, &b->bordercolor, cp->args[1]); 182 break; 183 case EFocus: 184 break; 185 case EImage: 186 _ctlargcount(b, cp, 2); 187 _setctlimage(b, &b->image, cp->args[1]); 188 break; 189 case ELinecolor: 190 _ctlargcount(b, cp, 2); 191 _setctlimage(b, &b->bordercolor, cp->args[1]); 192 break; 193 case ERect: 194 _ctlargcount(b, cp, 5); 195 r.min.x = cp->iargs[1]; 196 r.min.y = cp->iargs[2]; 197 r.max.x = cp->iargs[3]; 198 r.max.y = cp->iargs[4]; 199 if(Dx(r)<0 || Dy(r)<0) 200 ctlerror("%q: bad rectangle: %s", b->name, cp->str); 201 b->rect = r; 202 break; 203 case EReveal: 204 _ctlargcount(b, cp, 1); 205 b->hidden = 0; 206 scribshow(b); 207 break; 208 case EShow: 209 _ctlargcount(b, cp, 1); 210 scribshow(b); 211 break; 212 case EFont: 213 _ctlargcount(b, cp, 2); 214 _setctlfont(b, &b->font, cp->args[1]); 215 break; 216 case EHide: 217 _ctlargcount(b, cp, 1); 218 b->hidden = 1; 219 break; 220 case ESize: 221 if (cp->nargs == 3) 222 r.max = Pt(0x7fffffff, 0x7fffffff); 223 else{ 224 _ctlargcount(b, cp, 5); 225 r.max.x = cp->iargs[3]; 226 r.max.y = cp->iargs[4]; 227 } 228 r.min.x = cp->iargs[1]; 229 r.min.y = cp->iargs[2]; 230 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) 231 ctlerror("%q: bad sizes: %s", b->name, cp->str); 232 b->size.min = r.min; 233 b->size.max = r.max; 234 break; 235 } 236 } 237 238 static void 239 resetstroke(Scrib *w) 240 { 241 Scribble *s = w->scrib; 242 243 s->ps.npts = 0; 244 scribshow(w); 245 } 246 247 static void 248 displaystroke(Scrib *b) 249 { 250 Scribble *s = b->scrib; 251 252 poly(b->screen, s->pt, s->ps.npts, Endsquare, Endsquare, 0, b->color->image, ZP); 253 flushimage(display, 1); 254 } 255 256 static void 257 displaylast(Scrib *w) 258 { 259 int npt; 260 Scribble *s = w->scrib; 261 262 npt = s->ps.npts; 263 if (npt > 2) 264 npt = 2; 265 poly(w->screen, s->pt + (s->ps.npts - npt), npt, Endsquare, Endsquare, 266 0, w->color->image, ZP); 267 flushimage(display, 1); 268 } 269 270 static void 271 addpoint(Scrib *w, Point p) 272 { 273 pen_point *ppa; 274 Point *pt; 275 int ppasize; 276 Scribble *s = w->scrib; 277 278 if (s->ps.npts == s->ppasize) { 279 ppasize = s->ppasize + 100; 280 ppa = malloc ((sizeof (pen_point) + sizeof (Point)) * ppasize); 281 if (!ppa) 282 return; 283 pt = (Point *) (ppa + ppasize); 284 memmove(ppa, s->ps.pts, s->ppasize * sizeof (pen_point)); 285 memmove(pt, s->pt, s->ppasize * sizeof (Point)); 286 free (s->ps.pts); 287 s->ps.pts = ppa; 288 s->pt = pt; 289 s->ppasize = ppasize; 290 } 291 ppa = &s->ps.pts[s->ps.npts]; 292 ppa->Point = p; 293 294 pt = &s->pt[s->ps.npts]; 295 *pt = p; 296 297 s->ps.npts++; 298 299 displaylast(w); 300 } 301 302 Control* 303 createscribble(Controlset *cs, char *name) 304 { 305 Scrib *b; 306 307 b = (Scrib*)_createctl(cs, "scribble", sizeof(Scrib), name); 308 b->image = _getctlimage("white"); 309 b->color = _getctlimage("black"); 310 b->bordercolor = _getctlimage("black"); 311 b->align = Aupperleft; 312 b->format = ctlstrdup("%q: value 0x%x"); 313 b->font = _getctlfont("font"); 314 b->scrib = scribblealloc(); 315 b->lastbut = 0; 316 b->bordercolor = _getctlimage("black"); 317 b->border = 0; 318 b->ctl = scribctl; 319 b->mouse = scribmouse; 320 b->exit = scribfree; 321 return (Control*)b; 322 } 323