source: trunk/minix/commands/elle/eeterm.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 30.2 KB
Line 
1/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
5 */
6/*
7 * EETERM ELLE Terminal Driver.
8 * Directly supports DM2500, H-19, Omron 8025AG, Coherent/IBM-PC, TVI925.
9 * Others also supported if using TX_TERMCAP.
10 */
11
12#include "elle.h"
13
14/* Define terminal indices (there may be holes but C preprocessor is too
15 * stupid to let us close them). Should be one TN_ definition for every
16 * hardwired terminal type, even though whether or not it is actually
17 * compiled depends on which TX_ switches are defined.
18 */
19#define TN_TERMCAP 0
20#define TN_DM2500 1
21#define TN_H19 2
22#define TN_OM8025 3
23#define TN_COHIBM 4 /* Coherent IBM-PC console */
24#define TN_TVI925 5
25
26#if TX_COHIBM && !(TX_H19) /* Ensure H19 defined if COHIBM is. */
27#define TX_H19 1
28#endif
29
30#ifndef TXS_DEFAULT /* If no default is explicitly specified */
31#define TXS_DEFAULT "H19" /* Then settle for H-19 */
32#endif /*TXS_DEFAULT*/
33
34
35
36
37extern char *tv_stype; /* If set, specifies terminal type */
38extern int tibfmsk; /* Crock to mask off parity (meta) bit */
39static int tv_padc; /* Pad character to use */
40static int tv_cspeed; /* # msec per char (set from trm_ospeed) */
41static int tv_type; /* Index of selected terminal type */
42
43/* Internal functions */
44static void tpadn(), tpad();
45
46/* Character speed table, indexed by system output speed value (0-017).
47 * Value in table is 100 * <# msec used per character>.
48 */
49static int cspdtab[] =
50{ /* Val Idx Baud CPS Time/char in msec */
51 0, /* 0 Hangup - ---- */
52 13333, /* 1 50 7.5 133.33 (Baudot) */
53 10000, /* 2 75 10 100.0 (Baudot) */
54 10000, /* 3 110 10 100.0 */
55 8200, /* 4 134.5 12.2 82.0 (IBM2741) */
56 6666, /* 5 150 15 66.6666 */
57 5000, /* 6 200 20 50.0 */
58 3333, /* 7 300 30 33.3333 */
59 1666, /* 8 600 60 16.6666 */
60 833, /* 9 1200 120 8.3333 */
61 555, /* 10 1800 180 5.5555 */
62 416, /* 11 2400 240 4.1666 */
63 208, /* 12 4800 480 2.0833 */
64 104, /* 13 9600 960 1.04166 */
65 0, /* 14 Ext A ? ? */
66 0 /* 15 Ext B ? ? */
67};
68
69#if TX_TERMCAP
70/* Declarations for TERMCAP stuff. Only EETERM knows about them. */
71
72/* Termcap routines */
73extern int tgetent(), tgetnum(), tgetflag(), tputs();
74extern char *tgetstr(), *tgoto();
75static int getcap(); /* Internal routines */
76static void putpad(), putnpad(), putpar();
77
78/* Gross disgusting externals that must be defined for TERMCAP rtns */
79char PC; /* Pad char */
80char *BC; /* Backspace to use, if not ^H */
81char *UP; /* Cursor up */
82short ospeed; /* Terminal output speed */
83
84/* Termcap numerical values/flags */
85static int
86 tc_am, /* TRUE if has auto-wrap */
87 tc_km; /* TRUE if meta key exists */
88
89/* Termcap capability strings we want to know about */
90
91struct tcap { char tcicod1, tcicod2, *tccap; };
92static struct tcap tcap[] = {
93#define TC_al tcap[0].tccap /* Add (insert) line */
94 {'a','l', 0},
95#define TC_AL tcap[1].tccap /* Add N lines */
96 {'A','L', 0},
97#define TC_bc tcap[2].tccap /* Backspace Char (for BC) */
98 {'b','c', 0},
99#define TC_ce tcap[3].tccap /* Erase to end of line (CLEOL) */
100 {'c','e', 0},
101#define TC_cl tcap[4].tccap /* Clear screen */
102 {'c','l', 0},
103#define TC_cm tcap[5].tccap /* Cursor motion */
104 {'c','m', 0},
105#define TC_dc tcap[6].tccap /* Delete char */
106 {'d','c', 0},
107#define TC_DC tcap[7].tccap /* Delete N chars */
108 {'D','C', 0},
109#define TC_dl tcap[8].tccap /* Delete line */
110 {'d','l', 0},
111#define TC_DL tcap[9].tccap /* Delete N lines */
112 {'D','L', 0},
113#define TC_dm tcap[10].tccap /* Delete mode on */
114 {'d','m', 0},
115#define TC_ed tcap[11].tccap /* Delete mode off */
116 {'e','d', 0},
117#define TC_ei tcap[12].tccap /* Insert mode off */
118 {'e','i', 0},
119#define TC_ia tcap[13].tccap /* Add line while in insert mode (see note) */
120 {'i','a', 0},
121#define TC_ic tcap[14].tccap /* Insert blank char */
122 {'i','c', 0},
123#define TC_IC tcap[15].tccap /* Insert N blank chars */
124 {'I','C', 0},
125#define TC_id tcap[16].tccap /* Delete line while in del mode (see note) */
126 {'i','d', 0},
127#define TC_im tcap[17].tccap /* Insert mode on */
128 {'i','m', 0},
129#define TC_ip tcap[18].tccap /* Padding to send after char insertion */
130 {'i','p', 0},
131#define TC_mm tcap[19].tccap /* String to set (turn on) meta-key mode */
132 {'m','m', 0},
133#define TC_mo tcap[20].tccap /* String to reset (turn off) meta-key mode */
134 {'m','o', 0},
135#define TC_pc tcap[21].tccap /* Pad Char (for PC) */
136 {'p','c', 0},
137#define TC_se tcap[22].tccap /* End standout mode */
138 {'s','e', 0},
139#define TC_so tcap[23].tccap /* Enter standout mode */
140 {'s','o', 0},
141#define TC_te tcap[24].tccap /* String to end programs that use termcap */
142 {'t','e', 0},
143#define TC_ti tcap[25].tccap /* String to beg programs that use termcap */
144 {'t','i', 0},
145#define TC_up tcap[26].tccap /* Move cursor up (for UP) */
146 {'u','p', 0},
147#define TC_vb tcap[27].tccap /* Visible bell */
148 {'v','b', 0},
149};
150#define NTCAPS ((sizeof(tcap))/(sizeof(struct tcap))) /* # entries */
151
152/*
153 * There are many other things that must be taken into account.
154 * The termcap code here will probably not work for many termcap entries,
155 * but the only sure way to find out which ones they are is to try them.
156 */
157/* Note that the "ia" and "id" strings are not defined by the TERMCAP doc;
158 * their usage here is derived from examining other TERMCAP-using programs.
159 * Sigh!!!!
160 */
161#endif /*TX_TERMCAP*/
162
163
164/* T_INIT is called once only at program startup, to identify the
165 * terminal type and set up any one-time things.
166 * T_FATAL is only called if some routine detects an error related to the
167 * terminal specification, before any initialization is done.
168 * It prints a short error message and exits the program.
169 * T_ENTER is called after TS_ENTER to set the terminal parameters for
170 * editing (as opposed to normal typeout). It may be called
171 * several times.
172 * T_EXIT is called before TS_EXIT to restore normal typeout modes.
173 * It is called on exit from the program, and perhaps other times.
174 */
175t_init()
176{
177 char *getenv();
178
179 /* Set some default parameters */
180 scr_ht = 24;
181 scr_wid = 79;
182 trm_flags = 0;
183 tvc_cin = 1; /* Assume 1 char per char I/D pos */
184 tvc_cdn = 1;
185 tvc_pos = 4; /* Default abs-move cost is 4 chars */
186 tvc_bs = 1; /* Default backspace cost is 1 char */
187 tv_cspeed = cspdtab[trm_ospeed]; /* Find # msec per char */
188
189 /* First must determine terminal type, and check for terminals
190 * that are hardwired into ELLE. */
191 if(!tv_stype /* String set in command line args? */
192#if !(V6)
193 && !(tv_stype = getenv("TERM")) /* or given by TERM var? */
194#endif /*-V6*/
195 ) tv_stype = TXS_DEFAULT; /* No, try using default */
196 if(0) ; /* Sigh, stupid construct */
197#if TX_H19
198 else if(ustrcmp(tv_stype,"H19")) tv_type = TN_H19;
199#endif /*TX_H19*/
200#if TX_OM8025
201 else if(ustrcmp(tv_stype,"OM8025")) tv_type = TN_OM8025;
202#endif /*TX_OM8025*/
203#if TX_DM2500
204 else if(ustrcmp(tv_stype,"DM2500")) tv_type = TN_DM2500;
205 else if(ustrcmp(tv_stype,"DM3025")) tv_type = TN_DM2500;
206#endif /*TX_DM2500*/
207#if TX_COHIBM
208 else if(ustrcmp(tv_stype,"COHIBM")) tv_type = TN_COHIBM;
209#endif /*TX_COHIBM*/
210#if TX_TVI925
211 else if(ustrcmp(tv_stype,"TVI925")) tv_type = TN_TVI925;
212#endif /*TX_TVI925*/
213#if TX_TERMCAP /* This should be last thing */
214 else if(getcap(tv_stype)) tv_type = TN_TERMCAP;
215#endif /*TX_TERMCAP*/
216 else t_fatal("type unknown"); /* Ugh, barf and exit */
217
218 /* Terminal selected, now initialize parameters for it. */
219 switch(tv_type)
220 {
221#if TX_DM2500
222 case TN_DM2500:
223 tv_padc = 0177; /* Use rubout for pad */
224 tvc_pos = 3; /* Only 3 chars for abs mov */
225 tvc_ci = 2;
226 /* tvc_cin = 1; */ /* Default is OK */
227 tvc_cd = 2;
228 /* tvc_cdn = 1; */ /* Default is OK */
229 tvc_ld = 2;
230 tvc_ldn = 1;
231 tvc_li = 2;
232 tvc_lin = 1;
233 if(trm_ospeed == 13) /* If 9600, */
234 { tvc_cin = 5; /* Sigh, high cost */
235 tvc_cdn = 2;
236 tvc_lin = 18;
237 tvc_ldn = 2;
238 }
239 trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY;
240 break;
241#endif /*TX_DM2500*/
242#if TX_H19
243 case TN_H19:
244 trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
245 tvc_ci = 8;
246 /* tvc_cin = 1; */ /* default is ok */
247 tvc_cd = 0;
248 tvc_cdn = 2;
249 /* tvc_ld = 0; */ /* Default is OK */
250 tvc_ldn = 1 << (trm_ospeed - 7);
251 /* tvc_li = 0; */ /* Default is OK */
252 tvc_lin = tvc_ldn;
253 break;
254#endif /*TX_H19*/
255#if TX_COHIBM
256 case TN_COHIBM:
257 trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY|TF_DIRVID;
258 /* Always use lowest possible costs */
259 /* tvc_ci = 0; */ /* Default */
260 tvc_cin = 2;
261 /* tvc_cd = 0; */ /* Default */
262 tvc_cdn = 2;
263 /* tvc_ld = 0; */ /* Default */
264 tvc_ldn = 2;
265 /* tvc_li = 0; */ /* Default */
266 tvc_lin = 2;
267 break;
268#endif /*TX_COHIBM*/
269#if TX_OM8025
270 case TN_OM8025:
271 trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
272 tvc_pos = 6;
273 /* tvc_ci = tvc_cd = 0; */ /* Default */
274 tvc_cin = 4;
275 tvc_cdn = 2;
276 /* tvc_ld = tvc_li = 0; */ /* Default */
277 tvc_ldn = 10; /* Crude approx */
278 tvc_lin = 10;
279 if(trm_ospeed > 7) /* If faster than 300 baud */
280 trm_flags &= ~TF_IDLIN; /* Turn off LID */
281 break;
282#endif /*TX_OM8025*/
283#if TX_TVI925
284 case TN_TVI925:
285 trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
286 tvc_ci = tvc_cd = tvc_cin = tvc_cdn
287 = tvc_ldn = tvc_lin = 2;
288 break;
289#endif /*TX_TVI925*/
290 }
291 if(tibfmsk < 0) /* If mask is still default -1, set it. */
292 tibfmsk = ((trm_flags&TF_METAKEY) ? 0377 : 0177);
293}
294
295/* T_FATAL(str) - prints error message and exits.
296*/
297t_fatal(str)
298char *str;
299{ writerr("ELLE: \"");
300 writerr(tv_stype);
301 writerr("\" terminal ");
302 writerr(str);
303 writerr("\n");
304 exit(1); /* Terminate with prejudice */
305}
306
307
308/* T_ENTER is called after TS_ENTER to set the terminal parameters for
309 * editing (as opposed to normal typeout).
310 * Standout mode must initially be off.
311 */
312
313t_enter()
314{ switch(tv_type)
315 {
316#if TX_TERMCAP
317 case TN_TERMCAP:
318 putpad(TC_ti);
319 if(tc_km) putpad(TC_mm); /* Use meta if poss */
320#if FX_SOWIND
321 t_standout(0); /* Ensure standout mode off */
322#endif
323 break;
324#endif /*TX_TERMCAP*/
325#if TX_DM2500
326 case TN_DM2500:
327 tput(030); /* Just in case, flush stray modes */
328 break;
329#endif /*TX_DM2500*/
330#if TX_COHIBM
331 case TN_COHIBM: /* Note TN_H19 will exist too */
332#endif /*TX_COHIBM*/
333#if TX_H19
334 case TN_H19:
335 /* Enter ZDS (Heath) mode, then
336 * Exit graphics mode (G) Exit ins-char mode (O)
337 * exit rev video mode (q) exit hold-screen mode (\)
338 * set cursor on (y5)
339 */
340 tputz("\033[?2h\033G\033O\033q\033\\\033y5");
341 /* Set Discard-at-EOL (w)
342 * Set no auto-CR (y9)
343 * Enable 25th line (x1)
344 */
345 tputz("\033w\033y9\033x1");
346 break;
347#endif /*TX_H19*/
348 }
349}
350
351
352/* T_EXIT - Leave editing modes. This function should restore
353** the terminal's modes to what they were before ELLE was started.
354** Standout mode is turned off.
355*/
356
357t_exit()
358{
359 switch(tv_type)
360 {
361#if TX_TERMCAP
362 case TN_TERMCAP:
363 if(tc_km) putpad(TC_mo); /* Turn off meta */
364 putpad(TC_te);
365 break;
366#endif /*TX_TERMCAP*/
367#if TX_DM2500
368 case TN_DM2500:
369 tput(035); /* Turn on roll mode */
370 break;
371#endif /*TX_DM2500*/
372#if TX_COHIBM
373 case TN_COHIBM: /* If this exists, TN_H19 will too */
374#endif /*TX_COHIBM*/
375#if TX_H19
376 case TN_H19:
377 tputz("\033v"); /* Turn EOL-wrap back on */
378#if DNTTY
379 tputz("\033<"); /* Return to ANSI mode */
380#endif /*DNTTY*/
381 break;
382#endif /*TX_H19*/
383 }
384}
385
386
387/* T_CLEAR() - Clears the screen and homes the cursor.
388 * Always valid - ELLE refuses to support terminals without this.
389 */
390
391t_clear ()
392{ switch(tv_type)
393 {
394#if TX_TERMCAP
395 case TN_TERMCAP:
396 putnpad(TC_cl,scr_ht);
397 break;
398#endif /*TX_TERMCAP*/
399#if TX_DM2500
400 case TN_DM2500:
401 tputz("\036\036"); /* Double Master Clear */
402 break;
403#endif /*TX_DM2500*/
404#if TX_COHIBM
405 case TN_COHIBM: /* Note TN_H19 will exist too */
406#endif /*TX_COHIBM*/
407#if TX_H19
408 case TN_H19:
409 tputz("\033E");
410 /* tputn(zpadstr,9); */
411 break;
412#endif /*TX_H19*/
413#if TX_OM8025
414 case TN_OM8025:
415 tputz("\033H\033J"); /* Home then CLEOS */
416 tpad(1000); /* One second!!!! */
417 break;
418#endif /*TX_OM8025*/
419#if TX_TVI925
420 case TN_TVI925:
421 tput(032); /* ^Z */
422 break;
423#endif /*TX_TVI925*/
424 }
425 curs_lin = curs_col = 0;
426}
427
428
429/* T_CURPOS(y, x) - Absolute move. Place cursor in given position
430 * regardless of where it currently is.
431 * Updates curs_lin, curs_col.
432 * Always valid -- ELLE refuses to support terminals without this.
433 */
434
435t_curpos (lin, col)
436register int lin, col;
437{
438 if(col > scr_wid) /* Easiest to catch here */
439 col = scr_wid;
440
441 /* Do absolute positioning */
442 switch(tv_type)
443 {
444#if TX_TERMCAP
445 case TN_TERMCAP:
446 putpad(tgoto(TC_cm, col, lin));
447 break;
448#endif /*TX_TERMCAP*/
449#if TX_DM2500
450 case TN_DM2500:
451 tput(014);
452 tput(col^0140);
453 tput(lin^0140);
454 break;
455#endif /*TX_DM2500*/
456#if TX_COHIBM
457 case TN_COHIBM: /* If this exists, TN_H19 will too */
458#endif /*TX_COHIBM*/
459#if TX_H19
460 case TN_H19:
461 tputz("\033Y");
462 tput(lin+040);
463 tput(col+040);
464 break;
465#endif /*TX_H19*/
466#if TX_OM8025
467 case TN_OM8025:
468 tputz("\033\175");
469 tput(0100+((lin+1)>>4));
470 tput(0100+((lin+1)&017));
471 tput(0100+((col+1)>>4));
472 tput(0100+((col+1)&017));
473 break;
474#endif /*TX_OM8025*/
475#if TX_TVI925
476 case TN_TVI925:
477 tputz("\033=");
478 tput(lin+040);
479 tput(col+040);
480 break;
481#endif /*TX_TVI925*/
482 }
483 curs_lin = lin;
484 curs_col = col;
485}
486
487/* T_BACKSPACE() - Back up 1 character position.
488 * Updates curs_col.
489 * Only valid if tvc_bs has a "reasonable" value ( < 1000)
490 */
491
492t_backspace()
493{
494#if TX_TERMCAP
495 if(BC) tputz(BC); /* Use alternate BS */
496 else
497#endif
498 tput('\010'); /* Send BS */
499 --curs_col;
500}
501
502/* T_BELL() - Ring terminal's bell (or flash something, or whatever).
503 * Forces out all output thus far, to ensure immediate attention.
504 * This used to be an unbuffered feep, but was changed to use normal
505 * output path in order to avoid messing up terminal escape sequences.
506 */
507t_bell()
508{
509#if TXC_VISBEL && TX_TERMCAP
510 if(TC_vb)
511 tputz(TC_vb); /* Do visible bell if possible */
512 else
513#endif
514 tput(BELL);
515 tbufls(); /* Force it out */
516}
517
518
519/* T_CLEOL() - Clear to End Of Line.
520 * Only valid if trm_flags has TF_CLEOL set.
521 */
522
523t_cleol ()
524{
525 switch(tv_type)
526 {
527#if TX_TERMCAP
528 case TN_TERMCAP:
529 putpad(TC_ce);
530 break;
531#endif /*TX_TERMCAP*/
532#if TX_DM2500
533 case TN_DM2500:
534 tput(027);
535 break;
536#endif /*TX_DM2500*/
537#if TX_COHIBM
538 case TN_COHIBM: /* If this exists, TN_H19 will too */
539#endif /*TX_COHIBM*/
540#if TX_H19
541 case TN_H19:
542 tputz("\033K");
543 break;
544#endif /*TX_H19*/
545#if TX_OM8025
546 case TN_OM8025:
547 tputz("\033K");
548 tpad(41); /* 1/25 sec padding */
549 break;
550#endif /*TX_OM8025*/
551#if TX_TVI925
552 case TN_TVI925:
553 tputz("\033T");
554 break;
555#endif /*TX_TVI925*/
556 }
557}
558
559
560/* T_INSLIN(n, bot) - Insert lines in window.
561 * n - # blank lines to insert.
562 * bot - # of last line of current window
563 *
564 * The current line is moved down and N blank lines inserted.
565 * Lines which are moved past bot are lost.
566 * May leave cursor in random place.
567 * Only valid if trm_flags has TF_IDLIN set.
568 */
569
570t_inslin (n, bot)
571int n; /* number of lines */
572int bot; /* line number of last line in window */
573{ register i, j;
574 int savc,savl;
575
576 if((i = n) <= 0) return;
577 if(bot < (scr_ht-1))
578 { savc = curs_col;
579 savl = curs_lin;
580 t_curpos(bot-i, 0);
581 t_dellin(i, scr_ht);
582 t_curpos(savl, savc);
583 }
584 switch(tv_type)
585 {
586#if TX_TERMCAP
587 case TN_TERMCAP:
588 if(TC_AL)
589 putpar(TC_AL, i, i);
590 else if(TC_ia)
591 { putpad(TC_im);
592 do { putpad(TC_ia);
593 } while(--i);
594 putpad(TC_ei);
595 }
596 else
597 do { putnpad(TC_al, scr_ht - curs_lin);
598 } while(--i);
599 break;
600#endif /*TX_TERMCAP*/
601#if TX_DM2500
602 case TN_DM2500:
603 tput(020); /* Enter I/D mode */
604 do { tput(012); /* Insert line */
605 switch(trm_ospeed)
606 { case 13: j = 17; break; /* 9600 */
607 case 12: j = 8; break; /* 4800 */
608 case 11: j = 4; break; /* 2400 */
609 case 9: j = 2; break; /* 1200 */
610 default: j = 0; break;
611 }
612 tpadn(j);
613 } while(--i);
614 tput(030); /* Exit I/D mode */
615 break;
616#endif /*TX_DM2500*/
617#if TX_H19
618 /* NOTE: H19 supposedly requires 19 ms for each line during line I/D
619 * operations.
620 * In actual practice, at 9600 baud 25 pads are necessary (24 wont work!)
621 * for both I and D. Plus esc-E needs 9 pads.
622 */
623 case TN_H19:
624 do { tputz("\033L");
625 switch(trm_ospeed)
626 { case 13: j = 25; break;
627 case 9: j = 4; break;
628 case 7: j = 1; break;
629 default: j = 0; break;
630 }
631 tpadn(j);
632 } while(--i);
633 break;
634#endif /*TX_H19*/
635#if TX_COHIBM
636 case TN_COHIBM:
637 do { tputz("\033L"); /* no padding required */
638 } while(--i);
639 break;
640#endif /*TX_COHIBM*/
641#if TX_OM8025
642 case TN_OM8025:
643 do { tputz("\033L");
644 tpad(100*(scr_ht - curs_lin)); /* .1 per moved line*/
645 } while(--i);
646 break;
647#endif /*TX_OM8025*/
648#if TX_TVI925
649 case TN_TVI925:
650 do tputz("\033E");
651 while(--i);
652 break;
653#endif /*TX_TVI925*/
654 }
655}
656
657
658/* T_DELLIN(n, bot) - Delete lines from window.
659 * n - # lines to delete.
660 * bot - # of last line of current window.
661 * The current line, and N-1 following lines, are deleted.
662 * Blank lines are inserted past bot.
663 * Cursor should be left at original position.
664 * Only valid if trm_flags has TF_IDLIN set.
665 */
666t_dellin (n, bot)
667int n; /* number of lines */
668int bot; /* line number of last line in window */
669{ register i, j;
670 int savl, savc;
671
672 if((i = n) <= 0) return;
673 switch(tv_type)
674 {
675#if TX_TERMCAP
676 case TN_TERMCAP:
677 if(TC_DL)
678 putpar(TC_DL, i, i);
679 else if(TC_id)
680 { putpad(TC_dm);
681 do putpad(TC_id);
682 while(--i);
683 putpad(TC_ed);
684 }
685 else
686 do { putnpad(TC_dl,scr_ht - curs_lin);
687 } while(--i);
688
689 break;
690#endif /*TX_TERMCAP*/
691#if TX_DM2500
692 case TN_DM2500:
693 tput(020);
694 do { tput(032);
695 if(trm_ospeed >= 13) /* 9600 */
696 tput(0177);
697 } while(--i);
698 tput(030);
699 break;
700#endif /*TX_DM2500*/
701#if TX_H19
702 case TN_H19:
703 do { tputz("\033M");
704 switch(trm_ospeed){
705 case 13: j = 25; break;
706 case 9: j = 4; break;
707 case 7: j = 1; break;
708 default: j = 0; break;
709 }
710 tpadn(j);
711 } while(--i);
712 break;
713#endif /*TX_H19*/
714#if TX_COHIBM
715 case TN_COHIBM:
716 do { tputz("\033M"); /* no padding required */
717 } while(--i);
718 break;
719#endif /*TX_COHIBM*/
720#if TX_OM8025
721 case TN_OM8025:
722 do { tputz("\033M");
723 tpad(100*(scr_ht - curs_lin));
724 } while(--i);
725 break;
726#endif /*TX_OM8025*/
727#if TX_TVI925
728 case TN_TVI925:
729 do { tputz("\033R");
730 } while(--i);
731 break;
732#endif /*TX_TVI925*/
733 }
734 if(bot < (scr_ht-1))
735 { savl = curs_lin;
736 savc = curs_col;
737 t_curpos(bot-n,0);
738 t_inslin(n,scr_ht);
739 t_curpos(savl,savc);
740 }
741}
742
743
744/* T_INSCHR(n, str) - Insert n chars in current line
745 * n - # characters to insert
746 * str - Pointer to char string. If 0, insert spaces.
747 *
748 * Insert N characters from string str at current position.
749 * The cursor may move but curs_col must be updated.
750 * Only valid if trm_flags has TF_IDCHR set.
751 */
752t_inschr(n, str)
753int n;
754char *str;
755{ register int i;
756 register char *cp;
757
758 if((i = n) <= 0) return;
759 cp = str;
760 switch(tv_type)
761 {
762#if TX_TERMCAP
763 case TN_TERMCAP:
764 putpad(TC_im); /* Go into insert mode */
765 if(TC_IC)
766 { putpar(TC_IC, i, 1);
767 if(cp) tputn(cp, i);
768 else do tput(SP); while(--i);
769 }
770 else do {
771 if(TC_ic) putpad(TC_ic);
772 if(cp) tput(*cp++);
773 else tput(SP);
774 if(TC_ip) putpad(TC_ip);
775 } while(--i);
776 putpad(TC_ei); /* Exit insert mode */
777 curs_col += n;
778 break;
779#endif /*TX_TERMCAP*/
780#if TX_COHIBM
781 case TN_COHIBM: /* If this exists, TN_H19 will too */
782#endif /*TX_COHIBM*/
783#if TX_H19
784 case TN_H19:
785 tputz("\033@"); /* Enter ins char mode */
786 do { if(cp) tput(*cp++);
787 else tput(SP);
788 } while(--i);
789 tputz("\033O"); /* Exit ins char mode */
790 curs_col += n;
791 break;
792#endif /*TX_H19*/
793#if TX_DM2500
794 case TN_DM2500:
795 tput(020); /* Enter I/D mode */
796 if(trm_ospeed == 13) /* 9600 baud lossage */
797 { do {
798 tputz(" \177"); /* SP and DEL */
799 } while(--i);
800 tput(030);
801 i = n;
802 if(i < 3) /* If close enough, */
803 tputn("\010\010", i); /* use BSes */
804 else t_curpos(curs_lin, curs_col);
805 }
806 else /* Not 9600, can win */
807 { do { tput(034);
808 } while(--i);
809 tput(030);
810 if(cp == 0) return;
811 i = n;
812 }
813
814 do { if(cp) tput(*cp++);
815 else tput(SP);
816 } while(--i);
817 curs_col += n;
818 break;
819#endif /*TX_DM2500*/
820#if TX_OM8025
821 case TN_OM8025:
822 do {
823 tputz("\033@");
824 if(cp) tput(*cp++);
825 else tput(SP);
826 } while(--i);
827 curs_col += n;
828 break;
829#endif /*TX_OM8025*/
830#if TX_TVI925
831 case TN_TVI925:
832 do { tputz("\033Q");
833 } while(--i);
834 if(cp)
835 { tputn(cp, n);
836 curs_col += n;
837 }
838 break;
839#endif /*TX_TVI925*/
840 }
841}
842
843
844/* T_DELCHR(n) - Delete N chars in current line.
845 * Deletes the N characters to the right of the cursor. Remaining
846 * chars are shifted left. The cursor should not move.
847 * Only valid if trm_flags has TF_IDCHR set.
848 */
849t_delchr(n) /* Delete N chars at current loc */
850int n;
851{ register int i;
852
853 if((i = n) <= 0) return;
854 switch(tv_type)
855 {
856#if TX_TERMCAP
857 case TN_TERMCAP:
858 putpad(TC_dm); /* Enter delete mode */
859 if(TC_DC)
860 putpar(TC_DC, i, 1);
861 else do { /* Delete char while in del mode */
862 putpad(TC_dc);
863 } while(--i);
864 putpad(TC_ed); /* Exit delete mode */
865 break;
866#endif /*TX_TERMCAP*/
867#if TX_COHIBM
868 case TN_COHIBM: /* If this exists, TN_H19 will too */
869#endif /*TX_COHIBM*/
870#if TX_H19
871 case TN_H19:
872 do tputz("\033N");
873 while(--i);
874 break;
875#endif /*TX_H19*/
876#if TX_DM2500
877 case TN_DM2500:
878 tput(020); /* Enter I/D mode */
879 do if(trm_ospeed == 13) /* 9600? */
880 tputz("\010\177"); /* BS and DEL */
881 else tput(010);
882 while(--i);
883 tput(030); /* Exit I/D mode */
884 break;
885#endif /*TX_DM2500*/
886#if TX_OM8025
887 case TN_OM8025:
888 do tputz("\033P");
889 while (--i);
890 break;
891#endif /*TX_OM8025*/
892#if TX_TVI925
893 case TN_TVI925:
894 do { tputz("\033W");
895 } while(--i);
896#endif /*TX_TVI925*/
897 }
898}
899
900
901#if FX_SOWIND
902
903/* T_STANDOUT(n) - Enter or leave standout mode.
904 * n - 0 to return to normal display mode,
905 * 1 to enter standout display mode.
906 * This is usually reverse video but may be something else.
907 *
908 * Only valid if trm_flags has TF_SO set.
909 */
910
911t_standout(on)
912int on;
913{
914 switch(tv_type)
915 {
916#if TX_TERMCAP
917 case TN_TERMCAP:
918 putpad(on ? TC_so : TC_se);
919 break;
920#endif /*TX_TERMCAP*/
921
922#if TX_COHIBM
923 case TN_COHIBM: /* Note TN_H19 will exist too */
924#endif /*TX_COHIBM*/
925#if TX_H19
926 case TN_H19:
927 tputz(on ? "\033p" : "\033q");
928 break;
929#endif /*TX_H19*/
930 }
931}
932#endif /*FX_SOWIND*/
933
934
935
936/* TPADN(n) - Output N pad chars.
937 */
938static void
939tpadn(n)
940int n;
941{ register int i, pad;
942 if((i = n) > 0)
943 { pad = tv_padc;
944 do { tput(pad);
945 } while(--i);
946 }
947}
948
949/* TPAD(msec) - Output padding for given # of milliseconds.
950 */
951static void
952tpad(n)
953int n;
954{ register int i, i2;
955
956 i = n;
957 while(i > 0)
958 { if((i2 = 320) < i) /* So can use integers */
959 i2 = i;
960 i -= i2;
961 i2 *= 100;
962 while((i2 -= tv_cspeed) > 0)
963 tput(tv_padc);
964 }
965}
966#if TX_TERMCAP
967/*
968 * Print the string str, interpreting padding.
969 */
970int tput(); /* Our output function */
971static void
972putpad(str)
973char *str;
974{ if(str) tputs(str, 1, tput); /* Invoke TERMCAP function */
975}
976static void
977putnpad(str,n)
978char *str;
979int n;
980{ if(str) tputs(str, n, tput);
981}
982static void
983putpar(str, par, n) /* Wish we had tparm() */
984char *str;
985int par,n;
986{ putnpad(tgoto(str, 0, par), n);
987}
988#endif /*TX_TERMCAP*/
989
990
991/*
992 * Read in the stuff from termcap upon startup.
993 */
994
995#if TX_TERMCAP
996static int tstrlen(), tstrlp();
997
998#ifndef TCAPSLEN
999#define TCAPSLEN 1024 /* Default size of buffer for TERMCAP strings */
1000#endif /*-TCAPSLEN*/
1001
1002static int
1003getcap(stype)
1004char *stype;
1005{ register char *t;
1006 register int i;
1007 int buflen;
1008 char *tcbuf, *tcbptr; /* Pointers into termcap buffer */
1009 char tmpstr[4];
1010 char tmpbuf[TCAPSLEN]; /* Allocate from stack */
1011 char *malloc();
1012 char *realloc();
1013
1014 /* First see if can find the terminal type. */
1015 if((tgetent(tmpbuf, stype)) != 1)
1016 return(0);
1017
1018 /* Found it! Set up a string buffer to save the caps. */
1019 if(!(tcbuf = malloc(TCAPSLEN))) /* Get permanent buffer */
1020 t_fatal(" - cannot allocate termcap buffer");
1021 tcbptr = tcbuf;
1022
1023 /* Now gobble all the string caps that ELLE wants to know about. */
1024 tmpstr[3] = '\0';
1025 i = NTCAPS;
1026 do {
1027 tmpstr[0] = tcap[i].tcicod1; /* Make str of the code */
1028 tmpstr[1] = tcap[i].tcicod2;
1029 tcap[i].tccap = tgetstr(tmpstr, &tcbptr); /* Get cap */
1030 } while(--i);
1031 buflen = tcbptr - tcbuf; /* String buffer done, finalize */
1032 if(buflen >= TCAPSLEN)
1033 t_fatal("description too big!");
1034 realloc(tcbuf, buflen); /* Free up unused part of buffer */
1035 /* (this better not move it!!!) */
1036
1037 /* Now get the number/flag stuff that ELLE needs. */
1038 tc_am = tgetflag("am"); /* auto wrap */
1039 if (tgetflag("xn")) tc_am = 0; /* auto wrap at 81st char, nice! */
1040 tc_km = (tgetflag("km") /* TTY has meta key */
1041 || tgetflag("MT")); /* Alternate version of "km"?? */
1042 scr_ht = tgetnum("li"); /* Set screen height (# lines) */
1043 scr_wid = tgetnum("co"); /* Set screen width (# cols) */
1044 ts_winsize();
1045
1046 /* Now initialize the stupid external vars that TERMCAP rtns want. */
1047 if(TC_pc) PC = *TC_pc; /* Pad char */
1048 BC = TC_bc; /* Backspace str (if no BS) */
1049 UP = TC_up; /* Cursor up */
1050 ospeed = trm_ospeed; /* Put output speed here */
1051
1052
1053 /* Basic data extracted, now mull over it and set the remaining
1054 * ELLE variables
1055 */
1056#if FX_SOWIND
1057 if(tgetnum("sg") <= 0) /* If no magic cookie problems */
1058 { if (TC_so && TC_se) /* And have standout caps, */
1059 trm_flags |= TF_SO; /* Say has standout cap */
1060 }
1061#endif
1062
1063 if (!(TC_cm && TC_cl))
1064 t_fatal("lacks cursor addressing or clear screen.");
1065 tvc_pos = tstrlen(TC_cm); /* Find cost of abs move */
1066 if(BC) /* Find cost of backspace */
1067 tvc_bs = tstrlen(BC);
1068
1069 /* Find costs for doing I/D char operations */
1070 if ((TC_im||TC_ic) && (TC_dm||TC_dc))
1071 { trm_flags |= TF_IDCHR;
1072 tvc_ci = tstrlen(TC_im)+tstrlen(TC_ei);
1073 tvc_cin = tstrlen(TC_ic)+1+tstrlen(TC_ip);
1074 if(TC_IC) /* If have multi-IC, use it */
1075 { tvc_ci += tstrlp(TC_IC, 1);
1076 tvc_cin = 1;
1077 }
1078 tvc_cd = tstrlen(TC_dm)+tstrlen(TC_ed);
1079 tvc_cdn = tstrlen(TC_dc);
1080 if(TC_DC) /* If have multi-DC, use it */
1081 { tvc_cd += tstrlp(TC_DC, 1);
1082 tvc_cdn = 0;
1083 }
1084 }
1085
1086 /* Find costs for doing I/D line operations */
1087 if ((TC_ia || TC_al) && (TC_id || TC_dl))
1088 { trm_flags |= TF_IDLIN;
1089 tvc_li = 0; /* Usual case */
1090 tvc_lin = tstrlen(TC_al);
1091 if(TC_AL) /* If have multi-IL, use it */
1092 { tvc_li = tstrlp(TC_AL, 1);
1093 tvc_lin = tstrlp(TC_AL, 2) - tvc_lin;
1094 }
1095 else if(TC_ia)
1096 { tvc_li = tstrlen(TC_im)+tstrlen(TC_ei);
1097 tvc_lin = tstrlen(TC_ia);
1098 }
1099
1100 tvc_ld = 0; /* Usual case */
1101 tvc_ldn = tstrlen(TC_dl);
1102 if(TC_DL) /* If have multi-DL, use it */
1103 { tvc_ld = tstrlp(TC_DL, 1);
1104 tvc_ldn = tstrlp(TC_DL, 2) - tvc_ld;
1105 }
1106 else if(TC_id)
1107 { tvc_ld = tstrlen(TC_dm)+tstrlen(TC_ed);
1108 tvc_ldn = tstrlen(TC_id);
1109 }
1110 }
1111
1112 if (tc_am)
1113 { scr_wid--; /* For now, avoid invoking wrap. */
1114#if 0
1115 trm_flags |= AUTOWRAP; /* */
1116#endif
1117 }
1118 if (TC_ce) trm_flags |= TF_CLEOL; /* Term has CLEOL? */
1119 if (tc_km) trm_flags |= TF_METAKEY; /* Term has meta key? */
1120
1121 return(1);
1122}
1123
1124/* Pair of routines which conspire in order to find # chars actually output
1125 * by a particular termcap string.
1126 */
1127static int _tslen; /* Stored count */
1128static void _tslinc(ch) { _tslen++; }
1129static int
1130tstrlen(str)
1131char *str;
1132{ _tslen = 0;
1133 if(str && str[0])
1134 tputs(str, 1, _tslinc); /* Mult padding by just 1 */
1135 return(_tslen);
1136}
1137
1138static int
1139tstrlp(str, par) /* Same but with parameter */
1140char *str;
1141int par;
1142{
1143#if 0
1144 if(str)
1145 { char *cp = tgoto(str, 0, par);
1146 int i = strlen(cp);
1147 while(--i >= 0)
1148 printf(" %o", *cp++);
1149 printf("\n");
1150 }
1151#endif
1152 return !str ? 0 : tstrlen(tgoto(str, 0, par));
1153}
1154#endif /*TX_TERMCAP*/
1155
1156
1157/* Direct-Video terminal output routine
1158 * Currently only COHERENT has this capability.
1159 */
1160
1161#if COHERENT
1162#include <sgtty.h>
1163
1164struct vidctl {
1165 int v_position; /* Position in video memory */
1166 int v_count; /* Number of characters to transfer */
1167 char *v_buffer; /* Character buffer to read/write */
1168};
1169/*
1170 * Attribute masks for TIOVPUTB - attributes occupy odd addresses
1171 * in video memory.
1172 */
1173#define VNORM 0x07 /* Ordinary Video */
1174#define VINTE 0x08 /* Intense video */
1175#define VBLIN 0x80 /* Blinking video */
1176#define VREVE 0x70 /* Reverse video */
1177#define VUNDE 0x01 /* Underline video (mono board) */
1178
1179/* T_DIRECT(line, col, string, len) - Do direct-video output of string.
1180 * Puts the string ("len" chars in length) on the screen starting at
1181 * the X,Y character position given by col, line.
1182 * This routine is only called if terminal has the "TF_DIRVID" flag set.
1183 */
1184t_direct(lin, col, str, len)
1185int lin, col;
1186register char *str;
1187register int len;
1188{ register char *cp;
1189 char vbuf[MAXLINE*2];
1190 struct vidctl v;
1191
1192 if(len <= 0) return;
1193 tbufls(); /* Ensure normal output is forced out */
1194 v.v_position = (lin*80 + col)*2;
1195 v.v_count = len*2;
1196 v.v_buffer = cp = vbuf;
1197 do {
1198 *cp++ = *str++;
1199 *cp++ = VNORM;
1200 } while(--len);
1201 ioctl(1, TIOVPUTB, &v);
1202}
1203#endif /*COHERENT*/
1204
1205
1206/*
1207 * Terminal Output buffering routines
1208 */
1209
1210static char tbuf[TOBFSIZ]; /* Output buffer */
1211static int tbufcnt = 0; /* # chars of room left in buffer */
1212static char *tbufp = 0; /* Pointer to deposit in buffer */
1213
1214tput(ch)
1215int ch;
1216{ if(--tbufcnt < 0)
1217 tbufls();
1218 *tbufp++ = ch;
1219}
1220
1221tputz(str)
1222char *str;
1223{ register int c;
1224 register char *cp, *tp;
1225 cp = str;
1226 tp = tbufp;
1227 while(c = *cp++)
1228 { if(--tbufcnt < 0)
1229 { tbufp = tp;
1230 tbufls();
1231 tp = tbufp;
1232 }
1233 *tp++ = c;
1234 }
1235 tbufp = tp;
1236}
1237
1238tputn(str,cnt)
1239char *str;
1240int cnt;
1241{ register int c;
1242 register char *cp, *tp;
1243 cp = str;
1244 tp = tbufp;
1245 if((c = cnt) > 0)
1246 do {
1247 if(--tbufcnt < 0)
1248 {
1249 tbufp = tp;
1250 tbufls();
1251 tp = tbufp;
1252 }
1253 *tp++ = *cp++;
1254 } while(--c);
1255 tbufp = tp;
1256}
1257
1258tbufls()
1259{ register int cnt;
1260
1261 if(tbufp
1262 && (cnt = tbufp - tbuf) > 0) /* # chars written */
1263 write(1, tbuf, cnt); /* Out they go */
1264 tbufp = tbuf;
1265 tbufcnt = TOBFSIZ-1; /* Allow for usual expected decrement */
1266}
1267
1268
1269/*
1270 * Terminal Input buffering routines
1271 */
1272
1273int tibfmsk = -1; /* Mask AND'ed with input chars (external) */
1274static char tibuf[TIBFSIZ]; /* TTY input buffer */
1275static char *tibfp; /* Pointer to read from buffer */
1276static int tibfcnt = 0; /* # chars left to be read from buffer */
1277
1278tgetc()
1279{
1280#if SUN
1281 register int c;
1282 extern int sun_winfd, sun_rdevf;
1283
1284 if(sun_winfd)
1285 { if(!sun_rdevf)
1286 return(sun_input(1)&tibfmsk);
1287 sun_rdevf = 0; /* Check mouse too, but only once! */
1288 c = sun_input(0);
1289 if(c != -1) c &= tibfmsk;
1290 return(c);
1291 }
1292#endif /*SUN*/
1293 while(--tibfcnt < 0)
1294 tibfcnt = read(0,(tibfp = tibuf),TIBFSIZ);
1295 return((*tibfp++)&tibfmsk);
1296}
1297
1298tinwait()
1299{ return(tibfcnt > 0 || ts_inp());
1300}
Note: See TracBrowser for help on using the repository browser.