mirror of
https://github.com/fltk/fltk.git
synced 2026-05-28 11:25:22 +08:00
Improve handling of malformed ANSI. (#950)
This commit is contained in:
+15
-4
@@ -852,6 +852,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
Fl_Scrollbar *hscrollbar; // horizontal scrollbar
|
Fl_Scrollbar *hscrollbar; // horizontal scrollbar
|
||||||
private:
|
private:
|
||||||
|
// Special utf8 symbols
|
||||||
|
const char *error_char_; // utf8 string shown for invalid utf8, bad ANSI, etc
|
||||||
bool fontsize_defer_; // flag defers font calcs until first draw() (issue 837)
|
bool fontsize_defer_; // flag defers font calcs until first draw() (issue 837)
|
||||||
int scrollbar_size_; // local preference for scrollbar size
|
int scrollbar_size_; // local preference for scrollbar size
|
||||||
ScrollbarStyle hscrollbar_style_;
|
ScrollbarStyle hscrollbar_style_;
|
||||||
@@ -897,7 +899,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void create_ring(int drows, int dcols, int hrows);
|
void create_ring(int drows, int dcols, int hrows);
|
||||||
void init_(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist,bool fontsize_defer);
|
void init_(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist,bool fontsize_defer);
|
||||||
private:
|
|
||||||
// Tabstops
|
// Tabstops
|
||||||
void init_tabstops(int newsize);
|
void init_tabstops(int newsize);
|
||||||
void default_tabstops(void);
|
void default_tabstops(void);
|
||||||
@@ -999,6 +1000,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void handle_lf(void);
|
void handle_lf(void);
|
||||||
void handle_cr(void);
|
void handle_cr(void);
|
||||||
|
void handle_esc(void);
|
||||||
// Printing
|
// Printing
|
||||||
void handle_ctrl(char c);
|
void handle_ctrl(char c);
|
||||||
bool is_printable(char c);
|
bool is_printable(char c);
|
||||||
@@ -1168,11 +1170,20 @@ private:
|
|||||||
public:
|
public:
|
||||||
float redraw_rate(void) const;
|
float redraw_rate(void) const;
|
||||||
void redraw_rate(float val);
|
void redraw_rate(float val);
|
||||||
// API: Show unknown/unprintable chars
|
// API: Show unknown/invalid utf8/ANSI sequences with an error character (¿).
|
||||||
bool show_unknown(void) const;
|
bool show_unknown(void) const;
|
||||||
void show_unknown(bool val);
|
void show_unknown(bool val);
|
||||||
protected:
|
|
||||||
static const char *unknown_char; ///< "unknown" replacement character
|
/** Sets the "error character" utf8 string shown for invalid utf8
|
||||||
|
or bad ANSI sequences if show_unknown() is true. Default: "¿".
|
||||||
|
\See show_unknown(bool)
|
||||||
|
*/
|
||||||
|
void error_char(const char* val) { error_char_ = val; }
|
||||||
|
|
||||||
|
/** Returns the "error character" utf8 string, which is shown for invalid utf8
|
||||||
|
or bad ANSI sequences if show_unknown() is true. \See show_unknown(bool)
|
||||||
|
*/
|
||||||
|
const char* error_char(void) const { return error_char_; }
|
||||||
public:
|
public:
|
||||||
// API: ANSI sequences
|
// API: ANSI sequences
|
||||||
bool ansi(void) const;
|
bool ansi(void) const;
|
||||||
|
|||||||
+30
-22
@@ -37,12 +37,6 @@
|
|||||||
#include <FL/fl_string_functions.h>
|
#include <FL/fl_string_functions.h>
|
||||||
#include "Fl_String.H"
|
#include "Fl_String.H"
|
||||||
|
|
||||||
/////////////////////////////////
|
|
||||||
////// Static Class Data ////////
|
|
||||||
/////////////////////////////////
|
|
||||||
|
|
||||||
const char *Fl_Terminal::unknown_char = "¿";
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
////// Static Functions /////////
|
////// Static Functions /////////
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
@@ -181,6 +175,7 @@ bool Fl_Terminal::Selection::get_selection(int &srow,int &scol,
|
|||||||
// Always returns true.
|
// Always returns true.
|
||||||
//
|
//
|
||||||
bool Fl_Terminal::Selection::start(int row, int col, bool char_right) {
|
bool Fl_Terminal::Selection::start(int row, int col, bool char_right) {
|
||||||
|
(void) char_right; // silence warning
|
||||||
srow_ = erow_ = row;
|
srow_ = erow_ = row;
|
||||||
scol_ = ecol_ = col;
|
scol_ = ecol_ = col;
|
||||||
state_ = 1; // state: "started selection"
|
state_ = 1; // state: "started selection"
|
||||||
@@ -2558,6 +2553,16 @@ void Fl_Terminal::handle_lf(void) {
|
|||||||
else cursor_down(1, do_scroll);
|
else cursor_down(1, do_scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle '\e' escape character.
|
||||||
|
void Fl_Terminal::handle_esc(void) {
|
||||||
|
if (!ansi_) // not in ansi mode?
|
||||||
|
{ handle_unknown_char(); return; } // ..show unknown char, early exit
|
||||||
|
if (escseq.esc_mode() == 0x1b) // already in esc mode?
|
||||||
|
{ handle_unknown_char(); } // ..show 1st esc as unknown char, parse 2nd
|
||||||
|
if (escseq.parse(0x1b) == EscapeSeq::fail) // parse esc
|
||||||
|
{ handle_unknown_char(); return; } // ..error? show unknown char
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the combined output translation flags to \p val.
|
Sets the combined output translation flags to \p val.
|
||||||
|
|
||||||
@@ -2599,9 +2604,7 @@ void Fl_Terminal::handle_ctrl(char c) {
|
|||||||
case '\r': handle_cr(); return; // CR?
|
case '\r': handle_cr(); return; // CR?
|
||||||
case '\n': handle_lf(); return; // LF?
|
case '\n': handle_lf(); return; // LF?
|
||||||
case '\t': cursor_tab_right(); return; // TAB?
|
case '\t': cursor_tab_right(); return; // TAB?
|
||||||
case 0x1b: if (ansi_) escseq.parse(c); // ESC?
|
case 0x1b: handle_esc(); return; // ESC?
|
||||||
else append_utf8("␛");
|
|
||||||
return;
|
|
||||||
default: handle_unknown_char(); return; // Unknown ctrl char?
|
default: handle_unknown_char(); return; // Unknown ctrl char?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2731,12 +2734,16 @@ void Fl_Terminal::handle_escseq(char c) {
|
|||||||
// NOTE: Use xterm to test. gnome-terminal has bugs, even in 2022.
|
// NOTE: Use xterm to test. gnome-terminal has bugs, even in 2022.
|
||||||
const bool do_scroll = true;
|
const bool do_scroll = true;
|
||||||
const bool no_scroll = false;
|
const bool no_scroll = false;
|
||||||
//UNUSED const bool do_wrap = true;
|
|
||||||
//UNUSED const bool no_wrap = false;
|
|
||||||
switch (escseq.parse(c)) { // parse char, advance s..
|
switch (escseq.parse(c)) { // parse char, advance s..
|
||||||
case EscapeSeq::fail: escseq.reset(); return; // failed? reset, done
|
case EscapeSeq::fail: // failed?
|
||||||
case EscapeSeq::success: return; // keep parsing..
|
escseq.reset(); // ..reset to let error_char be visible
|
||||||
case EscapeSeq::completed: break; // parsed complete esc sequence?
|
handle_unknown_char(); // ..show error char (if enabled)
|
||||||
|
print_char(c); // ..show char we couldn't handle
|
||||||
|
return; // ..done.
|
||||||
|
case EscapeSeq::success: // success?
|
||||||
|
return; // ..keep parsing
|
||||||
|
case EscapeSeq::completed: // parsed complete esc sequence?
|
||||||
|
break; // ..fall through to handle operation
|
||||||
}
|
}
|
||||||
// Shortcut varnames for escseq parsing..
|
// Shortcut varnames for escseq parsing..
|
||||||
EscapeSeq &esc = escseq;
|
EscapeSeq &esc = escseq;
|
||||||
@@ -3254,7 +3261,7 @@ void Fl_Terminal::append(const char *s, int len/*=-1*/) {
|
|||||||
int Fl_Terminal::handle_unknown_char(void) {
|
int Fl_Terminal::handle_unknown_char(void) {
|
||||||
if (!show_unknown_) return 0;
|
if (!show_unknown_) return 0;
|
||||||
escseq.reset(); // disable any pending esc seq to prevent eating unknown char
|
escseq.reset(); // disable any pending esc seq to prevent eating unknown char
|
||||||
print_char(unknown_char);
|
print_char(error_char_);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3270,9 +3277,9 @@ int Fl_Terminal::handle_unknown_char(void) {
|
|||||||
*/
|
*/
|
||||||
int Fl_Terminal::handle_unknown_char(int drow, int dcol) {
|
int Fl_Terminal::handle_unknown_char(int drow, int dcol) {
|
||||||
if (!show_unknown_) return 0;
|
if (!show_unknown_) return 0;
|
||||||
int len = (int)strlen(unknown_char);
|
int len = (int)strlen(error_char_);
|
||||||
Utf8Char *u8c = u8c_disp_row(drow) + dcol;
|
Utf8Char *u8c = u8c_disp_row(drow) + dcol;
|
||||||
u8c->text_utf8(unknown_char, len, *current_style_);
|
u8c->text_utf8(error_char_, len, *current_style_);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3384,6 +3391,7 @@ Fl_Terminal::Fl_Terminal(int X,int Y,int W,int H,const char*L,int rows,int cols,
|
|||||||
|
|
||||||
// Private constructor method
|
// Private constructor method
|
||||||
void Fl_Terminal::init_(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist,bool fontsize_defer) {
|
void Fl_Terminal::init_(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist,bool fontsize_defer) {
|
||||||
|
error_char_ = "¿";
|
||||||
scrollbar = hscrollbar = 0; // avoid problems w/update_screen_xywh()
|
scrollbar = hscrollbar = 0; // avoid problems w/update_screen_xywh()
|
||||||
// currently unused params
|
// currently unused params
|
||||||
(void)X; (void)Y; (void)W; (void)H; (void)L;
|
(void)X; (void)Y; (void)W; (void)H; (void)L;
|
||||||
@@ -4039,7 +4047,7 @@ void Fl_Terminal::redraw_rate(float val) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Return the "show unknown" flag.
|
Return the "show unknown" flag.
|
||||||
See show_unknown(bool) for more info.
|
\See show_unknown(bool), error_char(const char*).
|
||||||
*/
|
*/
|
||||||
bool Fl_Terminal::show_unknown(void) const {
|
bool Fl_Terminal::show_unknown(void) const {
|
||||||
return show_unknown_;
|
return show_unknown_;
|
||||||
@@ -4048,12 +4056,12 @@ bool Fl_Terminal::show_unknown(void) const {
|
|||||||
/**
|
/**
|
||||||
Set the "show unknown" flag.
|
Set the "show unknown" flag.
|
||||||
|
|
||||||
If true, unknown escape sequences and unprintable control characters
|
If true, invalid utf8 and invalid ANSI sequences will be shown
|
||||||
will be shown with the error character "¿".
|
with the error character "¿".
|
||||||
|
|
||||||
If false, those sequences and characters will be ignored.
|
If false, errors characters won't be shown.
|
||||||
|
|
||||||
\see handle_unknown_char()
|
\see handle_unknown_char(), error_char(const char*).
|
||||||
*/
|
*/
|
||||||
void Fl_Terminal::show_unknown(bool val) {
|
void Fl_Terminal::show_unknown(bool val) {
|
||||||
show_unknown_ = val;
|
show_unknown_ = val;
|
||||||
|
|||||||
Reference in New Issue
Block a user