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 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 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* 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* 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 1124fec87e5SDavid du Colombier typedef struct Warning Warning; 1134fec87e5SDavid du Colombier 1144fec87e5SDavid du Colombier struct Warning{ 1154fec87e5SDavid du Colombier Mntdir *md; 1164fec87e5SDavid du Colombier Buffer buf; 1174fec87e5SDavid du Colombier Warning *next; 1184fec87e5SDavid du Colombier }; 1194fec87e5SDavid du Colombier 1204fec87e5SDavid du Colombier static Warning *warnings; 1214fec87e5SDavid du Colombier 1224fec87e5SDavid du Colombier static 1234fec87e5SDavid du Colombier void 1244fec87e5SDavid du Colombier addwarningtext(Mntdir *md, Rune *r, int nr) 1257dd7cddfSDavid du Colombier { 1264fec87e5SDavid du Colombier Warning *warn; 1274fec87e5SDavid du Colombier 1284fec87e5SDavid du Colombier for(warn = warnings; warn; warn=warn->next){ 1294fec87e5SDavid du Colombier if(warn->md == md){ 1304fec87e5SDavid du Colombier bufinsert(&warn->buf, warn->buf.nc, r, nr); 1314fec87e5SDavid du Colombier return; 1324fec87e5SDavid du Colombier } 1334fec87e5SDavid du Colombier } 1344fec87e5SDavid du Colombier warn = emalloc(sizeof(Warning)); 1354fec87e5SDavid du Colombier warn->next = warnings; 1364fec87e5SDavid du Colombier warnings = warn; 1374fec87e5SDavid du Colombier bufinsert(&warn->buf, 0, r, nr); 1384fec87e5SDavid du Colombier } 1394fec87e5SDavid du Colombier 1404fec87e5SDavid du Colombier /* called while row is locked */ 1414fec87e5SDavid du Colombier void 1424fec87e5SDavid du Colombier flushwarnings(void) 1434fec87e5SDavid du Colombier { 1444fec87e5SDavid du Colombier Warning *warn, *next; 1457dd7cddfSDavid du Colombier Window *w; 1467dd7cddfSDavid du Colombier Text *t; 1474fec87e5SDavid du Colombier int owner, nr, q0, n; 1484fec87e5SDavid du Colombier Rune *r; 1499a747e4fSDavid du Colombier 1507dd7cddfSDavid du Colombier if(row.ncol == 0){ /* really early error */ 1517dd7cddfSDavid du Colombier rowinit(&row, screen->clipr); 1527dd7cddfSDavid du Colombier rowadd(&row, nil, -1); 1537dd7cddfSDavid du Colombier rowadd(&row, nil, -1); 1547dd7cddfSDavid du Colombier if(row.ncol == 0) 1554fec87e5SDavid du Colombier error("initializing columns in flushwarnings()"); 1567dd7cddfSDavid du Colombier } 1579a747e4fSDavid du Colombier 1584fec87e5SDavid du Colombier for(warn=warnings; warn; warn=next) { 1594fec87e5SDavid du Colombier w = errorwin(warn->md, 'E'); 1607dd7cddfSDavid du Colombier t = &w->body; 1617dd7cddfSDavid du Colombier owner = w->owner; 1627dd7cddfSDavid du Colombier if(owner == 0) 1637dd7cddfSDavid du Colombier w->owner = 'E'; 1647dd7cddfSDavid du Colombier wincommit(w, t); 1654fec87e5SDavid du Colombier /* 1664fec87e5SDavid du Colombier * Most commands don't generate much output. For instance, 1674fec87e5SDavid du Colombier * Edit ,>cat goes through /dev/cons and is already in blocks 1684fec87e5SDavid du Colombier * because of the i/o system, but a few can. Edit ,p will 1694fec87e5SDavid du Colombier * put the entire result into a single hunk. So it's worth doing 1704fec87e5SDavid du Colombier * this in blocks (and putting the text in a buffer in the first 1714fec87e5SDavid du Colombier * place), to avoid a big memory footprint. 1724fec87e5SDavid du Colombier */ 1734fec87e5SDavid du Colombier r = fbufalloc(); 1744fec87e5SDavid du Colombier q0 = t->file->nc; 1754fec87e5SDavid du Colombier for(n = 0; n < warn->buf.nc; n += nr){ 1764fec87e5SDavid du Colombier nr = warn->buf.nc - n; 1774fec87e5SDavid du Colombier if(nr > RBUFSIZE) 1784fec87e5SDavid du Colombier nr = RBUFSIZE; 1794fec87e5SDavid du Colombier bufread(&warn->buf, n, r, nr); 1804fec87e5SDavid du Colombier textbsinsert(t, t->file->nc, r, nr, TRUE, &nr); 1814fec87e5SDavid du Colombier } 1824fec87e5SDavid du Colombier textshow(t, q0, t->file->nc, 1); 1834fec87e5SDavid du Colombier free(r); 1847dd7cddfSDavid du Colombier winsettag(t->w); 1857dd7cddfSDavid du Colombier textscrdraw(t); 1867dd7cddfSDavid du Colombier w->owner = owner; 1877dd7cddfSDavid du Colombier w->dirty = FALSE; 1887dd7cddfSDavid du Colombier winunlock(w); 1894fec87e5SDavid du Colombier bufclose(&warn->buf); 1904fec87e5SDavid du Colombier next = warn->next; 1914fec87e5SDavid du Colombier free(warn); 1924fec87e5SDavid du Colombier } 1934fec87e5SDavid du Colombier warnings = nil; 1947dd7cddfSDavid du Colombier } 1957dd7cddfSDavid du Colombier 196ef9eff0bSDavid du Colombier void 197ef9eff0bSDavid du Colombier warning(Mntdir *md, char *s, ...) 198ef9eff0bSDavid du Colombier { 199ef9eff0bSDavid du Colombier Rune *r; 200ef9eff0bSDavid du Colombier va_list arg; 201ef9eff0bSDavid du Colombier 202ef9eff0bSDavid du Colombier va_start(arg, s); 203ef9eff0bSDavid du Colombier r = runevsmprint(s, arg); 204ef9eff0bSDavid du Colombier va_end(arg); 2054fec87e5SDavid du Colombier if(r == nil) 2064fec87e5SDavid du Colombier error("runevsmprint failed"); 2074fec87e5SDavid du Colombier addwarningtext(md, r, runestrlen(r)); 208ef9eff0bSDavid du Colombier } 209ef9eff0bSDavid du Colombier 2107dd7cddfSDavid du Colombier int 2117dd7cddfSDavid du Colombier runeeq(Rune *s1, uint n1, Rune *s2, uint n2) 2127dd7cddfSDavid du Colombier { 2137dd7cddfSDavid du Colombier if(n1 != n2) 2147dd7cddfSDavid du Colombier return FALSE; 2157dd7cddfSDavid du Colombier return memcmp(s1, s2, n1*sizeof(Rune)) == 0; 2167dd7cddfSDavid du Colombier } 2177dd7cddfSDavid du Colombier 2187dd7cddfSDavid du Colombier uint 2197dd7cddfSDavid du Colombier min(uint a, uint b) 2207dd7cddfSDavid du Colombier { 2217dd7cddfSDavid du Colombier if(a < b) 2227dd7cddfSDavid du Colombier return a; 2237dd7cddfSDavid du Colombier return b; 2247dd7cddfSDavid du Colombier } 2257dd7cddfSDavid du Colombier 2267dd7cddfSDavid du Colombier uint 2277dd7cddfSDavid du Colombier max(uint a, uint b) 2287dd7cddfSDavid du Colombier { 2297dd7cddfSDavid du Colombier if(a > b) 2307dd7cddfSDavid du Colombier return a; 2317dd7cddfSDavid du Colombier return b; 2327dd7cddfSDavid du Colombier } 2337dd7cddfSDavid du Colombier 2347dd7cddfSDavid du Colombier char* 2357dd7cddfSDavid du Colombier runetobyte(Rune *r, int n) 2367dd7cddfSDavid du Colombier { 2377dd7cddfSDavid du Colombier char *s; 2387dd7cddfSDavid du Colombier 23934e04225SDavid du Colombier if(r == nil) 2407dd7cddfSDavid du Colombier return nil; 2417dd7cddfSDavid du Colombier s = emalloc(n*UTFmax+1); 24259cc4ca5SDavid du Colombier setmalloctag(s, getcallerpc(&r)); 2437dd7cddfSDavid du Colombier snprint(s, n*UTFmax+1, "%.*S", n, r); 2447dd7cddfSDavid du Colombier return s; 2457dd7cddfSDavid du Colombier } 2467dd7cddfSDavid du Colombier 2477dd7cddfSDavid du Colombier Rune* 2487dd7cddfSDavid du Colombier bytetorune(char *s, int *ip) 2497dd7cddfSDavid du Colombier { 2507dd7cddfSDavid du Colombier Rune *r; 2517dd7cddfSDavid du Colombier int nb, nr; 2527dd7cddfSDavid du Colombier 2537dd7cddfSDavid du Colombier nb = strlen(s); 2547dd7cddfSDavid du Colombier r = runemalloc(nb+1); 2557dd7cddfSDavid du Colombier cvttorunes(s, nb, r, &nb, &nr, nil); 2567dd7cddfSDavid du Colombier r[nr] = '\0'; 2577dd7cddfSDavid du Colombier *ip = nr; 2587dd7cddfSDavid du Colombier return r; 2597dd7cddfSDavid du Colombier } 2607dd7cddfSDavid du Colombier 2617dd7cddfSDavid du Colombier int 2627dd7cddfSDavid du Colombier isalnum(Rune c) 2637dd7cddfSDavid du Colombier { 2647dd7cddfSDavid du Colombier /* 2657dd7cddfSDavid du Colombier * Hard to get absolutely right. Use what we know about ASCII 2667dd7cddfSDavid du Colombier * and assume anything above the Latin control characters is 2677dd7cddfSDavid du Colombier * potentially an alphanumeric. 2687dd7cddfSDavid du Colombier */ 2697dd7cddfSDavid du Colombier if(c <= ' ') 2707dd7cddfSDavid du Colombier return FALSE; 2717dd7cddfSDavid du Colombier if(0x7F<=c && c<=0xA0) 2727dd7cddfSDavid du Colombier return FALSE; 2737dd7cddfSDavid du Colombier if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) 2747dd7cddfSDavid du Colombier return FALSE; 2757dd7cddfSDavid du Colombier return TRUE; 2767dd7cddfSDavid du Colombier } 2777dd7cddfSDavid du Colombier 2787dd7cddfSDavid du Colombier int 2797dd7cddfSDavid du Colombier rgetc(void *v, uint n) 2807dd7cddfSDavid du Colombier { 2817dd7cddfSDavid du Colombier return ((Rune*)v)[n]; 2827dd7cddfSDavid du Colombier } 2837dd7cddfSDavid du Colombier 2847dd7cddfSDavid du Colombier int 2857dd7cddfSDavid du Colombier tgetc(void *a, uint n) 2867dd7cddfSDavid du Colombier { 2877dd7cddfSDavid du Colombier Text *t; 2887dd7cddfSDavid du Colombier 2897dd7cddfSDavid du Colombier t = a; 2907dd7cddfSDavid du Colombier if(n >= t->file->nc) 2917dd7cddfSDavid du Colombier return 0; 2927dd7cddfSDavid du Colombier return textreadc(t, n); 2937dd7cddfSDavid du Colombier } 2947dd7cddfSDavid du Colombier 2957dd7cddfSDavid du Colombier Rune* 2967dd7cddfSDavid du Colombier skipbl(Rune *r, int n, int *np) 2977dd7cddfSDavid du Colombier { 298*ac1798d1SDavid du Colombier while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){ 2997dd7cddfSDavid du Colombier --n; 3007dd7cddfSDavid du Colombier r++; 3017dd7cddfSDavid du Colombier } 3027dd7cddfSDavid du Colombier *np = n; 3037dd7cddfSDavid du Colombier return r; 3047dd7cddfSDavid du Colombier } 3057dd7cddfSDavid du Colombier 3067dd7cddfSDavid du Colombier Rune* 3077dd7cddfSDavid du Colombier findbl(Rune *r, int n, int *np) 3087dd7cddfSDavid du Colombier { 3097dd7cddfSDavid du Colombier while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){ 3107dd7cddfSDavid du Colombier --n; 3117dd7cddfSDavid du Colombier r++; 3127dd7cddfSDavid du Colombier } 3137dd7cddfSDavid du Colombier *np = n; 3147dd7cddfSDavid du Colombier return r; 3157dd7cddfSDavid du Colombier } 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier void 3187dd7cddfSDavid du Colombier savemouse(Window *w) 3197dd7cddfSDavid du Colombier { 3207dd7cddfSDavid du Colombier prevmouse = mouse->xy; 3217dd7cddfSDavid du Colombier mousew = w; 3227dd7cddfSDavid du Colombier } 3237dd7cddfSDavid du Colombier 3247dd7cddfSDavid du Colombier void 3257dd7cddfSDavid du Colombier restoremouse(Window *w) 3267dd7cddfSDavid du Colombier { 3277dd7cddfSDavid du Colombier if(mousew!=nil && mousew==w) 3287dd7cddfSDavid du Colombier moveto(mousectl, prevmouse); 3297dd7cddfSDavid du Colombier mousew = nil; 3307dd7cddfSDavid du Colombier } 3317dd7cddfSDavid du Colombier 3327dd7cddfSDavid du Colombier void 3337dd7cddfSDavid du Colombier clearmouse() 3347dd7cddfSDavid du Colombier { 3357dd7cddfSDavid du Colombier mousew = nil; 3367dd7cddfSDavid du Colombier } 3377dd7cddfSDavid du Colombier 33859cc4ca5SDavid du Colombier char* 33959cc4ca5SDavid du Colombier estrdup(char *s) 34059cc4ca5SDavid du Colombier { 34159cc4ca5SDavid du Colombier char *t; 34259cc4ca5SDavid du Colombier 34359cc4ca5SDavid du Colombier t = strdup(s); 34459cc4ca5SDavid du Colombier if(t == nil) 34559cc4ca5SDavid du Colombier error("strdup failed"); 34659cc4ca5SDavid du Colombier setmalloctag(t, getcallerpc(&s)); 34759cc4ca5SDavid du Colombier return t; 34859cc4ca5SDavid du Colombier } 34959cc4ca5SDavid du Colombier 3507dd7cddfSDavid du Colombier void* 3517dd7cddfSDavid du Colombier emalloc(uint n) 3527dd7cddfSDavid du Colombier { 3537dd7cddfSDavid du Colombier void *p; 3547dd7cddfSDavid du Colombier 3557dd7cddfSDavid du Colombier p = malloc(n); 3567dd7cddfSDavid du Colombier if(p == nil) 3577dd7cddfSDavid du Colombier error("malloc failed"); 35859cc4ca5SDavid du Colombier setmalloctag(p, getcallerpc(&n)); 3597dd7cddfSDavid du Colombier memset(p, 0, n); 3607dd7cddfSDavid du Colombier return p; 3617dd7cddfSDavid du Colombier } 3627dd7cddfSDavid du Colombier 36359cc4ca5SDavid du Colombier void* 36459cc4ca5SDavid du Colombier erealloc(void *p, uint n) 36559cc4ca5SDavid du Colombier { 36659cc4ca5SDavid du Colombier p = realloc(p, n); 36759cc4ca5SDavid du Colombier if(p == nil) 36859cc4ca5SDavid du Colombier error("realloc failed"); 36959cc4ca5SDavid du Colombier setmalloctag(p, getcallerpc(&n)); 37059cc4ca5SDavid du Colombier return p; 37159cc4ca5SDavid du Colombier } 37259cc4ca5SDavid du Colombier 3737dd7cddfSDavid du Colombier /* 3747dd7cddfSDavid du Colombier * Heuristic city. 3757dd7cddfSDavid du Colombier */ 3767dd7cddfSDavid du Colombier Window* 377d9306527SDavid du Colombier makenewwindow(Text *t) 3787dd7cddfSDavid du Colombier { 3797dd7cddfSDavid du Colombier Column *c; 3807dd7cddfSDavid du Colombier Window *w, *bigw, *emptyw; 3817dd7cddfSDavid du Colombier Text *emptyb; 3827dd7cddfSDavid du Colombier int i, y, el; 3837dd7cddfSDavid du Colombier 3847dd7cddfSDavid du Colombier if(activecol) 3857dd7cddfSDavid du Colombier c = activecol; 3867dd7cddfSDavid du Colombier else if(seltext && seltext->col) 3877dd7cddfSDavid du Colombier c = seltext->col; 3887dd7cddfSDavid du Colombier else if(t && t->col) 3897dd7cddfSDavid du Colombier c = t->col; 3907dd7cddfSDavid du Colombier else{ 3917dd7cddfSDavid du Colombier if(row.ncol==0 && rowadd(&row, nil, -1)==nil) 3927dd7cddfSDavid du Colombier error("can't make column"); 3937dd7cddfSDavid du Colombier c = row.col[row.ncol-1]; 3947dd7cddfSDavid du Colombier } 3957dd7cddfSDavid du Colombier activecol = c; 3967dd7cddfSDavid du Colombier if(t==nil || t->w==nil || c->nw==0) 3977dd7cddfSDavid du Colombier return coladd(c, nil, nil, -1); 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier /* find biggest window and biggest blank spot */ 4007dd7cddfSDavid du Colombier emptyw = c->w[0]; 4017dd7cddfSDavid du Colombier bigw = emptyw; 4027dd7cddfSDavid du Colombier for(i=1; i<c->nw; i++){ 4037dd7cddfSDavid du Colombier w = c->w[i]; 4047dd7cddfSDavid du Colombier /* use >= to choose one near bottom of screen */ 4057dd7cddfSDavid du Colombier if(w->body.maxlines >= bigw->body.maxlines) 4067dd7cddfSDavid du Colombier bigw = w; 4077dd7cddfSDavid du Colombier if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines) 4087dd7cddfSDavid du Colombier emptyw = w; 4097dd7cddfSDavid du Colombier } 4107dd7cddfSDavid du Colombier emptyb = &emptyw->body; 4117dd7cddfSDavid du Colombier el = emptyb->maxlines-emptyb->nlines; 4127dd7cddfSDavid du Colombier /* if empty space is big, use it */ 4137dd7cddfSDavid du Colombier if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2)) 4147dd7cddfSDavid du Colombier y = emptyb->r.min.y+emptyb->nlines*font->height; 4157dd7cddfSDavid du Colombier else{ 4167dd7cddfSDavid du Colombier /* if this window is in column and isn't much smaller, split it */ 4177dd7cddfSDavid du Colombier if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3) 4187dd7cddfSDavid du Colombier bigw = t->w; 4197dd7cddfSDavid du Colombier y = (bigw->r.min.y + bigw->r.max.y)/2; 4207dd7cddfSDavid du Colombier } 4217dd7cddfSDavid du Colombier w = coladd(c, nil, nil, y); 4227dd7cddfSDavid du Colombier if(w->body.maxlines < 2) 4237dd7cddfSDavid du Colombier colgrow(w->col, w, 1); 4247dd7cddfSDavid du Colombier return w; 4257dd7cddfSDavid du Colombier } 426