~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to pico/osdep/terminal.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if !defined(lint) && !defined(DOS)
 
2
static char rcsid[] = "$Id: terminal.c 165 2006-10-04 01:09:47Z jpf@u.washington.edu $";
 
3
#endif
 
4
 
 
5
/*
 
6
 * ========================================================================
 
7
 * Copyright 2006 University of Washington
 
8
 *
 
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
 
12
 *
 
13
 *     http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 * ========================================================================
 
16
 *
 
17
 * Program:     Display routines
 
18
 */
 
19
 
 
20
#include <system.h>
 
21
#include <general.h>
 
22
 
 
23
 
 
24
#include "../estruct.h"
 
25
#include "../keydefs.h"
 
26
#include "../pico.h"
 
27
#include "../mode.h"
 
28
 
 
29
#include "tty.h"
 
30
#include "terminal.h"
 
31
 
 
32
#ifndef _WINDOWS
 
33
extern long gmode;
 
34
 
 
35
 
 
36
/*
 
37
 * Useful Defaults
 
38
 */
 
39
#define MARGIN  8                       /* size of minimim margin and   */
 
40
#define MROW    2                       /* rows in menu                 */
 
41
 
 
42
 
 
43
/* any special properties of the current terminal */
 
44
unsigned term_capabilities = (TT_EOLEXIST | TT_SCROLLEXIST | TT_INSCHAR | TT_DELCHAR);
 
45
 
 
46
 
 
47
/*
 
48
 *
 
49
 */
 
50
unsigned
 
51
tthascap(void)
 
52
{
 
53
    return(term_capabilities);
 
54
}
 
55
 
 
56
 
 
57
#if     HAS_TERMINFO
 
58
 
 
59
/*
 
60
 * terminfo-based terminal i/o and control routines
 
61
 */
 
62
 
 
63
 
 
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);
 
76
 
 
77
extern int      tput();
 
78
extern char    *tgoto(char *, int, int);
 
79
extern char    *tigetstr ();
 
80
 
 
81
/**
 
82
 ** Note: The tgoto calls should really be replaced by tparm calls for
 
83
 ** modern terminfo. tgoto(s, x, y) == tparm(s, y, x).
 
84
 **/
 
85
 
 
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;
 
107
char     term_name[40];
 
108
 
 
109
TERM term = {
 
110
        NROW-1,
 
111
        NCOL,
 
112
        MARGIN,
 
113
        MROW,
 
114
        tinfoopen,
 
115
        tinfoterminalinfo,
 
116
        tinfoclose,
 
117
        ttgetc,
 
118
        ttputc,
 
119
        ttflush,
 
120
        tinfomove,
 
121
        tinfoeeol,
 
122
        tinfoeeop,
 
123
        tinfobeep,
 
124
        tinforev
 
125
};
 
126
 
 
127
 
 
128
/*
 
129
 * Add default keypad sequences to the trie.
 
130
 */
 
131
static void
 
132
setup_dflt_esc_seq(void)
 
133
{
 
134
    /*
 
135
     * this is sort of a hack [no kidding], but it allows us to use
 
136
     * the function keys on pc's running telnet
 
137
     */
 
138
 
 
139
    /* 
 
140
     * UW-NDC/UCS vt10[02] application mode.
 
141
     */
 
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);
 
154
 
 
155
    /*
 
156
     * DEC vt100, ANSI and cursor key mode.
 
157
     */
 
158
    kpinsert("\033OA", KEY_UP, 1);
 
159
    kpinsert("\033OB", KEY_DOWN, 1);
 
160
    kpinsert("\033OC", KEY_RIGHT, 1);
 
161
    kpinsert("\033OD", KEY_LEFT, 1);
 
162
 
 
163
    /*
 
164
     * special keypad functions
 
165
     */
 
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);
 
170
 
 
171
    /*
 
172
     * vt220?
 
173
     */
 
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);
 
178
 
 
179
    /*
 
180
     * konsole, XTerm (XFree 4.x.x) keyboard setting
 
181
     */
 
182
    kpinsert("\033[H", KEY_HOME, 1);
 
183
    kpinsert("\033[F", KEY_END, 1);
 
184
 
 
185
    /* 
 
186
     * gnome-terminal 2.6.0, don't know why it
 
187
     * changed from 2.2.1
 
188
     */
 
189
    kpinsert("\033OH", KEY_HOME, 1);
 
190
    kpinsert("\033OF", KEY_END, 1);
 
191
 
 
192
    /*
 
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
 
197
     *  else:
 
198
     *    Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
 
199
     *    PgDn: "\033[6~"
 
200
     *  The best thing to do would be to fix TeraTerm
 
201
     *  keymappings or to tweak terminfo.
 
202
     */
 
203
 
 
204
    /* 
 
205
     * ANSI mode.
 
206
     */
 
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);
 
219
 
 
220
    /*
 
221
     * DEC vt100, ANSI and cursor key mode reset.
 
222
     */
 
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);
 
227
 
 
228
    /*
 
229
     * DEC vt52 mode.
 
230
     */
 
231
    kpinsert("\033A", KEY_UP, 1);
 
232
    kpinsert("\033B", KEY_DOWN, 1);
 
233
    kpinsert("\033C", KEY_RIGHT, 1);
 
234
    kpinsert("\033D", KEY_LEFT, 1);
 
