add gitignore, clang-format, build script; merge src's patch for spaces in filenames

This commit is contained in:
Iris Lightshard 2021-06-12 23:54:54 -06:00
parent cf57dbe235
commit 5540d37849
Signed by: Iris Lightshard
GPG key ID: 3B7FBC22144E6398
38 changed files with 15300 additions and 15770 deletions

23
.clang-format Normal file
View file

@ -0,0 +1,23 @@
TabWidth: 2
IndentWidth: 2
ContinuationIndentWidth: 2
UseTab: Never
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
PenaltyReturnTypeOnItsOwnLine: 255
IndentCaseLabels: true
SpaceBeforeParens: ControlStatements
AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: false
BinPackArguments: false
PointerAlignment: Left
BreakBeforeBraces: Attach
SortIncludes: false
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AlignEscapedNewlines: Left

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
**/*.o **/*.o
**/o.* **/o.*
acme

1953
acme.c

File diff suppressed because it is too large Load diff

506
addr.c
View file

@ -12,41 +12,29 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
enum enum { None = 0, Fore = '+', Back = '-' };
{
None = 0,
Fore = '+',
Back = '-'
};
enum enum { Char, Line };
{
Char,
Line
};
int int isaddrc(int r) {
isaddrc(int r) if (r && utfrune("0123456789+-/$.#,;?", r) != nil)
{ return TRUE;
if(r && utfrune("0123456789+-/$.#,;?", r)!=nil) return FALSE;
return TRUE;
return FALSE;
} }
/* /*
* quite hard: could be almost anything but white space, but we are a little conservative, * quite hard: could be almost anything but white space, but we are a little
* aiming for regular expressions of alphanumerics and no white space * conservative, aiming for regular expressions of alphanumerics and no white
* space
*/ */
int int isregexc(int r) {
isregexc(int r) if (r == 0)
{ return FALSE;
if(r == 0) if (isalnum(r))
return FALSE; return TRUE;
if(isalnum(r)) if (utfrune("^+-.*?#,;[]()$", r) != nil)
return TRUE; return TRUE;
if(utfrune("^+-.*?#,;[]()$", r)!=nil) return FALSE;
return TRUE;
return FALSE;
} }
// nlcounttopos starts at q0 and advances nl lines, // nlcounttopos starts at q0 and advances nl lines,
@ -54,242 +42,246 @@ isregexc(int r)
// and then nr chars, being careful not to walk past // and then nr chars, being careful not to walk past
// the end of the current line. // the end of the current line.
// It returns the final position. // It returns the final position.
long long nlcounttopos(Text* t, long q0, long nl, long nr) {
nlcounttopos(Text *t, long q0, long nl, long nr) while (nl > 0 && q0 < t->file->b.nc) {
{ if (textreadc(t, q0++) == '\n')
while(nl > 0 && q0 < t->file->b.nc) { nl--;
if(textreadc(t, q0++) == '\n') }
nl--; if (nl > 0)
} return q0;
if(nl > 0) while (nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') {
return q0; q0++;
while(nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') { nr--;
q0++; }
nr--; return q0;
}
return q0;
} }
Range Range number(
number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp) uint showerr, Text* t, Range r, int line, int dir, int size, int* evalp) {
{ uint q0, q1;
uint q0, q1;
if(size == Char){ if (size == Char) {
if(dir == Fore) if (dir == Fore)
line = r.q1+line; line = r.q1 + line;
else if(dir == Back){ else if (dir == Back) {
if(r.q0==0 && line>0) if (r.q0 == 0 && line > 0)
r.q0 = t->file->b.nc; r.q0 = t->file->b.nc;
line = r.q0 - line; line = r.q0 - line;
} }
if(line<0 || line>t->file->b.nc) if (line < 0 || line > t->file->b.nc)
goto Rescue; goto Rescue;
*evalp = TRUE; *evalp = TRUE;
return range(line, line); return range(line, line);
} }
q0 = r.q0; q0 = r.q0;
q1 = r.q1; q1 = r.q1;
switch(dir){ switch (dir) {
case None: case None:
q0 = 0; q0 = 0;
q1 = 0; q1 = 0;
Forward: Forward:
while(line>0 && q1<t->file->b.nc) while (line > 0 && q1 < t->file->b.nc)
if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc) if (textreadc(t, q1++) == '\n' || q1 == t->file->b.nc)
if(--line > 0) if (--line > 0)
q0 = q1; q0 = q1;
if(line==1 && q1==t->file->b.nc) // 6 goes to end of 5-line file if (line == 1 && q1 == t->file->b.nc) // 6 goes to end of 5-line file
break; break;
if(line > 0) if (line > 0)
goto Rescue; goto Rescue;
break; break;
case Fore: case Fore:
if(q1 > 0) if (q1 > 0)
while(q1<t->file->b.nc && textreadc(t, q1-1) != '\n') while (q1 < t->file->b.nc && textreadc(t, q1 - 1) != '\n')
q1++; q1++;
q0 = q1; q0 = q1;
goto Forward; goto Forward;
case Back: case Back:
if(q0 < t->file->b.nc) if (q0 < t->file->b.nc)
while(q0>0 && textreadc(t, q0-1)!='\n') while (q0 > 0 && textreadc(t, q0 - 1) != '\n')
q0--; q0--;
q1 = q0; q1 = q0;
while(line>0 && q0>0){ while (line > 0 && q0 > 0) {
if(textreadc(t, q0-1) == '\n'){ if (textreadc(t, q0 - 1) == '\n') {
if(--line >= 0) if (--line >= 0)
q1 = q0; q1 = q0;
} }
--q0; --q0;
} }
/* :1-1 is :0 = #0, but :1-2 is an error */ /* :1-1 is :0 = #0, but :1-2 is an error */
if(line > 1) if (line > 1)
goto Rescue; goto Rescue;
while(q0>0 && textreadc(t, q0-1)!='\n') while (q0 > 0 && textreadc(t, q0 - 1) != '\n')
--q0; --q0;
} }
*evalp = TRUE; *evalp = TRUE;
return range(q0, q1); return range(q0, q1);
Rescue: Rescue:
if(showerr) if (showerr)
warning(nil, "address out of range\n"); warning(nil, "address out of range\n");
*evalp = FALSE; *evalp = FALSE;
return r; return r;
} }
Range regexp(
uint showerr, Text* t, Range lim, Range r, Rune* pat, int dir, int* foundp) {
int found;
Rangeset sel;
int q;
Range if (pat[0] == '\0' && rxnull()) {
regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp) if (showerr)
{ warning(nil, "no previous regular expression\n");
int found; *foundp = FALSE;
Rangeset sel; return r;
int q; }
if (pat[0] && rxcompile(pat) == FALSE) {
if(pat[0] == '\0' && rxnull()){ *foundp = FALSE;
if(showerr) return r;
warning(nil, "no previous regular expression\n"); }
*foundp = FALSE; if (dir == Back)
return r; found = rxbexecute(t, r.q0, &sel);
} else {
if(pat[0] && rxcompile(pat) == FALSE){ if (lim.q0 < 0)
*foundp = FALSE; q = Infinity;
return r; else
} q = lim.q1;
if(dir == Back) found = rxexecute(t, nil, r.q1, q, &sel);
found = rxbexecute(t, r.q0, &sel); }
else{ if (!found && showerr)
if(lim.q0 < 0) warning(nil, "no match for regexp\n");
q = Infinity; *foundp = found;
else return sel.r[0];
q = lim.q1;
found = rxexecute(t, nil, r.q1, q, &sel);
}
if(!found && showerr)
warning(nil, "no match for regexp\n");
*foundp = found;
return sel.r[0];
} }
Range Range address(
address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint), int *evalp, uint *qp) uint showerr, Text* t, Range lim, Range ar, void* a, uint q0, uint q1,
{ int (*getc)(void*, uint), int* evalp, uint* qp) {
int dir, size, npat; int dir, size, npat;
int prevc, c, nc, n; int prevc, c, nc, n;
uint q; uint q;
Rune *pat; Rune* pat;
Range r, nr; Range r, nr;
r = ar; r = ar;
q = q0; q = q0;
dir = None; dir = None;
size = Line; size = Line;
c = 0; c = 0;
while(q < q1){ while (q < q1) {
prevc = c; prevc = c;
c = (*getc)(a, q++); c = (*getc)(a, q++);
switch(c){ switch (c) {
default: default:
*qp = q-1; *qp = q - 1;
return r; return r;
case ';': case ';':
ar = r; ar = r;
/* fall through */ /* fall through */
case ',': case ',':
if(prevc == 0) /* lhs defaults to 0 */ if (prevc == 0) /* lhs defaults to 0 */
r.q0 = 0; r.q0 = 0;
if(q>=q1 && t!=nil && t->file!=nil) /* rhs defaults to $ */ if (q >= q1 && t != nil && t->file != nil) /* rhs defaults to $ */
r.q1 = t->file->b.nc; r.q1 = t->file->b.nc;
else{ else {
nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q); nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);
r.q1 = nr.q1; r.q1 = nr.q1;
} }
*qp = q; *qp = q;
return r; return r;
case '+': case '+':
case '-': case '-':
if(*evalp && (prevc=='+' || prevc=='-')) if (*evalp && (prevc == '+' || prevc == '-'))
if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?') if ((nc = (*getc)(a, q)) != '#' && nc != '/' && nc != '?')
r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one */ r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one
dir = c; */
break; dir = c;
case '.': break;
case '$': case '.':
if(q != q0+1){ case '$':
*qp = q-1; if (q != q0 + 1) {
return r; *qp = q - 1;
} return r;
if(*evalp) }
if(c == '.') if (*evalp)
r = ar; if (c == '.')
else r = ar;
r = range(t->file->b.nc, t->file->b.nc); else
if(q < q1) r = range(t->file->b.nc, t->file->b.nc);
dir = Fore; if (q < q1)
else dir = Fore;
dir = None; else
break; dir = None;
case '#': break;
if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){ case '#':
*qp = q-1; if (q == q1 || (c = (*getc)(a, q++)) < '0' || '9' < c) {
return r; *qp = q - 1;
} return r;
size = Char; }
/* fall through */ size = Char;
case '0': case '1': case '2': case '3': case '4': /* fall through */
case '5': case '6': case '7': case '8': case '9': case '0':
n = c -'0'; case '1':
while(q<q1){ case '2':
nc = (*getc)(a, q++); case '3':
if(nc<'0' || '9'<nc){ case '4':
q--; case '5':
break; case '6':
} case '7':
n = n*10+(nc-'0'); case '8':
} case '9':
if(*evalp) n = c - '0';
r = number(showerr, t, r, n, dir, size, evalp); while (q < q1) {
dir = None; nc = (*getc)(a, q++);
size = Line; if (nc < '0' || '9' < nc) {
break; q--;
case '?': break;
dir = Back; }
/* fall through */ n = n * 10 + (nc - '0');
case '/': }
npat = 0; if (*evalp)
pat = nil; r = number(showerr, t, r, n, dir, size, evalp);
while(q<q1){ dir = None;
c = (*getc)(a, q++); size = Line;
switch(c){ break;
case '\n': case '?':
--q; dir = Back;
goto out; /* fall through */
case '\\': case '/':
pat = runerealloc(pat, npat+1); npat = 0;
pat[npat++] = c; pat = nil;
if(q == q1) while (q < q1) {
goto out; c = (*getc)(a, q++);
c = (*getc)(a, q++); switch (c) {
break; case '\n':
case '/': --q;
goto out; goto out;
} case '\\':
pat = runerealloc(pat, npat+1); pat = runerealloc(pat, npat + 1);
pat[npat++] = c; pat[npat++] = c;
} if (q == q1)
out: goto out;
pat = runerealloc(pat, npat+1); c = (*getc)(a, q++);
pat[npat] = 0; break;
if(*evalp) case '/':
r = regexp(showerr, t, lim, r, pat, dir, evalp); goto out;
free(pat); }
dir = None; pat = runerealloc(pat, npat + 1);
size = Line; pat[npat++] = c;
break; }
} out:
} pat = runerealloc(pat, npat + 1);
if(*evalp && dir != None) pat[npat] = 0;
r = number(showerr, t, r, 1, dir, Line, evalp); /* do previous one */ if (*evalp)
*qp = q; r = regexp(showerr, t, lim, r, pat, dir, evalp);
return r; free(pat);
dir = None;
size = Line;
break;
}
}
if (*evalp && dir != None)
r = number(showerr, t, r, 1, dir, Line, evalp); /* do previous one */
*qp = q;
return r;
} }

506
buff.c
View file

