11 typedef struct Text Text;
26 CImage *selectingcolor;
28 int selectmode; // Selsingle, Selmulti
29 int selectstyle; // Seldown, Selup (use Selup only with Selsingle)
34 int sel; // line nr of selection made by last button down
35 int but; // last button down (still being hold)
36 int offsel; // we are on selection
76 static char *cmds[] = {
77 [EAccumulate] = "accumulate",
81 [EBordercolor] = "bordercolor",
89 [EReplace] = "replace",
93 [ESelectcolor] = "selectcolor",
94 [ESelectingcolor] = "selectingcolor",
95 [ESelectmode] = "selectmode",
96 [ESelectstyle] = "selectstyle",
99 [ETextcolor] = "textcolor",
100 [ETopline] = "topline",
106 static void textshow(Text*);
107 static void texttogglei(Text*, int);
108 static int textline(Text*, Point);
109 static int texttoggle(Text*, Point);
112 textmouse(Control *c, Mouse *m)
118 if (debug) fprint(2, "textmouse %s t->lastbut %d; m->buttons %d\n", t->name, t->lastbut, m->buttons);
121 if ((t->selectstyle == Selup) && (m->buttons&7)) {
122 sel = textline(t, m->xy);
124 // if (debug) fprint(2, "textmouse Selup %q sel=%d t->sel=%d t->but=%d\n",
125 // t->name, sel, t->sel, t->but);
126 t->offsel = (sel == t->sel) ? 0 : 1;
127 if ((sel == t->sel &&
128 ((t->selected[t->sel] && !t->but) ||
129 ((!t->selected[t->sel]) && t->but))) ||
131 ((t->selected[t->sel] && t->but) ||
132 ((!t->selected[t->sel]) && (!t->but))))) {
133 texttogglei(t, t->sel);
137 if(t->lastbut != (m->buttons&7)){
139 sel = texttoggle(t, m->xy);
141 if (t->selectstyle == Seldown) {
142 chanprint(t->event, "%q: select %d %d",
143 t->name, sel, t->selected[sel] ? (m->buttons & 7) : 0);
144 if (debug) fprint(2, "textmouse Seldown event %q: select %d %d\n",
145 t->name, sel, t->selected[sel] ? (m->buttons & 7) : 0);
147 if (debug) fprint(2, "textmouse Selup no event yet %q: select %d %d\n",
148 t->name, sel, t->selected[sel] ? (m->buttons & 7) : 0);
150 t->but = t->selected[sel] ? (m->buttons & 7) : 0;
153 } else if (t->selectstyle == Selup) {
154 sel = textline(t, m->xy);
156 if ((sel >= 0) && (sel == t->sel)) {
157 chanprint(t->event, "%q: select %d %d",
158 t->name, sel, t->but);
159 if (debug) fprint(2, "textmouse Selup event %q: select %d %d\n",
160 t->name, sel, t->but);
161 } else if (sel != t->sel) {
162 if ((t->selected[t->sel] && t->but) ||
163 ((!t->selected[t->sel]) && (!t->but))) {
164 texttogglei(t, t->sel);
168 if (debug) fprint(2, "textmouse Selup cancel %q: select %d %d\n",
169 t->name, sel, t->but);
174 t->lastbut = m->buttons & 7;
185 _putctlfont(t->font);
186 _putctlimage(t->image);
187 _putctlimage(t->textcolor);
188 _putctlimage(t->bordercolor);
189 _putctlimage(t->selectcolor);
190 _putctlimage(t->selectingcolor);
191 for(i=0; i<t->nline; i++)
210 draw(t->screen, r, t->image->image, nil, t->image->image->r.min);
212 border(t->screen, r, t->border, t->bordercolor->image, t->bordercolor->image->r.min);
213 r = insetrect(r, t->border);
216 t->nvis = Dy(r)/f->height;
217 for(i=t->topline; i<t->nline && i<t->topline+t->nvis; i++){
219 ntext = runestrlen(text);
220 r.max.y = r.min.y+f->height;
221 if(t->sel == i && t->offsel)
222 draw(t->screen, r, t->selectingcolor->image, nil, ZP);
223 else if(t->selected[i])
224 draw(t->screen, r, t->selectcolor->image, nil, ZP);
225 p = _ctlalignpoint(r,
226 runestringnwidth(f, text, ntext),
227 f->height, t->align);
230 p2.x = p.x + 0.5*runestringnwidth(f, text, ntext);
231 p2.y = p.y + 0.5*f->height;
232 moveto(t->controlset->mousectl, p2);
235 _string(t->screen, p, t->textcolor->image,
236 ZP, f, nil, text, ntext, tr,
238 r.min.y += f->height;
240 flushimage(display, 1);
244 textctl(Control *c, CParse *cp)
252 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
255 ctlerror("%q: unrecognized message '%s'", t->name, cp->str);
258 _ctlargcount(t, cp, 2);
259 t->align = _ctlalignment(cp->args[1]);
262 _ctlargcount(t, cp, 2);
264 ctlerror("%q: bad border: %c", t->name, cp->str);
265 t->border = cp->iargs[1];
268 _ctlargcount(t, cp, 2);
269 _setctlimage(t, &t->bordercolor, cp->args[1]);
272 _ctlargcount(t, cp, 1);
273 for(i=0; i<t->nline; i++)
277 t->line = ctlmalloc(sizeof(Rune*));
278 t->selected = ctlmalloc(1);
283 _ctlargcount(t, cp, 2);
285 if(i<0 || i>=t->nline)
286 ctlerror("%q: line number out of range: %s", t->name, cp->str);
288 memmove(t->line+i, t->line+i+1, (t->nline-(i+1))*sizeof(Rune*));
289 memmove(t->selected+i, t->selected+i+1, t->nline-(i+1));
296 _ctlargcount(t, cp, 2);
297 _setctlfont(t, &t->font, cp->args[1]);
300 _ctlargcount(t, cp, 1);
304 _ctlargcount(t, cp, 2);
305 _setctlimage(t, &t->image, cp->args[1]);
308 _ctlargcount(t, cp, 5);
309 r.min.x = cp->iargs[1];
310 r.min.y = cp->iargs[2];
311 r.max.x = cp->iargs[3];
312 r.max.y = cp->iargs[4];
313 if(Dx(r)<=0 || Dy(r)<=0)
314 ctlerror("%q: bad rectangle: %s", t->name, cp->str);
316 t->nvis = (Dy(r)-2*t->border)/t->font->font->height;
319 _ctlargcount(t, cp, 3);
321 if(i<0 || i>=t->nline)
322 ctlerror("%q: line number out of range: %s", t->name, cp->str);
324 t->line[i] = _ctlrunestr(cp->args[2]);
328 _ctlargcount(t, cp, 1);
333 _ctlargcount(t, cp, 2);
334 t->scroll = cp->iargs[1];
337 if(cp->nargs!=2 && cp->nargs!=3)
339 ctlerror("%q: bad select message: %s", t->name, cp->str);
341 if(strcmp(cp->args[1], "all") == 0){
342 memset(t->selected, 1, t->nline);
345 if(strcmp(cp->args[1], "none") == 0){
346 memset(t->selected, 0, t->nline);
349 if(cp->args[1][0]<'0' && '9'<cp->args[1][0])
351 texttogglei(t, cp->iargs[1]);
354 if(cp->iargs[1]<0 || cp->iargs[1]>=t->nline)
355 ctlerror("%q: selection index out of range (nline %d): %s", t->name, t->nline, cp->str);
356 if(t->selected[cp->iargs[1]] != (cp->iargs[2]!=0))
357 texttogglei(t, cp->iargs[1]);
360 _ctlargcount(t, cp, 2);
361 _setctlimage(t, &t->selectcolor, cp->args[1]);
364 _ctlargcount(t, cp, 2);
365 if(strcmp(cp->args[1], "single") == 0)
366 t->selectmode = Selsingle;
367 else if(strncmp(cp->args[1], "multi", 5) == 0)
368 t->selectmode = Selmulti;
371 _ctlargcount(t, cp, 2);
372 if(strcmp(cp->args[1], "down") == 0)
373 t->selectstyle = Seldown;
374 else if(strcmp(cp->args[1], "up") == 0)
375 t->selectstyle = Selup;
378 _ctlargcount(t, cp, 1);
383 r.max = Pt(10000, 10000);
385 _ctlargcount(t, cp, 5);
386 r.max.x = cp->iargs[3];
387 r.max.y = cp->iargs[4];
389 r.min.x = cp->iargs[1];
390 r.min.y = cp->iargs[2];
391 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)
392 ctlerror("%q: bad sizes: %s", t->name, cp->str);
397 _ctlargcount(t, cp, 2);
398 _setctlimage(t, &t->textcolor, cp->args[1]);
401 _ctlargcount(t, cp, 2);
413 /* set contents to single line */
414 /* free existing text and fall through to add */
415 for(i=0; i<t->nline; i++){
426 ctlerror("%q: wrong argument count in '%s'", t->name, cp->str);
432 if(n<0 || n>t->nline)
433 ctlerror("%q: line number out of range: %s", t->name, cp->str);
436 rp = _ctlrunestr(cp->args[cp->nargs-1]);
437 t->line = ctlrealloc(t->line, (t->nline+1)*sizeof(Rune*));
438 memmove(t->line+n+1, t->line+n, (t->nline-n)*sizeof(Rune*));
440 t->selected = ctlrealloc(t->selected, t->nline+1);
441 memmove(t->selected+n+1, t->selected+n, t->nline-n);
442 t->selected[n] = (t->selectmode==Selmulti && cmd!=EAccumulate);
445 if(n > t->topline + (t->nvis - 1)){
446 t->topline = n - (t->nvis - 1);
453 if(cmd != EAccumulate)
454 if(t->scroll || t->nline<=t->topline+t->nvis)
458 _ctlargcount(t, cp, 2);
460 if(i <0 || i>=t->nline)
461 ctlerror("%q: selection index out of range (nline %d): %s", t->name, t->nline, cp->str);
462 if(i < t->topline || i >= t->topline+t->nvis){
465 t->warp = cp->iargs[1];
473 texttogglei(Text *t, int i)
477 if(t->selectmode == Selsingle){
478 /* clear the others */
479 prev = t->selected[i];
480 memset(t->selected, 0, t->nline);
481 t->selected[i] = prev;
488 textline(Text *t, Point p)
495 r = insetrect(r, t->border);
498 i = (p.y-r.min.y)/t->font->font->height;
506 texttoggle(Text *t, Point p)
517 createtext(Controlset *cs, char *name)
521 t = (Text*)_createctl(cs, "text", sizeof(Text), name);
522 t->line = ctlmalloc(sizeof(Rune*));
523 t->selected = ctlmalloc(1);
525 t->image = _getctlimage("white");
526 t->textcolor = _getctlimage("black");
527 t->bordercolor = _getctlimage("black");
528 t->selectcolor = _getctlimage("yellow");
529 t->selectingcolor = _getctlimage("paleyellow");
530 t->font = _getctlfont("font");
531 t->selectmode = Selsingle;
532 t->selectstyle = Selup; // Seldown;
534 t->mouse = textmouse;