Merge from vendor branch LESS:
[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  * @(#)ttgeneric.c      8.1 (Berkeley) 6/6/93
37  * $FreeBSD: src/usr.bin/window/ttgeneric.c,v 1.2.8.1 2001/05/17 09:45:01 obrien Exp $
38  * $DragonFly: src/usr.bin/window/ttgeneric.c,v 1.2 2003/06/17 04:29:34 dillon Exp $
39  */
40
41 #include "ww.h"
42 #include "tt.h"
43
44 char PC, *BC, *UP;
45
46         /* normal frame */
47 short gen_frame[16] = {
48         ' ', '|', '-', '+',
49         '|', '|', '+', '+',
50         '-', '+', '-', '+',
51         '+', '+', '+', '+'
52 };
53
54         /* ANSI graphics frame */
55 #define G (WWM_GRP << WWC_MSHIFT)
56 short ansi_frame[16] = {
57         ' ',    'x'|G,  'Q'|G,  'm'|G,
58         'x'|G,  'x'|G,  'l'|G,  't'|G,
59         'q'|G,  'j'|G,  'q'|G,  'v'|G,
60         'k'|G,  'u'|G,  'w'|G,  'n'|G
61 };
62 struct tt_str ansi_AS = {
63         "\033(0", 3
64 };
65
66 struct tt_str *gen_PC;
67 struct tt_str *gen_CM;
68 struct tt_str *gen_IM;
69 struct tt_str *gen_IC;
70 struct tt_str *gen_ICn;
71 struct tt_str *gen_IP;
72 struct tt_str *gen_EI;
73 struct tt_str *gen_DC;
74 struct tt_str *gen_DCn;
75 struct tt_str *gen_AL;
76 struct tt_str *gen_ALn;
77 struct tt_str *gen_DL;
78 struct tt_str *gen_DLn;
79 struct tt_str *gen_CE;
80 struct tt_str *gen_CD;
81 struct tt_str *gen_CL;
82 struct tt_str *gen_VS;
83 struct tt_str *gen_VE;
84 struct tt_str *gen_TI;
85 struct tt_str *gen_TE;
86 struct tt_str *gen_SO;
87 struct tt_str *gen_SE;
88 struct tt_str *gen_US;
89 struct tt_str *gen_UE;
90 struct tt_str *gen_LE;
91 struct tt_str *gen_ND;
92 struct tt_str *gen_UP;
93 struct tt_str *gen_DO;
94 struct tt_str *gen_BC;
95 struct tt_str *gen_NL;
96 struct tt_str *gen_CR;
97 struct tt_str *gen_HO;
98 struct tt_str *gen_AS;
99 struct tt_str *gen_AE;
100 struct tt_str *gen_XS;
101 struct tt_str *gen_XE;
102 struct tt_str *gen_SF;
103 struct tt_str *gen_SFn;
104 struct tt_str *gen_SR;
105 struct tt_str *gen_SRn;
106 struct tt_str *gen_CS;
107 char gen_MI;
108 char gen_MS;
109 char gen_AM;
110 char gen_OS;
111 char gen_BS;
112 char gen_DA;
113 char gen_DB;
114 char gen_NS;
115 char gen_XN;
116 int gen_CO;
117 int gen_LI;
118 int gen_UG;
119 int gen_SG;
120
121 gen_setinsert(new)
122 char new;
123 {
124         if (new) {
125                 if (gen_IM)
126                         ttxputs(gen_IM);
127         } else
128                 if (gen_EI)
129                         ttxputs(gen_EI);
130         tt.tt_insert = new;
131 }
132
133 gen_setmodes(new)
134 register new;
135 {
136         register diff;
137
138         diff = new ^ tt.tt_modes;
139         if (diff & WWM_REV) {
140                 if (new & WWM_REV) {
141                         if (gen_SO)
142                                 ttxputs(gen_SO);
143                 } else
144                         if (gen_SE)
145                                 ttxputs(gen_SE);
146         }
147         if (diff & WWM_UL) {
148                 if (new & WWM_UL) {
149                         if (gen_US)
150                                 ttxputs(gen_US);
151                 } else
152                         if (gen_UE)
153                                 ttxputs(gen_UE);
154         }
155         if (diff & WWM_GRP) {
156                 if (new & WWM_GRP) {
157                         if (gen_AS)
158                                 ttxputs(gen_AS);
159                 } else
160                         if (gen_AE)
161                                 ttxputs(gen_AE);
162         }
163         if (diff & WWM_USR) {
164                 if (new & WWM_USR) {
165                         if (gen_XS)
166                                 ttxputs(gen_XS);
167                 } else
168                         if (gen_XE)
169                                 ttxputs(gen_XE);
170         }
171         tt.tt_modes = new;
172 }
173
174 gen_insline(n)
175 {
176         if (tt.tt_modes)                        /* for concept 100 */
177                 gen_setmodes(0);
178         if (gen_ALn)
179                 ttpgoto(gen_ALn, 0, n, gen_LI - tt.tt_row);
180         else
181                 while (--n >= 0)
182                         tttputs(gen_AL, gen_LI - tt.tt_row);
183 }
184
185 gen_delline(n)
186 {
187         if (tt.tt_modes)                        /* for concept 100 */
188                 gen_setmodes(0);
189         if (gen_DLn)
190                 ttpgoto(gen_DLn, 0, n, gen_LI - tt.tt_row);
191         else
192                 while (--n >= 0)
193                         tttputs(gen_DL, gen_LI - tt.tt_row);
194 }
195
196 gen_putc(c)
197 register char c;
198 {
199         if (tt.tt_insert)
200                 gen_setinsert(0);
201         if (tt.tt_nmodes != tt.tt_modes)
202                 gen_setmodes(tt.tt_nmodes);
203         ttputc(c);
204         if (++tt.tt_col == gen_CO)
205                 if (gen_XN)
206                         tt.tt_col = tt.tt_row = -10;
207                 else if (gen_AM)
208                         tt.tt_col = 0, tt.tt_row++;
209                 else
210                         tt.tt_col--;
211 }
212
213 gen_write(p, n)
214         register char *p;
215         register n;
216 {
217         if (tt.tt_insert)
218                 gen_setinsert(0);
219         if (tt.tt_nmodes != tt.tt_modes)
220                 gen_setmodes(tt.tt_nmodes);
221         ttwrite(p, n);
222         tt.tt_col += n;
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(0, tt.tt_nrow - 1);
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_start()
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_insert = 0;
290         tt.tt_nmodes = tt.tt_modes = 0;
291 }
292
293 gen_end()
294 {
295         if (tt.tt_insert)
296                 gen_setinsert(0);
297         if (gen_TE)
298                 ttxputs(gen_TE);
299         if (gen_VE)
300                 ttxputs(gen_VE);
301 }
302
303 gen_clreol()
304 {
305         if (tt.tt_modes)                        /* for concept 100 */
306                 gen_setmodes(0);
307         tttputs(gen_CE, gen_CO - tt.tt_col);
308 }
309
310 gen_clreos()
311 {
312         if (tt.tt_modes)                        /* for concept 100 */
313                 gen_setmodes(0);
314         tttputs(gen_CD, gen_LI - tt.tt_row);
315 }
316
317 gen_clear()
318 {
319         if (tt.tt_modes)                        /* for concept 100 */
320                 gen_setmodes(0);
321         ttxputs(gen_CL);
322 }
323
324 gen_inschar(c)
325 register char c;
326 {
327         if (!tt.tt_insert)
328                 gen_setinsert(1);
329         if (tt.tt_nmodes != tt.tt_modes)
330                 gen_setmodes(tt.tt_nmodes);
331         if (gen_IC)
332                 tttputs(gen_IC, gen_CO - tt.tt_col);
333         ttputc(c);
334         if (gen_IP)
335                 tttputs(gen_IP, gen_CO - tt.tt_col);
336         if (++tt.tt_col == gen_CO)
337                 if (gen_XN)
338                         tt.tt_col = tt.tt_row = -10;
339                 else if (gen_AM)
340                         tt.tt_col = 0, tt.tt_row++;
341                 else
342                         tt.tt_col--;
343 }
344
345 gen_insspace(n)
346 {
347         if (gen_ICn)
348                 ttpgoto(gen_ICn, 0, n, gen_CO - tt.tt_col);
349         else
350                 while (--n >= 0)
351                         tttputs(gen_IC, gen_CO - tt.tt_col);
352 }
353
354 gen_delchar(n)
355 {
356         if (gen_DCn)
357                 ttpgoto(gen_DCn, 0, n, gen_CO - tt.tt_col);
358         else
359                 while (--n >= 0)
360                         tttputs(gen_DC, gen_CO - tt.tt_col);
361 }
362
363 gen_scroll_down(n)
364 {
365         gen_move(tt.tt_scroll_bot, 0);
366         if (gen_SFn)
367                 ttpgoto(gen_SFn, 0, n, n);
368         else
369                 while (--n >= 0)
370                         ttxputs(gen_SF);
371 }
372
373 gen_scroll_up(n)
374 {
375         gen_move(tt.tt_scroll_top, 0);
376         if (gen_SRn)
377                 ttpgoto(gen_SRn, 0, n, n);
378         else
379                 while (--n >= 0)
380                         ttxputs(gen_SR);
381 }
382
383 gen_setscroll(top, bot)
384 {
385         tttgoto(gen_CS, bot, top);
386         tt.tt_scroll_top = top;
387         tt.tt_scroll_bot = bot;
388         tt.tt_row = tt.tt_col = -10;
389 }
390
391 tt_generic()
392 {
393         gen_PC = tttgetstr("pc");
394         PC = gen_PC ? *gen_PC->ts_str : 0;
395
396         gen_CM = ttxgetstr("cm");               /* may not work */
397         gen_IM = ttxgetstr("im");
398         gen_IC = tttgetstr("ic");
399         gen_ICn = tttgetstr("IC");
400         gen_IP = tttgetstr("ip");
401         gen_EI = ttxgetstr("ei");
402         gen_DC = tttgetstr("dc");
403         gen_DCn = tttgetstr("DC");
404         gen_AL = tttgetstr("al");
405         gen_ALn = tttgetstr("AL");
406         gen_DL = tttgetstr("dl");
407         gen_DLn = tttgetstr("DL");
408         gen_CE = tttgetstr("ce");
409         gen_CD = tttgetstr("cd");
410         gen_CL = ttxgetstr("cl");
411         gen_VS = ttxgetstr("vs");
412         gen_VE = ttxgetstr("ve");
413         gen_TI = ttxgetstr("ti");
414         gen_TE = ttxgetstr("te");
415         gen_SO = ttxgetstr("so");
416         gen_SE = ttxgetstr("se");
417         gen_US = ttxgetstr("us");
418         gen_UE = ttxgetstr("ue");
419         gen_LE = ttxgetstr("le");
420         gen_ND = ttxgetstr("nd");
421         gen_UP = ttxgetstr("up");
422         gen_DO = ttxgetstr("do");
423         gen_BC = ttxgetstr("bc");
424         gen_NL = ttxgetstr("nl");
425         gen_CR = ttxgetstr("cr");
426         gen_HO = ttxgetstr("ho");
427         gen_AS = ttxgetstr("as");
428         gen_AE = ttxgetstr("ae");
429         gen_XS = ttxgetstr("XS");
430         gen_XE = ttxgetstr("XE");
431         gen_SF = ttxgetstr("sf");
432         gen_SFn = ttxgetstr("SF");
433         gen_SR = ttxgetstr("sr");
434         gen_SRn = ttxgetstr("SR");
435         gen_CS = ttxgetstr("cs");
436         gen_MI = tgetflag("mi");
437         gen_MS = tgetflag("ms");
438         gen_AM = tgetflag("am");
439         gen_OS = tgetflag("os");
440         gen_BS = tgetflag("bs");
441         gen_DA = tgetflag("da");
442         gen_DB = tgetflag("db");
443         gen_NS = tgetflag("ns");
444         gen_XN = tgetflag("xn");
445         gen_CO = tgetnum("co");
446         gen_LI = tgetnum("li");
447         gen_UG = tgetnum("ug");
448         gen_SG = tgetnum("sg");
449         if (gen_CL == 0 || gen_OS || gen_CM == 0)
450                 return -1;
451
452         /*
453          * Deal with obsolete termcap fields.
454          */
455         if (gen_LE == 0)
456                 if (gen_BC)
457                         gen_LE = gen_BC;
458                 else if (gen_BS) {
459                         static struct tt_str bc = { "\b", 1 };
460                         gen_BC = &bc;
461                 }
462         if (gen_NL == 0) {
463                 static struct tt_str nl = { "\n", 1 };
464                 gen_NL = &nl;
465         }
466         if (gen_DO == 0)
467                 gen_DO = gen_NL;
468         if (gen_CR == 0) {
469                 static struct tt_str cr = { "\r", 1 };
470                 gen_CR = &cr;
471         }
472         /*
473          * Most terminal will scroll with "nl", but very few specify "sf".
474          * We shouldn't use "do" here.
475          */
476         if (gen_SF == 0 && !gen_NS)
477                 gen_SF = gen_NL;
478         BC = gen_LE ? gen_LE->ts_str : 0;
479         UP = gen_UP ? gen_UP->ts_str : 0;
480         /*
481          * Fix up display attributes that we can't handle, or don't
482          * really exist.
483          */
484         if (gen_SG > 0)
485                 gen_SO = 0;
486         if (gen_UG > 0 || gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0)
487                 gen_US = 0;
488
489         if (gen_IM && gen_IM->ts_n == 0) {
490                 free((char *) gen_IM);
491                 gen_IM = 0;
492         }
493         if (gen_EI && gen_EI->ts_n == 0) {
494                 free((char *) gen_EI);
495                 gen_EI = 0;
496         }
497         if (gen_IC && gen_IC->ts_n == 0) {
498                 free((char *) gen_IC);
499                 gen_IC = 0;
500         }
501         if (gen_IM)
502                 tt.tt_inschar = gen_inschar;
503         else if (gen_IC)
504                 tt.tt_insspace = gen_insspace;
505         if (gen_DC)
506                 tt.tt_delchar = gen_delchar;
507         if (gen_AL)
508                 tt.tt_insline = gen_insline;
509         if (gen_DL)
510                 tt.tt_delline = gen_delline;
511         if (gen_CE)
512                 tt.tt_clreol = gen_clreol;
513         if (gen_CD)
514                 tt.tt_clreos = gen_clreos;
515         if (gen_SF)
516                 tt.tt_scroll_down = gen_scroll_down;
517         /*
518          * Don't allow scroll_up if da or db but not cs.
519          * See comment in wwscroll.c.
520          */
521         if (gen_SR && (gen_CS || !gen_DA && !gen_DB))
522                 tt.tt_scroll_up = gen_scroll_up;
523         if (gen_CS)
524                 tt.tt_setscroll = gen_setscroll;
525         if (gen_SO)
526                 tt.tt_availmodes |= WWM_REV;
527         if (gen_US)
528                 tt.tt_availmodes |= WWM_UL;
529         if (gen_AS)
530                 tt.tt_availmodes |= WWM_GRP;
531         if (gen_XS)
532                 tt.tt_availmodes |= WWM_USR;
533         tt.tt_wrap = gen_AM;
534         tt.tt_retain = gen_DB;
535         tt.tt_ncol = gen_CO;
536         tt.tt_nrow = gen_LI;
537         tt.tt_start = gen_start;
538         tt.tt_end = gen_end;
539         tt.tt_write = gen_write;
540         tt.tt_putc = gen_putc;
541         tt.tt_move = gen_move;
542         tt.tt_clear = gen_clear;
543         tt.tt_setmodes = gen_setmodes;
544         tt.tt_frame = gen_AS && ttstrcmp(gen_AS, &ansi_AS) == 0 ?
545                 ansi_frame : gen_frame;
546         return 0;
547 }