@ -12,47 +12,37 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
enum enum {
{ Slop = 100 /* room to grow with reallocation */
Slop = 100 /* room to grow with reallocation */
}; };
static static void sizecache(Buffer* b, uint n) {
void if (n <= b->cmax)
sizecache(Buffer *b, uint n) return;
{ b->cmax = n + Slop;
if(n <= b->cmax) b->c = runerealloc(b->c, b->cmax);
return;
b->cmax = n+Slop;
b->c = runerealloc(b->c, b->cmax);
} }
static static void addblock(Buffer* b, uint i, uint n) {
void if (i > b->nbl)
addblock(Buffer *b, uint i, uint n) error("internal error: addblock");
{
if(i > b->nbl)
error("internal error: addblock");
b->bl = realloc(b->bl, (b->nbl+1)*sizeof b->bl[0]); b->bl = realloc(b->bl, (b->nbl + 1) * sizeof b->bl[0]);
if(i < b->nbl) if (i < b->nbl)
memmove(b->bl+i+1, b->bl+i, (b->nbl-i)*sizeof(Block*)); memmove(b->bl + i + 1, b->bl + i, (b->nbl - i) * sizeof(Block*));
b->bl[i] = disknewblock(disk, n); b->bl[i] = disknewblock(disk, n);
b->nbl++; b->nbl++;
} }
static static void delblock(Buffer* b, uint i) {
void if (i >= b->nbl)
delblock(Buffer *b, uint i) error("internal error: delblock");
{
if(i >= b->nbl)
error("internal error: delblock");
diskrelease(disk, b->bl[i]); diskrelease(disk, b->bl[i]);
b->nbl--; b->nbl--;
if(i < b->nbl) if (i < b->nbl)
memmove(b->bl+i, b->bl+i+1, (b->nbl-i)*sizeof(Block*)); memmove(b->bl + i, b->bl + i + 1, (b->nbl - i) * sizeof(Block*));
b->bl = realloc(b->bl, b->nbl*sizeof b->bl[0]); b->bl = realloc(b->bl, b->nbl * sizeof b->bl[0]);
} }
/* /*
@ -60,266 +50,246 @@ delblock(Buffer *b, uint i)
* If at very end, q0 will fall on end of cache block. * If at very end, q0 will fall on end of cache block.
*/ */
static static void flush(Buffer* b) {
void if (b->cdirty || b->cnc == 0) {
flush(Buffer *b) if (b->cnc == 0)
{ delblock(b, b->cbi);
if(b->cdirty || b->cnc==0){ else
if(b->cnc == 0) diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
delblock(b, b->cbi); b->cdirty = FALSE;
else }
diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
b->cdirty = FALSE;
}
} }
static static void setcache(Buffer* b, uint q0) {
void Block **blp, *bl;
setcache(Buffer *b, uint q0) uint i, q;
{
Block **blp, *bl;
uint i, q;
if(q0 > b->nc) if (q0 > b->nc)
error("internal error: setcache"); error("internal error: setcache");
/* /*
* flush and reload if q0 is not in cache. * flush and reload if q0 is not in cache.
*/ */
if(b->nc == 0 || (b->cq<=q0 && q0<b->cq+b->cnc)) if (b->nc == 0 || (b->cq <= q0 && q0 < b->cq + b->cnc))
return; return;
/* /*
* if q0 is at end of file and end of cache, continue to grow this block * if q0 is at end of file and end of cache, continue to grow this block
*/ */
if(q0==b->nc && q0==b->cq+b->cnc && b->cnc<Maxblock) if (q0 == b->nc && q0 == b->cq + b->cnc && b->cnc < Maxblock)
return; return;
flush(b); flush(b);
/* find block */ /* find block */
if(q0 < b->cq){ if (q0 < b->cq) {
q = 0; q = 0;
i = 0; i = 0;
}else{ } else {
q = b->cq; q = b->cq;
i = b->cbi; i = b->cbi;
} }
blp = &b->bl[i]; blp = &b->bl[i];
while(q+(*blp)->u.n <= q0 && q+(*blp)->u.n < b->nc){ while (q + (*blp)->u.n <= q0 && q + (*blp)->u.n < b->nc) {
q += (*blp)->u.n; q += (*blp)->u.n;
i++; i++;
blp++; blp++;
if(i >= b->nbl) if (i >= b->nbl)
error("block not found"); error("block not found");
} }
bl = *blp; bl = *blp;
/* remember position */ /* remember position */
b->cbi = i; b->cbi = i;
b->cq = q; b->cq = q;
sizecache(b, bl->u.n); sizecache(b, bl->u.n);
b->cnc = bl->u.n; b->cnc = bl->u.n;
/*read block*/ /*read block*/
diskread(disk, bl, b->c, b->cnc); diskread(disk, bl, b->c, b->cnc);
} }
void void bufinsert(Buffer* b, uint q0, Rune* s, uint n) {
bufinsert(Buffer *b, uint q0, Rune *s, uint n) uint i, m, t, off;
{
uint i, m, t, off;
if(q0 > b->nc) if (q0 > b->nc)
error("internal error: bufinsert"); error("internal error: bufinsert");
while(n > 0){ while (n > 0) {
setcache(b, q0); setcache(b, q0);
off = q0-b->cq; off = q0 - b->cq;
if(b->cnc+n <= Maxblock){ if (b->cnc + n <= Maxblock) {
/* Everything fits in one block. */ /* Everything fits in one block. */
t = b->cnc+n; t = b->cnc + n;
m = n; m = n;
if(b->bl == nil){ /* allocate */ if (b->bl == nil) { /* allocate */
if(b->cnc != 0) if (b->cnc != 0)
error("internal error: bufinsert1 cnc!=0"); error("internal error: bufinsert1 cnc!=0");
addblock(b, 0, t); addblock(b, 0, t);
b->cbi = 0; b->cbi = 0;
} }
sizecache(b, t); sizecache(b, t);
runemove(b->c+off+m, b->c+off, b->cnc-off); runemove(b->c + off + m, b->c + off, b->cnc - off);
runemove(b->c+off, s, m); runemove(b->c + off, s, m);
b->cnc = t; b->cnc = t;
goto Tail; goto Tail;
} }
/* /*
* We must make a new block. If q0 is at * We must make a new block. If q0 is at
* the very beginning or end of this block, * the very beginning or end of this block,
* just make a new block and fill it. * just make a new block and fill it.
*/ */
if(q0==b->cq || q0==b->cq+b->cnc){ if (q0 == b->cq || q0 == b->cq + b->cnc) {
if(b->cdirty) if (b->cdirty)
flush(b); flush(b);
m = min(n, Maxblock); m = min(n, Maxblock);
if(b->bl == nil){ /* allocate */ if (b->bl == nil) { /* allocate */
if(b->cnc != 0) if (b->cnc != 0)
error("internal error: bufinsert2 cnc!=0"); error("internal error: bufinsert2 cnc!=0");
i = 0; i = 0;
}else{ } else {
i = b->cbi; i = b->cbi;
if(q0 > b->cq) if (q0 > b->cq)
i++; i++;
} }
addblock(b, i, m); addblock(b, i, m);
sizecache(b, m); sizecache(b, m);
runemove(b->c, s, m); runemove(b->c, s, m);
b->cq = q0; b->cq = q0;
b->cbi = i; b->cbi = i;
b->cnc = m; b->cnc = m;
goto Tail; goto Tail;
} }
/* /*
* Split the block; cut off the right side and * Split the block; cut off the right side and
* let go of it. * let go of it.
*/ */
m = b->cnc-off; m = b->cnc - off;
if(m > 0){ if (m > 0) {
i = b->cbi+1; i = b->cbi + 1;
addblock(b, i, m); addblock(b, i, m);
diskwrite(disk, &b->bl[i], b->c+off, m); diskwrite(disk, &b->bl[i], b->c + off, m);
b->cnc -= m; b->cnc -= m;
} }
/* /*
* Now at end of block. Take as much input * Now at end of block. Take as much input
* as possible and tack it on end of block. * as possible and tack it on end of block.
*/ */
m = min(n, Maxblock-b->cnc); m = min(n, Maxblock - b->cnc);
sizecache(b, b->cnc+m); sizecache(b, b->cnc + m);
runemove(b->c+b->cnc, s, m); runemove(b->c + b->cnc, s, m);
b->cnc += m; b->cnc += m;
Tail: Tail:
b->nc += m; b->nc += m;
q0 += m; q0 += m;
s += m; s += m;
n -= m; n -= m;
b->cdirty = TRUE; b->cdirty = TRUE;
} }
} }
void void bufdelete(Buffer* b, uint q0, uint q1) {
bufdelete(Buffer *b, uint q0, uint q1) uint m, n, off;
{
uint m, n, off;
if(!(q0<=q1 && q0<=b->nc && q1<=b->nc)) if (!(q0 <= q1 && q0 <= b->nc && q1 <= b->nc))
error("internal error: bufdelete"); error("internal error: bufdelete");
while(q1 > q0){ while (q1 > q0) {
setcache(b, q0); setcache(b, q0);
off = q0-b->cq; off = q0 - b->cq;
if(q1 > b->cq+b->cnc) if (q1 > b->cq + b->cnc)
n = b->cnc - off; n = b->cnc - off;
else else
n = q1-q0; n = q1 - q0;
m = b->cnc - (off+n); m = b->cnc - (off + n);
if(m > 0) if (m > 0)
runemove(b->c+off, b->c+off+n, m); runemove(b->c + off, b->c + off + n, m);
b->cnc -= n; b->cnc -= n;
b->cdirty = TRUE; b->cdirty = TRUE;
q1 -= n; q1 -= n;
b->nc -= n; b->nc -= n;
} }
} }
static int static int bufloader(void* v, uint q0, Rune* r, int nr) {
bufloader(void *v, uint q0, Rune *r, int nr) bufinsert(v, q0, r, nr);
{ return nr;
bufinsert(v, q0, r, nr);
return nr;
} }
uint uint loadfile(
loadfile(int fd, uint q0, int *nulls, int(*f)(void*, uint, Rune*, int), void *arg, DigestState *h) int fd, uint q0, int* nulls, int (*f)(void*, uint, Rune*, int), void* arg,
{ DigestState* h) {
char *p; char* p;
Rune *r; Rune* r;
int l, m, n, nb, nr; int l, m, n, nb, nr;
uint q1; uint q1;
p = emalloc((Maxblock+UTFmax+1)*sizeof p[0]); p = emalloc((Maxblock + UTFmax + 1) * sizeof p[0]);
r = runemalloc(Maxblock); r = runemalloc(Maxblock);
m = 0; m = 0;
n = 1; n = 1;
q1 = q0; q1 = q0;
/* /*
* At top of loop, may have m bytes left over from * At top of loop, may have m bytes left over from
* last pass, possibly representing a partial rune. * last pass, possibly representing a partial rune.
*/ */
while(n > 0){ while (n > 0) {
n = read(fd, p+m, Maxblock); n = read(fd, p + m, Maxblock);
if(n < 0){ if (n < 0) {
warning(nil, "read error in Buffer.load"); warning(nil, "read error in Buffer.load");
break; break;
} }
if(h != nil) if (h != nil)
sha1((uchar*)p+m, n, nil, h); sha1((uchar*)p + m, n, nil, h);
m += n; m += n;
p[m] = 0; p[m] = 0;
l = m; l = m;
if(n > 0) if (n > 0)
l -= UTFmax; l -= UTFmax;
cvttorunes(p, l, r, &nb, &nr, nulls); cvttorunes(p, l, r, &nb, &nr, nulls);
memmove(p, p+nb, m-nb); memmove(p, p + nb, m - nb);
m -= nb; m -= nb;
q1 += (*f)(arg, q1, r, nr); q1 += (*f)(arg, q1, r, nr);
} }
free(p); free(p);
free(r); free(r);
return q1-q0; return q1 - q0;
} }
uint uint bufload(Buffer* b, uint q0, int fd, int* nulls, DigestState* h) {
bufload(Buffer *b, uint q0, int fd, int *nulls, DigestState *h) if (q0 > b->nc)
{ error("internal error: bufload");
if(q0 > b->nc) return loadfile(fd, q0, nulls, bufloader, b, h);
error("internal error: bufload");
return loadfile(fd, q0, nulls, bufloader, b, h);
} }
void void bufread(Buffer* b, uint q0, Rune* s, uint n) {
bufread(Buffer *b, uint q0, Rune *s, uint n) uint m;
{
uint m;
if(!(q0<=b->nc && q0+n<=b->nc)) if (!(q0 <= b->nc && q0 + n <= b->nc))
error("bufread: internal error"); error("bufread: internal error");
while(n > 0){ while (n > 0) {
setcache(b, q0); setcache(b, q0);
m = min(n, b->cnc-(q0-b->cq)); m = min(n, b->cnc - (q0 - b->cq));
runemove(s, b->c+(q0-b->cq), m); runemove(s, b->c + (q0 - b->cq), m);
q0 += m; q0 += m;
s += m; s += m;
n -= m; n -= m;
} }
} }
void void bufreset(Buffer* b) {
bufreset(Buffer *b) int i;
{
int i;
b->nc = 0; b->nc = 0;
b->cnc = 0; b->cnc = 0;
b->cq = 0; b->cq = 0;
b->cdirty = 0; b->cdirty = 0;
b->cbi = 0; b->cbi = 0;
/* delete backwards to avoid n² behavior */ /* delete backwards to avoid n² behavior */
for(i=b->nbl-1; --i>=0; ) for (i = b->nbl - 1; --i >= 0;)
delblock(b, i); delblock(b, i);
} }
void void bufclose(Buffer* b) {
bufclose(Buffer *b) bufreset(b);
{ free(b->c);
bufreset(b); b->c = nil;
free(b->c); b->cnc = 0;
b->c = nil; free(b->bl);
b->cnc = 0; b->bl = nil;
free(b->bl); b->nbl = 0;
b->bl = nil;
b->nbl = 0;
} }

