xref: /plan9/sys/src/cmd/sam/moveto.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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