1 /* GNUPLOT - readline.c */
3 * Copyright (C) 1986 - 1993 Thomas Williams, Colin Kelley
5 * Permission to use, copy, and distribute this software and its
6 * documentation for any purpose with or without fee is hereby granted,
7 * provided that the above copyright notice appear in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation.
11 * Permission to modify the software is granted, but not the right to
12 * distribute the modified code. Modifications are to be distributed
13 * as patches to released version.
15 * This software is provided "as is" without express or implied warranty.
25 * Gershon Elber and many others.
27 * Ed Breen (Jun 10 08:11:14 EST 1996)
28 * Stripped down: EiC port.
29 * Added standalone capability -- for testing and experimenting:
30 * To make the stand alone version of readline:
31 * gcc -D_STANDALONE -Wall -o readline readline.c
32 * Added a limiter to the history recording mechanism:
33 * The default limit means that only the last 500 lines
34 * can be recalled. This can be set via the macro _HistLimit.
35 * Note, by setting _HistLimit to 0, effectively turns off the
37 * gcc -D_STANDALONE -D_HistLimit=0 -Wall -o readline readline.c
38 * Added tab recognition -- no, not file completion.
40 * void EiC_show_history(FILE *fp)
41 * outputs the history list to stream fp.
43 * returns a pointer to the last entered string in the history
44 * list. Will return NULL if no entry exists.
45 * Do not attempt to free this space, it is under control
47 * Added bracket balancing routine:
48 * void backupTo(char to, char from);
49 * Optimized for speedy cursor movements:
51 * ultrix, solaris, dec alpha, sunos, linux, irix-5.3, irix-6.x.
52 * Ed Breen (July 17 1999)
53 * Added win95, win98, NT win32 support
54 * Ed Breen (July 16 2000)
58 /* a small version of GNU's readline */
59 /* this is not the BASH or GNU EMACS version of READLINE due to Copyleft
61 /* do not need any terminal capabilities except , */
64 /* NANO-EMACS line editing facility */
65 /* printable characters print as themselves (insert not overwrite) */
66 /* ^A moves to the beginning of the line */
67 /* ^B moves back a single character */
68 /* ^E moves to the end of the line */
69 /* ^F moves forward a single character */
70 /* ^K kills from current position to the end of line */
71 /* ^P moves back through history */
72 /* ^N moves forward through history */
73 /* ^H and DEL delete the previous character */
74 /* ^D deletes the current character, or EOF if line is empty */
75 /* ^L/^R redraw line in case it gets trashed */
76 /* ^U kills the entire line */
77 /* ^W kills last word */
78 /* LF and CR return the entire line regardless of the cursor postition */
79 /* EOF with an empty line returns (char *)NULL */
81 /* all other characters are ignored */
85 /*#define _POSIX_SOURCE*/
98 # define special_getc() msdos_getch()
99 static char msdos_getch();
106 #define special_getc() ansi_getc()
107 static int ansi_getc();
109 /* watch out for SV4 and BSD+4.3 stuff */
122 #ifndef CLOCKS_PER_SEC
123 #define CLOCKS_PER_SEC 1000000
127 /* stubbs added by Ed Breen */
128 #define ralloc(x,y,z) realloc(x,y)
129 #define alloc(x,y) malloc(x)
130 #define int_error(text,code) {fprintf(stderr,"Fatal error..\n");\
131 fprintf(stderr,"%s\n",text);\
132 fprintf(stderr,"...now exiting to system ...\n");\
137 static struct termios orig_termio, rl_termio;
139 /* ULTRIX defines VRPRNT instead of VREPRINT */
140 #if defined(VRPRNT) && !defined(VREPRINT)
141 #define VREPRINT VRPRNT
144 /* define characters to use with our input character handler */
145 static char term_chars[NCCS];
147 static int term_set = 0; /* =1 if rl_termio set */
152 #define MAXBUF 512 /* initial size and increment of input line length */
153 #define BACKSPACE 0x08 /* ^H */
157 #define TABSTOPS 4 /* number of spaces per tab stop */
165 static struct hist *history = NULL; /* no history yet */
166 static struct hist *EndHist = NULL; /* end of history list */
167 static struct hist *cur_entry = NULL;
170 static char *cur_line; /* current contents of the line */
171 static int line_len=0;
172 static int cur_pos = 0; /* current position of the cursor */
173 static int max_pos = 0; /* maximum character position */
174 static int HistLineNo = 0; /* Current Line Number in history list */
176 static void fix_line (void) ;
177 static void redraw_line (char *prompt) ;
178 static void clear_line (char *prompt) ;
179 static void clear_eoline (void) ;
180 static void copy_line (char *line) ;
181 static void set_termio (void) ;
182 static void reset_termio (void) ;
183 static int ansi_getc (void) ;
184 static void user_putc (char ch) ;
185 static int user_putsn(char *str, int n) ;
187 static void extend_cur_line (void) ;
188 static void backupTo(char to, char from);
189 static char _BS = BACKSPACE;
192 #define backspace() _putch(BACKSPACE)
194 #define backspace() write(STDIN_FILENO,&_BS,1)
197 #define user_puts(x) user_putsn(x,strlen(x))
200 void delay(clock_t d)
202 clock_t et = clock() + d;
206 static void user_putc(char ch)
211 write(STDIN_FILENO,&ch,1);
216 static int user_putsn(char *str, int n)
223 rv = write(STDIN_FILENO,str,n);
228 static void extend_cur_line()
232 /* extent input line length */
233 new_line=ralloc(cur_line, line_len+MAXBUF, NULL);
236 int_error("Can't extend readline length", NO_CARET);
243 unsigned char * EiC_readline(char *prompt)
246 /* start with a string of MAXBUF chars */
247 char * editLine(char *);
253 cur_line=alloc((unsigned long)MAXBUF, "readline");
256 /* set the termio so we can do our own input processing */
259 /* print the prompt */
266 return editLine(prompt);
270 char * editLine(char *prompt)
272 /* The line to be edited is stored in cur_line.*/
277 cur_char = special_getc();
279 if(isprint(cur_char) || (((unsigned char)cur_char > 0x7f) &&
280 cur_char != EOF) || cur_char == '\t') {
282 if(cur_char == '\t') {
288 if(max_pos+inc>=line_len)
291 for(i=max_pos+inc-1; i-inc>=cur_pos; i--) {
292 cur_line[i] = cur_line[i-inc];
297 cur_line[cur_pos++] = cur_char;
299 if (cur_pos < max_pos)
301 cur_line[max_pos] = '\0';
303 case ')':backupTo('(',')');break;
304 case ']':backupTo('[',']');break;
307 } else if(cur_char == term_chars[VERASE] ){ /* DEL? */
312 for(i=cur_pos; i<max_pos; i++)
313 cur_line[i] = cur_line[i+1];
317 } else if(cur_char == term_chars[VEOF] ){ /* ^D? */
319 copy_line("to exit EiC, enter :exit\n");
325 if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
327 for(i=cur_pos; i<max_pos; i++)
328 cur_line[i] = cur_line[i+1];
333 } else if(cur_char == term_chars[VKILL] ){ /* ^U? */
336 } else if(cur_char == term_chars[VWERASE] ){ /* ^W? */
337 while((cur_pos > 0) &&
338 (cur_line[cur_pos-1] == SPACE)) {
342 while((cur_pos > 0) &&
343 (cur_line[cur_pos-1] != SPACE)) {
351 } else if(cur_char == term_chars[VREPRINT] ){ /* ^R? */
352 user_putc(NEWLINE); /* go to a fresh line */
356 } else if(cur_char == term_chars[VSUSP]) {
360 /* process stops here */
363 /* print the prompt */
367 /* do normal editing commands */
368 /* some of these are also done above */
373 return((char *)NULL);
387 while(cur_pos < max_pos) {
388 user_putc(cur_line[cur_pos]);
393 if(cur_pos < max_pos) {
394 user_putc(cur_line[cur_pos]);
404 if(history != NULL) {
405 if(cur_entry == NULL) {
408 copy_line(cur_entry->line);
409 } else if(cur_entry->prev != NULL) {
410 cur_entry = cur_entry->prev;
412 copy_line(cur_entry->line);
420 if(cur_entry != NULL) {
421 cur_entry = cur_entry->next;
423 if(cur_entry != NULL)
424 copy_line(cur_entry->line);
426 cur_pos = max_pos = 0;
432 user_putc(NEWLINE); /* go to a fresh line */
440 for(i=cur_pos; i<max_pos; i++)
441 cur_line[i] = cur_line[i+1];
449 return((char *)NULL);
451 if(cur_pos < max_pos) {
452 for(i=cur_pos; i<max_pos; i++)
453 cur_line[i] = cur_line[i+1];
462 while((cur_pos > 0) &&
463 (cur_line[cur_pos-1] == SPACE)) {
467 while((cur_pos > 0) &&
468 (cur_line[cur_pos-1] != SPACE)) {
478 cur_line[max_pos+1] = '\0';
479 cur_line = (char *)ralloc(cur_line,
481 long)(strlen(cur_line)+2),
495 /* fix up the line from cur_pos to max_pos */
496 /* do not need any terminal capabilities except backspace, */
497 /* and space overwrites a character */
498 static void fix_line()
502 /* write tail of string */
503 user_putsn(&cur_line[cur_pos],max_pos - cur_pos);
506 /* write a space at the end of the line in case we deleted one */
509 /* backup to original position */
510 for(i=max_pos+1; i>cur_pos; i--)
515 /* redraw the entire line, putting the cursor where it belongs */
516 static void redraw_line(char *prompt)
523 /* put the cursor where it belongs */
524 for(i=max_pos; i>cur_pos; i--)
528 /* clear cur_line and the screen line */
529 static void clear_line(char *prompt)
533 memset(cur_line,0,max_pos);
535 for(i=cur_pos; i>0; i--)
538 for(i=0; i<max_pos; i++)
548 static void backupTo(char to, char from)
551 int k = 1,i = cur_pos-1;
556 if(cur_line[i] == '\'') {
562 }else if(cur_line[i] == '\"') {
570 if(cur_line[i] == to && !cmode) {
573 }else if(cur_line[i] == from && !cmode)
580 delay(CLOCKS_PER_SEC / 2);
582 user_putsn(&cur_line[i],cur_pos - i);
586 /* clear to end of line and the screen end of line */
587 static void clear_eoline()
590 for(i=cur_pos; i<max_pos; i++)
593 for(i=cur_pos; i<max_pos; i++)
595 for(i=cur_pos; i<max_pos; i++)
599 /* copy line to cur_line, draw it and set cur_pos and max_pos */
600 static void copy_line(char *line)
602 while(strlen(line)+1>line_len) {
605 strcpy(cur_line, line);
607 cur_pos = max_pos = strlen(cur_line);
610 /* add line to the history */
611 #ifndef _HistLimit /* history limiter */
612 #define _HistLimit 500
615 void EiC_add_history(unsigned char *line)
617 static unsigned int limit = 0;
620 if(limit == _HistLimit && EndHist) {
623 EndHist = EndHist->next;
624 EndHist->prev = NULL;
626 entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
629 entry->line = alloc((unsigned long)(strlen(line)+1),"history");
630 strcpy(entry->line, line);
632 entry->prev = history;
634 if(history != NULL) {
635 history->next = entry;
636 } else /* get first entry */
643 int EiC_getHistLineNo()
648 void EiC_save_history(FILE *to, int from)
650 int cl = HistLineNo - 1;
656 fprintf(to,"%s\n",p->line);
661 /* show all history lines */
662 void EiC_show_history(FILE *fp)
674 int EiC_load_history(char * fname, int prompt)
682 FILE *fp = fopen(fname,"r");
686 while(fgets(buff,BufSz-2,fp)) {
687 for(i=0;buff[i] && buff[i] != '\n';++i)
693 printf("Re-enter [%s] (Y/N/E)?",buff);
694 switch(special_getc()) {
703 line = editLine("edit: ");
705 EiC_add_history(line);
715 EiC_add_history(buff);
723 printf("added %d lines\n",HistLineNo);
732 /* Convert Arrow keystrokes to Control characters: */
733 static char msdos_getch()
736 if (c == 224 || c== 0) {
737 c = _getch(); /* Get the extended code. */
739 case 75: /* Left Arrow. */
742 case 77: /* Right Arrow. */
745 case 72: /* Up Arrow. */
748 case 80: /* Down Arrow. */
751 case 115: /* Ctl Left Arrow. */
755 case 116: /* Ctl Right Arrow. */
759 case 83: /* Delete */
766 } else if (c == 033) { /* ESC */
772 static void set_termio() {}
773 static void reset_termio() {}
777 /* Convert ANSI arrow keys to control characters */
778 static int ansi_getc()
782 c = getc(stdin); /* check for CSI */
784 c = getc(stdin); /* get command character */
786 case 'D': /* left arrow key */
789 case 'C': /* right arrow key */
792 case 'A': /* up arrow key */
796 case 'B': /* down arrow key */
805 /* set termio so we can do our own input processing */
806 static void set_termio()
809 tcgetattr(0, &orig_termio);
810 rl_termio = orig_termio;
811 rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK/*|IUCLC*/|IXON|IXOFF);
812 rl_termio.c_iflag |= (IGNBRK|IGNPAR);
813 /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
814 rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
815 rl_termio.c_lflag |= (ISIG);
816 rl_termio.c_cc[VMIN] = 1;
817 rl_termio.c_cc[VTIME] = 0;
818 term_chars[VERASE] = orig_termio.c_cc[VERASE];
819 term_chars[VEOF] = orig_termio.c_cc[VEOF];
820 term_chars[VKILL] = orig_termio.c_cc[VKILL];
821 term_chars[VWERASE] = orig_termio.c_cc[VWERASE];
822 term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
823 term_chars[VSUSP] = orig_termio.c_cc[VSUSP];
824 /* disable suspending process on ^Z */
825 rl_termio.c_cc[VSUSP] = 0;
826 tcsetattr(0, TCSADRAIN, &rl_termio);
832 static void reset_termio()
835 tcsetattr(0, TCSADRAIN, &orig_termio);
846 printf("**Press ^D in empty line to exit**\n");
848 line = EiC_readline("$$> ");
851 EiC_add_history(line);
855 printf("\n-----------------\n");
856 EiC_show_history(stdout);