1
#if !defined(lint) && !defined(DOS)
2
static char rcsid[] = "$Id: terminal.c 165 2006-10-04 01:09:47Z jpf@u.washington.edu $";
6
* ========================================================================
7
* Copyright 2006 University of Washington
9
* Licensed under the Apache License, Version 2.0 (the "License");
10
* you may not use this file except in compliance with the License.
11
* You may obtain a copy of the License at
13
* http://www.apache.org/licenses/LICENSE-2.0
15
* ========================================================================
17
* Program: Display routines
24
#include "../estruct.h"
25
#include "../keydefs.h"
39
#define MARGIN 8 /* size of minimim margin and */
40
#define MROW 2 /* rows in menu */
43
/* any special properties of the current terminal */
44
unsigned term_capabilities = (TT_EOLEXIST | TT_SCROLLEXIST | TT_INSCHAR | TT_DELCHAR);
53
return(term_capabilities);
60
* terminfo-based terminal i/o and control routines
64
/* internal prototypes */
65
static int tinfomove(int, int);
66
static int tinfoeeol(void);
67
static int tinfoeeop(void);
68
static int tinfobeep(void);
69
static int tinforev(int);
70
static int tinfoopen(void);
71
static int tinfoterminalinfo(int);
72
static int tinfoclose(void);
73
static void setup_dflt_esc_seq(void);
74
static void tinfoinsert(int);
75
static void tinfodelete(void);
78
extern char *tgoto(char *, int, int);
79
extern char *tigetstr ();
82
** Note: The tgoto calls should really be replaced by tparm calls for
83
** modern terminfo. tgoto(s, x, y) == tparm(s, y, x).
86
int _tlines, _tcolumns;
87
char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
88
*_setinverse, *_clearinverse,
89
*_setunderline, *_clearunderline,
90
*_setbold, *_clearallattr, /* there is no clear only bold! */
91
*_cleartoeoln, *_cleartoeos,
92
*_deleteline, /* delete line */
93
*_insertline, /* insert line */
94
*_scrollregion, /* define a scrolling region, vt100 */
95
*_insertchar, /* insert character, preferable to : */
96
*_startinsert, /* set insert mode and, */
97
*_endinsert, /* end insert mode */
98
*_deletechar, /* delete character */
99
*_startdelete, /* set delete mode and, */
100
*_enddelete, /* end delete mode */
101
*_scrolldown, /* scroll down */
102
*_scrollup, /* scroll up */
103
*_termcap_init, /* string to start termcap */
104
*_termcap_end, /* string to end termcap */
105
*_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp;
106
int _colors, _pairs, _bce;
129
* Add default keypad sequences to the trie.
132
setup_dflt_esc_seq(void)
135
* this is sort of a hack [no kidding], but it allows us to use
136
* the function keys on pc's running telnet
140
* UW-NDC/UCS vt10[02] application mode.
142
kpinsert("\033OP", F1, 1);
143
kpinsert("\033OQ", F2, 1);
144
kpinsert("\033OR", F3, 1);
145
kpinsert("\033OS", F4, 1);
146
kpinsert("\033Op", F5, 1);
147
kpinsert("\033Oq", F6, 1);
148
kpinsert("\033Or", F7, 1);
149
kpinsert("\033Os", F8, 1);
150
kpinsert("\033Ot", F9, 1);
151
kpinsert("\033Ou", F10, 1);
152
kpinsert("\033Ov", F11, 1);
153
kpinsert("\033Ow", F12, 1);
156
* DEC vt100, ANSI and cursor key mode.
158
kpinsert("\033OA", KEY_UP, 1);
159
kpinsert("\033OB", KEY_DOWN, 1);
160
kpinsert("\033OC", KEY_RIGHT, 1);
161
kpinsert("\033OD", KEY_LEFT, 1);
164
* special keypad functions
166
kpinsert("\033[4J", KEY_PGUP, 1);
167
kpinsert("\033[3J", KEY_PGDN, 1);
168
kpinsert("\033[2J", KEY_HOME, 1);
169
kpinsert("\033[N", KEY_END, 1);
174
kpinsert("\033[5~", KEY_PGUP, 1);
175
kpinsert("\033[6~", KEY_PGDN, 1);
176
kpinsert("\033[1~", KEY_HOME, 1);
177
kpinsert("\033[4~", KEY_END, 1);
180
* konsole, XTerm (XFree 4.x.x) keyboard setting
182
kpinsert("\033[H", KEY_HOME, 1);
183
kpinsert("\033[F", KEY_END, 1);
186
* gnome-terminal 2.6.0, don't know why it
189
kpinsert("\033OH", KEY_HOME, 1);
190
kpinsert("\033OF", KEY_END, 1);
193
* "\033[2~" was common for KEY_HOME in a quick survey
194
* of terminals (though typically the Insert key).
195
* Teraterm 2.33 sends the following escape sequences,
196
* which is quite incompatible with everything
198
* Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
200
* The best thing to do would be to fix TeraTerm
201
* keymappings or to tweak terminfo.
207
kpinsert("\033[=a", F1, 1);
208
kpinsert("\033[=b", F2, 1);
209
kpinsert("\033[=c", F3, 1);
210
kpinsert("\033[=d", F4, 1);
211
kpinsert("\033[=e", F5, 1);
212
kpinsert("\033[=f", F6, 1);
213
kpinsert("\033[=g", F7, 1);
214
kpinsert("\033[=h", F8, 1);
215
kpinsert("\033[=i", F9, 1);
216
kpinsert("\033[=j", F10, 1);
217
kpinsert("\033[=k", F11, 1);
218
kpinsert("\033[=l", F12, 1);
221
* DEC vt100, ANSI and cursor key mode reset.
223
kpinsert("\033[A", KEY_UP, 1);
224
kpinsert("\033[B", KEY_DOWN, 1);
225
kpinsert("\033[C", KEY_RIGHT, 1);
226
kpinsert("\033[D", KEY_LEFT, 1);
231
kpinsert("\033A", KEY_UP, 1);
232
kpinsert("\033B", KEY_DOWN, 1);
233
kpinsert("\033C", KEY_RIGHT, 1);
234
kpinsert("\033D", KEY_LEFT, 1);
237
* DEC vt52 application keys, and some Zenith 19.
239
kpinsert("\033?r", KEY_DOWN, 1);
240
kpinsert("\033?t", KEY_LEFT, 1);
241
kpinsert("\033?v", KEY_RIGHT, 1);
242
kpinsert("\033?x", KEY_UP, 1);
245
* Sun Console sequences.
247
kpinsert("\033[1", KEY_SWALLOW_Z, 1);
248
kpinsert("\033[215", KEY_SWAL_UP, 1);
249
kpinsert("\033[217", KEY_SWAL_LEFT, 1);
250
kpinsert("\033[219", KEY_SWAL_RIGHT, 1);
251
kpinsert("\033[221", KEY_SWAL_DOWN, 1);
254
* Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
256
kpinsert("\033_", KEY_KERMIT, 1);
259
* Fake a control character.
261
kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
266
tinfoterminalinfo(int termcap_wins)
268
char *_ku, *_kd, *_kl, *_kr,
269
*_kppu, *_kppd, *_kphome, *_kpend, *_kpdel,
270
*_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6,
271
*_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12;
276
* setupterm() automatically retrieves the value
277
* of the TERM variable.
280
ttnm = getenv("TERM");
284
strncpy(term_name, ttnm, sizeof(term_name));
285
term_name[sizeof(term_name)-1] = '\0';
286
setupterm (0, 1, &err);
287
if (err != 1) return(err-2);
291
* setupterm() issues a message and exits, if the
292
* terminfo data base is gone or the term type is
293
* unknown, if arg2 is 0.
298
_clearscreen = tigetstr("clear");
299
_moveto = tigetstr("cup");
300
_up = tigetstr("cuu1");
301
_down = tigetstr("cud1");
302
_right = tigetstr("cuf1");
303
_left = tigetstr("cub1");
304
_setinverse = tigetstr("smso");
305
_clearinverse = tigetstr("rmso");
306
_setunderline = tigetstr("smul");
307
_clearunderline = tigetstr("rmul");
308
_setbold = tigetstr("bold");
309
_clearallattr = tigetstr("sgr0");
310
_cleartoeoln = tigetstr("el");
311
_cleartoeos = tigetstr("ed");
312
_deletechar = tigetstr("dch1");
313
_insertchar = tigetstr("ich1");
314
_startinsert = tigetstr("smir");
315
_endinsert = tigetstr("rmir");
316
_deleteline = tigetstr("dl1");
317
_insertline = tigetstr("il1");
318
_scrollregion = tigetstr("csr");
319
_scrolldown = tigetstr("ind");
320
_scrollup = tigetstr("ri");
321
_termcap_init = tigetstr("smcup");
322
_termcap_end = tigetstr("rmcup");
323
_startdelete = tigetstr("smdc");
324
_enddelete = tigetstr("rmdc");
325
_ku = tigetstr("kcuu1");
326
_kd = tigetstr("kcud1");
327
_kl = tigetstr("kcub1");
328
_kr = tigetstr("kcuf1");
329
_kppu = tigetstr("kpp");
330
_kppd = tigetstr("knp");
331
_kphome = tigetstr("khome");
332
_kpend = tigetstr("kend");
333
_kpdel = tigetstr("kdch1");
334
_kf1 = tigetstr("kf1");
335
_kf2 = tigetstr("kf2");
336
_kf3 = tigetstr("kf3");
337
_kf4 = tigetstr("kf4");
338
_kf5 = tigetstr("kf5");
339
_kf6 = tigetstr("kf6");
340
_kf7 = tigetstr("kf7");
341
_kf8 = tigetstr("kf8");
342
_kf9 = tigetstr("kf9");
343
_kf10 = tigetstr("kf10");
344
_kf11 = tigetstr("kf11");
345
_kf12 = tigetstr("kf12");
347
_colors = tigetnum("colors");
348
_pairs = tigetnum("pairs");
349
_setaf = tigetstr("setaf");
350
_setab = tigetstr("setab");
351
_setf = tigetstr("setf");
352
_setb = tigetstr("setb");
353
_scp = tigetstr("scp");
354
_op = tigetstr("op");
355
_oc = tigetstr("oc");
356
_bce = tigetflag("bce");
358
_tlines = tigetnum("lines");
363
/* tigetnum failed, try $LINES */
364
er = getenv("LINES");
365
if(er && (rr = atoi(er)) > 0)
369
_tcolumns = tigetnum("cols");
374
/* tigetnum failed, try $COLUMNS */
375
ec = getenv("COLUMNS");
376
if(ec && (cc = atoi(ec)) > 0)
381
* Add default keypad sequences to the trie.
382
* Since these come first, they will override any conflicting termcap
383
* or terminfo escape sequences defined below. An escape sequence is
384
* considered conflicting if one is a prefix of the other.
385
* So, without TERMCAP_WINS, there will likely be some termcap/terminfo
386
* escape sequences that don't work, because they conflict with default
387
* sequences defined here.
390
setup_dflt_esc_seq();
393
* add termcap/info escape sequences to the trie...
396
if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){
397
kpinsert(_ku, KEY_UP, termcap_wins);
398
kpinsert(_kd, KEY_DOWN, termcap_wins);
399
kpinsert(_kl, KEY_LEFT, termcap_wins);
400
kpinsert(_kr, KEY_RIGHT, termcap_wins);
403
if(_kppu != NULL && _kppd != NULL){
404
kpinsert(_kppu, KEY_PGUP, termcap_wins);
405
kpinsert(_kppd, KEY_PGDN, termcap_wins);
408
kpinsert(_kphome, KEY_HOME, termcap_wins);
409
kpinsert(_kpend, KEY_END, termcap_wins);
410
kpinsert(_kpdel, KEY_DEL, termcap_wins);
412
kpinsert(_kf1, F1, termcap_wins);
413
kpinsert(_kf2, F2, termcap_wins);
414
kpinsert(_kf3, F3, termcap_wins);
415
kpinsert(_kf4, F4, termcap_wins);
416
kpinsert(_kf5, F5, termcap_wins);
417
kpinsert(_kf6, F6, termcap_wins);
418
kpinsert(_kf7, F7, termcap_wins);
419
kpinsert(_kf8, F8, termcap_wins);
420
kpinsert(_kf9, F9, termcap_wins);
421
kpinsert(_kf10, F10, termcap_wins);
422
kpinsert(_kf11, F11, termcap_wins);
423
kpinsert(_kf12, F12, termcap_wins);
426
* Add default keypad sequences to the trie.
427
* Since these come after the termcap/terminfo escape sequences above,
428
* the termcap/info sequences will override any conflicting default
429
* escape sequences defined here.
430
* So, with TERMCAP_WINS, some of the default sequences will be missing.
431
* This means that you'd better get all of your termcap/terminfo entries
432
* correct if you define TERMCAP_WINS.
435
setup_dflt_esc_seq();
449
* determine the terminal's communication speed and decide
450
* if we need to do optimization ...
453
term_capabilities |= TT_OPTIMIZE;
460
ttgetwinsz(&row, &col);
461
term.t_nrow = (short) row;
462
term.t_ncol = (short) col;
464
if(_cleartoeoln != NULL) /* able to use clear to EOL? */
465
term_capabilities |= TT_EOLEXIST;
467
term_capabilities &= ~TT_EOLEXIST;
469
if(_setinverse != NULL)
470
term_capabilities |= TT_REVEXIST;
472
term_capabilities &= ~TT_REVEXIST;
474
if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
475
term_capabilities &= ~TT_DELCHAR;
477
if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
478
term_capabilities &= ~TT_INSCHAR;
480
if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
481
&& (_deleteline == NULL || _insertline == NULL))
482
term_capabilities &= ~TT_SCROLLEXIST;
484
if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
486
puts("Incomplete terminfo entry\n");
493
if(_termcap_init && !Pmaster) {
494
putpad(_termcap_init); /* any init terminfo requires */
496
putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
500
* Initialize UW-modified NCSA telnet to use its functionkeys
502
if((gmode & MDFKEY) && Pmaster == NULL)
515
puts("\033[99l"); /* reset UW-NCSA telnet keys */
517
if(_termcap_end) /* any clean up terminfo requires */
518
putpad(_termcap_end);
529
* tinfoinsert - insert a character at the current character position.
530
* _insertchar takes precedence.
535
if(_insertchar != NULL){
540
putpad(_startinsert);
548
* tinfodelete - delete a character at the current character position.
553
if(_startdelete == NULL && _enddelete == NULL)
556
putpad(_startdelete);
564
* o_scrolldown() - open a line at the given row position.
565
* use either region scrolling or deleteline/insertline
566
* to open a new line.
569
o_scrolldown(int row, int n)
573
if(_scrollregion != NULL){
574
putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
576
for(i = 0; i < n; i++)
577
putpad((_scrollup != NULL && *_scrollup != '\0') ? _scrollup : "\n" );
578
putpad(tgoto(_scrollregion, term.t_nrow, 0));
583
* this code causes a jiggly motion of the keymenu when scrolling
585
for(i = 0; i < n; i++){
586
tinfomove(term.t_nrow - (term.t_mrow+1), 0);
593
* this code causes a sweeping motion up and down the display
595
tinfomove(term.t_nrow - term.t_mrow - n, 0);
596
for(i = 0; i < n; i++)
599
for(i = 0; i < n; i++)
610
* o_scrollup() - open a line at the given row position.
611
* use either region scrolling or deleteline/insertline
612
* to open a new line.
615
o_scrollup(int row, int n)
619
if(_scrollregion != NULL){
620
putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
621
/* setting scrolling region moves cursor to home */
622
tinfomove(term.t_nrow-(term.t_mrow+1), 0);
623
for(i = 0;i < n; i++)
624
putpad((_scrolldown == NULL || _scrolldown[0] == '\0') ? "\n"
626
putpad(tgoto(_scrollregion, term.t_nrow, 0));
630
for(i = 0; i < n; i++){
633
tinfomove(term.t_nrow - (term.t_mrow+1), 0);
639
for(i = 0; i < n; i++)
641
tinfomove(term.t_nrow - term.t_mrow - n, 0);
642
for(i = 0;i < n; i++)
654
* o_insert - use terminfo to optimized character insert
655
* returns: true if it optimized output, false otherwise
660
if(term_capabilities & TT_INSCHAR){
662
return(1); /* no problems! */
665
return(0); /* can't do it. */
670
* o_delete - use terminfo to optimized character insert
671
* returns true if it optimized output, false otherwise
676
if(term_capabilities & TT_DELCHAR){
678
return(1); /* deleted, no problem! */
681
return(0); /* no dice. */
686
tinfomove(int row, int col)
688
putpad(tgoto(_moveto, col, row));
698
int c, starting_col, starting_line;
702
* If the terminal doesn't have back color erase, then we have to
703
* erase manually to preserve the background color.
705
if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
706
extern int ttcol, ttrow;
708
starting_col = ttcol;
709
starting_line = ttrow;
710
last_bg_color = pico_get_last_bg_color();
711
pico_set_nbg_color();
712
for(c = ttcol; c < term.t_ncol; c++)
715
tinfomove(starting_line, starting_col);
717
pico_set_bg_color(last_bg_color);
721
else if(_cleartoeoln)
722
putpad(_cleartoeoln);
732
int i, starting_col, starting_row;
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 || !_cleartoeos)){
739
extern int ttcol, ttrow;
741
starting_col = ttcol;
742
starting_row = ttrow;
743
tinfoeeol(); /* rest of this line */
744
for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */
749
tinfomove(starting_row, starting_col);
760
tinforev(int state) /* change reverse video status */
761
{ /* FALSE = normal video, TRUE = rev video */
784
tputs(str, 1, ttputc);
790
* termcap-based terminal i/o and control routines
794
/* internal prototypes */
795
static int tcapmove(int, int);
796
static int tcapeeol(void);
797
static int tcapeeop(void);
798
static int tcapbeep(void);
799
static int tcaprev(int);
800
static int tcapopen(void);
801
static int tcapterminalinfo(int);
802
static int tcapclose(void);
803
static void setup_dflt_esc_seq(void);
804
static void tcapinsert(int);
805
static void tcapdelete(void);
806
static void putpad(char *);
809
extern char *tgoto(char *, int, int);
812
* This number used to be 315. No doubt there was a reason for that but we
813
* don't know what it was. It's a bit of a hassle to make it dynamic, and most
814
* modern systems seem to be using terminfo, so we'll just change it to 800.
815
* We weren't stopping on overflow before, so we'll do that, too.
818
char tcapbuf[TCAPSLEN];
819
int _tlines, _tcolumns;
820
char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
821
*_setinverse, *_clearinverse,
822
*_setunderline, *_clearunderline,
823
*_setbold, *_clearallattr, /* there is no clear only bold! */
824
*_cleartoeoln, *_cleartoeos,
825
*_deleteline, /* delete line */
826
*_insertline, /* insert line */
827
*_scrollregion, /* define a scrolling region, vt100 */
828
*_insertchar, /* insert character, preferable to : */
829
*_startinsert, /* set insert mode and, */
830
*_endinsert, /* end insert mode */
831
*_deletechar, /* delete character */
832
*_startdelete, /* set delete mode and, */
833
*_enddelete, /* end delete mode */
834
*_scrolldown, /* scroll down */
835
*_scrollup, /* scroll up */
836
*_termcap_init, /* string to start termcap */
837
*_termcap_end, /* string to end termcap */
838
*_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp;
839
int _colors, _pairs, _bce;
862
* Add default keypad sequences to the trie.
865
setup_dflt_esc_seq(void)
868
* this is sort of a hack, but it allows us to use
869
* the function keys on pc's running telnet
873
* UW-NDC/UCS vt10[02] application mode.
875
kpinsert("\033OP", F1, 1);
876
kpinsert("\033OQ", F2, 1);
877
kpinsert("\033OR", F3, 1);
878
kpinsert("\033OS", F4, 1);
879
kpinsert("\033Op", F5, 1);
880
kpinsert("\033Oq", F6, 1);
881
kpinsert("\033Or", F7, 1);
882
kpinsert("\033Os", F8, 1);
883
kpinsert("\033Ot", F9, 1);
884
kpinsert("\033Ou", F10, 1);
885
kpinsert("\033Ov", F11, 1);
886
kpinsert("\033Ow", F12, 1);
889
* DC vt100, ANSI and cursor key mode.
891
kpinsert("\033OA", KEY_UP, 1);
892
kpinsert("\033OB", KEY_DOWN, 1);
893
kpinsert("\033OC", KEY_RIGHT, 1);
894
kpinsert("\033OD", KEY_LEFT, 1);
897
* special keypad functions
899
kpinsert("\033[4J", KEY_PGUP, 1);
900
kpinsert("\033[3J", KEY_PGDN, 1);
901
kpinsert("\033[2J", KEY_HOME, 1);
902
kpinsert("\033[N", KEY_END, 1);
907
kpinsert("\033[5~", KEY_PGUP, 1);
908
kpinsert("\033[6~", KEY_PGDN, 1);
909
kpinsert("\033[1~", KEY_HOME, 1);
910
kpinsert("\033[4~", KEY_END, 1);
913
* konsole, XTerm (XFree 4.x.x) keyboard setting
915
kpinsert("\033[H", KEY_HOME, 1);
916
kpinsert("\033[F", KEY_END, 1);
919
* gnome-terminal 2.6.0, don't know why it
922
kpinsert("\033OH", KEY_HOME, 1);
923
kpinsert("\033OF", KEY_END, 1);
926
* "\033[2~" was common for KEY_HOME in a quick survey
927
* of terminals (though typically the Insert key).
928
* Teraterm 2.33 sends the following escape sequences,
929
* which is quite incompatible with everything
931
* Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
933
* The best thing to do would be to fix TeraTerm
934
* keymappings or to tweak terminfo.
940
kpinsert("\033[=a", F1, 1);
941
kpinsert("\033[=b", F2, 1);
942
kpinsert("\033[=c", F3, 1);
943
kpinsert("\033[=d", F4, 1);
944
kpinsert("\033[=e", F5, 1);
945
kpinsert("\033[=f", F6, 1);
946
kpinsert("\033[=g", F7, 1);
947
kpinsert("\033[=h", F8, 1);
948
kpinsert("\033[=i", F9, 1);
949
kpinsert("\033[=j", F10, 1);
950
kpinsert("\033[=k", F11, 1);
951
kpinsert("\033[=l", F12, 1);
954
* DEC vt100, ANSI, cursor key mode reset.
956
kpinsert("\033[A", KEY_UP, 1);
957
kpinsert("\033[B", KEY_DOWN, 1);
958
kpinsert("\033[C", KEY_RIGHT, 1);
959
kpinsert("\033[D", KEY_LEFT, 1);
964
kpinsert("\033A", KEY_UP, 1);
965
kpinsert("\033B", KEY_DOWN, 1);
966
kpinsert("\033C", KEY_RIGHT, 1);
967
kpinsert("\033D", KEY_LEFT, 1);
970
* DEC vt52 application keys, and some Zenith 19.
972
kpinsert("\033?r", KEY_DOWN, 1);
973
kpinsert("\033?t", KEY_LEFT, 1);
974
kpinsert("\033?v", KEY_RIGHT, 1);
975
kpinsert("\033?x", KEY_UP, 1);
978
* Sun Console sequences.
980
kpinsert("\033[1", KEY_SWALLOW_Z, 1);
981
kpinsert("\033[215", KEY_SWAL_UP, 1);
982
kpinsert("\033[217", KEY_SWAL_LEFT, 1);
983
kpinsert("\033[219", KEY_SWAL_RIGHT, 1);
984
kpinsert("\033[221", KEY_SWAL_DOWN, 1);
987
* Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
989
kpinsert("\033_", KEY_KERMIT, 1);
992
* Fake a control character.
994
kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
999
* Read termcap and set some global variables. Initialize input trie to
1000
* decode escape sequences.
1003
tcapterminalinfo(int termcap_wins)
1005
char *p, *tgetstr();
1010
char *_ku, *_kd, *_kl, *_kr,
1011
*_kppu, *_kppd, *_kphome, *_kpend, *_kpdel,
1012
*_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6,
1013
*_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12;
1015
if (!(tv_stype = getenv("TERM")) || !strncpy(term_name, tv_stype, sizeof(term_name))){
1020
puts("Environment variable TERM not defined!");
1025
term_name[sizeof(term_name)-1] = '\0';
1027
if((err = tgetent(tcbuf, tv_stype)) != 1){
1032
snprintf(err_str, sizeof(err_str), "Unknown terminal type %s!", tv_stype);
1040
_clearscreen = tgetstr("cl", &p);
1041
_moveto = tgetstr("cm", &p);
1042
_up = tgetstr("up", &p);
1043
_down = tgetstr("do", &p);
1044
_right = tgetstr("nd", &p);
1045
_left = tgetstr("bs", &p);
1046
_setinverse = tgetstr("so", &p);
1047
_clearinverse = tgetstr("se", &p);
1048
_setunderline = tgetstr("us", &p);
1049
_clearunderline = tgetstr("ue", &p);
1050
_setbold = tgetstr("md", &p);
1051
_clearallattr = tgetstr("me", &p);
1052
_cleartoeoln = tgetstr("ce", &p);
1053
_cleartoeos = tgetstr("cd", &p);
1054
_deletechar = tgetstr("dc", &p);
1055
_insertchar = tgetstr("ic", &p);
1056
_startinsert = tgetstr("im", &p);
1057
_endinsert = tgetstr("ei", &p);
1058
_deleteline = tgetstr("dl", &p);
1059
_insertline = tgetstr("al", &p);
1060
_scrollregion = tgetstr("cs", &p);
1061
_scrolldown = tgetstr("sf", &p);
1062
_scrollup = tgetstr("sr", &p);
1063
_termcap_init = tgetstr("ti", &p);
1064
_termcap_end = tgetstr("te", &p);
1065
_startdelete = tgetstr("dm", &p);
1066
_enddelete = tgetstr("ed", &p);
1067
_ku = tgetstr("ku", &p);
1068
_kd = tgetstr("kd", &p);
1069
_kl = tgetstr("kl", &p);
1070
_kr = tgetstr("kr", &p);
1071
_kppu = tgetstr("kP", &p);
1072
_kppd = tgetstr("kN", &p);
1073
_kphome = tgetstr("kh", &p);
1074
_kpend = tgetstr("kH", &p);
1075
_kpdel = tgetstr("kD", &p);
1076
_kf1 = tgetstr("k1", &p);
1077
_kf2 = tgetstr("k2", &p);
1078
_kf3 = tgetstr("k3", &p);
1079
_kf4 = tgetstr("k4", &p);
1080
_kf5 = tgetstr("k5", &p);
1081
_kf6 = tgetstr("k6", &p);
1082
_kf7 = tgetstr("k7", &p);
1083
_kf8 = tgetstr("k8", &p);
1084
_kf9 = tgetstr("k9", &p);
1085
if((_kf10 = tgetstr("k;", &p)) == NULL)
1086
_kf10 = tgetstr("k0", &p);
1087
_kf11 = tgetstr("F1", &p);
1088
_kf12 = tgetstr("F2", &p);
1090
_colors = tgetnum("Co");
1091
_pairs = tgetnum("pa");
1092
_setaf = tgetstr("AF", &p);
1093
_setab = tgetstr("AB", &p);
1094
_setf = tgetstr("Sf", &p);
1095
_setb = tgetstr("Sb", &p);
1096
_scp = tgetstr("sp", &p);
1097
_op = tgetstr("op", &p);
1098
_oc = tgetstr("oc", &p);
1099
_bce = tgetflag("ut");
1101
if (p >= &tcapbuf[TCAPSLEN]){
1102
puts("Terminal description too big!\n");
1109
_tlines = tgetnum("li");
1114
/* tgetnum failed, try $LINES */
1115
er = getenv("LINES");
1116
if(er && (rr = atoi(er)) > 0)
1120
_tcolumns = tgetnum("co");
1121
if(_tcolumns == -1){
1125
/* tgetnum failed, try $COLUMNS */
1126
ec = getenv("COLUMNS");
1127
if(ec && (cc = atoi(ec)) > 0)
1132
* Add default keypad sequences to the trie.
1133
* Since these come first, they will override any conflicting termcap
1134
* or terminfo escape sequences defined below. An escape sequence is
1135
* considered conflicting if one is a prefix of the other.
1136
* So, without TERMCAP_WINS, there will likely be some termcap/terminfo
1137
* escape sequences that don't work, because they conflict with default
1138
* sequences defined here.
1141
setup_dflt_esc_seq();
1144
* add termcap/info escape sequences to the trie...
1147
if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){
1148
kpinsert(_ku, KEY_UP, termcap_wins);
1149
kpinsert(_kd, KEY_DOWN, termcap_wins);
1150
kpinsert(_kl, KEY_LEFT, termcap_wins);
1151
kpinsert(_kr, KEY_RIGHT, termcap_wins);
1154
if(_kppu != NULL && _kppd != NULL){
1155
kpinsert(_kppu, KEY_PGUP, termcap_wins);
1156
kpinsert(_kppd, KEY_PGDN, termcap_wins);
1159
kpinsert(_kphome, KEY_HOME, termcap_wins);
1160
kpinsert(_kpend, KEY_END, termcap_wins);
1161
kpinsert(_kpdel, KEY_DEL, termcap_wins);
1163
kpinsert(_kf1, F1, termcap_wins);
1164
kpinsert(_kf2, F2, termcap_wins);
1165
kpinsert(_kf3, F3, termcap_wins);
1166
kpinsert(_kf4, F4, termcap_wins);
1167
kpinsert(_kf5, F5, termcap_wins);
1168
kpinsert(_kf6, F6, termcap_wins);
1169
kpinsert(_kf7, F7, termcap_wins);
1170
kpinsert(_kf8, F8, termcap_wins);
1171
kpinsert(_kf9, F9, termcap_wins);
1172
kpinsert(_kf10, F10, termcap_wins);
1173
kpinsert(_kf11, F11, termcap_wins);
1174
kpinsert(_kf12, F12, termcap_wins);
1177
* Add default keypad sequences to the trie.
1178
* Since these come after the termcap/terminfo escape sequences above,
1179
* the termcap/info sequences will override any conflicting default
1180
* escape sequences defined here.
1181
* So, with TERMCAP_WINS, some of the default sequences will be missing.
1182
* This means that you'd better get all of your termcap/terminfo entries
1183
* correct if you define TERMCAP_WINS.
1186
setup_dflt_esc_seq();
1200
* determine the terminal's communication speed and decide
1201
* if we need to do optimization ...
1204
term_capabilities |= TT_OPTIMIZE;
1211
ttgetwinsz(&row, &col);
1212
term.t_nrow = (short) row;
1213
term.t_ncol = (short) col;
1215
if(_cleartoeoln != NULL) /* able to use clear to EOL? */
1216
term_capabilities |= TT_EOLEXIST;
1218
term_capabilities &= ~TT_EOLEXIST;
1220
if(_setinverse != NULL)
1221
term_capabilities |= TT_REVEXIST;
1223
term_capabilities &= ~TT_REVEXIST;
1225
if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
1226
term_capabilities &= ~TT_DELCHAR;
1228
if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
1229
term_capabilities &= ~TT_INSCHAR;
1231
if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
1232
&& (_deleteline == NULL || _insertline == NULL))
1233
term_capabilities &= ~TT_SCROLLEXIST;
1235
if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
1236
if(Pmaster == NULL){
1237
puts("Incomplete termcap entry\n");
1244
if(_termcap_init && !Pmaster) {
1245
putpad(_termcap_init); /* any init termcap requires */
1247
putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
1251
* Initialize UW-modified NCSA telnet to use it's functionkeys
1253
if(gmode&MDFKEY && Pmaster == NULL)
1256
/* return ignored */
1266
puts("\033[99l"); /* reset UW-NCSA telnet keys */
1268
if(_termcap_end) /* any cleanup termcap requires */
1269
putpad(_termcap_end);
1274
/* return ignored */
1281
* tcapinsert - insert a character at the current character position.
1282
* _insertchar takes precedence.
1287
if(_insertchar != NULL){
1288
putpad(_insertchar);
1292
putpad(_startinsert);
1300
* tcapdelete - delete a character at the current character position.
1305
if(_startdelete == NULL && _enddelete == NULL)
1306
putpad(_deletechar);
1308
putpad(_startdelete);
1309
putpad(_deletechar);
1316
* o_scrolldown - open a line at the given row position.
1317
* use either region scrolling or deleteline/insertline
1318
* to open a new line.
1321
o_scrolldown(int row, int n)
1325
if(_scrollregion != NULL){
1326
putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
1328
for(i = 0; i < n; i++)
1329
putpad( (_scrollup != NULL && *_scrollup != '\0')
1330
? _scrollup : "\n" );
1331
putpad(tgoto(_scrollregion, term.t_nrow, 0));
1336
* this code causes a jiggly motion of the keymenu when scrolling
1338
for(i = 0; i < n; i++){
1339
tcapmove(term.t_nrow - (term.t_mrow+1), 0);
1340
putpad(_deleteline);
1342
putpad(_insertline);
1344
#ifdef NOWIGGLYLINES
1346
* this code causes a sweeping motion up and down the display
1348
tcapmove(term.t_nrow - term.t_mrow - n, 0);
1349
for(i = 0; i < n; i++)
1350
putpad(_deleteline);
1352
for(i = 0; i < n; i++)
1353
putpad(_insertline);
1357
/* return ignored */
1363
* o_scrollup - open a line at the given row position.
1364
* use either region scrolling or deleteline/insertline
1365
* to open a new line.
1368
o_scrollup(int row, int n)
1372
if(_scrollregion != NULL){
1373
putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
1374
/* setting scrolling region moves cursor to home */
1375
tcapmove(term.t_nrow-(term.t_mrow+1), 0);
1376
for(i = 0;i < n; i++)
1377
putpad((_scrolldown == NULL || _scrolldown[0] == '\0')
1378
? "\n" : _scrolldown);
1379
putpad(tgoto(_scrollregion, term.t_nrow, 0));
1383
for(i = 0; i < n; i++){
1385
putpad(_deleteline);
1386
tcapmove(term.t_nrow - (term.t_mrow+1), 0);
1387
putpad(_insertline);
1389
#ifdef NOWIGGLYLINES
1390
/* see note above */
1392
for(i = 0; i < n; i++)
1393
putpad(_deleteline);
1394
tcapmove(term.t_nrow - term.t_mrow - n, 0);
1395
for(i = 0;i < n; i++)
1396
putpad(_insertline);
1400
/* return ignored */
1406
* o_insert - use termcap info to optimized character insert
1407
* returns: true if it optimized output, false otherwise
1412
if(term_capabilities & TT_INSCHAR){
1414
return(1); /* no problems! */
1417
return(0); /* can't do it. */
1422
* o_delete - use termcap info to optimized character insert
1423
* returns true if it optimized output, false otherwise
1428
if(term_capabilities & TT_DELCHAR){
1430
return(1); /* deleted, no problem! */
1433
return(0); /* no dice. */
1438
tcapmove(int row, int col)
1440
putpad(tgoto(_moveto, col, row));
1442
/* return ignored */
1450
int c, starting_col, starting_line;
1451
char *last_bg_color;
1454
* If the terminal doesn't have back color erase, then we have to
1455
* erase manually to preserve the background color.
1457
if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
1458
extern int ttcol, ttrow;
1460
starting_col = ttcol;
1461
starting_line = ttrow;
1462
last_bg_color = pico_get_last_bg_color();
1463
pico_set_nbg_color();
1464
for(c = ttcol; c < term.t_ncol; c++)
1467
tcapmove(starting_line, starting_col);
1469
pico_set_bg_color(last_bg_color);
1470
free(last_bg_color);
1473
else if(_cleartoeoln)
1474
putpad(_cleartoeoln);
1476
/* return ignored */
1484
int i, starting_col, starting_row;
1487
* If the terminal doesn't have back color erase, then we have to
1488
* erase manually to preserve the background color.
1490
if(pico_usingcolor() && (!_bce || !_cleartoeos)){
1491
extern int ttcol, ttrow;
1493
starting_col = ttcol;
1494
starting_row = ttrow;
1495
tcapeeol(); /* rest of this line */
1496
for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */
1501
tcapmove(starting_row, starting_col);
1503
else if(_cleartoeos)
1504
putpad(_cleartoeos);
1506
/* return ignored */
1512
tcaprev(int state) /* change reverse video status */
1513
{ /* FALSE = normal video, TRUE = reverse video */
1528
/* return ignored */
1536
tputs(str, 1, ttputc);
1539
#else /* HARD_CODED_ANSI_TERMINAL */
1542
* ANSI-specific terminal i/o and control routines
1546
#define BEL 0x07 /* BEL character. */
1547
#define ESC 0x1B /* ESC character. */
1550
extern int ttflush();
1552
extern int ansimove(int, int);
1553
extern int ansieeol(void);
1554
extern int ansieeop(void);
1555
extern int ansibeep(void);
1556
extern int ansiparm(int);
1557
extern int ansiopen(void);
1558
extern int ansiterminalinfo(int);
1559
extern int ansirev(int);
1562
* Standard terminal interface dispatch table. Most of the fields point into
1565
#if defined(VAX) && !defined(__ALPHA)
1588
ansimove(int row, int col)
1615
ansirev(int state) /* change reverse video state */
1616
{ /* TRUE = reverse, FALSE = normal */
1617
static int PrevState = 0;
1619
if(state != PrevState) {
1623
ttputc(state ? '7': '0');
1643
ttputc((n%10) + '0');
1648
ansiterminalinfo(int termcap_wins)
1654
if ((cp = getenv("TERM")) == NULL) {
1655
puts("Shell variable TERM not defined!");
1658
if (strcmp(cp, "vt100") != 0) {
1659
puts("Terminal type not 'vt100'!");
1663
/* revexist = TRUE; dead code? */
1673
#endif /* HARD_CODED_ANSI_TERMINAL */
1674
#else /* _WINDOWS */
1676
/* These are all just noops in Windows */
1685
* o_insert - optimize screen insert of char c
1695
* o_delete - optimized character deletion
1705
#endif /* _WINDOWS */