Line data Source code
1 : /* 2 : Mosh: the mobile shell 3 : Copyright 2012 Keith Winstein 4 : 5 : This program is free software: you can redistribute it and/or modify 6 : it under the terms of the GNU General Public License as published by 7 : the Free Software Foundation, either version 3 of the License, or 8 : (at your option) any later version. 9 : 10 : This program is distributed in the hope that it will be useful, 11 : but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : GNU General Public License for more details. 14 : 15 : You should have received a copy of the GNU General Public License 16 : along with this program. If not, see <http://www.gnu.org/licenses/>. 17 : 18 : In addition, as a special exception, the copyright holders give 19 : permission to link the code of portions of this program with the 20 : OpenSSL library under certain conditions as described in each 21 : individual source file, and distribute linked combinations including 22 : the two. 23 : 24 : You must obey the GNU General Public License in all respects for all 25 : of the code used other than OpenSSL. If you modify file(s) with this 26 : exception, you may extend this exception to your version of the 27 : file(s), but you are not obligated to do so. If you do not wish to do 28 : so, delete this exception statement from your version. If you delete 29 : this exception statement from all source files in the program, then 30 : also delete it here. 31 : */ 32 : 33 : /* This is in its own file because otherwise the ncurses #defines 34 : alias our own variable names. */ 35 : 36 : #include "config.h" 37 : #include "terminaldisplay.h" 38 : 39 : #include <string> 40 : #include <stdexcept> 41 : 42 : #if defined HAVE_NCURSESW_CURSES_H 43 : # include <ncursesw/curses.h> 44 : # include <ncursesw/term.h> 45 : #elif defined HAVE_NCURSESW_H 46 : # include <ncursesw.h> 47 : # include <term.h> 48 : #elif defined HAVE_NCURSES_CURSES_H 49 : # include <ncurses/curses.h> 50 : # include <ncurses/term.h> 51 : #elif defined HAVE_NCURSES_H 52 : # include <ncurses.h> 53 : # include <term.h> 54 : #elif defined HAVE_CURSES_H 55 : # include <curses.h> 56 : # include <term.h> 57 : #else 58 : # error "SysV or X/Open-compatible Curses header file required" 59 : #endif 60 : #include <stdlib.h> 61 : #include <string.h> 62 : 63 : using namespace Terminal; 64 : 65 448 : static bool ti_flag( const char *capname ) 66 : { 67 448 : int val = tigetflag( const_cast<char *>( capname ) ); 68 448 : if ( val == -1 ) { 69 0 : throw std::invalid_argument( std::string( "Invalid terminfo boolean capability " ) + capname ); 70 : } 71 448 : return val; 72 : } 73 : 74 1344 : static const char *ti_str( const char *capname ) 75 : { 76 1344 : const char *val = tigetstr( const_cast<char *>( capname ) ); 77 1344 : if ( val == (const char *)-1 ) { 78 0 : throw std::invalid_argument( std::string( "Invalid terminfo string capability " ) + capname ); 79 : } 80 1344 : return val; 81 : } 82 : 83 12102 : Display::Display( bool use_environment ) 84 12102 : : has_ech( true ), has_bce( true ), has_title( true ), smcup( NULL ), rmcup( NULL ) 85 : { 86 12102 : if ( use_environment ) { 87 448 : int errret = -2; 88 448 : int ret = setupterm( (char *)0, 1, &errret ); 89 : 90 448 : if ( ret != OK ) { 91 0 : switch ( errret ) { 92 0 : case 1: 93 0 : throw std::runtime_error( "Terminal is hardcopy and cannot be used by curses applications." ); 94 0 : break; 95 0 : case 0: 96 0 : throw std::runtime_error( "Unknown terminal type." ); 97 0 : break; 98 0 : case -1: 99 0 : throw std::runtime_error( "Terminfo database could not be found." ); 100 0 : break; 101 0 : default: 102 0 : throw std::runtime_error( "Unknown terminfo error." ); 103 448 : break; 104 : } 105 : } 106 : 107 : /* check for ECH */ 108 448 : has_ech = ti_str( "ech" ); 109 : 110 : /* check for BCE */ 111 448 : has_bce = ti_flag( "bce" ); 112 : 113 : /* Check if we can set the window title and icon name. terminfo does not 114 : have reliable information on this, so we hardcode a whitelist of 115 : terminal type prefixes. */ 116 448 : static const char * const title_term_types[] = { 117 : "xterm", "rxvt", "kterm", "Eterm", "alacritty", "screen", "tmux" 118 : }; 119 : 120 448 : has_title = false; 121 448 : const char *term_type = getenv( "TERM" ); 122 448 : if ( term_type ) { 123 2230 : for ( size_t i = 0; 124 2678 : i < sizeof( title_term_types ) / sizeof( const char * ); 125 : i++ ) { 126 2678 : if ( 0 == strncmp( term_type, title_term_types[ i ], 127 2678 : strlen( title_term_types[ i ] ) ) ) { 128 448 : has_title = true; 129 448 : break; 130 : } 131 : } 132 : } 133 : 134 448 : if ( !getenv( "MOSH_NO_TERM_INIT" ) ) { 135 448 : smcup = ti_str("smcup"); 136 448 : rmcup = ti_str("rmcup"); 137 : } 138 : } 139 12102 : }