1 #include "sam.h" 2 3 void 4 moveto(File *f, Range r) 5 { 6 Posn p1 = r.p1, p2 = r.p2; 7 8 f->dot.r.p1 = p1; 9 f->dot.r.p2 = p2; 10 if(f->rasp){ 11 telldot(f); 12 outTsl(Hmoveto, f->tag, f->dot.r.p1); 13 } 14 } 15 16 void 17 telldot(File *f) 18 { 19 if(f->rasp == 0) 20 panic("telldot"); 21 if(f->dot.r.p1==f->tdot.p1 && f->dot.r.p2==f->tdot.p2) 22 return; 23 outTsll(Hsetdot, f->tag, f->dot.r.p1, f->dot.r.p2); 24 f->tdot = f->dot.r; 25 } 26 27 void 28 tellpat(void) 29 { 30 outTS(Hsetpat, &lastpat); 31 patset = FALSE; 32 } 33 34 #define CHARSHIFT 128 35 36 void 37 lookorigin(File *f, Posn p0, Posn ls) 38 { 39 int nl, nc, c; 40 Posn oldp0; 41 42 if(p0 > f->nrunes) 43 p0 = f->nrunes; 44 oldp0 = p0; 45 Fgetcset(f, p0); 46 for(nl=nc=c=0; c!=-1 && nl<ls && nc<ls*CHARSHIFT; nc++) 47 if((c=Fbgetc(f)) == '\n'){ 48 nl++; 49 oldp0 = p0-nc; 50 } 51 if(c == -1) 52 p0 = 0; 53 else if(nl==0){ 54 if(p0>=CHARSHIFT/2) 55 p0-=CHARSHIFT/2; 56 else 57 p0 = 0; 58 }else 59 p0 = oldp0; 60 outTsl(Horigin, f->tag, p0); 61 } 62 63 int 64 alnum(int c) 65 { 66 /* 67 * Hard to get absolutely right. Use what we know about ASCII 68 * and assume anything above the Latin control characters is 69 * potentially an alphanumeric. 70 */ 71 if(c<=' ') 72 return 0; 73 if(0x7F<=c && c<=0xA0) 74 return 0; 75 if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) 76 return 0; 77 return 1; 78 } 79 80 int 81 clickmatch(File *f, int cl, int cr, int dir) 82 { 83 int c; 84 int nest = 1; 85 86 while((c=(dir>0? Fgetc(f) : Fbgetc(f))) > 0) 87 if(c == cr){ 88 if(--nest==0) 89 return 1; 90 }else if(c == cl) 91 nest++; 92 return cl=='\n' && nest==1; 93 } 94 95 Rune* 96 strrune(Rune *s, Rune c) 97 { 98 Rune c1; 99 100 if(c == 0) { 101 while(*s++) 102 ; 103 return s-1; 104 } 105 106 while(c1 = *s++) 107 if(c1 == c) 108 return s-1; 109 return 0; 110 } 111 112 void 113 doubleclick(File *f, Posn p1) 114 { 115 int c, i; 116 Rune *r, *l; 117 118 if(p1 > f->nrunes) 119 return; 120 f->dot.r.p1 = f->dot.r.p2 = p1; 121 for(i=0; left[i]; i++){ 122 l = left[i]; 123 r = right[i]; 124 /* try left match */ 125 if(p1 == 0){ 126 Fgetcset(f, p1); 127 c = '\n'; 128 }else{ 129 Fgetcset(f, p1-1); 130 c = Fgetc(f); 131 } 132 if(c!=-1 && strrune(l, c)){ 133 if(clickmatch(f, c, r[strrune(l, c)-l], 1)){ 134 f->dot.r.p1 = p1; 135 f->dot.r.p2 = f->getcp-(c!='\n'); 136 } 137 return; 138 } 139 /* try right match */ 140 if(p1 == f->nrunes){ 141 Fbgetcset(f, p1); 142 c = '\n'; 143 }else{ 144 Fbgetcset(f, p1+1); 145 c = Fbgetc(f); 146 } 147 if(c!=-1 && strrune(r, c)){ 148 if(clickmatch(f, c, l[strrune(r, c)-r], -1)){ 149 f->dot.r.p1 = f->getcp; 150 if(c!='\n' || f->getcp!=0 || 151 (Fgetcset(f, (Posn)0),Fgetc(f))=='\n') 152 f->dot.r.p1++; 153 f->dot.r.p2 = p1+(p1<f->nrunes && c=='\n'); 154 } 155 return; 156 } 157 } 158 /* try filling out word to right */ 159 Fgetcset(f, p1); 160 while((c=Fgetc(f))!=-1 && alnum(c)) 161 f->dot.r.p2++; 162 /* try filling out word to left */ 163 Fbgetcset(f, p1); 164 while((c=Fbgetc(f))!=-1 && alnum(c)) 165 f->dot.r.p1--; 166 } 167 168