235
 
 
236
    /*
 
237
     * DEC vt52 application keys, and some Zenith 19.
 
238
     */
 
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);
 
243
 
 
244
    /*
 
245
     * Sun Console sequences.
 
246
     */
 
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);
 
252
 
 
253
    /*
 
254
     * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
 
255
     */
 
256
    kpinsert("\033_", KEY_KERMIT, 1);
 
257
 
 
258
    /*
 
259
     * Fake a control character.
 
260
     */
 
261
    kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
 
262
}
 
263
 
 
264
 
 
265
static int
 
266
tinfoterminalinfo(int termcap_wins)
 
267
{
 
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;
 
272
    char   *ttnm;
 
273
 
 
274
    if (Pmaster) {
 
275
        /*
 
276
         *              setupterm() automatically retrieves the value
 
277
         *              of the TERM variable.
 
278
         */
 
279
        int err;
 
280
        ttnm = getenv("TERM");
 
281
        if(!ttnm)
 
282
          return(-1);
 
283
 
 
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);
 
288
    }
 
289
    else {
 
290
        /*
 
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.
 
294
         */
 
295
        setupterm (0, 1, 0);
 
296
    }
 
297
 
 
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");
 
346
 
 
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");
 
357
 
 
358
    _tlines = tigetnum("lines");
 
359
    if(_tlines == -1){
 
360
        char *er;
 
361
        int   rr;
 
362
 
 
363
        /* tigetnum failed, try $LINES */
 
364
        er = getenv("LINES");
 
365
        if(er && (rr = atoi(er)) > 0)
 
366
          _tlines = rr;
 
367
    }
 
368
 
 
369
    _tcolumns = tigetnum("cols");
 
370
    if(_tcolumns == -1){
 
371
        char *ec;
 
372
        int   cc;
 
373
 
 
374
        /* tigetnum failed, try $COLUMNS */
 
375
        ec = getenv("COLUMNS");
 
376
        if(ec && (cc = atoi(ec)) > 0)
 
377
          _tcolumns = cc;
 
378
    }
 
379
    
 
380
    /*
 
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.
 
388
     */
 
389
    if(!termcap_wins)
 
390
      setup_dflt_esc_seq();
 
391
 
 
392
    /*
 
393
     * add termcap/info escape sequences to the trie...
 
394
     */
 
395
 
 
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);
 
401
    }
 
402
 
 
403
    if(_kppu != NULL && _kppd != NULL){
 
404
        kpinsert(_kppu, KEY_PGUP, termcap_wins);
 
405
        kpinsert(_kppd, KEY_PGDN, termcap_wins);
 
406
    }
 
407
 
 
408
    kpinsert(_kphome, KEY_HOME, termcap_wins);
 
409
    kpinsert(_kpend,  KEY_END, termcap_wins);
 
410
    kpinsert(_kpdel,  KEY_DEL, termcap_wins);
 
411
 
 
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);
 
424
 
 
425
    /*
 
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.
 
433
     */
 
434
    if(termcap_wins)
 
435
      setup_dflt_esc_seq();
 
436
 
 
437
    if(Pmaster)
 
438
      return(0);
 
439
    else
 
440
      return(TRUE);
 
441
}
 
442
 
 
443
static int
 
444
tinfoopen(void)
 
445
{
 
446
    int     row, col;
 
447
 
 
448
    /*
 
449
     * determine the terminal's communication speed and decide
 
450
     * if we need to do optimization ...
 
451
     */
 
452
    if(ttisslow())
 
453
      term_capabilities |= TT_OPTIMIZE;
 
454
    
 
455
    col = _tcolumns;
 
456
    row = _tlines;
 
457
    if(row >= 0)
 
458
      row--;
 
459
 
 
460
    ttgetwinsz(&row, &col);
 
461
    term.t_nrow = (short) row;
 
462
    term.t_ncol = (short) col;
 
463
 
 
464
    if(_cleartoeoln != NULL)    /* able to use clear to EOL? */
 
465
      term_capabilities |= TT_EOLEXIST;
 
466
    else
 
467
      term_capabilities &= ~TT_EOLEXIST;
 
468
 
 
469
    if(_setinverse != NULL)
 
470
      term_capabilities |= TT_REVEXIST;
 
471
    else
 
472
      term_capabilities &= ~TT_REVEXIST;
 
473
 
 
474
    if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
 
475
      term_capabilities &= ~TT_DELCHAR;
 
476
 
 
477
    if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
 
478
      term_capabilities &= ~TT_INSCHAR;
 
479
 
 
480
    if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
 
481
       && (_deleteline == NULL || _insertline == NULL))
 
482
      term_capabilities &= ~TT_SCROLLEXIST;
 
483
 
 
484
    if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
 
485
        if(Pmaster == NULL){
 
486
            puts("Incomplete terminfo entry\n");
 
487
            exit(1);
 
488
        }
 
489
    }
 
490
 
 
491
    ttopen();
 
492
 
 
493
    if(_termcap_init && !Pmaster) {
 
494
        putpad(_termcap_init);          /* any init terminfo requires */
 
495
        if (_scrollregion)
 
496
          putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
 
497
    }
 
498
 
 
499
    /*
 
500
     * Initialize UW-modified NCSA telnet to use its functionkeys
 
501
     */
 
502
    if((gmode & MDFKEY) && Pmaster == NULL)
 
