cursor shape CSI and cursor blink toggle

http-comm
Ondřej Hruška 7 years ago
parent ea97752867
commit 2bea6397c6
  1. 47
      user/apars_csi.c
  2. 133
      user/screen.c
  3. 19
      user/screen.h

@ -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

@ -54,6 +54,7 @@ static struct {
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,7 +1466,7 @@ 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) |
@ -1411,8 +1475,9 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
((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;

@ -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 */

Loading…
Cancel
Save