Blame


1 b3994ec5 2003-12-11 devnull #include <u.h>
2 b3994ec5 2003-12-11 devnull #include <libc.h>
3 b3994ec5 2003-12-11 devnull #include <draw.h>
4 b3994ec5 2003-12-11 devnull #include <thread.h>
5 b3994ec5 2003-12-11 devnull #include <cursor.h>
6 b3994ec5 2003-12-11 devnull #include <mouse.h>
7 b3994ec5 2003-12-11 devnull #include <keyboard.h>
8 b3994ec5 2003-12-11 devnull #include <frame.h>
9 b3994ec5 2003-12-11 devnull #include <fcall.h>
10 b3994ec5 2003-12-11 devnull #include <plumb.h>
11 67dbeee5 2017-10-10 rsc #include <libsec.h>
12 b3994ec5 2003-12-11 devnull #include "dat.h"
13 b3994ec5 2003-12-11 devnull #include "edit.h"
14 b3994ec5 2003-12-11 devnull #include "fns.h"
15 b3994ec5 2003-12-11 devnull
16 b3994ec5 2003-12-11 devnull int Glooping;
17 b3994ec5 2003-12-11 devnull int nest;
18 b3994ec5 2003-12-11 devnull char Enoname[] = "no file name given";
19 b3994ec5 2003-12-11 devnull
20 b3994ec5 2003-12-11 devnull Address addr;
21 b3994ec5 2003-12-11 devnull File *menu;
22 b3994ec5 2003-12-11 devnull Rangeset sel;
23 b3994ec5 2003-12-11 devnull extern Text* curtext;
24 b3994ec5 2003-12-11 devnull Rune *collection;
25 b3994ec5 2003-12-11 devnull int ncollection;
26 b3994ec5 2003-12-11 devnull
27 b3994ec5 2003-12-11 devnull int append(File*, Cmd*, long);
28 b3994ec5 2003-12-11 devnull int pdisplay(File*);
29 b3994ec5 2003-12-11 devnull void pfilename(File*);
30 b3994ec5 2003-12-11 devnull void looper(File*, Cmd*, int);
31 d2df5d6c 2020-01-13 rsc void filelooper(Text*, Cmd*, int);
32 b3994ec5 2003-12-11 devnull void linelooper(File*, Cmd*);
33 b3994ec5 2003-12-11 devnull Address lineaddr(long, Address, int);
34 b3994ec5 2003-12-11 devnull int filematch(File*, String*);
35 b3994ec5 2003-12-11 devnull File *tofile(String*);
36 b3994ec5 2003-12-11 devnull Rune* cmdname(File *f, String *s, int);
37 b3994ec5 2003-12-11 devnull void runpipe(Text*, int, Rune*, int, int);
38 b3994ec5 2003-12-11 devnull
39 b3994ec5 2003-12-11 devnull void
40 b3994ec5 2003-12-11 devnull clearcollection(void)
41 b3994ec5 2003-12-11 devnull {
42 b3994ec5 2003-12-11 devnull free(collection);
43 b3994ec5 2003-12-11 devnull collection = nil;
44 b3994ec5 2003-12-11 devnull ncollection = 0;
45 b3994ec5 2003-12-11 devnull }
46 b3994ec5 2003-12-11 devnull
47 b3994ec5 2003-12-11 devnull void
48 b3994ec5 2003-12-11 devnull resetxec(void)
49 b3994ec5 2003-12-11 devnull {
50 b3994ec5 2003-12-11 devnull Glooping = nest = 0;
51 b3994ec5 2003-12-11 devnull clearcollection();
52 b3994ec5 2003-12-11 devnull }
53 b3994ec5 2003-12-11 devnull
54 b3994ec5 2003-12-11 devnull void
55 b3994ec5 2003-12-11 devnull mkaddr(Address *a, File *f)
56 b3994ec5 2003-12-11 devnull {
57 b3994ec5 2003-12-11 devnull a->r.q0 = f->curtext->q0;
58 b3994ec5 2003-12-11 devnull a->r.q1 = f->curtext->q1;
59 b3994ec5 2003-12-11 devnull a->f = f;
60 b3994ec5 2003-12-11 devnull }
61 b3994ec5 2003-12-11 devnull
62 b3994ec5 2003-12-11 devnull int
63 b3994ec5 2003-12-11 devnull cmdexec(Text *t, Cmd *cp)
64 b3994ec5 2003-12-11 devnull {
65 b3994ec5 2003-12-11 devnull int i;
66 b3994ec5 2003-12-11 devnull Addr *ap;
67 b3994ec5 2003-12-11 devnull File *f;
68 b3994ec5 2003-12-11 devnull Window *w;
69 b3994ec5 2003-12-11 devnull Address dot;
70 b3994ec5 2003-12-11 devnull
71 b3994ec5 2003-12-11 devnull if(t == nil)
72 b3994ec5 2003-12-11 devnull w = nil;
73 b3994ec5 2003-12-11 devnull else
74 b3994ec5 2003-12-11 devnull w = t->w;
75 b3994ec5 2003-12-11 devnull if(w==nil && (cp->addr==0 || cp->addr->type!='"') &&
76 b3994ec5 2003-12-11 devnull !utfrune("bBnqUXY!", cp->cmdc) &&
77 b3994ec5 2003-12-11 devnull !(cp->cmdc=='D' && cp->u.text))
78 b3994ec5 2003-12-11 devnull editerror("no current window");
79 b3994ec5 2003-12-11 devnull i = cmdlookup(cp->cmdc); /* will be -1 for '{' */
80 b3994ec5 2003-12-11 devnull f = nil;
81 b3994ec5 2003-12-11 devnull if(t && t->w){
82 b3994ec5 2003-12-11 devnull t = &t->w->body;
83 b3994ec5 2003-12-11 devnull f = t->file;
84 b3994ec5 2003-12-11 devnull f->curtext = t;
85 b3994ec5 2003-12-11 devnull }
86 b3994ec5 2003-12-11 devnull if(i>=0 && cmdtab[i].defaddr != aNo){
87 b3994ec5 2003-12-11 devnull if((ap=cp->addr)==0 && cp->cmdc!='\n'){
88 b3994ec5 2003-12-11 devnull cp->addr = ap = newaddr();
89 b3994ec5 2003-12-11 devnull ap->type = '.';
90 b3994ec5 2003-12-11 devnull if(cmdtab[i].defaddr == aAll)
91 b3994ec5 2003-12-11 devnull ap->type = '*';
92 b3994ec5 2003-12-11 devnull }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){
93 b3994ec5 2003-12-11 devnull ap->next = newaddr();
94 b3994ec5 2003-12-11 devnull ap->next->type = '.';
95 b3994ec5 2003-12-11 devnull if(cmdtab[i].defaddr == aAll)
96 b3994ec5 2003-12-11 devnull ap->next->type = '*';
97 b3994ec5 2003-12-11 devnull }
98 b3994ec5 2003-12-11 devnull if(cp->addr){ /* may be false for '\n' (only) */
99 b3994ec5 2003-12-11 devnull static Address none = {0,0,nil};
100 b3994ec5 2003-12-11 devnull if(f){
101 b3994ec5 2003-12-11 devnull mkaddr(&dot, f);
102 b3994ec5 2003-12-11 devnull addr = cmdaddress(ap, dot, 0);
103 b3994ec5 2003-12-11 devnull }else /* a " */
104 b3994ec5 2003-12-11 devnull addr = cmdaddress(ap, none, 0);
105 b3994ec5 2003-12-11 devnull f = addr.f;
106 b3994ec5 2003-12-11 devnull t = f->curtext;
107 b3994ec5 2003-12-11 devnull }
108 b3994ec5 2003-12-11 devnull }
109 b3994ec5 2003-12-11 devnull switch(cp->cmdc){
110 b3994ec5 2003-12-11 devnull case '{':
111 b3994ec5 2003-12-11 devnull mkaddr(&dot, f);
112 b3994ec5 2003-12-11 devnull if(cp->addr != nil)
113 b3994ec5 2003-12-11 devnull dot = cmdaddress(cp->addr, dot, 0);
114 b3994ec5 2003-12-11 devnull for(cp = cp->u.cmd; cp; cp = cp->next){
115 b3994ec5 2003-12-11 devnull if(dot.r.q1 > t->file->b.nc)
116 b3994ec5 2003-12-11 devnull editerror("dot extends past end of buffer during { command");
117 b3994ec5 2003-12-11 devnull t->q0 = dot.r.q0;
118 b3994ec5 2003-12-11 devnull t->q1 = dot.r.q1;
119 b3994ec5 2003-12-11 devnull cmdexec(t, cp);
120 b3994ec5 2003-12-11 devnull }
121 b3994ec5 2003-12-11 devnull break;
122 b3994ec5 2003-12-11 devnull default:
123 b3994ec5 2003-12-11 devnull if(i < 0)
124 b3994ec5 2003-12-11 devnull editerror("unknown command %c in cmdexec", cp->cmdc);
125 b3994ec5 2003-12-11 devnull i = (*cmdtab[i].fn)(t, cp);
126 b3994ec5 2003-12-11 devnull return i;
127 b3994ec5 2003-12-11 devnull }
128 b3994ec5 2003-12-11 devnull return 1;
129 b3994ec5 2003-12-11 devnull }
130 b3994ec5 2003-12-11 devnull
131 b3994ec5 2003-12-11 devnull char*
132 b3994ec5 2003-12-11 devnull edittext(Window *w, int q, Rune *r, int nr)
133 b3994ec5 2003-12-11 devnull {
134 b3994ec5 2003-12-11 devnull File *f;
135 b3994ec5 2003-12-11 devnull
136 b3994ec5 2003-12-11 devnull f = w->body.file;
137 b3994ec5 2003-12-11 devnull switch(editing){
138 b3994ec5 2003-12-11 devnull case Inactive:
139 b3994ec5 2003-12-11 devnull return "permission denied";
140 b3994ec5 2003-12-11 devnull case Inserting:
141 b3994ec5 2003-12-11 devnull eloginsert(f, q, r, nr);
142 b3994ec5 2003-12-11 devnull return nil;
143 b3994ec5 2003-12-11 devnull case Collecting:
144 b3994ec5 2003-12-11 devnull collection = runerealloc(collection, ncollection+nr+1);
145 b3994ec5 2003-12-11 devnull runemove(collection+ncollection, r, nr);
146 b3994ec5 2003-12-11 devnull ncollection += nr;
147 b3994ec5 2003-12-11 devnull collection[ncollection] = '\0';
148 b3994ec5 2003-12-11 devnull return nil;
149 b3994ec5 2003-12-11 devnull default:
150 b3994ec5 2003-12-11 devnull return "unknown state in edittext";
151 b3994ec5 2003-12-11 devnull }
152 b3994ec5 2003-12-11 devnull }
153 b3994ec5 2003-12-11 devnull
154 b3994ec5 2003-12-11 devnull /* string is known to be NUL-terminated */
155 b3994ec5 2003-12-11 devnull Rune*
156 b3994ec5 2003-12-11 devnull filelist(Text *t, Rune *r, int nr)
157 b3994ec5 2003-12-11 devnull {
158 b3994ec5 2003-12-11 devnull if(nr == 0)
159 b3994ec5 2003-12-11 devnull return nil;
160 b3994ec5 2003-12-11 devnull r = skipbl(r, nr, &nr);
161 b3994ec5 2003-12-11 devnull if(r[0] != '<')
162 b3994ec5 2003-12-11 devnull return runestrdup(r);
163 b3994ec5 2003-12-11 devnull /* use < command to collect text */
164 b3994ec5 2003-12-11 devnull clearcollection();
165 b3994ec5 2003-12-11 devnull runpipe(t, '<', r+1, nr-1, Collecting);
166 b3994ec5 2003-12-11 devnull return collection;
167 b3994ec5 2003-12-11 devnull }
168 b3994ec5 2003-12-11 devnull
169 b3994ec5 2003-12-11 devnull int
170 b3994ec5 2003-12-11 devnull a_cmd(Text *t, Cmd *cp)
171 b3994ec5 2003-12-11 devnull {
172 b3994ec5 2003-12-11 devnull return append(t->file, cp, addr.r.q1);
173 b3994ec5 2003-12-11 devnull }
174 b3994ec5 2003-12-11 devnull
175 b3994ec5 2003-12-11 devnull int
176 b3994ec5 2003-12-11 devnull b_cmd(Text *t, Cmd *cp)
177 b3994ec5 2003-12-11 devnull {
178 b3994ec5 2003-12-11 devnull File *f;
179 b3994ec5 2003-12-11 devnull
180 b3994ec5 2003-12-11 devnull USED(t);
181 b3994ec5 2003-12-11 devnull f = tofile(cp->u.text);
182 b3994ec5 2003-12-11 devnull if(nest == 0)
183 b3994ec5 2003-12-11 devnull pfilename(f);
184 b3994ec5 2003-12-11 devnull curtext = f->curtext;
185 b3994ec5 2003-12-11 devnull return TRUE;
186 b3994ec5 2003-12-11 devnull }
187 b3994ec5 2003-12-11 devnull
188 b3994ec5 2003-12-11 devnull int
189 b3994ec5 2003-12-11 devnull B_cmd(Text *t, Cmd *cp)
190 b3994ec5 2003-12-11 devnull {
191 b3994ec5 2003-12-11 devnull Rune *list, *r, *s;
192 b3994ec5 2003-12-11 devnull int nr;
193 b3994ec5 2003-12-11 devnull
194 b3994ec5 2003-12-11 devnull list = filelist(t, cp->u.text->r, cp->u.text->n);
195 b3994ec5 2003-12-11 devnull if(list == nil)
196 b3994ec5 2003-12-11 devnull editerror(Enoname);
197 b3994ec5 2003-12-11 devnull r = list;
198 b3994ec5 2003-12-11 devnull nr = runestrlen(r);
199 b3994ec5 2003-12-11 devnull r = skipbl(r, nr, &nr);
200 b3994ec5 2003-12-11 devnull if(nr == 0)
201 b3994ec5 2003-12-11 devnull new(t, t, nil, 0, 0, r, 0);
202 b3994ec5 2003-12-11 devnull else while(nr > 0){
203 b3994ec5 2003-12-11 devnull s = findbl(r, nr, &nr);
204 b3994ec5 2003-12-11 devnull *s = '\0';
205 b3994ec5 2003-12-11 devnull new(t, t, nil, 0, 0, r, runestrlen(r));
206 b3994ec5 2003-12-11 devnull if(nr > 0)
207 b3994ec5 2003-12-11 devnull r = skipbl(s+1, nr-1, &nr);
208 b3994ec5 2003-12-11 devnull }
209 b3994ec5 2003-12-11 devnull clearcollection();
210 b3994ec5 2003-12-11 devnull return TRUE;
211 b3994ec5 2003-12-11 devnull }
212 b3994ec5 2003-12-11 devnull
213 b3994ec5 2003-12-11 devnull int
214 b3994ec5 2003-12-11 devnull c_cmd(Text *t, Cmd *cp)
215 b3994ec5 2003-12-11 devnull {
216 b3994ec5 2003-12-11 devnull elogreplace(t->file, addr.r.q0, addr.r.q1, cp->u.text->r, cp->u.text->n);
217 b3994ec5 2003-12-11 devnull t->q0 = addr.r.q0;
218 5e77b8bb 2005-03-23 devnull t->q1 = addr.r.q1;
219 b3994ec5 2003-12-11 devnull return TRUE;
220 b3994ec5 2003-12-11 devnull }
221 b3994ec5 2003-12-11 devnull
222 b3994ec5 2003-12-11 devnull int
223 b3994ec5 2003-12-11 devnull d_cmd(Text *t, Cmd *cp)
224 b3994ec5 2003-12-11 devnull {
225 b3994ec5 2003-12-11 devnull USED(cp);
226 b3994ec5 2003-12-11 devnull if(addr.r.q1 > addr.r.q0)
227 b3994ec5 2003-12-11 devnull elogdelete(t->file, addr.r.q0, addr.r.q1);
228 b3994ec5 2003-12-11 devnull t->q0 = addr.r.q0;
229 b3994ec5 2003-12-11 devnull t->q1 = addr.r.q0;
230 b3994ec5 2003-12-11 devnull return TRUE;
231 b3994ec5 2003-12-11 devnull }
232 b3994ec5 2003-12-11 devnull
233 b3994ec5 2003-12-11 devnull void
234 b3994ec5 2003-12-11 devnull D1(Text *t)
235 b3994ec5 2003-12-11 devnull {
236 b3994ec5 2003-12-11 devnull if(t->w->body.file->ntext>1 || winclean(t->w, FALSE))
237 b3994ec5 2003-12-11 devnull colclose(t->col, t->w, TRUE);
238 b3994ec5 2003-12-11 devnull }
239 b3994ec5 2003-12-11 devnull
240 b3994ec5 2003-12-11 devnull int
241 b3994ec5 2003-12-11 devnull D_cmd(Text *t, Cmd *cp)
242 b3994ec5 2003-12-11 devnull {
243 b3994ec5 2003-12-11 devnull Rune *list, *r, *s, *n;
244 b3994ec5 2003-12-11 devnull int nr, nn;
245 b3994ec5 2003-12-11 devnull Window *w;
246 b3994ec5 2003-12-11 devnull Runestr dir, rs;
247 b3994ec5 2003-12-11 devnull char buf[128];
248 b3994ec5 2003-12-11 devnull
249 b3994ec5 2003-12-11 devnull list = filelist(t, cp->u.text->r, cp->u.text->n);
250 b3994ec5 2003-12-11 devnull if(list == nil){
251 b3994ec5 2003-12-11 devnull D1(t);
252 b3994ec5 2003-12-11 devnull return TRUE;
253 b3994ec5 2003-12-11 devnull }
254 b3994ec5 2003-12-11 devnull dir = dirname(t, nil, 0);
255 b3994ec5 2003-12-11 devnull r = list;
256 b3994ec5 2003-12-11 devnull nr = runestrlen(r);
257 b3994ec5 2003-12-11 devnull r = skipbl(r, nr, &nr);
258 b3994ec5 2003-12-11 devnull do{
259 b3994ec5 2003-12-11 devnull s = findbl(r, nr, &nr);
260 b3994ec5 2003-12-11 devnull *s = '\0';
261 b3994ec5 2003-12-11 devnull /* first time through, could be empty string, meaning delete file empty name */
262 b3994ec5 2003-12-11 devnull nn = runestrlen(r);
263 b3994ec5 2003-12-11 devnull if(r[0]=='/' || nn==0 || dir.nr==0){
264 b3994ec5 2003-12-11 devnull rs.r = runestrdup(r);
265 b3994ec5 2003-12-11 devnull rs.nr = nn;
266 b3994ec5 2003-12-11 devnull }else{
267 b3994ec5 2003-12-11 devnull n = runemalloc(dir.nr+1+nn);
268 b3994ec5 2003-12-11 devnull runemove(n, dir.r, dir.nr);
269 b3994ec5 2003-12-11 devnull n[dir.nr] = '/';
270 b3994ec5 2003-12-11 devnull runemove(n+dir.nr+1, r, nn);
271 8ad51794 2004-03-25 devnull rs = cleanrname(runestr(n, dir.nr+1+nn));
272 b3994ec5 2003-12-11 devnull }
273 b3994ec5 2003-12-11 devnull w = lookfile(rs.r, rs.nr);
274 b3994ec5 2003-12-11 devnull if(w == nil){
275 b3994ec5 2003-12-11 devnull snprint(buf, sizeof buf, "no such file %.*S", rs.nr, rs.r);
276 b3994ec5 2003-12-11 devnull free(rs.r);
277 b3994ec5 2003-12-11 devnull editerror(buf);
278 b3994ec5 2003-12-11 devnull }
279 b3994ec5 2003-12-11 devnull free(rs.r);
280 b3994ec5 2003-12-11 devnull D1(&w->body);
281 b3994ec5 2003-12-11 devnull if(nr > 0)
282 b3994ec5 2003-12-11 devnull r = skipbl(s+1, nr-1, &nr);
283 b3994ec5 2003-12-11 devnull }while(nr > 0);
284 b3994ec5 2003-12-11 devnull clearcollection();
285 b3994ec5 2003-12-11 devnull free(dir.r);
286 b3994ec5 2003-12-11 devnull return TRUE;
287 b3994ec5 2003-12-11 devnull }
288 b3994ec5 2003-12-11 devnull
289 b3994ec5 2003-12-11 devnull static int
290 b3994ec5 2003-12-11 devnull readloader(void *v, uint q0, Rune *r, int nr)
291 b3994ec5 2003-12-11 devnull {
292 b3994ec5 2003-12-11 devnull if(nr > 0)
293 b3994ec5 2003-12-11 devnull eloginsert(v, q0, r, nr);
294 b3994ec5 2003-12-11 devnull return 0;
295 b3994ec5 2003-12-11 devnull }
296 b3994ec5 2003-12-11 devnull
297 b3994ec5 2003-12-11 devnull int
298 b3994ec5 2003-12-11 devnull e_cmd(Text *t, Cmd *cp)
299 b3994ec5 2003-12-11 devnull {
300 b3994ec5 2003-12-11 devnull Rune *name;
301 b3994ec5 2003-12-11 devnull File *f;
302 b3994ec5 2003-12-11 devnull int i, isdir, q0, q1, fd, nulls, samename, allreplaced;
303 b3994ec5 2003-12-11 devnull char *s, tmp[128];
304 b3994ec5 2003-12-11 devnull Dir *d;
305 b3994ec5 2003-12-11 devnull
306 b3994ec5 2003-12-11 devnull f = t->file;
307 b3994ec5 2003-12-11 devnull q0 = addr.r.q0;
308 b3994ec5 2003-12-11 devnull q1 = addr.r.q1;
309 b3994ec5 2003-12-11 devnull if(cp->cmdc == 'e'){
310 b3994ec5 2003-12-11 devnull if(winclean(t->w, TRUE)==FALSE)
311 b3994ec5 2003-12-11 devnull editerror(""); /* winclean generated message already */
312 b3994ec5 2003-12-11 devnull q0 = 0;
313 b3994ec5 2003-12-11 devnull q1 = f->b.nc;
314 b3994ec5 2003-12-11 devnull }
315 b3994ec5 2003-12-11 devnull allreplaced = (q0==0 && q1==f->b.nc);
316 b3994ec5 2003-12-11 devnull name = cmdname(f, cp->u.text, cp->cmdc=='e');
317 b3994ec5 2003-12-11 devnull if(name == nil)
318 b3994ec5 2003-12-11 devnull editerror(Enoname);
319 b3994ec5 2003-12-11 devnull i = runestrlen(name);
320 b3994ec5 2003-12-11 devnull samename = runeeq(name, i, t->file->name, t->file->nname);
321 b3994ec5 2003-12-11 devnull s = runetobyte(name, i);
322 b3994ec5 2003-12-11 devnull free(name);
323 b3994ec5 2003-12-11 devnull fd = open(s, OREAD);
324 b3994ec5 2003-12-11 devnull if(fd < 0){
325 b3994ec5 2003-12-11 devnull snprint(tmp, sizeof tmp, "can't open %s: %r", s);
326 b3994ec5 2003-12-11 devnull free(s);
327 b3994ec5 2003-12-11 devnull editerror(tmp);
328 b3994ec5 2003-12-11 devnull }
329 b3994ec5 2003-12-11 devnull d = dirfstat(fd);
330 b3994ec5 2003-12-11 devnull isdir = (d!=nil && (d->qid.type&QTDIR));
331 b3994ec5 2003-12-11 devnull free(d);
332 b3994ec5 2003-12-11 devnull if(isdir){
333 b3994ec5 2003-12-11 devnull close(fd);
334 b3994ec5 2003-12-11 devnull snprint(tmp, sizeof tmp, "%s is a directory", s);
335 b3994ec5 2003-12-11 devnull free(s);
336 b3994ec5 2003-12-11 devnull editerror(tmp);
337 b3994ec5 2003-12-11 devnull }
338 b3994ec5 2003-12-11 devnull elogdelete(f, q0, q1);
339 b3994ec5 2003-12-11 devnull nulls = 0;
340 67dbeee5 2017-10-10 rsc loadfile(fd, q1, &nulls, readloader, f, nil);
341 b3994ec5 2003-12-11 devnull free(s);
342 b3994ec5 2003-12-11 devnull close(fd);
343 b3994ec5 2003-12-11 devnull if(nulls)
344 b3994ec5 2003-12-11 devnull warning(nil, "%s: NUL bytes elided\n", s);
345 b3994ec5 2003-12-11 devnull else if(allreplaced && samename)
346 b3994ec5 2003-12-11 devnull f->editclean = TRUE;
347 b3994ec5 2003-12-11 devnull return TRUE;
348 b3994ec5 2003-12-11 devnull }
349 b3994ec5 2003-12-11 devnull
350 b3994ec5 2003-12-11 devnull static Rune Lempty[] = { 0 };
351 b3994ec5 2003-12-11 devnull int
352 b3994ec5 2003-12-11 devnull f_cmd(Text *t, Cmd *cp)
353 b3994ec5 2003-12-11 devnull {
354 b3994ec5 2003-12-11 devnull Rune *name;
355 b3994ec5 2003-12-11 devnull String *str;
356 b3994ec5 2003-12-11 devnull String empty;
357 b3994ec5 2003-12-11 devnull
358 b3994ec5 2003-12-11 devnull if(cp->u.text == nil){
359 b3994ec5 2003-12-11 devnull empty.n = 0;
360 b3994ec5 2003-12-11 devnull empty.r = Lempty;
361 b3994ec5 2003-12-11 devnull str = &empty;
362 b3994ec5 2003-12-11 devnull }else
363 b3994ec5 2003-12-11 devnull str = cp->u.text;
364 b3994ec5 2003-12-11 devnull name = cmdname(t->file, str, TRUE);
365 b3994ec5 2003-12-11 devnull free(name);
366 b3994ec5 2003-12-11 devnull pfilename(t->file);
367 b3994ec5 2003-12-11 devnull return TRUE;
368 b3994ec5 2003-12-11 devnull }
369 b3994ec5 2003-12-11 devnull
370 b3994ec5 2003-12-11 devnull int
371 b3994ec5 2003-12-11 devnull g_cmd(Text *t, Cmd *cp)
372 b3994ec5 2003-12-11 devnull {
373 b3994ec5 2003-12-11 devnull if(t->file != addr.f){
374 b3994ec5 2003-12-11 devnull warning(nil, "internal error: g_cmd f!=addr.f\n");
375 b3994ec5 2003-12-11 devnull return FALSE;
376 b3994ec5 2003-12-11 devnull }
377 b3994ec5 2003-12-11 devnull if(rxcompile(cp->re->r) == FALSE)
378 b3994ec5 2003-12-11 devnull editerror("bad regexp in g command");
379 b3994ec5 2003-12-11 devnull if(rxexecute(t, nil, addr.r.q0, addr.r.q1, &sel) ^ cp->cmdc=='v'){
380 b3994ec5 2003-12-11 devnull t->q0 = addr.r.q0;
381 b3994ec5 2003-12-11 devnull t->q1 = addr.r.q1;
382 b3994ec5 2003-12-11 devnull return cmdexec(t, cp->u.cmd);
383 b3994ec5 2003-12-11 devnull }
384 b3994ec5 2003-12-11 devnull return TRUE;
385 b3994ec5 2003-12-11 devnull }
386 b3994ec5 2003-12-11 devnull
387 b3994ec5 2003-12-11 devnull int
388 b3994ec5 2003-12-11 devnull i_cmd(Text *t, Cmd *cp)
389 b3994ec5 2003-12-11 devnull {
390 b3994ec5 2003-12-11 devnull return append(t->file, cp, addr.r.q0);
391 b3994ec5 2003-12-11 devnull }
392 b3994ec5 2003-12-11 devnull
393 b3994ec5 2003-12-11 devnull void
394 b3994ec5 2003-12-11 devnull copy(File *f, Address addr2)
395 b3994ec5 2003-12-11 devnull {
396 b3994ec5 2003-12-11 devnull long p;
397 b3994ec5 2003-12-11 devnull int ni;
398 b3994ec5 2003-12-11 devnull Rune *buf;
399 b3994ec5 2003-12-11 devnull
400 b3994ec5 2003-12-11 devnull buf = fbufalloc();
401 b3994ec5 2003-12-11 devnull for(p=addr.r.q0; p<addr.r.q1; p+=ni){
402 b3994ec5 2003-12-11 devnull ni = addr.r.q1-p;
403 b3994ec5 2003-12-11 devnull if(ni > RBUFSIZE)
404 b3994ec5 2003-12-11 devnull ni = RBUFSIZE;
405 b3994ec5 2003-12-11 devnull bufread(&f->b, p, buf, ni);
406 b3994ec5 2003-12-11 devnull eloginsert(addr2.f, addr2.r.q1, buf, ni);
407 b3994ec5 2003-12-11 devnull }
408 b3994ec5 2003-12-11 devnull fbuffree(buf);
409 b3994ec5 2003-12-11 devnull }
410 b3994ec5 2003-12-11 devnull
411 b3994ec5 2003-12-11 devnull void
412 b3994ec5 2003-12-11 devnull move(File *f, Address addr2)
413 b3994ec5 2003-12-11 devnull {
414 b3994ec5 2003-12-11 devnull if(addr.f!=addr2.f || addr.r.q1<=addr2.r.q0){
415 b3994ec5 2003-12-11 devnull elogdelete(f, addr.r.q0, addr.r.q1);
416 b3994ec5 2003-12-11 devnull copy(f, addr2);
417 b3994ec5 2003-12-11 devnull }else if(addr.r.q0 >= addr2.r.q1){
418 b3994ec5 2003-12-11 devnull copy(f, addr2);
419 b3994ec5 2003-12-11 devnull elogdelete(f, addr.r.q0, addr.r.q1);
420 5e22f11b 2008-03-07 devnull }else if(addr.r.q0==addr2.r.q0 && addr.r.q1==addr2.r.q1){
421 5e22f11b 2008-03-07 devnull ; /* move to self; no-op */
422 b3994ec5 2003-12-11 devnull }else
423 5e22f11b 2008-03-07 devnull editerror("move overlaps itself");
424 b3994ec5 2003-12-11 devnull }
425 b3994ec5 2003-12-11 devnull
426 b3994ec5 2003-12-11 devnull int
427 b3994ec5 2003-12-11 devnull m_cmd(Text *t, Cmd *cp)
428 b3994ec5 2003-12-11 devnull {
429 b3994ec5 2003-12-11 devnull Address dot, addr2;
430 b3994ec5 2003-12-11 devnull
431 b3994ec5 2003-12-11 devnull mkaddr(&dot, t->file);
432 b3994ec5 2003-12-11 devnull addr2 = cmdaddress(cp->u.mtaddr, dot, 0);
433 b3994ec5 2003-12-11 devnull if(cp->cmdc == 'm')
434 b3994ec5 2003-12-11 devnull move(t->file, addr2);
435 b3994ec5 2003-12-11 devnull else
436 b3994ec5 2003-12-11 devnull copy(t->file, addr2);
437 b3994ec5 2003-12-11 devnull return TRUE;
438 b3994ec5 2003-12-11 devnull }
439 b3994ec5 2003-12-11 devnull
440 b3994ec5 2003-12-11 devnull int
441 b3994ec5 2003-12-11 devnull p_cmd(Text *t, Cmd *cp)
442 b3994ec5 2003-12-11 devnull {
443 b3994ec5 2003-12-11 devnull USED(cp);
444 b3994ec5 2003-12-11 devnull return pdisplay(t->file);
445 b3994ec5 2003-12-11 devnull }
446 b3994ec5 2003-12-11 devnull
447 b3994ec5 2003-12-11 devnull int
448 b3994ec5 2003-12-11 devnull s_cmd(Text *t, Cmd *cp)
449 b3994ec5 2003-12-11 devnull {
450 b3994ec5 2003-12-11 devnull int i, j, k, c, m, n, nrp, didsub;
451 b3994ec5 2003-12-11 devnull long p1, op, delta;
452 b3994ec5 2003-12-11 devnull String *buf;
453 b3994ec5 2003-12-11 devnull Rangeset *rp;
454 b3994ec5 2003-12-11 devnull char *err;
455 b3994ec5 2003-12-11 devnull Rune *rbuf;
456 b3994ec5 2003-12-11 devnull
457 b3994ec5 2003-12-11 devnull n = cp->num;
458 b3994ec5 2003-12-11 devnull op= -1;
459 b3994ec5 2003-12-11 devnull if(rxcompile(cp->re->r) == FALSE)
460 b3994ec5 2003-12-11 devnull editerror("bad regexp in s command");
461 b3994ec5 2003-12-11 devnull nrp = 0;
462 b3994ec5 2003-12-11 devnull rp = nil;
463 b3994ec5 2003-12-11 devnull delta = 0;
464 b3994ec5 2003-12-11 devnull didsub = FALSE;
465 b3994ec5 2003-12-11 devnull for(p1 = addr.r.q0; p1<=addr.r.q1 && rxexecute(t, nil, p1, addr.r.q1, &sel); ){
466 b3994ec5 2003-12-11 devnull if(sel.r[0].q0 == sel.r[0].q1){ /* empty match? */
467 b3994ec5 2003-12-11 devnull if(sel.r[0].q0 == op){
468 b3994ec5 2003-12-11 devnull p1++;
469 b3994ec5 2003-12-11 devnull continue;
470 b3994ec5 2003-12-11 devnull }
471 b3994ec5 2003-12-11 devnull p1 = sel.r[0].q1+1;
472 b3994ec5 2003-12-11 devnull }else
473 b3994ec5 2003-12-11 devnull p1 = sel.r[0].q1;
474 b3994ec5 2003-12-11 devnull op = sel.r[0].q1;
475 b3994ec5 2003-12-11 devnull if(--n>0)
476 b3994ec5 2003-12-11 devnull continue;
477 b3994ec5 2003-12-11 devnull nrp++;
478 b3994ec5 2003-12-11 devnull rp = erealloc(rp, nrp*sizeof(Rangeset));
479 b3994ec5 2003-12-11 devnull rp[nrp-1] = sel;
480 b3994ec5 2003-12-11 devnull }
481 b3994ec5 2003-12-11 devnull rbuf = fbufalloc();
482 b3994ec5 2003-12-11 devnull buf = allocstring(0);
483 b3994ec5 2003-12-11 devnull for(m=0; m<nrp; m++){
484 b3994ec5 2003-12-11 devnull buf->n = 0;
485 bb0266fe 2005-05-07 devnull buf->r[0] = '\0';
486 b3994ec5 2003-12-11 devnull sel = rp[m];
487 b3994ec5 2003-12-11 devnull for(i = 0; i<cp->u.text->n; i++)
488 b3994ec5 2003-12-11 devnull if((c = cp->u.text->r[i])=='\\' && i<cp->u.text->n-1){
489 b3994ec5 2003-12-11 devnull c = cp->u.text->r[++i];
490 b3994ec5 2003-12-11 devnull if('1'<=c && c<='9') {
491 b3994ec5 2003-12-11 devnull j = c-'0';
492 b3994ec5 2003-12-11 devnull if(sel.r[j].q1-sel.r[j].q0>RBUFSIZE){
493 b3994ec5 2003-12-11 devnull err = "replacement string too long";
494 b3994ec5 2003-12-11 devnull goto Err;
495 b3994ec5 2003-12-11 devnull }
496 b3994ec5 2003-12-11 devnull bufread(&t->file->b, sel.r[j].q0, rbuf, sel.r[j].q1-sel.r[j].q0);
497 b3994ec5 2003-12-11 devnull for(k=0; k<sel.r[j].q1-sel.r[j].q0; k++)
498 b3994ec5 2003-12-11 devnull Straddc(buf, rbuf[k]);
499 b3994ec5 2003-12-11 devnull }else
500 b3994ec5 2003-12-11 devnull Straddc(buf, c);
501 b3994ec5 2003-12-11 devnull }else if(c!='&')
502 b3994ec5 2003-12-11 devnull Straddc(buf, c);
503 b3994ec5 2003-12-11 devnull else{
504 b3994ec5 2003-12-11 devnull if(sel.r[0].q1-sel.r[0].q0>RBUFSIZE){
505 b3994ec5 2003-12-11 devnull err = "right hand side too long in substitution";
506 b3994ec5 2003-12-11 devnull goto Err;
507 b3994ec5 2003-12-11 devnull }
508 b3994ec5 2003-12-11 devnull bufread(&t->file->b, sel.r[0].q0, rbuf, sel.r[0].q1-sel.r[0].q0);
509 b3994ec5 2003-12-11 devnull for(k=0; k<sel.r[0].q1-sel.r[0].q0; k++)
510 b3994ec5 2003-12-11 devnull Straddc(buf, rbuf[k]);
511 b3994ec5 2003-12-11 devnull }
512 b3994ec5 2003-12-11 devnull elogreplace(t->file, sel.r[0].q0, sel.r[0].q1, buf->r, buf->n);
513 b3994ec5 2003-12-11 devnull delta -= sel.r[0].q1-sel.r[0].q0;
514 b3994ec5 2003-12-11 devnull delta += buf->n;
515 b3994ec5 2003-12-11 devnull didsub = 1;
516 b3994ec5 2003-12-11 devnull if(!cp->flag)
517 b3994ec5 2003-12-11 devnull break;
518 b3994ec5 2003-12-11 devnull }
519 b3994ec5 2003-12-11 devnull free(rp);
520 b3994ec5 2003-12-11 devnull freestring(buf);
521 b3994ec5 2003-12-11 devnull fbuffree(rbuf);
522 b3994ec5 2003-12-11 devnull if(!didsub && nest==0)
523 b3994ec5 2003-12-11 devnull editerror("no substitution");
524 b3994ec5 2003-12-11 devnull t->q0 = addr.r.q0;
525 5e77b8bb 2005-03-23 devnull t->q1 = addr.r.q1;
526 b3994ec5 2003-12-11 devnull return TRUE;
527 b3994ec5 2003-12-11 devnull
528 b3994ec5 2003-12-11 devnull Err:
529 b3994ec5 2003-12-11 devnull free(rp);
530 b3994ec5 2003-12-11 devnull freestring(buf);
531 b3994ec5 2003-12-11 devnull fbuffree(rbuf);
532 b3994ec5 2003-12-11 devnull editerror(err);
533 b3994ec5 2003-12-11 devnull return FALSE;
534 b3994ec5 2003-12-11 devnull }
535 b3994ec5 2003-12-11 devnull
536 b3994ec5 2003-12-11 devnull int
537 b3994ec5 2003-12-11 devnull u_cmd(Text *t, Cmd *cp)
538 b3994ec5 2003-12-11 devnull {
539 b3994ec5 2003-12-11 devnull int n, oseq, flag;
540 b3994ec5 2003-12-11 devnull
541 b3994ec5 2003-12-11 devnull n = cp->num;
542 b3994ec5 2003-12-11 devnull flag = TRUE;
543 b3994ec5 2003-12-11 devnull if(n < 0){
544 b3994ec5 2003-12-11 devnull n = -n;
545 b3994ec5 2003-12-11 devnull flag = FALSE;
546 b3994ec5 2003-12-11 devnull }
547 b3994ec5 2003-12-11 devnull oseq = -1;
548 68a6e0c0 2010-01-12 rsc while(n-->0 && t->file->seq!=oseq){
549 b3994ec5 2003-12-11 devnull oseq = t->file->seq;
550 b3994ec5 2003-12-11 devnull undo(t, nil, nil, flag, 0, nil, 0);
551 b3994ec5 2003-12-11 devnull }
552 b3994ec5 2003-12-11 devnull return TRUE;
553 b3994ec5 2003-12-11 devnull }
554 b3994ec5 2003-12-11 devnull
555 b3994ec5 2003-12-11 devnull int
556 b3994ec5 2003-12-11 devnull w_cmd(Text *t, Cmd *cp)
557 b3994ec5 2003-12-11 devnull {
558 b3994ec5 2003-12-11 devnull Rune *r;
559 b3994ec5 2003-12-11 devnull File *f;
560 b3994ec5 2003-12-11 devnull
561 b3994ec5 2003-12-11 devnull f = t->file;
562 b3994ec5 2003-12-11 devnull if(f->seq == seq)
563 b3994ec5 2003-12-11 devnull editerror("can't write file with pending modifications");
564 b3994ec5 2003-12-11 devnull r = cmdname(f, cp->u.text, FALSE);
565 b3994ec5 2003-12-11 devnull if(r == nil)
566 b3994ec5 2003-12-11 devnull editerror("no name specified for 'w' command");
567 b3994ec5 2003-12-11 devnull putfile(f, addr.r.q0, addr.r.q1, r, runestrlen(r));
568 b3994ec5 2003-12-11 devnull /* r is freed by putfile */
569 b3994ec5 2003-12-11 devnull return TRUE;
570 b3994ec5 2003-12-11 devnull }
571 b3994ec5 2003-12-11 devnull
572 b3994ec5 2003-12-11 devnull int
573 b3994ec5 2003-12-11 devnull x_cmd(Text *t, Cmd *cp)
574 b3994ec5 2003-12-11 devnull {
575 b3994ec5 2003-12-11 devnull if(cp->re)
576 b3994ec5 2003-12-11 devnull looper(t->file, cp, cp->cmdc=='x');
577 b3994ec5 2003-12-11 devnull else
578 b3994ec5 2003-12-11 devnull linelooper(t->file, cp);
579 b3994ec5 2003-12-11 devnull return TRUE;
580 b3994ec5 2003-12-11 devnull }
581 b3994ec5 2003-12-11 devnull
582 b3994ec5 2003-12-11 devnull int
583 b3994ec5 2003-12-11 devnull X_cmd(Text *t, Cmd *cp)
584 b3994ec5 2003-12-11 devnull {
585 b3994ec5 2003-12-11 devnull USED(t);
586 b3994ec5 2003-12-11 devnull
587 d2df5d6c 2020-01-13 rsc filelooper(t, cp, cp->cmdc=='X');
588 b3994ec5 2003-12-11 devnull return TRUE;
589 b3994ec5 2003-12-11 devnull }
590 b3994ec5 2003-12-11 devnull
591 b3994ec5 2003-12-11 devnull void
592 b3994ec5 2003-12-11 devnull runpipe(Text *t, int cmd, Rune *cr, int ncr, int state)
593 b3994ec5 2003-12-11 devnull {
594 b3994ec5 2003-12-11 devnull Rune *r, *s;
595 b3994ec5 2003-12-11 devnull int n;
596 b3994ec5 2003-12-11 devnull Runestr dir;
597 b3994ec5 2003-12-11 devnull Window *w;
598 66301756 2006-05-05 devnull QLock *q;
599 b3994ec5 2003-12-11 devnull
600 b3994ec5 2003-12-11 devnull r = skipbl(cr, ncr, &n);
601 b3994ec5 2003-12-11 devnull if(n == 0)
602 5a8e63b2 2004-02-29 devnull editerror("no command specified for %c", cmd);
603 b3994ec5 2003-12-11 devnull w = nil;
604 b3994ec5 2003-12-11 devnull if(state == Inserting){
605 b3994ec5 2003-12-11 devnull w = t->w;
606 b3994ec5 2003-12-11 devnull t->q0 = addr.r.q0;
607 b3994ec5 2003-12-11 devnull t->q1 = addr.r.q1;
608 b3994ec5 2003-12-11 devnull if(cmd == '<' || cmd=='|')
609 b3994ec5 2003-12-11 devnull elogdelete(t->file, t->q0, t->q1);
610 b3994ec5 2003-12-11 devnull }
611 b3994ec5 2003-12-11 devnull s = runemalloc(n+2);
612 b3994ec5 2003-12-11 devnull s[0] = cmd;
613 b3994ec5 2003-12-11 devnull runemove(s+1, r, n);
614 b3994ec5 2003-12-11 devnull n++;
615 b3994ec5 2003-12-11 devnull dir.r = nil;
616 b3994ec5 2003-12-11 devnull dir.nr = 0;
617 b3994ec5 2003-12-11 devnull if(t != nil)
618 b3994ec5 2003-12-11 devnull dir = dirname(t, nil, 0);
619 b3994ec5 2003-12-11 devnull if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
620 b3994ec5 2003-12-11 devnull free(dir.r);
621 b3994ec5 2003-12-11 devnull dir.r = nil;
622 b3994ec5 2003-12-11 devnull dir.nr = 0;
623 b3994ec5 2003-12-11 devnull }
624 b3994ec5 2003-12-11 devnull editing = state;
625 b3994ec5 2003-12-11 devnull if(t!=nil && t->w!=nil)
626 b3994ec5 2003-12-11 devnull incref(&t->w->ref); /* run will decref */
627 b3994ec5 2003-12-11 devnull run(w, runetobyte(s, n), dir.r, dir.nr, TRUE, nil, nil, TRUE);
628 b3994ec5 2003-12-11 devnull free(s);
629 b3994ec5 2003-12-11 devnull if(t!=nil && t->w!=nil)
630 b3994ec5 2003-12-11 devnull winunlock(t->w);
631 b3994ec5 2003-12-11 devnull qunlock(&row.lk);
632 b3994ec5 2003-12-11 devnull recvul(cedit);
633 66301756 2006-05-05 devnull /*
634 66301756 2006-05-05 devnull * The editoutlk exists only so that we can tell when
635 66301756 2006-05-05 devnull * the editout file has been closed. It can get closed *after*
636 fa325e9b 2020-01-10 cross * the process exits because, since the process cannot be
637 fa325e9b 2020-01-10 cross * connected directly to editout (no 9P kernel support),
638 66301756 2006-05-05 devnull * the process is actually connected to a pipe to another
639 66301756 2006-05-05 devnull * process (arranged via 9pserve) that reads from the pipe
640 66301756 2006-05-05 devnull * and then writes the data in the pipe to editout using
641 66301756 2006-05-05 devnull * 9P transactions. This process might still have a couple
642 66301756 2006-05-05 devnull * writes left to copy after the original process has exited.
643 66301756 2006-05-05 devnull */
644 66301756 2006-05-05 devnull if(w)
645 66301756 2006-05-05 devnull q = &w->editoutlk;
646 66301756 2006-05-05 devnull else
647 66301756 2006-05-05 devnull q = &editoutlk;
648 66301756 2006-05-05 devnull qlock(q); /* wait for file to close */
649 66301756 2006-05-05 devnull qunlock(q);
650 b3994ec5 2003-12-11 devnull qlock(&row.lk);
651 b3994ec5 2003-12-11 devnull editing = Inactive;
652 b3994ec5 2003-12-11 devnull if(t!=nil && t->w!=nil)
653 b3994ec5 2003-12-11 devnull winlock(t->w, 'M');
654 b3994ec5 2003-12-11 devnull }
655 b3994ec5 2003-12-11 devnull
656 b3994ec5 2003-12-11 devnull int
657 b3994ec5 2003-12-11 devnull pipe_cmd(Text *t, Cmd *cp)
658 b3994ec5 2003-12-11 devnull {
659 b3994ec5 2003-12-11 devnull runpipe(t, cp->cmdc, cp->u.text->r, cp->u.text->n, Inserting);
660 b3994ec5 2003-12-11 devnull return TRUE;
661 b3994ec5 2003-12-11 devnull }
662 b3994ec5 2003-12-11 devnull
663 b3994ec5 2003-12-11 devnull long
664 3d6e5cb5 2017-11-02 rsc nlcount(Text *t, long q0, long q1, long *pnr)
665 b3994ec5 2003-12-11 devnull {
666 3d6e5cb5 2017-11-02 rsc long nl, start;
667 b3994ec5 2003-12-11 devnull Rune *buf;
668 b3994ec5 2003-12-11 devnull int i, nbuf;
669 b3994ec5 2003-12-11 devnull
670 b3994ec5 2003-12-11 devnull buf = fbufalloc();
671 b3994ec5 2003-12-11 devnull nbuf = 0;
672 b3994ec5 2003-12-11 devnull i = nl = 0;
673 3d6e5cb5 2017-11-02 rsc start = q0;
674 b3994ec5 2003-12-11 devnull while(q0 < q1){
675 b3994ec5 2003-12-11 devnull if(i == nbuf){
676 b3994ec5 2003-12-11 devnull nbuf = q1-q0;
677 b3994ec5 2003-12-11 devnull if(nbuf > RBUFSIZE)
678 b3994ec5 2003-12-11 devnull nbuf = RBUFSIZE;
679 b3994ec5 2003-12-11 devnull bufread(&t->file->b, q0, buf, nbuf);
680 b3994ec5 2003-12-11 devnull i = 0;
681 b3994ec5 2003-12-11 devnull }
682 3d6e5cb5 2017-11-02 rsc if(buf[i++] == '\n') {
683 3d6e5cb5 2017-11-02 rsc start = q0+1;
684 b3994ec5 2003-12-11 devnull nl++;
685 3d6e5cb5 2017-11-02 rsc }
686 b3994ec5 2003-12-11 devnull q0++;
687 b3994ec5 2003-12-11 devnull }
688 b3994ec5 2003-12-11 devnull fbuffree(buf);
689 3d6e5cb5 2017-11-02 rsc if(pnr != nil)
690 3d6e5cb5 2017-11-02 rsc *pnr = q0 - start;
691 b3994ec5 2003-12-11 devnull return nl;
692 b3994ec5 2003-12-11 devnull }
693 b3994ec5 2003-12-11 devnull
694 3d6e5cb5 2017-11-02 rsc enum {
695 3d6e5cb5 2017-11-02 rsc PosnLine = 0,
696 3d6e5cb5 2017-11-02 rsc PosnChars = 1,
697 3d6e5cb5 2017-11-02 rsc PosnLineChars = 2,
698 3d6e5cb5 2017-11-02 rsc };
699 3d6e5cb5 2017-11-02 rsc
700 3d6e5cb5 2017-11-02 rsc void
701 3d6e5cb5 2017-11-02 rsc printposn(Text *t, int mode)
702 b3994ec5 2003-12-11 devnull {
703 3d6e5cb5 2017-11-02 rsc long l1, l2, r1, r2;
704 b3994ec5 2003-12-11 devnull
705 b3994ec5 2003-12-11 devnull if (t != nil && t->file != nil && t->file->name != nil)
706 b3994ec5 2003-12-11 devnull warning(nil, "%.*S:", t->file->nname, t->file->name);
707 fa325e9b 2020-01-10 cross
708 3d6e5cb5 2017-11-02 rsc switch(mode) {
709 3d6e5cb5 2017-11-02 rsc case PosnChars:
710 3d6e5cb5 2017-11-02 rsc warning(nil, "#%d", addr.r.q0);
711 3d6e5cb5 2017-11-02 rsc if(addr.r.q1 != addr.r.q0)
712 3d6e5cb5 2017-11-02 rsc warning(nil, ",#%d", addr.r.q1);
713 3d6e5cb5 2017-11-02 rsc warning(nil, "\n");
714 3d6e5cb5 2017-11-02 rsc return;
715 fa325e9b 2020-01-10 cross
716 3d6e5cb5 2017-11-02 rsc default:
717 3d6e5cb5 2017-11-02 rsc case PosnLine:
718 3d6e5cb5 2017-11-02 rsc l1 = 1+nlcount(t, 0, addr.r.q0, nil);
719 3d6e5cb5 2017-11-02 rsc l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, nil);
720 b3994ec5 2003-12-11 devnull /* check if addr ends with '\n' */
721 b3994ec5 2003-12-11 devnull if(addr.r.q1>0 && addr.r.q1>addr.r.q0 && textreadc(t, addr.r.q1-1)=='\n')
722 b3994ec5 2003-12-11 devnull --l2;
723 b3994ec5 2003-12-11 devnull warning(nil, "%lud", l1);
724 b3994ec5 2003-12-11 devnull if(l2 != l1)
725 b3994ec5 2003-12-11 devnull warning(nil, ",%lud", l2);
726 b3994ec5 2003-12-11 devnull warning(nil, "\n");
727 b3994ec5 2003-12-11 devnull return;
728 3d6e5cb5 2017-11-02 rsc
729 3d6e5cb5 2017-11-02 rsc case PosnLineChars:
730 3d6e5cb5 2017-11-02 rsc l1 = 1+nlcount(t, 0, addr.r.q0, &r1);
731 3d6e5cb5 2017-11-02 rsc l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, &r2);
732 3d6e5cb5 2017-11-02 rsc if(l2 == l1)
733 3d6e5cb5 2017-11-02 rsc r2 += r1;
734 3d6e5cb5 2017-11-02 rsc warning(nil, "%lud+#%d", l1, r1);
735 3d6e5cb5 2017-11-02 rsc if(l2 != l1)
736 3d6e5cb5 2017-11-02 rsc warning(nil, ",%lud+#%d", l2, r2);
737 3d6e5cb5 2017-11-02 rsc warning(nil, "\n");
738 3d6e5cb5 2017-11-02 rsc return;
739 b3994ec5 2003-12-11 devnull }
740 b3994ec5 2003-12-11 devnull }
741 b3994ec5 2003-12-11 devnull
742 b3994ec5 2003-12-11 devnull int
743 b3994ec5 2003-12-11 devnull eq_cmd(Text *t, Cmd *cp)
744 b3994ec5 2003-12-11 devnull {
745 3d6e5cb5 2017-11-02 rsc int mode;
746 b3994ec5 2003-12-11 devnull
747 b3994ec5 2003-12-11 devnull switch(cp->u.text->n){
748 b3994ec5 2003-12-11 devnull case 0:
749 3d6e5cb5 2017-11-02 rsc mode = PosnLine;
750 b3994ec5 2003-12-11 devnull break;
751 b3994ec5 2003-12-11 devnull case 1:
752 b3994ec5 2003-12-11 devnull if(cp->u.text->r[0] == '#'){
753 3d6e5cb5 2017-11-02 rsc mode = PosnChars;
754 b3994ec5 2003-12-11 devnull break;
755 b3994ec5 2003-12-11 devnull }
756 3d6e5cb5 2017-11-02 rsc if(cp->u.text->r[0] == '+'){
757 3d6e5cb5 2017-11-02 rsc mode = PosnLineChars;
758 3d6e5cb5 2017-11-02 rsc break;
759 3d6e5cb5 2017-11-02 rsc }
760 b3994ec5 2003-12-11 devnull default:
761 3d6e5cb5 2017-11-02 rsc SET(mode);
762 b3994ec5 2003-12-11 devnull editerror("newline expected");
763 b3994ec5 2003-12-11 devnull }
764 3d6e5cb5 2017-11-02 rsc printposn(t, mode);
765 b3994ec5 2003-12-11 devnull return TRUE;
766 b3994ec5 2003-12-11 devnull }
767 b3994ec5 2003-12-11 devnull
768 b3994ec5 2003-12-11 devnull int
769 b3994ec5 2003-12-11 devnull nl_cmd(Text *t, Cmd *cp)
770 b3994ec5 2003-12-11 devnull {
771 b3994ec5 2003-12-11 devnull Address a;
772 b3994ec5 2003-12-11 devnull File *f;
773 b3994ec5 2003-12-11 devnull
774 b3994ec5 2003-12-11 devnull f = t->file;
775 b3994ec5 2003-12-11 devnull if(cp->addr == 0){
776 b3994ec5 2003-12-11 devnull /* First put it on newline boundaries */
777 b3994ec5 2003-12-11 devnull mkaddr(&a, f);
778 b3994ec5 2003-12-11 devnull addr = lineaddr(0, a, -1);
779 b3994ec5 2003-12-11 devnull a = lineaddr(0, a, 1);
780 b3994ec5 2003-12-11 devnull addr.r.q1 = a.r.q1;
781 b3994ec5 2003-12-11 devnull if(addr.r.q0==t->q0 && addr.r.q1==t->q1){
782 b3994ec5 2003-12-11 devnull mkaddr(&a, f);
783 b3994ec5 2003-12-11 devnull addr = lineaddr(1, a, 1);
784 b3994ec5 2003-12-11 devnull }
785 b3994ec5 2003-12-11 devnull }
786 b3994ec5 2003-12-11 devnull textshow(t, addr.r.q0, addr.r.q1, 1);
787 b3994ec5 2003-12-11 devnull return TRUE;
788 b3994ec5 2003-12-11 devnull }
789 b3994ec5 2003-12-11 devnull
790 b3994ec5 2003-12-11 devnull int
791 b3994ec5 2003-12-11 devnull append(File *f, Cmd *cp, long p)
792 b3994ec5 2003-12-11 devnull {
793 b3994ec5 2003-12-11 devnull if(cp->u.text->n > 0)
794 b3994ec5 2003-12-11 devnull eloginsert(f, p, cp->u.text->r, cp->u.text->n);
795 b3994ec5 2003-12-11 devnull f->curtext->q0 = p;
796 5e77b8bb 2005-03-23 devnull f->curtext->q1 = p;
797 b3994ec5 2003-12-11 devnull return TRUE;
798 b3994ec5 2003-12-11 devnull }
799 b3994ec5 2003-12-11 devnull
800 b3994ec5 2003-12-11 devnull int
801 b3994ec5 2003-12-11 devnull pdisplay(File *f)
802 b3994ec5 2003-12-11 devnull {
803 b3994ec5 2003-12-11 devnull long p1, p2;
804 b3994ec5 2003-12-11 devnull int np;
805 b3994ec5 2003-12-11 devnull Rune *buf;
806 b3994ec5 2003-12-11 devnull
807 b3994ec5 2003-12-11 devnull p1 = addr.r.q0;
808 b3994ec5 2003-12-11 devnull p2 = addr.r.q1;
809 b3994ec5 2003-12-11 devnull if(p2 > f->b.nc)
810 b3994ec5 2003-12-11 devnull p2 = f->b.nc;
811 b3994ec5 2003-12-11 devnull buf = fbufalloc();
812 b3994ec5 2003-12-11 devnull while(p1 < p2){
813 b3994ec5 2003-12-11 devnull np = p2-p1;
814 b3994ec5 2003-12-11 devnull if(np>RBUFSIZE-1)
815 b3994ec5 2003-12-11 devnull np = RBUFSIZE-1;
816 b3994ec5 2003-12-11 devnull bufread(&f->b, p1, buf, np);
817 bb0266fe 2005-05-07 devnull buf[np] = '\0';
818 b3994ec5 2003-12-11 devnull warning(nil, "%S", buf);
819 b3994ec5 2003-12-11 devnull p1 += np;
820 b3994ec5 2003-12-11 devnull }
821 b3994ec5 2003-12-11 devnull fbuffree(buf);
822 b3994ec5 2003-12-11 devnull f->curtext->q0 = addr.r.q0;
823 b3994ec5 2003-12-11 devnull f->curtext->q1 = addr.r.q1;
824 b3994ec5 2003-12-11 devnull return TRUE;
825 b3994ec5 2003-12-11 devnull }
826 b3994ec5 2003-12-11 devnull
827 b3994ec5 2003-12-11 devnull void
828 b3994ec5 2003-12-11 devnull pfilename(File *f)
829 b3994ec5 2003-12-11 devnull {
830 b3994ec5 2003-12-11 devnull int dirty;
831 b3994ec5 2003-12-11 devnull Window *w;
832 b3994ec5 2003-12-11 devnull
833 b3994ec5 2003-12-11 devnull w = f->curtext->w;
834 b3994ec5 2003-12-11 devnull /* same check for dirty as in settag, but we know ncache==0 */
835 b3994ec5 2003-12-11 devnull dirty = !w->isdir && !w->isscratch && f->mod;
836 b3994ec5 2003-12-11 devnull warning(nil, "%c%c%c %.*S\n", " '"[dirty],
837 b3994ec5 2003-12-11 devnull '+', " ."[curtext!=nil && curtext->file==f], f->nname, f->name);
838 b3994ec5 2003-12-11 devnull }
839 b3994ec5 2003-12-11 devnull
840 b3994ec5 2003-12-11 devnull void
841 b3994ec5 2003-12-11 devnull loopcmd(File *f, Cmd *cp, Range *rp, long nrp)
842 b3994ec5 2003-12-11 devnull {
843 b3994ec5 2003-12-11 devnull long i;
844 b3994ec5 2003-12-11 devnull
845 b3994ec5 2003-12-11 devnull for(i=0; i<nrp; i++){
846 b3994ec5 2003-12-11 devnull f->curtext->q0 = rp[i].q0;
847 b3994ec5 2003-12-11 devnull f->curtext->q1 = rp[i].q1;
848 b3994ec5 2003-12-11 devnull cmdexec(f->curtext, cp);
849 b3994ec5 2003-12-11 devnull }
850 b3994ec5 2003-12-11 devnull }
851 b3994ec5 2003-12-11 devnull
852 b3994ec5 2003-12-11 devnull void
853 b3994ec5 2003-12-11 devnull looper(File *f, Cmd *cp, int xy)
854 b3994ec5 2003-12-11 devnull {
855 b3994ec5 2003-12-11 devnull long p, op, nrp;
856 b3994ec5 2003-12-11 devnull Range r, tr;
857 b3994ec5 2003-12-11 devnull Range *rp;
858 b3994ec5 2003-12-11 devnull
859 b3994ec5 2003-12-11 devnull r = addr.r;
860 b3994ec5 2003-12-11 devnull op= xy? -1 : r.q0;
861 b3994ec5 2003-12-11 devnull nest++;
862 b3994ec5 2003-12-11 devnull if(rxcompile(cp->re->r) == FALSE)
863 b3994ec5 2003-12-11 devnull editerror("bad regexp in %c command", cp->cmdc);
864 b3994ec5 2003-12-11 devnull nrp = 0;
865 b3994ec5 2003-12-11 devnull rp = nil;
866 b3994ec5 2003-12-11 devnull for(p = r.q0; p<=r.q1; ){
867 b3994ec5 2003-12-11 devnull if(!rxexecute(f->curtext, nil, p, r.q1, &sel)){ /* no match, but y should still run */
868 b3994ec5 2003-12-11 devnull if(xy || op>r.q1)
869 b3994ec5 2003-12-11 devnull break;
870 b3994ec5 2003-12-11 devnull tr.q0 = op, tr.q1 = r.q1;
871 b3994ec5 2003-12-11 devnull p = r.q1+1; /* exit next loop */
872 b3994ec5 2003-12-11 devnull }else{
873 b3994ec5 2003-12-11 devnull if(sel.r[0].q0==sel.r[0].q1){ /* empty match? */
874 b3994ec5 2003-12-11 devnull if(sel.r[0].q0==op){
875 b3994ec5 2003-12-11 devnull p++;
876 b3994ec5 2003-12-11 devnull continue;
877 b3994ec5 2003-12-11 devnull }
878 b3994ec5 2003-12-11 devnull p = sel.r[0].q1+1;
879 b3994ec5 2003-12-11 devnull }else
880 b3994ec5 2003-12-11 devnull p = sel.r[0].q1;
881 b3994ec5 2003-12-11 devnull if(xy)
882 b3994ec5 2003-12-11 devnull tr = sel.r[0];
883 b3994ec5 2003-12-11 devnull else
884 b3994ec5 2003-12-11 devnull tr.q0 = op, tr.q1 = sel.r[0].q0;
885 b3994ec5 2003-12-11 devnull }
886 b3994ec5 2003-12-11 devnull op = sel.r[0].q1;
887 b3994ec5 2003-12-11 devnull nrp++;
888 b3994ec5 2003-12-11 devnull rp = erealloc(rp, nrp*sizeof(Range));
889 b3994ec5 2003-12-11 devnull rp[nrp-1] = tr;
890 b3994ec5 2003-12-11 devnull }
891 b3994ec5 2003-12-11 devnull loopcmd(f, cp->u.cmd, rp, nrp);
892 b3994ec5 2003-12-11 devnull free(rp);
893 b3994ec5 2003-12-11 devnull --nest;
894 b3994ec5 2003-12-11 devnull }
895 b3994ec5 2003-12-11 devnull
896 b3994ec5 2003-12-11 devnull void
897 b3994ec5 2003-12-11 devnull linelooper(File *f, Cmd *cp)
898 b3994ec5 2003-12-11 devnull {
899 b3994ec5 2003-12-11 devnull long nrp, p;
900 b3994ec5 2003-12-11 devnull Range r, linesel;
901 b3994ec5 2003-12-11 devnull Address a, a3;
902 b3994ec5 2003-12-11 devnull Range *rp;
903 b3994ec5 2003-12-11 devnull
904 b3994ec5 2003-12-11 devnull nest++;
905 b3994ec5 2003-12-11 devnull nrp = 0;
906 b3994ec5 2003-12-11 devnull rp = nil;
907 b3994ec5 2003-12-11 devnull r = addr.r;
908 b3994ec5 2003-12-11 devnull a3.f = f;
909 b3994ec5 2003-12-11 devnull a3.r.q0 = a3.r.q1 = r.q0;
910 b3994ec5 2003-12-11 devnull a = lineaddr(0, a3, 1);
911 b3994ec5 2003-12-11 devnull linesel = a.r;
912 b3994ec5 2003-12-11 devnull for(p = r.q0; p<r.q1; p = a3.r.q1){
913 b3994ec5 2003-12-11 devnull a3.r.q0 = a3.r.q1;
914 b3994ec5 2003-12-11 devnull if(p!=r.q0 || linesel.q1==p){
915 b3994ec5 2003-12-11 devnull a = lineaddr(1, a3, 1);
916 b3994ec5 2003-12-11 devnull linesel = a.r;
917 b3994ec5 2003-12-11 devnull }
918 b3994ec5 2003-12-11 devnull if(linesel.q0 >= r.q1)
919 b3994ec5 2003-12-11 devnull break;
920 b3994ec5 2003-12-11 devnull if(linesel.q1 >= r.q1)
921 b3994ec5 2003-12-11 devnull linesel.q1 = r.q1;
922 b3994ec5 2003-12-11 devnull if(linesel.q1 > linesel.q0)
923 b3994ec5 2003-12-11 devnull if(linesel.q0>=a3.r.q1 && linesel.q1>a3.r.q1){
924 b3994ec5 2003-12-11 devnull a3.r = linesel;
925 b3994ec5 2003-12-11 devnull nrp++;
926 b3994ec5 2003-12-11 devnull rp = erealloc(rp, nrp*sizeof(Range));
927 b3994ec5 2003-12-11 devnull rp[nrp-1] = linesel;
928 b3994ec5 2003-12-11 devnull continue;
929 b3994ec5 2003-12-11 devnull }
930 b3994ec5 2003-12-11 devnull break;
931 b3994ec5 2003-12-11 devnull }
932 b3994ec5 2003-12-11 devnull loopcmd(f, cp->u.cmd, rp, nrp);
933 b3994ec5 2003-12-11 devnull free(rp);
934 b3994ec5 2003-12-11 devnull --nest;
935 b3994ec5 2003-12-11 devnull }
936 b3994ec5 2003-12-11 devnull
937 b3994ec5 2003-12-11 devnull struct Looper
938 b3994ec5 2003-12-11 devnull {
939 b3994ec5 2003-12-11 devnull Cmd *cp;
940 b3994ec5 2003-12-11 devnull int XY;
941 b3994ec5 2003-12-11 devnull Window **w;
942 b3994ec5 2003-12-11 devnull int nw;
943 b3994ec5 2003-12-11 devnull } loopstruct; /* only one; X and Y can't nest */
944 b3994ec5 2003-12-11 devnull
945 b3994ec5 2003-12-11 devnull void
946 b3994ec5 2003-12-11 devnull alllooper(Window *w, void *v)
947 b3994ec5 2003-12-11 devnull {
948 b3994ec5 2003-12-11 devnull Text *t;
949 b3994ec5 2003-12-11 devnull struct Looper *lp;
950 b3994ec5 2003-12-11 devnull Cmd *cp;
951 b3994ec5 2003-12-11 devnull
952 b3994ec5 2003-12-11 devnull lp = v;
953 b3994ec5 2003-12-11 devnull cp = lp->cp;
954 cbeb0b26 2006-04-01 devnull /* if(w->isscratch || w->isdir) */
955 cbeb0b26 2006-04-01 devnull /* return; */
956 b3994ec5 2003-12-11 devnull t = &w->body;
957 b3994ec5 2003-12-11 devnull /* only use this window if it's the current window for the file */
958 b3994ec5 2003-12-11 devnull if(t->file->curtext != t)
959 b3994ec5 2003-12-11 devnull return;
960 cbeb0b26 2006-04-01 devnull /* if(w->nopen[QWevent] > 0) */
961 cbeb0b26 2006-04-01 devnull /* return; */
962 b3994ec5 2003-12-11 devnull /* no auto-execute on files without names */
963 b3994ec5 2003-12-11 devnull if(cp->re==nil && t->file->nname==0)
964 b3994ec5 2003-12-11 devnull return;
965 b3994ec5 2003-12-11 devnull if(cp->re==nil || filematch(t->file, cp->re)==lp->XY){
966 b3994ec5 2003-12-11 devnull lp->w = erealloc(lp->w, (lp->nw+1)*sizeof(Window*));
967 b3994ec5 2003-12-11 devnull lp->w[lp->nw++] = w;
968 b3994ec5 2003-12-11 devnull }
969 b3994ec5 2003-12-11 devnull }
970 b3994ec5 2003-12-11 devnull
971 b3994ec5 2003-12-11 devnull void
972 b3994ec5 2003-12-11 devnull alllocker(Window *w, void *v)
973 b3994ec5 2003-12-11 devnull {
974 b3994ec5 2003-12-11 devnull if(v)
975 b3994ec5 2003-12-11 devnull incref(&w->ref);
976 b3994ec5 2003-12-11 devnull else
977 b3994ec5 2003-12-11 devnull winclose(w);
978 b3994ec5 2003-12-11 devnull }
979 b3994ec5 2003-12-11 devnull
980 b3994ec5 2003-12-11 devnull void
981 d2df5d6c 2020-01-13 rsc filelooper(Text *t, Cmd *cp, int XY)
982 b3994ec5 2003-12-11 devnull {
983 b3994ec5 2003-12-11 devnull int i;
984 d2df5d6c 2020-01-13 rsc Text *targ;
985 b3994ec5 2003-12-11 devnull
986 b3994ec5 2003-12-11 devnull if(Glooping++)
987 b3994ec5 2003-12-11 devnull editerror("can't nest %c command", "YX"[XY]);
988 b3994ec5 2003-12-11 devnull nest++;
989 b3994ec5 2003-12-11 devnull
990 b3994ec5 2003-12-11 devnull loopstruct.cp = cp;
991 b3994ec5 2003-12-11 devnull loopstruct.XY = XY;
992 b3994ec5 2003-12-11 devnull if(loopstruct.w) /* error'ed out last time */
993 b3994ec5 2003-12-11 devnull free(loopstruct.w);
994 b3994ec5 2003-12-11 devnull loopstruct.w = nil;
995 b3994ec5 2003-12-11 devnull loopstruct.nw = 0;
996 b3994ec5 2003-12-11 devnull allwindows(alllooper, &loopstruct);
997 b3994ec5 2003-12-11 devnull /*
998 b3994ec5 2003-12-11 devnull * add a ref to all windows to keep safe windows accessed by X
999 b3994ec5 2003-12-11 devnull * that would not otherwise have a ref to hold them up during
1000 5a8e63b2 2004-02-29 devnull * the shenanigans. note this with globalincref so that any
1001 5a8e63b2 2004-02-29 devnull * newly created windows start with an extra reference.
1002 b3994ec5 2003-12-11 devnull */
1003 b3994ec5 2003-12-11 devnull allwindows(alllocker, (void*)1);
1004 5a8e63b2 2004-02-29 devnull globalincref = 1;
1005 d2df5d6c 2020-01-13 rsc
1006 d2df5d6c 2020-01-13 rsc /*
1007 d2df5d6c 2020-01-13 rsc * Unlock the window running the X command.
1008 d2df5d6c 2020-01-13 rsc * We'll need to lock and unlock each target window in turn.
1009 d2df5d6c 2020-01-13 rsc */
1010 d2df5d6c 2020-01-13 rsc if(t && t->w)
1011 d2df5d6c 2020-01-13 rsc winunlock(t->w);
1012 d2df5d6c 2020-01-13 rsc
1013 d2df5d6c 2020-01-13 rsc for(i=0; i<loopstruct.nw; i++) {
1014 d2df5d6c 2020-01-13 rsc targ = &loopstruct.w[i]->body;
1015 d2df5d6c 2020-01-13 rsc if(targ && targ->w)
1016 d2df5d6c 2020-01-13 rsc winlock(targ->w, cp->cmdc);
1017 d2df5d6c 2020-01-13 rsc cmdexec(targ, cp->u.cmd);
1018 d2df5d6c 2020-01-13 rsc if(targ && targ->w)
1019 d2df5d6c 2020-01-13 rsc winunlock(targ->w);
1020 d2df5d6c 2020-01-13 rsc }
1021 d2df5d6c 2020-01-13 rsc
1022 d2df5d6c 2020-01-13 rsc if(t && t->w)
1023 d2df5d6c 2020-01-13 rsc winlock(t->w, cp->cmdc);
1024 d2df5d6c 2020-01-13 rsc
1025 b3994ec5 2003-12-11 devnull allwindows(alllocker, (void*)0);
1026 5a8e63b2 2004-02-29 devnull globalincref = 0;
1027 b3994ec5 2003-12-11 devnull free(loopstruct.w);
1028 b3994ec5 2003-12-11 devnull loopstruct.w = nil;
1029 b3994ec5 2003-12-11 devnull
1030 b3994ec5 2003-12-11 devnull --Glooping;
1031 b3994ec5 2003-12-11 devnull --nest;
1032 b3994ec5 2003-12-11 devnull }
1033 b3994ec5 2003-12-11 devnull
1034 b3994ec5 2003-12-11 devnull void
1035 b3994ec5 2003-12-11 devnull nextmatch(File *f, String *r, long p, int sign)
1036 b3994ec5 2003-12-11 devnull {
1037 b3994ec5 2003-12-11 devnull if(rxcompile(r->r) == FALSE)
1038 b3994ec5 2003-12-11 devnull editerror("bad regexp in command address");
1039 b3994ec5 2003-12-11 devnull if(sign >= 0){
1040 b3994ec5 2003-12-11 devnull if(!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel))
1041 b3994ec5 2003-12-11 devnull editerror("no match for regexp");
1042 b3994ec5 2003-12-11 devnull if(sel.r[0].q0==sel.r[0].q1 && sel.r[0].q0==p){
1043 b3994ec5 2003-12-11 devnull if(++p>f->b.nc)
1044 b3994ec5 2003-12-11 devnull p = 0;
1045 b3994ec5 2003-12-11 devnull if(!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel))
1046 b3994ec5 2003-12-11 devnull editerror("address");
1047 b3994ec5 2003-12-11 devnull }
1048 b3994ec5 2003-12-11 devnull }else{
1049 b3994ec5 2003-12-11 devnull if(!rxbexecute(f->curtext, p, &sel))
1050 b3994ec5 2003-12-11 devnull editerror("no match for regexp");
1051 b3994ec5 2003-12-11 devnull if(sel.r[0].q0==sel.r[0].q1 && sel.r[0].q1==p){
1052 b3994ec5 2003-12-11 devnull if(--p<0)
1053 b3994ec5 2003-12-11 devnull p = f->b.nc;
1054 b3994ec5 2003-12-11 devnull if(!rxbexecute(f->curtext, p, &sel))
1055 b3994ec5 2003-12-11 devnull editerror("address");
1056 b3994ec5 2003-12-11 devnull }
1057 b3994ec5 2003-12-11 devnull }
1058 b3994ec5 2003-12-11 devnull }
1059 b3994ec5 2003-12-11 devnull
1060 b3994ec5 2003-12-11 devnull File *matchfile(String*);
1061 b3994ec5 2003-12-11 devnull Address charaddr(long, Address, int);
1062 b3994ec5 2003-12-11 devnull Address lineaddr(long, Address, int);
1063 b3994ec5 2003-12-11 devnull
1064 b3994ec5 2003-12-11 devnull Address
1065 b3994ec5 2003-12-11 devnull cmdaddress(Addr *ap, Address a, int sign)
1066 b3994ec5 2003-12-11 devnull {
1067 b3994ec5 2003-12-11 devnull File *f = a.f;
1068 b3994ec5 2003-12-11 devnull Address a1, a2;
1069 b3994ec5 2003-12-11 devnull
1070 b3994ec5 2003-12-11 devnull do{
1071 b3994ec5 2003-12-11 devnull switch(ap->type){
1072 b3994ec5 2003-12-11 devnull case 'l':
1073 b3994ec5 2003-12-11 devnull case '#':
1074 b3994ec5 2003-12-11 devnull a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num, a, sign);
1075 b3994ec5 2003-12-11 devnull break;
1076 b3994ec5 2003-12-11 devnull
1077 b3994ec5 2003-12-11 devnull case '.':
1078 b3994ec5 2003-12-11 devnull mkaddr(&a, f);
1079 b3994ec5 2003-12-11 devnull break;
1080 b3994ec5 2003-12-11 devnull
1081 b3994ec5 2003-12-11 devnull case '$':
1082 b3994ec5 2003-12-11 devnull a.r.q0 = a.r.q1 = f->b.nc;
1083 b3994ec5 2003-12-11 devnull break;
1084 b3994ec5 2003-12-11 devnull
1085 b3994ec5 2003-12-11 devnull case '\'':
1086 b3994ec5 2003-12-11 devnull editerror("can't handle '");
1087 cbeb0b26 2006-04-01 devnull /* a.r = f->mark; */
1088 b3994ec5 2003-12-11 devnull break;
1089 b3994ec5 2003-12-11 devnull
1090 b3994ec5 2003-12-11 devnull case '?':
1091 b3994ec5 2003-12-11 devnull sign = -sign;
1092 b3994ec5 2003-12-11 devnull if(sign == 0)
1093 b3994ec5 2003-12-11 devnull sign = -1;
1094 b3994ec5 2003-12-11 devnull /* fall through */
1095 b3994ec5 2003-12-11 devnull case '/':
1096 b3994ec5 2003-12-11 devnull nextmatch(f, ap->u.re, sign>=0? a.r.q1 : a.r.q0, sign);
1097 b3994ec5 2003-12-11 devnull a.r = sel.r[0];
1098 b3994ec5 2003-12-11 devnull break;
1099 b3994ec5 2003-12-11 devnull
1100 b3994ec5 2003-12-11 devnull case '"':
1101 b3994ec5 2003-12-11 devnull f = matchfile(ap->u.re);
1102 b3994ec5 2003-12-11 devnull mkaddr(&a, f);
1103 b3994ec5 2003-12-11 devnull break;
1104 b3994ec5 2003-12-11 devnull
1105 b3994ec5 2003-12-11 devnull case '*':
1106 b3994ec5 2003-12-11 devnull a.r.q0 = 0, a.r.q1 = f->b.nc;
1107 b3994ec5 2003-12-11 devnull return a;
1108 b3994ec5 2003-12-11 devnull
1109 b3994ec5 2003-12-11 devnull case ',':
1110 b3994ec5 2003-12-11 devnull case ';':
1111 b3994ec5 2003-12-11 devnull if(ap->u.left)
1112 b3994ec5 2003-12-11 devnull a1 = cmdaddress(ap->u.left, a, 0);
1113 b3994ec5 2003-12-11 devnull else
1114 b3994ec5 2003-12-11 devnull a1.f = a.f, a1.r.q0 = a1.r.q1 = 0;
1115 b3994ec5 2003-12-11 devnull if(ap->type == ';'){
1116 b3994ec5 2003-12-11 devnull f = a1.f;
1117 b3994ec5 2003-12-11 devnull a = a1;
1118 b3994ec5 2003-12-11 devnull f->curtext->q0 = a1.r.q0;
1119 b3994ec5 2003-12-11 devnull f->curtext->q1 = a1.r.q1;
1120 b3994ec5 2003-12-11 devnull }
1121 b3994ec5 2003-12-11 devnull if(ap->next)
1122 b3994ec5 2003-12-11 devnull a2 = cmdaddress(ap->next, a, 0);
1123 b3994ec5 2003-12-11 devnull else
1124 b3994ec5 2003-12-11 devnull a2.f = a.f, a2.r.q0 = a2.r.q1 = f->b.nc;
1125 b3994ec5 2003-12-11 devnull if(a1.f != a2.f)
1126 b3994ec5 2003-12-11 devnull editerror("addresses in different files");
1127 b3994ec5 2003-12-11 devnull a.f = a1.f, a.r.q0 = a1.r.q0, a.r.q1 = a2.r.q1;
1128 b3994ec5 2003-12-11 devnull if(a.r.q1 < a.r.q0)
1129 b3994ec5 2003-12-11 devnull editerror("addresses out of order");
1130 b3994ec5 2003-12-11 devnull return a;
1131 b3994ec5 2003-12-11 devnull
1132 b3994ec5 2003-12-11 devnull case '+':
1133 b3994ec5 2003-12-11 devnull case '-':
1134 b3994ec5 2003-12-11 devnull sign = 1;
1135 b3994ec5 2003-12-11 devnull if(ap->type == '-')
1136 b3994ec5 2003-12-11 devnull sign = -1;
1137 b3994ec5 2003-12-11 devnull if(ap->next==0 || ap->next->type=='+' || ap->next->type=='-')
1138 b3994ec5 2003-12-11 devnull a = lineaddr(1L, a, sign);
1139 b3994ec5 2003-12-11 devnull break;
1140 b3994ec5 2003-12-11 devnull default:
1141 b3994ec5 2003-12-11 devnull error("cmdaddress");
1142 b3994ec5 2003-12-11 devnull return a;
1143 b3994ec5 2003-12-11 devnull }
1144 b3994ec5 2003-12-11 devnull }while(ap = ap->next); /* assign = */
1145 b3994ec5 2003-12-11 devnull return a;
1146 b3994ec5 2003-12-11 devnull }
1147 b3994ec5 2003-12-11 devnull
1148 b3994ec5 2003-12-11 devnull struct Tofile{
1149 b3994ec5 2003-12-11 devnull File *f;
1150 b3994ec5 2003-12-11 devnull String *r;
1151 b3994ec5 2003-12-11 devnull };
1152 b3994ec5 2003-12-11 devnull
1153 b3994ec5 2003-12-11 devnull void
1154 b3994ec5 2003-12-11 devnull alltofile(Window *w, void *v)
1155 b3994ec5 2003-12-11 devnull {
1156 b3994ec5 2003-12-11 devnull Text *t;
1157 b3994ec5 2003-12-11 devnull struct Tofile *tp;
1158 b3994ec5 2003-12-11 devnull
1159 b3994ec5 2003-12-11 devnull tp = v;
1160 b3994ec5 2003-12-11 devnull if(tp->f != nil)
1161 b3994ec5 2003-12-11 devnull return;
1162 b3994ec5 2003-12-11 devnull if(w->isscratch || w->isdir)
1163 b3994ec5 2003-12-11 devnull return;
1164 b3994ec5 2003-12-11 devnull t = &w->body;
1165 b3994ec5 2003-12-11 devnull /* only use this window if it's the current window for the file */
1166 b3994ec5 2003-12-11 devnull if(t->file->curtext != t)
1167 b3994ec5 2003-12-11 devnull return;
1168 cbeb0b26 2006-04-01 devnull /* if(w->nopen[QWevent] > 0) */
1169 cbeb0b26 2006-04-01 devnull /* return; */
1170 b3994ec5 2003-12-11 devnull if(runeeq(tp->r->r, tp->r->n, t->file->name, t->file->nname))
1171 b3994ec5 2003-12-11 devnull tp->f = t->file;
1172 b3994ec5 2003-12-11 devnull }
1173 b3994ec5 2003-12-11 devnull
1174 b3994ec5 2003-12-11 devnull File*
1175 b3994ec5 2003-12-11 devnull tofile(String *r)
1176 b3994ec5 2003-12-11 devnull {
1177 b3994ec5 2003-12-11 devnull struct Tofile t;
1178 b3994ec5 2003-12-11 devnull String rr;
1179 b3994ec5 2003-12-11 devnull
1180 b3994ec5 2003-12-11 devnull rr.r = skipbl(r->r, r->n, &rr.n);
1181 b3994ec5 2003-12-11 devnull t.f = nil;
1182 b3994ec5 2003-12-11 devnull t.r = &rr;
1183 b3994ec5 2003-12-11 devnull allwindows(alltofile, &t);
1184 b3994ec5 2003-12-11 devnull if(t.f == nil)
1185 b3994ec5 2003-12-11 devnull editerror("no such file\"%S\"", rr.r);
1186 b3994ec5 2003-12-11 devnull return t.f;
1187 b3994ec5 2003-12-11 devnull }
1188 b3994ec5 2003-12-11 devnull
1189 b3994ec5 2003-12-11 devnull void
1190 b3994ec5 2003-12-11 devnull allmatchfile(Window *w, void *v)
1191 b3994ec5 2003-12-11 devnull {
1192 b3994ec5 2003-12-11 devnull struct Tofile *tp;
1193 b3994ec5 2003-12-11 devnull Text *t;
1194 b3994ec5 2003-12-11 devnull
1195 b3994ec5 2003-12-11 devnull tp = v;
1196 b3994ec5 2003-12-11 devnull if(w->isscratch || w->isdir)
1197 b3994ec5 2003-12-11 devnull return;
1198 b3994ec5 2003-12-11 devnull t = &w->body;
1199 b3994ec5 2003-12-11 devnull /* only use this window if it's the current window for the file */
1200 b3994ec5 2003-12-11 devnull if(t->file->curtext != t)
1201 b3994ec5 2003-12-11 devnull return;
1202 cbeb0b26 2006-04-01 devnull /* if(w->nopen[QWevent] > 0) */
1203 cbeb0b26 2006-04-01 devnull /* return; */
1204 b3994ec5 2003-12-11 devnull if(filematch(w->body.file, tp->r)){
1205 b3994ec5 2003-12-11 devnull if(tp->f != nil)
1206 b3994ec5 2003-12-11 devnull editerror("too many files match \"%S\"", tp->r->r);
1207 b3994ec5 2003-12-11 devnull tp->f = w->body.file;
1208 b3994ec5 2003-12-11 devnull }
1209 b3994ec5 2003-12-11 devnull }
1210 b3994ec5 2003-12-11 devnull
1211 b3994ec5 2003-12-11 devnull File*
1212 b3994ec5 2003-12-11 devnull matchfile(String *r)
1213 b3994ec5 2003-12-11 devnull {
1214 b3994ec5 2003-12-11 devnull struct Tofile tf;
1215 b3994ec5 2003-12-11 devnull
1216 b3994ec5 2003-12-11 devnull tf.f = nil;
1217 b3994ec5 2003-12-11 devnull tf.r = r;
1218 b3994ec5 2003-12-11 devnull allwindows(allmatchfile, &tf);
1219 b3994ec5 2003-12-11 devnull
1220 b3994ec5 2003-12-11 devnull if(tf.f == nil)
1221 b3994ec5 2003-12-11 devnull editerror("no file matches \"%S\"", r->r);
1222 b3994ec5 2003-12-11 devnull return tf.f;
1223 b3994ec5 2003-12-11 devnull }
1224 b3994ec5 2003-12-11 devnull
1225 b3994ec5 2003-12-11 devnull int
1226 b3994ec5 2003-12-11 devnull filematch(File *f, String *r)
1227 b3994ec5 2003-12-11 devnull {
1228 b3994ec5 2003-12-11 devnull char *buf;
1229 b3994ec5 2003-12-11 devnull Rune *rbuf;
1230 b3994ec5 2003-12-11 devnull Window *w;
1231 b3994ec5 2003-12-11 devnull int match, i, dirty;
1232 b3994ec5 2003-12-11 devnull Rangeset s;
1233 b3994ec5 2003-12-11 devnull
1234 b3994ec5 2003-12-11 devnull /* compile expr first so if we get an error, we haven't allocated anything */
1235 b3994ec5 2003-12-11 devnull if(rxcompile(r->r) == FALSE)
1236 b3994ec5 2003-12-11 devnull editerror("bad regexp in file match");
1237 b3994ec5 2003-12-11 devnull buf = fbufalloc();
1238 b3994ec5 2003-12-11 devnull w = f->curtext->w;
1239 b3994ec5 2003-12-11 devnull /* same check for dirty as in settag, but we know ncache==0 */
1240 b3994ec5 2003-12-11 devnull dirty = !w->isdir && !w->isscratch && f->mod;
1241 b3994ec5 2003-12-11 devnull snprint(buf, BUFSIZE, "%c%c%c %.*S\n", " '"[dirty],
1242 b3994ec5 2003-12-11 devnull '+', " ."[curtext!=nil && curtext->file==f], f->nname, f->name);
1243 b3994ec5 2003-12-11 devnull rbuf = bytetorune(buf, &i);
1244 b3994ec5 2003-12-11 devnull fbuffree(buf);
1245 b3994ec5 2003-12-11 devnull match = rxexecute(nil, rbuf, 0, i, &s);
1246 b3994ec5 2003-12-11 devnull free(rbuf);
1247 b3994ec5 2003-12-11 devnull return match;
1248 b3994ec5 2003-12-11 devnull }
1249 b3994ec5 2003-12-11 devnull
1250 b3994ec5 2003-12-11 devnull Address
1251 b3994ec5 2003-12-11 devnull charaddr(long l, Address addr, int sign)
1252 b3994ec5 2003-12-11 devnull {
1253 b3994ec5 2003-12-11 devnull if(sign == 0)
1254 b3994ec5 2003-12-11 devnull addr.r.q0 = addr.r.q1 = l;
1255 b3994ec5 2003-12-11 devnull else if(sign < 0)
1256 b3994ec5 2003-12-11 devnull addr.r.q1 = addr.r.q0 -= l;
1257 b3994ec5 2003-12-11 devnull else if(sign > 0)
1258 b3994ec5 2003-12-11 devnull addr.r.q0 = addr.r.q1 += l;
1259 b3994ec5 2003-12-11 devnull if(addr.r.q0<0 || addr.r.q1>addr.f->b.nc)
1260 b3994ec5 2003-12-11 devnull editerror("address out of range");
1261 b3994ec5 2003-12-11 devnull return addr;
1262 b3994ec5 2003-12-11 devnull }
1263 b3994ec5 2003-12-11 devnull
1264 b3994ec5 2003-12-11 devnull Address
1265 b3994ec5 2003-12-11 devnull lineaddr(long l, Address addr, int sign)
1266 b3994ec5 2003-12-11 devnull {
1267 b3994ec5 2003-12-11 devnull int n;
1268 b3994ec5 2003-12-11 devnull int c;
1269 b3994ec5 2003-12-11 devnull File *f = addr.f;
1270 b3994ec5 2003-12-11 devnull Address a;
1271 b3994ec5 2003-12-11 devnull long p;
1272 b3994ec5 2003-12-11 devnull
1273 b3994ec5 2003-12-11 devnull a.f = f;
1274 b3994ec5 2003-12-11 devnull if(sign >= 0){
1275 b3994ec5 2003-12-11 devnull if(l == 0){
1276 b3994ec5 2003-12-11 devnull if(sign==0 || addr.r.q1==0){
1277 b3994ec5 2003-12-11 devnull a.r.q0 = a.r.q1 = 0;
1278 b3994ec5 2003-12-11 devnull return a;
1279 b3994ec5 2003-12-11 devnull }
1280 b3994ec5 2003-12-11 devnull a.r.q0 = addr.r.q1;
1281 b3994ec5 2003-12-11 devnull p = addr.r.q1-1;
1282 b3994ec5 2003-12-11 devnull }else{
1283 b3994ec5 2003-12-11 devnull if(sign==0 || addr.r.q1==0){
1284 b3994ec5 2003-12-11 devnull p = 0;
1285 b3994ec5 2003-12-11 devnull n = 1;
1286 b3994ec5 2003-12-11 devnull }else{
1287 b3994ec5 2003-12-11 devnull p = addr.r.q1-1;
1288 b3994ec5 2003-12-11 devnull n = textreadc(f->curtext, p++)=='\n';
1289 b3994ec5 2003-12-11 devnull }
1290 b3994ec5 2003-12-11 devnull while(n < l){
1291 b3994ec5 2003-12-11 devnull if(p >= f->b.nc)
1292 b3994ec5 2003-12-11 devnull editerror("address out of range");
1293 b3994ec5 2003-12-11 devnull if(textreadc(f->curtext, p++) == '\n')
1294 b3994ec5 2003-12-11 devnull n++;
1295 b3994ec5 2003-12-11 devnull }
1296 b3994ec5 2003-12-11 devnull a.r.q0 = p;
1297 b3994ec5 2003-12-11 devnull }
1298 b3994ec5 2003-12-11 devnull while(p < f->b.nc && textreadc(f->curtext, p++)!='\n')
1299 b3994ec5 2003-12-11 devnull ;
1300 b3994ec5 2003-12-11 devnull a.r.q1 = p;
1301 b3994ec5 2003-12-11 devnull }else{
1302 b3994ec5 2003-12-11 devnull p = addr.r.q0;
1303 b3994ec5 2003-12-11 devnull if(l == 0)
1304 b3994ec5 2003-12-11 devnull a.r.q1 = addr.r.q0;
1305 b3994ec5 2003-12-11 devnull else{
1306 b3994ec5 2003-12-11 devnull for(n = 0; n<l; ){ /* always runs once */
1307 b3994ec5 2003-12-11 devnull if(p == 0){
1308 b3994ec5 2003-12-11 devnull if(++n != l)
1309 b3994ec5 2003-12-11 devnull editerror("address out of range");
1310 b3994ec5 2003-12-11 devnull }else{
1311 b3994ec5 2003-12-11 devnull c = textreadc(f->curtext, p-1);
1312 b3994ec5 2003-12-11 devnull if(c != '\n' || ++n != l)
1313 b3994ec5 2003-12-11 devnull p--;
1314 b3994ec5 2003-12-11 devnull }
1315 b3994ec5 2003-12-11 devnull }
1316 b3994ec5 2003-12-11 devnull a.r.q1 = p;
1317 b3994ec5 2003-12-11 devnull if(p > 0)
1318 b3994ec5 2003-12-11 devnull p--;
1319 b3994ec5 2003-12-11 devnull }
1320 b3994ec5 2003-12-11 devnull while(p > 0 && textreadc(f->curtext, p-1)!='\n') /* lines start after a newline */
1321 b3994ec5 2003-12-11 devnull p--;
1322 b3994ec5 2003-12-11 devnull a.r.q0 = p;
1323 b3994ec5 2003-12-11 devnull }
1324 b3994ec5 2003-12-11 devnull return a;
1325 b3994ec5 2003-12-11 devnull }
1326 b3994ec5 2003-12-11 devnull
1327 b3994ec5 2003-12-11 devnull struct Filecheck
1328 b3994ec5 2003-12-11 devnull {
1329 b3994ec5 2003-12-11 devnull File *f;
1330 b3994ec5 2003-12-11 devnull Rune *r;
1331 b3994ec5 2003-12-11 devnull int nr;
1332 b3994ec5 2003-12-11 devnull };
1333 b3994ec5 2003-12-11 devnull
1334 b3994ec5 2003-12-11 devnull void
1335 b3994ec5 2003-12-11 devnull allfilecheck(Window *w, void *v)
1336 b3994ec5 2003-12-11 devnull {
1337 b3994ec5 2003-12-11 devnull struct Filecheck *fp;
1338 b3994ec5 2003-12-11 devnull File *f;
1339 b3994ec5 2003-12-11 devnull
1340 b3994ec5 2003-12-11 devnull fp = v;
1341 b3994ec5 2003-12-11 devnull f = w->body.file;
1342 b3994ec5 2003-12-11 devnull if(w->body.file == fp->f)
1343 b3994ec5 2003-12-11 devnull return;
1344 b3994ec5 2003-12-11 devnull if(runeeq(fp->r, fp->nr, f->name, f->nname))
1345 b3994ec5 2003-12-11 devnull warning(nil, "warning: duplicate file name \"%.*S\"\n", fp->nr, fp->r);
1346 b3994ec5 2003-12-11 devnull }
1347 b3994ec5 2003-12-11 devnull
1348 b3994ec5 2003-12-11 devnull Rune*
1349 b3994ec5 2003-12-11 devnull cmdname(File *f, String *str, int set)
1350 b3994ec5 2003-12-11 devnull {
1351 b3994ec5 2003-12-11 devnull Rune *r, *s;
1352 b3994ec5 2003-12-11 devnull int n;
1353 b3994ec5 2003-12-11 devnull struct Filecheck fc;
1354 b3994ec5 2003-12-11 devnull Runestr newname;
1355 b3994ec5 2003-12-11 devnull
1356 b3994ec5 2003-12-11 devnull r = nil;
1357 b3994ec5 2003-12-11 devnull n = str->n;
1358 b3994ec5 2003-12-11 devnull s = str->r;
1359 b3994ec5 2003-12-11 devnull if(n == 0){
1360 b3994ec5 2003-12-11 devnull /* no name; use existing */
1361 b3994ec5 2003-12-11 devnull if(f->nname == 0)
1362 b3994ec5 2003-12-11 devnull return nil;
1363 b3994ec5 2003-12-11 devnull r = runemalloc(f->nname+1);
1364 b3994ec5 2003-12-11 devnull runemove(r, f->name, f->nname);
1365 b3994ec5 2003-12-11 devnull return r;
1366 b3994ec5 2003-12-11 devnull }
1367 b3994ec5 2003-12-11 devnull s = skipbl(s, n, &n);
1368 b3994ec5 2003-12-11 devnull if(n == 0)
1369 b3994ec5 2003-12-11 devnull goto Return;
1370 b3994ec5 2003-12-11 devnull
1371 b3994ec5 2003-12-11 devnull if(s[0] == '/'){
1372 b3994ec5 2003-12-11 devnull r = runemalloc(n+1);
1373 b3994ec5 2003-12-11 devnull runemove(r, s, n);
1374 b3994ec5 2003-12-11 devnull }else{
1375 b3994ec5 2003-12-11 devnull newname = dirname(f->curtext, runestrdup(s), n);
1376 b3994ec5 2003-12-11 devnull n = newname.nr;
1377 734a96bd 2008-03-07 rsc r = runemalloc(n+1); /* NUL terminate */
1378 5e77b8bb 2005-03-23 devnull runemove(r, newname.r, n);
1379 5e77b8bb 2005-03-23 devnull free(newname.r);
1380 b3994ec5 2003-12-11 devnull }
1381 b3994ec5 2003-12-11 devnull fc.f = f;
1382 b3994ec5 2003-12-11 devnull fc.r = r;
1383 b3994ec5 2003-12-11 devnull fc.nr = n;
1384 b3994ec5 2003-12-11 devnull allwindows(allfilecheck, &fc);
1385 b3994ec5 2003-12-11 devnull if(f->nname == 0)
1386 b3994ec5 2003-12-11 devnull set = TRUE;
1387 b3994ec5 2003-12-11 devnull
1388 b3994ec5 2003-12-11 devnull Return:
1389 b3994ec5 2003-12-11 devnull if(set && !runeeq(r, n, f->name, f->nname)){
1390 b3994ec5 2003-12-11 devnull filemark(f);
1391 b3994ec5 2003-12-11 devnull f->mod = TRUE;
1392 b3994ec5 2003-12-11 devnull f->curtext->w->dirty = TRUE;
1393 b3994ec5 2003-12-11 devnull winsetname(f->curtext->w, r, n);
1394 b3994ec5 2003-12-11 devnull }
1395 b3994ec5 2003-12-11 devnull return r;
1396 b3994ec5 2003-12-11 devnull }