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