summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/g_rtext.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_rtext.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/g_rtext.c972
1 files changed, 972 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_rtext.c b/apps/plugins/pdbox/PDa/src/g_rtext.c
new file mode 100644
index 0000000000..8ffc8f415b
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/g_rtext.c
@@ -0,0 +1,972 @@
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
6/* have to insert gui-objects into editor-list */
7/* all changes are labeled with iemlib */
8
9#include <stdlib.h>
10#include <string.h>
11#include <stdio.h>
12#include <ctype.h>
13#include "m_pd.h"
14#include "s_stuff.h"
15#include "g_canvas.h"
16#include "t_tk.h"
17
18#define LMARGIN 1
19#define RMARGIN 1
20#define TMARGIN 2
21#define BMARGIN 2
22
23#define SEND_FIRST 1
24#define SEND_UPDATE 2
25#define SEND_CHECK 0
26
27struct _rtext
28{
29 char *x_buf;
30 int x_bufsize;
31 int x_selstart;
32 int x_selend;
33 int x_active;
34 int x_dragfrom;
35 int x_height;
36 int x_drawnwidth;
37 int x_drawnheight;
38 t_text *x_text;
39 t_glist *x_glist;
40 char x_tag[50];
41 struct _rtext *x_next;
42};
43
44t_rtext *rtext_new(t_glist *glist, t_text *who)
45{
46 t_rtext *x = (t_rtext *)getbytes(sizeof *x);
47 int w = 0, h = 0, indx;
48 x->x_height = -1;
49 x->x_text = who;
50 x->x_glist = glist;
51 x->x_next = glist->gl_editor->e_rtext;
52 x->x_selstart = x->x_selend = x->x_active =
53 x->x_drawnwidth = x->x_drawnheight = 0;
54 binbuf_gettext(who->te_binbuf, &x->x_buf, &x->x_bufsize);
55 glist->gl_editor->e_rtext = x;
56 sprintf(x->x_tag, ".x%x.t%x", (t_int)glist_getcanvas(x->x_glist),
57 (t_int)x);
58 return (x);
59}
60
61static t_rtext *rtext_entered;
62
63void rtext_free(t_rtext *x)
64{
65 if (x->x_glist->gl_editor->e_textedfor == x)
66 x->x_glist->gl_editor->e_textedfor = 0;
67 if (x->x_glist->gl_editor->e_rtext == x)
68 x->x_glist->gl_editor->e_rtext = x->x_next;
69 else
70 {
71 t_rtext *e2;
72 for (e2 = x->x_glist->gl_editor->e_rtext; e2; e2 = e2->x_next)
73 if (e2->x_next == x)
74 {
75 e2->x_next = x->x_next;
76 break;
77 }
78 }
79 if (rtext_entered == x) rtext_entered = 0;
80 freebytes(x->x_buf, x->x_bufsize);
81 freebytes(x, sizeof *x);
82}
83
84char *rtext_gettag(t_rtext *x)
85{
86 return (x->x_tag);
87}
88
89void rtext_gettext(t_rtext *x, char **buf, int *bufsize)
90{
91 *buf = x->x_buf;
92 *bufsize = x->x_bufsize;
93}
94
95
96/* LATER deal with tcl-significant characters */
97
98static int firstone(char *s, int c, int n)
99{
100 char *s2 = s + n;
101 int i = 0;
102 while (s != s2)
103 {
104 if (*s == c) return (i);
105 i++;
106 s++;
107 }
108 return (-1);
109}
110
111static int lastone(char *s, int c, int n)
112{
113 char *s2 = s + n;
114 while (s2 != s)
115 {
116 s2--;
117 n--;
118 if (*s2 == c) return (n);
119 }
120 return (-1);
121}
122
123 /* the following routine computes line breaks and carries out
124 some action which could be:
125 SEND_FIRST - draw the box for the first time
126 SEND_UPDATE - redraw the updated box
127 otherwise - don't draw, just calculate.
128 Called with *widthp and *heightpas coordinates of
129 a test point, the routine reports the index of the character found
130 there in *indexp. *widthp and *heightp are set to the width and height
131 of the entire text in pixels.
132 */
133
134 /* LATER get this and sys_vgui to work together properly,
135 breaking up messages as needed. As of now, there's
136 a limit of 1950 characters, imposed by sys_vgui(). */
137#define UPBUFSIZE 4000
138#define BOXWIDTH 60
139
140/* Older (pre-8.3.4) TCL versions handle text selection differently; this
141flag is set from the GUI if this happens. LATER take this out: early 2006? */
142
143extern int sys_oldtclversion;
144
145static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
146 int *indexp)
147{
148 float dispx, dispy;
149 char tempbuf[UPBUFSIZE], *tp = tempbuf, *bp = x->x_buf;
150 int outchars, inchars = x->x_bufsize, nlines = 0, ncolumns = 0,
151 pixwide, pixhigh;
152 int font = glist_getfont(x->x_glist);
153 int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
154 int findx = (*widthp + (fontwidth/2)) / fontwidth,
155 findy = *heightp / fontheight;
156 int reportedindex = 0;
157 t_canvas *canvas = glist_getcanvas(x->x_glist);
158 int widthspec = x->x_text->te_width;
159 int widthlimit = (widthspec ? widthspec : BOXWIDTH);
160 while (inchars)
161 {
162 int maxindex = (inchars > widthlimit ? widthlimit : inchars);
163 int eatchar = 1;
164 int foundit = firstone(bp, '\n', maxindex);
165 if (foundit < 0)
166 {
167 if (inchars > widthlimit)
168 {
169 foundit = lastone(bp, ' ', maxindex);
170 if (foundit < 0)
171 {
172 foundit = maxindex;
173 eatchar = 0;
174 }
175 }
176 else
177 {
178 foundit = inchars;
179 eatchar = 0;
180 }
181 }
182 if (nlines == findy)
183 {
184 int actualx = (findx < 0 ? 0 :
185 (findx > foundit ? foundit : findx));
186 *indexp = (bp - x->x_buf) + actualx;
187 reportedindex = 1;
188 }
189 strncpy(tp, bp, foundit);
190 tp += foundit;
191 bp += (foundit + eatchar);
192 inchars -= (foundit + eatchar);
193 if (inchars) *tp++ = '\n';
194 if (foundit > ncolumns) ncolumns = foundit;
195 nlines++;
196 }
197 outchars = tp - tempbuf;
198 if (outchars > 1950) outchars = 1950;
199 if (!reportedindex)
200 *indexp = outchars;
201 dispx = text_xpix(x->x_text, x->x_glist);
202 dispy = text_ypix(x->x_text, x->x_glist);
203 if (nlines < 1) nlines = 1;
204 if (!widthspec)
205 {
206 while (ncolumns < 3)
207 {
208 tempbuf[outchars++] = ' ';
209 ncolumns++;
210 }
211 }
212 else ncolumns = widthspec;
213 pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
214 pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
215
216 if (action == SEND_FIRST)
217 sys_vgui("pdtk_text_new .x%x.c %s %f %f {%.*s} %d %s\n",
218 canvas, x->x_tag,
219 dispx + LMARGIN, dispy + TMARGIN,
220 outchars, tempbuf, sys_hostfontsize(font),
221 (glist_isselected(x->x_glist,
222 &x->x_glist->gl_gobj)? "blue" : "black"));
223 else if (action == SEND_UPDATE)
224 {
225 sys_vgui("pdtk_text_set .x%x.c %s {%.*s}\n",
226 canvas, x->x_tag, outchars, tempbuf);
227 if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
228 text_drawborder(x->x_text, x->x_glist, x->x_tag,
229 pixwide, pixhigh, 0);
230 if (x->x_active)
231 {
232 if (x->x_selend > x->x_selstart)
233 {
234 sys_vgui(".x%x.c select from %s %d\n", canvas,
235 x->x_tag, x->x_selstart);
236 sys_vgui(".x%x.c select to %s %d\n", canvas,
237 x->x_tag, x->x_selend + (sys_oldtclversion ? 0 : -1));
238 sys_vgui(".x%x.c focus \"\"\n", canvas);
239 }
240 else
241 {
242 sys_vgui(".x%x.c select clear\n", canvas);
243 sys_vgui(".x%x.c icursor %s %d\n", canvas, x->x_tag,
244 x->x_selstart);
245 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
246 }
247 }
248 }
249 x->x_drawnwidth = pixwide;
250 x->x_drawnheight = pixhigh;
251
252 *widthp = pixwide;
253 *heightp = pixhigh;
254}
255
256void rtext_retext(t_rtext *x)
257{
258 int w = 0, h = 0, indx;
259 t_text *text = x->x_text;
260 t_freebytes(x->x_buf, x->x_bufsize);
261 binbuf_gettext(text->te_binbuf, &x->x_buf, &x->x_bufsize);
262 /* special case: for number boxes, try to pare the number down
263 to the specified width of the box. */
264 if (text->te_width > 0 && text->te_type == T_ATOM &&
265 x->x_bufsize > text->te_width)
266 {
267 t_atom *atomp = binbuf_getvec(text->te_binbuf);
268 int natom = binbuf_getnatom(text->te_binbuf);
269 int bufsize = x->x_bufsize;
270 if (natom == 1 && atomp->a_type == A_FLOAT)
271 {
272 /* try to reduce size by dropping decimal digits */
273 int wantreduce = bufsize - text->te_width;
274 char *decimal = 0, *nextchar, *ebuf = x->x_buf + bufsize,
275 *s1, *s2;
276 int ndecimals;
277 for (decimal = x->x_buf; decimal < ebuf; decimal++)
278 if (*decimal == '.')
279 break;
280 if (decimal >= ebuf)
281 goto giveup;
282 for (nextchar = decimal + 1; nextchar < ebuf; nextchar++)
283 if (*nextchar < '0' || *nextchar > '9')
284 break;
285 if (nextchar - decimal - 1 < wantreduce)
286 goto giveup;
287 for (s1 = nextchar - wantreduce, s2 = s1 + wantreduce;
288 s2 < ebuf; s1++, s2++)
289 *s1 = *s2;
290 t_resizebytes(x->x_buf, bufsize, text->te_width);
291 bufsize = text->te_width;
292 goto done;
293 giveup:
294 /* give up and bash it to "+" or "-" */
295 x->x_buf[0] = (atomp->a_w.w_float < 0 ? '-' : '+');
296 t_resizebytes(x->x_buf, bufsize, 1);
297 bufsize = 1;
298 }
299 else if (bufsize > text->te_width)
300 {
301 x->x_buf[text->te_width - 1] = '>';
302 t_resizebytes(x->x_buf, bufsize, text->te_width);
303 bufsize = text->te_width;
304 }
305 done:
306 x->x_bufsize = bufsize;
307 }
308 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
309}
310
311/* find the rtext that goes with a text item */
312t_rtext *glist_findrtext(t_glist *gl, t_text *who)
313{
314 t_rtext *x = gl->gl_editor->e_rtext;
315 while (x && x->x_text != who) x = x->x_next;
316 if (!x) bug("glist_findrtext");
317 return (x);
318}
319
320int rtext_width(t_rtext *x)
321{
322 int w = 0, h = 0, indx;
323 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
324 return (w);
325}
326
327int rtext_height(t_rtext *x)
328{
329 int w = 0, h = 0, indx;
330 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
331 return (h);
332}
333
334void rtext_draw(t_rtext *x)
335{
336 int w = 0, h = 0, indx;
337 rtext_senditup(x, SEND_FIRST, &w, &h, &indx);
338}
339
340void rtext_erase(t_rtext *x)
341{
342 sys_vgui(".x%x.c delete %s\n", glist_getcanvas(x->x_glist), x->x_tag);
343}
344
345void rtext_displace(t_rtext *x, int dx, int dy)
346{
347 sys_vgui(".x%x.c move %s %d %d\n", glist_getcanvas(x->x_glist),
348 x->x_tag, dx, dy);
349}
350
351void rtext_select(t_rtext *x, int state)
352{
353 t_glist *glist = x->x_glist;
354 t_canvas *canvas = glist_getcanvas(glist);
355 sys_vgui(".x%x.c itemconfigure %s -fill %s\n", canvas,
356 x->x_tag, (state? "blue" : "black"));
357 canvas_editing = canvas;
358}
359
360void rtext_activate(t_rtext *x, int state)
361{
362 int w = 0, h = 0, indx;
363 t_glist *glist = x->x_glist;
364 t_canvas *canvas = glist_getcanvas(glist);
365 if (state)
366 {
367 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
368 glist->gl_editor->e_textedfor = x;
369 glist->gl_editor->e_textdirty = 0;
370 x->x_dragfrom = x->x_selstart = 0;
371 x->x_selend = x->x_bufsize;
372 x->x_active = 1;
373 }
374 else
375 {
376 sys_vgui("selection clear .x%x.c\n", canvas);
377 sys_vgui(".x%x.c focus \"\"\n", canvas);
378 if (glist->gl_editor->e_textedfor == x)
379 glist->gl_editor->e_textedfor = 0;
380 x->x_active = 0;
381 }
382 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
383}
384
385void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
386{
387 int w = 0, h = 0, indx, i, newsize, ndel;
388 char *s1, *s2;
389 if (keynum)
390 {
391 int n = keynum;
392 if (n == '\r') n = '\n';
393 if (n == '\b') /* backspace */
394 {
395 /* LATER delete the box if all text is selected...
396 this causes reentrancy problems now. */
397 /* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize))
398 {
399 ....
400 } */
401 if (x->x_selstart && (x->x_selstart == x->x_selend))
402 x->x_selstart--;
403 }
404 else if (n == 127) /* delete */
405 {
406 if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
407 x->x_selend++;
408 }
409
410 ndel = x->x_selend - x->x_selstart;
411 for (i = x->x_selend; i < x->x_bufsize; i++)
412 x->x_buf[i- ndel] = x->x_buf[i];
413 newsize = x->x_bufsize - ndel;
414 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
415 x->x_bufsize = newsize;
416
417 if (n == '\n' || isprint(n))
418 {
419 newsize = x->x_bufsize+1;
420 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
421 for (i = x->x_bufsize; i > x->x_selstart; i--)
422 x->x_buf[i] = x->x_buf[i-1];
423 x->x_buf[x->x_selstart] = n;
424 x->x_bufsize = newsize;
425 x->x_selstart = x->x_selstart + 1;
426 }
427 x->x_selend = x->x_selstart;
428 x->x_glist->gl_editor->e_textdirty = 1;
429 }
430 else if (!strcmp(keysym->s_name, "Right"))
431 {
432 if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
433 x->x_selend = x->x_selstart = x->x_selstart + 1;
434 else
435 x->x_selstart = x->x_selend;
436 }
437 else if (!strcmp(keysym->s_name, "Left"))
438 {
439 if (x->x_selend == x->x_selstart && x->x_selstart > 0)
440 x->x_selend = x->x_selstart = x->x_selstart - 1;
441 else
442 x->x_selend = x->x_selstart;
443 }
444 /* this should be improved... life's too short */
445 else if (!strcmp(keysym->s_name, "Up"))
446 {
447 if (x->x_selstart)
448 x->x_selstart--;
449 while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
450 x->x_selstart--;
451 x->x_selend = x->x_selstart;
452 }
453 else if (!strcmp(keysym->s_name, "Down"))
454 {
455 while (x->x_selend < x->x_bufsize &&
456 x->x_buf[x->x_selend] != '\n')
457 x->x_selend++;
458 if (x->x_selend < x->x_bufsize)
459 x->x_selend++;
460 x->x_selstart = x->x_selend;
461 }
462 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
463}
464
465void rtext_mouse(t_rtext *x, int xval, int yval, int flag)
466{
467 int w = xval, h = yval, indx;
468 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
469 if (flag == RTEXT_DOWN)
470 {
471 x->x_dragfrom = x->x_selstart = x->x_selend = indx;
472 }
473 else if (flag == RTEXT_SHIFT)
474 {
475 if (indx * 2 > x->x_selstart + x->x_selend)
476 x->x_dragfrom = x->x_selstart, x->x_selend = indx;
477 else
478 x->x_dragfrom = x->x_selend, x->x_selstart = indx;
479 }
480 else if (flag == RTEXT_DRAG)
481 {
482 x->x_selstart = (x->x_dragfrom < indx ? x->x_dragfrom : indx);
483 x->x_selend = (x->x_dragfrom > indx ? x->x_dragfrom : indx);
484 }
485 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
486}
487/* Copyright (c) 1997-1999 Miller Puckette.
488* For information on usage and redistribution, and for a DISCLAIMER OF ALL
489* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
490
491/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
492/* have to insert gui-objects into editor-list */
493/* all changes are labeled with iemlib */
494
495#include <stdlib.h>
496#include <string.h>
497#include <stdio.h>
498#include <ctype.h>
499#include "m_pd.h"
500#include "s_stuff.h"
501#include "g_canvas.h"
502#include "t_tk.h"
503
504#define LMARGIN 1
505#define RMARGIN 1
506#define TMARGIN 2
507#define BMARGIN 2
508
509#define SEND_FIRST 1
510#define SEND_UPDATE 2
511#define SEND_CHECK 0
512
513struct _rtext
514{
515 char *x_buf;
516 int x_bufsize;
517 int x_selstart;
518 int x_selend;
519 int x_active;
520 int x_dragfrom;
521 int x_height;
522 int x_drawnwidth;
523 int x_drawnheight;
524 t_text *x_text;
525 t_glist *x_glist;
526 char x_tag[50];
527 struct _rtext *x_next;
528};
529
530t_rtext *rtext_new(t_glist *glist, t_text *who)
531{
532 t_rtext *x = (t_rtext *)getbytes(sizeof *x);
533 int w = 0, h = 0, indx;
534 x->x_height = -1;
535 x->x_text = who;
536 x->x_glist = glist;
537 x->x_next = glist->gl_editor->e_rtext;
538 x->x_selstart = x->x_selend = x->x_active =
539 x->x_drawnwidth = x->x_drawnheight = 0;
540 binbuf_gettext(who->te_binbuf, &x->x_buf, &x->x_bufsize);
541 glist->gl_editor->e_rtext = x;
542 sprintf(x->x_tag, ".x%x.t%x", (t_int)glist_getcanvas(x->x_glist),
543 (t_int)x);
544 return (x);
545}
546
547static t_rtext *rtext_entered;
548
549void rtext_free(t_rtext *x)
550{
551 if (x->x_glist->gl_editor->e_textedfor == x)
552 x->x_glist->gl_editor->e_textedfor = 0;
553 if (x->x_glist->gl_editor->e_rtext == x)
554 x->x_glist->gl_editor->e_rtext = x->x_next;
555 else
556 {
557 t_rtext *e2;
558 for (e2 = x->x_glist->gl_editor->e_rtext; e2; e2 = e2->x_next)
559 if (e2->x_next == x)
560 {
561 e2->x_next = x->x_next;
562 break;
563 }
564 }
565 if (rtext_entered == x) rtext_entered = 0;
566 freebytes(x->x_buf, x->x_bufsize);
567 freebytes(x, sizeof *x);
568}
569
570char *rtext_gettag(t_rtext *x)
571{
572 return (x->x_tag);
573}
574
575void rtext_gettext(t_rtext *x, char **buf, int *bufsize)
576{
577 *buf = x->x_buf;
578 *bufsize = x->x_bufsize;
579}
580
581
582/* LATER deal with tcl-significant characters */
583
584static int firstone(char *s, int c, int n)
585{
586 char *s2 = s + n;
587 int i = 0;
588 while (s != s2)
589 {
590 if (*s == c) return (i);
591 i++;
592 s++;
593 }
594 return (-1);
595}
596
597static int lastone(char *s, int c, int n)
598{
599 char *s2 = s + n;
600 while (s2 != s)
601 {
602 s2--;
603 n--;
604 if (*s2 == c) return (n);
605 }
606 return (-1);
607}
608
609 /* the following routine computes line breaks and carries out
610 some action which could be:
611 SEND_FIRST - draw the box for the first time
612 SEND_UPDATE - redraw the updated box
613 otherwise - don't draw, just calculate.
614 Called with *widthp and *heightpas coordinates of
615 a test point, the routine reports the index of the character found
616 there in *indexp. *widthp and *heightp are set to the width and height
617 of the entire text in pixels.
618 */
619
620 /* LATER get this and sys_vgui to work together properly,
621 breaking up messages as needed. As of now, there's
622 a limit of 1950 characters, imposed by sys_vgui(). */
623#define UPBUFSIZE 4000
624#define BOXWIDTH 60
625
626/* Older (pre-8.3.4) TCL versions handle text selection differently; this
627flag is set from the GUI if this happens. LATER take this out: early 2006? */
628
629extern int sys_oldtclversion;
630
631static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
632 int *indexp)
633{
634 float dispx, dispy;
635 char tempbuf[UPBUFSIZE], *tp = tempbuf, *bp = x->x_buf;
636 int outchars, inchars = x->x_bufsize, nlines = 0, ncolumns = 0,
637 pixwide, pixhigh;
638 int font = glist_getfont(x->x_glist);
639 int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
640 int findx = (*widthp + (fontwidth/2)) / fontwidth,
641 findy = *heightp / fontheight;
642 int reportedindex = 0;
643 t_canvas *canvas = glist_getcanvas(x->x_glist);
644 int widthspec = x->x_text->te_width;
645 int widthlimit = (widthspec ? widthspec : BOXWIDTH);
646 while (inchars)
647 {
648 int maxindex = (inchars > widthlimit ? widthlimit : inchars);
649 int eatchar = 1;
650 int foundit = firstone(bp, '\n', maxindex);
651 if (foundit < 0)
652 {
653 if (inchars > widthlimit)
654 {
655 foundit = lastone(bp, ' ', maxindex);
656 if (foundit < 0)
657 {
658 foundit = maxindex;
659 eatchar = 0;
660 }
661 }
662 else
663 {
664 foundit = inchars;
665 eatchar = 0;
666 }
667 }
668 if (nlines == findy)
669 {
670 int actualx = (findx < 0 ? 0 :
671 (findx > foundit ? foundit : findx));
672 *indexp = (bp - x->x_buf) + actualx;
673 reportedindex = 1;
674 }
675 strncpy(tp, bp, foundit);
676 tp += foundit;
677 bp += (foundit + eatchar);
678 inchars -= (foundit + eatchar);
679 if (inchars) *tp++ = '\n';
680 if (foundit > ncolumns) ncolumns = foundit;
681 nlines++;
682 }
683 outchars = tp - tempbuf;
684 if (outchars > 1950) outchars = 1950;
685 if (!reportedindex)
686 *indexp = outchars;
687 dispx = text_xpix(x->x_text, x->x_glist);
688 dispy = text_ypix(x->x_text, x->x_glist);
689 if (nlines < 1) nlines = 1;
690 if (!widthspec)
691 {
692 while (ncolumns < 3)
693 {
694 tempbuf[outchars++] = ' ';
695 ncolumns++;
696 }
697 }
698 else ncolumns = widthspec;
699 pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
700 pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
701
702 if (action == SEND_FIRST)
703 sys_vgui("pdtk_text_new .x%x.c %s %f %f {%.*s} %d %s\n",
704 canvas, x->x_tag,
705 dispx + LMARGIN, dispy + TMARGIN,
706 outchars, tempbuf, sys_hostfontsize(font),
707 (glist_isselected(x->x_glist,
708 &x->x_glist->gl_gobj)? "blue" : "black"));
709 else if (action == SEND_UPDATE)
710 {
711 sys_vgui("pdtk_text_set .x%x.c %s {%.*s}\n",
712 canvas, x->x_tag, outchars, tempbuf);
713 if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
714 text_drawborder(x->x_text, x->x_glist, x->x_tag,
715 pixwide, pixhigh, 0);
716 if (x->x_active)
717 {
718 if (x->x_selend > x->x_selstart)
719 {
720 sys_vgui(".x%x.c select from %s %d\n", canvas,
721 x->x_tag, x->x_selstart);
722 sys_vgui(".x%x.c select to %s %d\n", canvas,
723 x->x_tag, x->x_selend + (sys_oldtclversion ? 0 : -1));
724 sys_vgui(".x%x.c focus \"\"\n", canvas);
725 }
726 else
727 {
728 sys_vgui(".x%x.c select clear\n", canvas);
729 sys_vgui(".x%x.c icursor %s %d\n", canvas, x->x_tag,
730 x->x_selstart);
731 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
732 }
733 }
734 }
735 x->x_drawnwidth = pixwide;
736 x->x_drawnheight = pixhigh;
737
738 *widthp = pixwide;
739 *heightp = pixhigh;
740}
741
742void rtext_retext(t_rtext *x)
743{
744 int w = 0, h = 0, indx;
745 t_text *text = x->x_text;
746 t_freebytes(x->x_buf, x->x_bufsize);
747 binbuf_gettext(text->te_binbuf, &x->x_buf, &x->x_bufsize);
748 /* special case: for number boxes, try to pare the number down
749 to the specified width of the box. */
750 if (text->te_width > 0 && text->te_type == T_ATOM &&
751 x->x_bufsize > text->te_width)
752 {
753 t_atom *atomp = binbuf_getvec(text->te_binbuf);
754 int natom = binbuf_getnatom(text->te_binbuf);
755 int bufsize = x->x_bufsize;
756 if (natom == 1 && atomp->a_type == A_FLOAT)
757 {
758 /* try to reduce size by dropping decimal digits */
759 int wantreduce = bufsize - text->te_width;
760 char *decimal = 0, *nextchar, *ebuf = x->x_buf + bufsize,
761 *s1, *s2;
762 int ndecimals;
763 for (decimal = x->x_buf; decimal < ebuf; decimal++)
764 if (*decimal == '.')
765 break;
766 if (decimal >= ebuf)
767 goto giveup;
768 for (nextchar = decimal + 1; nextchar < ebuf; nextchar++)
769 if (*nextchar < '0' || *nextchar > '9')
770 break;
771 if (nextchar - decimal - 1 < wantreduce)
772 goto giveup;
773 for (s1 = nextchar - wantreduce, s2 = s1 + wantreduce;
774 s2 < ebuf; s1++, s2++)
775 *s1 = *s2;
776 t_resizebytes(x->x_buf, bufsize, text->te_width);
777 bufsize = text->te_width;
778 goto done;
779 giveup:
780 /* give up and bash it to "+" or "-" */
781 x->x_buf[0] = (atomp->a_w.w_float < 0 ? '-' : '+');
782 t_resizebytes(x->x_buf, bufsize, 1);
783 bufsize = 1;
784 }
785 else if (bufsize > text->te_width)
786 {
787 x->x_buf[text->te_width - 1] = '>';
788 t_resizebytes(x->x_buf, bufsize, text->te_width);
789 bufsize = text->te_width;
790 }
791 done:
792 x->x_bufsize = bufsize;
793 }
794 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
795}
796
797/* find the rtext that goes with a text item */
798t_rtext *glist_findrtext(t_glist *gl, t_text *who)
799{
800 t_rtext *x = gl->gl_editor->e_rtext;
801 while (x && x->x_text != who) x = x->x_next;
802 if (!x) bug("glist_findrtext");
803 return (x);
804}
805
806int rtext_width(t_rtext *x)
807{
808 int w = 0, h = 0, indx;
809 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
810 return (w);
811}
812
813int rtext_height(t_rtext *x)
814{
815 int w = 0, h = 0, indx;
816 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
817 return (h);
818}
819
820void rtext_draw(t_rtext *x)
821{
822 int w = 0, h = 0, indx;
823 rtext_senditup(x, SEND_FIRST, &w, &h, &indx);
824}
825
826void rtext_erase(t_rtext *x)
827{
828 sys_vgui(".x%x.c delete %s\n", glist_getcanvas(x->x_glist), x->x_tag);
829}
830
831void rtext_displace(t_rtext *x, int dx, int dy)
832{
833 sys_vgui(".x%x.c move %s %d %d\n", glist_getcanvas(x->x_glist),
834 x->x_tag, dx, dy);
835}
836
837void rtext_select(t_rtext *x, int state)
838{
839 t_glist *glist = x->x_glist;
840 t_canvas *canvas = glist_getcanvas(glist);
841 sys_vgui(".x%x.c itemconfigure %s -fill %s\n", canvas,
842 x->x_tag, (state? "blue" : "black"));
843 canvas_editing = canvas;
844}
845
846void rtext_activate(t_rtext *x, int state)
847{
848 int w = 0, h = 0, indx;
849 t_glist *glist = x->x_glist;
850 t_canvas *canvas = glist_getcanvas(glist);
851 if (state)
852 {
853 sys_vgui(".x%x.c focus %s\n", canvas, x->x_tag);
854 glist->gl_editor->e_textedfor = x;
855 glist->gl_editor->e_textdirty = 0;
856 x->x_dragfrom = x->x_selstart = 0;
857 x->x_selend = x->x_bufsize;
858 x->x_active = 1;
859 }
860 else
861 {
862 sys_vgui("selection clear .x%x.c\n", canvas);
863 sys_vgui(".x%x.c focus \"\"\n", canvas);
864 if (glist->gl_editor->e_textedfor == x)
865 glist->gl_editor->e_textedfor = 0;
866 x->x_active = 0;
867 }
868 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
869}
870
871void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
872{
873 int w = 0, h = 0, indx, i, newsize, ndel;
874 char *s1, *s2;
875 if (keynum)
876 {
877 int n = keynum;
878 if (n == '\r') n = '\n';
879 if (n == '\b') /* backspace */
880 {
881 /* LATER delete the box if all text is selected...
882 this causes reentrancy problems now. */
883 /* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize))
884 {
885 ....
886 } */
887 if (x->x_selstart && (x->x_selstart == x->x_selend))
888 x->x_selstart--;
889 }
890 else if (n == 127) /* delete */
891 {
892 if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
893 x->x_selend++;
894 }
895
896 ndel = x->x_selend - x->x_selstart;
897 for (i = x->x_selend; i < x->x_bufsize; i++)
898 x->x_buf[i- ndel] = x->x_buf[i];
899 newsize = x->x_bufsize - ndel;
900 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
901 x->x_bufsize = newsize;
902
903 if (n == '\n' || isprint(n))
904 {
905 newsize = x->x_bufsize+1;
906 x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
907 for (i = x->x_bufsize; i > x->x_selstart; i--)
908 x->x_buf[i] = x->x_buf[i-1];
909 x->x_buf[x->x_selstart] = n;
910 x->x_bufsize = newsize;
911 x->x_selstart = x->x_selstart + 1;
912 }
913 x->x_selend = x->x_selstart;
914 x->x_glist->gl_editor->e_textdirty = 1;
915 }
916 else if (!strcmp(keysym->s_name, "Right"))
917 {
918 if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
919 x->x_selend = x->x_selstart = x->x_selstart + 1;
920 else
921 x->x_selstart = x->x_selend;
922 }
923 else if (!strcmp(keysym->s_name, "Left"))
924 {
925 if (x->x_selend == x->x_selstart && x->x_selstart > 0)
926 x->x_selend = x->x_selstart = x->x_selstart - 1;
927 else
928 x->x_selend = x->x_selstart;
929 }
930 /* this should be improved... life's too short */
931 else if (!strcmp(keysym->s_name, "Up"))
932 {
933 if (x->x_selstart)
934 x->x_selstart--;
935 while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
936 x->x_selstart--;
937 x->x_selend = x->x_selstart;
938 }
939 else if (!strcmp(keysym->s_name, "Down"))
940 {
941 while (x->x_selend < x->x_bufsize &&
942 x->x_buf[x->x_selend] != '\n')
943 x->x_selend++;
944 if (x->x_selend < x->x_bufsize)
945 x->x_selend++;
946 x->x_selstart = x->x_selend;
947 }
948 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
949}
950
951void rtext_mouse(t_rtext *x, int xval, int yval, int flag)
952{
953 int w = xval, h = yval, indx;
954 rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
955 if (flag == RTEXT_DOWN)
956 {
957 x->x_dragfrom = x->x_selstart = x->x_selend = indx;
958 }
959 else if (flag == RTEXT_SHIFT)
960 {
961 if (indx * 2 > x->x_selstart + x->x_selend)
962 x->x_dragfrom = x->x_selstart, x->x_selend = indx;
963 else
964 x->x_dragfrom = x->x_selend, x->x_selstart = indx;
965 }
966 else if (flag == RTEXT_DRAG)
967 {
968 x->x_selstart = (x->x_dragfrom < indx ? x->x_dragfrom : indx);
969 x->x_selend = (x->x_dragfrom > indx ? x->x_dragfrom : indx);
970 }
971 rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
972}