503
      puts("\033[99h");
 
504
 
 
505
    /* return ignored */
 
506
    return(0);
 
507
}
 
508
 
 
509
 
 
510
static int
 
511
tinfoclose(void)
 
512
{
 
513
    if(!Pmaster){
 
514
        if(gmode&MDFKEY)
 
515
          puts("\033[99l");             /* reset UW-NCSA telnet keys */
 
516
 
 
517
        if(_termcap_end)                /* any clean up terminfo requires */
 
518
          putpad(_termcap_end);
 
519
    }
 
520
 
 
521
    ttclose();
 
522
    
 
523
    /* return ignored */
 
524
    return(0);
 
525
}
 
526
 
 
527
 
 
528
/*
 
529
 * tinfoinsert - insert a character at the current character position.
 
530
 *               _insertchar takes precedence.
 
531
 */
 
532
static void
 
533
tinfoinsert(int ch)
 
534
{
 
535
    if(_insertchar != NULL){
 
536
        putpad(_insertchar);
 
537
        ttputc(ch);
 
538
    }
 
539
    else{
 
540
        putpad(_startinsert);
 
541
        ttputc(ch);
 
542
        putpad(_endinsert);
 
543
    }
 
544
}
 
545
 
 
546
 
 
547
/*
 
548
 * tinfodelete - delete a character at the current character position.
 
549
 */
 
550
static void
 
551
tinfodelete(void)
 
552
{
 
553
    if(_startdelete == NULL && _enddelete == NULL)
 
554
      putpad(_deletechar);
 
555
    else{
 
556
        putpad(_startdelete);
 
557
        putpad(_deletechar);
 
558
        putpad(_enddelete);
 
559
    }
 
560
}
 
561
 
 
562
 
 
563
/*
 
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.
 
567
 */
 
568
int
 
569
o_scrolldown(int row, int n)
 
570
{
 
571
    register int i;
 
572
 
 
573
    if(_scrollregion != NULL){
 
574
        putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
 
575
        tinfomove(row, 0);
 
576
        for(i = 0; i < n; i++)
 
577
          putpad((_scrollup != NULL && *_scrollup != '\0') ? _scrollup : "\n" );
 
578
        putpad(tgoto(_scrollregion, term.t_nrow, 0));
 
579
        tinfomove(row, 0);
 
580
    }
 
581
    else{
 
582
        /*
 
583
         * this code causes a jiggly motion of the keymenu when scrolling
 
584
         */
 
585
        for(i = 0; i < n; i++){
 
586
            tinfomove(term.t_nrow - (term.t_mrow+1), 0);
 
587
            putpad(_deleteline);
 
588
            tinfomove(row, 0);
 
589
            putpad(_insertline);
 
590
        }
 
591
#ifdef  NOWIGGLYLINES
 
592
        /*
 
593
         * this code causes a sweeping motion up and down the display
 
594
         */
 
595
        tinfomove(term.t_nrow - term.t_mrow - n, 0);
 
596
        for(i = 0; i < n; i++)
 
597
          putpad(_deleteline);
 
598
        tinfomove(row, 0);
 
599
        for(i = 0; i < n; i++)
 
600
          putpad(_insertline);
 
601
#endif
 
602
    }
 
603
 
 
604
    /* return ignored */
 
605
    return(0);
 
606
}
 
607
 
 
608
 
 
609
/*
 
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.
 
613
 */
 
614
int
 
615
o_scrollup(int row, int n)
 
616
{
 
617
    register int i;
 
618
 
 
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"
 
625
                                                                 : _scrolldown);
 
626
        putpad(tgoto(_scrollregion, term.t_nrow, 0));
 
627
        tinfomove(2, 0);
 
628
    }
 
629
    else{
 
630
        for(i = 0; i < n; i++){
 
631
            tinfomove(row, 0);
 
632
            putpad(_deleteline);
 
633
            tinfomove(term.t_nrow - (term.t_mrow+1), 0);
 
634
            putpad(_insertline);
 
635
        }
 
636
#ifdef  NOWIGGLYLINES
 
637
        /* see note above */
 
638
        tinfomove(row, 0);
 
639
        for(i = 0; i < n; i++)
 
640
          putpad(_deleteline);
 
641
        tinfomove(term.t_nrow - term.t_mrow - n, 0);
 
642
        for(i = 0;i < n; i++)
 
643
          putpad(_insertline);
 
644
#endif
 
645
    }
 
646
 
 
647
    /* return ignored */
 
648
    return(0);
 
649
}
 
650
 
 
651
 
 
652
 
 
653
/*
 
654
 * o_insert - use terminfo to optimized character insert
 
655
 *            returns: true if it optimized output, false otherwise
 
656
 */
 
657
int
 
658
o_insert(int c)
 
659
{
 
660
    if(term_capabilities & TT_INSCHAR){
 
661
        tinfoinsert(c);
 
662
        return(1);                      /* no problems! */
 
663
    }
 
664
 
 
665
    return(0);                          /* can't do it. */
 
666
}
 
667
 
 
668
 
 
669
/*
 
670
 * o_delete - use terminfo to optimized character insert
 
671
 *            returns true if it optimized output, false otherwise
 
672
 */
 
673
int
 
674
o_delete(void)
 
