1 /**************************************************************************** 2 * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 * and: Thomas E. Dickey 1996-on * 33 * and: Juergen Pfeifer 2009 * 34 ****************************************************************************/ 35 36 /* 37 ** lib_newterm.c 38 ** 39 ** The newterm() function. 40 ** 41 */ 42 43 #include <curses.priv.h> 44 45 #ifndef CUR 46 #define CUR SP_TERMTYPE 47 #endif 48 49 #include <tic.h> 50 51 MODULE_ID("$Id: lib_newterm.c,v 1.92 2014/04/26 18:00:39 tom Exp $") 52 53 #ifdef USE_TERM_DRIVER 54 #define NumLabels InfoOf(SP_PARM).numlabels 55 #else 56 #define NumLabels num_labels 57 #endif 58 59 #ifndef ONLCR /* Allows compilation under the QNX 4.2 OS */ 60 #define ONLCR 0 61 #endif 62 63 /* 64 * SVr4/XSI Curses specify that hardware echo is turned off in initscr, and not 65 * restored during the curses session. The library simulates echo in software. 66 * (The behavior is unspecified if the application enables hardware echo). 67 * 68 * The newterm function also initializes terminal settings, and since initscr 69 * is supposed to behave as if it calls newterm, we do it here. 70 */ 71 static NCURSES_INLINE int 72 _nc_initscr(NCURSES_SP_DCL0) 73 { 74 int result = ERR; 75 TERMINAL *term = TerminalOf(SP_PARM); 76 77 /* for extended XPG4 conformance requires cbreak() at this point */ 78 /* (SVr4 curses does this anyway) */ 79 if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) { 80 TTY buf; 81 82 buf = term->Nttyb; 83 #ifdef TERMIOS 84 buf.c_lflag &= (unsigned) ~(ECHO | ECHONL); 85 buf.c_iflag &= (unsigned) ~(ICRNL | INLCR | IGNCR); 86 buf.c_oflag &= (unsigned) ~(ONLCR); 87 #elif HAVE_SGTTY_H 88 buf.sg_flags &= ~(ECHO | CRMOD); 89 #else 90 memset(&buf, 0, sizeof(buf)); 91 #endif 92 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); 93 if (result == OK) 94 term->Nttyb = buf; 95 } 96 return result; 97 } 98 99 /* 100 * filter() has to be called before either initscr() or newterm(), so there is 101 * apparently no way to make this flag apply to some terminals and not others, 102 * aside from possibly delaying a filter() call until some terminals have been 103 * initialized. 104 */ 105 NCURSES_EXPORT(void) 106 NCURSES_SP_NAME(filter) (NCURSES_SP_DCL0) 107 { 108 START_TRACE(); 109 T((T_CALLED("filter(%p)"), (void *) SP_PARM)); 110 #if NCURSES_SP_FUNCS 111 if (IsPreScreen(SP_PARM)) { 112 SP_PARM->_filtered = TRUE; 113 } 114 #else 115 _nc_prescreen.filter_mode = TRUE; 116 #endif 117 returnVoid; 118 } 119 120 #if NCURSES_SP_FUNCS 121 NCURSES_EXPORT(void) 122 filter(void) 123 { 124 START_TRACE(); 125 T((T_CALLED("filter()"))); 126 _nc_prescreen.filter_mode = TRUE; 127 returnVoid; 128 } 129 #endif 130 131 #if NCURSES_EXT_FUNCS 132 /* 133 * An extension, allowing the application to open a new screen without 134 * requiring it to also be filtered. 135 */ 136 NCURSES_EXPORT(void) 137 NCURSES_SP_NAME(nofilter) (NCURSES_SP_DCL0) 138 { 139 START_TRACE(); 140 T((T_CALLED("nofilter(%p)"), (void *) SP_PARM)); 141 #if NCURSES_SP_FUNCS 142 if (IsPreScreen(SP_PARM)) { 143 SP_PARM->_filtered = FALSE; 144 } 145 #else 146 _nc_prescreen.filter_mode = FALSE; 147 #endif 148 returnVoid; 149 } 150 151 #if NCURSES_SP_FUNCS 152 NCURSES_EXPORT(void) 153 nofilter(void) 154 { 155 START_TRACE(); 156 T((T_CALLED("nofilter()"))); 157 _nc_prescreen.filter_mode = FALSE; 158 returnVoid; 159 } 160 #endif 161 #endif /* NCURSES_EXT_FUNCS */ 162 163 NCURSES_EXPORT(SCREEN *) 164 NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx 165 NCURSES_CONST char *name, 166 FILE *ofp, 167 FILE *ifp) 168 { 169 int value; 170 int errret; 171 SCREEN *result = 0; 172 SCREEN *current; 173 TERMINAL *its_term; 174 FILE *_ofp = ofp ? ofp : stdout; 175 FILE *_ifp = ifp ? ifp : stdin; 176 int cols; 177 int slk_format; 178 int filter_mode; 179 TERMINAL *new_term = 0; 180 181 START_TRACE(); 182 T((T_CALLED("newterm(%p, \"%s\", %p,%p)"), 183 (void *) SP_PARM, 184 (name ? name : ""), 185 (void *) ofp, 186 (void *) ifp)); 187 188 #if NCURSES_SP_FUNCS 189 assert(SP_PARM != 0); 190 if (SP_PARM == 0) 191 returnSP(SP_PARM); 192 #endif 193 194 _nc_init_pthreads(); 195 _nc_lock_global(curses); 196 197 current = CURRENT_SCREEN; 198 its_term = (current ? current->_term : 0); 199 200 INIT_TERM_DRIVER(); 201 /* this loads the capability entry, then sets LINES and COLS */ 202 if ( 203 TINFO_SETUP_TERM(&new_term, name, 204 fileno(_ofp), &errret, FALSE) != ERR) { 205 206 _nc_set_screen(0); 207 #ifdef USE_TERM_DRIVER 208 assert(new_term != 0); 209 #endif 210 211 #if NCURSES_SP_FUNCS 212 slk_format = SP_PARM->slk_format; 213 filter_mode = SP_PARM->_filtered; 214 #else 215 slk_format = _nc_globals.slk_format; 216 filter_mode = _nc_prescreen.filter_mode; 217 #endif 218 219 /* 220 * This actually allocates the screen structure, and saves the original 221 * terminal settings. 222 */ 223 if (NCURSES_SP_NAME(_nc_setupscreen) ( 224 #if NCURSES_SP_FUNCS 225 &SP_PARM, 226 #endif 227 *(ptrLines(SP_PARM)), 228 *(ptrCols(SP_PARM)), 229 _ofp, 230 filter_mode, 231 slk_format) == ERR) { 232 _nc_set_screen(current); 233 result = 0; 234 } else { 235 #ifdef USE_TERM_DRIVER 236 TERMINAL_CONTROL_BLOCK *TCB; 237 #elif !NCURSES_SP_FUNCS 238 _nc_set_screen(CURRENT_SCREEN); 239 #endif 240 assert(SP_PARM != 0); 241 cols = *(ptrCols(SP_PARM)); 242 #ifdef USE_TERM_DRIVER 243 _nc_set_screen(SP_PARM); 244 TCB = (TERMINAL_CONTROL_BLOCK *) new_term; 245 TCB->csp = SP_PARM; 246 #endif 247 /* 248 * In setupterm() we did a set_curterm(), but it was before we set 249 * CURRENT_SCREEN. So the "current" screen's terminal pointer was 250 * overwritten with a different terminal. Later, in 251 * _nc_setupscreen(), we set CURRENT_SCREEN and the terminal 252 * pointer in the new screen. 253 * 254 * Restore the terminal-pointer for the pre-existing screen, if 255 * any. 256 */ 257 if (current) 258 current->_term = its_term; 259 260 #ifdef USE_TERM_DRIVER 261 SP_PARM->_term = new_term; 262 #else 263 new_term = SP_PARM->_term; 264 #endif 265 266 /* allow user to set maximum escape delay from the environment */ 267 if ((value = _nc_getenv_num("ESCDELAY")) >= 0) { 268 NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value); 269 } 270 271 /* if the terminal type has real soft labels, set those up */ 272 if (slk_format && NumLabels > 0 && SLK_STDFMT(slk_format)) 273 _nc_slk_initialize(StdScreen(SP_PARM), cols); 274 275 SP_PARM->_ifd = fileno(_ifp); 276 NCURSES_SP_NAME(typeahead) (NCURSES_SP_ARGx fileno(_ifp)); 277 #ifdef TERMIOS 278 SP_PARM->_use_meta = ((new_term->Ottyb.c_cflag & CSIZE) == CS8 && 279 !(new_term->Ottyb.c_iflag & ISTRIP)) || 280 USE_KLIBC_KBD; 281 #else 282 SP_PARM->_use_meta = FALSE; 283 #endif 284 SP_PARM->_endwin = FALSE; 285 #ifndef USE_TERM_DRIVER 286 /* 287 * Check whether we can optimize scrolling under dumb terminals in 288 * case we do not have any of these capabilities, scrolling 289 * optimization will be useless. 290 */ 291 SP_PARM->_scrolling = ((scroll_forward && scroll_reverse) || 292 ((parm_rindex || 293 parm_insert_line || 294 insert_line) && 295 (parm_index || 296 parm_delete_line || 297 delete_line))); 298 #endif 299 300 NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); /* sets a field in the screen structure */ 301 302 SP_PARM->_keytry = 0; 303 304 /* compute movement costs so we can do better move optimization */ 305 #ifdef USE_TERM_DRIVER 306 TCBOf(SP_PARM)->drv->td_scinit(SP_PARM); 307 #else /* ! USE_TERM_DRIVER */ 308 /* 309 * Check for mismatched graphic-rendition capabilities. Most SVr4 310 * terminfo trees contain entries that have rmul or rmso equated to 311 * sgr0 (Solaris curses copes with those entries). We do this only 312 * for curses, since many termcap applications assume that 313 * smso/rmso and smul/rmul are paired, and will not function 314 * properly if we remove rmso or rmul. Curses applications 315 * shouldn't be looking at this detail. 316 */ 317 #define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) 318 SP_PARM->_use_rmso = SGR0_TEST(exit_standout_mode); 319 SP_PARM->_use_rmul = SGR0_TEST(exit_underline_mode); 320 #if USE_ITALIC 321 SP_PARM->_use_ritm = SGR0_TEST(exit_italics_mode); 322 #endif 323 324 /* compute movement costs so we can do better move optimization */ 325 _nc_mvcur_init(); 326 327 /* initialize terminal to a sane state */ 328 _nc_screen_init(); 329 #endif /* USE_TERM_DRIVER */ 330 331 /* Initialize the terminal line settings. */ 332 _nc_initscr(NCURSES_SP_ARG); 333 334 _nc_signal_handler(TRUE); 335 result = SP_PARM; 336 } 337 } 338 _nc_unlock_global(curses); 339 returnSP(result); 340 } 341 342 #if NCURSES_SP_FUNCS 343 NCURSES_EXPORT(SCREEN *) 344 newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) 345 { 346 return NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp); 347 } 348 #endif 349