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