📄 rasp.c
字号:
#include "sam.h"/* * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's, * so they will be scrolled into visibility in the ~~sam~~ window (yuck!). */#define GROWDATASIZE 50 /* if size is > this, send data with grow */void rcut(List*, Posn, Posn);int rterm(List*, Posn);void rgrow(List*, Posn, Posn);static Posn growpos;static Posn grown;static Posn shrinkpos;static Posn shrunk;/* * rasp routines inform the terminal of changes to the file. * * a rasp is a list of spans within the file, and an indication * of whether the terminal knows about the span. * * optimize by coalescing multiple updates to the same span * if it is not known by the terminal. * * other possible optimizations: flush terminal's rasp by cut everything, * insert everything if rasp gets too large. *//* * only called for initial load of file */voidraspload(File *f){ if(f->rasp == nil) return; grown = f->nc; growpos = 0; if(f->nc) rgrow(f->rasp, 0, f->nc); raspdone(f, 1);}voidraspstart(File *f){ if(f->rasp == nil) return; grown = 0; shrunk = 0; noflush = 1;}voidraspdone(File *f, int toterm){ if(f->dot.r.p1 > f->nc) f->dot.r.p1 = f->nc; if(f->dot.r.p2 > f->nc) f->dot.r.p2 = f->nc; if(f->mark.p1 > f->nc) f->mark.p1 = f->nc; if(f->mark.p2 > f->nc) f->mark.p2 = f->nc; if(f->rasp == nil) return; if(grown) outTsll(Hgrow, f->tag, growpos, grown); else if(shrunk) outTsll(Hcut, f->tag, shrinkpos, shrunk); if(toterm) outTs(Hcheck0, f->tag); outflush(); noflush = 0; if(f == cmd){ cmdpt += cmdptadv; cmdptadv = 0; }}voidraspdelete(File *f, uint p1, uint p2, int toterm){ long n; n = p2 - p1; if(n == 0) return; if(p2 <= f->dot.r.p1){ f->dot.r.p1 -= n; f->dot.r.p2 -= n; } if(p2 <= f->mark.p1){ f->mark.p1 -= n; f->mark.p2 -= n; } if(f->rasp == nil) return; if(f==cmd && p1<cmdpt){ if(p2 <= cmdpt) cmdpt -= n; else cmdpt = p1; } if(toterm){ if(grown){ outTsll(Hgrow, f->tag, growpos, grown); grown = 0; }else if(shrunk && shrinkpos!=p1 && shrinkpos!=p2){ outTsll(Hcut, f->tag, shrinkpos, shrunk); shrunk = 0; } if(!shrunk || shrinkpos==p2) shrinkpos = p1; shrunk += n; } rcut(f->rasp, p1, p2);}voidraspinsert(File *f, uint p1, Rune *buf, uint n, int toterm){ Range r; if(n == 0) return; if(p1 < f->dot.r.p1){ f->dot.r.p1 += n; f->dot.r.p2 += n; } if(p1 < f->mark.p1){ f->mark.p1 += n; f->mark.p2 += n; } if(f->rasp == nil) return; if(f==cmd && p1<cmdpt) cmdpt += n; if(toterm){ if(shrunk){ outTsll(Hcut, f->tag, shrinkpos, shrunk); shrunk = 0; } if(n>GROWDATASIZE || !rterm(f->rasp, p1)){ rgrow(f->rasp, p1, n); if(grown && growpos+grown!=p1 && growpos!=p1){ outTsll(Hgrow, f->tag, growpos, grown); grown = 0; } if(!grown) growpos = p1; grown += n; }else{ if(grown){ outTsll(Hgrow, f->tag, growpos, grown); grown = 0; } rgrow(f->rasp, p1, n); r = rdata(f->rasp, p1, n); if(r.p1!=p1 || r.p2!=p1+n) panic("rdata in toterminal"); outTsllS(Hgrowdata, f->tag, p1, n, tmprstr(buf, n)); } }else{ rgrow(f->rasp, p1, n); r = rdata(f->rasp, p1, n); if(r.p1!=p1 || r.p2!=p1+n) panic("rdata in toterminal"); }}#define M 0x80000000L#define P(i) r->posnptr[i]#define T(i) (P(i)&M) /* in terminal */#define L(i) (P(i)&~M) /* length of this piece */voidrcut(List *r, Posn p1, Posn p2){ Posn p, x; int i; if(p1 == p2) panic("rcut 0"); for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++)) ; if(i == r->nused) panic("rcut 1"); if(p < p1){ /* chop this piece */ if(p+L(i) < p2){ x = p1-p; p += L(i); }else{ x = L(i)-(p2-p1); p = p2; } if(T(i)) P(i) = x|M; else P(i) = x; i++; } while(i<r->nused && p+L(i)<=p2){ p += L(i); dellist(r, i); } if(p < p2){ if(i == r->nused) panic("rcut 2"); x = L(i)-(p2-p); if(T(i)) P(i) = x|M; else P(i) = x; } /* can we merge i and i-1 ? */ if(i>0 && i<r->nused && T(i-1)==T(i)){ x = L(i-1)+L(i); dellist(r, i--); if(T(i)) P(i)=x|M; else P(i)=x; }}voidrgrow(List *r, Posn p1, Posn n){ Posn p; int i; if(n == 0) panic("rgrow 0"); for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++)) ; if(i == r->nused){ /* stick on end of file */ if(p!=p1) panic("rgrow 1"); if(i>0 && !T(i-1)) P(i-1)+=n; else inslist(r, i, n); }else if(!T(i)) /* goes in this empty piece */ P(i)+=n; else if(p==p1 && i>0 && !T(i-1)) /* special case; simplifies life */ P(i-1)+=n; else if(p==p1) inslist(r, i, n); else{ /* must break piece in terminal */ inslist(r, i+1, (L(i)-(p1-p))|M); inslist(r, i+1, n); P(i) = (p1-p)|M; }}intrterm(List *r, Posn p1){ Posn p; int i; for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++)) ; if(i==r->nused && (i==0 || !T(i-1))) return 0; return T(i);}Rangerdata(List *r, Posn p1, Posn n){ Posn p; int i; Range rg; if(n==0) panic("rdata 0"); for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++)) ; if(i==r->nused) panic("rdata 1"); if(T(i)){ n-=L(i)-(p1-p); if(n<=0){ rg.p1 = rg.p2 = p1; return rg; } p+=L(i++); p1 = p; } if(T(i) || i==r->nused) panic("rdata 2"); if(p+L(i)<p1+n) n = L(i)-(p1-p); rg.p1 = p1; rg.p2 = p1+n; if(p!=p1){ inslist(r, i+1, L(i)-(p1-p)); P(i)=p1-p; i++; } if(L(i)!=n){ inslist(r, i+1, L(i)-n); P(i)=n; } P(i)|=M; /* now i is set; can we merge? */ if(i<r->nused-1 && T(i+1)){ P(i)=(n+=L(i+1))|M; dellist(r, i+1); } if(i>0 && T(i-1)){ P(i)=(n+L(i-1))|M; dellist(r, i-1); } return rg;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -