Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <thread.h>
5
#include <mouse.h>
6
#include <keyboard.h>
7
#include <frame.h>
8
#include "flayer.h"
9
#include "samterm.h"
10
 
11
void
12
rinit(Rasp *r)
13
{
14
	r->nrunes=0;
15
	r->sect=0;
16
}
17
 
18
void
19
rclear(Rasp *r)
20
{
21
	Section *s, *ns;
22
 
23
	for(s=r->sect; s; s=ns){
24
		ns = s->next;
25
		free(s->text);
26
		free(s);
27
	}
28
	r->sect = 0;
29
}
30
 
31
Section*
32
rsinsert(Rasp *r, Section *s)	/* insert before s */
33
{
34
	Section *t;
35
	Section *u;
36
 
37
	t = alloc(sizeof(Section));
38
	if(r->sect == s){	/* includes empty list case: r->sect==s==0 */
39
		r->sect = t;
40
		t->next = s;
41
	}else{
42
		u = r->sect;
43
		if(u == 0)
44
			panic("rsinsert 1");
45
		do{
46
			if(u->next == s){
47
				t->next = s;
48
				u->next = t;
49
				goto Return;
50
			}
51
			u=u->next;
52
		}while(u);
53
		panic("rsinsert 2");
54
	}
55
    Return:
56
	return t;
57
}
58
 
59
void
60
rsdelete(Rasp *r, Section *s)
61
{
62
	Section *t;
63
 
64
	if(s == 0)
65
		panic("rsdelete");
66
	if(r->sect == s){
67
		r->sect = s->next;
68
		goto Free;
69
	}
70
	for(t=r->sect; t; t=t->next)
71
		if(t->next == s){
72
			t->next = s->next;
73
	Free:
74
			if(s->text)
75
				free(s->text);
76
			free(s);
77
			return;
78
		}
79
	panic("rsdelete 2");
80
}
81
 
82
void
83
splitsect(Rasp *r, Section *s, long n0)
84
{
85
	if(s == 0)
86
		panic("splitsect");
87
	rsinsert(r, s->next);
88
	if(s->text == 0)
89
		s->next->text = 0;
90
	else{
91
		s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
92
		Strcpy(s->next->text, s->text+n0);
93
		s->text[n0] = 0;
94
	}
95
	s->next->nrunes = s->nrunes-n0;
96
	s->nrunes = n0;
97
}
98
 
99
Section *
100
findsect(Rasp *r, Section *s, long p, long q)	/* find sect containing q and put q on a sect boundary */
101
{
102
	if(s==0 && p!=q)
103
		panic("findsect");
104
	for(; s && p+s->nrunes<=q; s=s->next)
105
		p += s->nrunes;
106
	if(p != q){
107
		splitsect(r, s, q-p);
108
		s = s->next;
109
	}
110
	return s;
111
}
112
 
113
void
114
rresize(Rasp *r, long a, long old, long new)
115
{
116
	Section *s, *t, *ns;
117
 
118
	s = findsect(r, r->sect, 0L, a);
119
	t = findsect(r, s, a, a+old);
120
	for(; s!=t; s=ns){
121
		ns=s->next;
122
		rsdelete(r, s);
123
	}
124
	/* now insert the new piece before t */
125
	if(new > 0){
126
		ns=rsinsert(r, t);
127
		ns->nrunes=new;
128
		ns->text=0;
129
	}
130
	r->nrunes += new-old;
131
}
132
 
133
void
134
rdata(Rasp *r, long p0, long p1, Rune *cp)
135
{
136
	Section *s, *t, *ns;
137
 
138
	s = findsect(r, r->sect, 0L, p0);
139
	t = findsect(r, s, p0, p1);
140
	for(; s!=t; s=ns){
141
		ns=s->next;
142
		if(s->text)
143
			panic("rdata");
144
		rsdelete(r, s);
145
	}
146
	p1 -= p0;
147
	s = rsinsert(r, t);
148
	s->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
149
	memmove(s->text, cp, RUNESIZE*p1);
150
	s->text[p1] = 0;
151
	s->nrunes = p1;
152
}
153
 
154
void
155
rclean(Rasp *r)
156
{
157
	Section *s;
158
 
159
	for(s=r->sect; s; s=s->next)
160
		while(s->next && (s->text!=0)==(s->next->text!=0)){
161
			if(s->text){
162
				if(s->nrunes+s->next->nrunes>TBLOCKSIZE)
163
					break;
164
				Strcpy(s->text+s->nrunes, s->next->text);
165
			}
166
			s->nrunes += s->next->nrunes;
167
			rsdelete(r, s->next);
168
		}
169
}
170
 
171
void
172
Strcpy(Rune *to, Rune *from)
173
{
174
	do; while(*to++ = *from++);
175
}
176
 
177
Rune*
178
rload(Rasp *r, ulong p0, ulong p1, ulong *nrp)
179
{
180
	Section *s;
181
	long p;
182
	int n, nb;
183
 
184
	nb = 0;
185
	Strgrow(&scratch, &nscralloc, p1-p0+1);
186
	scratch[0] = 0;
187
	for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
188
		p += s->nrunes;
189
	while(p<p1 && s){
190
		/*
191
		 * Subtle and important.  If we are preparing to handle an 'rdata'
192
		 * call, it's because we have an 'rresize' hole here, so the
193
		 * screen doesn't have data for that space anyway (it got cut
194
		 * first).  So pretend it isn't there.
195
		 */
196
		if(s->text){
197
			n = s->nrunes-(p0-p);
198
			if(n>p1-p0)	/* all in this section */
199
				n = p1-p0;
200
			memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE);
201
			nb += n;
202
			scratch[nb] = 0;
203
		}
204
		p += s->nrunes;
205
		p0 = p;
206
		s = s->next;
207
	}
208
	if(nrp)
209
		*nrp = nb;
210
	return scratch;
211
}
212
 
213
int
214
rmissing(Rasp *r, ulong p0, ulong p1)
215
{
216
	Section *s;
217
	long p;
218
	int n, nm=0;
219
 
220
	for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
221
		p += s->nrunes;
222
	while(p<p1 && s){
223
		if(s->text == 0){
224
			n = s->nrunes-(p0-p);
225
			if(n > p1-p0)	/* all in this section */
226
				n = p1-p0;
227
			nm += n;
228
		}
229
		p += s->nrunes;
230
		p0 = p;
231
		s = s->next;
232
	}
233
	return nm;
234
}
235
 
236
int
237
rcontig(Rasp *r, ulong p0, ulong p1, int text)
238
{
239
	Section *s;
240
	long p, n;
241
	int np=0;
242
 
243
	for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
244
		p += s->nrunes;
245
	while(p<p1 && s && (text? (s->text!=0) : (s->text==0))){
246
		n = s->nrunes-(p0-p);
247
		if(n > p1-p0)	/* all in this section */
248
			n = p1-p0;
249
		np += n;
250
		p += s->nrunes;
251
		p0 = p;
252
		s = s->next;
253
	}
254
	return np;
255
}
256
 
257
void
258
Strgrow(Rune **s, long *n, int want)	/* can always toss the old data when called */
259
{
260
	if(*n >= want)
261
		return;
262
	free(*s);
263
	*s = alloc(RUNESIZE*want);
264
	*n = want;
265
}