1 /* $OpenBSD: lib_set_term.c,v 1.15 2023/10/17 09:52:09 nicm Exp $ */ 2 3 /**************************************************************************** 4 * Copyright 2018-2021,2022 Thomas E. Dickey * 5 * Copyright 1998-2016,2017 Free Software Foundation, Inc. * 6 * * 7 * Permission is hereby granted, free of charge, to any person obtaining a * 8 * copy of this software and associated documentation files (the * 9 * "Software"), to deal in the Software without restriction, including * 10 * without limitation the rights to use, copy, modify, merge, publish, * 11 * distribute, distribute with modifications, sublicense, and/or sell * 12 * copies of the Software, and to permit persons to whom the Software is * 13 * furnished to do so, subject to the following conditions: * 14 * * 15 * The above copyright notice and this permission notice shall be included * 16 * in all copies or substantial portions of the Software. * 17 * * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 21 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 25 * * 26 * Except as contained in this notice, the name(s) of the above copyright * 27 * holders shall not be used in advertising or otherwise to promote the * 28 * sale, use or other dealings in this Software without prior written * 29 * authorization. * 30 ****************************************************************************/ 31 32 /**************************************************************************** 33 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 34 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 35 * and: Thomas E. Dickey 1996-on * 36 * and: Juergen Pfeifer 2009 * 37 ****************************************************************************/ 38 39 /* 40 ** lib_set_term.c 41 ** 42 ** The routine set_term(). 43 ** 44 */ 45 46 #define NEW_PAIR_INTERNAL 1 47 48 #include <curses.priv.h> 49 #include <tic.h> 50 #include <new_pair.h> 51 52 #if USE_GPM_SUPPORT 53 #ifdef HAVE_LIBDL 54 /* use dynamic loader to avoid linkage dependency */ 55 #include <dlfcn.h> 56 #endif 57 #endif 58 59 #undef CUR 60 #define CUR SP_TERMTYPE 61 62 MODULE_ID("$Id: lib_set_term.c,v 1.15 2023/10/17 09:52:09 nicm Exp $") 63 64 #ifdef USE_TERM_DRIVER 65 #define MaxColors InfoOf(sp).maxcolors 66 #define NumLabels InfoOf(sp).numlabels 67 #else 68 #define MaxColors max_colors 69 #define NumLabels num_labels 70 #endif 71 72 NCURSES_EXPORT(SCREEN *) 73 set_term(SCREEN *screenp) 74 { 75 SCREEN *oldSP; 76 SCREEN *newSP; 77 78 T((T_CALLED("set_term(%p)"), (void *) screenp)); 79 80 _nc_lock_global(curses); 81 82 oldSP = CURRENT_SCREEN; 83 _nc_set_screen(screenp); 84 newSP = screenp; 85 86 if (newSP != 0) { 87 TINFO_SET_CURTERM(newSP, newSP->_term); 88 #if !USE_REENTRANT 89 curscr = CurScreen(newSP); 90 newscr = NewScreen(newSP); 91 stdscr = StdScreen(newSP); 92 COLORS = newSP->_color_count; 93 COLOR_PAIRS = newSP->_pair_count; 94 #endif 95 } else { 96 TINFO_SET_CURTERM(oldSP, 0); 97 #if !USE_REENTRANT 98 curscr = 0; 99 newscr = 0; 100 stdscr = 0; 101 COLORS = 0; 102 COLOR_PAIRS = 0; 103 #endif 104 } 105 106 _nc_unlock_global(curses); 107 108 T((T_RETURN("%p"), (void *) oldSP)); 109 return (oldSP); 110 } 111 112 static void 113 _nc_free_keytry(TRIES * kt) 114 { 115 if (kt != 0) { 116 _nc_free_keytry(kt->child); 117 _nc_free_keytry(kt->sibling); 118 free(kt); 119 } 120 } 121 122 static bool 123 delink_screen(SCREEN *sp) 124 { 125 SCREEN *last = 0; 126 SCREEN *temp; 127 bool result = FALSE; 128 129 for (each_screen(temp)) { 130 if (temp == sp) { 131 if (last) 132 last->_next_screen = sp->_next_screen; 133 else 134 _nc_screen_chain = sp->_next_screen; 135 result = TRUE; 136 break; 137 } 138 last = temp; 139 } 140 return result; 141 } 142 143 /* 144 * Free the storage associated with the given SCREEN sp. 145 */ 146 NCURSES_EXPORT(void) 147 delscreen(SCREEN *sp) 148 { 149 150 T((T_CALLED("delscreen(%p)"), (void *) sp)); 151 152 _nc_lock_global(curses); 153 if (delink_screen(sp)) { 154 WINDOWLIST *wl; 155 bool is_current = (sp == CURRENT_SCREEN); 156 157 #ifdef USE_SP_RIPOFF 158 if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) { 159 ripoff_t *rop; 160 for (rop = safe_ripoff_stack; 161 rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS; 162 rop++) { 163 if (rop->win) { 164 (void) delwin(rop->win); 165 rop->win = 0; 166 } 167 } 168 } 169 #endif 170 171 /* delete all of the windows in this screen */ 172 rescan: 173 for (each_window(sp, wl)) { 174 if (_nc_freewin(&(wl->win)) == OK) { 175 goto rescan; 176 } 177 } 178 179 if (sp->_slk != 0) { 180 181 if (sp->_slk->ent != 0) { 182 int i; 183 184 for (i = 0; i < sp->_slk->labcnt; ++i) { 185 FreeIfNeeded(sp->_slk->ent[i].ent_text); 186 FreeIfNeeded(sp->_slk->ent[i].form_text); 187 } 188 free(sp->_slk->ent); 189 } 190 free(sp->_slk); 191 sp->_slk = 0; 192 } 193 194 _nc_free_keytry(sp->_keytry); 195 sp->_keytry = 0; 196 197 _nc_free_keytry(sp->_key_ok); 198 sp->_key_ok = 0; 199 200 FreeIfNeeded(sp->_current_attr); 201 202 _nc_free_ordered_pairs(sp); 203 FreeIfNeeded(sp->_color_table); 204 FreeIfNeeded(sp->_color_pairs); 205 206 FreeIfNeeded(sp->_oldnum_list); 207 FreeIfNeeded(sp->oldhash); 208 FreeIfNeeded(sp->newhash); 209 FreeIfNeeded(sp->hashtab); 210 211 FreeIfNeeded(sp->_acs_map); 212 FreeIfNeeded(sp->_screen_acs_map); 213 214 NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); 215 NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term); 216 FreeIfNeeded(sp->out_buffer); 217 if (_nc_find_prescr() == sp) { 218 _nc_forget_prescr(); 219 } 220 #if USE_GPM_SUPPORT 221 #ifdef HAVE_LIBDL 222 if (sp->_dlopen_gpm != 0) { 223 dlclose(sp->_dlopen_gpm); 224 sp->_dlopen_gpm = 0; 225 } 226 #endif 227 #endif /* USE_GPM_SUPPORT */ 228 free(sp); 229 230 /* 231 * If this was the current screen, reset everything that the 232 * application might try to use (except cur_term, which may have 233 * multiple references in different screens). 234 */ 235 if (is_current) { 236 #if !USE_REENTRANT 237 curscr = 0; 238 newscr = 0; 239 stdscr = 0; 240 COLORS = 0; 241 COLOR_PAIRS = 0; 242 #endif 243 _nc_set_screen(0); 244 #if USE_WIDEC_SUPPORT 245 if (SP == 0) { 246 FreeIfNeeded(_nc_wacs); 247 _nc_wacs = 0; 248 } 249 #endif 250 } else { 251 set_term(CURRENT_SCREEN); 252 } 253 } 254 _nc_unlock_global(curses); 255 256 returnVoid; 257 } 258 259 static bool 260 no_mouse_event(SCREEN *sp GCC_UNUSED) 261 { 262 return FALSE; 263 } 264 265 static bool 266 no_mouse_inline(SCREEN *sp GCC_UNUSED) 267 { 268 return FALSE; 269 } 270 271 static bool 272 no_mouse_parse(SCREEN *sp GCC_UNUSED, int code GCC_UNUSED) 273 { 274 return TRUE; 275 } 276 277 static void 278 no_mouse_resume(SCREEN *sp GCC_UNUSED) 279 { 280 } 281 282 static void 283 no_mouse_wrap(SCREEN *sp GCC_UNUSED) 284 { 285 } 286 287 #if NCURSES_EXT_FUNCS && USE_COLORFGBG 288 static const char * 289 extract_fgbg(const char *src, int *result) 290 { 291 const char *dst = 0; 292 char *tmp = 0; 293 long value = strtol(src, &tmp, 0); 294 295 if ((dst = tmp) == 0) { 296 dst = src; 297 } else if (value >= 0) { 298 *result = (int) value; 299 } 300 while (*dst != 0 && *dst != ';') 301 dst++; 302 if (*dst == ';') 303 dst++; 304 return dst; 305 } 306 #endif 307 308 #define ReturnScreenError() do { _nc_set_screen(0); \ 309 returnCode(ERR); } while (0) 310 311 /* OS-independent screen initializations */ 312 NCURSES_EXPORT(int) 313 NCURSES_SP_NAME(_nc_setupscreen) ( 314 #if NCURSES_SP_FUNCS 315 SCREEN **spp, 316 #endif 317 int slines, 318 int scolumns, 319 FILE *output, 320 int filtered, 321 int slk_format) 322 { 323 #ifndef USE_TERM_DRIVER 324 static const TTY null_TTY; /* all zeros iff uninitialized */ 325 #endif 326 char *env; 327 int bottom_stolen = 0; 328 SCREEN *sp; 329 #ifndef USE_TERM_DRIVER 330 bool support_cookies = USE_XMC_SUPPORT; 331 #endif 332 333 T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"), 334 slines, scolumns, (void *) output, filtered, slk_format)); 335 336 assert(CURRENT_SCREEN == 0); /* has been reset in newterm() ! */ 337 338 #if NCURSES_SP_FUNCS 339 assert(spp != 0); 340 sp = *spp; 341 342 if (!sp) { 343 sp = _nc_alloc_screen_sp(); 344 T(("_nc_alloc_screen_sp %p", (void *) sp)); 345 *spp = sp; 346 } 347 if (sp == NULL) { 348 ReturnScreenError(); 349 } 350 if ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == NULL) { 351 ReturnScreenError(); 352 } 353 if ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == NULL) { 354 free(sp->_acs_map); 355 ReturnScreenError(); 356 } 357 358 T(("created SP %p", (void *) sp)); 359 sp->_next_screen = _nc_screen_chain; 360 _nc_screen_chain = sp; 361 362 if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) { 363 ReturnScreenError(); 364 } 365 #else 366 if (!_nc_alloc_screen() 367 || ((SP->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0) 368 || ((SP->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) { 369 returnCode(ERR); 370 } 371 372 T(("created SP %p", (void *) SP)); 373 374 sp = SP; /* fixup so SET_LINES and SET_COLS works */ 375 sp->_next_screen = _nc_screen_chain; 376 _nc_screen_chain = sp; 377 378 if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) { 379 returnCode(ERR); 380 } 381 #endif 382 383 /* 384 * We should always check the screensize, just in case. 385 */ 386 _nc_set_screen(sp); 387 sp->_term = cur_term; 388 #ifdef USE_TERM_DRIVER 389 TCBOf(sp)->csp = sp; 390 _nc_get_screensize(sp, sp->_term, &slines, &scolumns); 391 #else 392 _nc_get_screensize(sp, &slines, &scolumns); 393 #endif 394 SET_LINES(slines); 395 SET_COLS(scolumns); 396 397 T((T_CREATE("screen %s %dx%d"), 398 NCURSES_SP_NAME(termname) (NCURSES_SP_ARG), slines, scolumns)); 399 400 sp->_filtered = filtered; 401 402 /* implement filter mode */ 403 if (filtered) { 404 slines = 1; 405 SET_LINES(slines); 406 #ifdef USE_TERM_DRIVER 407 CallDriver(sp, td_setfilter); 408 #else 409 /* *INDENT-EQLS* */ 410 clear_screen = ABSENT_STRING; 411 cursor_address = ABSENT_STRING; 412 cursor_down = ABSENT_STRING; 413 cursor_up = ABSENT_STRING; 414 parm_down_cursor = ABSENT_STRING; 415 parm_up_cursor = ABSENT_STRING; 416 row_address = ABSENT_STRING; 417 cursor_home = carriage_return; 418 419 if (back_color_erase) 420 clr_eos = ABSENT_STRING; 421 422 #endif 423 T(("filter screensize %dx%d", slines, scolumns)); 424 } 425 #ifdef __DJGPP__ 426 T(("setting output mode to binary")); 427 fflush(output); 428 setmode(output, O_BINARY); 429 #endif 430 #if defined(EXP_WIN32_DRIVER) 431 T(("setting output mode to binary")); 432 fflush(output); 433 _setmode(fileno(output), _O_BINARY); 434 #endif 435 sp->_lines = (NCURSES_SIZE_T) slines; 436 sp->_lines_avail = (NCURSES_SIZE_T) slines; 437 sp->_columns = (NCURSES_SIZE_T) scolumns; 438 439 fflush(output); 440 sp->_ofd = output ? fileno(output) : -1; 441 sp->_ofp = output; 442 #if defined(EXP_WIN32_DRIVER) 443 if (output) 444 _setmode(fileno(output), _O_BINARY); 445 #endif 446 sp->out_limit = (size_t) ((2 + slines) * (6 + scolumns)); 447 if ((sp->out_buffer = malloc(sp->out_limit)) == 0) 448 sp->out_limit = 0; 449 sp->out_inuse = 0; 450 451 SP_PRE_INIT(sp); 452 SetNoPadding(sp); 453 454 #if NCURSES_EXT_FUNCS 455 sp->_default_color = FALSE; 456 sp->_has_sgr_39_49 = FALSE; 457 458 /* 459 * Set our assumption of the terminal's default foreground and background 460 * colors. The curs_color man-page states that we can assume that the 461 * background is black. The origin of this assumption appears to be 462 * terminals that displayed colored text, but no colored backgrounds, e.g., 463 * the first colored terminals around 1980. More recent ones with better 464 * technology can display not only colored backgrounds, but all 465 * combinations. So a terminal might be something other than "white" on 466 * black (green/black looks monochrome too), but black on white or even 467 * on ivory. 468 * 469 * White-on-black is the simplest thing to use for monochrome. Almost 470 * all applications that use color paint both text and background, so 471 * the distinction is moot. But a few do not - which is why we leave this 472 * configurable (a better solution is to use assume_default_colors() for 473 * the rare applications that do require that sort of appearance, since 474 * is appears that more users expect to be able to make a white-on-black 475 * or black-on-white display under control of the application than not). 476 */ 477 #ifdef USE_ASSUMED_COLOR 478 sp->_default_fg = COLOR_WHITE; 479 sp->_default_bg = COLOR_BLACK; 480 #else 481 sp->_default_fg = COLOR_DEFAULT; 482 sp->_default_bg = COLOR_DEFAULT; 483 #endif 484 485 /* 486 * Allow those assumed/default color assumptions to be overridden at 487 * runtime: 488 */ 489 if ((env = getenv("NCURSES_ASSUMED_COLORS")) != 0) { 490 int fg, bg; 491 char sep1, sep2; 492 int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2); 493 if (count >= 1) { 494 sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : COLOR_DEFAULT); 495 if (count >= 3) { 496 sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : COLOR_DEFAULT); 497 } 498 TR(TRACE_CHARPUT | TRACE_MOVE, 499 ("from environment assumed fg=%d, bg=%d", 500 sp->_default_fg, 501 sp->_default_bg)); 502 } 503 } 504 #if USE_COLORFGBG 505 /* 506 * If rxvt's $COLORFGBG variable is set, use it to specify the assumed 507 * default colors. Note that rxvt (mis)uses bold colors, equating a bold 508 * color to that value plus 8. We'll only use the non-bold color for now - 509 * decide later if it is worth having default attributes as well. 510 */ 511 if (getenv("COLORFGBG") != 0) { 512 const char *p = getenv("COLORFGBG"); 513 TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p)); 514 p = extract_fgbg(p, &(sp->_default_fg)); 515 p = extract_fgbg(p, &(sp->_default_bg)); 516 if (*p) /* assume rxvt was compiled with xpm support */ 517 extract_fgbg(p, &(sp->_default_bg)); 518 TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d", 519 sp->_default_fg, sp->_default_bg)); 520 if (sp->_default_fg >= MaxColors) { 521 if (set_a_foreground != ABSENT_STRING 522 && !strcmp(set_a_foreground, "\033[3%p1%dm")) { 523 set_a_foreground = strdup("\033[3%?%p1%{8}%>%t9%e%p1%d%;m"); 524 } else { 525 sp->_default_fg %= MaxColors; 526 } 527 } 528 if (sp->_default_bg >= MaxColors) { 529 if (set_a_background != ABSENT_STRING 530 && !strcmp(set_a_background, "\033[4%p1%dm")) { 531 set_a_background = strdup("\033[4%?%p1%{8}%>%t9%e%p1%d%;m"); 532 } else { 533 sp->_default_bg %= MaxColors; 534 } 535 } 536 } 537 #endif 538 #endif /* NCURSES_EXT_FUNCS */ 539 540 sp->_maxclick = DEFAULT_MAXCLICK; 541 sp->_mouse_event = no_mouse_event; 542 sp->_mouse_inline = no_mouse_inline; 543 sp->_mouse_parse = no_mouse_parse; 544 sp->_mouse_resume = no_mouse_resume; 545 sp->_mouse_wrap = no_mouse_wrap; 546 sp->_mouse_fd = -1; 547 548 /* 549 * If we've no magic cookie support, we suppress attributes that xmc would 550 * affect, i.e., the attributes that affect the rendition of a space. 551 */ 552 sp->_ok_attributes = NCURSES_SP_NAME(termattrs) (NCURSES_SP_ARG); 553 if (NCURSES_SP_NAME(has_colors) (NCURSES_SP_ARG)) { 554 sp->_ok_attributes |= A_COLOR; 555 } 556 #ifdef USE_TERM_DRIVER 557 _nc_cookie_init(sp); 558 #else 559 #if USE_XMC_SUPPORT 560 /* 561 * If we have no magic-cookie support compiled-in, or if it is suppressed 562 * in the environment, reset the support-flag. 563 */ 564 if (magic_cookie_glitch >= 0) { 565 if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) { 566 support_cookies = FALSE; 567 } 568 } 569 #endif 570 571 if (!support_cookies && magic_cookie_glitch >= 0) { 572 T(("will disable attributes to work w/o magic cookies")); 573 } 574 575 if (magic_cookie_glitch > 0) { /* tvi, wyse */ 576 577 sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT; 578 #if 0 579 /* 580 * We "should" treat colors as an attribute. The wyse350 (and its 581 * clones) appear to be the only ones that have both colors and magic 582 * cookies. 583 */ 584 if (has_colors()) { 585 sp->_xmc_triggers |= A_COLOR; 586 } 587 #endif 588 sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD); 589 590 T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress))); 591 /* 592 * Supporting line-drawing may be possible. But make the regular 593 * video attributes work first. 594 */ 595 acs_chars = ABSENT_STRING; 596 ena_acs = ABSENT_STRING; 597 enter_alt_charset_mode = ABSENT_STRING; 598 exit_alt_charset_mode = ABSENT_STRING; 599 #if USE_XMC_SUPPORT 600 /* 601 * To keep the cookie support simple, suppress all of the optimization 602 * hooks except for clear_screen and the cursor addressing. 603 */ 604 if (support_cookies) { 605 clr_eol = ABSENT_STRING; 606 clr_eos = ABSENT_STRING; 607 set_attributes = ABSENT_STRING; 608 } 609 #endif 610 } else if (magic_cookie_glitch == 0) { /* hpterm */ 611 } 612 613 /* 614 * If magic cookies are not supported, cancel the strings that set 615 * video attributes. 616 */ 617 if (!support_cookies && magic_cookie_glitch >= 0) { 618 magic_cookie_glitch = ABSENT_NUMERIC; 619 set_attributes = ABSENT_STRING; 620 enter_blink_mode = ABSENT_STRING; 621 enter_bold_mode = ABSENT_STRING; 622 enter_dim_mode = ABSENT_STRING; 623 enter_reverse_mode = ABSENT_STRING; 624 enter_standout_mode = ABSENT_STRING; 625 enter_underline_mode = ABSENT_STRING; 626 } 627 628 /* initialize normal acs before wide, since we use mapping in the latter */ 629 #if !USE_WIDEC_SUPPORT 630 if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) { 631 acs_chars = NULL; 632 ena_acs = NULL; 633 enter_alt_charset_mode = NULL; 634 exit_alt_charset_mode = NULL; 635 set_attributes = NULL; 636 } 637 #endif 638 #endif 639 640 NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_ARG); 641 #if USE_WIDEC_SUPPORT 642 sp->_screen_unicode = _nc_unicode_locale(); 643 if (_nc_wacs == 0) { 644 _nc_init_wacs(); 645 } 646 if (_nc_wacs == 0) { 647 ReturnScreenError(); 648 } 649 650 sp->_screen_acs_fix = (sp->_screen_unicode 651 && _nc_locale_breaks_acs(sp->_term)); 652 #endif 653 env = _nc_get_locale(); 654 sp->_legacy_coding = ((env == 0) 655 || !strcmp(env, "C") 656 || !strcmp(env, "POSIX")); 657 T(("legacy-coding %d", sp->_legacy_coding)); 658 659 sp->_nc_sp_idcok = TRUE; 660 sp->_nc_sp_idlok = FALSE; 661 662 sp->oldhash = 0; 663 sp->newhash = 0; 664 665 T(("creating newscr")); 666 NewScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns, 667 0, 0); 668 if (NewScreen(sp) == 0) { 669 ReturnScreenError(); 670 } 671 T(("creating curscr")); 672 CurScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns, 673 0, 0); 674 if (CurScreen(sp) == 0) { 675 ReturnScreenError(); 676 } 677 #if !USE_REENTRANT 678 newscr = NewScreen(sp); 679 curscr = CurScreen(sp); 680 #endif 681 #if USE_SIZECHANGE 682 sp->_resize = NCURSES_SP_NAME(resizeterm); 683 sp->_ungetch = safe_ungetch; 684 #endif 685 686 NewScreen(sp)->_clear = TRUE; 687 CurScreen(sp)->_clear = FALSE; 688 689 /* 690 * Get the current tty-modes. setupterm() may already have done this, 691 * unless we use the term-driver. 692 */ 693 #ifndef USE_TERM_DRIVER 694 if (cur_term != 0 && 695 !memcmp(&cur_term->Ottyb, &null_TTY, sizeof(TTY))) 696 #endif 697 { 698 NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); 699 NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); 700 } 701 702 if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) { 703 ripoff_t *rop; 704 705 for (rop = safe_ripoff_stack; 706 rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS; 707 rop++) { 708 709 /* If we must simulate soft labels, grab off the line to be used. 710 We assume that we must simulate, if it is none of the standard 711 formats (4-4 or 3-2-3) for which there may be some hardware 712 support. */ 713 if (rop->hook == _nc_slk_initialize) { 714 if (!TerminalOf(sp)) { 715 continue; 716 } 717 if (!(NumLabels <= 0 || !SLK_STDFMT(slk_format))) { 718 continue; 719 } 720 } 721 if (rop->hook) { 722 int count; 723 WINDOW *w; 724 725 count = (rop->line < 0) ? -rop->line : rop->line; 726 T(("ripping off %i lines at %s", count, 727 ((rop->line < 0) 728 ? "bottom" 729 : "top"))); 730 731 w = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx 732 count, scolumns, 733 ((rop->line < 0) 734 ? sp->_lines_avail - count 735 : 0), 736 0); 737 if (w) { 738 rop->win = w; 739 rop->hook(w, scolumns); 740 } else { 741 ReturnScreenError(); 742 } 743 if (rop->line < 0) { 744 bottom_stolen += count; 745 } else { 746 sp->_topstolen = (NCURSES_SIZE_T) (sp->_topstolen + count); 747 } 748 sp->_lines_avail = (NCURSES_SIZE_T) (sp->_lines_avail - count); 749 } 750 } 751 /* reset the stack */ 752 safe_ripoff_sp = safe_ripoff_stack; 753 } 754 755 T(("creating stdscr")); 756 (void) bottom_stolen; 757 assert((sp->_lines_avail + sp->_topstolen + bottom_stolen) == slines); 758 if ((StdScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx 759 sp->_lines_avail, 760 scolumns, 0, 0)) == 0) { 761 ReturnScreenError(); 762 } 763 SET_LINES(sp->_lines_avail); 764 #if !USE_REENTRANT 765 stdscr = StdScreen(sp); 766 #endif 767 sp->_prescreen = FALSE; 768 returnCode(OK); 769 } 770 771 #if NCURSES_SP_FUNCS 772 NCURSES_EXPORT(int) 773 _nc_setupscreen(int slines GCC_UNUSED, 774 int scolumns GCC_UNUSED, 775 FILE *output, 776 int filtered, 777 int slk_format) 778 { 779 SCREEN *sp = 0; 780 int rc = NCURSES_SP_NAME(_nc_setupscreen) (&sp, 781 slines, 782 scolumns, 783 output, 784 filtered, 785 slk_format); 786 if (rc != OK) 787 _nc_set_screen(0); 788 return rc; 789 } 790 #endif 791 792 /* 793 * The internal implementation interprets line as the number of lines to rip 794 * off from the top or bottom. 795 */ 796 NCURSES_EXPORT(int) 797 NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx 798 int line, 799 int (*init) (WINDOW *, int)) 800 { 801 int code = ERR; 802 TR_FUNC_BFR(1); 803 804 START_TRACE(); 805 T((T_CALLED("ripoffline(%p,%d,%s)"), 806 (void *) SP_PARM, line, 807 TR_FUNC_ARG(0, init))); 808 809 #if NCURSES_SP_FUNCS 810 if (SP_PARM != 0 && SP_PARM->_prescreen) 811 #endif 812 { 813 if (line == 0) { 814 code = OK; 815 } else { 816 if (safe_ripoff_sp == 0) { 817 safe_ripoff_sp = safe_ripoff_stack; 818 } 819 if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) { 820 safe_ripoff_sp->line = line; 821 safe_ripoff_sp->hook = init; 822 (safe_ripoff_sp)++; 823 T(("ripped-off %d:%d chunks", 824 (int) (safe_ripoff_sp - safe_ripoff_stack), N_RIPS)); 825 code = OK; 826 } 827 } 828 } 829 830 returnCode(code); 831 } 832 833 #if NCURSES_SP_FUNCS 834 NCURSES_EXPORT(int) 835 _nc_ripoffline(int line, int (*init) (WINDOW *, int)) 836 { 837 int rc; 838 839 _nc_init_pthreads(); 840 _nc_lock_global(prescreen); 841 START_TRACE(); 842 rc = NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init); 843 _nc_unlock_global(prescreen); 844 845 return rc; 846 } 847 #endif 848 849 NCURSES_EXPORT(int) 850 NCURSES_SP_NAME(ripoffline) (NCURSES_SP_DCLx 851 int line, 852 int (*init) (WINDOW *, int)) 853 { 854 START_TRACE(); 855 return NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_ARGx 856 (line < 0) ? -1 : 1, 857 init); 858 } 859 860 #if NCURSES_SP_FUNCS 861 NCURSES_EXPORT(int) 862 ripoffline(int line, int (*init) (WINDOW *, int)) 863 { 864 int rc; 865 866 _nc_init_pthreads(); 867 _nc_lock_global(prescreen); 868 START_TRACE(); 869 rc = NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init); 870 _nc_unlock_global(prescreen); 871 872 return rc; 873 } 874 #endif 875