aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/acme/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/acme/util.c')
-rw-r--r--src/cmd/acme/util.c130
1 files changed, 84 insertions, 46 deletions
diff --git a/src/cmd/acme/util.c b/src/cmd/acme/util.c
index 8e3cfa29..180b2bd2 100644
--- a/src/cmd/acme/util.c
+++ b/src/cmd/acme/util.c
@@ -62,9 +62,11 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
int i, n;
static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
- r = runemalloc(ndir+7);
- if(n = ndir) /* assign = */
+ r = runemalloc(ndir+8);
+ if(n = ndir){ /* assign = */
runemove(r, dir, ndir);
+ r[n++] = L'/';
+ }
runemove(r+n, Lpluserrors, 7);
n += 7;
w = lookfile(r, n);
@@ -83,12 +85,13 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
runemove(r, incl[i], n);
winaddincl(w, r, n);
}
+ w->autoindent = globalautoindent;
return w;
}
/* make new window, if necessary; return with it locked */
Window*
-errorwin(Mntdir *md, int owner, Window *e)
+errorwin(Mntdir *md, int owner)
{
Window *w;
@@ -97,51 +100,100 @@ errorwin(Mntdir *md, int owner, Window *e)
w = errorwin1(nil, 0, nil, 0);
else
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
- if(w != e)
- winlock(w, owner);
+ winlock(w, owner);
if(w->col != nil)
break;
/* window was deleted too fast */
- if(w != e)
- winunlock(w);
+ winunlock(w);
}
return w;
}
-static void
-printwarning(Window *ew, Mntdir *md, Rune *r)
+typedef struct Warning Warning;
+
+struct Warning{
+ Mntdir *md;
+ Buffer buf;
+ Warning *next;
+};
+
+static Warning *warnings;
+
+static
+void
+addwarningtext(Mntdir *md, Rune *r, int nr)
{
- int nr, q0, owner;
+ 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;
+ warnings = warn;
+ bufinsert(&warn->buf, 0, r, nr);
+}
+
+void
+flushwarnings(int dolock)
+{
+ Warning *warn, *next;
Window *w;
Text *t;
+ int owner, nr, q0, n;
+ Rune *r;
- if(r == nil)
- error("runevsmprint failed");
- nr = runestrlen(r);
-
+ if(dolock)
+ qlock(&row.lk);
if(row.ncol == 0){ /* really early error */
rowinit(&row, screen->clipr);
rowadd(&row, nil, -1);
rowadd(&row, nil, -1);
if(row.ncol == 0)
- error("initializing columns in warning()");
+ error("initializing columns in flushwarnings()");
}
- w = errorwin(md, 'E', ew);
- t = &w->body;
- owner = w->owner;
- if(owner == 0)
- w->owner = 'E';
- wincommit(w, t);
- q0 = textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
- textshow(t, q0, q0+nr, 1);
- winsettag(t->w);
- textscrdraw(t);
- w->owner = owner;
- w->dirty = FALSE;
- if(ew != w)
+ 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);
- free(r);
+ bufclose(&warn->buf);
+ next = warn->next;
+ free(warn);
+ }
+ warnings = nil;
+ if(dolock)
+ qunlock(&row.lk);
}
void
@@ -153,23 +205,9 @@ warning(Mntdir *md, char *s, ...)
va_start(arg, s);
r = runevsmprint(s, arg);
va_end(arg);
- printwarning(nil, md, r);
-}
-
-/*
- * Warningew is like warning but avoids locking the error window
- * if it's already locked by checking that ew!=error window.
- */
-void
-warningew(Window *ew, Mntdir *md, char *s, ...)
-{
- Rune *r;
- va_list arg;
-
- va_start(arg, s);
- r = runevsmprint(s, arg);
- va_end(arg);
- printwarning(ew, md, r);
+ if(r == nil)
+ error("runevsmprint failed");
+ addwarningtext(md, r, runestrlen(r));
}
int