Outsourcing of data from FTerm to the classes FTermios, FTermDetection and FTermcapQuirks

This commit is contained in:
Markus Gans 2018-05-02 12:31:21 +02:00
parent b619f6bec5
commit 3a8689561a
15 changed files with 2496 additions and 1635 deletions

View File

@ -1,3 +1,7 @@
2017-05-02 Markus Gans <guru.mail@muenster.de>
* Outsourcing of data from FTerm to the classes FTermios,
FTermDetection and FTermcapQuirks
2017-04-19 Markus Gans <guru.mail@muenster.de> 2017-04-19 Markus Gans <guru.mail@muenster.de>
* Placing the terminal types in FTerm in a separate structure * Placing the terminal types in FTerm in a separate structure

View File

@ -211,20 +211,20 @@ void debug (FApplication& TermApp)
std::cout << "\n.------------------- debug -------------------\r\n"; std::cout << "\n.------------------- debug -------------------\r\n";
#if defined(__linux__) #if defined(__linux__)
std::cout << "| Framebuffer bpp: " std::cout << "| Framebuffer bpp: "
<< TermApp.framebuffer_bpp << "\r\n"; << TermApp.getFramebufferBpp() << "\r\n";
#endif #endif
std::cout << "| after init_256colorTerminal(): " std::cout << "| after init_256colorTerminal(): "
<< TermApp.termtype_256color << "\r\n"; << TermApp.getTermType_256color() << "\r\n";
std::cout << "| after parseAnswerbackMsg(): " std::cout << "| after parseAnswerbackMsg(): "
<< TermApp.termtype_Answerback << "\r\n"; << TermApp.getTermType_Answerback() << "\r\n";
std::cout << "| after parseSecDA(): " std::cout << "| after parseSecDA(): "
<< TermApp.termtype_SecDA << "\r\n"; << TermApp.getTermType_SecDA() << "\r\n";
if ( ab_s.isEmpty() ) if ( ! ab_s.isEmpty() )
tcapString ("| The answerback String", ab_s); tcapString ("| The answerback String", ab_s);
if ( sec_da.isEmpty() ) if ( ! sec_da.isEmpty() )
tcapString ("| The SecDA String", sec_da); tcapString ("| The SecDA String", sec_da);
std::cout << "`------------------- debug -------------------\r\n"; std::cout << "`------------------- debug -------------------\r\n";

View File

