xref: /plan9/sys/src/cmd/sam/moveto.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include "sam.h"
2 
3 void
moveto(File * f,Range r)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
telldot(File * f)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
tellpat(void)28 tellpat(void)
29 {
30 	outTS(Hsetpat, &lastpat);
31 	patset = FALSE;
32 }
33 
34 #define	CHARSHIFT	128
35 
36 void
lookorigin(File * f,Posn p0,Posn ls)37 lookorigin(File *f, Posn p0, Posn ls)
38 {
39 	int nl, nc, c;
40 	Posn p, oldp0;
41 
42 	if(p0 > f->nc)
43 		p0 = f->nc;
44 	oldp0 = p0;
45 	p = p0;
46 	for(nl=nc=c=0; c!=-1 && nl<ls && nc<ls*CHARSHIFT; nc++)
47 		if((c=filereadc(f, --p)) == '\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
alnum(int c)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
clickmatch(File * f,int cl,int cr,int dir,Posn * p)81 clickmatch(File *f, int cl, int cr, int dir, Posn *p)
82 {
83 	int c;
84 	int nest = 1;
85 
86 	for(;;){
87 		if(dir > 0){
88 			if(*p >= f->nc)
89 				break;
90 			c = filereadc(f, (*p)++);
91 		}else{
92 			if(*p == 0)
93 				break;
94 			c = filereadc(f, --(*p));
95 		}
96 		if(c == cr){
97 			if(--nest==0)
98 				return 1;
99 		}else if(c == cl)
100 			nest++;
101 	}
102 	return cl=='\n' && nest==1;
103 }
104 
105 Rune*
strrune(Rune * s,Rune c)106 strrune(Rune *s, Rune c)
107 {
108 	Rune c1;
109 
110 	if(c == 0) {
111 		while(*s++)
112 			;
113 		return s-1;
114 	}
115 
116 	while(c1 = *s++)
117 		if(c1 == c)
118 			return s-1;
119 	return 0;
120 }
121 
122 void
doubleclick(File * f,Posn p1)123 doubleclick(File *f, Posn p1)
124 {
125 	int c, i;
126 	Rune *r, *l;
127 	Posn p;
128 
129 	if(p1 > f->nc)
130 		return;
131 	f->dot.r.p1 = f->dot.r.p2 = p1;
132 	for(i=0; left[i]; i++){
133 		l = left[i];
134 		r = right[i];
135 		/* try left match */
136 		p = p1;
137 		if(p1 == 0)
138 			c = '\n';
139 		else
140 			c = filereadc(f, p - 1);
141 		if(strrune(l, c)){
142 			if(clickmatch(f, c, r[strrune(l, c)-l], 1, &p)){
143 				f->dot.r.p1 = p1;
144 				f->dot.r.p2 = p-(c!='\n');
145 			}
146 			return;
147 		}
148 		/* try right match */
149 		p = p1;
150 		if(p1 == f->nc)
151 			c = '\n';
152 		else
153 			c = filereadc(f, p);
154 		if(strrune(r, c)){
155 			if(clickmatch(f, c, l[strrune(r, c)-r], -1, &p)){
156 				f->dot.r.p1 = p;
157 				if(c!='\n' || p!=0 || filereadc(f, 0)=='\n')
158 					f->dot.r.p1++;
159 				f->dot.r.p2 = p1+(p1<f->nc && c=='\n');
160 			}
161 			return;
162 		}
163 	}
164 	/* try filling out word to right */
165 	p = p1;
166 	while(p < f->nc && alnum(filereadc(f, p++)))
167 		f->dot.r.p2++;
168 	/* try filling out word to left */
169 	p = p1;
170 	while(--p >= 0 && alnum(filereadc(f, p)))
171 		f->dot.r.p1--;
172 }
173 
174