diff options
Diffstat (limited to 'pico')
-rw-r--r-- | pico/browse.c | 41 | ||||
-rw-r--r-- | pico/efunc.h | 6 | ||||
-rw-r--r-- | pico/osdep/spell.c | 4 | ||||
-rw-r--r-- | pico/search.c | 238 |
4 files changed, 233 insertions, 56 deletions
diff --git a/pico/browse.c b/pico/browse.c index a34f6d4b..1c171db9 100644 --- a/pico/browse.c +++ b/pico/browse.c @@ -71,6 +71,7 @@ struct fcell { */ static struct bmaster { struct fcell *head; /* first cell in list */ + struct fcell *bottom; /* last cell in list */ struct fcell *top; /* cell in top left */ struct fcell *current; /* currently selected */ int longest; /* longest file name (in screen width) */ @@ -98,7 +99,7 @@ void percdircells(struct bmaster *); int PlaceCell(struct bmaster *, struct fcell *, int *, int *); void zotfcells(struct fcell *); void zotmaster(struct bmaster **); -struct fcell *FindCell(struct bmaster *, char *); +struct fcell *FindCell(struct bmaster *, char *, int); int sisin(char *, char *); void p_chdir(struct bmaster *); void BrowserAnchor(char *); @@ -316,6 +317,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, UCS c, new_c; int status, i, j; int row, col, crow, ccol; + int bsearch; /* search forward by default */ char *p, *envp, child[NLINE], tmp[NLINE]; struct bmaster *mp; struct fcell *tp; @@ -344,7 +346,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, tp = NULL; if(fn && *fn){ - if((tp = FindCell(gmp, fn)) != NULL){ + if((tp = FindCell(gmp, fn, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -904,12 +906,15 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, if(tp == gmp->head) gmp->head = tp->next; + if(tp == gmp->bottom) + gmp->bottom = tp->prev; + tp->fname = NULL; tp->next = tp->prev = NULL; if(tp != gmp->current) free((char *) tp); - if((tp = FindCell(gmp, gmp->current->fname)) != NULL){ + if((tp = FindCell(gmp, gmp->current->fname, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -1140,7 +1145,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, zotmaster(&gmp); gmp = mp; - if((tp = FindCell(gmp, child)) != NULL){ + if((tp = FindCell(gmp, child, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -1267,7 +1272,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, zotmaster(&gmp); gmp = mp; - if((tp = FindCell(gmp, child)) != NULL){ + if((tp = FindCell(gmp, child, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -1376,7 +1381,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, zotmaster(&gmp); gmp = mp; - if((tp = FindCell(gmp, ++p)) != NULL){ + if((tp = FindCell(gmp, ++p, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -1488,7 +1493,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, tp = NULL; if(*child){ - if((tp = FindCell(gmp, child)) != NULL){ + if((tp = FindCell(gmp, child, 0)) != NULL){ gmp->current = tp; PlaceCell(gmp, gmp->current, &row, &col); } @@ -1592,11 +1597,11 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, case 'w': /* Where is */ case 'W': case (CTRL|'W'): - i = 0; + bsearch = i = 0; while(!i){ - switch(readpattern(_("File name to find"), FALSE)){ + switch(readpattern(_("File name to find"), FALSE, bsearch)){ case HELPCH: emlwrite(_("\007No help yet!"), NULL); /* remove break and sleep after help text is installed */ @@ -1605,6 +1610,9 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, case (CTRL|'L'): PaintBrowser(gmp, 0, &crow, &ccol); break; + case (CTRL|'P'): + bsearch = ++bsearch % 2; + break; case (CTRL|'Y'): /* first first cell */ for(tp = gmp->top; tp->prev; tp = tp->prev) ; @@ -1665,7 +1673,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen, if(pat && pat[0]) utf8 = ucs4_to_utf8_cpystr(pat); - if(utf8 && (tp = FindCell(gmp, utf8)) != NULL){ + if(utf8 && (tp = FindCell(gmp, utf8, bsearch)) != NULL){ PlaceCell(gmp, gmp->current, &row, &col); PaintCell(row, col, gmp->cpf, gmp->current, 0); gmp->current = tp; @@ -1772,7 +1780,7 @@ getfcells(char *dname, int fb_flags) mp->dname[sizeof(mp->dname)-1] = '\0'; } - mp->head = mp->top = NULL; + mp->bottom = mp->head = mp->top = NULL; mp->cpf = mp->fpl = 0; mp->longest = 5; /* .. must be labeled! */ mp->flags = fb_flags; @@ -1865,6 +1873,7 @@ getfcells(char *dname, int fb_flags) mp->head = mp->top = mp->current = ncp; } else{ + mp->bottom = ncp; tcp->next = ncp; ncp->prev = tcp; } @@ -2403,7 +2412,7 @@ zotmaster(struct bmaster **mp) * the given string wrapping around if necessary */ struct fcell * -FindCell(struct bmaster *mp, char *utf8string) +FindCell(struct bmaster *mp, char *utf8string, int bsearch) { struct fcell *tp, *fp; @@ -2411,21 +2420,21 @@ FindCell(struct bmaster *mp, char *utf8string) return(NULL); fp = NULL; - tp = mp->current->next; + tp = bsearch ? mp->current->prev : mp->current->next; while(tp && !fp){ if(sisin(tp->fname, utf8string)) fp = tp; else - tp = tp->next; + tp = bsearch ? tp->prev : tp->next; } - tp = mp->head; + tp = bsearch ? mp->bottom : mp->head; while(tp != mp->current && !fp){ if(sisin(tp->fname, utf8string)) fp = tp; else - tp = tp->next; + tp = bsearch ? tp->prev : tp->next; } return(fp); diff --git a/pico/efunc.h b/pico/efunc.h index 624d1616..d657aaa2 100644 --- a/pico/efunc.h +++ b/pico/efunc.h @@ -229,9 +229,9 @@ extern void unmarkbuffer(void); /* search.c */ extern int forwsearch(int, int); -extern int readpattern(char *, int); -extern int forscan(int *, UCS *, LINE *, int, int); -extern void chword(UCS *, UCS *); +extern int readpattern(char *, int, int); +extern int forscan(int *, UCS *, int, LINE *, int, int); +extern void chword(UCS *, UCS *, int); /* spell.c */ #ifdef SPELLER diff --git a/pico/osdep/spell.c b/pico/osdep/spell.c index ca063ba2..1606ce68 100644 --- a/pico/osdep/spell.c +++ b/pico/osdep/spell.c @@ -207,7 +207,7 @@ spell(int f, int n) switch(status){ case TRUE: - chword(wb, cb); /* correct word */ + chword(wb, cb, 0); /* correct word */ case FALSE: update(); /* place cursor */ break; @@ -285,7 +285,7 @@ movetoword(UCS *w) olddotp = curwp->w_dotp; curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */ - while(forscan(&i, w, NULL, 0, 1) == TRUE){ + while(forscan(&i, w, 0, NULL, 0, 1) == TRUE){ if(i) break; /* wrap NOT allowed! */ diff --git a/pico/search.c b/pico/search.c index 0d07d904..49aaec2d 100644 --- a/pico/search.c +++ b/pico/search.c @@ -32,11 +32,16 @@ int eq(UCS, UCS); int expandp(UCS *, UCS *, int); int readnumpat(char *); void get_pat_cases(UCS *, UCS *); -int srpat(char *, UCS *, size_t, int); -int readpattern(char *, int); -int replace_pat(UCS *, int *); -int replace_all(UCS *, UCS *); - +int srpat(char *, UCS *, size_t, int, int); +int readpattern(char *, int, int); +int replace_pat(UCS *, int *, int); +int replace_all(UCS *, UCS *, int); +void reverse_line(LINE *); +void reverse_buffer(void); +void reverse_ucs4(UCS *); +void reverse_all(UCS *, int); +void supdate(UCS *, int); +char *sucs4_to_utf8_cpystr(UCS *, int); #define FWS_RETURN(RV) { \ thisflag |= CFSRCH; \ @@ -109,13 +114,14 @@ eq(UCS bc, UCS pc) int forwsearch(int f, int n) { - int status; + int status, bsearch; int wrapt = FALSE, wrapt2 = FALSE; int repl_mode = FALSE; UCS defpat[NPAT]; int search = FALSE; EML eml; + /* resolve the repeat count */ if (n == 0) n = 1; @@ -124,14 +130,15 @@ forwsearch(int f, int n) FWS_RETURN(0); defpat[0] = '\0'; + bsearch = 0; /* search forward by default */ /* ask the user for the text of a pattern */ while(1){ if (gmode & MDREPLACE) - status = srpat("Search", defpat, NPAT, repl_mode); + status = srpat("Search", defpat, NPAT, repl_mode, bsearch); else - status = readpattern("Search", TRUE); + status = readpattern("Search", TRUE, bsearch); switch(status){ case TRUE: /* user typed something */ @@ -158,6 +165,10 @@ forwsearch(int f, int n) update(); break; + case (CTRL|'P'): + bsearch = bsearch == 0 ? 1 : 0; + break; + case (CTRL|'V'): gotoeob(0, 1); mlerase(); @@ -258,6 +269,8 @@ forwsearch(int f, int n) } } + reverse_all(defpat, bsearch); + /* * This code is kind of dumb. What I want is successive C-W 's to * move dot to successive occurences of the pattern. So, if dot is @@ -270,19 +283,19 @@ forwsearch(int f, int n) while(1){ if(defpat[status] == '\0'){ forwchar(0, 1); - break; /* find next occurence! */ + break; } if(status + curwp->w_doto >= llength(curwp->w_dotp) || !eq(defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c)) - break; /* do nothing! */ + break; status++; } /* search for the pattern */ while (n-- > 0) { - if((status = forscan(&wrapt,defpat,NULL,0,PTBEG)) == FALSE) + if((status = forscan(&wrapt,defpat, bsearch, NULL,0,PTBEG)) == FALSE) break; } @@ -301,7 +314,7 @@ forwsearch(int f, int n) fs_give((void **) &utf8); } else if((gmode & MDREPLACE) && repl_mode == TRUE){ - status = replace_pat(defpat, &wrapt2); /* replace pattern */ + status = replace_pat(defpat, &wrapt2, bsearch); /* replace pattern */ if (wrapt == TRUE || wrapt2 == TRUE){ eml.s = (status == ABORT) ? "cancelled but wrapped" : "Wrapped"; emlwrite("Replacement %s", &eml); @@ -314,13 +327,18 @@ forwsearch(int f, int n) emlwrite("", NULL); } + reverse_all(defpat, bsearch); + if(curwp->w_doto == -1){ + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + } FWS_RETURN(status); } /* Replace a pattern with the pattern the user types in one or more times. */ int -replace_pat(UCS *defpat, int *wrapt) +replace_pat(UCS *defpat, int *wrapt, int bsearch) { register int status; UCS lpat[NPAT], origpat[NPAT]; /* case sensitive pattern */ @@ -331,7 +349,9 @@ replace_pat(UCS *defpat, int *wrapt) UCS prompt[NPMT]; UCS *promptp; - forscan(wrapt, defpat, NULL, 0, PTBEG); /* go to word to be replaced */ + if(bsearch) + curwp->w_doto -= ucs4_strlen(defpat) - 1; + forscan(wrapt, defpat, bsearch, NULL, 0, PTBEG); /* go to word to be replaced */ lpat[0] = '\0'; @@ -344,6 +364,13 @@ replace_pat(UCS *defpat, int *wrapt) while(1) { + /* we need to reverse the buffer back to its original state, so that + * the user will not see that we reversed it under them. The cursor + * is at the beginning of the reverse string, that is at the end + * of the string. Move it back to the beginning. + */ + + reverse_all(defpat, bsearch); /* reverse for normal view */ update(); (*term.t_rev)(1); get_pat_cases(origpat, defpat); @@ -402,6 +429,8 @@ replace_pat(UCS *defpat, int *wrapt) curwp->w_flag |= WFMOVE; + reverse_all(defpat, bsearch); /* reverse for internal use */ + switch(status){ case TRUE : @@ -416,10 +445,10 @@ replace_pat(UCS *defpat, int *wrapt) } if (repl_all){ - status = replace_all(defpat, lpat); + status = replace_all(defpat, lpat, bsearch); } else{ - chword(defpat, lpat); /* replace word */ + chword(defpat, lpat, bsearch); /* replace word */ update(); status = TRUE; } @@ -470,7 +499,7 @@ replace_pat(UCS *defpat, int *wrapt) } else{ mlerase(); - chword(defpat, origpat); + chword(defpat, origpat, bsearch); } update(); @@ -501,7 +530,7 @@ get_pat_cases(UCS *realpat, UCS *searchpat) /* Ask the user about every occurence of orig pattern and replace it with a repl pattern if the response is affirmative. */ int -replace_all(UCS *orig, UCS *repl) +replace_all(UCS *orig, UCS *repl, int bsearch) { register int status = 0; UCS *b; @@ -514,10 +543,20 @@ replace_all(UCS *orig, UCS *repl) int stop_offset = curwp->w_doto; EML eml; + /* similar to replace_pat. When we come here, if bsearch is set, + * the cursor is at the end of the match, so we must bring it back + * to the beginning. + */ + if(bsearch){ + curwp->w_doto -= ucs4_strlen(orig) - 1; + curwp->w_flag |= WFMOVE; + } + stop_offset = curwp->w_doto; while (1) - if (forscan(&wrapt, orig, stop_line, stop_offset, PTBEG)){ + if (forscan(&wrapt, orig, bsearch, stop_line, stop_offset, PTBEG)){ curwp->w_flag |= WFMOVE; /* put cursor back */ + reverse_all(orig, bsearch); /* undo reverse buffer and pattern */ update(); (*term.t_rev)(1); get_pat_cases(realpat, orig); @@ -562,10 +601,10 @@ replace_all(UCS *orig, UCS *repl) if (status == TRUE){ n++; - chword(realpat, repl); /* replace word */ + chword(realpat, repl, bsearch); /* replace word */ update(); }else{ - chword(realpat, realpat); /* replace word by itself */ + chword(realpat, realpat, bsearch); /* replace word by itself */ update(); if(status == ABORT){ /* if cancelled return */ eml.s = comatose(n); @@ -593,14 +632,14 @@ replace_all(UCS *orig, UCS *repl) /* Read a replacement pattern. Modeled after readpattern(). */ int -srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode) +srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode, int bsearch) { register int s; int i = 0; UCS *b; UCS prompt[NPMT]; UCS *promptp; - EXTRAKEYS menu_pat[8]; + EXTRAKEYS menu_pat[9]; menu_pat[i = 0].name = "^Y"; menu_pat[i].label = N_("FirstLine"); @@ -643,13 +682,24 @@ srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode) KS_OSDATASET(&menu_pat[i], KS_NONE); } + menu_pat[++i].name = "^P"; + menu_pat[i].label = bsearch ? N_("Forward") : N_("Backward") ; + menu_pat[i].key = (CTRL|'P'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + menu_pat[++i].name = NULL; b = utf8_to_ucs4_cpystr(utf8prompt); if(b){ ucs4_strncpy(prompt, b, NPMT); prompt[NPMT-1] = '\0'; - fs_give((void **) &b); + if(bsearch){ + fs_give((void **) &b); + b = utf8_to_ucs4_cpystr(N_(" backward")); + if(b) ucs4_strncat(prompt, b, ucs4_strlen(b)); + prompt[NPMT-1] = '\0'; + } + if(b) fs_give((void **) &b); } promptp = &prompt[ucs4_strlen(prompt)]; @@ -762,14 +812,14 @@ readnumpat(char *utf8prompt) int -readpattern(char *utf8prompt, int text_mode) +readpattern(char *utf8prompt, int text_mode, int bsearch) { register int s; int i; UCS *b; UCS tpat[NPAT+20]; UCS *tpatp; - EXTRAKEYS menu_pat[7]; + EXTRAKEYS menu_pat[8]; menu_pat[i = 0].name = "^Y"; menu_pat[i].label = N_("FirstLine"); @@ -803,13 +853,24 @@ readpattern(char *utf8prompt, int text_mode) KS_OSDATASET(&menu_pat[i], KS_NONE); } + menu_pat[++i].name = "^P"; + menu_pat[i].label = bsearch ? N_("Forward") : N_("Backward") ; + menu_pat[i].key = (CTRL|'P'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + menu_pat[++i].name = NULL; b = utf8_to_ucs4_cpystr(utf8prompt); if(b){ ucs4_strncpy(tpat, b, NPAT+20); tpat[NPAT+20-1] = '\0'; - fs_give((void **) &b); + if(bsearch){ + fs_give((void **) &b); + b = utf8_to_ucs4_cpystr(N_(" backward")); + if(b) ucs4_strncat(tpat, b, ucs4_strlen(b)); + tpat[NPAT+20-1] = '\0'; + } + if(b) fs_give((void **) &b); } tpatp = &tpat[ucs4_strlen(tpat)]; @@ -853,11 +914,82 @@ readpattern(char *utf8prompt, int text_mode) return(s); } +/* given a line, reverse its content */ +void reverse_line(LINE *l) +{ + int i, j, a; + UCS u; + + if(l == NULL) return; + j = llength(l) - 1; + for(i = 0; i < j; i++, j--){ + u = lgetc(l, j).c; /* reverse the text */ + lgetc(l, j).c = lgetc(l, i).c; + lgetc(l, i).c = u; + a = lgetc(l, j).a; /* and the attribute */ + lgetc(l, j).a = lgetc(l, i).a; + lgetc(l, i).a = a; + } +} + +void +reverse_all(UCS *pat, int bsearch) +{ + if(bsearch != 0){ + reverse_buffer(); + reverse_ucs4(pat); + } +} + +void +reverse_buffer(void) +{ + LINE *l; + + for(l = lforw(curbp->b_linep); l != curbp->b_linep; l = lforw(l)) + reverse_line(l); + + /* reverse links in buffer */ + l = curbp->b_linep; + do { + lforw(l) = lback(l); + l = lforw(l); + } while(l != curbp->b_linep); + + l = curbp->b_linep; + do { + lback(lforw(l)) = l; + l = lforw(l); + } while (l != curbp->b_linep); + + curwp->w_doto = llength(curwp->w_dotp) - 1 - curwp->w_doto; +} + + + +/* given a UCS4 string reverse its content */ +void reverse_ucs4(UCS *s) +{ + int i, j; + UCS u; + + j = ucs4_strlen(s) - 1; + for(i = 0; i < j; i++, j--){ + u = s[j]; + s[j] = s[i]; + s[i] = u; + } +} + -/* search forward for a <patrn> */ +/* search forward for a <patrn>. + * A backward search is a forward search in backward lines with backward + * patterns + */ int forscan(int *wrapt, /* boolean indicating search wrapped */ UCS *patrn, /* string to scan for */ + int bsearch, /* search backwards */ LINE *limitp, /* stop searching if reached */ int limito, /* stop searching if reached */ int leavep) /* place to leave point @@ -878,6 +1010,13 @@ forscan(int *wrapt, /* boolean indicating search wrapped */ *wrapt = FALSE; + /* if bsearch is set we return the match at the beginning of the + * matching string, so we make this algorithm return the end of + * the string, so that when we reverse we be at the beginning. + */ + if(bsearch) + leavep = leavep == PTBEG ? PTEND : PTBEG; + /* * the idea is to set the character to end the search at the * next character in the buffer. thus, let the search wrap @@ -919,12 +1058,17 @@ forscan(int *wrapt, /* boolean indicating search wrapped */ /* get the current character resolving EOLs */ if (curoff == llength(curline)) { /* if at EOL */ - curline = lforw(curline); /* skip to next line */ - curoff = 0; + curline = lforw(curline); /* skip to next line */ + curoff = 0; c = '\n'; /* and return a <NL> */ } + else if(curoff == -1){ + stopoff = curoff = 0; + continue; + c = '\n'; + } else - c = lgetc(curline, curoff++).c; /* get the char */ + c = lgetc(curline, curoff++).c; /* get the char */ /* test it against first char in pattern */ if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/ @@ -1025,13 +1169,37 @@ expandp(UCS *srcstr, /* string to expand */ /* * chword() - change the given word, wp, pointed to by the curwp->w_dot * pointers to the word in cb + * if bsearch is set, then cb is supposed to come unreversed, while + * the buffer is supposed to be reversed, so we must reverse cb before + * inserting it. */ void -chword(UCS *wb, UCS *cb) +chword(UCS *wb, UCS *cb, int bsearch) { - ldelete((long) ucs4_strlen(wb), NULL); /* not saved in kill buffer */ - while(*cb != '\0') - linsert(1, *cb++); + UCS *u; + ldelete(ucs4_strlen(wb), NULL); /* not saved in kill buffer */ + if(bsearch) reverse_ucs4(cb); + for(u = cb; *u != '\0'; u++) + linsert(1, *u); + if(bsearch) reverse_ucs4(cb); curwp->w_flag |= WFEDIT; } + +void + supdate(UCS *pat, int bsearch) +{ + reverse_all(pat, bsearch); /* undo reverse buffer and pattern */ + update(); + reverse_all(pat, bsearch); /* reverse buffer and pattern */ +} + +char * +sucs4_to_utf8_cpystr(UCS *orig, int bsearch) +{ + char *utf8; + if(bsearch) reverse_ucs4(orig); + utf8 = ucs4_to_utf8_cpystr(orig); + if(bsearch) reverse_ucs4(orig); + return utf8; +} |