~ubuntu-branches/ubuntu/saucy/9base/saucy

« back to all changes in this revision

Viewing changes to sam/rasp.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2010-06-04 17:22:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20100604172203-ei85j0da495sr8ut
Tags: 1:6-1
* Adding Kai as co-maintainer.
* Merging upstream version 6.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "sam.h"
 
2
/*
 
3
 * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's,
 
4
 * so they will be scrolled into visibility in the ~~sam~~ window (yuck!).
 
5
 */
 
6
#define GROWDATASIZE    50      /* if size is <= this, send data with grow */
 
7
 
 
8
void    rcut(List*, Posn, Posn);
 
9
int     rterm(List*, Posn);
 
10
void    rgrow(List*, Posn, Posn);
 
11
 
 
12
static  Posn    growpos;
 
13
static  Posn    grown;
 
14
static  Posn    shrinkpos;
 
15
static  Posn    shrunk;
 
16
 
 
17
/*
 
18
 * rasp routines inform the terminal of changes to the file.
 
19
 *
 
20
 * a rasp is a list of spans within the file, and an indication
 
21
 * of whether the terminal knows about the span.
 
22
 *
 
23
 * optimize by coalescing multiple updates to the same span
 
24
 * if it is not known by the terminal.
 
25
 *
 
26
 * other possible optimizations: flush terminal's rasp by cut everything,
 
27
 * insert everything if rasp gets too large.
 
28
 */
 
29
 
 
30
/*
 
31
 * only called for initial load of file
 
32
 */
 
33
void
 
34
raspload(File *f)
 
35
{
 
36
        if(f->rasp == nil)
 
37
                return;
 
38
        grown = f->b.nc;
 
39
        growpos = 0;
 
40
        if(f->b.nc)
 
41
                rgrow(f->rasp, 0, f->b.nc);
 
42
        raspdone(f, 1);
 
43
}
 
44
 
 
45
void
 
46
raspstart(File *f)
 
47
{
 
48
        if(f->rasp == nil)
 
49
                return;
 
50
        grown = 0;
 
51
        shrunk = 0;
 
52
        outbuffered = 1;
 
53
}
 
54
 
 
55
void
 
56
raspdone(File *f, int toterm)
 
57
{
 
58
        if(f->dot.r.p1 > f->b.nc)
 
59
                f->dot.r.p1 = f->b.nc;
 
60
        if(f->dot.r.p2 > f->b.nc)
 
61
                f->dot.r.p2 = f->b.nc;
 
62
        if(f->mark.p1 > f->b.nc)
 
63
                f->mark.p1 = f->b.nc;
 
64
        if(f->mark.p2 > f->b.nc)
 
65
                f->mark.p2 = f->b.nc;
 
66
        if(f->rasp == nil)
 
67
                return;
 
68
        if(grown)
 
69
                outTsll(Hgrow, f->tag, growpos, grown);
 
70
        else if(shrunk)
 
71
                outTsll(Hcut, f->tag, shrinkpos, shrunk);
 
72
        if(toterm)
 
73
                outTs(Hcheck0, f->tag);
 
74
        outflush();
 
75
        outbuffered = 0;
 
76
        if(f == cmd){
 
77
                cmdpt += cmdptadv;
 
78
                cmdptadv = 0;
 
79
        }
 
80
}
 
81
 
 
82
void
 
83
raspflush(File *f)
 
84
{
 
85
        if(grown){
 
86
                outTsll(Hgrow, f->tag, growpos, grown);
 
87
                grown = 0;
 
88
        }
 
89
        else if(shrunk){
 
90
                outTsll(Hcut, f->tag, shrinkpos, shrunk);
 
91
                shrunk = 0;
 
92
        }
 
93
        outflush();
 
94
}
 
95
 
 
96
void
 
97
raspdelete(File *f, uint p1, uint p2, int toterm)
 
