cursor shape CSI and cursor blink toggle
This commit is contained in:
+38
-9
@@ -112,9 +112,9 @@ apars_handle_csi(char leadchar, const int *params, int count, char interchar, ch
|
|||||||
// switch_csi_NoLeadInterDollar(opts);
|
// switch_csi_NoLeadInterDollar(opts);
|
||||||
// break;
|
// break;
|
||||||
|
|
||||||
// case ' ':
|
case ' ':
|
||||||
// switch_csi_NoLeadInterSpace(opts);
|
switch_csi_NoLeadInterSpace(opts);
|
||||||
// break;
|
break;
|
||||||
|
|
||||||
// case ',':
|
// case ',':
|
||||||
// switch_csi_NoLeadInterComma(opts);
|
// switch_csi_NoLeadInterComma(opts);
|
||||||
@@ -409,6 +409,36 @@ switch_csi_NoLeadInterBang(CSI_Data *opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSI none Pm SP key
|
||||||
|
*/
|
||||||
|
static inline void ICACHE_FLASH_ATTR
|
||||||
|
switch_csi_NoLeadInterSpace(CSI_Data *opts)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
switch(opts->key) {
|
||||||
|
case 'q':
|
||||||
|
// DECSCUSR
|
||||||
|
// CSI Ps SP q
|
||||||
|
// Set cursor style (DECSCUSR, VT520).
|
||||||
|
// Ps = 0 -> blinking block.
|
||||||
|
// Ps = 1 -> blinking block (default).
|
||||||
|
// Ps = 2 -> steady block.
|
||||||
|
// Ps = 3 -> blinking underline.
|
||||||
|
// Ps = 4 -> steady underline.
|
||||||
|
// Ps = 5 -> blinking bar (xterm).
|
||||||
|
// Ps = 6 -> steady bar (xterm).
|
||||||
|
n = opts->n[0];
|
||||||
|
if (n > 6) n = 1; // use default if bad value set
|
||||||
|
screen_cursor_shape((enum CursorShape) n);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
warn_bad_csi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CSI > Pm inter key
|
* CSI > Pm inter key
|
||||||
*/
|
*/
|
||||||
@@ -649,8 +679,10 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
mouse_tracking.focus_tracking);
|
mouse_tracking.focus_tracking);
|
||||||
}
|
}
|
||||||
else if (n == 12) {
|
else if (n == 12) {
|
||||||
// TODO Cursor blink on/off
|
screen_cursor_blink(yn);
|
||||||
ansi_noimpl("Cursor blink toggle");
|
}
|
||||||
|
else if (n == 25) {
|
||||||
|
screen_set_cursor_visible(yn);
|
||||||
}
|
}
|
||||||
else if (n == 40) {
|
else if (n == 40) {
|
||||||
// allow/disallow 80->132 mode
|
// allow/disallow 80->132 mode
|
||||||
@@ -659,7 +691,7 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
}
|
}
|
||||||
else if (n == 45) {
|
else if (n == 45) {
|
||||||
// reverse wrap-around
|
// reverse wrap-around
|
||||||
ansi_noimpl("Reverse Wraparound");
|
screen_reverse_wrap_enable(yn);
|
||||||
}
|
}
|
||||||
else if (n == 69) {
|
else if (n == 69) {
|
||||||
// horizontal margins
|
// horizontal margins
|
||||||
@@ -691,9 +723,6 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
// Bracketed paste mode
|
// Bracketed paste mode
|
||||||
ansi_noimpl("Bracketed paste");
|
ansi_noimpl("Bracketed paste");
|
||||||
}
|
}
|
||||||
else if (n == 25) {
|
|
||||||
screen_set_cursor_visible(yn);
|
|
||||||
}
|
|
||||||
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
||||||
termconf_scratch.show_buttons = yn;
|
termconf_scratch.show_buttons = yn;
|
||||||
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
||||||
|
|||||||
+109
-44
@@ -49,11 +49,12 @@ static struct {
|
|||||||
bool numpad_alt_mode; //!< DECNKM - Numpad Application Mode
|
bool numpad_alt_mode; //!< DECNKM - Numpad Application Mode
|
||||||
bool cursors_alt_mode; //!< DECCKM - Cursors Application mode
|
bool cursors_alt_mode; //!< DECCKM - Cursors Application mode
|
||||||
|
|
||||||
bool newline_mode; //!< LNM - CR automatically sends LF
|
bool newline_mode; //!< LNM - CR automatically sends LF
|
||||||
bool reverse; //!< DECSCNM - Reverse video
|
bool reverse; //!< DECSCNM - Reverse video
|
||||||
|
|
||||||
bool insert_mode; //!< IRM - Insert mode (move rest of the line to the right)
|
bool insert_mode; //!< IRM - Insert mode (move rest of the line to the right)
|
||||||
bool cursor_visible; //!< DECTCEM - Cursor visible
|
bool cursor_visible; //!< DECTCEM - Cursor visible
|
||||||
|
enum CursorShape cursor_shape;
|
||||||
|
|
||||||
// Vertical margin bounds (inclusive start/end of scrolling region)
|
// Vertical margin bounds (inclusive start/end of scrolling region)
|
||||||
int vm0;
|
int vm0;
|
||||||
@@ -90,6 +91,7 @@ typedef struct {
|
|||||||
|
|
||||||
/** Options saved with cursor */
|
/** Options saved with cursor */
|
||||||
bool auto_wrap; //!< DECAWM - Wrapping when EOL
|
bool auto_wrap; //!< DECAWM - Wrapping when EOL
|
||||||
|
bool reverse_wraparound; //!< Reverse-wraparound Mode. DECSET 45
|
||||||
bool origin_mode; //!< DECOM - absolute positioning is relative to vertical margins
|
bool origin_mode; //!< DECOM - absolute positioning is relative to vertical margins
|
||||||
} CursorTypeDef;
|
} CursorTypeDef;
|
||||||
|
|
||||||
@@ -165,6 +167,7 @@ terminal_restore_defaults(void)
|
|||||||
termconf->loopback = 0;
|
termconf->loopback = 0;
|
||||||
termconf->show_buttons = 1;
|
termconf->show_buttons = 1;
|
||||||
termconf->show_config_links = 1;
|
termconf->show_config_links = 1;
|
||||||
|
termconf->def_cursor_shape = CURSOR_BLOCK_BL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,6 +211,13 @@ terminal_apply_settings_noclear(void)
|
|||||||
changed = 1;
|
changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migrate to v3
|
||||||
|
if (termconf->config_version < 4) {
|
||||||
|
dbg("termconf: Updating to version 4");
|
||||||
|
termconf->def_cursor_shape = CURSOR_BLOCK_BL;
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
termconf->config_version = TERMCONF_VERSION;
|
termconf->config_version = TERMCONF_VERSION;
|
||||||
|
|
||||||
// Validation...
|
// Validation...
|
||||||
@@ -268,30 +278,6 @@ cursor_reset(void)
|
|||||||
screen_reset_sgr();
|
screen_reset_sgr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the cursor position & colors
|
|
||||||
*/
|
|
||||||
static void ICACHE_FLASH_ATTR
|
|
||||||
decopt_reset(void)
|
|
||||||
{
|
|
||||||
scr.cursor_visible = true;
|
|
||||||
scr.insert_mode = false;
|
|
||||||
cursor.origin_mode = false;
|
|
||||||
cursor.auto_wrap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the cursor (\e[0m)
|
|
||||||
*/
|
|
||||||
void ICACHE_FLASH_ATTR
|
|
||||||
screen_reset_sgr(void)
|
|
||||||
{
|
|
||||||
cursor.fg = termconf_scratch.default_fg;
|
|
||||||
cursor.bg = termconf_scratch.default_bg;
|
|
||||||
cursor.attrs = 0;
|
|
||||||
cursor.inverse = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the screen - called by ESC c
|
* Reset the screen - called by ESC c
|
||||||
*/
|
*/
|
||||||
@@ -314,6 +300,18 @@ screen_reset_on_resize(void)
|
|||||||
NOTIFY_DONE();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the cursor (\e[0m)
|
||||||
|
*/
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_reset_sgr(void)
|
||||||
|
{
|
||||||
|
cursor.fg = termconf_scratch.default_fg;
|
||||||
|
cursor.bg = termconf_scratch.default_bg;
|
||||||
|
cursor.attrs = 0;
|
||||||
|
cursor.inverse = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the screen - called by ESC c
|
* Reset the screen - called by ESC c
|
||||||
*/
|
*/
|
||||||
@@ -324,7 +322,14 @@ screen_reset(void)
|
|||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
cursor_reset();
|
cursor_reset();
|
||||||
decopt_reset();
|
|
||||||
|
// DECopts
|
||||||
|
scr.cursor_visible = true;
|
||||||
|
scr.insert_mode = false;
|
||||||
|
cursor.origin_mode = false;
|
||||||
|
cursor.auto_wrap = true;
|
||||||
|
cursor.reverse_wraparound = false;
|
||||||
|
scr.cursor_shape = termconf->def_cursor_shape;
|
||||||
|
|
||||||
scr.numpad_alt_mode = false;
|
scr.numpad_alt_mode = false;
|
||||||
scr.cursors_alt_mode = false;
|
scr.cursors_alt_mode = false;
|
||||||
@@ -838,6 +843,33 @@ screen_set_scrolling_region(int from, int to)
|
|||||||
|
|
||||||
//region --- Cursor manipulation ---
|
//region --- Cursor manipulation ---
|
||||||
|
|
||||||
|
/** set cursor type */
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_cursor_shape(enum CursorShape shape)
|
||||||
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
if (shape == CURSOR_DEFAULT) shape = termconf->def_cursor_shape;
|
||||||
|
scr.cursor_shape = shape;
|
||||||
|
NOTIFY_DONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set cursor blink option */
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_cursor_blink(bool blink)
|
||||||
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
if (blink) {
|
||||||
|
if (scr.cursor_shape == CURSOR_BLOCK) scr.cursor_shape = CURSOR_BLOCK_BL;
|
||||||
|
if (scr.cursor_shape == CURSOR_BAR) scr.cursor_shape = CURSOR_BAR_BL;
|
||||||
|
if (scr.cursor_shape == CURSOR_UNDERLINE) scr.cursor_shape = CURSOR_UNDERLINE_BL;
|
||||||
|
} else {
|
||||||
|
if (scr.cursor_shape == CURSOR_BLOCK_BL) scr.cursor_shape = CURSOR_BLOCK;
|
||||||
|
if (scr.cursor_shape == CURSOR_BAR_BL) scr.cursor_shape = CURSOR_BAR;
|
||||||
|
if (scr.cursor_shape == CURSOR_UNDERLINE_BL) scr.cursor_shape = CURSOR_UNDERLINE;
|
||||||
|
}
|
||||||
|
NOTIFY_DONE();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set cursor position
|
* Set cursor position
|
||||||
*/
|
*/
|
||||||
@@ -921,7 +953,34 @@ screen_cursor_move(int dy, int dx, bool scroll)
|
|||||||
cursor.x += dx;
|
cursor.x += dx;
|
||||||
cursor.y += dy;
|
cursor.y += dy;
|
||||||
if (cursor.x >= (int)W) cursor.x = W - 1;
|
if (cursor.x >= (int)W) cursor.x = W - 1;
|
||||||
if (cursor.x < (int)0) cursor.x = 0;
|
if (cursor.x < (int)0) {
|
||||||
|
if (cursor.auto_wrap && cursor.reverse_wraparound) {
|
||||||
|
// this is mimicking a behavior from xterm that allows any number of steps backwards with reverse wraparound enabled
|
||||||
|
int steps = -cursor.x;
|
||||||
|
if(steps > 1000) steps = 1; // avoid something stupid causing infinite loop here
|
||||||
|
for(;steps>0;steps--) {
|
||||||
|
if (cursor.x > 0) {
|
||||||
|
// backspace should go to col 79 if "hanging" after 80 (as if it never actually left the 80th col)
|
||||||
|
cursor.hanging = false;
|
||||||
|
cursor.x--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (cursor.y > 0) {
|
||||||
|
// end of previous line
|
||||||
|
cursor.y--;
|
||||||
|
cursor.x = W - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// end of screen, end of line (wrap around)
|
||||||
|
cursor.y = R1;
|
||||||
|
cursor.x = W - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cursor.y < R0) {
|
if (cursor.y < R0) {
|
||||||
if (was_inside) {
|
if (was_inside) {
|
||||||
@@ -1030,6 +1089,15 @@ screen_wrap_enable(bool enable)
|
|||||||
cursor.auto_wrap = enable;
|
cursor.auto_wrap = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable reverse wraparound
|
||||||
|
*/
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_reverse_wrap_enable(bool enable)
|
||||||
|
{
|
||||||
|
cursor.reverse_wraparound = enable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set cursor foreground color
|
* Set cursor foreground color
|
||||||
*/
|
*/
|
||||||
@@ -1170,11 +1238,7 @@ screen_putchar(const char *ch)
|
|||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
case BS:
|
case BS:
|
||||||
if (cursor.x > 0) {
|
screen_cursor_move(0, -1, false);
|
||||||
// backspace should go to col 79 if "hanging" after 80 (as if it never actually left the 80th col)
|
|
||||||
cursor.hanging = false;
|
|
||||||
cursor.x--;
|
|
||||||
}
|
|
||||||
// we should not wrap around, and backspace should not even clear the cell (verified in xterm)
|
// we should not wrap around, and backspace should not even clear the cell (verified in xterm)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@@ -1402,17 +1466,18 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
bufput_2B(W);
|
bufput_2B(W);
|
||||||
bufput_2B(cursor.y);
|
bufput_2B(cursor.y);
|
||||||
bufput_2B(cursor.x);
|
bufput_2B(cursor.x);
|
||||||
bufput_2B((
|
bufput_2B(
|
||||||
(scr.cursor_visible ? 1<<0 : 0) |
|
(scr.cursor_visible ? 1<<0 : 0) |
|
||||||
(cursor.hanging ? 1<<1 : 0) |
|
(cursor.hanging ? 1<<1 : 0) |
|
||||||
(scr.cursors_alt_mode ? 1<<2 : 0) |
|
(scr.cursors_alt_mode ? 1<<2 : 0) |
|
||||||
(scr.numpad_alt_mode ? 1<<3 : 0) |
|
(scr.numpad_alt_mode ? 1<<3 : 0) |
|
||||||
(termconf->fn_alt_mode ? 1<<4 : 0) |
|
(termconf->fn_alt_mode ? 1<<4 : 0) |
|
||||||
((mouse_tracking.mode>MTM_NONE) ? 1<<5 : 0) | // disables context menu
|
((mouse_tracking.mode>MTM_NONE) ? 1<<5 : 0) | // disables context menu
|
||||||
((mouse_tracking.mode>=MTM_NORMAL) ? 1<<6 : 0) | // disables selecting
|
((mouse_tracking.mode>=MTM_NORMAL) ? 1<<6 : 0) | // disables selecting
|
||||||
(termconf_scratch.show_buttons ? 1<<7 : 0) |
|
(termconf_scratch.show_buttons ? 1<<7 : 0) |
|
||||||
(termconf_scratch.show_config_links ? 1<<8 : 0)
|
(termconf_scratch.show_config_links ? 1<<8 : 0) |
|
||||||
));
|
((scr.cursor_shape&0x03)<<9) // 9,10,11 - cursor shape based on DECSCUSR
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = ss->index;
|
int i = ss->index;
|
||||||
|
|||||||
+18
-1
@@ -54,10 +54,20 @@
|
|||||||
/** Maximum screen size (determines size of the static data array) */
|
/** Maximum screen size (determines size of the static data array) */
|
||||||
#define MAX_SCREEN_SIZE (80*25)
|
#define MAX_SCREEN_SIZE (80*25)
|
||||||
|
|
||||||
#define TERMCONF_VERSION 3
|
#define TERMCONF_VERSION 4
|
||||||
|
|
||||||
// --- Persistent Settings ---
|
// --- Persistent Settings ---
|
||||||
|
|
||||||
|
enum CursorShape {
|
||||||
|
CURSOR_BLOCK_BL = 0,
|
||||||
|
CURSOR_DEFAULT = 1, // this is translated to a user configured style
|
||||||
|
CURSOR_BLOCK = 2,
|
||||||
|
CURSOR_UNDERLINE_BL = 3,
|
||||||
|
CURSOR_UNDERLINE = 4,
|
||||||
|
CURSOR_BAR_BL = 5,
|
||||||
|
CURSOR_BAR = 6,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
@@ -75,6 +85,7 @@ typedef struct {
|
|||||||
bool show_buttons;
|
bool show_buttons;
|
||||||
bool show_config_links;
|
bool show_config_links;
|
||||||
char btn_msg[TERM_BTN_COUNT][TERM_BTN_MSG_LEN];
|
char btn_msg[TERM_BTN_COUNT][TERM_BTN_MSG_LEN];
|
||||||
|
enum CursorShape def_cursor_shape;
|
||||||
} TerminalConfigBundle;
|
} TerminalConfigBundle;
|
||||||
|
|
||||||
// Live config
|
// Live config
|
||||||
@@ -173,6 +184,10 @@ void screen_scroll_down(unsigned int lines);
|
|||||||
|
|
||||||
// --- Cursor control ---
|
// --- Cursor control ---
|
||||||
|
|
||||||
|
/** Set cursor shape */
|
||||||
|
void screen_cursor_shape(enum CursorShape shape);
|
||||||
|
/** Toggle cursor blink (modifies shape) */
|
||||||
|
void screen_cursor_blink(bool blink);
|
||||||
/** Set cursor position */
|
/** Set cursor position */
|
||||||
void screen_cursor_set(int y, int x);
|
void screen_cursor_set(int y, int x);
|
||||||
/** Read cursor pos to given vars */
|
/** Read cursor pos to given vars */
|
||||||
@@ -196,6 +211,8 @@ void screen_set_insert_mode(bool insert);
|
|||||||
void screen_set_newline_mode(bool nlm);
|
void screen_set_newline_mode(bool nlm);
|
||||||
/** Enable auto wrap */
|
/** Enable auto wrap */
|
||||||
void screen_wrap_enable(bool enable);
|
void screen_wrap_enable(bool enable);
|
||||||
|
/** Enable reverse wrap-around */
|
||||||
|
void screen_reverse_wrap_enable(bool enable);
|
||||||
/** Set scrolling region */
|
/** Set scrolling region */
|
||||||
void screen_set_scrolling_region(int from, int to);
|
void screen_set_scrolling_region(int from, int to);
|
||||||
/** Enable or disable origin remap to top left of scrolling region */
|
/** Enable or disable origin remap to top left of scrolling region */
|
||||||
|
|||||||
Reference in New Issue
Block a user