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