Added source code
This commit is contained in:
@@ -0,0 +1,874 @@
|
||||
#if !defined(lint) && !defined(DOS)
|
||||
static char rcsid[] = "$Id: search.c 13728 2004-07-01 21:33:30Z jpf $";
|
||||
#endif
|
||||
/*
|
||||
* Program: Searching routines
|
||||
*
|
||||
*
|
||||
* Michael Seibel
|
||||
* Networks and Distributed Computing
|
||||
* Computing and Communications
|
||||
* University of Washington
|
||||
* Administration Builiding, AG-44
|
||||
* Seattle, Washington, 98195, USA
|
||||
* Internet: mikes@cac.washington.edu
|
||||
*
|
||||
* Please address all bugs and comments to "pine-bugs@cac.washington.edu"
|
||||
*
|
||||
*
|
||||
* Pine and Pico are registered trademarks of the University of Washington.
|
||||
* No commercial use of these trademarks may be made without prior written
|
||||
* permission of the University of Washington.
|
||||
*
|
||||
* Pine, Pico, and Pilot software and its included text are Copyright
|
||||
* 1989-2004 by the University of Washington.
|
||||
*
|
||||
* The full text of our legal notices is contained in the file called
|
||||
* CPYRIGHT, included with this distribution.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* The functions in this file implement commands that search in the forward
|
||||
* and backward directions. There are no special characters in the search
|
||||
* strings. Probably should have a regular expression search, or something
|
||||
* like that.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "headers.h"
|
||||
|
||||
int eq PROTO((int, int));
|
||||
int expandp PROTO((char *, char *, int));
|
||||
int readnumpat PROTO((char *));
|
||||
void get_pat_cases PROTO((char *, char *));
|
||||
|
||||
|
||||
#define FWS_RETURN(RV) { \
|
||||
thisflag |= CFSRCH; \
|
||||
curwp->w_flag |= WFMODE; \
|
||||
sgarbk = TRUE; \
|
||||
return(RV); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search forward. Get a search string from the user, and search, beginning at
|
||||
* ".", for the string. If found, reset the "." to be just after the match
|
||||
* string, and [perhaps] repaint the display. Bound to "C-S".
|
||||
*/
|
||||
|
||||
/* string search input parameters */
|
||||
|
||||
#define PTBEG 1 /* leave the point at the begining on search */
|
||||
#define PTEND 2 /* leave the point at the end on search */
|
||||
|
||||
|
||||
|
||||
static char *SearchHelpText[] = {
|
||||
"Help for Search Command",
|
||||
" ",
|
||||
"\tEnter the words or characters you would like to search",
|
||||
"~\tfor, then press ~R~e~t~u~r~n. The search then takes place.",
|
||||
"\tWhen the characters or words that you entered ",
|
||||
"\tare found, the buffer will be redisplayed with the cursor ",
|
||||
"\tat the beginning of the selected text.",
|
||||
" ",
|
||||
"\tThe most recent string for which a search was made is",
|
||||
"\tdisplayed in the \"Search\" prompt between the square",
|
||||
"\tbrackets. This string is the default search prompt.",
|
||||
"~ Hitting only ~R~e~t~u~r~n or at the prompt will cause the",
|
||||
"\tsearch to be made with the default value.",
|
||||
" ",
|
||||
"\tThe text search is not case sensitive, and will examine the",
|
||||
"\tentire message.",
|
||||
" ",
|
||||
"\tShould the search fail, a message will be displayed.",
|
||||
" ",
|
||||
"End of Search Help.",
|
||||
" ",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Compare two characters. The "bc" comes from the buffer. It has it's case
|
||||
* folded out. The "pc" is from the pattern.
|
||||
*/
|
||||
eq(bc, pc)
|
||||
int bc;
|
||||
int pc;
|
||||
{
|
||||
if ((curwp->w_bufp->b_mode & MDEXACT) == 0){
|
||||
if (bc>='a' && bc<='z')
|
||||
bc -= 0x20;
|
||||
|
||||
if (pc>='a' && pc<='z')
|
||||
pc -= 0x20;
|
||||
}
|
||||
|
||||
return(bc == pc);
|
||||
}
|
||||
|
||||
|
||||
forwsearch(f, n)
|
||||
int f, n;
|
||||
{
|
||||
register int status;
|
||||
int wrapt = FALSE, wrapt2 = FALSE;
|
||||
int repl_mode = FALSE;
|
||||
char defpat[NPAT];
|
||||
int search = FALSE;
|
||||
|
||||
/* resolve the repeat count */
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
if (n < 1) /* search backwards */
|
||||
FWS_RETURN(0);
|
||||
|
||||
defpat[0] = '\0';
|
||||
|
||||
/* ask the user for the text of a pattern */
|
||||
while(1){
|
||||
|
||||
if (gmode & MDREPLACE)
|
||||
status = srpat("Search", defpat, repl_mode);
|
||||
else
|
||||
status = readpattern("Search", TRUE);
|
||||
|
||||
switch(status){
|
||||
case TRUE: /* user typed something */
|
||||
search = TRUE;
|
||||
break;
|
||||
|
||||
case HELPCH: /* help requested */
|
||||
if(Pmaster){
|
||||
VARS_TO_SAVE *saved_state;
|
||||
|
||||
saved_state = save_pico_state();
|
||||
(*Pmaster->helper)(Pmaster->search_help,
|
||||
"Help for Searching", 1);
|
||||
if(saved_state){
|
||||
restore_pico_state(saved_state);
|
||||
free_pico_state(saved_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
pico_help(SearchHelpText, "Help for Searching", 1);
|
||||
|
||||
case (CTRL|'L'): /* redraw requested */
|
||||
pico_refresh(FALSE, 1);
|
||||
update();
|
||||
break;
|
||||
|
||||
case (CTRL|'V'):
|
||||
gotoeob(0, 1);
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
|
||||
case (CTRL|'Y'):
|
||||
gotobob(0, 1);
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
|
||||
case (CTRL|'T') :
|
||||
switch(status = readnumpat("Search to Line Number : ")){
|
||||
case -1 :
|
||||
emlwrite("Search to Line Number Cancelled", NULL);
|
||||
FWS_RETURN(FALSE);
|
||||
|
||||
case 0 :
|
||||
emlwrite("Line number must be greater than zero", NULL);
|
||||
FWS_RETURN(FALSE);
|
||||
|
||||
case -2 :
|
||||
emlwrite("Line number must contain only digits", NULL);
|
||||
FWS_RETURN(FALSE);
|
||||
|
||||
case -3 :
|
||||
continue;
|
||||
|
||||
default :
|
||||
gotoline(0, status);
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case (CTRL|'W'):
|
||||
{
|
||||
LINE *linep = curwp->w_dotp;
|
||||
int offset = curwp->w_doto;
|
||||
|
||||
gotobop(0, 1);
|
||||
gotobol(0, 1);
|
||||
|
||||
/*
|
||||
* if we're asked to backup and we're already
|
||||
*
|
||||
*/
|
||||
if((lastflag & CFSRCH)
|
||||
&& linep == curwp->w_dotp
|
||||
&& offset == curwp->w_doto
|
||||
&& !(offset == 0 && lback(linep) == curbp->b_linep)){
|
||||
backchar(0, 1);
|
||||
gotobop(0, 1);
|
||||
gotobol(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
|
||||
case (CTRL|'O'):
|
||||
if(curwp->w_dotp != curbp->b_linep){
|
||||
gotoeop(0, 1);
|
||||
forwchar(0, 1);
|
||||
}
|
||||
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
|
||||
case (CTRL|'U'):
|
||||
fillbuf(0, 1);
|
||||
mlerase();
|
||||
FWS_RETURN(TRUE);
|
||||
|
||||
case (CTRL|'R'): /* toggle replacement option */
|
||||
repl_mode = !repl_mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
if(status == ABORT)
|
||||
emlwrite("Search Cancelled", NULL);
|
||||
else
|
||||
mlerase();
|
||||
|
||||
FWS_RETURN(FALSE);
|
||||
}
|
||||
|
||||
/* replace option is disabled */
|
||||
if (!(gmode & MDREPLACE)){
|
||||
strcpy(defpat, pat);
|
||||
break;
|
||||
}
|
||||
else if (search){ /* search now */
|
||||
strcpy(pat, defpat); /* remember this search for the future */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* already sitting at the beginning of the pattern, then we'll move
|
||||
* forward a char before beginning the search. We'll let the
|
||||
* automatic wrapping handle putting the dot back in the right
|
||||
* place...
|
||||
*/
|
||||
status = 0; /* using "status" as int temporarily! */
|
||||
while(1){
|
||||
if(defpat[status] == '\0'){
|
||||
forwchar(0, 1);
|
||||
break; /* find next occurence! */
|
||||
}
|
||||
|
||||
if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
|
||||
!eq(defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
|
||||
break; /* do nothing! */
|
||||
status++;
|
||||
}
|
||||
|
||||
/* search for the pattern */
|
||||
|
||||
while (n-- > 0) {
|
||||
if((status = forscan(&wrapt,&defpat[0],NULL,0,PTBEG)) == FALSE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* and complain if not there */
|
||||
if (status == FALSE){
|
||||
emlwrite("\"%s\" not found", defpat);
|
||||
}
|
||||
else if((gmode & MDREPLACE) && repl_mode == TRUE){
|
||||
status = replace_pat(defpat, &wrapt2); /* replace pattern */
|
||||
if (wrapt == TRUE || wrapt2 == TRUE)
|
||||
emlwrite("Replacement %srapped",
|
||||
(status == ABORT) ? "cancelled but w" : "W");
|
||||
}
|
||||
else if(wrapt == TRUE){
|
||||
emlwrite("Search Wrapped", NULL);
|
||||
}
|
||||
else if(status == TRUE){
|
||||
emlwrite("", NULL);
|
||||
}
|
||||
|
||||
FWS_RETURN(status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Replace a pattern with the pattern the user types in one or more times. */
|
||||
int replace_pat(defpat, wrapt)
|
||||
char *defpat;
|
||||
int *wrapt;
|
||||
{
|
||||
register int status;
|
||||
char lpat[NPAT], origpat[NPAT]; /* case sensitive pattern */
|
||||
EXTRAKEYS menu_pat[2];
|
||||
int repl_all = FALSE;
|
||||
char prompt[2*NLINE+32];
|
||||
|
||||
forscan(wrapt, defpat, NULL, 0, PTBEG); /* go to word to be replaced */
|
||||
|
||||
lpat[0] = '\0';
|
||||
|
||||
/* additional 'replace all' menu option */
|
||||
menu_pat[0].name = "^X";
|
||||
menu_pat[0].key = (CTRL|'X');
|
||||
menu_pat[0].label = "Repl All";
|
||||
KS_OSDATASET(&menu_pat[0], KS_NONE);
|
||||
menu_pat[1].name = NULL;
|
||||
|
||||
while(1) {
|
||||
|
||||
update();
|
||||
(*term.t_rev)(1);
|
||||
get_pat_cases(origpat, defpat);
|
||||
pputs(origpat, 1); /* highlight word */
|
||||
(*term.t_rev)(0);
|
||||
|
||||
sprintf(prompt, "Replace%s \"", repl_all ? " every" : "");
|
||||
|
||||
expandp(&defpat[0], &prompt[strlen(prompt)], NPAT/2);
|
||||
strcat(prompt, "\" with");
|
||||
if(rpat[0] != 0){
|
||||
strcat(prompt, " [");
|
||||
expandp(rpat, &prompt[strlen(prompt)], NPAT/2);
|
||||
strcat(prompt, "]");
|
||||
}
|
||||
|
||||
strcat(prompt, " : ");
|
||||
|
||||
status = mlreplyd(prompt, lpat, NPAT, QDEFLT, menu_pat);
|
||||
|
||||
curwp->w_flag |= WFMOVE;
|
||||
|
||||
switch(status){
|
||||
|
||||
case TRUE :
|
||||
case FALSE :
|
||||
if(lpat[0])
|
||||
strcpy(rpat, lpat); /* remember default */
|
||||
else
|
||||
strcpy(lpat, rpat); /* use default */
|
||||
|
||||
if (repl_all){
|
||||
status = replace_all(defpat, lpat);
|
||||
}
|
||||
else{
|
||||
chword(defpat, lpat); /* replace word */
|
||||
update();
|
||||
status = TRUE;
|
||||
}
|
||||
|
||||
if(status == TRUE)
|
||||
emlwrite("", NULL);
|
||||
|
||||
return(status);
|
||||
|
||||
case HELPCH: /* help requested */
|
||||
if(Pmaster){
|
||||
VARS_TO_SAVE *saved_state;
|
||||
|
||||
saved_state = save_pico_state();
|
||||
(*Pmaster->helper)(Pmaster->search_help,
|
||||
"Help for Searching", 1);
|
||||
if(saved_state){
|
||||
restore_pico_state(saved_state);
|
||||
free_pico_state(saved_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
pico_help(SearchHelpText, "Help for Searching", 1);
|
||||
|
||||
case (CTRL|'L'): /* redraw requested */
|
||||
pico_refresh(FALSE, 1);
|
||||
update();
|
||||
break;
|
||||
|
||||
case (CTRL|'X'): /* toggle replace all option */
|
||||
if (repl_all){
|
||||
repl_all = FALSE;
|
||||
menu_pat[0].label = "Repl All";
|
||||
}
|
||||
else{
|
||||
repl_all = TRUE;
|
||||
menu_pat[0].label = "Repl One";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if(status == ABORT)
|
||||
emlwrite("Replacement Cancelled", NULL);
|
||||
else
|
||||
mlerase();
|
||||
chword(defpat, origpat);
|
||||
update();
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Since the search is not case sensitive, we must obtain the actual pattern
|
||||
that appears in the text, so that we can highlight (and unhighlight) it
|
||||
without using the wrong cases */
|
||||
void
|
||||
get_pat_cases(realpat, searchpat)
|
||||
char *searchpat, *realpat;
|
||||
{
|
||||
int i, searchpatlen, curoff;
|
||||
|
||||
curoff = curwp->w_doto;
|
||||
searchpatlen = strlen(searchpat);
|
||||
|
||||
for (i = 0; i < searchpatlen; i++)
|
||||
realpat[i] = lgetc(curwp->w_dotp, curoff++).c;
|
||||
realpat[searchpatlen] = '\0';
|
||||
}
|
||||
|
||||
/* Ask the user about every occurence of orig pattern and replace it with a
|
||||
repl pattern if the response is affirmative. */
|
||||
int replace_all(orig, repl)
|
||||
char *orig;
|
||||
char *repl;
|
||||
{
|
||||
register int status = 0;
|
||||
char prompt[NLINE], realpat[NPAT];
|
||||
int wrapt, n = 0;
|
||||
LINE *stop_line = curwp->w_dotp;
|
||||
int stop_offset = curwp->w_doto;
|
||||
|
||||
while (1)
|
||||
if (forscan(&wrapt, orig, stop_line, stop_offset, PTBEG)){
|
||||
curwp->w_flag |= WFMOVE; /* put cursor back */
|
||||
|
||||
update();
|
||||
(*term.t_rev)(1);
|
||||
get_pat_cases(realpat, orig);
|
||||
pputs(realpat, 1); /* highlight word */
|
||||
(*term.t_rev)(0);
|
||||
fflush(stdout);
|
||||
|
||||
strcpy(prompt, "Replace \"");
|
||||
expandp(&orig[0], &prompt[strlen(prompt)], NPAT/2);
|
||||
strcat(prompt, "\" with \"");
|
||||
expandp(&repl[0], &prompt[strlen(prompt)], NPAT/2);
|
||||
strcat(prompt, "\"");
|
||||
|
||||
status = mlyesno(prompt, TRUE); /* ask user */
|
||||
|
||||
if (status == TRUE){
|
||||
n++;
|
||||
chword(realpat, repl); /* replace word */
|
||||
update();
|
||||
}else{
|
||||
chword(realpat, realpat); /* replace word by itself */
|
||||
update();
|
||||
if(status == ABORT){ /* if cancelled return */
|
||||
emlwrite("Replace All cancelled after %d changes", (char *) n);
|
||||
return (ABORT); /* ... else keep looking */
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
emlwrite("No more matches for \"%s\"", orig);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read a replacement pattern. Modeled after readpattern(). */
|
||||
srpat(prompt, defpat, repl_mode)
|
||||
char *prompt;
|
||||
char *defpat;
|
||||
int repl_mode;
|
||||
{
|
||||
register int s;
|
||||
int i = 0;
|
||||
char tpat[NPAT+20];
|
||||
EXTRAKEYS menu_pat[8];
|
||||
|
||||
menu_pat[i = 0].name = "^Y";
|
||||
menu_pat[i].label = "FirstLine";
|
||||
menu_pat[i].key = (CTRL|'Y');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^V";
|
||||
menu_pat[i].label = "LastLine";
|
||||
menu_pat[i].key = (CTRL|'V');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^R";
|
||||
menu_pat[i].label = repl_mode ? "No Replace" : "Replace";
|
||||
menu_pat[i].key = (CTRL|'R');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
if(!repl_mode){
|
||||
menu_pat[++i].name = "^T";
|
||||
menu_pat[i].label = "LineNumber";
|
||||
menu_pat[i].key = (CTRL|'T');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^W";
|
||||
menu_pat[i].label = "Start of Para";
|
||||
menu_pat[i].key = (CTRL|'W');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^O";
|
||||
menu_pat[i].label = "End of Para";
|
||||
menu_pat[i].key = (CTRL|'O');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^U";
|
||||
menu_pat[i].label = "FullJustify";
|
||||
menu_pat[i].key = (CTRL|'U');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
}
|
||||
|
||||
menu_pat[++i].name = NULL;
|
||||
|
||||
strcpy(tpat, prompt); /* copy prompt to output string */
|
||||
if (repl_mode){
|
||||
strcat(tpat, " (to replace)");
|
||||
}
|
||||
if(pat[0] != '\0'){
|
||||
strcat(tpat, " ["); /* build new prompt string */
|
||||
expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /*add old pattern*/
|
||||
strcat(tpat, "]");
|
||||
}
|
||||
|
||||
strcat(tpat, ": ");
|
||||
|
||||
s = mlreplyd(tpat, defpat, NLINE, QDEFLT, menu_pat);
|
||||
|
||||
if (s == TRUE || s == FALSE){ /* changed or not, they're done */
|
||||
if(!defpat[0]){ /* use default */
|
||||
strcpy(defpat, pat);
|
||||
}
|
||||
else if(strcmp(pat, defpat)){ /* Specified */
|
||||
strcpy(pat, defpat);
|
||||
rpat[0] = '\0';
|
||||
}
|
||||
|
||||
s = TRUE; /* let caller know to proceed */
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a pattern. Stash it in the external variable "pat". The "pat" is not
|
||||
* updated if the user types in an empty line. If the user typed an empty line,
|
||||
* and there is no old pattern, it is an error. Display the old pattern, in the
|
||||
* style of Jeff Lomicka. There is some do-it-yourself control expansion.
|
||||
* change to using <ESC> to delemit the end-of-pattern to allow <NL>s in
|
||||
* the search string.
|
||||
*/
|
||||
|
||||
readnumpat(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
int i, n;
|
||||
char tpat[NPAT+20];
|
||||
EXTRAKEYS menu_pat[2];
|
||||
|
||||
menu_pat[i = 0].name = "^T";
|
||||
menu_pat[i].label = "No Line Number";
|
||||
menu_pat[i].key = (CTRL|'T');
|
||||
KS_OSDATASET(&menu_pat[i++], KS_NONE);
|
||||
|
||||
menu_pat[i].name = NULL;
|
||||
|
||||
tpat[0] = '\0';
|
||||
while(1)
|
||||
switch(mlreplyd(prompt, tpat, NPAT, QNORML, menu_pat)){
|
||||
case TRUE :
|
||||
if(*tpat){
|
||||
for(i = n = 0; tpat[i]; i++)
|
||||
if(strchr("0123456789", tpat[i])){
|
||||
n = (n * 10) + (tpat[i] - '0');
|
||||
}
|
||||
else
|
||||
return(-2);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
case FALSE :
|
||||
default :
|
||||
return(-1);
|
||||
|
||||
case (CTRL|'T') :
|
||||
return(-3);
|
||||
|
||||
case (CTRL|'L') :
|
||||
case HELPCH :
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readpattern(prompt, text_mode)
|
||||
char *prompt;
|
||||
int text_mode;
|
||||
{
|
||||
register int s;
|
||||
int i;
|
||||
char tpat[NPAT+20];
|
||||
EXTRAKEYS menu_pat[7];
|
||||
|
||||
menu_pat[i = 0].name = "^Y";
|
||||
menu_pat[i].label = "FirstLine";
|
||||
menu_pat[i].key = (CTRL|'Y');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^V";
|
||||
menu_pat[i].label = "LastLine";
|
||||
menu_pat[i].key = (CTRL|'V');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
if(text_mode){
|
||||
menu_pat[++i].name = "^T";
|
||||
menu_pat[i].label = "LineNumber";
|
||||
menu_pat[i].key = (CTRL|'T');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^W";
|
||||
menu_pat[i].label = "Start of Para";
|
||||
menu_pat[i].key = (CTRL|'W');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^O";
|
||||
menu_pat[i].label = "End of Para";
|
||||
menu_pat[i].key = (CTRL|'O');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
|
||||
menu_pat[++i].name = "^U";
|
||||
menu_pat[i].label = "FullJustify";
|
||||
menu_pat[i].key = (CTRL|'U');
|
||||
KS_OSDATASET(&menu_pat[i], KS_NONE);
|
||||
}
|
||||
|
||||
menu_pat[++i].name = NULL;
|
||||
|
||||
strcpy(tpat, prompt); /* copy prompt to output string */
|
||||
if(pat[0] != '\0'){
|
||||
strcat(tpat, " ["); /* build new prompt string */
|
||||
expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
|
||||
strcat(tpat, "]");
|
||||
}
|
||||
strcat(tpat, " : ");
|
||||
|
||||
s = mlreplyd(tpat, tpat, NPAT, QNORML, menu_pat);
|
||||
|
||||
if ((s == TRUE) && strcmp(pat,tpat)){ /* Specified */
|
||||
strcpy(pat, tpat);
|
||||
rpat[0] = '\0';
|
||||
}
|
||||
else if (s == FALSE && pat[0] != 0) /* CR, but old one */
|
||||
s = TRUE;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
|
||||
/* search forward for a <patrn> */
|
||||
forscan(wrapt,patrn,limitp,limito,leavep)
|
||||
int *wrapt; /* boolean indicating search wrapped */
|
||||
char *patrn; /* string to scan for */
|
||||
LINE *limitp; /* stop searching if reached */
|
||||
int limito; /* stop searching if reached */
|
||||
int leavep; /* place to leave point
|
||||
PTBEG = begining of match
|
||||
PTEND = at end of match */
|
||||
|
||||
{
|
||||
register LINE *curline; /* current line during scan */
|
||||
register int curoff; /* position within current line */
|
||||
register LINE *lastline; /* last line position during scan */
|
||||
register int lastoff; /* position within last line */
|
||||
register int c; /* character at current position */
|
||||
register LINE *matchline; /* current line during matching */
|
||||
register int matchoff; /* position in matching line */
|
||||
register char *patptr; /* pointer into pattern */
|
||||
register int stopoff; /* offset to stop search */
|
||||
register LINE *stopline; /* line to stop search */
|
||||
|
||||
*wrapt = FALSE;
|
||||
|
||||
/*
|
||||
* the idea is to set the character to end the search at the
|
||||
* next character in the buffer. thus, let the search wrap
|
||||
* completely around the buffer.
|
||||
*
|
||||
* first, test to see if we are at the end of the line,
|
||||
* otherwise start searching on the next character.
|
||||
*/
|
||||
if(curwp->w_doto == llength(curwp->w_dotp)){
|
||||
/*
|
||||
* dot is not on end of a line
|
||||
* start at 0 offset of the next line
|
||||
*/
|
||||
stopoff = curoff = 0;
|
||||
stopline = curline = lforw(curwp->w_dotp);
|
||||
if (curwp->w_dotp == curbp->b_linep)
|
||||
*wrapt = TRUE;
|
||||
}
|
||||
else{
|
||||
stopoff = curoff = curwp->w_doto;
|
||||
stopline = curline = curwp->w_dotp;
|
||||
}
|
||||
|
||||
/* scan each character until we hit the head link record */
|
||||
|
||||
/*
|
||||
* maybe wrapping is a good idea
|
||||
*/
|
||||
while (curline){
|
||||
|
||||
if (curline == curbp->b_linep)
|
||||
*wrapt = TRUE;
|
||||
|
||||
/* save the current position in case we need to
|
||||
restore it on a match */
|
||||
|
||||
lastline = curline;
|
||||
lastoff = curoff;
|
||||
|
||||
/* get the current character resolving EOLs */
|
||||
if (curoff == llength(curline)) { /* if at EOL */
|
||||
curline = lforw(curline); /* skip to next line */
|
||||
curoff = 0;
|
||||
c = '\n'; /* and return a <NL> */
|
||||
}
|
||||
else
|
||||
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..*/
|
||||
/* setup match pointers */
|
||||
matchline = curline;
|
||||
matchoff = curoff;
|
||||
patptr = &patrn[0];
|
||||
|
||||
/* scan through patrn for a match */
|
||||
while (*++patptr != 0) {
|
||||
/* advance all the pointers */
|
||||
if (matchoff == llength(matchline)) {
|
||||
/* advance past EOL */
|
||||
matchline = lforw(matchline);
|
||||
matchoff = 0;
|
||||
c = '\n';
|
||||
} else
|
||||
c = lgetc(matchline, matchoff++).c;
|
||||
|
||||
if(matchline == limitp && matchoff == limito)
|
||||
return(FALSE);
|
||||
|
||||
/* and test it against the pattern */
|
||||
if (eq(*patptr, c) == FALSE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* A SUCCESSFULL MATCH!!! */
|
||||
/* reset the global "." pointers */
|
||||
if (leavep == PTEND) { /* at end of string */
|
||||
curwp->w_dotp = matchline;
|
||||
curwp->w_doto = matchoff;
|
||||
}
|
||||
else { /* at begining of string */
|
||||
curwp->w_dotp = lastline;
|
||||
curwp->w_doto = lastoff;
|
||||
}
|
||||
|
||||
curwp->w_flag |= WFMOVE; /* flag that we have moved */
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
fail:; /* continue to search */
|
||||
if(((curline == stopline) && (curoff == stopoff))
|
||||
|| (curline == limitp && curoff == limito))
|
||||
break; /* searched everywhere... */
|
||||
}
|
||||
/* we could not find a match */
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* expandp: expand control key sequences for output */
|
||||
|
||||
expandp(srcstr, deststr, maxlength)
|
||||
|
||||
char *srcstr; /* string to expand */
|
||||
char *deststr; /* destination of expanded string */
|
||||
int maxlength; /* maximum chars in destination */
|
||||
|
||||
{
|
||||
char c; /* current char to translate */
|
||||
|
||||
/* scan through the string */
|
||||
while ((c = *srcstr++) != 0) {
|
||||
if (c == '\n') { /* its an EOL */
|
||||
*deststr++ = '<';
|
||||
*deststr++ = 'N';
|
||||
*deststr++ = 'L';
|
||||
*deststr++ = '>';
|
||||
maxlength -= 4;
|
||||
} else if (c < 0x20 || c == 0x7f) { /* control character */
|
||||
*deststr++ = '^';
|
||||
*deststr++ = c ^ 0x40;
|
||||
maxlength -= 2;
|
||||
} else if (c == '%') {
|
||||
*deststr++ = '%';
|
||||
*deststr++ = '%';
|
||||
maxlength -= 2;
|
||||
|
||||
} else { /* any other character */
|
||||
*deststr++ = c;
|
||||
maxlength--;
|
||||
}
|
||||
|
||||
/* check for maxlength */
|
||||
if (maxlength < 4) {
|
||||
*deststr++ = '$';
|
||||
*deststr = '\0';
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
*deststr = '\0';
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* chword() - change the given word, wp, pointed to by the curwp->w_dot
|
||||
* pointers to the word in cb
|
||||
*/
|
||||
void
|
||||
chword(wb, cb)
|
||||
char *wb; /* word buffer */
|
||||
char *cb; /* changed buffer */
|
||||
{
|
||||
ldelete((long) strlen(wb), NULL); /* not saved in kill buffer */
|
||||
while(*cb != '\0')
|
||||
linsert(1, *cb++);
|
||||
|
||||
curwp->w_flag |= WFEDIT;
|
||||
}
|
||||
Reference in New Issue
Block a user