From f5f14dca0600a5b5c0e225a1eee05d05b69e768b Mon Sep 17 00:00:00 2001
From: anon <anon@anon.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 <stdarg.h>
 #include <assert.h>
 
+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 <stdio.h>
 #include <readline/readline.h>
 #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 */
 }