Icons are changed
[gnuplot] / src / readline.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: readline.c,v 1.41.2.2 2008/12/12 06:57:50 sfeam Exp $"); }
3 #endif
4
5 /* GNUPLOT - readline.c */
6
7 /*[
8  * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
9  *
10  * Permission to use, copy, and distribute this software and its
11  * documentation for any purpose with or without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and
13  * that both that copyright notice and this permission notice appear
14  * in supporting documentation.
15  *
16  * Permission to modify the software is granted, but not the right to
17  * distribute the complete modified source code.  Modifications are to
18  * be distributed as patches to the released version.  Permission to
19  * distribute binaries produced by compiling modified sources is granted,
20  * provided you
21  *   1. distribute the corresponding source modifications from the
22  *    released version in the form of a patch file along with the binaries,
23  *   2. add special version identification to distinguish your version
24  *    in addition to the base release version number,
25  *   3. provide your name and address as the primary contact for the
26  *    support of your modified version, and
27  *   4. retain our contact information in regard to use of the base
28  *    software.
29  * Permission to distribute the released version of the source code along
30  * with corresponding source modifications in the form of a patch file is
31  * granted with same provisions 2 through 4 for binary distributions.
32  *
33  * This software is provided "as is" without express or implied warranty
34  * to the extent permitted by applicable law.
35 ]*/
36
37
38 /*
39  * AUTHORS
40  *
41  *   Original Software:
42  *     Tom Tkacik
43  *
44  *   Msdos port and some enhancements:
45  *     Gershon Elber and many others.
46  *
47  */
48
49 #include <signal.h>
50
51 #include "stdfn.h"
52 #include "readline.h"
53
54 #include "alloc.h"
55 #include "gp_hist.h"
56 #include "plot.h"
57 #include "util.h"
58 #include "term_api.h"
59
60 #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)
61 /* #include <readline/readline.h> --- HBB 20000508: now included by readline.h*/
62 /* #include <readline/history.h> --- HBB 20000508: now included by gp_hist */
63
64
65 static char* line_buffer;
66 static int line_complete;
67
68 /**
69  * called by libreadline or editline if the input
70  * was typed (not from the ipc).
71  */
72 static void
73 LineCompleteHandler(char* ptr)
74 {
75     rl_callback_handler_remove();
76     line_buffer = ptr;
77     line_complete = 1;
78 }
79
80 #if defined(HAVE_LIBEDITLINE)
81 int
82 #else
83 static int
84 #endif
85 #if defined(HAVE_LIBEDITLINE)
86 getc_wrapper(FILE* fp /* is NULL, supplied by libedit */)
87 #else
88 getc_wrapper(FILE* fp /* should be stdin, supplied by readline */)
89 #endif
90 {
91     int c;
92
93     while (1) {
94 #ifdef USE_MOUSE
95         if (term && term->waitforinput && interactive) {
96             c = term->waitforinput();
97         }
98         else
99 #endif
100 #if defined(HAVE_LIBEDITLINE)
101             c = getchar();
102 #else
103             c = getc(fp);
104 #endif
105         if (c == EOF && errno == EINTR)
106             continue;
107         return c;
108     }
109 }
110
111 #endif /* HAVE_LIBREADLINE || HAVE_LIBEDITLINE */
112
113 #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) || defined(READLINE)
114 char*
115 readline_ipc(const char* prompt)
116 {
117 #if defined(PIPE_IPC) && defined(HAVE_LIBREADLINE)
118     /* use readline's alternate interface.
119      * this requires rl_library_version > 2.2
120      * TODO: make a check in configure.in */
121
122     rl_callback_handler_install((char*) prompt, LineCompleteHandler);
123     rl_getc_function = getc_wrapper;
124
125     for (line_complete = 0; !line_complete; /* EMPTY */) {
126         rl_callback_read_char(); /* stdin */
127     }
128     return line_buffer;
129 #else
130     return readline((const char*) prompt);
131 #endif
132 }
133 #endif  /* defined(HAVE_LIBREADLINE) || define(READLINE) */
134
135
136 #if defined(READLINE) && !(defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE))
137
138 /* a small portable version of GNU's readline
139  * this is not the BASH or GNU EMACS version of READLINE due to Copyleft
140  * restrictions
141  * do not need any terminal capabilities except backspace,
142  * and space overwrites a character
143  */
144
145 /* NANO-EMACS line editing facility
146  * printable characters print as themselves (insert not overwrite)
147  * ^A moves to the beginning of the line
148  * ^B moves back a single character
149  * ^E moves to the end of the line
150  * ^F moves forward a single character
151  * ^K kills from current position to the end of line
152  * ^P moves back through history
153  * ^N moves forward through history
154  * ^H and DEL delete the previous character
155  * ^D deletes the current character, or EOF if line is empty
156  * ^L/^R redraw line in case it gets trashed
157  * ^U kills the entire line
158  * ^W kills last word
159  * LF and CR return the entire line regardless of the cursor postition
160  * EOF with an empty line returns (char *)NULL
161  *
162  * all other characters are ignored
163  */
164
165 #ifdef HAVE_SYS_IOCTL_H
166 /* For ioctl() prototype under Linux (and BeOS?) */
167 # include <sys/ioctl.h>
168 #endif
169
170 /* replaces the previous klugde in configure */
171 #if defined(HAVE_TERMIOS_H) && defined(HAVE_TCGETATTR)
172 # define TERMIOS
173 #else /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
174 # ifdef HAVE_SGTTY_H
175 #  define SGTTY
176 # endif
177 #endif /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
178
179 #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386) && !defined(OSK)
180
181 /*
182  * Set up structures using the proper include file
183  */
184 # if defined(_IBMR2) || defined(alliant)
185 #  define SGTTY
186 # endif
187
188 /*  submitted by Francois.Dagorn@cicb.fr */
189 # ifdef SGTTY
190 #  include <sgtty.h>
191 static struct sgttyb orig_termio, rl_termio;
192 /* define terminal control characters */
193 static struct tchars s_tchars;
194 #  ifndef VERASE
195 #   define VERASE    0
196 #  endif                        /* not VERASE */
197 #  ifndef VEOF
198 #   define VEOF      1
199 #  endif                        /* not VEOF */
200 #  ifndef VKILL
201 #   define VKILL     2
202 #  endif                        /* not VKILL */
203 #  ifdef TIOCGLTC               /* available only with the 'new' line discipline */
204 static struct ltchars s_ltchars;
205 #   ifndef VWERASE
206 #    define VWERASE   3
207 #   endif                       /* not VWERASE */
208 #   ifndef VREPRINT
209 #    define VREPRINT  4
210 #   endif                       /* not VREPRINT */
211 #   ifndef VSUSP
212 #    define VSUSP     5
213 #   endif                       /* not VSUP */
214 #  endif                        /* TIOCGLTC */
215 #  ifndef NCCS
216 #   define NCCS      6
217 #  endif                        /* not NCCS */
218
219 # else                          /* not SGTTY */
220
221 /* SIGTSTP defines job control
222  * if there is job control then we need termios.h instead of termio.h
223  * (Are there any systems with job control that use termio.h?  I hope not.)
224  */
225 #  if defined(SIGTSTP) || defined(TERMIOS)
226 #   ifndef TERMIOS
227 #    define TERMIOS
228 #   endif                       /* not TERMIOS */
229 #   include <termios.h>
230 /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
231 #   ifdef ISC22
232 #    ifndef ONOCR               /* taken from sys/termio.h */
233 #     define ONOCR 0000020      /* true at least for ISC 2.2 */
234 #    endif                      /* not ONOCR */
235 #    ifndef IUCLC
236 #     define IUCLC 0001000
237 #    endif                      /* not IUCLC */
238 #   endif                       /* ISC22 */
239 #   if !defined(IUCLC)
240      /* translate upper to lower case not supported */
241 #    define IUCLC 0
242 #   endif                       /* not IUCLC */
243
244 static struct termios orig_termio, rl_termio;
245 #  else                         /* not SIGSTP || TERMIOS */
246 #   include <termio.h>
247 static struct termio orig_termio, rl_termio;
248 /* termio defines NCC instead of NCCS */
249 #   define NCCS    NCC
250 #  endif                        /* not SIGTSTP || TERMIOS */
251 # endif                         /* SGTTY */
252
253 /* ULTRIX defines VRPRNT instead of VREPRINT */
254 # if defined(VRPRNT) && !defined(VREPRINT)
255 #  define VREPRINT VRPRNT
256 # endif                         /* VRPRNT */
257
258 /* define characters to use with our input character handler */
259 static char term_chars[NCCS];
260
261 static int term_set = 0;        /* =1 if rl_termio set */
262
263 #define special_getc() ansi_getc()
264 static int ansi_getc __PROTO((void));
265
266 #else /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
267
268 # ifdef _Windows
269 #  include <windows.h>
270 #  include "win/wtext.h"
271 #  include "win/winmain.h"
272 #  define TEXTUSER 0xf1
273 #  define TEXTGNUPLOT 0xf0
274 #  define special_getc() msdos_getch()
275 static char msdos_getch __PROTO((void));        /* HBB 980308: PROTO'ed it */
276 # endif                         /* _Windows */
277
278 # if defined(MSDOS) || defined(DOS386)
279 /* MSDOS specific stuff */
280 #  ifdef DJGPP
281 #   include <pc.h>
282 #  endif                        /* DJGPP */
283 #  if defined(__EMX__) || defined (__WATCOMC__)
284 #   include <conio.h>
285 #  endif                        /* __EMX__ */
286 #  define special_getc() msdos_getch()
287 static char msdos_getch();
288 # endif                         /* MSDOS || DOS386 */
289
290 # ifdef OSK
291 #  include <sgstat.h>
292 #  include <modes.h>
293
294 #  define STDIN 0
295 static int term_set = 0;        /* =1 if new_settings is set */
296
297 static struct _sgs old_settings;        /* old terminal settings        */
298 static struct _sgs new_settings;        /* new terminal settings        */
299
300 #  define special_getc() ansi_getc()
301 static int ansi_getc __PROTO((void));
302
303 /* On OS9 a '\n' is a character 13 and '\r' == '\n'. This gives troubles
304    here, so we need a new putc wich handles this correctly and print a
305    character 10 on each place we want a '\n'.
306  */
307 #  undef putc                   /* Undefine the macro for putc */
308
309 static int
310 putc(char c, FILE *fp)
311 {
312     write(fileno(fp), &c, 1);
313     if (c == '\012') {          /* A normal ASCII '\n' */
314         c = '\r';
315         write(fileno(fp), &c, 1);
316     }
317 }
318
319 # endif                         /* OSK */
320
321 # if defined(ATARI) || defined(MTOS)
322 #  define special_getc() tos_getch()
323 # endif                         /* ATARI || MTOS */
324
325 #endif /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
326
327 #ifdef OS2
328 # if defined( special_getc )
329 #  undef special_getc()
330 # endif                         /* special_getc */
331 # define special_getc() os2_getch()
332 static char msdos_getch __PROTO((void));        /* HBB 980308: PROTO'ed it */
333 static char os2_getch __PROTO((void));
334 #endif /* OS2 */
335
336
337 /* initial size and increment of input line length */
338 #define MAXBUF  1024
339 #define BACKSPACE 0x08   /* ^H */
340 #define SPACE   ' '
341
342 #ifdef OSK
343 # define NEWLINE        '\012'
344 #else /* OSK */
345 # define NEWLINE        '\n'
346 #endif /* not OSK */
347
348 static char *cur_line;          /* current contents of the line */
349 static size_t line_len = 0;
350 static size_t cur_pos = 0;      /* current position of the cursor */
351 static size_t max_pos = 0;      /* maximum character position */
352
353 static void fix_line __PROTO((void));
354 static void redraw_line __PROTO((const char *prompt));
355 static void clear_line __PROTO((const char *prompt));
356 static void clear_eoline __PROTO((void));
357 static void copy_line __PROTO((char *line));
358 static void set_termio __PROTO((void));
359 static void reset_termio __PROTO((void));
360 static int user_putc __PROTO((int ch));
361 static int user_puts __PROTO((char *str));
362 static void backspace __PROTO((void));
363 static void extend_cur_line __PROTO((void));
364
365
366 /* user_putc and user_puts should be used in the place of
367  * fputc(ch,stderr) and fputs(str,stderr) for all output
368  * of user typed characters.  This allows MS-Windows to
369  * display user input in a different color.
370  */
371 static int
372 user_putc(int ch)
373 {
374     int rv;
375 #ifdef _Windows
376     TextAttr(&textwin, TEXTUSER);
377 #endif
378     rv = fputc(ch, stderr);
379 #ifdef _Windows
380     TextAttr(&textwin, TEXTGNUPLOT);
381 #endif
382     return rv;
383 }
384
385 static int
386 user_puts(char *str)
387 {
388     int rv;
389 #ifdef _Windows
390     TextAttr(&textwin, TEXTUSER);
391 #endif
392     rv = fputs(str, stderr);
393 #ifdef _Windows
394     TextAttr(&textwin, TEXTGNUPLOT);
395 #endif
396     return rv;
397 }
398
399 /* This function provides a centralized non-destructive backspace capability
400  * M. Castro
401  */
402 static void
403 backspace()
404 {
405     user_putc(BACKSPACE);
406 }
407
408 static void
409 extend_cur_line()
410 {
411     char *new_line;
412
413     /* extent input line length */
414     new_line = gp_realloc(cur_line, line_len + MAXBUF, NULL);
415     if (!new_line) {
416         reset_termio();
417         int_error(NO_CARET, "Can't extend readline length");
418     }
419     cur_line = new_line;
420     line_len += MAXBUF;
421     FPRINTF((stderr, "\nextending readline length to %d chars\n", line_len));
422 }
423
424 char *
425 readline(const char *prompt)
426 {
427     int cur_char;
428     char *new_line;
429
430
431     /* start with a string of MAXBUF chars */
432     if (line_len != 0) {
433         free(cur_line);
434         line_len = 0;
435     }
436     cur_line = gp_alloc(MAXBUF, "readline");
437     line_len = MAXBUF;
438
439     /* set the termio so we can do our own input processing */
440     set_termio();
441
442     /* print the prompt */
443     fputs(prompt, stderr);
444     cur_line[0] = '\0';
445     cur_pos = 0;
446     max_pos = 0;
447     cur_entry = NULL;
448
449     /* get characters */
450     for (;;) {
451
452         cur_char = special_getc();
453
454         /* The #define CHARSET7BIT should be used when one encounters
455          * problems with 8bit characters that should not be entered on
456          * the commandline. I cannot think on any reasonable example
457          * where this could happen, but what do I know?  After all,
458          * the unix world still ignores 8bit chars in most
459          * applications.
460          *
461          * Note that latin1 defines the chars 0x80-0x9f as control
462          * chars. For the benefit of Atari, MSDOS, Windows and NeXT I
463          * have decided to ignore this, since it would require more
464          * #ifs. */
465
466         if (isprint(cur_char)
467 #ifndef CHARSET7BIT
468             /* || ((unsigned char) cur_char == 011) */ /* EAM allowing <tab> breaks auto-completion! */
469             || (((unsigned char) cur_char > 0x7f) && cur_char != EOF)
470 #endif /* CHARSET7BIT */
471             ) {
472             size_t i;
473
474             if (max_pos + 1 >= line_len) {
475                 extend_cur_line();
476             }
477             for (i = max_pos; i > cur_pos; i--) {
478                 cur_line[i] = cur_line[i - 1];
479             }
480             user_putc(cur_char);
481             cur_line[cur_pos] = cur_char;
482             cur_pos += 1;
483             max_pos += 1;
484             if (cur_pos < max_pos)
485                 fix_line();
486             cur_line[max_pos] = '\0';
487
488             /* else interpret unix terminal driver characters */
489 #ifdef VERASE
490         } else if (cur_char == term_chars[VERASE]) {    /* DEL? */
491             if (cur_pos > 0) {
492                 size_t i;
493                 cur_pos -= 1;
494                 backspace();
495                 for (i = cur_pos; i < max_pos; i++)
496                     cur_line[i] = cur_line[i + 1];
497                 max_pos -= 1;
498                 fix_line();
499             }
500 #endif /* VERASE */
501 #ifdef VEOF
502         } else if (cur_char == term_chars[VEOF]) {      /* ^D? */
503             if (max_pos == 0) {
504                 reset_termio();
505                 return ((char *) NULL);
506             }
507             if ((cur_pos < max_pos) && (cur_char == 004)) {     /* ^D */
508                 size_t i;
509                 for (i = cur_pos; i < max_pos; i++)
510                     cur_line[i] = cur_line[i + 1];
511                 max_pos -= 1;
512                 fix_line();
513             }
514 #endif /* VEOF */
515 #ifdef VKILL
516         } else if (cur_char == term_chars[VKILL]) {     /* ^U? */
517             clear_line(prompt);
518 #endif /* VKILL */
519 #ifdef VWERASE
520         } else if (cur_char == term_chars[VWERASE]) {   /* ^W? */
521             while ((cur_pos > 0) &&
522                    (cur_line[cur_pos - 1] == SPACE)) {
523                 cur_pos -= 1;
524                 backspace();
525             }
526             while ((cur_pos > 0) &&
527                    (cur_line[cur_pos - 1] != SPACE)) {
528                 cur_pos -= 1;
529                 backspace();
530             }
531             clear_eoline();
532             max_pos = cur_pos;
533 #endif /* VWERASE */
534 #ifdef VREPRINT
535         } else if (cur_char == term_chars[VREPRINT]) {  /* ^R? */
536             putc(NEWLINE, stderr);      /* go to a fresh line */
537             redraw_line(prompt);
538 #endif /* VREPRINT */
539 #ifdef VSUSP
540         } else if (cur_char == term_chars[VSUSP]) {
541             reset_termio();
542             kill(0, SIGTSTP);
543
544             /* process stops here */
545
546             set_termio();
547             /* print the prompt */
548             redraw_line(prompt);
549 #endif /* VSUSP */
550         } else {
551             /* do normal editing commands */
552             /* some of these are also done above */
553             size_t i;
554             switch (cur_char) {
555             case EOF:
556                 reset_termio();
557                 return ((char *) NULL);
558             case 001:           /* ^A */
559                 while (cur_pos > 0) {
560                     cur_pos -= 1;
561                     backspace();
562                 }
563                 break;
564             case 002:           /* ^B */
565                 if (cur_pos > 0) {
566                     cur_pos -= 1;
567                     backspace();
568                 }
569                 break;
570             case 005:           /* ^E */
571                 while (cur_pos < max_pos) {
572                     user_putc(cur_line[cur_pos]);
573                     cur_pos += 1;
574                 }
575                 break;
576             case 006:           /* ^F */
577                 if (cur_pos < max_pos) {
578                     user_putc(cur_line[cur_pos]);
579                     cur_pos += 1;
580                 }
581                 break;
582             case 013:           /* ^K */
583                 clear_eoline();
584                 max_pos = cur_pos;
585                 break;
586             case 020:           /* ^P */
587                 if (history != NULL) {
588                     if (cur_entry == NULL) {
589                         cur_entry = history;
590                         clear_line(prompt);
591                         copy_line(cur_entry->line);
592                     } else if (cur_entry->prev != NULL) {
593                         cur_entry = cur_entry->prev;
594                         clear_line(prompt);
595                         copy_line(cur_entry->line);
596                     }
597                 }
598                 break;
599             case 016:           /* ^N */
600                 if (cur_entry != NULL) {
601                     cur_entry = cur_entry->next;
602                     clear_line(prompt);
603                     if (cur_entry != NULL)
604                         copy_line(cur_entry->line);
605                     else
606                         cur_pos = max_pos = 0;
607                 }
608                 break;
609             case 014:           /* ^L */
610             case 022:           /* ^R */
611                 putc(NEWLINE, stderr);  /* go to a fresh line */
612                 redraw_line(prompt);
613                 break;
614             case 0177:          /* DEL */
615             case 010:           /* ^H */
616                 if (cur_pos > 0) {
617                     cur_pos -= 1;
618                     backspace();
619                     for (i = cur_pos; i < max_pos; i++)
620                         cur_line[i] = cur_line[i + 1];
621                     max_pos -= 1;
622                     fix_line();
623                 }
624                 break;
625             case 004:           /* ^D */
626                 if (max_pos == 0) {
627                     reset_termio();
628                     return ((char *) NULL);
629                 }
630                 if (cur_pos < max_pos) {
631                     for (i = cur_pos; i < max_pos; i++)
632                         cur_line[i] = cur_line[i + 1];
633                     max_pos -= 1;
634                     fix_line();
635                 }
636                 break;
637             case 025:           /* ^U */
638                 clear_line(prompt);
639                 break;
640             case 027:           /* ^W */
641                 while ((cur_pos > 0) &&
642                        (cur_line[cur_pos - 1] == SPACE)) {
643                     cur_pos -= 1;
644                     backspace();
645                 }
646                 while ((cur_pos > 0) &&
647                        (cur_line[cur_pos - 1] != SPACE)) {
648                     cur_pos -= 1;
649                     backspace();
650                 }
651                 clear_eoline();
652                 max_pos = cur_pos;
653                 break;
654             case '\n':          /* ^J */
655 #ifndef OSK
656             case '\r':          /* ^M */
657 #endif
658                 cur_line[max_pos + 1] = '\0';
659 #ifdef OS2
660                 while (cur_pos < max_pos) {
661                     user_putc(cur_line[cur_pos]);
662                     cur_pos += 1;
663                 }
664 #endif
665                 putc(NEWLINE, stderr);
666
667                 /* Shrink the block down to fit the string ?
668                  * if the alloc fails, we still own block at cur_line,
669                  * but this shouldn't really fail.
670                  */
671                 new_line = (char *) gp_realloc(cur_line, strlen(cur_line) + 1,
672                                                "line resize");
673                 if (new_line)
674                     cur_line = new_line;
675                 /* else we just hang on to what we had - it's not a problem */
676
677                 line_len = 0;
678                 FPRINTF((stderr, "Resizing input line to %d chars\n", strlen(cur_line)));
679                 reset_termio();
680                 return (cur_line);
681             default:
682                 break;
683             }
684         }
685     }
686 }
687
688 /* fix up the line from cur_pos to max_pos
689  * do not need any terminal capabilities except backspace,
690  * and space overwrites a character
691  */
692 static void
693 fix_line()
694 {
695     size_t i;
696
697     /* write tail of string */
698     for (i = cur_pos; i < max_pos; i++)
699         user_putc(cur_line[i]);
700
701     /* write a space at the end of the line in case we deleted one */
702     user_putc(SPACE);
703
704     /* backup to original position */
705     for (i = max_pos + 1; i > cur_pos; i--)
706         backspace();
707
708 }
709
710 /* redraw the entire line, putting the cursor where it belongs */
711 static void
712 redraw_line(const char *prompt)
713 {
714     size_t i;
715
716     fputs(prompt, stderr);
717     user_puts(cur_line);
718
719     /* put the cursor where it belongs */
720     for (i = max_pos; i > cur_pos; i--)
721         backspace();
722 }
723
724 /* clear cur_line and the screen line */
725 static void
726 clear_line(const char *prompt)
727 {
728     size_t i;
729     for (i = 0; i < max_pos; i++)
730         cur_line[i] = '\0';
731
732     for (i = cur_pos; i > 0; i--)
733         backspace();
734
735     for (i = 0; i < max_pos; i++)
736         putc(SPACE, stderr);
737
738     putc('\r', stderr);
739     fputs(prompt, stderr);
740
741     cur_pos = 0;
742     max_pos = 0;
743 }
744
745 /* clear to end of line and the screen end of line */
746 static void
747 clear_eoline()
748 {
749     size_t i;
750     for (i = cur_pos; i < max_pos; i++)
751         cur_line[i] = '\0';
752
753     for (i = cur_pos; i < max_pos; i++)
754         putc(SPACE, stderr);
755     for (i = cur_pos; i < max_pos; i++)
756         backspace();
757 }
758
759 /* copy line to cur_line, draw it and set cur_pos and max_pos */
760 static void
761 copy_line(char *line)
762 {
763     while (strlen(line) + 1 > line_len) {
764         extend_cur_line();
765     }
766     strcpy(cur_line, line);
767     user_puts(cur_line);
768     cur_pos = max_pos = strlen(cur_line);
769 }
770
771 #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386) && !defined(OSK)
772 /* Convert ANSI arrow keys to control characters */
773 static int
774 ansi_getc()
775 {
776     int c;
777
778 #ifdef USE_MOUSE
779     if (term && term->waitforinput && interactive)
780         c = term->waitforinput();
781     else
782 #endif
783     c = getc(stdin);
784
785     if (c == 033) {
786         c = getc(stdin);        /* check for CSI */
787         if (c == '[') {
788             c = getc(stdin);    /* get command character */
789             switch (c) {
790             case 'D':           /* left arrow key */
791                 c = 002;
792                 break;
793             case 'C':           /* right arrow key */
794                 c = 006;
795                 break;
796             case 'A':           /* up arrow key */
797                 c = 020;
798                 break;
799             case 'B':           /* down arrow key */
800                 c = 016;
801                 break;
802             case 'F':           /* end key */
803                 c = 005;
804                 break;
805             case 'H':           /* home key */
806                 c = 001;
807                 break;
808             }
809         }
810     }
811     return c;
812 }
813 #endif
814
815 #if defined(MSDOS) || defined(_Windows) || defined(DOS386) || defined(OS2)
816
817 /* Convert Arrow keystrokes to Control characters: */
818 static char
819 msdos_getch()
820 {
821         char c;
822         
823 #ifdef DJGPP
824     int ch = getkey();
825     c = (ch & 0xff00) ? 0 : ch & 0xff;
826 #elif defined (OS2)
827     c = getc(stdin);
828 #else /* not OS2, not DJGPP*/
829 # if defined (_Windows) && defined (USE_MOUSE)
830     if (term && term->waitforinput && interactive)
831         c = term->waitforinput();
832     else
833 # endif /* not _Windows && not USE_MOUSE */
834     c = getch();
835 #endif /* not DJGPP, not OS2 */
836
837     if (c == 0) {
838 #ifdef DJGPP
839         c = ch & 0xff;
840 #else /* not DJGPP */
841 # ifdef OS2
842         c = getc(stdin);
843 # else                          /* not OS2 */
844         c = getch();            /* Get the extended code. */
845 # endif                         /* OS2 */
846 #endif /* not DJGPP */
847
848         switch (c) {
849         case 75:                /* Left Arrow. */
850             c = 002;
851             break;
852         case 77:                /* Right Arrow. */
853             c = 006;
854             break;
855         case 72:                /* Up Arrow. */
856             c = 020;
857             break;
858         case 80:                /* Down Arrow. */
859             c = 016;
860             break;
861         case 115:               /* Ctl Left Arrow. */
862         case 71:                /* Home */
863             c = 001;
864             break;
865         case 116:               /* Ctl Right Arrow. */
866         case 79:                /* End */
867             c = 005;
868             break;
869         case 83:                /* Delete */
870             c = 004;
871             break;
872         default:
873             c = 0;
874             break;
875         }
876     } else if (c == 033) {      /* ESC */
877         c = 025;
878     }
879     return c;
880 }
881
882 #endif /* MSDOS || _Windows || DOS386 || OS2 */
883
884 #ifdef OS2
885 /* We need to call different procedures, dependent on the
886    session type: VIO/window or an (XFree86) xterm */
887 static char
888 os2_getch() {
889   static int IsXterm = 0;
890   static int init = 0;
891
892   if (!init) {
893      if (getenv("WINDOWID")) {
894         IsXterm = 1;
895      }
896      init = 1;
897   }
898   if (IsXterm) {
899      return ansi_getc();
900   } else {
901      return msdos_getch();
902   }
903 }
904 #endif /* OS2 */
905
906 #if defined(ATARI) || defined(MTOS)
907
908 /* Convert Arrow keystrokes to Control characters: TOS version */
909
910 /* from term/atariaes.trm: */
911 long poll_events(int);
912
913 /* this function is used in help.c as well. this means that the
914  * program doesn't work without -DREADLINE (which would be the case
915  * if help.c didn't use it as well, since no events would be processed)
916  */
917 char
918 tos_getch()
919 {
920     long rawkey;
921     char c;
922     int scan_code;
923     static int in_help = 0;
924
925     if (strcmp(term->name, "atari") == 0)
926         poll_events(0);
927
928     if (in_help) {
929         switch (in_help) {
930         case 1:
931         case 5:
932             in_help++;
933             return 'e';
934         case 2:
935         case 6:
936             in_help++;
937             return 'l';
938         case 3:
939         case 7:
940             in_help++;
941             return 'p';
942         case 4:
943             in_help = 0;
944             return 0x0d;
945         case 8:
946             in_help = 0;
947             return ' ';
948         }
949     }
950     if (strcmp(term->name, "atari") == 0) {
951         do {
952             if (Bconstat(2))
953                 rawkey = Cnecin();
954             else
955                 rawkey = poll_events(1);
956         } while (rawkey == 0);
957     } else
958         rawkey = Cnecin();
959
960     c = (char) rawkey;
961     scan_code = ((int) (rawkey >> 16)) & 0xff;  /* get the scancode */
962     if (Kbshift(-1) & 0x00000007)
963         scan_code |= 0x80;      /* shift or control ? */
964
965     switch (scan_code) {
966     case 0x62:                  /* HELP         */
967     case 0xe2:                  /* shift HELP   */
968         if (max_pos == 0) {
969             if (scan_code == 0x62) {
970                 in_help = 1;
971             } else {
972                 in_help = 5;
973             }
974             return 'h';
975         } else {
976             return 0;
977         }
978     case 0x48:                  /* Up Arrow */
979         return 0x10;            /* ^P */
980     case 0x50:                  /* Down Arrow */
981         return 0x0e;            /* ^N */
982     case 0x4b:                  /* Left Arrow */
983         return 0x02;            /* ^B */
984     case 0x4d:                  /* Right Arrow */
985         return 0x06;            /* ^F */
986     case 0xcb:                  /* Shift Left Arrow */
987     case 0xf3:                  /* Ctrl Left Arrow (TOS-bug ?) */
988     case 0x47:                  /* Home */
989         return 0x01;            /* ^A */
990     case 0xcd:                  /* Shift Right Arrow */
991     case 0xf4:                  /* Ctrl Right Arrow (TOS-bug ?) */
992     case 0xc7:                  /* Shift Home */
993     case 0xf7:                  /* Ctrl Home */
994         return 0x05;            /* ^E */
995     case 0x61:                  /* Undo - redraw line */
996         return 0x0c;            /* ^L */
997     default:
998         if (c == 0x1b)
999             return 0x15;        /* ESC becomes ^U */
1000         if (c == 0x7f)
1001             return 0x04;        /* Del becomes ^D */
1002         break;
1003     }
1004     return c;
1005 }
1006
1007 #endif /* ATARI || MTOS */
1008
1009   /* set termio so we can do our own input processing */
1010 static void
1011 set_termio()
1012 {
1013 #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
1014 /* set termio so we can do our own input processing */
1015 /* and save the old terminal modes so we can reset them later */
1016     if (term_set == 0) {
1017         /*
1018          * Get terminal modes.
1019          */
1020 # ifndef OSK
1021 #  ifdef SGTTY
1022         ioctl(0, TIOCGETP, &orig_termio);
1023 #  else                         /* not SGTTY */
1024 #   ifdef TERMIOS
1025 #    ifdef TCGETS
1026         ioctl(0, TCGETS, &orig_termio);
1027 #    else                       /* not TCGETS */
1028         tcgetattr(0, &orig_termio);
1029 #    endif                      /* not TCGETS */
1030 #   else                        /* not TERMIOS */
1031         ioctl(0, TCGETA, &orig_termio);
1032 #   endif                       /* TERMIOS */
1033 #  endif                        /* not SGTTY */
1034 # else                          /* OSK */
1035         setbuf(stdin, (char *) 0);      /* Make stdin and stdout unbuffered */
1036         setbuf(stderr, (char *) 0);
1037         _gs_opt(STDIN, &new_settings);
1038 # endif                         /* OSK */
1039
1040         /*
1041          * Save terminal modes
1042          */
1043 # ifndef OSK
1044         rl_termio = orig_termio;
1045 # else                          /* OSK */
1046         _gs_opt(STDIN, &old_settings);
1047 # endif                         /* OSK */
1048
1049         /*
1050          * Set the modes to the way we want them
1051          *  and save our input special characters
1052          */
1053 # ifndef OSK
1054 #  ifdef SGTTY
1055         rl_termio.sg_flags |= CBREAK;
1056         rl_termio.sg_flags &= ~(ECHO | XTABS);
1057         ioctl(0, TIOCSETN, &rl_termio);
1058
1059         ioctl(0, TIOCGETC, &s_tchars);
1060         term_chars[VERASE] = orig_termio.sg_erase;
1061         term_chars[VEOF] = s_tchars.t_eofc;
1062         term_chars[VKILL] = orig_termio.sg_kill;
1063 #   ifdef TIOCGLTC
1064         ioctl(0, TIOCGLTC, &s_ltchars);
1065         term_chars[VWERASE] = s_ltchars.t_werasc;
1066         term_chars[VREPRINT] = s_ltchars.t_rprntc;
1067         term_chars[VSUSP] = s_ltchars.t_suspc;
1068
1069         /* disable suspending process on ^Z */
1070         s_ltchars.t_suspc = 0;
1071         ioctl(0, TIOCSLTC, &s_ltchars);
1072 #   endif                       /* TIOCGLTC */
1073 #  else                         /* not SGTTY */
1074         rl_termio.c_iflag &= ~(BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF);
1075         rl_termio.c_iflag |= (IGNBRK | IGNPAR);
1076
1077         /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
1078
1079         rl_termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH);
1080 #   ifdef OS2
1081         /* for emx: remove default terminal processing */
1082         rl_termio.c_lflag &= ~(IDEFAULT);
1083 #   endif                       /* OS2 */
1084         rl_termio.c_lflag |= (ISIG);
1085         rl_termio.c_cc[VMIN] = 1;
1086         rl_termio.c_cc[VTIME] = 0;
1087
1088 #   ifndef VWERASE
1089 #    define VWERASE 3
1090 #   endif                       /* VWERASE */
1091         term_chars[VERASE] = orig_termio.c_cc[VERASE];
1092         term_chars[VEOF] = orig_termio.c_cc[VEOF];
1093         term_chars[VKILL] = orig_termio.c_cc[VKILL];
1094 #   ifdef TERMIOS
1095         term_chars[VWERASE] = orig_termio.c_cc[VWERASE];
1096 #    ifdef VREPRINT
1097         term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
1098 #    else                       /* not VREPRINT */
1099 #     ifdef VRPRNT
1100         term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
1101 #     endif                     /* VRPRNT */
1102 #    endif                      /* not VREPRINT */
1103         term_chars[VSUSP] = orig_termio.c_cc[VSUSP];
1104
1105         /* disable suspending process on ^Z */
1106         rl_termio.c_cc[VSUSP] = 0;
1107 #   endif                       /* TERMIOS */
1108 #  endif                        /* not SGTTY */
1109 # else                          /* OSK */
1110         new_settings._sgs_echo = 0;     /* switch off terminal echo */
1111         new_settings._sgs_pause = 0;    /* inhibit page pause */
1112         new_settings._sgs_eofch = 0;    /* inhibit eof  */
1113         new_settings._sgs_kbich = 0;    /* inhibit ^C   */
1114         new_settings._sgs_kbach = 0;    /* inhibit ^E   */
1115 # endif                         /* OSK */
1116
1117         /*
1118          * Set the new terminal modes.
1119          */
1120 # ifndef OSK
1121 #  ifdef SGTTY
1122         ioctl(0, TIOCSLTC, &s_ltchars);
1123 #  else                         /* not SGTTY */
1124 #   ifdef TERMIOS
1125 #    ifdef TCSETSW
1126         ioctl(0, TCSETSW, &rl_termio);
1127 #    else                       /* not TCSETSW */
1128         tcsetattr(0, TCSADRAIN, &rl_termio);
1129 #    endif                      /* not TCSETSW */
1130 #   else                        /* not TERMIOS */
1131         ioctl(0, TCSETAW, &rl_termio);
1132 #   endif                       /* not TERMIOS */
1133 #  endif                        /* not SGTTY */
1134 # else                          /* OSK */
1135         _ss_opt(STDIN, &new_settings);
1136 # endif                         /* OSK */
1137         term_set = 1;
1138     }
1139 #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
1140 }
1141
1142 static void
1143 reset_termio()
1144 {
1145 #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
1146 /* reset saved terminal modes */
1147     if (term_set == 1) {
1148 # ifndef OSK
1149 #  ifdef SGTTY
1150         ioctl(0, TIOCSETN, &orig_termio);
1151 #   ifdef TIOCGLTC
1152         /* enable suspending process on ^Z */
1153         s_ltchars.t_suspc = term_chars[VSUSP];
1154         ioctl(0, TIOCSLTC, &s_ltchars);
1155 #   endif                       /* TIOCGLTC */
1156 #  else                         /* not SGTTY */
1157 #   ifdef TERMIOS
1158 #    ifdef TCSETSW
1159         ioctl(0, TCSETSW, &orig_termio);
1160 #    else                       /* not TCSETSW */
1161         tcsetattr(0, TCSADRAIN, &orig_termio);
1162 #    endif                      /* not TCSETSW */
1163 #   else                        /* not TERMIOS */
1164         ioctl(0, TCSETAW, &orig_termio);
1165 #   endif                       /* TERMIOS */
1166 #  endif                        /* not SGTTY */
1167 # else                          /* OSK */
1168         _ss_opt(STDIN, &old_settings);
1169 # endif                         /* OSK */
1170         term_set = 0;
1171     }
1172 #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
1173 }
1174
1175 #endif /* READLINE && !HAVE_LIBREADLINE */