Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <mouse.h>
5 #include <frame.h>
7 #define SLOP 25
9 void
10 _fraddbox(Frame *f, int bn, int n) /* add n boxes after bn, shift the rest up,
11 * box[bn+n]==box[bn] */
12 {
13 int i;
15 if(bn > f->nbox)
16 drawerror(f->display, "_fraddbox");
17 if(f->nbox+n > f->nalloc)
18 _frgrowbox(f, n+SLOP);
19 for(i=f->nbox; --i>=bn; )
20 f->box[i+n] = f->box[i];
21 f->nbox+=n;
22 }
24 void
25 _frclosebox(Frame *f, int n0, int n1) /* inclusive */
26 {
27 int i;
29 if(n0>=f->nbox || n1>=f->nbox || n1<n0)
30 drawerror(f->display, "_frclosebox");
31 n1++;
32 for(i=n1; i<f->nbox; i++)
33 f->box[i-(n1-n0)] = f->box[i];
34 f->nbox -= n1-n0;
35 }
37 void
38 _frdelbox(Frame *f, int n0, int n1) /* inclusive */
39 {
40 if(n0>=f->nbox || n1>=f->nbox || n1<n0)
41 drawerror(f->display, "_frdelbox");
42 _frfreebox(f, n0, n1);
43 _frclosebox(f, n0, n1);
44 }
46 void
47 _frfreebox(Frame *f, int n0, int n1) /* inclusive */
48 {
49 int i;
51 if(n1<n0)
52 return;
53 if(n0>=f->nbox || n1>=f->nbox)
54 drawerror(f->display, "_frfreebox");
55 n1++;
56 for(i=n0; i<n1; i++)
57 if(f->box[i].nrune >= 0)
58 free(f->box[i].ptr);
59 }
61 void
62 _frgrowbox(Frame *f, int delta)
63 {
64 f->nalloc += delta;
65 f->box = realloc(f->box, f->nalloc*sizeof(Frbox));
66 if(f->box == 0)
67 drawerror(f->display, "_frgrowbox");
68 }
70 static
71 void
72 dupbox(Frame *f, int bn)
73 {
74 uchar *p;
76 if(f->box[bn].nrune < 0)
77 drawerror(f->display, "dupbox");
78 _fraddbox(f, bn, 1);
79 if(f->box[bn].nrune >= 0){
80 p = _frallocstr(f, NBYTE(&f->box[bn])+1);
81 strcpy((char*)p, (char*)f->box[bn].ptr);
82 f->box[bn+1].ptr = p;
83 }
84 }
86 static
87 uchar*
88 runeindex(uchar *p, int n)
89 {
90 int i, w;
91 Rune rune;
93 for(i=0; i<n; i++,p+=w)
94 if(*p < Runeself)
95 w = 1;
96 else{
97 w = chartorune(&rune, (char*)p);
98 USED(rune);
99 }
100 return p;
103 static
104 void
105 truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */
107 if(b->nrune<0 || b->nrune<n)
108 drawerror(f->display, "truncatebox");
109 b->nrune -= n;
110 runeindex(b->ptr, b->nrune)[0] = 0;
111 b->wid = stringwidth(f->font, (char *)b->ptr);
114 static
115 void
116 chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */
118 char *p;
120 if(b->nrune<0 || b->nrune<n)
121 drawerror(f->display, "chopbox");
122 p = (char*)runeindex(b->ptr, n);
123 memmove((char*)b->ptr, p, strlen(p)+1);
124 b->nrune -= n;
125 b->wid = stringwidth(f->font, (char *)b->ptr);
128 void
129 _frsplitbox(Frame *f, int bn, int n)
131 dupbox(f, bn);
132 truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
133 chopbox(f, &f->box[bn+1], n);
136 void
137 _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */
139 Frbox *b;
141 b = &f->box[bn];
142 _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
143 strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr);
144 b[0].wid += b[1].wid;
145 b[0].nrune += b[1].nrune;
146 _frdelbox(f, bn+1, bn+1);
149 int
150 _frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q and put q on a box boundary */
152 Frbox *b;
154 for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
155 p += NRUNE(b);
156 if(p != q)
157 _frsplitbox(f, bn++, (int)(q-p));
158 return bn;