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: nilix
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.*
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 "fns.h"
enum
{
None = 0,
Fore = '+',
Back = '-'
};
enum { None = 0, Fore = '+', Back = '-' };
enum
{
Char,
Line
};
enum { Char, Line };
int
isaddrc(int r)
{
if(r && utfrune("0123456789+-/$.#,;?", r)!=nil)
return TRUE;
return FALSE;
int isaddrc(int r) {
if (r && utfrune("0123456789+-/$.#,;?", r) != nil)
return TRUE;
return FALSE;
}
/*
* quite hard: could be almost anything but white space, but we are a little conservative,
* aiming for regular expressions of alphanumerics and no white space
* quite hard: could be almost anything but white space, but we are a little
* conservative, aiming for regular expressions of alphanumerics and no white
* space
*/
int
isregexc(int r)
{
if(r == 0)
return FALSE;
if(isalnum(r))
return TRUE;
if(utfrune("^+-.*?#,;[]()$", r)!=nil)
return TRUE;
return FALSE;
int isregexc(int r) {
if (r == 0)
return FALSE;
if (isalnum(r))
return TRUE;
if (utfrune("^+-.*?#,;[]()$", r) != nil)
return TRUE;
return FALSE;
}
// 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
// the end of the current line.
// It returns the final position.
long
nlcounttopos(Text *t, long q0, long nl, long nr)
{
while(nl > 0 && q0 < t->file->b.nc) {
if(textreadc(t, q0++) == '\n')
nl--;
}
if(nl > 0)
return q0;
while(nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') {
q0++;
nr--;
}
return q0;
long nlcounttopos(Text* t, long q0, long nl, long nr) {
while (nl > 0 && q0 < t->file->b.nc) {
if (textreadc(t, q0++) == '\n')
nl--;
}
if (nl > 0)
return q0;
while (nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') {
q0++;
nr--;
}
return q0;
}
Range
number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp)
{
uint q0, q1;
Range number(
uint showerr, Text* t, Range r, int line, int dir, int size, int* evalp) {
uint q0, q1;
if(size == Char){
if(dir == Fore)
line = r.q1+line;
else if(dir == Back){
if(r.q0==0 && line>0)
r.q0 = t->file->b.nc;
line = r.q0 - line;
}
if(line<0 || line>t->file->b.nc)
goto Rescue;
*evalp = TRUE;
return range(line, line);
}
q0 = r.q0;
q1 = r.q1;
switch(dir){
case None:
q0 = 0;
q1 = 0;
Forward:
while(line>0 && q1<t->file->b.nc)
if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc)
if(--line > 0)
q0 = q1;
if(line==1 && q1==t->file->b.nc) // 6 goes to end of 5-line file
break;
if(line > 0)
goto Rescue;
break;
case Fore:
if(q1 > 0)
while(q1<t->file->b.nc && textreadc(t, q1-1) != '\n')
q1++;
q0 = q1;
goto Forward;
case Back:
if(q0 < t->file->b.nc)
while(q0>0 && textreadc(t, q0-1)!='\n')
q0--;
q1 = q0;
while(line>0 && q0>0){
if(textreadc(t, q0-1) == '\n'){
if(--line >= 0)
q1 = q0;
}
--q0;
}
/* :1-1 is :0 = #0, but :1-2 is an error */
if(line > 1)
goto Rescue;
while(q0>0 && textreadc(t, q0-1)!='\n')
--q0;
}
*evalp = TRUE;
return range(q0, q1);
if (size == Char) {
if (dir == Fore)
line = r.q1 + line;
else if (dir == Back) {
if (r.q0 == 0 && line > 0)
r.q0 = t->file->b.nc;
line = r.q0 - line;
}
if (line < 0 || line > t->file->b.nc)
goto Rescue;
*evalp = TRUE;
return range(line, line);
}
q0 = r.q0;
q1 = r.q1;
switch (dir) {
case None:
q0 = 0;
q1 = 0;
Forward:
while (line > 0 && q1 < t->file->b.nc)
if (textreadc(t, q1++) == '\n' || q1 == t->file->b.nc)
if (--line > 0)
q0 = q1;
if (line == 1 && q1 == t->file->b.nc) // 6 goes to end of 5-line file
break;
if (line > 0)
goto Rescue;
break;
case Fore:
if (q1 > 0)
while (q1 < t->file->b.nc && textreadc(t, q1 - 1) != '\n')
q1++;
q0 = q1;
goto Forward;
case Back:
if (q0 < t->file->b.nc)
while (q0 > 0 && textreadc(t, q0 - 1) != '\n')
q0--;
q1 = q0;
while (line > 0 && q0 > 0) {
if (textreadc(t, q0 - 1) == '\n') {
if (--line >= 0)
q1 = q0;
}
--q0;
}
/* :1-1 is :0 = #0, but :1-2 is an error */
if (line > 1)
goto Rescue;
while (q0 > 0 && textreadc(t, q0 - 1) != '\n')
--q0;
}
*evalp = TRUE;
return range(q0, q1);
Rescue:
if(showerr)
warning(nil, "address out of range\n");
*evalp = FALSE;
return r;
Rescue:
if (showerr)
warning(nil, "address out of range\n");
*evalp = FALSE;
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
regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)
{
int found;
Rangeset sel;
int q;
if(pat[0] == '\0' && rxnull()){
if(showerr)
warning(nil, "no previous regular expression\n");
*foundp = FALSE;
return r;
}
if(pat[0] && rxcompile(pat) == FALSE){
*foundp = FALSE;
return r;
}
if(dir == Back)
found = rxbexecute(t, r.q0, &sel);
else{
if(lim.q0 < 0)
q = Infinity;
else
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];
if (pat[0] == '\0' && rxnull()) {
if (showerr)
warning(nil, "no previous regular expression\n");
*foundp = FALSE;
return r;
}
if (pat[0] && rxcompile(pat) == FALSE) {
*foundp = FALSE;
return r;
}
if (dir == Back)
found = rxbexecute(t, r.q0, &sel);
else {
if (lim.q0 < 0)
q = Infinity;
else
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
address(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 prevc, c, nc, n;
uint q;
Rune *pat;
Range r, nr;
Range address(
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 prevc, c, nc, n;
uint q;
Rune* pat;
Range r, nr;
r = ar;
q = q0;
dir = None;
size = Line;
c = 0;
while(q < q1){
prevc = c;
c = (*getc)(a, q++);
switch(c){
default:
*qp = q-1;
return r;
case ';':
ar = r;
/* fall through */
case ',':
if(prevc == 0) /* lhs defaults to 0 */
r.q0 = 0;
if(q>=q1 && t!=nil && t->file!=nil) /* rhs defaults to $ */
r.q1 = t->file->b.nc;
else{
nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);
r.q1 = nr.q1;
}
*qp = q;
return r;
case '+':
case '-':
if(*evalp && (prevc=='+' || prevc=='-'))
if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?')
r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one */
dir = c;
break;
case '.':
case '$':
if(q != q0+1){
*qp = q-1;
return r;
}
if(*evalp)
if(c == '.')
r = ar;
else
r = range(t->file->b.nc, t->file->b.nc);
if(q < q1)
dir = Fore;
else
dir = None;
break;
case '#':
if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){
*qp = q-1;
return r;
}
size = Char;
/* fall through */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = c -'0';
while(q<q1){
nc = (*getc)(a, q++);
if(nc<'0' || '9'<nc){
q--;
break;
}
n = n*10+(nc-'0');
}
if(*evalp)
r = number(showerr, t, r, n, dir, size, evalp);
dir = None;
size = Line;
break;
case '?':
dir = Back;
/* fall through */
case '/':
npat = 0;
pat = nil;
while(q<q1){
c = (*getc)(a, q++);
switch(c){
case '\n':
--q;
goto out;
case '\\':
pat = runerealloc(pat, npat+1);
pat[npat++] = c;
if(q == q1)
goto out;
c = (*getc)(a, q++);
break;
case '/':
goto out;
}
pat = runerealloc(pat, npat+1);
pat[npat++] = c;
}
out:
pat = runerealloc(pat, npat+1);
pat[npat] = 0;
if(*evalp)
r = regexp(showerr, t, lim, r, pat, dir, evalp);
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;
r = ar;
q = q0;
dir = None;
size = Line;
c = 0;
while (q < q1) {
prevc = c;
c = (*getc)(a, q++);
switch (c) {
default:
*qp = q - 1;
return r;
case ';':
ar = r;
/* fall through */
case ',':
if (prevc == 0) /* lhs defaults to 0 */
r.q0 = 0;
if (q >= q1 && t != nil && t->file != nil) /* rhs defaults to $ */
r.q1 = t->file->b.nc;
else {
nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);
r.q1 = nr.q1;
}
*qp = q;
return r;
case '+':
case '-':
if (*evalp && (prevc == '+' || prevc == '-'))
if ((nc = (*getc)(a, q)) != '#' && nc != '/' && nc != '?')
r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one
*/
dir = c;
break;
case '.':
case '$':
if (q != q0 + 1) {
*qp = q - 1;
return r;
}
if (*evalp)
if (c == '.')
r = ar;
else
r = range(t->file->b.nc, t->file->b.nc);
if (q < q1)
dir = Fore;
else
dir = None;
break;
case '#':
if (q == q1 || (c = (*getc)(a, q++)) < '0' || '9' < c) {
*qp = q - 1;
return r;
}
size = Char;
/* fall through */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
n = c - '0';
while (q < q1) {
nc = (*getc)(a, q++);
if (nc < '0' || '9' < nc) {
q--;
break;
}
n = n * 10 + (nc - '0');
}
if (*evalp)
r = number(showerr, t, r, n, dir, size, evalp);
dir = None;
size = Line;
break;
case '?':
dir = Back;
/* fall through */
case '/':
npat = 0;
pat = nil;
while (q < q1) {
c = (*getc)(a, q++);
switch (c) {
case '\n':
--q;
goto out;
case '\\':
pat = runerealloc(pat, npat + 1);
pat[npat++] = c;
if (q == q1)
goto out;
c = (*getc)(a, q++);
break;
case '/':
goto out;
}
pat = runerealloc(pat, npat + 1);
pat[npat++] = c;
}
out:
pat = runerealloc(pat, npat + 1);
pat[npat] = 0;
if (*evalp)
r = regexp(showerr, t, lim, r, pat, dir, evalp);
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 "fns.h"
enum
{
Slop = 100 /* room to grow with reallocation */
enum {
Slop = 100 /* room to grow with reallocation */
};
static
void
sizecache(Buffer *b, uint n)
{
if(n <= b->cmax)
return;
b->cmax = n+Slop;
b->c = runerealloc(b->c, b->cmax);
static void sizecache(Buffer* b, uint n) {
if (n <= b->cmax)
return;
b->cmax = n + Slop;
b->c = runerealloc(b->c, b->cmax);
}
static
void
addblock(Buffer *b, uint i, uint n)
{
if(i > b->nbl)
error("internal error: addblock");
static void addblock(Buffer* b, uint i, uint n) {
if (i > b->nbl)
error("internal error: addblock");
b->bl = realloc(b->bl, (b->nbl+1)*sizeof b->bl[0]);
if(i < b->nbl)
memmove(b->bl+i+1, b->bl+i, (b->nbl-i)*sizeof(Block*));
b->bl[i] = disknewblock(disk, n);
b->nbl++;
b->bl = realloc(b->bl, (b->nbl + 1) * sizeof b->bl[0]);
if (i < b->nbl)
memmove(b->bl + i + 1, b->bl + i, (b->nbl - i) * sizeof(Block*));
b->bl[i] = disknewblock(disk, n);
b->nbl++;
}
static
void
delblock(Buffer *b, uint i)
{
if(i >= b->nbl)
error("internal error: delblock");
static void delblock(Buffer* b, uint i) {
if (i >= b->nbl)
error("internal error: delblock");
diskrelease(disk, b->bl[i]);
b->nbl--;
if(i < b->nbl)
memmove(b->bl+i, b->bl+i+1, (b->nbl-i)*sizeof(Block*));
b->bl = realloc(b->bl, b->nbl*sizeof b->bl[0]);
diskrelease(disk, b->bl[i]);
b->nbl--;
if (i < b->nbl)
memmove(b->bl + i, b->bl + i + 1, (b->nbl - i) * sizeof(Block*));
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.
*/
static
void
flush(Buffer *b)
{
if(b->cdirty || b->cnc==0){
if(b->cnc == 0)
delblock(b, b->cbi);
else
diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
b->cdirty = FALSE;
}
static void flush(Buffer* b) {
if (b->cdirty || b->cnc == 0) {
if (b->cnc == 0)
delblock(b, b->cbi);
else
diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
b->cdirty = FALSE;
}
}
static
void
setcache(Buffer *b, uint q0)
{
Block **blp, *bl;
uint i, q;
static void setcache(Buffer* b, uint q0) {
Block **blp, *bl;
uint i, q;
if(q0 > b->nc)
error("internal error: setcache");
/*
* flush and reload if q0 is not in cache.
*/
if(b->nc == 0 || (b->cq<=q0 && q0<b->cq+b->cnc))
return;
/*
* 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)
return;
flush(b);
/* find block */
if(q0 < b->cq){
q = 0;
i = 0;
}else{
q = b->cq;
i = b->cbi;
}
blp = &b->bl[i];
while(q+(*blp)->u.n <= q0 && q+(*blp)->u.n < b->nc){
q += (*blp)->u.n;
i++;
blp++;
if(i >= b->nbl)
error("block not found");
}
bl = *blp;
/* remember position */
b->cbi = i;
b->cq = q;
sizecache(b, bl->u.n);
b->cnc = bl->u.n;
/*read block*/
diskread(disk, bl, b->c, b->cnc);
if (q0 > b->nc)
error("internal error: setcache");
/*
* flush and reload if q0 is not in cache.
*/
if (b->nc == 0 || (b->cq <= q0 && q0 < b->cq + b->cnc))
return;
/*
* 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)
return;
flush(b);
/* find block */
if (q0 < b->cq) {
q = 0;
i = 0;
} else {
q = b->cq;
i = b->cbi;
}
blp = &b->bl[i];
while (q + (*blp)->u.n <= q0 && q + (*blp)->u.n < b->nc) {
q += (*blp)->u.n;
i++;
blp++;
if (i >= b->nbl)
error("block not found");
}
bl = *blp;
/* remember position */
b->cbi = i;
b->cq = q;
sizecache(b, bl->u.n);
b->cnc = bl->u.n;
/*read block*/
diskread(disk, bl, b->c, b->cnc);
}
void
bufinsert(Buffer *b, uint q0, Rune *s, uint n)
{
uint i, m, t, off;
void bufinsert(Buffer* b, uint q0, Rune* s, uint n) {
uint i, m, t, off;
if(q0 > b->nc)
error("internal error: bufinsert");
if (q0 > b->nc)
error("internal error: bufinsert");
while(n > 0){
setcache(b, q0);
off = q0-b->cq;
if(b->cnc+n <= Maxblock){
/* Everything fits in one block. */
t = b->cnc+n;
m = n;
if(b->bl == nil){ /* allocate */
if(b->cnc != 0)
error("internal error: bufinsert1 cnc!=0");
addblock(b, 0, t);
b->cbi = 0;
}
sizecache(b, t);
runemove(b->c+off+m, b->c+off, b->cnc-off);
runemove(b->c+off, s, m);
b->cnc = t;
goto Tail;
}
/*
* We must make a new block. If q0 is at
* the very beginning or end of this block,
* just make a new block and fill it.
*/
if(q0==b->cq || q0==b->cq+b->cnc){
if(b->cdirty)
flush(b);
m = min(n, Maxblock);
if(b->bl == nil){ /* allocate */
if(b->cnc != 0)
error("internal error: bufinsert2 cnc!=0");
i = 0;
}else{
i = b->cbi;
if(q0 > b->cq)
i++;
}
addblock(b, i, m);
sizecache(b, m);
runemove(b->c, s, m);
b->cq = q0;
b->cbi = i;
b->cnc = m;
goto Tail;
}
/*
* Split the block; cut off the right side and
* let go of it.
*/
m = b->cnc-off;
if(m > 0){
i = b->cbi+1;
addblock(b, i, m);
diskwrite(disk, &b->bl[i], b->c+off, m);
b->cnc -= m;
}
/*
* Now at end of block. Take as much input
* as possible and tack it on end of block.
*/
m = min(n, Maxblock-b->cnc);
sizecache(b, b->cnc+m);
runemove(b->c+b->cnc, s, m);
b->cnc += m;
while (n > 0) {
setcache(b, q0);
off = q0 - b->cq;
if (b->cnc + n <= Maxblock) {
/* Everything fits in one block. */
t = b->cnc + n;
m = n;
if (b->bl == nil) { /* allocate */
if (b->cnc != 0)
error("internal error: bufinsert1 cnc!=0");
addblock(b, 0, t);
b->cbi = 0;
}
sizecache(b, t);
runemove(b->c + off + m, b->c + off, b->cnc - off);
runemove(b->c + off, s, m);
b->cnc = t;
goto Tail;
}
/*
* We must make a new block. If q0 is at
* the very beginning or end of this block,
* just make a new block and fill it.
*/
if (q0 == b->cq || q0 == b->cq + b->cnc) {
if (b->cdirty)
flush(b);
m = min(n, Maxblock);
if (b->bl == nil) { /* allocate */
if (b->cnc != 0)
error("internal error: bufinsert2 cnc!=0");
i = 0;
} else {
i = b->cbi;
if (q0 > b->cq)
i++;
}
addblock(b, i, m);
sizecache(b, m);
runemove(b->c, s, m);
b->cq = q0;
b->cbi = i;
b->cnc = m;
goto Tail;
}
/*
* Split the block; cut off the right side and
* let go of it.
*/
m = b->cnc - off;
if (m > 0) {
i = b->cbi + 1;
addblock(b, i, m);
diskwrite(disk, &b->bl[i], b->c + off, m);
b->cnc -= m;
}
/*
* Now at end of block. Take as much input
* as possible and tack it on end of block.
*/
m = min(n, Maxblock - b->cnc);
sizecache(b, b->cnc + m);
runemove(b->c + b->cnc, s, m);
b->cnc += m;
Tail:
b->nc += m;
q0 += m;
s += m;
n -= m;
b->cdirty = TRUE;
}
b->nc += m;
q0 += m;
s += m;
n -= m;
b->cdirty = TRUE;
}
}
void
bufdelete(Buffer *b, uint q0, uint q1)
{
uint m, n, off;
void bufdelete(Buffer* b, uint q0, uint q1) {
uint m, n, off;
if(!(q0<=q1 && q0<=b->nc && q1<=b->nc))
error("internal error: bufdelete");
while(q1 > q0){
setcache(b, q0);
off = q0-b->cq;
if(q1 > b->cq+b->cnc)
n = b->cnc - off;
else
n = q1-q0;
m = b->cnc - (off+n);
if(m > 0)
runemove(b->c+off, b->c+off+n, m);
b->cnc -= n;
b->cdirty = TRUE;
q1 -= n;
b->nc -= n;
}
if (!(q0 <= q1 && q0 <= b->nc && q1 <= b->nc))
error("internal error: bufdelete");
while (q1 > q0) {
setcache(b, q0);
off = q0 - b->cq;
if (q1 > b->cq + b->cnc)
n = b->cnc - off;
else
n = q1 - q0;
m = b->cnc - (off + n);
if (m > 0)
runemove(b->c + off, b->c + off + n, m);
b->cnc -= n;
b->cdirty = TRUE;
q1 -= n;
b->nc -= n;
}
}
static int
bufloader(void *v, uint q0, Rune *r, int nr)
{
bufinsert(v, q0, r, nr);
return nr;
static int bufloader(void* v, uint q0, Rune* r, int nr) {
bufinsert(v, q0, r, nr);
return nr;
}
uint
loadfile(int fd, uint q0, int *nulls, int(*f)(void*, uint, Rune*, int), void *arg, DigestState *h)
{
char *p;
Rune *r;
int l, m, n, nb, nr;
uint q1;
uint loadfile(
int fd, uint q0, int* nulls, int (*f)(void*, uint, Rune*, int), void* arg,
DigestState* h) {
char* p;
Rune* r;
int l, m, n, nb, nr;
uint q1;
p = emalloc((Maxblock+UTFmax+1)*sizeof p[0]);
r = runemalloc(Maxblock);
m = 0;
n = 1;
q1 = q0;
/*
* At top of loop, may have m bytes left over from
* last pass, possibly representing a partial rune.
*/
while(n > 0){
n = read(fd, p+m, Maxblock);
if(n < 0){
warning(nil, "read error in Buffer.load");
break;
}
if(h != nil)
sha1((uchar*)p+m, n, nil, h);
m += n;
p[m] = 0;
l = m;
if(n > 0)
l -= UTFmax;
cvttorunes(p, l, r, &nb, &nr, nulls);
memmove(p, p+nb, m-nb);
m -= nb;
q1 += (*f)(arg, q1, r, nr);
}
free(p);
free(r);
return q1-q0;
p = emalloc((Maxblock + UTFmax + 1) * sizeof p[0]);
r = runemalloc(Maxblock);
m = 0;
n = 1;
q1 = q0;
/*
* At top of loop, may have m bytes left over from
* last pass, possibly representing a partial rune.
*/
while (n > 0) {
n = read(fd, p + m, Maxblock);
if (n < 0) {
warning(nil, "read error in Buffer.load");
break;
}
if (h != nil)
sha1((uchar*)p + m, n, nil, h);
m += n;
p[m] = 0;
l = m;
if (n > 0)
l -= UTFmax;
cvttorunes(p, l, r, &nb, &nr, nulls);
memmove(p, p + nb, m - nb);
m -= nb;
q1 += (*f)(arg, q1, r, nr);
}
free(p);
free(r);
return q1 - q0;
}
uint
bufload(Buffer *b, uint q0, int fd, int *nulls, DigestState *h)
{
if(q0 > b->nc)
error("internal error: bufload");
return loadfile(fd, q0, nulls, bufloader, b, h);
uint bufload(Buffer* b, uint q0, int fd, int* nulls, DigestState* h) {
if (q0 > b->nc)
error("internal error: bufload");
return loadfile(fd, q0, nulls, bufloader, b, h);
}
void
bufread(Buffer *b, uint q0, Rune *s, uint n)
{
uint m;
void bufread(Buffer* b, uint q0, Rune* s, uint n) {
uint m;
if(!(q0<=b->nc && q0+n<=b->nc))
error("bufread: internal error");
if (!(q0 <= b->nc && q0 + n <= b->nc))
error("bufread: internal error");
while(n > 0){
setcache(b, q0);
m = min(n, b->cnc-(q0-b->cq));
runemove(s, b->c+(q0-b->cq), m);
q0 += m;
s += m;
n -= m;
}
while (n > 0) {
setcache(b, q0);
m = min(n, b->cnc - (q0 - b->cq));
runemove(s, b->c + (q0 - b->cq), m);
q0 += m;
s += m;
n -= m;
}
}
void
bufreset(Buffer *b)
{
int i;
void bufreset(Buffer* b) {
int i;
b->nc = 0;
b->cnc = 0;
b->cq = 0;
b->cdirty = 0;
b->cbi = 0;
/* delete backwards to avoid n² behavior */
for(i=b->nbl-1; --i>=0; )
delblock(b, i);
b->nc = 0;
b->cnc = 0;
b->cq = 0;
b->cdirty = 0;
b->cbi = 0;
/* delete backwards to avoid n² behavior */
for (i = b->nbl - 1; --i >= 0;)
delblock(b, i);
}
void
bufclose(Buffer *b)
{
bufreset(b);
free(b->c);
b->c = nil;
b->cnc = 0;
free(b->bl);
b->bl = nil;
b->nbl = 0;
void bufclose(Buffer* b) {
bufreset(b);
free(b->c);
b->c = nil;
b->cnc = 0;
free(b->bl);
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 "fns.h"
static Block *blist;
static Block* blist;
int
tempfile(void)
{
char buf[128];
int i, fd;
int tempfile(void) {
char buf[128];
int i, fd;
snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
for(i='A'; i<='Z'; i++){
buf[5] = i;
if(access(buf, AEXIST) == 0)
continue;
fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
if(fd >= 0)
return fd;
}
return -1;
snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
for (i = 'A'; i <= 'Z'; i++) {
buf[5] = i;
if (access(buf, AEXIST) == 0)
continue;
fd = create(buf, ORDWR | ORCLOSE | OCEXEC, 0600);
if (fd >= 0)
return fd;
}
return -1;
}
Disk*
diskinit()
{
Disk *d;
Disk* diskinit() {
Disk* d;
d = emalloc(sizeof(Disk));
d->fd = tempfile();
if(d->fd < 0){
fprint(2, "acme: can't create temp file: %r\n");
threadexitsall("diskinit");
}
return d;
d = emalloc(sizeof(Disk));
d->fd = tempfile();
if (d->fd < 0) {
fprint(2, "acme: can't create temp file: %r\n");
threadexitsall("diskinit");
}
return d;
}
static
uint
ntosize(uint n, uint *ip)
{
uint size;
static uint ntosize(uint n, uint* ip) {
uint size;
if(n > Maxblock)
error("internal error: ntosize");
size = n;
if(size & (Blockincr-1))
size += Blockincr - (size & (Blockincr-1));
/* last bucket holds blocks of exactly Maxblock */
if(ip)
*ip = size/Blockincr;
return size * sizeof(Rune);
if (n > Maxblock)
error("internal error: ntosize");
size = n;
if (size & (Blockincr - 1))
size += Blockincr - (size & (Blockincr - 1));
/* last bucket holds blocks of exactly Maxblock */
if (ip)
*ip = size / Blockincr;
return size * sizeof(Rune);
}
Block*
disknewblock(Disk *d, uint n)
{
uint i, j, size;
Block *b;
Block* disknewblock(Disk* d, uint n) {
uint i, j, size;
Block* b;
size = ntosize(n, &i);
b = d->free[i];
if(b)
d->free[i] = b->u.next;
else{
/* allocate in chunks to reduce malloc overhead */
if(blist == nil){
blist = emalloc(100*sizeof(Block));
for(j=0; j<100-1; j++)
blist[j].u.next = &blist[j+1];
}
b = blist;
blist = b->u.next;
b->addr = d->addr;
if(d->addr+size < d->addr){
error("temp file overflow");
}
d->addr += size;
}
b->u.n = n;
return b;
size = ntosize(n, &i);
b = d->free[i];
if (b)
d->free[i] = b->u.next;
else {
/* allocate in chunks to reduce malloc overhead */
if (blist == nil) {
blist = emalloc(100 * sizeof(Block));
for (j = 0; j < 100 - 1; j++)
blist[j].u.next = &blist[j + 1];
}
b = blist;
blist = b->u.next;
b->addr = d->addr;
if (d->addr + size < d->addr) {
error("temp file overflow");
}
d->addr += size;
}
b->u.n = n;
return b;
}
void
diskrelease(Disk *d, Block *b)
{
uint i;
void diskrelease(Disk* d, Block* b) {
uint i;
ntosize(b->u.n, &i);
b->u.next = d->free[i];
d->free[i] = b;
ntosize(b->u.n, &i);
b->u.next = d->free[i];
d->free[i] = b;
}
void
diskwrite(Disk *d, Block **bp, Rune *r, uint n)
{
int size, nsize;
Block *b;
void diskwrite(Disk* d, Block** bp, Rune* r, uint n) {
int size, nsize;
Block* b;
b = *bp;
size = ntosize(b->u.n, nil);
nsize = ntosize(n, nil);
if(size != nsize){
diskrelease(d, b);
b = disknewblock(d, n);
*bp = b;
}
if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
error("write error to temp file");
b->u.n = n;
b = *bp;
size = ntosize(b->u.n, nil);
nsize = ntosize(n, nil);
if (size != nsize) {
diskrelease(d, b);
b = disknewblock(d, n);
*bp = b;
}
if (pwrite(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
error("write error to temp file");
b->u.n = n;
}
void
diskread(Disk *d, Block *b, Rune *r, uint n)
{
if(n > b->u.n)
error("internal error: diskread");
void diskread(Disk* d, Block* b, Rune* r, uint n) {
if (n > b->u.n)
error("internal error: diskread");
ntosize(b->u.n, nil);
if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
error("read error from temp file");
ntosize(b->u.n, nil);
if (pread(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
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"
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:
@ -27,328 +27,321 @@ static int warned = FALSE;
*/
typedef struct Buflog Buflog;
struct Buflog
{
short type; /* Replace, Filename */
uint q0; /* location of change (unused in f) */
uint nd; /* # runes to delete */
uint nr; /* # runes in string or file name */
struct Buflog {
short type; /* Replace, Filename */
uint q0; /* location of change (unused in f) */
uint nd; /* # runes to delete */
uint nr; /* # runes in string or file name */
};
enum
{
Buflogsize = sizeof(Buflog)/sizeof(Rune)
};
enum { Buflogsize = sizeof(Buflog) / sizeof(Rune) };
/*
* 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.
*/
enum
{
Minstring = 16, /* distance beneath which we merge changes */
Maxstring = RBUFSIZE /* maximum length of change we will merge into one */
enum {
Minstring = 16, /* distance beneath which we merge changes */
Maxstring = RBUFSIZE /* maximum length of change we will merge into one */
};
void
eloginit(File *f)
{
if(f->elog.type != Empty)
return;
f->elog.type = Null;
if(f->elogbuf == nil)
f->elogbuf = emalloc(sizeof(Buffer));
if(f->elog.r == nil)
f->elog.r = fbufalloc();
bufreset(f->elogbuf);
void eloginit(File* f) {
if (f->elog.type != Empty)
return;
f->elog.type = Null;
if (f->elogbuf == nil)
f->elogbuf = emalloc(sizeof(Buffer));
if (f->elog.r == nil)
f->elog.r = fbufalloc();
bufreset(f->elogbuf);
}
void
elogclose(File *f)
{
if(f->elogbuf){
bufclose(f->elogbuf);
free(f->elogbuf);
f->elogbuf = nil;
}
void elogclose(File* f) {
if (f->elogbuf) {
bufclose(f->elogbuf);
free(f->elogbuf);
f->elogbuf = nil;
}
}
void
elogreset(File *f)
{
f->elog.type = Null;
f->elog.nd = 0;
f->elog.nr = 0;
void elogreset(File* f) {
f->elog.type = Null;
f->elog.nd = 0;
f->elog.nr = 0;
}
void
elogterm(File *f)
{
elogreset(f);
if(f->elogbuf)
bufreset(f->elogbuf);
f->elog.type = Empty;
fbuffree(f->elog.r);
f->elog.r = nil;
warned = FALSE;
void elogterm(File* f) {
elogreset(f);
if (f->elogbuf)
bufreset(f->elogbuf);
f->elog.type = Empty;
fbuffree(f->elog.r);
f->elog.r = nil;
warned = FALSE;
}
void
elogflush(File *f)
{
Buflog b;
void elogflush(File* f) {
Buflog b;
b.type = f->elog.type;
b.q0 = f->elog.q0;
b.nd = f->elog.nd;
b.nr = f->elog.nr;
switch(f->elog.type){
default:
warning(nil, "unknown elog type 0x%ux\n", f->elog.type);
break;
case Null:
break;
case Insert:
case Replace:
if(f->elog.nr > 0)
bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr);
/* fall through */
case Delete:
bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize);
break;
}
elogreset(f);
b.type = f->elog.type;
b.q0 = f->elog.q0;
b.nd = f->elog.nd;
b.nr = f->elog.nr;
switch (f->elog.type) {
default:
warning(nil, "unknown elog type 0x%ux\n", f->elog.type);
break;
case Null:
break;
case Insert:
case Replace:
if (f->elog.nr > 0)
bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr);
/* fall through */
case Delete:
bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize);
break;
}
elogreset(f);
}
void
elogreplace(File *f, int q0, int q1, Rune *r, int nr)
{
uint gap;
void elogreplace(File* f, int q0, int q1, Rune* r, int nr) {
uint gap;
if(q0==q1 && nr==0)
return;
eloginit(f);
if(f->elog.type!=Null && q0<f->elog.q0){
if(warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
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(gap < Minstring){
if(gap > 0){
bufread(&f->b, f->elog.q0+f->elog.nd, f->elog.r+f->elog.nr, gap);
f->elog.nr += gap;
}
f->elog.nd += gap + q1-q0;
runemove(f->elog.r+f->elog.nr, r, nr);
f->elog.nr += nr;
return;
}
}
elogflush(f);
f->elog.type = Replace;
f->elog.q0 = q0;
f->elog.nd = q1-q0;
f->elog.nr = nr;
if(nr > RBUFSIZE)
editerror("internal error: replacement string too large(%d)", nr);
runemove(f->elog.r, r, nr);
if (q0 == q1 && nr == 0)
return;
eloginit(f);
if (f->elog.type != Null && q0 < f->elog.q0) {
if (warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
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 (gap < Minstring) {
if (gap > 0) {
bufread(&f->b, f->elog.q0 + f->elog.nd, f->elog.r + f->elog.nr, gap);
f->elog.nr += gap;
}
f->elog.nd += gap + q1 - q0;
runemove(f->elog.r + f->elog.nr, r, nr);
f->elog.nr += nr;
return;
}
}
elogflush(f);
f->elog.type = Replace;
f->elog.q0 = q0;
f->elog.nd = q1 - q0;
f->elog.nr = nr;
if (nr > RBUFSIZE)
editerror("internal error: replacement string too large(%d)", nr);
runemove(f->elog.r, r, nr);
}
void
eloginsert(File *f, int q0, Rune *r, int nr)
{
int n;
void eloginsert(File* f, int q0, Rune* r, int nr) {
int n;
if(nr == 0)
return;
eloginit(f);
if(f->elog.type!=Null && q0<f->elog.q0){
if(warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
if(f->elog.type==Insert && q0==f->elog.q0 && f->elog.nr+nr<Maxstring){
runemove(f->elog.r+f->elog.nr, r, nr);
f->elog.nr += nr;
return;
}
while(nr > 0){
elogflush(f);
f->elog.type = Insert;
f->elog.q0 = q0;
n = nr;
if(n > RBUFSIZE)
n = RBUFSIZE;
f->elog.nr = n;
runemove(f->elog.r, r, n);
r += n;
nr -= n;
}
if (nr == 0)
return;
eloginit(f);
if (f->elog.type != Null && q0 < f->elog.q0) {
if (warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
if (
f->elog.type == Insert && q0 == f->elog.q0 && f->elog.nr + nr < Maxstring) {
runemove(f->elog.r + f->elog.nr, r, nr);
f->elog.nr += nr;
return;
}
while (nr > 0) {
elogflush(f);
f->elog.type = Insert;
f->elog.q0 = q0;
n = nr;
if (n > RBUFSIZE)
n = RBUFSIZE;
f->elog.nr = n;
runemove(f->elog.r, r, n);
r += n;
nr -= n;
}
}
void
elogdelete(File *f, int q0, int q1)
{
if(q0 == q1)
return;
eloginit(f);
if(f->elog.type!=Null && q0<f->elog.q0+f->elog.nd){
if(warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
if(f->elog.type==Delete && f->elog.q0+f->elog.nd==q0){
f->elog.nd += q1-q0;
return;
}
elogflush(f);
f->elog.type = Delete;
f->elog.q0 = q0;
f->elog.nd = q1-q0;
void elogdelete(File* f, int q0, int q1) {
if (q0 == q1)
return;
eloginit(f);
if (f->elog.type != Null && q0 < f->elog.q0 + f->elog.nd) {
if (warned++ == 0)
warning(nil, Wsequence);
elogflush(f);
}
/* try to merge with previous */
if (f->elog.type == Delete && f->elog.q0 + f->elog.nd == q0) {
f->elog.nd += q1 - q0;
return;
}
elogflush(f);
f->elog.type = Delete;
f->elog.q0 = q0;
f->elog.nd = q1 - q0;
}
#define tracelog 0
void
elogapply(File *f)
{
Buflog b;
Rune *buf;
uint i, n, up, mod;
uint tq0, tq1;
Buffer *log;
Text *t;
int owner;
void elogapply(File* f) {
Buflog b;
Rune* buf;
uint i, n, up, mod;
uint tq0, tq1;
Buffer* log;
Text* t;
int owner;
elogflush(f);
log = f->elogbuf;
t = f->curtext;
elogflush(f);
log = f->elogbuf;
t = f->curtext;
buf = fbufalloc();
mod = FALSE;
buf = fbufalloc();
mod = FALSE;
owner = 0;
if(t->w){
owner = t->w->owner;
if(owner == 0)
t->w->owner = 'E';
}
owner = 0;
if (t->w) {
owner = t->w->owner;
if (owner == 0)
t->w->owner = 'E';
}
/*
* 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,
* we have to update the coordinates to be relative to the modified buffer.
* Textinsert and textdelete will do this for us; our only work is to apply the
* convention that an insertion at t->q0==t->q1 is intended to select the
* inserted text.
*/
/*
* 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, we have to update the coordinates to be relative to the modified
* buffer. Textinsert and textdelete will do this for us; our only work is to
* apply the convention that an insertion at t->q0==t->q1 is intended to
* select the inserted text.
*/
/*
* We constrain the addresses in here (with textconstrain()) because
* overlapping changes will generate bogus addresses. We will warn
* about changes out of sequence but proceed anyway; here we must
* keep things in range.
*/
/*
* We constrain the addresses in here (with textconstrain()) because
* overlapping changes will generate bogus addresses. We will warn
* about changes out of sequence but proceed anyway; here we must
* keep things in range.
*/
while(log->nc > 0){
up = log->nc-Buflogsize;
bufread(log, up, (Rune*)&b, Buflogsize);
switch(b.type){
default:
fprint(2, "elogapply: 0x%ux\n", b.type);
abort();
break;
while (log->nc > 0) {
up = log->nc - Buflogsize;
bufread(log, up, (Rune*)&b, Buflogsize);
switch (b.type) {
default:
fprint(2, "elogapply: 0x%ux\n", b.type);
abort();
break;
case Replace:
if(tracelog)
warning(nil, "elog replace %d %d (%d %d)\n",
b.q0, b.q0+b.nd, t->q0, t->q1);
if(!mod){
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1);
textdelete(t, tq0, tq1, TRUE);
up -= b.nr;
for(i=0; i<b.nr; i+=n){
n = b.nr - i;
if(n > RBUFSIZE)
n = RBUFSIZE;
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 Replace:
if (tracelog)
warning(
nil,
"elog replace %d %d (%d %d)\n",
b.q0,
b.q0 + b.nd,
t->q0,
t->q1);
if (!mod) {
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1);
textdelete(t, tq0, tq1, TRUE);
up -= b.nr;
for (i = 0; i < b.nr; i += n) {
n = b.nr - i;
if (n > RBUFSIZE)
n = RBUFSIZE;
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:
if(tracelog)
warning(nil, "elog delete %d %d (%d %d)\n",
b.q0, b.q0+b.nd, t->q0, t->q1);
if(!mod){
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1);
textdelete(t, tq0, tq1, TRUE);
break;
case Delete:
if (tracelog)
warning(
nil,
"elog delete %d %d (%d %d)\n",
b.q0,
b.q0 + b.nd,
t->q0,
t->q1);
if (!mod) {
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1);
textdelete(t, tq0, tq1, TRUE);
break;
case Insert:
if(tracelog)
warning(nil, "elog insert %d %d (%d %d)\n",
b.q0, b.q0+b.nr, t->q0, t->q1);
if(!mod){
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0, &tq0, &tq1);
up -= b.nr;
for(i=0; i<b.nr; i+=n){
n = b.nr - i;
if(n > RBUFSIZE)
n = RBUFSIZE;
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 Insert:
if (tracelog)
warning(
nil,
"elog insert %d %d (%d %d)\n",
b.q0,
b.q0 + b.nr,
t->q0,
t->q1);
if (!mod) {
mod = TRUE;
filemark(f);
}
textconstrain(t, b.q0, b.q0, &tq0, &tq1);
up -= b.nr;
for (i = 0; i < b.nr; i += n) {
n = b.nr - i;
if (n > RBUFSIZE)
n = RBUFSIZE;
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:
f->seq = u.seq;
fileunsetname(f, epsilon);
f->mod = u.mod;
up -= u.n;
free(f->name);
if(u.n == 0)
f->name = nil;
else
f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n);
f->nname = u.n;
break;
*/
}
bufdelete(log, up, log->nc);
}
fbuffree(buf);
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);
}
/* case Filename:
f->seq = u.seq;
fileunsetname(f, epsilon);
f->mod = u.mod;
up -= u.n;
free(f->name);
if(u.n == 0)
f->name = nil;
else
f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n);
f->nname = u.n;
break;
*/
}
bufdelete(log, up, log->nc);
}
fbuffree(buf);
elogterm(f);
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;
struct Undo
{
short type; /* Delete, Insert, Filename */
short mod; /* modify bit */
uint seq; /* sequence number */
uint p0; /* location of change (unused in f) */
uint n; /* # runes in string or file name */
struct Undo {
short type; /* Delete, Insert, Filename */
short mod; /* modify bit */
uint seq; /* sequence number */
uint p0; /* location of change (unused in f) */
uint n; /* # runes in string or file name */
};
enum
{
Undosize = sizeof(Undo)/sizeof(Rune)
};
enum { Undosize = sizeof(Undo) / sizeof(Rune) };
File*
fileaddtext(File *f, Text *t)
{
if(f == nil){
f = emalloc(sizeof(File));
f->unread = TRUE;
}
f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
f->text[f->ntext++] = t;
f->curtext = t;
return f;
File* fileaddtext(File* f, Text* t) {
if (f == nil) {
f = emalloc(sizeof(File));
f->unread = TRUE;
}
f->text = realloc(f->text, (f->ntext + 1) * sizeof(Text*));
f->text[f->ntext++] = t;
f->curtext = t;
return f;
}
void
filedeltext(File *f, Text *t)
{
int i;
void filedeltext(File* f, Text* t) {
int i;
for(i=0; i<f->ntext; i++)
if(f->text[i] == t)
goto Found;
error("can't find text in filedeltext");
for (i = 0; i < f->ntext; i++)
if (f->text[i] == t)
goto Found;
error("can't find text in filedeltext");
Found:
f->ntext--;
if(f->ntext == 0){
fileclose(f);
return;
}
memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
if(f->curtext == t)
f->curtext = f->text[0];
Found:
f->ntext--;
if (f->ntext == 0) {
fileclose(f);
return;
}
memmove(f->text + i, f->text + i + 1, (f->ntext - i) * sizeof(Text*));
if (f->curtext == t)
f->curtext = f->text[0];
}
void
fileinsert(File *f, uint p0, Rune *s, uint ns)
{
if(p0 > f->b.nc)
error("internal error: fileinsert");
if(f->seq > 0)
fileuninsert(f, &f->delta, p0, ns);
bufinsert(&f->b, p0, s, ns);
if(ns)
f->mod = TRUE;
void fileinsert(File* f, uint p0, Rune* s, uint ns) {
if (p0 > f->b.nc)
error("internal error: fileinsert");
if (f->seq > 0)
fileuninsert(f, &f->delta, p0, ns);
bufinsert(&f->b, p0, s, ns);
if (ns)
f->mod = TRUE;
}
void
fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
{
Undo u;
void fileuninsert(File* f, Buffer* delta, uint p0, uint ns) {
Undo u;
/* undo an insertion by deleting */
u.type = Delete;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = p0;
u.n = ns;
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
/* undo an insertion by deleting */
u.type = Delete;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = p0;
u.n = ns;
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
}
void
filedelete(File *f, uint p0, uint p1)
{
if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc))
error("internal error: filedelete");
if(f->seq > 0)
fileundelete(f, &f->delta, p0, p1);
bufdelete(&f->b, p0, p1);
if(p1 > p0)
f->mod = TRUE;
void filedelete(File* f, uint p0, uint p1) {
if (!(p0 <= p1 && p0 <= f->b.nc && p1 <= f->b.nc))
error("internal error: filedelete");
if (f->seq > 0)
fileundelete(f, &f->delta, p0, p1);
bufdelete(&f->b, p0, p1);
if (p1 > p0)
f->mod = TRUE;
}
void
fileundelete(File *f, Buffer *delta, uint p0, uint p1)
{
Undo u;
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);
void fileundelete(File* f, Buffer* delta, uint p0, uint p1) {
Undo u;
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);
}
void
filesetname(File *f, Rune *name, int n)
{
if(f->seq > 0)
fileunsetname(f, &f->delta);
free(f->name);
f->name = runemalloc(n);
runemove(f->name, name, n);
f->nname = n;
f->unread = TRUE;
void filesetname(File* f, Rune* name, int n) {
if (f->seq > 0)
fileunsetname(f, &f->delta);
free(f->name);
f->name = runemalloc(n);
runemove(f->name, name, n);
f->nname = n;
f->unread = TRUE;
}
void
fileunsetname(File *f, Buffer *delta)
{
Undo u;
void fileunsetname(File* f, Buffer* delta) {
Undo u;
/* undo a file name change by restoring old name */
u.type = Filename;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = 0; /* unused */
u.n = f->nname;
if(f->nname)
bufinsert(delta, delta->nc, f->name, f->nname);
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
/* undo a file name change by restoring old name */
u.type = Filename;
u.mod = f->mod;
u.seq = f->seq;
u.p0 = 0; /* unused */
u.n = f->nname;
if (f->nname)
bufinsert(delta, delta->nc, f->name, f->nname);
bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
}
uint
fileload(File *f, uint p0, int fd, int *nulls, DigestState *h)
{
if(f->seq > 0)
error("undo in file.load unimplemented");
return bufload(&f->b, p0, fd, nulls, h);
uint fileload(File* f, uint p0, int fd, int* nulls, DigestState* h) {
if (f->seq > 0)
error("undo in file.load unimplemented");
return bufload(&f->b, p0, fd, nulls, h);
}
/* return sequence number of pending redo */
uint
fileredoseq(File *f)
{
Undo u;
Buffer *delta;
uint fileredoseq(File* f) {
Undo u;
Buffer* delta;
delta = &f->epsilon;
if(delta->nc == 0)
return 0;
bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize);
return u.seq;
delta = &f->epsilon;
if (delta->nc == 0)
return 0;
bufread(delta, delta->nc - Undosize, (Rune*)&u, Undosize);
return u.seq;
}
void
fileundo(File *f, int isundo, uint *q0p, uint *q1p)
{
Undo u;
Rune *buf;
uint i, j, n, up;
uint stop;
Buffer *delta, *epsilon;
void fileundo(File* f, int isundo, uint* q0p, uint* q1p) {
Undo u;
Rune* buf;
uint i, j, n, up;
uint stop;
Buffer *delta, *epsilon;
if(isundo){
/* undo; reverse delta onto epsilon, seq decreases */
delta = &f->delta;
epsilon = &f->epsilon;
stop = f->seq;
}else{
/* redo; reverse epsilon onto delta, seq increases */
delta = &f->epsilon;
epsilon = &f->delta;
stop = 0; /* don't know yet */
}
if (isundo) {
/* undo; reverse delta onto epsilon, seq decreases */
delta = &f->delta;
epsilon = &f->epsilon;
stop = f->seq;
} else {
/* redo; reverse epsilon onto delta, seq increases */
delta = &f->epsilon;
epsilon = &f->delta;
stop = 0; /* don't know yet */
}
buf = fbufalloc();
while(delta->nc > 0){
up = delta->nc-Undosize;
bufread(delta, up, (Rune*)&u, Undosize);
if(isundo){
if(u.seq < stop){
f->seq = u.seq;
goto Return;
}
}else{
if(stop == 0)
stop = u.seq;
if(u.seq > stop)
goto Return;
}
switch(u.type){
default:
fprint(2, "undo: 0x%ux\n", u.type);
abort();
break;
buf = fbufalloc();
while (delta->nc > 0) {
up = delta->nc - Undosize;
bufread(delta, up, (Rune*)&u, Undosize);
if (isundo) {
if (u.seq < stop) {
f->seq = u.seq;
goto Return;
}
} else {
if (stop == 0)
stop = u.seq;
if (u.seq > stop)
goto Return;
}
switch (u.type) {
default:
fprint(2, "undo: 0x%ux\n", u.type);
abort();
break;
case Delete:
f->seq = u.seq;
fileundelete(f, epsilon, u.p0, u.p0+u.n);
f->mod = u.mod;
bufdelete(&f->b, u.p0, u.p0+u.n);
for(j=0; j<f->ntext; j++)
textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
*q0p = u.p0;
*q1p = u.p0;
break;
case Delete:
f->seq = u.seq;
fileundelete(f, epsilon, u.p0, u.p0 + u.n);
f->mod = u.mod;
bufdelete(&f->b, u.p0, u.p0 + u.n);
for (j = 0; j < f->ntext; j++)
textdelete(f->text[j], u.p0, u.p0 + u.n, FALSE);
*q0p = u.p0;
*q1p = u.p0;
break;
case Insert:
f->seq = u.seq;
fileuninsert(f, epsilon, u.p0, u.n);
f->mod = u.mod;
up -= u.n;
for(i=0; i<u.n; i+=n){
n = u.n - i;
if(n > RBUFSIZE)
n = RBUFSIZE;
bufread(delta, up+i, buf, n);
bufinsert(&f->b, u.p0+i, buf, n);
for(j=0; j<f->ntext; j++)
textinsert(f->text[j], u.p0+i, buf, n, FALSE);
}
*q0p = u.p0;
*q1p = u.p0+u.n;
break;
case Insert:
f->seq = u.seq;
fileuninsert(f, epsilon, u.p0, u.n);
f->mod = u.mod;
up -= u.n;
for (i = 0; i < u.n; i += n) {
n = u.n - i;
if (n > RBUFSIZE)
n = RBUFSIZE;
bufread(delta, up + i, buf, n);
bufinsert(&f->b, u.p0 + i, buf, n);
for (j = 0; j < f->ntext; j++)
textinsert(f->text[j], u.p0 + i, buf, n, FALSE);
}
*q0p = u.p0;
*q1p = u.p0 + u.n;
break;
case Filename:
f->seq = u.seq;
fileunsetname(f, epsilon);
f->mod = u.mod;
up -= u.n;
free(f->name);
if(u.n == 0)
f->name = nil;
else
f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n);
f->nname = u.n;
break;
}
bufdelete(delta, up, delta->nc);
}
if(isundo)
f->seq = 0;
Return:
fbuffree(buf);
case Filename:
f->seq = u.seq;
fileunsetname(f, epsilon);
f->mod = u.mod;
up -= u.n;
free(f->name);
if (u.n == 0)
f->name = nil;
else
f->name = runemalloc(u.n);
bufread(delta, up, f->name, u.n);
f->nname = u.n;
break;
}
bufdelete(delta, up, delta->nc);
}
if (isundo)
f->seq = 0;
Return:
fbuffree(buf);
}
void
filereset(File *f)
{
bufreset(&f->delta);
bufreset(&f->epsilon);
f->seq = 0;
void filereset(File* f) {
bufreset(&f->delta);
bufreset(&f->epsilon);
f->seq = 0;
}
void
fileclose(File *f)
{
free(f->name);
f->nname = 0;
f->name = nil;
free(f->text);
f->ntext = 0;
f->text = nil;
bufclose(&f->b);
bufclose(&f->delta);
bufclose(&f->epsilon);
elogclose(f);
free(f);
void fileclose(File* f) {
free(f->name);
f->nname = 0;
f->name = nil;
free(f->text);
f->ntext = 0;
f->text = nil;
bufclose(&f->b);
bufclose(&f->delta);
bufclose(&f->epsilon);
elogclose(f);
free(f);
}
void
filemark(File *f)
{
if(f->epsilon.nc)
bufdelete(&f->epsilon, 0, f->epsilon.nc);
f->seq = seq;
void filemark(File* f) {
if (f->epsilon.nc)
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);
long nlcount(Text*, long, long, long*);
long nlcounttopos(Text*, long, long, long);
Rune* parsetag(Window*, int*);
Runestr runestr(Rune*, uint);
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.
typedef struct Log Log;
struct Log
{
QLock lk;
Rendez r;
struct Log {
QLock lk;
Rendez r;
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;
vlong start; // msg[0] corresponds to 'start' in the global sequence of events
// open acme/put files that need to read events
Fid **f;
int nf;
int mf;
// active (blocked) reads waiting for events
Xfid **read;
int nread;
int mread;
// 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
Fid** f;
int nf;
int mf;
// active (blocked) reads waiting for events
Xfid** read;
int nread;
int mread;
};
static Log eventlog;
void
xfidlogopen(Xfid *x)
{
qlock(&eventlog.lk);
if(eventlog.nf >= eventlog.mf) {
eventlog.mf = eventlog.mf*2;
if(eventlog.mf == 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;
void xfidlogopen(Xfid* x) {
qlock(&eventlog.lk);
if (eventlog.nf >= eventlog.mf) {
eventlog.mf = eventlog.mf * 2;
if (eventlog.mf == 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;
qunlock(&eventlog.lk);
qunlock(&eventlog.lk);
}
void
xfidlogclose(Xfid *x)
{
int i;
void xfidlogclose(Xfid* x) {
int i;
qlock(&eventlog.lk);
for(i=0; i<eventlog.nf; i++) {
if(eventlog.f[i] == x->f) {
eventlog.f[i] = eventlog.f[--eventlog.nf];
break;
}
}
qunlock(&eventlog.lk);
qlock(&eventlog.lk);
for (i = 0; i < eventlog.nf; i++) {
if (eventlog.f[i] == x->f) {
eventlog.f[i] = eventlog.f[--eventlog.nf];
break;
}
}
qunlock(&eventlog.lk);
}
void
xfidlogread(Xfid *x)
{
char *p;
int i;
Fcall fc;
void xfidlogread(Xfid* x) {
char* p;
int i;
Fcall fc;
qlock(&eventlog.lk);
if(eventlog.nread >= eventlog.mread) {
eventlog.mread = eventlog.mread*2;
if(eventlog.mread == 0)
eventlog.mread = 8;
eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]);
}
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;
}
}
qlock(&eventlog.lk);
if (eventlog.nread >= eventlog.mread) {
eventlog.mread = eventlog.mread * 2;
if (eventlog.mread == 0)
eventlog.mread = 8;
eventlog.read =
erealloc(eventlog.read, eventlog.mread * sizeof eventlog.read[0]);
}
eventlog.read[eventlog.nread++] = x;
if(x->flushed) {
qunlock(&eventlog.lk);
return;
}
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);
i = x->f->logoff - eventlog.start;
p = estrdup(eventlog.ev[i]);
x->f->logoff++;
qunlock(&eventlog.lk);
for (i = 0; i < eventlog.nread; i++) {
if (eventlog.read[i] == x) {
eventlog.read[i] = eventlog.read[--eventlog.nread];
break;
}
}
fc.data = p;
fc.count = strlen(p);
respond(x, &fc, nil);
free(p);
if (x->flushed) {
qunlock(&eventlog.lk);
return;
}
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
xfidlogflush(Xfid *x)
{
int i;
Xfid *rx;
void xfidlogflush(Xfid* x) {
int i;
Xfid* rx;
qlock(&eventlog.lk);
for(i=0; i<eventlog.nread; i++) {
rx = eventlog.read[i];
if(rx->fcall.tag == x->fcall.oldtag) {
rx->flushed = TRUE;
rwakeupall(&eventlog.r);
}
}
qunlock(&eventlog.lk);
qlock(&eventlog.lk);
for (i = 0; i < eventlog.nread; i++) {
rx = eventlog.read[i];
if (rx->fcall.tag == x->fcall.oldtag) {
rx->flushed = TRUE;
rwakeupall(&eventlog.r);
}
}
qunlock(&eventlog.lk);
}
/*
@ -153,47 +145,48 @@ xfidlogflush(Xfid *x)
* op == "del" for deleted window
* - called from winclose
*/
void
xfidlog(Window *w, char *op)
{
int i, n;
vlong min;
File *f;
char *name;
void xfidlog(Window* w, char* op) {
int i, n;
vlong min;
File* f;
char* name;
qlock(&eventlog.lk);
if(eventlog.nev >= eventlog.mev) {
// Remove and free any entries that all readers have read.
min = eventlog.start + eventlog.nev;
for(i=0; i<eventlog.nf; i++) {
if(min > eventlog.f[i]->logoff)
min = eventlog.f[i]->logoff;
}
if(min > eventlog.start) {
n = min - eventlog.start;
for(i=0; i<n; i++)
free(eventlog.ev[i]);
eventlog.nev -= n;
eventlog.start += n;
memmove(eventlog.ev, eventlog.ev+n, eventlog.nev*sizeof eventlog.ev[0]);
}
// Otherwise grow.
if(eventlog.nev >= eventlog.mev) {
eventlog.mev = eventlog.mev*2;
if(eventlog.mev == 0)
eventlog.mev = 8;
eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]);
}
}
f = w->body.file;
name = runetobyte(f->name, f->nname);
if(name == nil)
name = estrdup("");
eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name);
free(name);
if(eventlog.r.l == nil)
eventlog.r.l = &eventlog.lk;
rwakeupall(&eventlog.r);
qunlock(&eventlog.lk);
qlock(&eventlog.lk);
if (eventlog.nev >= eventlog.mev) {
// Remove and free any entries that all readers have read.
min = eventlog.start + eventlog.nev;
for (i = 0; i < eventlog.nf; i++) {
if (min > eventlog.f[i]->logoff)
min = eventlog.f[i]->logoff;
}
if (min > eventlog.start) {
n = min - eventlog.start;
for (i = 0; i < n; i++)
free(eventlog.ev[i]);
eventlog.nev -= n;
eventlog.start += n;
memmove(
eventlog.ev,
eventlog.ev + n,
eventlog.nev * sizeof eventlog.ev[0]);
}
// Otherwise grow.
if (eventlog.nev >= eventlog.mev) {
eventlog.mev = eventlog.mev * 2;
if (eventlog.mev == 0)
eventlog.mev = 8;
eventlog.ev = erealloc(eventlog.ev, eventlog.mev * sizeof eventlog.ev[0]);
}
}
f = w->body.file;
name = runetobyte(f->name, f->nname);
if (name == nil)
name = estrdup("");
eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name);
free(name);
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 "dat.h"
char*
formathtml(char *body, int *np)
{
int i, j, p[2], q[2];
Exec *e;
char buf[1024];
Channel *sync;
char* formathtml(char* body, int* np) {
int i, j, p[2], q[2];
Exec* e;
char buf[1024];
Channel* sync;
e = emalloc(sizeof(struct Exec));
if(pipe(p) < 0 || pipe(q) < 0)
error("can't create pipe: %r");
e = emalloc(sizeof(struct Exec));
if (pipe(p) < 0 || pipe(q) < 0)
error("can't create pipe: %r");
e->p[0] = p[0];
e->p[1] = p[1];
e->q[0] = q[0];
e->q[1] = q[1];
e->argv = emalloc(3*sizeof(char*));
e->argv[0] = estrdup("htmlfmt");
e->argv[1] = estrdup("-cutf-8");
e->argv[2] = nil;
e->prog = "htmlfmt";
sync = chancreate(sizeof(int), 0);
e->sync = sync;
proccreate(execproc, e, EXECSTACK);
recvul(sync);
close(p[0]);
close(q[1]);
e->p[0] = p[0];
e->p[1] = p[1];
e->q[0] = q[0];
e->q[1] = q[1];
e->argv = emalloc(3 * sizeof(char*));
e->argv[0] = estrdup("htmlfmt");
e->argv[1] = estrdup("-cutf-8");
e->argv[2] = nil;
e->prog = "htmlfmt";
sync = chancreate(sizeof(int), 0);
e->sync = sync;
proccreate(execproc, e, EXECSTACK);
recvul(sync);
close(p[0]);
close(q[1]);
if((i=write(p[1], body, *np)) != *np){
fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np);
close(p[1]);
close(q[0]);
return body;
}
close(p[1]);
if ((i = write(p[1], body, *np)) != *np) {
fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np);
close(p[1]);
close(q[0]);
return body;
}
close(p[1]);
free(body);
body = nil;
i = 0;
for(;;){
j = read(q[0], buf, sizeof buf);
if(j <= 0)
break;
body = realloc(body, i+j+1);
if(body == nil)
error("realloc failed: %r");
memmove(body+i, buf, j);
i += j;
body[i] = '\0';
}
close(q[0]);
free(body);
body = nil;
i = 0;
for (;;) {
j = read(q[0], buf, sizeof buf);
if (j <= 0)
break;
body = realloc(body, i + j + 1);
if (body == nil)
error("realloc failed: %r");
memmove(body + i, buf, j);
i += j;
body[i] = '\0';
}
close(q[0]);
*np = i;
return body;
*np = i;
return body;
}
char*
readbody(char *type, char *dir, int *np)
{
char *body;
body = readfile(dir, "body", np);
if(body != nil && strcmp(type, "text/html") == 0)
return formathtml(body, np);
return body;
char* readbody(char* type, char* dir, int* np) {
char* body;
body = readfile(dir, "body", np);
if (body != nil && strcmp(type, "text/html") == 0)
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 "dat.h"
void*
emalloc(uint n)
{
void *p;
void* emalloc(uint n) {
void* p;
p = malloc(n);
if(p == nil)
error("can't malloc: %r");
memset(p, 0, n);
setmalloctag(p, getcallerpc(&n));
return p;
p = malloc(n);
if (p == nil)
error("can't malloc: %r");
memset(p, 0, n);
setmalloctag(p, getcallerpc(&n));
return p;
}
void*
erealloc(void *p, uint n)
{
p = realloc(p, n);
if(p == nil)
error("can't realloc: %r");
setmalloctag(p, getcallerpc(&n));
return p;
void* erealloc(void* p, uint n) {
p = realloc(p, n);
if (p == nil)
error("can't realloc: %r");
setmalloctag(p, getcallerpc(&n));
return p;
}
char*
estrdup(char *s)
{
char *t;
char* estrdup(char* s) {
char* t;
t = emalloc(strlen(s)+1);
strcpy(t, s);
return t;
t = emalloc(strlen(s) + 1);
strcpy(t, s);
return t;
}
char*
estrstrdup(char *s, char *t)
{
char *u;
char* estrstrdup(char* s, char* t) {
char* u;
u = emalloc(strlen(s)+strlen(t)+1);
strcpy(u, s);
strcat(u, t);
return u;
u = emalloc(strlen(s) + strlen(t) + 1);
strcpy(u, s);
strcat(u, t);
return u;
}
char*
eappend(char *s, char *sep, char *t)
{
char *u;
char* eappend(char* s, char* sep, char* t) {
char* u;
if(t == nil)
u = estrstrdup(s, sep);
else{
u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
strcpy(u, s);
strcat(u, sep);
strcat(u, t);
}
free(s);
return u;
if (t == nil)
u = estrstrdup(s, sep);
else {
u = emalloc(strlen(s) + strlen(sep) + strlen(t) + 1);
strcpy(u, s);
strcat(u, sep);
strcat(u, t);
}
free(s);
return u;
}
char*
egrow(char *s, char *sep, char *t)
{
s = eappend(s, sep, t);
free(t);
return s;
char* egrow(char* s, char* sep, char* t) {
s = eappend(s, sep, t);
free(t);
return s;
}
void
error(char *fmt, ...)
{
Fmt f;
char buf[64];
va_list arg;
void error(char* fmt, ...) {
Fmt f;
char buf[64];
va_list arg;
fmtfdinit(&f, 2, buf, sizeof buf);
fmtprint(&f, "Mail: ");
va_start(arg, fmt);
fmtvprint(&f, fmt, arg);
va_end(arg);
fmtprint(&f, "\n");
fmtfdflush(&f);
threadexitsall(fmt);
fmtfdinit(&f, 2, buf, sizeof buf);
fmtprint(&f, "Mail: ");
va_start(arg, fmt);
fmtvprint(&f, fmt, arg);
va_end(arg);
fmtprint(&f, "\n");
fmtfdflush(&f);
threadexitsall(fmt);
}
void
ctlprint(CFid *fd, char *fmt, ...)
{
int n;
va_list arg;
void ctlprint(CFid* fd, char* fmt, ...) {
int n;
va_list arg;
va_start(arg, fmt);
n = fsvprint(fd, fmt, arg);
va_end(arg);
if(n <= 0)
error("control file write error: %r");
va_start(arg, fmt);
n = fsvprint(fd, fmt, arg);
va_end(arg);
if (n <= 0)
error("control file write error: %r");
}

Binary file not shown.

View file

@ -6,374 +6,325 @@
#include <9pclient.h>
#include "dat.h"
Window*
newwindow(void)
{
char buf[12];
Window *w;
Window* newwindow(void) {
char buf[12];
Window* w;
w = emalloc(sizeof(Window));
w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC);
if(w->ctl == nil || fsread(w->ctl, buf, 12)!=12)
error("can't open window ctl file: %r");
w = emalloc(sizeof(Window));
w->ctl = fsopen(acmefs, "new/ctl", ORDWR | OCEXEC);
if (w->ctl == nil || fsread(w->ctl, buf, 12) != 12)
error("can't open window ctl file: %r");
w->id = atoi(buf);
w->event = winopenfile(w, "event");
w->addr = nil; /* will be opened when needed */
w->body = nil;
w->data = nil;
w->cevent = chancreate(sizeof(Event*), 0);
w->ref = 1;
return w;
w->id = atoi(buf);
w->event = winopenfile(w, "event");
w->addr = nil; /* will be opened when needed */
w->body = nil;
w->data = nil;
w->cevent = chancreate(sizeof(Event*), 0);
w->ref = 1;
return w;
}
void
winincref(Window *w)
{
qlock(&w->lk);
++w->ref;
qunlock(&w->lk);
void winincref(Window* w) {
qlock(&w->lk);
++w->ref;
qunlock(&w->lk);
}
void
windecref(Window *w)
{
qlock(&w->lk);
if(--w->ref > 0){
qunlock(&w->lk);
return;
}
fsclose(w->event);
chanfree(w->cevent);
free(w);
void windecref(Window* w) {
qlock(&w->lk);
if (--w->ref > 0) {
qunlock(&w->lk);
return;
}
fsclose(w->event);
chanfree(w->cevent);
free(w);
}
void
winsetdump(Window *w, char *dir, char *cmd)
{
if(dir != nil)
ctlprint(w->ctl, "dumpdir %s\n", dir);
if(cmd != nil)
ctlprint(w->ctl, "dump %s\n", cmd);
void winsetdump(Window* w, char* dir, char* cmd) {
if (dir != nil)
ctlprint(w->ctl, "dumpdir %s\n", dir);
if (cmd != nil)
ctlprint(w->ctl, "dump %s\n", cmd);
}
void
wineventproc(void *v)
{
Window *w;
int i;
void wineventproc(void* v) {
Window* w;
int i;
w = v;
for(i=0; ; i++){
if(i >= NEVENT)
i = 0;
wingetevent(w, &w->e[i]);
sendp(w->cevent, &w->e[i]);
}
w = v;
for (i = 0;; i++) {
if (i >= NEVENT)
i = 0;
wingetevent(w, &w->e[i]);
sendp(w->cevent, &w->e[i]);
}
}
static CFid*
winopenfile1(Window *w, char *f, int m)
{
char buf[64];
CFid* fd;
static CFid* winopenfile1(Window* w, char* f, int m) {
char buf[64];
CFid* fd;
sprint(buf, "%d/%s", w->id, f);
fd = fsopen(acmefs, buf, m|OCEXEC);
if(fd == nil)
error("can't open window file %s: %r", f);
return fd;
sprint(buf, "%d/%s", w->id, f);
fd = fsopen(acmefs, buf, m | OCEXEC);
if (fd == nil)
error("can't open window file %s: %r", f);
return fd;
}
CFid*
winopenfile(Window *w, char *f)
{
return winopenfile1(w, f, ORDWR);
CFid* winopenfile(Window* w, char* f) { return winopenfile1(w, f, ORDWR); }
void wintagwrite(Window* w, char* s, int n) {
CFid* fid;
fid = winopenfile(w, "tag");
if (fswrite(fid, s, n) != n)
error("tag write: %r");
fsclose(fid);
}
void
wintagwrite(Window *w, char *s, int n)
{
CFid* fid;
void winname(Window* w, char* s) {
int len;
char *ns, *sp;
Rune r = L''; /* visible space */
fid = winopenfile(w, "tag");
if(fswrite(fid, s, n) != n)
error("tag write: %r");
fsclose(fid);
len = 0;
ns = emalloc(strlen(s) * runelen(r) + 1);
for (sp = s; *sp != '\0'; sp++, len++) {
if (isspace(*sp)) {
len += runetochar(ns + len, &r) - 1;
continue;
}
*(ns + len) = *sp;
}
ctlprint(w->ctl, "name %s\n", ns);
free(ns);
return;
}
void
winname(Window *w, char *s)
{
int len;
char *ns, *sp;
Rune r = L''; /* visible space */
void winopenbody(Window* w, int mode) {
char buf[256];
CFid* fid;
len = 0;
ns = emalloc(strlen(s)*runelen(r) + 1);
for(sp = s; *sp != '\0'; sp++, len++){
if(isspace(*sp)){
len += runetochar(ns+len, &r)-1;
continue;
}
*(ns+len) = *sp;
}
ctlprint(w->ctl, "name %s\n", ns);
free(ns);
return;
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
winopenbody(Window *w, int mode)
{
char buf[256];
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 winclosebody(Window* w) {
if (w->body != nil) {
fsclose(w->body);
w->body = nil;
}
}
void
winclosebody(Window *w)
{
if(w->body != nil){
fsclose(w->body);
w->body = nil;
}
void winwritebody(Window* w, char* s, int n) {
if (w->body == nil)
winopenbody(w, OWRITE);
if (fswrite(w->body, s, n) != n)
error("write error to window: %r");
}
void
winwritebody(Window *w, char *s, int n)
{
if(w->body == nil)
winopenbody(w, OWRITE);
if(fswrite(w->body, s, n) != n)
error("write error to window: %r");
int wingetec(Window* w) {
if (w->nbuf == 0) {
w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
if (w->nbuf <= 0) {
/* probably because window has exited, and only called by wineventproc, so
* just shut down */
windecref(w);
threadexits(nil);
}
w->bufp = w->buf;
}
w->nbuf--;
return *w->bufp++;
}
int
wingetec(Window *w)
{
if(w->nbuf == 0){
w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
if(w->nbuf <= 0){
/* probably because window has exited, and only called by wineventproc, so just shut down */
windecref(w);
threadexits(nil);
}
w->bufp = w->buf;
}
w->nbuf--;
return *w->bufp++;
int wingeten(Window* w) {
int n, c;
n = 0;
while ('0' <= (c = wingetec(w)) && c <= '9')
n = n * 10 + (c - '0');
if (c != ' ')
error("event number syntax");
return n;
}
int
wingeten(Window *w)
{
int n, c;
int wingeter(Window* w, char* buf, int* nb) {
Rune r;
int n;
n = 0;
while('0'<=(c=wingetec(w)) && c<='9')
n = n*10+(c-'0');
if(c != ' ')
error("event number syntax");
return n;
r = wingetec(w);
buf[0] = r;
n = 1;
if (r >= Runeself) {
while (!fullrune(buf, n))
buf[n++] = wingetec(w);
chartorune(&r, buf);
}
*nb = n;
return r;
}
int
wingeter(Window *w, char *buf, int *nb)
{
Rune r;
int n;
void wingetevent(Window* w, Event* e) {
int i, nb;
r = wingetec(w);
buf[0] = r;
n = 1;
if(r >= Runeself) {
while(!fullrune(buf, n))
buf[n++] = wingetec(w);
chartorune(&r, buf);
}
*nb = n;
return r;
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
wingetevent(Window *w, Event *e)
{
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 winwriteevent(Window* w, Event* e) {
fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
}
void
winwriteevent(Window *w, Event *e)
{
fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
void winread(Window* w, uint q0, uint q1, char* data) {
int m, n, nr;
char buf[256];
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
winread(Window *w, uint q0, uint q1, char *data)
{
int m, n, nr;
char buf[256];
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 windormant(Window* w) {
if (w->addr != nil) {
fsclose(w->addr);
w->addr = nil;
}
if (w->body != nil) {
fsclose(w->body);
w->body = nil;
}
if (w->data != nil) {
fsclose(w->data);
w->data = nil;
}
}
void
windormant(Window *w)
{
if(w->addr != nil){
fsclose(w->addr);
w->addr = nil;
}
if(w->body != nil){
fsclose(w->body);
w->body = nil;
}
if(w->data != nil){
fsclose(w->data);
w->data = nil;
}
int windel(Window* w, int sure) {
if (sure)
fswrite(w->ctl, "delete\n", 7);
else if (fswrite(w->ctl, "del\n", 4) != 4)
return 0;
/* event proc will die due to read error from event file */
windormant(w);
fsclose(w->ctl);
w->ctl = nil;
return 1;
}
void winclean(Window* w) { ctlprint(w->ctl, "clean\n"); }
int
windel(Window *w, int sure)
{
if(sure)
fswrite(w->ctl, "delete\n", 7);
else if(fswrite(w->ctl, "del\n", 4) != 4)
return 0;
/* event proc will die due to read error from event file */
windormant(w);
fsclose(w->ctl);
w->ctl = nil;
return 1;
int winsetaddr(Window* w, char* addr, int errok) {
if (w->addr == nil)
w->addr = winopenfile(w, "addr");
if (fswrite(w->addr, addr, strlen(addr)) < 0) {
if (!errok)
error("error writing addr(%s): %r", addr);
return 0;
}
return 1;
}
void
winclean(Window *w)
{
ctlprint(w->ctl, "clean\n");
int winselect(Window* w, char* addr, int errok) {
if (winsetaddr(w, addr, errok)) {
ctlprint(w->ctl, "dot=addr\n");
return 1;
}
return 0;
}
int
winsetaddr(Window *w, char *addr, int errok)
char* winreadbody(
Window* w,
int* np) /* can't use readfile because acme doesn't report the length */
{
if(w->addr == nil)
w->addr = winopenfile(w, "addr");
if(fswrite(w->addr, addr, strlen(addr)) < 0){
if(!errok)
error("error writing addr(%s): %r", addr);
return 0;
}
return 1;
char* s;
int m, na, n;
if (w->body != nil)
winclosebody(w);
winopenbody(w, OREAD);
s = nil;
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
winselect(Window *w, char *addr, int errok)
{
if(winsetaddr(w, addr, errok)){
ctlprint(w->ctl, "dot=addr\n");
return 1;
}
return 0;
}
char*
winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
{
char *s;
int m, na, n;
if(w->body != nil)
winclosebody(w);
winopenbody(w, OREAD);
s = nil;
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;
}
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;
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 "fns.h"
static Image *scrtmp;
static Image* scrtmp;
static
Rectangle
scrpos(Rectangle r, uint p0, uint p1, uint tot)
{
Rectangle q;
int h;
static Rectangle scrpos(Rectangle r, uint p0, uint p1, uint tot) {
Rectangle q;
int h;
q = r;
h = q.max.y-q.min.y;
if(tot == 0)
return q;
if(tot > 1024*1024){
tot>>=10;
p0>>=10;
p1>>=10;
}
if(p0 > 0)
q.min.y += h*p0/tot;
if(p1 < tot)
q.max.y -= h*(tot-p1)/tot;
if(q.max.y < q.min.y+2){
if(q.min.y+2 <= r.max.y)
q.max.y = q.min.y+2;
else
q.min.y = q.max.y-2;
}
return q;
q = r;
h = q.max.y - q.min.y;
if (tot == 0)
return q;
if (tot > 1024 * 1024) {
tot >>= 10;
p0 >>= 10;
p1 >>= 10;
}
if (p0 > 0)
q.min.y += h * p0 / tot;
if (p1 < tot)
q.max.y -= h * (tot - p1) / tot;
if (q.max.y < q.min.y + 2) {
if (q.min.y + 2 <= r.max.y)
q.max.y = q.min.y + 2;
else
q.min.y = q.max.y - 2;
}
return q;
}
void
scrlresize(void)
{
freeimage(scrtmp);
scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);
if(scrtmp == nil)
error("scroll alloc");
void scrlresize(void) {
freeimage(scrtmp);
scrtmp = allocimage(
display,
Rect(0, 0, 32, screen->r.max.y),
screen->chan,
0,
DNofill);
if (scrtmp == nil)
error("scroll alloc");
}
void
textscrdraw(Text *t)
{
Rectangle r, r1, r2;
Image *b;
void textscrdraw(Text* t) {
Rectangle r, r1, r2;
Image* b;
if(t->w==nil || t!=&t->w->body)
return;
if(scrtmp == nil)
scrlresize();
r = t->scrollr;
b = scrtmp;
r1 = r;
r1.min.x = 0;
r1.max.x = Dx(r);
r2 = scrpos(r1, t->org, t->org+t->fr.nchars, t->file->b.nc);
if(!eqrect(r2, t->lastsr)){
t->lastsr = r2;
draw(b, r1, t->fr.cols[BORD], nil, ZP);
draw(b, r2, t->fr.cols[BACK], nil, ZP);
r2.min.x = r2.max.x-1;
draw(b, r2, t->fr.cols[BORD], nil, ZP);
draw(t->fr.b, r, b, nil, Pt(0, r1.min.y));
/*flushimage(display, 1); // BUG? */
}
if (t->w == nil || t != &t->w->body)
return;
if (scrtmp == nil)
scrlresize();
r = t->scrollr;
b = scrtmp;
r1 = r;
r1.min.x = 0;
r1.max.x = Dx(r);
r2 = scrpos(r1, t->org, t->org + t->fr.nchars, t->file->b.nc);
if (!eqrect(r2, t->lastsr)) {
t->lastsr = r2;
draw(b, r1, t->fr.cols[BORD], nil, ZP);
draw(b, r2, t->fr.cols[BACK], nil, ZP);
r2.min.x = r2.max.x - 1;
draw(b, r2, t->fr.cols[BORD], nil, ZP);
draw(t->fr.b, r, b, nil, Pt(0, r1.min.y));
/*flushimage(display, 1); // BUG? */
}
}
void
scrsleep(uint dt)
{
Timer *timer;
static Alt alts[3];
void scrsleep(uint dt) {
Timer* timer;
static Alt alts[3];
timer = timerstart(dt);
alts[0].c = timer->c;
alts[0].v = nil;
alts[0].op = CHANRCV;
alts[1].c = mousectl->c;
alts[1].v = &mousectl->m;
alts[1].op = CHANRCV;
alts[2].op = CHANEND;
for(;;)
switch(alt(alts)){
case 0:
timerstop(timer);
return;
case 1:
timercancel(timer);
return;
}
timer = timerstart(dt);
alts[0].c = timer->c;
alts[0].v = nil;
alts[0].op = CHANRCV;
alts[1].c = mousectl->c;
alts[1].v = &mousectl->m;
alts[1].op = CHANRCV;
alts[2].op = CHANEND;
for (;;)
switch (alt(alts)) {
case 0:
timerstop(timer);
return;
case 1:
timercancel(timer);
return;
}
}
void
textscroll(Text *t, int but)
{
uint p0, oldp0;
Rectangle s;
int x, y, my, h, first;
void textscroll(Text* t, int but) {
uint p0, oldp0;
Rectangle s;
int x, y, my, h, first;
s = insetrect(t->scrollr, 1);
h = s.max.y-s.min.y;
x = (s.min.x+s.max.x)/2;
oldp0 = ~0;
first = TRUE;
do{
flushimage(display, 1);
my = mouse->xy.y;
if(my < s.min.y)
my = s.min.y;
if(my >= s.max.y)
my = s.max.y;
if(!eqpt(mouse->xy, Pt(x, my))){
moveto(mousectl, Pt(x, my));
readmouse(mousectl); /* absorb event generated by moveto() */
}
if(but == 2){
y = my;
p0 = (vlong)t->file->b.nc*(y-s.min.y)/h;
if(p0 >= t->q1)
p0 = textbacknl(t, p0, 2);
if(oldp0 != p0)
textsetorigin(t, p0, FALSE);
oldp0 = p0;
readmouse(mousectl);
continue;
}
if(but == 1)
p0 = textbacknl(t, t->org, (my-s.min.y)/t->fr.font->height);
else
p0 = t->org+frcharofpt(&t->fr, Pt(s.max.x, my));
if(oldp0 != p0)
textsetorigin(t, p0, TRUE);
oldp0 = p0;
/* debounce */
if(first){
flushimage(display, 1);
sleep(200);
nbrecv(mousectl->c, &mousectl->m);
first = FALSE;
}
scrsleep(80);
}while(mouse->buttons & (1<<(but-1)));
while(mouse->buttons)
readmouse(mousectl);
s = insetrect(t->scrollr, 1);
h = s.max.y - s.min.y;
x = (s.min.x + s.max.x) / 2;
oldp0 = ~0;
first = TRUE;
do {
flushimage(display, 1);
my = mouse->xy.y;
if (my < s.min.y)
my = s.min.y;
if (my >= s.max.y)
my = s.max.y;
if (!eqpt(mouse->xy, Pt(x, my))) {
moveto(mousectl, Pt(x, my));
readmouse(mousectl); /* absorb event generated by moveto() */
}
if (but == 2) {
y = my;
p0 = (vlong)t->file->b.nc * (y - s.min.y) / h;
if (p0 >= t->q1)
p0 = textbacknl(t, p0, 2);
if (oldp0 != p0)
textsetorigin(t, p0, FALSE);
oldp0 = p0;
readmouse(mousectl);
continue;
}
if (but == 1)
p0 = textbacknl(t, t->org, (my - s.min.y) / t->fr.font->height);
else
p0 = t->org + frcharofpt(&t->fr, Pt(s.max.x, my));
if (oldp0 != p0)
textsetorigin(t, p0, TRUE);
oldp0 = p0;
/* debounce */
if (first) {
flushimage(display, 1);
sleep(200);
nbrecv(mousectl->c, &mousectl->m);
first = FALSE;
}
scrsleep(80);
} while (mouse->buttons & (1 << (but - 1)));
while (mouse->buttons)
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 "fns.h"
static Channel* ctimer; /* chan(Timer*)[100] */
static Timer *timer;
static Channel* ctimer; /* chan(Timer*)[100] */
static Timer* timer;
static
uint
msec(void)
{
return nsec()/1000000;
static uint msec(void) { return nsec() / 1000000; }
void timerstop(Timer* t) {
t->next = timer;
timer = t;
}
void
timerstop(Timer *t)
{
t->next = timer;
timer = t;
void timercancel(Timer* t) { t->cancel = TRUE; }
static void timerproc(void* v) {
int i, nt, na, dt, del;
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
timercancel(Timer *t)
{
t->cancel = TRUE;
void timerinit(void) {
ctimer = chancreate(sizeof(Timer*), 100);
chansetname(ctimer, "ctimer");
proccreate(timerproc, nil, STACK);
}
static
void
timerproc(void *v)
{
int i, nt, na, dt, del;
Timer **t, *x;
uint old, new;
Timer* timerstart(int dt) {
Timer* t;
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
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;
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 "fns.h"
static Point prevmouse;
static Window *mousew;
static Point prevmouse;
static Window* mousew;
Range
range(int q0, int q1)
{
Range r;
Range range(int q0, int q1) {
Range r;
r.q0 = q0;
r.q1 = q1;
return r;
r.q0 = q0;
r.q1 = q1;
return r;
}
Runestr
runestr(Rune *r, uint n)
{
Runestr rs;
Runestr runestr(Rune* r, uint n) {
Runestr rs;
rs.r = r;
rs.nr = n;
return rs;
rs.r = r;
rs.nr = n;
return rs;
}
void
cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
{
uchar *q;
Rune *s;
int j, w;
void cvttorunes(char* p, int n, Rune* r, int* nb, int* nr, int* nulls) {
uchar* q;
Rune* s;
int j, w;
/*
* Always guaranteed that n bytes may be interpreted
* without worrying about partial runes. This may mean
* reading up to UTFmax-1 more bytes than n; the caller
* knows this. If n is a firm limit, the caller should
* set p[n] = 0.
*/
q = (uchar*)p;
s = r;
for(j=0; j<n; j+=w){
if(*q < Runeself){
w = 1;
*s = *q++;
}else{
w = chartorune(s, (char*)q);
q += w;
}
if(*s)
s++;
else if(nulls)
*nulls = TRUE;
}
*nb = (char*)q-p;
*nr = s-r;
/*
* Always guaranteed that n bytes may be interpreted
* without worrying about partial runes. This may mean
* reading up to UTFmax-1 more bytes than n; the caller
* knows this. If n is a firm limit, the caller should
* set p[n] = 0.
*/
q = (uchar*)p;
s = r;
for (j = 0; j < n; j += w) {
if (*q < Runeself) {
w = 1;
*s = *q++;
} else {
w = chartorune(s, (char*)q);
q += w;
}
if (*s)
s++;
else if (nulls)
*nulls = TRUE;
}
*nb = (char*)q - p;
*nr = s - r;
}
void
error(char *s)
{
fprint(2, "acme: %s: %r\n", s);
threadexitsall(nil);
void error(char* s) {
fprint(2, "acme: %s: %r\n", s);
threadexitsall(nil);
}
Window*
errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
{
Window *w;
Rune *r;
int i, n;
static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
Window* errorwin1(Rune* dir, int ndir, Rune** incl, int nincl) {
Window* w;
Rune* r;
int i, n;
static Rune Lpluserrors[] = {'+', 'E', 'r', 'r', 'o', 'r', 's', 0};
r = runemalloc(ndir+8);
if((n = ndir) != 0){
runemove(r, dir, ndir);
r[n++] = L'/';
}
runemove(r+n, Lpluserrors, 7);
n += 7;
w = lookfile(r, n);
if(w == nil){
if(row.ncol == 0)
if(rowadd(&row, nil, -1) == nil)
error("can't create column to make error window");
w = coladd(row.col[row.ncol-1], nil, nil, -1);
w->filemenu = FALSE;
winsetname(w, r, n);
xfidlog(w, "new");
}
free(r);
for(i=nincl; --i>=0; ){
n = runestrlen(incl[i]);
r = runemalloc(n);
runemove(r, incl[i], n);
winaddincl(w, r, n);
}
for(i=0; i<NINDENT; i++)
w->indent[i] = globalindent[i];
return w;
r = runemalloc(ndir + 8);
if ((n = ndir) != 0) {
runemove(r, dir, ndir);
r[n++] = L'/';
}
runemove(r + n, Lpluserrors, 7);
n += 7;
w = lookfile(r, n);
if (w == nil) {
if (row.ncol == 0)
if (rowadd(&row, nil, -1) == nil)
error("can't create column to make error window");
w = coladd(row.col[row.ncol - 1], nil, nil, -1);
w->filemenu = FALSE;
winsetname(w, r, n);
xfidlog(w, "new");
}
free(r);
for (i = nincl; --i >= 0;) {
n = runestrlen(incl[i]);
r = runemalloc(n);
runemove(r, incl[i], n);
winaddincl(w, r, n);
}
for (i = 0; i < NINDENT; i++)
w->indent[i] = globalindent[i];
return w;
}
/* make new window, if necessary; return with it locked */
Window*
errorwin(Mntdir *md, int owner)
{
Window *w;
Window* errorwin(Mntdir* md, int owner) {
Window* w;
for(;;){
if(md == nil)
w = errorwin1(nil, 0, nil, 0);
else
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
winlock(w, owner);
if(w->col != nil)
break;
/* window was deleted too fast */
winunlock(w);
}
return w;
for (;;) {
if (md == nil)
w = errorwin1(nil, 0, nil, 0);
else
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
winlock(w, owner);
if (w->col != nil)
break;
/* window was deleted too fast */
winunlock(w);
}
return w;
}
/*
@ -137,360 +125,315 @@ errorwin(Mntdir *md, int owner)
* It will be unlocked and returned window
* will be locked in its place.
*/
Window*
errorwinforwin(Window *w)
{
int i, n, nincl, owner;
Rune **incl;
Runestr dir;
Text *t;
Window* errorwinforwin(Window* w) {
int i, n, nincl, owner;
Rune** incl;
Runestr dir;
Text* t;
t = &w->body;
dir = dirname(t, nil, 0);
if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
free(dir.r);
dir.r = nil;
dir.nr = 0;
}
incl = nil;
nincl = w->nincl;
if(nincl > 0){
incl = emalloc(nincl*sizeof(Rune*));
for(i=0; i<nincl; i++){
n = runestrlen(w->incl[i]);
incl[i] = runemalloc(n+1);
runemove(incl[i], w->incl[i], n);
}
}
owner = w->owner;
winunlock(w);
for(;;){
w = errorwin1(dir.r, dir.nr, incl, nincl);
winlock(w, owner);
if(w->col != nil)
break;
/* window deleted too fast */
winunlock(w);
}
return w;
t = &w->body;
dir = dirname(t, nil, 0);
if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */
free(dir.r);
dir.r = nil;
dir.nr = 0;
}
incl = nil;
nincl = w->nincl;
if (nincl > 0) {
incl = emalloc(nincl * sizeof(Rune*));
for (i = 0; i < nincl; i++) {
n = runestrlen(w->incl[i]);
incl[i] = runemalloc(n + 1);
runemove(incl[i], w->incl[i], n);
}
}
owner = w->owner;
winunlock(w);
for (;;) {
w = errorwin1(dir.r, dir.nr, incl, nincl);
winlock(w, owner);
if (w->col != nil)
break;
/* window deleted too fast */
winunlock(w);
}
return w;
}
typedef struct Warning Warning;
struct Warning{
Mntdir *md;
Buffer buf;
Warning *next;
struct Warning {
Mntdir* md;
Buffer buf;
Warning* next;
};
static Warning *warnings;
static Warning* warnings;
static
void
addwarningtext(Mntdir *md, Rune *r, int nr)
{
Warning *warn;
static void addwarningtext(Mntdir* md, Rune* r, int nr) {
Warning* warn;
for(warn = warnings; warn; warn=warn->next){
if(warn->md == md){
bufinsert(&warn->buf, warn->buf.nc, r, nr);
return;
}
}
warn = emalloc(sizeof(Warning));
warn->next = warnings;
warn->md = md;
if(md)
fsysincid(md);
warnings = warn;
bufinsert(&warn->buf, 0, r, nr);
nbsendp(cwarn, 0);
for (warn = warnings; warn; warn = warn->next) {
if (warn->md == md) {
bufinsert(&warn->buf, warn->buf.nc, r, nr);
return;
}
}
warn = emalloc(sizeof(Warning));
warn->next = warnings;
warn->md = md;
if (md)
fsysincid(md);
warnings = warn;
bufinsert(&warn->buf, 0, r, nr);
nbsendp(cwarn, 0);
}
/* called while row is locked */
void
flushwarnings(void)
{
Warning *warn, *next;
Window *w;
Text *t;
int owner, nr, q0, n;
Rune *r;
void flushwarnings(void) {
Warning *warn, *next;
Window* w;
Text* t;
int owner, nr, q0, n;
Rune* r;
for(warn=warnings; warn; warn=next) {
w = errorwin(warn->md, 'E');
t = &w->body;
owner = w->owner;
if(owner == 0)
w->owner = 'E';
wincommit(w, t);
/*
* Most commands don't generate much output. For instance,
* Edit ,>cat goes through /dev/cons and is already in blocks
* 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
* this in blocks (and putting the text in a buffer in the first
* place), to avoid a big memory footprint.
*/
r = fbufalloc();
q0 = t->file->b.nc;
for(n = 0; n < warn->buf.nc; n += nr){
nr = warn->buf.nc - n;
if(nr > RBUFSIZE)
nr = RBUFSIZE;
bufread(&warn->buf, n, r, nr);
textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
}
textshow(t, q0, t->file->b.nc, 1);
free(r);
winsettag(t->w);
textscrdraw(t);
w->owner = owner;
w->dirty = FALSE;
winunlock(w);
bufclose(&warn->buf);
next = warn->next;
if(warn->md)
fsysdelid(warn->md);
free(warn);
}
warnings = nil;
for (warn = warnings; warn; warn = next) {
w = errorwin(warn->md, 'E');
t = &w->body;
owner = w->owner;
if (owner == 0)
w->owner = 'E';
wincommit(w, t);
/*
* Most commands don't generate much output. For instance,
* Edit ,>cat goes through /dev/cons and is already in blocks
* 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
* this in blocks (and putting the text in a buffer in the first
* place), to avoid a big memory footprint.
*/
r = fbufalloc();
q0 = t->file->b.nc;
for (n = 0; n < warn->buf.nc; n += nr) {
nr = warn->buf.nc - n;
if (nr > RBUFSIZE)
nr = RBUFSIZE;
bufread(&warn->buf, n, r, nr);
textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
}
textshow(t, q0, t->file->b.nc, 1);
free(r);
winsettag(t->w);
textscrdraw(t);
w->owner = owner;
w->dirty = FALSE;
winunlock(w);
bufclose(&warn->buf);
next = warn->next;
if (warn->md)
fsysdelid(warn->md);
free(warn);
}
warnings = nil;
}
void
warning(Mntdir *md, char *s, ...)
{
Rune *r;
va_list arg;
void warning(Mntdir* md, char* s, ...) {
Rune* r;
va_list arg;
va_start(arg, s);
r = runevsmprint(s, arg);
va_end(arg);
if(r == nil)
error("runevsmprint failed");
addwarningtext(md, r, runestrlen(r));
free(r);
va_start(arg, s);
r = runevsmprint(s, arg);
va_end(arg);
if (r == nil)
error("runevsmprint failed");
addwarningtext(md, r, runestrlen(r));
free(r);
}
int
runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
{
if(n1 != n2)
return FALSE;
return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
int runeeq(Rune* s1, uint n1, Rune* s2, uint n2) {
if (n1 != n2)
return FALSE;
return memcmp(s1, s2, n1 * sizeof(Rune)) == 0;
}
uint
min(uint a, uint b)
{
if(a < b)
return a;
return b;
uint min(uint a, uint b) {
if (a < b)
return a;
return b;
}
uint
max(uint a, uint b)
{
if(a > b)
return a;
return b;
uint max(uint a, uint b) {
if (a > b)
return a;
return b;
}
char*
runetobyte(Rune *r, int n)
{
char *s;
char* runetobyte(Rune* r, int n) {
char* s;
if(r == nil)
return nil;
s = emalloc(n*UTFmax+1);
setmalloctag(s, getcallerpc(&r));
snprint(s, n*UTFmax+1, "%.*S", n, r);
return s;
if (r == nil)
return nil;
s = emalloc(n * UTFmax + 1);
setmalloctag(s, getcallerpc(&r));
snprint(s, n * UTFmax + 1, "%.*S", n, r);
return s;
}
Rune*
bytetorune(char *s, int *ip)
{
Rune *r;
int nb, nr;
Rune* bytetorune(char* s, int* ip) {
Rune* r;
int nb, nr;
nb = strlen(s);
r = runemalloc(nb+1);
cvttorunes(s, nb, r, &nb, &nr, nil);
r[nr] = '\0';
*ip = nr;
return r;
nb = strlen(s);
r = runemalloc(nb + 1);
cvttorunes(s, nb, r, &nb, &nr, nil);
r[nr] = '\0';
*ip = nr;
return r;
}
int
isalnum(Rune c)
{
/*
* Hard to get absolutely right. Use what we know about ASCII
* and assume anything above the Latin control characters is
* potentially an alphanumeric.
*/
if(c <= ' ')
return FALSE;
if(0x7F<=c && c<=0xA0)
return FALSE;
if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
return FALSE;
return TRUE;
int isalnum(Rune c) {
/*
* Hard to get absolutely right. Use what we know about ASCII
* and assume anything above the Latin control characters is
* potentially an alphanumeric.
*/
if (c <= ' ')
return FALSE;
if (0x7F <= c && c <= 0xA0)
return FALSE;
if (utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
return FALSE;
return TRUE;
}
int
rgetc(void *v, uint n)
{
return ((Rune*)v)[n];
int rgetc(void* v, uint n) { return ((Rune*)v)[n]; }
int tgetc(void* a, uint n) {
Text* t;
t = a;
if (n >= t->file->b.nc)
return 0;
return textreadc(t, n);
}
int
tgetc(void *a, uint n)
{
Text *t;
t = a;
if(n >= t->file->b.nc)
return 0;
return textreadc(t, n);
Rune* skipbl(Rune* r, int n, int* np) {
while (n > 0 && (*r == ' ' || *r == '\t' || *r == '\n')) {
--n;
r++;
}
*np = n;
return r;
}
Rune*
skipbl(Rune *r, int n, int *np)
{
while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
--n;
r++;
}
*np = n;
return r;
Rune* findbl(Rune* r, int n, int* np) {
while (n > 0 && *r != ' ' && *r != '\t' && *r != '\n') {
--n;
r++;
}
*np = n;
return r;
}
Rune*
findbl(Rune *r, int n, int *np)
{
while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
--n;
r++;
}
*np = n;
return r;
void savemouse(Window* w) {
prevmouse = mouse->xy;
mousew = w;
}
void
savemouse(Window *w)
{
prevmouse = mouse->xy;
mousew = w;
int restoremouse(Window* w) {
int did;
did = 0;
if (mousew != nil && mousew == w) {
moveto(mousectl, prevmouse);
did = 1;
}
mousew = nil;
return did;
}
int
restoremouse(Window *w)
{
int did;
void clearmouse() { mousew = nil; }
did = 0;
if(mousew!=nil && mousew==w) {
moveto(mousectl, prevmouse);
did = 1;
}
mousew = nil;
return did;
char* estrdup(char* s) {
char* t;
t = strdup(s);
if (t == nil)
error("strdup failed");
setmalloctag(t, getcallerpc(&s));
return t;
}
void
clearmouse()
{
mousew = nil;
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;
}
char*
estrdup(char *s)
{
char *t;
t = strdup(s);
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;
void* erealloc(void* p, uint n) {
p = realloc(p, n);
if (p == nil)
error("realloc failed");
setmalloctag(p, getcallerpc(&n));
return p;
}
/*
* Heuristic city.
*/
Window*
makenewwindow(Text *t)
{
Column *c;
Window *w, *bigw, *emptyw;
Text *emptyb;
int i, y, el;
Window* makenewwindow(Text* t) {
Column* c;
Window *w, *bigw, *emptyw;
Text* emptyb;
int i, y, el;
if(activecol)
c = activecol;
else if(seltext && seltext->col)
c = seltext->col;
else if(t && t->col)
c = t->col;
else{
if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
error("can't make column");
c = row.col[row.ncol-1];
}
activecol = c;
if(t==nil || t->w==nil || c->nw==0)
return coladd(c, nil, nil, -1);
if (activecol)
c = activecol;
else if (seltext && seltext->col)
c = seltext->col;
else if (t && t->col)
c = t->col;
else {
if (row.ncol == 0 && rowadd(&row, nil, -1) == nil)
error("can't make column");
c = row.col[row.ncol - 1];
}
activecol = c;
if (t == nil || t->w == nil || c->nw == 0)
return coladd(c, nil, nil, -1);
/* find biggest window and biggest blank spot */
emptyw = c->w[0];
bigw = emptyw;
for(i=1; i<c->nw; i++){
w = c->w[i];
/* use >= to choose one near bottom of screen */
if(w->body.fr.maxlines >= bigw->body.fr.maxlines)
bigw = w;
if(w->body.fr.maxlines-w->body.fr.nlines >= emptyw->body.fr.maxlines-emptyw->body.fr.nlines)
emptyw = w;
}
emptyb = &emptyw->body;
el = emptyb->fr.maxlines-emptyb->fr.nlines;
/* if empty space is big, use it */
if(el>15 || (el>3 && el>(bigw->body.fr.maxlines-1)/2))
y = emptyb->fr.r.min.y+emptyb->fr.nlines*font->height;
else{
/* if this window is in column and isn't much smaller, split it */
if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
bigw = t->w;
y = (bigw->r.min.y + bigw->r.max.y)/2;
}
w = coladd(c, nil, nil, y);
if(w->body.fr.maxlines < 2)
colgrow(w->col, w, 1);
return w;
/* find biggest window and biggest blank spot */
emptyw = c->w[0];
bigw = emptyw;
for (i = 1; i < c->nw; i++) {
w = c->w[i];
/* use >= to choose one near bottom of screen */
if (w->body.fr.maxlines >= bigw->body.fr.maxlines)
bigw = w;
if (
w->body.fr.maxlines - w->body.fr.nlines >=
emptyw->body.fr.maxlines - emptyw->body.fr.nlines)
emptyw = w;
}
emptyb = &emptyw->body;
el = emptyb->fr.maxlines - emptyb->fr.nlines;
/* if empty space is big, use it */
if (el > 15 || (el > 3 && el > (bigw->body.fr.maxlines - 1) / 2))
y = emptyb->fr.r.min.y + emptyb->fr.nlines * font->height;
else {
/* if this window is in column and isn't much smaller, split it */
if (t->col == c && Dy(t->w->r) > 2 * Dy(bigw->r) / 3)
bigw = t->w;
y = (bigw->r.min.y + bigw->r.max.y) / 2;
}
w = coladd(c, nil, nil, y);
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