@ -78,8 +78,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <langinfo.h> #include <langinfo.h>
#include <termios.h>
#if defined(__sun) && defined(__SVR4) #if defined(__sun) && defined(__SVR4)
#include <termio.h> #include <termio.h>
@ -105,9 +103,6 @@
#include <ttyent.h> #include <ttyent.h>
#endif #endif
#include <unistd.h>
#include <clocale> #include <clocale>
#include <cmath> #include <cmath>
#include <csignal> #include <csignal>
@ -125,6 +120,9 @@
#include "final/frect.h" #include "final/frect.h"
#include "final/fstring.h" #include "final/fstring.h"
#include "final/ftermcap.h" #include "final/ftermcap.h"
#include "final/ftermcapquirks.h"
#include "final/ftermdetection.h"
#include "final/ftermios.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -185,6 +183,10 @@ class FTerm
#if DEBUG #if DEBUG
static const FString& getAnswerbackString(); static const FString& getAnswerbackString();
static const FString& getSecDAString(); static const FString& getSecDAString();
static const char* getTermType_256color();
static const char* getTermType_Answerback();
static const char* getTermType_SecDA();
static int getFramebufferBpp();
#endif #endif
// Inquiries // Inquiries
@ -210,6 +212,7 @@ class FTerm
static bool isCygwinTerminal(); static bool isCygwinTerminal();
static bool isMinttyTerm(); static bool isMinttyTerm();
static bool isLinuxTerm(); static bool isLinuxTerm();
static bool isFreeBSDTerm();
static bool isNetBSDTerm(); static bool isNetBSDTerm();
static bool isOpenBSDTerm(); static bool isOpenBSDTerm();
static bool isScreenTerm(); static bool isScreenTerm();
@ -219,6 +222,7 @@ class FTerm
static bool isUTF8(); static bool isUTF8();
// Mutators // Mutators
static void setTermType (char[]);
static bool setCursorOptimisation (bool); static bool setCursorOptimisation (bool);
static void setXTermDefaultColors (bool); static void setXTermDefaultColors (bool);
@ -234,12 +238,6 @@ class FTerm
static void setKeypressTimeout (const long); static void setKeypressTimeout (const long);
static void setDblclickInterval (const long); static void setDblclickInterval (const long);
static void setTTY (const termios&);
static void noHardwareEcho();
static bool setRawMode (bool);
static bool setRawMode();
static bool unsetRawMode();
static bool setCookedMode();
static void disableAltScreen(); static void disableAltScreen();
static bool setUTF8 (bool); static bool setUTF8 (bool);
static bool setUTF8(); static bool setUTF8();
@ -263,7 +261,6 @@ class FTerm
static void setKDECursor (fc::kdeKonsoleCursorShape); static void setKDECursor (fc::kdeKonsoleCursorShape);
static const FString* getXTermFont(); static const FString* getXTermFont();
static const FString* getXTermTitle(); static const FString* getXTermTitle();
static const FString getXTermColorName (int);
static void setXTermCursorStyle (fc::xtermCursorStyle); static void setXTermCursorStyle (fc::xtermCursorStyle);
static void setXTermTitle (const FString&); static void setXTermTitle (const FString&);
static void setXTermForeground (const FString&); static void setXTermForeground (const FString&);
@ -295,9 +292,6 @@ class FTerm
static bool scrollTermForward(); static bool scrollTermForward();
static bool scrollTermReverse(); static bool scrollTermReverse();
static const FString getAnswerbackMsg();
static const FString getSecDA();
// function pointer -> static function // function pointer -> static function
static int (*Fputchar)(int); static int (*Fputchar)(int);
@ -319,9 +313,6 @@ class FTerm
static int UTF8decode (const char[]); static int UTF8decode (const char[]);
#if DEBUG #if DEBUG
static char termtype_256color[256];
static char termtype_Answerback[256];
static char termtype_SecDA[256];
static int framebuffer_bpp; static int framebuffer_bpp;
#endif #endif
@ -349,8 +340,6 @@ class FTerm
#endif #endif
; ;
// Data Members // Data Members
static int stdin_no;
static int stdout_no;
static int erase_ch_length; static int erase_ch_length;
static int repeat_char_length; static int repeat_char_length;
static int clr_bol_length; static int clr_bol_length;
@ -434,13 +423,6 @@ class FTerm
static int openConsole(); static int openConsole();
static int closeConsole(); static int closeConsole();
static void getSystemTermType();
static void getTTYtype();
#if F_HAVE_GETTTYNAM
static bool getTTYSFileEntry();
#endif
static void storeTTYsettings();
static void restoreTTYsettings();
#if defined(__linux__) #if defined(__linux__)
static int getScreenFont(); static int getScreenFont();
@ -467,52 +449,21 @@ class FTerm
static void initWSConsConsole(); static void initWSConsConsole();
#endif #endif
static uInt getBaudRate (const struct termios*);
static void init_global_values(); static void init_global_values();
static void detectTerminal();
static void termtypeAnalysis();
static bool get256colorEnvString();
static char* termtype_256color_quirks();
static char* init_256colorTerminal();
static char* determineMaxColor (char[]);
static char* parseAnswerbackMsg (char[]);
static char* parseSecDA (char[]);
static char* secDA_Analysis (char[]);
static char* secDA_Analysis_0 (char[]);
static char* secDA_Analysis_1 (char[]);
static char* secDA_Analysis_24 (char[]);
static char* secDA_Analysis_32 (char[]);
static char* secDA_Analysis_77 (char[]);
static char* secDA_Analysis_82 (char[]);
static char* secDA_Analysis_83 (char[]);
static char* secDA_Analysis_85 (char[]);
static void oscPrefix(); static void oscPrefix();
static void oscPostfix(); static void oscPostfix();
static void init_alt_charset(); static void init_alt_charset();
static void init_pc_charset(); static void init_pc_charset();
static void init_cygwin_charmap(); static void init_cygwin_charmap();
static void init_teraterm_charmap(); static void init_teraterm_charmap();
static void init_termcaps(); static void init_fixed_max_color();
static void init_termcaps_error (int); static void init_termcap();
static void init_termcaps_variables(char*&); static void init_termcap_error (int);
static void init_termcaps_booleans(); static void init_termcap_variables(char*&);
static void init_termcaps_numerics(); static void init_termcap_booleans();
static void init_termcaps_strings (char*&); static void init_termcap_numerics();
static void init_termcaps_quirks(); static void init_termcap_strings (char*&);
#if defined(__FreeBSD__) || defined(__DragonFly__) static void init_termcap_keys (char*&);
static void init_termcaps_freebsd_quirks();
#endif
static void init_termcaps_cygwin_quirks();
static void init_termcaps_linux_quirks();
static void init_termcaps_xterm_quirks();
static void init_termcaps_rxvt_quirks();
static void init_termcaps_vte_quirks();
static void init_termcaps_putty_quirks();
static void init_termcaps_teraterm_quirks();
static void init_termcaps_sun_quirks();
static void init_termcaps_screen_quirks();
static void init_termcaps_general_quirks();
static void init_termcaps_keys (char*&);
static void init_OptiMove(); static void init_OptiMove();
static void init_OptiAttr(); static void init_OptiAttr();
static void init_font(); static void init_font();
@ -552,9 +503,6 @@ class FTerm
static std::map <std::string,fc::encoding>* encoding_set; static std::map <std::string,fc::encoding>* encoding_set;
static FTermcap::tcap_map* tcap; static FTermcap::tcap_map* tcap;
static bool decscusr_support;
static bool terminal_detection;
static bool raw_mode;
static bool input_data_pending; static bool input_data_pending;
static bool non_blocking_stdin; static bool non_blocking_stdin;
static bool pc_charset_console; static bool pc_charset_console;
@ -571,16 +519,14 @@ class FTerm
static char termfilename[256]; static char termfilename[256];
static char* locale_name; static char* locale_name;
static char* locale_xterm; static char* locale_xterm;
static FRect* term; // current terminal geometry static FRect* term; // current terminal geometry
static int gnome_terminal_id;
static int stdin_status_flags; static int stdin_status_flags;
static int fd_tty; static int fd_tty;
static uInt baudrate; static uInt baudrate;
static long key_timeout; static long key_timeout;
static bool resize_term; static bool resize_term;
static struct termios term_init;
static fc::linuxConsoleCursorStyle linux_console_cursor_style; static fc::linuxConsoleCursorStyle linux_console_cursor_style;
static fc::freebsdConsoleCursorStyle freebsd_console_cursor_style; static fc::freebsdConsoleCursorStyle freebsd_console_cursor_style;
static struct console_font_op screen_font; static struct console_font_op screen_font;
@ -594,39 +540,12 @@ class FTerm
static kbd_t wscons_keyboard_encoding; static kbd_t wscons_keyboard_encoding;
#endif #endif
static FOptiMove* opti_move; static FOptiMove* opti_move;
static FOptiAttr* opti_attr; static FOptiAttr* opti_attr;
static FMouseControl* mouse; static FTermDetection* term_detection;
static const FString* xterm_font; static FMouseControl* mouse;
static const FString* xterm_title; static const FString* xterm_font;
static const FString* answer_back; static const FString* xterm_title;
static const FString* sec_da;
static struct terminalType
{
// byte #0
uInt8 xterm : 1;
uInt8 ansi : 1;
uInt8 rxvt : 1;
uInt8 urxvt : 1;
uInt8 mlterm : 1;
uInt8 putty : 1;
uInt8 kde_konsole : 1;
uInt8 gnome_terminal : 1;
// byte #1
uInt8 kterm : 1;
uInt8 tera_term : 1;
uInt8 sun : 1;
uInt8 cygwin : 1;
uInt8 mintty : 1;
uInt8 linux_con : 1;
uInt8 netbsd_con : 1;
uInt8 openbsd_con : 1;
// byte #2
uInt8 screen : 1;
uInt8 tmux : 1;
uInt8 : 6; // padding bits
} terminal_type;
static struct colorEnv static struct colorEnv
{ {
@ -666,6 +585,8 @@ class FTerm
{ {
dacreg d[16]; dacreg d[16];
} color_map; } color_map;
friend class FTermDetection;
}; };
#pragma pack(pop) #pragma pack(pop)
@ -694,21 +615,33 @@ inline int FTerm::getMaxColor()
#if DEBUG #if DEBUG
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline const FString& FTerm::getAnswerbackString() inline const FString& FTerm::getAnswerbackString()
{ return ( answer_back ) ? *answer_back : fc::emptyFString::get(); } { return term_detection->getAnswerbackString(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline const FString& FTerm::getSecDAString() inline const FString& FTerm::getSecDAString()
{ return ( sec_da ) ? *sec_da : fc::emptyFString::get(); } { return term_detection->getSecDAString(); }
//----------------------------------------------------------------------
inline const char* FTerm::getTermType_256color()
{ return term_detection->getTermType_256color(); }
//----------------------------------------------------------------------
inline const char* FTerm::getTermType_Answerback()
{ return term_detection->getTermType_Answerback(); }
//----------------------------------------------------------------------
inline const char* FTerm::getTermType_SecDA()
{ return term_detection->getTermType_SecDA(); }
//----------------------------------------------------------------------
inline int FTerm::getFramebufferBpp()
{ return framebuffer_bpp; }
#endif #endif
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isKeypressTimeout (timeval* time) inline bool FTerm::isKeypressTimeout (timeval* time)
{ return FObject::isTimeout (time, key_timeout); } { return FObject::isTimeout (time, key_timeout); }
//----------------------------------------------------------------------
inline bool FTerm::isRaw()
{ return raw_mode; }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::hasPCcharset() inline bool FTerm::hasPCcharset()
{ return pc_charset_console; } { return pc_charset_console; }
@ -731,75 +664,79 @@ inline bool FTerm::isMonochron()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isXTerminal() inline bool FTerm::isXTerminal()
{ return terminal_type.xterm; } { return term_detection->isXTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isAnsiTerminal() inline bool FTerm::isAnsiTerminal()
{ return terminal_type.ansi; } { return term_detection->isAnsiTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isRxvtTerminal() inline bool FTerm::isRxvtTerminal()
{ return terminal_type.rxvt; } { return term_detection->isRxvtTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isUrxvtTerminal() inline bool FTerm::isUrxvtTerminal()
{ return terminal_type.urxvt; } { return term_detection->isUrxvtTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isMltermTerminal() inline bool FTerm::isMltermTerminal()
{ return terminal_type.mlterm; } { return term_detection->isMltermTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isPuttyTerminal() inline bool FTerm::isPuttyTerminal()
{ return terminal_type.putty; } { return term_detection->isPuttyTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isKdeTerminal() inline bool FTerm::isKdeTerminal()
{ return terminal_type.kde_konsole; } { return term_detection->isKdeTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isGnomeTerminal() inline bool FTerm::isGnomeTerminal()
{ return terminal_type.gnome_terminal; } { return term_detection->isGnomeTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isKtermTerminal() inline bool FTerm::isKtermTerminal()
{ return terminal_type.kterm; } { return term_detection->isKtermTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isTeraTerm() inline bool FTerm::isTeraTerm()
{ return terminal_type.tera_term; } { return term_detection->isTeraTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isSunTerminal() inline bool FTerm::isSunTerminal()
{ return terminal_type.sun; } { return term_detection->isSunTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isCygwinTerminal() inline bool FTerm::isCygwinTerminal()
{ return terminal_type.cygwin; } { return term_detection->isCygwinTerminal(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isMinttyTerm() inline bool FTerm::isMinttyTerm()
{ return terminal_type.mintty; } { return term_detection->isMinttyTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isLinuxTerm() inline bool FTerm::isLinuxTerm()
{ return terminal_type.linux_con; } { return term_detection->isLinuxTerm(); }
//----------------------------------------------------------------------
inline bool FTerm::isFreeBSDTerm()
{ return term_detection->isFreeBSDTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isNetBSDTerm() inline bool FTerm::isNetBSDTerm()
{ return terminal_type.netbsd_con; } { return term_detection->isNetBSDTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isOpenBSDTerm() inline bool FTerm::isOpenBSDTerm()
{ return terminal_type.openbsd_con; } { return term_detection->isOpenBSDTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isScreenTerm() inline bool FTerm::isScreenTerm()
{ return terminal_type.screen; } { return term_detection->isScreenTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isTmuxTerm() inline bool FTerm::isTmuxTerm()
{ return terminal_type.tmux; } { return term_detection->isTmuxTerm(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTerm::isInputDataPending() inline bool FTerm::isInputDataPending()
@ -825,18 +762,6 @@ inline void FTerm::setXTermDefaultColors (bool on)
inline void FTerm::setKeypressTimeout (const long timeout) inline void FTerm::setKeypressTimeout (const long timeout)
{ key_timeout = timeout; } { key_timeout = timeout; }
//----------------------------------------------------------------------
inline bool FTerm::setRawMode()
{ return setRawMode(true); }
//----------------------------------------------------------------------
inline bool FTerm::unsetRawMode()
{ return setRawMode(false); }
//----------------------------------------------------------------------
inline bool FTerm::setCookedMode()
{ return setRawMode(false); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FTerm::disableAltScreen() inline void FTerm::disableAltScreen()
{ use_alternate_screen = false; } { use_alternate_screen = false; }

View File

@ -0,0 +1,91 @@
/***********************************************************************
* ftermcapquirks.h - Termcap quirks for some well-known terminals *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
/* Standalone class
*
*
*
* FTermcapQuirks
*
*/
#ifndef FTERMCAPQUIRKS_H
#define FTERMCAPQUIRKS_H
#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
#error "Only <final/final.h> can be included directly."
#endif
#include "final/fc.h"
#include "final/fterm.h"
#include "final/ftermcap.h"
#include "final/ftermdetection.h"
//----------------------------------------------------------------------
// class FTermcapsQuirks
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class FTermcapQuirks
{
public:
// Constructors
FTermcapQuirks();
// Destructor
~FTermcapQuirks();
// Mutator
static void setTerminalType (char[]);
static void setTermcapMap (FTermcap::tcap_map*);
static void setFTermDetection (FTermDetection*);
// Methods
static void terminalFixup();
private:
// Methods
#if defined(__FreeBSD__) || defined(__DragonFly__)
static void init_termcap_freebsd_quirks();
#endif
static void init_termcap_cygwin_quirks();
static void init_termcap_linux_quirks();
static void init_termcap_xterm_quirks();
static void init_termcap_rxvt_quirks();
static void init_termcap_vte_quirks();
static void init_termcap_putty_quirks();
static void init_termcap_teraterm_quirks();
static void init_termcap_sun_quirks();
static void init_termcap_screen_quirks();
static void init_termcap_general_quirks();
// Data Members
static char termtype[256];
static FTermcap::tcap_map* tcap;
static FTermDetection* term_detection;
};
#pragma pack(pop)
#endif // FTERMCAPQUIRKS_H

View File

@ -0,0 +1,441 @@
/***********************************************************************
* ftermdetection.h - Detection of the terminal type *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
/* Standalone class
*
*
*
* FTermDetection
*
*/
#ifndef FTERMDETECTION_H
#define FTERMDETECTION_H
#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
#error "Only <final/final.h> can be included directly."
#endif
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "final/fc.h"
#include "final/ftermios.h"
#include "final/ftypes.h"
//----------------------------------------------------------------------
// class FTermDetection
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class FTermDetection
{
public:
// Typedefs
typedef struct
{
// byte #0
uInt8 xterm : 1;
uInt8 ansi : 1;
uInt8 rxvt : 1;
uInt8 urxvt : 1;
uInt8 mlterm : 1;
uInt8 putty : 1;
uInt8 kde_konsole : 1;
uInt8 gnome_terminal : 1;
// byte #1
uInt8 kterm : 1;
uInt8 tera_term : 1;
uInt8 cygwin : 1;
uInt8 mintty : 1;
uInt8 linux_con : 1;
uInt8 freebsd_con : 1;
uInt8 netbsd_con : 1;
uInt8 openbsd_con : 1;
// byte #2
uInt8 sun_con : 1;
uInt8 screen : 1;
uInt8 tmux : 1;
uInt8 : 5; // padding bits
} terminalType;
// Constructors
FTermDetection();
// Destructor
~FTermDetection();
// Accessor
static char* getTermType();
static char* getTermFileName();
static int getGnomeTerminalID();
terminalType& getTermTypeStruct();
#if DEBUG
static const FString& getAnswerbackString();
static const FString& getSecDAString();
static const char* getTermType_256color();
static const char* getTermType_Answerback();
static const char* getTermType_SecDA();
#endif
// Inquiries
static bool isXTerminal();
static bool isAnsiTerminal();
static bool isRxvtTerminal();
static bool isUrxvtTerminal();
static bool isMltermTerminal();
static bool isPuttyTerminal();
static bool isKdeTerminal();
static bool isGnomeTerminal();
static bool isKtermTerminal();
static bool isTeraTerm();
static bool isSunTerminal();
static bool isCygwinTerminal();
static bool isMinttyTerm();
static bool isLinuxTerm();
static bool isFreeBSDTerm();
static bool isNetBSDTerm();
static bool isOpenBSDTerm();
static bool isScreenTerm();
static bool isTmuxTerm();
static bool hasTerminalDetection();
static bool hasSetCursorStyleSupport();
// Mutators
static void setXTerminal (bool);
static void setAnsiTerminal (bool);
static void setRxvtTerminal (bool);
static void setUrxvtTerminal (bool);
static void setMltermTerminal (bool);
static void setPuttyTerminal (bool);
static void setKdeTerminal (bool);
static void setGnomeTerminal (bool);
static void setKtermTerminal (bool);
static void setTeraTerm (bool);
static void setSunTerminal (bool);
static void setCygwinTerminal (bool);
static void setMinttyTerm (bool);
static void setLinuxTerm (bool);
static void setFreeBSDTerm (bool);
static void setNetBSDTerm (bool);
static void setOpenBSDTerm (bool);
static void setScreenTerm (bool);
static void setTmuxTerm (bool);
static void setTerminalDetection (bool);
static void setTermFileName (char[]);
// Methods
static void detect();
// Data Members
#if DEBUG
static char termtype_256color[256];
static char termtype_Answerback[256];
static char termtype_SecDA[256];
#endif
private:
// Methods
static void getSystemTermType();
static void getTTYtype();
#if F_HAVE_GETTTYNAM
static bool getTTYSFileEntry();
#endif
static void termtypeAnalysis();
static void detectTerminal();
static char* init_256colorTerminal();
static bool get256colorEnvString();
static char* termtype_256color_quirks();
static char* determineMaxColor (char[]);
static const FString getXTermColorName (int);
static char* parseAnswerbackMsg (char[]);
static const FString getAnswerbackMsg();
static char* parseSecDA (char[]);
static const FString getSecDA();
static char* secDA_Analysis (char[]);
static char* secDA_Analysis_0 (char[]);
static char* secDA_Analysis_1 (char[]);
static char* secDA_Analysis_24 (char[]);
static char* secDA_Analysis_32 (char[]);
static char* secDA_Analysis_77 (char[]);
static char* secDA_Analysis_82 (char[]);
static char* secDA_Analysis_83 (char[]);
static char* secDA_Analysis_85 (char[]);
// Data Members
static char termtype[256];
static char termfilename[256];
static bool decscusr_support;
static bool terminal_detection;
static bool color256;
static int gnome_terminal_id;
static const FString* answer_back;
static const FString* sec_da;
static terminalType terminal_type;
static struct colorEnv
{
void setDefault()
{
string1 = 0;
string2 = 0;
string3 = 0;
string4 = 0;
string5 = 0;
string6 = 0;
}
char* string1;
char* string2;
char* string3;
char* string4;
char* string5;
char* string6;
} color_env;
static struct secondaryDA
{
void setDefault()
{
terminal_id_type = -1;
terminal_id_version = -1;
terminal_id_hardware = -1;
}
int terminal_id_type;
int terminal_id_version;
int terminal_id_hardware;
} secondary_da;
};
#pragma pack(pop)
// FTermDetection inline functions
//----------------------------------------------------------------------
inline char* FTermDetection::getTermType()
{ return termtype; }
//----------------------------------------------------------------------
inline char* FTermDetection::getTermFileName()
{ return termfilename; }
//----------------------------------------------------------------------
inline int FTermDetection::getGnomeTerminalID()
{ return gnome_terminal_id; }
//----------------------------------------------------------------------
inline FTermDetection::terminalType& FTermDetection::getTermTypeStruct()
{ return terminal_type; }
#if DEBUG
//----------------------------------------------------------------------
inline const FString& FTermDetection::getAnswerbackString()
{ return ( answer_back ) ? *answer_back : fc::emptyFString::get(); }
//----------------------------------------------------------------------
inline const FString& FTermDetection::getSecDAString()
{ return ( sec_da ) ? *sec_da : fc::emptyFString::get(); }
//----------------------------------------------------------------------
inline const char* FTermDetection::getTermType_256color()
{ return termtype_256color; }
//----------------------------------------------------------------------
inline const char* FTermDetection::getTermType_Answerback()
{ return termtype_Answerback; }
//----------------------------------------------------------------------
inline const char* FTermDetection::getTermType_SecDA()
{ return termtype_SecDA; }
#endif
//----------------------------------------------------------------------
inline bool FTermDetection::hasSetCursorStyleSupport()
{ return decscusr_support; }
//----------------------------------------------------------------------
inline bool FTermDetection::isXTerminal()
{ return terminal_type.xterm; }
//----------------------------------------------------------------------
inline bool FTermDetection::isAnsiTerminal()
{ return terminal_type.ansi; }
//----------------------------------------------------------------------
inline bool FTermDetection::isRxvtTerminal()
{ return terminal_type.rxvt; }
//----------------------------------------------------------------------
inline bool FTermDetection::isUrxvtTerminal()
{ return terminal_type.urxvt; }
//----------------------------------------------------------------------
inline bool FTermDetection::isMltermTerminal()
{ return terminal_type.mlterm; }
//----------------------------------------------------------------------
inline bool FTermDetection::isPuttyTerminal()
{ return terminal_type.putty; }
//----------------------------------------------------------------------
inline bool FTermDetection::isKdeTerminal()
{ return terminal_type.kde_konsole; }
//----------------------------------------------------------------------
inline bool FTermDetection::isGnomeTerminal()
{ return terminal_type.gnome_terminal; }
//----------------------------------------------------------------------
inline bool FTermDetection::isKtermTerminal()
{ return terminal_type.kterm; }
//----------------------------------------------------------------------
inline bool FTermDetection::isTeraTerm()
{ return terminal_type.tera_term; }
//----------------------------------------------------------------------
inline bool FTermDetection::isSunTerminal()
{ return terminal_type.sun_con; }
//----------------------------------------------------------------------
inline bool FTermDetection::isCygwinTerminal()
{ return terminal_type.cygwin; }
//----------------------------------------------------------------------
inline bool FTermDetection::isMinttyTerm()
{ return terminal_type.mintty; }
//----------------------------------------------------------------------
inline bool FTermDetection::isLinuxTerm()
{ return terminal_type.linux_con; }
//----------------------------------------------------------------------
inline bool FTermDetection::isFreeBSDTerm()
{ return terminal_type.freebsd_con; }
//----------------------------------------------------------------------
inline bool FTermDetection::isNetBSDTerm()
{ return terminal_type.netbsd_con; }
//----------------------------------------------------------------------
inline bool FTermDetection::isOpenBSDTerm()
{ return terminal_type.openbsd_con; }
//----------------------------------------------------------------------
inline bool FTermDetection::isScreenTerm()
{ return terminal_type.screen; }
//----------------------------------------------------------------------
inline bool FTermDetection::isTmuxTerm()
{ return terminal_type.tmux; }
//----------------------------------------------------------------------
inline bool FTermDetection::hasTerminalDetection()
{ return terminal_detection; }
//----------------------------------------------------------------------
inline void FTermDetection::setXTerminal (bool on)
{ terminal_type.xterm = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setAnsiTerminal (bool on)
{ terminal_type.ansi = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setRxvtTerminal (bool on)
{ terminal_type.rxvt = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setUrxvtTerminal (bool on)
{ terminal_type.urxvt = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setMltermTerminal (bool on)
{ terminal_type.mlterm = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setPuttyTerminal (bool on)
{ terminal_type.putty = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setKdeTerminal (bool on)
{ terminal_type.kde_konsole = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setGnomeTerminal (bool on)
{ terminal_type.gnome_terminal = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setKtermTerminal (bool on)
{ terminal_type.kterm = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setTeraTerm (bool on)
{ terminal_type.tera_term = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setSunTerminal (bool on)
{ terminal_type.sun_con = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setCygwinTerminal (bool on)
{ terminal_type.cygwin = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setMinttyTerm (bool on)
{ terminal_type.mintty = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setLinuxTerm (bool on)
{ terminal_type.linux_con = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setFreeBSDTerm (bool on)
{ terminal_type.freebsd_con = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setNetBSDTerm (bool on)
{ terminal_type.netbsd_con = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setOpenBSDTerm (bool on)
{ terminal_type.openbsd_con = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setScreenTerm (bool on)
{ terminal_type.screen = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setTmuxTerm (bool on)
{ terminal_type.tmux = on; }
//----------------------------------------------------------------------
inline void FTermDetection::setTerminalDetection (bool on)
{ terminal_detection = on; }
#endif // FTERMDETECTION_H

119
include/final/ftermios.h Normal file
View File

@ -0,0 +1,119 @@
/***********************************************************************
* ftermios.h - Provides access to POSIX tty I/O control *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
/* Standalone class
*
*
*
* FTermios
*
*/
#ifndef FTERMIOS_H
#define FTERMIOS_H
#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
#error "Only <final/final.h> can be included directly."
#endif
#include <termios.h>
#include <unistd.h>
#include "final/fterm.h"
#include "final/ftypes.h"
//----------------------------------------------------------------------
// class FTermios
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class FTermios
{
public:
// Constructors
FTermios();
// Destructor
~FTermios();
// Accessors
static termios getTTY();
static int getStdIn();
static int getStdOut();
// Inquiries
static bool isRaw();
// Methods
static void init();
static void setTTY (const termios&);
static void storeTTYsettings();
static void restoreTTYsettings();
static void setHardwareEcho();
static void unsetHardwareEcho();
static void setCaptureSendCharacters();
static void unsetCaptureSendCharacters();
static bool setRawMode (bool);
static bool setRawMode();
static bool unsetRawMode();
static bool setCookedMode();
static uInt getBaudRate();
private:
// Data Members
static int stdin_no;
static int stdout_no;
static bool raw_mode;
static struct termios term_init;
};
#pragma pack(pop)
// FTermios inline functions
//----------------------------------------------------------------------
inline int FTermios::getStdIn()
{ return stdin_no; }
//----------------------------------------------------------------------
inline int FTermios::getStdOut()
{ return stdout_no; }
//----------------------------------------------------------------------
inline bool FTermios::isRaw()
{ return raw_mode; }
//----------------------------------------------------------------------
inline bool FTermios::setRawMode()
{ return setRawMode(true); }
//----------------------------------------------------------------------
inline bool FTermios::unsetRawMode()
{ return setRawMode(false); }
//----------------------------------------------------------------------
inline bool FTermios::setCookedMode()
{ return setRawMode(false); }
#endif // FTERMIOS_H

View File

@ -40,6 +40,9 @@ libfinal_la_SOURCES = \
ffiledialog.cpp \ ffiledialog.cpp \
ftextview.cpp \ ftextview.cpp \
fstatusbar.cpp \ fstatusbar.cpp \
ftermcapquirks.cpp \
ftermdetection.cpp \
ftermios.cpp \
fterm.cpp \ fterm.cpp \
fvterm.cpp \ fvterm.cpp \
fevent.cpp \ fevent.cpp \
@ -67,6 +70,7 @@ finalcutinclude_HEADERS = \
../include/final/fdialog.h \ ../include/final/fdialog.h \
../include/final/fc.h \ ../include/final/fc.h \
../include/final/ftypes.h \ ../include/final/ftypes.h \
../include/final/emptyfstring.h \
../include/final/fevent.h \ ../include/final/fevent.h \
../include/final/ffiledialog.h \ ../include/final/ffiledialog.h \
../include/final/final.h \ ../include/final/final.h \
@ -99,6 +103,9 @@ finalcutinclude_HEADERS = \
../include/final/fstring.h \ ../include/final/fstring.h \
../include/final/ftcap_map.h \ ../include/final/ftcap_map.h \
../include/final/ftermcap.h \ ../include/final/ftermcap.h \
../include/final/ftermcapquirks.h \
../include/final/ftermdetection.h \
../include/final/ftermios.h \
../include/final/fterm.h \ ../include/final/fterm.h \
../include/final/fvterm.h \ ../include/final/fvterm.h \
../include/final/ftextview.h \ ../include/final/ftextview.h \

View File

@ -44,6 +44,9 @@ INCLUDE_HEADERS = \
fstring.h \ fstring.h \
ftermcap.h \ ftermcap.h \
fterm.h \ fterm.h \
ftermios.h \
ftermdetection.h \
ftermcapquirks.h \
fvterm.h \ fvterm.h \
ftextview.h \ ftextview.h \
ftogglebutton.h \ ftogglebutton.h \
@ -95,6 +98,9 @@ OBJS = \
ftextview.o \ ftextview.o \
fstatusbar.o \ fstatusbar.o \
fterm.o \ fterm.o \
ftermios.o \
ftermdetection.o \
ftermcapquirks.o \
fvterm.o \ fvterm.o \
fevent.o \ fevent.o \
foptiattr.o \ foptiattr.o \

View File

@ -44,6 +44,9 @@ INCLUDE_HEADERS = \
fstring.h \ fstring.h \
ftermcap.h \ ftermcap.h \
fterm.h \ fterm.h \
ftermios.h \
ftermdetection.h \
ftermcapquirks.h \
fvterm.h \ fvterm.h \
ftextview.h \ ftextview.h \
ftogglebutton.h \ ftogglebutton.h \
@ -95,6 +98,9 @@ OBJS = \
ftextview.o \ ftextview.o \
fstatusbar.o \ fstatusbar.o \
fterm.o \ fterm.o \
ftermios.o \
ftermdetection.o \
ftermcapquirks.o \
fvterm.o \ fvterm.o \
fevent.o \ fevent.o \
foptiattr.o \ foptiattr.o \

View File

@ -136,9 +136,10 @@ am_libfinal_la_OBJECTS = fstring.lo fpoint.lo frect.lo fscrollbar.lo \
fdialoglistmenu.lo fmenubar.lo fmenuitem.lo fradiomenuitem.lo \ fdialoglistmenu.lo fmenubar.lo fmenuitem.lo fradiomenuitem.lo \
fcheckmenuitem.lo fmenulist.lo fdialog.lo fscrollview.lo \ fcheckmenuitem.lo fmenulist.lo fdialog.lo fscrollview.lo \
fwindow.lo fmessagebox.lo ftooltip.lo ffiledialog.lo \ fwindow.lo fmessagebox.lo ftooltip.lo ffiledialog.lo \
ftextview.lo fstatusbar.lo fterm.lo fvterm.lo fevent.lo \ ftextview.lo fstatusbar.lo ftermcapquirks.lo ftermdetection.lo \
foptiattr.lo foptimove.lo ftermbuffer.lo fapplication.lo \ ftermios.lo fterm.lo fvterm.lo fevent.lo foptiattr.lo \
fcolorpalette.lo fwidgetcolors.lo fwidget.lo fobject.lo foptimove.lo ftermbuffer.lo fapplication.lo fcolorpalette.lo \
fwidgetcolors.lo fwidget.lo fobject.lo
libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS) libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -412,6 +413,9 @@ libfinal_la_SOURCES = \
ffiledialog.cpp \ ffiledialog.cpp \
ftextview.cpp \ ftextview.cpp \
fstatusbar.cpp \ fstatusbar.cpp \
ftermcapquirks.cpp \
ftermdetection.cpp \
ftermios.cpp \
fterm.cpp \ fterm.cpp \
fvterm.cpp \ fvterm.cpp \
fevent.cpp \ fevent.cpp \
@ -437,6 +441,7 @@ finalcutinclude_HEADERS = \
../include/final/fdialog.h \ ../include/final/fdialog.h \
../include/final/fc.h \ ../include/final/fc.h \
../include/final/ftypes.h \ ../include/final/ftypes.h \
../include/final/emptyfstring.h \
../include/final/fevent.h \ ../include/final/fevent.h \
../include/final/ffiledialog.h \ ../include/final/ffiledialog.h \
../include/final/final.h \ ../include/final/final.h \
@ -469,6 +474,9 @@ finalcutinclude_HEADERS = \
../include/final/fstring.h \ ../include/final/fstring.h \
../include/final/ftcap_map.h \ ../include/final/ftcap_map.h \
../include/final/ftermcap.h \ ../include/final/ftermcap.h \
../include/final/ftermcapquirks.h \
../include/final/ftermdetection.h \
../include/final/ftermios.h \
../include/final/fterm.h \ ../include/final/fterm.h \
../include/final/fvterm.h \ ../include/final/fvterm.h \
../include/final/ftextview.h \ ../include/final/ftextview.h \
@ -592,6 +600,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fswitch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fswitch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fterm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fterm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftermbuffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftermbuffer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftermcapquirks.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftermdetection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftermios.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftextview.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftextview.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftogglebutton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftogglebutton.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftooltip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftooltip.Plo@am__quote@

View File

@ -369,7 +369,7 @@ void FApplication::init (long key_time, long dblclick_time)
// Set stdin number for a gpm-mouse // Set stdin number for a gpm-mouse
if ( mouse ) if ( mouse )
mouse->setStdinNo (stdin_no); mouse->setStdinNo (FTermios::getStdIn());
// Set the default double click interval // Set the default double click interval
if ( mouse ) if ( mouse )
@ -465,6 +465,7 @@ inline bool FApplication::KeyPressed()
register int result; register int result;
fd_set ifds; fd_set ifds;
struct timeval tv; struct timeval tv;
int stdin_no = FTermios::getStdIn();
FD_ZERO(&ifds); FD_ZERO(&ifds);
FD_SET(stdin_no, &ifds); FD_SET(stdin_no, &ifds);
@ -483,7 +484,7 @@ inline ssize_t FApplication::readKey()
{ {
register ssize_t bytes; register ssize_t bytes;
setNonBlockingInput(); setNonBlockingInput();
bytes = read(stdin_no, &k_buf, sizeof(k_buf) - 1); bytes = read(FTermios::getStdIn(), &k_buf, sizeof(k_buf) - 1);
unsetNonBlockingInput(); unsetNonBlockingInput();
return bytes; return bytes;
} }

File diff suppressed because it is too large Load Diff

500
src/ftermcapquirks.cpp Normal file
View File

@ -0,0 +1,500 @@
/***********************************************************************
* ftermcapquirks.cpp - Termcap quirks for some well-known terminals *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
#include "final/ftermcapquirks.h"
// static class attributes
char FTermcapQuirks::termtype[256] = {};
FTermcap::tcap_map* FTermcapQuirks::tcap = 0;
FTermDetection* FTermcapQuirks::term_detection = 0;
//----------------------------------------------------------------------
// class FTermcapQuirks
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
FTermcapQuirks::FTermcapQuirks()
{ }
//----------------------------------------------------------------------
FTermcapQuirks::~FTermcapQuirks() // destructor
{ }
// public methods of FTermcapQuirks
//----------------------------------------------------------------------
void FTermcapQuirks::setTerminalType (char tt[])
{
std::strncpy (termtype, tt, sizeof(termtype) - 1);
}
//----------------------------------------------------------------------
void FTermcapQuirks::setTermcapMap (FTermcap::tcap_map* tc)
{
tcap = tc;
}
//----------------------------------------------------------------------
void FTermcapQuirks::setFTermDetection (FTermDetection* td)
{
term_detection = td;
}
// private methods of FTermcapQuirks
//----------------------------------------------------------------------
void FTermcapQuirks::terminalFixup()
{
FTermDetection* td = term_detection;
if ( td->isCygwinTerminal() )
{
init_termcap_cygwin_quirks();
}
else if ( td->isLinuxTerm() )
{
init_termcap_linux_quirks();
}
else if ( td->isRxvtTerminal() )
{
init_termcap_rxvt_quirks();
}
else if ( td->isGnomeTerminal() )
{
init_termcap_vte_quirks();
}
else if ( td->isTeraTerm() )
{
init_termcap_teraterm_quirks();
}
else if ( td->isSunTerminal() )
{
init_termcap_sun_quirks();
}
else if ( td->isPuttyTerminal() )
{
init_termcap_putty_quirks();
}
else if ( td->isScreenTerm() )
{
init_termcap_screen_quirks();
}
#if defined(__FreeBSD__) || defined(__DragonFly__)
else if ( td->isFreeBSDTerm() )
{
init_termcap_freebsd_quirks();
}
#endif
// xterm and compatible terminals
if ( td->isXTerminal() && ! td->isPuttyTerminal() )
init_termcap_xterm_quirks();
// Fixes general quirks
init_termcap_general_quirks();
}
#if defined(__FreeBSD__) || defined(__DragonFly__)
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_freebsd_quirks()
{
// FreeBSD console fixes
TCAP(fc::t_acs_chars) = \
C_STR("-\036.\0370\333"
"a\260f\370g\361"
"h\261j\331k\277"
"l\332m\300n\305"
"q\304t\303u\264"
"v\301w\302x\263"
"y\363z\362~\371");
TCAP(fc::t_set_attributes) = \
C_STR(CSI "0"
"%?%p1%p6%|%t;1%;"
"%?%p2%t;4%;"
"%?%p1%p3%|%t;7%;"
"%?%p4%t;5%;m"
"%?%p9%t\016%e\017%;");
FTermcap::attr_without_color = 18;
}
#endif
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_cygwin_quirks()
{
// Set invisible cursor for cygwin terminal
if ( ! TCAP(fc::t_cursor_invisible) )
TCAP(fc::t_cursor_invisible) = \
C_STR(CSI "?25l");
// Set visible cursor for cygwin terminal
if ( ! TCAP(fc::t_cursor_visible) )
TCAP(fc::t_cursor_visible) = \
C_STR(CSI "?25h");
// Set ansi blink for cygwin terminal
if ( ! TCAP(fc::t_enter_blink_mode) )
TCAP(fc::t_enter_blink_mode) = \
C_STR(CSI "5m");
// Set enable alternate character set for cygwin terminal
if ( ! TCAP(fc::t_enable_acs) )
TCAP(fc::t_enable_acs) = \
C_STR(ESC "(B" ESC ")0");
// Set background color erase for cygwin terminal
FTermcap::background_color_erase = true;
// Include the Linux console quirks
init_termcap_linux_quirks();
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_linux_quirks()
{
/* Same settings are used by cygwin */
// Set ansi foreground and background color
if ( FTermcap::max_color > 8 )
{
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "3%p1%{8}%m%d%?%p1%{7}%>%t;1%e;22%;m");
TCAP(fc::t_set_a_background) = \
C_STR(CSI "4%p1%{8}%m%d%?%p1%{7}%>%t;5%e;25%;m");
// Avoid underline, blink and dim mode
FTermcap::attr_without_color = 26;
}
else
{
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "3%p1%dm");
TCAP(fc::t_set_a_background) = \
C_STR(CSI "4%p1%dm");
// Avoid underline and dim mode
FTermcap::attr_without_color = 18;
}
// Set select graphic rendition attributes
TCAP(fc::t_set_attributes) = \
C_STR(CSI "0"
"%?%p6%|%t;1%;"
"%?%p1%p3%|%t;7%;"
"%?%p4%t;5%;m"
"%?%p9%t\016%e\017%;");
TCAP(fc::t_enter_alt_charset_mode) = C_STR("\016");
TCAP(fc::t_exit_alt_charset_mode) = C_STR("\017");
TCAP(fc::t_exit_attribute_mode) = C_STR(CSI "0m\017");
TCAP(fc::t_exit_bold_mode) = C_STR(CSI "22m");
TCAP(fc::t_exit_blink_mode) = C_STR(CSI "25m");
TCAP(fc::t_exit_reverse_mode) = C_STR(CSI "27m");
TCAP(fc::t_exit_secure_mode) = 0;
TCAP(fc::t_exit_protected_mode) = 0;
TCAP(fc::t_exit_crossed_out_mode) = 0;
TCAP(fc::t_orig_pair) = C_STR(CSI "39;49;25m");
// Avoid underline and dim mode
TCAP(fc::t_enter_dim_mode) = 0;
TCAP(fc::t_exit_dim_mode) = 0;
TCAP(fc::t_enter_underline_mode) = 0;
TCAP(fc::t_exit_underline_mode) = 0;
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_xterm_quirks()
{
// Fallback if "Ic" is not found
if ( ! TCAP(fc::t_initialize_color) )
{
TCAP(fc::t_initialize_color) = \
C_STR(OSC "4;%p1%d;rgb:"
"%p2%{255}%*%{1000}%/%2.2X/"
"%p3%{255}%*%{1000}%/%2.2X/"
"%p4%{255}%*%{1000}%/%2.2X" ESC "\\");
}
// Fallback if "vi" is not found
if ( ! TCAP(fc::t_cursor_invisible) )
TCAP(fc::t_cursor_invisible) = \
C_STR(CSI "?25l");
// Fallback if "ve" is not found
if ( ! TCAP(fc::t_cursor_normal) )
TCAP(fc::t_cursor_normal) = \
C_STR(CSI "?12l" CSI "?25h");
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_rxvt_quirks()
{
// Set enter/exit alternative charset mode for rxvt terminal
if ( std::strncmp(termtype, "rxvt-16color", 12) == 0 )
{
TCAP(fc::t_enter_alt_charset_mode) = \
C_STR(ESC "(0");
TCAP(fc::t_exit_alt_charset_mode) = \
C_STR(ESC "(B");
}
// Set ansi foreground and background color
if ( ! term_detection->isUrxvtTerminal() )
{
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "%?%p1%{8}%<%t%p1%{30}%+%e%p1%'R'%+%;%dm");
TCAP(fc::t_set_a_background) = \
C_STR(CSI "%?%p1%{8}%<%t%p1%'('%+%e%p1%{92}%+%;%dm");
}
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_vte_quirks()
{
// gnome-terminal has NC=16 however, it can use the dim attribute
FTermcap::attr_without_color = 0;
// set exit underline for gnome terminal
TCAP(fc::t_exit_underline_mode) = \
C_STR(CSI "24m");
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_putty_quirks()
{
FTermcap::background_color_erase = true;
FTermcap::osc_support = true;
// PuTTY has NC=22 however, it can show underline and reverse
// and since version 0.71 is the dim attribute is also supported
FTermcap::attr_without_color = 0;
// Set ansi foreground and background color
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "%?%p1%{8}%<"
"%t3%p1%d"
"%e%p1%{16}%<"
"%t9%p1%{8}%-%d"
"%e38;5;%p1%d%;m");
TCAP(fc::t_set_a_background) = \
C_STR(CSI "%?%p1%{8}%<"
"%t4%p1%d"
"%e%p1%{16}%<"
"%t10%p1%{8}%-%d"
"%e48;5;%p1%d%;m");
TCAP(fc::t_set_attributes) = \
C_STR(CSI "0"
"%?%p1%p6%|%t;1%;"
"%?%p5%t;2%;" // since putty 0.71
"%?%p2%t;4%;"
"%?%p1%p3%|%t;7%;"
"%?%p4%t;5%;m"
"%?%p9%t\016%e\017%;");
// PuTTY 0.71 or higher
TCAP(fc::t_enter_dim_mode) = \
C_STR(CSI "2m");
// PuTTY 0.71 or higher
TCAP(fc::t_exit_dim_mode) = \
C_STR(CSI "22m");
if ( ! TCAP(fc::t_clr_bol) )
TCAP(fc::t_clr_bol) = \
C_STR(CSI "1K");
if ( ! TCAP(fc::t_orig_pair) )
TCAP(fc::t_orig_pair) = \
C_STR(CSI "39;49m");
if ( ! TCAP(fc::t_orig_colors) )
TCAP(fc::t_orig_colors) = \
C_STR(OSC "R");
if ( ! TCAP(fc::t_column_address) )
TCAP(fc::t_column_address) = \
C_STR(CSI "%i%p1%dG");
if ( ! TCAP(fc::t_row_address) )
TCAP(fc::t_row_address) = \
C_STR(CSI "%i%p1%dd");
if ( ! TCAP(fc::t_enable_acs) )
TCAP(fc::t_enable_acs) = \
C_STR(ESC "(B" ESC ")0");
if ( ! TCAP(fc::t_enter_am_mode) )
TCAP(fc::t_enter_am_mode) = \
C_STR(CSI "?7h");
if ( ! TCAP(fc::t_exit_am_mode) )
TCAP(fc::t_exit_am_mode) = \
C_STR(CSI "?7l");
if ( ! TCAP(fc::t_enter_pc_charset_mode) )
TCAP(fc::t_enter_pc_charset_mode) = \
C_STR(CSI "11m");
if ( ! TCAP(fc::t_exit_pc_charset_mode) )
TCAP(fc::t_exit_pc_charset_mode) = \
C_STR(CSI "10m");
if ( ! TCAP(fc::t_key_mouse) )
TCAP(fc::t_key_mouse) = \
C_STR(CSI "M");
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_teraterm_quirks()
{
// Tera Term eat_nl_glitch fix
FTermcap::eat_nl_glitch = true;
// Tera Term color settings
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "38;5;%p1%dm");
TCAP(fc::t_set_a_background) = \
C_STR(CSI "48;5;%p1%dm");
TCAP(fc::t_exit_attribute_mode) = \
C_STR(CSI "0m" SI);
TCAP(fc::t_orig_pair) = \
C_STR(CSI "39;49m");
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_sun_quirks()
{
// Sun Microsystems workstation console eat_nl_glitch fix
FTermcap::eat_nl_glitch = true;
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_screen_quirks()
{
// Fallback if "Ic" is not found
if ( ! TCAP(fc::t_initialize_color) )
{
if ( term_detection->isTmuxTerm() )
{
TCAP(fc::t_initialize_color) = \
C_STR(ESC "Ptmux;" ESC OSC "4;%p1%d;rgb:"
"%p2%{255}%*%{1000}%/%2.2X/"
"%p3%{255}%*%{1000}%/%2.2X/"
"%p4%{255}%*%{1000}%/%2.2X" BEL ESC "\\");
}
else
{
TCAP(fc::t_initialize_color) = \
C_STR(ESC "P" OSC "4;%p1%d;rgb:"
"%p2%{255}%*%{1000}%/%2.2X/"
"%p3%{255}%*%{1000}%/%2.2X/"
"%p4%{255}%*%{1000}%/%2.2X" BEL ESC "\\");
}
}
}
//----------------------------------------------------------------------
void FTermcapQuirks::init_termcap_general_quirks()
{
static const int not_available = -1;
if ( FTermcap::tabstop == not_available )
FTermcap::tabstop = 8;
if ( FTermcap::attr_without_color == not_available )
FTermcap::attr_without_color = 0;
// Fallback if "AF" is not found
if ( ! TCAP(fc::t_set_a_foreground) )
TCAP(fc::t_set_a_foreground) = \
C_STR(CSI "3%p1%dm");
// Fallback if "AB" is not found
if ( ! TCAP(fc::t_set_a_background) )
TCAP(fc::t_set_a_background) = \
C_STR(CSI "4%p1%dm");
// Fallback if "Ic" is not found
if ( ! TCAP(fc::t_initialize_color) )
{
TCAP(fc::t_initialize_color) = \
C_STR(OSC "P%p1%x"
"%p2%{255}%*%{1000}%/%02x"
"%p3%{255}%*%{1000}%/%02x"
"%p4%{255}%*%{1000}%/%02x");
}
// Fallback if "ti" is not found
if ( ! TCAP(fc::t_enter_ca_mode) )
TCAP(fc::t_enter_ca_mode) = \
C_STR(ESC "7" CSI "?47h");
// Fallback if "te" is not found
if ( ! TCAP(fc::t_exit_ca_mode) )
TCAP(fc::t_exit_ca_mode) = \
C_STR(CSI "?47l" ESC "8" CSI "m");
// Set ansi move if "cm" is not found
if ( ! TCAP(fc::t_cursor_address) )
TCAP(fc::t_cursor_address) = \
C_STR(CSI "%i%p1%d;%p2%dH");
// Test for standard ECMA-48 (ANSI X3.64) terminal
if ( TCAP(fc::t_exit_underline_mode)
&& std::strncmp(TCAP(fc::t_exit_underline_mode), CSI "24m", 5) == 0 )
{
// Seems to be a ECMA-48 (ANSI X3.64) compatible terminal
TCAP(fc::t_enter_dbl_underline_mode) = \
C_STR(CSI "21m"); // Exit single underline, too
TCAP(fc::t_exit_dbl_underline_mode) = \
C_STR(CSI "24m");
TCAP(fc::t_exit_bold_mode) = \
C_STR(CSI "22m"); // Exit dim, too
TCAP(fc::t_exit_dim_mode) = \
C_STR(CSI "22m");
TCAP(fc::t_exit_underline_mode) = \
C_STR(CSI "24m");
TCAP(fc::t_exit_blink_mode) = \
C_STR(CSI "25m");
TCAP(fc::t_exit_reverse_mode) = \
C_STR(CSI "27m");
TCAP(fc::t_exit_secure_mode) = \
C_STR(CSI "28m");
TCAP(fc::t_enter_crossed_out_mode) = \
C_STR(CSI "9m");
TCAP(fc::t_exit_crossed_out_mode) = \
C_STR(CSI "29m");
}
}

893
src/ftermdetection.cpp Normal file
View File

@ -0,0 +1,893 @@
/***********************************************************************
* ftermdetection.cpp - Detection of the terminal type *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
#include "final/fterm.h"
#include "final/ftermdetection.h"
// static class attributes
FTermDetection::terminalType FTermDetection::terminal_type = \
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FTermDetection::colorEnv FTermDetection::color_env;
FTermDetection::secondaryDA FTermDetection::secondary_da;
char FTermDetection::termtype[256] = {};
char FTermDetection::termfilename[256] = {};
bool FTermDetection::decscusr_support;
bool FTermDetection::terminal_detection;
bool FTermDetection::color256;
const FString* FTermDetection::answer_back = 0;
const FString* FTermDetection::sec_da = 0;
int FTermDetection::gnome_terminal_id;
#if DEBUG
char FTermDetection::termtype_256color[256] = {};
char FTermDetection::termtype_Answerback[256] = {};
char FTermDetection::termtype_SecDA[256] = {};
#endif
//----------------------------------------------------------------------
// class FTermDetection
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
FTermDetection::FTermDetection()
{
// Preset to true
terminal_detection = true;
// Preset to false
decscusr_support = false;
// Gnome terminal id from SecDA
// Example: vte version 0.40.0 = 0 * 100 + 40 * 100 + 0 = 4000
// a.b.c = a * 100 + b * 100 + c
gnome_terminal_id = 0;
}
//----------------------------------------------------------------------
FTermDetection::~FTermDetection() // destructor
{
if ( sec_da )
delete sec_da;
if ( answer_back )
delete answer_back;
}
// public methods of FTermDetection
//----------------------------------------------------------------------
void FTermDetection::setTermFileName (char term_filename[])
{
if ( ! term_filename )
return;
std::strncpy ( termfilename
, term_filename
, std::strlen(term_filename) + 1 );
}
//----------------------------------------------------------------------
void FTermDetection::detect()
{
// Set the variable 'termtype' to the predefined type of the terminal
getSystemTermType();
// Analysis the termtype
termtypeAnalysis();
// Terminal detection
detectTerminal();
}
// private methods of FTermDetection
//----------------------------------------------------------------------
void FTermDetection::getSystemTermType()
{
// Import the untrusted environment variable TERM
const char* const& term_env = std::getenv(C_STR("TERM"));
if ( term_env )
{
// Save name in termtype
std::strncpy (termtype, term_env, sizeof(termtype) - 1);
return;
}
else if ( *termfilename ) // 1st fallback: use the teminal file name
{
getTTYtype(); // Look into /etc/ttytype
#if F_HAVE_GETTTYNAM
if ( getTTYSFileEntry() ) // Look into /etc/ttys
return;
#endif
}
// 2nd fallback: use vt100 if not found
std::strncpy (termtype, C_STR("vt100"), 6);
}
//----------------------------------------------------------------------
void FTermDetection::getTTYtype()
{
// Analyse /etc/ttytype and get the term name
// ------------------------------------------
// file format:
// <terminal type> <whitespace> <tty name>
//
// Example:
// linux tty1
// vt100 ttys0
// Get term basename
const char* term_basename = std::strrchr(termfilename, '/');
if ( term_basename == 0 )
term_basename = termfilename;
else
term_basename++;
std::FILE *fp;
if ( (fp = std::fopen("/etc/ttytype", "r")) != 0 )
{
char* p;
char str[BUFSIZ];
// Read and parse the file
while ( fgets(str, sizeof(str) - 1, fp) != 0 )
{
char* name;
char* type;
type = name = 0; // 0 == not found
p = str;
while ( *p )
{
if ( std::isspace(uChar(*p)) )
*p = '\0';
else if ( type == 0 )
type = p;
else if ( name == 0 && p != str && p[-1] == '\0' )
name = p;
p++;
}
if ( type != 0 && name != 0 && ! std::strcmp(name, term_basename) )
{
// Save name in termtype
std::strncpy (termtype, type, sizeof(termtype) - 1);
std::fclose(fp);
return;
}
}
std::fclose(fp);
}
}
#if F_HAVE_GETTTYNAM
//----------------------------------------------------------------------
bool FTermDetection::getTTYSFileEntry()
{
// Analyse /etc/ttys and get the term name
// get term basename
const char* term_basename = std::strrchr(termfilename, '/');
if ( term_basename == 0 )
term_basename = termfilename;
else
term_basename++;
struct ttyent* ttys_entryt;
ttys_entryt = getttynam(term_basename);
if ( ttys_entryt )
{
char* type = ttys_entryt->ty_type;
if ( type != 0 )
{
// Save name in termtype
std::strncpy (termtype, type, sizeof(termtype) - 1);
endttyent();
return true;
}
}
endttyent();
return false;
}
#endif
//----------------------------------------------------------------------
void FTermDetection::termtypeAnalysis()
{
// Cygwin console
if ( std::strncmp(termtype, "cygwin", 6) == 0 )
terminal_type.cygwin = true;
// rxvt terminal emulator (native MS Window System port) on cygwin
if ( std::strncmp(termtype, "rxvt-cygwin-native", 18) == 0 )
terminal_type.rxvt = true;
// Ansi terminal
if ( std::strncmp(termtype, "ansi", 4) == 0 )
{
terminal_detection = false;
terminal_type.ansi = true;
}
// Sun Microsystems workstation console
if ( std::strncmp(termtype, "sun", 3) == 0 )
{
terminal_detection = false;
terminal_type.sun_con = true;
}
// Kterm
if ( std::strncmp(termtype, "kterm", 5) == 0 )
{
terminal_detection = false;
terminal_type.kterm = true;
}
// Linux console
if ( std::strncmp(termtype, C_STR("linux"), 5) == 0
|| std::strncmp(termtype, C_STR("con"), 3) == 0 )
terminal_type.linux_con = true;
// NetBSD workstation console
if ( std::strncmp(termtype, C_STR("wsvt25"), 6) == 0 )
terminal_type.netbsd_con = true;
}
//----------------------------------------------------------------------
void FTermDetection::detectTerminal()
{
// Terminal detection
char* new_termtype = 0;
if ( terminal_detection )
{
FTermios::setCaptureSendCharacters();
// Initialize 256 colors terminals
new_termtype = init_256colorTerminal();
// Identify the terminal via the answerback-message
new_termtype = parseAnswerbackMsg (new_termtype);
// Identify the terminal via the secondary device attributes (SEC_DA)
new_termtype = parseSecDA (new_termtype);
// Determines the maximum number of colors
new_termtype = determineMaxColor(new_termtype);
FTermios::unsetCaptureSendCharacters();
}
//
// Additional termtype analysis
//
// Test if the terminal is a xterm
if ( std::strncmp(termtype, C_STR("xterm"), 5) == 0
|| std::strncmp(termtype, C_STR("Eterm"), 5) == 0 )
{
terminal_type.xterm = true;
// Each xterm should be able to use at least 16 colors
if ( ! new_termtype && std::strlen(termtype) == 5 )
new_termtype = C_STR("xterm-16color");
}
// set the new environment variable TERM
if ( new_termtype )
{
setenv(C_STR("TERM"), new_termtype, 1);
std::strncpy (termtype, new_termtype, std::strlen(new_termtype) + 1);
}
}
//----------------------------------------------------------------------
char* FTermDetection::init_256colorTerminal()
{
char* new_termtype = 0;
if ( get256colorEnvString() )
color256 = true;
else if ( std::strstr (termtype, "256color") )
color256 = true;
else
color256 = false;
new_termtype = termtype_256color_quirks();
#if DEBUG
if ( new_termtype )
std::strncpy ( termtype_256color
, new_termtype
, std::strlen(new_termtype) + 1 );
#endif
return new_termtype;
}
//----------------------------------------------------------------------
bool FTermDetection::get256colorEnvString()
{
// Enable 256 color capabilities
color_env.string1 = std::getenv("COLORTERM");
color_env.string2 = std::getenv("VTE_VERSION");
color_env.string3 = std::getenv("XTERM_VERSION");
color_env.string4 = std::getenv("ROXTERM_ID");
color_env.string5 = std::getenv("KONSOLE_DBUS_SESSION");
color_env.string6 = std::getenv("KONSOLE_DCOP");
if ( color_env.string1 != 0 )
return true;
if ( color_env.string2 != 0 )
return true;
if ( color_env.string3 != 0 )
return true;
if ( color_env.string4 != 0 )
return true;
if ( color_env.string5 != 0 )
return true;
if ( color_env.string6 != 0 )
return true;
return false;
}
//----------------------------------------------------------------------
char* FTermDetection::termtype_256color_quirks()
{
char* new_termtype = 0;
if ( ! color256 )
return new_termtype;
if ( std::strncmp(termtype, "xterm", 5) == 0 )
new_termtype = C_STR("xterm-256color");
if ( std::strncmp(termtype, "screen", 6) == 0 )
{
new_termtype = C_STR("screen-256color");
terminal_type.screen = true;
char* tmux = std::getenv("TMUX");
if ( tmux && std::strlen(tmux) != 0 )
terminal_type.tmux = true;
}
if ( std::strncmp(termtype, "Eterm", 5) == 0 )
new_termtype = C_STR("Eterm-256color");
if ( std::strncmp(termtype, "mlterm", 6) == 0 )
{
new_termtype = C_STR("mlterm-256color");
terminal_type.mlterm = true;
}
if ( std::strncmp(termtype, "rxvt", 4) != 0
&& color_env.string1
&& std::strncmp(color_env.string1, "rxvt-xpm", 8) == 0 )
{
new_termtype = C_STR("rxvt-256color");
terminal_type.rxvt = true;
}
if ( (color_env.string5 && std::strlen(color_env.string5) > 0)
|| (color_env.string6 && std::strlen(color_env.string6) > 0) )
terminal_type.kde_konsole = true;
if ( (color_env.string1 && std::strncmp(color_env.string1, "gnome-terminal", 14) == 0)
|| color_env.string2 )
{
terminal_type.gnome_terminal = true;
// Each gnome-terminal should be able to use 256 colors
color256 = true;
if ( ! isScreenTerm() )
new_termtype = C_STR("gnome-256color");
}
return new_termtype;
}
//----------------------------------------------------------------------
char* FTermDetection::determineMaxColor (char current_termtype[])
{
// Determine xterm maximum number of colors via OSC 4
char* new_termtype = current_termtype;
if ( ! color256
&& ! isCygwinTerminal()
&& ! isTeraTerm()
&& ! isLinuxTerm()
&& ! isNetBSDTerm()
&& ! getXTermColorName(0).isEmpty() )
{
if ( ! getXTermColorName(256).isEmpty() )
{
if ( isPuttyTerminal() )
new_termtype = C_STR("putty-256color");
else
new_termtype = C_STR("xterm-256color");
}
else if ( ! getXTermColorName(87).isEmpty() )
{
new_termtype = C_STR("xterm-88color");
}
else if ( ! getXTermColorName(15).isEmpty() )
{
new_termtype = C_STR("xterm-16color");
}
}
return new_termtype;
}
//----------------------------------------------------------------------
const FString FTermDetection::getXTermColorName (int color)
{
FString color_str("");
fd_set ifds;
struct timeval tv;
int stdin_no = FTermios::getStdIn();
char temp[512] = {};
FTerm::putstringf (OSC "4;%d;?" BEL, color); // get color
std::fflush(stdout);
FD_ZERO(&ifds);
FD_SET(stdin_no, &ifds);
tv.tv_sec = 0;
tv.tv_usec = 150000; // 150 ms
// read the terminal answer
if ( select (stdin_no + 1, &ifds, 0, 0, &tv) > 0 )
{
if ( std::scanf("\033]4;%10d;%509[^\n]s", &color, temp) == 2 )
{
std::size_t n = std::strlen(temp);
// BEL + '\0' = string terminator
if ( n >= 6 && temp[n - 1] == BEL[0] && temp[n] == '\0' )
temp[n - 1] = '\0';
// Esc + \ = OSC string terminator (mintty)
if ( n >= 6 && temp[n - 2] == ESC[0] && temp[n - 1] == '\\' )
temp[n - 2] = '\0';
color_str = temp;
}
}
return color_str;
}
//----------------------------------------------------------------------
char* FTermDetection::parseAnswerbackMsg (char current_termtype[])
{
char* new_termtype = current_termtype;
// send ENQ and read the answerback message
try
{
answer_back = new FString(getAnswerbackMsg());
}
catch (const std::bad_alloc& ex)
{
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
return 0;
}
if ( *answer_back == "PuTTY" )
{
terminal_type.putty = true;
if ( color256 )
new_termtype = C_STR("putty-256color");
else
new_termtype = C_STR("putty");
}
// cygwin needs a backspace to delete the '♣' char
if ( isCygwinTerminal() )
FTerm::putstring (BS " " BS);
#if DEBUG
if ( new_termtype )
std::strncpy ( termtype_Answerback
, new_termtype
, std::strlen(new_termtype) + 1 );
#endif
return new_termtype;
}
//----------------------------------------------------------------------
const FString FTermDetection::getAnswerbackMsg()
{
FString answerback = "";
fd_set ifds;
struct timeval tv;
char temp[10] = {};
int stdin_no = FTermios::getStdIn();
std::putchar (ENQ[0]); // Send enquiry character
std::fflush(stdout);
FD_ZERO(&ifds);
FD_SET(stdin_no, &ifds);
tv.tv_sec = 0;
tv.tv_usec = 150000; // 150 ms
// Read the answerback message
if ( select (stdin_no + 1, &ifds, 0, 0, &tv) > 0 )
if ( std::fgets (temp, sizeof(temp) - 1, stdin) != 0 )
answerback = temp;
return answerback;
}
//----------------------------------------------------------------------
char* FTermDetection::parseSecDA (char current_termtype[])
{
// The Linux console and older cygwin terminals knows no Sec_DA
if ( isLinuxTerm() || isCygwinTerminal() )
return current_termtype;
try
{
// Secondary device attributes (SEC_DA) <- decTerminalID string
sec_da = new FString(getSecDA());
}
catch (const std::bad_alloc& ex)
{
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
return current_termtype;
}
if ( sec_da->getLength() < 6 )
return current_termtype;
// remove the first 3 bytes ("\033[>")
FString temp = sec_da->right(sec_da->getLength() - 3);
// remove the last byte ("c")
temp.remove(temp.getLength() - 1, 1);
// split into components
FStringList sec_da_list = temp.split(';');
uLong num_components = sec_da_list.size();
// The second device attribute (SEC_DA) always has 3 parameters,
// otherwise it usually has a copy of the device attribute (primary DA)
if ( num_components < 3 )
return current_termtype;
const FString* sec_da_components = &sec_da_list[0];
if ( sec_da_components[0].isEmpty() )
return current_termtype;
// Read the terminal type
try
{
secondary_da.terminal_id_type = sec_da_components[0].toInt();
}
catch (const std::exception&)
{
secondary_da.terminal_id_type = -1;
}
// Read the terminal (firmware) version
try
{
if ( sec_da_components[1] )
secondary_da.terminal_id_version = sec_da_components[1].toInt();
else
secondary_da.terminal_id_version = -1;
}
catch (const std::exception&)
{
secondary_da.terminal_id_version = -1;
}
// Read the terminal hardware option
try
{
if ( sec_da_components[2] )
secondary_da.terminal_id_hardware = sec_da_components[2].toInt();
else
secondary_da.terminal_id_hardware = -1;
}
catch (const std::exception&)
{
secondary_da.terminal_id_hardware = -1;
}
char* new_termtype = secDA_Analysis(current_termtype);
#if DEBUG
if ( new_termtype )
std::strncpy ( termtype_SecDA
, new_termtype
, std::strlen(new_termtype) + 1 );
#endif
return new_termtype;
}
//----------------------------------------------------------------------
const FString FTermDetection::getSecDA()
{
FString sec_da_str = "";
int a = 0
, b = 0
, c = 0
, stdin_no = FTermios::getStdIn();
fd_set ifds;
struct timeval tv;
// Get the secondary device attributes
#if defined(__CYGWIN__)
puts (SECDA);
#else
FTerm::putstring (SECDA);
#endif
std::fflush(stdout);
FD_ZERO(&ifds);
FD_SET(stdin_no, &ifds);
tv.tv_sec = 0;
tv.tv_usec = 600000; // 600 ms
// Read the answer
if ( select (stdin_no + 1, &ifds, 0, 0, &tv) == 1 )
if ( std::scanf("\033[>%10d;%10d;%10dc", &a, &b, &c) == 3 )
sec_da_str.sprintf("\033[>%d;%d;%dc", a, b, c);
return sec_da_str;
}
//----------------------------------------------------------------------
char* FTermDetection::secDA_Analysis (char current_termtype[])
{
char* new_termtype = current_termtype;
switch ( secondary_da.terminal_id_type )
{
case 0: // DEC VT100
new_termtype = secDA_Analysis_0(current_termtype);
break;
case 1: // DEC VT220
new_termtype = secDA_Analysis_1(current_termtype);
break;
case 2: // DEC VT240
case 18: // DEC VT330
case 19: // DEC VT340
case 24: // DEC VT320
new_termtype = secDA_Analysis_24(current_termtype);
break;
case 32: // Tera Term
new_termtype = secDA_Analysis_32(current_termtype);
break;
case 41: // DEC VT420
case 61: // DEC VT510
case 64: // DEC VT520
case 65: // DEC VT525
case 67: // Cygwin
break;
case 77: // mintty
new_termtype = secDA_Analysis_77(current_termtype);
break;
case 82: // rxvt
new_termtype = secDA_Analysis_82(current_termtype);
break;
case 83: // screen
new_termtype = secDA_Analysis_83(current_termtype);
break;
case 85: // rxvt-unicode
new_termtype = secDA_Analysis_85(current_termtype);
break;
default:
break;
}
// Correct false assumptions
if ( isGnomeTerminal() && secondary_da.terminal_id_type != 1 )
terminal_type.gnome_terminal = false;
if ( isKdeTerminal() && secondary_da.terminal_id_type != 0 )
terminal_type.kde_konsole = false;
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_0 (char current_termtype[])
{
// Terminal ID 0 - DEC VT100
char* new_termtype = current_termtype;
if ( secondary_da.terminal_id_version == 115 )
terminal_type.kde_konsole = true;
else if ( secondary_da.terminal_id_version == 136 )
terminal_type.putty = true; // PuTTY
#if defined(__FreeBSD__) || defined(__DragonFly__)
if ( FTerm::isFreeBSDConsole() )
terminal_type.freebsd_con = true;
#endif
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_1 (char current_termtype[])
{
// Terminal ID 1 - DEC VT220
char* new_termtype = current_termtype;
if ( secondary_da.terminal_id_version > 1000 )
{
terminal_type.gnome_terminal = true;
// Each gnome-terminal should be able to use 256 colors
color256 = true;
new_termtype = C_STR("gnome-256color");
gnome_terminal_id = secondary_da.terminal_id_version;
// VTE 0.40.0 or higher and gnome-terminal 3.16 or higher
if ( gnome_terminal_id >= 4000 )
decscusr_support = true;
}
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_24 (char current_termtype[])
{
// Terminal ID 24 - DEC VT320
char* new_termtype = current_termtype;
#if defined(__NetBSD__) || defined(__OpenBSD__)
if ( secondary_da.terminal_id_version == 20 && FTerm::isWSConsConsole() )
{
// NetBSD/OpenBSD workstation console
if ( std::strncmp(termtype, C_STR("wsvt25"), 6) == 0 )
terminal_type.netbsd_con = true;
else if ( std::strncmp(termtype, C_STR("vt220"), 5) == 0 )
{
terminal_type.openbsd_con = true;
new_termtype = C_STR("pccon");
}
}
#endif
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_32 (char[])
{
// Terminal ID 32 - Tera Term
char* new_termtype;
terminal_type.tera_term = true;
new_termtype = C_STR("teraterm");
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_77 (char[])
{
// Terminal ID 77 - mintty
char* new_termtype;
terminal_type.mintty = true;
new_termtype = C_STR("xterm-256color");
std::fflush(stdout);
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_82 (char current_termtype[])
{
// Terminal ID 82 - rxvt
char* new_termtype = current_termtype;
terminal_type.rxvt = true;
if ( std::strncmp(termtype, "rxvt-", 5) != 0
&& std::strncmp(termtype, "rxvt-cygwin-native", 18) == 0 )
new_termtype = C_STR("rxvt-16color");
else
new_termtype = termtype;
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_83 (char current_termtype[])
{
// Terminal ID 83 - screen
char* new_termtype = current_termtype;
terminal_type.screen = true;
return new_termtype;
}
//----------------------------------------------------------------------
inline char* FTermDetection::secDA_Analysis_85 (char current_termtype[])
{
// Terminal ID 85 - rxvt-unicode
char* new_termtype = current_termtype;
terminal_type.rxvt = true;
terminal_type.urxvt = true;
if ( std::strncmp(termtype, "rxvt-", 5) != 0 )
{
if ( color256 )
new_termtype = C_STR("rxvt-256color");
else
new_termtype = C_STR("rxvt");
}
else
new_termtype = termtype;
return new_termtype;
}

223
src/ftermios.cpp Normal file
View File

@ -0,0 +1,223 @@
/***********************************************************************
* ftermios.cpp - Provides access to POSIX tty I/O control *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2018 Markus Gans *
* *
* 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/>. *
***********************************************************************/
#include "final/ftermios.h"
// static class attributes
int FTermios::stdin_no;
int FTermios::stdout_no;
bool FTermios::raw_mode;
termios FTermios::term_init;
//----------------------------------------------------------------------
// class FTermios
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
FTermios::FTermios()
{
init();
}
//----------------------------------------------------------------------
FTermios::~FTermios() // destructor
{ }
// public methods of FTermios
//----------------------------------------------------------------------
void FTermios::init()
{
// Assertion: programm start in cooked mode
raw_mode = false;
// Get file descriptor for standard input and standard output
stdin_no = fileno(stdin);
stdout_no = fileno(stdout);
}
//----------------------------------------------------------------------
termios FTermios::getTTY()
{
struct termios t;
tcgetattr (stdin_no, &t);
return t;
}
//----------------------------------------------------------------------
void FTermios::setTTY (const termios& t)
{
tcsetattr (stdin_no, TCSADRAIN, &t);
}
//----------------------------------------------------------------------
void FTermios::storeTTYsettings()
{
// Store termios settings
term_init = getTTY();
}
//----------------------------------------------------------------------
void FTermios::restoreTTYsettings()
{
// Restore termios settings
setTTY (term_init);
}
//----------------------------------------------------------------------
void FTermios::setHardwareEcho()
{
// Info under: man 3 termios
struct termios t;
tcgetattr (stdin_no, &t);
// local mode
t.c_lflag &= uInt(ECHO | ECHONL);
// input mode
t.c_iflag &= uInt(ICRNL | INLCR | IGNCR);
// output mode
t.c_oflag &= uInt(ONLCR);
// set the new termios settings
setTTY (t);
}
//----------------------------------------------------------------------
void FTermios::unsetHardwareEcho()
{
// Info under: man 3 termios
struct termios t;
tcgetattr (stdin_no, &t);
// local mode
t.c_lflag &= uInt(~(ECHO | ECHONL));
// input mode
t.c_iflag &= uInt(~(ICRNL | INLCR | IGNCR));
// output mode
t.c_oflag &= uInt(~ONLCR);
// set the new termios settings
setTTY (t);
}
//----------------------------------------------------------------------
void FTermios::setCaptureSendCharacters()
{
struct termios t;
tcgetattr (stdin_no, &t);
t.c_lflag &= uInt(~(ICANON | ECHO));
t.c_cc[VTIME] = 1; // Timeout in deciseconds
t.c_cc[VMIN] = 0; // Minimum number of characters
tcsetattr (stdin_no, TCSANOW, &t);
}
//----------------------------------------------------------------------
void FTermios::unsetCaptureSendCharacters()
{
struct termios t;
tcgetattr (stdin_no, &t);
t.c_lflag |= uInt(ICANON | ECHO);
t.c_cc[VTIME] = 0; // Timeout in deciseconds
t.c_cc[VMIN] = 1; // Minimum number of characters
setTTY (t);
}
//----------------------------------------------------------------------
bool FTermios::setRawMode (bool on)
{
// set + unset flags for raw mode
if ( on == raw_mode )
return raw_mode;
// Info under: man 3 termios
struct termios t;
tcgetattr (stdin_no, &t);
if ( on )
{
// local mode
#if DEBUG
// Exit with ctrl-c only if compiled with "DEBUG" option
t.c_lflag &= uInt(~(ICANON | IEXTEN));
#else
t.c_lflag &= uInt(~(ICANON | ISIG | IEXTEN));
#endif
// input mode
t.c_iflag &= uInt(~(IXON | BRKINT | PARMRK));
// defines the terminal special characters for noncanonical read
t.c_cc[VTIME] = 0; // Timeout in deciseconds
t.c_cc[VMIN] = 1; // Minimum number of characters
// set the new termios settings
setTTY (t);
raw_mode = true;
}
else
{
// local mode
t.c_lflag |= uInt(ISIG | ICANON | (term_init.c_lflag & IEXTEN));
// input mode
t.c_iflag |= uInt(IXON | BRKINT | PARMRK);
// set the new termios settings
setTTY (t);
raw_mode = false;
}
return raw_mode;
}
//----------------------------------------------------------------------
uInt FTermios::getBaudRate()
{
std::map<speed_t,uInt> outspeed;
outspeed[B0] = 0; // hang up
outspeed[B50] = 50; // 50 baud
outspeed[B75] = 75; // 75 baud
outspeed[B110] = 110; // 110 baud
outspeed[B134] = 134; // 134.5 baud
outspeed[B150] = 150; // 150 baud
outspeed[B200] = 200; // 200 baud
outspeed[B300] = 300; // 300 baud
outspeed[B600] = 600; // 600 baud
outspeed[B1200] = 1200; // 1,200 baud
outspeed[B1800] = 1800; // 1,800 baud
outspeed[B2400] = 2400; // 2,400 baud
outspeed[B4800] = 4800; // 4,800 baud
outspeed[B9600] = 9600; // 9,600 baud
outspeed[B19200] = 19200; // 19,200 baud
outspeed[B38400] = 38400; // 38,400 baud
outspeed[B57600] = 57600; // 57,600 baud
outspeed[B115200] = 115200; // 115,200 baud
outspeed[B230400] = 230400; // 230,400 baud
return outspeed[cfgetospeed(&term_init)];
}