98
{
 
99
        long n;
 
100
 
 
101
        n = p2 - p1;
 
102
        if(n == 0)
 
103
                return;
 
104
 
 
105
        if(p2 <= f->dot.r.p1){
 
106
                f->dot.r.p1 -= n;
 
107
                f->dot.r.p2 -= n;
 
108
        }
 
109
        if(p2 <= f->mark.p1){
 
110
                f->mark.p1 -= n;
 
111
                f->mark.p2 -= n;
 
112
        }
 
113
 
 
114
        if(f->rasp == nil)
 
115
                return;
 
116
 
 
117
        if(f==cmd && p1<cmdpt){
 
118
                if(p2 <= cmdpt)
 
119
                        cmdpt -= n;
 
120
                else
 
121
                        cmdpt = p1;
 
122
        }
 
123
        if(toterm){
 
124
                if(grown){
 
125
                        outTsll(Hgrow, f->tag, growpos, grown);
 
126
                        grown = 0;
 
127
                }else if(shrunk && shrinkpos!=p1 && shrinkpos!=p2){
 
128
                        outTsll(Hcut, f->tag, shrinkpos, shrunk);
 
129
                        shrunk = 0;
 
130
                }
 
131
                if(!shrunk || shrinkpos==p2)
 
132
                        shrinkpos = p1;
 
133
                shrunk += n;
 
134
        }
 
135
        rcut(f->rasp, p1, p2);
 
136
}
 
137
 
 
138
void
 
139
raspinsert(File *f, uint p1, Rune *buf, uint n, int toterm)
 
140
{
 
141
        Range r;
 
142
 
 
143
        if(n == 0)
 
144
                return;
 
145
 
 
146
        if(p1 < f->dot.r.p1){
 
147
                f->dot.r.p1 += n;
 
148
                f->dot.r.p2 += n;
 
149
        }
 
150
        if(p1 < f->mark.p1){
 
151
                f->mark.p1 += n;
 
152
                f->mark.p2 += n;
 
153
        }
 
154
 
 
155
 
 
156
        if(f->rasp == nil)
 
157
                return;
 
158
        if(f==cmd && p1<cmdpt)
 
159
                cmdpt += n;
 
160
        if(toterm){
 
161
                if(shrunk){
 
162
                        outTsll(Hcut, f->tag, shrinkpos, shrunk);
 
163
                        shrunk = 0;
 
164
                }
 
165
                if(n>GROWDATASIZE || !rterm(f->rasp, p1)){
 
166
                        rgrow(f->rasp, p1, n);
 
167
                        if(grown && growpos+grown!=p1 && growpos!=p1){
 
168
                                outTsll(Hgrow, f->tag, growpos, grown);
 
169
                                grown = 0;
 
170
                        }
 
171
                        if(!grown)
 
172
                                growpos = p1;
 
173
                        grown += n;
 
174
                }else{
 
175
                        if(grown){
 
176
                                outTsll(Hgrow, f->tag, growpos, grown);
 
177
                                grown = 0;
 
178
                        }
 
179
                        rgrow(f->rasp, p1, n);
 
180
                        r = rdata(f->rasp, p1, n);
 
181
                        if(r.p1!=p1 || r.p2!=p1+n)
 
182
                                panic("rdata in toterminal");
 
183
                        outTsllS(Hgrowdata, f->tag, p1, n, tmprstr(buf, n));
 
184
                }
 
185
        }else{
 
186
                rgrow(f->rasp, p1, n);
 
187
                r = rdata(f->rasp, p1, n);
 
188
                if(r.p1!=p1 || r.p2!=p1+n)
 
189
                        panic("rdata in toterminal");
 
190
        }
 
191
}
 
192
 
 
193
#define M       0x80000000L
 
194
#define P(i)    r->posnptr[i]
 
195
#define T(i)    (P(i)&M)        /* in terminal */
 
196
#define L(i)    (P(i)&~M)       /* length of this piece */
 
197
 
 
198
void
 
199
rcut(List *r, Posn p1, Posn p2)
 
