2017-11-04 07:03:53 +01:00
|
|
|
/***********************************************************************
|
2019-05-17 15:48:09 +02:00
|
|
|
* fterm.cpp - Base class for terminal control *
|
2017-11-04 07:03:53 +01:00
|
|
|
* *
|
|
|
|
* This file is part of the Final Cut widget toolkit *
|
|
|
|
* *
|
2019-01-02 03:00:07 +01:00
|
|
|
* Copyright 2012-2019 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>
|
2019-01-03 07:36:18 +01:00
|
|
|
#include <unordered_map>
|
2017-09-11 03:06:02 +02:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2017-09-17 21:32:46 +02:00
|
|
|
#include "final/fterm.h"
|
|
|
|
#include "final/fcharmap.h"
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-09-20 23:59:01 +02:00
|
|
|
namespace finalcut
|
|
|
|
{
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
// global FTerm object
|
2018-12-10 01:48:26 +01:00
|
|
|
static FTerm* init_term_object = nullptr;
|
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
|
2018-10-01 22:27:54 +02:00
|
|
|
FTerm::initializationValues FTerm::init_values;
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermData* FTerm::data = nullptr;
|
2019-05-17 15:48:09 +02:00
|
|
|
FSystem* FTerm::fsys = nullptr;
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermcap::tcap_map* FTerm::tcap = nullptr;
|
|
|
|
FOptiMove* FTerm::opti_move = nullptr;
|
|
|
|
FOptiAttr* FTerm::opti_attr = nullptr;
|
|
|
|
FTermDetection* FTerm::term_detection = nullptr;
|
|
|
|
FTermXTerminal* FTerm::xterm = nullptr;
|
|
|
|
FKeyboard* FTerm::keyboard = nullptr;
|
|
|
|
FMouseControl* FTerm::mouse = nullptr;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermLinux* FTerm::linux = nullptr;
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermFreeBSD* FTerm::freebsd = nullptr;
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermOpenBSD* FTerm::openbsd = nullptr;
|
2017-04-14 23:55:44 +02:00
|
|
|
#endif
|
|
|
|
|
2018-11-01 21:29:54 +01:00
|
|
|
#if DEBUG
|
2018-12-10 01:48:26 +01:00
|
|
|
FTermDebugData* FTerm::debug_data = nullptr;
|
2018-11-01 21:29:54 +01:00
|
|
|
#endif
|
|
|
|
|
2018-11-24 23:43:09 +01:00
|
|
|
// function prototypes
|
|
|
|
uInt env2uint (const char*);
|
|
|
|
|
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)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
|
|
|
if ( ! term_initialized )
|
2018-10-01 22:27:54 +02:00
|
|
|
init (disable_alt_screen);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FTerm::~FTerm() // destructor
|
|
|
|
{
|
2016-10-11 04:57:36 +02:00
|
|
|
if ( init_term_object == this )
|
2018-05-27 19:43:18 +02:00
|
|
|
finish(); // Resetting console settings
|
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
|
|
|
//----------------------------------------------------------------------
|
2018-10-14 06:25:33 +02:00
|
|
|
std::size_t FTerm::getLineNumber()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
auto& term_geometry = data->getTermGeometry();
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
if ( term_geometry.getHeight() == 0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
detectTermSize();
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
return term_geometry.getHeight();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-10-14 06:25:33 +02:00
|
|
|
std::size_t FTerm::getColumnNumber()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
auto& term_geometry = data->getTermGeometry();
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
if ( term_geometry.getWidth() == 0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
detectTermSize();
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
return term_geometry.getWidth();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-10-17 08:44:38 +02:00
|
|
|
//----------------------------------------------------------------------
|
2018-11-21 20:07:08 +01:00
|
|
|
const FString FTerm::getKeyName (FKey keynum)
|
2016-10-17 08:44:38 +02:00
|
|
|
{
|
2018-07-15 19:52:59 +02:00
|
|
|
return keyboard->getKeyName (keynum);
|
2018-01-14 21:21:08 +01:00
|
|
|
}
|
|
|
|
|
2016-11-26 15:18:44 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-06-25 00:14:53 +02:00
|
|
|
bool FTerm::isNormal (charData*& ch)
|
2016-11-26 15:18:44 +01:00
|
|
|
{
|
|
|
|
return opti_attr->isNormal(ch);
|
|
|
|
}
|
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
//----------------------------------------------------------------------
|
2018-10-29 00:45:45 +01:00
|
|
|
bool FTerm::isCursorHideable()
|
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
const char* cursor_off_str = disableCursor();
|
2018-10-29 00:45:45 +01:00
|
|
|
|
|
|
|
if ( cursor_off_str && std::strlen(cursor_off_str) > 0 )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-03 20:56:09 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::canChangeColorPalette()
|
|
|
|
{
|
|
|
|
if ( isCygwinTerminal()
|
|
|
|
|| isKdeTerminal()
|
|
|
|
|| isTeraTerm()
|
|
|
|
|| isMltermTerminal()
|
|
|
|
|| isNetBSDTerm()
|
|
|
|
|| isOpenBSDTerm()
|
|
|
|
|| isSunTerminal()
|
|
|
|
|| isAnsiTerminal() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return FTermcap::can_change_color_palette;
|
|
|
|
}
|
|
|
|
|
2018-10-29 00:45:45 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-08-09 00:04:00 +02:00
|
|
|
void FTerm::setTermType (const char term_name[])
|
2018-05-02 12:31:21 +02:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTermType(term_name);
|
2018-05-02 12:31:21 +02:00
|
|
|
}
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
//----------------------------------------------------------------------
|
2018-12-22 23:50:10 +01:00
|
|
|
void FTerm::setInsertCursor (bool enable)
|
2018-05-20 15:15:42 +02:00
|
|
|
{
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( enable )
|
2018-05-20 15:15:42 +02:00
|
|
|
setInsertCursorStyle();
|
|
|
|
else
|
|
|
|
setOverwriteCursorStyle();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-12-22 23:50:10 +01:00
|
|
|
void FTerm::redefineDefaultColors (bool enable)
|
2018-05-20 15:15:42 +02:00
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
if ( isNewFont() ) // NewFont need the reverse-video attribute
|
|
|
|
return;
|
|
|
|
|
2018-12-22 23:50:10 +01:00
|
|
|
xterm->redefineDefaultColors (enable);
|
2018-05-20 15:15:42 +02:00
|
|
|
}
|
|
|
|
|
2018-01-16 16:16:29 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-12-28 22:57:43 +01:00
|
|
|
void FTerm::setDblclickInterval (const uInt64 timeout)
|
2018-01-16 16:16:29 +01:00
|
|
|
{
|
|
|
|
mouse->setDblclickInterval(timeout);
|
|
|
|
}
|
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2018-12-22 23:50:10 +01:00
|
|
|
bool FTerm::setUTF8 (bool enable) // UTF-8 (Unicode)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( data->isUTF8() == enable )
|
|
|
|
return enable;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( enable )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setUTF8(true);
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setUTF8(false);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
#if defined(__linux__)
|
2018-12-22 23:50:10 +01:00
|
|
|
linux->setUTF8 (enable);
|
2018-06-12 16:37:48 +02:00
|
|
|
#endif
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
return data->isUTF8();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool FTerm::setVGAFont()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->isVGAFont() )
|
|
|
|
return data->isVGAFont();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-10-09 00:33:26 +02:00
|
|
|
if ( hasNoFontSettingOption() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( isXTerminal() || isScreenTerm()
|
|
|
|
|| isUrxvtTerminal() || FTermcap::osc_support )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setVGAFont(true);
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set font in xterm to vga
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->setFont("vga");
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setNewFont(false);
|
|
|
|
data->setTermEncoding (fc::PC);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( isXTerminal() && data->hasUTF8Console() )
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setVGAFont(linux->loadVGAFont());
|
|
|
|
data->setTermEncoding (fc::PC);
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_ASCII;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setVGAFont(false);
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->isVGAFont() )
|
|
|
|
{
|
|
|
|
data->supportShadowCharacter (true);
|
|
|
|
data->supportHalfBlockCharacter (true);
|
|
|
|
}
|
2018-06-12 16:37:48 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
return data->isVGAFont();
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( isNewFont() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return true;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-10-09 00:33:26 +02:00
|
|
|
if ( hasNoFontSettingOption() )
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setNewFont(true);
|
2016-11-02 00:37:58 +01:00
|
|
|
// Set font in xterm to 8x16graph
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->setFont("8x16graph");
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTermEncoding (fc::PC);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( isXTerminal() && data->hasUTF8Console() )
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setNewFont(linux->loadNewFont());
|
|
|
|
data->setTermEncoding (fc::PC);
|
2016-11-02 00:37:58 +01:00
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setNewFont(false);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( isNewFont() )
|
|
|
|
{
|
|
|
|
data->supportShadowCharacter (true);
|
|
|
|
data->supportHalfBlockCharacter (true);
|
|
|
|
}
|
2018-06-12 16:37:48 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
return isNewFont();
|
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
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
bool retval = false;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( ! (data->isNewFont() || data->isVGAFont()) )
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
retval = false;
|
|
|
|
data->setNewFont(false);
|
|
|
|
data->setVGAFont(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
|
|
|
{
|
2018-12-26 23:41:49 +01:00
|
|
|
const auto& font = data->getXtermFont();
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
if ( font.getLength() > 2 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
// restore saved xterm font
|
2018-10-01 22:27:54 +02:00
|
|
|
xterm->setFont (font);
|
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
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->setFont("vga");
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
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
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
retval = linux->loadOldFont(fc::character);
|
2018-06-12 22:53:11 +02:00
|
|
|
|
|
|
|
if ( retval )
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->supportShadowCharacter (linux->hasShadowCharacter());
|
|
|
|
data->supportHalfBlockCharacter (linux->hasHalfBlockCharacter());
|
2018-06-12 22:53:11 +02:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( retval )
|
2018-10-01 22:27:54 +02:00
|
|
|
{
|
|
|
|
data->setVGAFont(false);
|
|
|
|
data->setNewFont(false);
|
|
|
|
}
|
2018-06-12 16:37:48 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
return retval;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::openConsole()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
int fd = data->getTTYFileDescriptor();
|
2018-12-15 00:50:09 +01:00
|
|
|
const char* termfilename = data->getTermFileName();
|
2018-10-01 22:27:54 +02:00
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
static const char* terminal_devices[] =
|
|
|
|
{
|
|
|
|
"/proc/self/fd/0",
|
|
|
|
"/dev/tty",
|
|
|
|
"/dev/tty0",
|
|
|
|
"/dev/vc/0",
|
|
|
|
"/dev/systty",
|
|
|
|
"/dev/console",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( fd >= 0 ) // console is already opened
|
2018-06-12 16:37:48 +02:00
|
|
|
return 0;
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( ! *termfilename || ! fsys )
|
2018-06-12 16:37:48 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
for (std::size_t i = 0; terminal_devices[i] != 0; i++)
|
2018-10-01 22:27:54 +02:00
|
|
|
{
|
2019-05-17 15:48:09 +02:00
|
|
|
fd = fsys->open(terminal_devices[i], O_RDWR, 0);
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTTYFileDescriptor(fd);
|
|
|
|
|
|
|
|
if ( fd >= 0 )
|
2018-06-12 16:37:48 +02:00
|
|
|
return 0;
|
2018-10-01 22:27:54 +02:00
|
|
|
}
|
2018-06-12 16:37:48 +02:00
|
|
|
|
|
|
|
return -1; // No file descriptor referring to the console
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FTerm::closeConsole()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
int fd = data->getTTYFileDescriptor();
|
2019-05-17 15:48:09 +02:00
|
|
|
int ret = -1;
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
if ( fd < 0 ) // console is already closed
|
2018-06-12 16:37:48 +02:00
|
|
|
return 0;
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( fsys )
|
|
|
|
ret = fsys->close(fd); // close console
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTTYFileDescriptor(-1);
|
2018-06-12 16:37:48 +02:00
|
|
|
|
|
|
|
if ( ret == 0 )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2018-05-27 19:43:18 +02:00
|
|
|
// Returns the cursor move string
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->hasCursorOptimisation() )
|
2016-11-02 00:37:58 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
//----------------------------------------------------------------------
|
2018-12-22 23:50:10 +01:00
|
|
|
char* FTerm::cursorsVisibility (bool enable)
|
2018-05-20 15:15:42 +02:00
|
|
|
{
|
|
|
|
// Hides or shows the input cursor on the terminal
|
|
|
|
|
2018-12-10 01:48:26 +01:00
|
|
|
char* visibility_str = nullptr;
|
2018-05-20 15:15:42 +02:00
|
|
|
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( data->isCursorHidden() == enable )
|
2018-05-20 15:15:42 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( enable )
|
2018-05-20 15:15:42 +02:00
|
|
|
{
|
|
|
|
visibility_str = disableCursor();
|
|
|
|
|
|
|
|
if ( visibility_str )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setCursorHidden (true); // Global state
|
2018-05-20 15:15:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
visibility_str = enableCursor();
|
|
|
|
|
|
|
|
if ( visibility_str )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setCursorHidden (false); // Global state
|
2018-05-20 15:15:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return visibility_str;
|
|
|
|
}
|
|
|
|
|
2016-11-26 15:18:44 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::printMoveDurations()
|
|
|
|
{
|
2018-11-01 00:49:13 +01:00
|
|
|
finalcut::printDurations(*opti_move);
|
2016-11-26 15:18:44 +01:00
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2018-05-27 19:43:18 +02:00
|
|
|
// Returns the cursor enable string
|
|
|
|
|
2018-12-26 23:41:49 +01:00
|
|
|
static constexpr std::size_t SIZE = 32;
|
2018-05-20 15:15:42 +02:00
|
|
|
static char enable_str[SIZE] = { };
|
2018-12-15 00:50:09 +01:00
|
|
|
const auto& vs = TCAP(fc::t_cursor_visible);
|
|
|
|
const auto& ve = TCAP(fc::t_cursor_normal);
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ve )
|
2018-09-24 04:02:35 +02:00
|
|
|
std::strncpy (enable_str, ve, SIZE - 1);
|
2016-11-02 00:37:58 +01:00
|
|
|
else if ( vs )
|
2018-09-24 04:02:35 +02:00
|
|
|
std::strncpy (enable_str, vs, SIZE - 1);
|
2016-10-11 04:57:36 +02:00
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
if ( isLinuxTerm() )
|
|
|
|
{
|
2018-05-27 19:43:18 +02:00
|
|
|
// Restore the last used Linux console cursor style
|
2018-12-15 00:50:09 +01:00
|
|
|
const char* cstyle = linux->restoreCursorStyle();
|
2018-10-22 01:26:24 +02:00
|
|
|
std::strncat (enable_str, cstyle, SIZE - std::strlen(enable_str) - 1);
|
2018-05-20 15:15:42 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2018-05-20 15:15:42 +02:00
|
|
|
|
2018-09-16 19:33:40 +02:00
|
|
|
enable_str[SIZE - 1] = '\0';
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( isFreeBSDTerm() )
|
|
|
|
{
|
|
|
|
// Restore the last used FreeBSD console cursor style
|
|
|
|
freebsd->restoreCursorStyle();
|
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-05-20 15:15:42 +02:00
|
|
|
|
|
|
|
return enable_str;
|
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
|
|
|
{
|
2018-05-27 19:43:18 +02:00
|
|
|
// Returns the cursor disable string
|
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
const auto& 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
|
|
|
{
|
2018-05-27 19:43:18 +02:00
|
|
|
// Detect the terminal width and height
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
struct winsize win_size;
|
|
|
|
bool close_after_detect = false;
|
2018-10-01 22:27:54 +02:00
|
|
|
int fd = data->getTTYFileDescriptor();
|
2016-11-02 00:37:58 +01:00
|
|
|
int ret;
|
2016-07-23 19:50:28 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( fd < 0 ) // console is 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
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
fd = data->getTTYFileDescriptor();
|
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
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
auto& term_geometry = data->getTermGeometry();
|
2019-05-17 15:48:09 +02:00
|
|
|
|
|
|
|
if ( fsys )
|
|
|
|
ret = fsys->ioControl (fd, TIOCGWINSZ, &win_size);
|
|
|
|
else
|
|
|
|
ret = -1;
|
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
|
|
|
{
|
2018-10-24 00:16:45 +02:00
|
|
|
term_geometry.setPos (1, 1);
|
2017-07-03 16:56:32 +02:00
|
|
|
// Use COLUMNS or fallback to the xterm default width of 80 characters
|
2018-11-24 23:43:09 +01:00
|
|
|
uInt Columns = env2uint ("COLUMNS");
|
|
|
|
term_geometry.setWidth( ( Columns == 0) ? 80 : Columns);
|
2017-07-03 16:56:32 +02:00
|
|
|
// Use LINES or fallback to the xterm default height of 24 characters
|
2018-11-24 23:43:09 +01:00
|
|
|
uInt Lines = env2uint ("LINES");
|
|
|
|
term_geometry.setHeight( ( Lines == 0 ) ? 24 : Lines);
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
term_geometry.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
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( opti_move )
|
|
|
|
opti_move->setTermSize ( term_geometry.getWidth()
|
|
|
|
, term_geometry.getHeight() );
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
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
|
|
|
//----------------------------------------------------------------------
|
2019-01-21 03:42:18 +01:00
|
|
|
void FTerm::setTermSize (const FSize& size)
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2019-01-21 03:42:18 +01:00
|
|
|
// Set xterm size
|
2017-04-06 01:31:21 +02:00
|
|
|
|
2019-01-21 03:42:18 +01:00
|
|
|
xterm->setTermSize (size);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-20 15:15:42 +02:00
|
|
|
void FTerm::setTermTitle (const FString& title)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
// Set the xterm window title
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->setTitle (title);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-20 15:15:42 +02:00
|
|
|
void FTerm::setKDECursor (fc::kdeKonsoleCursorShape style)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-05-20 15:15:42 +02:00
|
|
|
// Set cursor style in KDE konsole
|
2016-07-09 00:01:59 +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();
|
2018-05-20 15:15:42 +02:00
|
|
|
putstringf (OSC "50;CursorShape=%d" BEL, style);
|
2016-11-02 00:37:58 +01:00
|
|
|
oscPostfix();
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
2016-01-08 01:00:05 +01:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::saveColorMap()
|
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
linux->saveColorMap();
|
|
|
|
#endif
|
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()
|
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
const auto& oc = TCAP(fc::t_orig_colors);
|
|
|
|
const auto& 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);
|
2018-06-12 16:37:48 +02:00
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
else
|
2018-09-14 22:42:56 +02:00
|
|
|
linux->resetColorMap();
|
2018-06-12 16:37:48 +02:00
|
|
|
#endif
|
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
|
|
|
//----------------------------------------------------------------------
|
2018-11-07 22:06:58 +01:00
|
|
|
void FTerm::setPalette (FColor index, int r, int g, int b)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-01-24 00:25:32 +01:00
|
|
|
// Redefine RGB color value for a palette entry
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
const auto& Ic = TCAP(fc::t_initialize_color);
|
|
|
|
const auto& 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-06-12 16:37:48 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
linux->setPalette(index, r, g, b);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-06-12 16:37:48 +02:00
|
|
|
#endif
|
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
|
|
|
//----------------------------------------------------------------------
|
2018-06-17 23:25:32 +02:00
|
|
|
#if defined(__linux__)
|
2016-11-02 00:37:58 +01:00
|
|
|
void FTerm::setBeep (int Hz, int ms)
|
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
linux->setBeep (Hz, ms);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-06-17 23:25:32 +02:00
|
|
|
#else
|
|
|
|
void FTerm::setBeep (int, int)
|
|
|
|
{ }
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::resetBeep()
|
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
linux->resetBeep();
|
|
|
|
#endif
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTermEncoding (enc);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
assert ( enc == fc::UTF8
|
|
|
|
|| enc == fc::VT100 // VT100 line drawing
|
|
|
|
|| enc == fc::PC // CP-437
|
|
|
|
|| enc == fc::ASCII );
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-01-02 20:38:45 +01:00
|
|
|
// Set the new Fputchar function pointer
|
2018-10-01 22:27:54 +02:00
|
|
|
switch ( enc )
|
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-10-01 22:27:54 +02:00
|
|
|
if ( isXTerminal() && data->hasUTF8Console() )
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( enc == fc::VT100 || enc == fc::PC )
|
2016-12-27 23:03:32 +01:00
|
|
|
{
|
2018-12-10 01:48:26 +01:00
|
|
|
char* empty = nullptr;
|
2016-12-27 23:03:32 +01:00
|
|
|
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()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
return data->getTermEncoding();
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
std::string FTerm::getEncodingString()
|
2015-10-07 02:36:38 +02:00
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
auto term_encoding = data->getTermEncoding();
|
|
|
|
auto& encoding_list = data->getEncodingList();
|
|
|
|
auto end = encoding_list.end();
|
2015-10-07 21:32:30 +02:00
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
for (auto it = encoding_list.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 "";
|
|
|
|
}
|
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
//----------------------------------------------------------------------
|
2019-01-02 03:00:07 +01:00
|
|
|
bool FTerm::charEncodable (wchar_t c)
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
wchar_t ch = charEncode(c);
|
2018-06-12 16:37:48 +02:00
|
|
|
return bool(ch > 0 && ch != c);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2019-01-02 03:00:07 +01:00
|
|
|
wchar_t FTerm::charEncode (wchar_t c)
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
return charEncode (c, data->getTermEncoding());
|
2018-06-12 16:37:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2019-01-02 03:00:07 +01:00
|
|
|
wchar_t FTerm::charEncode (wchar_t c, fc::encoding enc)
|
|
|
|
{
|
|
|
|
wchar_t ch_enc = c;
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i <= fc::lastCharItem; i++)
|
|
|
|
{
|
|
|
|
if ( fc::character[i][fc::UTF8] == uInt(c) )
|
|
|
|
{
|
|
|
|
ch_enc = wchar_t(fc::character[i][enc]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( enc == fc::PC && ch_enc == c )
|
|
|
|
ch_enc = FTerm::unicode_to_cp437(c);
|
|
|
|
|
|
|
|
return ch_enc;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
wchar_t FTerm::cp437_to_unicode (uChar c)
|
|
|
|
{
|
|
|
|
constexpr std::size_t CP437 = 0;
|
|
|
|
constexpr std::size_t UNICODE = 1;
|
|
|
|
wchar_t ucs = wchar_t(c);
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i <= fc::lastCP437Item; i++)
|
|
|
|
{
|
|
|
|
if ( fc::cp437_to_ucs[i][CP437] == c ) // found
|
|
|
|
{
|
|
|
|
ucs = fc::cp437_to_ucs[UNICODE][1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ucs;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uChar FTerm::unicode_to_cp437 (wchar_t ucs)
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
constexpr std::size_t CP437 = 0;
|
|
|
|
constexpr std::size_t UNICODE = 1;
|
|
|
|
uChar c = '?';
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i <= fc::lastCP437Item; i++)
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
if ( fc::cp437_to_ucs[i][UNICODE] == ucs ) // found
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
2019-01-03 07:36:18 +01:00
|
|
|
c = uChar(fc::cp437_to_ucs[i][CP437]);
|
2018-06-12 16:37:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
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)
|
|
|
|
//----------------------------------------------------------------------
|
2018-09-12 22:51:15 +02:00
|
|
|
int FTerm::putchar_ASCII (char c)
|
2017-12-17 01:06:53 +01:00
|
|
|
{
|
|
|
|
if ( std::putchar(c) == EOF )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__sun) && defined(__SVR4)
|
2015-10-07 02:36:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-09-12 22:51:15 +02:00
|
|
|
int FTerm::putchar_ASCII (int c)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
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
|
|
|
//----------------------------------------------------------------------
|
2018-09-12 22:51:15 +02:00
|
|
|
int FTerm::putchar_UTF8 (int c)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
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
|
|
|
// protected methods of FTerm
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-20 15:15:42 +02:00
|
|
|
void FTerm::initScreenSettings()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-05-20 15:15:42 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
// Important: Do not use setNewFont() or setVGAFont() after
|
|
|
|
// the console character mapping has been initialized
|
2018-06-12 16:37:48 +02:00
|
|
|
linux->initCharMap (fc::character);
|
2018-10-01 22:27:54 +02:00
|
|
|
data->supportShadowCharacter (linux->hasShadowCharacter());
|
|
|
|
data->supportHalfBlockCharacter (linux->hasHalfBlockCharacter());
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-06-17 23:25:32 +02:00
|
|
|
freebsd->initCharMap (fc::character);
|
2018-05-20 15:15:42 +02:00
|
|
|
#endif
|
2017-04-02 21:32:48 +02:00
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
// set xterm underline cursor
|
|
|
|
xterm->setCursorStyle (fc::blinking_underline);
|
2017-04-02 21:32:48 +02:00
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
// set xterm color settings to defaults
|
|
|
|
xterm->setDefaults();
|
2017-04-02 21:32:48 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-06-25 00:14:53 +02:00
|
|
|
char* FTerm::changeAttribute ( charData*& term_attr
|
|
|
|
, charData*& next_attr )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
return opti_attr->changeAttribute (term_attr, next_attr);
|
|
|
|
}
|
2015-12-24 02:34:30 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-10-01 22:27:54 +02:00
|
|
|
void FTerm::exitWithMessage (const FString& message)
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
|
|
|
// Exit the programm
|
|
|
|
if ( init_term_object )
|
|
|
|
init_term_object->finish();
|
|
|
|
|
|
|
|
std::fflush (stderr);
|
|
|
|
std::fflush (stdout);
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( ! message.isEmpty() )
|
|
|
|
std::cerr << "Warning: " << message << std::endl;
|
2017-11-18 02:34:41 +01:00
|
|
|
|
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
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-10-01 22:27:54 +02:00
|
|
|
void FTerm::init_global_values (bool disable_alt_screen)
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
|
|
|
// Initialize global values
|
|
|
|
|
|
|
|
// Preset to false
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setNewFont(false);
|
|
|
|
|
|
|
|
// Sets alternative screen usage
|
|
|
|
data->useAlternateScreen(! disable_alt_screen);
|
2017-12-14 00:35:10 +01:00
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
// Initialize xterm object
|
|
|
|
xterm->setFTermDetection(term_detection);
|
|
|
|
|
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);
|
2018-11-01 21:29:54 +01:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
debug_data->setFTermDetection(term_detection);
|
|
|
|
debug_data->setFTermData(data);
|
|
|
|
#endif
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_terminal_device_path()
|
|
|
|
{
|
|
|
|
char termfilename[256] = { };
|
|
|
|
int stdout_no = FTermios::getStdOut();
|
|
|
|
|
|
|
|
if ( ttyname_r(stdout_no, termfilename, sizeof(termfilename)) )
|
|
|
|
termfilename[0] = '\0';
|
|
|
|
|
|
|
|
data->setTermFileName(termfilename);
|
|
|
|
}
|
|
|
|
|
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-20 15:15:42 +02:00
|
|
|
// Read the used VT100 pairs
|
2017-11-18 02:34:41 +01:00
|
|
|
|
2019-01-03 07:36:18 +01:00
|
|
|
std::unordered_map<uChar, uChar> vt100_alt_char;
|
2018-10-01 22:27:54 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
if ( TCAP(fc::t_acs_chars) )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
for (std::size_t n = 0; TCAP(fc::t_acs_chars)[n]; n += 2)
|
2018-05-02 12:31:21 +02:00
|
|
|
{
|
2018-05-20 15:15:42 +02:00
|
|
|
// insert the VT100 key/value pairs into a map
|
2018-05-02 12:31:21 +02:00
|
|
|
uChar p1 = uChar(TCAP(fc::t_acs_chars)[n]);
|
|
|
|
uChar p2 = uChar(TCAP(fc::t_acs_chars)[n + 1]);
|
2018-10-01 22:27:54 +02:00
|
|
|
vt100_alt_char[p1] = p2;
|
2018-05-02 12:31:21 +02:00
|
|
|
}
|
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-20 15:15:42 +02:00
|
|
|
// Update array 'character' with discovered VT100 pairs
|
2018-12-15 00:50:09 +01:00
|
|
|
for (std::size_t 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]);
|
2018-10-01 22:27:54 +02:00
|
|
|
uChar altChar = uChar(vt100_alt_char[keyChar]);
|
2018-05-02 12:31:21 +02:00
|
|
|
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-10-01 22:27:54 +02:00
|
|
|
if ( altChar ) // update alternate character set
|
|
|
|
fc::character[item][fc::VT100] = altChar;
|
|
|
|
else // delete VT100 char in character
|
|
|
|
fc::character[item][fc::VT100] = 0;
|
2018-05-02 12:31:21 +02:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->hasUTF8Console() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->hasUTF8Console() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
// 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
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
// Replace don't printable PC charset 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;
|
|
|
|
|
2019-01-03 21:38:19 +01:00
|
|
|
// PC encoding changes
|
2018-12-15 00:50:09 +01:00
|
|
|
for (std::size_t i = 0; i <= fc::lastCharItem; i++ )
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2019-01-02 03:00:07 +01:00
|
|
|
if ( fc::character[i][fc::UTF8] == fc::BlackUpPointingTriangle ) // ▲
|
|
|
|
fc::character[i][fc::PC] = 0x18;
|
|
|
|
|
|
|
|
if ( fc::character[i][fc::UTF8] == fc::BlackDownPointingTriangle ) // ▼
|
|
|
|
fc::character[i][fc::PC] = 0x19;
|
|
|
|
|
|
|
|
if ( fc::character[i][fc::UTF8] == fc::InverseBullet // ◘
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::InverseWhiteCircle // ◙
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::UpDownArrow // ↕
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::LeftRightArrow // ↔
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::DoubleExclamationMark // ‼
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::BlackRectangle // ▬
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::RightwardsArrow // →
|
|
|
|
|| fc::character[i][fc::UTF8] == fc::Section // §
|
2017-12-17 01:06:53 +01:00
|
|
|
|| 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
|
|
|
}
|
2019-01-03 21:38:19 +01:00
|
|
|
|
|
|
|
// General encoding changes
|
|
|
|
characterSub& sub_map = data->getCharSubstitutionMap();
|
|
|
|
sub_map[L'•'] = L'*';
|
|
|
|
sub_map[L'●'] = L'*';
|
|
|
|
sub_map[L'◘'] = L'*';
|
|
|
|
sub_map[L'○'] = L'*';
|
|
|
|
sub_map[L'◙'] = L'*';
|
|
|
|
sub_map[L'♪'] = L'♫';
|
|
|
|
sub_map[L'√'] = L'x';
|
|
|
|
sub_map[L'ˣ'] = L'`';
|
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;
|
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
for (std::size_t i = 0; i <= fc::lastCharItem; i++ )
|
2017-12-17 01:06:53 +01:00
|
|
|
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-07-15 19:52:59 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_keyboard()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
keyboard->setFTermLinux (linux);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-05-02 12:31:21 +02:00
|
|
|
void FTerm::init_termcap()
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-10-08 04:14:20 +02:00
|
|
|
// Initialize the terminal capabilities
|
2018-02-19 01:36:38 +01:00
|
|
|
|
2018-10-08 04:14:20 +02:00
|
|
|
FTermcap termcap;
|
2018-11-01 21:29:54 +01:00
|
|
|
termcap.setFTermData(data);
|
2018-10-08 04:14:20 +02:00
|
|
|
termcap.setFTermDetection(term_detection);
|
|
|
|
termcap.init();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-10-08 04:14:20 +02:00
|
|
|
// Share the terminal capabilities
|
|
|
|
tcap = termcap.getTermcapMap();
|
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-10-08 04:14:20 +02:00
|
|
|
void FTerm::init_quirks()
|
2018-02-19 01:36:38 +01:00
|
|
|
{
|
2018-10-08 04:14:20 +02:00
|
|
|
// Initialize terminal quirks
|
2016-10-02 21:26:25 +02:00
|
|
|
|
2018-08-09 00:04:00 +02:00
|
|
|
FTermcapQuirks quirks;
|
2018-11-01 21:29:54 +01:00
|
|
|
quirks.setFTermData (data);
|
2018-08-09 00:04:00 +02:00
|
|
|
quirks.setFTermDetection (term_detection);
|
2018-10-08 04:14:20 +02:00
|
|
|
quirks.terminalFixup(); // Fix terminal quirks
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-10-08 04:14:20 +02:00
|
|
|
void FTerm::init_optiMove()
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
|
|
|
// Duration precalculation of the cursor movement strings
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-07-01 14:48:53 +02:00
|
|
|
FOptiMove::termEnv optimove_env =
|
|
|
|
{
|
|
|
|
FTermcap::automatic_left_margin,
|
|
|
|
FTermcap::eat_nl_glitch,
|
|
|
|
FTermcap::tabstop,
|
|
|
|
TCAP(fc::t_cursor_home),
|
|
|
|
TCAP(fc::t_carriage_return),
|
|
|
|
TCAP(fc::t_cursor_to_ll),
|
|
|
|
TCAP(fc::t_tab),
|
|
|
|
TCAP(fc::t_back_tab),
|
|
|
|
TCAP(fc::t_cursor_up),
|
|
|
|
TCAP(fc::t_cursor_down),
|
|
|
|
TCAP(fc::t_cursor_left),
|
|
|
|
TCAP(fc::t_cursor_right),
|
|
|
|
TCAP(fc::t_cursor_address),
|
|
|
|
TCAP(fc::t_column_address),
|
|
|
|
TCAP(fc::t_row_address),
|
|
|
|
TCAP(fc::t_parm_up_cursor),
|
|
|
|
TCAP(fc::t_parm_down_cursor),
|
|
|
|
TCAP(fc::t_parm_left_cursor),
|
|
|
|
TCAP(fc::t_parm_right_cursor),
|
|
|
|
TCAP(fc::t_erase_chars),
|
|
|
|
TCAP(fc::t_repeat_char),
|
|
|
|
TCAP(fc::t_clr_bol),
|
|
|
|
TCAP(fc::t_clr_eol)
|
|
|
|
};
|
|
|
|
|
|
|
|
opti_move->setTermEnvironment(optimove_env);
|
2017-11-18 21:03:02 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-18 21:03:02 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-10-08 04:14:20 +02:00
|
|
|
void FTerm::init_optiAttr()
|
2017-11-18 21:03:02 +01:00
|
|
|
{
|
2017-11-22 23:56:21 +01:00
|
|
|
// Setting video attribute optimization
|
2017-11-19 19:47:24 +01:00
|
|
|
|
2018-06-25 00:14:53 +02:00
|
|
|
FOptiAttr::termEnv optiattr_env =
|
|
|
|
{
|
|
|
|
FTermcap::ansi_default_color,
|
|
|
|
FTermcap::max_color,
|
|
|
|
FTermcap::attr_without_color,
|
|
|
|
TCAP(fc::t_enter_bold_mode),
|
|
|
|
TCAP(fc::t_exit_bold_mode),
|
|
|
|
TCAP(fc::t_enter_dim_mode),
|
|
|
|
TCAP(fc::t_exit_dim_mode),
|
|
|
|
TCAP(fc::t_enter_italics_mode),
|
|
|
|
TCAP(fc::t_exit_italics_mode),
|
|
|
|
TCAP(fc::t_enter_underline_mode),
|
|
|
|
TCAP(fc::t_exit_underline_mode),
|
|
|
|
TCAP(fc::t_enter_blink_mode),
|
|
|
|
TCAP(fc::t_exit_blink_mode),
|
|
|
|
TCAP(fc::t_enter_reverse_mode),
|
|
|
|
TCAP(fc::t_exit_reverse_mode),
|
|
|
|
TCAP(fc::t_enter_standout_mode),
|
|
|
|
TCAP(fc::t_exit_standout_mode),
|
|
|
|
TCAP(fc::t_enter_secure_mode),
|
|
|
|
TCAP(fc::t_exit_secure_mode),
|
|
|
|
TCAP(fc::t_enter_protected_mode),
|
|
|
|
TCAP(fc::t_exit_protected_mode),
|
|
|
|
TCAP(fc::t_enter_crossed_out_mode),
|
|
|
|
TCAP(fc::t_exit_crossed_out_mode),
|
|
|
|
TCAP(fc::t_enter_dbl_underline_mode),
|
|
|
|
TCAP(fc::t_exit_dbl_underline_mode),
|
|
|
|
TCAP(fc::t_set_attributes),
|
|
|
|
TCAP(fc::t_exit_attribute_mode),
|
|
|
|
TCAP(fc::t_enter_alt_charset_mode),
|
2018-07-15 23:27:03 +02:00
|
|
|
TCAP(fc::t_exit_alt_charset_mode),
|
2018-06-25 00:14:53 +02:00
|
|
|
TCAP(fc::t_enter_pc_charset_mode),
|
|
|
|
TCAP(fc::t_exit_pc_charset_mode),
|
|
|
|
TCAP(fc::t_set_a_foreground),
|
|
|
|
TCAP(fc::t_set_a_background),
|
|
|
|
TCAP(fc::t_set_foreground),
|
|
|
|
TCAP(fc::t_set_background),
|
|
|
|
TCAP(fc::t_orig_pair),
|
|
|
|
TCAP(fc::t_orig_pair),
|
|
|
|
TCAP(fc::t_orig_colors)
|
|
|
|
};
|
|
|
|
|
|
|
|
opti_attr->setTermEnvironment(optiattr_env);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_font()
|
|
|
|
{
|
2018-12-15 00:50:09 +01:00
|
|
|
if ( init_values.vgafont && ! setVGAFont() )
|
|
|
|
exitWithMessage ("VGAfont is not supported by this terminal");
|
2017-11-26 19:00:04 +01:00
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
if ( init_values.newfont && ! setNewFont() )
|
|
|
|
exitWithMessage ("Newfont is not supported by this terminal");
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_locale()
|
|
|
|
{
|
|
|
|
// Init current locale
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
char* locale_name;
|
|
|
|
char* locale_xterm;
|
|
|
|
const char* termtype = data->getTermType();
|
2017-11-18 02:34:41 +01:00
|
|
|
locale_name = std::setlocale (LC_ALL, "");
|
2018-10-03 22:23:55 +02:00
|
|
|
std::setlocale (LC_NUMERIC, "");
|
2017-11-18 02:34:41 +01:00
|
|
|
|
|
|
|
// 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 )
|
2018-10-03 22:23:55 +02:00
|
|
|
std::setlocale (LC_ALL, "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-10-01 22:27:54 +02:00
|
|
|
bool force_vt100 = false; // VT100 line drawing (G1 character set)
|
2018-02-19 23:02:54 +01:00
|
|
|
init_encoding_set();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
if ( isRxvtTerminal() && ! isUrxvtTerminal() )
|
2018-05-02 12:31:21 +02:00
|
|
|
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();
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( force_vt100 )
|
|
|
|
init_force_vt100_encoding();
|
|
|
|
else
|
2018-02-19 23:02:54 +01:00
|
|
|
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
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
auto& encoding_list = data->getEncodingList();
|
2018-10-01 22:27:54 +02:00
|
|
|
encoding_list["UTF8"] = fc::UTF8;
|
|
|
|
encoding_list["UTF-8"] = fc::UTF8;
|
|
|
|
encoding_list["VT100"] = fc::VT100; // VT100 line drawing
|
|
|
|
encoding_list["PC"] = fc::PC; // CP-437
|
|
|
|
encoding_list["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();
|
2018-10-01 22:27:54 +02:00
|
|
|
const char* termtype = data->getTermType();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( fsys->isTTY(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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setUTF8Console(true);
|
|
|
|
data->setTermEncoding (fc::UTF8);
|
|
|
|
Fputchar = &FTerm::putchar_UTF8; // function pointer
|
|
|
|
data->setUTF8(true);
|
2016-11-02 00:37:58 +01:00
|
|
|
setUTF8(true);
|
2018-07-15 19:52:59 +02:00
|
|
|
keyboard->enableUTF8();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2019-05-17 15:48:09 +02:00
|
|
|
else if ( fsys->isTTY(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
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setVT100Console (true);
|
|
|
|
data->setTermEncoding (fc::VT100);
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setASCIIConsole (true);
|
|
|
|
data->setTermEncoding (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()
|
2018-10-01 22:27:54 +02:00
|
|
|
|| (isPuttyTerminal() && ! data->isUTF8())
|
|
|
|
|| (isTeraTerm() && ! data->isUTF8()) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTermEncoding (fc::PC);
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2019-01-02 03:00:07 +01:00
|
|
|
if ( hasUTF8() && init_values.encoding == fc::UNKNOWN )
|
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
|
|
|
//----------------------------------------------------------------------
|
2018-10-01 22:27:54 +02:00
|
|
|
void FTerm::init_force_vt100_encoding()
|
2018-02-19 23:02:54 +01:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setVT100Console(true);
|
|
|
|
data->setTermEncoding (fc::VT100);
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2018-02-19 23:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_utf8_without_alt_charset()
|
|
|
|
{
|
|
|
|
// Fall back to ascii for utf-8 terminals that
|
|
|
|
// do not support VT100 line drawings
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( FTermcap::no_utf8_acs_chars && data->isUTF8()
|
|
|
|
&& data->getTermEncoding() == fc::VT100 )
|
2018-01-02 20:38:45 +01:00
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setASCIIConsole(true);
|
|
|
|
data->setTermEncoding (fc::ASCII);
|
|
|
|
Fputchar = &FTerm::putchar_ASCII; // function pointer
|
2018-01-02 20:38:45 +01:00
|
|
|
}
|
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
|
|
|
|
2018-12-15 00:50:09 +01:00
|
|
|
auto enc = data->getTermEncoding();
|
2018-10-01 22:27:54 +02:00
|
|
|
|
|
|
|
if ( enc == fc::VT100 || enc == fc::PC )
|
2016-12-27 23:03:32 +01:00
|
|
|
{
|
2018-12-10 01:48:26 +01:00
|
|
|
char* empty = nullptr;
|
2016-12-27 23:03:32 +01:00
|
|
|
opti_move->set_tabular (empty);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 22:58:22 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::init_captureFontAndTitle()
|
|
|
|
{
|
|
|
|
// Save the used xterm font and window title
|
|
|
|
|
|
|
|
xterm->captureFontAndTitle();
|
2018-12-26 23:41:49 +01:00
|
|
|
const auto font = xterm->getFont();
|
|
|
|
const auto title = xterm->getTitle();
|
2018-05-27 22:58:22 +02:00
|
|
|
|
|
|
|
if ( font )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setXtermFont(*font);
|
2018-05-27 22:58:22 +02:00
|
|
|
|
|
|
|
if ( title )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setXtermTitle(*title);
|
2018-05-27 22:58:22 +02:00
|
|
|
}
|
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-10-09 00:33:26 +02:00
|
|
|
inline bool FTerm::hasNoFontSettingOption()
|
2017-11-18 02:34:41 +01:00
|
|
|
{
|
2018-10-09 00:33:26 +02:00
|
|
|
if ( isGnomeTerminal()
|
|
|
|
|| isKdeTerminal()
|
|
|
|
|| isPuttyTerminal()
|
|
|
|
|| isTeraTerm()
|
|
|
|
|| isCygwinTerminal()
|
|
|
|
|| isMinttyTerm() )
|
|
|
|
return true;
|
2018-01-24 00:25:32 +01:00
|
|
|
|
2018-10-09 00:33:26 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::redefineColorPalette()
|
|
|
|
{
|
|
|
|
// Redefine the color palette
|
|
|
|
|
|
|
|
if ( ! canChangeColorPalette() )
|
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();
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
if ( getMaxColor() >= 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-10-09 00:33:26 +02:00
|
|
|
if ( ! canChangeColorPalette() )
|
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
|
2018-05-20 15:15:42 +02:00
|
|
|
if ( getMaxColor() >= 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
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->resetColorMap();
|
2017-12-14 00:35:10 +01:00
|
|
|
resetColorMap();
|
2017-11-18 02:34:41 +01:00
|
|
|
}
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setInsertCursorStyle()
|
|
|
|
{
|
|
|
|
xterm->setCursorStyle (fc::blinking_underline);
|
|
|
|
setKDECursor(fc::UnderlineCursor);
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
2018-12-15 00:50:09 +01:00
|
|
|
const char* cstyle = linux->setCursorStyle ( fc::underscore_cursor
|
|
|
|
, data->isCursorHidden() );
|
2018-06-12 16:37:48 +02:00
|
|
|
putstring (cstyle);
|
|
|
|
std::fflush(stdout);
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-10-01 22:27:54 +02:00
|
|
|
freebsd->setCursorStyle ( fc::destructive_cursor
|
|
|
|
, data->isCursorHidden() );
|
2018-05-20 15:15:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( isUrxvtTerminal() )
|
|
|
|
xterm->setCursorColor ("rgb:ffff/ffff/ffff");
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::setOverwriteCursorStyle()
|
|
|
|
{
|
|
|
|
xterm->setCursorStyle (fc::steady_block);
|
|
|
|
setKDECursor(fc::BlockCursor);
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
2018-12-15 00:50:09 +01:00
|
|
|
char* cstyle = linux->setCursorStyle ( fc::full_block_cursor
|
|
|
|
, data->isCursorHidden() );
|
2018-06-12 16:37:48 +02:00
|
|
|
putstring (cstyle);
|
|
|
|
std::fflush(stdout);
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-10-01 22:27:54 +02:00
|
|
|
freebsd->setCursorStyle ( fc::normal_cursor
|
|
|
|
, data->isCursorHidden() );
|
2018-05-20 15:15:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( isUrxvtTerminal() )
|
|
|
|
xterm->setCursorColor ("rgb:eeee/0000/0000");
|
|
|
|
}
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::enableMouse()
|
|
|
|
{
|
2018-10-09 00:33:26 +02:00
|
|
|
// Enable the terminal mouse support
|
|
|
|
|
|
|
|
if ( ! init_values.mouse_support )
|
|
|
|
return;
|
|
|
|
|
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-06-12 16:37:48 +02:00
|
|
|
if ( linux->isLinuxConsole() )
|
2018-01-14 21:21:08 +01:00
|
|
|
gpm_mouse = true;
|
|
|
|
|
|
|
|
closeConsole();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
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;
|
|
|
|
|
2018-07-15 19:52:59 +02:00
|
|
|
keyboard->enableMouseSequences();
|
2018-12-28 22:57:43 +01:00
|
|
|
mouse->setMaxWidth (uInt16(getColumnNumber()));
|
|
|
|
mouse->setMaxHeight (uInt16(getLineNumber()));
|
2018-01-14 21:21:08 +01:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-10-09 00:33:26 +02:00
|
|
|
inline void FTerm::disableMouse()
|
2017-11-26 19:00:04 +01:00
|
|
|
{
|
2018-10-09 00:33:26 +02:00
|
|
|
// Disable the terminal mouse support
|
|
|
|
|
2018-07-15 19:52:59 +02:00
|
|
|
keyboard->disableMouseSequences();
|
2018-01-14 21:21:08 +01:00
|
|
|
mouse->disable();
|
2017-11-26 19:00:04 +01:00
|
|
|
}
|
|
|
|
|
2018-10-09 00:33:26 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::enableKeypad()
|
|
|
|
{
|
|
|
|
// Enter 'keyboard_transmit' mode
|
|
|
|
|
|
|
|
if ( TCAP(fc::t_keypad_xmit) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_keypad_xmit));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::disableKeypad()
|
|
|
|
{
|
|
|
|
// Leave 'keyboard_transmit' mode
|
|
|
|
|
|
|
|
if ( TCAP(fc::t_keypad_local) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_keypad_local));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::enableAlternateCharset()
|
|
|
|
{
|
|
|
|
// Enable alternate charset
|
|
|
|
|
|
|
|
if ( TCAP(fc::t_enable_acs) )
|
|
|
|
{
|
|
|
|
putstring (TCAP(fc::t_enable_acs));
|
|
|
|
std::fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::enableApplicationEscKey()
|
|
|
|
{
|
|
|
|
// switch to application escape key mode
|
|
|
|
|
|
|
|
if ( isMinttyTerm() )
|
|
|
|
FTerm::putstring (CSI "?7727h");
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::disableApplicationEscKey()
|
|
|
|
{
|
|
|
|
// Switch to normal escape key mode
|
|
|
|
|
|
|
|
if ( isMinttyTerm() )
|
|
|
|
putstring (CSI "?7727l");
|
|
|
|
}
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::useAlternateScreenBuffer()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( ! hasAlternateScreen() )
|
2018-02-04 19:42:30 +01:00
|
|
|
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()
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( ! hasAlternateScreen() )
|
2018-02-04 19:42:30 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
{
|
2018-10-01 22:27:54 +02:00
|
|
|
data = new FTermData();
|
2019-05-17 15:48:09 +02:00
|
|
|
fsys = new FSystemImpl;
|
2017-08-12 22:55:29 +02:00
|
|
|
opti_move = new FOptiMove();
|
|
|
|
opti_attr = new FOptiAttr();
|
2018-05-02 12:31:21 +02:00
|
|
|
term_detection = new FTermDetection();
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm = new FTermXTerminal();
|
2018-10-01 22:27:54 +02:00
|
|
|
keyboard = new FKeyboard();
|
|
|
|
mouse = new FMouseControl();
|
2018-05-27 19:43:18 +02:00
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
#if defined(__linux__)
|
|
|
|
linux = new FTermLinux();
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-05-27 19:43:18 +02:00
|
|
|
freebsd = new FTermFreeBSD();
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
2018-06-12 16:37:48 +02:00
|
|
|
openbsd = new FTermOpenBSD();
|
|
|
|
#endif
|
2018-11-01 21:29:54 +01:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
debug_data = new FTermDebugData();
|
|
|
|
#endif
|
2017-08-12 22:55:29 +02:00
|
|
|
}
|
|
|
|
catch (const std::bad_alloc& ex)
|
|
|
|
{
|
2018-11-22 21:51:32 +01:00
|
|
|
std::cerr << bad_alloc_str << ex.what() << std::endl;
|
2017-08-12 22:55:29 +02:00
|
|
|
std::abort();
|
|
|
|
}
|
2017-12-21 00:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
inline void FTerm::deallocationValues()
|
|
|
|
{
|
2018-11-01 21:29:54 +01:00
|
|
|
#if DEBUG
|
|
|
|
if ( debug_data )
|
|
|
|
delete debug_data;
|
|
|
|
#endif
|
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
if ( openbsd )
|
|
|
|
delete openbsd;
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-05-27 19:43:18 +02:00
|
|
|
if ( freebsd )
|
|
|
|
delete freebsd;
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__linux__)
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( linux )
|
|
|
|
delete linux;
|
|
|
|
#endif
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( mouse )
|
|
|
|
delete mouse;
|
|
|
|
|
|
|
|
if ( keyboard )
|
|
|
|
delete keyboard;
|
|
|
|
|
2018-05-20 15:15:42 +02:00
|
|
|
if ( xterm )
|
|
|
|
delete xterm;
|
|
|
|
|
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;
|
2018-10-01 22:27:54 +02:00
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( fsys )
|
|
|
|
delete fsys;
|
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data )
|
|
|
|
delete data;
|
2017-12-21 00:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-10-01 22:27:54 +02:00
|
|
|
void FTerm::init (bool disable_alt_screen)
|
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();
|
2018-10-01 22:27:54 +02:00
|
|
|
init_global_values(disable_alt_screen);
|
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
|
|
|
|
2017-09-11 03:06:02 +02:00
|
|
|
// Get pathname of the terminal device
|
2018-10-01 22:27:54 +02:00
|
|
|
init_terminal_device_path();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
// Initialize Linux or *BSD console
|
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-10-09 00:33:26 +02:00
|
|
|
initBaudRate();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-04-08 02:40:22 +02:00
|
|
|
// Terminal detection
|
2018-11-01 21:29:54 +01:00
|
|
|
term_detection->setFTermData(data);
|
2019-05-17 15:48:09 +02:00
|
|
|
term_detection->setFSystem(fsys);
|
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();
|
2018-10-08 04:14:20 +02:00
|
|
|
|
|
|
|
// Initialize terminal quirks
|
|
|
|
init_quirks();
|
|
|
|
|
|
|
|
// Initialize cursor movement optimization
|
|
|
|
init_optiMove();
|
|
|
|
|
|
|
|
// Initialize video attributes optimization
|
|
|
|
init_optiAttr();
|
|
|
|
|
|
|
|
// Initialize vt100 alternate character set
|
2016-11-02 00:37:58 +01:00
|
|
|
init_alt_charset();
|
|
|
|
|
2018-07-15 19:52:59 +02:00
|
|
|
// Pass the terminal capabilities to the keyboard object
|
|
|
|
keyboard->setTermcapMap (fc::Fkey);
|
|
|
|
|
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
|
|
|
|
2018-07-15 19:52:59 +02:00
|
|
|
// Initializes keyboard settings
|
|
|
|
init_keyboard();
|
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Enable the terminal mouse support
|
2018-10-09 00:33:26 +02:00
|
|
|
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() )
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->metaSendsESC(true);
|
2017-04-11 00:30:27 +02:00
|
|
|
|
2018-05-02 12:31:21 +02:00
|
|
|
// switch to application escape key mode
|
2018-10-09 00:33:26 +02:00
|
|
|
enableApplicationEscKey();
|
2018-05-02 12:31:21 +02:00
|
|
|
|
2017-12-14 00:35:10 +01:00
|
|
|
// Enter 'keyboard_transmit' mode
|
2018-10-09 00:33:26 +02:00
|
|
|
enableKeypad();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
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
|
2018-10-09 00:33:26 +02:00
|
|
|
enableAlternateCharset();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-11-26 19:00:04 +01:00
|
|
|
// Save the used xterm font and window title
|
2018-05-27 22:58:22 +02:00
|
|
|
init_captureFontAndTitle();
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2018-10-02 01:03:44 +02:00
|
|
|
// KDE terminal cursor and cygwin + teraterm charmap correction
|
|
|
|
initTermspecifics();
|
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 )
|
2018-10-01 22:27:54 +02:00
|
|
|
data->supportCursorOptimisation(false);
|
2017-11-18 02:34:41 +01:00
|
|
|
|
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__)
|
2019-01-03 07:36:18 +01:00
|
|
|
linux->setFTermData(data);
|
2019-05-17 15:48:09 +02:00
|
|
|
linux->setFSystem(fsys);
|
2018-06-12 16:37:48 +02:00
|
|
|
linux->setFTermDetection(term_detection);
|
|
|
|
linux->init(); // Initialize Linux console
|
2018-09-01 19:06:17 +02:00
|
|
|
|
|
|
|
#if DEBUG
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setFramebufferBpp (linux->getFramebufferBpp());
|
2018-02-04 19:42:30 +01:00
|
|
|
#endif
|
|
|
|
|
2018-09-20 23:59:01 +02:00
|
|
|
#endif // defined(__linux__)
|
2018-09-01 19:06:17 +02:00
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
2019-05-17 15:48:09 +02:00
|
|
|
freebsd->setFSystem(fsys);
|
|
|
|
|
2018-06-17 23:25:32 +02:00
|
|
|
if ( init_values.meta_sends_escape )
|
|
|
|
freebsd->enableMetaSendsEscape();
|
|
|
|
else
|
|
|
|
freebsd->disableMetaSendsEscape();
|
|
|
|
|
|
|
|
if ( init_values.change_cursorstyle )
|
|
|
|
freebsd->enableChangeCursorStyle();
|
|
|
|
else
|
|
|
|
freebsd->disableChangeCursorStyle();
|
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
freebsd->init(); // Initialize BSD console
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
2019-05-17 15:48:09 +02:00
|
|
|
openbsd->setFSystem(fsys);
|
|
|
|
|
2018-06-17 23:25:32 +02:00
|
|
|
if ( init_values.meta_sends_escape )
|
|
|
|
openbsd->enableMetaSendsEscape();
|
|
|
|
else
|
|
|
|
openbsd->disableMetaSendsEscape();
|
|
|
|
|
2018-06-12 16:37:48 +02:00
|
|
|
openbsd->init(); // Initialize wscons console
|
2018-02-04 19:42:30 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-10-02 01:03:44 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::initTermspecifics()
|
|
|
|
{
|
|
|
|
if ( isKdeTerminal() )
|
|
|
|
setKDECursor(fc::UnderlineCursor);
|
|
|
|
|
|
|
|
if ( isCygwinTerminal() )
|
|
|
|
init_cygwin_charmap();
|
|
|
|
|
|
|
|
if ( isTeraTerm() )
|
|
|
|
init_teraterm_charmap();
|
|
|
|
}
|
|
|
|
|
2018-10-09 00:33:26 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::initBaudRate()
|
|
|
|
{
|
|
|
|
int stdout_no = FTermios::getStdOut();
|
|
|
|
uInt baud = FTermios::getBaudRate();
|
|
|
|
data->setBaudrate(baud);
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
if ( fsys->isTTY(stdout_no) )
|
2018-10-09 00:33:26 +02:00
|
|
|
opti_move->setBaudRate(int(baud));
|
|
|
|
}
|
|
|
|
|
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
|
2018-10-01 22:27:54 +02:00
|
|
|
|
2018-12-26 23:41:49 +01:00
|
|
|
const auto& title = data->getXtermTitle();
|
2017-11-18 02:34:41 +01:00
|
|
|
resetSignalHandler();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( title && isXTerminal() && ! isRxvtTerminal() )
|
|
|
|
setTermTitle (title);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
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
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->resetDefaults();
|
2016-11-06 16:36:21 +01:00
|
|
|
|
2017-11-18 02:34:41 +01:00
|
|
|
// Set xterm full block cursor
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->setCursorStyle (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-10-09 00:33:26 +02:00
|
|
|
// Switch to normal escape key mode
|
|
|
|
disableApplicationEscKey();
|
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
|
2018-06-17 23:25:32 +02:00
|
|
|
if ( init_values.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() )
|
2018-05-20 15:15:42 +02:00
|
|
|
xterm->metaSendsESC(false);
|
2017-04-11 00:30:27 +02:00
|
|
|
|
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
|
2018-10-09 00:33:26 +02:00
|
|
|
disableKeypad();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-06-17 23:25:32 +02:00
|
|
|
finish_encoding();
|
2018-06-12 16:37:48 +02:00
|
|
|
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( data->isNewFont() || data->isVGAFont() )
|
2018-06-12 16:37:48 +02:00
|
|
|
setOldFont();
|
|
|
|
|
2018-02-04 19:42:30 +01:00
|
|
|
deallocationValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FTerm::finishOSspecifics1()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
2018-06-12 16:37:48 +02:00
|
|
|
linux->finish();
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
2018-05-27 19:43:18 +02:00
|
|
|
freebsd->finish();
|
2018-10-08 04:14:20 +02:00
|
|
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
2018-05-27 19:43:18 +02:00
|
|
|
openbsd->finish();
|
2018-02-04 19:42:30 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-06-17 23:25:32 +02:00
|
|
|
void FTerm::finish_encoding()
|
2018-02-04 19:42:30 +01:00
|
|
|
{
|
2017-03-26 20:40:04 +02:00
|
|
|
#if defined(__linux__)
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( isLinuxTerm() && data->hasUTF8Console() )
|
2016-11-02 00:37:58 +01:00
|
|
|
setUTF8(true);
|
2017-03-26 20:40:04 +02:00
|
|
|
#endif
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
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:
|
2018-10-01 22:27:54 +02:00
|
|
|
if ( ! data )
|
2016-11-02 00:37:58 +01:00
|
|
|
break;
|
2018-10-01 22:27:54 +02:00
|
|
|
else if ( data->hasTermResized() )
|
|
|
|
break;
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// initialize a resize event to the root element
|
2018-10-01 22:27:54 +02:00
|
|
|
data->setTermResized(true);
|
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
|
|
|
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
|
|
|
}
|
2018-11-24 23:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// FTerm non-member functions
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uInt env2uint (const char* env)
|
|
|
|
{
|
2019-05-17 15:48:09 +02:00
|
|
|
FString str(getenv(env));
|
2018-11-24 23:43:09 +01:00
|
|
|
|
|
|
|
if ( str.isEmpty() )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return str.toUInt();
|
|
|
|
}
|
2018-11-25 04:48:57 +01:00
|
|
|
catch (const std::exception&)
|
2018-11-24 23:43:09 +01:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
|
|
|
|
} // namespace finalcut
|