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