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