From f5f14dca0600a5b5c0e225a1eee05d05b69e768b Mon Sep 17 00:00:00 2001 From: anon Date: Fri, 4 Aug 2023 19:12:06 +0200 Subject: [PATCH] ops --- README.md | 7 +- comp.sh | 4 - src/command.c | 642 -------------------------------------------------------- src/constants.h | 9 +- src/display.c | 62 ++---- src/exec.c | 1 + src/global.h | 11 +- src/input.c | 244 +++++++++++++++++++++ src/main.c | 521 ++++++++++++++++++++++----------------------- src/opt.c | 2 +- src/readline.c | 124 ++++++++++- 11 files changed, 654 insertions(+), 973 deletions(-) delete mode 100755 comp.sh diff --git a/README.md b/README.md index 16317c7..e308a7d 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,11 @@ Fork of Cscope, with various improvements, because cscope is good and shall not +------------Message-------------+ +--------------------------------+ A |+--------------+---------------+| |+------------------------------+| | || Input Window | Result window || || || - |+--------------+ || ? || || - ? || Mode Window | || ---> || Help || - ? || | || <--- || || + | |+--------------+ || ? || || + || Mode Window | || ---> || Help || + % || | || <--- || || || | || ESC || || | || | || || || + | || | || || || V |+--------------+---------------+| |+------------------------------+| +-----------Tool Tips------------+ +--------------------------------+ diff --git a/comp.sh b/comp.sh deleted file mode 100755 index 869038d..0000000 --- a/comp.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -make clean -make diff --git a/src/command.c b/src/command.c index 879ebc7..1331f02 100644 --- a/src/command.c +++ b/src/command.c @@ -63,448 +63,12 @@ BOOL caseless; /* ignore letter case when searching */ BOOL *change; /* change this line */ BOOL changing; /* changing text */ char newpat[PATLEN + 1]; /* new pattern */ -char Pattern[PATLEN + 1]; /* symbol or text pattern */ - -static const char appendprompt[] = "Append to file: "; -static const char pipeprompt[] = "Pipe to shell command: "; -static const char readprompt[] = "Read from file: "; -static const char toprompt[] = "To: "; - /* Internal prototypes: */ -static BOOL changestring(void); static void clearprompt(void); static void mark(unsigned int i); static void scrollbar(MOUSE *p); - -/* execute the command */ -BOOL -command(int commandc) -{ - char filename[PATHLEN + 1]; /* file path name */ - MOUSE *p; /* mouse data */ - int c, i; - FILE *file; - struct cmd *curritem, *item; /* command history */ - char *s; - - switch (commandc) { - case ctrl('C'): /* toggle caseless mode */ - if (caseless == NO) { - caseless = YES; - postmsg2("Caseless mode is now ON"); - } else { - caseless = NO; - postmsg2("Caseless mode is now OFF"); - } - egrepcaseless(caseless); /* turn on/off -i flag */ - return(NO); - - case ctrl('R'): /* rebuild the cross reference */ - if (isuptodate == YES) { - postmsg("The -d option prevents rebuilding the symbol database"); - return(NO); - } - exitcurses(); - freefilelist(); /* remake the source file list */ - makefilelist(); - rebuild(); - if (errorsfound == YES) { - errorsfound = NO; - askforreturn(); - } - entercurses(); - clearmsg(); /* clear any previous message */ - totallines = 0; - disprefs = 0; - topline = nextline = 1; - break; - - case ESC: /* possible unixpc mouse selection */ - case ctrl('X'): /* mouse selection */ - if ((p = getmouseaction(DUMMYCHAR)) == NULL) { - return(NO); /* unknown control sequence */ - } - /* if the button number is a scrollbar tag */ - if (p->button == '0') { - scrollbar(p); - break; - } - /* ignore a sweep */ - if (p->x2 >= 0) { - return(NO); - } - /* if this is a line selection */ - if (p->y1 > FLDLINE) { - - /* find the selected line */ - /* note: the selection is forced into range */ - for (i = disprefs - 1; i > 0; --i) { - if (p->y1 >= displine[i]) { - break; - } - } - /* display it in the file with the editor */ - editref(i); - } else { /* this is an input field selection */ - field = p->y1 - FLDLINE; - /* force it into range */ - if (field >= FIELDS) { - field = FIELDS - 1; - } - resetcmd(); - return(NO); - } - break; - - case '\t': /* go to next input field */ - if (disprefs) { - horswp_field(); - } - return(NO); - - case '%': - verswp_field(); - return(NO); - - case KEY_ENTER: - case '\r': - case '\n': /* go to reference */ - if (current_window == &wresult) { - editref(curdispline); - window_change = CH_ALL; - return(YES); - } - /* FALLTHROUGH */ - - case ctrl('N'): - case KEY_DOWN: - case KEY_RIGHT: - if (current_window == &wresult) { - if ((curdispline + 1) < disprefs) { - ++curdispline; - } - } else { - field = (field + 1) % FIELDS; - resetcmd(); - } - return(NO); - - case ctrl('P'): /* go to previous input field */ - case KEY_UP: - case KEY_LEFT: - if (current_window == &wresult) { - if (curdispline) { - --curdispline; - } - } else { - field = (field + (FIELDS - 1)) % FIELDS; - resetcmd(); - } - return(NO); - case KEY_HOME: /* go to first input field */ - if (current_window == &wresult) { - curdispline = 0; - } else { - field = 0; - resetcmd(); - } - return(NO); - - case KEY_LL: /* go to last input field */ - if (current_window == &wresult) { - curdispline = disprefs; - refresh(); - } else { - field = FIELDS - 1; - resetcmd(); - } - return(NO); - - case ' ': /* display next page */ - case '+': - case ctrl('V'): - case KEY_NPAGE: - /* don't redisplay if there are no lines */ - if (totallines == 0) { - return(NO); - } - /* NOTE: seekline() is not used to move to the next - * page because display() leaves the file pointer at - * the next page to optimize paging forward - */ - curdispline = 0; - break; - - case ctrl('H'): - case '-': /* display previous page */ - case KEY_PPAGE: - /* don't redisplay if there are no lines */ - if (totallines == 0) { - return(NO); - } - - curdispline = 0; - - /* if there are only two pages, just go to the other one */ - if (totallines <= 2 * mdisprefs) { - break; - } - /* if on first page but not at beginning, go to beginning */ - nextline -= mdisprefs; /* already at next page */ - if (nextline > 1 && nextline <= mdisprefs) { - nextline = 1; - } else { - nextline -= mdisprefs; - if (nextline < 1) { - nextline = totallines - mdisprefs + 1; - if (nextline < 1) { - nextline = 1; - } - } - } - seekline(nextline); - break; - - case '>': /* write or append the lines to a file */ - if (totallines == 0) { - postmsg("There are no lines to write to a file"); - } else { /* get the file name */ - move(PRLINE, 0); - addstr("Write to file: "); - s = "w"; - if ((c = mygetch()) == '>') { - move(PRLINE, 0); - addstr(appendprompt); - c = '\0'; - s = "a"; - } - if (c != '\r' && - mygetline("", newpat, COLS - sizeof(appendprompt), c, NO) > 0) { - shellpath(filename, sizeof(filename), newpat); - if ((file = myfopen(filename, s)) == NULL) { - cannotopen(filename); - } else { - seekline(1); - while ((c = getc(refsfound)) != EOF) { - putc(c, file); - } - seekline(topline); - fclose(file); - } - } - clearprompt(); - } - return(NO); /* return to the previous field */ - - case '<': /* read lines from a file */ - move(PRLINE, 0); - addstr(readprompt); - if (mygetline("", newpat, COLS - sizeof(readprompt), '\0', NO) > 0) { - clearprompt(); - shellpath(filename, sizeof(filename), newpat); - if (readrefs(filename) == NO) { - postmsg2("Ignoring an empty file"); - return(NO); - } - window_change |= CH_INPUT; - return(YES); - } - clearprompt(); - return(NO); - - case '^': /* pipe the lines through a shell command */ - case '|': /* pipe the lines to a shell command */ - if (totallines == 0) { - postmsg("There are no lines to pipe to a shell command"); - return(NO); - } - /* get the shell command */ - move(PRLINE, 0); - addstr(pipeprompt); - if (mygetline("", newpat, COLS - sizeof(pipeprompt), '\0', NO) == 0) { - clearprompt(); - return(NO); - } - /* if the ^ command, redirect output to a temp file */ - if (commandc == '^') { - strcat(strcat(newpat, " >"), temp2); - /* HBB 20020708: somebody might have even - * their non-interactive default shells - * complain about clobbering - * redirections... --> delete before - * overwriting */ - remove(temp2); - } - exitcurses(); - if ((file = mypopen(newpat, "w")) == NULL) { - fprintf(stderr, "\ -cscope: cannot open pipe to shell command: %s\n", newpat); - } else { - seekline(1); - while ((c = getc(refsfound)) != EOF) { - putc(c, file); - } - seekline(topline); - mypclose(file); - } - if (commandc == '^') { - if (readrefs(temp2) == NO) { - postmsg("Ignoring empty output of ^ command"); - } - } - askforreturn(); - entercurses(); - break; -#if defined(KEY_RESIZE) && !defined(__DJGPP__) - case KEY_RESIZE: - /* XXX: fill in*/ - break; -#endif - case ctrl('L'): /* redraw screen */ - case KEY_CLEAR: - /* XXX: no */ - //clearmsg2(); - //clearok(curscr, TRUE); - //wrefresh(curscr); - //drawscrollbar(topline, bottomline); - return(NO); - - case '!': /* shell escape */ - execute(shell, shell, NULL); - seekline(topline); - break; - - case '?': /* help */ - clear(); - help(); - clear(); - seekline(topline); - break; - - case ctrl('E'): /* edit all lines */ - editall(); - break; - - case ctrl('A'): - case ctrl('Y'): /* repeat last pattern */ - if (*Pattern != '\0') { - addstr(Pattern); - goto repeat; - } - break; - - case ctrl('B'): /* cmd history back */ - case ctrl('F'): /* cmd history fwd */ - if (current_window == &wresult) { - horswp_field(); - } - - curritem = currentcmd(); - item = (commandc == ctrl('F')) ? nextcmd() : prevcmd(); - clearmsg2(); - if (curritem == item) { /* inform user that we're at history end */ - postmsg2("End of input field and search pattern history"); - } - if (item) { - field = item->field; - addstr(item->text); - strcpy(Pattern, item->text); - switch (c = mygetch()) { - case '\r': - case '\n': - goto repeat; - case ctrl('F'): - case ctrl('B'): - myungetch(c); - clrtoeol(); /* clear current field */ - break; - default: - myungetch(c); - if (mygetline(Pattern, newpat, COLS - fldcolumn - 1, '\0', caseless )) { - strcpy (Pattern, newpat); - resetcmd(); - } - goto repeat; - break; - } - } - return(NO); - - case '\\': /* next character is not a command */ - addch('\\'); /* display the quote character */ - - /* get a character from the terminal */ - if ((commandc = mygetch()) == EOF) { - return(NO); /* quit */ - } - addstr("\b \b"); /* erase the quote character */ - goto ispat; - - case '.': - postmsg("The . command has been replaced by ^Y"); - /* FALLTHROUGH */ - default: - if (current_window == &wresult && !mouse) { - char *c; - - if ((c = strchr(dispchars, commandc))) - editref(c - dispchars); - - /* if this is the start of a pattern */ - } else if (isprint(commandc)) { - ispat: - if (mygetline("", newpat, COLS - fldcolumn - 1, - commandc, caseless) > 0) { - strcpy(Pattern, newpat); - resetcmd(); /* reset command history */ - repeat: - addcmd(field, Pattern); /* add to command history */ - if (field == CHANGE) { - /* prompt for the new text */ - move(PRLINE, 0); - addstr(toprompt); - mygetline("", newpat, - COLS - sizeof(toprompt), - '\0', NO); - } - /* search for the pattern */ - if (search() == YES) { - curdispline = 0; - if(current_window != &wresult){ - horswp_field(); - } - - switch (field) { - case DEFINITION: - case FILENAME: - if (totallines > 1) { - break; - } - topline = 1; - editref(0); - break; - case CHANGE: - return(changestring()); - } - - } else if (field == FILENAME && - access(newpat, READ) == 0) { - /* try to edit the file anyway */ - edit(newpat, "1"); - } - } else { /* no pattern--the input was erased */ - return(NO); - } - } else { /* control character */ - return(NO); - } - } /* switch(commandc) */ - window_change |= CH_INPUT; - return(YES); -} - /* clear the prompt line */ static void @@ -550,212 +114,6 @@ readrefs(char *filename) return(YES); } -/* change one text string to another */ -static BOOL -changestring(void) -{ - char newfile[PATHLEN + 1]; /* new file name */ - char oldfile[PATHLEN + 1]; /* old file name */ - char linenum[NUMLEN + 1]; /* file line number */ - char msg[MSGLEN + 1]; /* message */ - FILE *script; /* shell script file */ - BOOL anymarked = NO; /* any line marked */ - MOUSE *p; /* mouse data */ - int c; - unsigned int i; - char *s; - - /* open the temporary file */ - if ((script = myfopen(temp2, "w")) == NULL) { - cannotopen(temp2); - return(NO); - } - /* create the line change indicators */ - change = calloc(totallines, sizeof(*change)); - changing = YES; - mousemenu(); - - /* until the quit command is entered */ - for (;;) { - /* display the current page of lines */ - display(); - same: - //atchange(); - - /* get a character from the terminal */ - if ((c = mygetch()) == EOF || c == ctrl('D')) { - break; /* change lines */ - } - if (c == ctrl('Z')) { -#ifdef SIGTSTP - kill(0, SIGTSTP); - goto same; -#else - break; /* change lines */ -#endif - } - /* see if the input character is a command */ - // wtf is this? ?! - switch (c) { - case ' ': /* display next page */ - case '+': - case ctrl('V'): - case KEY_NPAGE: - case '-': /* display previous page */ - case KEY_PPAGE: - case '!': /* shell escape */ - case '?': /* help */ - command(c); - break; - - case ctrl('L'): /* redraw screen */ - case KEY_CLEAR: - command(c); - goto same; - - case ESC: /* don't change lines */ -#if UNIXPC - if((p = getmouseaction(DUMMYCHAR)) == NULL) { - goto nochange; /* unknown escape sequence */ - } - break; -#endif - case ctrl('G'): - goto nochange; - - case '*': /* mark/unmark all displayed lines */ - for (i = 0; topline + i < nextline; ++i) { - mark(i); - } - goto same; - - case ctrl('A'): /* mark/unmark all lines */ - for (i = 0; i < totallines; ++i) { - if (change[i] == NO) { - change[i] = YES; - } else { - change[i] = NO; - } - } - /* show that all have been marked */ - seekline(totallines); - break; - - case ctrl('X'): /* mouse selection */ - if ((p = getmouseaction(DUMMYCHAR)) == NULL) { - goto same; /* unknown control sequence */ - } - /* if the button number is a scrollbar tag */ - if (p->button == '0') { - scrollbar(p); - break; - } - /* find the selected line */ - /* note: the selection is forced into range */ - for (i = disprefs - 1; i > 0; --i) { - if (p->y1 >= displine[i]) { - break; - } - } - mark(i); - goto same; - - default: - { - /* if a line was selected */ - char *cc; - - if ((cc = strchr(dispchars, c))) - mark(cc - dispchars); - - goto same; - } /* default case */ - } /* switch(change code character) */ - } /* for(ever) */ - - /* for each line containing the old text */ - fprintf(script, "ed - <<\\!\n"); - *oldfile = '\0'; - seekline(1); - for (i = 0; - fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", newfile, linenum) == 2; - ++i) { - /* see if the line is to be changed */ - if (change[i] == YES) { - anymarked = YES; - - /* if this is a new file */ - if (strcmp(newfile, oldfile) != 0) { - - /* make sure it can be changed */ - if (access(newfile, WRITE) != 0) { - snprintf(msg, sizeof(msg), "Cannot write to file %s", newfile); - postmsg(msg); - anymarked = NO; - break; - } - /* if there was an old file */ - if (*oldfile != '\0') { - fprintf(script, "w\n"); /* save it */ - } - /* edit the new file */ - strcpy(oldfile, newfile); - fprintf(script, "e %s\n", oldfile); - } - /* output substitute command */ - fprintf(script, "%ss/", linenum); /* change */ - for (s = Pattern; *s != '\0'; ++s) { - /* old text */ - if (strchr("/\\[.^*", *s) != NULL) { - putc('\\', script); - } - if (caseless == YES && isalpha((unsigned char)*s)) { - putc('[', script); - if(islower((unsigned char)*s)) { - putc(toupper((unsigned char)*s), script); - putc(*s, script); - } else { - putc(*s, script); - putc(tolower((unsigned char)*s), script); - } - putc(']', script); - } else - putc(*s, script); - } - putc('/', script); /* to */ - for (s = newpat; *s != '\0'; ++s) { /* new text */ - if (strchr("/\\&", *s) != NULL) { - putc('\\', script); - } - putc(*s, script); - } - fprintf(script, "/gp\n"); /* and print */ - } - } - fprintf(script, "w\nq\n!\n"); /* write and quit */ - fclose(script); - - /* if any line was marked */ - if (anymarked == YES) { - /* edit the files */ - clearprompt(); - refresh(); - fprintf(stderr, "Changed lines:\n\r"); - execute("sh", "sh", temp2, NULL); - askforreturn(); - seekline(1); - } else { - nochange: - clearprompt(); - } - changing = NO; - mousemenu(); - fclose(script); - free(change); - return(anymarked); -} - - /* mark/unmark this displayed line to be changed */ static void mark(unsigned int i) diff --git a/src/constants.h b/src/constants.h index 4de6c5a..0a70218 100644 --- a/src/constants.h +++ b/src/constants.h @@ -57,7 +57,9 @@ this macro will always be in a statement by itself */ #define skiprefchar() if (*(++blockp + 1) == '\0') (void) read_block() -#define ESC '\033' /* escape character */ +#ifndef ESC +# define ESC '\033' /* escape character */ +#endif #define DEL '\177' /* delete character */ #define DUMMYCHAR ' ' /* use space as a dummy character */ #define MSGLEN ((PATLEN) + 80) /* displayed message length */ @@ -151,6 +153,9 @@ #ifndef KEY_CLEAR # define KEY_CLEAR KEY_UNDEF_BASE-10 #endif +#ifndef KEY_RESIZE +# define KEY_RESIZE KEY_UNDEF_BASE-11 +#endif /**/ #if (BSD || V9) && !__NetBSD__ && !__FreeBSD__ && !__APPLE__ @@ -184,6 +189,4 @@ # endif /* if UNIXPC */ #endif /* if !TERMINFO */ -#define INPUT_PROMPT "$ " - #endif /* CSCOPE_CONSTANTS_H */ diff --git a/src/display.c b/src/display.c index 6c68c67..cb4efa0 100644 --- a/src/display.c +++ b/src/display.c @@ -52,6 +52,12 @@ #include #include +static const char appendprompt[] = "Append to file: "; +static const char pipeprompt[] = "Pipe to shell command: "; +static const char readprompt[] = "Read from file: "; +static const char toprompt[] = "To: "; +static const char inputprompt[] = "$ "; + int subsystemlen = sizeof("Subsystem")-1; /* OGS subsystem name display field length */ int booklen = sizeof("Book")-1; /* OGS book name display field length */ int filelen = sizeof("File")-1; /* file name display field length */ @@ -202,7 +208,8 @@ static inline void display_mode(){ } static inline void display_command_field(){ - mvwprintw(winput, 0, 0, INPUT_PROMPT); + mvwaddstr(winput, 0, 0, inputprompt); + waddstr(winput, rl_line_buffer); } static inline void display_results(){ @@ -228,10 +235,10 @@ static inline void display_results(){ /* display the pattern */ if (changing == YES) { - wprintw(wresult, "Change \"%s\" to \"%s\"", Pattern, newpat); + wprintw(wresult, "Change \"%s\" to \"%s\"", input_line, newpat); } else { wprintw(wresult, "%c%s: %s", toupper((unsigned char)fields[field].text2[0]), - fields[field].text2 + 1, Pattern); + fields[field].text2 + 1, input_line); } /* display the column headings */ wmove(wresult, 2, 2); @@ -417,7 +424,7 @@ void display_cursor(void){ int yoffset = 0, xoffset = 0; if(current_window == &winput){ - xoffset = sizeof(INPUT_PROMPT)-1; + xoffset = sizeof(inputprompt)-1 + rl_point; }else if(current_window == &wmode){ yoffset = field; }else if(current_window == &wresult){ @@ -439,16 +446,19 @@ display(void) //drawscrollbar(topline, nextline); /* display the scrollbar */ if(window_change){ - if(window_change & CH_ALL){ + if(window_change == CH_ALL){ display_frame(); } if(window_change & CH_INPUT){ + werase(winput); display_command_field(); } if(window_change & CH_RESULT){ + werase(wresult); display_results(); } if(window_change & CH_MODE){ + werase(wmode); display_mode(); } @@ -479,32 +489,6 @@ verswp_field(void){ current_window = (current_window == &winput) ? &wmode : &winput; } -/* set the cursor position for the field */ -//void -//setfield(void) -//{ -// fldline = FLDLINE + field; -// fldcolumn = strlen(fields[field].text1) + strlen(fields[field].text2) + 3; -//} - -/* move to the current input field */ -// -//void -//atfield(void) -//{ -// wmove(input_fields, fldline, fldcolumn); -//} - -/* move to the changing lines prompt */ - -//void -//atchange(void) -//{ -// wmove(wresult, PRLINE, (int) sizeof(selprompt) - 1); -//} - -/* search for the symbol or text pattern */ - /*ARGSUSED*/ static void jumpback(int sig) @@ -536,15 +520,15 @@ search(void) if (sigsetjmp(env, 1) == 0) { f = fields[field].findfcn; if (f == findregexp || f == findstring) { - findresult = (*f)(Pattern); + findresult = (*f)(input_line); } else { if ((nonglobalrefs = myfopen(temp2, "wb")) == NULL) { cannotopen(temp2); return(NO); } - if ((rc = findinit(Pattern)) == NOERROR) { + if ((rc = findinit(input_line)) == NOERROR) { (void) dbseek(0L); /* read the first block */ - findresult = (*f)(Pattern); + findresult = (*f)(input_line); if (f == findcalledby) funcexist = (*findresult == 'y'); findcleanup(); @@ -582,20 +566,20 @@ search(void) if ((c = getc(refsfound)) == EOF) { if (findresult != NULL) { (void) snprintf(lastmsg, sizeof(lastmsg), "Egrep %s in this pattern: %s", - findresult, Pattern); + findresult, input_line); } else if (rc == NOTSYMBOL) { (void) snprintf(lastmsg, sizeof(lastmsg), "This is not a C symbol: %s", - Pattern); + input_line); } else if (rc == REGCMPERROR) { (void) snprintf(lastmsg, sizeof(lastmsg), "Error in this regcomp(3) regular expression: %s", - Pattern); + input_line); } else if (funcexist == NO) { (void) snprintf(lastmsg, sizeof(lastmsg), "Function definition does not exist: %s", - Pattern); + input_line); } else { (void) snprintf(lastmsg, sizeof(lastmsg), "Could not find the %s: %s", - fields[field].text2, Pattern); + fields[field].text2, input_line); } return(NO); } diff --git a/src/exec.c b/src/exec.c index 2ab611c..ec87b15 100644 --- a/src/exec.c +++ b/src/exec.c @@ -126,6 +126,7 @@ myexecvp(char *a, char **args) askforreturn(); /* wait until the user sees the message */ myexit(1); /* exit the child */ /* NOTREACHED */ + return 0; } /* myfork acts like fork but also handles signals */ diff --git a/src/global.h b/src/global.h index 08f4423..4e7fd65 100644 --- a/src/global.h +++ b/src/global.h @@ -154,7 +154,6 @@ extern BOOL *change; /* change this line */ extern BOOL changing; /* changing text */ extern unsigned int curdispline; extern char newpat[]; /* new pattern */ -extern char Pattern[]; /* symbol or text pattern */ /* crossref.c global data */ extern long dboffset; /* new database offset */ @@ -209,9 +208,10 @@ extern struct keystruct { /* mouse.c global data */ extern BOOL mouse; /* mouse interface */ -/* display.c global data */ -extern int input_available; -extern char input_char; +/* readline.c global data */ +extern char* rl_line_buffer; +extern char input_line[PATLEN + 1]; +extern int rl_point; #if UNIXPC extern BOOL unixpcmouse; /* UNIX PC mouse interface */ @@ -245,6 +245,8 @@ extern BOOL onesearch; /* one search only in line mode */ extern char *reflines; /* symbol reference lines file */ void verswp_field(void); void horswp_field(void); +BOOL interpret(int c); // XXX: probably rename +int handle_input(const char c); void rlinit(void); @@ -299,7 +301,6 @@ void myungetch(int c); void warning(char *text); void writestring(char *s); -BOOL command(int commandc); BOOL infilelist(char *file); BOOL readrefs(char *filename); BOOL search(void); diff --git a/src/input.c b/src/input.c index d26d663..798c57c 100644 --- a/src/input.c +++ b/src/input.c @@ -328,3 +328,247 @@ shellpath(char *out, int limit, char *in) } *out = '\0'; } + +static int +wmode_input(const int c){ + switch (c) { + case KEY_ENTER: + case '\r': + case '\n': + case ctrl('N'): /* go to next input field */ + case KEY_DOWN: + case KEY_RIGHT: + field = (field + 1) % FIELDS; + resetcmd(); + return(NO); + case ctrl('P'): /* go to previous input field */ + case KEY_UP: + case KEY_LEFT: + field = (field + (FIELDS - 1)) % FIELDS; + resetcmd(); + return(NO); + case KEY_HOME: /* go to first input field */ + field = 0; + resetcmd(); + return(NO); + case KEY_LL: /* go to last input field */ + curdispline = disprefs; + return(YES); + } +} + +static int +wresult_input(const int c){ + switch (c) { + case KEY_ENTER: /* open for editing */ + case '\r': + case '\n': + editref(curdispline); + window_change = CH_ALL; + return(YES); + case ctrl('N'): + case KEY_DOWN: + case KEY_RIGHT: + if ((curdispline + 1) < disprefs) { + ++curdispline; + } + return(NO); + case ctrl('P'): + case KEY_UP: + case KEY_LEFT: + if (curdispline) { + --curdispline; + } + return(NO); + case KEY_HOME: + curdispline = 0; + return(NO); + case KEY_LL: + field = FIELDS - 1; + resetcmd(); + return(NO); + default: + char *e; + if ((e = strchr(dispchars, c))) + editref(e - dispchars); + } +} + +static int +global_input(const int c){ + switch(c){ + case ' ': /* display next page */ + case '+': + case ctrl('V'): + case KEY_NPAGE: + if (totallines == 0) { return(NO); } /* don't redisplay if there are no lines */ + /* XXX: figure out whether this comment is useful or not */ + /* NOTE: seekline() is not used to move to the next + * page because display() leaves the file pointer at + * the next page to optimize paging forward + */ + curdispline = 0; + break; + case ctrl('H'): /* display previous page */ + case '-': + case KEY_PPAGE: + if (totallines == 0) { return(NO); } /* don't redisplay if there are no lines */ + curdispline = 0; + /* if there are only two pages, just go to the other one */ + if (totallines <= 2 * mdisprefs) { + break; + } + /* if on first page but not at beginning, go to beginning */ + nextline -= mdisprefs; /* already at next page */ + if (nextline > 1 && nextline <= mdisprefs) { + nextline = 1; + } else { + nextline -= mdisprefs; + if (nextline < 1) { + nextline = totallines - mdisprefs + 1; + if (nextline < 1) { + nextline = 1; + } + } + } + seekline(nextline); + break; + case '>': /* write or append the lines to a file */ + break; // XXX + //char filename[PATHLEN + 1]; + //char* s; + //char ch; + //FILE* file; + //if (totallines == 0) { + // postmsg("There are no lines to write to a file"); + // return(NO); + //} + //move(PRLINE, 0); + ////addstr("Write to file: "); // XXX + //s = "w"; + //if ((ch = mygetch()) == '>') { + //move(PRLINE, 0); + ////addstr(appendprompt); // XXX fix + ////ch = '\0'; + ////s = "a"; + ////} + ////if (ch != '\r' && mygetline("", newpat, COLS - sizeof(appendprompt), c, NO) > 0) { + //// shellpath(filename, sizeof(filename), newpat); + //// if ((file = myfopen(filename, s)) == NULL) { + //// cannotopen(filename); + //// } else { + //// seekline(1); + //// while ((ch = getc(refsfound)) != EOF) { + //// putc(ch, file); + //// } + //// seekline(topline); + //// fclose(file); + //// } + ////} + ////clearprompt(); + return(NO); /* return to the previous field */ + case '<': /* read lines from a file */ + break; // XXX + move(PRLINE, 0); + //addstr(readprompt); // XXX fix + //if (mygetline("", newpat, COLS - sizeof(readprompt), '\0', NO) > 0) { + // clearprompt(); + // shellpath(filename, sizeof(filename), newpat); + // if (readrefs(filename) == NO) { + // postmsg2("Ignoring an empty file"); + // return(NO); + // } + // window_change |= CH_INPUT; + // return(YES); + //} + //clearprompt(); + return(NO); + case '|': /* pipe the lines to a shell command */ + case '^': + break; // XXX fix + if (totallines == 0) { + postmsg("There are no lines to pipe to a shell command"); + return(NO); + } + /* get the shell command */ + move(PRLINE, 0); + //addstr(pipeprompt); + //if (mygetline("", newpat, COLS - sizeof(pipeprompt), '\0', NO) == 0) { + // clearprompt(); + // return(NO); + //} + ///* if the ^ command, redirect output to a temp file */ + //if (commandc == '^') { + // strcat(strcat(newpat, " >"), temp2); + // /* HBB 20020708: somebody might have even + // * their non-interactive default shells + // * complain about clobbering + // * redirections... --> delete before + // * overwriting */ + // remove(temp2); + //} + //exitcurses(); + //if ((file = mypopen(newpat, "w")) == NULL) { + // fprintf(stderr, "cscope: cannot open pipe to shell command: %s\n", newpat); + //} else { + // seekline(1); + // while ((c = getc(refsfound)) != EOF) { + // putc(c, file); + // } + // seekline(topline); + // mypclose(file); + //} + //if (commandc == '^') { + // if (readrefs(temp2) == NO) { + // postmsg("Ignoring empty output of ^ command"); + // } + //} + //askforreturn(); + //entercurses(); + break; + case '!': /* shell escape */ + execute(shell, shell, NULL); + seekline(topline); + break; + case KEY_RESIZE: + /* XXX: fill in*/ + break; + case ctrl('L'): /* redraw screen */ + case KEY_CLEAR: + window_change = CH_ALL; + return(NO); + case '?': /* help */ + clear(); + help(); + clear(); + seekline(topline); + break; + case ctrl('E'): /* edit all lines */ + editall(); + break; + } + + return 0; +} + +extern const void const* winput; +extern const void const* wmode; +extern const void const* wresult; +extern const void const* const* current_window; + +int +handle_input(const char c){ + /* --- global --- */ + const int r = global_input(c); + if(r){ return r; } + /* --- mode specific --- */ + if(*current_window == winput){ + return interpret(c); + }else if(*current_window == wmode){ + return wmode_input(c); + }else if(*current_window == wresult){ + return wresult_input(c); + } + + return 0; +} diff --git a/src/main.c b/src/main.c index 7d73b5a..66a69ae 100644 --- a/src/main.c +++ b/src/main.c @@ -153,6 +153,256 @@ siginit(void){ } } +void +cannotopen(char *file) +{ + posterr("Cannot open file %s", file); +} + +/* FIXME MTE - should use postfatal here */ +void +cannotwrite(char *file) +{ + char msg[MSGLEN + 1]; + + snprintf(msg, sizeof(msg), "Removed file %s because write failed", file); + + myperror(msg); /* display the reason */ + + unlink(file); + myexit(1); /* calls exit(2), which closes files */ +} + + +/* set up the digraph character tables for text compression */ +static void +initcompress(void) +{ + int i; + + if (compress == YES) { + for (i = 0; i < 16; ++i) { + dicode1[(unsigned char) (dichar1[i])] = i * 8 + 1; + } + for (i = 0; i < 8; ++i) { + dicode2[(unsigned char) (dichar2[i])] = i + 1; + } + } +} + +/* skip the list in the cross-reference file */ + +static void +skiplist(FILE *oldrefs) +{ + int i; + + if (fscanf(oldrefs, "%d", &i) != 1) { + postfatal("cscope: cannot read list size from file %s\n", reffile); + /* NOTREACHED */ + } + while (--i >= 0) { + if (fscanf(oldrefs, "%*s") != 0) { + postfatal("cscope: cannot read list name from file %s\n", reffile); + /* NOTREACHED */ + } + } +} + + +/* enter curses mode */ +void +entercurses(void) +{ + incurses = YES; +#ifndef __MSDOS__ /* HBB 20010313 */ + nonl(); /* don't translate an output \n to \n\r */ +#endif + raw(); /* single character input */ + noecho(); /* don't echo input characters */ + clear(); /* clear the screen */ + mouseinit(); /* initialize any mouse interface */ + drawscrollbar(topline, nextline); +} + + +/* exit curses mode */ +void +exitcurses(void) +{ + /* clear the bottom line */ + move(LINES - 1, 0); + clrtoeol(); + refresh(); + + /* exit curses and restore the terminal modes */ + endwin(); + incurses = NO; + + /* restore the mouse */ + mousecleanup(); + fflush(stdout); +} + +/* cleanup and exit */ +void +myexit(int sig) +{ + /* Close file before unlinking it. DOS absolutely needs it */ + if (refsfound != NULL){ + fclose(refsfound); + } + + /* remove any temporary files */ + if (temp1[0] != '\0') { + unlink(temp1); + unlink(temp2); + rmdir(tempdirpv); + } + /* restore the terminal to its original mode */ + if (incurses == YES) { + exitcurses(); + } + /* dump core for debugging on the quit signal */ + if (sig == SIGQUIT) { + abort(); + } + /* HBB 20000421: be nice: free allocated data */ + freefilelist(); + freeinclist(); + freesrclist(); + freecrossref(); + free_newbuildfiles(); + + if( remove_symfile_onexit == YES ) { + unlink( reffile ); + unlink( invname ); + unlink( invpost ); + } + + exit(sig); +} + +static inline void readenv(void){ + editor = mygetenv("EDITOR", EDITOR); + editor = mygetenv("VIEWER", editor); /* use viewer if set */ + editor = mygetenv("CSCOPE_EDITOR", editor); /* has last word */ + home = mygetenv("HOME", HOME); + shell = mygetenv("SHELL", SHELL); + lineflag = mygetenv("CSCOPE_LINEFLAG", LINEFLAG); + lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0; + tmpdir = mygetenv("TMPDIR", TMPDIR); +} + +static inline void linemode_event_loop(void){ + int c; + + if (*input_line != '\0') { /* do any optional search */ + if (search() == YES) { + /* print the total number of lines in + * verbose mode */ + if (verbosemode == YES) + printf("cscope: %d lines\n", + totallines); + + while ((c = getc(refsfound)) != EOF) + putchar(c); + } + } + if (onesearch == YES) { + myexit(0); + /* NOTREACHED */ + } + + for (char *s;;) { + char buf[PATLEN + 2]; + + printf(">> "); + fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + myexit(0); + } + /* remove any trailing newline character */ + if (*(s = buf + strlen(buf) - 1) == '\n') { + *s = '\0'; + } + switch (*buf) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* samuel only */ + field = *buf - '0'; + strcpy(input_line, buf + 1); + if (search() == NO) { + printf("Unable to search database\n"); + } else { + printf("cscope: %d lines\n", totallines); + while ((c = getc(refsfound)) != EOF) { + putchar(c); + } + } + break; + + case 'c': /* toggle caseless mode */ + case ctrl('C'): + if (caseless == NO) { + caseless = YES; + } else { + caseless = NO; + } + egrepcaseless(caseless); + break; + + case 'r': /* rebuild database cscope style */ + case ctrl('R'): + freefilelist(); + makefilelist(); + /* FALLTHROUGH */ + + case 'R': /* rebuild database samuel style */ + rebuild(); + putchar('\n'); + break; + + case 'C': /* clear file names */ + freefilelist(); + putchar('\n'); + break; + + case 'F': /* add a file name */ + strcpy(path, buf + 1); + if (infilelist(path) == NO && + (s = inviewpath(path)) != NULL) { + addsrcfile(s); + } + putchar('\n'); + break; + + case 'q': /* quit */ + case ctrl('D'): + case ctrl('Z'): + myexit(0); + + default: + fprintf(stderr, "cscope: unknown command '%s'\n", buf); + break; + } + } +} + +static inline void screenmode_event_loop(void){ + for (;;) { + display(); + if(handle_input(getch())){ break; } + } +} + int main(int argc, char **argv) { @@ -334,7 +584,7 @@ main(int argc, char **argv) switch (i) { case 'p': /* file path components to display */ if (*s < '0' || *s > '9') { - posterr("cscope: -p option in file %s: missing or invalid numeric value\n", namefile); + posterr("cscope: -p option in file %s: missing or invalid numeric value\n", namefile); } dispcomponents = atoi(s); @@ -417,8 +667,8 @@ main(int argc, char **argv) askforreturn(); } /* do any optional search */ - if (*Pattern != '\0') { - command(ctrl('Y')); /* search */ + if (*input_line != '\0') { + //command(ctrl('Y')); /* search */ // XXX: fix } else if (reflines != NULL) { /* read any symbol reference lines file */ readrefs(reflines); @@ -430,268 +680,3 @@ main(int argc, char **argv) /* NOTREACHED */ return 0; /* avoid warning... */ } - -void -cannotopen(char *file) -{ - posterr("Cannot open file %s", file); -} - -/* FIXME MTE - should use postfatal here */ -void -cannotwrite(char *file) -{ - char msg[MSGLEN + 1]; - - snprintf(msg, sizeof(msg), "Removed file %s because write failed", file); - - myperror(msg); /* display the reason */ - - unlink(file); - myexit(1); /* calls exit(2), which closes files */ -} - - -/* set up the digraph character tables for text compression */ -static void -initcompress(void) -{ - int i; - - if (compress == YES) { - for (i = 0; i < 16; ++i) { - dicode1[(unsigned char) (dichar1[i])] = i * 8 + 1; - } - for (i = 0; i < 8; ++i) { - dicode2[(unsigned char) (dichar2[i])] = i + 1; - } - } -} - -/* skip the list in the cross-reference file */ - -static void -skiplist(FILE *oldrefs) -{ - int i; - - if (fscanf(oldrefs, "%d", &i) != 1) { - postfatal("cscope: cannot read list size from file %s\n", reffile); - /* NOTREACHED */ - } - while (--i >= 0) { - if (fscanf(oldrefs, "%*s") != 0) { - postfatal("cscope: cannot read list name from file %s\n", reffile); - /* NOTREACHED */ - } - } -} - - -/* enter curses mode */ -void -entercurses(void) -{ - incurses = YES; -#ifndef __MSDOS__ /* HBB 20010313 */ - nonl(); /* don't translate an output \n to \n\r */ -#endif - raw(); /* single character input */ - noecho(); /* don't echo input characters */ - clear(); /* clear the screen */ - mouseinit(); /* initialize any mouse interface */ - drawscrollbar(topline, nextline); -} - - -/* exit curses mode */ -void -exitcurses(void) -{ - /* clear the bottom line */ - move(LINES - 1, 0); - clrtoeol(); - refresh(); - - /* exit curses and restore the terminal modes */ - endwin(); - incurses = NO; - - /* restore the mouse */ - mousecleanup(); - fflush(stdout); -} - -/* cleanup and exit */ -void -myexit(int sig) -{ - /* HBB 20010313; close file before unlinking it. Unix may not care - * about that, but DOS absolutely needs it */ - if (refsfound != NULL) - fclose(refsfound); - - /* remove any temporary files */ - if (temp1[0] != '\0') { - unlink(temp1); - unlink(temp2); - rmdir(tempdirpv); - } - /* restore the terminal to its original mode */ - if (incurses == YES) { - exitcurses(); - } - /* dump core for debugging on the quit signal */ - if (sig == SIGQUIT) { - abort(); - } - /* HBB 20000421: be nice: free allocated data */ - freefilelist(); - freeinclist(); - freesrclist(); - freecrossref(); - free_newbuildfiles(); - - if( remove_symfile_onexit == YES ) { - unlink( reffile ); - unlink( invname ); - unlink( invpost ); - } - - exit(sig); -} - -static inline void readenv(void){ - editor = mygetenv("EDITOR", EDITOR); - editor = mygetenv("VIEWER", editor); /* use viewer if set */ - editor = mygetenv("CSCOPE_EDITOR", editor); /* has last word */ - home = mygetenv("HOME", HOME); - shell = mygetenv("SHELL", SHELL); - lineflag = mygetenv("CSCOPE_LINEFLAG", LINEFLAG); - lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0; - tmpdir = mygetenv("TMPDIR", TMPDIR); -} - -static inline void linemode_event_loop(void){ - int c; - - if (*Pattern != '\0') { /* do any optional search */ - if (search() == YES) { - /* print the total number of lines in - * verbose mode */ - if (verbosemode == YES) - printf("cscope: %d lines\n", - totallines); - - while ((c = getc(refsfound)) != EOF) - putchar(c); - } - } - if (onesearch == YES) { - myexit(0); - /* NOTREACHED */ - } - - for (char *s;;) { - char buf[PATLEN + 2]; - - printf(">> "); - fflush(stdout); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - myexit(0); - } - /* remove any trailing newline character */ - if (*(s = buf + strlen(buf) - 1) == '\n') { - *s = '\0'; - } - switch (*buf) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': /* samuel only */ - field = *buf - '0'; - strcpy(Pattern, buf + 1); - if (search() == NO) { - printf("Unable to search database\n"); - } else { - printf("cscope: %d lines\n", totallines); - while ((c = getc(refsfound)) != EOF) { - putchar(c); - } - } - break; - - case 'c': /* toggle caseless mode */ - case ctrl('C'): - if (caseless == NO) { - caseless = YES; - } else { - caseless = NO; - } - egrepcaseless(caseless); - break; - - case 'r': /* rebuild database cscope style */ - case ctrl('R'): - freefilelist(); - makefilelist(); - /* FALLTHROUGH */ - - case 'R': /* rebuild database samuel style */ - rebuild(); - putchar('\n'); - break; - - case 'C': /* clear file names */ - freefilelist(); - putchar('\n'); - break; - - case 'F': /* add a file name */ - strcpy(path, buf + 1); - if (infilelist(path) == NO && - (s = inviewpath(path)) != NULL) { - addsrcfile(s); - } - putchar('\n'); - break; - - case 'q': /* quit */ - case ctrl('D'): - case ctrl('Z'): - myexit(0); - - default: - fprintf(stderr, "cscope: unknown command '%s'\n", buf); - break; - } - } -} - -static inline void screenmode_event_loop(void){ - int c; - - for (;;) { - display(); - - c = mygetch(); - input_available = 1; - rl_callback_read_char(); - - /* exit if the quit command is entered */ - if (c == EOF || c == ctrl('D')) { - break; - } - if (c == ctrl('Z')) { - kill(0, SIGTSTP); - continue; - } - - } -} diff --git a/src/opt.c b/src/opt.c index 58bee40..b920a06 100644 --- a/src/opt.c +++ b/src/opt.c @@ -55,7 +55,7 @@ char ** parse_options(int *argc, char **argv) cscope: pattern too long, cannot be > \ %d characters\n", PATLEN); } - strcpy(Pattern, optarg); + strcpy(input_line, optarg); break; case 'b': /* only build the cross-reference */ buildonly = YES; diff --git a/src/readline.c b/src/readline.c index 1e04e2e..2a92974 100644 --- a/src/readline.c +++ b/src/readline.c @@ -1,31 +1,128 @@ +#include #include #include "global.h" +#include "build.h" -int input_available = 0; -char input_char; +extern int LINES; // XXX -static void getc_function(FILE* ignore){ +static int input_available = 0; +static char input_char; +char input_line[PATLEN + 1]; + +BOOL do_terminate = NO; + +BOOL interpret(int c){ + input_char = c; + input_available = 1; + rl_callback_read_char(); + + return do_terminate; +} + +static int getc_function(FILE* ignore){ input_available = 0; return (int)input_char; } -static input_available_hook(){ +static int input_available_hook(){ return input_available; } static void redisplay_function(){ window_change |= CH_INPUT; - //display(); } static void callback_handler(char* line){ - // ?! + strncpy(input_line, line, PATLEN); + search(); } -int proxy(int i, int h){ +static int horswp_field_proxy(int i, int h){ horswp_field(); } +static int verswp_field_proxy(int i, int h){ + verswp_field(); +} + +static int interpret_break(){ + do_terminate = YES; +} + +static int ctrl_z(){ + kill(0, SIGTSTP); +} + +static int toggle_caseless(){ + if (caseless == NO) { + caseless = YES; + postmsg2("Caseless mode is now ON"); + } else { + caseless = NO; + postmsg2("Caseless mode is now OFF"); + } + egrepcaseless(caseless); /* turn on/off -i flag */ +} + +static int rebuild_reference(){ + if (isuptodate == YES) { + postmsg("The -d option prevents rebuilding the symbol database"); + return(NO); + } + exitcurses(); + freefilelist(); /* remake the source file list */ + makefilelist(); + rebuild(); + if (errorsfound == YES) { + errorsfound = NO; + askforreturn(); + } + entercurses(); + clearmsg(); /* clear any previous message */ + totallines = 0; + disprefs = 0; + topline = nextline = 1; + return(YES); +} + +static int process_mouse(){ + int i; + MOUSE* p; + if ((p = getmouseaction(DUMMYCHAR)) == NULL) { + return(NO); /* unknown control sequence */ + } + /* if the button number is a scrollbar tag */ + if (p->button == '0') { + //scrollbar(p); // XXX + return(NO); + } + /* ignore a sweep */ + if (p->x2 >= 0) { + return(NO); + } + /* if this is a line selection */ + if (p->y1 > FLDLINE) { + + /* find the selected line */ + /* note: the selection is forced into range */ + for (i = disprefs - 1; i > 0; --i) { + if (p->y1 >= displine[i]) { + return(NO); + } + } + /* display it in the file with the editor */ + editref(i); + } else { /* this is an input field selection */ + field = p->y1 - FLDLINE; + /* force it into range */ + if (field >= FIELDS) { + field = FIELDS - 1; + } + resetcmd(); + return(NO); + } +} + void rlinit(){ rl_catch_signals = 0; rl_catch_sigwinch = 0; @@ -38,5 +135,16 @@ void rlinit(){ rl_redisplay_function = redisplay_function; rl_callback_handler_install("", callback_handler); - rl_bind_key('\t', proxy); + rl_bind_key('\t', horswp_field_proxy); + rl_bind_key('%', verswp_field_proxy); + + rl_bind_key(EOF, interpret_break); + rl_bind_key(ctrl('D'), interpret_break); //XXX: why the fuck does it not work if its the first char? + rl_bind_key(ctrl('Z'), ctrl_z); + rl_bind_key(ctrl('Z'), toggle_caseless); + rl_bind_key(ctrl('R'), rebuild_reference); + rl_bind_key(ESC, process_mouse); /* possible unixpc mouse selection */ + rl_bind_key(ctrl('X'), process_mouse); /* mouse selection */ + + //rl_bind_key(ctrl('\\'), /**/); /* bypass bindings */ }