8
build.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
clang-format -i ./*.c
clang-format -i ./mail/*.c
mk
mv o.acme acme

1091
cols.c

File diff suppressed because it is too large Load diff

181
disk.c
View file

@ -12,122 +12,107 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
static Block *blist; static Block* blist;
int int tempfile(void) {
tempfile(void) char buf[128];
{ int i, fd;
char buf[128];
int i, fd;
snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser()); snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
for(i='A'; i<='Z'; i++){ for (i = 'A'; i <= 'Z'; i++) {
buf[5] = i; buf[5] = i;
if(access(buf, AEXIST) == 0) if (access(buf, AEXIST) == 0)
continue; continue;
fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600); fd = create(buf, ORDWR | ORCLOSE | OCEXEC, 0600);
if(fd >= 0) if (fd >= 0)
return fd; return fd;
} }
return -1; return -1;
} }
Disk* Disk* diskinit() {
diskinit() Disk* d;
{
Disk *d;
d = emalloc(sizeof(Disk)); d = emalloc(sizeof(Disk));
d->fd = tempfile(); d->fd = tempfile();
if(d->fd < 0){ if (d->fd < 0) {
fprint(2, "acme: can't create temp file: %r\n"); fprint(2, "acme: can't create temp file: %r\n");
threadexitsall("diskinit"); threadexitsall("diskinit");
} }
return d; return d;
} }
static static uint ntosize(uint n, uint* ip) {
uint uint size;
ntosize(uint n, uint *ip)
{
uint size;
if(n > Maxblock) if (n > Maxblock)
error("internal error: ntosize"); error("internal error: ntosize");
size = n; size = n;
if(size & (Blockincr-1)) if (size & (Blockincr - 1))
size += Blockincr - (size & (Blockincr-1)); size += Blockincr - (size & (Blockincr - 1));
/* last bucket holds blocks of exactly Maxblock */ /* last bucket holds blocks of exactly Maxblock */
if(ip) if (ip)
*ip = size/Blockincr; *ip = size / Blockincr;
return size * sizeof(Rune); return size * sizeof(Rune);
} }
Block* Block* disknewblock(Disk* d, uint n) {
disknewblock(Disk *d, uint n) uint i, j, size;
{ Block* b;
uint i, j, size;
Block *b;
size = ntosize(n, &i); size = ntosize(n, &i);
b = d->free[i]; b = d->free[i];
if(b) if (b)
d->free[i] = b->u.next; d->free[i] = b->u.next;
else{ else {
/* allocate in chunks to reduce malloc overhead */ /* allocate in chunks to reduce malloc overhead */
if(blist == nil){ if (blist == nil) {
blist = emalloc(100*sizeof(Block)); blist = emalloc(100 * sizeof(Block));
for(j=0; j<100-1; j++) for (j = 0; j < 100 - 1; j++)
blist[j].u.next = &blist[j+1]; blist[j].u.next = &blist[j + 1];
} }
b = blist; b = blist;
blist = b->u.next; blist = b->u.next;
b->addr = d->addr; b->addr = d->addr;
if(d->addr+size < d->addr){ if (d->addr + size < d->addr) {
error("temp file overflow"); error("temp file overflow");
} }
d->addr += size; d->addr += size;
} }
b->u.n = n; b->u.n = n;
return b; return b;
} }
void void diskrelease(Disk* d, Block* b) {
diskrelease(Disk *d, Block *b) uint i;
{
uint i;
ntosize(b->u.n, &i); ntosize(b->u.n, &i);
b->u.next = d->free[i]; b->u.next = d->free[i];
d->free[i] = b; d->free[i] = b;
} }
void void diskwrite(Disk* d, Block** bp, Rune* r, uint n) {
diskwrite(Disk *d, Block **bp, Rune *r, uint n) int size, nsize;
{ Block* b;
int size, nsize;
Block *b;
b = *bp; b = *bp;
size = ntosize(b->u.n, nil); size = ntosize(b->u.n, nil);
nsize = ntosize(n, nil); nsize = ntosize(n, nil);
if(size != nsize){ if (size != nsize) {
diskrelease(d, b); diskrelease(d, b);
b = disknewblock(d, n); b = disknewblock(d, n);
*bp = b; *bp = b;
} }
if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) if (pwrite(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
error("write error to temp file"); error("write error to temp file");
b->u.n = n; b->u.n = n;
} }
void void diskread(Disk* d, Block* b, Rune* r, uint n) {
diskread(Disk *d, Block *b, Rune *r, uint n) if (n > b->u.n)
{ error("internal error: diskread");
if(n > b->u.n)
error("internal error: diskread");
ntosize(b->u.n, nil); ntosize(b->u.n, nil);
if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) if (pread(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
error("read error from temp file"); error("read error from temp file");
} }

2312
ecmd.c

File diff suppressed because it is too large Load diff

1310
edit.c

File diff suppressed because it is too large Load diff

563
elog.c
View file

@ -14,7 +14,7 @@
#include "edit.h" #include "edit.h"
static char Wsequence[] = "warning: changes out of sequence\n"; static char Wsequence[] = "warning: changes out of sequence\n";
static int warned = FALSE; static int warned = FALSE;
/* /*
* Log of changes made by editing commands. Three reasons for this: * Log of changes made by editing commands. Three reasons for this:
@ -27,328 +27,321 @@ static int warned = FALSE;
*/ */
typedef struct Buflog Buflog; typedef struct Buflog Buflog;
struct Buflog struct Buflog {
{ short type; /* Replace, Filename */
short type; /* Replace, Filename */ uint q0; /* location of change (unused in f) */
uint q0; /* location of change (unused in f) */ uint nd; /* # runes to delete */
uint nd; /* # runes to delete */ uint nr; /* # runes in string or file name */
uint nr; /* # runes in string or file name */
}; };
enum enum { Buflogsize = sizeof(Buflog) / sizeof(Rune) };
{
Buflogsize = sizeof(Buflog)/sizeof(Rune)
};
/* /*
* Minstring shouldn't be very big or we will do lots of I/O for small changes. * Minstring shouldn't be very big or we will do lots of I/O for small changes.
* Maxstring is RBUFSIZE so we can fbufalloc() once and not realloc elog.r. * Maxstring is RBUFSIZE so we can fbufalloc() once and not realloc elog.r.
*/ */
enum enum {
{ Minstring = 16, /* distance beneath which we merge changes */
Minstring = 16, /* distance beneath which we merge changes */ Maxstring = RBUFSIZE /* maximum length of change we will merge into one */
Maxstring = RBUFSIZE /* maximum length of change we will merge into one */
}; };
void void eloginit(File* f) {
eloginit(File *f) if (f->elog.type != Empty)
{ return;
if(f->elog.type != Empty) f->elog.type = Null;
return; if (f->elogbuf == nil)
f->elog.type = Null; f->elogbuf = emalloc(sizeof(Buffer));
if(f->elogbuf == nil) if (f->elog.r == nil)
f->elogbuf = emalloc(sizeof(Buffer)); f->elog.r = fbufalloc();
if(f->elog.r == nil) bufreset(f->elogbuf);
f->elog.r = fbufalloc();
bufreset(f->elogbuf);
} }
void void elogclose(File* f) {
elogclose(File *f) if (f->elogbuf) {
{ bufclose(f->elogbuf);
if(f->elogbuf){ free(f->elogbuf);
bufclose(f->elogbuf); f->elogbuf = nil;
free(f->elogbuf); }
f->elogbuf = nil;
}
} }
void void elogreset(File* f) {
elogreset(File *f) f->elog.type = Null;
{ f->elog.nd = 0;
f->elog.type = Null; f->elog.nr = 0;
f->elog.nd = 0;
f->elog.nr = 0;
} }
void void elogterm(File* f) {
elogterm(File *f) elogreset(f);
{ if (f->elogbuf)
elogreset(f); bufreset(f->elogbuf);
if(f->elogbuf) f->elog.type = Empty;
bufreset(f->elogbuf); fbuffree(f->elog.r);
f->elog.type = Empty; f->elog.r = nil;
fbuffree(f->elog.r); warned = FALSE;
f->elog.r = nil;
warned = FALSE;
} }
void void elogflush(File* f) {
elogflush(File *f) Buflog b;
{
Buflog b;
b.type = f->elog.type; b.type = f->elog.type;
b.q0 = f->elog.q0; b.q0 = f->elog.q0;
b.nd = f->elog.nd; b.nd = f->elog.nd;
b.nr = f->elog.nr; b.nr = f->elog.nr;
switch(f->elog.type){ switch (f->elog.type) {
default: default:
warning(nil, "unknown elog type 0x%ux\n", f->elog.type); warning(nil, "unknown elog type 0x%ux\n", f->elog.type);
break; break;
case Null: case Null:
break; break;
case Insert: case Insert:
case Replace: case Replace:
if(f->elog.nr > 0) if (f->elog.nr > 0)
bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr); bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr);
/* fall through */ /* fall through */
case Delete: case Delete:
bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize); bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize);
break; break;
} }
elogreset(f); elogreset(f);
} }
void void elogreplace(File* f, int q0, int q1, Rune* r, int nr) {
elogreplace(File *f, int q0, int q1, Rune *r, int nr) uint gap;
{
uint gap;
if(q0==q1 && nr==0) if (q0 == q1 && nr == 0)
return; return;
eloginit(f); eloginit(f);
if(f->elog.type!=Null && q0<f->elog.q0){ if (f->elog.type != Null && q0 < f->elog.q0) {
if(warned++ == 0) if (warned++ == 0)
warning(nil, Wsequence); warning(nil, Wsequence);
elogflush(f); elogflush(f);
} }
/* try to merge with previous */ /* try to merge with previous */
gap = q0 - (f->elog.q0+f->elog.nd); /* gap between previous and this */ gap = q0 - (f->elog.q0 + f->elog.nd); /* gap between previous and this */
if(f->elog.type==Replace && f->elog.nr+gap+nr<Maxstring){ if (f->elog.type == Replace && f->elog.nr + gap + nr < Maxstring) {
if(gap < Minstring){ if (gap < Minstring) {
if(gap > 0){ if (gap > 0) {
bufread(&f->b, f->elog.q0+f->elog.nd, f->elog.r+f->elog.nr, gap); bufread(&f->b, f->elog.q0 + f->elog.nd, f->elog.r + f->elog.nr, gap);
f->elog.nr += gap; f->elog.nr += gap;
} }
f->elog.nd += gap + q1-q0; f->elog.nd += gap + q1 - q0;
runemove(f->elog.r+f->elog.nr, r, nr); runemove(f->elog.r + f->elog.nr, r, nr);
f->elog.nr += nr; f->elog.nr += nr;
return; return;
} }
} }
elogflush(f); elogflush(f);
f->elog.type = Replace; f->elog.type = Replace;
f->elog.q0 = q0; f->elog.q0 = q0;
f->elog.nd = q1-q0; f->elog.nd = q1 - q0;
f->elog.nr = nr; f->elog.nr = nr;
if(nr > RBUFSIZE) if (nr > RBUFSIZE)
editerror("internal error: replacement string too large(%d)", nr); editerror("internal error: replacement string too large(%d)", nr);
runemove(f->elog.r, r, nr); runemove(f->elog.r, r, nr);
} }
void void eloginsert(File* f, int q0, Rune* r, int nr) {
eloginsert(File *f, int q0, Rune *r, int nr) int n;
{
int n;
if(nr == 0) if (nr == 0)
return; return;
eloginit(f); eloginit(f);
if(f->elog.type!=Null && q0<f->elog.q0){ if (f->elog.type != Null && q0 < f->elog.q0) {
if(warned++ == 0) if (warned++ == 0)
warning(nil, Wsequence); warning(nil, Wsequence);
elogflush(f); elogflush(f);
} }
/* try to merge with previous */ /* try to merge with previous */
if(f->elog.type==Insert && q0==f->elog.q0 && f->elog.nr+nr<Maxstring){ if (
runemove(f->elog.r+f->elog.nr, r, nr); f->elog.type == Insert && q0 == f->elog.q0 && f->elog.nr + nr < Maxstring) {
f->elog.nr += nr; runemove(f->elog.r + f->elog.nr, r, nr);
return; f->elog.nr += nr;
} return;
while(nr > 0){ }
elogflush(f); while (nr > 0) {
f->elog.type = Insert; elogflush(f);
f->elog.q0 = q0; f->elog.type = Insert;
n = nr; f->elog.q0 = q0;
if(n > RBUFSIZE) n = nr;
n = RBUFSIZE; if (n > RBUFSIZE)
f->elog.nr = n; n = RBUFSIZE;
runemove(f->elog.r, r, n); f->elog.nr = n;
r += n; runemove(f->elog.r, r, n);
nr -= n; r += n;
} nr -= n;
}
} }
void void elogdelete(File* f, int q0, int q1) {
elogdelete(File *f, int q0, int q1) if (q0 == q1)
{ return;
if(q0 == q1) eloginit(f);
return; if (f->elog.type != Null && q0 < f->elog.q0 + f->elog.nd) {
eloginit(f); if (warned++ == 0)
if(f->elog.type!=Null && q0<f->elog.q0+f->elog.nd){ warning(nil, Wsequence);
if(warned++ == 0) elogflush(f);
warning(nil, Wsequence); }
elogflush(f); /* try to merge with previous */
} if (f->elog.type == Delete && f->elog.q0 + f->elog.nd == q0) {
/* try to merge with previous */ f->elog.nd += q1 - q0;
if(f->elog.type==Delete && f->elog.q0+f->elog.nd==q0){ return;
f->elog.nd += q1-q0; }
return; elogflush(f);
} f->elog.type = Delete;
elogflush(f); f->elog.q0 = q0;
f->elog.type = Delete; f->elog.nd = q1 - q0;
f->elog.q0 = q0;
f->elog.nd = q1-q0;
} }
#define tracelog 0 #define tracelog 0
void void elogapply(File* f) {
elogapply(File *f) Buflog b;
{ Rune* buf;
Buflog b; uint i, n, up, mod;
Rune *buf; uint tq0, tq1;
uint i, n, up, mod; Buffer* log;
uint tq0, tq1; Text* t;
Buffer *log; int owner;
Text *t;
int owner;
elogflush(f); elogflush(f);
log = f->elogbuf; log = f->elogbuf;
t = f->curtext; t = f->curtext;
buf = fbufalloc(); buf = fbufalloc();
mod = FALSE; mod = FALSE;
owner = 0; owner = 0;
if(t->w){ if (t->w) {
owner = t->w->owner; owner = t->w->owner;
if(owner == 0) if (owner == 0)
t->w->owner = 'E'; t->w->owner = 'E';
} }
/* /*
* The edit commands have already updated the selection in t->q0, t->q1, * The edit commands have already updated the selection in t->q0, t->q1,
* but using coordinates relative to the unmodified buffer. As we apply the log, * but using coordinates relative to the unmodified buffer. As we apply the
* we have to update the coordinates to be relative to the modified buffer. * log, we have to update the coordinates to be relative to the modified
* Textinsert and textdelete will do this for us; our only work is to apply the * buffer. Textinsert and textdelete will do this for us; our only work is to
* convention that an insertion at t->q0==t->q1 is intended to select the * apply the convention that an insertion at t->q0==t->q1 is intended to
* inserted text. * select the inserted text.
*/ */
/* /*
* We constrain the addresses in here (with textconstrain()) because * We constrain the addresses in here (with textconstrain()) because
* overlapping changes will generate bogus addresses. We will warn * overlapping changes will generate bogus addresses. We will warn
* about changes out of sequence but proceed anyway; here we must * about changes out of sequence but proceed anyway; here we must
* keep things in range. * keep things in range.
*/ */
while(log->nc > 0){ while (log->nc > 0) {
up = log->nc-Buflogsize; up = log->nc - Buflogsize;
bufread(log, up, (Rune*)&b, Buflogsize); bufread(log, up, (Rune*)&b, Buflogsize);
switch(b.type){ switch (b.type) {
default: default:
fprint(2, "elogapply: 0x%ux\n", b.type); fprint(2, "elogapply: 0x%ux\n", b.type);
abort(); abort();
break; break;
case Replace: case Replace:
if(tracelog) if (tracelog)
warning(nil, "elog replace %d %d (%d %d)\n", warning(
b.q0, b.q0+b.nd, t->q0, t->q1); nil,
if(!mod){ "elog replace %d %d (%d %d)\n",
mod = TRUE; b.q0,
filemark(f); b.q0 + b.nd,
} t->q0,
textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1); t->q1);
textdelete(t, tq0, tq1, TRUE); if (!mod) {
up -= b.nr; mod = TRUE;
for(i=0; i<b.nr; i+=n){ filemark(f);
n = b.nr - i; }
if(n > RBUFSIZE) textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1);
n = RBUFSIZE; textdelete(t, tq0, tq1, TRUE);
bufread(log, up+i, buf, n); up -= b.nr;
textinsert(t, tq0+i, buf, n, TRUE); for (i = 0; i < b.nr; i += n) {
} n = b.nr - i;
if(t->q0 == b.q0 && t->q1 == b.q0) if (n > RBUFSIZE)
t->q1 += b.nr; n = RBUFSIZE;
break; bufread(log, up + i, buf, n);
textinsert(t, tq0 + i, buf, n, TRUE);
}
if (t->q0 == b.q0 && t->q1 == b.q0)
t->q1 += b.nr;
break;
case Delete: case Delete:
if(tracelog) if (tracelog)
warning(nil, "elog delete %d %d (%d %d)\n", warning(
b.q0, b.q0+b.nd, t->q0, t->q1); nil,
if(!mod){ "elog delete %d %d (%d %d)\n",
mod = TRUE; b.q0,
filemark(f); b.q0 + b.nd,
} t->q0,
textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1); t->q1);
textdelete(t, tq0, tq1, TRUE); if (!mod) {
break; mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1);
textdelete(t, tq0, tq1, TRUE);
break;
case Insert: case Insert:
if(tracelog) if (tracelog)
warning(nil, "elog insert %d %d (%d %d)\n", warning(
b.q0, b.q0+b.nr, t->q0, t->q1); nil,
if(!mod){ "elog insert %d %d (%d %d)\n",
mod = TRUE; b.q0,
filemark(f); b.q0 + b.nr,
} t->q0,
textconstrain(t, b.q0, b.q0, &tq0, &tq1); t->q1);
up -= b.nr; if (!mod) {
for(i=0; i<b.nr; i+=n){ mod = TRUE;
n = b.nr - i; filemark(f);
if(n > RBUFSIZE) }
n = RBUFSIZE; textconstrain(t, b.q0, b.q0, &tq0, &tq1);
bufread(log, up+i, buf, n); up -= b.nr;
textinsert(t, tq0+i, buf, n, TRUE); for (i = 0; i < b.nr; i += n) {
} n = b.nr - i;
if(t->q0 == b.q0 && t->q1 == b.q0) if (n > RBUFSIZE)
t->q1 += b.nr; n = RBUFSIZE;
break; bufread(log, up + i, buf, n);
textinsert(t, tq0 + i, buf, n, TRUE);
}
if (t->q0 == b.q0 && t->q1 == b.q0)
t->q1 += b.nr;
break;
/* case Filename: /* case Filename:
f->seq = u.seq; f->seq = u.seq;
fileunsetname(f, epsilon); fileunsetname(f, epsilon);
f->mod = u.mod; f->mod = u.mod;
up -= u.n; up -= u.n;
free(f->name); free(f->name);
if(u.n == 0) if(u.n == 0)
f->name = nil; f->name = nil;
else else
f->name = runemalloc(u.n); f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n); bufread(delta, up, f->name, u.n);
f->nname = u.n; f->nname = u.n;
break; break;
*/ */
} }
bufdelete(log, up, log->nc); bufdelete(log, up, log->nc);
} }
fbuffree(buf); fbuffree(buf);
elogterm(f); elogterm(f);
/*
* Bad addresses will cause bufload to crash, so double check.
* If changes were out of order, we expect problems so don't complain further.
*/
if(t->q0 > f->b.nc || t->q1 > f->b.nc || t->q0 > t->q1){
if(!warned)
warning(nil, "elogapply: can't happen %d %d %d\n", t->q0, t->q1, f->b.nc);
t->q1 = min(t->q1, f->b.nc);
t->q0 = min(t->q0, t->q1);
}
if(t->w) /*
t->w->owner = owner; * Bad addresses will cause bufload to crash, so double check.
* If changes were out of order, we expect problems so don't complain further.
*/
if (t->q0 > f->b.nc || t->q1 > f->b.nc || t->q0 > t->q1) {
if (!warned)
warning(nil, "elogapply: can't happen %d %d %d\n", t->q0, t->q1, f->b.nc);
t->q1 = min(t->q1, f->b.nc);
t->q0 = min(t->q0, t->q1);
}
if (t->w)
t->w->owner = owner;
} }

