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 static Point prevmouse;
157dd7cddfSDavid du Colombier static Window *mousew;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier void
cvttorunes(char * p,int n,Rune * r,int * nb,int * nr,int * nulls)187dd7cddfSDavid du Colombier cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier uchar *q;
217dd7cddfSDavid du Colombier Rune *s;
227dd7cddfSDavid du Colombier int j, w;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier /*
257dd7cddfSDavid du Colombier * Always guaranteed that n bytes may be interpreted
267dd7cddfSDavid du Colombier * without worrying about partial runes. This may mean
277dd7cddfSDavid du Colombier * reading up to UTFmax-1 more bytes than n; the caller
287dd7cddfSDavid du Colombier * knows this. If n is a firm limit, the caller should
297dd7cddfSDavid du Colombier * set p[n] = 0.
307dd7cddfSDavid du Colombier */
317dd7cddfSDavid du Colombier q = (uchar*)p;
327dd7cddfSDavid du Colombier s = r;
337dd7cddfSDavid du Colombier for(j=0; j<n; j+=w){
347dd7cddfSDavid du Colombier if(*q < Runeself){
357dd7cddfSDavid du Colombier w = 1;
367dd7cddfSDavid du Colombier *s = *q++;
377dd7cddfSDavid du Colombier }else{
387dd7cddfSDavid du Colombier w = chartorune(s, (char*)q);
397dd7cddfSDavid du Colombier q += w;
407dd7cddfSDavid du Colombier }
417dd7cddfSDavid du Colombier if(*s)
427dd7cddfSDavid du Colombier s++;
437dd7cddfSDavid du Colombier else if(nulls)
447dd7cddfSDavid du Colombier *nulls = TRUE;
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier *nb = (char*)q-p;
477dd7cddfSDavid du Colombier *nr = s-r;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier void
error(char * s)517dd7cddfSDavid du Colombier error(char *s)
527dd7cddfSDavid du Colombier {
537dd7cddfSDavid du Colombier fprint(2, "acme: %s: %r\n", s);
547dd7cddfSDavid du Colombier remove(acmeerrorfile);
557dd7cddfSDavid du Colombier abort();
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier Window*
errorwin1(Rune * dir,int ndir,Rune ** incl,int nincl)593ff48bf5SDavid du Colombier errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
607dd7cddfSDavid du Colombier {
617dd7cddfSDavid du Colombier Window *w;
627dd7cddfSDavid du Colombier Rune *r;
637dd7cddfSDavid du Colombier int i, n;
647dd7cddfSDavid du Colombier
65a3b78ba5SDavid du Colombier r = runemalloc(ndir+8);
6606300895SDavid du Colombier if(n = ndir){ /* assign = */
677dd7cddfSDavid du Colombier runemove(r, dir, ndir);
6806300895SDavid du Colombier r[n++] = L'/';
6906300895SDavid du Colombier }
7006300895SDavid du Colombier runemove(r+n, L"+Errors", 7);
7106300895SDavid du Colombier n += 7;
727dd7cddfSDavid du Colombier w = lookfile(r, n);
737dd7cddfSDavid du Colombier if(w == nil){
74d9306527SDavid du Colombier if(row.ncol == 0)
75d9306527SDavid du Colombier if(rowadd(&row, nil, -1) == nil)
76d9306527SDavid du Colombier error("can't create column to make error window");
777dd7cddfSDavid du Colombier w = coladd(row.col[row.ncol-1], nil, nil, -1);
787dd7cddfSDavid du Colombier w->filemenu = FALSE;
797dd7cddfSDavid du Colombier winsetname(w, r, n);
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier free(r);
827dd7cddfSDavid du Colombier for(i=nincl; --i>=0; ){
837dd7cddfSDavid du Colombier n = runestrlen(incl[i]);
847dd7cddfSDavid du Colombier r = runemalloc(n);
857dd7cddfSDavid du Colombier runemove(r, incl[i], n);
867dd7cddfSDavid du Colombier winaddincl(w, r, n);
877dd7cddfSDavid du Colombier }
884fec87e5SDavid du Colombier w->autoindent = globalautoindent;
897dd7cddfSDavid du Colombier return w;
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier
923ff48bf5SDavid du Colombier /* make new window, if necessary; return with it locked */
933ff48bf5SDavid du Colombier Window*
errorwin(Mntdir * md,int owner)944fec87e5SDavid du Colombier errorwin(Mntdir *md, int owner)
953ff48bf5SDavid du Colombier {
963ff48bf5SDavid du Colombier Window *w;
973ff48bf5SDavid du Colombier
983ff48bf5SDavid du Colombier for(;;){
993ff48bf5SDavid du Colombier if(md == nil)
1003ff48bf5SDavid du Colombier w = errorwin1(nil, 0, nil, 0);
1013ff48bf5SDavid du Colombier else
1023ff48bf5SDavid du Colombier w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
1033ff48bf5SDavid du Colombier winlock(w, owner);
1043ff48bf5SDavid du Colombier if(w->col != nil)
1053ff48bf5SDavid du Colombier break;
1063ff48bf5SDavid du Colombier /* window was deleted too fast */
1073ff48bf5SDavid du Colombier winunlock(w);
1083ff48bf5SDavid du Colombier }
1093ff48bf5SDavid du Colombier return w;
1103ff48bf5SDavid du Colombier }
1113ff48bf5SDavid du Colombier
112673c3d8aSDavid du Colombier /*
113673c3d8aSDavid du Colombier * Incoming window should be locked.
114673c3d8aSDavid du Colombier * It will be unlocked and returned window
115673c3d8aSDavid du Colombier * will be locked in its place.
116673c3d8aSDavid du Colombier */
117673c3d8aSDavid du Colombier Window*
errorwinforwin(Window * w)118673c3d8aSDavid du Colombier errorwinforwin(Window *w)
119673c3d8aSDavid du Colombier {
120673c3d8aSDavid du Colombier int i, n, nincl, owner;
121673c3d8aSDavid du Colombier Rune **incl;
122673c3d8aSDavid du Colombier Runestr dir;
123673c3d8aSDavid du Colombier Text *t;
124673c3d8aSDavid du Colombier
125673c3d8aSDavid du Colombier t = &w->body;
126673c3d8aSDavid du Colombier dir = dirname(t, nil, 0);
127673c3d8aSDavid du Colombier if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
128673c3d8aSDavid du Colombier free(dir.r);
129673c3d8aSDavid du Colombier dir.r = nil;
130673c3d8aSDavid du Colombier dir.nr = 0;
131673c3d8aSDavid du Colombier }
132673c3d8aSDavid du Colombier incl = nil;
133673c3d8aSDavid du Colombier nincl = w->nincl;
134673c3d8aSDavid du Colombier if(nincl > 0){
135673c3d8aSDavid du Colombier incl = emalloc(nincl*sizeof(Rune*));
136673c3d8aSDavid du Colombier for(i=0; i<nincl; i++){
137673c3d8aSDavid du Colombier n = runestrlen(w->incl[i]);
138673c3d8aSDavid du Colombier incl[i] = runemalloc(n+1);
139673c3d8aSDavid du Colombier runemove(incl[i], w->incl[i], n);
140673c3d8aSDavid du Colombier }
141673c3d8aSDavid du Colombier }
142673c3d8aSDavid du Colombier owner = w->owner;
143673c3d8aSDavid du Colombier winunlock(w);
144673c3d8aSDavid du Colombier for(;;){
145673c3d8aSDavid du Colombier w = errorwin1(dir.r, dir.nr, incl, nincl);
146673c3d8aSDavid du Colombier winlock(w, owner);
147673c3d8aSDavid du Colombier if(w->col != nil)
148673c3d8aSDavid du Colombier break;
149673c3d8aSDavid du Colombier /* window deleted too fast */
150673c3d8aSDavid du Colombier winunlock(w);
151673c3d8aSDavid du Colombier }
152673c3d8aSDavid du Colombier return w;
153673c3d8aSDavid du Colombier }
154673c3d8aSDavid du Colombier
1554fec87e5SDavid du Colombier typedef struct Warning Warning;
1564fec87e5SDavid du Colombier
1574fec87e5SDavid du Colombier struct Warning{
1584fec87e5SDavid du Colombier Mntdir *md;
1594fec87e5SDavid du Colombier Buffer buf;
1604fec87e5SDavid du Colombier Warning *next;
1614fec87e5SDavid du Colombier };
1624fec87e5SDavid du Colombier
1634fec87e5SDavid du Colombier static Warning *warnings;
1644fec87e5SDavid du Colombier
1654fec87e5SDavid du Colombier static
1664fec87e5SDavid du Colombier void
addwarningtext(Mntdir * md,Rune * r,int nr)1674fec87e5SDavid du Colombier addwarningtext(Mntdir *md, Rune *r, int nr)
1687dd7cddfSDavid du Colombier {
1694fec87e5SDavid du Colombier Warning *warn;
1704fec87e5SDavid du Colombier
1714fec87e5SDavid du Colombier for(warn = warnings; warn; warn=warn->next){
1724fec87e5SDavid du Colombier if(warn->md == md){
1734fec87e5SDavid du Colombier bufinsert(&warn->buf, warn->buf.nc, r, nr);
1744fec87e5SDavid du Colombier return;
1754fec87e5SDavid du Colombier }
1764fec87e5SDavid du Colombier }
1774fec87e5SDavid du Colombier warn = emalloc(sizeof(Warning));
1784fec87e5SDavid du Colombier warn->next = warnings;
1793df12bc6SDavid du Colombier warn->md = md;
1803df12bc6SDavid du Colombier if(md)
1813df12bc6SDavid du Colombier fsysincid(md);
1824fec87e5SDavid du Colombier warnings = warn;
1834fec87e5SDavid du Colombier bufinsert(&warn->buf, 0, r, nr);
1845316891fSDavid du Colombier nbsendp(cwarn, 0);
1854fec87e5SDavid du Colombier }
1864fec87e5SDavid du Colombier
1874fec87e5SDavid du Colombier /* called while row is locked */
1884fec87e5SDavid du Colombier void
flushwarnings(void)1894fec87e5SDavid du Colombier flushwarnings(void)
1904fec87e5SDavid du Colombier {
1914fec87e5SDavid du Colombier Warning *warn, *next;
1927dd7cddfSDavid du Colombier Window *w;
1937dd7cddfSDavid du Colombier Text *t;
1944fec87e5SDavid du Colombier int owner, nr, q0, n;
1954fec87e5SDavid du Colombier Rune *r;
1969a747e4fSDavid du Colombier
1974fec87e5SDavid du Colombier for(warn=warnings; warn; warn=next) {
1984fec87e5SDavid du Colombier w = errorwin(warn->md, 'E');
1997dd7cddfSDavid du Colombier t = &w->body;
2007dd7cddfSDavid du Colombier owner = w->owner;
2017dd7cddfSDavid du Colombier if(owner == 0)
2027dd7cddfSDavid du Colombier w->owner = 'E';
2037dd7cddfSDavid du Colombier wincommit(w, t);
2044fec87e5SDavid du Colombier /*
2054fec87e5SDavid du Colombier * Most commands don't generate much output. For instance,
2064fec87e5SDavid du Colombier * Edit ,>cat goes through /dev/cons and is already in blocks
2074fec87e5SDavid du Colombier * because of the i/o system, but a few can. Edit ,p will
2084fec87e5SDavid du Colombier * put the entire result into a single hunk. So it's worth doing
2094fec87e5SDavid du Colombier * this in blocks (and putting the text in a buffer in the first
2104fec87e5SDavid du Colombier * place), to avoid a big memory footprint.
2114fec87e5SDavid du Colombier */
2124fec87e5SDavid du Colombier r = fbufalloc();
2134fec87e5SDavid du Colombier q0 = t->file->nc;
2144fec87e5SDavid du Colombier for(n = 0; n < warn->buf.nc; n += nr){
2154fec87e5SDavid du Colombier nr = warn->buf.nc - n;
2164fec87e5SDavid du Colombier if(nr > RBUFSIZE)
2174fec87e5SDavid du Colombier nr = RBUFSIZE;
2184fec87e5SDavid du Colombier bufread(&warn->buf, n, r, nr);
2194fec87e5SDavid du Colombier textbsinsert(t, t->file->nc, r, nr, TRUE, &nr);
2204fec87e5SDavid du Colombier }
2214fec87e5SDavid du Colombier textshow(t, q0, t->file->nc, 1);
2224fec87e5SDavid du Colombier free(r);
2237dd7cddfSDavid du Colombier winsettag(t->w);
2247dd7cddfSDavid du Colombier textscrdraw(t);
2257dd7cddfSDavid du Colombier w->owner = owner;
2267dd7cddfSDavid du Colombier w->dirty = FALSE;
2277dd7cddfSDavid du Colombier winunlock(w);
2284fec87e5SDavid du Colombier bufclose(&warn->buf);
2294fec87e5SDavid du Colombier next = warn->next;
2303df12bc6SDavid du Colombier if(warn->md)
2313df12bc6SDavid du Colombier fsysdelid(warn->md);
2324fec87e5SDavid du Colombier free(warn);
2334fec87e5SDavid du Colombier }
2344fec87e5SDavid du Colombier warnings = nil;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier
237ef9eff0bSDavid du Colombier void
warning(Mntdir * md,char * s,...)238ef9eff0bSDavid du Colombier warning(Mntdir *md, char *s, ...)
239ef9eff0bSDavid du Colombier {
240ef9eff0bSDavid du Colombier Rune *r;
241ef9eff0bSDavid du Colombier va_list arg;
242ef9eff0bSDavid du Colombier
243ef9eff0bSDavid du Colombier va_start(arg, s);
244ef9eff0bSDavid du Colombier r = runevsmprint(s, arg);
245ef9eff0bSDavid du Colombier va_end(arg);
2464fec87e5SDavid du Colombier if(r == nil)
2474fec87e5SDavid du Colombier error("runevsmprint failed");
2484fec87e5SDavid du Colombier addwarningtext(md, r, runestrlen(r));
249b3cbc4e1SDavid du Colombier free(r);
250ef9eff0bSDavid du Colombier }
251ef9eff0bSDavid du Colombier
2527dd7cddfSDavid du Colombier int
runeeq(Rune * s1,uint n1,Rune * s2,uint n2)2537dd7cddfSDavid du Colombier runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
2547dd7cddfSDavid du Colombier {
2557dd7cddfSDavid du Colombier if(n1 != n2)
2567dd7cddfSDavid du Colombier return FALSE;
2577dd7cddfSDavid du Colombier return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier uint
min(uint a,uint b)2617dd7cddfSDavid du Colombier min(uint a, uint b)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier if(a < b)
2647dd7cddfSDavid du Colombier return a;
2657dd7cddfSDavid du Colombier return b;
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier uint
max(uint a,uint b)2697dd7cddfSDavid du Colombier max(uint a, uint b)
2707dd7cddfSDavid du Colombier {
2717dd7cddfSDavid du Colombier if(a > b)
2727dd7cddfSDavid du Colombier return a;
2737dd7cddfSDavid du Colombier return b;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier char*
runetobyte(Rune * r,int n)2777dd7cddfSDavid du Colombier runetobyte(Rune *r, int n)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier char *s;
2807dd7cddfSDavid du Colombier
28134e04225SDavid du Colombier if(r == nil)
2827dd7cddfSDavid du Colombier return nil;
2837dd7cddfSDavid du Colombier s = emalloc(n*UTFmax+1);
28459cc4ca5SDavid du Colombier setmalloctag(s, getcallerpc(&r));
2857dd7cddfSDavid du Colombier snprint(s, n*UTFmax+1, "%.*S", n, r);
2867dd7cddfSDavid du Colombier return s;
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier
2897dd7cddfSDavid du Colombier Rune*
bytetorune(char * s,int * ip)2907dd7cddfSDavid du Colombier bytetorune(char *s, int *ip)
2917dd7cddfSDavid du Colombier {
2927dd7cddfSDavid du Colombier Rune *r;
2937dd7cddfSDavid du Colombier int nb, nr;
2947dd7cddfSDavid du Colombier
2957dd7cddfSDavid du Colombier nb = strlen(s);
2967dd7cddfSDavid du Colombier r = runemalloc(nb+1);
2977dd7cddfSDavid du Colombier cvttorunes(s, nb, r, &nb, &nr, nil);
2987dd7cddfSDavid du Colombier r[nr] = '\0';
2997dd7cddfSDavid du Colombier *ip = nr;
3007dd7cddfSDavid du Colombier return r;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier int
isalnum(Rune c)3047dd7cddfSDavid du Colombier isalnum(Rune c)
3057dd7cddfSDavid du Colombier {
3067dd7cddfSDavid du Colombier /*
3077dd7cddfSDavid du Colombier * Hard to get absolutely right. Use what we know about ASCII
3087dd7cddfSDavid du Colombier * and assume anything above the Latin control characters is
3097dd7cddfSDavid du Colombier * potentially an alphanumeric.
310c4cb05bbSDavid du Colombier *
311c4cb05bbSDavid du Colombier * Treat 0xA0 (non-breaking space) as a special alphanumeric
312c4cb05bbSDavid du Colombier * character [sape]
3137dd7cddfSDavid du Colombier */
3147dd7cddfSDavid du Colombier if(c <= ' ')
3157dd7cddfSDavid du Colombier return FALSE;
316c4cb05bbSDavid du Colombier if(0x7F<=c && c<0xA0)
3177dd7cddfSDavid du Colombier return FALSE;
3187dd7cddfSDavid du Colombier if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
3197dd7cddfSDavid du Colombier return FALSE;
3207dd7cddfSDavid du Colombier return TRUE;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier int
rgetc(void * v,uint n)3247dd7cddfSDavid du Colombier rgetc(void *v, uint n)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier return ((Rune*)v)[n];
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier int
tgetc(void * a,uint n)3307dd7cddfSDavid du Colombier tgetc(void *a, uint n)
3317dd7cddfSDavid du Colombier {
3327dd7cddfSDavid du Colombier Text *t;
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier t = a;
3357dd7cddfSDavid du Colombier if(n >= t->file->nc)
3367dd7cddfSDavid du Colombier return 0;
3377dd7cddfSDavid du Colombier return textreadc(t, n);
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier Rune*
skipbl(Rune * r,int n,int * np)3417dd7cddfSDavid du Colombier skipbl(Rune *r, int n, int *np)
3427dd7cddfSDavid du Colombier {
343ac1798d1SDavid du Colombier while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
3447dd7cddfSDavid du Colombier --n;
3457dd7cddfSDavid du Colombier r++;
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier *np = n;
3487dd7cddfSDavid du Colombier return r;
3497dd7cddfSDavid du Colombier }
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier Rune*
findbl(Rune * r,int n,int * np)3527dd7cddfSDavid du Colombier findbl(Rune *r, int n, int *np)
3537dd7cddfSDavid du Colombier {
3547dd7cddfSDavid du Colombier while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
3557dd7cddfSDavid du Colombier --n;
3567dd7cddfSDavid du Colombier r++;
3577dd7cddfSDavid du Colombier }
3587dd7cddfSDavid du Colombier *np = n;
3597dd7cddfSDavid du Colombier return r;
3607dd7cddfSDavid du Colombier }
3617dd7cddfSDavid du Colombier
3627dd7cddfSDavid du Colombier void
savemouse(Window * w)3637dd7cddfSDavid du Colombier savemouse(Window *w)
3647dd7cddfSDavid du Colombier {
3657dd7cddfSDavid du Colombier prevmouse = mouse->xy;
3667dd7cddfSDavid du Colombier mousew = w;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier
369*588d0145SDavid du Colombier int
restoremouse(Window * w)3707dd7cddfSDavid du Colombier restoremouse(Window *w)
3717dd7cddfSDavid du Colombier {
372*588d0145SDavid du Colombier int did;
373*588d0145SDavid du Colombier
374*588d0145SDavid du Colombier did = 0;
375*588d0145SDavid du Colombier if(mousew!=nil && mousew==w){
3767dd7cddfSDavid du Colombier moveto(mousectl, prevmouse);
377*588d0145SDavid du Colombier did = 1;
378*588d0145SDavid du Colombier }
3797dd7cddfSDavid du Colombier mousew = nil;
380*588d0145SDavid du Colombier return did;
3817dd7cddfSDavid du Colombier }
3827dd7cddfSDavid du Colombier
3837dd7cddfSDavid du Colombier void
clearmouse()3847dd7cddfSDavid du Colombier clearmouse()
3857dd7cddfSDavid du Colombier {
3867dd7cddfSDavid du Colombier mousew = nil;
3877dd7cddfSDavid du Colombier }
3887dd7cddfSDavid du Colombier
38959cc4ca5SDavid du Colombier char*
estrdup(char * s)39059cc4ca5SDavid du Colombier estrdup(char *s)
39159cc4ca5SDavid du Colombier {
39259cc4ca5SDavid du Colombier char *t;
39359cc4ca5SDavid du Colombier
39459cc4ca5SDavid du Colombier t = strdup(s);
39559cc4ca5SDavid du Colombier if(t == nil)
39659cc4ca5SDavid du Colombier error("strdup failed");
39759cc4ca5SDavid du Colombier setmalloctag(t, getcallerpc(&s));
39859cc4ca5SDavid du Colombier return t;
39959cc4ca5SDavid du Colombier }
40059cc4ca5SDavid du Colombier
4017dd7cddfSDavid du Colombier void*
emalloc(uint n)4027dd7cddfSDavid du Colombier emalloc(uint n)
4037dd7cddfSDavid du Colombier {
4047dd7cddfSDavid du Colombier void *p;
4057dd7cddfSDavid du Colombier
4067dd7cddfSDavid du Colombier p = malloc(n);
4077dd7cddfSDavid du Colombier if(p == nil)
4087dd7cddfSDavid du Colombier error("malloc failed");
40959cc4ca5SDavid du Colombier setmalloctag(p, getcallerpc(&n));
4107dd7cddfSDavid du Colombier memset(p, 0, n);
4117dd7cddfSDavid du Colombier return p;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier
41459cc4ca5SDavid du Colombier void*
erealloc(void * p,uint n)41559cc4ca5SDavid du Colombier erealloc(void *p, uint n)
41659cc4ca5SDavid du Colombier {
41759cc4ca5SDavid du Colombier p = realloc(p, n);
41859cc4ca5SDavid du Colombier if(p == nil)
41959cc4ca5SDavid du Colombier error("realloc failed");
42059cc4ca5SDavid du Colombier setmalloctag(p, getcallerpc(&n));
42159cc4ca5SDavid du Colombier return p;
42259cc4ca5SDavid du Colombier }
42359cc4ca5SDavid du Colombier
4247dd7cddfSDavid du Colombier /*
4257dd7cddfSDavid du Colombier * Heuristic city.
4267dd7cddfSDavid du Colombier */
4277dd7cddfSDavid du Colombier Window*
makenewwindow(Text * t)428d9306527SDavid du Colombier makenewwindow(Text *t)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier Column *c;
4317dd7cddfSDavid du Colombier Window *w, *bigw, *emptyw;
4327dd7cddfSDavid du Colombier Text *emptyb;
4337dd7cddfSDavid du Colombier int i, y, el;
4347dd7cddfSDavid du Colombier
4357dd7cddfSDavid du Colombier if(activecol)
4367dd7cddfSDavid du Colombier c = activecol;
4377dd7cddfSDavid du Colombier else if(seltext && seltext->col)
4387dd7cddfSDavid du Colombier c = seltext->col;
4397dd7cddfSDavid du Colombier else if(t && t->col)
4407dd7cddfSDavid du Colombier c = t->col;
4417dd7cddfSDavid du Colombier else{
4427dd7cddfSDavid du Colombier if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
4437dd7cddfSDavid du Colombier error("can't make column");
4447dd7cddfSDavid du Colombier c = row.col[row.ncol-1];
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier activecol = c;
4477dd7cddfSDavid du Colombier if(t==nil || t->w==nil || c->nw==0)
4487dd7cddfSDavid du Colombier return coladd(c, nil, nil, -1);
4497dd7cddfSDavid du Colombier
4507dd7cddfSDavid du Colombier /* find biggest window and biggest blank spot */
4517dd7cddfSDavid du Colombier emptyw = c->w[0];
4527dd7cddfSDavid du Colombier bigw = emptyw;
4537dd7cddfSDavid du Colombier for(i=1; i<c->nw; i++){
4547dd7cddfSDavid du Colombier w = c->w[i];
4557dd7cddfSDavid du Colombier /* use >= to choose one near bottom of screen */
4567dd7cddfSDavid du Colombier if(w->body.maxlines >= bigw->body.maxlines)
4577dd7cddfSDavid du Colombier bigw = w;
4587dd7cddfSDavid du Colombier if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines)
4597dd7cddfSDavid du Colombier emptyw = w;
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier emptyb = &emptyw->body;
4627dd7cddfSDavid du Colombier el = emptyb->maxlines-emptyb->nlines;
4637dd7cddfSDavid du Colombier /* if empty space is big, use it */
4647dd7cddfSDavid du Colombier if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2))
4657dd7cddfSDavid du Colombier y = emptyb->r.min.y+emptyb->nlines*font->height;
4667dd7cddfSDavid du Colombier else{
4677dd7cddfSDavid du Colombier /* if this window is in column and isn't much smaller, split it */
4687dd7cddfSDavid du Colombier if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
4697dd7cddfSDavid du Colombier bigw = t->w;
4707dd7cddfSDavid du Colombier y = (bigw->r.min.y + bigw->r.max.y)/2;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier w = coladd(c, nil, nil, y);
4737dd7cddfSDavid du Colombier if(w->body.maxlines < 2)
4747dd7cddfSDavid du Colombier colgrow(w->col, w, 1);
4757dd7cddfSDavid du Colombier return w;
4767dd7cddfSDavid du Colombier }
477