1 /**************************************************************************** 2 * Copyright 2018-2019,2020 Thomas E. Dickey * 3 * Copyright 2008-2016,2017 Free Software Foundation, Inc. * 4 * * 5 * Permission is hereby granted, free of charge, to any person obtaining a * 6 * copy of this software and associated documentation files (the * 7 * "Software"), to deal in the Software without restriction, including * 8 * without limitation the rights to use, copy, modify, merge, publish, * 9 * distribute, distribute with modifications, sublicense, and/or sell * 10 * copies of the Software, and to permit persons to whom the Software is * 11 * furnished to do so, subject to the following conditions: * 12 * * 13 * The above copyright notice and this permission notice shall be included * 14 * in all copies or substantial portions of the Software. * 15 * * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 23 * * 24 * Except as contained in this notice, the name(s) of the above copyright * 25 * holders shall not be used in advertising or otherwise to promote the * 26 * sale, use or other dealings in this Software without prior written * 27 * authorization. * 28 ****************************************************************************/ 29 30 /**************************************************************************** 31 * Author: Juergen Pfeifer * 32 * and: Thomas E. Dickey * 33 ****************************************************************************/ 34 35 #include <curses.priv.h> 36 #define CUR TerminalType((TERMINAL*)TCB). 37 #include <tic.h> 38 #include <termcap.h> /* ospeed */ 39 40 #if HAVE_NANOSLEEP 41 #include <time.h> 42 #if HAVE_SYS_TIME_H 43 #include <sys/time.h> /* needed for MacOS X DP3 */ 44 #endif 45 #endif 46 47 #if HAVE_SIZECHANGE 48 # if !defined(sun) || !TERMIOS 49 # if HAVE_SYS_IOCTL_H 50 # include <sys/ioctl.h> 51 # endif 52 # endif 53 #endif 54 55 MODULE_ID("$Id: tinfo_driver.c,v 1.67 2020/02/02 23:34:34 tom Exp $") 56 57 /* 58 * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, 59 * Solaris, IRIX) define TIOCGWINSZ and struct winsize. 60 */ 61 #ifdef TIOCGSIZE 62 # define IOCTL_WINSIZE TIOCGSIZE 63 # define STRUCT_WINSIZE struct ttysize 64 # define WINSIZE_ROWS(n) (int)n.ts_lines 65 # define WINSIZE_COLS(n) (int)n.ts_cols 66 #else 67 # ifdef TIOCGWINSZ 68 # define IOCTL_WINSIZE TIOCGWINSZ 69 # define STRUCT_WINSIZE struct winsize 70 # define WINSIZE_ROWS(n) (int)n.ws_row 71 # define WINSIZE_COLS(n) (int)n.ws_col 72 # endif 73 #endif 74 75 /* 76 * These should be screen structure members. They need to be globals for 77 * historical reasons. So we assign them in start_color() and also in 78 * set_term()'s screen-switching logic. 79 */ 80 #if USE_REENTRANT 81 NCURSES_EXPORT(int) 82 NCURSES_PUBLIC_VAR(COLOR_PAIRS) (void) 83 { 84 return CURRENT_SCREEN ? CURRENT_SCREEN->_pair_count : -1; 85 } 86 NCURSES_EXPORT(int) 87 NCURSES_PUBLIC_VAR(COLORS) (void) 88 { 89 return CURRENT_SCREEN ? CURRENT_SCREEN->_color_count : -1; 90 } 91 #else 92 NCURSES_EXPORT_VAR(int) COLOR_PAIRS = 0; 93 NCURSES_EXPORT_VAR(int) COLORS = 0; 94 #endif 95 96 #define TCBMAGIC NCDRV_MAGIC(NCDRV_TINFO) 97 #define AssertTCB() assert(TCB!=0 && TCB->magic==TCBMAGIC) 98 #define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp 99 100 /* 101 * This routine needs to do all the work to make curscr look 102 * like newscr. 103 */ 104 static int 105 drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB) 106 { 107 AssertTCB(); 108 return TINFO_DOUPDATE(TCB->csp); 109 } 110 111 static const char * 112 drv_Name(TERMINAL_CONTROL_BLOCK * TCB) 113 { 114 (void) TCB; 115 return "tinfo"; 116 } 117 118 static void 119 get_baudrate(TERMINAL *termp) 120 { 121 int my_ospeed; 122 int result; 123 if (GET_TTY(termp->Filedes, &termp->Nttyb) == OK) { 124 #ifdef TERMIOS 125 termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS); 126 #else 127 termp->Nttyb.sg_flags &= (unsigned) (~XTABS); 128 #endif 129 } 130 #ifdef USE_OLD_TTY 131 result = (int) cfgetospeed(&(termp->Nttyb)); 132 my_ospeed = (NCURSES_OSPEED) _nc_ospeed(result); 133 #else /* !USE_OLD_TTY */ 134 #ifdef TERMIOS 135 my_ospeed = (NCURSES_OSPEED) cfgetospeed(&(termp->Nttyb)); 136 #else 137 my_ospeed = (NCURSES_OSPEED) termp->Nttyb.sg_ospeed; 138 #endif 139 result = _nc_baudrate(my_ospeed); 140 #endif 141 termp->_baudrate = result; 142 ospeed = (NCURSES_OSPEED) my_ospeed; 143 } 144 145 #undef SETUP_FAIL 146 #define SETUP_FAIL FALSE 147 148 #define NO_COPY {} 149 150 static bool 151 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret) 152 { 153 bool result = FALSE; 154 int status; 155 TERMINAL *termp; 156 SCREEN *sp; 157 158 START_TRACE(); 159 T((T_CALLED("tinfo::drv_CanHandle(%p)"), (void *) TCB)); 160 161 assert(TCB != 0 && tname != 0); 162 termp = (TERMINAL *) TCB; 163 sp = TCB->csp; 164 TCB->magic = TCBMAGIC; 165 166 #if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP) 167 status = _nc_setup_tinfo(tname, &TerminalType(termp)); 168 T(("_nc_setup_tinfo returns %d", status)); 169 #else 170 T(("no database available")); 171 status = TGETENT_NO; 172 #endif 173 174 /* try fallback list if entry on disk */ 175 if (status != TGETENT_YES) { 176 const TERMTYPE2 *fallback = _nc_fallback2(tname); 177 178 if (fallback) { 179 T(("found fallback entry")); 180 TerminalType(termp) = *fallback; 181 status = TGETENT_YES; 182 } 183 } 184 185 if (status != TGETENT_YES) { 186 NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx termp); 187 if (status == TGETENT_ERR) { 188 ret_error0(status, "terminals database is inaccessible\n"); 189 } else if (status == TGETENT_NO) { 190 ret_error1(status, "unknown terminal type.\n", 191 tname, NO_COPY); 192 } else { 193 ret_error0(status, "unexpected return-code\n"); 194 } 195 } 196 result = TRUE; 197 #if NCURSES_EXT_NUMBERS 198 _nc_export_termtype2(&termp->type, &TerminalType(termp)); 199 #endif 200 #if !USE_REENTRANT 201 save_ttytype(termp); 202 #endif 203 204 if (command_character) 205 _nc_tinfo_cmdch(termp, *command_character); 206 207 /* 208 * If an application calls setupterm() rather than initscr() or 209 * newterm(), we will not have the def_prog_mode() call in 210 * _nc_setupscreen(). Do it now anyway, so we can initialize the 211 * baudrate. 212 */ 213 if (sp == 0 && NC_ISATTY(termp->Filedes)) { 214 get_baudrate(termp); 215 } 216 #if NCURSES_EXT_NUMBERS 217 #define cleanup_termtype() \ 218 _nc_free_termtype2(&TerminalType(termp)); \ 219 _nc_free_termtype(&termp->type) 220 #else 221 #define cleanup_termtype() \ 222 _nc_free_termtype2(&TerminalType(termp)) 223 #endif 224 225 if (generic_type) { 226 /* 227 * BSD 4.3's termcap contains mis-typed "gn" for wy99. Do a sanity 228 * check before giving up. 229 */ 230 if ((VALID_STRING(cursor_address) 231 || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home))) 232 && VALID_STRING(clear_screen)) { 233 cleanup_termtype(); 234 ret_error1(TGETENT_YES, "terminal is not really generic.\n", 235 tname, NO_COPY); 236 } else { 237 cleanup_termtype(); 238 ret_error1(TGETENT_NO, "I need something more specific.\n", 239 tname, NO_COPY); 240 } 241 } 242 if (hard_copy) { 243 cleanup_termtype(); 244 ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", 245 tname, NO_COPY); 246 } 247 248 returnBool(result); 249 } 250 251 static int 252 drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, int beepFlag) 253 { 254 SCREEN *sp; 255 int res = ERR; 256 257 AssertTCB(); 258 SetSP(); 259 260 /* FIXME: should make sure that we are not in altchar mode */ 261 if (beepFlag) { 262 if (bell) { 263 res = NCURSES_PUTP2("bell", bell); 264 NCURSES_SP_NAME(_nc_flush) (sp); 265 } else if (flash_screen) { 266 res = NCURSES_PUTP2("flash_screen", flash_screen); 267 NCURSES_SP_NAME(_nc_flush) (sp); 268 } 269 } else { 270 if (flash_screen) { 271 res = NCURSES_PUTP2("flash_screen", flash_screen); 272 NCURSES_SP_NAME(_nc_flush) (sp); 273 } else if (bell) { 274 res = NCURSES_PUTP2("bell", bell); 275 NCURSES_SP_NAME(_nc_flush) (sp); 276 } 277 } 278 return res; 279 } 280 281 /* 282 * SVr4 curses is known to interchange color codes (1,4) and (3,6), possibly 283 * to maintain compatibility with a pre-ANSI scheme. The same scheme is 284 * also used in the FreeBSD syscons. 285 */ 286 static int 287 toggled_colors(int c) 288 { 289 if (c < 16) { 290 static const int table[] = 291 {0, 4, 2, 6, 1, 5, 3, 7, 292 8, 12, 10, 14, 9, 13, 11, 15}; 293 c = table[c]; 294 } 295 return c; 296 } 297 298 static int 299 drv_print(TERMINAL_CONTROL_BLOCK * TCB, char *data, int len) 300 { 301 SCREEN *sp; 302 303 AssertTCB(); 304 SetSP(); 305 #if NCURSES_EXT_FUNCS 306 return NCURSES_SP_NAME(mcprint) (TCB->csp, data, len); 307 #else 308 return ERR; 309 #endif 310 } 311 312 static int 313 drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB, int fg, int bg) 314 { 315 SCREEN *sp; 316 int code = ERR; 317 318 AssertTCB(); 319 SetSP(); 320 321 if (sp != 0 && orig_pair && orig_colors && (initialize_pair != 0)) { 322 #if NCURSES_EXT_FUNCS 323 sp->_default_color = isDefaultColor(fg) || isDefaultColor(bg); 324 sp->_has_sgr_39_49 = (NCURSES_SP_NAME(tigetflag) (NCURSES_SP_ARGx 325 "AX") 326 == TRUE); 327 sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg; 328 sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg; 329 if (sp->_color_pairs != 0) { 330 bool save = sp->_default_color; 331 sp->_default_color = TRUE; 332 NCURSES_SP_NAME(init_pair) (NCURSES_SP_ARGx 333 0, 334 (short)fg, 335 (short)bg); 336 sp->_default_color = save; 337 } 338 #endif 339 code = OK; 340 } 341 return (code); 342 } 343 344 static void 345 drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB, 346 int fore, 347 int color, 348 NCURSES_SP_OUTC outc) 349 { 350 SCREEN *sp; 351 352 AssertTCB(); 353 SetSP(); 354 355 if (fore) { 356 if (set_a_foreground) { 357 TPUTS_TRACE("set_a_foreground"); 358 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 359 TPARM_1(set_a_foreground, color), 1, outc); 360 } else { 361 TPUTS_TRACE("set_foreground"); 362 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 363 TPARM_1(set_foreground, 364 toggled_colors(color)), 1, outc); 365 } 366 } else { 367 if (set_a_background) { 368 TPUTS_TRACE("set_a_background"); 369 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 370 TPARM_1(set_a_background, color), 1, outc); 371 } else { 372 TPUTS_TRACE("set_background"); 373 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 374 TPARM_1(set_background, 375 toggled_colors(color)), 1, outc); 376 } 377 } 378 } 379 380 static bool 381 drv_rescol(TERMINAL_CONTROL_BLOCK * TCB) 382 { 383 bool result = FALSE; 384 SCREEN *sp; 385 386 AssertTCB(); 387 SetSP(); 388 389 if (orig_pair != 0) { 390 NCURSES_PUTP2("orig_pair", orig_pair); 391 result = TRUE; 392 } 393 return result; 394 } 395 396 static bool 397 drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB) 398 { 399 int result = FALSE; 400 SCREEN *sp; 401 402 AssertTCB(); 403 SetSP(); 404 405 if (orig_colors != 0) { 406 NCURSES_PUTP2("orig_colors", orig_colors); 407 result = TRUE; 408 } 409 return result; 410 } 411 412 static int 413 drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) 414 { 415 SCREEN *sp; 416 bool useEnv = TRUE; 417 bool useTioctl = TRUE; 418 419 AssertTCB(); 420 sp = TCB->csp; /* can be null here */ 421 422 if (sp) { 423 useEnv = sp->_use_env; 424 useTioctl = sp->use_tioctl; 425 } else { 426 useEnv = _nc_prescreen.use_env; 427 useTioctl = _nc_prescreen.use_tioctl; 428 } 429 430 /* figure out the size of the screen */ 431 T(("screen size: terminfo lines = %d columns = %d", lines, columns)); 432 433 *linep = (int) lines; 434 *colp = (int) columns; 435 436 if (useEnv || useTioctl) { 437 int value; 438 439 #ifdef __EMX__ 440 { 441 int screendata[2]; 442 _scrsize(screendata); 443 *colp = screendata[0]; 444 *linep = ((sp != 0 && sp->_filtered) 445 ? 1 446 : screendata[1]); 447 T(("EMX screen size: environment LINES = %d COLUMNS = %d", 448 *linep, *colp)); 449 } 450 #endif 451 #if HAVE_SIZECHANGE 452 /* try asking the OS */ 453 { 454 TERMINAL *termp = (TERMINAL *) TCB; 455 if (NC_ISATTY(termp->Filedes)) { 456 STRUCT_WINSIZE size; 457 458 errno = 0; 459 do { 460 if (ioctl(termp->Filedes, IOCTL_WINSIZE, &size) >= 0) { 461 *linep = ((sp != 0 && sp->_filtered) 462 ? 1 463 : WINSIZE_ROWS(size)); 464 *colp = WINSIZE_COLS(size); 465 T(("SYS screen size: environment LINES = %d COLUMNS = %d", 466 *linep, *colp)); 467 break; 468 } 469 } while 470 (errno == EINTR); 471 } 472 } 473 #endif /* HAVE_SIZECHANGE */ 474 475 if (useEnv) { 476 if (useTioctl) { 477 /* 478 * If environment variables are used, update them. 479 */ 480 if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) { 481 _nc_setenv_num("LINES", *linep); 482 } 483 if (_nc_getenv_num("COLUMNS") > 0) { 484 _nc_setenv_num("COLUMNS", *colp); 485 } 486 } 487 488 /* 489 * Finally, look for environment variables. 490 * 491 * Solaris lets users override either dimension with an environment 492 * variable. 493 */ 494 if ((value = _nc_getenv_num("LINES")) > 0) { 495 *linep = value; 496 T(("screen size: environment LINES = %d", *linep)); 497 } 498 if ((value = _nc_getenv_num("COLUMNS")) > 0) { 499 *colp = value; 500 T(("screen size: environment COLUMNS = %d", *colp)); 501 } 502 } 503 504 /* if we can't get dynamic info about the size, use static */ 505 if (*linep <= 0) { 506 *linep = (int) lines; 507 } 508 if (*colp <= 0) { 509 *colp = (int) columns; 510 } 511 512 /* the ultimate fallback, assume fixed 24x80 size */ 513 if (*linep <= 0) { 514 *linep = 24; 515 } 516 if (*colp <= 0) { 517 *colp = 80; 518 } 519 520 /* 521 * Put the derived values back in the screen-size caps, so 522 * tigetnum() and tgetnum() will do the right thing. 523 */ 524 lines = (short) (*linep); 525 columns = (short) (*colp); 526 } 527 528 T(("screen size is %dx%d", *linep, *colp)); 529 return OK; 530 } 531 532 static int 533 drv_getsize(TERMINAL_CONTROL_BLOCK * TCB, int *l, int *c) 534 { 535 AssertTCB(); 536 assert(l != 0 && c != 0); 537 *l = lines; 538 *c = columns; 539 return OK; 540 } 541 542 static int 543 drv_setsize(TERMINAL_CONTROL_BLOCK * TCB, int l, int c) 544 { 545 AssertTCB(); 546 lines = (short) l; 547 columns = (short) c; 548 return OK; 549 } 550 551 static int 552 drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf) 553 { 554 SCREEN *sp = TCB->csp; 555 TERMINAL *_term = (TERMINAL *) TCB; 556 int result = OK; 557 558 AssertTCB(); 559 if (setFlag) { 560 for (;;) { 561 if (SET_TTY(_term->Filedes, buf) != 0) { 562 if (errno == EINTR) 563 continue; 564 if (errno == ENOTTY) { 565 if (sp) 566 sp->_notty = TRUE; 567 } 568 result = ERR; 569 } 570 break; 571 } 572 } else { 573 for (;;) { 574 if (GET_TTY(_term->Filedes, buf) != 0) { 575 if (errno == EINTR) 576 continue; 577 result = ERR; 578 } 579 break; 580 } 581 } 582 return result; 583 } 584 585 static int 586 drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag) 587 { 588 SCREEN *sp; 589 TERMINAL *_term = (TERMINAL *) TCB; 590 int code = ERR; 591 592 AssertTCB(); 593 sp = TCB->csp; 594 595 if (progFlag) /* prog mode */ 596 { 597 if (defFlag) { 598 /* def_prog_mode */ 599 /* 600 * Turn off the XTABS bit in the tty structure if it was on. 601 */ 602 if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) { 603 #ifdef TERMIOS 604 _term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS; 605 #else 606 _term->Nttyb.sg_flags &= (unsigned) ~XTABS; 607 #endif 608 code = OK; 609 } 610 } else { 611 /* reset_prog_mode */ 612 if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) { 613 if (sp) { 614 if (sp->_keypad_on) 615 _nc_keypad(sp, TRUE); 616 } 617 code = OK; 618 } 619 } 620 } else { /* shell mode */ 621 if (defFlag) { 622 /* def_shell_mode */ 623 /* 624 * If XTABS was on, remove the tab and backtab capabilities. 625 */ 626 if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) { 627 #ifdef TERMIOS 628 if (_term->Ottyb.c_oflag & OFLAGS_TABS) 629 tab = back_tab = NULL; 630 #else 631 if (_term->Ottyb.sg_flags & XTABS) 632 tab = back_tab = NULL; 633 #endif 634 code = OK; 635 } 636 } else { 637 /* reset_shell_mode */ 638 if (sp) { 639 _nc_keypad(sp, FALSE); 640 NCURSES_SP_NAME(_nc_flush) (sp); 641 } 642 code = drv_sgmode(TCB, TRUE, &(_term->Ottyb)); 643 } 644 } 645 return (code); 646 } 647 648 static void 649 drv_wrap(SCREEN *sp) 650 { 651 if (sp) { 652 sp->_mouse_wrap(sp); 653 NCURSES_SP_NAME(_nc_screen_wrap) (sp); 654 NCURSES_SP_NAME(_nc_mvcur_wrap) (sp); /* wrap up cursor addressing */ 655 } 656 } 657 658 static void 659 drv_release(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED) 660 { 661 } 662 663 # define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) 664 665 static void 666 drv_screen_init(SCREEN *sp) 667 { 668 TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp); 669 670 AssertTCB(); 671 672 /* 673 * Check for mismatched graphic-rendition capabilities. Most SVr4 674 * terminfo trees contain entries that have rmul or rmso equated to 675 * sgr0 (Solaris curses copes with those entries). We do this only 676 * for curses, since many termcap applications assume that 677 * smso/rmso and smul/rmul are paired, and will not function 678 * properly if we remove rmso or rmul. Curses applications 679 * shouldn't be looking at this detail. 680 */ 681 sp->_use_rmso = SGR0_TEST(exit_standout_mode); 682 sp->_use_rmul = SGR0_TEST(exit_underline_mode); 683 684 /* 685 * Check whether we can optimize scrolling under dumb terminals in 686 * case we do not have any of these capabilities, scrolling 687 * optimization will be useless. 688 */ 689 sp->_scrolling = ((scroll_forward && scroll_reverse) || 690 ((parm_rindex || 691 parm_insert_line || 692 insert_line) && 693 (parm_index || 694 parm_delete_line || 695 delete_line))); 696 697 NCURSES_SP_NAME(baudrate) (sp); 698 699 NCURSES_SP_NAME(_nc_mvcur_init) (sp); 700 /* initialize terminal to a sane state */ 701 NCURSES_SP_NAME(_nc_screen_init) (sp); 702 } 703 704 static void 705 drv_init(TERMINAL_CONTROL_BLOCK * TCB) 706 { 707 TERMINAL *trm; 708 709 AssertTCB(); 710 711 trm = (TERMINAL *) TCB; 712 713 TCB->info.initcolor = VALID_STRING(initialize_color); 714 TCB->info.canchange = can_change; 715 TCB->info.hascolor = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) 716 && (((set_foreground != NULL) 717 && (set_background != NULL)) 718 || ((set_a_foreground != NULL) 719 && (set_a_background != NULL)) 720 || set_color_pair)) ? TRUE : FALSE); 721 722 TCB->info.caninit = !(exit_ca_mode && non_rev_rmcup); 723 724 TCB->info.maxpairs = VALID_NUMERIC(max_pairs) ? max_pairs : 0; 725 TCB->info.maxcolors = VALID_NUMERIC(max_colors) ? max_colors : 0; 726 TCB->info.numlabels = VALID_NUMERIC(num_labels) ? num_labels : 0; 727 TCB->info.labelwidth = VALID_NUMERIC(label_width) ? label_width : 0; 728 TCB->info.labelheight = VALID_NUMERIC(label_height) ? label_height : 0; 729 TCB->info.nocolorvideo = VALID_NUMERIC(no_color_video) ? no_color_video 730 : 0; 731 TCB->info.tabsize = VALID_NUMERIC(init_tabs) ? (int) init_tabs : 8; 732 733 TCB->info.defaultPalette = hue_lightness_saturation ? _nc_hls_palette : _nc_cga_palette; 734 735 /* 736 * If an application calls setupterm() rather than initscr() or 737 * newterm(), we will not have the def_prog_mode() call in 738 * _nc_setupscreen(). Do it now anyway, so we can initialize the 739 * baudrate. 740 */ 741 if (NC_ISATTY(trm->Filedes)) { 742 TCB->drv->td_mode(TCB, TRUE, TRUE); 743 } 744 } 745 746 #define MAX_PALETTE 8 747 #define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE) 748 749 static void 750 drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, int pair, int f, int b) 751 { 752 SCREEN *sp; 753 754 AssertTCB(); 755 SetSP(); 756 757 if ((initialize_pair != NULL) && InPalette(f) && InPalette(b)) { 758 const color_t *tp = InfoOf(sp).defaultPalette; 759 760 TR(TRACE_ATTRS, 761 ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)", 762 pair, 763 tp[f].red, tp[f].green, tp[f].blue, 764 tp[b].red, tp[b].green, tp[b].blue)); 765 766 NCURSES_PUTP2("initialize_pair", 767 TPARM_7(initialize_pair, 768 pair, 769 tp[f].red, tp[f].green, tp[f].blue, 770 tp[b].red, tp[b].green, tp[b].blue)); 771 } 772 } 773 774 static int 775 default_fg(SCREEN *sp) 776 { 777 #if NCURSES_EXT_FUNCS 778 return (sp != 0) ? sp->_default_fg : COLOR_WHITE; 779 #else 780 return COLOR_WHITE; 781 #endif 782 } 783 784 static int 785 default_bg(SCREEN *sp) 786 { 787 #if NCURSES_EXT_FUNCS 788 return sp != 0 ? sp->_default_bg : COLOR_BLACK; 789 #else 790 return COLOR_BLACK; 791 #endif 792 } 793 794 static void 795 drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB, 796 int color, int r, int g, int b) 797 { 798 SCREEN *sp = TCB->csp; 799 800 AssertTCB(); 801 if (initialize_color != NULL) { 802 NCURSES_PUTP2("initialize_color", 803 TPARM_4(initialize_color, color, r, g, b)); 804 } 805 } 806 807 static void 808 drv_do_color(TERMINAL_CONTROL_BLOCK * TCB, 809 int old_pair, 810 int pair, 811 int reverse, 812 NCURSES_SP_OUTC outc) 813 { 814 SCREEN *sp = TCB->csp; 815 int fg = COLOR_DEFAULT; 816 int bg = COLOR_DEFAULT; 817 int old_fg, old_bg; 818 819 AssertTCB(); 820 if (sp == 0) 821 return; 822 823 if (pair < 0 || pair >= COLOR_PAIRS) { 824 return; 825 } else if (pair != 0) { 826 if (set_color_pair) { 827 TPUTS_TRACE("set_color_pair"); 828 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 829 TPARM_1(set_color_pair, pair), 1, outc); 830 return; 831 } else if (sp != 0) { 832 _nc_pair_content(SP_PARM, pair, &fg, &bg); 833 } 834 } 835 836 if (old_pair >= 0 837 && sp != 0 838 && _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) { 839 if ((isDefaultColor(fg) && !isDefaultColor(old_fg)) 840 || (isDefaultColor(bg) && !isDefaultColor(old_bg))) { 841 #if NCURSES_EXT_FUNCS 842 /* 843 * A minor optimization - but extension. If "AX" is specified in 844 * the terminal description, treat it as screen's indicator of ECMA 845 * SGR 39 and SGR 49, and assume the two sequences are independent. 846 */ 847 if (sp->_has_sgr_39_49 848 && isDefaultColor(old_bg) 849 && !isDefaultColor(old_fg)) { 850 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc); 851 } else if (sp->_has_sgr_39_49 852 && isDefaultColor(old_fg) 853 && !isDefaultColor(old_bg)) { 854 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc); 855 } else 856 #endif 857 drv_rescol(TCB); 858 } 859 } else { 860 drv_rescol(TCB); 861 if (old_pair < 0) 862 return; 863 } 864 865 #if NCURSES_EXT_FUNCS 866 if (isDefaultColor(fg)) 867 fg = default_fg(sp); 868 if (isDefaultColor(bg)) 869 bg = default_bg(sp); 870 #endif 871 872 if (reverse) { 873 int xx = fg; 874 fg = bg; 875 bg = xx; 876 } 877 878 TR(TRACE_ATTRS, ("setting colors: pair = %d, fg = %d, bg = %d", pair, 879 fg, bg)); 880 881 if (!isDefaultColor(fg)) { 882 drv_setcolor(TCB, TRUE, fg, outc); 883 } 884 if (!isDefaultColor(bg)) { 885 drv_setcolor(TCB, FALSE, bg, outc); 886 } 887 } 888 889 #define xterm_kmous "\033[M" 890 static void 891 init_xterm_mouse(SCREEN *sp) 892 { 893 sp->_mouse_type = M_XTERM; 894 sp->_mouse_xtermcap = NCURSES_SP_NAME(tigetstr) (NCURSES_SP_ARGx "XM"); 895 if (!VALID_STRING(sp->_mouse_xtermcap)) 896 sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;"; 897 } 898 899 static void 900 drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB) 901 { 902 SCREEN *sp; 903 904 AssertTCB(); 905 SetSP(); 906 907 /* we know how to recognize mouse events under "xterm" */ 908 if (sp != 0) { 909 if (NonEmpty(key_mouse)) { 910 init_xterm_mouse(sp); 911 } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) { 912 if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK) 913 init_xterm_mouse(sp); 914 } 915 } 916 } 917 918 static int 919 drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, 920 int delay 921 EVENTLIST_2nd(_nc_eventlist * evl)) 922 { 923 int rc = 0; 924 SCREEN *sp; 925 926 AssertTCB(); 927 SetSP(); 928 929 #if USE_SYSMOUSE 930 if ((sp->_mouse_type == M_SYSMOUSE) 931 && (sp->_sysmouse_head < sp->_sysmouse_tail)) { 932 rc = TW_MOUSE; 933 } else 934 #endif 935 { 936 rc = TCBOf(sp)->drv->td_twait(TCBOf(sp), 937 TWAIT_MASK, 938 delay, 939 (int *) 0 940 EVENTLIST_2nd(evl)); 941 #if USE_SYSMOUSE 942 if ((sp->_mouse_type == M_SYSMOUSE) 943 && (sp->_sysmouse_head < sp->_sysmouse_tail) 944 && (rc == 0) 945 && (errno == EINTR)) { 946 rc |= TW_MOUSE; 947 } 948 #endif 949 } 950 return rc; 951 } 952 953 static int 954 drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB, int yold, int xold, int ynew, int xnew) 955 { 956 SCREEN *sp = TCB->csp; 957 AssertTCB(); 958 return NCURSES_SP_NAME(_nc_mvcur) (sp, yold, xold, ynew, xnew); 959 } 960 961 static void 962 drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB, int labnum, char *text) 963 { 964 SCREEN *sp = TCB->csp; 965 966 AssertTCB(); 967 if (labnum > 0 && labnum <= num_labels) { 968 NCURSES_PUTP2("plab_norm", 969 TPARM_2(plab_norm, labnum, text)); 970 } 971 } 972 973 static void 974 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB, int OnFlag) 975 { 976 SCREEN *sp = TCB->csp; 977 978 AssertTCB(); 979 if (OnFlag) { 980 NCURSES_PUTP2("label_on", label_on); 981 } else { 982 NCURSES_PUTP2("label_off", label_off); 983 } 984 } 985 986 static chtype 987 drv_conattr(TERMINAL_CONTROL_BLOCK * TCB) 988 { 989 SCREEN *sp = TCB->csp; 990 chtype attrs = A_NORMAL; 991 992 AssertTCB(); 993 if (enter_alt_charset_mode) 994 attrs |= A_ALTCHARSET; 995 996 if (enter_blink_mode) 997 attrs |= A_BLINK; 998 999 if (enter_bold_mode) 1000 attrs |= A_BOLD; 1001 1002 if (enter_dim_mode) 1003 attrs |= A_DIM; 1004 1005 if (enter_reverse_mode) 1006 attrs |= A_REVERSE; 1007 1008 if (enter_standout_mode) 1009 attrs |= A_STANDOUT; 1010 1011 if (enter_protected_mode) 1012 attrs |= A_PROTECT; 1013 1014 if (enter_secure_mode) 1015 attrs |= A_INVIS; 1016 1017 if (enter_underline_mode) 1018 attrs |= A_UNDERLINE; 1019 1020 if (sp && sp->_coloron) 1021 attrs |= A_COLOR; 1022 1023 #if USE_ITALIC 1024 if (enter_italics_mode) 1025 attrs |= A_ITALIC; 1026 #endif 1027 1028 return (attrs); 1029 } 1030 1031 static void 1032 drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB) 1033 { 1034 AssertTCB(); 1035 1036 /* *INDENT-EQLS* */ 1037 clear_screen = ABSENT_STRING; 1038 cursor_address = ABSENT_STRING; 1039 cursor_down = ABSENT_STRING; 1040 cursor_up = ABSENT_STRING; 1041 parm_down_cursor = ABSENT_STRING; 1042 parm_up_cursor = ABSENT_STRING; 1043 row_address = ABSENT_STRING; 1044 cursor_home = carriage_return; 1045 1046 if (back_color_erase) 1047 clr_eos = ABSENT_STRING; 1048 } 1049 1050 static void 1051 drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) 1052 { 1053 SCREEN *sp = TCB->csp; 1054 1055 AssertTCB(); 1056 assert(sp != 0); 1057 if (ena_acs != NULL) { 1058 NCURSES_PUTP2("ena_acs", ena_acs); 1059 } 1060 #if NCURSES_EXT_FUNCS 1061 /* 1062 * Linux console "supports" the "PC ROM" character set by the coincidence 1063 * that smpch/rmpch and smacs/rmacs have the same values. ncurses has 1064 * no codepage support (see SCO Merge for an example). Outside of the 1065 * values defined in acsc, there are no definitions for the "PC ROM" 1066 * character set (assumed by some applications to be codepage 437), but we 1067 * allow those applications to use those codepoints. 1068 * 1069 * test/blue.c uses this feature. 1070 */ 1071 #define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b)) 1072 if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) && 1073 PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) { 1074 size_t i; 1075 for (i = 1; i < ACS_LEN; ++i) { 1076 if (real_map[i] == 0) { 1077 real_map[i] = (chtype) i; 1078 if (real_map != fake_map) { 1079 if (sp != 0) 1080 sp->_screen_acs_map[i] = TRUE; 1081 } 1082 } 1083 } 1084 } 1085 #endif 1086 1087 if (acs_chars != NULL) { 1088 size_t i = 0; 1089 size_t length = strlen(acs_chars); 1090 1091 while (i + 1 < length) { 1092 if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { 1093 real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; 1094 T(("#%d real_map[%s] = %s", 1095 (int) i, 1096 _tracechar(UChar(acs_chars[i])), 1097 _tracechtype(real_map[UChar(acs_chars[i])]))); 1098 if (sp != 0) { 1099 sp->_screen_acs_map[UChar(acs_chars[i])] = TRUE; 1100 } 1101 } 1102 i += 2; 1103 } 1104 } 1105 #ifdef TRACE 1106 /* Show the equivalent mapping, noting if it does not match the 1107 * given attribute, whether by re-ordering or duplication. 1108 */ 1109 if (USE_TRACEF(TRACE_CALLS)) { 1110 size_t n, m; 1111 char show[ACS_LEN * 2 + 1]; 1112 for (n = 1, m = 0; n < ACS_LEN; n++) { 1113 if (real_map[n] != 0) { 1114 show[m++] = (char) n; 1115 show[m++] = (char) ChCharOf(real_map[n]); 1116 } 1117 } 1118 show[m] = 0; 1119 if (acs_chars == NULL || strcmp(acs_chars, show)) 1120 _tracef("%s acs_chars %s", 1121 (acs_chars == NULL) ? "NULL" : "READ", 1122 _nc_visbuf(acs_chars)); 1123 _tracef("%s acs_chars %s", 1124 (acs_chars == NULL) 1125 ? "NULL" 1126 : (strcmp(acs_chars, show) 1127 ? "DIFF" 1128 : "SAME"), 1129 _nc_visbuf(show)); 1130 _nc_unlock_global(tracef); 1131 } 1132 #endif /* TRACE */ 1133 } 1134 1135 #define ENSURE_TINFO(sp) (TCBOf(sp)->drv->isTerminfo) 1136 1137 NCURSES_EXPORT(void) 1138 _nc_cookie_init(SCREEN *sp) 1139 { 1140 bool support_cookies = USE_XMC_SUPPORT; 1141 TERMINAL_CONTROL_BLOCK *TCB = (TERMINAL_CONTROL_BLOCK *) (sp->_term); 1142 1143 if (sp == 0 || !ENSURE_TINFO(sp)) 1144 return; 1145 1146 #if USE_XMC_SUPPORT 1147 /* 1148 * If we have no magic-cookie support compiled-in, or if it is suppressed 1149 * in the environment, reset the support-flag. 1150 */ 1151 if (magic_cookie_glitch >= 0) { 1152 if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) { 1153 support_cookies = FALSE; 1154 } 1155 } 1156 #endif 1157 1158 if (!support_cookies && magic_cookie_glitch >= 0) { 1159 T(("will disable attributes to work w/o magic cookies")); 1160 } 1161 1162 if (magic_cookie_glitch > 0) { /* tvi, wyse */ 1163 1164 sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT; 1165 #if 0 1166 /* 1167 * We "should" treat colors as an attribute. The wyse350 (and its 1168 * clones) appear to be the only ones that have both colors and magic 1169 * cookies. 1170 */ 1171 if (has_colors()) { 1172 sp->_xmc_triggers |= A_COLOR; 1173 } 1174 #endif 1175 sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD); 1176 1177 T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress))); 1178 /* 1179 * Supporting line-drawing may be possible. But make the regular 1180 * video attributes work first. 1181 */ 1182 acs_chars = ABSENT_STRING; 1183 ena_acs = ABSENT_STRING; 1184 enter_alt_charset_mode = ABSENT_STRING; 1185 exit_alt_charset_mode = ABSENT_STRING; 1186 #if USE_XMC_SUPPORT 1187 /* 1188 * To keep the cookie support simple, suppress all of the optimization 1189 * hooks except for clear_screen and the cursor addressing. 1190 */ 1191 if (support_cookies) { 1192 clr_eol = ABSENT_STRING; 1193 clr_eos = ABSENT_STRING; 1194 set_attributes = ABSENT_STRING; 1195 } 1196 #endif 1197 } else if (magic_cookie_glitch == 0) { /* hpterm */ 1198 } 1199 1200 /* 1201 * If magic cookies are not supported, cancel the strings that set 1202 * video attributes. 1203 */ 1204 if (!support_cookies && magic_cookie_glitch >= 0) { 1205 magic_cookie_glitch = ABSENT_NUMERIC; 1206 set_attributes = ABSENT_STRING; 1207 enter_blink_mode = ABSENT_STRING; 1208 enter_bold_mode = ABSENT_STRING; 1209 enter_dim_mode = ABSENT_STRING; 1210 enter_reverse_mode = ABSENT_STRING; 1211 enter_standout_mode = ABSENT_STRING; 1212 enter_underline_mode = ABSENT_STRING; 1213 } 1214 1215 /* initialize normal acs before wide, since we use mapping in the latter */ 1216 #if !USE_WIDEC_SUPPORT 1217 if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) { 1218 acs_chars = NULL; 1219 ena_acs = NULL; 1220 enter_alt_charset_mode = NULL; 1221 exit_alt_charset_mode = NULL; 1222 set_attributes = NULL; 1223 } 1224 #endif 1225 } 1226 1227 static int 1228 drv_twait(TERMINAL_CONTROL_BLOCK * TCB, 1229 int mode, 1230 int milliseconds, 1231 int *timeleft 1232 EVENTLIST_2nd(_nc_eventlist * evl)) 1233 { 1234 SCREEN *sp; 1235 1236 AssertTCB(); 1237 SetSP(); 1238 1239 return _nc_timed_wait(sp, mode, milliseconds, timeleft EVENTLIST_2nd(evl)); 1240 } 1241 1242 static int 1243 drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf) 1244 { 1245 SCREEN *sp; 1246 unsigned char c2 = 0; 1247 int n; 1248 1249 AssertTCB(); 1250 assert(buf); 1251 SetSP(); 1252 1253 # if USE_PTHREADS_EINTR 1254 if ((pthread_self) && (pthread_kill) && (pthread_equal)) 1255 _nc_globals.read_thread = pthread_self(); 1256 # endif 1257 n = (int) read(sp->_ifd, &c2, (size_t) 1); 1258 #if USE_PTHREADS_EINTR 1259 _nc_globals.read_thread = 0; 1260 #endif 1261 *buf = (int) c2; 1262 return n; 1263 } 1264 1265 static int 1266 drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms) 1267 { 1268 #if HAVE_NANOSLEEP 1269 { 1270 struct timespec request, remaining; 1271 request.tv_sec = ms / 1000; 1272 request.tv_nsec = (ms % 1000) * 1000000; 1273 while (nanosleep(&request, &remaining) == -1 1274 && errno == EINTR) { 1275 request = remaining; 1276 } 1277 } 1278 #else 1279 _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0)); 1280 #endif 1281 return OK; 1282 } 1283 1284 static int 1285 __nc_putp(SCREEN *sp, const char *name GCC_UNUSED, const char *value) 1286 { 1287 int rc = ERR; 1288 1289 if (value) { 1290 rc = NCURSES_PUTP2(name, value); 1291 } 1292 return rc; 1293 } 1294 1295 static int 1296 __nc_putp_flush(SCREEN *sp, const char *name, const char *value) 1297 { 1298 int rc = __nc_putp(sp, name, value); 1299 if (rc != ERR) { 1300 NCURSES_SP_NAME(_nc_flush) (sp); 1301 } 1302 return rc; 1303 } 1304 1305 static int 1306 drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag) 1307 { 1308 int ret = ERR; 1309 SCREEN *sp; 1310 1311 AssertTCB(); 1312 1313 sp = TCB->csp; 1314 1315 if (sp) { 1316 if (flag) { 1317 (void) __nc_putp_flush(sp, "keypad_xmit", keypad_xmit); 1318 } else if (!flag && keypad_local) { 1319 (void) __nc_putp_flush(sp, "keypad_local", keypad_local); 1320 } 1321 if (flag && !sp->_tried) { 1322 _nc_init_keytry(sp); 1323 sp->_tried = TRUE; 1324 } 1325 ret = OK; 1326 } 1327 1328 return ret; 1329 } 1330 1331 static int 1332 drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, int flag) 1333 { 1334 SCREEN *sp; 1335 int code = ERR; 1336 int count = 0; 1337 char *s; 1338 1339 AssertTCB(); 1340 SetSP(); 1341 1342 if (c >= 0) { 1343 unsigned ch = (unsigned) c; 1344 if (flag) { 1345 while ((s = _nc_expand_try(sp->_key_ok, 1346 ch, &count, (size_t) 0)) != 0) { 1347 if (_nc_remove_key(&(sp->_key_ok), ch)) { 1348 code = _nc_add_to_try(&(sp->_keytry), s, ch); 1349 free(s); 1350 count = 0; 1351 if (code != OK) 1352 break; 1353 } else { 1354 free(s); 1355 } 1356 } 1357 } else { 1358 while ((s = _nc_expand_try(sp->_keytry, 1359 ch, &count, (size_t) 0)) != 0) { 1360 if (_nc_remove_key(&(sp->_keytry), ch)) { 1361 code = _nc_add_to_try(&(sp->_key_ok), s, ch); 1362 free(s); 1363 count = 0; 1364 if (code != OK) 1365 break; 1366 } else { 1367 free(s); 1368 } 1369 } 1370 } 1371 } 1372 return (code); 1373 } 1374 1375 static int 1376 drv_cursorSet(TERMINAL_CONTROL_BLOCK * TCB, int vis) 1377 { 1378 SCREEN *sp; 1379 int code = ERR; 1380 1381 AssertTCB(); 1382 SetSP(); 1383 1384 T((T_CALLED("tinfo:drv_cursorSet(%p,%d)"), (void *) SP_PARM, vis)); 1385 1386 if (SP_PARM != 0 && IsTermInfo(SP_PARM)) { 1387 switch (vis) { 1388 case 2: 1389 code = NCURSES_PUTP2_FLUSH("cursor_visible", cursor_visible); 1390 break; 1391 case 1: 1392 code = NCURSES_PUTP2_FLUSH("cursor_normal", cursor_normal); 1393 break; 1394 case 0: 1395 code = NCURSES_PUTP2_FLUSH("cursor_invisible", cursor_invisible); 1396 break; 1397 } 1398 } else { 1399 code = ERR; 1400 } 1401 returnCode(code); 1402 } 1403 1404 static bool 1405 drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int key) 1406 { 1407 bool res = FALSE; 1408 1409 AssertTCB(); 1410 if (TCB->csp) 1411 res = TINFO_HAS_KEY(TCB->csp, key) == 0 ? FALSE : TRUE; 1412 1413 return res; 1414 } 1415 1416 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = { 1417 TRUE, 1418 drv_Name, /* Name */ 1419 drv_CanHandle, /* CanHandle */ 1420 drv_init, /* init */ 1421 drv_release, /* release */ 1422 drv_size, /* size */ 1423 drv_sgmode, /* sgmode */ 1424 drv_conattr, /* conattr */ 1425 drv_mvcur, /* hwcur */ 1426 drv_mode, /* mode */ 1427 drv_rescol, /* rescol */ 1428 drv_rescolors, /* rescolors */ 1429 drv_setcolor, /* color */ 1430 drv_dobeepflash, /* doBeepOrFlash */ 1431 drv_initpair, /* initpair */ 1432 drv_initcolor, /* initcolor */ 1433 drv_do_color, /* docolor */ 1434 drv_initmouse, /* initmouse */ 1435 drv_testmouse, /* testmouse */ 1436 drv_setfilter, /* setfilter */ 1437 drv_hwlabel, /* hwlabel */ 1438 drv_hwlabelOnOff, /* hwlabelOnOff */ 1439 drv_doupdate, /* update */ 1440 drv_defaultcolors, /* defaultcolors */ 1441 drv_print, /* print */ 1442 drv_getsize, /* getsize */ 1443 drv_setsize, /* setsize */ 1444 drv_initacs, /* initacs */ 1445 drv_screen_init, /* scinit */ 1446 drv_wrap, /* scexit */ 1447 drv_twait, /* twait */ 1448 drv_read, /* read */ 1449 drv_nap, /* nap */ 1450 drv_kpad, /* kpad */ 1451 drv_keyok, /* kyOk */ 1452 drv_kyExist, /* kyExist */ 1453 drv_cursorSet /* cursorSet */ 1454 }; 1455