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 b3994ec5 2003-12-11 devnull #include "dat.h"
12 b3994ec5 2003-12-11 devnull #include "fns.h"
13 b3994ec5 2003-12-11 devnull
14 b3994ec5 2003-12-11 devnull int winid;
15 b3994ec5 2003-12-11 devnull
16 b3994ec5 2003-12-11 devnull void
17 b3994ec5 2003-12-11 devnull wininit(Window *w, Window *clone, Rectangle r)
18 b3994ec5 2003-12-11 devnull {
19 b3994ec5 2003-12-11 devnull Rectangle r1, br;
20 b3994ec5 2003-12-11 devnull File *f;
21 b3994ec5 2003-12-11 devnull Reffont *rf;
22 b3994ec5 2003-12-11 devnull Rune *rp;
23 b3994ec5 2003-12-11 devnull int nc;
24 b3994ec5 2003-12-11 devnull
25 b3994ec5 2003-12-11 devnull w->tag.w = w;
26 b3994ec5 2003-12-11 devnull w->body.w = w;
27 b3994ec5 2003-12-11 devnull w->id = ++winid;
28 b3994ec5 2003-12-11 devnull incref(&w->ref);
29 5a8e63b2 2004-02-29 devnull if(globalincref)
30 5a8e63b2 2004-02-29 devnull incref(&w->ref);
31 b3994ec5 2003-12-11 devnull w->ctlfid = ~0;
32 b3994ec5 2003-12-11 devnull w->utflastqid = -1;
33 b3994ec5 2003-12-11 devnull r1 = r;
34 b3994ec5 2003-12-11 devnull r1.max.y = r1.min.y + font->height;
35 b3994ec5 2003-12-11 devnull incref(&reffont.ref);
36 b3994ec5 2003-12-11 devnull f = fileaddtext(nil, &w->tag);
37 b3994ec5 2003-12-11 devnull textinit(&w->tag, f, r1, &reffont, tagcols);
38 b3994ec5 2003-12-11 devnull w->tag.what = Tag;
39 b3994ec5 2003-12-11 devnull /* tag is a copy of the contents, not a tracked image */
40 b3994ec5 2003-12-11 devnull if(clone){
41 b3994ec5 2003-12-11 devnull textdelete(&w->tag, 0, w->tag.file->b.nc, TRUE);
42 b3994ec5 2003-12-11 devnull nc = clone->tag.file->b.nc;
43 b3994ec5 2003-12-11 devnull rp = runemalloc(nc);
44 b3994ec5 2003-12-11 devnull bufread(&clone->tag.file->b, 0, rp, nc);
45 b3994ec5 2003-12-11 devnull textinsert(&w->tag, 0, rp, nc, TRUE);
46 b3994ec5 2003-12-11 devnull free(rp);
47 b3994ec5 2003-12-11 devnull filereset(w->tag.file);
48 b3994ec5 2003-12-11 devnull textsetselect(&w->tag, nc, nc);
49 b3994ec5 2003-12-11 devnull }
50 c1973705 2004-02-09 devnull //assert(w->body.w == w);
51 b3994ec5 2003-12-11 devnull r1 = r;
52 b3994ec5 2003-12-11 devnull r1.min.y += font->height + 1;
53 b3994ec5 2003-12-11 devnull if(r1.max.y < r1.min.y)
54 b3994ec5 2003-12-11 devnull r1.max.y = r1.min.y;
55 b3994ec5 2003-12-11 devnull f = nil;
56 b3994ec5 2003-12-11 devnull if(clone){
57 b3994ec5 2003-12-11 devnull f = clone->body.file;
58 b3994ec5 2003-12-11 devnull w->body.org = clone->body.org;
59 b3994ec5 2003-12-11 devnull w->isscratch = clone->isscratch;
60 b3994ec5 2003-12-11 devnull rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name);
61 b3994ec5 2003-12-11 devnull }else
62 b3994ec5 2003-12-11 devnull rf = rfget(FALSE, FALSE, FALSE, nil);
63 c1973705 2004-02-09 devnull //assert(w->body.w == w);
64 b3994ec5 2003-12-11 devnull f = fileaddtext(f, &w->body);
65 b3994ec5 2003-12-11 devnull w->body.what = Body;
66 b3994ec5 2003-12-11 devnull textinit(&w->body, f, r1, rf, textcols);
67 b3994ec5 2003-12-11 devnull r1.min.y -= 1;
68 b3994ec5 2003-12-11 devnull r1.max.y = r1.min.y+1;
69 b3994ec5 2003-12-11 devnull draw(screen, r1, tagcols[BORD], nil, ZP);
70 b3994ec5 2003-12-11 devnull textscrdraw(&w->body);
71 b3994ec5 2003-12-11 devnull w->r = r;
72 b3994ec5 2003-12-11 devnull w->r.max.y = w->body.fr.r.max.y;
73 b3994ec5 2003-12-11 devnull br.min = w->tag.scrollr.min;
74 b3994ec5 2003-12-11 devnull br.max.x = br.min.x + Dx(button->r);
75 b3994ec5 2003-12-11 devnull br.max.y = br.min.y + Dy(button->r);
76 b3994ec5 2003-12-11 devnull draw(screen, br, button, nil, button->r.min);
77 b3994ec5 2003-12-11 devnull w->filemenu = TRUE;
78 b3994ec5 2003-12-11 devnull w->maxlines = w->body.fr.maxlines;
79 53998c99 2004-09-28 devnull w->autoindent = globalautoindent;
80 c1973705 2004-02-09 devnull //assert(w->body.w == w);
81 b3994ec5 2003-12-11 devnull if(clone){
82 b3994ec5 2003-12-11 devnull w->dirty = clone->dirty;
83 2a373ea4 2005-03-18 devnull w->autoindent = clone->autoindent;
84 b3994ec5 2003-12-11 devnull textsetselect(&w->body, clone->body.q0, clone->body.q1);
85 b3994ec5 2003-12-11 devnull winsettag(w);
86 b3994ec5 2003-12-11 devnull }
87 b3994ec5 2003-12-11 devnull }
88 b3994ec5 2003-12-11 devnull
89 b3994ec5 2003-12-11 devnull int
90 b3994ec5 2003-12-11 devnull winresize(Window *w, Rectangle r, int safe)
91 b3994ec5 2003-12-11 devnull {
92 b3994ec5 2003-12-11 devnull Rectangle r1;
93 b3994ec5 2003-12-11 devnull int y;
94 b3994ec5 2003-12-11 devnull Image *b;
95 b3994ec5 2003-12-11 devnull Rectangle br;
96 b3994ec5 2003-12-11 devnull
97 b3994ec5 2003-12-11 devnull r1 = r;
98 b3994ec5 2003-12-11 devnull r1.max.y = r1.min.y + font->height;
99 b3994ec5 2003-12-11 devnull y = r1.max.y;
100 b3994ec5 2003-12-11 devnull if(!safe || !eqrect(w->tag.fr.r, r1)){
101 b3994ec5 2003-12-11 devnull y = textresize(&w->tag, r1);
102 b3994ec5 2003-12-11 devnull b = button;
103 b3994ec5 2003-12-11 devnull if(w->body.file->mod && !w->isdir && !w->isscratch)
104 b3994ec5 2003-12-11 devnull b = modbutton;
105 b3994ec5 2003-12-11 devnull br.min = w->tag.scrollr.min;
106 b3994ec5 2003-12-11 devnull br.max.x = br.min.x + Dx(b->r);
107 b3994ec5 2003-12-11 devnull br.max.y = br.min.y + Dy(b->r);
108 b3994ec5 2003-12-11 devnull draw(screen, br, b, nil, b->r.min);
109 b3994ec5 2003-12-11 devnull }
110 b3994ec5 2003-12-11 devnull if(!safe || !eqrect(w->body.fr.r, r1)){
111 b3994ec5 2003-12-11 devnull if(y+1+font->height > r.max.y){ /* no body */
112 b3994ec5 2003-12-11 devnull r1.min.y = y;
113 b3994ec5 2003-12-11 devnull r1.max.y = y;
114 b3994ec5 2003-12-11 devnull textresize(&w->body, r1);
115 b3994ec5 2003-12-11 devnull w->r = r;
116 b3994ec5 2003-12-11 devnull w->r.max.y = y;
117 b3994ec5 2003-12-11 devnull return y;
118 b3994ec5 2003-12-11 devnull }
119 b3994ec5 2003-12-11 devnull r1 = r;
120 b3994ec5 2003-12-11 devnull r1.min.y = y;
121 b3994ec5 2003-12-11 devnull r1.max.y = y + 1;
122 b3994ec5 2003-12-11 devnull draw(screen, r1, tagcols[BORD], nil, ZP);
123 b3994ec5 2003-12-11 devnull r1.min.y = y + 1;
124 b3994ec5 2003-12-11 devnull r1.max.y = r.max.y;
125 b3994ec5 2003-12-11 devnull y = textresize(&w->body, r1);
126 b3994ec5 2003-12-11 devnull w->r = r;
127 b3994ec5 2003-12-11 devnull w->r.max.y = y;
128 b3994ec5 2003-12-11 devnull textscrdraw(&w->body);
129 b3994ec5 2003-12-11 devnull }
130 b3994ec5 2003-12-11 devnull w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines));
131 b3994ec5 2003-12-11 devnull return w->r.max.y;
132 b3994ec5 2003-12-11 devnull }
133 b3994ec5 2003-12-11 devnull
134 b3994ec5 2003-12-11 devnull void
135 b3994ec5 2003-12-11 devnull winlock1(Window *w, int owner)
136 b3994ec5 2003-12-11 devnull {
137 b3994ec5 2003-12-11 devnull incref(&w->ref);
138 b3994ec5 2003-12-11 devnull qlock(&w->lk);
139 b3994ec5 2003-12-11 devnull w->owner = owner;
140 b3994ec5 2003-12-11 devnull }
141 b3994ec5 2003-12-11 devnull
142 b3994ec5 2003-12-11 devnull void
143 b3994ec5 2003-12-11 devnull winlock(Window *w, int owner)
144 b3994ec5 2003-12-11 devnull {
145 b3994ec5 2003-12-11 devnull int i;
146 b3994ec5 2003-12-11 devnull File *f;
147 b3994ec5 2003-12-11 devnull
148 b3994ec5 2003-12-11 devnull f = w->body.file;
149 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++)
150 b3994ec5 2003-12-11 devnull winlock1(f->text[i]->w, owner);
151 b3994ec5 2003-12-11 devnull }
152 b3994ec5 2003-12-11 devnull
153 b3994ec5 2003-12-11 devnull void
154 b3994ec5 2003-12-11 devnull winunlock(Window *w)
155 b3994ec5 2003-12-11 devnull {
156 b3994ec5 2003-12-11 devnull int i;
157 b3994ec5 2003-12-11 devnull File *f;
158 b3994ec5 2003-12-11 devnull
159 725d9fd7 2005-07-28 devnull /*
160 725d9fd7 2005-07-28 devnull * subtle: loop runs backwards to avoid tripping over
161 725d9fd7 2005-07-28 devnull * winclose indirectly editing f->text and freeing f
162 725d9fd7 2005-07-28 devnull * on the last iteration of the loop.
163 725d9fd7 2005-07-28 devnull */
164 b3994ec5 2003-12-11 devnull f = w->body.file;
165 725d9fd7 2005-07-28 devnull for(i=f->ntext-1; i>=0; i--){
166 b3994ec5 2003-12-11 devnull w = f->text[i]->w;
167 b3994ec5 2003-12-11 devnull w->owner = 0;
168 b3994ec5 2003-12-11 devnull qunlock(&w->lk);
169 b3994ec5 2003-12-11 devnull winclose(w);
170 b3994ec5 2003-12-11 devnull }
171 b3994ec5 2003-12-11 devnull }
172 b3994ec5 2003-12-11 devnull
173 b3994ec5 2003-12-11 devnull void
174 b3994ec5 2003-12-11 devnull winmousebut(Window *w)
175 b3994ec5 2003-12-11 devnull {
176 b3994ec5 2003-12-11 devnull moveto(mousectl, divpt(addpt(w->tag.scrollr.min, w->tag.scrollr.max), 2));
177 b3994ec5 2003-12-11 devnull }
178 b3994ec5 2003-12-11 devnull
179 b3994ec5 2003-12-11 devnull void
180 b3994ec5 2003-12-11 devnull windirfree(Window *w)
181 b3994ec5 2003-12-11 devnull {
182 b3994ec5 2003-12-11 devnull int i;
183 b3994ec5 2003-12-11 devnull Dirlist *dl;
184 b3994ec5 2003-12-11 devnull
185 b3994ec5 2003-12-11 devnull if(w->isdir){
186 b3994ec5 2003-12-11 devnull for(i=0; i<w->ndl; i++){
187 b3994ec5 2003-12-11 devnull dl = w->dlp[i];
188 b3994ec5 2003-12-11 devnull free(dl->r);
189 b3994ec5 2003-12-11 devnull free(dl);
190 b3994ec5 2003-12-11 devnull }
191 b3994ec5 2003-12-11 devnull free(w->dlp);
192 b3994ec5 2003-12-11 devnull }
193 b3994ec5 2003-12-11 devnull w->dlp = nil;
194 b3994ec5 2003-12-11 devnull w->ndl = 0;
195 b3994ec5 2003-12-11 devnull }
196 b3994ec5 2003-12-11 devnull
197 b3994ec5 2003-12-11 devnull void
198 b3994ec5 2003-12-11 devnull winclose(Window *w)
199 b3994ec5 2003-12-11 devnull {
200 b3994ec5 2003-12-11 devnull int i;
201 b3994ec5 2003-12-11 devnull
202 b3994ec5 2003-12-11 devnull if(decref(&w->ref) == 0){
203 b3994ec5 2003-12-11 devnull windirfree(w);
204 b3994ec5 2003-12-11 devnull textclose(&w->tag);
205 b3994ec5 2003-12-11 devnull textclose(&w->body);
206 b3994ec5 2003-12-11 devnull if(activewin == w)
207 b3994ec5 2003-12-11 devnull activewin = nil;
208 b3994ec5 2003-12-11 devnull for(i=0; i<w->nincl; i++)
209 b3994ec5 2003-12-11 devnull free(w->incl[i]);
210 b3994ec5 2003-12-11 devnull free(w->incl);
211 b3994ec5 2003-12-11 devnull free(w->events);
212 b3994ec5 2003-12-11 devnull free(w);
213 b3994ec5 2003-12-11 devnull }
214 b3994ec5 2003-12-11 devnull }
215 b3994ec5 2003-12-11 devnull
216 b3994ec5 2003-12-11 devnull void
217 b3994ec5 2003-12-11 devnull windelete(Window *w)
218 b3994ec5 2003-12-11 devnull {
219 b3994ec5 2003-12-11 devnull Xfid *x;
220 b3994ec5 2003-12-11 devnull
221 b3994ec5 2003-12-11 devnull x = w->eventx;
222 b3994ec5 2003-12-11 devnull if(x){
223 b3994ec5 2003-12-11 devnull w->nevents = 0;
224 b3994ec5 2003-12-11 devnull free(w->events);
225 b3994ec5 2003-12-11 devnull w->events = nil;
226 b3994ec5 2003-12-11 devnull w->eventx = nil;
227 b3994ec5 2003-12-11 devnull sendp(x->c, nil); /* wake him up */
228 b3994ec5 2003-12-11 devnull }
229 b3994ec5 2003-12-11 devnull }
230 b3994ec5 2003-12-11 devnull
231 b3994ec5 2003-12-11 devnull void
232 b3994ec5 2003-12-11 devnull winundo(Window *w, int isundo)
233 b3994ec5 2003-12-11 devnull {
234 b3994ec5 2003-12-11 devnull Text *body;
235 b3994ec5 2003-12-11 devnull int i;
236 b3994ec5 2003-12-11 devnull File *f;
237 b3994ec5 2003-12-11 devnull Window *v;
238 b3994ec5 2003-12-11 devnull
239 b3994ec5 2003-12-11 devnull w->utflastqid = -1;
240 b3994ec5 2003-12-11 devnull body = &w->body;
241 b3994ec5 2003-12-11 devnull fileundo(body->file, isundo, &body->q0, &body->q1);
242 b3994ec5 2003-12-11 devnull textshow(body, body->q0, body->q1, 1);
243 b3994ec5 2003-12-11 devnull f = body->file;
244 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++){
245 b3994ec5 2003-12-11 devnull v = f->text[i]->w;
246 b3994ec5 2003-12-11 devnull v->dirty = (f->seq != v->putseq);
247 b3994ec5 2003-12-11 devnull if(v != w){
248 b3994ec5 2003-12-11 devnull v->body.q0 = v->body.fr.p0+v->body.org;
249 b3994ec5 2003-12-11 devnull v->body.q1 = v->body.fr.p1+v->body.org;
250 b3994ec5 2003-12-11 devnull }
251 b3994ec5 2003-12-11 devnull }
252 b3994ec5 2003-12-11 devnull winsettag(w);
253 b3994ec5 2003-12-11 devnull }
254 b3994ec5 2003-12-11 devnull
255 b3994ec5 2003-12-11 devnull void
256 b3994ec5 2003-12-11 devnull winsetname(Window *w, Rune *name, int n)
257 b3994ec5 2003-12-11 devnull {
258 b3994ec5 2003-12-11 devnull Text *t;
259 b3994ec5 2003-12-11 devnull Window *v;
260 b3994ec5 2003-12-11 devnull int i;
261 b3994ec5 2003-12-11 devnull static Rune Lslashguide[] = { '/', 'g', 'u', 'i', 'd', 'e', 0 };
262 b3994ec5 2003-12-11 devnull static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
263 b3994ec5 2003-12-11 devnull t = &w->body;
264 b3994ec5 2003-12-11 devnull if(runeeq(t->file->name, t->file->nname, name, n) == TRUE)
265 b3994ec5 2003-12-11 devnull return;
266 b3994ec5 2003-12-11 devnull w->isscratch = FALSE;
267 b3994ec5 2003-12-11 devnull if(n>=6 && runeeq(Lslashguide, 6, name+(n-6), 6))
268 b3994ec5 2003-12-11 devnull w->isscratch = TRUE;
269 b3994ec5 2003-12-11 devnull else if(n>=7 && runeeq(Lpluserrors, 7, name+(n-7), 7))
270 b3994ec5 2003-12-11 devnull w->isscratch = TRUE;
271 b3994ec5 2003-12-11 devnull filesetname(t->file, name, n);
272 b3994ec5 2003-12-11 devnull for(i=0; i<t->file->ntext; i++){
273 b3994ec5 2003-12-11 devnull v = t->file->text[i]->w;
274 b3994ec5 2003-12-11 devnull winsettag(v);
275 b3994ec5 2003-12-11 devnull v->isscratch = w->isscratch;
276 b3994ec5 2003-12-11 devnull }
277 b3994ec5 2003-12-11 devnull }
278 b3994ec5 2003-12-11 devnull
279 b3994ec5 2003-12-11 devnull void
280 b3994ec5 2003-12-11 devnull wintype(Window *w, Text *t, Rune r)
281 b3994ec5 2003-12-11 devnull {
282 b3994ec5 2003-12-11 devnull int i;
283 b3994ec5 2003-12-11 devnull
284 b3994ec5 2003-12-11 devnull texttype(t, r);
285 b3994ec5 2003-12-11 devnull if(t->what == Body)
286 b3994ec5 2003-12-11 devnull for(i=0; i<t->file->ntext; i++)
287 b3994ec5 2003-12-11 devnull textscrdraw(t->file->text[i]);
288 b3994ec5 2003-12-11 devnull winsettag(w);
289 b3994ec5 2003-12-11 devnull }
290 b3994ec5 2003-12-11 devnull
291 b3994ec5 2003-12-11 devnull void
292 b3994ec5 2003-12-11 devnull wincleartag(Window *w)
293 b3994ec5 2003-12-11 devnull {
294 b3994ec5 2003-12-11 devnull int i, n;
295 b3994ec5 2003-12-11 devnull Rune *r;
296 b3994ec5 2003-12-11 devnull
297 b3994ec5 2003-12-11 devnull /* w must be committed */
298 b3994ec5 2003-12-11 devnull n = w->tag.file->b.nc;
299 b3994ec5 2003-12-11 devnull r = runemalloc(n);
300 b3994ec5 2003-12-11 devnull bufread(&w->tag.file->b, 0, r, n);
301 b3994ec5 2003-12-11 devnull for(i=0; i<n; i++)
302 b3994ec5 2003-12-11 devnull if(r[i]==' ' || r[i]=='\t')
303 b3994ec5 2003-12-11 devnull break;
304 b3994ec5 2003-12-11 devnull for(; i<n; i++)
305 b3994ec5 2003-12-11 devnull if(r[i] == '|')
306 b3994ec5 2003-12-11 devnull break;
307 b3994ec5 2003-12-11 devnull if(i == n)
308 b3994ec5 2003-12-11 devnull return;
309 b3994ec5 2003-12-11 devnull i++;
310 b3994ec5 2003-12-11 devnull textdelete(&w->tag, i, n, TRUE);
311 b3994ec5 2003-12-11 devnull free(r);
312 b3994ec5 2003-12-11 devnull w->tag.file->mod = FALSE;
313 b3994ec5 2003-12-11 devnull if(w->tag.q0 > i)
314 b3994ec5 2003-12-11 devnull w->tag.q0 = i;
315 b3994ec5 2003-12-11 devnull if(w->tag.q1 > i)
316 b3994ec5 2003-12-11 devnull w->tag.q1 = i;
317 b3994ec5 2003-12-11 devnull textsetselect(&w->tag, w->tag.q0, w->tag.q1);
318 b3994ec5 2003-12-11 devnull }
319 b3994ec5 2003-12-11 devnull
320 b3994ec5 2003-12-11 devnull void
321 b3994ec5 2003-12-11 devnull winsettag1(Window *w)
322 b3994ec5 2003-12-11 devnull {
323 d96da29b 2005-03-14 devnull int bar, dirty, i, j, k, n, ntagname;
324 d96da29b 2005-03-14 devnull Rune *new, *old, *r, *tagname;
325 b3994ec5 2003-12-11 devnull Image *b;
326 b3994ec5 2003-12-11 devnull uint q0, q1;
327 b3994ec5 2003-12-11 devnull Rectangle br;
328 b3994ec5 2003-12-11 devnull static Rune Ldelsnarf[] = { ' ', 'D', 'e', 'l', ' ',
329 b3994ec5 2003-12-11 devnull 'S', 'n', 'a', 'r', 'f', 0 };
330 b3994ec5 2003-12-11 devnull static Rune Lundo[] = { ' ', 'U', 'n', 'd', 'o', 0 };
331 b3994ec5 2003-12-11 devnull static Rune Lredo[] = { ' ', 'R', 'e', 'd', 'o', 0 };
332 b3994ec5 2003-12-11 devnull static Rune Lget[] = { ' ', 'G', 'e', 't', 0 };
333 b3994ec5 2003-12-11 devnull static Rune Lput[] = { ' ', 'P', 'u', 't', 0 };
334 b3994ec5 2003-12-11 devnull static Rune Llook[] = { ' ', 'L', 'o', 'o', 'k', ' ', 0 };
335 b3994ec5 2003-12-11 devnull static Rune Lpipe[] = { ' ', '|', 0 };
336 b3994ec5 2003-12-11 devnull /* there are races that get us here with stuff in the tag cache, so we take extra care to sync it */
337 b3994ec5 2003-12-11 devnull if(w->tag.ncache!=0 || w->tag.file->mod)
338 b3994ec5 2003-12-11 devnull wincommit(w, &w->tag); /* check file name; also guarantees we can modify tag contents */
339 b3994ec5 2003-12-11 devnull old = runemalloc(w->tag.file->b.nc+1);
340 b3994ec5 2003-12-11 devnull bufread(&w->tag.file->b, 0, old, w->tag.file->b.nc);
341 b3994ec5 2003-12-11 devnull old[w->tag.file->b.nc] = '\0';
342 b3994ec5 2003-12-11 devnull for(i=0; i<w->tag.file->b.nc; i++)
343 b3994ec5 2003-12-11 devnull if(old[i]==' ' || old[i]=='\t')
344 b3994ec5 2003-12-11 devnull break;
345 d96da29b 2005-03-14 devnull
346 d96da29b 2005-03-14 devnull /* make sure the file name is set correctly in the tag */
347 d96da29b 2005-03-14 devnull ntagname = w->body.file->nname;
348 d96da29b 2005-03-14 devnull tagname = runemalloc(ntagname);
349 d96da29b 2005-03-14 devnull runemove(tagname, w->body.file->name, ntagname);
350 44e41b1f 2005-07-13 devnull abbrevenv(&tagname, (uint*)&ntagname);
351 d96da29b 2005-03-14 devnull
352 3b33df99 2005-03-18 devnull /*
353 3b33df99 2005-03-18 devnull * XXX Why is this here instead of letting the code
354 3b33df99 2005-03-18 devnull * down below do the work?
355 3b33df99 2005-03-18 devnull */
356 d96da29b 2005-03-14 devnull if(runeeq(old, i, tagname, ntagname) == FALSE){
357 3b33df99 2005-03-18 devnull q0 = w->tag.q0;
358 3b33df99 2005-03-18 devnull q1 = w->tag.q1;
359 b3994ec5 2003-12-11 devnull textdelete(&w->tag, 0, i, TRUE);
360 d96da29b 2005-03-14 devnull textinsert(&w->tag, 0, tagname, ntagname, TRUE);
361 b3994ec5 2003-12-11 devnull free(old);
362 b3994ec5 2003-12-11 devnull old = runemalloc(w->tag.file->b.nc+1);
363 b3994ec5 2003-12-11 devnull bufread(&w->tag.file->b, 0, old, w->tag.file->b.nc);
364 b3994ec5 2003-12-11 devnull old[w->tag.file->b.nc] = '\0';
365 3b33df99 2005-03-18 devnull if(q0 >= i){
366 3b33df99 2005-03-18 devnull /*
367 3b33df99 2005-03-18 devnull * XXX common case - typing at end of name
368 3b33df99 2005-03-18 devnull */
369 3b33df99 2005-03-18 devnull w->tag.q0 = q0+ntagname-i;
370 3b33df99 2005-03-18 devnull w->tag.q1 = q1+ntagname-i;
371 3b33df99 2005-03-18 devnull }
372 b3994ec5 2003-12-11 devnull }
373 d96da29b 2005-03-14 devnull
374 d96da29b 2005-03-14 devnull /* compute the text for the whole tag, replacing current only if it differs */
375 d96da29b 2005-03-14 devnull new = runemalloc(ntagname+100);
376 b3994ec5 2003-12-11 devnull i = 0;
377 d96da29b 2005-03-14 devnull runemove(new+i, tagname, ntagname);
378 d96da29b 2005-03-14 devnull i += ntagname;
379 b3994ec5 2003-12-11 devnull runemove(new+i, Ldelsnarf, 10);
380 b3994ec5 2003-12-11 devnull i += 10;
381 b3994ec5 2003-12-11 devnull if(w->filemenu){
382 b3994ec5 2003-12-11 devnull if(w->body.file->delta.nc>0 || w->body.ncache){
383 b3994ec5 2003-12-11 devnull runemove(new+i, Lundo, 5);
384 b3994ec5 2003-12-11 devnull i += 5;
385 b3994ec5 2003-12-11 devnull }
386 b3994ec5 2003-12-11 devnull if(w->body.file->epsilon.nc > 0){
387 b3994ec5 2003-12-11 devnull runemove(new+i, Lredo, 5);
388 b3994ec5 2003-12-11 devnull i += 5;
389 b3994ec5 2003-12-11 devnull }
390 b3994ec5 2003-12-11 devnull dirty = w->body.file->nname && (w->body.ncache || w->body.file->seq!=w->putseq);
391 b3994ec5 2003-12-11 devnull if(!w->isdir && dirty){
392 b3994ec5 2003-12-11 devnull runemove(new+i, Lput, 4);
393 b3994ec5 2003-12-11 devnull i += 4;
394 b3994ec5 2003-12-11 devnull }
395 b3994ec5 2003-12-11 devnull }
396 b3994ec5 2003-12-11 devnull if(w->isdir){
397 b3994ec5 2003-12-11 devnull runemove(new+i, Lget, 4);
398 b3994ec5 2003-12-11 devnull i += 4;
399 b3994ec5 2003-12-11 devnull }
400 b3994ec5 2003-12-11 devnull runemove(new+i, Lpipe, 2);
401 b3994ec5 2003-12-11 devnull i += 2;
402 b3994ec5 2003-12-11 devnull r = runestrchr(old, '|');
403 b3994ec5 2003-12-11 devnull if(r)
404 b3994ec5 2003-12-11 devnull k = r-old+1;
405 b3994ec5 2003-12-11 devnull else{
406 b3994ec5 2003-12-11 devnull k = w->tag.file->b.nc;
407 b3994ec5 2003-12-11 devnull if(w->body.file->seq == 0){
408 b3994ec5 2003-12-11 devnull runemove(new+i, Llook, 6);
409 b3994ec5 2003-12-11 devnull i += 6;
410 b3994ec5 2003-12-11 devnull }
411 b3994ec5 2003-12-11 devnull }
412 b3994ec5 2003-12-11 devnull new[i] = 0;
413 b3994ec5 2003-12-11 devnull if(runestrlen(new) != i)
414 b3994ec5 2003-12-11 devnull fprint(2, "s '%S' len not %d\n", new, i);
415 b3994ec5 2003-12-11 devnull assert(i==runestrlen(new));
416 d96da29b 2005-03-14 devnull
417 d96da29b 2005-03-14 devnull /* replace tag if the new one is different */
418 b3994ec5 2003-12-11 devnull if(runeeq(new, i, old, k) == FALSE){
419 b3994ec5 2003-12-11 devnull n = k;
420 b3994ec5 2003-12-11 devnull if(n > i)
421 b3994ec5 2003-12-11 devnull n = i;
422 b3994ec5 2003-12-11 devnull for(j=0; j<n; j++)
423 b3994ec5 2003-12-11 devnull if(old[j] != new[j])
424 b3994ec5 2003-12-11 devnull break;
425 b3994ec5 2003-12-11 devnull q0 = w->tag.q0;
426 b3994ec5 2003-12-11 devnull q1 = w->tag.q1;
427 b3994ec5 2003-12-11 devnull textdelete(&w->tag, j, k, TRUE);
428 b3994ec5 2003-12-11 devnull textinsert(&w->tag, j, new+j, i-j, TRUE);
429 b3994ec5 2003-12-11 devnull /* try to preserve user selection */
430 b3994ec5 2003-12-11 devnull r = runestrchr(old, '|');
431 b3994ec5 2003-12-11 devnull if(r){
432 b3994ec5 2003-12-11 devnull bar = r-old;
433 b3994ec5 2003-12-11 devnull if(q0 > bar){
434 b3994ec5 2003-12-11 devnull bar = (runestrchr(new, '|')-new)-bar;
435 b3994ec5 2003-12-11 devnull w->tag.q0 = q0+bar;
436 b3994ec5 2003-12-11 devnull w->tag.q1 = q1+bar;
437 b3994ec5 2003-12-11 devnull }
438 b3994ec5 2003-12-11 devnull }
439 b3994ec5 2003-12-11 devnull }
440 d96da29b 2005-03-14 devnull free(tagname);
441 b3994ec5 2003-12-11 devnull free(old);
442 b3994ec5 2003-12-11 devnull free(new);
443 b3994ec5 2003-12-11 devnull w->tag.file->mod = FALSE;
444 b3994ec5 2003-12-11 devnull n = w->tag.file->b.nc+w->tag.ncache;
445 b3994ec5 2003-12-11 devnull if(w->tag.q0 > n)
446 b3994ec5 2003-12-11 devnull w->tag.q0 = n;
447 b3994ec5 2003-12-11 devnull if(w->tag.q1 > n)
448 b3994ec5 2003-12-11 devnull w->tag.q1 = n;
449 b3994ec5 2003-12-11 devnull textsetselect(&w->tag, w->tag.q0, w->tag.q1);
450 b3994ec5 2003-12-11 devnull b = button;
451 b3994ec5 2003-12-11 devnull if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache))
452 b3994ec5 2003-12-11 devnull b = modbutton;
453 b3994ec5 2003-12-11 devnull br.min = w->tag.scrollr.min;
454 b3994ec5 2003-12-11 devnull br.max.x = br.min.x + Dx(b->r);
455 b3994ec5 2003-12-11 devnull br.max.y = br.min.y + Dy(b->r);
456 b3994ec5 2003-12-11 devnull draw(screen, br, b, nil, b->r.min);
457 b3994ec5 2003-12-11 devnull }
458 b3994ec5 2003-12-11 devnull
459 b3994ec5 2003-12-11 devnull void
460 b3994ec5 2003-12-11 devnull winsettag(Window *w)
461 b3994ec5 2003-12-11 devnull {
462 b3994ec5 2003-12-11 devnull int i;
463 b3994ec5 2003-12-11 devnull File *f;
464 b3994ec5 2003-12-11 devnull Window *v;
465 b3994ec5 2003-12-11 devnull
466 b3994ec5 2003-12-11 devnull f = w->body.file;
467 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++){
468 b3994ec5 2003-12-11 devnull v = f->text[i]->w;
469 b3994ec5 2003-12-11 devnull if(v->col->safe || v->body.fr.maxlines>0)
470 b3994ec5 2003-12-11 devnull winsettag1(v);
471 b3994ec5 2003-12-11 devnull }
472 b3994ec5 2003-12-11 devnull }
473 b3994ec5 2003-12-11 devnull
474 b3994ec5 2003-12-11 devnull void
475 b3994ec5 2003-12-11 devnull wincommit(Window *w, Text *t)
476 b3994ec5 2003-12-11 devnull {
477 b3994ec5 2003-12-11 devnull Rune *r;
478 b3994ec5 2003-12-11 devnull int i;
479 b3994ec5 2003-12-11 devnull File *f;
480 b3994ec5 2003-12-11 devnull
481 b3994ec5 2003-12-11 devnull textcommit(t, TRUE);
482 b3994ec5 2003-12-11 devnull f = t->file;
483 b3994ec5 2003-12-11 devnull if(f->ntext > 1)
484 b3994ec5 2003-12-11 devnull for(i=0; i<f->ntext; i++)
485 b3994ec5 2003-12-11 devnull textcommit(f->text[i], FALSE); /* no-op for t */
486 b3994ec5 2003-12-11 devnull if(t->what == Body)
487 b3994ec5 2003-12-11 devnull return;
488 b3994ec5 2003-12-11 devnull r = runemalloc(w->tag.file->b.nc);
489 b3994ec5 2003-12-11 devnull bufread(&w->tag.file->b, 0, r, w->tag.file->b.nc);
490 b3994ec5 2003-12-11 devnull for(i=0; i<w->tag.file->b.nc; i++)
491 b3994ec5 2003-12-11 devnull if(r[i]==' ' || r[i]=='\t')
492 b3994ec5 2003-12-11 devnull break;
493 44e41b1f 2005-07-13 devnull expandenv(&r, (uint*)&i);
494 b3994ec5 2003-12-11 devnull if(runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE){
495 b3994ec5 2003-12-11 devnull seq++;
496 b3994ec5 2003-12-11 devnull filemark(w->body.file);
497 b3994ec5 2003-12-11 devnull w->body.file->mod = TRUE;
498 b3994ec5 2003-12-11 devnull w->dirty = TRUE;
499 b3994ec5 2003-12-11 devnull winsetname(w, r, i);
500 b3994ec5 2003-12-11 devnull winsettag(w);
501 b3994ec5 2003-12-11 devnull }
502 b3994ec5 2003-12-11 devnull free(r);
503 b3994ec5 2003-12-11 devnull }
504 b3994ec5 2003-12-11 devnull
505 b3994ec5 2003-12-11 devnull void
506 b3994ec5 2003-12-11 devnull winaddincl(Window *w, Rune *r, int n)
507 b3994ec5 2003-12-11 devnull {
508 b3994ec5 2003-12-11 devnull char *a;
509 b3994ec5 2003-12-11 devnull Dir *d;
510 b3994ec5 2003-12-11 devnull Runestr rs;
511 b3994ec5 2003-12-11 devnull
512 b3994ec5 2003-12-11 devnull a = runetobyte(r, n);
513 b3994ec5 2003-12-11 devnull d = dirstat(a);
514 b3994ec5 2003-12-11 devnull if(d == nil){
515 b3994ec5 2003-12-11 devnull if(a[0] == '/')
516 b3994ec5 2003-12-11 devnull goto Rescue;
517 b3994ec5 2003-12-11 devnull rs = dirname(&w->body, r, n);
518 b3994ec5 2003-12-11 devnull r = rs.r;
519 b3994ec5 2003-12-11 devnull n = rs.nr;
520 b3994ec5 2003-12-11 devnull free(a);
521 b3994ec5 2003-12-11 devnull a = runetobyte(r, n);
522 b3994ec5 2003-12-11 devnull d = dirstat(a);
523 b3994ec5 2003-12-11 devnull if(d == nil)
524 b3994ec5 2003-12-11 devnull goto Rescue;
525 b3994ec5 2003-12-11 devnull r = runerealloc(r, n+1);
526 b3994ec5 2003-12-11 devnull r[n] = 0;
527 b3994ec5 2003-12-11 devnull }
528 b3994ec5 2003-12-11 devnull free(a);
529 b3994ec5 2003-12-11 devnull if((d->qid.type&QTDIR) == 0){
530 b3994ec5 2003-12-11 devnull free(d);
531 b3994ec5 2003-12-11 devnull warning(nil, "%s: not a directory\n", a);
532 b3994ec5 2003-12-11 devnull free(r);
533 b3994ec5 2003-12-11 devnull return;
534 b3994ec5 2003-12-11 devnull }
535 b3994ec5 2003-12-11 devnull free(d);
536 b3994ec5 2003-12-11 devnull w->nincl++;
537 b3994ec5 2003-12-11 devnull w->incl = realloc(w->incl, w->nincl*sizeof(Rune*));
538 b3994ec5 2003-12-11 devnull memmove(w->incl+1, w->incl, (w->nincl-1)*sizeof(Rune*));
539 b3994ec5 2003-12-11 devnull w->incl[0] = runemalloc(n+1);
540 b3994ec5 2003-12-11 devnull runemove(w->incl[0], r, n);
541 b3994ec5 2003-12-11 devnull free(r);
542 b3994ec5 2003-12-11 devnull return;
543 b3994ec5 2003-12-11 devnull
544 b3994ec5 2003-12-11 devnull Rescue:
545 b3994ec5 2003-12-11 devnull warning(nil, "%s: %r\n", a);
546 b3994ec5 2003-12-11 devnull free(r);
547 b3994ec5 2003-12-11 devnull free(a);
548 b3994ec5 2003-12-11 devnull return;
549 b3994ec5 2003-12-11 devnull }
550 b3994ec5 2003-12-11 devnull
551 b3994ec5 2003-12-11 devnull int
552 b3994ec5 2003-12-11 devnull winclean(Window *w, int conservative) /* as it stands, conservative is always TRUE */
553 b3994ec5 2003-12-11 devnull {
554 b3994ec5 2003-12-11 devnull if(w->isscratch || w->isdir) /* don't whine if it's a guide file, error window, etc. */
555 b3994ec5 2003-12-11 devnull return TRUE;
556 b3994ec5 2003-12-11 devnull if(!conservative && w->nopen[QWevent]>0)
557 b3994ec5 2003-12-11 devnull return TRUE;
558 b3994ec5 2003-12-11 devnull if(w->dirty){
559 b3994ec5 2003-12-11 devnull if(w->body.file->nname)
560 b3994ec5 2003-12-11 devnull warning(nil, "%.*S modified\n", w->body.file->nname, w->body.file->name);
561 b3994ec5 2003-12-11 devnull else{
562 b3994ec5 2003-12-11 devnull if(w->body.file->b.nc < 100) /* don't whine if it's too small */
563 b3994ec5 2003-12-11 devnull return TRUE;
564 b3994ec5 2003-12-11 devnull warning(nil, "unnamed file modified\n");
565 b3994ec5 2003-12-11 devnull }
566 b3994ec5 2003-12-11 devnull w->dirty = FALSE;
567 b3994ec5 2003-12-11 devnull return FALSE;
568 b3994ec5 2003-12-11 devnull }
569 b3994ec5 2003-12-11 devnull return TRUE;
570 b3994ec5 2003-12-11 devnull }
571 b3994ec5 2003-12-11 devnull
572 627bae9c 2005-01-04 devnull char*
573 b3994ec5 2003-12-11 devnull winctlprint(Window *w, char *buf, int fonts)
574 b3994ec5 2003-12-11 devnull {
575 627bae9c 2005-01-04 devnull sprint(buf, "%11d %11d %11d %11d %11d ", w->id, w->tag.file->b.nc,
576 b3994ec5 2003-12-11 devnull w->body.file->b.nc, w->isdir, w->dirty);
577 b3994ec5 2003-12-11 devnull if(fonts)
578 627bae9c 2005-01-04 devnull return smprint("%s%11d %q %11d ", buf, Dx(w->body.fr.r),
579 627bae9c 2005-01-04 devnull w->body.reffont->f->name, w->body.fr.maxtab);
580 627bae9c 2005-01-04 devnull return buf;
581 b3994ec5 2003-12-11 devnull }
582 b3994ec5 2003-12-11 devnull
583 b3994ec5 2003-12-11 devnull void
584 b3994ec5 2003-12-11 devnull winevent(Window *w, char *fmt, ...)
585 b3994ec5 2003-12-11 devnull {
586 b3994ec5 2003-12-11 devnull int n;
587 b3994ec5 2003-12-11 devnull char *b;
588 b3994ec5 2003-12-11 devnull Xfid *x;
589 b3994ec5 2003-12-11 devnull va_list arg;
590 b3994ec5 2003-12-11 devnull
591 b3994ec5 2003-12-11 devnull if(w->nopen[QWevent] == 0)
592 b3994ec5 2003-12-11 devnull return;
593 b3994ec5 2003-12-11 devnull if(w->owner == 0)
594 b3994ec5 2003-12-11 devnull error("no window owner");
595 b3994ec5 2003-12-11 devnull va_start(arg, fmt);
596 b3994ec5 2003-12-11 devnull b = vsmprint(fmt, arg);
597 b3994ec5 2003-12-11 devnull va_end(arg);
598 b3994ec5 2003-12-11 devnull if(b == nil)
599 b3994ec5 2003-12-11 devnull error("vsmprint failed");
600 b3994ec5 2003-12-11 devnull n = strlen(b);
601 b3994ec5 2003-12-11 devnull w->events = realloc(w->events, w->nevents+1+n);
602 b3994ec5 2003-12-11 devnull w->events[w->nevents++] = w->owner;
603 b3994ec5 2003-12-11 devnull memmove(w->events+w->nevents, b, n);
604 b3994ec5 2003-12-11 devnull free(b);
605 b3994ec5 2003-12-11 devnull w->nevents += n;
606 b3994ec5 2003-12-11 devnull x = w->eventx;
607 b3994ec5 2003-12-11 devnull if(x){
608 b3994ec5 2003-12-11 devnull w->eventx = nil;
609 b3994ec5 2003-12-11 devnull sendp(x->c, nil);
610 d96da29b 2005-03-14 devnull }
611 d96da29b 2005-03-14 devnull }
612 d96da29b 2005-03-14 devnull
613 d96da29b 2005-03-14 devnull /*
614 d96da29b 2005-03-14 devnull * This is here as a first stab at something.
615 d96da29b 2005-03-14 devnull * Run acme with the -'$' flag to enable it.
616 d96da29b 2005-03-14 devnull *
617 d96da29b 2005-03-14 devnull * This code isn't quite right, in that it doesn't play well with
618 d96da29b 2005-03-14 devnull * the plumber and with other applications. For example:
619 d96da29b 2005-03-14 devnull *
620 d96da29b 2005-03-14 devnull * If the window tag is $home/bin and you execute script, then acme runs
621 d96da29b 2005-03-14 devnull * script in $home/bin, via the shell, so everything is fine. If you do
622 d96da29b 2005-03-14 devnull * execute "echo $home", it too goes to the shell so you see the value
623 d96da29b 2005-03-14 devnull * of $home. And if you right-click on script, then acme plumbs "script"
624 d96da29b 2005-03-14 devnull * in the directory "/home/you/bin", so that works, but if you right-click
625 d96da29b 2005-03-14 devnull * on "$home/bin/script", then what? It's not correct to expand in acme
626 d96da29b 2005-03-14 devnull * since what you're plumbing might be a price tag for all we know. So the
627 d96da29b 2005-03-14 devnull * plumber has to expand it, but in order to do that the plumber should
628 d96da29b 2005-03-14 devnull * probably publish (and allow users to change) the set of variables it is
629 d96da29b 2005-03-14 devnull * using in expansions.
630 d96da29b 2005-03-14 devnull *
631 d96da29b 2005-03-14 devnull * Rob has suggested that a better solution is to make tag lines expand
632 d96da29b 2005-03-14 devnull * automatically to fit the necessary number of lines.
633 d96da29b 2005-03-14 devnull *
634 d96da29b 2005-03-14 devnull * The best solution, of course, is to use nice short path names, but this
635 d96da29b 2005-03-14 devnull * is not always possible.
636 d96da29b 2005-03-14 devnull */
637 d96da29b 2005-03-14 devnull
638 d96da29b 2005-03-14 devnull int
639 d96da29b 2005-03-14 devnull expandenv(Rune **rp, uint *np)
640 d96da29b 2005-03-14 devnull {
641 d96da29b 2005-03-14 devnull char *s, *t;
642 d96da29b 2005-03-14 devnull Rune *p, *r, *q;
643 d96da29b 2005-03-14 devnull uint n, pref;
644 d96da29b 2005-03-14 devnull int nb, nr, slash;
645 d96da29b 2005-03-14 devnull Runestr rs;
646 d96da29b 2005-03-14 devnull
647 d96da29b 2005-03-14 devnull if(!dodollarsigns)
648 d96da29b 2005-03-14 devnull return FALSE;
649 d96da29b 2005-03-14 devnull
650 d96da29b 2005-03-14 devnull r = *rp;
651 d96da29b 2005-03-14 devnull n = *np;
652 d96da29b 2005-03-14 devnull if(n == 0 || r[0] != '$')
653 d96da29b 2005-03-14 devnull return FALSE;
654 d96da29b 2005-03-14 devnull for(p=r+1; *p && *p != '/'; p++)
655 d96da29b 2005-03-14 devnull ;
656 d96da29b 2005-03-14 devnull pref = p-r;
657 d96da29b 2005-03-14 devnull s = runetobyte(r+1, pref-1);
658 d96da29b 2005-03-14 devnull if((t = getenv(s)) == nil){
659 d96da29b 2005-03-14 devnull free(s);
660 d96da29b 2005-03-14 devnull return FALSE;
661 b3994ec5 2003-12-11 devnull }
662 d96da29b 2005-03-14 devnull
663 d96da29b 2005-03-14 devnull q = runemalloc(utflen(t)+(n-pref));
664 d96da29b 2005-03-14 devnull cvttorunes(t, strlen(t), q, &nb, &nr, nil);
665 d96da29b 2005-03-14 devnull assert(nr==utflen(t));
666 d96da29b 2005-03-14 devnull runemove(q+nr, p, n-pref);
667 d96da29b 2005-03-14 devnull free(r);
668 d96da29b 2005-03-14 devnull rs = runestr(q, nr+(n-pref));
669 d96da29b 2005-03-14 devnull slash = rs.nr>0 && q[rs.nr-1] == '/';
670 d96da29b 2005-03-14 devnull rs = cleanrname(rs);
671 d96da29b 2005-03-14 devnull if(slash){
672 d96da29b 2005-03-14 devnull rs.r = runerealloc(rs.r, rs.nr+1);
673 d96da29b 2005-03-14 devnull rs.r[rs.nr++] = '/';
674 d96da29b 2005-03-14 devnull }
675 d96da29b 2005-03-14 devnull *rp = rs.r;
676 d96da29b 2005-03-14 devnull *np = rs.nr;
677 d96da29b 2005-03-14 devnull free(t);
678 d96da29b 2005-03-14 devnull return TRUE;
679 b3994ec5 2003-12-11 devnull }
680 d96da29b 2005-03-14 devnull
681 d96da29b 2005-03-14 devnull extern char **environ;
682 d96da29b 2005-03-14 devnull Rune **runeenv;
683 d96da29b 2005-03-14 devnull
684 d96da29b 2005-03-14 devnull /*
685 d96da29b 2005-03-14 devnull * Weird sort order -- shorter names first,
686 d96da29b 2005-03-14 devnull * prefer lowercase over uppercase ($home over $HOME),
687 d96da29b 2005-03-14 devnull * then do normal string comparison.
688 d96da29b 2005-03-14 devnull */
689 d96da29b 2005-03-14 devnull int
690 d96da29b 2005-03-14 devnull runeenvcmp(const void *va, const void *vb)
691 d96da29b 2005-03-14 devnull {
692 d96da29b 2005-03-14 devnull Rune *a, *b;
693 d96da29b 2005-03-14 devnull int na, nb;
694 d96da29b 2005-03-14 devnull
695 d96da29b 2005-03-14 devnull a = *(Rune**)va;
696 d96da29b 2005-03-14 devnull b = *(Rune**)vb;
697 d96da29b 2005-03-14 devnull na = runestrchr(a, '=') - a;
698 d96da29b 2005-03-14 devnull nb = runestrchr(b, '=') - b;
699 d96da29b 2005-03-14 devnull if(na < nb)
700 d96da29b 2005-03-14 devnull return -1;
701 d96da29b 2005-03-14 devnull if(nb > na)
702 d96da29b 2005-03-14 devnull return 1;
703 d96da29b 2005-03-14 devnull if(na == 0)
704 d96da29b 2005-03-14 devnull return 0;
705 d96da29b 2005-03-14 devnull if(islowerrune(a[0]) && !islowerrune(b[0]))
706 d96da29b 2005-03-14 devnull return -1;
707 d96da29b 2005-03-14 devnull if(islowerrune(b[0]) && !islowerrune(a[0]))
708 d96da29b 2005-03-14 devnull return 1;
709 d96da29b 2005-03-14 devnull return runestrncmp(a, b, na);
710 d96da29b 2005-03-14 devnull }
711 d96da29b 2005-03-14 devnull
712 d96da29b 2005-03-14 devnull void
713 d96da29b 2005-03-14 devnull mkruneenv(void)
714 d96da29b 2005-03-14 devnull {
715 d96da29b 2005-03-14 devnull int i, bad, n, nr;
716 d96da29b 2005-03-14 devnull char *p;
717 d96da29b 2005-03-14 devnull Rune *r, *q;
718 d96da29b 2005-03-14 devnull
719 d96da29b 2005-03-14 devnull n = 0;
720 d96da29b 2005-03-14 devnull for(i=0; environ[i]; i++){
721 d96da29b 2005-03-14 devnull /*
722 d96da29b 2005-03-14 devnull * Ignore some pollution.
723 d96da29b 2005-03-14 devnull */
724 d96da29b 2005-03-14 devnull if(environ[i][0] == '_')
725 d96da29b 2005-03-14 devnull continue;
726 d96da29b 2005-03-14 devnull if(strncmp(environ[i], "PWD=", 4) == 0)
727 d96da29b 2005-03-14 devnull continue;
728 d96da29b 2005-03-14 devnull if(strncmp(environ[i], "OLDPWD=", 7) == 0)
729 d96da29b 2005-03-14 devnull continue;
730 d96da29b 2005-03-14 devnull
731 d96da29b 2005-03-14 devnull /*
732 d96da29b 2005-03-14 devnull * Must be a rooted path.
733 d96da29b 2005-03-14 devnull */
734 d96da29b 2005-03-14 devnull if((p = strchr(environ[i], '=')) == nil || *(p+1) != '/')
735 d96da29b 2005-03-14 devnull continue;
736 d96da29b 2005-03-14 devnull
737 d96da29b 2005-03-14 devnull /*
738 d96da29b 2005-03-14 devnull * Only use the ones that we accept in look - all isfilec
739 d96da29b 2005-03-14 devnull */
740 d96da29b 2005-03-14 devnull bad = 0;
741 d96da29b 2005-03-14 devnull r = bytetorune(environ[i], &nr);
742 d96da29b 2005-03-14 devnull for(q=r; *q != '='; q++)
743 d96da29b 2005-03-14 devnull if(!isfilec(*q)){
744 d96da29b 2005-03-14 devnull free(r);
745 d96da29b 2005-03-14 devnull bad = 1;
746 d96da29b 2005-03-14 devnull break;
747 d96da29b 2005-03-14 devnull }
748 d96da29b 2005-03-14 devnull if(!bad){
749 d96da29b 2005-03-14 devnull runeenv = erealloc(runeenv, (n+1)*sizeof(runeenv[0]));
750 d96da29b 2005-03-14 devnull runeenv[n++] = r;
751 d96da29b 2005-03-14 devnull }
752 d96da29b 2005-03-14 devnull }
753 d96da29b 2005-03-14 devnull runeenv = erealloc(runeenv, (n+1)*sizeof(runeenv[0]));
754 d96da29b 2005-03-14 devnull runeenv[n] = nil;
755 d96da29b 2005-03-14 devnull qsort(runeenv, n, sizeof(runeenv[0]), runeenvcmp);
756 d96da29b 2005-03-14 devnull }
757 d96da29b 2005-03-14 devnull
758 d96da29b 2005-03-14 devnull int
759 d96da29b 2005-03-14 devnull abbrevenv(Rune **rp, uint *np)
760 d96da29b 2005-03-14 devnull {
761 d96da29b 2005-03-14 devnull int i, len, alen;
762 d96da29b 2005-03-14 devnull Rune *r, *p, *q;
763 d96da29b 2005-03-14 devnull uint n;
764 d96da29b 2005-03-14 devnull
765 d96da29b 2005-03-14 devnull if(!dodollarsigns)
766 d96da29b 2005-03-14 devnull return FALSE;
767 d96da29b 2005-03-14 devnull
768 d96da29b 2005-03-14 devnull r = *rp;
769 d96da29b 2005-03-14 devnull n = *np;
770 d96da29b 2005-03-14 devnull if(n == 0 || r[0] != '/')
771 d96da29b 2005-03-14 devnull return FALSE;
772 d96da29b 2005-03-14 devnull
773 d96da29b 2005-03-14 devnull if(runeenv == nil)
774 d96da29b 2005-03-14 devnull mkruneenv();
775 d96da29b 2005-03-14 devnull
776 d96da29b 2005-03-14 devnull for(i=0; runeenv[i]; i++){
777 d96da29b 2005-03-14 devnull p = runestrchr(runeenv[i], '=')+1;
778 d96da29b 2005-03-14 devnull len = runestrlen(p);
779 d96da29b 2005-03-14 devnull if(len <= n && (r[len]==0 || r[len]=='/') && runeeq(r, len, p, len)==TRUE){
780 d96da29b 2005-03-14 devnull alen = (p-1) - runeenv[i];
781 d96da29b 2005-03-14 devnull q = runemalloc(1+alen+n-len);
782 d96da29b 2005-03-14 devnull q[0] = '$';
783 d96da29b 2005-03-14 devnull runemove(q+1, runeenv[i], alen);
784 d96da29b 2005-03-14 devnull runemove(q+1+alen, r+len, n-len);
785 d96da29b 2005-03-14 devnull free(r);
786 d96da29b 2005-03-14 devnull *rp = q;
787 d96da29b 2005-03-14 devnull *np = 1+alen+n-len;
788 d96da29b 2005-03-14 devnull return TRUE;
789 d96da29b 2005-03-14 devnull }
790 d96da29b 2005-03-14 devnull }
791 d96da29b 2005-03-14 devnull return FALSE;
792 d96da29b 2005-03-14 devnull }
793 d96da29b 2005-03-14 devnull