xref: /original-bsd/usr.bin/window/ttgeneric.c (revision c73c5200)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)ttgeneric.c	3.38 (Berkeley) 05/11/89";
20 #endif /* not lint */
21 
22 #include "ww.h"
23 #include "tt.h"
24 
25 char PC, *BC, *UP;
26 short ospeed;
27 
28 	/* normal frame */
29 short gen_frame[16] = {
30 	' ', '|', '-', '+',
31 	'|', '|', '+', '+',
32 	'-', '+', '-', '+',
33 	'+', '+', '+', '+'
34 };
35 
36 	/* ANSI graphics frame */
37 #define G (WWM_GRP << WWC_MSHIFT)
38 short ansi_frame[16] = {
39 	' ',	'x'|G,	'Q'|G,	'm'|G,
40 	'x'|G,	'x'|G,	'l'|G,	't'|G,
41 	'q'|G,	'j'|G,	'q'|G,	'v'|G,
42 	'k'|G,	'u'|G,	'w'|G,	'n'|G
43 };
44 struct tt_str ansi_AS = {
45 	"\033(0", 3
46 };
47 
48 struct tt_str *gen_PC;
49 struct tt_str *gen_CM;
50 struct tt_str *gen_IM;
51 struct tt_str *gen_IC;
52 struct tt_str *gen_ICn;
53 struct tt_str *gen_IP;
54 struct tt_str *gen_EI;
55 struct tt_str *gen_DC;
56 struct tt_str *gen_DCn;
57 struct tt_str *gen_AL;
58 struct tt_str *gen_ALn;
59 struct tt_str *gen_DL;
60 struct tt_str *gen_DLn;
61 struct tt_str *gen_CE;
62 struct tt_str *gen_CD;
63 struct tt_str *gen_CL;
64 struct tt_str *gen_VS;
65 struct tt_str *gen_VE;
66 struct tt_str *gen_TI;
67 struct tt_str *gen_TE;
68 struct tt_str *gen_SO;
69 struct tt_str *gen_SE;
70 struct tt_str *gen_US;
71 struct tt_str *gen_UE;
72 struct tt_str *gen_LE;
73 struct tt_str *gen_ND;
74 struct tt_str *gen_UP;
75 struct tt_str *gen_DO;
76 struct tt_str *gen_BC;
77 struct tt_str *gen_NL;
78 struct tt_str *gen_CR;
79 struct tt_str *gen_HO;
80 struct tt_str *gen_AS;
81 struct tt_str *gen_AE;
82 struct tt_str *gen_XS;
83 struct tt_str *gen_XE;
84 struct tt_str *gen_SF;
85 struct tt_str *gen_SFn;
86 struct tt_str *gen_SR;
87 struct tt_str *gen_SRn;
88 struct tt_str *gen_CS;
89 char gen_MI;
90 char gen_MS;
91 char gen_AM;
92 char gen_OS;
93 char gen_BS;
94 char gen_DA;
95 char gen_DB;
96 char gen_NS;
97 char gen_XN;
98 int gen_CO;
99 int gen_LI;
100 int gen_UG;
101 int gen_SG;
102 
103 gen_setinsert(new)
104 char new;
105 {
106 	if (new) {
107 		if (gen_IM)
108 			ttxputs(gen_IM);
109 	} else
110 		if (gen_EI)
111 			ttxputs(gen_EI);
112 	tt.tt_insert = new;
113 }
114 
115 gen_setmodes(new)
116 register new;
117 {
118 	register diff;
119 
120 	diff = new ^ tt.tt_modes;
121 	if (diff & WWM_REV) {
122 		if (new & WWM_REV) {
123 			if (gen_SO)
124 				ttxputs(gen_SO);
125 		} else
126 			if (gen_SE)
127 				ttxputs(gen_SE);
128 	}
129 	if (diff & WWM_UL) {
130 		if (new & WWM_UL) {
131 			if (gen_US)
132 				ttxputs(gen_US);
133 		} else
134 			if (gen_UE)
135 				ttxputs(gen_UE);
136 	}
137 	if (diff & WWM_GRP) {
138 		if (new & WWM_GRP) {
139 			if (gen_AS)
140 				ttxputs(gen_AS);
141 		} else
142 			if (gen_AE)
143 				ttxputs(gen_AE);
144 	}
145 	if (diff & WWM_USR) {
146 		if (new & WWM_USR) {
147 			if (gen_XS)
148 				ttxputs(gen_XS);
149 		} else
150 			if (gen_XE)
151 				ttxputs(gen_XE);
152 	}
153 	tt.tt_modes = new;
154 }
155 
156 gen_insline(n)
157 {
158 	if (tt.tt_modes)			/* for concept 100 */
159 		gen_setmodes(0);
160 	if (gen_ALn)
161 		ttpgoto(gen_ALn, 0, n, gen_LI - tt.tt_row);
162 	else
163 		while (--n >= 0)
164 			tttputs(gen_AL, gen_LI - tt.tt_row);
165 }
166 
167 gen_delline(n)
168 {
169 	if (tt.tt_modes)			/* for concept 100 */
170 		gen_setmodes(0);
171 	if (gen_DLn)
172 		ttpgoto(gen_DLn, 0, n, gen_LI - tt.tt_row);
173 	else
174 		while (--n >= 0)
175 			tttputs(gen_DL, gen_LI - tt.tt_row);
176 }
177 
178 gen_putc(c)
179 register char c;
180 {
181 	if (tt.tt_ninsert != tt.tt_insert)
182 		gen_setinsert(tt.tt_ninsert);
183 	if (tt.tt_nmodes != tt.tt_modes)
184 		gen_setmodes(tt.tt_nmodes);
185 	if (tt.tt_insert) {
186 		if (gen_IC)
187 			tttputs(gen_IC, gen_CO - tt.tt_col);
188 		ttputc(c);
189 		if (gen_IP)
190 			tttputs(gen_IP, gen_CO - tt.tt_col);
191 	} else
192 		ttputc(c);
193 	if (++tt.tt_col == gen_CO)
194 		if (gen_XN)
195 			tt.tt_col = tt.tt_row = -10;
196 		else if (gen_AM)
197 			tt.tt_col = 0, tt.tt_row++;
198 		else
199 			tt.tt_col--;
200 }
201 
202 gen_write(p, n)
203 	register char *p;
204 	register n;
205 {
206 	if (tt.tt_ninsert != tt.tt_insert)
207 		gen_setinsert(tt.tt_ninsert);
208 	if (tt.tt_nmodes != tt.tt_modes)
209 		gen_setmodes(tt.tt_nmodes);
210 	if (tt.tt_insert && (gen_IC || gen_IP)) {
211 		while (--n >= 0) {
212 			if (gen_IC)
213 				tttputs(gen_IC, gen_CO - tt.tt_col);
214 			ttputc(*p++);
215 			if (gen_IP)
216 				tttputs(gen_IP, gen_CO - tt.tt_col);
217 			tt.tt_col++;
218 		}
219 	} else {
220 		tt.tt_col += n;
221 		ttwrite(p, n);
222 	}
223 	if (tt.tt_col == gen_CO)
224 		if (gen_XN)
225 			tt.tt_col = tt.tt_row = -10;
226 		else if (gen_AM)
227 			tt.tt_col = 0, tt.tt_row++;
228 		else
229 			tt.tt_col--;
230 }
231 
232 gen_move(row, col)
233 register int row, col;
234 {
235 	if (tt.tt_row == row && tt.tt_col == col)
236 		return;
237 	if (!gen_MI && tt.tt_insert)
238 		gen_setinsert(0);
239 	if (!gen_MS && tt.tt_modes)
240 		gen_setmodes(0);
241 	if (row < tt.tt_scroll_top || row > tt.tt_scroll_bot)
242 		gen_setscroll(tt.tt_nrow - 1, 0);
243 	if (tt.tt_row == row) {
244 		if (col == 0) {
245 			ttxputs(gen_CR);
246 			goto out;
247 		}
248 		if (tt.tt_col == col - 1) {
249 			if (gen_ND) {
250 				ttxputs(gen_ND);
251 				goto out;
252 			}
253 		} else if (tt.tt_col == col + 1) {
254 			if (gen_LE) {
255 				ttxputs(gen_LE);
256 				goto out;
257 			}
258 		}
259 	}
260 	if (tt.tt_col == col) {
261 		if (tt.tt_row == row + 1) {
262 			if (gen_UP) {
263 				ttxputs(gen_UP);
264 				goto out;
265 			}
266 		} else if (tt.tt_row == row - 1) {
267 			ttxputs(gen_DO);
268 			goto out;
269 		}
270 	}
271 	if (gen_HO && col == 0 && row == 0) {
272 		ttxputs(gen_HO);
273 		goto out;
274 	}
275 	tttgoto(gen_CM, col, row);
276 out:
277 	tt.tt_col = col;
278 	tt.tt_row = row;
279 }
280 
281 gen_init()
282 {
283 	if (gen_VS)
284 		ttxputs(gen_VS);
285 	if (gen_TI)
286 		ttxputs(gen_TI);
287 	ttxputs(gen_CL);
288 	tt.tt_col = tt.tt_row = 0;
289 	tt.tt_ninsert = tt.tt_insert = 0;
290 	tt.tt_nmodes = tt.tt_modes = 0;
291 }
292 
293 gen_end()
294 {
295 	if (gen_TE)
296 		ttxputs(gen_TE);
297 	if (gen_VE)
298 		ttxputs(gen_VE);
299 }
300 
301 gen_clreol()
302 {
303 	if (tt.tt_modes)			/* for concept 100 */
304 		gen_setmodes(0);
305 	tttputs(gen_CE, gen_CO - tt.tt_col);
306 }
307 
308 gen_clreos()
309 {
310 	if (tt.tt_modes)			/* for concept 100 */
311 		gen_setmodes(0);
312 	tttputs(gen_CD, gen_LI - tt.tt_row);
313 }
314 
315 gen_clear()
316 {
317 	if (tt.tt_modes)			/* for concept 100 */
318 		gen_setmodes(0);
319 	ttxputs(gen_CL);
320 }
321 
322 gen_inschar(n)
323 {
324 	if (gen_ICn)
325 		ttpgoto(gen_ICn, 0, n, gen_CO - tt.tt_col);
326 	else
327 		while (--n >= 0)
328 			tttputs(gen_IC, gen_CO - tt.tt_col);
329 }
330 
331 gen_delchar(n)
332 {
333 	if (gen_DCn)
334 		ttpgoto(gen_DCn, 0, n, gen_CO - tt.tt_col);
335 	else
336 		while (--n >= 0)
337 			tttputs(gen_DC, gen_CO - tt.tt_col);
338 }
339 
340 gen_scroll_down(n)
341 {
342 	gen_move(tt.tt_scroll_bot, 0);
343 	if (gen_SFn)
344 		ttpgoto(gen_SFn, 0, n, n);
345 	else
346 		while (--n >= 0)
347 			ttxputs(gen_SF);
348 }
349 
350 gen_scroll_up(n)
351 {
352 	gen_move(tt.tt_scroll_top, 0);
353 	if (gen_SRn)
354 		ttpgoto(gen_SRn, 0, n, n);
355 	else
356 		while (--n >= 0)
357 			ttxputs(gen_SR);
358 }
359 
360 gen_setscroll(top, bot)
361 {
362 	tttgoto(gen_CS, bot, top);
363 	tt.tt_scroll_top = top;
364 	tt.tt_scroll_bot = bot;
365 	tt.tt_row = tt.tt_col = -10;
366 }
367 
368 tt_generic()
369 {
370 	gen_PC = tttgetstr("pc");
371 	PC = gen_PC ? *gen_PC->ts_str : 0;
372 	ospeed = wwoldtty.ww_sgttyb.sg_ospeed;
373 
374 	gen_CM = ttxgetstr("cm");		/* may not work */
375 	gen_IM = ttxgetstr("im");
376 	gen_IC = tttgetstr("ic");
377 	gen_ICn = tttgetstr("IC");
378 	gen_IP = tttgetstr("ip");
379 	gen_EI = ttxgetstr("ei");
380 	gen_DC = tttgetstr("dc");
381 	gen_DCn = tttgetstr("DC");
382 	gen_AL = tttgetstr("al");
383 	gen_ALn = tttgetstr("AL");
384 	gen_DL = tttgetstr("dl");
385 	gen_DLn = tttgetstr("DL");
386 	gen_CE = tttgetstr("ce");
387 	gen_CD = tttgetstr("cd");
388 	gen_CL = ttxgetstr("cl");
389 	gen_VS = ttxgetstr("vs");
390 	gen_VE = ttxgetstr("ve");
391 	gen_TI = ttxgetstr("ti");
392 	gen_TE = ttxgetstr("te");
393 	gen_SO = ttxgetstr("so");
394 	gen_SE = ttxgetstr("se");
395 	gen_US = ttxgetstr("us");
396 	gen_UE = ttxgetstr("ue");
397 	gen_LE = ttxgetstr("le");
398 	gen_ND = ttxgetstr("nd");
399 	gen_UP = ttxgetstr("up");
400 	gen_DO = ttxgetstr("do");
401 	gen_BC = ttxgetstr("bc");
402 	gen_NL = ttxgetstr("nl");
403 	gen_CR = ttxgetstr("cr");
404 	gen_HO = ttxgetstr("ho");
405 	gen_AS = ttxgetstr("as");
406 	gen_AE = ttxgetstr("ae");
407 	gen_XS = ttxgetstr("XS");
408 	gen_XE = ttxgetstr("XE");
409 	gen_SF = ttxgetstr("sf");
410 	gen_SFn = ttxgetstr("SF");
411 	gen_SR = ttxgetstr("sr");
412 	gen_SRn = ttxgetstr("SR");
413 	gen_CS = ttxgetstr("cs");
414 	gen_MI = tgetflag("mi");
415 	gen_MS = tgetflag("ms");
416 	gen_AM = tgetflag("am");
417 	gen_OS = tgetflag("os");
418 	gen_BS = tgetflag("bs");
419 	gen_DA = tgetflag("da");
420 	gen_DB = tgetflag("db");
421 	gen_NS = tgetflag("ns");
422 	gen_XN = tgetflag("xn");
423 	gen_CO = tgetnum("co");
424 	gen_LI = tgetnum("li");
425 	gen_UG = tgetnum("ug");
426 	gen_SG = tgetnum("sg");
427 	if (gen_CL == 0 || gen_OS || gen_CM == 0)
428 		return -1;
429 
430 	/*
431 	 * Deal with obsolete termcap fields.
432 	 */
433 	if (gen_LE == 0)
434 		if (gen_BC)
435 			gen_LE = gen_BC;
436 		else if (gen_BS) {
437 			static struct tt_str bc = { "\b", 1 };
438 			gen_BC = &bc;
439 		}
440 	if (gen_NL == 0) {
441 		static struct tt_str nl = { "\n", 1 };
442 		gen_NL = &nl;
443 	}
444 	if (gen_DO == 0)
445 		gen_DO = gen_NL;
446 	if (gen_CR == 0) {
447 		static struct tt_str cr = { "\r", 1 };
448 		gen_CR = &cr;
449 	}
450 	/*
451 	 * Most terminal will scroll with "nl", but very few specify "sf".
452 	 * We shouldn't use "do" here.
453 	 */
454 	if (gen_SF == 0 && !gen_NS)
455 		gen_SF = gen_NL;
456 	BC = gen_LE ? gen_LE->ts_str : 0;
457 	UP = gen_UP ? gen_UP->ts_str : 0;
458 	/*
459 	 * Fix up display attributes that we can't handle, or don't
460 	 * really exist.
461 	 */
462 	if (gen_SG > 0)
463 		gen_SO = 0;
464 	if (gen_UG > 0 || gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0)
465 		gen_US = 0;
466 
467 	if (gen_IM)
468 		tt.tt_setinsert = gen_setinsert;
469 	else if (gen_IC)
470 		tt.tt_inschar = gen_inschar;
471 	if (gen_DC)
472 		tt.tt_delchar = gen_delchar;
473 	if (gen_AL)
474 		tt.tt_insline = gen_insline;
475 	if (gen_DL)
476 		tt.tt_delline = gen_delline;
477 	if (gen_CE)
478 		tt.tt_clreol = gen_clreol;
479 	if (gen_CD)
480 		tt.tt_clreos = gen_clreos;
481 	if (gen_SF)
482 		tt.tt_scroll_down = gen_scroll_down;
483 	/*
484 	 * Don't allow scroll_up if da or db but not cs.
485 	 * See comment in wwscroll.c.
486 	 */
487 	if (gen_SR && (gen_CS || !gen_DA && !gen_DB))
488 		tt.tt_scroll_up = gen_scroll_up;
489 	if (gen_CS)
490 		tt.tt_setscroll = gen_setscroll;
491 	if (gen_SO)
492 		tt.tt_availmodes |= WWM_REV;
493 	if (gen_US)
494 		tt.tt_availmodes |= WWM_UL;
495 	if (gen_AS)
496 		tt.tt_availmodes |= WWM_GRP;
497 	if (gen_XS)
498 		tt.tt_availmodes |= WWM_USR;
499 	tt.tt_wrap = gen_AM;
500 	tt.tt_retain = gen_DB;
501 	tt.tt_ncol = gen_CO;
502 	tt.tt_nrow = gen_LI;
503 	tt.tt_init = gen_init;
504 	tt.tt_end = gen_end;
505 	tt.tt_write = gen_write;
506 	tt.tt_putc = gen_putc;
507 	tt.tt_move = gen_move;
508 	tt.tt_clear = gen_clear;
509 	tt.tt_setmodes = gen_setmodes;
510 	tt.tt_frame = gen_AS && ttstrcmp(gen_AS, &ansi_AS) == 0 ?
511 		ansi_frame : gen_frame;
512 	return 0;
513 }
514