1 /* @(#)ttycmds.c	1.30 21/07/07 Copyright 1984-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)ttycmds.c	1.30 21/07/07 Copyright 1984-2021 J. Schilling";
6 #endif
7 /*
8  *	Lower layer support routines for terminal.c
9  *
10  *	Copyright (c) 1984-2021 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 /*
27  * Exports:
28  *	tty_start()	- Parse TERMCAP entry and do set up for this package
29  *	tty_entry(i)	- Return pointer to decoded TERMCAP entries
30  *	tty_fkey(i)	- Return TERMCAP mapping for function key 'i'
31  *	tty_pagesize()	- Return the terminal's pagesize from TERMCAP entry
32  *	tty_linelength()- Return the terminal's linelength from TERMCAP entry
33  *	tty_init()	- Initialize terminal (send startup sequence)
34  *	tty_term()	- Restore terminal to default mode (send term sequence)
35  *
36  *	TTY*		- Several pointers to apropriate functions
37  *			  implementing TERMCAP functionality.
38  *			  These pointers are not intended for direct use by the
39  *			  higher level software but for terminal.c
40  *
41  * If a specific TERMCAP functionality is not present the corresponding
42  * TTY* function pointer is a NULL pointer.
43  *
44  * If a specific function is not available in a parameterized form directly,
45  * this functionality is emulated by multiple calls to the simple function.
46  * e.g. if your terminal does not support to move the cursor 'n' lines down,
47  * this package calls the cursor-down-single function 'n' times.
48  */
49 #include "ved.h"
50 #include "ttys.h"
51 #include <schily/termcap.h>
52 
53 LOCAL	int (*sputchar)		__PR((int c))	= 0;	/* scr putc for tputs*/
54 
55 EXPORT	void (*TTYclrscreen)	__PR((ewin_t *wp))	= 0;	/* clr screen */
56 EXPORT	void (*TTYclr_endscr)	__PR((ewin_t *wp))	= 0;	/* clr to end of scr */
57 EXPORT	void (*TTYclrendln)	__PR((void))	= 0;	/* clr to end of line*/
58 EXPORT	void (*TTYdelchars)	__PR((int))	= 0;	/* delete chars */
59 EXPORT	void (*TTYdellines)	__PR((int))	= 0;	/* delete lines */
60 EXPORT	void (*TTYinschars)	__PR((char *))	= 0;	/* insert chars */
61 EXPORT	void (*TTYinslines)	__PR((int))	= 0;	/* insert lines */
62 EXPORT	void (*TTYaltvideo)	__PR((char *))	= 0;	/* alternate video */
63 EXPORT	void (*TTYhome)		__PR((void))	= 0;	/* cursor home */
64 EXPORT	void (*TTYup)		__PR((int))	= 0;	/* cursor up */
65 EXPORT	void (*TTYdown)		__PR((int))	= 0;	/* cursor down */
66 EXPORT	void (*TTYleft)		__PR((int))	= 0;	/* cursor left */
67 EXPORT	void (*TTYright)	__PR((int))	= 0;	/* cursor right */
68 EXPORT	void (*TTYcursor)	__PR((int y, int x)) = 0; /* move cursor abs */
69 EXPORT	void (*TTYsscroll)	__PR((int, int)) = 0;	/* set scroll region */
70 EXPORT	void (*TTYsup)		__PR((int))	= 0;	/* scroll up */
71 EXPORT	void (*TTYsdown)	__PR((int))	= 0;	/* scroll down */
72 
73 
74 LOCAL	char	_stbuf[1024];	/* storage for the decoded termcap entries */
75 LOCAL	char	*stbp;		/* export storage pointer for map.c */
76 LOCAL	int	pagesize;	/* number of lines in a page */
77 LOCAL	int	linelength;	/* numver of characters in a line */
78 
79 /*
80  * We add kb=\b to the ansi terminal capabilities in order to be
81  * friendly to people who are using a PC type keyboard.
82  */
83 LOCAL	char	builtin_ansi[] =
84     "sx|ansi|any ansi terminal with pessimistic assumptions:\
85 	:co#80:li#24:cl=50\\E[;H\\E[2J:bs:am:cm=\\E[%i%d;%dH:\
86 	:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt:kb=\b:";
87 
88 #ifdef	USE_DUMB
89 LOCAL	char	builtin_dumb[] = "xx|dumb:";
90 #endif
91 
92 #undef	HZ		/* param.h included ???			*/
93 #undef	UC		/* is defined (unsigned char *) in ved.h*/
94 
95 char	AM;		/* Automatic Margins			*/
96 char	BS;		/* Backspace works			*/
97 char	CA;		/* Cursor Adressable			*/
98 char	DA;		/* Display retained above the Screen	*/
99 char	DB;		/* Display retained below the Screen	*/
100 char	EO;		/* ca Erase Overstrikes with a blank	*/
101 char	HC;		/* Hardcopy Terminal			*/
102 char	HZ;		/* Cannot print ~s (Hazeltine)		*/
103 char	IN;		/* Insert Mode distinguish nulls	*/
104 char	MI;		/* Can move in Insert Mode		*/
105 char	MS;		/* Save to move in standout Mode	*/
106 char	NC;		/* Not correctly working CR		*/
107 char	NS;		/* CRT that does not Scroll		*/
108 char	OS;		/* Overstrike works			*/
109 char	UL;		/* Underline Character overstrikes	*/
110 char	XB;		/* Beehive (f1=ESC, f2=^C)		*/
111 char	XN;		/* Newline ignored after 80 cols	*/
112 char	XT;		/* TABS destructive, so magic		*/
113 char	XS;		/* Standout not erased by overwriting	*/
114 char	XX;		/* Tektronix Insert Line		*/
115 
116 char	*AL;		/* Add 1 line				*/
117 char	*AL_PARM;	/* Add n lines				*/
118 #ifdef	OLD_TERMCAP	/* 'BC' is now defined in tgoto.c	*/
119 char	*BC;		/* Back Cursor movement (Cursor left)	*/
120 #endif
121 char	*BT;		/* Back Tab				*/
122 char	*CD;		/* Clear to End of Display		*/
123 char	*CE;		/* Clear to End of Line			*/
124 char	*CL;		/* Clear Scereen			*/
125 char	*CM;		/* Cursor Motion			*/
126 char	*CR;		/* Carriage return			*/
127 #undef	CS		/* We may have included sys/regset.h	*/
128 char	*CS;		/* Change scrolling region		*/
129 char	*DC;		/* Delete 1 character			*/
130 char	*DC_PARM;	/* Delete n characters			*/
131 char	*DL;		/* Delete 1 line			*/
132 char	*DL_PARM;	/* Delete n lines			*/
133 char	*DM;		/* Delete mode enter			*/
134 char	*DO;		/* Cursor down 1 line			*/
135 char	*DOWN_PARM;	/* Cursor down n lines			*/
136 char	*ED;		/* End delete mode			*/
137 char	*EI;		/* End insert mode			*/
138 char	*HO;		/* Home cursor				*/
139 char	*IC;		/* Insert 1 character			*/
140 char	*IC_PARM;	/* Insert n characters			*/
141 char	*IM;		/* Insert mode (add im=: if has ic=)	*/
142 char	*IP;		/* Insert pad after using IM and EI	*/
143 char	*KD;		/* Keypad down arrow			*/
144 char	*KE;		/* Keypad end transmit mode		*/
145 char	*KH;		/* Keypad home key			*/
146 char	*KEK;		/* Keypad end key			*/
147 char	*KDK;		/* Keypad delete key			*/
148 char	*KL;		/* Keypad left arrow			*/
149 char	*KR;		/* Keypad right arrow			*/
150 char	*KS;		/* Keypad start transmit mode		*/
151 char	*KU;		/* Keypad up arrow			*/
152 char	*LEFT_PARM;	/* Cursor left n chars			*/
153 char	*LL;		/* Move to last line, first column	*/
154 char	*MA;		/* Arrow key map			*/
155 char	*MD;		/* Bold mode start			*/
156 char	*ME;		/* All attribute end			*/
157 char	*ND;		/* Non destructive space (Cursor right)	*/
158 char	*NL;		/* Linefeed if not NL			*/
159 char	*RC;		/* Restore cursor			*/
160 char	*RIGHT_PARM;	/* Right n chars			*/
161 char	*SC;		/* Save cursor				*/
162 char	*SE;		/* Standout end				*/
163 char	*SF;		/* Scroll forward 1 line		*/
164 char	*SF_PARM;	/* Scroll forward n lines		*/
165 char	*SO;		/* Standout begin			*/
166 char	*SR;		/* Scroll reverse 1 line		*/
167 char	*SR_PARM;	/* Scroll reverse n lines		*/
168 char	*TA;		/* Tab if not ^I or need padding	*/
169 char	*TE;		/* Terminal end sequence		*/
170 char	*TI;		/* Terminal init sequence		*/
171 char	*UC;		/* Underscore one char and move past it	*/
172 char	*UE;		/* Underscore mode end			*/
173 #ifdef	OLD_TERMCAP	/* 'UP' is now defined in tgoto.c	*/
174 char	*UP;		/* Cursor up 1 line			*/
175 #endif
176 char	*UP_PARM;	/* Cursor up n lines			*/
177 char	*US;		/* Underscore mode start		*/
178 char	*VB;		/* Visible bell				*/
179 char	*VE;		/* Visual end sequence			*/
180 char	*VS;		/* Visual start sequence		*/
181 
182 /*
183  * Various function keys (f0 .. f19)
184  */
185 char	*K0,  *K1,  *K2,  *K3,  *K4,  *K5,  *K6,  *K7,  *K8,  *K9;
186 char	*K10, *K11, *K12, *K13, *K14, *K15, *K16, *K17, *K18, *K19;
187 
188 LOCAL	char	*_PC;	/* Pad Character String			*/
189 #ifdef	OLD_TERMCAP	/* 'PC' is now defined in tputs.c	*/
190 char	PC;		/* Pad Character			*/
191 #endif
192 
193 /*
194  * From the tty modes...
195  */
196 char	GT;		/* Gtty told us that we may use tabs	*/
197 char	NONL;		/* Terminal don't needs linefeed on CR	*/
198 char	UPPERCASE;	/* Terminal is upper case only		*/
199 #ifdef	OLD_TERMCAP	/* 'ospeed' is now defined in tputs.c	*/
200 short	ospeed = -1;	/* Needed to compute padding in tputs()	*/
201 #endif
202 
203 LOCAL	char	*tflags[] = {
204 			&AM, &BS, &DA, &DB, &EO, &HC, &HZ, &IN, &MI,
205 			&MS, &NC, &NS, &OS, &UL, &XB, &XN, &XT, &XS,
206 			&XX
207 		};
208 
209 LOCAL	char	**tstrs[] = {
210 			&AL, &BC, &BT, &CD, &CE, &CL, &CM, &CR, &CS,
211 			&DC, &DL, &DM, &DO, &ED, &EI, &HO, &IC,
212 			&IM, &IP, &KD, &KE, &KH, &KL, &KR, &KS, &KU,
213 			&LL, &MA, &MD, &ME, &ND, &NL, &_PC, &RC, &SC, &SE, &SF,
214 			&SO, &SR, &TA, &TE, &TI, &UC, &UE, &UP, &US,
215 			&VB, &VS, &VE, &AL_PARM, &DL_PARM, &UP_PARM,
216 			&DOWN_PARM, &LEFT_PARM, &RIGHT_PARM, &DC_PARM,
217 			&IC_PARM, &SF_PARM, &SR_PARM,
218 			&KEK, &KDK,
219 		};
220 
221 LOCAL	char	**tfkeys[] = {
222 		&K0,  &K1,  &K2,  &K3,  &K4,  &K5,  &K6,  &K7,  &K8,  &K9,
223 		&K10, &K11, &K12, &K13, &K14, &K15, &K16, &K17, &K18, &K19,
224 		};
225 
226 EXPORT	char *	tty_start	__PR((int (*)(int c)));
227 LOCAL	void	tputstr		__PR((char *s));
228 EXPORT	char **	tty_entry	__PR((void));
229 EXPORT	void	tty_init	__PR((void));
230 EXPORT	void	tty_term	__PR((void));
231 EXPORT	char *	tty_fkey	__PR((int n));
232 EXPORT	int	tty_pagesize	__PR((void));
233 EXPORT	int	tty_linelength	__PR((void));
234 LOCAL	void	cur_abs		__PR((int y, int x));
235 LOCAL	void	cl_screen	__PR((ewin_t *wp));
236 LOCAL	void	cl_e_screen	__PR((ewin_t *wp));
237 LOCAL	void	cl_e_line	__PR((void));
238 LOCAL	void	home_cursor	__PR((void));
239 LOCAL	void	up_S		__PR((int n));
240 LOCAL	void	up_M		__PR((int n));
241 LOCAL	void	down_S		__PR((int n));
242 LOCAL	void	down_M		__PR((int n));
243 LOCAL	void	left_S		__PR((int n));
244 LOCAL	void	left_M		__PR((int n));
245 LOCAL	void	right_S		__PR((int n));
246 LOCAL	void	right_M		__PR((int n));
247 LOCAL	void	del_c_S		__PR((int n));
248 LOCAL	void	del_c_M		__PR((int n));
249 LOCAL	void	del_l_S		__PR((int n));
250 LOCAL	void	del_l_M		__PR((int n));
251 LOCAL	void	ins_c_S		__PR((char *str));
252 LOCAL	void	ins_c_M		__PR((char *str));
253 LOCAL	void	ins_str		__PR((char *str));
254 LOCAL	void	ins_l_S		__PR((int n));
255 LOCAL	void	ins_l_M		__PR((int n));
256 #ifdef	__needed__
257 LOCAL	void	alt_S_Svideo	__PR((char *str));
258 #endif
259 LOCAL	void	alt_S_video	__PR((char *str));
260 LOCAL	void	alt_B_video	__PR((char *str));
261 LOCAL	void	alt_U_video	__PR((char *str));
262 LOCAL	void	sscr		__PR((int b, int e));
263 LOCAL	void	sup_S		__PR((int n));
264 LOCAL	void	sup_M		__PR((int n));
265 LOCAL	void	sdown_S		__PR((int n));
266 LOCAL	void	sdown_M		__PR((int n));
267 LOCAL	void	gettc		__PR((void));
268 LOCAL	void	setupttycmds	__PR((void));
269 
270 
271 /*
272  * Initialization ot the TERMCAP package.
273  * -	Read the TERMCAP data base and set pagesize & linelength.
274  * -	Set up function key maps.
275  * -	Set up pointers to the implementation functions.
276  *
277  * outchar() is a pointer to the function that is used to send
278  * the control sequences to the terminal.
279  *
280  * Returns:
281  *	NULL	- success
282  *	!= NULL	- pointer to string with error message
283  */
284 EXPORT char *
285 tty_start(outchar)
286 	int (*outchar) __PR((int c));
287 {
288 		int	ret;
289 	static	char	noterm[] = "unknown";
290 		char	*tname;
291 		char	*errstr = NULL;
292 
293 	/*
294 	 * Look up the TERMCAP database for the current terminal type.
295 	 * Use some "smart" defaults if "TERM" is not defined or contains junk.
296 	 */
297 	if ((tname = getenv("TERM")) == NULL)
298 		tname = noterm;
299 	if (tname[0] == '\0')
300 		tname = "xx";
301 
302 /*	unknown = FALSE;*/
303 	seterrno(0);
304 	if ((ret = tgetent(NULL, tname)) != 1) {
305 		char	*bp = tcgetbuf();
306 
307 /*		unknown++;*/
308 
309 #ifndef	NO_BUILTIN_ANSI
310 		if (bp) {
311 			if (ret < 0) {
312 				errmsgno(EX_BAD,
313 				    "Cannot open termcap file '%s'.\n", bp);
314 			}
315 			errmsgno(EX_BAD,
316 			    "Cannot find description for 'TERM=%s'.\n",
317 			    tname);
318 			errmsgno(EX_BAD,
319 			    "Using builtin ansi terminal description.\n");
320 			errmsgno(EX_BAD,
321 			    "Please install a termcap file in %s %s.\n",
322 			    "$HOME/.termcap",
323 			    "to avoid this message");
324 			sleep(1);
325 			strcpy(bp, builtin_ansi);
326 		} else
327 #endif
328 		if (ret == -1) {
329 			js_snprintf(_stbuf, sizeof (_stbuf),
330 					"Cannot open termcap file.\n");
331 			return (_stbuf);
332 		} else {
333 			js_snprintf(_stbuf, sizeof (_stbuf),
334 					"Cannot find terminal type: %s.\n",
335 								tname);
336 			if (geterrno() == 0)
337 				seterrno(EX_BAD);
338 			return (_stbuf);
339 		}
340 	}
341 
342 	if (errstr)		/* XXX */
343 		return (errstr);
344 
345 #ifdef	__never__
346 	/*
347 	 * Do not set up  default unless we invented a method to let ved
348 	 * work on a hardcopy terminal.
349 	 */
350 	if ((pagesize = tgetnum("li")) <= 1)
351 		pagesize = 2;
352 	if ((linelength = tgetnum("co")) <= 4)
353 		linelength = 80;
354 #endif
355 
356 	/*
357 	 *  Now, parse the content of the TERMCAP data base buffer.
358 	 */
359 	gettc();
360 
361 	/*
362 	 * Set up the exported implementation function pointers
363 	 * and a pointer to the output function.
364 	 */
365 	init_fk_maps();
366 	setupttycmds();
367 	sputchar = outchar;
368 	return (0);
369 }
370 
371 LOCAL void
tputstr(s)372 tputstr(s)
373 	register char	*s;
374 {
375 	while (*s) {
376 		if (*s == '\n')
377 			(*sputchar)('\r');
378 		(*sputchar)(*s++);
379 	}
380 }
381 
382 /*
383  * Return space to be used by tgetstr()
384  */
385 EXPORT char **
tty_entry()386 tty_entry()
387 {
388 	return (&stbp);
389 }
390 
391 /*
392  * Put Terminal into a mode useful for the TERMCAP packet.
393  */
394 EXPORT void
tty_init()395 tty_init()
396 {
397 	if (!XT) GT = 0;		/* Do not use tabs if destructive */
398 
399 	if (TI)
400 		tputs(TI, 0, sputchar);	/* initialize terminal */
401 	if (VS)
402 		tputs(VS, 0, sputchar);	/* make cursor visible */
403 	if (KS)
404 		tputs(KS, 0, sputchar);	/* start keypad transmit mode */
405 
406 }
407 
408 /*
409  * Restore Terminal mode to general purpose mode.
410  */
411 EXPORT void
tty_term()412 tty_term()
413 {
414 	if (VE && sputchar)
415 		tputs(VE, 0, sputchar);
416 	if (KE && sputchar)
417 		tputs(KE, 0, sputchar);
418 	if (TE && sputchar)
419 		tputs(TE, 0, sputchar);
420 
421 }
422 
423 /*
424  * Return decoded strings for function keys.
425  */
426 EXPORT char *
tty_fkey(n)427 tty_fkey(n)
428 	int	n;
429 {
430 	if (n >= 0 && n < (sizeof (tfkeys)/sizeof (tfkeys[0])))
431 		return (*tfkeys[n]);
432 	return ((char *)0);
433 }
434 
435 /*
436  * Return pagesize from TERMCAP entry for TERM.
437  */
438 EXPORT int
tty_pagesize()439 tty_pagesize()
440 {
441 	return (pagesize);
442 }
443 
444 /*
445  * Return linelength from TERMCAP entry for TERM.
446  */
447 EXPORT int
tty_linelength()448 tty_linelength()
449 {
450 	return (linelength);
451 }
452 
453 /*
454  * move cursor absolute (Y/row/vpos, X/col/hpos)
455  */
456 LOCAL void
cur_abs(y,x)457 cur_abs(y, x)
458 	int	y;
459 	int	x;
460 {
461 	tputs(tgoto(CM, x, y), 0, sputchar);
462 }
463 
464 /*
465  * clear screen
466  */
467 LOCAL void
cl_screen(wp)468 cl_screen(wp)
469 	ewin_t	*wp;
470 {
471 	tputs(CL, wp->psize, sputchar);
472 }
473 
474 /*
475  * clear from cursor to end of screen
476  */
477 LOCAL void
cl_e_screen(wp)478 cl_e_screen(wp)
479 	ewin_t	*wp;
480 {
481 	tputs(CD, wp->psize-cpos.vp, sputchar);
482 }
483 
484 /*
485  * clear from cursor to end of line
486  */
487 LOCAL void
cl_e_line()488 cl_e_line()
489 {
490 	tputs(CE, 1, sputchar);
491 }
492 
493 /*
494  * home cursor
495  */
496 LOCAL void
home_cursor()497 home_cursor()
498 {
499 	tputs(HO, 0, sputchar);
500 }
501 
502 /*
503  * cursor up - using non parameter mode
504  */
505 LOCAL void
up_S(n)506 up_S(n)
507 	register int n;
508 {
509 	while (--n >= 0)
510 		tputs(UP, 0, sputchar);
511 }
512 
513 /*
514  * cursor up - parameter mode
515  */
516 LOCAL void
up_M(n)517 up_M(n)
518 	int	n;
519 {
520 	tputs(tgoto(UP_PARM, 0, n), n, sputchar);
521 }
522 
523 /*
524  * cursor down - using non parameter mode
525  */
526 LOCAL void
down_S(n)527 down_S(n)
528 	register int n;
529 {
530 	while (--n >= 0)
531 		tputs(DO, 0, sputchar);
532 }
533 
534 /*
535  * cursor down - parameter mode
536  */
537 LOCAL void
down_M(n)538 down_M(n)
539 	int	n;
540 {
541 	tputs(tgoto(DOWN_PARM, 0, n), n, sputchar);
542 }
543 
544 /*
545  * cursor left - using non parameter mode
546  */
547 LOCAL void
left_S(n)548 left_S(n)
549 	register int n;
550 {
551 	while (--n >= 0)
552 		tputs(BC, 0, sputchar);
553 }
554 
555 /*
556  * cursor left - parameter mode
557  */
558 LOCAL void
left_M(n)559 left_M(n)
560 	int	n;
561 {
562 	tputs(tgoto(LEFT_PARM, 0, n), n, sputchar);
563 }
564 
565 /*
566  * cursor right - using non parameter mode
567  */
568 LOCAL void
right_S(n)569 right_S(n)
570 	register int n;
571 {
572 	while (--n >= 0)
573 		tputs(ND, 0, sputchar);
574 }
575 
576 /*
577  * cursor right - parameter mode
578  */
579 LOCAL void
right_M(n)580 right_M(n)
581 	int	n;
582 {
583 	tputs(tgoto(RIGHT_PARM, 0, n), n, sputchar);
584 }
585 
586 /*
587  * delete chars - using non parameter mode
588  */
589 LOCAL void
del_c_S(n)590 del_c_S(n)
591 	register int n;
592 {
593 	while (--n >= 0)
594 		tputs(DC, 0, sputchar);
595 }
596 
597 /*
598  * delete chars - parameter mode
599  */
600 LOCAL void
del_c_M(n)601 del_c_M(n)
602 	int	n;
603 {
604 	tputs(tgoto(DC_PARM, 0, n), n, sputchar);
605 }
606 
607 /*
608  * delete lines - using non parameter mode
609  */
610 LOCAL void
del_l_S(n)611 del_l_S(n)
612 	register int n;
613 {
614 	while (--n >= 0)
615 		tputs(DL, 0, sputchar);
616 }
617 
618 /*
619  * delete lines - parameter mode
620  */
621 LOCAL void
del_l_M(n)622 del_l_M(n)
623 	int	n;
624 {
625 	tputs(tgoto(DL_PARM, 0, n), n, sputchar);
626 }
627 
628 /*
629  * insert chars - using non parameter mode
630  */
631 LOCAL void
ins_c_S(str)632 ins_c_S(str)
633 	register char *str;
634 {
635 	while (*str) {
636 		tputs(IC, 0, sputchar);
637 		(*sputchar)(*str++);
638 	}
639 }
640 
641 /*
642  * insert chars - parameter mode
643  */
644 LOCAL void
ins_c_M(str)645 ins_c_M(str)
646 	char *str;
647 {
648 	int	n = strlen(str);
649 
650 	tputs(tgoto(IC_PARM, 0, n), n, sputchar);
651 	tputstr(str);
652 }
653 
654 /*
655  * insert string
656  */
657 LOCAL void
ins_str(str)658 ins_str(str)
659 	char *str;
660 {
661 	tputs(IM, 0, sputchar);
662 	tputstr(str);
663 	tputs(EI, 0, sputchar);
664 }
665 
666 /*
667  * insert lines - using non parameter mode
668  */
669 LOCAL void
ins_l_S(n)670 ins_l_S(n)
671 	register int n;
672 {
673 	while (--n >= 0)
674 		tputs(AL, 0, sputchar);
675 }
676 
677 LOCAL void
678 /*
679  * insert lines - parameter mode
680  */
ins_l_M(n)681 ins_l_M(n)
682 	int	n;
683 {
684 	tputs(tgoto(AL_PARM, 0, n), n, sputchar);
685 }
686 
687 #ifdef	__needed__
688 /*
689  * alternate video - using non parameter mode
690  * XXX is this function possible with termcap?
691  */
692 LOCAL void
alt_S_Svideo(str)693 alt_S_Svideo(str)
694 	register char *str;
695 {
696 	while (*str) {
697 /*		tputs(SO XXX, 0, sputchar);*/
698 		(*sputchar)(*str++);
699 	}
700 }
701 #endif
702 
703 /*
704  * alternate video - using Standout Mode
705  */
706 LOCAL void
alt_S_video(str)707 alt_S_video(str)
708 	register char *str;
709 {
710 	tputs(SO, 0, sputchar);
711 	tputstr(str);
712 	tputs(SE, 0, sputchar);
713 }
714 
715 /*
716  * alternate video - using Bold Mode
717  */
718 LOCAL void
alt_B_video(str)719 alt_B_video(str)
720 	register char *str;
721 {
722 	tputs(MD, 0, sputchar);
723 	tputstr(str);
724 	tputs(ME, 0, sputchar);
725 }
726 
727 /*
728  * alternate video - using Underline Mode
729  */
730 LOCAL void
alt_U_video(str)731 alt_U_video(str)
732 	register char *str;
733 {
734 	tputs(US, 0, sputchar);
735 	tputstr(str);
736 	tputs(UE, 0, sputchar);
737 }
738 
739 /*
740  * set scroll region
741  */
742 LOCAL void
sscr(b,e)743 sscr(b, e)
744 	int	b;
745 	int	e;
746 {
747 	tputs(tgoto(CS, e, b), 0, sputchar);
748 }
749 
750 /*
751  * scroll up - using non parameter mode
752  */
753 LOCAL void
sup_S(n)754 sup_S(n)
755 	register int n;
756 {
757 	while (--n >= 0)
758 		tputs(SF, 0, sputchar);
759 }
760 
761 /*
762  * scroll up - parameter mode
763  */
764 LOCAL void
sup_M(n)765 sup_M(n)
766 	int	n;
767 {
768 	tputs(tgoto(SF_PARM, 0, n), n, sputchar);
769 }
770 
771 /*
772  * scroll down - using non parameter mode
773  */
774 LOCAL void
sdown_S(n)775 sdown_S(n)
776 	register int n;
777 {
778 	while (--n >= 0)
779 		tputs(SR, 0, sputchar);
780 }
781 
782 /*
783  * scroll down - parameter mode
784  */
785 LOCAL void
sdown_M(n)786 sdown_M(n)
787 	int	n;
788 {
789 	tputs(tgoto(SR_PARM, 0, n), n, sputchar);
790 }
791 
792 /*
793  * Get Flags and Strings from Termcap Entry
794  */
795 LOCAL void
gettc()796 gettc()
797 {
798 	register char	*np;
799 	register char	**fp;
800 	register char	***sp;
801 		char	*sbp;
802 
803 	sbp = _stbuf;
804 
805 	/*
806 	 * Parse boolean flags.
807 	 */
808 	np = "ambsdadbeohchzinmimsncnsosulxbxnxtxsxx";
809 	fp = tflags;
810 	do {
811 		*(*fp++) = tgetflag(np);
812 		np += 2;
813 	} while (*np);
814 
815 	/*
816 	 * Parse string capabilities.
817 	 */
818 	np = "albcbtcdceclcmcrcsdcdldmdoedeihoicimipkdkekhklkrkskullmamdmendnlpcrcscsesfsosrtatetiucueupusvbvsveALDLUPDOLERIDCICSFSR@7kD";
819 	sp = tstrs;
820 	do {
821 		*(*sp++) = tgetstr(np, &sbp);
822 		np += 2;
823 	} while (*np);
824 
825 	/*
826 	 * Parse function key values.
827 	 */
828 	np = "k0k1k2k3k4k5k6k7k8k9k;F1F2F3F4F5F6F7F8F9";
829 	sp = tfkeys;
830 	do {
831 		*(*sp++) = tgetstr(np, &sbp);
832 		np += 2;
833 	} while (*np);
834 
835 	stbp = sbp;
836 
837 	if (XS) {
838 		SO = SE = NULL;
839 	} else {
840 		/*
841 		 * Enter/Exit Standout Glitch present?
842 		 */
843 		if (tgetnum("sg") > 0)	/* # of glitch chars left by so or se*/
844 			SO = NULL;
845 		/*
846 		 * Enter/Exit Underline Glitch present?
847 		 */
848 		if (tgetnum("ug") > 0)	/* # of glitch chars left by us or ue*/
849 			US = NULL;
850 		if (!SO && US) {
851 			SO = US;
852 			SE = UE;
853 		}
854 	}
855 
856 	/*
857 	 * Handle funny termcap capabilities
858 	 */
859 	if (CS && SC && RC) AL = DL = "";	/* XXX */
860 	if (AL_PARM && AL == NULL) AL = "";
861 	if (DL_PARM && DL == NULL) DL = "";
862 	if (IC && IM == NULL) IM = "";
863 	if (IC && EI == NULL) EI = "";
864 	if (IM == NULL || EI == NULL) IM = EI = NULL;
865 	if (!XT) GT = 0;	/* Do not use tabs if destructive */
866 	if (!GT) BT = NULL;	/* If we can't tab, we can't backtab either */
867 
868 	if (tgoto(CM, 2, 2)[0] == 'O')
869 		CA = FALSE, CM = 0;
870 	else
871 		CA = TRUE;
872 
873 	PC = _PC ? _PC[0] : '\0';
874 
875 /*	if (unknown)*/
876 /*		return ERR;*/
877 /*	return OK;*/
878 }
879 
880 LOCAL void
setupttycmds()881 setupttycmds()
882 {
883 #ifdef CURSOR
884 		char	*ku;
885 		char	*kd;
886 		char	*kr;
887 		char	*kl;
888 		char	*kB;
889 		char	*kE;
890 #endif
891 
892 #ifdef CURSOR
893 	ku = tgetstr("ku", &sbp);		/* Corsor up */
894 	kd = tgetstr("kd", &sbp);		/* Corsor down */
895 	kr = tgetstr("kr", &sbp);		/* Corsor forward */
896 	kl = tgetstr("kl", &sbp);		/* Corsor left */
897 	kB = tgetstr("kB", &sbp);		/* Corsor leftmost */
898 	kE = tgetstr("kE", &sbp);		/* Corsor rightmost */
899 	if (ku) _add_map(ku, "");		/* Corsor up */
900 	if (kd) _add_map(kd, "");		/* Corsor down */
901 	if (kr) _add_map(kr, "");		/* Corsor forward */
902 	if (kl) _add_map(kl, "");		/* Corsor left */
903 	if (kB) _add_map(kB, "");		/* Corsor leftmost */
904 	if (kE)	_add_map(kE, "");		/* Corsor rightmost */
905 #endif
906 
907 	if (CA)
908 		TTYcursor = cur_abs;
909 	if (CL)
910 		TTYclrscreen = cl_screen;
911 	if (CD)
912 		TTYclr_endscr = cl_e_screen;
913 	if (CE)
914 		TTYclrendln = cl_e_line;
915 	if (HO)
916 		TTYhome = home_cursor;
917 
918 	if (UP_PARM)
919 		TTYup = up_M;
920 	else if (UP)
921 		TTYup = up_S;
922 	if (DOWN_PARM)
923 		TTYdown = down_M;
924 	else if (DO)
925 		TTYdown = down_S;
926 	if (LEFT_PARM)
927 		TTYleft = left_M;
928 	else if (BC)
929 		TTYleft = left_S;
930 	if (RIGHT_PARM)
931 		TTYright = right_M;
932 	else if (ND)
933 		TTYright = right_S;
934 
935 	if (DC_PARM)
936 		TTYdelchars = del_c_M;
937 	else if (DC)
938 		TTYdelchars = del_c_S;
939 	if (DL_PARM)
940 		TTYdellines = del_l_M;
941 	else if (DL && *DL)
942 		TTYdellines = del_l_S;
943 
944 	if (IC_PARM)
945 		TTYinschars = ins_c_M;
946 	/*
947 	 * Pr�fen, wann IM und EI im vi verwendet werden !!!
948 	 * Es sieht so aus, als ob im vi hier der volle Pfusch abgeht.
949 	 * Mal nimmt er er IM und EI, mal nimmt er IC.
950 	 * Man mu� hier wohl sehr vorsichtig sein, was die Richtigkeit
951 	 * der Termcap Eintr�ge angeht, denn die sind wohl auf das Chaos
952 	 * im vi abgestimmt. Nach vorsichtiger Betrachtung scheint der vi
953 	 * auf eine sehr komplexe Art beides geschachtelt zu verwenden.
954 	 */
955 	else if (IM && *IM)
956 		TTYinschars = ins_str;
957 	else if (IC)
958 		TTYinschars = ins_c_S;
959 	if (AL_PARM)
960 		TTYinslines = ins_l_M;
961 	else if (AL && *AL)
962 		TTYinslines = ins_l_S;
963 
964 	if (SO && SE)
965 		TTYaltvideo = alt_S_video;
966 	else if (MD && ME)
967 		TTYaltvideo = alt_B_video;
968 	else if (US && UE)
969 		TTYaltvideo = alt_U_video;
970 
971 	if (CS)
972 		TTYsscroll = sscr;
973 
974 	if (SF_PARM)
975 		TTYsup = sup_M;
976 	else if (!NS) {
977 		SF = "\n";
978 		TTYsup = sup_S;
979 	} else if (SF)
980 		TTYsup = sup_S;
981 
982 	if (SR_PARM)
983 		TTYsdown = sdown_M;
984 	else if (SR)
985 		TTYsdown = sdown_S;
986 }
987