675
{
 
676
    if(term_capabilities & TT_DELCHAR){
 
677
        tinfodelete();
 
678
        return(1);                      /* deleted, no problem! */
 
679
    }
 
680
 
 
681
    return(0);                          /* no dice. */
 
682
}
 
683
 
 
684
 
 
685
static int
 
686
tinfomove(int row, int col)
 
687
{
 
688
    putpad(tgoto(_moveto, col, row));
 
689
 
 
690
    /* return ignored */
 
691
    return(0);
 
692
}
 
693
 
 
694
 
 
695
static int
 
696
tinfoeeol(void)
 
697
{
 
698
    int   c, starting_col, starting_line;
 
699
    char *last_bg_color;
 
700
 
 
701
    /*
 
702
     * If the terminal doesn't have back color erase, then we have to
 
703
     * erase manually to preserve the background color.
 
704
     */
 
705
    if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
 
706
        extern int ttcol, ttrow;
 
707
 
 
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++)
 
713
          ttputc(' ');
 
714
        
 
715
        tinfomove(starting_line, starting_col);
 
716
        if(last_bg_color){
 
717
            pico_set_bg_color(last_bg_color);
 
718
            free(last_bg_color);
 
719
        }
 
720
    }
 
721
    else if(_cleartoeoln)
 
722
      putpad(_cleartoeoln);
 
723
 
 
724
    /* return ignored */
 
725
    return(0);
 
726
}
 
727
 
 
728
 
 
729
static int
 
730
tinfoeeop(void)
 
731
{
 
732
    int i, starting_col, starting_row;
 
733
 
 
734
    /*
 
735
     * If the terminal doesn't have back color erase, then we have to
 
736
     * erase manually to preserve the background color.
 
737
     */
 
738
    if(pico_usingcolor() && (!_bce || !_cleartoeos)){
 
739
        extern int ttcol, ttrow;
 
740
 
 
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 */
 
745
            tinfomove(i, 0);
 
746
            tinfoeeol();
 
747
        }
 
748
 
 
749
        tinfomove(starting_row, starting_col);
 
750
    }
 
751
    else if(_cleartoeos)
 
752
      putpad(_cleartoeos);
 
753
 
 
754
    /* return ignored */
 
755
    return(0);
 
756
}
 
757
 
 
758
 
 
759
static int
 
760
tinforev(int state)             /* change reverse video status */
 
761
{                               /* FALSE = normal video, TRUE = rev video */
 
762
    if(state)
 
763
      StartInverse();
 
764
    else
 
765
      EndInverse();
 
766
 
 
767
    return(1);
 
768
}
 
769
 
 
770
 
 
771
static int
 
772
tinfobeep(void)
 
773
{
 
774
    ttputc(BELL);
 
775
 
 
776
    /* return ignored */
 
777
    return(0);
 
778
}
 
779
 
 
780
 
 
781
void
 
782
putpad(char *str)
 
783
{
 
784
    tputs(str, 1, ttputc);
 
785
}
 
786
 
 
787
#elif   HAS_TERMCAP
 
788
 
 
789
/*
 
790
 * termcap-based terminal i/o and control routines
 
791
 */
 
792
 
 
793
 
 
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 *);
 
807
 
 
808
extern int      tput();
 
809
extern char     *tgoto(char *, int, int);
 
810
 
 
811
/*
 
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. 
 
816
 */
 
817
#define TCAPSLEN 800
 
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;
 
840
char     term_name[40];
 
841
 
 
842
TERM term = {
 
843
        NROW-1,
 
844
        NCOL,
 
845
        MARGIN,
 
846
        MROW,
 
847
        tcapopen,
 
848
        tcapterminalinfo,
 
849
        tcapclose,
 
850
        ttgetc,
 
851
        ttputc,
 
852
        ttflush,
 
853
        tcapmove,
 
854
        tcapeeol,
 
855
        tcapeeop,
 
856
        tcapbeep,
 
857
        tcaprev
 
858
};
 
859
 
 
860
 
 
861
/*
 
862
 * Add default keypad sequences to the trie.
 
863
 */
 
864
static void
 
865
setup_dflt_esc_seq(void)
 
866
{
 
867
    /*
 
868
     * this is sort of a hack, but it allows us to use
 
869
     * the function keys on pc's running telnet
 
870
     */
 
871
 
 
872
    /* 
 
873
     * UW-NDC/UCS vt10[02] application mode.
 
874
     */
 
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);
 
887
 
 
888
    /*
 
889
     * DC vt100, ANSI and cursor key mode.
 
890
     */
 
891
    kpinsert("\033OA", KEY_UP, 1);
 
892
    kpinsert("\033OB", KEY_DOWN, 1);
 
893
    kpinsert("\033OC", KEY_RIGHT, 1);
 
894
    kpinsert("\033OD", KEY_LEFT, 1);
 
895
 
 
896
    /*
 
897
     * special keypad functions
 
898
     */
 
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);
 
903
 
 
904
    /*
 
905
     * vt220?
 
906
     */
 
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);
 
911
 
 
912
    /*
 
913
     * konsole, XTerm (XFree 4.x.x) keyboard setting
 
914
     */
 
915
    kpinsert("\033[H", KEY_HOME, 1);
 
916
    kpinsert("\033[F", KEY_END, 1);
 
917
 
 
918
    /* 
 
919
     * gnome-terminal 2.6.0, don't know why it
 
920
     * changed from 2.2.1
 
921
     */
 