3144
exec.c

File diff suppressed because it is too large Load diff

455
file.c
View file

@ -23,289 +23,256 @@
*/ */
typedef struct Undo Undo; typedef struct Undo Undo;
struct Undo struct Undo {
{ short type; /* Delete, Insert, Filename */
short type; /* Delete, Insert, Filename */ short mod; /* modify bit */
short mod; /* modify bit */ uint seq; /* sequence number */
uint seq; /* sequence number */ uint p0; /* location of change (unused in f) */
uint p0; /* location of change (unused in f) */ uint n; /* # runes in string or file name */
uint n; /* # runes in string or file name */
}; };
enum enum { Undosize = sizeof(Undo) / sizeof(Rune) };
{
Undosize = sizeof(Undo)/sizeof(Rune)
};
File* File* fileaddtext(File* f, Text* t) {
fileaddtext(File *f, Text *t) if (f == nil) {
{ f = emalloc(sizeof(File));
if(f == nil){ f->unread = TRUE;
f = emalloc(sizeof(File)); }
f->unread = TRUE; f->text = realloc(f->text, (f->ntext + 1) * sizeof(Text*));
} f->text[f->ntext++] = t;
f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*)); f->curtext = t;
f->text[f->ntext++] = t; return f;
f->curtext = t;
return f;
} }
void void filedeltext(File* f, Text* t) {
filedeltext(File *f, Text *t) int i;
{
int i;
for(i=0; i<f->ntext; i++) for (i = 0; i < f->ntext; i++)
if(f->text[i] == t) if (f->text[i] == t)
goto Found; goto Found;
error("can't find text in filedeltext"); error("can't find text in filedeltext");
Found: Found:
f->ntext--; f->ntext--;
if(f->ntext == 0){ if (f->ntext == 0) {
fileclose(f); fileclose(f);
return; return;
} }
memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*)); memmove(f->text + i, f->text + i + 1, (f->ntext - i) * sizeof(Text*));
if(f->curtext == t) if (f->curtext == t)
f->curtext = f->text[0]; f->curtext = f->text[0];
} }
void void fileinsert(File* f, uint p0, Rune* s, uint ns) {
fileinsert(File *f, uint p0, Rune *s, uint ns) if (p0 > f->b.nc)
{ error("internal error: fileinsert");
if(p0 > f->b.nc) if (f->seq > 0)
error("internal error: fileinsert"); fileuninsert(f, &f->delta, p0, ns);
if(f->seq > 0) bufinsert(&f->b, p0, s, ns);
fileuninsert(f, &f->delta, p0, ns); if (ns)
bufinsert(&f->b, p0, s, ns); f->mod = TRUE;
if(ns)
f->mod = TRUE;
} }
void void fileuninsert(File* f, Buffer* delta, uint p0, uint ns) {
fileuninsert(File *f, Buffer *delta, uint p0, uint ns) Undo u;
{
Undo u;
/* undo an insertion by deleting */ /* undo an insertion by deleting */
u.type = Delete; u.type = Delete;
u.mod = f->mod; u.mod = f->mod;
u.seq = f->seq; u.seq = f->seq;
u.p0 = p0; u.p0 = p0;
u.n = ns; u.n = ns;
bufinsert(delta, delta->nc, (Rune*)&u, Undosize); bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
} }
void void filedelete(File* f, uint p0, uint p1) {
filedelete(File *f, uint p0, uint p1) if (!(p0 <= p1 && p0 <= f->b.nc && p1 <= f->b.nc))
{ error("internal error: filedelete");
if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc)) if (f->seq > 0)
error("internal error: filedelete"); fileundelete(f, &f->delta, p0, p1);
if(f->seq > 0) bufdelete(&f->b, p0, p1);
fileundelete(f, &f->delta, p0, p1); if (p1 > p0)
bufdelete(&f->b, p0, p1); f->mod = TRUE;
if(p1 > p0)
f->mod = TRUE;
} }
void void fileundelete(File* f, Buffer* delta, uint p0, uint p1) {
fileundelete(File *f, Buffer *delta, uint p0, uint p1) Undo u;
{ Rune* buf;
Undo u; uint i, n;
Rune *buf;
uint i, n;
/* undo a deletion by inserting */
u.type = Insert;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = p0;
u.n = p1-p0;
buf = fbufalloc();
for(i=p0; i<p1; i+=n){
n = p1 - i;
if(n > RBUFSIZE)
n = RBUFSIZE;
bufread(&f->b, i, buf, n);
bufinsert(delta, delta->nc, buf, n);
}
fbuffree(buf);
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
/* undo a deletion by inserting */
u.type = Insert;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = p0;
u.n = p1 - p0;
buf = fbufalloc();
for (i = p0; i < p1; i += n) {
n = p1 - i;
if (n > RBUFSIZE)
n = RBUFSIZE;
bufread(&f->b, i, buf, n);
bufinsert(delta, delta->nc, buf, n);
}
fbuffree(buf);
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
} }
void void filesetname(File* f, Rune* name, int n) {
filesetname(File *f, Rune *name, int n) if (f->seq > 0)
{ fileunsetname(f, &f->delta);
if(f->seq > 0) free(f->name);
fileunsetname(f, &f->delta); f->name = runemalloc(n);
free(f->name); runemove(f->name, name, n);
f->name = runemalloc(n); f->nname = n;
runemove(f->name, name, n); f->unread = TRUE;
f->nname = n;
f->unread = TRUE;
} }
void void fileunsetname(File* f, Buffer* delta) {
fileunsetname(File *f, Buffer *delta) Undo u;
{
Undo u;
/* undo a file name change by restoring old name */ /* undo a file name change by restoring old name */
u.type = Filename; u.type = Filename;
u.mod = f->mod; u.mod = f->mod;
u.seq = f->seq; u.seq = f->seq;
u.p0 = 0; /* unused */ u.p0 = 0; /* unused */
u.n = f->nname; u.n = f->nname;
if(f->nname) if (f->nname)
bufinsert(delta, delta->nc, f->name, f->nname); bufinsert(delta, delta->nc, f->name, f->nname);
bufinsert(delta, delta->nc, (Rune*)&u, Undosize); bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
} }
uint uint fileload(File* f, uint p0, int fd, int* nulls, DigestState* h) {
fileload(File *f, uint p0, int fd, int *nulls, DigestState *h) if (f->seq > 0)
{ error("undo in file.load unimplemented");
if(f->seq > 0) return bufload(&f->b, p0, fd, nulls, h);
error("undo in file.load unimplemented");
return bufload(&f->b, p0, fd, nulls, h);
} }
/* return sequence number of pending redo */ /* return sequence number of pending redo */
uint uint fileredoseq(File* f) {
fileredoseq(File *f) Undo u;
{ Buffer* delta;
Undo u;
Buffer *delta;
delta = &f->epsilon; delta = &f->epsilon;
if(delta->nc == 0) if (delta->nc == 0)
return 0; return 0;
bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize); bufread(delta, delta->nc - Undosize, (Rune*)&u, Undosize);
return u.seq; return u.seq;
} }
void void fileundo(File* f, int isundo, uint* q0p, uint* q1p) {
fileundo(File *f, int isundo, uint *q0p, uint *q1p) Undo u;
{ Rune* buf;
Undo u; uint i, j, n, up;
Rune *buf; uint stop;
uint i, j, n, up; Buffer *delta, *epsilon;
uint stop;
Buffer *delta, *epsilon;
if(isundo){ if (isundo) {
/* undo; reverse delta onto epsilon, seq decreases */ /* undo; reverse delta onto epsilon, seq decreases */
delta = &f->delta; delta = &f->delta;
epsilon = &f->epsilon; epsilon = &f->epsilon;
stop = f->seq; stop = f->seq;
}else{ } else {
/* redo; reverse epsilon onto delta, seq increases */ /* redo; reverse epsilon onto delta, seq increases */
delta = &f->epsilon; delta = &f->epsilon;
epsilon = &f->delta; epsilon = &f->delta;
stop = 0; /* don't know yet */ stop = 0; /* don't know yet */
} }
buf = fbufalloc(); buf = fbufalloc();
while(delta->nc > 0){ while (delta->nc > 0) {
up = delta->nc-Undosize; up = delta->nc - Undosize;
bufread(delta, up, (Rune*)&u, Undosize); bufread(delta, up, (Rune*)&u, Undosize);
if(isundo){ if (isundo) {
if(u.seq < stop){ if (u.seq < stop) {
f->seq = u.seq; f->seq = u.seq;
goto Return; goto Return;
} }
}else{ } else {
if(stop == 0) if (stop == 0)
stop = u.seq; stop = u.seq;
if(u.seq > stop) if (u.seq > stop)
goto Return; goto Return;
} }
switch(u.type){ switch (u.type) {
default: default:
fprint(2, "undo: 0x%ux\n", u.type); fprint(2, "undo: 0x%ux\n", u.type);
abort(); abort();
break; break;
case Delete: case Delete:
f->seq = u.seq; f->seq = u.seq;
fileundelete(f, epsilon, u.p0, u.p0+u.n); fileundelete(f, epsilon, u.p0, u.p0 + u.n);
f->mod = u.mod; f->mod = u.mod;
bufdelete(&f->b, u.p0, u.p0+u.n); bufdelete(&f->b, u.p0, u.p0 + u.n);
for(j=0; j<f->ntext; j++) for (j = 0; j < f->ntext; j++)
textdelete(f->text[j], u.p0, u.p0+u.n, FALSE); textdelete(f->text[j], u.p0, u.p0 + u.n, FALSE);
*q0p = u.p0; *q0p = u.p0;
*q1p = u.p0; *q1p = u.p0;
break; break;
case Insert: case Insert:
f->seq = u.seq; f->seq = u.seq;
fileuninsert(f, epsilon, u.p0, u.n); fileuninsert(f, epsilon, u.p0, u.n);
f->mod = u.mod; f->mod = u.mod;
up -= u.n; up -= u.n;
for(i=0; i<u.n; i+=n){ for (i = 0; i < u.n; i += n) {
n = u.n - i; n = u.n - i;
if(n > RBUFSIZE) if (n > RBUFSIZE)
n = RBUFSIZE; n = RBUFSIZE;
bufread(delta, up+i, buf, n); bufread(delta, up + i, buf, n);
bufinsert(&f->b, u.p0+i, buf, n); bufinsert(&f->b, u.p0 + i, buf, n);
for(j=0; j<f->ntext; j++) for (j = 0; j < f->ntext; j++)
textinsert(f->text[j], u.p0+i, buf, n, FALSE); textinsert(f->text[j], u.p0 + i, buf, n, FALSE);
} }
*q0p = u.p0; *q0p = u.p0;
*q1p = u.p0+u.n; *q1p = u.p0 + u.n;
break; break;
case Filename: case Filename:
f->seq = u.seq; f->seq = u.seq;
fileunsetname(f, epsilon); fileunsetname(f, epsilon);
f->mod = u.mod; f->mod = u.mod;
up -= u.n; up -= u.n;
free(f->name); free(f->name);
if(u.n == 0) if (u.n == 0)
f->name = nil; f->name = nil;
else else
f->name = runemalloc(u.n); f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n); bufread(delta, up, f->name, u.n);
f->nname = u.n; f->nname = u.n;
break; break;
} }
bufdelete(delta, up, delta->nc); bufdelete(delta, up, delta->nc);
} }
if(isundo) if (isundo)
f->seq = 0; f->seq = 0;
Return: Return:
fbuffree(buf); fbuffree(buf);
} }
void void filereset(File* f) {
filereset(File *f) bufreset(&f->delta);
{ bufreset(&f->epsilon);
bufreset(&f->delta); f->seq = 0;
bufreset(&f->epsilon);
f->seq = 0;
} }
void void fileclose(File* f) {
fileclose(File *f) free(f->name);
{ f->nname = 0;
free(f->name); f->name = nil;
f->nname = 0; free(f->text);
f->name = nil; f->ntext = 0;
free(f->text); f->text = nil;
f->ntext = 0; bufclose(&f->b);
f->text = nil; bufclose(&f->delta);
bufclose(&f->b); bufclose(&f->epsilon);
bufclose(&f->delta); elogclose(f);
bufclose(&f->epsilon); free(f);
elogclose(f);
free(f);
} }
void void filemark(File* f) {
filemark(File *f) if (f->epsilon.nc)
{ bufdelete(&f->epsilon, 0, f->epsilon.nc);
if(f->epsilon.nc) f->seq = seq;
bufdelete(&f->epsilon, 0, f->epsilon.nc);
f->seq = seq;
} }

1
fns.h
View file

@ -95,6 +95,7 @@ void flushwarnings(void);
void startplumbing(void); void startplumbing(void);
long nlcount(Text*, long, long, long*); long nlcount(Text*, long, long, long*);
long nlcounttopos(Text*, long, long, long); long nlcounttopos(Text*, long, long, long);
Rune* parsetag(Window*, int*);
Runestr runestr(Rune*, uint); Runestr runestr(Rune*, uint);
Range range(int, int); Range range(int, int);

