aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-02-09 19:32:18 +0000
committerrsc <devnull@localhost>2004-02-09 19:32:18 +0000
commitc1973705501d05e906bd14a0dc25cc4472b5871f (patch)
tree590c9c5345fff217d62df2d6922c0e36be5b0e13
parent97fdda4e861f7f66c707d32443f3d8461594b9a5 (diff)
downloadplan9port-c1973705501d05e906bd14a0dc25cc4472b5871f.tar.gz
plan9port-c1973705501d05e906bd14a0dc25cc4472b5871f.tar.bz2
plan9port-c1973705501d05e906bd14a0dc25cc4472b5871f.zip
completion, pageup/pagedown
-rw-r--r--src/cmd/acme/acme.c2
-rw-r--r--src/cmd/acme/cols.c1
-rw-r--r--src/cmd/acme/mkfile2
-rw-r--r--src/cmd/acme/text.c136
-rw-r--r--src/cmd/acme/wind.c5
5 files changed, 139 insertions, 7 deletions
diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c
index d9412c4e..0ac66e12 100644
--- a/src/cmd/acme/acme.c
+++ b/src/cmd/acme/acme.c
@@ -138,6 +138,7 @@ threadmain(int argc, char *argv[])
d = display;
font = d->defaultfont;
+//assert(font);
reffont.f = font;
reffonts[0] = &reffont;
@@ -790,6 +791,7 @@ rfget(int fix, int save, int setfont, char *name)
}
f = openfont(display, name);
if(f == nil){
+ fprint(2, "can't open font file %s: %r\n", name);
warning(nil, "can't open font file %s: %r\n", name);
return nil;
}
diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c
index 0e6ff409..14a715b3 100644
--- a/src/cmd/acme/cols.c
+++ b/src/cmd/acme/cols.c
@@ -102,6 +102,7 @@ coladd(Column *c, Window *w, Window *clone, int y)
w->col = c;
winresize(w, r, FALSE);
}
+//assert(w->body.w == w);
w->tag.col = c;
w->tag.row = c->row;
w->body.col = c;
diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile
index f92f903a..cb72fea0 100644
--- a/src/cmd/acme/mkfile
+++ b/src/cmd/acme/mkfile
@@ -36,6 +36,6 @@ UPDATE=\
<$PLAN9/src/mkone
-LDFLAGS=$LDFLAGS -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
+LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
edit.$O ecmd.$O elog.$O: edit.h
diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
index c38773ea..0b9f7cc6 100644
--- a/src/cmd/acme/text.c
+++ b/src/cmd/acme/text.c
@@ -8,11 +8,13 @@
#include <frame.h>
#include <fcall.h>
#include <plumb.h>
+#include <complete.h>
#include "dat.h"
#include "fns.h"
Image *tagcols[NCOL];
Image *textcols[NCOL];
+static Rune Ldot[] = { '.', 0 };
enum{
TABDIR = 3 /* width of tabs in directory windows */
@@ -526,24 +528,136 @@ textbswidth(Text *t, Rune c)
return t->q0-q;
}
+int
+textfilewidth(Text *t, uint q0, int oneelement)
+{
+ uint q;
+ Rune r;
+
+ q = q0;
+ while(q > 0){
+ r = textreadc(t, q-1);
+ if(r<=' ')
+ break;
+ if(oneelement && r=='/')
+ break;
+ --q;
+ }
+ return q0-q;
+}
+
+Rune*
+textcomplete(Text *t)
+{
+ int i, nstr, npath;
+ uint q;
+ Rune tmp[200];
+ Rune *str, *path;
+ Rune *rp;
+ Completion *c;
+ char *s, *dirs;
+ Runestr dir;
+
+ /* control-f: filename completion; works back to white space or / */
+ if(t->q0<t->file->b.nc && textreadc(t, t->q0)>' ') /* must be at end of word */
+ return nil;
+ nstr = textfilewidth(t, t->q0, TRUE);
+ str = runemalloc(nstr);
+ npath = textfilewidth(t, t->q0-nstr, FALSE);
+ path = runemalloc(npath);
+
+ c = nil;
+ rp = nil;
+ dirs = nil;
+
+ q = t->q0-nstr;
+ for(i=0; i<nstr; i++)
+ str[i] = textreadc(t, q++);
+ q = t->q0-nstr-npath;
+ for(i=0; i<npath; i++)
+ path[i] = textreadc(t, q++);
+ /* is path rooted? if not, we need to make it relative to window path */
+ if(npath>0 && path[0]=='/')
+ dir = (Runestr){path, npath};
+ else{
+ dir = dirname(t, nil, 0);
+ if(dir.nr + 1 + npath > nelem(tmp)){
+ free(dir.r);
+ goto Return;
+ }
+ if(dir.nr == 0){
+ dir.nr = 1;
+ dir.r = runestrdup(Ldot);
+ }
+ runemove(tmp, dir.r, dir.nr);
+ tmp[dir.nr] = '/';
+ runemove(tmp+dir.nr+1, path, npath);
+ free(dir.r);
+ dir.r = tmp;
+ dir.nr += 1+npath;
+ dir = cleanrname(dir);
+ }
+
+ s = smprint("%.*S", nstr, str);
+ dirs = smprint("%.*S", dir.nr, dir.r);
+ c = complete(dirs, s);
+ free(s);
+ if(c == nil){
+ warning(nil, "error attempting completion: %r\n");
+ goto Return;
+ }
+
+ if(!c->advance){
+ warning(nil, "%.*S%s%.*S*\n",
+ dir.nr, dir.r,
+ dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
+ nstr, str);
+ for(i=0; i<c->nfile; i++)
+ warning(nil, " %s\n", c->filename[i]);
+ }
+
+ if(c->advance)
+ rp = runesmprint("%s", c->string);
+ else
+ rp = nil;
+ Return:
+ freecompletion(c);
+ free(dirs);
+ free(str);
+ free(path);
+ return rp;
+}
+
void
texttype(Text *t, Rune r)
{
uint q0, q1;
int nnb, nb, n, i;
+ int nr;
+ Rune *rp;
Text *u;
if(t->what!=Body && r=='\n')
return;
+ nr = 1;
+ rp = &r;
switch(r){
- case Kdown:
case Kleft:
+ if(t->q0 > 0)
+ textshow(t, t->q0-1, t->q0-1, TRUE);
+ return;
case Kright:
+ if(t->q1 < t->file->b.nc)
+ textshow(t, t->q1+1, t->q1+1, TRUE);
+ return;
+ case Kdown:
+ case Kpgdown:
n = t->fr.maxlines/2;
q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height));
textsetorigin(t, q0, FALSE);
return;
case Kup:
+ case Kpgup:
n = t->fr.maxlines/2;
q0 = textbacknl(t, t->org, n);
textsetorigin(t, q0, FALSE);
@@ -561,6 +675,13 @@ texttype(Text *t, Rune r)
}
textshow(t, t->q0, t->q0, 1);
switch(r){
+ case 0x06: /* ^F: complete */
+ case Kins:
+ rp = textcomplete(t);
+ if(rp == nil)
+ return;
+ nr = runestrlen(rp);
+ break; /* fall through to normal insertion case */
case 0x1B:
if(t->eq0 != ~0)
textsetselect(t, t->eq0, t->q0);
@@ -623,16 +744,19 @@ texttype(Text *t, Rune r)
u->cq0 = t->q0;
else if(t->q0 != u->cq0+u->ncache)
error("text.type cq1");
- textinsert(u, t->q0, &r, 1, FALSE);
+ textinsert(u, t->q0, rp, nr, FALSE);
if(u != t)
textsetselect(u, u->q0, u->q1);
- if(u->ncache == u->ncachealloc){
- u->ncachealloc += 10;
+ if(u->ncache+nr > u->ncachealloc){
+ u->ncachealloc += 10 + nr;
u->cache = runerealloc(u->cache, u->ncachealloc);
}
- u->cache[u->ncache++] = r;
+ runemove(u->cache+u->ncache, rp, nr);
+ u->ncache += nr;
}
- textsetselect(t, t->q0+1, t->q0+1);
+ if(rp != &r)
+ free(rp);
+ textsetselect(t, t->q0+nr, t->q0+nr);
if(r=='\n' && t->w!=nil)
wincommit(t->w, t);
}
diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c
index a9a1c4bf..06a815e9 100644
--- a/src/cmd/acme/wind.c
+++ b/src/cmd/acme/wind.c
@@ -45,6 +45,7 @@ wininit(Window *w, Window *clone, Rectangle r)
filereset(w->tag.file);
textsetselect(&w->tag, nc, nc);
}
+//assert(w->body.w == w);
r1 = r;
r1.min.y += font->height + 1;
if(r1.max.y < r1.min.y)
@@ -57,6 +58,7 @@ wininit(Window *w, Window *clone, Rectangle r)
rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name);
}else
rf = rfget(FALSE, FALSE, FALSE, nil);
+//assert(w->body.w == w);
f = fileaddtext(f, &w->body);
w->body.what = Body;
textinit(&w->body, f, r1, rf, textcols);
@@ -72,6 +74,7 @@ wininit(Window *w, Window *clone, Rectangle r)
draw(screen, br, button, nil, button->r.min);
w->filemenu = TRUE;
w->maxlines = w->body.fr.maxlines;
+//assert(w->body.w == w);
if(clone){
w->dirty = clone->dirty;
textsetselect(&w->body, clone->body.q0, clone->body.q1);
@@ -138,6 +141,7 @@ winlock(Window *w, int owner)
int i;
File *f;
+fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
f = w->body.file;
for(i=0; i<f->ntext; i++)
winlock1(f->text[i]->w, owner);
@@ -149,6 +153,7 @@ winunlock(Window *w)
int i;
File *f;
+fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
f = w->body.file;
for(i=0; i<f->ntext; i++){
w = f->text[i]->w;