17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier int winid;
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier void
wininit(Window * w,Window * clone,Rectangle r)177dd7cddfSDavid du Colombier wininit(Window *w, Window *clone, Rectangle r)
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier Rectangle r1, br;
207dd7cddfSDavid du Colombier File *f;
217dd7cddfSDavid du Colombier Reffont *rf;
227dd7cddfSDavid du Colombier Rune *rp;
237dd7cddfSDavid du Colombier int nc;
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier w->tag.w = w;
267dd7cddfSDavid du Colombier w->body.w = w;
277dd7cddfSDavid du Colombier w->id = ++winid;
287dd7cddfSDavid du Colombier incref(w);
2906300895SDavid du Colombier if(globalincref)
3006300895SDavid du Colombier incref(w);
317dd7cddfSDavid du Colombier w->ctlfid = ~0;
327dd7cddfSDavid du Colombier w->utflastqid = -1;
337dd7cddfSDavid du Colombier r1 = r;
347dd7cddfSDavid du Colombier r1.max.y = r1.min.y + font->height;
357dd7cddfSDavid du Colombier incref(&reffont);
367dd7cddfSDavid du Colombier f = fileaddtext(nil, &w->tag);
377dd7cddfSDavid du Colombier textinit(&w->tag, f, r1, &reffont, tagcols);
387dd7cddfSDavid du Colombier w->tag.what = Tag;
397dd7cddfSDavid du Colombier /* tag is a copy of the contents, not a tracked image */
407dd7cddfSDavid du Colombier if(clone){
417dd7cddfSDavid du Colombier textdelete(&w->tag, 0, w->tag.file->nc, TRUE);
427dd7cddfSDavid du Colombier nc = clone->tag.file->nc;
437dd7cddfSDavid du Colombier rp = runemalloc(nc);
447dd7cddfSDavid du Colombier bufread(clone->tag.file, 0, rp, nc);
457dd7cddfSDavid du Colombier textinsert(&w->tag, 0, rp, nc, TRUE);
467dd7cddfSDavid du Colombier free(rp);
477dd7cddfSDavid du Colombier filereset(w->tag.file);
487dd7cddfSDavid du Colombier textsetselect(&w->tag, nc, nc);
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier r1 = r;
517dd7cddfSDavid du Colombier r1.min.y += font->height + 1;
527dd7cddfSDavid du Colombier if(r1.max.y < r1.min.y)
537dd7cddfSDavid du Colombier r1.max.y = r1.min.y;
547dd7cddfSDavid du Colombier f = nil;
557dd7cddfSDavid du Colombier if(clone){
567dd7cddfSDavid du Colombier f = clone->body.file;
577dd7cddfSDavid du Colombier w->body.org = clone->body.org;
587dd7cddfSDavid du Colombier w->isscratch = clone->isscratch;
597dd7cddfSDavid du Colombier rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name);
607dd7cddfSDavid du Colombier }else
617dd7cddfSDavid du Colombier rf = rfget(FALSE, FALSE, FALSE, nil);
627dd7cddfSDavid du Colombier f = fileaddtext(f, &w->body);
637dd7cddfSDavid du Colombier w->body.what = Body;
647dd7cddfSDavid du Colombier textinit(&w->body, f, r1, rf, textcols);
657dd7cddfSDavid du Colombier r1.min.y -= 1;
667dd7cddfSDavid du Colombier r1.max.y = r1.min.y+1;
677dd7cddfSDavid du Colombier draw(screen, r1, tagcols[BORD], nil, ZP);
687dd7cddfSDavid du Colombier textscrdraw(&w->body);
697dd7cddfSDavid du Colombier w->r = r;
707dd7cddfSDavid du Colombier w->r.max.y = w->body.r.max.y;
717dd7cddfSDavid du Colombier br.min = w->tag.scrollr.min;
727dd7cddfSDavid du Colombier br.max.x = br.min.x + Dx(button->r);
737dd7cddfSDavid du Colombier br.max.y = br.min.y + Dy(button->r);
747dd7cddfSDavid du Colombier draw(screen, br, button, nil, button->r.min);
757dd7cddfSDavid du Colombier w->filemenu = TRUE;
767dd7cddfSDavid du Colombier w->maxlines = w->body.maxlines;
77a30303efSDavid du Colombier w->autoindent = globalautoindent;
787dd7cddfSDavid du Colombier if(clone){
797dd7cddfSDavid du Colombier w->dirty = clone->dirty;
807dd7cddfSDavid du Colombier textsetselect(&w->body, clone->body.q0, clone->body.q1);
817dd7cddfSDavid du Colombier winsettag(w);
82a30303efSDavid du Colombier w->autoindent = clone->autoindent;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier int
delrunepos(Window * w)87*588d0145SDavid du Colombier delrunepos(Window *w)
88*588d0145SDavid du Colombier {
89*588d0145SDavid du Colombier int n;
90*588d0145SDavid du Colombier Rune rune;
91*588d0145SDavid du Colombier
92*588d0145SDavid du Colombier for(n=0; n<w->tag.file->nc; n++) {
93*588d0145SDavid du Colombier bufread(w->tag.file, n, &rune, 1);
94*588d0145SDavid du Colombier if(rune == ' ')
95*588d0145SDavid du Colombier break;
96*588d0145SDavid du Colombier }
97*588d0145SDavid du Colombier n += 2;
98*588d0145SDavid du Colombier if(n >= w->tag.file->nc)
99*588d0145SDavid du Colombier return -1;
100*588d0145SDavid du Colombier return n;
101*588d0145SDavid du Colombier }
102*588d0145SDavid du Colombier
103*588d0145SDavid du Colombier void
movetodel(Window * w)104*588d0145SDavid du Colombier movetodel(Window *w)
105*588d0145SDavid du Colombier {
106*588d0145SDavid du Colombier int n;
107*588d0145SDavid du Colombier
108*588d0145SDavid du Colombier n = delrunepos(w);
109*588d0145SDavid du Colombier if(n < 0)
110*588d0145SDavid du Colombier return;
111*588d0145SDavid du Colombier moveto(mousectl, addpt(frptofchar(&w->tag, n), Pt(4, w->tag.font->height-4)));
112*588d0145SDavid du Colombier }
113*588d0145SDavid du Colombier
114*588d0145SDavid du Colombier int
winresize(Window * w,Rectangle r,int safe)1157dd7cddfSDavid du Colombier winresize(Window *w, Rectangle r, int safe)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier Rectangle r1;
1187dd7cddfSDavid du Colombier int y;
1197dd7cddfSDavid du Colombier Image *b;
1207dd7cddfSDavid du Colombier Rectangle br;
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier r1 = r;
1237dd7cddfSDavid du Colombier r1.max.y = r1.min.y + font->height;
1247dd7cddfSDavid du Colombier y = r1.max.y;
1257dd7cddfSDavid du Colombier if(!safe || !eqrect(w->tag.r, r1)){
1267dd7cddfSDavid du Colombier y = textresize(&w->tag, r1);
1277dd7cddfSDavid du Colombier b = button;
1287dd7cddfSDavid du Colombier if(w->body.file->mod && !w->isdir && !w->isscratch)
1297dd7cddfSDavid du Colombier b = modbutton;
1307dd7cddfSDavid du Colombier br.min = w->tag.scrollr.min;
1317dd7cddfSDavid du Colombier br.max.x = br.min.x + Dx(b->r);
1327dd7cddfSDavid du Colombier br.max.y = br.min.y + Dy(b->r);
1337dd7cddfSDavid du Colombier draw(screen, br, b, nil, b->r.min);
1347dd7cddfSDavid du Colombier }
1357dd7cddfSDavid du Colombier if(!safe || !eqrect(w->body.r, r1)){
1367dd7cddfSDavid du Colombier if(y+1+font->height > r.max.y){ /* no body */
1377dd7cddfSDavid du Colombier r1.min.y = y;
1387dd7cddfSDavid du Colombier r1.max.y = y;
1397dd7cddfSDavid du Colombier textresize(&w->body, r1);
1407dd7cddfSDavid du Colombier w->r = r;
1417dd7cddfSDavid du Colombier w->r.max.y = y;
1427dd7cddfSDavid du Colombier return y;
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier r1 = r;
1457dd7cddfSDavid du Colombier r1.min.y = y;
1467dd7cddfSDavid du Colombier r1.max.y = y + 1;
1477dd7cddfSDavid du Colombier draw(screen, r1, tagcols[BORD], nil, ZP);
1487dd7cddfSDavid du Colombier r1.min.y = y + 1;
1497dd7cddfSDavid du Colombier r1.max.y = r.max.y;
1507dd7cddfSDavid du Colombier y = textresize(&w->body, r1);
1517dd7cddfSDavid du Colombier w->r = r;
1527dd7cddfSDavid du Colombier w->r.max.y = y;
1537dd7cddfSDavid du Colombier textscrdraw(&w->body);
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines));
1567dd7cddfSDavid du Colombier return w->r.max.y;
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier void
winlock1(Window * w,int owner)1607dd7cddfSDavid du Colombier winlock1(Window *w, int owner)
1617dd7cddfSDavid du Colombier {
1627dd7cddfSDavid du Colombier incref(w);
1637dd7cddfSDavid du Colombier qlock(w);
1647dd7cddfSDavid du Colombier w->owner = owner;
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier void
winlock(Window * w,int owner)1687dd7cddfSDavid du Colombier winlock(Window *w, int owner)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier int i;
1717dd7cddfSDavid du Colombier File *f;
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier f = w->body.file;
1747dd7cddfSDavid du Colombier for(i=0; i<f->ntext; i++)
1757dd7cddfSDavid du Colombier winlock1(f->text[i]->w, owner);
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier void
winunlock(Window * w)1797dd7cddfSDavid du Colombier winunlock(Window *w)
1807dd7cddfSDavid du Colombier {
1817dd7cddfSDavid du Colombier int i;
1827dd7cddfSDavid du Colombier File *f;
1837dd7cddfSDavid du Colombier
184e6f18918SDavid du Colombier /*
185e6f18918SDavid du Colombier * subtle: loop runs backwards to avoid tripping over
186e6f18918SDavid du Colombier * winclose indirectly editing f->text and freeing f
187e6f18918SDavid du Colombier * on the last iteration of the loop.
188e6f18918SDavid du Colombier */
1897dd7cddfSDavid du Colombier f = w->body.file;
190e6f18918SDavid du Colombier for(i=f->ntext-1; i>=0; i--){
1917dd7cddfSDavid du Colombier w = f->text[i]->w;
1927dd7cddfSDavid du Colombier w->owner = 0;
1937dd7cddfSDavid du Colombier qunlock(w);
1947dd7cddfSDavid du Colombier winclose(w);
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier void
winmousebut(Window * w)1997dd7cddfSDavid du Colombier winmousebut(Window *w)
2007dd7cddfSDavid du Colombier {
2017dd7cddfSDavid du Colombier moveto(mousectl, divpt(addpt(w->tag.scrollr.min, w->tag.scrollr.max), 2));
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier void
windirfree(Window * w)2057dd7cddfSDavid du Colombier windirfree(Window *w)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier int i;
2087dd7cddfSDavid du Colombier Dirlist *dl;
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier if(w->isdir){
2117dd7cddfSDavid du Colombier for(i=0; i<w->ndl; i++){
2127dd7cddfSDavid du Colombier dl = w->dlp[i];
2137dd7cddfSDavid du Colombier free(dl->r);
2147dd7cddfSDavid du Colombier free(dl);
2157dd7cddfSDavid du Colombier }
2167dd7cddfSDavid du Colombier free(w->dlp);
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier w->dlp = nil;
2197dd7cddfSDavid du Colombier w->ndl = 0;
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier void
winclose(Window * w)2237dd7cddfSDavid du Colombier winclose(Window *w)
2247dd7cddfSDavid du Colombier {
2257dd7cddfSDavid du Colombier int i;
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier if(decref(w) == 0){
2287dd7cddfSDavid du Colombier windirfree(w);
2297dd7cddfSDavid du Colombier textclose(&w->tag);
2307dd7cddfSDavid du Colombier textclose(&w->body);
2317dd7cddfSDavid du Colombier if(activewin == w)
2327dd7cddfSDavid du Colombier activewin = nil;
2337dd7cddfSDavid du Colombier for(i=0; i<w->nincl; i++)
2347dd7cddfSDavid du Colombier free(w->incl[i]);
2357dd7cddfSDavid du Colombier free(w->incl);
2367dd7cddfSDavid du Colombier free(w->events);
2377dd7cddfSDavid du Colombier free(w);
2387dd7cddfSDavid du Colombier }
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier void
windelete(Window * w)2427dd7cddfSDavid du Colombier windelete(Window *w)
2437dd7cddfSDavid du Colombier {
2447dd7cddfSDavid du Colombier Xfid *x;
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier x = w->eventx;
2477dd7cddfSDavid du Colombier if(x){
2487dd7cddfSDavid du Colombier w->nevents = 0;
2497dd7cddfSDavid du Colombier free(w->events);
2507dd7cddfSDavid du Colombier w->events = nil;
2517dd7cddfSDavid du Colombier w->eventx = nil;
2527dd7cddfSDavid du Colombier sendp(x->c, nil); /* wake him up */
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier }
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier void
winundo(Window * w,int isundo)2577dd7cddfSDavid du Colombier winundo(Window *w, int isundo)
2587dd7cddfSDavid du Colombier {
2597dd7cddfSDavid du Colombier Text *body;
2607dd7cddfSDavid du Colombier int i;
2617dd7cddfSDavid du Colombier File *f;
2627dd7cddfSDavid du Colombier Window *v;
2637dd7cddfSDavid du Colombier
2647dd7cddfSDavid du Colombier w->utflastqid = -1;
2657dd7cddfSDavid du Colombier body = &w->body;
2667dd7cddfSDavid du Colombier fileundo(body->file, isundo, &body->q0, &body->q1);
2679a747e4fSDavid du Colombier textshow(body, body->q0, body->q1, 1);
2687dd7cddfSDavid du Colombier f = body->file;
2697dd7cddfSDavid du Colombier for(i=0; i<f->ntext; i++){
2707dd7cddfSDavid du Colombier v = f->text[i]->w;
2717dd7cddfSDavid du Colombier v->dirty = (f->seq != v->putseq);
2727dd7cddfSDavid du Colombier if(v != w){
2737dd7cddfSDavid du Colombier v->body.q0 = v->body.p0+v->body.org;
2747dd7cddfSDavid du Colombier v->body.q1 = v->body.p1+v->body.org;
2757dd7cddfSDavid du Colombier }
2767dd7cddfSDavid du Colombier }
2777dd7cddfSDavid du Colombier winsettag(w);
2787dd7cddfSDavid du Colombier }
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier void
winsetname(Window * w,Rune * name,int n)2817dd7cddfSDavid du Colombier winsetname(Window *w, Rune *name, int n)
2827dd7cddfSDavid du Colombier {
2837dd7cddfSDavid du Colombier Text *t;
2847dd7cddfSDavid du Colombier Window *v;
2857dd7cddfSDavid du Colombier int i;
2867dd7cddfSDavid du Colombier
2877dd7cddfSDavid du Colombier t = &w->body;
2887dd7cddfSDavid du Colombier if(runeeq(t->file->name, t->file->nname, name, n) == TRUE)
2897dd7cddfSDavid du Colombier return;
2907dd7cddfSDavid du Colombier w->isscratch = FALSE;
2917dd7cddfSDavid du Colombier if(n>=6 && runeeq(L"/guide", 6, name+(n-6), 6))
2927dd7cddfSDavid du Colombier w->isscratch = TRUE;
2937dd7cddfSDavid du Colombier else if(n>=7 && runeeq(L"+Errors", 7, name+(n-7), 7))
2947dd7cddfSDavid du Colombier w->isscratch = TRUE;
2957dd7cddfSDavid du Colombier filesetname(t->file, name, n);
2967dd7cddfSDavid du Colombier for(i=0; i<t->file->ntext; i++){
2977dd7cddfSDavid du Colombier v = t->file->text[i]->w;
2987dd7cddfSDavid du Colombier winsettag(v);
2997dd7cddfSDavid du Colombier v->isscratch = w->isscratch;
3007dd7cddfSDavid du Colombier }
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier void
wintype(Window * w,Text * t,Rune r)3047dd7cddfSDavid du Colombier wintype(Window *w, Text *t, Rune r)
3057dd7cddfSDavid du Colombier {
3067dd7cddfSDavid du Colombier int i;
3077dd7cddfSDavid du Colombier
3087dd7cddfSDavid du Colombier texttype(t, r);
3097dd7cddfSDavid du Colombier if(t->what == Body)
3107dd7cddfSDavid du Colombier for(i=0; i<t->file->ntext; i++)
3117dd7cddfSDavid du Colombier textscrdraw(t->file->text[i]);
3127dd7cddfSDavid du Colombier winsettag(w);
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier
3157dd7cddfSDavid du Colombier void
wincleartag(Window * w)3167dd7cddfSDavid du Colombier wincleartag(Window *w)
3177dd7cddfSDavid du Colombier {
3187dd7cddfSDavid du Colombier int i, n;
3197dd7cddfSDavid du Colombier Rune *r;
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier /* w must be committed */
3227dd7cddfSDavid du Colombier n = w->tag.file->nc;
3237dd7cddfSDavid du Colombier r = runemalloc(n);
3247dd7cddfSDavid du Colombier bufread(w->tag.file, 0, r, n);
3257dd7cddfSDavid du Colombier for(i=0; i<n; i++)
3267dd7cddfSDavid du Colombier if(r[i]==' ' || r[i]=='\t')
3277dd7cddfSDavid du Colombier break;
3287dd7cddfSDavid du Colombier for(; i<n; i++)
3297dd7cddfSDavid du Colombier if(r[i] == '|')
3307dd7cddfSDavid du Colombier break;
3317dd7cddfSDavid du Colombier if(i == n)
3327dd7cddfSDavid du Colombier return;
3337dd7cddfSDavid du Colombier i++;
3347dd7cddfSDavid du Colombier textdelete(&w->tag, i, n, TRUE);
3357dd7cddfSDavid du Colombier free(r);
3367dd7cddfSDavid du Colombier w->tag.file->mod = FALSE;
3377dd7cddfSDavid du Colombier if(w->tag.q0 > i)
3387dd7cddfSDavid du Colombier w->tag.q0 = i;
3397dd7cddfSDavid du Colombier if(w->tag.q1 > i)
3407dd7cddfSDavid du Colombier w->tag.q1 = i;
3417dd7cddfSDavid du Colombier textsetselect(&w->tag, w->tag.q0, w->tag.q1);
3427dd7cddfSDavid du Colombier }
3437dd7cddfSDavid du Colombier
3447dd7cddfSDavid du Colombier void
winsettag1(Window * w)3457dd7cddfSDavid du Colombier winsettag1(Window *w)
3467dd7cddfSDavid du Colombier {
3477dd7cddfSDavid du Colombier int i, j, k, n, bar, dirty;
3487dd7cddfSDavid du Colombier Rune *new, *old, *r;
3497dd7cddfSDavid du Colombier Image *b;
3507dd7cddfSDavid du Colombier uint q0, q1;
3517dd7cddfSDavid du Colombier Rectangle br;
3527dd7cddfSDavid du Colombier
3537dd7cddfSDavid du Colombier /* there are races that get us here with stuff in the tag cache, so we take extra care to sync it */
3547dd7cddfSDavid du Colombier if(w->tag.ncache!=0 || w->tag.file->mod)
3557dd7cddfSDavid du Colombier wincommit(w, &w->tag); /* check file name; also guarantees we can modify tag contents */
3567dd7cddfSDavid du Colombier old = runemalloc(w->tag.file->nc+1);
3577dd7cddfSDavid du Colombier bufread(w->tag.file, 0, old, w->tag.file->nc);
3587dd7cddfSDavid du Colombier old[w->tag.file->nc] = '\0';
3597dd7cddfSDavid du Colombier for(i=0; i<w->tag.file->nc; i++)
3607dd7cddfSDavid du Colombier if(old[i]==' ' || old[i]=='\t')
3617dd7cddfSDavid du Colombier break;
3627dd7cddfSDavid du Colombier if(runeeq(old, i, w->body.file->name, w->body.file->nname) == FALSE){
3637dd7cddfSDavid du Colombier textdelete(&w->tag, 0, i, TRUE);
3647dd7cddfSDavid du Colombier textinsert(&w->tag, 0, w->body.file->name, w->body.file->nname, TRUE);
3657dd7cddfSDavid du Colombier free(old);
3667dd7cddfSDavid du Colombier old = runemalloc(w->tag.file->nc+1);
3677dd7cddfSDavid du Colombier bufread(w->tag.file, 0, old, w->tag.file->nc);
3687dd7cddfSDavid du Colombier old[w->tag.file->nc] = '\0';
3697dd7cddfSDavid du Colombier }
3707dd7cddfSDavid du Colombier new = runemalloc(w->body.file->nname+100);
3717dd7cddfSDavid du Colombier i = 0;
3727dd7cddfSDavid du Colombier runemove(new+i, w->body.file->name, w->body.file->nname);
3737dd7cddfSDavid du Colombier i += w->body.file->nname;
3747dd7cddfSDavid du Colombier runemove(new+i, L" Del Snarf", 10);
3757dd7cddfSDavid du Colombier i += 10;
3767dd7cddfSDavid du Colombier if(w->filemenu){
3777dd7cddfSDavid du Colombier if(w->body.file->delta.nc>0 || w->body.ncache){
3787dd7cddfSDavid du Colombier runemove(new+i, L" Undo", 5);
3797dd7cddfSDavid du Colombier i += 5;
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier if(w->body.file->epsilon.nc > 0){
3827dd7cddfSDavid du Colombier runemove(new+i, L" Redo", 5);
3837dd7cddfSDavid du Colombier i += 5;
3847dd7cddfSDavid du Colombier }
3857dd7cddfSDavid du Colombier dirty = w->body.file->nname && (w->body.ncache || w->body.file->seq!=w->putseq);
3867dd7cddfSDavid du Colombier if(!w->isdir && dirty){
3877dd7cddfSDavid du Colombier runemove(new+i, L" Put", 4);
3887dd7cddfSDavid du Colombier i += 4;
3897dd7cddfSDavid du Colombier }
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier if(w->isdir){
3927dd7cddfSDavid du Colombier runemove(new+i, L" Get", 4);
3937dd7cddfSDavid du Colombier i += 4;
3947dd7cddfSDavid du Colombier }
3957dd7cddfSDavid du Colombier runemove(new+i, L" |", 2);
3967dd7cddfSDavid du Colombier i += 2;
39759cc4ca5SDavid du Colombier r = runestrchr(old, '|');
3987dd7cddfSDavid du Colombier if(r)
3997dd7cddfSDavid du Colombier k = r-old+1;
4007dd7cddfSDavid du Colombier else{
4017dd7cddfSDavid du Colombier k = w->tag.file->nc;
4027dd7cddfSDavid du Colombier if(w->body.file->seq == 0){
4037dd7cddfSDavid du Colombier runemove(new+i, L" Look ", 6);
4047dd7cddfSDavid du Colombier i += 6;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier }
4077dd7cddfSDavid du Colombier if(runeeq(new, i, old, k) == FALSE){
4087dd7cddfSDavid du Colombier n = k;
4097dd7cddfSDavid du Colombier if(n > i)
4107dd7cddfSDavid du Colombier n = i;
4117dd7cddfSDavid du Colombier for(j=0; j<n; j++)
4127dd7cddfSDavid du Colombier if(old[j] != new[j])
4137dd7cddfSDavid du Colombier break;
4147dd7cddfSDavid du Colombier q0 = w->tag.q0;
4157dd7cddfSDavid du Colombier q1 = w->tag.q1;
4167dd7cddfSDavid du Colombier textdelete(&w->tag, j, k, TRUE);
4177dd7cddfSDavid du Colombier textinsert(&w->tag, j, new+j, i-j, TRUE);
4187dd7cddfSDavid du Colombier /* try to preserve user selection */
41959cc4ca5SDavid du Colombier r = runestrchr(old, '|');
4207dd7cddfSDavid du Colombier if(r){
4217dd7cddfSDavid du Colombier bar = r-old;
4227dd7cddfSDavid du Colombier if(q0 > bar){
42359cc4ca5SDavid du Colombier bar = (runestrchr(new, '|')-new)-bar;
4247dd7cddfSDavid du Colombier w->tag.q0 = q0+bar;
4257dd7cddfSDavid du Colombier w->tag.q1 = q1+bar;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier }
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier free(old);
4307dd7cddfSDavid du Colombier free(new);
4317dd7cddfSDavid du Colombier w->tag.file->mod = FALSE;
4327dd7cddfSDavid du Colombier n = w->tag.file->nc+w->tag.ncache;
4337dd7cddfSDavid du Colombier if(w->tag.q0 > n)
4347dd7cddfSDavid du Colombier w->tag.q0 = n;
4357dd7cddfSDavid du Colombier if(w->tag.q1 > n)
4367dd7cddfSDavid du Colombier w->tag.q1 = n;
4377dd7cddfSDavid du Colombier textsetselect(&w->tag, w->tag.q0, w->tag.q1);
4387dd7cddfSDavid du Colombier b = button;
4397dd7cddfSDavid du Colombier if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache))
4407dd7cddfSDavid du Colombier b = modbutton;
4417dd7cddfSDavid du Colombier br.min = w->tag.scrollr.min;
4427dd7cddfSDavid du Colombier br.max.x = br.min.x + Dx(b->r);
4437dd7cddfSDavid du Colombier br.max.y = br.min.y + Dy(b->r);
4447dd7cddfSDavid du Colombier draw(screen, br, b, nil, b->r.min);
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier
4477dd7cddfSDavid du Colombier void
winsettag(Window * w)4487dd7cddfSDavid du Colombier winsettag(Window *w)
4497dd7cddfSDavid du Colombier {
4507dd7cddfSDavid du Colombier int i;
4517dd7cddfSDavid du Colombier File *f;
4527dd7cddfSDavid du Colombier Window *v;
4537dd7cddfSDavid du Colombier
4547dd7cddfSDavid du Colombier f = w->body.file;
4557dd7cddfSDavid du Colombier for(i=0; i<f->ntext; i++){
4567dd7cddfSDavid du Colombier v = f->text[i]->w;
4577dd7cddfSDavid du Colombier if(v->col->safe || v->body.maxlines>0)
4587dd7cddfSDavid du Colombier winsettag1(v);
4597dd7cddfSDavid du Colombier }
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier
4627dd7cddfSDavid du Colombier void
wincommit(Window * w,Text * t)4637dd7cddfSDavid du Colombier wincommit(Window *w, Text *t)
4647dd7cddfSDavid du Colombier {
4657dd7cddfSDavid du Colombier Rune *r;
4667dd7cddfSDavid du Colombier int i;
4677dd7cddfSDavid du Colombier File *f;
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier textcommit(t, TRUE);
4707dd7cddfSDavid du Colombier f = t->file;
4717dd7cddfSDavid du Colombier if(f->ntext > 1)
4727dd7cddfSDavid du Colombier for(i=0; i<f->ntext; i++)
4737dd7cddfSDavid du Colombier textcommit(f->text[i], FALSE); /* no-op for t */
4747dd7cddfSDavid du Colombier if(t->what == Body)
4757dd7cddfSDavid du Colombier return;
4767dd7cddfSDavid du Colombier r = runemalloc(w->tag.file->nc);
4777dd7cddfSDavid du Colombier bufread(w->tag.file, 0, r, w->tag.file->nc);
4787dd7cddfSDavid du Colombier for(i=0; i<w->tag.file->nc; i++)
4797dd7cddfSDavid du Colombier if(r[i]==' ' || r[i]=='\t')
4807dd7cddfSDavid du Colombier break;
4817dd7cddfSDavid du Colombier if(runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE){
4827dd7cddfSDavid du Colombier seq++;
4837dd7cddfSDavid du Colombier filemark(w->body.file);
4847dd7cddfSDavid du Colombier w->body.file->mod = TRUE;
4857dd7cddfSDavid du Colombier w->dirty = TRUE;
4867dd7cddfSDavid du Colombier winsetname(w, r, i);
4877dd7cddfSDavid du Colombier winsettag(w);
4887dd7cddfSDavid du Colombier }
4897dd7cddfSDavid du Colombier free(r);
4907dd7cddfSDavid du Colombier }
4917dd7cddfSDavid du Colombier
4927dd7cddfSDavid du Colombier void
winaddincl(Window * w,Rune * r,int n)4937dd7cddfSDavid du Colombier winaddincl(Window *w, Rune *r, int n)
4947dd7cddfSDavid du Colombier {
4957dd7cddfSDavid du Colombier char *a;
4969a747e4fSDavid du Colombier Dir *d;
4977dd7cddfSDavid du Colombier Runestr rs;
4987dd7cddfSDavid du Colombier
4997dd7cddfSDavid du Colombier a = runetobyte(r, n);
5009a747e4fSDavid du Colombier d = dirstat(a);
5019a747e4fSDavid du Colombier if(d == nil){
5027dd7cddfSDavid du Colombier if(a[0] == '/')
5037dd7cddfSDavid du Colombier goto Rescue;
5047dd7cddfSDavid du Colombier rs = dirname(&w->body, r, n);
5057dd7cddfSDavid du Colombier r = rs.r;
5067dd7cddfSDavid du Colombier n = rs.nr;
5077dd7cddfSDavid du Colombier free(a);
5087dd7cddfSDavid du Colombier a = runetobyte(r, n);
5099a747e4fSDavid du Colombier d = dirstat(a);
5109a747e4fSDavid du Colombier if(d == nil)
5117dd7cddfSDavid du Colombier goto Rescue;
5127dd7cddfSDavid du Colombier r = runerealloc(r, n+1);
5137dd7cddfSDavid du Colombier r[n] = 0;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier free(a);
5169a747e4fSDavid du Colombier if((d->qid.type&QTDIR) == 0){
5179a747e4fSDavid du Colombier free(d);
5187dd7cddfSDavid du Colombier warning(nil, "%s: not a directory\n", a);
5197dd7cddfSDavid du Colombier free(r);
5207dd7cddfSDavid du Colombier return;
5217dd7cddfSDavid du Colombier }
5229a747e4fSDavid du Colombier free(d);
5237dd7cddfSDavid du Colombier w->nincl++;
5247dd7cddfSDavid du Colombier w->incl = realloc(w->incl, w->nincl*sizeof(Rune*));
5257dd7cddfSDavid du Colombier memmove(w->incl+1, w->incl, (w->nincl-1)*sizeof(Rune*));
5267dd7cddfSDavid du Colombier w->incl[0] = runemalloc(n+1);
5277dd7cddfSDavid du Colombier runemove(w->incl[0], r, n);
5287dd7cddfSDavid du Colombier free(r);
5297dd7cddfSDavid du Colombier return;
5307dd7cddfSDavid du Colombier
5317dd7cddfSDavid du Colombier Rescue:
5327dd7cddfSDavid du Colombier warning(nil, "%s: %r\n", a);
5337dd7cddfSDavid du Colombier free(r);
5347dd7cddfSDavid du Colombier free(a);
5357dd7cddfSDavid du Colombier return;
5367dd7cddfSDavid du Colombier }
5377dd7cddfSDavid du Colombier
5387dd7cddfSDavid du Colombier int
winclean(Window * w,int conservative)5397dd7cddfSDavid du Colombier winclean(Window *w, int conservative) /* as it stands, conservative is always TRUE */
5407dd7cddfSDavid du Colombier {
5417dd7cddfSDavid du Colombier if(w->isscratch || w->isdir) /* don't whine if it's a guide file, error window, etc. */
5427dd7cddfSDavid du Colombier return TRUE;
5437dd7cddfSDavid du Colombier if(!conservative && w->nopen[QWevent]>0)
5447dd7cddfSDavid du Colombier return TRUE;
5457dd7cddfSDavid du Colombier if(w->dirty){
5467dd7cddfSDavid du Colombier if(w->body.file->nname)
5477dd7cddfSDavid du Colombier warning(nil, "%.*S modified\n", w->body.file->nname, w->body.file->name);
5487dd7cddfSDavid du Colombier else{
5497dd7cddfSDavid du Colombier if(w->body.file->nc < 100) /* don't whine if it's too small */
5507dd7cddfSDavid du Colombier return TRUE;
5517dd7cddfSDavid du Colombier warning(nil, "unnamed file modified\n");
5527dd7cddfSDavid du Colombier }
5537dd7cddfSDavid du Colombier w->dirty = FALSE;
5547dd7cddfSDavid du Colombier return FALSE;
5557dd7cddfSDavid du Colombier }
5567dd7cddfSDavid du Colombier return TRUE;
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier
5598a2c5ad0SDavid du Colombier char*
winctlprint(Window * w,char * buf,int fonts)5609a747e4fSDavid du Colombier winctlprint(Window *w, char *buf, int fonts)
5617dd7cddfSDavid du Colombier {
5628a2c5ad0SDavid du Colombier sprint(buf, "%11d %11d %11d %11d %11d ", w->id, w->tag.file->nc,
5637dd7cddfSDavid du Colombier w->body.file->nc, w->isdir, w->dirty);
5649a747e4fSDavid du Colombier if(fonts)
5658a2c5ad0SDavid du Colombier return smprint("%s%11d %q %11d " , buf, Dx(w->body.r),
5668a2c5ad0SDavid du Colombier w->body.reffont->f->name, w->body.maxtab);
5678a2c5ad0SDavid du Colombier return buf;
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier void
winevent(Window * w,char * fmt,...)5717dd7cddfSDavid du Colombier winevent(Window *w, char *fmt, ...)
5727dd7cddfSDavid du Colombier {
5737dd7cddfSDavid du Colombier int n;
5747dd7cddfSDavid du Colombier char *b;
5757dd7cddfSDavid du Colombier Xfid *x;
5767dd7cddfSDavid du Colombier va_list arg;
5777dd7cddfSDavid du Colombier
5787dd7cddfSDavid du Colombier if(w->nopen[QWevent] == 0)
5797dd7cddfSDavid du Colombier return;
5807dd7cddfSDavid du Colombier if(w->owner == 0)
5817dd7cddfSDavid du Colombier error("no window owner");
5827dd7cddfSDavid du Colombier va_start(arg, fmt);
5839a747e4fSDavid du Colombier b = vsmprint(fmt, arg);
5847dd7cddfSDavid du Colombier va_end(arg);
5859a747e4fSDavid du Colombier if(b == nil)
5869a747e4fSDavid du Colombier error("vsmprint failed");
5879a747e4fSDavid du Colombier n = strlen(b);
5887dd7cddfSDavid du Colombier w->events = realloc(w->events, w->nevents+1+n);
5897dd7cddfSDavid du Colombier w->events[w->nevents++] = w->owner;
5907dd7cddfSDavid du Colombier memmove(w->events+w->nevents, b, n);
5919a747e4fSDavid du Colombier free(b);
5927dd7cddfSDavid du Colombier w->nevents += n;
5937dd7cddfSDavid du Colombier x = w->eventx;
5947dd7cddfSDavid du Colombier if(x){
5957dd7cddfSDavid du Colombier w->eventx = nil;
5967dd7cddfSDavid du Colombier sendp(x->c, nil);
5977dd7cddfSDavid du Colombier }
5987dd7cddfSDavid du Colombier }
599