1203
fsys.c

File diff suppressed because it is too large Load diff

271
logf.c
View file

@ -14,122 +14,114 @@
// State for global log file. // State for global log file.
typedef struct Log Log; typedef struct Log Log;
struct Log struct Log {
{ QLock lk;
QLock lk; Rendez r;
Rendez r;
vlong start; // msg[0] corresponds to 'start' in the global sequence of events vlong start; // msg[0] corresponds to 'start' in the global sequence of events
// queued events (nev=entries in ev, mev=capacity of p)
char **ev;
int nev;
int mev;
// open acme/put files that need to read events // queued events (nev=entries in ev, mev=capacity of p)
Fid **f; char** ev;
int nf; int nev;
int mf; int mev;
// active (blocked) reads waiting for events // open acme/put files that need to read events
Xfid **read; Fid** f;
int nread; int nf;
int mread; int mf;
// active (blocked) reads waiting for events
Xfid** read;
int nread;
int mread;
}; };
static Log eventlog; static Log eventlog;
void void xfidlogopen(Xfid* x) {
xfidlogopen(Xfid *x) qlock(&eventlog.lk);
{ if (eventlog.nf >= eventlog.mf) {
qlock(&eventlog.lk); eventlog.mf = eventlog.mf * 2;
if(eventlog.nf >= eventlog.mf) { if (eventlog.mf == 0)
eventlog.mf = eventlog.mf*2; eventlog.mf = 8;
if(eventlog.mf == 0) eventlog.f = erealloc(eventlog.f, eventlog.mf * sizeof eventlog.f[0]);
eventlog.mf = 8; }
eventlog.f = erealloc(eventlog.f, eventlog.mf*sizeof eventlog.f[0]); eventlog.f[eventlog.nf++] = x->f;
} x->f->logoff = eventlog.start + eventlog.nev;
eventlog.f[eventlog.nf++] = x->f;
x->f->logoff = eventlog.start + eventlog.nev;
qunlock(&eventlog.lk); qunlock(&eventlog.lk);
} }
void void xfidlogclose(Xfid* x) {
xfidlogclose(Xfid *x) int i;
{
int i;
qlock(&eventlog.lk); qlock(&eventlog.lk);
for(i=0; i<eventlog.nf; i++) { for (i = 0; i < eventlog.nf; i++) {
if(eventlog.f[i] == x->f) { if (eventlog.f[i] == x->f) {
eventlog.f[i] = eventlog.f[--eventlog.nf]; eventlog.f[i] = eventlog.f[--eventlog.nf];
break; break;
} }
} }
qunlock(&eventlog.lk); qunlock(&eventlog.lk);
} }
void void xfidlogread(Xfid* x) {
xfidlogread(Xfid *x) char* p;
{ int i;
char *p; Fcall fc;
int i;
Fcall fc;
qlock(&eventlog.lk); qlock(&eventlog.lk);
if(eventlog.nread >= eventlog.mread) { if (eventlog.nread >= eventlog.mread) {
eventlog.mread = eventlog.mread*2; eventlog.mread = eventlog.mread * 2;
if(eventlog.mread == 0) if (eventlog.mread == 0)
eventlog.mread = 8; eventlog.mread = 8;
eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]); eventlog.read =
} erealloc(eventlog.read, eventlog.mread * sizeof eventlog.read[0]);
eventlog.read[eventlog.nread++] = x; }
eventlog.read[eventlog.nread++] = x;
if(eventlog.r.l == nil)
eventlog.r.l = &eventlog.lk;
x->flushed = FALSE;
while(x->f->logoff >= eventlog.start+eventlog.nev && !x->flushed)
rsleep(&eventlog.r);
for(i=0; i<eventlog.nread; i++) {
if(eventlog.read[i] == x) {
eventlog.read[i] = eventlog.read[--eventlog.nread];
break;
}
}
if(x->flushed) { if (eventlog.r.l == nil)
qunlock(&eventlog.lk); eventlog.r.l = &eventlog.lk;
return; x->flushed = FALSE;
} while (x->f->logoff >= eventlog.start + eventlog.nev && !x->flushed)
rsleep(&eventlog.r);
i = x->f->logoff - eventlog.start; for (i = 0; i < eventlog.nread; i++) {
p = estrdup(eventlog.ev[i]); if (eventlog.read[i] == x) {
x->f->logoff++; eventlog.read[i] = eventlog.read[--eventlog.nread];
qunlock(&eventlog.lk); break;
}
}
fc.data = p; if (x->flushed) {
fc.count = strlen(p); qunlock(&eventlog.lk);
respond(x, &fc, nil); return;
free(p); }
i = x->f->logoff - eventlog.start;
p = estrdup(eventlog.ev[i]);
x->f->logoff++;
qunlock(&eventlog.lk);
fc.data = p;
fc.count = strlen(p);
respond(x, &fc, nil);
free(p);
} }
void void xfidlogflush(Xfid* x) {
xfidlogflush(Xfid *x) int i;
{ Xfid* rx;
int i;
Xfid *rx;
qlock(&eventlog.lk); qlock(&eventlog.lk);
for(i=0; i<eventlog.nread; i++) { for (i = 0; i < eventlog.nread; i++) {
rx = eventlog.read[i]; rx = eventlog.read[i];
if(rx->fcall.tag == x->fcall.oldtag) { if (rx->fcall.tag == x->fcall.oldtag) {
rx->flushed = TRUE; rx->flushed = TRUE;
rwakeupall(&eventlog.r); rwakeupall(&eventlog.r);
} }
} }
qunlock(&eventlog.lk); qunlock(&eventlog.lk);
} }
/* /*
@ -153,47 +145,48 @@ xfidlogflush(Xfid *x)
* op == "del" for deleted window * op == "del" for deleted window
* - called from winclose * - called from winclose
*/ */
void void xfidlog(Window* w, char* op) {
xfidlog(Window *w, char *op) int i, n;
{ vlong min;
int i, n; File* f;
vlong min; char* name;
File *f;
char *name;
qlock(&eventlog.lk); qlock(&eventlog.lk);
if(eventlog.nev >= eventlog.mev) { if (eventlog.nev >= eventlog.mev) {
// Remove and free any entries that all readers have read. // Remove and free any entries that all readers have read.
min = eventlog.start + eventlog.nev; min = eventlog.start + eventlog.nev;
for(i=0; i<eventlog.nf; i++) { for (i = 0; i < eventlog.nf; i++) {
if(min > eventlog.f[i]->logoff) if (min > eventlog.f[i]->logoff)
min = eventlog.f[i]->logoff; min = eventlog.f[i]->logoff;
} }
if(min > eventlog.start) { if (min > eventlog.start) {
n = min - eventlog.start; n = min - eventlog.start;
for(i=0; i<n; i++) for (i = 0; i < n; i++)
free(eventlog.ev[i]); free(eventlog.ev[i]);
eventlog.nev -= n; eventlog.nev -= n;
eventlog.start += n; eventlog.start += n;
memmove(eventlog.ev, eventlog.ev+n, eventlog.nev*sizeof eventlog.ev[0]); memmove(
} eventlog.ev,
eventlog.ev + n,
// Otherwise grow. eventlog.nev * sizeof eventlog.ev[0]);
if(eventlog.nev >= eventlog.mev) { }
eventlog.mev = eventlog.mev*2;
if(eventlog.mev == 0) // Otherwise grow.
eventlog.mev = 8; if (eventlog.nev >= eventlog.mev) {
eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]); eventlog.mev = eventlog.mev * 2;
} if (eventlog.mev == 0)
} eventlog.mev = 8;
f = w->body.file; eventlog.ev = erealloc(eventlog.ev, eventlog.mev * sizeof eventlog.ev[0]);
name = runetobyte(f->name, f->nname); }
if(name == nil) }
name = estrdup(""); f = w->body.file;
eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name); name = runetobyte(f->name, f->nname);
free(name); if (name == nil)
if(eventlog.r.l == nil) name = estrdup("");
eventlog.r.l = &eventlog.lk; eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name);
rwakeupall(&eventlog.r); free(name);
qunlock(&eventlog.lk); if (eventlog.r.l == nil)
eventlog.r.l = &eventlog.lk;
rwakeupall(&eventlog.r);
qunlock(&eventlog.lk);
} }

1593
look.c

File diff suppressed because it is too large Load diff

View file

@ -7,69 +7,65 @@
#include <9pclient.h> #include <9pclient.h>
#include "dat.h" #include "dat.h"
char* char* formathtml(char* body, int* np) {
formathtml(char *body, int *np) int i, j, p[2], q[2];
{ Exec* e;
int i, j, p[2], q[2]; char buf[1024];
Exec *e; Channel* sync;
char buf[1024];
Channel *sync;
e = emalloc(sizeof(struct Exec)); e = emalloc(sizeof(struct Exec));
if(pipe(p) < 0 || pipe(q) < 0) if (pipe(p) < 0 || pipe(q) < 0)
error("can't create pipe: %r"); error("can't create pipe: %r");
e->p[0] = p[0]; e->p[0] = p[0];
e->p[1] = p[1]; e->p[1] = p[1];
e->q[0] = q[0]; e->q[0] = q[0];
e->q[1] = q[1]; e->q[1] = q[1];
e->argv = emalloc(3*sizeof(char*)); e->argv = emalloc(3 * sizeof(char*));
e->argv[0] = estrdup("htmlfmt"); e->argv[0] = estrdup("htmlfmt");
e->argv[1] = estrdup("-cutf-8"); e->argv[1] = estrdup("-cutf-8");
e->argv[2] = nil; e->argv[2] = nil;
e->prog = "htmlfmt"; e->prog = "htmlfmt";
sync = chancreate(sizeof(int), 0); sync = chancreate(sizeof(int), 0);
e->sync = sync; e->sync = sync;
proccreate(execproc, e, EXECSTACK); proccreate(execproc, e, EXECSTACK);
recvul(sync); recvul(sync);
close(p[0]); close(p[0]);
close(q[1]); close(q[1]);
if((i=write(p[1], body, *np)) != *np){ if ((i = write(p[1], body, *np)) != *np) {
fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np); fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np);
close(p[1]); close(p[1]);
close(q[0]); close(q[0]);
return body; return body;
} }
close(p[1]); close(p[1]);
free(body); free(body);
body = nil; body = nil;
i = 0; i = 0;
for(;;){ for (;;) {
j = read(q[0], buf, sizeof buf); j = read(q[0], buf, sizeof buf);
if(j <= 0) if (j <= 0)
break; break;
body = realloc(body, i+j+1); body = realloc(body, i + j + 1);
if(body == nil) if (body == nil)
error("realloc failed: %r"); error("realloc failed: %r");
memmove(body+i, buf, j); memmove(body + i, buf, j);
i += j; i += j;
body[i] = '\0'; body[i] = '\0';
} }
close(q[0]); close(q[0]);
*np = i; *np = i;
return body; return body;
} }
char* char* readbody(char* type, char* dir, int* np) {
readbody(char *type, char *dir, int *np) char* body;
{
char *body; body = readfile(dir, "body", np);
if (body != nil && strcmp(type, "text/html") == 0)
body = readfile(dir, "body", np); return formathtml(body, np);
if(body != nil && strcmp(type, "text/html") == 0) return body;
return formathtml(body, np);
return body;
} }

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -6,102 +6,85 @@
#include <9pclient.h> #include <9pclient.h>
#include "dat.h" #include "dat.h"
void* void* emalloc(uint n) {
emalloc(uint n) void* p;
{
void *p;
p = malloc(n); p = malloc(n);
if(p == nil) if (p == nil)
error("can't malloc: %r"); error("can't malloc: %r");
memset(p, 0, n); memset(p, 0, n);
setmalloctag(p, getcallerpc(&n)); setmalloctag(p, getcallerpc(&n));
return p; return p;
} }
void* void* erealloc(void* p, uint n) {
erealloc(void *p, uint n) p = realloc(p, n);
{ if (p == nil)
p = realloc(p, n); error("can't realloc: %r");
if(p == nil) setmalloctag(p, getcallerpc(&n));
error("can't realloc: %r"); return p;
setmalloctag(p, getcallerpc(&n));
return p;
} }
char* char* estrdup(char* s) {
estrdup(char *s) char* t;
{
char *t;
t = emalloc(strlen(s)+1); t = emalloc(strlen(s) + 1);
strcpy(t, s); strcpy(t, s);
return t; return t;
} }
char* char* estrstrdup(char* s, char* t) {
estrstrdup(char *s, char *t) char* u;
{
char *u;
u = emalloc(strlen(s)+strlen(t)+1); u = emalloc(strlen(s) + strlen(t) + 1);
strcpy(u, s); strcpy(u, s);
strcat(u, t); strcat(u, t);
return u; return u;
} }
char* char* eappend(char* s, char* sep, char* t) {
eappend(char *s, char *sep, char *t) char* u;
{
char *u;
if(t == nil) if (t == nil)
u = estrstrdup(s, sep); u = estrstrdup(s, sep);
else{ else {
u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1); u = emalloc(strlen(s) + strlen(sep) + strlen(t) + 1);
strcpy(u, s); strcpy(u, s);
strcat(u, sep); strcat(u, sep);
strcat(u, t); strcat(u, t);
} }
free(s); free(s);
return u; return u;
} }
char* char* egrow(char* s, char* sep, char* t) {
egrow(char *s, char *sep, char *t) s = eappend(s, sep, t);
{ free(t);
s = eappend(s, sep, t); return s;
free(t);
return s;
} }
void void error(char* fmt, ...) {
error(char *fmt, ...) Fmt f;
{ char buf[64];
Fmt f; va_list arg;
char buf[64];
va_list arg;
fmtfdinit(&f, 2, buf, sizeof buf); fmtfdinit(&f, 2, buf, sizeof buf);
fmtprint(&f, "Mail: "); fmtprint(&f, "Mail: ");
va_start(arg, fmt); va_start(arg, fmt);
fmtvprint(&f, fmt, arg); fmtvprint(&f, fmt, arg);
va_end(arg); va_end(arg);
fmtprint(&f, "\n"); fmtprint(&f, "\n");
fmtfdflush(&f); fmtfdflush(&f);
threadexitsall(fmt); threadexitsall(fmt);
} }
void void ctlprint(CFid* fd, char* fmt, ...) {
ctlprint(CFid *fd, char *fmt, ...) int n;
{ va_list arg;
int n;
va_list arg;
va_start(arg, fmt); va_start(arg, fmt);
n = fsvprint(fd, fmt, arg); n = fsvprint(fd, fmt, arg);
va_end(arg); va_end(arg);
if(n <= 0) if (n <= 0)
error("control file write error: %r"); error("control file write error: %r");
} }

Binary file not shown.

View file