922
    kpinsert("\033OH", KEY_HOME, 1);
 
923
    kpinsert("\033OF", KEY_END, 1);
 
924
 
 
925
    /*
 
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
 
930
     *  else:
 
931
     *    Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~"
 
932
     *    PgDn: "\033[6~"
 
933
     *  The best thing to do would be to fix TeraTerm
 
934
     *  keymappings or to tweak terminfo.
 
935
     */
 
936
 
 
937
    /* 
 
938
     * ANSI mode.
 
939
     */
 
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);
 
952
 
 
953
    /*
 
954
     * DEC vt100, ANSI, cursor key mode reset.
 
955
     */
 
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);
 
960
 
 
961
    /*
 
962
     * DEC vt52 mode.
 
963
     */
 
964
    kpinsert("\033A", KEY_UP, 1);
 
965
    kpinsert("\033B", KEY_DOWN, 1);
 
966
    kpinsert("\033C", KEY_RIGHT, 1);
 
967
    kpinsert("\033D", KEY_LEFT, 1);
 
968
 
 
969
    /*
 
970
     * DEC vt52 application keys, and some Zenith 19.
 
971
     */
 
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);
 
976
 
 
977
    /*
 
978
     * Sun Console sequences.
 
979
     */
 
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);
 
985
 
 
986
    /*
 
987
     * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
 
988
     */
 
989
    kpinsert("\033_", KEY_KERMIT, 1);
 
990
 
 
991
    /*
 
992
     * Fake a control character.
 
993
     */
 
994
    kpinsert("\033\033", KEY_DOUBLE_ESC, 1);
 
995
}
 
996
 
 
997
 
 
998
/*
 
999
 * Read termcap and set some global variables. Initialize input trie to
 
1000
 * decode escape sequences.
 
1001
 */
 
1002
static int
 
1003
tcapterminalinfo(int termcap_wins)
 
1004
{
 
1005
    char   *p, *tgetstr();
 
1006
    char    tcbuf[2*1024];
 
1007
    char   *tv_stype;
 
1008
    char    err_str[72];
 
1009
    int     err;
 
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;
 
1014
 
 
1015
    if (!(tv_stype = getenv("TERM")) || !strncpy(term_name, tv_stype, sizeof(term_name))){
 
1016
        if(Pmaster){
 
1017
            return(-1);
 
1018
        }
 
1019
        else{
 
1020
            puts("Environment variable TERM not defined!");
 
1021
            exit(1);
 
1022
        }
 
1023
    }
 
1024
 
 
1025
    term_name[sizeof(term_name)-1] = '\0';
 
1026
 
 
1027
    if((err = tgetent(tcbuf, tv_stype)) != 1){
 
1028
        if(Pmaster){
 
1029
            return(err - 2);
 
1030
        }
 
1031
        else{
 
1032
            snprintf(err_str, sizeof(err_str), "Unknown terminal type %s!", tv_stype);
 
1033
            puts(err_str);
 
1034
            exit(1);
 
1035
        }
 
1036
    }
 
1037
 
 
1038
    p = tcapbuf;
 
1039
 
 
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);
 
1089
 
 
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");
 
1100
 
 
1101
    if (p >= &tcapbuf[TCAPSLEN]){
 
1102
        puts("Terminal description too big!\n");
 
1103
        if(Pmaster)
 
1104
          return(-3);
 
1105
        else
 
1106
          exit(1);
 
1107
    }
 
1108
 
 
1109
    _tlines = tgetnum("li");
 
1110
    if(_tlines == -1){
 
1111
        char *er;
 
1112
        int   rr;
 
1113
 
 
1114
        /* tgetnum failed, try $LINES */
 
1115
        er = getenv("LINES");
 
1116
        if(er && (rr = atoi(er)) > 0)
 
1117
          _tlines = rr;
 
1118
    }
 
1119
 
 
1120
    _tcolumns = tgetnum("co");
 
1121
    if(_tcolumns == -1){
 
1122
        char *ec;
 
1123
        int   cc;
 
1124
 
 
1125
        /* tgetnum failed, try $COLUMNS */
 
1126
        ec = getenv("COLUMNS");
 
1127
        if(ec && (cc = atoi(ec)) > 0)
 
1128
          _tcolumns = cc;
 
1129
    }
 
1130
 
 
1131
    /*
 
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.
 
1139
     */
 
1140
    if(!termcap_wins)
 
1141
      setup_dflt_esc_seq();
 
1142
 
 
1143
    /*
 
1144
     * add termcap/info escape sequences to the trie...
 
1145
     */
 
1146
 
 
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);
 
1152
    }
 
1153
 
 
1154
    if(_kppu != NULL && _kppd != NULL){
 
1155
        kpinsert(_kppu, KEY_PGUP, termcap_wins);
 
1156
        kpinsert(_kppd, KEY_PGDN, termcap_wins);
 
1157
    }
 
1158
 
 
1159
    kpinsert(_kphome, KEY_HOME, termcap_wins);
 
1160
    kpinsert(_kpend,  KEY_END, termcap_wins);
 
1161
    kpinsert(_kpdel,  KEY_DEL, termcap_wins);
 
1162
 
 
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);
 
1175
 
 
1176
    /*
 
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.
 
1184
     */
 
1185
    if(termcap_wins)
 
