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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 == 0 || gen_OS || gen_CM == 0) 492 return -1; 493 494 /* 495 * Deal with obsolete termcap fields. 496 */ 497 if (gen_LE == 0) { 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 == 0) { 506 static struct tt_str nl = { "\n", 1 }; 507 gen_NL = &nl; 508 } 509 if (gen_DO == 0) 510 gen_DO = gen_NL; 511 if (gen_CR == 0) { 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 == 0 && !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 = 0; 529 if (gen_UG > 0 || (gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0)) 530 gen_US = 0; 531 532 if (gen_IM && gen_IM->ts_n == 0) { 533 free((char *) gen_IM); 534 gen_IM = 0; 535 } 536 if (gen_EI && gen_EI->ts_n == 0) { 537 free((char *) gen_EI); 538 gen_EI = 0; 539 } 540 if (gen_IC && gen_IC->ts_n == 0) { 541 free((char *) gen_IC); 542 gen_IC = 0; 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