1 /*-------------------------------------------------------*/
2 /* term.c ( NTHU CS MapleBBS Ver 2.36 ) */
3 /*-------------------------------------------------------*/
4 /* target : termcap I/O control routines */
5 /* create : 1995/03/29 */
6 /* update : 2009/12/18 from sob_pack */
7 /*-------------------------------------------------------*/
8
9 #include "bbs.h"
10 #include <sys/ioctl.h>
11
12 #ifdef HP_UX
13 #define O_HUPCL 01
14 #define O_XTABS 02
15 #endif
16
17 #ifdef LINUX
18 #include <linux/termios.h>
19 #endif
20 #define stty(fd, data) tcsetattr( fd, TCSETS, data )
21 #define gtty(fd, data) tcgetattr( fd, data )
22
23 #ifndef TANDEM
24 #define TANDEM 0x00000001
25 #endif
26
27 #ifndef CBREAK
28 #define CBREAK 0x00000002
29 #endif
30
31 #ifndef RAW
32 #define RAW 24
33 #endif
34
35 struct termios tty_state, tty_new;
36
37 #ifndef BSD44
38
39 #include <ctype.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #ifdef SunOS
44 #include "termcap.h_SunOS"
45 #else
46 #include "termcap.h"
47 #endif
48
49 #ifdef USE_SCCS_IDS
50 static const char SCCSid[] = "@(#) mytinfo tparm.c 3.2 92/02/01 public domain, By Ross Ridge";
51 #endif
52
53 #ifndef MAX_PUSHED
54 #define MAX_PUSHED 32
55 #endif
56
57 #define ARG 1
58 #define NUM 2
59
60 #define INTEGER 1
61 #define STRING 2
62
63 #define MAX_LINE 640
64
65 typedef void* anyptr;
66
67 typedef struct stack_str {
68 int type;
69 int argnum;
70 int value;
71 } stack;
72
73 static stack S[MAX_PUSHED];
74 static stack vars['z'-'a'+1];
75 static int pos = 0;
76
77 static struct arg_str {
78 int type;
79 int integer;
80 char *string;
81 } arg_list[10];
82
83 static int argcnt;
84
85 static va_list tparm_args;
86
87 static int
pusharg(arg)88 pusharg(arg)
89 int arg; {
90 if (pos == MAX_PUSHED)
91 return 1;
92 S[pos].type = ARG;
93 S[pos++].argnum = arg;
94 return 0;
95 }
96
97 static int
pushnum(num)98 pushnum(num)
99 int num; {
100 if (pos == MAX_PUSHED)
101 return 1;
102 S[pos].type = NUM;
103 S[pos++].value = num;
104 return 0;
105 }
106
107 /* VARARGS2 */
108 static int
getarg(argnum,type,p)109 getarg(argnum, type, p)
110 int argnum, type;
111 anyptr p; {
112 while (argcnt < argnum) {
113 arg_list[argcnt].type = INTEGER;
114 arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
115 }
116 if (argcnt > argnum) {
117 if (arg_list[argnum].type != type)
118 return 1;
119 else if (type == STRING)
120 *(char **)p = arg_list[argnum].string;
121 else
122 *(int *)p = arg_list[argnum].integer;
123 } else {
124 arg_list[argcnt].type = type;
125 if (type == STRING)
126 *(char **)p = arg_list[argcnt++].string
127 = (char *) va_arg(tparm_args, char *);
128 else
129 *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
130 }
131 return 0;
132 }
133
134
135 static int
popstring(str)136 popstring(str)
137 char **str; {
138 if (pos-- == 0)
139 return 1;
140 if (S[pos].type != ARG)
141 return 1;
142 return(getarg(S[pos].argnum, STRING, (anyptr) str));
143 }
144
145 static int
popnum(num)146 popnum(num)
147 int *num; {
148 if (pos-- == 0)
149 return 1;
150 switch (S[pos].type) {
151 case ARG:
152 return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
153 case NUM:
154 *num = S[pos].value;
155 return 0;
156 }
157 return 1;
158 }
159
160 static int
cvtchar(sp,c)161 cvtchar(sp, c)
162 register char *sp, *c; {
163 switch(*sp) {
164 case '\\':
165 switch(*++sp) {
166 case '\'':
167 case '$':
168 case '\\':
169 case '%':
170 *c = *sp;
171 return 2;
172 case '\0':
173 *c = '\\';
174 return 1;
175 case '0':
176 if (sp[1] == '0' && sp[2] == '0') {
177 *c = '\0';
178 return 4;
179 }
180 *c = '\200'; /* '\0' ???? */
181 return 2;
182 default:
183 *c = *sp;
184 return 2;
185 }
186 default:
187 *c = *sp;
188 return 1;
189 }
190 }
191
192 static int termcap;
193
get_tty()194 void get_tty() {
195 if (gtty (1, &tty_state) < 0) {
196 fprintf (stderr, "gtty failed\n");
197 exit (-1);
198 }
199 }
200
201 /* sigh... this has got to be the ugliest code I've ever written.
202 Trying to handle everything has its cost, I guess.
203
204 It actually isn't to hard to figure out if a given % code is supposed
205 to be interpeted with its termcap or terminfo meaning since almost
206 all terminfo codes are invalid unless something has been pushed on
207 the stack and termcap strings will never push things on the stack
208 (%p isn't used by termcap). So where we have a choice we make the
209 decision by wether or not somthing has been pushed on the stack.
210 The static variable termcap keeps track of this; it starts out set
211 to 1 and is incremented as each argument processed by a termcap % code,
212 however if something is pushed on the stack it's set to 0 and the
213 rest of the % codes are interpeted as terminfo % codes. Another way
214 of putting it is that if termcap equals one we haven't decided either
215 way yet, if it equals zero we're looking for terminfo codes, and if
216 its greater than 1 we're looking for termcap codes.
217
218 Terminfo % codes:
219
220 %% output a '%'
221 %[[:][-+# ][width][.precision]][doxXs]
222 output pop according to the printf format
223 %c output pop as a char
224 %'c' push character constant c.
225 %{n} push decimal constant n.
226 %p[1-9] push paramter [1-9]
227 %g[a-z] push variable [a-z]
228 %P[a-z] put pop in variable [a-z]
229 %l push the length of pop (a string)
230 %+ add pop to pop and push the result
231 %- subtract pop from pop and push the result
232 %* multiply pop and pop and push the result
233 %& bitwise and pop and pop and push the result
234 %| bitwise or pop and pop and push the result
235 %^ bitwise xor pop and pop and push the result
236 %~ push the bitwise not of pop
237 %= compare if pop and pop are equal and push the result
238 %> compare if pop is less than pop and push the result
239 %< compare if pop is greater than pop and push the result
240 %A logical and pop and pop and push the result
241 %O logical or pop and pop and push the result
242 %! push the logical not of pop
243 %? condition %t if_true [%e if_false] %;
244 if condtion evaulates as true then evaluate if_true,
245 else evaluate if_false. elseif's can be done:
246 %? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
247 %i add one to parameters 1 and 2. (ANSI)
248
249 Termcap Codes:
250
251 %% output a %
252 %. output parameter as a character
253 %d output parameter as a decimal number
254 %2 output parameter in printf format %02d
255 %3 output parameter in printf format %03d
256 %+x add the character x to parameter and output it as a character
257 (UW) %-x subtract parameter FROM the character x and output it as a char
258 (UW) %ax add the character x to parameter
259 (GNU) %a[+*-/=][cp]x
260 GNU arithmetic.
261 (UW) %sx subtract parameter FROM the character x
262 %>xy if parameter > character x then add character y to parameter
263 %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
264 %D Delta Data encode (parameter = parameter - 2*(paramter%16))
265 %i increment the first two parameters by one
266 %n xor the first two parameters by 0140
267 (GNU) %m xor the first two parameters by 0177
268 %r swap the first two parameters
269 (GNU) %b backup to previous parameter
270 (GNU) %f skip this parameter
271
272 Note the two definitions of %a, the GNU defintion is used if the characters
273 after the 'a' are valid, otherwise the UW definition is used.
274
275 (GNU) used by GNU Emacs termcap libraries
276 (UW) used by the University of Waterloo (MFCF) termcap libraries
277
278 */
279
tparm(const char * str,...)280 char *tparm(const char *str, ...) {
281 static char OOPS[] = "OOPS";
282 static char buf[MAX_LINE];
283 register const char *sp;
284 register char *dp;
285 register char *fmt;
286 char conv_char;
287 char scan_for;
288 int scan_depth = 0, if_depth;
289 static int i, j;
290 static char *s, c;
291 char fmt_buf[MAX_LINE];
292 char sbuf[MAX_LINE];
293
294 va_start(tparm_args, str);
295
296 sp = str;
297 dp = buf;
298 scan_for = 0;
299 if_depth = 0;
300 argcnt = 0;
301 pos = 0;
302 termcap = 1;
303 while(*sp != '\0') {
304 switch(*sp) {
305 case '\\':
306 if (scan_for) {
307 if (*++sp != '\0')
308 sp++;
309 break;
310 }
311 *dp++ = *sp++;
312 if (*sp != '\0')
313 *dp++ = *sp++;
314 break;
315 case '%':
316 sp++;
317 if (scan_for) {
318 if (*sp == scan_for && if_depth == scan_depth) {
319 if (scan_for == ';')
320 if_depth--;
321 scan_for = 0;
322 } else if (*sp == '?')
323 if_depth++;
324 else if (*sp == ';') {
325 if (if_depth == 0)
326 return OOPS;
327 else
328 if_depth--;
329 }
330 sp++;
331 break;
332 }
333 fmt = NULL;
334 switch(*sp) {
335 case '%':
336 *dp++ = *sp++;
337 break;
338 case '+':
339 if (!termcap) {
340 if (popnum(&j) || popnum(&i))
341 return OOPS;
342 i += j;
343 if (pushnum(i))
344 return OOPS;
345 sp++;
346 break;
347 }
348 ;/* FALLTHROUGH */
349 case 'C':
350 if (*sp == 'C') {
351 if (getarg(termcap - 1, INTEGER, &i))
352 return OOPS;
353 if (i >= 96) {
354 i /= 96;
355 if (i == '$')
356 *dp++ = '\\';
357 *dp++ = i;
358 }
359 }
360 fmt = "%c";
361 /* FALLTHROUGH */
362 case 'a':
363 if (!termcap)
364 return OOPS;
365 if (getarg(termcap - 1, INTEGER, (anyptr) &i))
366 return OOPS;
367 if (*++sp == '\0')
368 return OOPS;
369 if ((sp[1] == 'p' || sp[1] == 'c')
370 && sp[2] != '\0' && fmt == NULL) {
371 /* GNU aritmitic parameter, what they
372 realy need is terminfo. */
373 int val, lc;
374 if (sp[1] == 'p'
375 && getarg(termcap - 1 + sp[2] - '@',
376 INTEGER, (anyptr) &val))
377 return OOPS;
378 if (sp[1] == 'c') {
379 lc = cvtchar(sp + 2, &c) + 2;
380 /* Mask out 8th bit so \200 can be
381 used for \0 as per GNU doc's */
382 val = c & 0177;
383 } else
384 lc = 2;
385 switch(sp[0]) {
386 case '=':
387 break;
388 case '+':
389 val = i + val;
390 break;
391 case '-':
392 val = i - val;
393 break;
394 case '*':
395 val = i * val;
396 break;
397 case '/':
398 val = i / val;
399 break;
400 default:
401 /* Not really GNU's %a after all... */
402 lc = cvtchar(sp, &c);
403 val = c + i;
404 break;
405 }
406 arg_list[termcap - 1].integer = val;
407 sp += lc;
408 break;
409 }
410 sp += cvtchar(sp, &c);
411 arg_list[termcap - 1].integer = c + i;
412 if (fmt == NULL)
413 break;
414 sp--;
415 /* FALLTHROUGH */
416 case '-':
417 if (!termcap) {
418 if (popnum(&j) || popnum(&i))
419 return OOPS;
420 i -= j;
421 if (pushnum(i))
422 return OOPS;
423 sp++;
424 break;
425 }
426 fmt = "%c";
427 /* FALLTHROUGH */
428 case 's':
429 if (termcap && (fmt == NULL || *sp == '-')) {
430 if (getarg(termcap - 1, INTEGER, &i))
431 return OOPS;
432 if (*++sp == '\0')
433 return OOPS;
434 sp += cvtchar(sp, &c);
435 arg_list[termcap - 1].integer = c - i;
436 if (fmt == NULL)
437 break;
438 sp--;
439 }
440 if (!termcap)
441 return OOPS;
442 ;/* FALLTHROUGH */
443 case '.':
444 if (termcap && fmt == NULL)
445 fmt = "%c";
446 ;/* FALLTHROUGH */
447 case 'd':
448 if (termcap && fmt == NULL)
449 fmt = "%d";
450 ;/* FALLTHROUGH */
451 case '2':
452 if (termcap && fmt == NULL)
453 fmt = "%02d";
454 ;/* FALLTHROUGH */
455 case '3':
456 if (termcap && fmt == NULL)
457 fmt = "%03d";
458 ;/* FALLTHROUGH */
459 case ':': case ' ': case '#': case 'u':
460 case 'x': case 'X': case 'o': case 'c':
461 case '0': case '1': case '4': case '5':
462 case '6': case '7': case '8': case '9':
463 if (fmt == NULL) {
464 if (termcap)
465 return OOPS;
466 if (*sp == ':')
467 sp++;
468 fmt = fmt_buf;
469 *fmt++ = '%';
470 while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
471 if (*sp == '\0')
472 return OOPS;
473 *fmt++ = *sp++;
474 }
475 *fmt++ = *sp;
476 *fmt = '\0';
477 fmt = fmt_buf;
478 }
479 conv_char = fmt[strlen(fmt) - 1];
480 if (conv_char == 's') {
481 if (popstring(&s))
482 return OOPS;
483 sprintf(sbuf, fmt, s);
484 } else {
485 if (termcap) {
486 if (getarg(termcap++ - 1,
487 INTEGER, &i))
488 return OOPS;
489 } else
490 if (popnum(&i))
491 return OOPS;
492 if (i == 0 && conv_char == 'c')
493 strcpy(sbuf, "\000");
494 else
495 sprintf(sbuf, fmt, i);
496 }
497 sp++;
498 fmt = sbuf;
499 while(*fmt != '\0') {
500 if (*fmt == '$')
501 *dp++ = '\\';
502 *dp++ = *fmt++;
503 }
504 break;
505 case 'r':
506 if (!termcap || getarg(1, INTEGER, &i))
507 return OOPS;
508 arg_list[1].integer = arg_list[0].integer;
509 arg_list[0].integer = i;
510 sp++;
511 break;
512 case 'i':
513 if (getarg(1, INTEGER, &i)
514 || arg_list[0].type != INTEGER)
515 return OOPS;
516 arg_list[1].integer++;
517 arg_list[0].integer++;
518 sp++;
519 break;
520 case 'n':
521 if (!termcap || getarg(1, INTEGER, &i))
522 return OOPS;
523 arg_list[0].integer ^= 0140;
524 arg_list[1].integer ^= 0140;
525 sp++;
526 break;
527 case '>':
528 if (!termcap) {
529 if (popnum(&j) || popnum(&i))
530 return OOPS;
531 i = (i > j);
532 if (pushnum(i))
533 return OOPS;
534 sp++;
535 break;
536 }
537 if (getarg(termcap-1, INTEGER, &i))
538 return OOPS;
539 sp += cvtchar(sp, &c);
540 if (i > c) {
541 sp += cvtchar(sp, &c);
542 arg_list[termcap-1].integer += c;
543 } else
544 sp += cvtchar(sp, &c);
545 sp++;
546 break;
547 case 'B':
548 if (!termcap || getarg(termcap-1, INTEGER, &i))
549 return OOPS;
550 arg_list[termcap-1].integer = 16*(i/10)+i%10;
551 sp++;
552 break;
553 case 'D':
554 if (!termcap || getarg(termcap-1, INTEGER, &i))
555 return OOPS;
556 arg_list[termcap-1].integer = i - 2 * (i % 16);
557 sp++;
558 break;
559 case 'p':
560 if (termcap > 1)
561 return OOPS;
562 if (*++sp == '\0')
563 return OOPS;
564 if (*sp == '0')
565 i = 9;
566 else
567 i = *sp - '1';
568 if (i < 0 || i > 9)
569 return OOPS;
570 if (pusharg(i))
571 return OOPS;
572 termcap = 0;
573 sp++;
574 break;
575 case 'P':
576 if (termcap || *++sp == '\0')
577 return OOPS;
578 i = *sp++ - 'a';
579 if (i < 0 || i > 25)
580 return OOPS;
581 if (pos-- == 0)
582 return OOPS;
583 switch(vars[i].type = S[pos].type) {
584 case ARG:
585 vars[i].argnum = S[pos].argnum;
586 break;
587 case NUM:
588 vars[i].value = S[pos].value;
589 break;
590 }
591 break;
592 case 'g':
593 if (termcap || *++sp == '\0')
594 return OOPS;
595 i = *sp++ - 'a';
596 if (i < 0 || i > 25)
597 return OOPS;
598 switch(vars[i].type) {
599 case ARG:
600 if (pusharg(vars[i].argnum))
601 return OOPS;
602 break;
603 case NUM:
604 if (pushnum(vars[i].value))
605 return OOPS;
606 break;
607 }
608 break;
609 case '\'':
610 if (termcap > 1)
611 return OOPS;
612 if (*++sp == '\0')
613 return OOPS;
614 sp += cvtchar(sp, &c);
615 if (pushnum(c) || *sp++ != '\'')
616 return OOPS;
617 termcap = 0;
618 break;
619 case '{':
620 if (termcap > 1)
621 return OOPS;
622 i = 0;
623 sp++;
624 while(isdigit(*sp))
625 i = 10 * i + *sp++ - '0';
626 if (*sp++ != '}' || pushnum(i))
627 return OOPS;
628 termcap = 0;
629 break;
630 case 'l':
631 if (termcap || popstring(&s))
632 return OOPS;
633 i = strlen(s);
634 if (pushnum(i))
635 return OOPS;
636 sp++;
637 break;
638 case '*':
639 if (termcap || popnum(&j) || popnum(&i))
640 return OOPS;
641 i *= j;
642 if (pushnum(i))
643 return OOPS;
644 sp++;
645 break;
646 case '/':
647 if (termcap || popnum(&j) || popnum(&i))
648 return OOPS;
649 i /= j;
650 if (pushnum(i))
651 return OOPS;
652 sp++;
653 break;
654 case 'm':
655 if (termcap) {
656 if (getarg(1, INTEGER, &i))
657 return OOPS;
658 arg_list[0].integer ^= 0177;
659 arg_list[1].integer ^= 0177;
660 sp++;
661 break;
662 }
663 if (popnum(&j) || popnum(&i))
664 return OOPS;
665 i %= j;
666 if (pushnum(i))
667 return OOPS;
668 sp++;
669 break;
670 case '&':
671 if (popnum(&j) || popnum(&i))
672 return OOPS;
673 i &= j;
674 if (pushnum(i))
675 return OOPS;
676 sp++;
677 break;
678 case '|':
679 if (popnum(&j) || popnum(&i))
680 return OOPS;
681 i |= j;
682 if (pushnum(i))
683 return OOPS;
684 sp++;
685 break;
686 case '^':
687 if (popnum(&j) || popnum(&i))
688 return OOPS;
689 i ^= j;
690 if (pushnum(i))
691 return OOPS;
692 sp++;
693 break;
694 case '=':
695 if (popnum(&j) || popnum(&i))
696 return OOPS;
697 i = (i == j);
698 if (pushnum(i))
699 return OOPS;
700 sp++;
701 break;
702 case '<':
703 if (popnum(&j) || popnum(&i))
704 return OOPS;
705 i = (i < j);
706 if (pushnum(i))
707 return OOPS;
708 sp++;
709 break;
710 case 'A':
711 if (popnum(&j) || popnum(&i))
712 return OOPS;
713 i = (i && j);
714 if (pushnum(i))
715 return OOPS;
716 sp++;
717 break;
718 case 'O':
719 if (popnum(&j) || popnum(&i))
720 return OOPS;
721 i = (i || j);
722 if (pushnum(i))
723 return OOPS;
724 sp++;
725 break;
726 case '!':
727 if (popnum(&i))
728 return OOPS;
729 i = !i;
730 if (pushnum(i))
731 return OOPS;
732 sp++;
733 break;
734 case '~':
735 if (popnum(&i))
736 return OOPS;
737 i = ~i;
738 if (pushnum(i))
739 return OOPS;
740 sp++;
741 break;
742 case '?':
743 if (termcap > 1)
744 return OOPS;
745 termcap = 0;
746 if_depth++;
747 sp++;
748 break;
749 case 't':
750 if (popnum(&i) || if_depth == 0)
751 return OOPS;
752 if (!i) {
753 scan_for = 'e';
754 scan_depth = if_depth;
755 }
756 sp++;
757 break;
758 case 'e':
759 if (if_depth == 0)
760 return OOPS;
761 scan_for = ';';
762 scan_depth = if_depth;
763 sp++;
764 break;
765 case ';':
766 if (if_depth-- == 0)
767 return OOPS;
768 sp++;
769 break;
770 case 'b':
771 if (--termcap < 1)
772 return OOPS;
773 sp++;
774 break;
775 case 'f':
776 if (!termcap++)
777 return OOPS;
778 sp++;
779 break;
780 }
781 break;
782 default:
783 if (scan_for)
784 sp++;
785 else
786 *dp++ = *sp++;
787 break;
788 }
789 }
790 va_end(tparm_args);
791 *dp = '\0';
792 return buf;
793 }
794 #endif
795
796
797
798
799
800 /* ----------------------------------------------------- */
801 /* basic tty control */
802 /* ----------------------------------------------------- */
803
804
805 void
init_tty()806 init_tty() {
807 if (gtty(1, &tty_state) < 0)
808 {
809 fprintf(stderr, "gtty failed\n");
810 exit(-1);
811 }
812 memcpy(&tty_new, &tty_state, sizeof(tty_new));
813
814 tty_new.c_lflag &= ~(ICANON | ECHO | RAW | ISIG);
815 tcsetattr(1, TCSANOW, &tty_new);
816 restore_tty();
817 }
818
reset_tty()819 reset_tty() {
820 system("stty -raw echo");
821 }
822
restore_tty()823 restore_tty() {
824 system("stty raw -echo");
825 }
826
827 /* ----------------------------------------------------- */
828 /* init tty control code */
829 /* ----------------------------------------------------- */
830
831
832 #define TERMCOMSIZE (40)
833
834 int dumb_term = YEA;
835
836 char clearbuf[TERMCOMSIZE];
837 int clearbuflen;
838
839 char cleolbuf[TERMCOMSIZE];
840 int cleolbuflen;
841
842 char cursorm[TERMCOMSIZE];
843 char *cm;
844
845 char changescroll[TERMCOMSIZE];
846 char *cs;
847
848 char savecursor[TERMCOMSIZE];
849 char *sc;
850
851 char restorecursor[TERMCOMSIZE];
852 char *rc;
853
854 char scrollforward[TERMCOMSIZE];
855 char *sf;
856
857 char scrollreverse[TERMCOMSIZE];
858 char *sr;
859
860 char scrollrev[TERMCOMSIZE];
861 int scrollrevlen;
862
863 char scrollset[TERMCOMSIZE];
864 int scrollsetlen;
865
866 char strtstandout[TERMCOMSIZE];
867 int strtstandoutlen;
868
869 char endstandout[TERMCOMSIZE];
870 int endstandoutlen;
871
872 extern ochar();
873
874 int t_lines = 24;
875 int b_lines = 23;
876 int p_lines = 20;
877 int t_columns = 80;
878
879 int automargins;
880
881 char *outp;
882 int *outlp;
883
884
885 static
outcf(ch)886 outcf(ch)
887 char ch;
888 {
889 if (*outlp < TERMCOMSIZE)
890 {
891 (*outlp)++;
892 *outp++ = ch;
893 }
894 }
895
896
897 int
term_init(term)898 term_init(term)
899 char *term;
900 {
901 extern char PC, *UP, *BC;
902 #ifndef LINUX
903 extern short ospeed;
904 #endif
905 static char UPbuf[TERMCOMSIZE];
906 static char BCbuf[TERMCOMSIZE];
907 static char buf[1024];
908 char sbuf[2048];
909 char *sbp, *s;
910 char *tgetstr();
911
912 ospeed = cfgetospeed(&tty_state);
913
914 if (tgetent(buf, term) != 1)
915 return NA;
916
917 sbp = sbuf;
918 s = tgetstr("pc", &sbp); /* get pad character */
919 if (s)
920 PC = *s;
921
922 t_lines = tgetnum("li");
923 t_columns = tgetnum("co");
924 automargins = tgetflag("am");
925
926 outp = clearbuf; /* fill clearbuf with clear screen command */
927 outlp = &clearbuflen;
928 clearbuflen = 0;
929 sbp = sbuf;
930 s = tgetstr("cl", &sbp);
931 if (s)
932 tputs(s, t_lines, outcf);
933
934 outp = cleolbuf; /* fill cleolbuf with clear to eol command */
935 outlp = &cleolbuflen;
936 cleolbuflen = 0;
937 sbp = sbuf;
938 s = tgetstr("ce", &sbp);
939 if (s)
940 tputs(s, 1, outcf);
941
942 outp = scrollrev;
943 outlp = &scrollrevlen;
944 scrollrevlen = 0;
945 sbp = sbuf;
946 s = tgetstr("sr", &sbp);
947 if (s)
948 tputs(s, 1, outcf);
949
950 outp = strtstandout;
951 outlp = &strtstandoutlen;
952 strtstandoutlen = 0;
953 sbp = sbuf;
954 s = tgetstr("so", &sbp);
955 if (s)
956 tputs(s, 1, outcf);
957
958 outp = endstandout;
959 outlp = &endstandoutlen;
960 endstandoutlen = 0;
961 sbp = sbuf;
962 s = tgetstr("se", &sbp);
963 if (s)
964 tputs(s, 1, outcf);
965
966 sbp = cursorm;
967 cm = tgetstr("cm", &sbp);
968 if (cm)
969 dumb_term = NA;
970 else
971 {
972 dumb_term = YEA;
973 t_lines = 24;
974 t_columns = 80;
975 }
976
977 sbp = changescroll;
978 cs = tgetstr("cs", &sbp);
979
980 sbp = scrollforward;
981 sf = tgetstr("sf", &sbp);
982
983 sbp = scrollreverse;
984 sr = tgetstr("sr", &sbp);
985
986 sbp = savecursor;
987 sc = tgetstr("sc", &sbp);
988
989 sbp = restorecursor;
990 rc = tgetstr("rc", &sbp);
991
992 sbp = UPbuf;
993 UP = tgetstr("up", &sbp);
994 sbp = BCbuf;
995 BC = tgetstr("bc", &sbp);
996
997 b_lines = t_lines - 1;
998 p_lines = t_lines - 4;
999 return YEA;
1000 }
1001
do_move(int col,int row)1002 do_move(int col, int row) {
1003 char s[8];
1004
1005 sprintf(s, "\033[%d;%dH", row + 1, col + 1);
1006 output(s, strlen(s));
1007 }
1008
save_cursor()1009 save_cursor()
1010 {
1011 tputs(sc, 0, ochar);
1012 }
1013
restore_cursor()1014 restore_cursor()
1015 {
1016 tputs(rc, 0, ochar);
1017 }
1018
1019 /*
1020 woju
1021 */
change_scroll_range(int top,int bottom)1022 change_scroll_range(int top, int bottom)
1023 {
1024 tputs(tparm(cs, top, bottom), 0, ochar);
1025 }
1026
scroll_forward()1027 scroll_forward()
1028 {
1029 tputs(sf, 0, ochar);
1030 }
1031
scroll_reverse()1032 scroll_reverse()
1033 {
1034 tputs(sr, 0, ochar);
1035 }
1036