xref: /dragonfly/usr.bin/window/ttgeneric.c (revision a632cd2d33eae3cdf365948061576a303057c733)
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
gen_setinsert(char new)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
gen_setmodes(int new)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
gen_insline(int n)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
gen_delline(int n)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
gen_putc(char c)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
gen_write(const char * p,int n)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
gen_move(int row,int col)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
gen_start(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
gen_end(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
gen_clreol(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
gen_clreos(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
gen_clear(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
gen_inschar(char c)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
gen_insspace(int n)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
gen_delchar(int n)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
gen_scroll_down(int n)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
gen_scroll_up(int n)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
gen_setscroll(int top,int bot)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
tt_generic(void)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 == NULL || gen_OS || gen_CM == NULL)
492                     return -1;
493 
494           /*
495            * Deal with obsolete termcap fields.
496            */
497           if (gen_LE == NULL) {
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 == NULL) {
506                     static struct tt_str nl = { "\n", 1 };
507                     gen_NL = &nl;
508           }
509           if (gen_DO == NULL)
510                     gen_DO = gen_NL;
511           if (gen_CR == NULL) {
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 == NULL && !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 = NULL;
529           if (gen_UG > 0 || (gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0))
530                     gen_US = NULL;
531 
532           if (gen_IM && gen_IM->ts_n == 0) {
533                     free((char *) gen_IM);
534                     gen_IM = NULL;
535           }
536           if (gen_EI && gen_EI->ts_n == 0) {
537                     free((char *) gen_EI);
538                     gen_EI = NULL;
539           }
540           if (gen_IC && gen_IC->ts_n == 0) {
541                     free((char *) gen_IC);
542                     gen_IC = NULL;
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