1186
      setup_dflt_esc_seq();
 
1187
 
 
1188
    if(Pmaster)
 
1189
      return(0);
 
1190
    else
 
1191
      return(TRUE);
 
1192
}
 
1193
 
 
1194
static int
 
1195
tcapopen(void)
 
1196
{
 
1197
    int     row, col;
 
1198
 
 
1199
    /*
 
1200
     * determine the terminal's communication speed and decide
 
1201
     * if we need to do optimization ...
 
1202
     */
 
1203
    if(ttisslow())
 
1204
      term_capabilities |= TT_OPTIMIZE;
 
1205
 
 
1206
    col = _tcolumns;
 
1207
    row = _tlines;
 
1208
    if(row >= 0)
 
1209
      row--;
 
1210
 
 
1211
    ttgetwinsz(&row, &col);
 
1212
    term.t_nrow = (short) row;
 
1213
    term.t_ncol = (short) col;
 
1214
 
 
1215
    if(_cleartoeoln != NULL)    /* able to use clear to EOL? */
 
1216
      term_capabilities |= TT_EOLEXIST;
 
1217
    else
 
1218
      term_capabilities &= ~TT_EOLEXIST;
 
1219
 
 
1220
    if(_setinverse != NULL)
 
1221
      term_capabilities |= TT_REVEXIST;
 
1222
    else
 
1223
      term_capabilities &= ~TT_REVEXIST;
 
1224
 
 
1225
    if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL))
 
1226
      term_capabilities &= ~TT_DELCHAR;
 
1227
 
 
1228
    if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL))
 
1229
      term_capabilities &= ~TT_INSCHAR;
 
1230
 
 
1231
    if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL)
 
1232
       && (_deleteline == NULL || _insertline == NULL))
 
1233
      term_capabilities &= ~TT_SCROLLEXIST;
 
1234
 
 
1235
    if(_clearscreen == NULL || _moveto == NULL || _up == NULL){
 
1236
        if(Pmaster == NULL){
 
1237
            puts("Incomplete termcap entry\n");
 
1238
            exit(1);
 
1239
        }
 
1240
    }
 
1241
 
 
1242
    ttopen();
 
1243
 
 
1244
    if(_termcap_init && !Pmaster) {
 
1245
        putpad(_termcap_init);          /* any init termcap requires */
 
1246
        if (_scrollregion)
 
1247
          putpad(tgoto(_scrollregion, term.t_nrow, 0)) ;
 
1248
    }
 
1249
 
 
1250
    /*
 
1251
     * Initialize UW-modified NCSA telnet to use it's functionkeys
 
1252
     */
 
1253
    if(gmode&MDFKEY && Pmaster == NULL)
 
1254
      puts("\033[99h");
 
1255
    
 
1256
    /* return ignored */
 
1257
    return(0);
 
1258
}
 
1259
 
 
1260
 
 
1261
static int
 
1262
tcapclose(void)
 
1263
{
 
1264
    if(!Pmaster){
 
1265
        if(gmode&MDFKEY)
 
1266
          puts("\033[99l");             /* reset UW-NCSA telnet keys */
 
1267
 
 
1268
        if(_termcap_end)                /* any cleanup termcap requires */
 
1269
          putpad(_termcap_end);
 
1270
    }
 
1271
 
 
1272
    ttclose();
 
1273
    
 
1274
    /* return ignored */
 
1275
    return(0);
 
1276
}
 
1277
 
 
1278
 
 
1279
 
 
1280
/*
 
1281
 * tcapinsert - insert a character at the current character position.
 
1282
 *              _insertchar takes precedence.
 
1283
 */
 
1284
static void
 
1285
tcapinsert(int ch)
 
1286
{
 
1287
    if(_insertchar != NULL){
 
1288
        putpad(_insertchar);
 
1289
        ttputc(ch);
 
1290
    }
 
1291
    else{
 
1292
        putpad(_startinsert);
 
1293
        ttputc(ch);
 
1294
        putpad(_endinsert);
 
1295
    }
 
1296
}
 
1297
 
 
1298
 
 
1299
/*
 
1300
 * tcapdelete - delete a character at the current character position.
 
1301
 */
 
1302
static void
 
1303
tcapdelete(void)
 
1304
{
 
1305
    if(_startdelete == NULL && _enddelete == NULL)
 
1306
      putpad(_deletechar);
 
1307
    else{
 
1308
        putpad(_startdelete);
 
1309
        putpad(_deletechar);
 
1310
        putpad(_enddelete);
 
1311
    }
 
1312
}
 
1313
 
 
1314
 
 
1315
/*
 
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.
 
1319
 */
 
1320
int
 
1321
o_scrolldown(int row, int n)
 
1322
{
 
1323
    register int i;
 
1324
 
 
1325
    if(_scrollregion != NULL){
 
1326
        putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row));
 
1327
        tcapmove(row, 0);
 
1328
        for(i = 0; i < n; i++)
 
1329
          putpad( (_scrollup != NULL && *_scrollup != '\0')
 
1330
                  ? _scrollup : "\n" );
 
1331
        putpad(tgoto(_scrollregion, term.t_nrow, 0));
 
1332
        tcapmove(row, 0);
 
1333
    }
 