@ -6,374 +6,325 @@
#include <9pclient.h> #include <9pclient.h>
#include "dat.h" #include "dat.h"
Window* Window* newwindow(void) {
newwindow(void) char buf[12];
{ Window* w;
char buf[12];
Window *w;
w = emalloc(sizeof(Window)); w = emalloc(sizeof(Window));
w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC); w->ctl = fsopen(acmefs, "new/ctl", ORDWR | OCEXEC);
if(w->ctl == nil || fsread(w->ctl, buf, 12)!=12) if (w->ctl == nil || fsread(w->ctl, buf, 12) != 12)
error("can't open window ctl file: %r"); error("can't open window ctl file: %r");
w->id = atoi(buf); w->id = atoi(buf);
w->event = winopenfile(w, "event"); w->event = winopenfile(w, "event");
w->addr = nil; /* will be opened when needed */ w->addr = nil; /* will be opened when needed */
w->body = nil; w->body = nil;
w->data = nil; w->data = nil;
w->cevent = chancreate(sizeof(Event*), 0); w->cevent = chancreate(sizeof(Event*), 0);
w->ref = 1; w->ref = 1;
return w; return w;
} }
void void winincref(Window* w) {
winincref(Window *w) qlock(&w->lk);
{ ++w->ref;
qlock(&w->lk); qunlock(&w->lk);
++w->ref;
qunlock(&w->lk);
} }
void void windecref(Window* w) {
windecref(Window *w) qlock(&w->lk);
{ if (--w->ref > 0) {
qlock(&w->lk); qunlock(&w->lk);
if(--w->ref > 0){ return;
qunlock(&w->lk); }
return; fsclose(w->event);
} chanfree(w->cevent);
fsclose(w->event); free(w);
chanfree(w->cevent);
free(w);
} }
void void winsetdump(Window* w, char* dir, char* cmd) {
winsetdump(Window *w, char *dir, char *cmd) if (dir != nil)
{ ctlprint(w->ctl, "dumpdir %s\n", dir);
if(dir != nil) if (cmd != nil)
ctlprint(w->ctl, "dumpdir %s\n", dir); ctlprint(w->ctl, "dump %s\n", cmd);
if(cmd != nil)
ctlprint(w->ctl, "dump %s\n", cmd);
} }
void void wineventproc(void* v) {
wineventproc(void *v) Window* w;
{ int i;
Window *w;
int i;
w = v; w = v;
for(i=0; ; i++){ for (i = 0;; i++) {
if(i >= NEVENT) if (i >= NEVENT)
i = 0; i = 0;
wingetevent(w, &w->e[i]); wingetevent(w, &w->e[i]);
sendp(w->cevent, &w->e[i]); sendp(w->cevent, &w->e[i]);
} }
} }
static CFid* static CFid* winopenfile1(Window* w, char* f, int m) {
winopenfile1(Window *w, char *f, int m) char buf[64];
{ CFid* fd;
char buf[64];
CFid* fd;
sprint(buf, "%d/%s", w->id, f); sprint(buf, "%d/%s", w->id, f);
fd = fsopen(acmefs, buf, m|OCEXEC); fd = fsopen(acmefs, buf, m | OCEXEC);
if(fd == nil) if (fd == nil)
error("can't open window file %s: %r", f); error("can't open window file %s: %r", f);
return fd; return fd;
} }
CFid* CFid* winopenfile(Window* w, char* f) { return winopenfile1(w, f, ORDWR); }
winopenfile(Window *w, char *f)
{ void wintagwrite(Window* w, char* s, int n) {
return winopenfile1(w, f, ORDWR); CFid* fid;
fid = winopenfile(w, "tag");
if (fswrite(fid, s, n) != n)
error("tag write: %r");
fsclose(fid);
} }
void void winname(Window* w, char* s) {
wintagwrite(Window *w, char *s, int n) int len;
{ char *ns, *sp;
CFid* fid; Rune r = L''; /* visible space */
fid = winopenfile(w, "tag"); len = 0;
if(fswrite(fid, s, n) != n) ns = emalloc(strlen(s) * runelen(r) + 1);
error("tag write: %r"); for (sp = s; *sp != '\0'; sp++, len++) {
fsclose(fid); if (isspace(*sp)) {
len += runetochar(ns + len, &r) - 1;
continue;
}
*(ns + len) = *sp;
}
ctlprint(w->ctl, "name %s\n", ns);
free(ns);
return;
} }
void void winopenbody(Window* w, int mode) {
winname(Window *w, char *s) char buf[256];
{ CFid* fid;
int len;
char *ns, *sp;
Rune r = L''; /* visible space */
len = 0; sprint(buf, "%d/body", w->id);
ns = emalloc(strlen(s)*runelen(r) + 1); fid = fsopen(acmefs, buf, mode | OCEXEC);
for(sp = s; *sp != '\0'; sp++, len++){ w->body = fid;
if(isspace(*sp)){ if (w->body == nil)
len += runetochar(ns+len, &r)-1; error("can't open window body file: %r");
continue;
}
*(ns+len) = *sp;
}
ctlprint(w->ctl, "name %s\n", ns);
free(ns);
return;
} }
void void winclosebody(Window* w) {
winopenbody(Window *w, int mode) if (w->body != nil) {
{ fsclose(w->body);
char buf[256]; w->body = nil;
CFid* fid; }
sprint(buf, "%d/body", w->id);
fid = fsopen(acmefs, buf, mode|OCEXEC);
w->body = fid;
if(w->body == nil)
error("can't open window body file: %r");
} }
void void winwritebody(Window* w, char* s, int n) {
winclosebody(Window *w) if (w->body == nil)
{ winopenbody(w, OWRITE);
if(w->body != nil){ if (fswrite(w->body, s, n) != n)
fsclose(w->body); error("write error to window: %r");
w->body = nil;
}
} }
void int wingetec(Window* w) {
winwritebody(Window *w, char *s, int n) if (w->nbuf == 0) {
{ w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
if(w->body == nil) if (w->nbuf <= 0) {
winopenbody(w, OWRITE); /* probably because window has exited, and only called by wineventproc, so
if(fswrite(w->body, s, n) != n) * just shut down */
error("write error to window: %r"); windecref(w);
threadexits(nil);
}
w->bufp = w->buf;
}
w->nbuf--;
return *w->bufp++;
} }
int int wingeten(Window* w) {
wingetec(Window *w) int n, c;
{
if(w->nbuf == 0){ n = 0;
w->nbuf = fsread(w->event, w->buf, sizeof w->buf); while ('0' <= (c = wingetec(w)) && c <= '9')
if(w->nbuf <= 0){ n = n * 10 + (c - '0');
/* probably because window has exited, and only called by wineventproc, so just shut down */ if (c != ' ')
windecref(w); error("event number syntax");
threadexits(nil); return n;
}
w->bufp = w->buf;
}
w->nbuf--;
return *w->bufp++;
} }
int int wingeter(Window* w, char* buf, int* nb) {
wingeten(Window *w) Rune r;
{ int n;
int n, c;
n = 0; r = wingetec(w);
while('0'<=(c=wingetec(w)) && c<='9') buf[0] = r;
n = n*10+(c-'0'); n = 1;
if(c != ' ') if (r >= Runeself) {
error("event number syntax"); while (!fullrune(buf, n))
return n; buf[n++] = wingetec(w);
chartorune(&r, buf);
}
*nb = n;
return r;
} }
int void wingetevent(Window* w, Event* e) {
wingeter(Window *w, char *buf, int *nb) int i, nb;
{
Rune r;
int n;
r = wingetec(w); e->c1 = wingetec(w);
buf[0] = r; e->c2 = wingetec(w);
n = 1; e->q0 = wingeten(w);
if(r >= Runeself) { e->q1 = wingeten(w);
while(!fullrune(buf, n)) e->flag = wingeten(w);
buf[n++] = wingetec(w); e->nr = wingeten(w);
chartorune(&r, buf); if (e->nr > EVENTSIZE)
} error("event string too long");
*nb = n; e->nb = 0;
return r; for (i = 0; i < e->nr; i++) {
e->r[i] = wingeter(w, e->b + e->nb, &nb);
e->nb += nb;
}
e->r[e->nr] = 0;
e->b[e->nb] = 0;
if (wingetec(w) != '\n')
error("event syntax error");
} }
void void winwriteevent(Window* w, Event* e) {
wingetevent(Window *w, Event *e) fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
{
int i, nb;
e->c1 = wingetec(w);
e->c2 = wingetec(w);
e->q0 = wingeten(w);
e->q1 = wingeten(w);
e->flag = wingeten(w);
e->nr = wingeten(w);
if(e->nr > EVENTSIZE)
error("event string too long");
e->nb = 0;
for(i=0; i<e->nr; i++){
e->r[i] = wingeter(w, e->b+e->nb, &nb);
e->nb += nb;
}
e->r[e->nr] = 0;
e->b[e->nb] = 0;
if(wingetec(w) != '\n')
error("event syntax error");
} }
void void winread(Window* w, uint q0, uint q1, char* data) {
winwriteevent(Window *w, Event *e) int m, n, nr;
{ char buf[256];
fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
if (w->addr == nil)
w->addr = winopenfile(w, "addr");
if (w->data == nil)
w->data = winopenfile(w, "data");
m = q0;
while (m < q1) {
n = sprint(buf, "#%d", m);
if (fswrite(w->addr, buf, n) != n)
error("error writing addr: %r");
n = fsread(w->data, buf, sizeof buf);
if (n <= 0)
error("reading data: %r");
nr = utfnlen(buf, n);
while (m + nr > q1) {
do
;
while (n > 0 && (buf[--n] & 0xC0) == 0x80);
--nr;
}
if (n == 0)
break;
memmove(data, buf, n);
data += n;
*data = 0;
m += nr;
}
} }
void void windormant(Window* w) {
winread(Window *w, uint q0, uint q1, char *data) if (w->addr != nil) {
{ fsclose(w->addr);
int m, n, nr; w->addr = nil;
char buf[256]; }
if (w->body != nil) {
if(w->addr == nil) fsclose(w->body);
w->addr = winopenfile(w, "addr"); w->body = nil;
if(w->data == nil) }
w->data = winopenfile(w, "data"); if (w->data != nil) {
m = q0; fsclose(w->data);
while(m < q1){ w->data = nil;
n = sprint(buf, "#%d", m); }
if(fswrite(w->addr, buf, n) != n)
error("error writing addr: %r");
n = fsread(w->data, buf, sizeof buf);
if(n <= 0)
error("reading data: %r");
nr = utfnlen(buf, n);
while(m+nr >q1){
do; while(n>0 && (buf[--n]&0xC0)==0x80);
--nr;
}
if(n == 0)
break;
memmove(data, buf, n);
data += n;
*data = 0;
m += nr;
}
} }
void int windel(Window* w, int sure) {
windormant(Window *w) if (sure)
{ fswrite(w->ctl, "delete\n", 7);
if(w->addr != nil){ else if (fswrite(w->ctl, "del\n", 4) != 4)
fsclose(w->addr); return 0;
w->addr = nil; /* event proc will die due to read error from event file */
} windormant(w);
if(w->body != nil){ fsclose(w->ctl);
fsclose(w->body); w->ctl = nil;
w->body = nil; return 1;
}
if(w->data != nil){
fsclose(w->data);
w->data = nil;
}
} }
void winclean(Window* w) { ctlprint(w->ctl, "clean\n"); }
int int winsetaddr(Window* w, char* addr, int errok) {
windel(Window *w, int sure) if (w->addr == nil)
{ w->addr = winopenfile(w, "addr");
if(sure) if (fswrite(w->addr, addr, strlen(addr)) < 0) {
fswrite(w->ctl, "delete\n", 7); if (!errok)
else if(fswrite(w->ctl, "del\n", 4) != 4) error("error writing addr(%s): %r", addr);
return 0; return 0;
/* event proc will die due to read error from event file */ }
windormant(w); return 1;
fsclose(w->ctl);
w->ctl = nil;
return 1;
} }
void int winselect(Window* w, char* addr, int errok) {
winclean(Window *w) if (winsetaddr(w, addr, errok)) {
{ ctlprint(w->ctl, "dot=addr\n");
ctlprint(w->ctl, "clean\n"); return 1;
}
return 0;
} }
int char* winreadbody(
winsetaddr(Window *w, char *addr, int errok) Window* w,
int* np) /* can't use readfile because acme doesn't report the length */
{ {
if(w->addr == nil) char* s;
w->addr = winopenfile(w, "addr"); int m, na, n;
if(fswrite(w->addr, addr, strlen(addr)) < 0){
if(!errok) if (w->body != nil)
error("error writing addr(%s): %r", addr); winclosebody(w);
return 0; winopenbody(w, OREAD);
} s = nil;
return 1; na = 0;
n = 0;
for (;;) {
if (na < n + 512) {
na += 1024;
s = realloc(s, na + 1);
}
m = fsread(w->body, s + n, na - n);
if (m <= 0)
break;
n += m;
}
s[n] = 0;
winclosebody(w);
*np = n;
return s;
} }
int char* winselection(Window* w) {
winselect(Window *w, char *addr, int errok) int m, n;
{ char* buf;
if(winsetaddr(w, addr, errok)){ char tmp[256];
ctlprint(w->ctl, "dot=addr\n"); CFid* fid;
return 1;
} fid = winopenfile1(w, "rdsel", OREAD);
return 0; if (fid == nil)
} error("can't open rdsel: %r");
n = 0;
char* buf = nil;
winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */ for (;;) {
{ m = fsread(fid, tmp, sizeof tmp);
char *s; if (m <= 0)
int m, na, n; break;
buf = erealloc(buf, n + m + 1);
if(w->body != nil) memmove(buf + n, tmp, m);
winclosebody(w); n += m;
winopenbody(w, OREAD); buf[n] = '\0';
s = nil; }
na = 0; fsclose(fid);
n = 0; return buf;
for(;;){
if(na < n+512){
na += 1024;
s = realloc(s, na+1);
}
m = fsread(w->body, s+n, na-n);
if(m <= 0)
break;
n += m;
}
s[n] = 0;
winclosebody(w);
*np = n;
return s;
}
char*
winselection(Window *w)
{
int m, n;
char *buf;
char tmp[256];
CFid* fid;
fid = winopenfile1(w, "rdsel", OREAD);
if(fid == nil)
error("can't open rdsel: %r");
n = 0;
buf = nil;
for(;;){
m = fsread(fid, tmp, sizeof tmp);
if(m <= 0)
break;
buf = erealloc(buf, n+m+1);
memmove(buf+n, tmp, m);
n += m;
buf[n] = '\0';
}
fsclose(fid);
return buf;
} }

Binary file not shown.

1411
regx.c

File diff suppressed because it is too large Load diff

1534
rows.c

File diff suppressed because it is too large Load diff

256
scrl.c
View file

