2017-11-04 07:03:53 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* fterm.cpp - Base class for terminal detection and control *
|
|
|
|
* *
|
|
|
|
* This file is part of the Final Cut widget toolkit *
|
|
|
|
* *
|
2018-01-02 20:38:45 +01:00
|
|
|
* Copyright 2012-2018 Markus Gans *
|
2017-11-04 07:03:53 +01:00
|
|
|
* *
|
|
|
|
* The Final Cut is free software; you can redistribute it and/or *
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License *
|
|
|
|
* as published by the Free Software Foundation; either version 3 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* The Final Cut is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU Lesser General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
|
|
* License along with this program. If not, see *
|
|
|
|
* <http://www.gnu.org/licenses/>. *
|
|
|
|
***********************************************************************/
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
#include <algorithm>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2017-09-17 21:32:46 +02:00
|
|
|
#include "final/fterm.h"
|
|
|
|
#include "final/fcharmap.h"
|
|
|
|
#include "final/fkey_map.h"
|
|
|
|
#include "final/ftcap_map.h"
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2017-11-02 16:05:34 +01:00
|
|
|
#include "../fonts/newfont.h"
|
|
|
|
#include "../fonts/unicodemap.h"
|
|
|
|
#include "../fonts/vgafont.h"
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2015-05-23 13:35:12 +02:00
|
|
|
|
|
|
|
// global FTerm object
|
2016-10-11 04:57:36 +02:00
|
|
|
static FTerm* init_term_object = 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
|
|
|
// global init state
|
|
|
|
static bool term_initialized = false;
|
|
|
|
|
|
|
|
// function pointer
|
|
|
|
int (*FTerm::Fputchar)(int);
|
|
|
|
|
|
|
|
// static class attributes
|
|
|
|
int FTerm::fd_tty;
|
|
|
|
int FTerm::stdin_status_flags;
|
2016-12-15 23:11:34 +01:00
|
|
|
int FTerm::erase_ch_length;
|
|
|
|
int FTerm::repeat_char_length;
|
2016-12-11 16:42:50 +01:00
|
|
|
int FTerm::clr_bol_length;
|
|
|
|
int FTerm::clr_eol_length;
|
2016-12-15 23:11:34 +01:00
|
|
|
int FTerm::cursor_addres_lengths;
|
2015-05-23 13:35:12 +02:00
|
|
|
uInt FTerm::baudrate;
|
2018-01-03 08:42:10 +01:00
|
|
|
long FTerm::key_timeout;
|
2015-05-23 13:35:12 +02:00
|
|
|
bool FTerm::resize_term;
|
2018-05-02 12:31:21 +02:00
|
|
|
|
2015-10-03 01:45:13 +02:00
|
|
|
bool FTerm::input_data_pending;
|
2015-05-23 13:35:12 +02:00
|
|
|
bool FTerm::non_blocking_stdin;
|
|
|
|
bool FTerm::color256;
|
|
|
|
bool FTerm::monochron;
|
|
|
|
bool FTerm::pc_charset_console;
|
|
|
|
bool FTerm::utf8_input;
|
|
|
|
bool FTerm::utf8_state;
|
|
|
|
bool FTerm::utf8_console;
|
|
|
|
bool FTerm::utf8_linux_terminal;
|
|
|
|
bool FTerm::force_vt100;
|
|
|
|
bool FTerm::vt100_console;
|
|
|
|
bool FTerm::ascii_console;
|
|
|
|
bool FTerm::NewFont;
|
|
|
|
bool FTerm::VGAFont;
|
2016-11-13 22:08:40 +01:00
|
|
|
bool FTerm::no_shadow_character;
|
|
|
|
bool FTerm::no_half_block_character;
|
2015-12-21 18:37:20 +01:00
|
|
|
bool FTerm::cursor_optimisation;
|
2016-11-06 16:36:21 +01:00
|
|
|
bool FTerm::xterm_default_colors;
|
2017-03-26 20:40:04 +02:00
|
|
|
bool FTerm::use_alternate_screen = true;
|
2018-05-02 12:31:21 +02:00
|
|
|
char FTerm::termtype[256] = {};
|
2018-02-11 23:41:23 +01:00
|
|
|
char FTerm::termfilename[256] = {};
|
2017-03-26 21:10:43 +02:00
|
|
|
#if DEBUG
|
2017-11-24 00:28:25 +01:00
|
|
|
int FTerm::framebuffer_bpp = -1;
|
2017-03-26 21:10:43 +02:00
|
|
|
#endif
|
2015-05-23 13:35:12 +02:00
|
|
|
char* FTerm::locale_name = 0;
|
|
|
|
char* FTerm::locale_xterm = 0;
|
|
|
|
FRect* FTerm::term = 0;
|
|
|
|
|
2016-10-13 02:16:51 +02:00
|
|
|
char FTerm::exit_message[8192] = "";
|
2017-11-18 02:34:41 +01:00
|
|
|
fc::encoding FTerm::term_encoding;
|
2016-10-13 02:16:51 +02:00
|
|
|
const FString* FTerm::xterm_font = 0;
|
|
|
|
const FString* FTerm::xterm_title = 0;
|
|
|
|
FOptiMove* FTerm::opti_move = 0;
|
|
|
|
FOptiAttr* FTerm::opti_attr = 0;
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermDetection* FTerm::term_detection = 0;
|
2018-01-14 21:21:08 +01:00
|
|
|
FMouseControl* FTerm::mouse = 0;
|
2016-10-13 02:16:51 +02:00
|
|
|
std::map<uChar,uChar>* FTerm::vt100_alt_char = 0;
|
2015-10-23 00:24:20 +02:00
|
|
|
std::map<std::string,fc::encoding>* \
|
2016-10-13 02:16:51 +02:00
|
|
|
FTerm::encoding_set = 0;
|
2017-12-17 01:06:53 +01:00
|
|
|
FTerm::termcap_map* FTerm::tcap = fc::term_caps;
|
2016-10-13 02:16:51 +02:00
|
|
|
bool FTermcap::background_color_erase = false;
|
|
|
|
bool FTermcap::automatic_left_margin = false;
|
|
|
|
bool FTermcap::automatic_right_margin = false;
|
|
|
|
bool FTermcap::eat_nl_glitch = false;
|
|
|
|
bool FTermcap::ansi_default_color = false;
|
|
|
|
bool FTermcap::osc_support = false;
|
2017-02-07 17:15:01 +01:00
|
|
|
bool FTermcap::no_utf8_acs_chars = false;
|
2016-10-13 02:16:51 +02:00
|
|
|
int FTermcap::max_color = 1;
|
2017-03-26 20:40:04 +02:00
|
|
|
int FTermcap::tabstop = 8;
|
|
|
|
int FTermcap::attr_without_color = 0;
|
2018-01-02 20:38:45 +01:00
|
|
|
FTerm::colorEnv FTerm::color_env;
|
2018-04-19 01:55:17 +02:00
|
|
|
FTerm::secondaryDA FTerm::secondary_da;
|
2017-12-03 21:06:21 +01:00
|
|
|
FTerm::initializationValues FTerm::init_values;
|
2017-04-09 20:08:53 +02:00
|
|
|
fc::linuxConsoleCursorStyle FTerm::linux_console_cursor_style;
|
|
|
|
fc::freebsdConsoleCursorStyle FTerm::freebsd_console_cursor_style;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2017-12-02 19:06:27 +01:00
|
|
|
FTerm::modifier_key FTerm::mod_key;
|
2017-03-26 20:40:04 +02:00
|
|
|
console_font_op FTerm::screen_font;
|
|
|
|
unimapdesc FTerm::screen_unicode_map;
|
|
|
|
#endif
|
|
|
|
|
2017-04-14 23:55:44 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
uInt FTerm::bsd_alt_keymap = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
kbd_t FTerm::wscons_keyboard_encoding = 0;
|
|
|
|
#endif
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// class FTerm
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
// constructors and destructor
|
|
|
|
//----------------------------------------------------------------------
|
2017-03-26 20:40:04 +02:00
|
|
|
FTerm::FTerm (bool disable_alt_screen)
|
2016-10-17 08:44:38 +02:00
|
|
|
: color_map()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-10-13 02:16:51 +02:00
|
|
|
resize_term = false;
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
if ( ! term_initialized )
|
2017-03-26 20:40:04 +02:00
|
|
|
{
|
|
|
|
use_alternate_screen = ! disable_alt_screen;
|
2015-05-23 13:35:12 +02:00
|
|
|
init();
|
2017-03-26 20:40:04 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FTerm::~FTerm() // destructor
|
|
|
|
{
|
2016-10-11 04:57:36 +02:00
|
|
|
if ( init_term_object == this )
|
|
|
|
finish();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// public methods of FTerm
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
int FTerm::getLineNumber()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( term->getHeight() == 0 )
|
|
|
|
detectTermSize();
|
|
|
|
|
|
|
|
return term->getHeight();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
int FTerm::getColumnNumber()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( term->getWidth() == 0 )
|
|
|
|
detectTermSize();
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return term->getWidth();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-10-17 08:44:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-03-17 22:59:06 +01:00
|
|
|
const FString FTerm::getKeyName (int keynum)
|
2016-10-17 08:44:38 +02:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; fc::FkeyName[i].string[0] != 0; i++)
|
|
|
|
if ( fc::FkeyName[i].num && fc::FkeyName[i].num == keynum )
|
|
|
|
return FString(fc::FkeyName[i].string);
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( keynum > 32 && keynum < 127 )
|
|
|
|
return FString(char(keynum));
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return FString("");
|
2016-10-17 08:44:38 +02:00
|
|
|
}
|
|
|
|
|
2018-01-14 21:21:08 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FMouseControl* FTerm::getMouseControl()
|
|
|
|
{
|
|
|
|
if ( mouse )
|
|
|
|
return mouse;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2016-10-17 08:44:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-14 23:55:44 +02:00
|
|
|
FTerm::modifier_key& FTerm::getLinuxModifierKey()
|
2016-10-17 08:44:38 +02:00
|
|
|
{
|
2017-12-02 18:52:51 +01:00
|
|
|
// Get Linux console shift state
|
|
|
|
|
|
|
|
char subcode = 6; // Shift state command + return value
|
2017-07-03 16:56:32 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// fill bit field with 0
|
|
|
|
std::memset (&mod_key, 0x00, sizeof(mod_key));
|
|
|
|
|
2017-10-02 07:32:33 +02:00
|
|
|
// TIOCLINUX, subcode = 6
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ioctl(0, TIOCLINUX, &subcode) >= 0 )
|
|
|
|
{
|
|
|
|
if ( subcode & (1 << KG_SHIFT) )
|
|
|
|
mod_key.shift = true;
|
|
|
|
|
|
|
|
if ( subcode & (1 << KG_ALTGR) )
|
|
|
|
mod_key.alt_gr = true;
|
|
|
|
|
|
|
|
if ( subcode & (1 << KG_CTRL) )
|
|
|
|
mod_key.ctrl = true;
|
|
|
|
|
|
|
|
if ( subcode & (1 << KG_ALT) )
|
|
|
|
mod_key.alt = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mod_key;
|
2016-10-17 08:44:38 +02:00
|
|
|
}
|
2017-04-06 01:31:21 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
fc::linuxConsoleCursorStyle FTerm::getLinuxConsoleCursorStyle()
|
|
|
|
{
|
|
|
|
return linux_console_cursor_style;
|
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2016-10-17 08:44:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
fc::freebsdConsoleCursorStyle FTerm::getFreeBSDConsoleCursorStyle()
|
2016-10-17 08:44:38 +02:00
|
|
|
{
|
2017-04-09 20:08:53 +02:00
|
|
|
return freebsd_console_cursor_style;
|
2016-10-17 08:44:38 +02:00
|
|
|
}
|
2017-04-06 01:31:21 +02:00
|
|
|
#endif
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-26 15:18:44 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::isNormal (char_data*& ch)
|
|
|
|
{
|
|
|
|
return opti_attr->isNormal(ch);
|
|
|
|
}
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setTermType (char term_name[])
|
|
|
|
{
|
|
|
|
if ( ! term_name )
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::strncpy ( termtype
|
|
|
|
, term_name
|
|
|
|
, std::strlen(term_name) + 1 );
|
|
|
|
}
|
|
|
|
|
2017-04-06 01:31:21 +02:00
|
|
|
#if defined(__linux__)
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-06 01:31:21 +02:00
|
|
|
void FTerm::setLinuxConsoleCursorStyle ( fc::linuxConsoleCursorStyle style
|
|
|
|
, bool hidden )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// Set cursor style in linux console
|
2017-04-06 01:31:21 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2017-04-06 01:31:21 +02:00
|
|
|
linux_console_cursor_style = style;
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( hidden )
|
|
|
|
return;
|
|
|
|
|
|
|
|
putstringf (CSI "?%dc", style);
|
|
|
|
std::fflush(stdout);
|
2016-10-17 08:44:38 +02:00
|
|
|
}
|
2017-04-06 01:31:21 +02:00
|
|
|
#endif
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2017-04-06 01:31:21 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
void FTerm::setFreeBSDConsoleCursorStyle ( fc::freebsdConsoleCursorStyle style
|
|
|
|
, bool hidden )
|
2017-04-06 01:31:21 +02:00
|
|
|
{
|
|
|
|
// Set cursor style in a BSD console
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
if ( ! isFreeBSDConsole() )
|
2017-04-06 01:31:21 +02:00
|
|
|
return;
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
freebsd_console_cursor_style = style;
|
2017-04-06 01:31:21 +02:00
|
|
|
|
|
|
|
if ( hidden )
|
|
|
|
return;
|
|
|
|
|
|
|
|
ioctl(0, CONS_CURSORTYPE, &style);
|
|
|
|
}
|
|
|
|
#endif
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2018-01-16 16:16:29 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setDblclickInterval (const long timeout)
|
|
|
|
{
|
|
|
|
mouse->setDblclickInterval(timeout);
|
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-09-11 03:06:02 +02:00
|
|
|
bool FTerm::setUTF8 (bool on) // UTF-8 (Unicode)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( on == utf8_state )
|
|
|
|
return utf8_state;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( on )
|
|
|
|
utf8_state = true;
|
|
|
|
else
|
|
|
|
utf8_state = false;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( on )
|
|
|
|
putstring (ESC "%G");
|
|
|
|
else
|
|
|
|
putstring (ESC "%@");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::fflush(stdout);
|
|
|
|
return utf8_state;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
bool FTerm::setNonBlockingInput (bool on)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( on == non_blocking_stdin )
|
|
|
|
return non_blocking_stdin;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( on ) // make stdin non-blocking
|
|
|
|
{
|
|
|
|
stdin_status_flags |= O_NONBLOCK;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( fcntl (FTermios::getStdIn(), F_SETFL, stdin_status_flags) != -1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
non_blocking_stdin = true;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
stdin_status_flags &= ~O_NONBLOCK;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( fcntl (FTermios::getStdIn(), F_SETFL, stdin_status_flags) != -1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
non_blocking_stdin = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return non_blocking_stdin;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-05-01 21:45:27 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-20 18:26:15 +01:00
|
|
|
int FTerm::parseKeyString ( char buffer[]
|
2016-11-02 00:37:58 +01:00
|
|
|
, int buf_size
|
|
|
|
, timeval* time_keypressed )
|
|
|
|
{
|
2018-01-03 08:42:10 +01:00
|
|
|
uChar firstchar = uChar(buffer[0]);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( firstchar == ESC[0] )
|
2016-05-01 21:45:27 +02:00
|
|
|
{
|
2018-01-03 08:42:10 +01:00
|
|
|
int key = getMouseProtocolKey(buffer);
|
2016-05-16 21:11:32 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
if ( key > 0 )
|
|
|
|
return key;
|
2016-05-01 21:45:27 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
key = getTermcapKey(buffer, buf_size);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
if ( key > 0 )
|
|
|
|
return key;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
key = getMetaKey(buffer, buf_size, time_keypressed);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
if ( key > 0 )
|
|
|
|
return key;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
if ( ! isKeypressTimeout(time_keypressed) )
|
2016-11-02 00:37:58 +01:00
|
|
|
return NEED_MORE_DATA;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
return getSingleKey(buffer, buf_size);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
bool& FTerm::unprocessedInput()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
return input_data_pending;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setVGAFont()
|
|
|
|
{
|
|
|
|
if ( VGAFont )
|
|
|
|
return VGAFont;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isGnomeTerminal()
|
|
|
|
|| isKdeTerminal()
|
|
|
|
|| isPuttyTerminal()
|
|
|
|
|| isTeraTerm()
|
|
|
|
|| isCygwinTerminal()
|
|
|
|
|| isMinttyTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
VGAFont = true;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set font in xterm to vga
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "50;vga" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
NewFont = false;
|
|
|
|
pc_charset_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::PC;
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() && utf8_console )
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_UTF8;
|
|
|
|
else
|
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
else if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( openConsole() == 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-03-28 08:50:37 +02:00
|
|
|
if ( isLinuxConsole() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// standard vga font 8x16
|
2017-12-17 01:06:53 +01:00
|
|
|
int ret = setScreenFont(fc::__8x16std, 256, 8, 16);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 )
|
|
|
|
VGAFont = false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// unicode character mapping
|
|
|
|
struct unimapdesc unimap;
|
2017-12-17 01:06:53 +01:00
|
|
|
unimap.entry_ct = uChar ( sizeof(fc::unicode_cp437_pairs)
|
2016-11-02 00:37:58 +01:00
|
|
|
/ sizeof(unipair) );
|
2017-12-17 01:06:53 +01:00
|
|
|
unimap.entries = &fc::unicode_cp437_pairs[0];
|
2016-11-02 00:37:58 +01:00
|
|
|
setUnicodeMap(&unimap);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
VGAFont = false;
|
|
|
|
|
|
|
|
detectTermSize();
|
|
|
|
closeConsole();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
VGAFont = false;
|
|
|
|
|
|
|
|
pc_charset_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::PC;
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
|
|
|
VGAFont = false;
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return VGAFont;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
bool FTerm::setNewFont()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( NewFont )
|
|
|
|
return true;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isGnomeTerminal()
|
|
|
|
|| isKdeTerminal()
|
|
|
|
|| isPuttyTerminal()
|
|
|
|
|| isTeraTerm()
|
|
|
|
|| isCygwinTerminal()
|
|
|
|
|| isMinttyTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
NewFont = true;
|
|
|
|
// Set font in xterm to 8x16graph
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "50;8x16graph" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
pc_charset_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::PC;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() && utf8_console )
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_UTF8;
|
|
|
|
else
|
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
else if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
NewFont = true;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( openConsole() == 0 )
|
|
|
|
{
|
2017-03-28 08:50:37 +02:00
|
|
|
if ( isLinuxConsole() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
struct unimapdesc unimap;
|
|
|
|
int ret;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set the graphical font 8x16
|
2017-12-17 01:06:53 +01:00
|
|
|
ret = setScreenFont(fc::__8x16graph, 256, 8, 16);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 )
|
|
|
|
NewFont = false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// unicode character mapping
|
2017-12-17 01:06:53 +01:00
|
|
|
unimap.entry_ct = uInt16 ( sizeof(fc::unicode_cp437_pairs)
|
2016-11-02 00:37:58 +01:00
|
|
|
/ sizeof(unipair) );
|
2017-12-17 01:06:53 +01:00
|
|
|
unimap.entries = &fc::unicode_cp437_pairs[0];
|
2016-11-02 00:37:58 +01:00
|
|
|
setUnicodeMap(&unimap);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
detectTermSize();
|
|
|
|
closeConsole();
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
pc_charset_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::PC;
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
|
|
|
NewFont = false;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return NewFont;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
bool FTerm::setOldFont()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
bool retval;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! (NewFont || VGAFont) )
|
|
|
|
return false;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
retval = \
|
|
|
|
NewFont = \
|
|
|
|
VGAFont = false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( xterm_font && xterm_font->getLength() > 2 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// restore saved xterm font
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "50;%s" BEL, xterm_font->c_str() );
|
|
|
|
oscPostfix();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set font in xterm to vga
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "50;vga" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
retval = true;
|
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
else if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( openConsole() == 0 )
|
|
|
|
{
|
2017-03-28 08:50:37 +02:00
|
|
|
if ( isLinuxConsole() )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( screen_font.data )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
int ret = setScreenFont ( screen_font.data
|
|
|
|
, screen_font.charcount
|
|
|
|
, screen_font.width
|
|
|
|
, screen_font.height
|
|
|
|
, true );
|
|
|
|
delete[] screen_font.data;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
|
|
|
retval = true;
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( screen_unicode_map.entries )
|
|
|
|
{
|
|
|
|
setUnicodeMap (&screen_unicode_map);
|
|
|
|
delete[] screen_unicode_map.entries;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
detectTermSize();
|
|
|
|
closeConsole();
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return retval;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-10-11 04:57:36 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
char* FTerm::moveCursor (int xold, int yold, int xnew, int ynew)
|
2016-10-11 04:57:36 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// returns the cursor move string
|
|
|
|
if ( cursor_optimisation )
|
|
|
|
return opti_move->moveCursor (xold, yold, xnew, ynew);
|
|
|
|
else
|
2017-09-11 03:06:02 +02:00
|
|
|
return tgoto(TCAP(fc::t_cursor_address), xnew, ynew);
|
2016-10-11 04:57:36 +02:00
|
|
|
}
|
|
|
|
|
2016-11-26 15:18:44 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::printMoveDurations()
|
|
|
|
{
|
|
|
|
opti_move->printDurations();
|
|
|
|
}
|
|
|
|
|
2016-10-11 04:57:36 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
char* FTerm::enableCursor()
|
2016-10-11 04:57:36 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
char*& vs = TCAP(fc::t_cursor_visible);
|
|
|
|
char*& ve = TCAP(fc::t_cursor_normal);
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ve )
|
|
|
|
return ve;
|
|
|
|
else if ( vs )
|
|
|
|
return vs;
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return 0;
|
2016-10-11 04:57:36 +02:00
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
char* FTerm::disableCursor()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
char*& vi = TCAP(fc::t_cursor_invisible);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( vi )
|
|
|
|
return vi;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-07-23 19:50:28 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::detectTermSize()
|
2016-07-23 19:50:28 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
struct winsize win_size;
|
|
|
|
bool close_after_detect = false;
|
|
|
|
int ret;
|
2016-07-23 19:50:28 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 ) // console is already closed
|
2016-07-23 19:50:28 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( openConsole() != 0 )
|
|
|
|
return;
|
2016-07-23 19:50:28 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
close_after_detect = true;
|
2016-07-23 19:50:28 +02:00
|
|
|
}
|
2016-10-13 02:16:51 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
ret = ioctl (fd_tty, TIOCGWINSZ, &win_size);
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 || win_size.ws_col == 0 || win_size.ws_row == 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
char* str;
|
|
|
|
term->setPos(1,1);
|
2017-07-03 16:56:32 +02:00
|
|
|
// Use COLUMNS or fallback to the xterm default width of 80 characters
|
2016-11-02 00:37:58 +01:00
|
|
|
str = std::getenv("COLUMNS");
|
|
|
|
term->setWidth(str ? std::atoi(str) : 80);
|
2017-07-03 16:56:32 +02:00
|
|
|
// Use LINES or fallback to the xterm default height of 24 characters
|
2016-11-02 00:37:58 +01:00
|
|
|
str = std::getenv("LINES");
|
2017-07-03 16:56:32 +02:00
|
|
|
term->setHeight(str ? std::atoi(str) : 24);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
term->setRect(1, 1, win_size.ws_col, win_size.ws_row);
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
opti_move->setTermSize (term->getWidth(), term->getHeight());
|
|
|
|
|
|
|
|
if ( close_after_detect )
|
|
|
|
closeConsole();
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2015-10-07 02:36:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::setTermSize (int term_width, int term_height)
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set xterm size to {term_width} x {term_height}
|
2017-04-06 01:31:21 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
putstringf (CSI "8;%d;%dt", term_height, term_width);
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::setKDECursor (fc::kdeKonsoleCursorShape style)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set cursor style in KDE konsole
|
2017-04-06 01:31:21 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isKdeTerminal() )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "50;CursorShape=%d" BEL, style);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2017-03-17 22:59:06 +01:00
|
|
|
const FString* FTerm::getXTermFont()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2016-11-20 18:26:15 +01:00
|
|
|
fd_set ifds;
|
|
|
|
struct timeval tv;
|
2018-05-02 12:31:21 +02:00
|
|
|
int stdin_no = FTermios::getStdIn();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-20 18:26:15 +01:00
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "50;?" BEL); // get font
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-20 18:26:15 +01:00
|
|
|
FD_ZERO(&ifds);
|
|
|
|
FD_SET(stdin_no, &ifds);
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 150000; // 150 ms
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// Read the terminal answer
|
|
|
|
if ( select(stdin_no + 1, &ifds, 0, 0, &tv) > 0 )
|
2016-11-20 18:26:15 +01:00
|
|
|
{
|
2017-09-17 21:32:46 +02:00
|
|
|
char temp[150] = {};
|
|
|
|
|
2017-09-18 00:10:14 +02:00
|
|
|
if ( std::scanf("\033]50;%148[^\n]s", temp) == 1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-08-12 22:55:29 +02:00
|
|
|
FString* xtermfont;
|
2017-03-08 23:48:30 +01:00
|
|
|
std::size_t n = std::strlen(temp);
|
2016-11-20 18:26:15 +01:00
|
|
|
|
|
|
|
// BEL + '\0' = string terminator
|
2017-08-27 09:50:30 +02:00
|
|
|
if ( n >= 5 && temp[n - 1] == BEL[0] && temp[n] == '\0' )
|
|
|
|
temp[n - 1] = '\0';
|
2016-11-20 18:26:15 +01:00
|
|
|
|
2017-08-12 22:55:29 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
xtermfont = new FString(temp);
|
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return xtermfont;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-29 00:23:45 +01:00
|
|
|
return 0;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-03-17 22:59:06 +01:00
|
|
|
const FString* FTerm::getXTermTitle()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isKdeTerminal() )
|
2016-11-29 00:23:45 +01:00
|
|
|
return 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-20 18:26:15 +01:00
|
|
|
fd_set ifds;
|
|
|
|
struct timeval tv;
|
2018-05-02 12:31:21 +02:00
|
|
|
int stdin_no = FTermios::getStdIn();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-20 18:26:15 +01:00
|
|
|
putstring (CSI "21t"); // get title
|
|
|
|
std::fflush(stdout);
|
|
|
|
|
|
|
|
FD_ZERO(&ifds);
|
|
|
|
FD_SET(stdin_no, &ifds);
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 150000; // 150 ms
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-20 18:26:15 +01:00
|
|
|
// read the terminal answer
|
2017-10-06 12:19:39 +02:00
|
|
|
if ( select (stdin_no + 1, &ifds, 0, 0, &tv) > 0 )
|
2016-11-20 18:26:15 +01:00
|
|
|
{
|
2017-09-17 21:32:46 +02:00
|
|
|
char temp[512] = {};
|
|
|
|
|
2017-09-18 00:10:14 +02:00
|
|
|
if ( std::scanf("\033]l%509[^\n]s", temp) == 1 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-03-08 23:48:30 +01:00
|
|
|
std::size_t n = std::strlen(temp);
|
2016-11-20 18:26:15 +01:00
|
|
|
|
|
|
|
// Esc + \ = OSC string terminator
|
2017-08-27 09:50:30 +02:00
|
|
|
if ( n >= 2 && temp[n - 2] == ESC[0] && temp[n - 1] == '\\' )
|
2016-11-29 00:23:45 +01:00
|
|
|
{
|
2017-08-12 22:55:29 +02:00
|
|
|
FString* xtermtitle;
|
|
|
|
|
2016-11-29 00:23:45 +01:00
|
|
|
if ( n < 4 )
|
|
|
|
return 0;
|
2016-11-20 18:26:15 +01:00
|
|
|
|
2017-08-27 09:50:30 +02:00
|
|
|
temp[n - 2] = '\0';
|
2017-08-12 22:55:29 +02:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
xtermtitle = new FString(temp);
|
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return xtermtitle;
|
2016-11-29 00:23:45 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-29 00:23:45 +01:00
|
|
|
return 0;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermCursorStyle (fc::xtermCursorStyle style)
|
|
|
|
{
|
|
|
|
// Set the xterm cursor style
|
2017-04-06 01:31:21 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( (isGnomeTerminal() && ! term_detection->hasSetCursorStyleSupport())
|
|
|
|
|| isKdeTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
if ( isFreeBSDConsole() )
|
2017-04-06 01:31:21 +02:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isXTerminal() || isMinttyTerm()
|
|
|
|
|| term_detection->hasSetCursorStyleSupport() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
putstringf (CSI "%d q", style);
|
|
|
|
std::fflush(stdout);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermTitle (const FString& title)
|
|
|
|
{
|
|
|
|
// Set the xterm title
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isMinttyTerm() || isPuttyTerminal()
|
2017-11-26 22:37:18 +01:00
|
|
|
|| FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "0;%s" BEL, title.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermForeground (const FString& fg)
|
|
|
|
{
|
|
|
|
// Set the VT100 text foreground color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isMinttyTerm() || isMltermTerminal()
|
2017-11-26 22:37:18 +01:00
|
|
|
|| FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "10;%s" BEL, fg.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermBackground (const FString& bg)
|
|
|
|
{
|
|
|
|
// Set the VT100 text background color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isMinttyTerm() || isMltermTerminal()
|
2017-11-26 22:37:18 +01:00
|
|
|
|| FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "11;%s" BEL, bg.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::setXTermCursorColor (const FString& cc)
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set the text cursor color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isMinttyTerm() || isUrxvtTerminal()
|
2017-11-26 22:37:18 +01:00
|
|
|
|| FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "12;%s" BEL, cc.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermMouseForeground (const FString& mfg)
|
|
|
|
{
|
|
|
|
// Set the mouse foreground color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "13;%s" BEL, mfg.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermMouseBackground (const FString& mbg)
|
|
|
|
{
|
|
|
|
// Set the mouse background color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "14;%s" BEL, mbg.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermHighlightBackground (const FString& hbg)
|
|
|
|
{
|
|
|
|
// Set the highlight background color
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "17;%s" BEL, hbg.c_str());
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-06 16:36:21 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setXTermDefaults()
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2016-11-06 16:36:21 +01:00
|
|
|
setXTermMouseBackground("rgb:ffff/ffff/ffff");
|
|
|
|
setXTermMouseForeground ("rgb:0000/0000/0000");
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isGnomeTerminal() )
|
2016-11-06 16:36:21 +01:00
|
|
|
setXTermCursorColor("rgb:ffff/ffff/ffff");
|
|
|
|
|
|
|
|
if ( xterm_default_colors
|
2018-04-19 01:55:17 +02:00
|
|
|
&& ! (isMinttyTerm() || isRxvtTerminal() || isScreenTerm()) )
|
2016-11-06 16:36:21 +01:00
|
|
|
{
|
|
|
|
// mintty and rxvt can't reset these settings
|
|
|
|
setXTermBackground("rgb:8080/a4a4/ecec");
|
|
|
|
setXTermForeground("rgb:0000/0000/0000");
|
|
|
|
setXTermHighlightBackground("rgb:8686/8686/8686");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermColors()
|
|
|
|
{
|
|
|
|
// Reset the entire color table
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "104" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermForeground()
|
|
|
|
{
|
|
|
|
// Reset the VT100 text foreground color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "110" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::resetXTermBackground()
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// Reset the VT100 text background color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "111" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermCursorColor()
|
|
|
|
{
|
|
|
|
// Reset the text cursor color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "112" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermMouseForeground()
|
|
|
|
{
|
|
|
|
// Reset the mouse foreground color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "113" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-12-11 06:04:29 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermMouseBackground()
|
|
|
|
{
|
|
|
|
// Reset the mouse background color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm() || FTermcap::osc_support )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
oscPrefix();
|
|
|
|
putstring (OSC "114" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermHighlightBackground()
|
|
|
|
{
|
|
|
|
// Reset the highlight background color
|
2017-10-06 12:19:39 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isGnomeTerminal() && term_detection->getGnomeTerminalID() < 3502 )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
oscPrefix();
|
|
|
|
putstringf (OSC "117" BEL);
|
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-06 16:36:21 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetXTermDefaults()
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isPuttyTerminal() )
|
2017-10-06 12:19:39 +02:00
|
|
|
return;
|
|
|
|
|
2016-11-06 16:36:21 +01:00
|
|
|
setXTermCursorColor("rgb:b1b1/b1b1/b1b1");
|
|
|
|
resetXTermMouseForeground();
|
|
|
|
resetXTermMouseBackground();
|
|
|
|
resetXTermCursorColor();
|
|
|
|
|
|
|
|
if ( xterm_default_colors )
|
|
|
|
{
|
|
|
|
resetXTermForeground();
|
|
|
|
resetXTermBackground();
|
|
|
|
resetXTermHighlightBackground();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::saveColorMap()
|
|
|
|
{
|
2017-09-09 22:03:17 +02:00
|
|
|
//ioctl (0, GIO_CMAP, &color_map);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetColorMap()
|
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
char*& oc = TCAP(fc::t_orig_colors);
|
2018-05-03 04:54:51 +02:00
|
|
|
char*& op = TCAP(fc::t_orig_pair);
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2018-05-03 04:54:51 +02:00
|
|
|
if ( oc )
|
2016-11-02 00:37:58 +01:00
|
|
|
putstring (oc);
|
|
|
|
/*else
|
|
|
|
{
|
|
|
|
dacreg CurrentColors[16] =
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
{0x00, 0x00, 0x00}, {0xAA, 0x00, 0x00},
|
|
|
|
{0x00, 0xAA, 0x00}, {0xAA, 0x55, 0x00},
|
|
|
|
{0x00, 0x00, 0xAA}, {0xAA, 0x00, 0xAA},
|
|
|
|
{0x00, 0xAA, 0xAA}, {0xAA, 0xAA, 0xAA},
|
|
|
|
{0x55, 0x55, 0x55}, {0xFF, 0x55, 0x55},
|
|
|
|
{0x55, 0xFF, 0x55}, {0xFF, 0xFF, 0x55},
|
|
|
|
{0x55, 0x55, 0xFF}, {0xFF, 0x55, 0xFF},
|
|
|
|
{0x55, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF}
|
|
|
|
};
|
2017-08-27 09:50:30 +02:00
|
|
|
for (int x = 0; x < 16; x++)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
color_map.d[x].red = CurrentColors[x].red;
|
|
|
|
color_map.d[x].green = CurrentColors[x].green;
|
|
|
|
color_map.d[x].blue = CurrentColors[x].blue;
|
|
|
|
}
|
|
|
|
ioctl (0, PIO_CMAP, &color_map);
|
|
|
|
}*/
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2018-05-03 04:54:51 +02:00
|
|
|
if ( op )
|
|
|
|
putstring (op);
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-10-01 03:48:58 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setPalette (short index, int r, int g, int b)
|
|
|
|
{
|
2018-01-24 00:25:32 +01:00
|
|
|
// Redefine RGB color value for a palette entry
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
char*& Ic = TCAP(fc::t_initialize_color);
|
|
|
|
char*& Ip = TCAP(fc::t_initialize_pair);
|
2015-10-01 03:48:58 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
index = FOptiAttr::vga2ansi(index);
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( Ic || Ip )
|
|
|
|
{
|
|
|
|
const char* color_str = "";
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2017-10-02 07:32:33 +02:00
|
|
|
int rr = (r * 1001) / 256
|
|
|
|
, gg = (g * 1001) / 256
|
|
|
|
, bb = (b * 1001) / 256;
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( Ic )
|
|
|
|
color_str = tparm(Ic, index, rr, gg, bb, 0, 0, 0, 0, 0);
|
|
|
|
else if ( Ip )
|
|
|
|
color_str = tparm(Ip, index, 0, 0, 0, rr, gg, bb, 0, 0);
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
putstring (color_str);
|
|
|
|
}
|
2018-04-19 01:55:17 +02:00
|
|
|
else if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
/* // direct vga-register set
|
2017-01-15 19:48:27 +01:00
|
|
|
if ( r>=0 && r<256
|
2017-11-26 22:37:18 +01:00
|
|
|
&& g>=0 && g<256
|
|
|
|
&& b>=0 && b<256 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
map.d[index].red = r;
|
|
|
|
map.d[index].green = g;
|
|
|
|
map.d[index].blue = b;
|
|
|
|
}
|
|
|
|
ioctl (0, PIO_CMAP, &map); */
|
|
|
|
}
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setBeep (int Hz, int ms)
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// range for frequency: 21-32766
|
|
|
|
if ( Hz < 21 || Hz > 32766 )
|
|
|
|
return;
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// range for duration: 0-1999
|
|
|
|
if ( ms < 0 || ms > 1999 )
|
|
|
|
return;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
putstringf ( CSI "10;%d]"
|
|
|
|
CSI "11;%d]"
|
|
|
|
, Hz, ms );
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetBeep()
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
2016-10-09 02:06:06 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// default frequency: 750 Hz
|
|
|
|
// default duration: 125 ms
|
|
|
|
putstring ( CSI "10;750]"
|
|
|
|
CSI "11;125]" );
|
|
|
|
std::fflush(stdout);
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-02-04 01:27:15 +01:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::beep()
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_bell) )
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_bell));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
2016-02-04 01:27:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2017-11-18 02:34:41 +01:00
|
|
|
void FTerm::setEncoding (fc::encoding enc)
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = enc;
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
assert ( term_encoding == fc::UTF8
|
2017-11-26 22:37:18 +01:00
|
|
|
|| term_encoding == fc::VT100
|
|
|
|
|| term_encoding == fc::PC
|
|
|
|
|| term_encoding == fc::ASCII );
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Set the new Fputchar function pointer
|
2017-11-18 02:34:41 +01:00
|
|
|
switch ( term_encoding )
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
case fc::UTF8:
|
|
|
|
Fputchar = &FTerm::putchar_UTF8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case fc::VT100:
|
|
|
|
case fc::PC:
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() && utf8_console )
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_UTF8;
|
2017-08-12 20:10:27 +02:00
|
|
|
else
|
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
|
|
|
break;
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
case fc::ASCII:
|
2017-12-10 15:36:02 +01:00
|
|
|
case fc::UNKNOWN:
|
|
|
|
case fc::NUM_OF_ENCODINGS:
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
2016-02-04 01:27:15 +01:00
|
|
|
}
|
2016-12-27 23:03:32 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() )
|
2016-12-27 23:03:32 +01:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
if ( term_encoding == fc::VT100 || term_encoding == fc::PC )
|
2016-12-27 23:03:32 +01:00
|
|
|
{
|
|
|
|
char* empty = 0;
|
|
|
|
opti_move->set_tabular (empty);
|
|
|
|
}
|
|
|
|
else
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_move->set_tabular (TCAP(fc::t_tab));
|
2016-12-27 23:03:32 +01:00
|
|
|
}
|
2016-02-04 01:27:15 +01:00
|
|
|
}
|
|
|
|
|
2015-10-07 02:36:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-11-18 02:34:41 +01:00
|
|
|
fc::encoding FTerm::getEncoding()
|
|
|
|
{
|
|
|
|
return term_encoding;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
std::string FTerm::getEncodingString()
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
std::map<std::string,fc::encoding>::const_iterator it, end;
|
|
|
|
end = encoding_set->end();
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
for (it = encoding_set->begin(); it != end; ++it )
|
2017-11-18 02:34:41 +01:00
|
|
|
if ( it->second == term_encoding )
|
2016-11-02 00:37:58 +01:00
|
|
|
return it->first;
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::scrollTermForward()
|
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_scroll_forward) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_scroll_forward));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
return true;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::scrollTermReverse()
|
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_scroll_reverse) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_scroll_reverse));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
return true;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
return false;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-12-25 21:17:08 +01:00
|
|
|
void FTerm::putstringf (const char format[], ...)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
assert ( format != 0 );
|
|
|
|
char buf[512];
|
|
|
|
char* buffer;
|
|
|
|
va_list args;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
buffer = buf;
|
|
|
|
va_start (args, format);
|
2017-03-26 20:40:04 +02:00
|
|
|
vsnprintf (buffer, sizeof(buf), format, args);
|
2016-11-02 00:37:58 +01:00
|
|
|
va_end (args);
|
2015-10-23 00:24:20 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
tputs (buffer, 1, FTerm::putchar_ASCII);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-10-23 00:24:20 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-01-14 22:24:15 +01:00
|
|
|
void FTerm::putstring (const char s[], int affcnt)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
#if defined(__sun) && defined(__SVR4)
|
|
|
|
tputs (C_STR(s), affcnt, FTerm::putchar_ASCII);
|
|
|
|
#else
|
|
|
|
tputs (s, affcnt, FTerm::putchar_ASCII);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__sun) && defined(__SVR4)
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::putchar_ASCII (register char c)
|
|
|
|
{
|
|
|
|
if ( std::putchar(c) == EOF )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2017-12-17 01:06:53 +01:00
|
|
|
#endif
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::putchar_ASCII (register int c)
|
|
|
|
{
|
|
|
|
if ( std::putchar(char(c)) == EOF )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::putchar_UTF8 (register int c)
|
|
|
|
{
|
2017-10-06 12:19:39 +02:00
|
|
|
if ( c < 0x80 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 1 Byte (7-bit): 0xxxxxxx
|
|
|
|
std::putchar (c);
|
|
|
|
return 1;
|
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( c < 0x800 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 2 byte (11-bit): 110xxxxx 10xxxxxx
|
|
|
|
std::putchar (0xc0 | (c >> 6) );
|
|
|
|
std::putchar (0x80 | (c & 0x3f) );
|
|
|
|
return 2;
|
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( c < 0x10000 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 3 byte (16-bit): 1110xxxx 10xxxxxx 10xxxxxx
|
|
|
|
std::putchar (0xe0 | (c >> 12) );
|
|
|
|
std::putchar (0x80 | ((c >> 6) & 0x3f) );
|
|
|
|
std::putchar (0x80 | (c & 0x3f) );
|
|
|
|
return 3;
|
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( c < 0x200000 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 4 byte (21-bit): 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
|
|
std::putchar (0xf0 | (c >> 18) );
|
|
|
|
std::putchar (0x80 | ((c >> 12) & 0x3f) );
|
|
|
|
std::putchar (0x80 | ((c >> 6) & 0x3f) );
|
|
|
|
std::putchar (0x80 | (c & 0x3f));
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return EOF;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-20 18:26:15 +01:00
|
|
|
int FTerm::UTF8decode (const char utf8[])
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-08-27 09:50:30 +02:00
|
|
|
register int ucs = 0;
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-08-27 09:50:30 +02:00
|
|
|
for (register int i = 0; i < int(std::strlen(utf8)); ++i)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
register uChar ch = uChar(utf8[i]);
|
|
|
|
|
2017-10-06 12:19:39 +02:00
|
|
|
if ( (ch & 0xc0) == 0x80 )
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// byte 2..4 = 10xxxxxx
|
|
|
|
ucs = (ucs << 6) | (ch & 0x3f);
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( ch < 128 )
|
2016-01-08 01:00:05 +01:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// byte 1 = 0xxxxxxx (1 byte mapping)
|
|
|
|
ucs = ch & 0xff;
|
2016-01-08 01:00:05 +01:00
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( (ch & 0xe0) == 0xc0 )
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// byte 1 = 110xxxxx (2 byte mapping)
|
|
|
|
ucs = ch & 0x1f;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( (ch & 0xf0) == 0xe0 )
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// byte 1 = 1110xxxx (3 byte mapping)
|
|
|
|
ucs = ch & 0x0f;
|
|
|
|
}
|
2017-10-06 12:19:39 +02:00
|
|
|
else if ( (ch & 0xf8) == 0xf0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// byte 1 = 11110xxx (4 byte mapping)
|
|
|
|
ucs = ch & 0x07;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// error
|
|
|
|
ucs = EOF;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return ucs;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// protected methods of FTerm
|
|
|
|
//----------------------------------------------------------------------
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2017-04-02 13:30:23 +02:00
|
|
|
void FTerm::initLinuxConsoleCharMap()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2016-11-13 22:08:40 +01:00
|
|
|
uInt c1, c2, c3, c4, c5;
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( NewFont || VGAFont )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( screen_unicode_map.entry_ct != 0 )
|
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; i <= fc::lastCharItem; i++ )
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
bool found = false;
|
|
|
|
|
2017-08-27 09:50:30 +02:00
|
|
|
for (uInt n = 0; n < screen_unicode_map.entry_ct; n++)
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( fc::character[i][fc::UTF8] == screen_unicode_map.entries[n].unicode )
|
2016-02-04 01:27:15 +01:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
found = true;
|
|
|
|
break;
|
2016-02-04 01:27:15 +01:00
|
|
|
}
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! found )
|
2017-12-17 01:06:53 +01:00
|
|
|
fc::character[i][fc::PC] = fc::character[i][fc::ASCII];
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
}
|
2016-11-13 22:08:40 +01:00
|
|
|
|
|
|
|
c1 = fc::UpperHalfBlock;
|
|
|
|
c2 = fc::LowerHalfBlock;
|
|
|
|
c3 = fc::FullBlock;
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( charEncode(c1, fc::PC) == charEncode(c1, fc::ASCII)
|
2017-11-26 22:37:18 +01:00
|
|
|
|| charEncode(c2, fc::PC) == charEncode(c2, fc::ASCII)
|
|
|
|
|| charEncode(c3, fc::PC) == charEncode(c3, fc::ASCII) )
|
2016-11-13 22:08:40 +01:00
|
|
|
{
|
2017-09-09 22:03:17 +02:00
|
|
|
no_shadow_character = true;
|
2016-11-13 22:08:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
c4 = fc::RightHalfBlock;
|
|
|
|
c5 = fc::LeftHalfBlock;
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( charEncode(c4, fc::PC) == charEncode(c4, fc::ASCII)
|
2017-11-26 22:37:18 +01:00
|
|
|
|| charEncode(c5, fc::PC) == charEncode(c5, fc::ASCII) )
|
2016-11-13 22:08:40 +01:00
|
|
|
{
|
2017-09-09 22:03:17 +02:00
|
|
|
no_half_block_character = true;
|
2016-11-13 22:08:40 +01:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2017-04-02 21:32:48 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
void FTerm::initFreeBSDConsoleCharMap()
|
2017-04-02 21:32:48 +02:00
|
|
|
{
|
|
|
|
// A FreeBSD console can't show ASCII codes from 0x00 to 0x1b
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
if ( ! isFreeBSDConsole() )
|
2017-04-02 21:32:48 +02:00
|
|
|
return;
|
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; i <= fc::lastCharItem; i++ )
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( fc::character[i][fc::PC] < 0x1c )
|
|
|
|
fc::character[i][fc::PC] = fc::character[i][fc::ASCII];
|
2017-04-02 21:32:48 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::charEncodable (uInt c)
|
|
|
|
{
|
|
|
|
uInt ch = charEncode(c);
|
|
|
|
return bool(ch > 0 && ch != c);
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uInt FTerm::charEncode (uInt c)
|
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
return charEncode (c, term_encoding);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uInt FTerm::charEncode (uInt c, fc::encoding enc)
|
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
for (uInt i = 0; i <= uInt(fc::lastCharItem); i++)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( fc::character[i][0] == c )
|
2015-10-11 04:09:58 +02:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
c = fc::character[i][enc];
|
2016-11-02 00:37:58 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-24 02:34:30 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return c;
|
|
|
|
}
|
2015-12-24 02:34:30 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
char* FTerm::changeAttribute ( char_data*& term_attr
|
|
|
|
, char_data*& next_attr )
|
|
|
|
{
|
|
|
|
return opti_attr->changeAttribute (term_attr, next_attr);
|
|
|
|
}
|
2015-12-24 02:34:30 +01:00
|
|
|
|
2017-04-11 00:30:27 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::xtermMetaSendsESC (bool on)
|
|
|
|
{
|
|
|
|
// activate/deactivate the xterm meta key sends escape prefix
|
|
|
|
|
|
|
|
if ( on )
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (CSI "?1036s" // save meta key sends escape
|
|
|
|
CSI "?1036h"); // enable meta key sends escape
|
2017-04-11 00:30:27 +02:00
|
|
|
else
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (CSI "?1036r"); // restore meta key sends escape
|
2017-04-11 00:30:27 +02:00
|
|
|
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::exitWithMessage (std::string message)
|
|
|
|
{
|
|
|
|
// Set the exit_message for the atexit-handler
|
|
|
|
snprintf ( exit_message
|
|
|
|
, sizeof(exit_message)
|
|
|
|
, "%s"
|
|
|
|
, message.c_str() );
|
|
|
|
|
|
|
|
// Exit the programm
|
|
|
|
if ( init_term_object )
|
|
|
|
init_term_object->finish();
|
|
|
|
|
|
|
|
std::fflush (stderr);
|
|
|
|
std::fflush (stdout);
|
|
|
|
|
|
|
|
if ( exit_message[0] )
|
|
|
|
std::fprintf (stderr, "Warning: %s\n", exit_message);
|
|
|
|
|
2017-12-10 15:36:02 +01:00
|
|
|
std::exit (EXIT_FAILURE);
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// private methods of FTerm
|
2016-11-05 23:12:05 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2017-03-28 08:50:37 +02:00
|
|
|
int FTerm::isLinuxConsole()
|
2016-11-05 23:12:05 +01:00
|
|
|
{
|
|
|
|
char arg = 0;
|
|
|
|
// get keyboard type an compare
|
2016-12-18 23:34:11 +01:00
|
|
|
return ( isatty (fd_tty)
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ioctl(fd_tty, KDGKBTYPE, &arg) == 0
|
|
|
|
&& ((arg == KB_101) || (arg == KB_84)) );
|
2016-11-05 23:12:05 +01:00
|
|
|
}
|
2017-03-28 08:50:37 +02:00
|
|
|
#endif
|
2016-11-05 23:12:05 +01:00
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2017-04-02 13:30:23 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
bool FTerm::isFreeBSDConsole()
|
2017-03-28 08:50:37 +02:00
|
|
|
{
|
|
|
|
keymap_t keymap;
|
|
|
|
|
|
|
|
if ( ioctl(0, GIO_KEYMAP, &keymap) == 0 )
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2017-04-14 23:55:44 +02:00
|
|
|
#endif
|
2017-03-28 08:50:37 +02:00
|
|
|
|
2017-04-02 13:30:23 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-14 23:55:44 +02:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
bool FTerm::isWSConsConsole()
|
2017-04-02 13:30:23 +02:00
|
|
|
{
|
2017-04-14 23:55:44 +02:00
|
|
|
static kbd_t kbdencoding;
|
2017-04-02 13:30:23 +02:00
|
|
|
|
2017-04-14 23:55:44 +02:00
|
|
|
if ( ioctl(0, WSKBDIO_GETENCODING, &kbdencoding) == 0 )
|
2017-04-02 13:30:23 +02:00
|
|
|
return true;
|
2017-04-14 23:55:44 +02:00
|
|
|
else
|
|
|
|
return false;
|
2017-04-02 13:30:23 +02:00
|
|
|
}
|
2017-03-28 08:50:37 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
2017-11-22 23:56:21 +01:00
|
|
|
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline uInt16 FTerm::getInputStatusRegisterOne()
|
|
|
|
{
|
|
|
|
// Gets the VGA input-status-register-1
|
2017-07-03 16:56:32 +02:00
|
|
|
|
|
|
|
// Miscellaneous output (read port)
|
|
|
|
static const uInt16 misc_read = 0x3cc;
|
2017-09-17 21:32:46 +02:00
|
|
|
const uInt16 io_base = ( inb(misc_read) & 0x01 ) ? 0x3d0 : 0x3b0;
|
2016-11-02 00:37:58 +01:00
|
|
|
// 0x3ba : Input status 1 MDA (read port)
|
|
|
|
// 0x3da : Input status 1 CGA (read port)
|
|
|
|
return io_base + 0x0a;
|
|
|
|
}
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uChar FTerm::readAttributeController (uChar index)
|
|
|
|
{
|
|
|
|
// Reads a byte from the attribute controller from a given index
|
2017-07-03 16:56:32 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
uChar res;
|
2017-07-03 16:56:32 +02:00
|
|
|
// Attribute controller (write port)
|
|
|
|
static const uInt16 attrib_cntlr_write = 0x3c0;
|
|
|
|
// Attribute controller (read port)
|
|
|
|
static const uInt16 attrib_cntlr_read = 0x3c1;
|
|
|
|
const uInt16 input_status_1 = getInputStatusRegisterOne();
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
inb (input_status_1); // switch to index mode
|
|
|
|
outb (index & 0x1f, attrib_cntlr_write);
|
|
|
|
res = inb (attrib_cntlr_read);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
inb (input_status_1); // switch to data mode
|
2017-09-11 03:06:02 +02:00
|
|
|
index = (index & 0x1f) | 0x20; // set bit 5 (enable display)
|
2016-11-02 00:37:58 +01:00
|
|
|
outb (index, attrib_cntlr_write);
|
|
|
|
inb (attrib_cntlr_read);
|
|
|
|
return res;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::writeAttributeController (uChar index, uChar data)
|
|
|
|
{
|
|
|
|
// Writes a byte from the attribute controller from a given index
|
2017-07-03 16:56:32 +02:00
|
|
|
|
|
|
|
// Attribute controller (write port)
|
|
|
|
static const uInt16 attrib_cntlr_write = 0x3c0;
|
|
|
|
const uInt16 input_status_1 = getInputStatusRegisterOne();
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
inb (input_status_1); // switch to index mode
|
|
|
|
outb (index & 0x1f, attrib_cntlr_write);
|
|
|
|
outb (data, attrib_cntlr_write);
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
inb (input_status_1); // switch to data mode
|
2017-09-11 03:06:02 +02:00
|
|
|
index = (index & 0x1f) | 0x20; // set bit 5 (enable display)
|
2016-11-02 00:37:58 +01:00
|
|
|
outb (index, attrib_cntlr_write);
|
|
|
|
outb (data, attrib_cntlr_write);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline uChar FTerm::getAttributeMode()
|
|
|
|
{
|
|
|
|
// Gets the attribute mode value from the vga attribute controller
|
2017-07-03 16:56:32 +02:00
|
|
|
static const uChar attrib_mode = 0x10;
|
2016-11-02 00:37:58 +01:00
|
|
|
return readAttributeController(attrib_mode);
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-01-02 20:38:45 +01:00
|
|
|
inline void FTerm::setAttributeMode (uChar data)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// Sets the attribute mode value from the vga attribute controller
|
2017-07-03 16:56:32 +02:00
|
|
|
static const uChar attrib_mode = 0x10;
|
2016-11-02 00:37:58 +01:00
|
|
|
writeAttributeController (attrib_mode, data);
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::setBlinkAsIntensity (bool on)
|
|
|
|
{
|
|
|
|
// Uses blink-bit as background intensity.
|
|
|
|
// That permits 16 colors for background
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2017-11-24 23:57:41 +01:00
|
|
|
// Test if the blink-bit is used by the screen font (512 characters)
|
|
|
|
if ( screen_font.charcount > 256 )
|
|
|
|
return -1;
|
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( getuid() != 0 ) // Direct hardware access requires root privileges
|
2016-11-02 00:37:58 +01:00
|
|
|
return -2;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 )
|
|
|
|
return -1;
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// Enable access to VGA I/O ports (from 0x3B4 with num = 0x2C)
|
|
|
|
if ( ioctl(fd_tty, KDENABIO, 0) < 0 )
|
|
|
|
return -1; // error on KDENABIO
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( on )
|
|
|
|
setAttributeMode (getAttributeMode() & 0xF7); // clear bit 3
|
|
|
|
else
|
|
|
|
setAttributeMode (getAttributeMode() | 0x08); // set bit 3
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// Disable access to VGA I/O ports
|
|
|
|
if ( ioctl(fd_tty, KDDISABIO, 0) < 0 )
|
|
|
|
return -1; // error on KDDISABIO
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return 0;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2017-11-22 23:56:21 +01:00
|
|
|
#endif
|
2015-10-07 02:36:38 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
int FTerm::getFramebuffer_bpp ()
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
int fd = -1;
|
|
|
|
struct fb_var_screeninfo fb_var;
|
|
|
|
struct fb_fix_screeninfo fb_fix;
|
2016-05-24 22:30:01 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
const char* fb = C_STR("/dev/fb/0");
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
if ( (fd = open(fb, O_RDWR)) < 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( errno != ENOENT && errno != ENOTDIR )
|
|
|
|
return -1;
|
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
fb = C_STR("/dev/fb0");
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
if ( (fd = open(fb, O_RDWR)) < 0 )
|
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-10-02 07:32:33 +02:00
|
|
|
if ( ! ioctl(fd, FBIOGET_VSCREENINFO, &fb_var)
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ! ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-10-02 07:32:33 +02:00
|
|
|
::close(fd);
|
|
|
|
return int(fb_var.bits_per_pixel);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
::close(fd);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return -1;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2015-10-07 02:36:38 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
int FTerm::openConsole()
|
2017-12-27 01:38:28 +01:00
|
|
|
{
|
2017-12-25 21:17:08 +01:00
|
|
|
static const char* terminal_devices[] =
|
|
|
|
{
|
|
|
|
"/proc/self/fd/0",
|
|
|
|
"/dev/tty",
|
|
|
|
"/dev/tty0",
|
|
|
|
"/dev/vc/0",
|
|
|
|
"/dev/systty",
|
|
|
|
"/dev/console",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty >= 0 ) // console is already opened
|
|
|
|
return 0;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2018-02-11 23:41:23 +01:00
|
|
|
if ( ! *termfilename )
|
2017-12-25 21:17:08 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (int i = 0; terminal_devices[i] != 0; i++)
|
|
|
|
if ( (fd_tty = open(terminal_devices[i], O_RDWR, 0)) >= 0 )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return -1; // No file descriptor referring to the console
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-12-21 18:37:20 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::closeConsole()
|
|
|
|
{
|
|
|
|
if ( fd_tty < 0 ) // console is already closed
|
|
|
|
return 0;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
int ret = ::close (fd_tty); // use 'close' from the global namespace
|
|
|
|
fd_tty = -1;
|
2016-08-28 22:43:14 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::getScreenFont()
|
|
|
|
{
|
2017-07-03 16:56:32 +02:00
|
|
|
static const std::size_t data_size = 4 * 32 * 512;
|
2016-11-02 00:37:58 +01:00
|
|
|
struct console_font_op font;
|
2017-07-03 16:56:32 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
int ret;
|
2016-10-06 23:15:09 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 )
|
|
|
|
return -1;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// initialize unused padding bytes in struct
|
|
|
|
std::memset (&font, 0, sizeof(console_font_op));
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
font.op = KD_FONT_OP_GET;
|
|
|
|
font.flags = 0;
|
|
|
|
font.width = 32;
|
|
|
|
font.height = 32;
|
|
|
|
font.charcount = 512;
|
2017-11-24 23:57:41 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// initialize with 0
|
2017-08-12 22:55:29 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
font.data = new uChar[data_size]();
|
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// font operation
|
|
|
|
ret = ioctl (fd_tty, KDFONTOP, &font);
|
2015-10-29 21:10:50 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
2015-10-24 00:49:56 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
screen_font.width = font.width;
|
|
|
|
screen_font.height = font.height;
|
|
|
|
screen_font.charcount = font.charcount;
|
|
|
|
screen_font.data = font.data;
|
|
|
|
return 0;
|
2015-10-24 00:49:56 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
2015-10-24 00:49:56 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-12-25 21:17:08 +01:00
|
|
|
int FTerm::setScreenFont ( uChar fontdata[], uInt count
|
2016-11-02 00:37:58 +01:00
|
|
|
, uInt fontwidth, uInt fontheight
|
|
|
|
, bool direct)
|
|
|
|
{
|
|
|
|
struct console_font_op font;
|
|
|
|
int ret;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 )
|
|
|
|
return -1;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// initialize unused padding bytes in struct
|
|
|
|
std::memset (&font, 0x00, sizeof(console_font_op));
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
font.op = KD_FONT_OP_SET;
|
|
|
|
font.flags = 0;
|
|
|
|
font.width = fontwidth;
|
|
|
|
font.height = fontheight;
|
|
|
|
font.charcount = count;
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( direct )
|
|
|
|
font.data = fontdata;
|
2015-10-07 02:36:38 +02:00
|
|
|
else
|
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
const uInt bytes_per_line = font.width / 8;
|
2017-03-08 23:48:30 +01:00
|
|
|
const std::size_t data_size = bytes_per_line * 32 * font.charcount;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
try
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
font.data = new uChar[data_size](); // initialize with 0
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
return -1;
|
2015-10-07 02:36:38 +02:00
|
|
|
}
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2017-08-27 09:50:30 +02:00
|
|
|
for (uInt i = 0; i < count; i++)
|
2017-10-02 07:32:33 +02:00
|
|
|
std::memcpy ( const_cast<uChar*>(font.data + bytes_per_line * 32 * i)
|
2016-11-02 00:37:58 +01:00
|
|
|
, &fontdata[i * font.height]
|
|
|
|
, font.height);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
// font operation
|
|
|
|
ret = ioctl (fd_tty, KDFONTOP, &font);
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 && errno != ENOSYS && errno != EINVAL )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! direct )
|
|
|
|
delete[] font.data;
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! direct )
|
|
|
|
delete[] font.data;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::getUnicodeMap()
|
|
|
|
{
|
|
|
|
struct unimapdesc unimap;
|
|
|
|
int ret;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 )
|
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
unimap.entry_ct = 0;
|
|
|
|
unimap.entries = 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// get count
|
|
|
|
ret = ioctl (fd_tty, GIO_UNIMAP, &unimap);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
int count;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( errno != ENOMEM || unimap.entry_ct == 0 )
|
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
count = unimap.entry_ct;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
unimap.entries = new struct unipair[count]();
|
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// get unicode-to-font mapping from kernel
|
|
|
|
ret = ioctl(fd_tty, GIO_UNIMAP, &unimap);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
|
|
|
{
|
|
|
|
screen_unicode_map.entry_ct = unimap.entry_ct;
|
|
|
|
screen_unicode_map.entries = unimap.entries;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-01-17 02:57:08 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
int FTerm::setUnicodeMap (struct unimapdesc* unimap)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
struct unimapinit advice;
|
|
|
|
int ret;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fd_tty < 0 )
|
|
|
|
return -1;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
advice.advised_hashsize = 0;
|
|
|
|
advice.advised_hashstep = 0;
|
|
|
|
advice.advised_hashlevel = 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
do
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// clear the unicode-to-font table
|
|
|
|
ret = ioctl(fd_tty, PIO_UNIMAPCLR, &advice);
|
2015-10-23 23:57:00 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret != 0 )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// put the new unicode-to-font mapping in kernel
|
|
|
|
ret = ioctl(fd_tty, PIO_UNIMAP, unimap);
|
|
|
|
|
|
|
|
if ( ret != 0 )
|
|
|
|
advice.advised_hashlevel++;
|
2016-01-08 01:00:05 +01:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
while ( ret != 0 && errno == ENOMEM && advice.advised_hashlevel < 100);
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ret == 0 )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-02 13:30:23 +02:00
|
|
|
void FTerm::initLinuxConsole()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-04-02 13:30:23 +02:00
|
|
|
// initialize Linux console
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
screen_unicode_map.entries = 0;
|
|
|
|
screen_font.data = 0;
|
|
|
|
|
|
|
|
if ( openConsole() == 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection->setLinuxTerm (isLinuxConsole());
|
2017-11-24 23:57:41 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
getUnicodeMap();
|
|
|
|
getScreenFont();
|
2017-11-25 18:37:40 +01:00
|
|
|
|
2017-11-24 23:57:41 +01:00
|
|
|
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
|
|
|
|
// Enable 16 background colors
|
|
|
|
if ( setBlinkAsIntensity(true) == 0 )
|
|
|
|
FTermcap::max_color = 16;
|
|
|
|
else
|
|
|
|
FTermcap::max_color = 8;
|
|
|
|
#endif
|
2017-11-25 18:37:40 +01:00
|
|
|
// Underline cursor
|
|
|
|
setLinuxConsoleCursorStyle (fc::underscore_cursor, true);
|
|
|
|
|
|
|
|
// Framebuffer color depth in bits per pixel
|
|
|
|
int bpp = getFramebuffer_bpp();
|
|
|
|
|
2018-01-24 23:02:45 +01:00
|
|
|
// More than 4 bits per pixel and the font uses the blink-bit
|
|
|
|
if ( bpp >= 4 && screen_font.charcount <= 256 )
|
2017-11-25 18:37:40 +01:00
|
|
|
FTermcap::max_color = 16;
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
framebuffer_bpp = bpp;
|
|
|
|
#endif
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
detectTermSize();
|
|
|
|
closeConsole();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
std::cerr << "can not open the console.\n";
|
|
|
|
std::abort();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2017-04-14 23:55:44 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::saveFreeBSDAltKey()
|
|
|
|
{
|
|
|
|
static const int left_alt = 0x38;
|
2017-07-03 16:56:32 +02:00
|
|
|
int ret;
|
|
|
|
keymap_t keymap;
|
2017-04-14 23:55:44 +02:00
|
|
|
|
|
|
|
ret = ioctl(0, GIO_KEYMAP, &keymap);
|
|
|
|
|
|
|
|
if ( ret < 0 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// save current mapping
|
|
|
|
bsd_alt_keymap = keymap.key[left_alt].map[0];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setFreeBSDAltKey (uInt key)
|
|
|
|
{
|
|
|
|
static const int left_alt = 0x38;
|
2017-07-03 16:56:32 +02:00
|
|
|
int ret;
|
|
|
|
keymap_t keymap;
|
2017-04-14 23:55:44 +02:00
|
|
|
|
|
|
|
ret = ioctl(0, GIO_KEYMAP, &keymap);
|
|
|
|
|
|
|
|
if ( ret < 0 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// map to meta key
|
|
|
|
keymap.key[left_alt].map[0] = key;
|
|
|
|
|
2017-10-06 12:19:39 +02:00
|
|
|
if ( (keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0) )
|
2017-04-14 23:55:44 +02:00
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setFreeBSDAlt2Meta()
|
|
|
|
{
|
|
|
|
return setFreeBSDAltKey (META);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::resetFreeBSDAlt2Meta()
|
|
|
|
{
|
|
|
|
return setFreeBSDAltKey (bsd_alt_keymap);
|
|
|
|
}
|
|
|
|
|
2017-04-02 13:30:23 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
void FTerm::initFreeBSDConsole()
|
2017-04-02 13:30:23 +02:00
|
|
|
{
|
|
|
|
// initialize BSD console
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
if ( isFreeBSDConsole() )
|
2017-04-02 13:30:23 +02:00
|
|
|
{
|
|
|
|
// save current left alt key mapping
|
2017-04-09 20:08:53 +02:00
|
|
|
saveFreeBSDAltKey();
|
2017-04-02 13:30:23 +02:00
|
|
|
|
|
|
|
// map meta key to left alt key
|
2017-04-09 20:08:53 +02:00
|
|
|
setFreeBSDAlt2Meta();
|
2017-11-25 18:37:40 +01:00
|
|
|
|
|
|
|
// Initialize FreeBSD console cursor
|
|
|
|
setFreeBSDConsoleCursorStyle (fc::destructive_cursor, true);
|
2017-04-02 13:30:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-14 23:55:44 +02:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::saveWSConsEncoding()
|
|
|
|
{
|
|
|
|
static kbd_t k_encoding;
|
|
|
|
int ret = ioctl(0, WSKBDIO_GETENCODING, &k_encoding);
|
|
|
|
|
|
|
|
if ( ret < 0 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// save current encoding
|
|
|
|
wscons_keyboard_encoding = k_encoding;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setWSConsEncoding (kbd_t k_encoding)
|
|
|
|
{
|
|
|
|
if ( ioctl(0, WSKBDIO_SETENCODING, &k_encoding) < 0 )
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setWSConsMetaEsc()
|
|
|
|
{
|
|
|
|
static const kbd_t meta_esc = 0x20; // generate ESC prefix on ALT-key
|
|
|
|
|
|
|
|
return setWSConsEncoding (wscons_keyboard_encoding | meta_esc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::resetWSConsEncoding()
|
|
|
|
{
|
|
|
|
return setWSConsEncoding (wscons_keyboard_encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::initWSConsConsole()
|
|
|
|
{
|
|
|
|
// initialize wscons console
|
|
|
|
|
|
|
|
if ( isWSConsConsole() )
|
|
|
|
{
|
|
|
|
// save current left alt key mapping
|
|
|
|
saveWSConsEncoding();
|
|
|
|
|
|
|
|
// alt key generate ESC prefix
|
|
|
|
setWSConsMetaEsc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_global_values()
|
|
|
|
{
|
|
|
|
// Initialize global values
|
|
|
|
|
|
|
|
// Teletype (tty) file descriptor is still undefined
|
|
|
|
fd_tty = -1;
|
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
// Set default timeout for keypress
|
|
|
|
key_timeout = 100000; // 100 ms
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// Preset to true
|
|
|
|
cursor_optimisation = true;
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Preset to false
|
|
|
|
utf8_console = \
|
|
|
|
utf8_input = \
|
|
|
|
utf8_state = \
|
|
|
|
utf8_linux_terminal = \
|
|
|
|
pc_charset_console = \
|
|
|
|
vt100_console = \
|
|
|
|
NewFont = \
|
|
|
|
VGAFont = \
|
|
|
|
no_shadow_character = \
|
|
|
|
no_half_block_character = \
|
|
|
|
ascii_console = \
|
|
|
|
force_vt100 = \
|
|
|
|
xterm_default_colors = false;
|
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Assertion: programm start in cooked mode
|
2017-11-18 02:34:41 +01:00
|
|
|
input_data_pending = \
|
|
|
|
non_blocking_stdin = false;
|
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Init arrays with '\0'
|
2017-11-18 02:34:41 +01:00
|
|
|
std::fill_n (exit_message, sizeof(exit_message), '\0');
|
2017-12-14 00:35:10 +01:00
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
// Initialize the structs
|
|
|
|
color_env.setDefault();
|
|
|
|
secondary_da.setDefault();
|
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
if ( ! init_values.terminal_detection )
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection->setTerminalDetection (false);
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::oscPrefix()
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isTmuxTerm() )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
// tmux device control string
|
|
|
|
putstring (ESC "Ptmux;" ESC);
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
2018-05-02 12:31:21 +02:00
|
|
|
else if ( isScreenTerm() )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
// GNU Screen device control string
|
|
|
|
putstring (ESC "P");
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
2018-05-02 12:31:21 +02:00
|
|
|
}
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::oscPostfix()
|
|
|
|
{
|
|
|
|
if ( isScreenTerm() || isTmuxTerm() )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
// GNU Screen/tmux string terminator
|
|
|
|
putstring (ESC "\\");
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_alt_charset()
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
// Read the used vt100 pairs
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( TCAP(fc::t_acs_chars) )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
for (int n = 0; TCAP(fc::t_acs_chars)[n]; n += 2)
|
|
|
|
{
|
|
|
|
// insert the vt100 key/value pairs into a map
|
|
|
|
uChar p1 = uChar(TCAP(fc::t_acs_chars)[n]);
|
|
|
|
uChar p2 = uChar(TCAP(fc::t_acs_chars)[n + 1]);
|
|
|
|
(*vt100_alt_char)[p1] = p2;
|
|
|
|
}
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
enum column
|
2017-12-14 00:35:10 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
vt100_key = 0,
|
|
|
|
utf8_char = 1
|
|
|
|
};
|
2017-12-14 00:35:10 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// Update array 'character' with discovered vt100 pairs
|
|
|
|
for (int n = 0; n <= fc::lastKeyItem; n++ )
|
2018-01-02 20:38:45 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
uChar keyChar = uChar(fc::vt100_key_to_utf8[n][vt100_key]);
|
|
|
|
uChar altChar = uChar((*vt100_alt_char)[ keyChar ]);
|
|
|
|
uInt utf8char = uInt(fc::vt100_key_to_utf8[n][utf8_char]);
|
|
|
|
fc::encoding num = fc::NUM_OF_ENCODINGS;
|
2018-01-02 20:38:45 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
uInt* p = std::find ( fc::character[0]
|
|
|
|
, fc::character[fc::lastCharItem] + num
|
|
|
|
, utf8char );
|
|
|
|
if ( p != fc::character[fc::lastCharItem] + num ) // found in character
|
|
|
|
{
|
|
|
|
int item = int(std::distance(fc::character[0], p) / num);
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( altChar )
|
|
|
|
fc::character[item][fc::VT100] = altChar; // update alternate character set
|
|
|
|
else
|
|
|
|
fc::character[item][fc::VT100] = 0; // delete vt100 char in character
|
|
|
|
}
|
|
|
|
}
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_pc_charset()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
bool reinit = false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// rxvt does not support pc charset
|
|
|
|
if ( isRxvtTerminal() || isUrxvtTerminal() )
|
|
|
|
return;
|
2016-10-13 02:16:51 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isGnomeTerminal() || isLinuxTerm() )
|
2016-10-13 02:16:51 +02:00
|
|
|
{
|
2018-01-02 20:38:45 +01:00
|
|
|
// Fallback if tcap "S2" is not found
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( ! TCAP(fc::t_enter_pc_charset_mode) )
|
2016-10-13 02:16:51 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( utf8_console )
|
|
|
|
{
|
|
|
|
// Select iso8859-1 + null mapping
|
2017-09-11 03:06:02 +02:00
|
|
|
TCAP(fc::t_enter_pc_charset_mode) = \
|
2017-12-17 01:06:53 +01:00
|
|
|
C_STR(ESC "%@" ESC "(U");
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Select null mapping
|
2017-09-11 03:06:02 +02:00
|
|
|
TCAP(fc::t_enter_pc_charset_mode) = \
|
2017-12-17 01:06:53 +01:00
|
|
|
C_STR(ESC "(U");
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-10-13 02:16:51 +02:00
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_attr->set_enter_pc_charset_mode \
|
|
|
|
(TCAP(fc::t_enter_pc_charset_mode));
|
2016-11-02 00:37:58 +01:00
|
|
|
reinit = true;
|
|
|
|
}
|
2016-10-13 02:16:51 +02:00
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Fallback if tcap "S3" is not found
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( ! TCAP(fc::t_exit_pc_charset_mode) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( utf8_console )
|
|
|
|
{
|
|
|
|
// Select ascii mapping + utf8
|
2017-09-11 03:06:02 +02:00
|
|
|
TCAP(fc::t_exit_pc_charset_mode) = \
|
2017-12-17 01:06:53 +01:00
|
|
|
C_STR(ESC "(B" ESC "%G");
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Select ascii mapping
|
2017-09-11 03:06:02 +02:00
|
|
|
TCAP(fc::t_enter_pc_charset_mode) = \
|
2017-12-17 01:06:53 +01:00
|
|
|
C_STR(ESC "(B");
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_attr->set_exit_pc_charset_mode \
|
2017-11-30 02:38:55 +01:00
|
|
|
(TCAP(fc::t_exit_pc_charset_mode));
|
2016-11-02 00:37:58 +01:00
|
|
|
reinit = true;
|
2016-10-13 02:16:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( reinit )
|
2018-04-02 22:04:29 +02:00
|
|
|
opti_attr->initialize();
|
2016-01-08 01:00:05 +01:00
|
|
|
}
|
|
|
|
|
2016-10-09 02:06:06 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-11-18 02:34:41 +01:00
|
|
|
void FTerm::init_cygwin_charmap()
|
2016-10-09 02:06:06 +02:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
// Replace don't printable characters in a Cygwin terminal
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isCygwinTerminal() )
|
2017-11-18 02:34:41 +01:00
|
|
|
return;
|
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; i <= fc::lastCharItem; i++ )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( fc::character[i][fc::UTF8] == fc::BlackUpPointingTriangle // ▲
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::BlackDownPointingTriangle // ▼
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::SquareRoot ) // SquareRoot √
|
|
|
|
fc::character[i][fc::PC] = fc::character[i][fc::ASCII];
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_fixed_max_color()
|
|
|
|
{
|
|
|
|
// Initialize maximum number of colors for known terminals
|
|
|
|
|
|
|
|
if ( isCygwinTerminal()
|
|
|
|
|| isPuttyTerminal()
|
|
|
|
|| isTeraTerm()
|
|
|
|
|| isRxvtTerminal() )
|
|
|
|
{
|
|
|
|
FTermcap::max_color = 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_teraterm_charmap()
|
|
|
|
{
|
|
|
|
// Tera Term can't print ascii characters < 0x20
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( ! isTeraTerm() )
|
2017-11-18 02:34:41 +01:00
|
|
|
return;
|
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; i <= fc::lastCharItem; i++ )
|
|
|
|
if ( fc::character[i][fc::PC] < 0x20 )
|
|
|
|
fc::character[i][fc::PC] = fc::character[i][fc::ASCII];
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-02-19 01:36:38 +01:00
|
|
|
/* Terminal capability data base
|
|
|
|
* -----------------------------
|
|
|
|
* Info under: man 5 terminfo
|
|
|
|
*
|
|
|
|
* Importent shell commands:
|
|
|
|
* captoinfo - convert all termcap descriptions into terminfo descriptions
|
|
|
|
* infocmp - print out terminfo description from the current terminal
|
|
|
|
*/
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap()
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-02-19 01:36:38 +01:00
|
|
|
std::vector<std::string> terminals;
|
|
|
|
std::vector<std::string>::iterator iter;
|
|
|
|
static const int success = 1;
|
|
|
|
static const int uninitialized = -2;
|
2017-11-18 02:34:41 +01:00
|
|
|
static char term_buffer[2048];
|
|
|
|
static char string_buf[2048];
|
|
|
|
char* buffer = string_buf;
|
|
|
|
int status = uninitialized;
|
|
|
|
|
|
|
|
// share the terminal capabilities
|
|
|
|
FTermcap().setTermcapMap(tcap);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
// open termcap file
|
|
|
|
terminals.push_back(termtype); // available terminal type
|
2016-10-02 21:26:25 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
if ( color256 ) // 1st fallback if not found
|
|
|
|
terminals.push_back("xterm-256color");
|
|
|
|
|
|
|
|
terminals.push_back("xterm"); // 2nd fallback if not found
|
|
|
|
terminals.push_back("ansi"); // 3rd fallback if not found
|
|
|
|
terminals.push_back("vt100"); // 4th fallback if not found
|
|
|
|
iter = terminals.begin();
|
2017-04-02 21:32:48 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
while ( iter != terminals.end() )
|
2017-03-26 20:40:04 +02:00
|
|
|
{
|
2018-02-19 01:36:38 +01:00
|
|
|
// Copy c-string + terminating null-character ('\0')
|
2018-03-16 01:05:45 +01:00
|
|
|
std::strncpy (termtype, iter->c_str(), iter->length() + 1);
|
2018-02-19 01:36:38 +01:00
|
|
|
|
|
|
|
// Open the termcap file + load entry for termtype
|
2017-03-26 20:40:04 +02:00
|
|
|
status = tgetent(term_buffer, termtype);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( status == success || ! term_detection->hasTerminalDetection() )
|
2018-02-19 01:36:38 +01:00
|
|
|
break;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
++iter;
|
2017-03-26 20:40:04 +02:00
|
|
|
}
|
2016-10-02 21:26:25 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
if ( std::strncmp(termtype, "ansi", 4) == 0 )
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection->setAnsiTerminal (true);
|
2018-02-19 01:36:38 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap_error (status);
|
|
|
|
init_termcap_variables (buffer);
|
2018-02-19 01:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_error (int status)
|
2018-02-19 01:36:38 +01:00
|
|
|
{
|
|
|
|
static const int no_entry = 0;
|
|
|
|
static const int db_not_found = -1;
|
|
|
|
static const int uninitialized = -2;
|
|
|
|
|
|
|
|
if ( status == no_entry || status == uninitialized )
|
2017-03-26 20:40:04 +02:00
|
|
|
{
|
|
|
|
std::cerr << "Unknown terminal: " << termtype << "\n"
|
|
|
|
<< "Check the TERM environment variable\n"
|
|
|
|
<< "Also make sure that the terminal\n"
|
|
|
|
<< "is defined in the termcap/terminfo database.\n";
|
|
|
|
std::abort();
|
|
|
|
}
|
|
|
|
else if ( status == db_not_found )
|
|
|
|
{
|
|
|
|
std::cerr << "The termcap/terminfo database could not be found.\n";
|
|
|
|
std::abort();
|
|
|
|
}
|
2018-02-19 01:36:38 +01:00
|
|
|
}
|
2016-10-02 21:26:25 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_variables (char*& buffer)
|
2018-02-19 01:36:38 +01:00
|
|
|
{
|
2017-11-18 21:03:02 +01:00
|
|
|
// Get termcap booleans
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap_booleans();
|
2016-10-02 21:26:25 +02:00
|
|
|
|
2018-02-19 01:36:38 +01:00
|
|
|
// Get termcap numerics
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap_numerics();
|
2017-11-18 21:03:02 +01:00
|
|
|
|
|
|
|
// Get termcap strings
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap_strings(buffer);
|
2017-11-18 21:03:02 +01:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// Terminal quirks
|
|
|
|
FTermcapQuirks termcap_quirks;
|
|
|
|
termcap_quirks.setTermcapMap (tcap); // Parameter
|
|
|
|
termcap_quirks.setFTermDetection (term_detection);
|
|
|
|
termcap_quirks.setTerminalType (termtype);
|
|
|
|
termcap_quirks.terminalFixup(); // Fix terminal quirks
|
2017-11-25 18:37:40 +01:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Get termcap keys
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap_keys(buffer);
|
2017-11-18 21:03:02 +01:00
|
|
|
|
|
|
|
// Initialize cursor movement optimization
|
|
|
|
init_OptiMove();
|
|
|
|
|
|
|
|
// Initialize video attributes optimization
|
|
|
|
init_OptiAttr();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_booleans()
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
|
|
|
// Get termcap booleans
|
|
|
|
|
|
|
|
// Screen erased with the background color
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::background_color_erase = tgetflag(C_STR("ut"));
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
// t_cursor_left wraps from column 0 to last column
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::automatic_left_margin = tgetflag(C_STR("bw"));
|
2017-02-07 17:15:01 +01:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Terminal has auto-matic margins
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::automatic_right_margin = tgetflag(C_STR("am"));
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// NewLine ignored after 80 cols
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::eat_nl_glitch = tgetflag(C_STR("xn"));
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Terminal supports ANSI set default fg and bg color
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::ansi_default_color = tgetflag(C_STR("AX"));
|
2015-08-09 23:39:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Terminal supports operating system commands (OSC)
|
2017-03-26 20:40:04 +02:00
|
|
|
// OSC = Esc + ']'
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::osc_support = tgetflag(C_STR("XT"));
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
// U8 is nonzero for terminals with no VT100 line-drawing in UTF-8 mode
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::no_utf8_acs_chars = bool(tgetnum(C_STR("U8")) != 0);
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
2015-08-09 23:39:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_numerics()
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
|
|
|
// Get termcap numeric
|
|
|
|
|
|
|
|
// Maximum number of colors on screen
|
2017-03-26 20:40:04 +02:00
|
|
|
FTermcap::max_color = std::max( FTermcap::max_color
|
2017-12-17 01:06:53 +01:00
|
|
|
, tgetnum(C_STR("Co")) );
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
if ( FTermcap::max_color < 0 )
|
|
|
|
FTermcap::max_color = 1;
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
if ( FTermcap::max_color < 8 )
|
|
|
|
monochron = true;
|
|
|
|
else
|
|
|
|
monochron = false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Get initial spacing for hardware tab stop
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::tabstop = tgetnum(C_STR("it"));
|
2016-10-09 02:06:06 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Get video attributes that cannot be used with colors
|
2017-12-17 01:06:53 +01:00
|
|
|
FTermcap::attr_without_color = tgetnum(C_STR("NC"));
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_strings (char*& buffer)
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
|
|
|
// Get termcap strings
|
2017-03-26 20:40:04 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Read termcap output strings
|
2017-08-27 09:50:30 +02:00
|
|
|
for (int i = 0; tcap[i].tname[0] != 0; i++)
|
2017-03-26 20:40:04 +02:00
|
|
|
tcap[i].string = tgetstr(tcap[i].tname, &buffer);
|
2017-11-25 18:37:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap_keys (char*& buffer)
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
|
|
|
// Read termcap key strings
|
2017-03-28 08:50:37 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; fc::Fkey[i].tname[0] != 0; i++)
|
2017-03-26 20:40:04 +02:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
fc::Fkey[i].string = tgetstr(fc::Fkey[i].tname, &buffer);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Fallback for rxvt with TERM=xterm
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "khx", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "7~"); // Home key
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "@7x", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "8~"); // End key
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k1x", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "11~"); // F1
|
2016-10-13 02:16:51 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k2x", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "12~"); // F2
|
2017-03-26 20:40:04 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k3x", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "13~"); // F3
|
2017-03-26 20:40:04 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k4x", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "14~"); // F4
|
2017-03-26 20:40:04 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
// Fallback for TERM=ansi
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "@7X", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "K"); // End key
|
2017-03-26 20:40:04 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
// Some terminals (e.g. PuTTY) send the wrong code for the arrow keys
|
|
|
|
// http://www.unix.com/shell-programming-scripting/..
|
|
|
|
// ..110380-using-arrow-keys-shell-scripts.html
|
2017-12-17 01:06:53 +01:00
|
|
|
char* key_up_string = tgetstr(C_STR("ku"), &buffer);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
if ( (key_up_string && (std::strcmp(key_up_string, CSI "A") == 0))
|
2017-11-26 22:37:18 +01:00
|
|
|
|| ( TCAP(fc::t_cursor_up)
|
|
|
|
&& (std::strcmp(TCAP(fc::t_cursor_up), CSI "A") == 0) ) )
|
2017-03-26 20:40:04 +02:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
for (int i = 0; fc::Fkey[i].tname[0] != 0; i++)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "kux", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "A"); // Key up
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "kdx", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "B"); // Key down
|
2016-02-04 01:27:15 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "krx", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "C"); // Key right
|
2017-11-25 18:37:40 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "klx", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(CSI "D"); // Key left
|
2016-02-04 01:27:15 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k1X", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(ESC "OP"); // PF1
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k2X", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(ESC "OQ"); // PF2
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k3X", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(ESC "OR"); // PF3
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( std::strncmp(fc::Fkey[i].tname, "k4X", 3) == 0 )
|
|
|
|
fc::Fkey[i].string = C_STR(ESC "OS"); // PF4
|
2015-09-30 22:39:02 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_OptiMove()
|
|
|
|
{
|
|
|
|
// Duration precalculation of the cursor movement strings
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
opti_move->setTabStop(int(FTermcap::tabstop));
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_move->set_cursor_home (TCAP(fc::t_cursor_home));
|
|
|
|
opti_move->set_cursor_to_ll (TCAP(fc::t_cursor_to_ll));
|
|
|
|
opti_move->set_carriage_return (TCAP(fc::t_carriage_return));
|
|
|
|
opti_move->set_tabular (TCAP(fc::t_tab));
|
|
|
|
opti_move->set_back_tab (TCAP(fc::t_back_tab));
|
|
|
|
opti_move->set_cursor_up (TCAP(fc::t_cursor_up));
|
|
|
|
opti_move->set_cursor_down (TCAP(fc::t_cursor_down));
|
|
|
|
opti_move->set_cursor_left (TCAP(fc::t_cursor_left));
|
|
|
|
opti_move->set_cursor_right (TCAP(fc::t_cursor_right));
|
|
|
|
cursor_addres_lengths = \
|
2017-11-30 02:38:55 +01:00
|
|
|
opti_move->set_cursor_address (TCAP(fc::t_cursor_address));
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_move->set_column_address (TCAP(fc::t_column_address));
|
|
|
|
opti_move->set_row_address (TCAP(fc::t_row_address));
|
|
|
|
opti_move->set_parm_up_cursor (TCAP(fc::t_parm_up_cursor));
|
|
|
|
opti_move->set_parm_down_cursor (TCAP(fc::t_parm_down_cursor));
|
|
|
|
opti_move->set_parm_left_cursor (TCAP(fc::t_parm_left_cursor));
|
|
|
|
opti_move->set_parm_right_cursor (TCAP(fc::t_parm_right_cursor));
|
2016-11-02 00:37:58 +01:00
|
|
|
opti_move->set_auto_left_margin (FTermcap::automatic_left_margin);
|
|
|
|
opti_move->set_eat_newline_glitch (FTermcap::eat_nl_glitch);
|
2017-09-11 03:06:02 +02:00
|
|
|
erase_ch_length = \
|
2017-11-30 02:38:55 +01:00
|
|
|
opti_move->set_erase_chars (TCAP(fc::t_erase_chars));
|
2017-09-11 03:06:02 +02:00
|
|
|
repeat_char_length = \
|
2017-11-30 02:38:55 +01:00
|
|
|
opti_move->set_repeat_char (TCAP(fc::t_repeat_char));
|
2017-09-11 03:06:02 +02:00
|
|
|
clr_bol_length = opti_move->set_clr_bol (TCAP(fc::t_clr_bol));
|
|
|
|
clr_eol_length = opti_move->set_clr_eol (TCAP(fc::t_clr_eol));
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_OptiAttr()
|
|
|
|
{
|
2017-11-22 23:56:21 +01:00
|
|
|
// Setting video attribute optimization
|
2017-11-19 19:47:24 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
opti_attr->setNoColorVideo (int(FTermcap::attr_without_color));
|
2017-09-11 03:06:02 +02:00
|
|
|
opti_attr->set_enter_bold_mode (TCAP(fc::t_enter_bold_mode));
|
|
|
|
opti_attr->set_exit_bold_mode (TCAP(fc::t_exit_bold_mode));
|
|
|
|
opti_attr->set_enter_dim_mode (TCAP(fc::t_enter_dim_mode));
|
|
|
|
opti_attr->set_exit_dim_mode (TCAP(fc::t_exit_dim_mode));
|
|
|
|
opti_attr->set_enter_italics_mode (TCAP(fc::t_enter_italics_mode));
|
|
|
|
opti_attr->set_exit_italics_mode (TCAP(fc::t_exit_italics_mode));
|
|
|
|
opti_attr->set_enter_underline_mode (TCAP(fc::t_enter_underline_mode));
|
|
|
|
opti_attr->set_exit_underline_mode (TCAP(fc::t_exit_underline_mode));
|
|
|
|
opti_attr->set_enter_blink_mode (TCAP(fc::t_enter_blink_mode));
|
|
|
|
opti_attr->set_exit_blink_mode (TCAP(fc::t_exit_blink_mode));
|
|
|
|
opti_attr->set_enter_reverse_mode (TCAP(fc::t_enter_reverse_mode));
|
|
|
|
opti_attr->set_exit_reverse_mode (TCAP(fc::t_exit_reverse_mode));
|
|
|
|
opti_attr->set_enter_standout_mode (TCAP(fc::t_enter_standout_mode));
|
|
|
|
opti_attr->set_exit_standout_mode (TCAP(fc::t_exit_standout_mode));
|
|
|
|
opti_attr->set_enter_secure_mode (TCAP(fc::t_enter_secure_mode));
|
|
|
|
opti_attr->set_exit_secure_mode (TCAP(fc::t_exit_secure_mode));
|
|
|
|
opti_attr->set_enter_protected_mode (TCAP(fc::t_enter_protected_mode));
|
|
|
|
opti_attr->set_exit_protected_mode (TCAP(fc::t_exit_protected_mode));
|
|
|
|
opti_attr->set_enter_crossed_out_mode (TCAP(fc::t_enter_crossed_out_mode));
|
|
|
|
opti_attr->set_exit_crossed_out_mode (TCAP(fc::t_exit_crossed_out_mode));
|
|
|
|
opti_attr->set_enter_dbl_underline_mode (TCAP(fc::t_enter_dbl_underline_mode));
|
|
|
|
opti_attr->set_exit_dbl_underline_mode (TCAP(fc::t_exit_dbl_underline_mode));
|
|
|
|
opti_attr->set_set_attributes (TCAP(fc::t_set_attributes));
|
|
|
|
opti_attr->set_exit_attribute_mode (TCAP(fc::t_exit_attribute_mode));
|
|
|
|
opti_attr->set_enter_alt_charset_mode (TCAP(fc::t_enter_alt_charset_mode));
|
|
|
|
opti_attr->set_exit_alt_charset_mode (TCAP(fc::t_exit_alt_charset_mode));
|
|
|
|
opti_attr->set_enter_pc_charset_mode (TCAP(fc::t_enter_pc_charset_mode));
|
|
|
|
opti_attr->set_exit_pc_charset_mode (TCAP(fc::t_exit_pc_charset_mode));
|
|
|
|
opti_attr->set_a_foreground_color (TCAP(fc::t_set_a_foreground));
|
|
|
|
opti_attr->set_a_background_color (TCAP(fc::t_set_a_background));
|
|
|
|
opti_attr->set_foreground_color (TCAP(fc::t_set_foreground));
|
|
|
|
opti_attr->set_background_color (TCAP(fc::t_set_background));
|
|
|
|
opti_attr->set_term_color_pair (TCAP(fc::t_set_color_pair));
|
|
|
|
opti_attr->set_orig_pair (TCAP(fc::t_orig_pair));
|
|
|
|
opti_attr->set_orig_orig_colors (TCAP(fc::t_orig_colors));
|
2016-11-02 00:37:58 +01:00
|
|
|
opti_attr->setMaxColor (FTermcap::max_color);
|
2015-10-17 20:39:08 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( FTermcap::ansi_default_color )
|
|
|
|
opti_attr->setDefaultColorSupport();
|
2015-10-17 20:39:08 +02:00
|
|
|
|
2018-04-02 22:04:29 +02:00
|
|
|
opti_attr->initialize();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_font()
|
|
|
|
{
|
|
|
|
if ( init_values.vgafont )
|
|
|
|
{
|
|
|
|
bool ret = setVGAFont();
|
|
|
|
|
|
|
|
if ( ! ret )
|
|
|
|
exitWithMessage ("VGAfont is not supported by this terminal");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( init_values.newfont )
|
|
|
|
{
|
|
|
|
bool ret = setNewFont();
|
|
|
|
|
|
|
|
if ( ! ret )
|
|
|
|
exitWithMessage ("Newfont is not supported by this terminal");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_locale()
|
|
|
|
{
|
|
|
|
// Init current locale
|
|
|
|
locale_name = std::setlocale (LC_ALL, "");
|
|
|
|
locale_name = std::setlocale (LC_NUMERIC, "");
|
|
|
|
|
|
|
|
// Get XTERM_LOCALE
|
|
|
|
locale_xterm = std::getenv("XTERM_LOCALE");
|
|
|
|
|
|
|
|
// set LC_ALL to XTERM_LOCALE
|
|
|
|
if ( locale_xterm )
|
|
|
|
locale_name = std::setlocale (LC_ALL, locale_xterm);
|
|
|
|
|
|
|
|
// TeraTerm can not show UTF-8 character
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isTeraTerm() && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") )
|
2017-11-18 02:34:41 +01:00
|
|
|
locale_name = std::setlocale (LC_ALL, "C");
|
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Kterm
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isKtermTerminal() && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") )
|
2018-01-02 20:38:45 +01:00
|
|
|
locale_name = std::setlocale (LC_ALL, "C");
|
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Sun (color) workstation console can't show UTF-8 character
|
|
|
|
if ( std::strncmp(termtype, "sun", 3) == 0
|
|
|
|
&& ! std::strcmp(nl_langinfo(CODESET), "UTF-8") )
|
|
|
|
locale_name = std::setlocale (LC_ALL, "C");
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Try to found a meaningful content for locale_name
|
|
|
|
if ( locale_name )
|
|
|
|
locale_name = std::setlocale (LC_CTYPE, 0);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
locale_name = std::getenv("LC_ALL");
|
|
|
|
|
|
|
|
if ( ! locale_name )
|
|
|
|
{
|
|
|
|
locale_name = std::getenv("LC_CTYPE");
|
|
|
|
|
|
|
|
if ( ! locale_name )
|
|
|
|
locale_name = std::getenv("LANG");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fallback to C
|
|
|
|
if ( ! locale_name )
|
2017-12-17 01:06:53 +01:00
|
|
|
locale_name = C_STR("C");
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::init_encoding()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// detect encoding and set the Fputchar function pointer
|
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
init_encoding_set();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
|
|
|
if ( isRxvtTerminal() )
|
|
|
|
force_vt100 = true; // This rxvt terminal does not support utf-8
|
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
init_term_encoding();
|
|
|
|
init_pc_charset();
|
|
|
|
init_individual_term_encoding();
|
|
|
|
|
|
|
|
if ( ! init_force_vt100_encoding() )
|
|
|
|
init_utf8_without_alt_charset();
|
|
|
|
|
|
|
|
init_tab_quirks();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
|
|
|
if ( init_values.encoding != fc::UNKNOWN )
|
|
|
|
{
|
|
|
|
setEncoding(init_values.encoding);
|
|
|
|
}
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::init_encoding_set()
|
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
// Define the encoding set
|
2018-02-19 23:02:54 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
(*encoding_set)["UTF8"] = fc::UTF8;
|
|
|
|
(*encoding_set)["UTF-8"] = fc::UTF8;
|
|
|
|
(*encoding_set)["VT100"] = fc::VT100;
|
|
|
|
(*encoding_set)["PC"] = fc::PC;
|
|
|
|
(*encoding_set)["ASCII"] = fc::ASCII;
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_term_encoding()
|
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
int stdout_no = FTermios::getStdOut();
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( isatty(stdout_no)
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ! std::strcmp(nl_langinfo(CODESET), "UTF-8") )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
utf8_console = true;
|
|
|
|
term_encoding = fc::UTF8;
|
|
|
|
Fputchar = &FTerm::putchar_UTF8; // function pointer
|
|
|
|
utf8_state = true;
|
|
|
|
utf8_input = true;
|
2016-11-02 00:37:58 +01:00
|
|
|
setUTF8(true);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-12-18 23:34:11 +01:00
|
|
|
else if ( isatty(stdout_no)
|
2017-11-26 22:37:18 +01:00
|
|
|
&& (std::strlen(termtype) > 0)
|
|
|
|
&& (TCAP(fc::t_exit_alt_charset_mode) != 0) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
vt100_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::VT100;
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ascii_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::ASCII;
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_individual_term_encoding()
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm()
|
|
|
|
|| isCygwinTerminal()
|
|
|
|
|| isNewFont()
|
|
|
|
|| (isPuttyTerminal() && ! isUTF8())
|
|
|
|
|| (isTeraTerm() && ! isUTF8()) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
pc_charset_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::PC;
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( hasUTF8() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() )
|
|
|
|
setUTF8(false);
|
|
|
|
else if ( isXTerminal() )
|
|
|
|
Fputchar = &FTerm::putchar_UTF8; // function pointer
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::init_force_vt100_encoding()
|
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( force_vt100 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
vt100_console = true;
|
2017-11-18 02:34:41 +01:00
|
|
|
term_encoding = fc::VT100;
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-02-19 23:02:54 +01:00
|
|
|
|
|
|
|
return force_vt100;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_utf8_without_alt_charset()
|
|
|
|
{
|
|
|
|
// Fall back to ascii for utf-8 terminals that
|
|
|
|
// do not support VT100 line drawings
|
|
|
|
|
|
|
|
if ( FTermcap::no_utf8_acs_chars && isUTF8()
|
|
|
|
&& term_encoding == fc::VT100 )
|
2018-01-02 20:38:45 +01:00
|
|
|
{
|
|
|
|
ascii_console = true;
|
|
|
|
term_encoding = fc::ASCII;
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
|
|
|
}
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
2016-12-27 23:03:32 +01:00
|
|
|
|
2018-02-19 23:02:54 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_tab_quirks()
|
|
|
|
{
|
2017-03-26 20:40:04 +02:00
|
|
|
// In some alternative character sets, a tab character prints a '○'
|
|
|
|
// on the terminal and does not move the cursor to the next tab stop
|
|
|
|
// position
|
2018-02-19 23:02:54 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
if ( term_encoding == fc::VT100 || term_encoding == fc::PC )
|
2016-12-27 23:03:32 +01:00
|
|
|
{
|
|
|
|
char* empty = 0;
|
|
|
|
opti_move->set_tabular (empty);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::redefineColorPalette()
|
|
|
|
{
|
2018-01-24 00:25:32 +01:00
|
|
|
// Redefine the color palette
|
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isCygwinTerminal()
|
|
|
|
|| isKdeTerminal()
|
|
|
|
|| isTeraTerm()
|
2018-05-02 12:31:21 +02:00
|
|
|
|| isNetBSDTerm()
|
|
|
|
|| isOpenBSDTerm()
|
2018-04-19 01:55:17 +02:00
|
|
|
|| isSunTerminal()
|
|
|
|
|| isAnsiTerminal() )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
resetColorMap();
|
|
|
|
saveColorMap();
|
|
|
|
|
|
|
|
if ( FTermcap::max_color >= 16 )
|
2018-01-24 23:02:45 +01:00
|
|
|
FColorPalette::set16ColorPalette (FTerm::setPalette);
|
2017-12-14 00:35:10 +01:00
|
|
|
else // 8 colors
|
2018-01-24 23:02:45 +01:00
|
|
|
FColorPalette::set8ColorPalette (FTerm::setPalette);
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::restoreColorPalette()
|
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( isCygwinTerminal()
|
|
|
|
|| isKdeTerminal()
|
2018-04-19 01:55:17 +02:00
|
|
|
|| isTeraTerm()
|
2018-05-02 12:31:21 +02:00
|
|
|
|| isNetBSDTerm()
|
|
|
|
|| isOpenBSDTerm()
|
2018-04-19 01:55:17 +02:00
|
|
|
|| isSunTerminal()
|
|
|
|
|| isAnsiTerminal() )
|
2017-12-14 00:35:10 +01:00
|
|
|
return;
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Reset screen settings
|
|
|
|
if ( FTermcap::max_color >= 16 )
|
2018-01-24 23:02:45 +01:00
|
|
|
FColorPalette::reset16ColorPalette (FTerm::setPalette);
|
2017-12-14 00:35:10 +01:00
|
|
|
else // 8 colors
|
2018-01-24 23:02:45 +01:00
|
|
|
FColorPalette::reset8ColorPalette (FTerm::setPalette);
|
2017-12-14 00:35:10 +01:00
|
|
|
|
|
|
|
resetXTermColors();
|
|
|
|
resetColorMap();
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::enableMouse()
|
|
|
|
{
|
2018-01-14 21:21:08 +01:00
|
|
|
bool gpm_mouse = false;
|
|
|
|
bool xterm_mouse = false;
|
2017-11-26 19:00:04 +01:00
|
|
|
|
2018-01-16 16:16:29 +01:00
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() && openConsole() == 0 )
|
2017-11-26 19:00:04 +01:00
|
|
|
{
|
2018-01-14 21:21:08 +01:00
|
|
|
if ( isLinuxConsole() )
|
|
|
|
gpm_mouse = true;
|
|
|
|
|
|
|
|
closeConsole();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
2018-01-16 16:16:29 +01:00
|
|
|
#endif
|
2018-01-14 21:21:08 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( TCAP(fc::t_key_mouse) && ! isLinuxTerm() )
|
2018-01-14 21:21:08 +01:00
|
|
|
xterm_mouse = true;
|
|
|
|
|
|
|
|
mouse->setMaxWidth (short(getColumnNumber()));
|
|
|
|
mouse->setMaxHeight (short(getLineNumber()));
|
|
|
|
// Enable the linux general purpose mouse (gpm) server
|
|
|
|
mouse->useGpmMouse (gpm_mouse);
|
|
|
|
// Enable xterm mouse support
|
|
|
|
mouse->useXtermMouse (xterm_mouse);
|
|
|
|
mouse->enable();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::disableMouse()
|
|
|
|
{
|
2018-01-14 21:21:08 +01:00
|
|
|
mouse->disable();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::useAlternateScreenBuffer()
|
|
|
|
{
|
|
|
|
if ( ! use_alternate_screen )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Save current cursor position
|
|
|
|
if ( TCAP(fc::t_save_cursor) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_save_cursor));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Saves the screen and the cursor position
|
|
|
|
if ( TCAP(fc::t_enter_ca_mode) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_enter_ca_mode));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::useNormalScreenBuffer()
|
|
|
|
{
|
|
|
|
if ( ! use_alternate_screen )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// restores the screen and the cursor position
|
|
|
|
if ( TCAP(fc::t_exit_ca_mode) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_exit_ca_mode));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// restore cursor to position of last save_cursor
|
|
|
|
if ( TCAP(fc::t_restore_cursor) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_restore_cursor));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::captureXTermFontAndTitle()
|
|
|
|
{
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( (isXTerminal() || isUrxvtTerminal()) && ! isRxvtTerminal() )
|
2017-11-26 19:00:04 +01:00
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::setCaptureSendCharacters();
|
2017-11-26 19:00:04 +01:00
|
|
|
xterm_font = getXTermFont();
|
|
|
|
xterm_title = getXTermTitle();
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::unsetCaptureSendCharacters();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2017-12-21 00:45:04 +01:00
|
|
|
inline void FTerm::allocationValues()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-08-12 22:55:29 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
opti_move = new FOptiMove();
|
|
|
|
opti_attr = new FOptiAttr();
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection = new FTermDetection();
|
2018-01-14 21:21:08 +01:00
|
|
|
mouse = new FMouseControl();
|
2017-09-11 03:06:02 +02:00
|
|
|
term = new FRect(0, 0, 0, 0);
|
|
|
|
vt100_alt_char = new std::map<uChar, uChar>;
|
|
|
|
encoding_set = new std::map<std::string, fc::encoding>;
|
2017-08-12 22:55:29 +02:00
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
|
|
|
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
|
|
|
|
std::abort();
|
|
|
|
}
|
2017-12-21 00:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::deallocationValues()
|
|
|
|
{
|
|
|
|
if ( encoding_set )
|
|
|
|
delete encoding_set;
|
|
|
|
|
|
|
|
if ( vt100_alt_char )
|
|
|
|
delete vt100_alt_char;
|
|
|
|
|
|
|
|
if ( xterm_title )
|
|
|
|
delete xterm_title;
|
|
|
|
|
|
|
|
if ( xterm_font )
|
|
|
|
delete xterm_font;
|
|
|
|
|
|
|
|
if ( term )
|
|
|
|
delete term;
|
|
|
|
|
2018-01-14 21:21:08 +01:00
|
|
|
if ( mouse )
|
|
|
|
delete mouse;
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( term_detection )
|
|
|
|
delete term_detection;
|
|
|
|
|
2017-12-21 00:45:04 +01:00
|
|
|
if ( opti_attr )
|
|
|
|
delete opti_attr;
|
|
|
|
|
|
|
|
if ( opti_move )
|
|
|
|
delete opti_move;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init()
|
|
|
|
{
|
2018-05-02 12:31:21 +02:00
|
|
|
int stdout_no = FTermios::getStdOut();
|
2017-12-21 00:45:04 +01:00
|
|
|
init_term_object = this;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Initialize global values for all objects
|
2017-12-21 00:45:04 +01:00
|
|
|
allocationValues();
|
2017-11-18 02:34:41 +01:00
|
|
|
init_global_values();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// Initialize termios
|
|
|
|
FTermios::init();
|
2017-11-18 02:34:41 +01:00
|
|
|
|
|
|
|
// Get the stdin file status flags
|
2018-05-02 12:31:21 +02:00
|
|
|
stdin_status_flags = fcntl(FTermios::getStdIn(), F_GETFL);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( stdin_status_flags == -1 )
|
|
|
|
std::abort();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
// Get pathname of the terminal device
|
2018-02-11 23:41:23 +01:00
|
|
|
if ( ttyname_r(stdout_no, termfilename, sizeof(termfilename)) )
|
|
|
|
termfilename[0] = '\0';
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection->setTermFileName(termfilename);
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
initOSspecifics();
|
2017-04-14 23:55:44 +02:00
|
|
|
|
2017-04-08 02:40:22 +02:00
|
|
|
// Save termios settings
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::storeTTYsettings();
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2017-04-08 02:40:22 +02:00
|
|
|
// Get output baud rate
|
2018-05-02 12:31:21 +02:00
|
|
|
baudrate = FTermios::getBaudRate();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( isatty(stdout_no) )
|
|
|
|
opti_move->setBaudRate(int(baudrate));
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-04-08 02:40:22 +02:00
|
|
|
// Terminal detection
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection->detect();
|
|
|
|
setTermType (term_detection->getTermType());
|
|
|
|
|
|
|
|
// Set maximum number of colors for detected terminals
|
|
|
|
init_fixed_max_color();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
// Initializes variables for the current terminal
|
2018-05-02 12:31:21 +02:00
|
|
|
init_termcap();
|
2016-11-02 00:37:58 +01:00
|
|
|
init_alt_charset();
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Initializes locale information
|
|
|
|
init_locale();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// Detect environment and set encoding
|
|
|
|
init_encoding();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Enable the terminal mouse support
|
|
|
|
enableMouse();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Activate meta key sends escape
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() )
|
2017-04-11 00:30:27 +02:00
|
|
|
xtermMetaSendsESC(true);
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// switch to application escape key mode
|
|
|
|
if ( isMinttyTerm() )
|
|
|
|
FTerm::putstring (CSI "?7727h");
|
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Enter 'keyboard_transmit' mode
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_keypad_xmit) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_keypad_xmit));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
useAlternateScreenBuffer();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Enable alternate charset
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_enable_acs) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_enable_acs));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Save the used xterm font and window title
|
|
|
|
captureXTermFontAndTitle();
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isKdeTerminal() )
|
2016-11-02 00:37:58 +01:00
|
|
|
setKDECursor(fc::UnderlineCursor);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isCygwinTerminal() )
|
2017-11-18 02:34:41 +01:00
|
|
|
init_cygwin_charmap();
|
2017-04-05 00:30:52 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isTeraTerm() )
|
2017-11-18 02:34:41 +01:00
|
|
|
init_teraterm_charmap();
|
2017-04-05 00:30:52 +02:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Redefine the color palette
|
|
|
|
if ( init_values.color_change )
|
|
|
|
redefineColorPalette();
|
|
|
|
|
2017-12-19 02:06:27 +01:00
|
|
|
// Set 200 Hz beep (100 ms)
|
2017-11-18 02:34:41 +01:00
|
|
|
setBeep(200, 100);
|
|
|
|
|
|
|
|
// Set FTerm signal handler
|
|
|
|
setSignalHandler();
|
|
|
|
|
|
|
|
if ( ! init_values.cursor_optimisation )
|
|
|
|
setCursorOptimisation (false);
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Activate the VGA or the new graphic font
|
|
|
|
// (depending on the initialization values)
|
|
|
|
init_font();
|
2016-11-20 18:26:15 +01:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Turn off hardware echo
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::unsetHardwareEcho();
|
2016-11-20 18:26:15 +01:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Switch to the raw mode
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::setRawMode();
|
2017-11-18 02:34:41 +01:00
|
|
|
|
|
|
|
// The terminal is now initialized
|
|
|
|
term_initialized = true;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::initOSspecifics()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
// initialize Linux console
|
|
|
|
initLinuxConsole();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
// Initialize BSD console
|
|
|
|
initFreeBSDConsole();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
// Initialize wscons console
|
|
|
|
initWSConsConsole();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-10-08 02:54:32 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::finish()
|
2016-10-08 02:54:32 +02:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
// Set default signal handler
|
|
|
|
resetSignalHandler();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( xterm_title && isXTerminal() && ! isRxvtTerminal() )
|
2016-11-02 00:37:58 +01:00
|
|
|
setXTermTitle (*xterm_title);
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Restore the saved termios settings
|
2018-05-02 12:31:21 +02:00
|
|
|
FTermios::restoreTTYsettings();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Turn off all attributes
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_exit_attribute_mode) )
|
2016-10-08 02:54:32 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_exit_attribute_mode));
|
2016-10-08 02:54:32 +02:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Turn off pc charset mode
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_exit_pc_charset_mode) )
|
2016-10-08 02:54:32 +02:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_exit_pc_charset_mode));
|
2016-10-08 02:54:32 +02:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Reset xterm color settings to default values
|
2016-11-06 16:36:21 +01:00
|
|
|
resetXTermDefaults();
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Set xterm full block cursor
|
2016-11-02 00:37:58 +01:00
|
|
|
setXTermCursorStyle(fc::steady_block);
|
2016-10-08 02:54:32 +02:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Restore the color palette
|
|
|
|
if ( init_values.color_change )
|
|
|
|
restoreColorPalette();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isMinttyTerm() )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-11-18 02:34:41 +01:00
|
|
|
// Switch to normal escape key mode
|
2016-11-02 00:37:58 +01:00
|
|
|
putstring (CSI "?7727l");
|
|
|
|
std::fflush(stdout);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
finishOSspecifics1();
|
2017-04-14 23:55:44 +02:00
|
|
|
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isKdeTerminal() )
|
2016-11-02 00:37:58 +01:00
|
|
|
setKDECursor(fc::BlockCursor);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
resetBeep();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Disable the terminal mouse support
|
|
|
|
disableMouse();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Deactivate meta key sends escape
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isXTerminal() )
|
2017-04-11 00:30:27 +02:00
|
|
|
xtermMetaSendsESC(false);
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
useNormalScreenBuffer();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// leave 'keyboard_transmit' mode
|
2017-09-11 03:06:02 +02:00
|
|
|
if ( TCAP(fc::t_keypad_local) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
putstring (TCAP(fc::t_keypad_local));
|
2016-11-02 00:37:58 +01:00
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
finishOSspecifics2();
|
|
|
|
deallocationValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::finishOSspecifics1()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() )
|
2018-02-04 19:42:30 +01:00
|
|
|
{
|
|
|
|
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
|
|
|
|
setBlinkAsIntensity (false);
|
|
|
|
#endif
|
|
|
|
setLinuxConsoleCursorStyle (fc::default_cursor, false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
resetFreeBSDAlt2Meta();
|
|
|
|
setFreeBSDConsoleCursorStyle (fc::normal_cursor, false);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
resetWSConsEncoding();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::finishOSspecifics2()
|
|
|
|
{
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-04-19 01:55:17 +02:00
|
|
|
if ( isLinuxTerm() && utf8_console )
|
2016-11-02 00:37:58 +01:00
|
|
|
setUTF8(true);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( NewFont || VGAFont )
|
|
|
|
setOldFont();
|
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( screen_font.data != 0 )
|
|
|
|
delete[] screen_font.data;
|
2015-10-03 01:45:13 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( screen_unicode_map.entries != 0 )
|
|
|
|
delete[] screen_unicode_map.entries;
|
|
|
|
}
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
uInt FTerm::cp437_to_unicode (uChar c)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
register uInt ucs = uInt(c);
|
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
for (register uInt i = 0; i <= fc::lastCP437Item; i++)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( fc::cp437_to_ucs[i][0] == c ) // found
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2017-12-17 01:06:53 +01:00
|
|
|
ucs = fc::cp437_to_ucs[i][1];
|
2016-11-02 00:37:58 +01:00
|
|
|
break;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
return ucs;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline int FTerm::getMouseProtocolKey (char buffer[])
|
|
|
|
{
|
|
|
|
// Looking for mouse string in the key buffer
|
|
|
|
register std::size_t buf_len = std::strlen(buffer);
|
|
|
|
|
|
|
|
// x11 mouse tracking
|
|
|
|
if ( buf_len >= 6 && buffer[1] == '[' && buffer[2] == 'M' )
|
|
|
|
return fc::Fkey_mouse;
|
|
|
|
|
|
|
|
// SGR mouse tracking
|
|
|
|
if ( buffer[1] == '[' && buffer[2] == '<' && buf_len >= 9
|
|
|
|
&& (buffer[buf_len - 1] == 'M' || buffer[buf_len - 1] == 'm') )
|
|
|
|
return fc::Fkey_extended_mouse;
|
|
|
|
|
|
|
|
// urxvt mouse tracking
|
|
|
|
if ( buffer[1] == '[' && buffer[2] >= '1' && buffer[2] <= '9'
|
|
|
|
&& buffer[3] >= '0' && buffer[3] <= '9' && buf_len >= 9
|
|
|
|
&& buffer[buf_len - 1] == 'M' )
|
|
|
|
return fc::Fkey_urxvt_mouse;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline int FTerm::getTermcapKey (char buffer[], int buf_size)
|
|
|
|
{
|
|
|
|
// Looking for termcap key strings in the buffer
|
|
|
|
assert ( buf_size > 0 );
|
|
|
|
|
|
|
|
for (int i = 0; fc::Fkey[i].tname[0] != 0; i++)
|
|
|
|
{
|
|
|
|
char* k = fc::Fkey[i].string;
|
2018-01-05 00:49:00 +01:00
|
|
|
register int len = ( k ) ? int(std::strlen(k)) : 0;
|
2018-01-03 08:42:10 +01:00
|
|
|
|
|
|
|
if ( k && std::strncmp(k, buffer, uInt(len)) == 0 ) // found
|
|
|
|
{
|
2018-01-05 00:49:00 +01:00
|
|
|
register int n;
|
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
for (n = len; n < buf_size; n++) // Remove founded entry
|
|
|
|
buffer[n - len] = buffer[n];
|
|
|
|
|
|
|
|
for (; n - len < len; n++) // Fill rest with '\0'
|
|
|
|
buffer[n - len] = '\0';
|
|
|
|
|
|
|
|
input_data_pending = bool(buffer[0] != '\0');
|
|
|
|
return fc::Fkey[i].num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline int FTerm::getMetaKey ( char buffer[]
|
|
|
|
, int buf_size
|
|
|
|
, timeval* time_keypressed )
|
|
|
|
{
|
|
|
|
// Looking for meta key strings in the buffer
|
|
|
|
assert ( buf_size > 0 );
|
|
|
|
|
|
|
|
for (int i = 0; fc::Fmetakey[i].string[0] != 0; i++)
|
|
|
|
{
|
|
|
|
char* kmeta = fc::Fmetakey[i].string; // The string is never null
|
2018-01-14 21:21:08 +01:00
|
|
|
register int len = int(std::strlen(kmeta));
|
2018-01-03 08:42:10 +01:00
|
|
|
|
|
|
|
if ( std::strncmp(kmeta, buffer, uInt(len)) == 0 ) // found
|
|
|
|
{
|
2018-01-14 21:21:08 +01:00
|
|
|
register int n;
|
|
|
|
|
2018-01-03 08:42:10 +01:00
|
|
|
if ( len == 2 && ( buffer[1] == 'O'
|
|
|
|
|| buffer[1] == '['
|
|
|
|
|| buffer[1] == ']' ) )
|
|
|
|
{
|
|
|
|
if ( ! isKeypressTimeout(time_keypressed) )
|
|
|
|
return NEED_MORE_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (n = len; n < buf_size; n++) // Remove founded entry
|
|
|
|
buffer[n - len] = buffer[n];
|
|
|
|
|
|
|
|
for (; n - len < len; n++) // Fill rest with '\0'
|
|
|
|
buffer[n - len] = '\0';
|
|
|
|
|
|
|
|
input_data_pending = bool(buffer[0] != '\0');
|
|
|
|
return fc::Fmetakey[i].num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-01-03 20:06:22 +01:00
|
|
|
inline int FTerm::getSingleKey (char buffer[], int buf_size)
|
2018-01-03 08:42:10 +01:00
|
|
|
{
|
|
|
|
register uChar firstchar = uChar(buffer[0]);
|
|
|
|
int key, n, len;
|
|
|
|
len = 1;
|
|
|
|
|
|
|
|
// Look for a utf-8 character
|
|
|
|
if ( utf8_input && (firstchar & 0xc0) == 0xc0 )
|
|
|
|
{
|
|
|
|
char utf8char[4] = {}; // Init array with '\0'
|
|
|
|
|
|
|
|
if ( (firstchar & 0xe0) == 0xc0 )
|
|
|
|
len = 2;
|
|
|
|
else if ( (firstchar & 0xf0) == 0xe0 )
|
|
|
|
len = 3;
|
|
|
|
else if ( (firstchar & 0xf8) == 0xf0 )
|
|
|
|
len = 4;
|
|
|
|
|
|
|
|
for (int i = 0; i < len ; i++)
|
|
|
|
utf8char[i] = char(buffer[i] & 0xff);
|
|
|
|
|
|
|
|
key = UTF8decode(utf8char);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
key = uChar(buffer[0] & 0xff);
|
|
|
|
|
|
|
|
for (n = len; n < buf_size; n++) // Remove the key from the buffer front
|
|
|
|
buffer[n - len] = buffer[n];
|
|
|
|
|
|
|
|
for (n = n - len; n < buf_size; n++) // Fill the rest with '\0' bytes
|
|
|
|
buffer[n] = '\0';
|
|
|
|
|
|
|
|
input_data_pending = bool(buffer[0] != '\0');
|
|
|
|
|
|
|
|
if ( key == 0 ) // Ctrl+Space or Ctrl+@
|
|
|
|
key = fc::Fckey_space;
|
|
|
|
|
|
|
|
return int(key == 127 ? fc::Fkey_backspace : key);
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setSignalHandler()
|
|
|
|
{
|
|
|
|
signal(SIGTERM, FTerm::signal_handler); // Termination signal
|
|
|
|
signal(SIGQUIT, FTerm::signal_handler); // Quit from keyboard (Ctrl-\)
|
|
|
|
signal(SIGINT, FTerm::signal_handler); // Keyboard interrupt (Ctrl-C)
|
|
|
|
signal(SIGABRT, FTerm::signal_handler); // Abort signal from abort(3)
|
|
|
|
signal(SIGILL, FTerm::signal_handler); // Illegal Instruction
|
|
|
|
signal(SIGSEGV, FTerm::signal_handler); // Invalid memory reference
|
|
|
|
signal(SIGWINCH, FTerm::signal_handler); // Window resize signal
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetSignalHandler()
|
|
|
|
{
|
|
|
|
signal(SIGWINCH, SIG_DFL); // Window resize signal
|
|
|
|
signal(SIGSEGV, SIG_DFL); // Invalid memory reference
|
|
|
|
signal(SIGILL, SIG_DFL); // Illegal Instruction
|
|
|
|
signal(SIGABRT, SIG_DFL); // Abort signal from abort(3)
|
|
|
|
signal(SIGINT, SIG_DFL); // Keyboard interrupt (Ctrl-C)
|
|
|
|
signal(SIGQUIT, SIG_DFL); // Quit from keyboard (Ctrl-\)
|
|
|
|
signal(SIGTERM, SIG_DFL); // Termination signal
|
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::signal_handler (int signum)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
switch (signum)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
case SIGWINCH:
|
|
|
|
if ( resize_term )
|
|
|
|
break;
|
|
|
|
// initialize a resize event to the root element
|
|
|
|
resize_term = true;
|
|
|
|
break;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
case SIGTERM:
|
|
|
|
case SIGQUIT:
|
|
|
|
case SIGINT:
|
|
|
|
case SIGABRT:
|
|
|
|
case SIGILL:
|
|
|
|
case SIGSEGV:
|
|
|
|
init_term_object->finish();
|
|
|
|
std::fflush (stderr);
|
|
|
|
std::fflush (stdout);
|
|
|
|
std::fprintf ( stderr
|
|
|
|
, "\nProgram stopped: signal %d (%s)\n"
|
|
|
|
, signum
|
|
|
|
, strsignal(signum) );
|
|
|
|
std::terminate();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
}
|