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