diff options
Diffstat (limited to 'src/cmd/acme/look.c')
| -rw-r--r-- | src/cmd/acme/look.c | 185 |
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"); |