200
{
 
201
        Posn p, x;
 
202
        int i;
 
203
 
 
204
        if(p1 == p2)
 
205
                panic("rcut 0");
 
206
        for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
 
207
                ;
 
208
        if(i == r->nused)
 
209
                panic("rcut 1");
 
210
        if(p < p1){     /* chop this piece */
 
211
                if(p+L(i) < p2){
 
212
                        x = p1-p;
 
213
                        p += L(i);
 
214
                }else{
 
215
                        x = L(i)-(p2-p1);
 
216
                        p = p2;
 
217
                }
 
218
                if(T(i))
 
219
                        P(i) = x|M;
 
220
                else
 
221
                        P(i) = x;
 
222
                i++;
 
223
        }
 
224
        while(i<r->nused && p+L(i)<=p2){
 
225
                p += L(i);
 
226
                dellist(r, i);
 
227
        }
 
228
        if(p < p2){
 
229
                if(i == r->nused)
 
230
                        panic("rcut 2");
 
231
                x = L(i)-(p2-p);
 
232
                if(T(i))
 
233
                        P(i) = x|M;
 
234
                else
 
235
                        P(i) = x;
 
236
        }
 
237
        /* can we merge i and i-1 ? */
 
238
        if(i>0 && i<r->nused && T(i-1)==T(i)){
 
239
                x = L(i-1)+L(i);
 
240
                dellist(r, i--);
 
241
                if(T(i))
 
242
                        P(i)=x|M;
 
243
                else
 
244
                        P(i)=x;
 
245
        }
 
246
}
 
247
 
 
248
void
 
249
rgrow(List *r, Posn p1, Posn n)
 
250
{
 
251
        Posn p;
 
252
        int i;
 
253
 
 
254
        if(n == 0)
 
255
                panic("rgrow 0");
 
256
        for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
 
257
                ;
 
258
        if(i == r->nused){      /* stick on end of file */
 
259
                if(p!=p1)
 
260
                        panic("rgrow 1");
 
261
                if(i>0 && !T(i-1))
 
262
                        P(i-1)+=n;
 
263
                else
 
264
                        inslist(r, i, n);
 
265
        }else if(!T(i))         /* goes in this empty piece */
 
266
                P(i)+=n;
 
267
        else if(p==p1 && i>0 && !T(i-1))        /* special case; simplifies life */
 
268
                P(i-1)+=n;
 
269
        else if(p==p1)
 
270
                inslist(r, i, n);
 
271
        else{                   /* must break piece in terminal */
 
272
                inslist(r, i+1, (L(i)-(p1-p))|M);
 
273
                inslist(r, i+1, n);
 
274
                P(i) = (p1-p)|M;
 
275
        }
 
276
}
 
277
 
 
278
int
 
279
rterm(List *r, Posn p1)
 
280
{
 
281
        Posn p;
 
282
        int i;
 
283
 
 
284
        for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
 
285
                ;
 
286
        if(i==r->nused && (i==0 || !T(i-1)))
 
287
                return 0;
 
288
        return T(i);
 
289
}
 
290
 
 
291
Range
 
292
rdata(List *r, Posn p1, Posn n)
 
293
{
 
294
        Posn p;
 
295
        int i;
 
296
        Range rg;
 
297
 
 
298
        if(n==0)
 
299
                panic("rdata 0");
 
300
        for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
 
301
                ;
 
302
        if(i==r->nused)
 
303
                panic("rdata 1");
 
304
        if(T(i)){
 
305
                n-=L(i)-(p1-p);
 
306
                if(n<=0){
 
307
                        rg.p1 = rg.p2 = p1;
 
308
                        return rg;
 
309
                }
 
310
                p+=L(i++);
 
311
                p1 = p;
 
312
        }
 
313
        if(T(i) || i==r->nused)
 
314
                panic("rdata 2");
 
315
        if(p+L(i)<p1+n)
 
316
                n = L(i)-(p1-p);
 
317
        rg.p1 = p1;
 
318
        rg.p2 = p1+n;
 
319
        if(p!=p1){
 
320
                inslist(r, i+1, L(i)-(p1-p));
 
321
                P(i)=p1-p;
 
322
                i++;
 
323
        }
 
324
        if(L(i)!=n){
 
325
                inslist(r, i+1, L(i)-n);
 
326
                P(i)=n;
 
327
        }
 
328
        P(i)|=M;
 
329
        /* now i is set; can we merge? */
 
330
        if(i<r->nused-1 && T(i+1)){
 
331
                P(i)=(n+=L(i+1))|M;
 
332
                dellist(r, i+1);
 
333
        }
 
334
        if(i>0 && T(i-1)){
 
335
                P(i)=(n+L(i-1))|M;
 
336
                dellist(r, i-1);
 
337
        }
 
338
        return rg;
 
339
}
 
340