mirror of https://github.com/fltk/fltk
1014 lines
44 KiB
C++
1014 lines
44 KiB
C++
|
//
|
||
|
// Fl_Terminal.cxx - A terminal widget for Fast Light Tool Kit (FLTK).
|
||
|
//
|
||
|
// Copyright 2022 by Greg Ercolano.
|
||
|
// Copyright 2023 by Bill Spitzak and others.
|
||
|
//
|
||
|
// This library is free software. Distribution and use rights are outlined in
|
||
|
// the file "COPYING" which should have been included with this file. If this
|
||
|
// file is missing or damaged, see the license at:
|
||
|
//
|
||
|
// https://www.fltk.org/COPYING.php
|
||
|
//
|
||
|
// Please see the following page on how to report bugs and issues:
|
||
|
//
|
||
|
// https://www.fltk.org/bugs.php
|
||
|
//
|
||
|
|
||
|
/** \file
|
||
|
Fl_Terminal widget.
|
||
|
*/
|
||
|
|
||
|
#ifndef Fl_Terminal_H
|
||
|
#define Fl_Terminal_H
|
||
|
|
||
|
#include <FL/Fl.H>
|
||
|
#include <FL/Fl_Window.H>
|
||
|
#include <FL/Fl_Group.H>
|
||
|
#include <FL/Fl_Scrollbar.H>
|
||
|
#include <FL/Fl_Rect.H>
|
||
|
|
||
|
/** \class Fl_Terminal
|
||
|
|
||
|
\brief Terminal widget supporting Unicode/utf-8, ANSI/xterm escape codes with full RGB color control.
|
||
|
|
||
|
\section Fl_Terminal
|
||
|
|
||
|
\image html Fl_Terminal-demo.png "Fl_Terminal widget showing a linux manual page"
|
||
|
\image latex Fl_Terminal-demo.png "Fl_Terminal widget showing a linux manual page" width=6cm
|
||
|
|
||
|
Fl_Terminal is an output-only text widget supporting ASCII and UTF-8/Unicode.
|
||
|
It supports most terminal text features, such as most VT100/xterm style escape sequences
|
||
|
(see \ref Fl_Terminal_escape_codes), text colors/attributes, scrollback history, mouse selection, etc.
|
||
|
|
||
|
It is recommended that accessing features such as setting text colors and cursor positioning
|
||
|
is best done with ANSI/XTERM escape sequences. But if one sets ansi(false) then this is
|
||
|
not possible. Many commonly used API functions are public, such as textfgcolor() for setting
|
||
|
text colors. Others, such as cursor_up() are protected to prevent common misuse, and are
|
||
|
available only to subclasses.
|
||
|
|
||
|
For applications that need input support, the widget can be subclassed to provide
|
||
|
keyboard input, and advanced features like pseudo ttys, termio, serial port I/O, etc.,
|
||
|
as such features are beyond the scope of FLTK.
|
||
|
|
||
|
\subsection Fl_Terminal_Examples Examples
|
||
|
|
||
|
\par
|
||
|
\code
|
||
|
//
|
||
|
// Fl_Terminal: Simple Use
|
||
|
//
|
||
|
Fl_Terminal *tty = new Fl_Terminal(...);
|
||
|
:
|
||
|
tty->append("Hello world.\n"); // simple strings
|
||
|
tty->append("\033[31mThis text is red.\033[0m\n"); // colored text
|
||
|
tty->append("\033[32mThis text is green.\033[0m\n");
|
||
|
tty->printf("The value of x is %.02f\n", x); // printf() formatting
|
||
|
\endcode
|
||
|
\par
|
||
|
There are also public methods for doing what most "\033[" escape codes do,
|
||
|
so that if ansi(bool) is set to "false", one can still change text colors
|
||
|
or clear the screen via application control, e.g.
|
||
|
\par
|
||
|
\code
|
||
|
tty->home(); // home the cursor
|
||
|
tty->clear_screen(); // clear the screen
|
||
|
tty->textfgcolor(0xff000000); // change the text color to RED
|
||
|
tty->textbgcolor(0x0000ff00); // change the background color to BLUE
|
||
|
// ├┘├┘├┘
|
||
|
// R G B
|
||
|
\endcode
|
||
|
\par
|
||
|
When creating the widget, the width/height determine the default column
|
||
|
and row count for the terminal's display based on the current font size.
|
||
|
The column width determines where text will wrap.
|
||
|
\par
|
||
|
You can specify wider column sizes than the screen using
|
||
|
display_columns(colwidth). When this value is larger than
|
||
|
the widget's width, text will wrap off-screen, and can be revealed by
|
||
|
resizing the widget wider.
|
||
|
|
||
|
\subsection Fl_Terminal_Writing Writing To Terminal From Applications
|
||
|
|
||
|
\par
|
||
|
An application needing terminal output as part of its user interface
|
||
|
can instance Fl_Terminal, and write text strings with:
|
||
|
\par
|
||
|
- append() to append strings
|
||
|
- printf() to append formatted strings
|
||
|
\par
|
||
|
Single character output can be done with:
|
||
|
\par
|
||
|
- print_char() to print a single ASCII/UTF-8 char at the cursor
|
||
|
- putchar() to put single ASCII/UTF-8 char at an x,y position
|
||
|
\par
|
||
|
|
||
|
\subsection Fl_Terminal_Attributes Text Attributes
|
||
|
\par
|
||
|
The terminal's text supports these attributes:
|
||
|
\par
|
||
|
- Italic - italicized text: <TT>\\033[3m</TT>
|
||
|
- Bold - brighter/thicker text: <TT>\\033[1m</TT>
|
||
|
- Dim - lower brightness text: <TT>\\033[2m</TT>
|
||
|
- Underline - text that is underlined: <TT>\\033[4m</TT>
|
||
|
- Strikeout - text that has a line through the text: <TT>\\033[9m</TT>
|
||
|
- Inverse - text whose background and foreground colors are swapped: <TT>\\033[7m</TT>
|
||
|
- Normal - normal text: <TT>\\033[0m</TT>
|
||
|
\par
|
||
|
\image html Fl_Terminal-utf8-demo.png "Fl_Terminal screen"
|
||
|
\image latex Fl_Terminal-utf8-demo.png "Fl_Terminal screen" width=6cm
|
||
|
|
||
|
\subsection Fl_Terminal_Colors Text and Background Colors
|
||
|
|
||
|
\par
|
||
|
There's at least two ways to specify colors for text and background colors:
|
||
|
\par
|
||
|
- 3 bit / 8 Color Values
|
||
|
- Full 24 bit R/G/B colors
|
||
|
\par
|
||
|
Example of 3 bit colors:
|
||
|
\image html Fl_Terminal-3bit-colors.png "Fl_Terminal 3 bit colors"
|
||
|
\image latex Fl_Terminal-3bit-colors.png "Fl_Terminal 3 bit colors" width=6cm
|
||
|
\par
|
||
|
Example application source code using 3 bit colors:
|
||
|
\code
|
||
|
//
|
||
|
// Text colors
|
||
|
//
|
||
|
tty->append("\033[31m Red text.\033[0m\n"); // Print red text..
|
||
|
tty->append("\033[32m Green text.\033[0m\n");
|
||
|
:
|
||
|
tty->append("\033[36m Cyan text.\033[0m\n");
|
||
|
tty->append("\033[37m White text.\033[0m\n");
|
||
|
//
|
||
|
// Background colors
|
||
|
//
|
||
|
tty->append("\033[41m Red Background.\033[0m\n"); // background will be red
|
||
|
tty->append("\033[42m Green Background.\033[0m\n");
|
||
|
:
|
||
|
tty->append("\033[46m Cyan Background.\033[0m\n");
|
||
|
tty->append("\033[47m White Background.\033[0m\n");
|
||
|
\endcode
|
||
|
\par
|
||
|
Example of 24 bit colors:
|
||
|
\image html Fl_Terminal-24bit-colors.png "Fl_Terminal 24 bit colors"
|
||
|
\image latex Fl_Terminal-24bit-colors.png "Fl_Terminal 24 bit colors" width=6cm
|
||
|
\par
|
||
|
Example application source code using 24 bit colors:
|
||
|
\code
|
||
|
//
|
||
|
// 24 bit Text Color
|
||
|
//
|
||
|
tty->append("\033[38;2;0;0;255m Text is BLUE.\033[0m\n"); // RGB: R=0, G=0, B=255
|
||
|
tty->append("\033[38;2;255;0;0m Text is RED.\033[0m\n"); // RGB: R=255, G=0, B=0
|
||
|
tty->append("\033[38;2;127;64;0m Text is DARK ORANGE.\033[0m\n"); // RGB: R=127, G=64, B=0
|
||
|
//
|
||
|
// 24 bit Background Color
|
||
|
//
|
||
|
tty->append("\033[48;2;0;0;255m Background is BLUE.\033[0m\n"); // RGB: R=0, G=0, B=255
|
||
|
tty->append("\033[48;2;255;0;0m Background is RED.\033[0m\n"); // RGB: R=255, G=0, B=0
|
||
|
tty->append("\033[48;2;127;64;0m Background is DARK ORANGE.\033[0m\n"); // RGB: R=127, G=64, B=0
|
||
|
\endcode
|
||
|
\par
|
||
|
For more on the ANSI escape codes, see \ref Fl_Terminal_escape_codes.
|
||
|
|
||
|
\subsection Fl_Terminal_Features Features
|
||
|
|
||
|
\par
|
||
|
Most standard terminal behaviors are supported, e.g.
|
||
|
\par
|
||
|
- ASCII + UTF-8/Unicode
|
||
|
- scrollback history management
|
||
|
- mouse selection + copy/paste (^C, ^A)
|
||
|
- autoscroll during selection
|
||
|
\par
|
||
|
Most popular ANSI/DEC VT100/Xterm escape sequences are supported (see \ref Fl_Terminal_escape_codes), including:
|
||
|
- per-character colors for text and background
|
||
|
- per-character text attributes: bold/dim, underline, strikeout
|
||
|
- scrolling up/down
|
||
|
- character insert/delete for characters/rows/screen
|
||
|
- clearing characters/rows/screen
|
||
|
\par
|
||
|
Does not (yet) support:
|
||
|
- programmable regions (scroll regions and attribute blocks)
|
||
|
- dynamic line wrap (where resizing display dynamically re-wraps long lines)
|
||
|
\par
|
||
|
Will likely never implement as part of this widget:
|
||
|
- pty/termio management (such features should be _subclassed_)
|
||
|
- Different per-character font family + sizes (font family/size is global only)
|
||
|
- variable width fonts
|
||
|
\par
|
||
|
Regarding the font family+size; the way the terminal is currently designed,
|
||
|
the font family and size must not vary within text; rows have to be consistent
|
||
|
height. Varying widths are tricky too, esp. when it comes to moving the cursor
|
||
|
up/down within a column; varying *widths* are supported (due to Unicode characters
|
||
|
sometimes being "wide", but not heights.
|
||
|
|
||
|
\subsection Fl_Terminal_Margins Margins
|
||
|
|
||
|
\par
|
||
|
The margins define the amount of space (in pixels) around the outside of the
|
||
|
text display area, the space between the widget's inner edge (inside the box())
|
||
|
and the text display area's outer edge. The margins can be inspected and changed
|
||
|
with the margin_left(), margin_right(), margin_top() and margin_bottom() methods.
|
||
|
\par
|
||
|
\code
|
||
|
·
|
||
|
TERMINAL WIDGET (Fl_Terminal)
|
||
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━┓
|
||
|
┃ ↑ margin_top ┃ ┃
|
||
|
┃ TEXT DISPLAY AREA ↓ ┃ ┃
|
||
|
┃ ┌──────────────────────────────────────────────────────┐ ┃ ┃
|
||
|
┃ │ ↑ │ ┃ S ┃
|
||
|
┃ │ │ │ ┃ c ┃
|
||
|
┃ │ display_rows │ ┃ r ┃
|
||
|
┃ │ │ │ ┃ o ┃
|
||
|
┃ │ │ │ ┃ l ┃
|
||
|
┃ │ │ │ ┃ l ┃
|
||
|
┃ │◄───display_columns────────┼─────────────────────────►│ ┃ ┃
|
||
|
┃ │ │ │ ┃ B ┃
|
||
|
┃ │ │ │ ┃ a ┃
|
||
|
┃ │ │ │ ┃ r ┃
|
||
|
┃ │ │ │ ┃ ┃
|
||
|
┃ │ │ │ ┃ ┃
|
||
|
┃◄──┬──►│ ↓ │◄──┬──►┃ ┃
|
||
|
┃ │ └──────────────────────────────────────────────────────┘ │ ┃ ┃
|
||
|
┃ margin_left ↑ margin_right ┃ ┃
|
||
|
┃ ↓ margin_bottom ┃ ┃
|
||
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━┛
|
||
|
Fl_Terminal Margins
|
||
|
·
|
||
|
\endcode
|
||
|
|
||
|
\subsection Fl_Terminal_Caveats Caveats
|
||
|
|
||
|
\par
|
||
|
- This widget is not a full terminal emulator; it does not do stdio redirection,
|
||
|
pseudo ttys/termios/character cooking, keyboard input processing, full
|
||
|
curses(3) support. However, such features CAN be implemented with subclassing.
|
||
|
\par
|
||
|
- The printf() and vprintf() functions are limited to strings no longer than
|
||
|
1024 characters (including NULL). For printing longer strings, use append()
|
||
|
which has no string limits.
|
||
|
**/
|
||
|
|
||
|
class Fl_Terminal : public Fl_Group {
|
||
|
public:
|
||
|
//////////////////////////////////////
|
||
|
////// Fl_Terminal Public Enums //////
|
||
|
//////////////////////////////////////
|
||
|
|
||
|
/**
|
||
|
\enum RedrawStyle
|
||
|
Determines when Fl_Terminal calls redraw() if new text is added.
|
||
|
RATE_LIMITED is the recommended setting, using redraw_rate(float) to determine
|
||
|
the maximum rate of redraws.
|
||
|
\see redraw_style(), redraw_rate()
|
||
|
*/
|
||
|
enum RedrawStyle {
|
||
|
NO_REDRAW=0, ///< app must call redraw() as needed to update text to screen
|
||
|
RATE_LIMITED, ///< timer controlled redraws. (DEFAULT)
|
||
|
PER_WRITE ///< redraw triggered after *every* append() / printf() / etc. operation
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
\enum Attrib
|
||
|
Bits for the per-character attributes, which control text features
|
||
|
such as italic, bold, underlined text, etc.
|
||
|
|
||
|
NOTE: enum names with a leading underbar must not be used, and are
|
||
|
reserved for future use.
|
||
|
*/
|
||
|
enum Attrib {
|
||
|
NORMAL = 0x00, ///< all attributes off
|
||
|
BOLD = 0x01, ///< bold text: uses bold font, color brighter than normal
|
||
|
DIM = 0x02, ///< dim text; color slightly darker than normal
|
||
|
ITALIC = 0x04, ///< italic font text
|
||
|
UNDERLINE = 0x08, ///< underlined text
|
||
|
_RESERVED_1 = 0x10, ///< <EM>(reserved for internal future use)</EM>
|
||
|
INVERSE = 0x20, ///< inverse text; fg/bg color are swapped
|
||
|
_RESERVED_2 = 0x40, ///< <EM>(reserved for internal future use)</EM>
|
||
|
STRIKEOUT = 0x80 ///< strikeout text
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
\enum CharFlags
|
||
|
Per-character 8 bit flags (uchar) used to manage special states for characters.
|
||
|
*/
|
||
|
enum CharFlags {
|
||
|
FG_XTERM = 0x01, ///< this char's fg color is an XTERM color; can be affected by Dim+Bold
|
||
|
BG_XTERM = 0x02, ///< this char's bg color is an XTERM color; can be affected by Dim+Bold
|
||
|
EOL = 0x04, ///< this char at end of line, used for line wrap during screen resizing
|
||
|
RESV_A = 0x08,
|
||
|
RESV_B = 0x10,
|
||
|
RESV_C = 0x20,
|
||
|
RESV_D = 0x40,
|
||
|
RESV_E = 0x80,
|
||
|
COLORMASK = (FG_XTERM | BG_XTERM)
|
||
|
};
|
||
|
|
||
|
protected:
|
||
|
// Margin Class ////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage the terminal's margins
|
||
|
//
|
||
|
class Margin {
|
||
|
int left_, right_, top_, bottom_;
|
||
|
public:
|
||
|
Margin(void) { left_ = right_ = top_ = bottom_ = 3; }
|
||
|
int left(void) const { return left_; }
|
||
|
int right(void) const { return right_; }
|
||
|
int top(void) const { return top_; }
|
||
|
int bottom(void) const { return bottom_; }
|
||
|
void left(int val) { left_ = val; }
|
||
|
void right(int val) { right_ = val; }
|
||
|
void top(int val) { top_ = val; }
|
||
|
void bottom(int val) { bottom_ = val; }
|
||
|
};
|
||
|
|
||
|
// CharStyle Class ////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage the terminal's character style
|
||
|
// This includes the font, color, and some cached internal
|
||
|
// info for optimized drawing speed.
|
||
|
//
|
||
|
class CharStyle {
|
||
|
uchar attrib_; // bold, underline..
|
||
|
uchar flags_; // CharFlags
|
||
|
Fl_Color fgcolor_; // foreground color for text
|
||
|
Fl_Color bgcolor_; // background color for text
|
||
|
Fl_Color defaultfgcolor_; // default fg color used by ESC[0m
|
||
|
Fl_Color defaultbgcolor_; // default bg color used by ESC[0m
|
||
|
Fl_Font fontface_; // font face
|
||
|
Fl_Fontsize fontsize_; // font size
|
||
|
int fontheight_; // font height (in pixels)
|
||
|
int fontdescent_; // font descent (pixels below font baseline)
|
||
|
int charwidth_; // width of a fixed width ASCII character
|
||
|
public:
|
||
|
CharStyle(void);
|
||
|
Fl_Color fgcolor(void) const;
|
||
|
Fl_Color bgcolor(void) const;
|
||
|
Fl_Color defaultfgcolor(void) const { return defaultfgcolor_; }
|
||
|
Fl_Color defaultbgcolor(void) const { return defaultbgcolor_; }
|
||
|
uchar attrib(void) const { return attrib_; }
|
||
|
Fl_Font fontface(void) const { return fontface_; }
|
||
|
Fl_Fontsize fontsize(void) const { return fontsize_; }
|
||
|
int fontheight(void) const { return fontheight_; }
|
||
|
int fontdescent(void) const { return fontdescent_; }
|
||
|
int charwidth(void) const { return charwidth_; }
|
||
|
uchar colorbits_only(uchar inflags) const;
|
||
|
void attrib(uchar val) { attrib_ = val; }
|
||
|
void set_flag(uchar val) { flags_ |= val; }
|
||
|
void clr_flag(uchar val) { flags_ &= ~val; }
|
||
|
void fgcolor_uchar(uchar val);
|
||
|
void bgcolor_uchar(uchar val);
|
||
|
void fgcolor(int r,int g,int b) { fgcolor_ = (r<<24) | (g<<16) | (b<<8); clr_flag(FG_XTERM); }
|
||
|
void bgcolor(int r,int g,int b) { bgcolor_ = (r<<24) | (g<<16) | (b<<8); clr_flag(BG_XTERM); }
|
||
|
void fgcolor(Fl_Color val) { fgcolor_ = val; clr_flag(FG_XTERM); }
|
||
|
void bgcolor(Fl_Color val) { bgcolor_ = val; clr_flag(BG_XTERM); }
|
||
|
void defaultfgcolor(Fl_Color val) { defaultfgcolor_ = val; }
|
||
|
void defaultbgcolor(Fl_Color val) { defaultbgcolor_ = val; }
|
||
|
void fontface(Fl_Font val) { fontface_ = val; update(); }
|
||
|
void fontsize(Fl_Fontsize val) { fontsize_ = val; update(); }
|
||
|
void update(void);
|
||
|
// SGR MODES: Set Graphics Rendition
|
||
|
void sgr_reset(void) { // e.g. ESC[0m
|
||
|
attrib(Fl_Terminal::NORMAL);
|
||
|
fgcolor(defaultfgcolor_);
|
||
|
bgcolor(defaultbgcolor_);
|
||
|
}
|
||
|
int onoff(bool flag, Attrib a) { return (flag ? (attrib_ | a) : (attrib_ & ~a)); }
|
||
|
void sgr_bold(bool val) { attrib_ = onoff(val, Fl_Terminal::BOLD); } // e.g. ESC[1m
|
||
|
void sgr_dim(bool val) { attrib_ = onoff(val, Fl_Terminal::DIM); } // e.g. ESC[2m
|
||
|
void sgr_italic(bool val) { attrib_ = onoff(val, Fl_Terminal::ITALIC); } // e.g. ESC[3m
|
||
|
void sgr_underline(bool val) { attrib_ = onoff(val, Fl_Terminal::UNDERLINE); } // e.g. ESC[3m
|
||
|
void sgr_dbl_under(bool val) { attrib_ = onoff(val, Fl_Terminal::UNDERLINE); } // e.g. ESC[21m (TODO!)
|
||
|
void sgr_blink(bool val) { /* NOT IMPLEMENTED */ } // e.g. ESC[5m
|
||
|
void sgr_inverse(bool val) { attrib_ = onoff(val, Fl_Terminal::INVERSE); } // e.g. ESC[7m
|
||
|
void sgr_strike(bool val) { attrib_ = onoff(val, Fl_Terminal::STRIKEOUT); } // e.g. ESC[9m
|
||
|
};
|
||
|
|
||
|
protected:
|
||
|
// Cursor Class ///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage the terminal's cursor position, color, etc.
|
||
|
//
|
||
|
class Cursor {
|
||
|
int col_; // cursor's current col (x) position on display
|
||
|
int row_; // cursor's current row (y) position on display
|
||
|
int h_; // cursor's height (affected by font size)
|
||
|
Fl_Color fgcolor_; // cursor's fg color (color of text, if any)
|
||
|
Fl_Color bgcolor_; // cursor's bg color
|
||
|
public:
|
||
|
Cursor(void) {
|
||
|
col_ = 0;
|
||
|
row_ = 0;
|
||
|
h_ = 10;
|
||
|
fgcolor_ = 0xfffff000; // wht
|
||
|
bgcolor_ = 0x00d00000; // grn
|
||
|
}
|
||
|
int col(void) const { return col_; }
|
||
|
int row(void) const { return row_; }
|
||
|
int h(void) const { return h_; }
|
||
|
Fl_Color fgcolor(void) const { return fgcolor_; }
|
||
|
Fl_Color bgcolor(void) const { return bgcolor_; }
|
||
|
void col(int val) { col_ = val >= 0 ? val : 0; }
|
||
|
void row(int val) { row_ = val >= 0 ? val : 0; }
|
||
|
void h(int val) { h_ = val; }
|
||
|
void fgcolor(Fl_Color val) { fgcolor_ = val; }
|
||
|
void bgcolor(Fl_Color val) { bgcolor_ = val; }
|
||
|
int left(void) { col_ = (col_>0) ? (col_-1) : 0; return col_; }
|
||
|
int right(void) { return ++col_; }
|
||
|
int up(void) { row_ = (row_>0) ? (row_-1) : 0; return row_; }
|
||
|
int down(void) { return ++row_; }
|
||
|
bool is_rowcol(int drow,int dcol) const;
|
||
|
void scroll(int nrows);
|
||
|
void home(void) { row_ = 0; col_ = 0; }
|
||
|
};
|
||
|
|
||
|
// Utf8Char Class ///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage the terminal's individual UTF-8 characters.
|
||
|
// Includes fg/bg color, attributes (BOLD, UNDERLINE..)
|
||
|
//
|
||
|
class Utf8Char {
|
||
|
static const int max_utf8_ = 4; // RFC 3629 paraphrased: In UTF-8, chars are encoded with 1 to 4 octets
|
||
|
char text_[max_utf8_]; // memory for actual ASCII or UTF-8 byte contents
|
||
|
uchar len_; // length of bytes in text_[] buffer; 1 for ASCII, >1 for UTF-8
|
||
|
uchar attrib_; // attribute bits for this char (bold, underline..)
|
||
|
uchar flags_; // CharFlags bits
|
||
|
Fl_Color fgcolor_; // fltk fg color (supports 8color or 24bit color set w/ESC[37;<r>;<g>;<b>m)
|
||
|
Fl_Color bgcolor_; // fltk bg color (supports 8color or 24bit color set w/ESC[47;<r>;<g>;<b>m)
|
||
|
// Private methods
|
||
|
void text_utf8_(const char *text, int len);
|
||
|
public:
|
||
|
// Public methods
|
||
|
Utf8Char(void); // ctor
|
||
|
Utf8Char(const Utf8Char& o); // copy ctor
|
||
|
~Utf8Char(void); // dtor
|
||
|
Utf8Char& operator=(const Utf8Char& o); // assignment
|
||
|
inline int max_utf8() const { return max_utf8_; }
|
||
|
void text_utf8(const char *text, int len, const CharStyle& style);
|
||
|
void text_ascii(char c, const CharStyle& style);
|
||
|
void fl_font_set(const CharStyle& style) const;
|
||
|
|
||
|
// Return the UTF-8 text string for this character.
|
||
|
// Use length() to get number of bytes in string, which will be 1 for ASCII chars.
|
||
|
//
|
||
|
const char* text_utf8(void) const { return text_; }
|
||
|
// Return the attribute for this char
|
||
|
uchar attrib(void) const { return attrib_; }
|
||
|
uchar flags(void) const { return flags_; }
|
||
|
Fl_Color fgcolor(void) const;
|
||
|
Fl_Color bgcolor(void) const;
|
||
|
// Return the length of this character in bytes (UTF-8 can be multibyte..)
|
||
|
int length(void) const { return int(len_); }
|
||
|
double pwidth(void) const;
|
||
|
int pwidth_int(void) const;
|
||
|
// Clear the character to a 'space'
|
||
|
void clear(const CharStyle& style) { text_ascii(' ', style); }
|
||
|
bool is_char(char c) const { return *text_ == c; }
|
||
|
void show_char(void) const { ::printf("%.*s", len_, text_); }
|
||
|
void show_char_info(void) const { ::fprintf(stderr, "UTF-8('%.*s', len=%d)\n", len_, text_, len_); }
|
||
|
|
||
|
Fl_Color attr_color(Fl_Color col, const Fl_Widget *grp) const;
|
||
|
Fl_Color attr_fg_color(const Fl_Widget *grp) const;
|
||
|
Fl_Color attr_bg_color(const Fl_Widget *grp) const;
|
||
|
};
|
||
|
|
||
|
// RingBuffer Class ///////////////////////////////////////////////////
|
||
|
//
|
||
|
// Manages ring with indexed row/col and "history" vs. "display" concepts.
|
||
|
//
|
||
|
class RingBuffer {
|
||
|
Utf8Char *ring_chars_; // the ring UTF-8 char buffer
|
||
|
int ring_rows_; // #rows in ring total
|
||
|
int ring_cols_; // #columns in ring/hist/disp
|
||
|
int nchars_; // #chars in ring (ring_rows*ring_cols)
|
||
|
int hist_rows_; // #rows in history
|
||
|
int hist_use_; // #rows in use by history
|
||
|
int disp_rows_; // #rows in display
|
||
|
int offset_; // index offset (used for 'scrolling')
|
||
|
|
||
|
private:
|
||
|
void new_copy(int drows, int dcols, int hrows, const CharStyle& style);
|
||
|
//DEBUG void write_row(FILE *fp, Utf8Char *u8c, int cols) const {
|
||
|
//DEBUG cols = (cols != 0) ? cols : ring_cols();
|
||
|
//DEBUG for ( int col=0; col<cols; col++, u8c++ ) {
|
||
|
//DEBUG ::fprintf(fp, "%.*s", u8c->length(), u8c->text_utf8());
|
||
|
//DEBUG }
|
||
|
//DEBUG }
|
||
|
public:
|
||
|
void clear(void);
|
||
|
void clear_hist(void);
|
||
|
RingBuffer(void);
|
||
|
RingBuffer(int drows, int dcols, int hrows);
|
||
|
~RingBuffer(void);
|
||
|
|
||
|
// Methods to access ring
|
||
|
//
|
||
|
// The 'offset' concept allows the 'history' and 'display'
|
||
|
// to be scrolled indefinitely. The 'offset' is applied
|
||
|
// to all the row accesses, and are clamped to within their bounds.
|
||
|
//
|
||
|
// For 'raw' access to the ring (without the offset concept),
|
||
|
// use the ring_chars() method, and walk from 0 - ring_rows().
|
||
|
//
|
||
|
// _____________
|
||
|
// | | <- hist_srow() <- ring_srow()
|
||
|
// | H i s t |
|
||
|
// | |
|
||
|
// |_____________| <- hist_erow()
|
||
|
// | | <- disp_srow()
|
||
|
// | D i s p |
|
||
|
// | |
|
||
|
// |_____________| <- disp_erow() <- ring_erow()
|
||
|
//
|
||
|
// \___________/
|
||
|
// ring_cols()
|
||
|
// hist_cols()
|
||
|
// disp_cols()
|
||
|
//
|
||
|
inline int ring_rows(void) const { return ring_rows_; }
|
||
|
inline int ring_cols(void) const { return ring_cols_; }
|
||
|
inline int ring_srow(void) const { return(0); }
|
||
|
inline int ring_erow(void) const { return(ring_rows_ - 1); }
|
||
|
inline int hist_rows(void) const { return hist_rows_; }
|
||
|
inline int hist_cols(void) const { return ring_cols_; }
|
||
|
inline int hist_srow(void) const { return((offset_ + 0) % ring_rows_); }
|
||
|
inline int hist_erow(void) const { return((offset_ + hist_rows_ - 1) % ring_rows_); }
|
||
|
inline int disp_rows(void) const { return disp_rows_; }
|
||
|
inline int disp_cols(void) const { return ring_cols_; }
|
||
|
inline int disp_srow(void) const { return((offset_ + hist_rows_) % ring_rows_); }
|
||
|
inline int disp_erow(void) const { return((offset_ + hist_rows_ + disp_rows_ - 1) % ring_rows_); }
|
||
|
inline int offset(void) const { return offset_; }
|
||
|
// History use
|
||
|
inline int hist_use(void) const { return hist_use_; }
|
||
|
inline void hist_use(int val) { hist_use_ = val; }
|
||
|
inline int hist_use_srow(void) const { return((offset_ + hist_rows_ - hist_use_) % ring_rows_); }
|
||
|
inline Utf8Char *ring_chars(void) { return ring_chars_; } // access ring buffer directly
|
||
|
inline Utf8Char *ring_chars(void) const { return ring_chars_; } // access ring buffer directly
|
||
|
|
||
|
bool is_hist_ring_row(int grow) const;
|
||
|
bool is_disp_ring_row(int grow) const;
|
||
|
//DEBUG void show_ring_info(void) const;
|
||
|
void move_disp_row(int src_row, int dst_row);
|
||
|
void clear_disp_row(int drow, const CharStyle& style);
|
||
|
void scroll(int rows, const CharStyle& style);
|
||
|
|
||
|
const Utf8Char* u8c_ring_row(int row) const;
|
||
|
const Utf8Char* u8c_hist_row(int hrow) const;
|
||
|
const Utf8Char* u8c_hist_use_row(int hurow) const;
|
||
|
const Utf8Char* u8c_disp_row(int drow) const;
|
||
|
|
||
|
// Non-const versions of the above methods
|
||
|
// Using "Effective C++" ugly-as-hell syntax technique.
|
||
|
//
|
||
|
Utf8Char* u8c_ring_row(int row);
|
||
|
Utf8Char* u8c_hist_row(int hrow);
|
||
|
Utf8Char* u8c_hist_use_row(int hurow);
|
||
|
Utf8Char* u8c_disp_row(int drow);
|
||
|
|
||
|
void create(int drows, int dcols, int hrows);
|
||
|
void resize(int drows, int dcols, int hrows, const CharStyle& style);
|
||
|
|
||
|
void change_disp_rows(int drows, const CharStyle& style);
|
||
|
void change_disp_cols(int dcols, const CharStyle& style);
|
||
|
};
|
||
|
|
||
|
// Selection Class ///////////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage mouse selection
|
||
|
//
|
||
|
class Selection {
|
||
|
int srow_, scol_, erow_, ecol_; // selection start/end. NOTE: start *might* be > end
|
||
|
int push_row_, push_col_; // global row/col for last FL_PUSH
|
||
|
Fl_Color selectionbgcolor_;
|
||
|
Fl_Color selectionfgcolor_;
|
||
|
int state_ ; // 0=none, 1=started, 2=extended, 3=done
|
||
|
bool is_selection_; // false: no selection
|
||
|
public:
|
||
|
Selection(void);
|
||
|
int srow(void) const { return srow_; }
|
||
|
int scol(void) const { return scol_; }
|
||
|
int erow(void) const { return erow_; }
|
||
|
int ecol(void) const { return ecol_; }
|
||
|
void push_clear() { push_row_ = push_col_ = -1; }
|
||
|
void push_rowcol(int row,int col) { push_row_ = row; push_col_ = col; }
|
||
|
void start_push() { start(push_row_, push_col_); }
|
||
|
bool dragged_off(int row,int col) { return (push_row_ != row) || (push_col_ != col); }
|
||
|
void selectionfgcolor(Fl_Color val) { selectionfgcolor_ = val; }
|
||
|
void selectionbgcolor(Fl_Color val) { selectionbgcolor_ = val; }
|
||
|
Fl_Color selectionfgcolor(void) const { return selectionfgcolor_; }
|
||
|
Fl_Color selectionbgcolor(void) const { return selectionbgcolor_; }
|
||
|
bool is_selection(void) const { return is_selection_; }
|
||
|
bool get_selection(int &srow,int &scol,int &erow,int &ecol) const; // guarantees return (start < end)
|
||
|
bool start(int row, int col);
|
||
|
bool extend(int row, int col);
|
||
|
void end(void);
|
||
|
void select(int srow, int scol, int erow, int ecol);
|
||
|
bool clear(void);
|
||
|
int state(void) const { return state_; }
|
||
|
void scroll(int nrows);
|
||
|
};
|
||
|
|
||
|
// EscapeSeq Class ///////////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to handle parsing ESC sequences
|
||
|
//
|
||
|
// Holds all state information for parsing esc sequences,
|
||
|
// so sequences can span multiple block read(2) operations, etc.
|
||
|
// Handling of parsed sequences is NOT handled in this class,
|
||
|
// just the parsing of the sequences and managing generic integers.
|
||
|
//
|
||
|
class EscapeSeq {
|
||
|
public:
|
||
|
// EscapeSeq Constants
|
||
|
// Maximums
|
||
|
static const int maxbuff = 80; // character buffer
|
||
|
static const int maxvals = 20; // integer value buffer
|
||
|
// Return codes
|
||
|
static const int success = 0; // operation succeeded
|
||
|
static const int fail = -1; // operation failed
|
||
|
static const int completed = 1; // multi-step operation completed successfully
|
||
|
private:
|
||
|
char esc_mode_; // escape parsing mode state
|
||
|
char csi_; // This is an ESC[.. sequence (Ctrl Seq Introducer)
|
||
|
char buff_[maxbuff]; // escape sequence being parsed
|
||
|
char *buffp_; // parsing ptr into buff[]
|
||
|
char *buffendp_; // end of buff[] (ptr to last valid buff char)
|
||
|
char *valbuffp_; // pointer to first char in buff of integer being parsed
|
||
|
int vals_[maxvals]; // value array for parsing #'s in ESC[#;#;#..
|
||
|
int vali_; // parsing index into vals_[], 0 if none
|
||
|
int save_row_, save_col_; // used by ESC[s/u for save/restore
|
||
|
|
||
|
int append_buff(char c);
|
||
|
int append_val(void);
|
||
|
|
||
|
public:
|
||
|
EscapeSeq(void);
|
||
|
void reset(void);
|
||
|
char esc_mode(void) const;
|
||
|
void esc_mode(char val);
|
||
|
int total_vals(void) const;
|
||
|
int val(int i) const;
|
||
|
int defvalmax(int dval, int max) const;
|
||
|
bool parse_in_progress(void) const;
|
||
|
bool is_csi(void) const;
|
||
|
int parse(char c);
|
||
|
void save_cursor(int row, int col);
|
||
|
void restore_cursor(int &row, int &col);
|
||
|
};
|
||
|
|
||
|
// Partial UTF-8 Buffer Class ////////////////////////////////////////////
|
||
|
//
|
||
|
// Class to manage buffering partial UTF-8 characters between write calls.
|
||
|
//
|
||
|
class PartialUtf8Buf {
|
||
|
char buf_[10]; // buffer partial UTF-8 encoded char
|
||
|
int buflen_; // length of buffered UTF-8 encoded char
|
||
|
int clen_; // final byte length of a UTF-8 char
|
||
|
public:
|
||
|
void clear(void) { buflen_ = clen_ = 0; } // clear the buffer
|
||
|
PartialUtf8Buf(void) { clear(); } // Ctor
|
||
|
// Is byte 'c' in the middle of a UTF-8 encoded byte sequence?
|
||
|
bool is_continuation(char c) {
|
||
|
// Byte 1 Byte 2 Byte 3 ..etc..
|
||
|
// ASCII: 0xxxxxxx
|
||
|
// UTF8(2): 110xxxxx 10xxxxxx
|
||
|
// UTF8(3): 1110xxxx 10xxxxxx 10xxxxxx
|
||
|
// UTF8(4): 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
|
// UTF8(5): 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
|
// UTF8(6): 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
|
// \______/ \______________________________________________/
|
||
|
// Start byte Continuation bytes
|
||
|
// (c & 0xc0) == 0x80
|
||
|
return ((c & 0xc0) == 0x80);
|
||
|
}
|
||
|
// Access buffer
|
||
|
const char* buf(void) const { return buf_; }
|
||
|
// Access buffer length
|
||
|
int buflen(void) const { return buflen_; }
|
||
|
// Append bytes of a partial UTF-8 string to the buffer.
|
||
|
//
|
||
|
// Returns:
|
||
|
// - true if done OK. Use is_complete() to see if a complete char received.
|
||
|
// - false if buffer overrun occurred, class is clear()ed.
|
||
|
//
|
||
|
// An appropriate response to 'false' would be to print the
|
||
|
// "unknown character" and skip all subsequent UTF-8 continuation chars.
|
||
|
//
|
||
|
bool append(const char* p, int len) {
|
||
|
if (len <= 0) return true; // ignore silly requests: say we did but dont
|
||
|
if (buflen_ + len >= (int)sizeof(buf_)) // overrun check
|
||
|
{ clear(); return false; } // clear self, return false
|
||
|
if (!buflen_) clen_ = fl_utf8len(*p); // first byte? save char len for later
|
||
|
while (len>0) { buf_[buflen_++] = *p++; len--; } // append byte to buffer
|
||
|
return true;
|
||
|
}
|
||
|
bool is_complete(void) const { return (buflen_ && (buflen_ == clen_)); }
|
||
|
};
|
||
|
|
||
|
private:
|
||
|
// Fl_Terminal Members
|
||
|
Fl_Scrollbar *vscroll_; // vertical scrollbar (value: rows above disp_chars[])
|
||
|
int scrollbar_size_; // local preference for scrollbar size
|
||
|
CharStyle current_style_; // current font, attrib, color..
|
||
|
|
||
|
// A ring buffer is used for the terminal's history (hist) and display (disp) buffer.
|
||
|
// See README-Fl_Terminal.txt, section "RING BUFFER DESCRIPTION" for diagrams/info.
|
||
|
//
|
||
|
// Ring buffer
|
||
|
RingBuffer ring_; // terminal history/display ring buffer
|
||
|
Cursor cursor_; // terminal cursor (position, color, etc)
|
||
|
Margin margin_; // terminal margins (top,left,bottom,right)
|
||
|
Selection select_; // mouse selection
|
||
|
EscapeSeq escseq; // Escape sequence parsing (ESC[ xterm/vt100)
|
||
|
bool show_unknown_; // if true, show unknown chars as '¿' (default off)
|
||
|
bool ansi_; // if true, parse ansi codes (default on)
|
||
|
char *tabstops_; // array of tab stops (0|1) \__ TODO: This should probably
|
||
|
int tabstops_size_; // size of tabstops[] array / be a class "TabStops".
|
||
|
Fl_Rect scrn_; // terminal screen xywh inside box(), margins, and vscroll
|
||
|
int autoscroll_dir_; // 0=autoscroll timer off, 3=scrolling up, 4=scrolling down
|
||
|
int autoscroll_amt_; // #pixels above or below edge, used for autoscroll speed
|
||
|
RedrawStyle redraw_style_; // NO_REDRAW, RATE_LIMITED, PER_WRITE
|
||
|
float redraw_rate_; // maximum redraw rate in seconds, default=0.10
|
||
|
bool redraw_modified_; // display modified; used by update_cb() to rate limit redraws
|
||
|
bool redraw_timer_; // if true, redraw timer is running
|
||
|
PartialUtf8Buf pub_; // handles Partial Utf8 Buffer (pub)
|
||
|
|
||
|
protected:
|
||
|
// Ring buffer management
|
||
|
const Utf8Char* u8c_ring_row(int grow) const;
|
||
|
const Utf8Char* u8c_hist_row(int hrow) const;
|
||
|
const Utf8Char* u8c_hist_use_row(int hrow) const;
|
||
|
const Utf8Char* u8c_disp_row(int drow) const;
|
||
|
// non-const versions of the above.
|
||
|
// "Effective C++" says: implement non-const method to cast away const
|
||
|
//
|
||
|
Utf8Char* u8c_ring_row(int grow);
|
||
|
Utf8Char* u8c_hist_row(int hrow);
|
||
|
Utf8Char* u8c_hist_use_row(int hurow);
|
||
|
Utf8Char* u8c_disp_row(int drow);
|
||
|
private:
|
||
|
void create_ring(int drows, int dcols, int hrows);
|
||
|
protected:
|
||
|
Utf8Char* u8c_cursor(void);
|
||
|
private:
|
||
|
int vscroll_width(void) const;
|
||
|
// Tabstops
|
||
|
void init_tabstops(int newsize);
|
||
|
void default_tabstops(void);
|
||
|
void clear_all_tabstops(void);
|
||
|
void set_tabstop(void);
|
||
|
void clear_tabstop(void);
|
||
|
// Updates
|
||
|
void update_screen_xywh(void);
|
||
|
void update_screen(bool font_changed);
|
||
|
void update_scrollbar(void);
|
||
|
// Resize
|
||
|
void resize_display_rows(int drows);
|
||
|
void resize_display_columns(int dcols);
|
||
|
void refit_disp_to_screen(void);
|
||
|
// Callbacks
|
||
|
static void scrollbar_cb(Fl_Widget*, void*); // scrollbar manipulation
|
||
|
static void autoscroll_timer_cb(void*); // mouse drag autoscroll
|
||
|
void autoscroll_timer_cb2(void);
|
||
|
static void redraw_timer_cb(void*); // redraw rate limiting timer
|
||
|
void redraw_timer_cb2(void);
|
||
|
|
||
|
// Screen management
|
||
|
protected:
|
||
|
const CharStyle& current_style(void) const;
|
||
|
void current_style(const CharStyle& sty);
|
||
|
int x_to_glob_col(int X, int grow, int &gcol) const;
|
||
|
int xy_to_glob_rowcol(int X, int Y, int &grow, int &gcol) const;
|
||
|
int w_to_col(int W) const;
|
||
|
int h_to_row(int H) const;
|
||
|
// API: Display clear operations
|
||
|
void clear_screen(bool scroll_to_hist=true);
|
||
|
void clear_screen_home(bool scroll_to_hist=true);
|
||
|
void clear_sod(void);
|
||
|
void clear_eod(void);
|
||
|
void clear_eol(void);
|
||
|
void clear_sol(void);
|
||
|
void clear_line(int row);
|
||
|
void clear_line(void);
|
||
|
const Utf8Char* walk_selection(const Utf8Char *u8c, int &row, int &col) const;
|
||
|
bool get_selection(int &srow,int &scol,int &erow,int &ecol) const;
|
||
|
bool is_selection(void) const;
|
||
|
bool is_inside_selection(int row,int col) const;
|
||
|
bool is_hist_ring_row(int grow) const;
|
||
|
bool is_disp_ring_row(int grow) const;
|
||
|
int selection_text_len(void) const;
|
||
|
const char* selection_text(void) const;
|
||
|
void clear_mouse_selection(void);
|
||
|
bool selection_extend(int X,int Y);
|
||
|
void scroll(int rows);
|
||
|
void insert_rows(int count);
|
||
|
void delete_rows(int count);
|
||
|
void insert_char_eol(char c, int drow, int dcol, int rep);
|
||
|
void insert_char(char c, int rep);
|
||
|
void delete_chars(int drow, int dcol, int rep);
|
||
|
void delete_chars(int rep);
|
||
|
// History
|
||
|
void history_use(int val, bool update=true);
|
||
|
public:
|
||
|
// API: Terminal operations
|
||
|
void clear_history(void); // ESC [ 3 J
|
||
|
void reset_terminal(void); // ESC c
|
||
|
protected:
|
||
|
// Cursor management
|
||
|
int cursor_h(void) const;
|
||
|
public:
|
||
|
// API: Cursor
|
||
|
void cursorfgcolor(Fl_Color val);
|
||
|
void cursorbgcolor(Fl_Color val);
|
||
|
Fl_Color cursorfgcolor(void) const;
|
||
|
Fl_Color cursorbgcolor(void) const;
|
||
|
protected:
|
||
|
void cursor_row(int row);
|
||
|
void cursor_col(int col);
|
||
|
public:
|
||
|
int cursor_row(void) const;
|
||
|
int cursor_col(void) const;
|
||
|
protected:
|
||
|
void cursor_up(int count=1, bool do_scroll=false);
|
||
|
void cursor_down(int count=1, bool do_scroll=false);
|
||
|
void cursor_left(int count=1);
|
||
|
void cursor_right(int count=1, bool do_scroll=false);
|
||
|
void cursor_home(void);
|
||
|
void cursor_eol(void);
|
||
|
void cursor_sol(void);
|
||
|
void cursor_cr(void);
|
||
|
void cursor_crlf(int count=1);
|
||
|
void cursor_tab_right(int count=1);
|
||
|
void cursor_tab_left(int count=1);
|
||
|
void save_cursor(void);
|
||
|
void restore_cursor(void);
|
||
|
// Printing
|
||
|
void handle_ctrl(char c);
|
||
|
bool is_printable(char c);
|
||
|
bool is_ctrl(char c);
|
||
|
void handle_SGR(void);
|
||
|
void handle_DECRARA(void);
|
||
|
void handle_escseq(char c);
|
||
|
// --
|
||
|
void display_modified(void);
|
||
|
void display_modified_clear(void);
|
||
|
void clear_char_at_disp(int drow, int dcol);
|
||
|
const Utf8Char* utf8_char_at_disp(int drow, int dcol) const;
|
||
|
const Utf8Char* utf8_char_at_glob(int grow, int gcol) const;
|
||
|
void repeat_char(char c, int rep);
|
||
|
void utf8_cache_clear(void);
|
||
|
void utf8_cache_flush(void);
|
||
|
|
||
|
// API: Character display output
|
||
|
public:
|
||
|
void putchar(const char *text, int len, int drow, int dcol);
|
||
|
void putchar(char c, int drow, int dcol);
|
||
|
void print_char(const char *text, int len=-1);
|
||
|
void print_char(char c);
|
||
|
// API: String display output
|
||
|
void append_utf8(const char *buf, int len=-1);
|
||
|
void append_ascii(const char *s);
|
||
|
void append(const char *s, int len=-1);
|
||
|
protected:
|
||
|
int handle_unknown_char(void);
|
||
|
// Drawing
|
||
|
void draw_row_bg(int grow, int X, int Y) const;
|
||
|
void draw_row(int grow, int Y) const;
|
||
|
void draw_buff(int Y) const;
|
||
|
void handle_selection_autoscroll(void);
|
||
|
int handle_selection(int e);
|
||
|
public:
|
||
|
// FLTK: draw(), resize(), handle()
|
||
|
void draw(void) FL_OVERRIDE;
|
||
|
void resize(int X,int Y,int W,int H) FL_OVERRIDE;
|
||
|
int handle(int e) FL_OVERRIDE;
|
||
|
|
||
|
protected:
|
||
|
// Internal short names
|
||
|
// Don't make these public, but allow internals and
|
||
|
// derived classes to maintain brevity.
|
||
|
//
|
||
|
inline int ring_rows(void) const { return ring_.ring_rows(); }
|
||
|
inline int ring_cols(void) const { return ring_.ring_cols(); }
|
||
|
inline int ring_srow(void) const { return ring_.ring_srow(); }
|
||
|
inline int ring_erow(void) const { return ring_.ring_erow(); }
|
||
|
inline int hist_rows(void) const { return ring_.hist_rows(); }
|
||
|
inline int hist_cols(void) const { return ring_.hist_cols(); }
|
||
|
inline int hist_srow(void) const { return ring_.hist_srow(); }
|
||
|
inline int hist_erow(void) const { return ring_.hist_erow(); }
|
||
|
inline int hist_use(void) const { return ring_.hist_use(); }
|
||
|
inline int hist_use_srow(void) const { return ring_.hist_use_srow(); }
|
||
|
inline int disp_rows(void) const { return ring_.disp_rows(); }
|
||
|
inline int disp_cols(void) const { return ring_.disp_cols(); }
|
||
|
inline int disp_srow(void) const { return ring_.disp_srow(); }
|
||
|
inline int disp_erow(void) const { return ring_.disp_erow(); }
|
||
|
inline int offset(void) const { return ring_.offset(); }
|
||
|
|
||
|
// TODO: CLEAN UP WHAT'S PUBLIC, AND WHAT SHOULD BE 'PROTECTED' AND 'PRIVATE'
|
||
|
// Some of the public stuff should, quite simply, "not be".
|
||
|
|
||
|
// API: Terminal features
|
||
|
public:
|
||
|
// API: Scrollbar
|
||
|
int scrollbar_size(void) const;
|
||
|
void scrollbar_size(int val);
|
||
|
int scrollbar_actual_size(void) const;
|
||
|
// API: History
|
||
|
int history_rows(void) const;
|
||
|
void history_rows(int val);
|
||
|
int history_use(void) const;
|
||
|
// API: Display
|
||
|
int display_rows(void) const;
|
||
|
void display_rows(int val);
|
||
|
int display_columns(void) const;
|
||
|
void display_columns(int val);
|
||
|
// API: Box
|
||
|
/// Sets the box type, updates terminal margins et al. Default is FL_DOWN_FRAME.
|
||
|
///
|
||
|
/// FL_XXX_FRAME types are handled in a special way by this widget, and guarantee
|
||
|
/// the background is a flat field.
|
||
|
///
|
||
|
/// FL_XXX_BOX may draw gradients as inherited by Fl::scheme().
|
||
|
///
|
||
|
void box(Fl_Boxtype val) { Fl_Group::box(val); update_screen(false); }
|
||
|
/// Returns the current box type.
|
||
|
Fl_Boxtype box(void) const { return Fl_Group::box(); }
|
||
|
// API: Margins
|
||
|
/// Return the left margin; see \ref Fl_Terminal_Margins.
|
||
|
int margin_left(void) const { return margin_.left(); }
|
||
|
/// Return the right margin; see \ref Fl_Terminal_Margins.
|
||
|
int margin_right(void) const { return margin_.right(); }
|
||
|
/// Return the top margin; see \ref Fl_Terminal_Margins.
|
||
|
int margin_top(void) const { return margin_.top(); }
|
||
|
/// Return the bottom margin; see \ref Fl_Terminal_Margins.
|
||
|
int margin_bottom(void) const { return margin_.bottom(); }
|
||
|
void margin_left(int val);
|
||
|
void margin_right(int val);
|
||
|
void margin_top(int val);
|
||
|
void margin_bottom(int val);
|
||
|
// API: Text font/size/color
|
||
|
void textfont(Fl_Font val);
|
||
|
void textsize(Fl_Fontsize val);
|
||
|
void textfgcolor(Fl_Color val);
|
||
|
void textbgcolor(Fl_Color val);
|
||
|
void textfgcolor_default(Fl_Color val);
|
||
|
void textbgcolor_default(Fl_Color val);
|
||
|
/// Return text font used to draw all text in the terminal.
|
||
|
Fl_Font textfont(void) const { return current_style_.fontface(); }
|
||
|
/// Return text font size used to draw all text in the terminal.
|
||
|
Fl_Fontsize textsize(void) const { return current_style_.fontsize(); }
|
||
|
/// Return text's current foreground color.
|
||
|
Fl_Color textfgcolor(void) const { return current_style_.fgcolor(); }
|
||
|
/// Return text's current background color.
|
||
|
Fl_Color textbgcolor(void) const { return current_style_.bgcolor(); }
|
||
|
/// Return text's default foreground color. \see textfgcolor()
|
||
|
Fl_Color textfgcolor_default(void) const { return current_style_.defaultfgcolor(); }
|
||
|
/// Return text's default background color. \see textbgcolor()
|
||
|
Fl_Color textbgcolor_default(void) const { return current_style_.defaultbgcolor(); }
|
||
|
void textfgcolor_xterm(uchar val);
|
||
|
void textbgcolor_xterm(uchar val);
|
||
|
/// Set mouse selection foreground color.
|
||
|
void selectionfgcolor(Fl_Color val) { select_.selectionfgcolor(val); }
|
||
|
/// Set mouse selection background color.
|
||
|
void selectionbgcolor(Fl_Color val) { select_.selectionbgcolor(val); }
|
||
|
/// Get mouse selection foreground color.
|
||
|
Fl_Color selectionfgcolor(void) const { return select_.selectionfgcolor(); }
|
||
|
/// Get mouse selection background color.
|
||
|
Fl_Color selectionbgcolor(void) const { return select_.selectionbgcolor(); }
|
||
|
// API: Text attrib
|
||
|
void textattrib(uchar val);
|
||
|
// API: Redraw style/rate
|
||
|
RedrawStyle redraw_style(void) const;
|
||
|
void redraw_style(RedrawStyle val);
|
||
|
protected:
|
||
|
bool is_redraw_style(RedrawStyle val) { return redraw_style_ == val; }
|
||
|
public:
|
||
|
float redraw_rate(void) const;
|
||
|
void redraw_rate(float val);
|
||
|
// API: Show unknown/unprintable chars
|
||
|
bool show_unknown(void) const;
|
||
|
void show_unknown(bool val);
|
||
|
// API: ANSI sequences
|
||
|
bool ansi(void) const;
|
||
|
void ansi(bool val);
|
||
|
// Fl_Simple_Terminal API compatibility
|
||
|
int history_lines(void) const;
|
||
|
void history_lines(int val);
|
||
|
// API: printf()
|
||
|
void printf(const char *fmt, ...);
|
||
|
void vprintf(const char *fmt, va_list ap);
|
||
|
// Ctor
|
||
|
Fl_Terminal(int X, int Y, int W, int H, const char*L=0);
|
||
|
// Dtor
|
||
|
~Fl_Terminal(void);
|
||
|
// Debugging features
|
||
|
//DEBUG void show_ring_info() const { ring_.show_ring_info(); }
|
||
|
//DEBUG void write_row(FILE *fp, Utf8Char *u8c, int cols) const;
|
||
|
//DEBUG void show_buffers(RingBuffer *a, RingBuffer *b=0) const;
|
||
|
};
|
||
|
#endif
|