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