1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <kernel.h>
3*37da2899SCharles.Forsyth #include "draw.h"
4*37da2899SCharles.Forsyth #include "tk.h"
5*37da2899SCharles.Forsyth #include "canvs.h"
6*37da2899SCharles.Forsyth
7*37da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
8*37da2899SCharles.Forsyth
9*37da2899SCharles.Forsyth /* Text Options (+ means implemented)
10*37da2899SCharles.Forsyth +anchor
11*37da2899SCharles.Forsyth +fill
12*37da2899SCharles.Forsyth +font
13*37da2899SCharles.Forsyth +justify
14*37da2899SCharles.Forsyth +stipple
15*37da2899SCharles.Forsyth +tags
16*37da2899SCharles.Forsyth +text
17*37da2899SCharles.Forsyth +width
18*37da2899SCharles.Forsyth */
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsyth /* Layout constants */
21*37da2899SCharles.Forsyth enum {
22*37da2899SCharles.Forsyth Cvsicursor = 1, /* Extra height of insertion cursor in canvas */
23*37da2899SCharles.Forsyth };
24*37da2899SCharles.Forsyth
25*37da2899SCharles.Forsyth typedef struct TkCtext TkCtext;
26*37da2899SCharles.Forsyth struct TkCtext
27*37da2899SCharles.Forsyth {
28*37da2899SCharles.Forsyth int anchor;
29*37da2899SCharles.Forsyth Point anchorp;
30*37da2899SCharles.Forsyth int justify;
31*37da2899SCharles.Forsyth int icursor;
32*37da2899SCharles.Forsyth int focus;
33*37da2899SCharles.Forsyth int pixwidth;
34*37da2899SCharles.Forsyth int pixheight;
35*37da2899SCharles.Forsyth int sell;
36*37da2899SCharles.Forsyth int self;
37*37da2899SCharles.Forsyth int selfrom;
38*37da2899SCharles.Forsyth int sbw;
39*37da2899SCharles.Forsyth int width;
40*37da2899SCharles.Forsyth int nlines;
41*37da2899SCharles.Forsyth Image* stipple;
42*37da2899SCharles.Forsyth Image* pen;
43*37da2899SCharles.Forsyth char* text;
44*37da2899SCharles.Forsyth int tlen;
45*37da2899SCharles.Forsyth TkEnv *env;
46*37da2899SCharles.Forsyth };
47*37da2899SCharles.Forsyth
48*37da2899SCharles.Forsyth static
49*37da2899SCharles.Forsyth TkOption textopts[] =
50*37da2899SCharles.Forsyth {
51*37da2899SCharles.Forsyth "anchor", OPTstab, O(TkCtext, anchor), tkanchor,
52*37da2899SCharles.Forsyth "justify", OPTstab, O(TkCtext, justify), tktabjust,
53*37da2899SCharles.Forsyth "width", OPTdist, O(TkCtext, width), IAUX(O(TkCtext, env)),
54*37da2899SCharles.Forsyth "stipple", OPTbmap, O(TkCtext, stipple), nil,
55*37da2899SCharles.Forsyth "text", OPTtext, O(TkCtext, text), nil,
56*37da2899SCharles.Forsyth nil
57*37da2899SCharles.Forsyth };
58*37da2899SCharles.Forsyth
59*37da2899SCharles.Forsyth static
60*37da2899SCharles.Forsyth TkOption itemopts[] =
61*37da2899SCharles.Forsyth {
62*37da2899SCharles.Forsyth "tags", OPTctag, O(TkCitem, tags), nil,
63*37da2899SCharles.Forsyth "font", OPTfont, O(TkCitem, env), nil,
64*37da2899SCharles.Forsyth "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill),
65*37da2899SCharles.Forsyth nil
66*37da2899SCharles.Forsyth };
67*37da2899SCharles.Forsyth
68*37da2899SCharles.Forsyth static char*
tkcvstextgetl(TkCtext * t,Font * font,char * start,int * len)69*37da2899SCharles.Forsyth tkcvstextgetl(TkCtext *t, Font *font, char *start, int *len)
70*37da2899SCharles.Forsyth {
71*37da2899SCharles.Forsyth int w, n;
72*37da2899SCharles.Forsyth char *lspc, *posn;
73*37da2899SCharles.Forsyth
74*37da2899SCharles.Forsyth w = t->width;
75*37da2899SCharles.Forsyth if(w <= 0)
76*37da2899SCharles.Forsyth w = 1000000;
77*37da2899SCharles.Forsyth
78*37da2899SCharles.Forsyth n = 0;
79*37da2899SCharles.Forsyth lspc = nil;
80*37da2899SCharles.Forsyth posn = start;
81*37da2899SCharles.Forsyth while(*posn && *posn != '\n') {
82*37da2899SCharles.Forsyth if(*posn == ' ')
83*37da2899SCharles.Forsyth lspc = posn;
84*37da2899SCharles.Forsyth n += stringnwidth(font, posn, 1);
85*37da2899SCharles.Forsyth if(n >= w && posn != start) {
86*37da2899SCharles.Forsyth if(lspc != nil)
87*37da2899SCharles.Forsyth posn = lspc;
88*37da2899SCharles.Forsyth *len = posn - start;
89*37da2899SCharles.Forsyth if(lspc != nil)
90*37da2899SCharles.Forsyth posn++;
91*37da2899SCharles.Forsyth return posn;
92*37da2899SCharles.Forsyth }
93*37da2899SCharles.Forsyth posn++;
94*37da2899SCharles.Forsyth }
95*37da2899SCharles.Forsyth *len = posn - start;
96*37da2899SCharles.Forsyth if(*posn == '\n')
97*37da2899SCharles.Forsyth posn++;
98*37da2899SCharles.Forsyth return posn;
99*37da2899SCharles.Forsyth }
100*37da2899SCharles.Forsyth
101*37da2899SCharles.Forsyth void
tkcvstextsize(TkCitem * i)102*37da2899SCharles.Forsyth tkcvstextsize(TkCitem *i)
103*37da2899SCharles.Forsyth {
104*37da2899SCharles.Forsyth Point o;
105*37da2899SCharles.Forsyth Font *font;
106*37da2899SCharles.Forsyth TkCtext *t;
107*37da2899SCharles.Forsyth Display *d;
108*37da2899SCharles.Forsyth char *next, *p;
109*37da2899SCharles.Forsyth int len, pixw, locked;
110*37da2899SCharles.Forsyth
111*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
112*37da2899SCharles.Forsyth
113*37da2899SCharles.Forsyth font = i->env->font;
114*37da2899SCharles.Forsyth d = i->env->top->display;
115*37da2899SCharles.Forsyth t->pixwidth = 0;
116*37da2899SCharles.Forsyth t->pixheight = 0;
117*37da2899SCharles.Forsyth
118*37da2899SCharles.Forsyth p = t->text;
119*37da2899SCharles.Forsyth if(p != nil) {
120*37da2899SCharles.Forsyth locked = lockdisplay(d);
121*37da2899SCharles.Forsyth while(*p) {
122*37da2899SCharles.Forsyth next = tkcvstextgetl(t, font, p, &len);
123*37da2899SCharles.Forsyth pixw = stringnwidth(font, p, len);
124*37da2899SCharles.Forsyth if(pixw > t->pixwidth)
125*37da2899SCharles.Forsyth t->pixwidth = pixw;
126*37da2899SCharles.Forsyth t->pixheight += font->height;
127*37da2899SCharles.Forsyth p = next;
128*37da2899SCharles.Forsyth }
129*37da2899SCharles.Forsyth if(locked)
130*37da2899SCharles.Forsyth unlockdisplay(d);
131*37da2899SCharles.Forsyth }
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsyth o = tkcvsanchor(i->p.drawpt[0], t->pixwidth, t->pixheight, t->anchor);
134*37da2899SCharles.Forsyth
135*37da2899SCharles.Forsyth i->p.bb.min.x = o.x;
136*37da2899SCharles.Forsyth i->p.bb.min.y = o.y - Cvsicursor;
137*37da2899SCharles.Forsyth i->p.bb.max.x = o.x + t->pixwidth;
138*37da2899SCharles.Forsyth i->p.bb.max.y = o.y + t->pixheight + Cvsicursor;
139*37da2899SCharles.Forsyth i->p.bb = insetrect(i->p.bb, -2*t->sbw);
140*37da2899SCharles.Forsyth t->anchorp = subpt(o, i->p.drawpt[0]);
141*37da2899SCharles.Forsyth }
142*37da2899SCharles.Forsyth
143*37da2899SCharles.Forsyth char*
tkcvstextcreat(Tk * tk,char * arg,char ** val)144*37da2899SCharles.Forsyth tkcvstextcreat(Tk* tk, char *arg, char **val)
145*37da2899SCharles.Forsyth {
146*37da2899SCharles.Forsyth char *e;
147*37da2899SCharles.Forsyth TkCtext *t;
148*37da2899SCharles.Forsyth TkCitem *i;
149*37da2899SCharles.Forsyth TkCanvas *c;
150*37da2899SCharles.Forsyth TkOptab tko[3];
151*37da2899SCharles.Forsyth
152*37da2899SCharles.Forsyth c = TKobj(TkCanvas, tk);
153*37da2899SCharles.Forsyth
154*37da2899SCharles.Forsyth i = tkcnewitem(tk, TkCVtext, sizeof(TkCitem)+sizeof(TkCtext));
155*37da2899SCharles.Forsyth if(i == nil)
156*37da2899SCharles.Forsyth return TkNomem;
157*37da2899SCharles.Forsyth
158*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
159*37da2899SCharles.Forsyth t->justify = Tkleft;
160*37da2899SCharles.Forsyth t->anchor = Tkcenter;
161*37da2899SCharles.Forsyth t->sell = -1;
162*37da2899SCharles.Forsyth t->self = -1;
163*37da2899SCharles.Forsyth t->icursor = -1;
164*37da2899SCharles.Forsyth t->sbw = c->sborderwidth;
165*37da2899SCharles.Forsyth t->env = tk->env;
166*37da2899SCharles.Forsyth
167*37da2899SCharles.Forsyth e = tkparsepts(tk->env->top, &i->p, &arg, 0);
168*37da2899SCharles.Forsyth if(e != nil) {
169*37da2899SCharles.Forsyth tkcvsfreeitem(i);
170*37da2899SCharles.Forsyth return e;
171*37da2899SCharles.Forsyth }
172*37da2899SCharles.Forsyth if(i->p.npoint != 1) {
173*37da2899SCharles.Forsyth tkcvsfreeitem(i);
174*37da2899SCharles.Forsyth return TkFewpt;
175*37da2899SCharles.Forsyth }
176*37da2899SCharles.Forsyth
177*37da2899SCharles.Forsyth tko[0].ptr = t;
178*37da2899SCharles.Forsyth tko[0].optab = textopts;
179*37da2899SCharles.Forsyth tko[1].ptr = i;
180*37da2899SCharles.Forsyth tko[1].optab = itemopts;
181*37da2899SCharles.Forsyth tko[2].ptr = nil;
182*37da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
183*37da2899SCharles.Forsyth if(e != nil) {
184*37da2899SCharles.Forsyth tkcvsfreeitem(i);
185*37da2899SCharles.Forsyth return e;
186*37da2899SCharles.Forsyth }
187*37da2899SCharles.Forsyth
188*37da2899SCharles.Forsyth e = tkcaddtag(tk, i, 1);
189*37da2899SCharles.Forsyth if(e != nil) {
190*37da2899SCharles.Forsyth tkcvsfreeitem(i);
191*37da2899SCharles.Forsyth return e;
192*37da2899SCharles.Forsyth }
193*37da2899SCharles.Forsyth
194*37da2899SCharles.Forsyth t->tlen = 0;
195*37da2899SCharles.Forsyth if(t->text != nil)
196*37da2899SCharles.Forsyth t->tlen = strlen(t->text);
197*37da2899SCharles.Forsyth
198*37da2899SCharles.Forsyth tkmkpen(&t->pen, i->env, t->stipple);
199*37da2899SCharles.Forsyth tkcvstextsize(i);
200*37da2899SCharles.Forsyth e = tkvalue(val, "%d", i->id);
201*37da2899SCharles.Forsyth if(e != nil) {
202*37da2899SCharles.Forsyth tkcvsfreeitem(i);
203*37da2899SCharles.Forsyth return e;
204*37da2899SCharles.Forsyth }
205*37da2899SCharles.Forsyth
206*37da2899SCharles.Forsyth tkcvsappend(c, i);
207*37da2899SCharles.Forsyth
208*37da2899SCharles.Forsyth tkbbmax(&c->update, &i->p.bb);
209*37da2899SCharles.Forsyth tkcvssetdirty(tk);
210*37da2899SCharles.Forsyth return nil;
211*37da2899SCharles.Forsyth }
212*37da2899SCharles.Forsyth
213*37da2899SCharles.Forsyth char*
tkcvstextcget(TkCitem * i,char * arg,char ** val)214*37da2899SCharles.Forsyth tkcvstextcget(TkCitem *i, char *arg, char **val)
215*37da2899SCharles.Forsyth {
216*37da2899SCharles.Forsyth TkOptab tko[3];
217*37da2899SCharles.Forsyth TkCtext *t = TKobj(TkCtext, i);
218*37da2899SCharles.Forsyth
219*37da2899SCharles.Forsyth tko[0].ptr = t;
220*37da2899SCharles.Forsyth tko[0].optab = textopts;
221*37da2899SCharles.Forsyth tko[1].ptr = i;
222*37da2899SCharles.Forsyth tko[1].optab = itemopts;
223*37da2899SCharles.Forsyth tko[2].ptr = nil;
224*37da2899SCharles.Forsyth
225*37da2899SCharles.Forsyth return tkgencget(tko, arg, val, i->env->top);
226*37da2899SCharles.Forsyth }
227*37da2899SCharles.Forsyth
228*37da2899SCharles.Forsyth char*
tkcvstextconf(Tk * tk,TkCitem * i,char * arg)229*37da2899SCharles.Forsyth tkcvstextconf(Tk *tk, TkCitem *i, char *arg)
230*37da2899SCharles.Forsyth {
231*37da2899SCharles.Forsyth char *e;
232*37da2899SCharles.Forsyth TkOptab tko[3];
233*37da2899SCharles.Forsyth TkCtext *t = TKobj(TkCtext, i);
234*37da2899SCharles.Forsyth
235*37da2899SCharles.Forsyth tko[0].ptr = t;
236*37da2899SCharles.Forsyth tko[0].optab = textopts;
237*37da2899SCharles.Forsyth tko[1].ptr = i;
238*37da2899SCharles.Forsyth tko[1].optab = itemopts;
239*37da2899SCharles.Forsyth tko[2].ptr = nil;
240*37da2899SCharles.Forsyth
241*37da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
242*37da2899SCharles.Forsyth
243*37da2899SCharles.Forsyth t->tlen = 0;
244*37da2899SCharles.Forsyth if(t->text != nil)
245*37da2899SCharles.Forsyth t->tlen = strlen(t->text);
246*37da2899SCharles.Forsyth
247*37da2899SCharles.Forsyth tkmkpen(&t->pen, i->env, t->stipple);
248*37da2899SCharles.Forsyth tkcvstextsize(i);
249*37da2899SCharles.Forsyth
250*37da2899SCharles.Forsyth return e;
251*37da2899SCharles.Forsyth }
252*37da2899SCharles.Forsyth
253*37da2899SCharles.Forsyth void
tkcvstextfree(TkCitem * i)254*37da2899SCharles.Forsyth tkcvstextfree(TkCitem *i)
255*37da2899SCharles.Forsyth {
256*37da2899SCharles.Forsyth TkCtext *t;
257*37da2899SCharles.Forsyth
258*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
259*37da2899SCharles.Forsyth if(t->stipple != nil)
260*37da2899SCharles.Forsyth freeimage(t->stipple);
261*37da2899SCharles.Forsyth if(t->pen != nil)
262*37da2899SCharles.Forsyth freeimage(t->pen);
263*37da2899SCharles.Forsyth if(t->text != nil)
264*37da2899SCharles.Forsyth free(t->text);
265*37da2899SCharles.Forsyth }
266*37da2899SCharles.Forsyth
267*37da2899SCharles.Forsyth void
tkcvstextdraw(Image * img,TkCitem * i,TkEnv * pe)268*37da2899SCharles.Forsyth tkcvstextdraw(Image *img, TkCitem *i, TkEnv *pe)
269*37da2899SCharles.Forsyth {
270*37da2899SCharles.Forsyth TkEnv *e;
271*37da2899SCharles.Forsyth TkCtext *t;
272*37da2899SCharles.Forsyth Point o, dp;
273*37da2899SCharles.Forsyth Rectangle r;
274*37da2899SCharles.Forsyth char *p, *next;
275*37da2899SCharles.Forsyth Image *pen;
276*37da2899SCharles.Forsyth int len, lw, end, start;
277*37da2899SCharles.Forsyth
278*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
279*37da2899SCharles.Forsyth
280*37da2899SCharles.Forsyth e = i->env;
281*37da2899SCharles.Forsyth pen = t->pen;
282*37da2899SCharles.Forsyth if(pen == nil) {
283*37da2899SCharles.Forsyth if (e->set & (1<<TkCfill))
284*37da2899SCharles.Forsyth pen = tkgc(e, TkCfill);
285*37da2899SCharles.Forsyth else
286*37da2899SCharles.Forsyth pen = img->display->black;
287*37da2899SCharles.Forsyth }
288*37da2899SCharles.Forsyth
289*37da2899SCharles.Forsyth
290*37da2899SCharles.Forsyth o = addpt(t->anchorp, i->p.drawpt[0]);
291*37da2899SCharles.Forsyth p = t->text;
292*37da2899SCharles.Forsyth while(p && *p) {
293*37da2899SCharles.Forsyth next = tkcvstextgetl(t, e->font, p, &len);
294*37da2899SCharles.Forsyth dp = o;
295*37da2899SCharles.Forsyth if(t->justify != Tkleft) {
296*37da2899SCharles.Forsyth lw = stringnwidth(e->font, p, len);
297*37da2899SCharles.Forsyth if(t->justify == Tkcenter)
298*37da2899SCharles.Forsyth dp.x += (t->pixwidth - lw)/2;
299*37da2899SCharles.Forsyth else
300*37da2899SCharles.Forsyth if(t->justify == Tkright)
301*37da2899SCharles.Forsyth dp.x += t->pixwidth - lw;
302*37da2899SCharles.Forsyth }
303*37da2899SCharles.Forsyth lw = p - t->text;
304*37da2899SCharles.Forsyth if(t->self != -1 && lw+len > t->self) {
305*37da2899SCharles.Forsyth if(t->sell >= t->self) {
306*37da2899SCharles.Forsyth start = t->self - lw;
307*37da2899SCharles.Forsyth end = t->sell - lw;
308*37da2899SCharles.Forsyth }
309*37da2899SCharles.Forsyth else {
310*37da2899SCharles.Forsyth start = t->sell - lw;
311*37da2899SCharles.Forsyth end = t->self - lw;
312*37da2899SCharles.Forsyth }
313*37da2899SCharles.Forsyth if(start < 0)
314*37da2899SCharles.Forsyth r.min.x = o.x;
315*37da2899SCharles.Forsyth else
316*37da2899SCharles.Forsyth r.min.x = dp.x + stringnwidth(e->font, p, start);
317*37da2899SCharles.Forsyth r.min.y = dp.y;
318*37da2899SCharles.Forsyth if(end > len)
319*37da2899SCharles.Forsyth r.max.x = o.x + t->pixwidth;
320*37da2899SCharles.Forsyth else
321*37da2899SCharles.Forsyth r.max.x = dp.x + stringnwidth(e->font, p, end);
322*37da2899SCharles.Forsyth r.max.y = dp.y + e->font->height;
323*37da2899SCharles.Forsyth tktextsdraw(img, r, pe, t->sbw);
324*37da2899SCharles.Forsyth r.max.y = dp.y;
325*37da2899SCharles.Forsyth if(start > 0)
326*37da2899SCharles.Forsyth stringn(img, dp, pen, dp, e->font, p, start);
327*37da2899SCharles.Forsyth if(end > start)
328*37da2899SCharles.Forsyth stringn(img, r.min, tkgc(pe, TkCselectfgnd), r.min, e->font, p+start, end-start);
329*37da2899SCharles.Forsyth if(len > end)
330*37da2899SCharles.Forsyth stringn(img, r.max, pen, r.max, e->font, p+end, len-end);
331*37da2899SCharles.Forsyth }
332*37da2899SCharles.Forsyth else
333*37da2899SCharles.Forsyth stringn(img, dp, pen, dp, e->font, p, len);
334*37da2899SCharles.Forsyth if(t->focus) {
335*37da2899SCharles.Forsyth lw = p - t->text;
336*37da2899SCharles.Forsyth if(t->icursor >= lw && t->icursor <= lw+len) {
337*37da2899SCharles.Forsyth lw = t->icursor - lw;
338*37da2899SCharles.Forsyth if(lw > 0)
339*37da2899SCharles.Forsyth lw = stringnwidth(e->font, p, lw);
340*37da2899SCharles.Forsyth r.min.x = dp.x + lw;
341*37da2899SCharles.Forsyth r.min.y = dp.y - 1;
342*37da2899SCharles.Forsyth r.max.x = r.min.x + 2;
343*37da2899SCharles.Forsyth r.max.y = r.min.y + e->font->height + 1;
344*37da2899SCharles.Forsyth draw(img, r, pen, nil, ZP);
345*37da2899SCharles.Forsyth }
346*37da2899SCharles.Forsyth }
347*37da2899SCharles.Forsyth o.y += e->font->height;
348*37da2899SCharles.Forsyth p = next;
349*37da2899SCharles.Forsyth }
350*37da2899SCharles.Forsyth }
351*37da2899SCharles.Forsyth
352*37da2899SCharles.Forsyth char*
tkcvstextcoord(TkCitem * i,char * arg,int x,int y)353*37da2899SCharles.Forsyth tkcvstextcoord(TkCitem *i, char *arg, int x, int y)
354*37da2899SCharles.Forsyth {
355*37da2899SCharles.Forsyth char *e;
356*37da2899SCharles.Forsyth TkCpoints p;
357*37da2899SCharles.Forsyth
358*37da2899SCharles.Forsyth if(arg == nil) {
359*37da2899SCharles.Forsyth tkxlatepts(i->p.parampt, i->p.npoint, x, y);
360*37da2899SCharles.Forsyth tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
361*37da2899SCharles.Forsyth i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
362*37da2899SCharles.Forsyth }
363*37da2899SCharles.Forsyth else {
364*37da2899SCharles.Forsyth e = tkparsepts(i->env->top, &p, &arg, 0);
365*37da2899SCharles.Forsyth if(e != nil)
366*37da2899SCharles.Forsyth return e;
367*37da2899SCharles.Forsyth if(p.npoint != 1) {
368*37da2899SCharles.Forsyth tkfreepoint(&p);
369*37da2899SCharles.Forsyth return TkFewpt;
370*37da2899SCharles.Forsyth }
371*37da2899SCharles.Forsyth tkfreepoint(&i->p);
372*37da2899SCharles.Forsyth i->p = p;
373*37da2899SCharles.Forsyth tkcvstextsize(i);
374*37da2899SCharles.Forsyth }
375*37da2899SCharles.Forsyth return nil;
376*37da2899SCharles.Forsyth }
377*37da2899SCharles.Forsyth
378*37da2899SCharles.Forsyth int
tkcvstextsrch(TkCitem * i,int x,int y)379*37da2899SCharles.Forsyth tkcvstextsrch(TkCitem *i, int x, int y)
380*37da2899SCharles.Forsyth {
381*37da2899SCharles.Forsyth TkCtext *t;
382*37da2899SCharles.Forsyth Font *font;
383*37da2899SCharles.Forsyth Display *d;
384*37da2899SCharles.Forsyth char *p, *next;
385*37da2899SCharles.Forsyth int n, len, locked;
386*37da2899SCharles.Forsyth
387*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
388*37da2899SCharles.Forsyth
389*37da2899SCharles.Forsyth n = 0;
390*37da2899SCharles.Forsyth font = i->env->font;
391*37da2899SCharles.Forsyth d = i->env->top->display;
392*37da2899SCharles.Forsyth p = t->text;
393*37da2899SCharles.Forsyth if(p == nil)
394*37da2899SCharles.Forsyth return 0;
395*37da2899SCharles.Forsyth while(*p) {
396*37da2899SCharles.Forsyth next = tkcvstextgetl(t, font, p, &len);
397*37da2899SCharles.Forsyth if(y <= font->height) {
398*37da2899SCharles.Forsyth locked = lockdisplay(d);
399*37da2899SCharles.Forsyth for(n = 0; n < len && x > stringnwidth(font, p, n+1); n++)
400*37da2899SCharles.Forsyth ;
401*37da2899SCharles.Forsyth if(locked)
402*37da2899SCharles.Forsyth unlockdisplay(d);
403*37da2899SCharles.Forsyth break;
404*37da2899SCharles.Forsyth }
405*37da2899SCharles.Forsyth y -= font->height;
406*37da2899SCharles.Forsyth p = next;
407*37da2899SCharles.Forsyth }
408*37da2899SCharles.Forsyth return p - t->text + n;
409*37da2899SCharles.Forsyth }
410*37da2899SCharles.Forsyth
411*37da2899SCharles.Forsyth static char*
tkcvsparseindex(TkCitem * i,char * buf,int * index)412*37da2899SCharles.Forsyth tkcvsparseindex(TkCitem *i, char *buf, int *index)
413*37da2899SCharles.Forsyth {
414*37da2899SCharles.Forsyth Point o;
415*37da2899SCharles.Forsyth char *p;
416*37da2899SCharles.Forsyth int x, y;
417*37da2899SCharles.Forsyth TkCtext *t;
418*37da2899SCharles.Forsyth
419*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
420*37da2899SCharles.Forsyth
421*37da2899SCharles.Forsyth if(strcmp(buf, "end") == 0) {
422*37da2899SCharles.Forsyth *index = t->tlen;
423*37da2899SCharles.Forsyth return nil;
424*37da2899SCharles.Forsyth }
425*37da2899SCharles.Forsyth if(strcmp(buf, "sel.first") == 0) {
426*37da2899SCharles.Forsyth if(t->self < 0)
427*37da2899SCharles.Forsyth return TkBadix;
428*37da2899SCharles.Forsyth *index = t->self;
429*37da2899SCharles.Forsyth return nil;
430*37da2899SCharles.Forsyth }
431*37da2899SCharles.Forsyth if(strcmp(buf, "sel.last") == 0) {
432*37da2899SCharles.Forsyth if(t->sell < 0)
433*37da2899SCharles.Forsyth return TkBadix;
434*37da2899SCharles.Forsyth *index = t->sell;
435*37da2899SCharles.Forsyth return nil;
436*37da2899SCharles.Forsyth }
437*37da2899SCharles.Forsyth if(strcmp(buf, "insert") == 0) {
438*37da2899SCharles.Forsyth *index = t->icursor;
439*37da2899SCharles.Forsyth return nil;
440*37da2899SCharles.Forsyth }
441*37da2899SCharles.Forsyth if(buf[0] == '@') {
442*37da2899SCharles.Forsyth x = atoi(buf+1);
443*37da2899SCharles.Forsyth p = strchr(buf, ',');
444*37da2899SCharles.Forsyth if(p == nil)
445*37da2899SCharles.Forsyth return TkBadix;
446*37da2899SCharles.Forsyth y = atoi(p+1);
447*37da2899SCharles.Forsyth o = i->p.drawpt[0];
448*37da2899SCharles.Forsyth *index = tkcvstextsrch(i, (x-t->anchorp.x)-o.x, (y-t->anchorp.y)-o.y);
449*37da2899SCharles.Forsyth return nil;
450*37da2899SCharles.Forsyth }
451*37da2899SCharles.Forsyth
452*37da2899SCharles.Forsyth if(buf[0] < '0' || buf[0] > '9')
453*37da2899SCharles.Forsyth return TkBadix;
454*37da2899SCharles.Forsyth x = atoi(buf);
455*37da2899SCharles.Forsyth if(x < 0)
456*37da2899SCharles.Forsyth x = 0;
457*37da2899SCharles.Forsyth if(x > t->tlen)
458*37da2899SCharles.Forsyth x = t->tlen;
459*37da2899SCharles.Forsyth *index = x;
460*37da2899SCharles.Forsyth return nil;
461*37da2899SCharles.Forsyth }
462*37da2899SCharles.Forsyth
463*37da2899SCharles.Forsyth char*
tkcvstextdchar(Tk * tk,TkCitem * i,char * arg)464*37da2899SCharles.Forsyth tkcvstextdchar(Tk *tk, TkCitem *i, char *arg)
465*37da2899SCharles.Forsyth {
466*37da2899SCharles.Forsyth TkTop *top;
467*37da2899SCharles.Forsyth TkCtext *t;
468*37da2899SCharles.Forsyth int first, last;
469*37da2899SCharles.Forsyth char *e, buf[Tkmaxitem];
470*37da2899SCharles.Forsyth
471*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
472*37da2899SCharles.Forsyth
473*37da2899SCharles.Forsyth top = tk->env->top;
474*37da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+sizeof(buf), nil);
475*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &first);
476*37da2899SCharles.Forsyth if(e != nil)
477*37da2899SCharles.Forsyth return e;
478*37da2899SCharles.Forsyth
479*37da2899SCharles.Forsyth last = first+1;
480*37da2899SCharles.Forsyth if(*arg != '\0') {
481*37da2899SCharles.Forsyth tkword(top, arg, buf, buf+sizeof(buf), nil);
482*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &last);
483*37da2899SCharles.Forsyth if(e != nil)
484*37da2899SCharles.Forsyth return e;
485*37da2899SCharles.Forsyth }
486*37da2899SCharles.Forsyth if(last <= first || t->tlen == 0)
487*37da2899SCharles.Forsyth return nil;
488*37da2899SCharles.Forsyth
489*37da2899SCharles.Forsyth tkbbmax(&TKobj(TkCanvas, tk)->update, &i->p.bb);
490*37da2899SCharles.Forsyth
491*37da2899SCharles.Forsyth memmove(t->text+first, t->text+last, t->tlen-last+1);
492*37da2899SCharles.Forsyth t->tlen -= last-first;
493*37da2899SCharles.Forsyth
494*37da2899SCharles.Forsyth tkcvstextsize(i);
495*37da2899SCharles.Forsyth tkbbmax(&TKobj(TkCanvas, tk)->update, &i->p.bb);
496*37da2899SCharles.Forsyth
497*37da2899SCharles.Forsyth tkcvssetdirty(tk);
498*37da2899SCharles.Forsyth return nil;
499*37da2899SCharles.Forsyth }
500*37da2899SCharles.Forsyth
501*37da2899SCharles.Forsyth char*
tkcvstextinsert(Tk * tk,TkCitem * i,char * arg)502*37da2899SCharles.Forsyth tkcvstextinsert(Tk *tk, TkCitem *i, char *arg)
503*37da2899SCharles.Forsyth {
504*37da2899SCharles.Forsyth TkTop *top;
505*37da2899SCharles.Forsyth TkCtext *t;
506*37da2899SCharles.Forsyth int first, n;
507*37da2899SCharles.Forsyth char *e, *text, buf[Tkmaxitem];
508*37da2899SCharles.Forsyth
509*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
510*37da2899SCharles.Forsyth
511*37da2899SCharles.Forsyth top = tk->env->top;
512*37da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+sizeof(buf), nil);
513*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &first);
514*37da2899SCharles.Forsyth if(e != nil)
515*37da2899SCharles.Forsyth return e;
516*37da2899SCharles.Forsyth
517*37da2899SCharles.Forsyth if(*arg == '\0')
518*37da2899SCharles.Forsyth return nil;
519*37da2899SCharles.Forsyth
520*37da2899SCharles.Forsyth text = malloc(Tkcvstextins);
521*37da2899SCharles.Forsyth if(text == nil)
522*37da2899SCharles.Forsyth return TkNomem;
523*37da2899SCharles.Forsyth
524*37da2899SCharles.Forsyth tkword(top, arg, text, text+Tkcvstextins, nil);
525*37da2899SCharles.Forsyth n = strlen(text);
526*37da2899SCharles.Forsyth t->text = realloc(t->text, t->tlen+n+1);
527*37da2899SCharles.Forsyth if(t->text == nil) {
528*37da2899SCharles.Forsyth free(text);
529*37da2899SCharles.Forsyth return TkNomem;
530*37da2899SCharles.Forsyth }
531*37da2899SCharles.Forsyth if(t->tlen == 0)
532*37da2899SCharles.Forsyth t->text[0] = '\0';
533*37da2899SCharles.Forsyth
534*37da2899SCharles.Forsyth tkbbmax(&TKobj(TkCanvas, tk)->update, &i->p.bb);
535*37da2899SCharles.Forsyth
536*37da2899SCharles.Forsyth memmove(t->text+first+n, t->text+first, t->tlen-first+1);
537*37da2899SCharles.Forsyth memmove(t->text+first, text, n);
538*37da2899SCharles.Forsyth t->tlen += n;
539*37da2899SCharles.Forsyth free(text);
540*37da2899SCharles.Forsyth
541*37da2899SCharles.Forsyth tkcvstextsize(i);
542*37da2899SCharles.Forsyth tkbbmax(&TKobj(TkCanvas, tk)->update, &i->p.bb);
543*37da2899SCharles.Forsyth
544*37da2899SCharles.Forsyth tkcvssetdirty(tk);
545*37da2899SCharles.Forsyth return nil;
546*37da2899SCharles.Forsyth }
547*37da2899SCharles.Forsyth
548*37da2899SCharles.Forsyth char*
tkcvstextindex(Tk * tk,TkCitem * i,char * arg,char ** val)549*37da2899SCharles.Forsyth tkcvstextindex(Tk *tk, TkCitem *i, char *arg, char **val)
550*37da2899SCharles.Forsyth {
551*37da2899SCharles.Forsyth int first;
552*37da2899SCharles.Forsyth char *e, buf[Tkmaxitem];
553*37da2899SCharles.Forsyth
554*37da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
555*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &first);
556*37da2899SCharles.Forsyth if(e != nil)
557*37da2899SCharles.Forsyth return e;
558*37da2899SCharles.Forsyth
559*37da2899SCharles.Forsyth return tkvalue(val, "%d", first);
560*37da2899SCharles.Forsyth }
561*37da2899SCharles.Forsyth
562*37da2899SCharles.Forsyth char*
tkcvstexticursor(Tk * tk,TkCitem * i,char * arg)563*37da2899SCharles.Forsyth tkcvstexticursor(Tk *tk, TkCitem *i, char *arg)
564*37da2899SCharles.Forsyth {
565*37da2899SCharles.Forsyth int first;
566*37da2899SCharles.Forsyth TkCanvas *c;
567*37da2899SCharles.Forsyth char *e, buf[Tkmaxitem];
568*37da2899SCharles.Forsyth
569*37da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
570*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &first);
571*37da2899SCharles.Forsyth if(e != nil)
572*37da2899SCharles.Forsyth return e;
573*37da2899SCharles.Forsyth
574*37da2899SCharles.Forsyth TKobj(TkCtext, i)->icursor = first;
575*37da2899SCharles.Forsyth
576*37da2899SCharles.Forsyth c = TKobj(TkCanvas, tk);
577*37da2899SCharles.Forsyth if(c->focus == i) {
578*37da2899SCharles.Forsyth tkbbmax(&c->update, &i->p.bb);
579*37da2899SCharles.Forsyth tkcvssetdirty(tk);
580*37da2899SCharles.Forsyth }
581*37da2899SCharles.Forsyth return nil;
582*37da2899SCharles.Forsyth }
583*37da2899SCharles.Forsyth
584*37da2899SCharles.Forsyth void
tkcvstextfocus(Tk * tk,TkCitem * i,int x)585*37da2899SCharles.Forsyth tkcvstextfocus(Tk *tk, TkCitem *i, int x)
586*37da2899SCharles.Forsyth {
587*37da2899SCharles.Forsyth TkCtext *t;
588*37da2899SCharles.Forsyth TkCanvas *c;
589*37da2899SCharles.Forsyth
590*37da2899SCharles.Forsyth if(i == nil)
591*37da2899SCharles.Forsyth return;
592*37da2899SCharles.Forsyth
593*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
594*37da2899SCharles.Forsyth c = TKobj(TkCanvas, tk);
595*37da2899SCharles.Forsyth
596*37da2899SCharles.Forsyth if(t->focus != x) {
597*37da2899SCharles.Forsyth t->focus = x;
598*37da2899SCharles.Forsyth tkbbmax(&c->update, &i->p.bb);
599*37da2899SCharles.Forsyth tkcvssetdirty(tk);
600*37da2899SCharles.Forsyth }
601*37da2899SCharles.Forsyth }
602*37da2899SCharles.Forsyth
603*37da2899SCharles.Forsyth void
tkcvstextclr(Tk * tk)604*37da2899SCharles.Forsyth tkcvstextclr(Tk *tk)
605*37da2899SCharles.Forsyth {
606*37da2899SCharles.Forsyth TkCtext *t;
607*37da2899SCharles.Forsyth TkCanvas *c;
608*37da2899SCharles.Forsyth TkCitem *item;
609*37da2899SCharles.Forsyth
610*37da2899SCharles.Forsyth c = TKobj(TkCanvas, tk);
611*37da2899SCharles.Forsyth item = c->selection;
612*37da2899SCharles.Forsyth if(item == nil)
613*37da2899SCharles.Forsyth return;
614*37da2899SCharles.Forsyth
615*37da2899SCharles.Forsyth c->selection = nil;
616*37da2899SCharles.Forsyth t = TKobj(TkCtext, item);
617*37da2899SCharles.Forsyth t->sell = -1;
618*37da2899SCharles.Forsyth t->self = -1;
619*37da2899SCharles.Forsyth tkbbmax(&c->update, &item->p.bb);
620*37da2899SCharles.Forsyth tkcvssetdirty(tk);
621*37da2899SCharles.Forsyth }
622*37da2899SCharles.Forsyth
623*37da2899SCharles.Forsyth char*
tkcvstextselect(Tk * tk,TkCitem * i,char * arg,int op)624*37da2899SCharles.Forsyth tkcvstextselect(Tk *tk, TkCitem *i, char *arg, int op)
625*37da2899SCharles.Forsyth {
626*37da2899SCharles.Forsyth int indx;
627*37da2899SCharles.Forsyth TkCtext *t;
628*37da2899SCharles.Forsyth TkCanvas *c;
629*37da2899SCharles.Forsyth char *e, buf[Tkmaxitem];
630*37da2899SCharles.Forsyth
631*37da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
632*37da2899SCharles.Forsyth e = tkcvsparseindex(i, buf, &indx);
633*37da2899SCharles.Forsyth if(e != nil)
634*37da2899SCharles.Forsyth return e;
635*37da2899SCharles.Forsyth
636*37da2899SCharles.Forsyth c = TKobj(TkCanvas, tk);
637*37da2899SCharles.Forsyth t = TKobj(TkCtext, i);
638*37da2899SCharles.Forsyth switch(op) {
639*37da2899SCharles.Forsyth case TkCselfrom:
640*37da2899SCharles.Forsyth t->selfrom = indx;
641*37da2899SCharles.Forsyth return nil;
642*37da2899SCharles.Forsyth case TkCseladjust:
643*37da2899SCharles.Forsyth if(c->selection == i) {
644*37da2899SCharles.Forsyth if(abs(t->self-indx) < abs(t->sell-indx)) {
645*37da2899SCharles.Forsyth t->self = indx;
646*37da2899SCharles.Forsyth t->selfrom = t->sell;
647*37da2899SCharles.Forsyth }
648*37da2899SCharles.Forsyth else {
649*37da2899SCharles.Forsyth t->sell = indx;
650*37da2899SCharles.Forsyth t->selfrom = t->self;
651*37da2899SCharles.Forsyth }
652*37da2899SCharles.Forsyth }
653*37da2899SCharles.Forsyth /* No break */
654*37da2899SCharles.Forsyth case TkCselto:
655*37da2899SCharles.Forsyth if(c->selection != i)
656*37da2899SCharles.Forsyth tkcvstextclr(tk);
657*37da2899SCharles.Forsyth c->selection = i;
658*37da2899SCharles.Forsyth t->self = t->selfrom;
659*37da2899SCharles.Forsyth t->sell = indx;
660*37da2899SCharles.Forsyth break;
661*37da2899SCharles.Forsyth }
662*37da2899SCharles.Forsyth t->sbw = c->sborderwidth;
663*37da2899SCharles.Forsyth tkbbmax(&TKobj(TkCanvas, tk)->update, &i->p.bb);
664*37da2899SCharles.Forsyth tkcvssetdirty(tk);
665*37da2899SCharles.Forsyth return nil;
666*37da2899SCharles.Forsyth }
667