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 } 326