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