1334
    else{
 
1335
        /*
 
1336
         * this code causes a jiggly motion of the keymenu when scrolling
 
1337
         */
 
1338
        for(i = 0; i < n; i++){
 
1339
            tcapmove(term.t_nrow - (term.t_mrow+1), 0);
 
1340
            putpad(_deleteline);
 
1341
            tcapmove(row, 0);
 
1342
            putpad(_insertline);
 
1343
        }
 
1344
#ifdef  NOWIGGLYLINES
 
1345
        /*
 
1346
         * this code causes a sweeping motion up and down the display
 
1347
         */
 
1348
        tcapmove(term.t_nrow - term.t_mrow - n, 0);
 
1349
        for(i = 0; i < n; i++)
 
1350
          putpad(_deleteline);
 
1351
        tcapmove(row, 0);
 
1352
        for(i = 0; i < n; i++)
 
1353
          putpad(_insertline);
 
1354
#endif
 
1355
    }
 
1356
    
 
1357
    /* return ignored */
 
1358
    return(0);
 
1359
}
 
1360
 
 
1361
 
 
1362
/*
 
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.
 
1366
 */
 
1367
int
 
1368
o_scrollup(int row, int n)
 
1369
{
 
1370
    register int i;
 
1371
 
 
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));
 
1380
        tcapmove(2, 0);
 
1381
    }
 
1382
    else{
 
1383
        for(i = 0; i < n; i++){
 
1384
            tcapmove(row, 0);
 
1385
            putpad(_deleteline);
 
1386
            tcapmove(term.t_nrow - (term.t_mrow+1), 0);
 
1387
            putpad(_insertline);
 
1388
        }
 
1389
#ifdef  NOWIGGLYLINES
 
1390
        /* see note above */
 
1391
        tcapmove(row, 0);
 
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);
 
1397
#endif
 
1398
    }
 
1399
 
 
1400
    /* return ignored */
 
1401
    return(0);
 
1402
}
 
1403
 
 
1404
 
 
1405
/*
 
1406
 * o_insert - use termcap info to optimized character insert
 
1407
 *            returns: true if it optimized output, false otherwise
 
1408
 */
 
1409
int
 
1410
o_insert(int c)
 
1411
{
 
1412
    if(term_capabilities & TT_INSCHAR){
 
1413
        tcapinsert(c);
 
1414
        return(1);                      /* no problems! */
 
1415
    }
 
1416
 
 
1417
    return(0);                          /* can't do it. */
 
1418
}
 
1419
 
 
1420
 
 
1421
/*
 
1422
 * o_delete - use termcap info to optimized character insert
 
1423
 *            returns true if it optimized output, false otherwise
 
1424
 */
 
1425
int
 
1426
o_delete(void)
 
1427
{
 
1428
    if(term_capabilities & TT_DELCHAR){
 
1429
        tcapdelete();
 
1430
        return(1);                      /* deleted, no problem! */
 
1431
    }
 
1432
 
 
1433
    return(0);                          /* no dice. */
 
1434
}
 
1435
 
 
1436
 
 
1437
static int
 
1438
tcapmove(int row, int col)
 
1439
{
 
1440
    putpad(tgoto(_moveto, col, row));
 
1441
 
 
1442
    /* return ignored */
 
1443
    return(0);
 
1444
}
 
1445
 
 
1446
 
 
1447
static int
 
1448
tcapeeol(void)
 
1449
{
 
1450
    int   c, starting_col, starting_line;
 
1451
    char *last_bg_color;
 
1452
 
 
1453
    /*
 
1454
     * If the terminal doesn't have back color erase, then we have to
 
1455
     * erase manually to preserve the background color.
 
1456
     */
 
1457
    if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
 
1458
        extern int ttcol, ttrow;
 
1459
 
 
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++)
 
1465
          ttputc(' ');
 
1466
        
 
1467
        tcapmove(starting_line, starting_col);
 
1468
        if(last_bg_color){
 
1469
            pico_set_bg_color(last_bg_color);
 
1470
            free(last_bg_color);
 
1471
        }
 
1472
    }
 
1473
    else if(_cleartoeoln)
 
1474
      putpad(_cleartoeoln);
 
1475
 
 
1476
    /* return ignored */
 
1477
    return(0);
 
1478
}
 
1479
 
 
1480
 
 
1481
static int
 
1482
tcapeeop(void)
 
1483
{
 
1484
    int i, starting_col, starting_row;
 
1485
 
 
1486
    /*
 
1487
     * If the terminal doesn't have back color erase, then we have to
 
1488
     * erase manually to preserve the background color.
 
1489
     */
 
1490
    if(pico_usingcolor() && (!_bce || !_cleartoeos)){
 
1491
        extern int ttcol, ttrow;
 
1492
 
 
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 */
 
1497
            tcapmove(i, 0);
 
1498
            tcapeeol();
 
1499
        }
 
1500
 
 
1501
        tcapmove(starting_row, starting_col);
 
1502
    }
 
1503
    else if(_cleartoeos)
 
1504
      putpad(_cleartoeos);
 
1505
 
 
1506
    /* return ignored */
 
1507
    return(0);
 
1508
}
 
1509
 
 
1510
 
 
1511
static int
 
1512
tcaprev(int state)              /* change reverse video status */
 
1513
{                               /* FALSE = normal video, TRUE = reverse video */
 
1514
    if(state)
 
1515
      StartInverse();
 
1516
    else
 
1517
      EndInverse();
 
1518
 
 
1519
    return(1);
 
1520
}
 
