150276Speter/**************************************************************************** 2262685Sdelphij * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 33262629Sdelphij * and: Juergen Pfeifer 2009 * 3450276Speter ****************************************************************************/ 3550276Speter 3650276Speter/* 3750276Speter** lib_newterm.c 3850276Speter** 3950276Speter** The newterm() function. 4050276Speter** 4150276Speter*/ 4250276Speter 4350276Speter#include <curses.priv.h> 4450276Speter 45262629Sdelphij#ifndef CUR 46262629Sdelphij#define CUR SP_TERMTYPE 47262629Sdelphij#endif 48262629Sdelphij 4962449Speter#include <tic.h> 5050276Speter 51262685SdelphijMODULE_ID("$Id: lib_newterm.c,v 1.90 2013/09/28 21:02:56 tom Exp $") 5250276Speter 53262629Sdelphij#ifdef USE_TERM_DRIVER 54262629Sdelphij#define NumLabels InfoOf(SP_PARM).numlabels 55262629Sdelphij#else 56262629Sdelphij#define NumLabels num_labels 57262629Sdelphij#endif 58262629Sdelphij 5962449Speter#ifndef ONLCR /* Allows compilation under the QNX 4.2 OS */ 6050276Speter#define ONLCR 0 6150276Speter#endif 6250276Speter 6350276Speter/* 6450276Speter * SVr4/XSI Curses specify that hardware echo is turned off in initscr, and not 6550276Speter * restored during the curses session. The library simulates echo in software. 6650276Speter * (The behavior is unspecified if the application enables hardware echo). 6750276Speter * 6850276Speter * The newterm function also initializes terminal settings, and since initscr 6950276Speter * is supposed to behave as if it calls newterm, we do it here. 7050276Speter */ 71166124Srafanstatic NCURSES_INLINE int 72262629Sdelphij_nc_initscr(NCURSES_SP_DCL0) 7350276Speter{ 74166124Srafan int result = ERR; 75262629Sdelphij TERMINAL *term = TerminalOf(SP_PARM); 76166124Srafan 7762449Speter /* for extended XPG4 conformance requires cbreak() at this point */ 7862449Speter /* (SVr4 curses does this anyway) */ 79262629Sdelphij if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) { 80166124Srafan TTY buf; 8150276Speter 82262629Sdelphij buf = term->Nttyb; 8350276Speter#ifdef TERMIOS 84262629Sdelphij buf.c_lflag &= (unsigned) ~(ECHO | ECHONL); 85262629Sdelphij buf.c_iflag &= (unsigned) ~(ICRNL | INLCR | IGNCR); 86262629Sdelphij buf.c_oflag &= (unsigned) ~(ONLCR); 87166124Srafan#elif HAVE_SGTTY_H 88166124Srafan buf.sg_flags &= ~(ECHO | CRMOD); 8950276Speter#else 90166124Srafan memset(&buf, 0, sizeof(buf)); 9150276Speter#endif 92262629Sdelphij result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); 93262629Sdelphij if (result == OK) 94262629Sdelphij term->Nttyb = buf; 95166124Srafan } 96166124Srafan return result; 9750276Speter} 9850276Speter 9950276Speter/* 10050276Speter * filter() has to be called before either initscr() or newterm(), so there is 10150276Speter * apparently no way to make this flag apply to some terminals and not others, 10250276Speter * aside from possibly delaying a filter() call until some terminals have been 10350276Speter * initialized. 10450276Speter */ 10576726SpeterNCURSES_EXPORT(void) 106262629SdelphijNCURSES_SP_NAME(filter) (NCURSES_SP_DCL0) 107262629Sdelphij{ 108262629Sdelphij START_TRACE(); 109262629Sdelphij T((T_CALLED("filter(%p)"), (void *) SP_PARM)); 110262629Sdelphij#if NCURSES_SP_FUNCS 111262629Sdelphij if (IsPreScreen(SP_PARM)) { 112262629Sdelphij SP_PARM->_filtered = TRUE; 113262629Sdelphij } 114262629Sdelphij#else 115262629Sdelphij _nc_prescreen.filter_mode = TRUE; 116262629Sdelphij#endif 117262629Sdelphij returnVoid; 118262629Sdelphij} 119262629Sdelphij 120262629Sdelphij#if NCURSES_SP_FUNCS 121262629SdelphijNCURSES_EXPORT(void) 12262449Speterfilter(void) 12350276Speter{ 124166124Srafan START_TRACE(); 125262629Sdelphij T((T_CALLED("filter()"))); 126174993Srafan _nc_prescreen.filter_mode = TRUE; 12797049Speter returnVoid; 12850276Speter} 129262629Sdelphij#endif 13050276Speter 131166124Srafan#if NCURSES_EXT_FUNCS 132166124Srafan/* 133166124Srafan * An extension, allowing the application to open a new screen without 134166124Srafan * requiring it to also be filtered. 135166124Srafan */ 136166124SrafanNCURSES_EXPORT(void) 137262629SdelphijNCURSES_SP_NAME(nofilter) (NCURSES_SP_DCL0) 138262629Sdelphij{ 139262629Sdelphij START_TRACE(); 140262629Sdelphij T((T_CALLED("nofilter(%p)"), (void *) SP_PARM)); 141262629Sdelphij#if NCURSES_SP_FUNCS 142262629Sdelphij if (IsPreScreen(SP_PARM)) { 143262629Sdelphij SP_PARM->_filtered = FALSE; 144262629Sdelphij } 145262629Sdelphij#else 146262629Sdelphij _nc_prescreen.filter_mode = FALSE; 147262629Sdelphij#endif 148262629Sdelphij returnVoid; 149262629Sdelphij} 150262629Sdelphij 151262629Sdelphij#if NCURSES_SP_FUNCS 152262629SdelphijNCURSES_EXPORT(void) 153166124Srafannofilter(void) 154166124Srafan{ 155166124Srafan START_TRACE(); 156262629Sdelphij T((T_CALLED("nofilter()"))); 157174993Srafan _nc_prescreen.filter_mode = FALSE; 158166124Srafan returnVoid; 159166124Srafan} 160166124Srafan#endif 161262629Sdelphij#endif /* NCURSES_EXT_FUNCS */ 162166124Srafan 16376726SpeterNCURSES_EXPORT(SCREEN *) 164262629SdelphijNCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx 165262629Sdelphij NCURSES_CONST char *name, 166262629Sdelphij FILE *ofp, 167262629Sdelphij FILE *ifp) 16850276Speter{ 169166124Srafan int value; 17062449Speter int errret; 171262629Sdelphij SCREEN *result = 0; 17262449Speter SCREEN *current; 173184989Srafan TERMINAL *its_term; 174262629Sdelphij FILE *_ofp = ofp ? ofp : stdout; 175262629Sdelphij FILE *_ifp = ifp ? ifp : stdin; 176262629Sdelphij int cols; 177262629Sdelphij int slk_format; 178262629Sdelphij int filter_mode; 179262629Sdelphij TERMINAL *new_term = 0; 18050276Speter 181166124Srafan START_TRACE(); 182262629Sdelphij T((T_CALLED("newterm(%p, \"%s\", %p,%p)"), 183262629Sdelphij (void *) SP_PARM, 184262685Sdelphij (name ? name : ""), 185262629Sdelphij (void *) ofp, 186262629Sdelphij (void *) ifp)); 18750276Speter 188262629Sdelphij#if NCURSES_SP_FUNCS 189262629Sdelphij assert(SP_PARM != 0); 190262629Sdelphij if (SP_PARM == 0) 191262629Sdelphij returnSP(SP_PARM); 192262629Sdelphij#endif 193262629Sdelphij 194184989Srafan _nc_init_pthreads(); 195184989Srafan _nc_lock_global(curses); 196184989Srafan 197262629Sdelphij current = CURRENT_SCREEN; 198262629Sdelphij its_term = (current ? current->_term : 0); 199184989Srafan 200262629Sdelphij INIT_TERM_DRIVER(); 201166124Srafan /* this loads the capability entry, then sets LINES and COLS */ 202262629Sdelphij if ( 203262629Sdelphij#if NCURSES_SP_FUNCS 204262629Sdelphij SP_PARM->_prescreen && 205262629Sdelphij#endif 206262629Sdelphij TINFO_SETUP_TERM(&new_term, name, 207262629Sdelphij fileno(_ofp), &errret, FALSE) != ERR) { 208178866Srafan 209262629Sdelphij _nc_set_screen(0); 210262629Sdelphij#ifdef USE_TERM_DRIVER 211262629Sdelphij assert(new_term != 0); 212262629Sdelphij#endif 213262629Sdelphij 214262629Sdelphij#if NCURSES_SP_FUNCS 215262629Sdelphij slk_format = SP_PARM->slk_format; 216262629Sdelphij filter_mode = SP_PARM->_filtered; 217262629Sdelphij#else 218262629Sdelphij slk_format = _nc_globals.slk_format; 219262629Sdelphij filter_mode = _nc_prescreen.filter_mode; 220262629Sdelphij#endif 221262629Sdelphij 222166124Srafan /* 223166124Srafan * This actually allocates the screen structure, and saves the original 224166124Srafan * terminal settings. 225166124Srafan */ 226262629Sdelphij if (NCURSES_SP_NAME(_nc_setupscreen) ( 227262629Sdelphij#if NCURSES_SP_FUNCS 228262629Sdelphij &SP_PARM, 229262629Sdelphij#endif 230262629Sdelphij *(ptrLines(SP_PARM)), 231262629Sdelphij *(ptrCols(SP_PARM)), 232262629Sdelphij _ofp, 233262629Sdelphij filter_mode, 234262629Sdelphij slk_format) == ERR) { 235166124Srafan _nc_set_screen(current); 236166124Srafan result = 0; 237166124Srafan } else { 238262629Sdelphij#ifdef USE_TERM_DRIVER 239262629Sdelphij TERMINAL_CONTROL_BLOCK *TCB; 240262629Sdelphij#elif !NCURSES_SP_FUNCS 241262629Sdelphij _nc_set_screen(CURRENT_SCREEN); 242262629Sdelphij#endif 243262629Sdelphij assert(SP_PARM != 0); 244262629Sdelphij cols = *(ptrCols(SP_PARM)); 245262629Sdelphij#ifdef USE_TERM_DRIVER 246262629Sdelphij _nc_set_screen(SP_PARM); 247262629Sdelphij TCB = (TERMINAL_CONTROL_BLOCK *) new_term; 248262629Sdelphij TCB->csp = SP_PARM; 249262629Sdelphij#endif 250184989Srafan /* 251184989Srafan * In setupterm() we did a set_curterm(), but it was before we set 252262629Sdelphij * CURRENT_SCREEN. So the "current" screen's terminal pointer was 253262629Sdelphij * overwritten with a different terminal. Later, in 254262629Sdelphij * _nc_setupscreen(), we set CURRENT_SCREEN and the terminal 255262629Sdelphij * pointer in the new screen. 256184989Srafan * 257184989Srafan * Restore the terminal-pointer for the pre-existing screen, if 258184989Srafan * any. 259184989Srafan */ 260184989Srafan if (current) 261184989Srafan current->_term = its_term; 262184989Srafan 263262629Sdelphij#ifdef USE_TERM_DRIVER 264262629Sdelphij SP_PARM->_term = new_term; 265262629Sdelphij#else 266262629Sdelphij new_term = SP_PARM->_term; 267262629Sdelphij#endif 268262629Sdelphij 269262629Sdelphij /* allow user to set maximum escape delay from the environment */ 270262629Sdelphij if ((value = _nc_getenv_num("ESCDELAY")) >= 0) { 271262629Sdelphij NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value); 272262629Sdelphij } 273262629Sdelphij 274166124Srafan /* if the terminal type has real soft labels, set those up */ 275262629Sdelphij if (slk_format && NumLabels > 0 && SLK_STDFMT(slk_format)) 276262629Sdelphij _nc_slk_initialize(StdScreen(SP_PARM), cols); 27750276Speter 278262629Sdelphij SP_PARM->_ifd = fileno(_ifp); 279262629Sdelphij NCURSES_SP_NAME(typeahead) (NCURSES_SP_ARGx fileno(_ifp)); 28050276Speter#ifdef TERMIOS 281262629Sdelphij SP_PARM->_use_meta = ((new_term->Ottyb.c_cflag & CSIZE) == CS8 && 282262685Sdelphij !(new_term->Ottyb.c_iflag & ISTRIP)) || 283262685Sdelphij USE_KLIBC_KBD; 28450276Speter#else 285262629Sdelphij SP_PARM->_use_meta = FALSE; 28650276Speter#endif 287262629Sdelphij SP_PARM->_endwin = FALSE; 288262629Sdelphij#ifndef USE_TERM_DRIVER 289166124Srafan /* 290166124Srafan * Check whether we can optimize scrolling under dumb terminals in 291166124Srafan * case we do not have any of these capabilities, scrolling 292166124Srafan * optimization will be useless. 293166124Srafan */ 294262629Sdelphij SP_PARM->_scrolling = ((scroll_forward && scroll_reverse) || 295262629Sdelphij ((parm_rindex || 296262629Sdelphij parm_insert_line || 297262629Sdelphij insert_line) && 298262629Sdelphij (parm_index || 299262629Sdelphij parm_delete_line || 300262629Sdelphij delete_line))); 301262629Sdelphij#endif 30250276Speter 303262629Sdelphij NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); /* sets a field in the screen structure */ 30450276Speter 305262629Sdelphij SP_PARM->_keytry = 0; 30650276Speter 307262629Sdelphij /* compute movement costs so we can do better move optimization */ 308262629Sdelphij#ifdef USE_TERM_DRIVER 309262629Sdelphij TCBOf(SP_PARM)->drv->scinit(SP_PARM); 310262685Sdelphij#else /* ! USE_TERM_DRIVER */ 311166124Srafan /* 312166124Srafan * Check for mismatched graphic-rendition capabilities. Most SVr4 313166124Srafan * terminfo trees contain entries that have rmul or rmso equated to 314166124Srafan * sgr0 (Solaris curses copes with those entries). We do this only 315166124Srafan * for curses, since many termcap applications assume that 316166124Srafan * smso/rmso and smul/rmul are paired, and will not function 317166124Srafan * properly if we remove rmso or rmul. Curses applications 318166124Srafan * shouldn't be looking at this detail. 319166124Srafan */ 32050276Speter#define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) 321262629Sdelphij SP_PARM->_use_rmso = SGR0_TEST(exit_standout_mode); 322262629Sdelphij SP_PARM->_use_rmul = SGR0_TEST(exit_underline_mode); 323262685Sdelphij#if USE_ITALIC 324262685Sdelphij SP_PARM->_use_ritm = SGR0_TEST(exit_italics_mode); 325262685Sdelphij#endif 32650276Speter 327166124Srafan /* compute movement costs so we can do better move optimization */ 328166124Srafan _nc_mvcur_init(); 32950276Speter 330166124Srafan /* initialize terminal to a sane state */ 331166124Srafan _nc_screen_init(); 332262685Sdelphij#endif /* USE_TERM_DRIVER */ 33350276Speter 334166124Srafan /* Initialize the terminal line settings. */ 335262629Sdelphij _nc_initscr(NCURSES_SP_ARG); 33650276Speter 337166124Srafan _nc_signal_handler(TRUE); 338262629Sdelphij result = SP_PARM; 339166124Srafan } 340166124Srafan } 341184989Srafan _nc_unlock_global(curses); 342166124Srafan returnSP(result); 34350276Speter} 344262629Sdelphij 345262629Sdelphij#if NCURSES_SP_FUNCS 346262629SdelphijNCURSES_EXPORT(SCREEN *) 347262629Sdelphijnewterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) 348262629Sdelphij{ 349262629Sdelphij return NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp); 350262629Sdelphij} 351262629Sdelphij#endif 352