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 } 548