From ac5fbeed478a0808126f6153a5e5927dfb9898a6 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Sun, 15 Dec 2024 04:32:20 +0100 Subject: [PATCH] - far2l extensions: added cursor shape change support - worked around one more Wine issue --- putty.h | 12 ++++++------ terminal/terminal.c | 26 +++++++++++++++++++++++--- terminal/terminal.h | 1 + test/fuzzterm.c | 4 ++-- test/test_terminal.c | 4 ++-- unix/window.c | 4 ++-- windows/window.c | 40 ++++++++++++++++++++++++++++------------ 7 files changed, 64 insertions(+), 27 deletions(-) diff --git a/putty.h b/putty.h index 2404841..bbbc7f1 100644 --- a/putty.h +++ b/putty.h @@ -1641,14 +1641,14 @@ struct TermWinVtable { bool (*setup_draw_ctx)(TermWin *); /* Draw text in the window, during a painting operation */ void (*draw_text)(TermWin *, int x, int y, wchar_t *text, int len, - unsigned long attrs, int line_attrs, truecolour tc); + unsigned long attrs, int line_attrs, truecolour tc, int custom); /* Draw the visible cursor. Expects you to have called do_text * first (because it might just draw an underline over a character * presumed to exist already), but also expects you to pass in all * the details of the character under the cursor (because it might * redraw it in different colours). */ void (*draw_cursor)(TermWin *, int x, int y, wchar_t *text, int len, - unsigned long attrs, int line_attrs, truecolour tc); + unsigned long attrs, int line_attrs, truecolour tc, int custom); /* Draw the sigil indicating that a line of text has come from * PuTTY itself rather than the far end (defence against end-of- * authentication spoofing) */ @@ -1729,12 +1729,12 @@ static inline bool win_setup_draw_ctx(TermWin *win) { return win->vt->setup_draw_ctx(win); } static inline void win_draw_text( TermWin *win, int x, int y, wchar_t *text, int len, - unsigned long attrs, int line_attrs, truecolour tc) -{ win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc); } + unsigned long attrs, int line_attrs, truecolour tc, int custom) +{ win->vt->draw_text(win, x, y, text, len, attrs, line_attrs, tc, custom); } static inline void win_draw_cursor( TermWin *win, int x, int y, wchar_t *text, int len, - unsigned long attrs, int line_attrs, truecolour tc) -{ win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc); } + unsigned long attrs, int line_attrs, truecolour tc, int custom) +{ win->vt->draw_cursor(win, x, y, text, len, attrs, line_attrs, tc, custom); } static inline void win_draw_trust_sigil(TermWin *win, int x, int y) { win->vt->draw_trust_sigil(win, x, y); } static inline int win_char_width(TermWin *win, int uc) diff --git a/terminal/terminal.c b/terminal/terminal.c index 22295d6..7f1d730 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -1436,6 +1436,7 @@ static void power_on(Terminal *term, bool clear) term->far2l_ext = 0; term->prev_uchar = 0; term->notif_hwnd = 0; + term->cursor_custom = -1; term->alt_x = term->alt_y = 0; term->savecurs.x = term->savecurs.y = 0; @@ -2075,6 +2076,7 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) term->far2l_ext = 0; term->is_apc = 0; //term->clip_allowed = -1; + term->cursor_custom = -1; term->win = win; term->ucsdata = ucsdata; @@ -3256,6 +3258,24 @@ static void do_osc(Terminal *term) // next from the end byte is command switch (d_out[d_count-2]) { + case 'h':; + + int height = d_out[d_count-3]; + + if (height < 30) { + term->cursor_custom = CURSOR_UNDERLINE; + term->big_cursor = false; + } else { + term->cursor_custom = CURSOR_BLOCK; + } + term->blink_cur = 1; // should always blink in far2l exts mode + + reply_size = 5; + reply = malloc(reply_size); + memcpy(reply, &zero, sizeof(DWORD)); + + break; + case 'f':; reply_size = 5; @@ -6639,13 +6659,13 @@ static void do_paint_draw(Terminal *term, termline *ldata, int x, int y, wchar_t tch[2]; tch[0] = tch[1] = L' '; win_draw_text(term->win, x, y, tch, 2, term->basic_erase_char.attr, - ldata->lattr, term->basic_erase_char.truecolour); + ldata->lattr, term->basic_erase_char.truecolour, term->cursor_custom); win_draw_trust_sigil(term->win, x, y); } else { - win_draw_text(term->win, x, y, ch, ccount, attr, ldata->lattr, tc); + win_draw_text(term->win, x, y, ch, ccount, attr, ldata->lattr, tc, term->cursor_custom); if (attr & (TATTR_ACTCURS | TATTR_PASCURS)) win_draw_cursor(term->win, x, y, ch, ccount, - attr, ldata->lattr, tc); + attr, ldata->lattr, tc, term->cursor_custom); } } diff --git a/terminal/terminal.h b/terminal/terminal.h index cf1c1f9..b9f3223 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -185,6 +185,7 @@ struct terminal_tag { /* far2l */ #define OSC_ALLOCATE_BLOCK_SIZE 1048576 + int cursor_custom; int osc_strlen; int osc_allocated_size; char* osc_string; diff --git a/test/fuzzterm.c b/test/fuzzterm.c index 45ba91d..bfc97e1 100644 --- a/test/fuzzterm.c +++ b/test/fuzzterm.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) static bool fuzz_setup_draw_ctx(TermWin *tw) { return true; } static void fuzz_draw_text( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour tc) + unsigned long attr, int lattr, truecolour tc, int custom) { int i; @@ -54,7 +54,7 @@ static void fuzz_draw_text( } static void fuzz_draw_cursor( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour tc) + unsigned long attr, int lattr, truecolour tc, int custom) { int i; diff --git a/test/test_terminal.c b/test/test_terminal.c index 9fdca6c..497f5e3 100644 --- a/test/test_terminal.c +++ b/test/test_terminal.c @@ -41,10 +41,10 @@ typedef struct Mock { static bool mock_setup_draw_ctx(TermWin *win) { return false; } static void mock_draw_text(TermWin *win, int x, int y, wchar_t *text, int len, - unsigned long attrs, int lattrs, truecolour tc) {} + unsigned long attrs, int lattrs, truecolour tc, int custom) {} static void mock_draw_cursor(TermWin *win, int x, int y, wchar_t *text, int len, unsigned long attrs, int lattrs, - truecolour tc) {} + truecolour tc, int custom) {} static void mock_set_raw_mouse_mode(TermWin *win, bool enable) {} static void mock_set_raw_mouse_mode_pointer(TermWin *win, bool enable) {} static void mock_palette_set(TermWin *win, unsigned start, unsigned ncolours, diff --git a/unix/window.c b/unix/window.c index f8dbda7..4351362 100644 --- a/unix/window.c +++ b/unix/window.c @@ -4034,7 +4034,7 @@ static void do_text_internal( static void gtkwin_draw_text( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour truecolour) + unsigned long attr, int lattr, truecolour truecolour, int custom) { GtkFrontend *inst = container_of(tw, GtkFrontend, termwin); int widefactor; @@ -4064,7 +4064,7 @@ static void gtkwin_draw_text( static void gtkwin_draw_cursor( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour truecolour) + unsigned long attr, int lattr, truecolour truecolour, int custom) { GtkFrontend *inst = container_of(tw, GtkFrontend, termwin); bool active, passive; diff --git a/windows/window.c b/windows/window.c index cac5a08..c1e659c 100644 --- a/windows/window.c +++ b/windows/window.c @@ -152,9 +152,9 @@ struct WinGuiSeatListNode wgslisthead = { static bool wintw_setup_draw_ctx(TermWin *); static void wintw_draw_text(TermWin *, int x, int y, wchar_t *text, int len, - unsigned long attrs, int lattrs, truecolour tc); + unsigned long attrs, int lattrs, truecolour tc, int custom); static void wintw_draw_cursor(TermWin *, int x, int y, wchar_t *text, int len, - unsigned long attrs, int lattrs, truecolour tc); + unsigned long attrs, int lattrs, truecolour tc, int custom); static void wintw_draw_trust_sigil(TermWin *, int x, int y); static int wintw_char_width(TermWin *, int uc); static void wintw_free_draw_ctx(TermWin *); @@ -3328,6 +3328,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } } + if ((ctrl & 504) == 504) { ctrl = 0; } // work around one more Wine issue (kb layout change affects?) + char* kev = malloc(15); // keyboard event structure length memcpy(kev, &repeat, sizeof(repeat)); memcpy(kev + 2, &vkc, sizeof(vkc)); @@ -3336,6 +3338,16 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, memcpy(kev + 10, &uchar, sizeof(uchar)); memcpy(kev + 14, &type, sizeof(type)); + /* + // debug + printf(" type: %u\n", type); + printf(" vkc: %u (0x%04X)\n", vkc, vkc); + printf(" vsc: %u (0x%04X)\n", vsc, vsc); + printf(" ctrl: %lu (0x%08lX)\n", ctrl, ctrl); + printf(" repeat: %u\n", repeat); + printf("\n"); + */ + // base64-encode kev base64_encodestate _state; base64_init_encodestate(&_state); @@ -3671,7 +3683,7 @@ static void draw_horizontal_line_on_text( */ static void do_text_internal( WinGuiSeat *wgs, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour truecolour) + unsigned long attr, int lattr, truecolour truecolour, int custom) { COLORREF fg, bg, t; int nfg, nbg, nfont; @@ -3707,8 +3719,11 @@ static void do_text_internal( x += wgs->offset_width; y += wgs->offset_height; + int ctype = wgs->cursor_type; + if (custom != -1) { ctype = custom; } + if ((attr & TATTR_ACTCURS) && - (wgs->cursor_type == CURSOR_BLOCK || wgs->term->big_cursor)) { + (ctype == CURSOR_BLOCK || wgs->term->big_cursor)) { truecolour.fg = truecolour.bg = optionalrgb_none; attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS|ATTR_DIM); /* cursor fg and bg */ @@ -4050,7 +4065,7 @@ static void do_text_internal( */ static void wintw_draw_text( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour truecolour) + unsigned long attr, int lattr, truecolour truecolour, int custom) { WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); if (attr & TATTR_COMBINING) { @@ -4061,13 +4076,13 @@ static void wintw_draw_text( len0 = 2; if (len-len0 >= 1 && IS_LOW_VARSEL(text[len0])) { attr &= ~TATTR_COMBINING; - do_text_internal(wgs, x, y, text, len0+1, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len0+1, attr, lattr, truecolour, custom); text += len0+1; len -= len0+1; a = TATTR_COMBINING; } else if (len-len0 >= 2 && IS_HIGH_VARSEL(text[len0], text[len0+1])) { attr &= ~TATTR_COMBINING; - do_text_internal(wgs, x, y, text, len0+2, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len0+2, attr, lattr, truecolour, custom); text += len0+2; len -= len0+2; a = TATTR_COMBINING; @@ -4078,35 +4093,36 @@ static void wintw_draw_text( while (len--) { if (len >= 1 && IS_SURROGATE_PAIR(text[0], text[1])) { do_text_internal(wgs, x, y, text, 2, attr | a, lattr, - truecolour); + truecolour, custom); len--; text++; } else do_text_internal(wgs, x, y, text, 1, attr | a, lattr, - truecolour); + truecolour, custom); text++; a = TATTR_COMBINING; } } else - do_text_internal(wgs, x, y, text, len, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len, attr, lattr, truecolour, custom); } static void wintw_draw_cursor( TermWin *tw, int x, int y, wchar_t *text, int len, - unsigned long attr, int lattr, truecolour truecolour) + unsigned long attr, int lattr, truecolour truecolour, int custom) { WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); int fnt_width; int char_width; int ctype = wgs->cursor_type; + if (custom != -1) { ctype = custom; } lattr &= LATTR_MODE; if ((attr & TATTR_ACTCURS) && (ctype == CURSOR_BLOCK || wgs->term->big_cursor)) { if (*text != UCSWIDE) { - win_draw_text(tw, x, y, text, len, attr, lattr, truecolour); + win_draw_text(tw, x, y, text, len, attr, lattr, truecolour, custom); return; } ctype = CURSOR_VERTICAL_LINE;