1 /************************************************************************
2  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
3  * provided to you without charge, and with no warranty.  You may give  *
4  * away copies of JOVE, including sources, provided that this notice is *
5  * included in all the files.                                           *
6  ************************************************************************/
7 
8 #include "jove.h"
9 
10 #ifdef TERMCAP	/* the body is the rest of the file */
11 
12 #include "term.h"
13 
14 #include "disp.h"
15 #include "fmt.h"
16 #include "fp.h"
17 #include "jctype.h"
18 #include "screen.h"
19 
20 extern int	UNMACRO(tgetent) proto((char */*buf*/, const char */*name*/));
21 extern int	UNMACRO(tgetflag) proto((const char */*id*/));
22 extern int	UNMACRO(tgetnum) proto((const char */*id*/));
23 extern char	*UNMACRO(tgetstr) proto((const char */*id*/, char **/*area*/));
24 extern void	UNMACRO(tputs) proto((const char *, int, void (*) proto((int))));
25 
26 /* Termcap definitions */
27 
28 char
29 	*CS,	/* change scrolling region */
30 	*SO,	/* Start standout */
31 	*SE,	/* End standout */
32 	*US,	/* Start underlining */
33 	*UE,	/* End underlining */
34 	*CM,	/* The cursor motion string */
35 	*CL,	/* Clear screen */
36 	*CE,	/* Clear to end of line */
37 	*HO,	/* Home cursor */
38 	*AL,	/* Addline (insert line) */
39 	*DL,	/* Delete line */
40 	*VS,	/* Visual start */
41 	*VE,	/* Visual end */
42 	*KS,	/* Keypad mode start */
43 	*KE,	/* Keypad mode end */
44 	*TI,	/* Cursor addressing start */
45 	*TE,	/* Cursor addressing end */
46 	*LL,	/* Last line, first column */
47 	*SF = "\n",	/* Scroll forward (defaults to \n) */
48 	*SR,	/* Scroll reverse */
49 	*VB,	/* visible bell */
50 	*BL = "\007",	/* audible bell (defaults to BEL) */
51 	*lPC,	/* pad character (as a string!) */
52 	*NL = "\n",	/* newline character (defaults to \n) */
53 	*DO = "\n",	/* down one line (defaults to \n capability) */
54 	*M_AL,	/* Insert line with arg */
55 	*M_DL,	/* Delete line with arg */
56 	*M_SF,	/* Scroll forward with arg */
57 	*M_SR;	/* Scroll back with arg */
58 
59 int
60 	UPlen = INFINITY,		/* length of the UP string */
61 	HOlen = INFINITY,		/* length of Home string */
62 	LLlen = INFINITY,		/* length of last line string */
63 
64 	phystab = 8,	/* ("it") terminal's tabstop settings */
65 	UG;		/* number of magic cookies left by US and UE */
66 
67 bool
68 	Hazeltine,	/* Hazeltine tilde kludge */
69 	UL,		/* underscores don't replace chars already on screen */
70 	NP;		/* there is No Pad character */
71 
72 #  ifdef DEFINE_PC_BC_UP_OSPEED
73 	/* This is needed for HP-UX, possibly for other SYSVR2 systems */
74 char
75 	PC,		/* pad character, as a char (set from lPC; defaults to NUL) */
76 	*BC,	/* back space (defaults to BS) */
77 	*UP;	/* Scroll reverse, or up */
78 
79 short	ospeed;
80 #  endif /* DEFINE_PC_BC_UP_OSPEED */
81 
82 bool	CanScroll;	/* can this terminal scroll? */
83 
84 #  ifdef ID_CHAR
85 
86 char
87 	*IC,	/* Insert char */
88 	*DC,	/* Delete char */
89 	*IM,	/* Insert mode */
90 	*EI,	/* End insert mode */
91 	*IP,	/* insert pad after character inserted */
92 	*M_IC,	/* Insert char with arg */
93 	*M_DC;	/* Delete char with arg */
94 
95 bool	UseIC = NO;	/* VAR: whether or not to use i/d char processesing */
96 
97 int
98 	IMlen = 0,	/* length of insert mode */
99 	EIlen = 0,	/* length of end insert mode string */
100 	IClen = 0,	/* length of insert char */
101 	DClen = 0,	/* length of delete char */
102 	MIClen = INFINITY,	/* length of insert char with arg */
103 	MDClen = INFINITY,	/* length of delete char with arg */
104 	CElen = 0;	/* length of clear to end of line */
105 
106 bool
107 	MI;		/* okay to move while in insert mode */
108 
109 #  endif /* ID_CHAR */
110 
111 private char	tspace[256];	/* space for termcap strings */
112 
113 /* The ordering of ts and meas must agree !! */
114 private const char	ts[] =
115 #  ifdef ID_CHAR
116 /*                   |                   |                   | |             */
117 "vsvealdlcssoseusuecmclcehoupbcllsfsrvbksketitepcblnldoALDLSFSRicimdceiipICDC";
118 #  else
119 "vsvealdlcssoseusuecmclcehoupbcllsfsrvbksketitepcblnldoALDLSFSR";
120 #  endif
121 
122 private char	**const meas[] = {
123 	&VS, &VE, &AL, &DL, &CS, &SO, &SE, &US, &UE, &CM,
124 	&CL, &CE, &HO, &UP, &BC, &LL, &SF, &SR, &VB, &KS,
125 	&KE, &TI, &TE, &lPC, &BL, &NL, &DO, &M_AL, &M_DL, &M_SF,
126 	&M_SR,
127 #  ifdef ID_CHAR
128 	&IC, &IM, &DC, &EI, &IP, &M_IC, &M_DC,
129 #  endif
130 	NULL
131 };
132 
133 struct CapLen {
134 	char	**cap_var;
135 	int	*len_var;
136 };
137 
138 private const struct CapLen	CapLenTab[] = {
139 	{ &HO,	&HOlen },
140 	{ &LL,	&LLlen },
141 	{ &UP,	&UPlen },
142 #  ifdef ID_CHAR
143 	{ &IM,	&IMlen },
144 	{ &EI,	&EIlen },
145 	{ &IC,	&IClen },
146 	{ &DC,	&DClen },
147 	{ &M_IC,	&MIClen },
148 	{ &M_DC,	&MDClen },
149 	{ &CE,	&CElen },
150 #  endif
151 	{ NULL,	NULL }
152 };
153 
154 private void
tcbad(termname,why)155 tcbad(termname, why)
156 const char
157 	*termname,
158 	*why;
159 {
160 	writef("You can't run JOVE on a %s terminal: %s\n", termname, why);
161 	flushscreen();
162 	_exit(1);
163 }
164 
165 void
getTERM()166 getTERM()
167 {
168 	char	termnmbuf[13],
169 		*termname = getenv("TERM"),
170 		*termp = tspace,
171 		tbuff[2048];	/* Good grief! */
172 
173 	if (termname == NULL || *termname == '\0'
174 	|| strcmp(termname, "dumb") == 0
175 	|| strcmp(termname, "unknown") == 0
176 	|| strcmp(termname, "network") == 0)
177 	{
178 		int	len;
179 		putstr("Enter terminal type (e.g, vt100): ");
180 		flushscreen();
181 		len = read(0, (UnivPtr) termnmbuf, sizeof(termnmbuf));
182 		termnmbuf[len > 1? len - 1 : 0] = '\0';
183 		termname = termnmbuf;
184 	}
185 
186 	if (tgetent(tbuff, termname) < 1)
187 		tcbad(termname, "type unknown");
188 
189 	/* get numeric capabilities */
190 
191 	if ((CO = tgetnum("co")) == -1)
192 		tcbad(termname, "co unknown (width)");
193 
194 	if (CO > MAXCOLS)
195 		CO = MAXCOLS;
196 
197 	if ((LI = tgetnum("li")) == -1)
198 		tcbad(termname, "li unknown (height)");
199 
200 	if ((phystab = tgetnum("it")) == -1 || phystab <= 0)
201 		phystab = 8;
202 
203 	if ((SG = tgetnum("sg")) == -1)
204 		SG = 0;			/* Used for mode line only */
205 
206 	if ((UG = tgetnum("ug")) == -1)
207 		UG = 0;			/* We shan't bother if != 0 */
208 
209 	/* get string capabilities */
210 	{
211 		const char	*tsp = ts;
212 		char	**const *measp;
213 
214 		for (measp = meas; *measp != NULL; measp++) {
215 			static char	nm[3] = "xx";
216 			char	*val;
217 
218 			nm[0] = *tsp++;
219 			nm[1] = *tsp++;
220 			val = tgetstr(nm, &termp);
221 			if (val != NULL)
222 				**measp = val;
223 			if (termp > tspace + sizeof(tspace))
224 				tcbad(termname, "too many bytes of termcap strings");
225 		}
226 	}
227 	if (lPC)
228 		PC = *lPC;	/* convert lPC string attribute to char PC */
229 
230 	/* get boolean capabilities */
231 
232 	Hazeltine = tgetflag("hz")==YES;	/* Hazeltine tilde kludge */
233 	NP = tgetflag("NP")==YES;	/* there is No Pad character */
234 	UL = tgetflag("ul")==YES;	/* underscores don't replace chars already on screen */
235 
236 	/* adjust capabilities */
237 
238 	if (tgetflag("km") == YES
239 #  if defined(USE_CTYPE) && !defined(NO_SETLOCALE)
240 	&& strcmp(LcCtype, "C") == 0
241 #  endif
242 	)
243 		MetaKey = YES;	/* has meta-key and default locale */
244 
245 	if (tgetflag("xs") == YES) {
246 		SO = SE = NULL;	/* don't use braindamaged standout mode */
247 		SG = 0;
248 	}
249 
250 	if (SR == NULL && M_SR == NULL)
251 		CS = NULL;	/* don't use scrolling region without way of reverse scrolling */
252 
253 	/* Note: the way termcap/terminfo is defined, we must use *both*
254 	 * IC and IM to insert, but normally only one will be defined.
255 	 * See terminfo(5), under the heading "Insert/Delete Character".
256 	 * Because of this, IM might be defined as a null string.
257 	 */
258 #  ifdef ID_CHAR
259 	if (IM != NULL && *IM == '\0')
260 		IM = NULL;	/* If IM is empty, supress. */
261 
262 	UseIC = (IC != NULL || IM != NULL || M_IC != NULL);
263 	MI = tgetflag("mi")==YES;	/* okay to move while in insert mode */
264 #  endif /* ID_CHAR */
265 
266 	/* strip stupid padding information */
267 	while ('0' <= *NL && *NL <= '9')
268 		NL += 1;
269 	if (*NL == '*')
270 		NL += 1;
271 
272 	if (BC == NULL)
273 		BC = "\b";	/* default back space to BS */
274 
275 	CanScroll = (AL != NULL && DL != NULL) || CS != NULL;
276 
277 	/* calculate lengths */
278 	{
279 		static const struct CapLen	*p;
280 
281 		for (p = CapLenTab; p->cap_var != NULL; p++)
282 			if (*p->cap_var != NULL)
283 				*p->len_var = strlen(*p->cap_var);
284 	}
285 	if (!(CM != NULL || HO != NULL))
286 		tcbad(termname, "JOVE needs either cm or ho termcap/terminfo capability");
287 }
288 
289 /* Put multi-unit or multiple single-unit strings, as appropriate. */
290 
291 private void
tputc(c)292 tputc(c)
293 char	c;
294 {
295 	scr_putchar(c);
296 }
297 
298 void
putmulti(ss,ms,num,lines)299 putmulti(ss, ms, num, lines)
300 const char
301 	*ss,	/* single line */
302 	*ms;	/* multiline */
303 int
304 	num,	/* number of iterations */
305 	lines;	/* lines affected (for padding) */
306 {
307 	if (ms && (num > 1 || !ss)) {
308 		/* use the multi string */
309 		tputs(targ1(ms, num), lines, tputc);
310 	} else {
311 		/* repeatedly use single string */
312 		while (num--)
313 			putpad(ss, lines);
314 	}
315 }
316 
317 /* put a string with padding */
318 
319 void
putpad(str,lines)320 putpad(str, lines)
321 const char	*str;
322 int	lines;
323 {
324 	if (str != NULL)
325 		tputs(str, lines, tputc);
326 }
327 
328 void
dobell(n)329 dobell(n)	/* declared in term.h */
330 int	n;
331 {
332 	while (--n >= 0) {
333 		if (VisBell && VB)
334 			putstr(VB);
335 		else
336 			putpad(BL, 1);
337 	}
338 	flushscreen();
339 }
340 
341 void
clr_page()342 clr_page()
343 {
344 	putpad(CL, LI);
345 }
346 
347 #endif /* TERMCAP */
348