@ -12,148 +12,142 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
static Image *scrtmp; static Image* scrtmp;
static static Rectangle scrpos(Rectangle r, uint p0, uint p1, uint tot) {
Rectangle Rectangle q;
scrpos(Rectangle r, uint p0, uint p1, uint tot) int h;
{
Rectangle q;
int h;
q = r; q = r;
h = q.max.y-q.min.y; h = q.max.y - q.min.y;
if(tot == 0) if (tot == 0)
return q; return q;
if(tot > 1024*1024){ if (tot > 1024 * 1024) {
tot>>=10; tot >>= 10;
p0>>=10; p0 >>= 10;
p1>>=10; p1 >>= 10;
} }
if(p0 > 0) if (p0 > 0)
q.min.y += h*p0/tot; q.min.y += h * p0 / tot;
if(p1 < tot) if (p1 < tot)
q.max.y -= h*(tot-p1)/tot; q.max.y -= h * (tot - p1) / tot;
if(q.max.y < q.min.y+2){ if (q.max.y < q.min.y + 2) {
if(q.min.y+2 <= r.max.y) if (q.min.y + 2 <= r.max.y)
q.max.y = q.min.y+2; q.max.y = q.min.y + 2;
else else
q.min.y = q.max.y-2; q.min.y = q.max.y - 2;
} }
return q; return q;
} }
void void scrlresize(void) {
scrlresize(void) freeimage(scrtmp);
{ scrtmp = allocimage(
freeimage(scrtmp); display,
scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill); Rect(0, 0, 32, screen->r.max.y),
if(scrtmp == nil) screen->chan,
error("scroll alloc"); 0,
DNofill);
if (scrtmp == nil)
error("scroll alloc");
} }
void void textscrdraw(Text* t) {
textscrdraw(Text *t) Rectangle r, r1, r2;
{ Image* b;
Rectangle r, r1, r2;
Image *b;
if(t->w==nil || t!=&t->w->body) if (t->w == nil || t != &t->w->body)
return; return;
if(scrtmp == nil) if (scrtmp == nil)
scrlresize(); scrlresize();
r = t->scrollr; r = t->scrollr;
b = scrtmp; b = scrtmp;
r1 = r; r1 = r;
r1.min.x = 0; r1.min.x = 0;
r1.max.x = Dx(r); r1.max.x = Dx(r);
r2 = scrpos(r1, t->org, t->org+t->fr.nchars, t->file->b.nc); r2 = scrpos(r1, t->org, t->org + t->fr.nchars, t->file->b.nc);
if(!eqrect(r2, t->lastsr)){ if (!eqrect(r2, t->lastsr)) {
t->lastsr = r2; t->lastsr = r2;
draw(b, r1, t->fr.cols[BORD], nil, ZP); draw(b, r1, t->fr.cols[BORD], nil, ZP);
draw(b, r2, t->fr.cols[BACK], nil, ZP); draw(b, r2, t->fr.cols[BACK], nil, ZP);
r2.min.x = r2.max.x-1; r2.min.x = r2.max.x - 1;
draw(b, r2, t->fr.cols[BORD], nil, ZP); draw(b, r2, t->fr.cols[BORD], nil, ZP);
draw(t->fr.b, r, b, nil, Pt(0, r1.min.y)); draw(t->fr.b, r, b, nil, Pt(0, r1.min.y));
/*flushimage(display, 1); // BUG? */ /*flushimage(display, 1); // BUG? */
} }
} }
void void scrsleep(uint dt) {
scrsleep(uint dt) Timer* timer;
{ static Alt alts[3];
Timer *timer;
static Alt alts[3];
timer = timerstart(dt); timer = timerstart(dt);
alts[0].c = timer->c; alts[0].c = timer->c;
alts[0].v = nil; alts[0].v = nil;
alts[0].op = CHANRCV; alts[0].op = CHANRCV;
alts[1].c = mousectl->c; alts[1].c = mousectl->c;
alts[1].v = &mousectl->m; alts[1].v = &mousectl->m;
alts[1].op = CHANRCV; alts[1].op = CHANRCV;
alts[2].op = CHANEND; alts[2].op = CHANEND;
for(;;) for (;;)
switch(alt(alts)){ switch (alt(alts)) {
case 0: case 0:
timerstop(timer); timerstop(timer);
return; return;
case 1: case 1:
timercancel(timer); timercancel(timer);
return; return;
} }
} }
void void textscroll(Text* t, int but) {
textscroll(Text *t, int but) uint p0, oldp0;
{ Rectangle s;
uint p0, oldp0; int x, y, my, h, first;
Rectangle s;
int x, y, my, h, first;
s = insetrect(t->scrollr, 1); s = insetrect(t->scrollr, 1);
h = s.max.y-s.min.y; h = s.max.y - s.min.y;
x = (s.min.x+s.max.x)/2; x = (s.min.x + s.max.x) / 2;
oldp0 = ~0; oldp0 = ~0;
first = TRUE; first = TRUE;
do{ do {
flushimage(display, 1); flushimage(display, 1);
my = mouse->xy.y; my = mouse->xy.y;
if(my < s.min.y) if (my < s.min.y)
my = s.min.y; my = s.min.y;
if(my >= s.max.y) if (my >= s.max.y)
my = s.max.y; my = s.max.y;
if(!eqpt(mouse->xy, Pt(x, my))){ if (!eqpt(mouse->xy, Pt(x, my))) {
moveto(mousectl, Pt(x, my)); moveto(mousectl, Pt(x, my));
readmouse(mousectl); /* absorb event generated by moveto() */ readmouse(mousectl); /* absorb event generated by moveto() */
} }
if(but == 2){ if (but == 2) {
y = my; y = my;
p0 = (vlong)t->file->b.nc*(y-s.min.y)/h; p0 = (vlong)t->file->b.nc * (y - s.min.y) / h;
if(p0 >= t->q1) if (p0 >= t->q1)
p0 = textbacknl(t, p0, 2); p0 = textbacknl(t, p0, 2);
if(oldp0 != p0) if (oldp0 != p0)
textsetorigin(t, p0, FALSE); textsetorigin(t, p0, FALSE);
oldp0 = p0; oldp0 = p0;
readmouse(mousectl); readmouse(mousectl);
continue; continue;
} }
if(but == 1) if (but == 1)
p0 = textbacknl(t, t->org, (my-s.min.y)/t->fr.font->height); p0 = textbacknl(t, t->org, (my - s.min.y) / t->fr.font->height);
else else
p0 = t->org+frcharofpt(&t->fr, Pt(s.max.x, my)); p0 = t->org + frcharofpt(&t->fr, Pt(s.max.x, my));
if(oldp0 != p0) if (oldp0 != p0)
textsetorigin(t, p0, TRUE); textsetorigin(t, p0, TRUE);
oldp0 = p0; oldp0 = p0;
/* debounce */ /* debounce */
if(first){ if (first) {
flushimage(display, 1); flushimage(display, 1);
sleep(200); sleep(200);
nbrecv(mousectl->c, &mousectl->m); nbrecv(mousectl->c, &mousectl->m);
first = FALSE; first = FALSE;
} }
scrsleep(80); scrsleep(80);
}while(mouse->buttons & (1<<(but-1))); } while (mouse->buttons & (1 << (but - 1)));
while(mouse->buttons) while (mouse->buttons)
readmouse(mousectl); readmouse(mousectl);
} }

3174
text.c

File diff suppressed because it is too large Load diff

185
time.c
View file

@ -12,113 +12,96 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
static Channel* ctimer; /* chan(Timer*)[100] */ static Channel* ctimer; /* chan(Timer*)[100] */
static Timer *timer; static Timer* timer;
static static uint msec(void) { return nsec() / 1000000; }
uint
msec(void) void timerstop(Timer* t) {
{ t->next = timer;
return nsec()/1000000; timer = t;
} }
void void timercancel(Timer* t) { t->cancel = TRUE; }
timerstop(Timer *t)
{ static void timerproc(void* v) {
t->next = timer; int i, nt, na, dt, del;
timer = t; Timer **t, *x;
uint old, new;
USED(v);
threadsetname("timerproc");
rfork(RFFDG);
t = nil;
na = 0;
nt = 0;
old = msec();
for (;;) {
sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not
be noticeable */
new = msec();
dt = new - old;
old = new;
if (dt < 0) /* timer wrapped; go around, losing a tick */
continue;
for (i = 0; i < nt; i++) {
x = t[i];
x->dt -= dt;
del = FALSE;
if (x->cancel) {
timerstop(x);
del = TRUE;
} else if (x->dt <= 0) {
/*
* avoid possible deadlock if client is
* now sending on ctimer
*/
if (nbsendul(x->c, 0) > 0)
del = TRUE;
}
if (del) {
memmove(&t[i], &t[i + 1], (nt - i - 1) * sizeof t[0]);
--nt;
--i;
}
}
if (nt == 0) {
x = recvp(ctimer);
gotit:
if (nt == na) {
na += 10;
t = realloc(t, na * sizeof(Timer*));
if (t == nil)
error("timer realloc failed");
}
t[nt++] = x;
old = msec();
}
if (nbrecv(ctimer, &x) > 0)
goto gotit;
}
} }
void void timerinit(void) {
timercancel(Timer *t) ctimer = chancreate(sizeof(Timer*), 100);
{ chansetname(ctimer, "ctimer");
t->cancel = TRUE; proccreate(timerproc, nil, STACK);
} }
static Timer* timerstart(int dt) {
void Timer* t;
timerproc(void *v)
{
int i, nt, na, dt, del;
Timer **t, *x;
uint old, new;
USED(v); t = timer;
threadsetname("timerproc"); if (t)
rfork(RFFDG); timer = timer->next;
t = nil; else {
na = 0; t = emalloc(sizeof(Timer));
nt = 0; t->c = chancreate(sizeof(int), 0);
old = msec(); chansetname(t->c, "tc%p", t->c);
for(;;){ }
sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not be noticeable */ t->next = nil;
new = msec(); t->dt = dt;
dt = new-old; t->cancel = FALSE;
old = new; sendp(ctimer, t);
if(dt < 0) /* timer wrapped; go around, losing a tick */ return t;
continue;
for(i=0; i<nt; i++){
x = t[i];
x->dt -= dt;
del = FALSE;
if(x->cancel){
timerstop(x);
del = TRUE;
}else if(x->dt <= 0){
/*
* avoid possible deadlock if client is
* now sending on ctimer
*/
if(nbsendul(x->c, 0) > 0)
del = TRUE;
}
if(del){
memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
--nt;
--i;
}
}
if(nt == 0){
x = recvp(ctimer);
gotit:
if(nt == na){
na += 10;
t = realloc(t, na*sizeof(Timer*));
if(t == nil)
error("timer realloc failed");
}
t[nt++] = x;
old = msec();
}
if(nbrecv(ctimer, &x) > 0)
goto gotit;
}
}
void
timerinit(void)
{
ctimer = chancreate(sizeof(Timer*), 100);
chansetname(ctimer, "ctimer");
proccreate(timerproc, nil, STACK);
}
Timer*
timerstart(int dt)
{
Timer *t;
t = timer;
if(t)
timer = timer->next;
else{
t = emalloc(sizeof(Timer));
t->c = chancreate(sizeof(int), 0);
chansetname(t->c, "tc%p", t->c);
}
t->next = nil;
t->dt = dt;
t->cancel = FALSE;
sendp(ctimer, t);
return t;
} }

749
util.c
View file

