frbox.c - sam - An updated version of the sam text editor.
(HTM) git clone git://vernunftzentrum.de/sam.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
frbox.c (3196B)
---
1 /* Copyright (c) 1998 Lucent Technologies - All rights reserved. */
2 #include <u.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].a.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 uint8_t *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].a.ptr);
81 f->box[bn+1].a.ptr = p;
82 }
83 }
84
85 static
86 uint8_t*
87 runeindex(uint8_t *p, int n)
88 {
89 int i, w;
90 wchar_t rune;
91
92 for(i=0; i<n; i++,p+=w)
93 w = chartorune(&rune, (char*)p);
94 return p;
95 }
96
97 static
98 void
99 truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */
100 {
101 if(b->nrune<0 || b->nrune<n)
102 berror("truncatebox");
103 b->nrune -= n;
104 runeindex(b->a.ptr, b->nrune)[0] = 0;
105 b->wid = strwidth(f->font, (char *)b->a.ptr);
106 }
107
108 static
109 void
110 chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */
111 {
112 if(b->nrune<0 || b->nrune<n)
113 berror("chopbox");
114
115 uint8_t *ri = runeindex(b->a.ptr, n);
116 memmove(b->a.ptr, ri, strlen((char *)ri) + 1);
117 b->nrune -= n;
118 b->wid = strwidth(f->font, (char *)b->a.ptr);
119 }
120
121 void
122 _frsplitbox(Frame *f, int bn, int n)
123 {
124 dupbox(f, bn);
125 truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
126 chopbox(f, &f->box[bn+1], n);
127 }
128
129 void
130 _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */
131 {
132 Frbox *b;
133
134 b = &f->box[bn];
135 _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
136 strcpy((char*)runeindex(b[0].a.ptr, b[0].nrune), (char*)b[1].a.ptr);
137 b[0].wid += b[1].wid;
138 b[0].nrune += b[1].nrune;
139 _frdelbox(f, bn+1, bn+1);
140 }
141
142 int
143 _frfindbox(Frame *f, int bn, uint64_t p, uint64_t q) /* find box containing q and put q on a box boundary */
144 {
145 Frbox *b;
146
147 for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
148 p += NRUNE(b);
149 if(p != q)
150 _frsplitbox(f, bn++, (int)(q-p));
151 return bn;
152 }