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