@ -12,124 +12,112 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
static Point prevmouse; static Point prevmouse;
static Window *mousew; static Window* mousew;
Range Range range(int q0, int q1) {
range(int q0, int q1) Range r;
{
Range r;
r.q0 = q0; r.q0 = q0;
r.q1 = q1; r.q1 = q1;
return r; return r;
} }
Runestr Runestr runestr(Rune* r, uint n) {
runestr(Rune *r, uint n) Runestr rs;
{
Runestr rs;
rs.r = r; rs.r = r;
rs.nr = n; rs.nr = n;
return rs; return rs;
} }
void void cvttorunes(char* p, int n, Rune* r, int* nb, int* nr, int* nulls) {
cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls) uchar* q;
{ Rune* s;
uchar *q; int j, w;
Rune *s;
int j, w;
/* /*
* Always guaranteed that n bytes may be interpreted * Always guaranteed that n bytes may be interpreted
* without worrying about partial runes. This may mean * without worrying about partial runes. This may mean
* reading up to UTFmax-1 more bytes than n; the caller * reading up to UTFmax-1 more bytes than n; the caller
* knows this. If n is a firm limit, the caller should * knows this. If n is a firm limit, the caller should
* set p[n] = 0. * set p[n] = 0.
*/ */
q = (uchar*)p; q = (uchar*)p;
s = r; s = r;
for(j=0; j<n; j+=w){ for (j = 0; j < n; j += w) {
if(*q < Runeself){ if (*q < Runeself) {
w = 1; w = 1;
*s = *q++; *s = *q++;
}else{ } else {
w = chartorune(s, (char*)q); w = chartorune(s, (char*)q);
q += w; q += w;
} }
if(*s) if (*s)
s++; s++;
else if(nulls) else if (nulls)
*nulls = TRUE; *nulls = TRUE;
} }
*nb = (char*)q-p; *nb = (char*)q - p;
*nr = s-r; *nr = s - r;
} }
void void error(char* s) {
error(char *s) fprint(2, "acme: %s: %r\n", s);
{ threadexitsall(nil);
fprint(2, "acme: %s: %r\n", s);
threadexitsall(nil);
} }
Window* Window* errorwin1(Rune* dir, int ndir, Rune** incl, int nincl) {
errorwin1(Rune *dir, int ndir, Rune **incl, int nincl) Window* w;
{ Rune* r;
Window *w; int i, n;
Rune *r; static Rune Lpluserrors[] = {'+', 'E', 'r', 'r', 'o', 'r', 's', 0};
int i, n;
static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
r = runemalloc(ndir+8); r = runemalloc(ndir + 8);
if((n = ndir) != 0){ if ((n = ndir) != 0) {
runemove(r, dir, ndir); runemove(r, dir, ndir);
r[n++] = L'/'; r[n++] = L'/';
} }
runemove(r+n, Lpluserrors, 7); runemove(r + n, Lpluserrors, 7);
n += 7; n += 7;
w = lookfile(r, n); w = lookfile(r, n);
if(w == nil){ if (w == nil) {
if(row.ncol == 0) if (row.ncol == 0)
if(rowadd(&row, nil, -1) == nil) if (rowadd(&row, nil, -1) == nil)
error("can't create column to make error window"); error("can't create column to make error window");
w = coladd(row.col[row.ncol-1], nil, nil, -1); w = coladd(row.col[row.ncol - 1], nil, nil, -1);
w->filemenu = FALSE; w->filemenu = FALSE;
winsetname(w, r, n); winsetname(w, r, n);
xfidlog(w, "new"); xfidlog(w, "new");
} }
free(r); free(r);
for(i=nincl; --i>=0; ){ for (i = nincl; --i >= 0;) {
n = runestrlen(incl[i]); n = runestrlen(incl[i]);
r = runemalloc(n); r = runemalloc(n);
runemove(r, incl[i], n); runemove(r, incl[i], n);
winaddincl(w, r, n); winaddincl(w, r, n);
} }
for(i=0; i<NINDENT; i++) for (i = 0; i < NINDENT; i++)
w->indent[i] = globalindent[i]; w->indent[i] = globalindent[i];
return w; return w;
} }
/* make new window, if necessary; return with it locked */ /* make new window, if necessary; return with it locked */
Window* Window* errorwin(Mntdir* md, int owner) {
errorwin(Mntdir *md, int owner) Window* w;
{
Window *w;
for(;;){ for (;;) {
if(md == nil) if (md == nil)
w = errorwin1(nil, 0, nil, 0); w = errorwin1(nil, 0, nil, 0);
else else
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl); w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
winlock(w, owner); winlock(w, owner);
if(w->col != nil) if (w->col != nil)
break; break;
/* window was deleted too fast */ /* window was deleted too fast */
winunlock(w); winunlock(w);
} }
return w; return w;
} }
/* /*
@ -137,360 +125,315 @@ errorwin(Mntdir *md, int owner)
* It will be unlocked and returned window * It will be unlocked and returned window
* will be locked in its place. * will be locked in its place.
*/ */
Window* Window* errorwinforwin(Window* w) {
errorwinforwin(Window *w) int i, n, nincl, owner;
{ Rune** incl;
int i, n, nincl, owner; Runestr dir;
Rune **incl; Text* t;
Runestr dir;
Text *t;
t = &w->body; t = &w->body;
dir = dirname(t, nil, 0); dir = dirname(t, nil, 0);
if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */
free(dir.r); free(dir.r);
dir.r = nil; dir.r = nil;
dir.nr = 0; dir.nr = 0;
} }
incl = nil; incl = nil;
nincl = w->nincl; nincl = w->nincl;
if(nincl > 0){ if (nincl > 0) {
incl = emalloc(nincl*sizeof(Rune*)); incl = emalloc(nincl * sizeof(Rune*));
for(i=0; i<nincl; i++){ for (i = 0; i < nincl; i++) {
n = runestrlen(w->incl[i]); n = runestrlen(w->incl[i]);
incl[i] = runemalloc(n+1); incl[i] = runemalloc(n + 1);
runemove(incl[i], w->incl[i], n); runemove(incl[i], w->incl[i], n);
} }
} }
owner = w->owner; owner = w->owner;
winunlock(w); winunlock(w);
for(;;){ for (;;) {
w = errorwin1(dir.r, dir.nr, incl, nincl); w = errorwin1(dir.r, dir.nr, incl, nincl);
winlock(w, owner); winlock(w, owner);
if(w->col != nil) if (w->col != nil)
break; break;
/* window deleted too fast */ /* window deleted too fast */
winunlock(w); winunlock(w);
} }
return w; return w;
} }
typedef struct Warning Warning; typedef struct Warning Warning;
struct Warning{ struct Warning {
Mntdir *md; Mntdir* md;
Buffer buf; Buffer buf;
Warning *next; Warning* next;
}; };
static Warning *warnings; static Warning* warnings;
static static void addwarningtext(Mntdir* md, Rune* r, int nr) {
void Warning* warn;
addwarningtext(Mntdir *md, Rune *r, int nr)
{
Warning *warn;
for(warn = warnings; warn; warn=warn->next){ for (warn = warnings; warn; warn = warn->next) {
if(warn->md == md){ if (warn->md == md) {
bufinsert(&warn->buf, warn->buf.nc, r, nr); bufinsert(&warn->buf, warn->buf.nc, r, nr);
return; return;
} }
} }
warn = emalloc(sizeof(Warning)); warn = emalloc(sizeof(Warning));
warn->next = warnings; warn->next = warnings;
warn->md = md; warn->md = md;
if(md) if (md)
fsysincid(md); fsysincid(md);
warnings = warn; warnings = warn;
bufinsert(&warn->buf, 0, r, nr); bufinsert(&warn->buf, 0, r, nr);
nbsendp(cwarn, 0); nbsendp(cwarn, 0);
} }
/* called while row is locked */ /* called while row is locked */
void void flushwarnings(void) {
flushwarnings(void) Warning *warn, *next;
{ Window* w;
Warning *warn, *next; Text* t;
Window *w; int owner, nr, q0, n;
Text *t; Rune* r;
int owner, nr, q0, n;
Rune *r;
for(warn=warnings; warn; warn=next) { for (warn = warnings; warn; warn = next) {
w = errorwin(warn->md, 'E'); w = errorwin(warn->md, 'E');
t = &w->body; t = &w->body;
owner = w->owner; owner = w->owner;
if(owner == 0) if (owner == 0)
w->owner = 'E'; w->owner = 'E';
wincommit(w, t); wincommit(w, t);
/* /*
* Most commands don't generate much output. For instance, * Most commands don't generate much output. For instance,
* Edit ,>cat goes through /dev/cons and is already in blocks * Edit ,>cat goes through /dev/cons and is already in blocks
* because of the i/o system, but a few can. Edit ,p will * because of the i/o system, but a few can. Edit ,p will
* put the entire result into a single hunk. So it's worth doing * put the entire result into a single hunk. So it's worth doing
* this in blocks (and putting the text in a buffer in the first * this in blocks (and putting the text in a buffer in the first
* place), to avoid a big memory footprint. * place), to avoid a big memory footprint.
*/ */
r = fbufalloc(); r = fbufalloc();
q0 = t->file->b.nc; q0 = t->file->b.nc;
for(n = 0; n < warn->buf.nc; n += nr){ for (n = 0; n < warn->buf.nc; n += nr) {
nr = warn->buf.nc - n; nr = warn->buf.nc - n;
if(nr > RBUFSIZE) if (nr > RBUFSIZE)
nr = RBUFSIZE; nr = RBUFSIZE;
bufread(&warn->buf, n, r, nr); bufread(&warn->buf, n, r, nr);
textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr); textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
} }
textshow(t, q0, t->file->b.nc, 1); textshow(t, q0, t->file->b.nc, 1);
free(r); free(r);
winsettag(t->w); winsettag(t->w);
textscrdraw(t); textscrdraw(t);
w->owner = owner; w->owner = owner;
w->dirty = FALSE; w->dirty = FALSE;
winunlock(w); winunlock(w);
bufclose(&warn->buf); bufclose(&warn->buf);
next = warn->next; next = warn->next;
if(warn->md) if (warn->md)
fsysdelid(warn->md); fsysdelid(warn->md);
free(warn); free(warn);
} }
warnings = nil; warnings = nil;
} }
void void warning(Mntdir* md, char* s, ...) {
warning(Mntdir *md, char *s, ...) Rune* r;
{ va_list arg;
Rune *r;
va_list arg;
va_start(arg, s); va_start(arg, s);
r = runevsmprint(s, arg); r = runevsmprint(s, arg);
va_end(arg); va_end(arg);
if(r == nil) if (r == nil)
error("runevsmprint failed"); error("runevsmprint failed");
addwarningtext(md, r, runestrlen(r)); addwarningtext(md, r, runestrlen(r));
free(r); free(r);
} }
int int runeeq(Rune* s1, uint n1, Rune* s2, uint n2) {
runeeq(Rune *s1, uint n1, Rune *s2, uint n2) if (n1 != n2)
{ return FALSE;
if(n1 != n2) return memcmp(s1, s2, n1 * sizeof(Rune)) == 0;
return FALSE;
return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
} }
uint uint min(uint a, uint b) {
min(uint a, uint b) if (a < b)
{ return a;
if(a < b) return b;
return a;
return b;
} }
uint uint max(uint a, uint b) {
max(uint a, uint b) if (a > b)
{ return a;
if(a > b) return b;
return a;
return b;
} }
char* char* runetobyte(Rune* r, int n) {
runetobyte(Rune *r, int n) char* s;
{
char *s;
if(r == nil) if (r == nil)
return nil; return nil;
s = emalloc(n*UTFmax+1); s = emalloc(n * UTFmax + 1);
setmalloctag(s, getcallerpc(&r)); setmalloctag(s, getcallerpc(&r));
snprint(s, n*UTFmax+1, "%.*S", n, r); snprint(s, n * UTFmax + 1, "%.*S", n, r);
return s; return s;
} }
Rune* Rune* bytetorune(char* s, int* ip) {
bytetorune(char *s, int *ip) Rune* r;
{ int nb, nr;
Rune *r;
int nb, nr;
nb = strlen(s); nb = strlen(s);
r = runemalloc(nb+1); r = runemalloc(nb + 1);
cvttorunes(s, nb, r, &nb, &nr, nil); cvttorunes(s, nb, r, &nb, &nr, nil);
r[nr] = '\0'; r[nr] = '\0';
*ip = nr; *ip = nr;
return r; return r;
} }
int int isalnum(Rune c) {
isalnum(Rune c) /*
{ * Hard to get absolutely right. Use what we know about ASCII
/* * and assume anything above the Latin control characters is
* Hard to get absolutely right. Use what we know about ASCII * potentially an alphanumeric.
* and assume anything above the Latin control characters is */
* potentially an alphanumeric. if (c <= ' ')
*/ return FALSE;
if(c <= ' ') if (0x7F <= c && c <= 0xA0)
return FALSE; return FALSE;
if(0x7F<=c && c<=0xA0) if (utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
return FALSE; return FALSE;
if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) return TRUE;
return FALSE;
return TRUE;
} }
int int rgetc(void* v, uint n) { return ((Rune*)v)[n]; }
rgetc(void *v, uint n)
{ int tgetc(void* a, uint n) {
return ((Rune*)v)[n]; Text* t;
t = a;
if (n >= t->file->b.nc)
return 0;
return textreadc(t, n);
} }
int Rune* skipbl(Rune* r, int n, int* np) {
tgetc(void *a, uint n) while (n > 0 && (*r == ' ' || *r == '\t' || *r == '\n')) {
{ --n;
Text *t; r++;
}
t = a; *np = n;
if(n >= t->file->b.nc) return r;
return 0;
return textreadc(t, n);
} }
Rune* Rune* findbl(Rune* r, int n, int* np) {
skipbl(Rune *r, int n, int *np) while (n > 0 && *r != ' ' && *r != '\t' && *r != '\n') {
{ --n;
while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){ r++;
--n; }
r++; *np = n;
} return r;
*np = n;
return r;
} }
Rune* void savemouse(Window* w) {
findbl(Rune *r, int n, int *np) prevmouse = mouse->xy;
{ mousew = w;
while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
--n;
r++;
}
*np = n;
return r;
} }
void int restoremouse(Window* w) {
savemouse(Window *w) int did;
{
prevmouse = mouse->xy; did = 0;
mousew = w; if (mousew != nil && mousew == w) {
moveto(mousectl, prevmouse);
did = 1;
}
mousew = nil;
return did;
} }
int void clearmouse() { mousew = nil; }
restoremouse(Window *w)
{
int did;
did = 0; char* estrdup(char* s) {
if(mousew!=nil && mousew==w) { char* t;
moveto(mousectl, prevmouse);
did = 1; t = strdup(s);
} if (t == nil)
mousew = nil; error("strdup failed");
return did; setmalloctag(t, getcallerpc(&s));
return t;
} }
void void* emalloc(uint n) {
clearmouse() void* p;
{
mousew = nil; p = malloc(n);
if (p == nil)
error("malloc failed");
setmalloctag(p, getcallerpc(&n));
memset(p, 0, n);
return p;
} }
char* void* erealloc(void* p, uint n) {
estrdup(char *s) p = realloc(p, n);
{ if (p == nil)
char *t; error("realloc failed");
setmalloctag(p, getcallerpc(&n));
t = strdup(s); return p;
if(t == nil)
error("strdup failed");
setmalloctag(t, getcallerpc(&s));
return t;
}
void*
emalloc(uint n)
{
void *p;
p = malloc(n);
if(p == nil)
error("malloc failed");
setmalloctag(p, getcallerpc(&n));
memset(p, 0, n);
return p;
}
void*
erealloc(void *p, uint n)
{
p = realloc(p, n);
if(p == nil)
error("realloc failed");
setmalloctag(p, getcallerpc(&n));
return p;
} }
/* /*
* Heuristic city. * Heuristic city.
*/ */
Window* Window* makenewwindow(Text* t) {
makenewwindow(Text *t) Column* c;
{ Window *w, *bigw, *emptyw;
Column *c; Text* emptyb;
Window *w, *bigw, *emptyw; int i, y, el;
Text *emptyb;
int i, y, el;
if(activecol) if (activecol)
c = activecol; c = activecol;
else if(seltext && seltext->col) else if (seltext && seltext->col)
c = seltext->col; c = seltext->col;
else if(t && t->col) else if (t && t->col)
c = t->col; c = t->col;
else{ else {
if(row.ncol==0 && rowadd(&row, nil, -1)==nil) if (row.ncol == 0 && rowadd(&row, nil, -1) == nil)
error("can't make column"); error("can't make column");
c = row.col[row.ncol-1]; c = row.col[row.ncol - 1];
} }
activecol = c; activecol = c;
if(t==nil || t->w==nil || c->nw==0) if (t == nil || t->w == nil || c->nw == 0)
return coladd(c, nil, nil, -1); return coladd(c, nil, nil, -1);
/* find biggest window and biggest blank spot */ /* find biggest window and biggest blank spot */
emptyw = c->w[0]; emptyw = c->w[0];
bigw = emptyw; bigw = emptyw;
for(i=1; i<c->nw; i++){ for (i = 1; i < c->nw; i++) {
w = c->w[i]; w = c->w[i];
/* use >= to choose one near bottom of screen */ /* use >= to choose one near bottom of screen */
if(w->body.fr.maxlines >= bigw->body.fr.maxlines) if (w->body.fr.maxlines >= bigw->body.fr.maxlines)
bigw = w; bigw = w;
if(w->body.fr.maxlines-w->body.fr.nlines >= emptyw->body.fr.maxlines-emptyw->body.fr.nlines) if (
emptyw = w; w->body.fr.maxlines - w->body.fr.nlines >=
} emptyw->body.fr.maxlines - emptyw->body.fr.nlines)
emptyb = &emptyw->body; emptyw = w;
el = emptyb->fr.maxlines-emptyb->fr.nlines; }
/* if empty space is big, use it */ emptyb = &emptyw->body;
if(el>15 || (el>3 && el>(bigw->body.fr.maxlines-1)/2)) el = emptyb->fr.maxlines - emptyb->fr.nlines;
y = emptyb->fr.r.min.y+emptyb->fr.nlines*font->height; /* if empty space is big, use it */
else{ if (el > 15 || (el > 3 && el > (bigw->body.fr.maxlines - 1) / 2))
/* if this window is in column and isn't much smaller, split it */ y = emptyb->fr.r.min.y + emptyb->fr.nlines * font->height;
if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3) else {
bigw = t->w; /* if this window is in column and isn't much smaller, split it */
y = (bigw->r.min.y + bigw->r.max.y)/2; if (t->col == c && Dy(t->w->r) > 2 * Dy(bigw->r) / 3)
} bigw = t->w;
w = coladd(c, nil, nil, y); y = (bigw->r.min.y + bigw->r.max.y) / 2;
if(w->body.fr.maxlines < 2) }
colgrow(w->col, w, 1); w = coladd(c, nil, nil, y);
return w; if (w->body.fr.maxlines < 2)
colgrow(w->col, w, 1);
return w;
} }

1201
wind.c

File diff suppressed because it is too large Load diff

2041
xfid.c

File diff suppressed because it is too large Load diff