aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/acme/look.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/acme/look.c')
-rw-r--r--src/cmd/acme/look.c185
1 files changed, 129 insertions, 56 deletions
diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c
index a7172b50..87bfbcd6 100644
--- a/src/cmd/acme/look.c
+++ b/src/cmd/acme/look.c
@@ -80,7 +80,7 @@ startplumbing(void)
void
-look3(Text *t, uint q0, uint q1, int external)
+look3(Text *t, uint q0, uint q1, int external, int reverse)
{
int n, c, f, expanded;
Text *ct;
@@ -94,7 +94,7 @@ look3(Text *t, uint q0, uint q1, int external)
ct = seltext;
if(ct == nil)
seltext = t;
- expanded = expand(t, q0, q1, &e);
+ expanded = expand(t, q0, q1, &e, reverse);
if(!external && t->w!=nil && t->w->nopen[QWevent]>0){
/* send alphanumeric expansion to external client */
if(expanded == FALSE)
@@ -109,6 +109,8 @@ look3(Text *t, uint q0, uint q1, int external)
c = 'l';
if(t->what == Body)
c = 'L';
+ if(reverse)
+ c += 'R' - 'L';
n = q1-q0;
if(n <= EVENTSIZE){
r = runemalloc(n);
@@ -203,12 +205,17 @@ look3(Text *t, uint q0, uint q1, int external)
ct = &t->w->body;
if(t->w != ct->w)
winlock(ct->w, 'M');
- if(t == ct)
- textsetselect(ct, e.q1, e.q1);
+ if(t == ct) {
+ uint q;
+ q = e.q1;
+ if(reverse)
+ q = e.q0;
+ textsetselect(ct, q, q);
+ }
n = e.q1 - e.q0;
r = runemalloc(n);
bufread(&t->file->b, e.q0, r, n);
- if(search(ct, r, n) && e.jump)
+ if(search(ct, r, n, reverse) && e.jump)
moveto(mousectl, addpt(frptofchar(&ct->fr, ct->fr.p0), Pt(4, ct->fr.font->height-4)));
if(t->w != ct->w)
winunlock(ct->w);
@@ -241,6 +248,7 @@ plumblook(Plumbmsg *m)
warning(nil, "insanely long file name (%d bytes) in plumb message (%.32s...)\n", m->ndata, m->data);
return;
}
+ memset(&e, 0, sizeof e);
e.q0 = 0;
e.q1 = 0;
if(m->data[0] == '\0')
@@ -303,11 +311,11 @@ plumbshow(Plumbmsg *m)
}
int
-search(Text *ct, Rune *r, uint n)
+search(Text *ct, Rune *r, uint n, int reverse)
{
- uint q, nb, maxn;
+ uint nb, maxn;
int around;
- Rune *s, *b, *c;
+ Rune *s, *b;
if(n==0 || n>ct->file->b.nc)
return FALSE;
@@ -321,55 +329,111 @@ search(Text *ct, Rune *r, uint n)
nb = 0;
b[nb] = 0;
around = 0;
- q = ct->q1;
- for(;;){
- if(q >= ct->file->b.nc){
- q = 0;
- around = 1;
- nb = 0;
- b[nb] = 0;
- }
- if(nb > 0){
- c = runestrchr(b, r[0]);
- if(c == nil){
- q += nb;
+ if(reverse){
+ uint q1;
+ q1 = ct->q0; // q1 is (past) end of text being searched.
+ for(;;){
+ if(q1 <= 0){
+ q1 = ct->file->b.nc;
+ around = 1;
nb = 0;
b[nb] = 0;
- if(around && q>=ct->q1)
- break;
- continue;
}
- q += (c-b);
- nb -= (c-b);
- b = c;
- }
- /* reload if buffer covers neither string nor rest of file */
- if(nb<n && nb!=ct->file->b.nc-q){
- nb = ct->file->b.nc-q;
- if(nb >= maxn)
- nb = maxn-1;
- bufread(&ct->file->b, q, s, nb);
- b = s;
- b[nb] = '\0';
+ if(nb > 0){
+ Rune *c;
+ for(c=b+nb; c>b; c--)
+ if(c[-1] == r[n-1])
+ break;
+ if(c == b) {
+ q1 -= nb;
+ nb = 0;
+ b[nb] = 0;
+ if(around && q1 <= 0)
+ break;
+ continue;
+ }
+ q1 -= nb - (c - b);
+ nb = c - b;
+ }
+ /* reload if buffer covers neither string nor beginning of file */
+ if(nb<n && nb!=q1){
+ nb = q1;
+ if(nb >= maxn)
+ nb = maxn-1;
+ bufread(&ct->file->b, q1-nb, s, nb);
+ b = s;
+ b[nb] = '\0';
+ }
+ if(runeeq(b+nb-n, n, r, n)==TRUE){
+ if(ct->w){
+ textshow(ct, q1-n, q1, 1);
+ winsettag(ct->w);
+ }else{
+ ct->q0 = q1-n;
+ ct->q1 = q1;
+ }
+ seltext = ct;
+ fbuffree(s);
+ return TRUE;
+ }
+ q1--;
+ nb--;
+ if(around && q1 <= 0)
+ break;
}
- /* this runeeq is fishy but the null at b[nb] makes it safe */
- if(runeeq(b, n, r, n)==TRUE){
- if(ct->w){
- textshow(ct, q, q+n, 1);
- winsettag(ct->w);
- }else{
- ct->q0 = q;
- ct->q1 = q+n;
+ }else{
+ uint q;
+ q = ct->q1;
+ for(;;){
+ if(q >= ct->file->b.nc){
+ q = 0;
+ around = 1;
+ nb = 0;
+ b[nb] = 0;
}
- seltext = ct;
- fbuffree(s);
- return TRUE;
+ if(nb > 0){
+ Rune *c;
+ c = runestrchr(b, r[0]);
+ if(c == nil){
+ q += nb;
+ nb = 0;
+ b[nb] = 0;
+ if(around && q>=ct->q1)
+ break;
+ continue;
+ }
+ q += (c-b);
+ nb -= (c-b);
+ b = c;
+ }
+ /* reload if buffer covers neither string nor rest of file */
+ if(nb<n && nb!=ct->file->b.nc-q){
+ nb = ct->file->b.nc-q;
+ if(nb >= maxn)
+ nb = maxn-1;
+ bufread(&ct->file->b, q, s, nb);
+ b = s;
+ b[nb] = '\0';
+ }
+ /* this runeeq is fishy but the null at b[nb] makes it safe */
+ if(runeeq(b, n, r, n)==TRUE){
+ if(ct->w){
+ textshow(ct, q, q+n, 1);
+ winsettag(ct->w);
+ }else{
+ ct->q0 = q;
+ ct->q1 = q+n;
+ }
+ seltext = ct;
+ fbuffree(s);
+ return TRUE;
+ }
+ --nb;
+ b++;
+ q++;
+ if(around && q>=ct->q1)
+ break;
}
- --nb;
- b++;
- q++;
- if(around && q>=ct->q1)
- break;
}
fbuffree(s);
return FALSE;
@@ -526,7 +590,7 @@ texthas(Text *t, uint q0, Rune *r)
}
int
-expandfile(Text *t, uint q0, uint q1, Expand *e)
+expandfile(Text *t, uint q0, uint q1, Expand *e, int reverse)
{
int i, n, nname, colon, eval;
uint amin, amax;
@@ -570,6 +634,11 @@ expandfile(Text *t, uint q0, uint q1, Expand *e)
break;
}else
amax = t->file->b.nc;
+ if(colon != q0)
+ reverse = FALSE;
+ }else if(reverse){
+ if(textreadc(t, q0) != ':')
+ reverse = FALSE;
}
amin = amax;
e->q0 = q0;
@@ -643,12 +712,16 @@ expandfile(Text *t, uint q0, uint q1, Expand *e)
}
Isfile:
+ print("isfile reverse=%d colon=%d q0=%d\n", reverse, colon, q0);
e->name = r;
e->nname = nname;
e->u.at = t;
e->a0 = amin+1;
+ e->reverse = reverse;
eval = FALSE;
- address(TRUE, nil, range(-1,-1), range(0,0), t, e->a0, amax, tgetc, &eval, (uint*)&e->a1);
+ // Note: address is repeated in openfile when
+ // expandfile returns to expand returns to look3.
+ address(TRUE, nil, range(-1,-1), range(0,0), t, e->a0, amax, tgetc, &eval, (uint*)&e->a1, e->reverse);
return TRUE;
Isntfile:
@@ -657,7 +730,7 @@ expandfile(Text *t, uint q0, uint q1, Expand *e)
}
int
-expand(Text *t, uint q0, uint q1, Expand *e)
+expand(Text *t, uint q0, uint q1, Expand *e, int reverse)
{
memset(e, 0, sizeof *e);
e->agetc = tgetc;
@@ -670,7 +743,7 @@ expand(Text *t, uint q0, uint q1, Expand *e)
e->jump = FALSE;
}
- if(expandfile(t, q0, q1, e))
+ if(expandfile(t, q0, q1, e, reverse))
return TRUE;
if(q0 == q1){
@@ -806,7 +879,7 @@ openfile(Text *t, Expand *e)
eval = FALSE;
else{
eval = TRUE;
- r = address(TRUE, t, range(-1,-1), range(t->q0, t->q1), e->u.at, e->a0, e->a1, e->agetc, &eval, &dummy);
+ r = address(TRUE, t, range(-1,-1), range(t->q0, t->q1), e->u.at, e->a0, e->a1, e->agetc, &eval, &dummy, e->reverse);
if(r.q0 > r.q1) {
eval = FALSE;
warning(nil, "addresses out of order\n");