* Update to version 2.19.5
[alpine.git] / pico / osdep / terminal.c
blob179d6cdc8c01a22bd17b608740c3503db162f862
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: terminal.c 921 2008-01-31 02:09:25Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
18 * Program: Display routines
21 #include <system.h>
22 #include <general.h>
25 #include "../estruct.h"
26 #include "../keydefs.h"
27 #include "../pico.h"
28 #include "../mode.h"
30 #include "raw.h"
31 #include "color.h"
32 #include "tty.h"
33 #include "terminal.h"
34 #include "getkey.h"
36 #ifndef _WINDOWS
37 extern long gmode;
41 * Useful Defaults
43 #define MARGIN 8 /* size of minimim margin and */
44 #define MROW 2 /* rows in menu */
47 /* any special properties of the current terminal */
48 unsigned term_capabilities = (TT_EOLEXIST | TT_SCROLLEXIST | TT_INSCHAR | TT_DELCHAR);
54 unsigned
55 tthascap(void)
57 return(term_capabilities);
61 #if HAS_TERMINFO
64 * terminfo-based terminal i/o and control routines
68 /* internal prototypes */
69 static int tinfomove(int, int);
70 static int tinfoeeol(void);
71 static int tinfoeeop(void);
72 static int tinfobeep(void);
73 static int tinforev(int);
74 static int tinfoopen(void);
75 static int tinfoterminalinfo(int);
76 static int tinfoclose(void);
77 static void setup_dflt_esc_seq(void);
78 static void tinfoinsert(UCS);
79 static void tinfodelete(void);
81 extern int tput();
82 extern int tputs(char *, int, int (*)(int));
83 extern char *tgoto(char *, int, int);
84 extern char *tigetstr ();
85 extern int setupterm(char *, int, int *);
86 extern int tigetnum(char *);
87 extern int tigetflag(char *);
89 /**
90 ** Note: The tgoto calls should really be replaced by tparm calls for
91 ** modern terminfo. tgoto(s, x, y) == tparm(s, y, x).
92 **/
94 int _tlines, _tcolumns;
95 char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
96 *_setinverse, *_clearinverse,
97 *_setunderline, *_clearunderline,
98 *_setbold, *_clearallattr, /* there is no clear only bold! */
99 *_cleartoeoln, *_cleartoeos,
100 *_deleteline, /* delete line */
101 *_insertline, /* insert line */
102 *_scrollregion, /* define a scrolling region, vt100 */
103 *_insertchar, /* insert character, preferable to : */
104 *_startinsert, /* set insert mode and, */
105 *_endinsert, /* end insert mode */
106 *_deletechar, /* delete character */
107 *_startdelete, /* set delete mode and, */
108 *_enddelete, /* end delete mode */
109 *_scrolldown, /* scroll down */
110 *_scrollup, /* scroll up */
111 *_termcap_init, /* string to start termcap */
112 *_termcap_end, /* string to end termcap */
113 *_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp;
114 int _colors, _pairs, _bce;
115 char term_name[40];
117 TERM term = {
118 NROW-1,
119 NCOL,
120 MARGIN,
121 MROW,
122 tinfoopen,
123 tinfoterminalinfo,
124 tinfoclose,
125 ttgetc,
126 ttputc,
127 ttflush,
128 tinfomove,
129 tinfoeeol,
130 tinfoeeop,
131 tinfobeep,
132 tinforev
137 * Add default keypad sequences to the trie.
139 static void
140 setup_dflt_esc_seq(void)
143 * this is sort of a hack [no kidding], but it allows us to use
144 * the function keys on pc's running telnet
148 * UW-NDC/UCS vt10[02] application mode.
150 kpinsert("\033OP", F1, 1);
151 kpinsert("\033OQ", F2, 1);
152 kpinsert("\033OR", F3, 1);
153 kpinsert("\033OS", F4, 1);
154 kpinsert("\033Op", F5, 1);
155 kpinsert("\033Oq", F6, 1);
156 kpinsert("\033Or", F7, 1);
157 kpinsert("\033Os", F8, 1);
158 kpinsert("\033Ot", F9, 1);
159 kpinsert("\033Ou", F10, 1);
160 kpinsert("\033Ov", F11, 1);
161 kpinsert("\033Ow", F12, 1);
164 * DEC vt100, ANSI and cursor key mode.
166 kpinsert("\033OA", KEY_UP, 1);
167 kpinsert("\033OB", KEY_DOWN, 1);
168 kpinsert("\033OC", KEY_RIGHT, 1);
169 kpinsert("\033OD", KEY_LEFT, 1);
172 * special keypad functions
174 kpinsert("\033[4J", KEY_PGUP, 1);
175 kpinsert("\033[3J", KEY_PGDN, 1);
176 kpinsert("\033[2J", KEY_HOME, 1);
177 kpinsert("\033[N", KEY_END, 1);
180 * vt220?
182 kpinsert("\033[5~", KEY_PGUP, 1);
183 kpinsert("\033[6~", KEY_PGDN, 1);
184 kpinsert("\033[1~", KEY_HOME, 1);
185 kpinsert("\033[4~", KEY_END, 1);
188 * konsole, XTerm (XFree 4.x.x) keyboard setting
190 kpinsert("\033[H", KEY_HOME, 1);
191 kpinsert("\033[F", KEY_END, 1);
194 * gnome-terminal 2.6.0, don't know why it
195 * changed from 2.2.1
197 kpinsert("\033OH", KEY_HOME, 1);
198 kpinsert("\033OF", KEY_END, 1);
201 * "\033[2~" was common for KEY_HOME in a quick survey
202 * of terminals (though typically the Insert key).
203 * Teraterm 2.33 sends the following escape sequences,
204 * which is quite incompatible with everything
205 * else:
206 * Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
207 * PgDn: "\033[6~"
208 * The best thing to do would be to fix TeraTerm
209 * keymappings or to tweak terminfo.
213 * ANSI mode.
215 kpinsert("\033[=a", F1, 1);
216 kpinsert("\033[=b", F2, 1);
217 kpinsert("\033[=c", F3, 1);
218 kpinsert("\033[=d", F4, 1);
219 kpinsert("\033[=e", F5, 1);
220 kpinsert("\033[=f", F6, 1);
221 kpinsert("\033[=g", F7, 1);
222 kpinsert("\033[=h", F8, 1);
223 kpinsert("\033[=i", F9, 1);
224 kpinsert("\033[=j", F10, 1);
225 kpinsert("\033[=k", F11, 1);
226 kpinsert("\033[=l", F12, 1);
229 * DEC vt100, ANSI and cursor key mode reset.
231 kpinsert("\033[A", KEY_UP, 1);
232 kpinsert("\033[B", KEY_DOWN, 1);
233 kpinsert("\033[C", KEY_RIGHT, 1);
234 kpinsert("\033[D", KEY_LEFT, 1);
237 * DEC vt52 mode.
239 kpinsert("\033A", KEY_UP, 1);
240 kpinsert("\033B", KEY_DOWN, 1);
241 kpinsert("\033C", KEY_RIGHT, 1);
242 kpinsert("\033D", KEY_LEFT, 1);
245 * DEC vt52 application keys, and some Zenith 19.
247 kpinsert("\033?r", KEY_DOWN, 1);
248 kpinsert("\033?t", KEY_LEFT, 1);
249 kpinsert("\033?v", KEY_RIGHT, 1);
250 kpinsert("\033?x", KEY_UP, 1);
253 * Some Ctrl-Arrow keys
255 kpinsert("\033[5A", CTRL_KEY_UP, 1);
256 kpinsert("\033[5B", CTRL_KEY_DOWN, 1);
257 kpinsert("\033[5C", CTRL_KEY_RIGHT, 1);
258 kpinsert("\033[5D", CTRL_KEY_LEFT, 1);
260 kpinsert("\033[1;5A", CTRL_KEY_UP, 1);
261 kpinsert("\033[1;5B", CTRL_KEY_DOWN, 1);
262 kpinsert("\033[1;5C", CTRL_KEY_RIGHT, 1);
263 kpinsert("\033[1;5D", CTRL_KEY_LEFT, 1);
266 * Map some shift+up/down/left/right to their shiftless counterparts
268 kpinsert("\033[1;2A", KEY_UP, 1);
269 kpinsert("\033[1;2B", KEY_DOWN, 1);
270 kpinsert("\033[1;2C", KEY_RIGHT, 1);
271 kpinsert("\033[1;2D", KEY_LEFT, 1);
272 kpinsert("\033[a", KEY_UP, 1);
273 kpinsert("\033[b", KEY_DOWN, 1);
274 kpinsert("\033[c", KEY_RIGHT, 1);
275 kpinsert("\033[d", KEY_LEFT, 1);
278 * Sun Console sequences.
280 kpinsert("\033[1", KEY_SWALLOW_Z, 1);
281 kpinsert("\033[215", KEY_SWAL_UP, 1);
282 kpinsert("\033[217", KEY_SWAL_LEFT, 1);
283 kpinsert("\033[219", KEY_SWAL_RIGHT, 1);
284 kpinsert("\033[221", KEY_SWAL_DOWN, 1);
287 * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
289 kpinsert("\033_", KEY_KERMIT, 1);
292 * Fake a control character.
294 kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
298 static int
299 tinfoterminalinfo(int termcap_wins)
301 char *_ku, *_kd, *_kl, *_kr,
302 *_kppu, *_kppd, *_kphome, *_kpend, *_kpdel,
303 *_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6,
304 *_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12;
305 char *ttnm;
307 if (Pmaster) {
309 * setupterm() automatically retrieves the value
310 * of the TERM variable.
312 int err;
313 ttnm = getenv("TERM");
314 if(!ttnm)
315 return(-1);
317 strncpy(term_name, ttnm, sizeof(term_name));
318 term_name[sizeof(term_name)-1] = '\0';
319 setupterm ((char *) 0, 1, &err);
320 if (err != 1) return(err-2);
322 else {
324 * setupterm() issues a message and exits, if the
325 * terminfo data base is gone or the term type is
326 * unknown, if arg2 is 0.
328 setupterm ((char *) 0, 1, (int *) 0);
331 _clearscreen = tigetstr("clear");
332 _moveto = tigetstr("cup");
333 _up = tigetstr("cuu1");
334 _down = tigetstr("cud1");
335 _right = tigetstr("cuf1");
336 _left = tigetstr("cub1");
337 _setinverse = tigetstr("smso");
338 _clearinverse = tigetstr("rmso");
339 _setunderline = tigetstr("smul");
340 _clearunderline = tigetstr("rmul");
341 _setbold = tigetstr("bold");
342 _clearallattr = tigetstr("sgr0");
343 _cleartoeoln = tigetstr("el");
344 _cleartoeos = tigetstr("ed");
345 _deletechar = tigetstr("dch1");
346 _insertchar = tigetstr("ich1");
347 _startinsert = tigetstr("smir");
348 _endinsert = tigetstr("rmir");
349 _deleteline = tigetstr("dl1");
350 _insertline = tigetstr("il1");
351 _scrollregion = tigetstr("csr");
352 _scrolldown = tigetstr("ind");
353 _scrollup = tigetstr("ri");
354 _termcap_init = tigetstr("smcup");
355 _termcap_end = tigetstr("rmcup");
356 _startdelete = tigetstr("smdc");
357 _enddelete = tigetstr("rmdc");
358 _ku = tigetstr("kcuu1");
359 _kd = tigetstr("kcud1");
360 _kl = tigetstr("kcub1");
361 _kr = tigetstr("kcuf1");
362 _kppu = tigetstr("kpp");
363 _kppd = tigetstr("knp");
364 _kphome = tigetstr("khome");
365 _kpend = tigetstr("kend");
366 _kpdel = tigetstr("kdch1");
367 _kf1 = tigetstr("kf1");
368 _kf2 = tigetstr("kf2");
369 _kf3 = tigetstr("kf3");
370 _kf4 = tigetstr("kf4");
371 _kf5 = tigetstr("kf5");
372 _kf6 = tigetstr("kf6");
373 _kf7 = tigetstr("kf7");
374 _kf8 = tigetstr("kf8");
375 _kf9 = tigetstr("kf9");
376 _kf10 = tigetstr("kf10");
377 _kf11 = tigetstr("kf11");
378 _kf12 = tigetstr("kf12");
380 _colors = tigetnum("colors");
381 _pairs = tigetnum("pairs");
382 _setaf = tigetstr("setaf");
383 _setab = tigetstr("setab");
384 _setf = tigetstr("setf");
385 _setb = tigetstr("setb");
386 _scp = tigetstr("scp");
387 _op = tigetstr("op");
388 _oc = tigetstr("oc");
389 _bce = tigetflag("bce");
391 _tlines = tigetnum("lines");
392 if(_tlines == -1){
393 char *er;
394 int rr;
396 /* tigetnum failed, try $LINES */
397 er = getenv("LINES");
398 if(er && (rr = atoi(er)) > 0)
399 _tlines = rr;
402 _tcolumns = tigetnum("cols");
403 if(_tcolumns == -1){
404 char *ec;
405 int cc;
407 /* tigetnum failed, try $COLUMNS */
408 ec = getenv("COLUMNS");
409 if(ec && (cc = atoi(ec)) > 0)
410 _tcolumns = cc;
414 * Add default keypad sequences to the trie.
415 * Since these come first, they will override any conflicting termcap
416 * or terminfo escape sequences defined below. An escape sequence is
417 * considered conflicting if one is a prefix of the other.
418 * So, without TERMCAP_WINS, there will likely be some termcap/terminfo
419 * escape sequences that don't work, because they conflict with default
420 * sequences defined here.
422 if(!termcap_wins)
423 setup_dflt_esc_seq();
426 * add termcap/info escape sequences to the trie...
429 if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){
430 kpinsert(_ku, KEY_UP, termcap_wins);
431 kpinsert(_kd, KEY_DOWN, termcap_wins);
432 kpinsert(_kl, KEY_LEFT, termcap_wins);
433 kpinsert(_kr, KEY_RIGHT, termcap_wins);
436 if(_kppu != NULL && _kppd != NULL){
437 kpinsert(_kppu, KEY_PGUP, termcap_wins);
438 kpinsert(_kppd, KEY_PGDN, termcap_wins);
441 kpinsert(_kphome, KEY_HOME, termcap_wins);
442 kpinsert(_kpend, KEY_END, termcap_wins);
443 kpinsert(_kpdel, KEY_DEL, termcap_wins);
445 kpinsert(_kf1, F1, termcap_wins);
446 kpinsert(_kf2, F2, termcap_wins);
447 kpinsert(_kf3, F3, termcap_wins);
448 kpinsert(_kf4, F4, termcap_wins);
449 kpinsert(_kf5, F5, termcap_wins);
450 kpinsert(_kf6, F6, termcap_wins);
451 kpinsert(_kf7, F7, termcap_wins);
452 kpinsert(_kf8, F8, termcap_wins);
453 kpinsert(_kf9, F9, termcap_wins);
454 kpinsert(_kf10, F10, termcap_wins);
455 kpinsert(_kf11, F11, termcap_wins);
456 kpinsert(_kf12, F12, termcap_wins);
459 * Add default keypad sequences to the trie.
460 * Since these come after the termcap/terminfo escape sequences above,
461 * the termcap/info sequences will override any conflicting default
462 * escape sequences defined here.
463 * So, with TERMCAP_WINS, some of the default sequences will be missing.
464 * This means that you'd better get all of your termcap/terminfo entries
465 * correct if you define TERMCAP_WINS.
467 if(termcap_wins)
468 setup_dflt_esc_seq();
470 if(Pmaster)
471 return(0);
472 else
473 return(TRUE);
476 static int
477 tinfoopen(void)
479 int row, col;
482 * determine the terminal's communication speed and decide
483 * if we need to do optimization ...
485 if(ttisslow())
486 term_capabilities |= TT_OPTIMIZE;
488 col = _tcolumns;
489 row = _tlines;
490 if(row >= 0)
491 row--;
493 ttgetwinsz(&row, &col);
494 term.t_nrow = (short) row;
495 term.t_ncol = (short) col;
497 if(_cleartoeoln != NULL) /* able to use clear to EOL? */
498 term_capabilities |= TT_EOLEXIST;
499 else
500 term_capabilities &= ~TT_EOLEXIST;
502 if(_setinverse != NULL)
503 term_capabilities |= TT_REVEXIST;
504 else
505 term_capabilities &= ~TT_REVEXIST;
507 if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
508 term_capabilities &= ~TT_DELCHAR;
510 if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
511 term_capabilities &= ~TT_INSCHAR;
513 if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
514 && (_deleteline == NULL || _insertline == NULL))
515 term_capabilities &= ~TT_SCROLLEXIST;
517 if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
518 if(Pmaster == NULL){
519 puts("Incomplete terminfo entry\n");
520 exit(1);
524 ttopen();
526 if(_termcap_init && !Pmaster) {
527 putpad(_termcap_init); /* any init terminfo requires */
528 if (_scrollregion)
529 putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
533 * Initialize UW-modified NCSA telnet to use its functionkeys
535 if((gmode & MDFKEY) && Pmaster == NULL)
536 puts("\033[99h");
538 /* return ignored */
539 return(0);
543 static int
544 tinfoclose(void)
546 if(!Pmaster){
547 if(gmode&MDFKEY)
548 puts("\033[99l"); /* reset UW-NCSA telnet keys */
550 if(_termcap_end) /* any clean up terminfo requires */
551 putpad(_termcap_end);
554 ttclose();
556 /* return ignored */
557 return(0);
562 * tinfoinsert - insert a character at the current character position.
563 * _insertchar takes precedence.
565 static void
566 tinfoinsert(UCS ch)
568 if(_insertchar != NULL){
569 putpad(_insertchar);
570 ttputc(ch);
572 else{
573 putpad(_startinsert);
574 ttputc(ch);
575 putpad(_endinsert);
581 * tinfodelete - delete a character at the current character position.
583 static void
584 tinfodelete(void)
586 if(_startdelete == NULL && _enddelete == NULL)
587 putpad(_deletechar);
588 else{
589 putpad(_startdelete);
590 putpad(_deletechar);
591 putpad(_enddelete);
597 * o_scrolldown() - open a line at the given row position.
598 * use either region scrolling or deleteline/insertline
599 * to open a new line.
602 o_scrolldown(int row, int n)
604 register int i;
606 if(_scrollregion != NULL){
607 putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
608 tinfomove(row, 0);
609 for(i = 0; i < n; i++)
610 putpad((_scrollup != NULL && *_scrollup != '\0') ? _scrollup : "\n" );
611 putpad(tgoto(_scrollregion, term.t_nrow, 0));
612 tinfomove(row, 0);
614 else{
616 * this code causes a jiggly motion of the keymenu when scrolling
618 for(i = 0; i < n; i++){
619 tinfomove(term.t_nrow - (term.t_mrow+1), 0);
620 putpad(_deleteline);
621 tinfomove(row, 0);
622 putpad(_insertline);
624 #ifdef NOWIGGLYLINES
626 * this code causes a sweeping motion up and down the display
628 tinfomove(term.t_nrow - term.t_mrow - n, 0);
629 for(i = 0; i < n; i++)
630 putpad(_deleteline);
631 tinfomove(row, 0);
632 for(i = 0; i < n; i++)
633 putpad(_insertline);
634 #endif
637 /* return ignored */
638 return(0);
643 * o_scrollup() - open a line at the given row position.
644 * use either region scrolling or deleteline/insertline
645 * to open a new line.
648 o_scrollup(int row, int n)
650 register int i;
652 if(_scrollregion != NULL){
653 putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
654 /* setting scrolling region moves cursor to home */
655 tinfomove(term.t_nrow-(term.t_mrow+1), 0);
656 for(i = 0;i < n; i++)
657 putpad((_scrolldown == NULL || _scrolldown[0] == '\0') ? "\n"
658 : _scrolldown);
659 putpad(tgoto(_scrollregion, term.t_nrow, 0));
660 tinfomove(2, 0);
662 else{
663 for(i = 0; i < n; i++){
664 tinfomove(row, 0);
665 putpad(_deleteline);
666 tinfomove(term.t_nrow - (term.t_mrow+1), 0);
667 putpad(_insertline);
669 #ifdef NOWIGGLYLINES
670 /* see note above */
671 tinfomove(row, 0);
672 for(i = 0; i < n; i++)
673 putpad(_deleteline);
674 tinfomove(term.t_nrow - term.t_mrow - n, 0);
675 for(i = 0;i < n; i++)
676 putpad(_insertline);
677 #endif
680 /* return ignored */
681 return(0);
687 * o_insert - use terminfo to optimized character insert
688 * returns: true if it optimized output, false otherwise
691 o_insert(UCS c)
693 if(term_capabilities & TT_INSCHAR){
694 tinfoinsert(c);
695 return(1); /* no problems! */
698 return(0); /* can't do it. */
703 * o_delete - use terminfo to optimized character insert
704 * returns true if it optimized output, false otherwise
707 o_delete(void)
709 if(term_capabilities & TT_DELCHAR){
710 tinfodelete();
711 return(1); /* deleted, no problem! */
714 return(0); /* no dice. */
718 static int
719 tinfomove(int row, int col)
721 putpad(tgoto(_moveto, col, row));
723 /* return ignored */
724 return(0);
728 static int
729 tinfoeeol(void)
731 int c, starting_col, starting_line;
732 char *last_bg_color;
735 * If the terminal doesn't have back color erase, then we have to
736 * erase manually to preserve the background color.
738 if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
739 extern int ttcol, ttrow;
741 starting_col = ttcol;
742 starting_line = ttrow;
743 last_bg_color = pico_get_last_bg_color();
744 pico_set_nbg_color();
745 for(c = ttcol; c < term.t_ncol; c++)
746 ttputc(' ');
748 tinfomove(starting_line, starting_col);
749 if(last_bg_color){
750 pico_set_bg_color(last_bg_color);
751 free(last_bg_color);
754 else if(_cleartoeoln)
755 putpad(_cleartoeoln);
757 /* return ignored */
758 return(0);
762 static int
763 tinfoeeop(void)
765 int i, starting_col, starting_row;
768 * If the terminal doesn't have back color erase, then we have to
769 * erase manually to preserve the background color.
771 if(pico_usingcolor() && (!_bce || !_cleartoeos)){
772 extern int ttcol, ttrow;
774 starting_col = ttcol;
775 starting_row = ttrow;
776 tinfoeeol(); /* rest of this line */
777 for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */
778 tinfomove(i, 0);
779 tinfoeeol();
782 tinfomove(starting_row, starting_col);
784 else if(_cleartoeos)
785 putpad(_cleartoeos);
787 /* return ignored */
788 return(0);
792 static int
793 tinforev(int state) /* change reverse video status */
794 { /* FALSE = normal video, TRUE = rev video */
795 if(state)
796 StartInverse();
797 else
798 EndInverse();
800 return(1);
804 static int
805 tinfobeep(void)
807 ttputc(BELL);
809 /* return ignored */
810 return(0);
814 void
815 putpad(char *str)
817 tputs(str, 1, putchar);
820 #elif HAS_TERMCAP
823 * termcap-based terminal i/o and control routines
827 /* internal prototypes */
828 static int tcapmove(int, int);
829 static int tcapeeol(void);
830 static int tcapeeop(void);
831 static int tcapbeep(void);
832 static int tcaprev(int);
833 static int tcapopen(void);
834 static int tcapterminalinfo(int);
835 static int tcapclose(void);
836 static void setup_dflt_esc_seq(void);
837 static void tcapinsert(UCS);
838 static void tcapdelete(void);
840 extern int tput();
841 extern char *tgoto(char *, int, int);
844 * This number used to be 315. No doubt there was a reason for that but we
845 * don't know what it was. It's a bit of a hassle to make it dynamic, and most
846 * modern systems seem to be using terminfo, so we'll just change it to 800.
847 * We weren't stopping on overflow before, so we'll do that, too.
849 #define TCAPSLEN 800
850 char tcapbuf[TCAPSLEN];
851 int _tlines, _tcolumns;
852 char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
853 *_setinverse, *_clearinverse,
854 *_setunderline, *_clearunderline,
855 *_setbold, *_clearallattr, /* there is no clear only bold! */
856 *_cleartoeoln, *_cleartoeos,
857 *_deleteline, /* delete line */
858 *_insertline, /* insert line */
859 *_scrollregion, /* define a scrolling region, vt100 */
860 *_insertchar, /* insert character, preferable to : */
861 *_startinsert, /* set insert mode and, */
862 *_endinsert, /* end insert mode */
863 *_deletechar, /* delete character */
864 *_startdelete, /* set delete mode and, */
865 *_enddelete, /* end delete mode */
866 *_scrolldown, /* scroll down */
867 *_scrollup, /* scroll up */
868 *_termcap_init, /* string to start termcap */
869 *_termcap_end, /* string to end termcap */
870 *_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp;
871 int _colors, _pairs, _bce;
872 char term_name[40];
874 TERM term = {
875 NROW-1,
876 NCOL,
877 MARGIN,
878 MROW,
879 tcapopen,
880 tcapterminalinfo,
881 tcapclose,
882 ttgetc,
883 ttputc,
884 ttflush,
885 tcapmove,
886 tcapeeol,
887 tcapeeop,
888 tcapbeep,
889 tcaprev
894 * Add default keypad sequences to the trie.
896 static void
897 setup_dflt_esc_seq(void)
900 * this is sort of a hack, but it allows us to use
901 * the function keys on pc's running telnet
905 * UW-NDC/UCS vt10[02] application mode.
907 kpinsert("\033OP", F1, 1);
908 kpinsert("\033OQ", F2, 1);
909 kpinsert("\033OR", F3, 1);
910 kpinsert("\033OS", F4, 1);
911 kpinsert("\033Op", F5, 1);
912 kpinsert("\033Oq", F6, 1);
913 kpinsert("\033Or", F7, 1);
914 kpinsert("\033Os", F8, 1);
915 kpinsert("\033Ot", F9, 1);
916 kpinsert("\033Ou", F10, 1);
917 kpinsert("\033Ov", F11, 1);
918 kpinsert("\033Ow", F12, 1);
921 * DEC vt100, ANSI and cursor key mode.
923 kpinsert("\033OA", KEY_UP, 1);
924 kpinsert("\033OB", KEY_DOWN, 1);
925 kpinsert("\033OC", KEY_RIGHT, 1);
926 kpinsert("\033OD", KEY_LEFT, 1);
929 * special keypad functions
931 kpinsert("\033[4J", KEY_PGUP, 1);
932 kpinsert("\033[3J", KEY_PGDN, 1);
933 kpinsert("\033[2J", KEY_HOME, 1);
934 kpinsert("\033[N", KEY_END, 1);
937 * vt220?
939 kpinsert("\033[5~", KEY_PGUP, 1);
940 kpinsert("\033[6~", KEY_PGDN, 1);
941 kpinsert("\033[1~", KEY_HOME, 1);
942 kpinsert("\033[4~", KEY_END, 1);
945 * konsole, XTerm (XFree 4.x.x) keyboard setting
947 kpinsert("\033[H", KEY_HOME, 1);
948 kpinsert("\033[F", KEY_END, 1);
951 * gnome-terminal 2.6.0, don't know why it
952 * changed from 2.2.1
954 kpinsert("\033OH", KEY_HOME, 1);
955 kpinsert("\033OF", KEY_END, 1);
958 * "\033[2~" was common for KEY_HOME in a quick survey
959 * of terminals (though typically the Insert key).
960 * Teraterm 2.33 sends the following escape sequences,
961 * which is quite incompatible with everything
962 * else:
963 * Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
964 * PgDn: "\033[6~"
965 * The best thing to do would be to fix TeraTerm
966 * keymappings or to tweak terminfo.
970 * ANSI mode.
972 kpinsert("\033[=a", F1, 1);
973 kpinsert("\033[=b", F2, 1);
974 kpinsert("\033[=c", F3, 1);
975 kpinsert("\033[=d", F4, 1);
976 kpinsert("\033[=e", F5, 1);
977 kpinsert("\033[=f", F6, 1);
978 kpinsert("\033[=g", F7, 1);
979 kpinsert("\033[=h", F8, 1);
980 kpinsert("\033[=i", F9, 1);
981 kpinsert("\033[=j", F10, 1);
982 kpinsert("\033[=k", F11, 1);
983 kpinsert("\033[=l", F12, 1);
986 * DEC vt100, ANSI and cursor key mode reset.
988 kpinsert("\033[A", KEY_UP, 1);
989 kpinsert("\033[B", KEY_DOWN, 1);
990 kpinsert("\033[C", KEY_RIGHT, 1);
991 kpinsert("\033[D", KEY_LEFT, 1);
994 * DEC vt52 mode.
996 kpinsert("\033A", KEY_UP, 1);
997 kpinsert("\033B", KEY_DOWN, 1);
998 kpinsert("\033C", KEY_RIGHT, 1);
999 kpinsert("\033D", KEY_LEFT, 1);
1002 * DEC vt52 application keys, and some Zenith 19.
1004 kpinsert("\033?r", KEY_DOWN, 1);
1005 kpinsert("\033?t", KEY_LEFT, 1);
1006 kpinsert("\033?v", KEY_RIGHT, 1);
1007 kpinsert("\033?x", KEY_UP, 1);
1010 * Some Ctrl-Arrow keys
1012 kpinsert("\033[5A", CTRL_KEY_UP, 1);
1013 kpinsert("\033[5B", CTRL_KEY_DOWN, 1);
1014 kpinsert("\033[5C", CTRL_KEY_RIGHT, 1);
1015 kpinsert("\033[5D", CTRL_KEY_LEFT, 1);
1017 kpinsert("\033[1;5A", CTRL_KEY_UP, 1);
1018 kpinsert("\033[1;5B", CTRL_KEY_DOWN, 1);
1019 kpinsert("\033[1;5C", CTRL_KEY_RIGHT, 1);
1020 kpinsert("\033[1;5D", CTRL_KEY_LEFT, 1);
1023 * Map some shift+up/down/left/right to their shiftless counterparts
1025 kpinsert("\033[1;2A", KEY_UP, 1);
1026 kpinsert("\033[1;2B", KEY_DOWN, 1);
1027 kpinsert("\033[1;2C", KEY_RIGHT, 1);
1028 kpinsert("\033[1;2D", KEY_LEFT, 1);
1029 kpinsert("\033[a", KEY_UP, 1);
1030 kpinsert("\033[b", KEY_DOWN, 1);
1031 kpinsert("\033[c", KEY_RIGHT, 1);
1032 kpinsert("\033[d", KEY_LEFT, 1);
1035 * Sun Console sequences.
1037 kpinsert("\033[1", KEY_SWALLOW_Z, 1);
1038 kpinsert("\033[215", KEY_SWAL_UP, 1);
1039 kpinsert("\033[217", KEY_SWAL_LEFT, 1);
1040 kpinsert("\033[219", KEY_SWAL_RIGHT, 1);
1041 kpinsert("\033[221", KEY_SWAL_DOWN, 1);
1044 * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
1046 kpinsert("\033_", KEY_KERMIT, 1);
1049 * Fake a control character.
1051 kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
1056 * Read termcap and set some global variables. Initialize input trie to
1057 * decode escape sequences.
1059 static int
1060 tcapterminalinfo(int termcap_wins)
1062 char *p, *tgetstr();
1063 char tcbuf[2*1024];
1064 char *tv_stype;
1065 char err_str[72];
1066 int err;
1067 char *_ku, *_kd, *_kl, *_kr,
1068 *_kppu, *_kppd, *_kphome, *_kpend, *_kpdel,
1069 *_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6,
1070 *_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12;
1072 if (!(tv_stype = getenv("TERM")) || !strncpy(term_name, tv_stype, sizeof(term_name))){
1073 if(Pmaster){
1074 return(-1);
1076 else{
1077 puts("Environment variable TERM not defined!");
1078 exit(1);
1082 term_name[sizeof(term_name)-1] = '\0';
1084 if((err = tgetent(tcbuf, tv_stype)) != 1){
1085 if(Pmaster){
1086 return(err - 2);
1088 else{
1089 snprintf(err_str, sizeof(err_str), "Unknown terminal type %s!", tv_stype);
1090 puts(err_str);
1091 exit(1);
1095 p = tcapbuf;
1097 _clearscreen = tgetstr("cl", &p);
1098 _moveto = tgetstr("cm", &p);
1099 _up = tgetstr("up", &p);
1100 _down = tgetstr("do", &p);
1101 _right = tgetstr("nd", &p);
1102 _left = tgetstr("bs", &p);
1103 _setinverse = tgetstr("so", &p);
1104 _clearinverse = tgetstr("se", &p);
1105 _setunderline = tgetstr("us", &p);
1106 _clearunderline = tgetstr("ue", &p);
1107 _setbold = tgetstr("md", &p);
1108 _clearallattr = tgetstr("me", &p);
1109 _cleartoeoln = tgetstr("ce", &p);
1110 _cleartoeos = tgetstr("cd", &p);
1111 _deletechar = tgetstr("dc", &p);
1112 _insertchar = tgetstr("ic", &p);
1113 _startinsert = tgetstr("im", &p);
1114 _endinsert = tgetstr("ei", &p);
1115 _deleteline = tgetstr("dl", &p);
1116 _insertline = tgetstr("al", &p);
1117 _scrollregion = tgetstr("cs", &p);
1118 _scrolldown = tgetstr("sf", &p);
1119 _scrollup = tgetstr("sr", &p);
1120 _termcap_init = tgetstr("ti", &p);
1121 _termcap_end = tgetstr("te", &p);
1122 _startdelete = tgetstr("dm", &p);
1123 _enddelete = tgetstr("ed", &p);
1124 _ku = tgetstr("ku", &p);
1125 _kd = tgetstr("kd", &p);
1126 _kl = tgetstr("kl", &p);
1127 _kr = tgetstr("kr", &p);
1128 _kppu = tgetstr("kP", &p);
1129 _kppd = tgetstr("kN", &p);
1130 _kphome = tgetstr("kh", &p);
1131 _kpend = tgetstr("kH", &p);
1132 _kpdel = tgetstr("kD", &p);
1133 _kf1 = tgetstr("k1", &p);
1134 _kf2 = tgetstr("k2", &p);
1135 _kf3 = tgetstr("k3", &p);
1136 _kf4 = tgetstr("k4", &p);
1137 _kf5 = tgetstr("k5", &p);
1138 _kf6 = tgetstr("k6", &p);
1139 _kf7 = tgetstr("k7", &p);
1140 _kf8 = tgetstr("k8", &p);
1141 _kf9 = tgetstr("k9", &p);
1142 if((_kf10 = tgetstr("k;", &p)) == NULL)
1143 _kf10 = tgetstr("k0", &p);
1144 _kf11 = tgetstr("F1", &p);
1145 _kf12 = tgetstr("F2", &p);
1147 _colors = tgetnum("Co");
1148 _pairs = tgetnum("pa");
1149 _setaf = tgetstr("AF", &p);
1150 _setab = tgetstr("AB", &p);
1151 _setf = tgetstr("Sf", &p);
1152 _setb = tgetstr("Sb", &p);
1153 _scp = tgetstr("sp", &p);
1154 _op = tgetstr("op", &p);
1155 _oc = tgetstr("oc", &p);
1156 _bce = tgetflag("ut");
1158 if (p >= &tcapbuf[TCAPSLEN]){
1159 puts("Terminal description too big!\n");
1160 if(Pmaster)
1161 return(-3);
1162 else
1163 exit(1);
1166 _tlines = tgetnum("li");
1167 if(_tlines == -1){
1168 char *er;
1169 int rr;
1171 /* tgetnum failed, try $LINES */
1172 er = getenv("LINES");
1173 if(er && (rr = atoi(er)) > 0)
1174 _tlines = rr;
1177 _tcolumns = tgetnum("co");
1178 if(_tcolumns == -1){
1179 char *ec;
1180 int cc;
1182 /* tgetnum failed, try $COLUMNS */
1183 ec = getenv("COLUMNS");
1184 if(ec && (cc = atoi(ec)) > 0)
1185 _tcolumns = cc;
1189 * Add default keypad sequences to the trie.
1190 * Since these come first, they will override any conflicting termcap
1191 * or terminfo escape sequences defined below. An escape sequence is
1192 * considered conflicting if one is a prefix of the other.
1193 * So, without TERMCAP_WINS, there will likely be some termcap/terminfo
1194 * escape sequences that don't work, because they conflict with default
1195 * sequences defined here.
1197 if(!termcap_wins)
1198 setup_dflt_esc_seq();
1201 * add termcap/info escape sequences to the trie...
1204 if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){
1205 kpinsert(_ku, KEY_UP, termcap_wins);
1206 kpinsert(_kd, KEY_DOWN, termcap_wins);
1207 kpinsert(_kl, KEY_LEFT, termcap_wins);
1208 kpinsert(_kr, KEY_RIGHT, termcap_wins);
1211 if(_kppu != NULL && _kppd != NULL){
1212 kpinsert(_kppu, KEY_PGUP, termcap_wins);
1213 kpinsert(_kppd, KEY_PGDN, termcap_wins);
1216 kpinsert(_kphome, KEY_HOME, termcap_wins);
1217 kpinsert(_kpend, KEY_END, termcap_wins);
1218 kpinsert(_kpdel, KEY_DEL, termcap_wins);
1220 kpinsert(_kf1, F1, termcap_wins);
1221 kpinsert(_kf2, F2, termcap_wins);
1222 kpinsert(_kf3, F3, termcap_wins);
1223 kpinsert(_kf4, F4, termcap_wins);
1224 kpinsert(_kf5, F5, termcap_wins);
1225 kpinsert(_kf6, F6, termcap_wins);
1226 kpinsert(_kf7, F7, termcap_wins);
1227 kpinsert(_kf8, F8, termcap_wins);
1228 kpinsert(_kf9, F9, termcap_wins);
1229 kpinsert(_kf10, F10, termcap_wins);
1230 kpinsert(_kf11, F11, termcap_wins);
1231 kpinsert(_kf12, F12, termcap_wins);
1234 * Add default keypad sequences to the trie.
1235 * Since these come after the termcap/terminfo escape sequences above,
1236 * the termcap/info sequences will override any conflicting default
1237 * escape sequences defined here.
1238 * So, with TERMCAP_WINS, some of the default sequences will be missing.
1239 * This means that you'd better get all of your termcap/terminfo entries
1240 * correct if you define TERMCAP_WINS.
1242 if(termcap_wins)
1243 setup_dflt_esc_seq();
1245 if(Pmaster)
1246 return(0);
1247 else
1248 return(TRUE);
1251 static int
1252 tcapopen(void)
1254 int row, col;
1257 * determine the terminal's communication speed and decide
1258 * if we need to do optimization ...
1260 if(ttisslow())
1261 term_capabilities |= TT_OPTIMIZE;
1263 col = _tcolumns;
1264 row = _tlines;
1265 if(row >= 0)
1266 row--;
1268 ttgetwinsz(&row, &col);
1269 term.t_nrow = (short) row;
1270 term.t_ncol = (short) col;
1272 if(_cleartoeoln != NULL) /* able to use clear to EOL? */
1273 term_capabilities |= TT_EOLEXIST;
1274 else
1275 term_capabilities &= ~TT_EOLEXIST;
1277 if(_setinverse != NULL)
1278 term_capabilities |= TT_REVEXIST;
1279 else
1280 term_capabilities &= ~TT_REVEXIST;
1282 if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
1283 term_capabilities &= ~TT_DELCHAR;
1285 if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
1286 term_capabilities &= ~TT_INSCHAR;
1288 if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
1289 && (_deleteline == NULL || _insertline == NULL))
1290 term_capabilities &= ~TT_SCROLLEXIST;
1292 if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
1293 if(Pmaster == NULL){
1294 puts("Incomplete termcap entry\n");
1295 exit(1);
1299 ttopen();
1301 if(_termcap_init && !Pmaster) {
1302 putpad(_termcap_init); /* any init termcap requires */
1303 if (_scrollregion)
1304 putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
1308 * Initialize UW-modified NCSA telnet to use it's functionkeys
1310 if(gmode&MDFKEY && Pmaster == NULL)
1311 puts("\033[99h");
1313 /* return ignored */
1314 return(0);
1318 static int
1319 tcapclose(void)
1321 if(!Pmaster){
1322 if(gmode&MDFKEY)
1323 puts("\033[99l"); /* reset UW-NCSA telnet keys */
1325 if(_termcap_end) /* any cleanup termcap requires */
1326 putpad(_termcap_end);
1329 ttclose();
1331 /* return ignored */
1332 return(0);
1338 * tcapinsert - insert a character at the current character position.
1339 * _insertchar takes precedence.
1341 static void
1342 tcapinsert(UCS ch)
1344 if(_insertchar != NULL){
1345 putpad(_insertchar);
1346 ttputc(ch);
1348 else{
1349 putpad(_startinsert);
1350 ttputc(ch);
1351 putpad(_endinsert);
1357 * tcapdelete - delete a character at the current character position.
1359 static void
1360 tcapdelete(void)
1362 if(_startdelete == NULL && _enddelete == NULL)
1363 putpad(_deletechar);
1364 else{
1365 putpad(_startdelete);
1366 putpad(_deletechar);
1367 putpad(_enddelete);
1373 * o_scrolldown - open a line at the given row position.
1374 * use either region scrolling or deleteline/insertline
1375 * to open a new line.
1378 o_scrolldown(int row, int n)
1380 register int i;
1382 if(_scrollregion != NULL){
1383 putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
1384 tcapmove(row, 0);
1385 for(i = 0; i < n; i++)
1386 putpad( (_scrollup != NULL && *_scrollup != '\0')
1387 ? _scrollup : "\n" );
1388 putpad(tgoto(_scrollregion, term.t_nrow, 0));
1389 tcapmove(row, 0);
1391 else{
1393 * this code causes a jiggly motion of the keymenu when scrolling
1395 for(i = 0; i < n; i++){
1396 tcapmove(term.t_nrow - (term.t_mrow+1), 0);
1397 putpad(_deleteline);
1398 tcapmove(row, 0);
1399 putpad(_insertline);
1401 #ifdef NOWIGGLYLINES
1403 * this code causes a sweeping motion up and down the display
1405 tcapmove(term.t_nrow - term.t_mrow - n, 0);
1406 for(i = 0; i < n; i++)
1407 putpad(_deleteline);
1408 tcapmove(row, 0);
1409 for(i = 0; i < n; i++)
1410 putpad(_insertline);
1411 #endif
1414 /* return ignored */
1415 return(0);
1420 * o_scrollup - open a line at the given row position.
1421 * use either region scrolling or deleteline/insertline
1422 * to open a new line.
1425 o_scrollup(int row, int n)
1427 register int i;
1429 if(_scrollregion != NULL){
1430 putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
1431 /* setting scrolling region moves cursor to home */
1432 tcapmove(term.t_nrow-(term.t_mrow+1), 0);
1433 for(i = 0;i < n; i++)
1434 putpad((_scrolldown == NULL || _scrolldown[0] == '\0')
1435 ? "\n" : _scrolldown);
1436 putpad(tgoto(_scrollregion, term.t_nrow, 0));
1437 tcapmove(2, 0);
1439 else{
1440 for(i = 0; i < n; i++){
1441 tcapmove(row, 0);
1442 putpad(_deleteline);
1443 tcapmove(term.t_nrow - (term.t_mrow+1), 0);
1444 putpad(_insertline);
1446 #ifdef NOWIGGLYLINES
1447 /* see note above */
1448 tcapmove(row, 0);
1449 for(i = 0; i < n; i++)
1450 putpad(_deleteline);
1451 tcapmove(term.t_nrow - term.t_mrow - n, 0);
1452 for(i = 0;i < n; i++)
1453 putpad(_insertline);
1454 #endif
1457 /* return ignored */
1458 return(0);
1463 * o_insert - use termcap info to optimized character insert
1464 * returns: true if it optimized output, false otherwise
1467 o_insert(UCS c)
1469 if(term_capabilities & TT_INSCHAR){
1470 tcapinsert(c);
1471 return(1); /* no problems! */
1474 return(0); /* can't do it. */
1479 * o_delete - use termcap info to optimized character insert
1480 * returns true if it optimized output, false otherwise
1483 o_delete(void)
1485 if(term_capabilities & TT_DELCHAR){
1486 tcapdelete();
1487 return(1); /* deleted, no problem! */
1490 return(0); /* no dice. */
1494 static int
1495 tcapmove(int row, int col)
1497 putpad(tgoto(_moveto, col, row));
1499 /* return ignored */
1500 return(0);
1504 static int
1505 tcapeeol(void)
1507 int c, starting_col, starting_line;
1508 char *last_bg_color;
1511 * If the terminal doesn't have back color erase, then we have to
1512 * erase manually to preserve the background color.
1514 if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
1515 extern int ttcol, ttrow;
1517 starting_col = ttcol;
1518 starting_line = ttrow;
1519 last_bg_color = pico_get_last_bg_color();
1520 pico_set_nbg_color();
1521 for(c = ttcol; c < term.t_ncol; c++)
1522 ttputc(' ');
1524 tcapmove(starting_line, starting_col);
1525 if(last_bg_color){
1526 pico_set_bg_color(last_bg_color);
1527 free(last_bg_color);
1530 else if(_cleartoeoln)
1531 putpad(_cleartoeoln);
1533 /* return ignored */
1534 return(0);
1538 static int
1539 tcapeeop(void)
1541 int i, starting_col, starting_row;
1544 * If the terminal doesn't have back color erase, then we have to
1545 * erase manually to preserve the background color.
1547 if(pico_usingcolor() && (!_bce || !_cleartoeos)){
1548 extern int ttcol, ttrow;
1550 starting_col = ttcol;
1551 starting_row = ttrow;
1552 tcapeeol(); /* rest of this line */
1553 for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */
1554 tcapmove(i, 0);
1555 tcapeeol();
1558 tcapmove(starting_row, starting_col);
1560 else if(_cleartoeos)
1561 putpad(_cleartoeos);
1563 /* return ignored */
1564 return(0);
1568 static int
1569 tcaprev(int state) /* change reverse video status */
1570 { /* FALSE = normal video, TRUE = reverse video */
1571 if(state)
1572 StartInverse();
1573 else
1574 EndInverse();
1576 return(1);
1580 static int
1581 tcapbeep(void)
1583 ttputc(BELL);
1585 /* return ignored */
1586 return(0);
1590 void
1591 putpad(char *str)
1593 tputs(str, 1, putchar);
1596 #else /* HARD_CODED_ANSI_TERMINAL */
1599 * ANSI-specific terminal i/o and control routines
1603 #define BEL 0x07 /* BEL character. */
1604 #define ESC 0x1B /* ESC character. */
1607 extern int ttflush();
1609 extern int ansimove(int, int);
1610 extern int ansieeol(void);
1611 extern int ansieeop(void);
1612 extern int ansibeep(void);
1613 extern int ansiparm(int);
1614 extern int ansiopen(void);
1615 extern int ansiterminalinfo(int);
1616 extern int ansirev(int);
1619 * Standard terminal interface dispatch table. Most of the fields point into
1620 * "termio" code.
1622 #if defined(VAX) && !defined(__ALPHA)
1623 globaldef
1624 #endif
1626 TERM term = {
1627 NROW-1,
1628 NCOL,
1629 MARGIN,
1630 MROW,
1631 ansiopen,
1632 ansiterminalinfo,
1633 ttclose,
1634 ttgetc,
1635 ttputc,
1636 ttflush,
1637 ansimove,
1638 ansieeol,
1639 ansieeop,
1640 ansibeep,
1641 ansirev
1645 ansimove(int row, int col)
1647 ttputc(ESC);
1648 ttputc('[');
1649 ansiparm(row+1);
1650 ttputc(';');
1651 ansiparm(col+1);
1652 ttputc('H');
1656 ansieeol(void)
1658 ttputc(ESC);
1659 ttputc('[');
1660 ttputc('K');
1664 ansieeop(void)
1666 ttputc(ESC);
1667 ttputc('[');
1668 ttputc('J');
1672 ansirev(int state) /* change reverse video state */
1673 { /* TRUE = reverse, FALSE = normal */
1674 static int PrevState = 0;
1676 if(state != PrevState) {
1677 PrevState = state ;
1678 ttputc(ESC);
1679 ttputc('[');
1680 ttputc(state ? '7': '0');
1681 ttputc('m');
1686 ansibeep(void)
1688 ttputc(BEL);
1689 ttflush();
1693 ansiparm(int n)
1695 register int q;
1697 q = n/10;
1698 if (q != 0)
1699 ansiparm(q);
1700 ttputc((n%10) + '0');
1705 ansiterminalinfo(int termcap_wins)
1707 #if V7
1708 register char *cp;
1709 char *getenv();
1711 if ((cp = getenv("TERM")) == NULL) {
1712 puts("Shell variable TERM not defined!");
1713 exit(1);
1715 if (strcmp(cp, "vt100") != 0) {
1716 puts("Terminal type not 'vt100'!");
1717 exit(1);
1719 #endif
1720 /* revexist = TRUE; dead code? */
1724 ansiopen(void)
1726 ttopen();
1730 #endif /* HARD_CODED_ANSI_TERMINAL */
1731 #else /* _WINDOWS */
1733 /* These are all just noops in Windows */
1735 unsigned
1736 tthascap(void)
1738 return(0);
1742 * o_insert - optimize screen insert of char c
1745 o_insert(UCS c)
1747 return(0);
1752 * o_delete - optimized character deletion
1755 o_delete(void)
1757 return(0);
1762 #endif /* _WINDOWS */