1521
 
 
1522
 
 
1523
static int
 
1524
tcapbeep(void)
 
1525
{
 
1526
    ttputc(BELL);
 
1527
 
 
1528
    /* return ignored */
 
1529
    return(0);
 
1530
}
 
1531
 
 
1532
 
 
1533
static void
 
1534
putpad(char *str)
 
1535
{
 
1536
    tputs(str, 1, ttputc);
 
1537
}
 
1538
 
 
1539
#else  /* HARD_CODED_ANSI_TERMINAL */
 
1540
 
 
1541
/*
 
1542
 * ANSI-specific terminal i/o and control routines
 
1543
 */
 
1544
 
 
1545
 
 
1546
#define BEL     0x07                    /* BEL character.               */
 
1547
#define ESC     0x1B                    /* ESC character.               */
 
1548
 
 
1549
 
 
1550
extern  int     ttflush();
 
1551
 
 
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);
 
1560
 
 
1561
/*
 
1562
 * Standard terminal interface dispatch table. Most of the fields point into
 
1563
 * "termio" code.
 
1564
 */
 
1565
#if defined(VAX) && !defined(__ALPHA)
 
1566
globaldef
 
1567
#endif
 
1568
 
 
1569
TERM    term    = {
 
1570
        NROW-1,
 
1571
        NCOL,
 
1572
        MARGIN,
 
1573
        MROW,
 
1574
        ansiopen,
 
1575
        ansiterminalinfo,
 
1576
        ttclose,
 
1577
        ttgetc,
 
1578
        ttputc,
 
1579
        ttflush,
 
1580
        ansimove,
 
1581
        ansieeol,
 
1582
        ansieeop,
 
1583
        ansibeep,
 
1584
        ansirev
 
1585
};
 
1586
 
 
1587
int
 
1588
ansimove(int row, int col)
 
1589
{
 
1590
        ttputc(ESC);
 
1591
        ttputc('[');
 
1592
        ansiparm(row+1);
 
1593
        ttputc(';');
 
1594
        ansiparm(col+1);
 
1595
        ttputc('H');
 
1596
}
 
1597
 
 
1598
int
 
1599
ansieeol(void)
 
1600
{
 
1601
        ttputc(ESC);
 
1602
        ttputc('[');
 
1603
        ttputc('K');
 
1604
}
 
1605
 
 
1606
int
 
1607
ansieeop(void)
 
1608
{
 
1609
        ttputc(ESC);
 
1610
        ttputc('[');
 
1611
        ttputc('J');
 
1612
}
 
1613
 
 
1614
int
 
1615
ansirev(int state)      /* change reverse video state */
 
1616
{                       /* TRUE = reverse, FALSE = normal */
 
1617
        static int PrevState = 0;
 
1618
 
 
1619
        if(state != PrevState) {
 
1620
                PrevState = state ;
 
1621
                ttputc(ESC);
 
1622
                ttputc('[');
 
1623
                ttputc(state ? '7': '0');
 
1624
                ttputc('m');
 
1625
        }
 
1626
}
 
1627
 
 
1628
int
 
1629
ansibeep(void)
 
1630
{
 
1631
        ttputc(BEL);
 
1632
        ttflush();
 
1633
}
 
1634
 
 
1635
int
 
1636
ansiparm(int n)
 
1637
{
 
1638
        register int    q;
 
1639
 
 
1640
        q = n/10;
 
1641
        if (q != 0)
 
1642
                ansiparm(q);
 
1643
        ttputc((n%10) + '0');
 
1644
}
 
1645
 
 
1646
 
 
1647
int
 
1648
ansiterminalinfo(int termcap_wins)
 
1649
{
 
1650
#if     V7
 
1651
        register char *cp;
 
1652
        char *getenv();
 
1653
 
 
1654
        if ((cp = getenv("TERM")) == NULL) {
 
1655
                puts("Shell variable TERM not defined!");
 
1656
                exit(1);
 
1657
        }
 
1658
        if (strcmp(cp, "vt100") != 0) {
 
1659
                puts("Terminal type not 'vt100'!");
 
1660
                exit(1);
 
1661
        }
 
1662
#endif
 
1663
        /* revexist = TRUE; dead code? */
 
1664
}
 
1665
 
 
1666
int
 
1667
ansiopen(void)
 
1668
{
 
1669
        ttopen();
 
1670
}
 
1671
 
 
1672
 
 
1673
#endif /* HARD_CODED_ANSI_TERMINAL */
 
1674
#else /* _WINDOWS */
 
1675
 
 
1676
/* These are all just noops in Windows */
 
1677
 
 
1678
unsigned
 
1679
tthascap(void)
 
1680
{
 
1681
    return(0);
 
1682
}
 
1683
 
 
1684
/*
 
1685
 * o_insert - optimize screen insert of char c
 
1686
 */
 
1687
int
 
1688
o_insert(int c)
 
1689
{
 
1690
    return(0);
 
1691
}
 
1692
 
 
1693
 
 
1694
/*
 
1695
 * o_delete - optimized character deletion
 
1696
 */
 
1697
int
 
1698
o_delete(void)
 
1699
{
 
1700
    return(0);
 
1701
}
 
1702
 
 
1703
 
 
1704
 
 
1705
#endif /* _WINDOWS */