diff --git a/misc.c b/misc.c index 9775fccb..ee27cdb6 100644 --- a/misc.c +++ b/misc.c @@ -368,6 +368,7 @@ bool nullseat_verbose_no(Seat *seat) { return false; } bool nullseat_verbose_yes(Seat *seat) { return true; } bool nullseat_interactive_no(Seat *seat) { return false; } bool nullseat_interactive_yes(Seat *seat) { return true; } +bool nullseat_get_cursor_position(Seat *seat, int *x, int *y) { return false; } bool null_lp_verbose_no(LogPolicy *lp) { return false; } bool null_lp_verbose_yes(LogPolicy *lp) { return true; } diff --git a/pscp.c b/pscp.c index 695ace3d..96db467a 100644 --- a/pscp.c +++ b/pscp.c @@ -83,6 +83,7 @@ static const SeatVtable pscp_seat_vt = { nullseat_set_trust_status_vacuously, cmdline_seat_verbose, nullseat_interactive_no, + nullseat_get_cursor_position, }; static Seat pscp_seat[1] = {{ &pscp_seat_vt }}; diff --git a/psftp.c b/psftp.c index 2be47894..99e0e12e 100644 --- a/psftp.c +++ b/psftp.c @@ -65,6 +65,7 @@ static const SeatVtable psftp_seat_vt = { nullseat_set_trust_status_vacuously, cmdline_seat_verbose, nullseat_interactive_yes, + nullseat_get_cursor_position, }; static Seat psftp_seat[1] = {{ &psftp_seat_vt }}; diff --git a/putty.h b/putty.h index 4a67ed14..b08efcfd 100644 --- a/putty.h +++ b/putty.h @@ -918,6 +918,13 @@ struct SeatVtable { * Ask the seat whether it's an interactive program. */ bool (*interactive)(Seat *seat); + + /* + * Return the seat's current idea of where the output cursor is. + * + * Returns true if the seat has a cursor. Returns false if not. + */ + bool (*get_cursor_position)(Seat *seat, int *x, int *y); }; static inline size_t seat_output( @@ -967,6 +974,8 @@ static inline bool seat_verbose(Seat *seat) { return seat->vt->verbose(seat); } static inline bool seat_interactive(Seat *seat) { return seat->vt->interactive(seat); } +static inline bool seat_get_cursor_position(Seat *seat, int *x, int *y) +{ return seat->vt->get_cursor_position(seat, x, y); } /* Unlike the seat's actual method, the public entry point * seat_connection_fatal is a wrapper function with a printf-like API, @@ -1023,6 +1032,7 @@ bool nullseat_verbose_no(Seat *seat); bool nullseat_verbose_yes(Seat *seat); bool nullseat_interactive_no(Seat *seat); bool nullseat_interactive_yes(Seat *seat); +bool nullseat_get_cursor_position(Seat *seat, int *x, int *y); /* * Seat functions provided by the platform's console-application @@ -1607,6 +1617,7 @@ int term_get_userpass_input(Terminal *term, prompts_t *p, bufchain *input); void term_set_trust_status(Terminal *term, bool trusted); void term_keyinput(Terminal *, int codepage, const void *buf, int len); void term_keyinputw(Terminal *, const wchar_t * widebuf, int len); +void term_get_cursor_position(Terminal *term, int *x, int *y); typedef enum SmallKeypadKey { SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN, diff --git a/sesschan.c b/sesschan.c index 1f5d06dd..223c77d7 100644 --- a/sesschan.c +++ b/sesschan.c @@ -199,6 +199,7 @@ static const SeatVtable sesschan_seat_vt = { nullseat_set_trust_status, nullseat_verbose_no, nullseat_interactive_no, + nullseat_get_cursor_position, }; Channel *sesschan_new(SshChannel *c, LogContext *logctx, diff --git a/sshserver.c b/sshserver.c index 97dd9403..daf4c65c 100644 --- a/sshserver.c +++ b/sshserver.c @@ -122,6 +122,7 @@ static const SeatVtable server_seat_vt = { nullseat_set_trust_status, nullseat_verbose_no, nullseat_interactive_no, + nullseat_get_cursor_position, }; static void server_socket_log(Plug *plug, PlugLogType type, SockAddr *addr, diff --git a/terminal.c b/terminal.c index dd6b8a9e..42d42ea3 100644 --- a/terminal.c +++ b/terminal.c @@ -1810,6 +1810,12 @@ void term_set_trust_status(Terminal *term, bool trusted) term->trusted = trusted; } +void term_get_cursor_position(Terminal *term, int *x, int *y) +{ + *x = term->curs.x; + *y = term->curs.y; +} + /* * Set up the terminal for a given size. */ diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 5660ee94..6d964a11 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -373,6 +373,7 @@ static const char *gtk_seat_get_x_display(Seat *seat); static bool gtk_seat_get_windowid(Seat *seat, long *id); #endif static bool gtk_seat_set_trust_status(Seat *seat, bool trusted); +static bool gtk_seat_get_cursor_position(Seat *seat, int *x, int *y); static const SeatVtable gtk_seat_vt = { gtk_seat_output, @@ -399,6 +400,7 @@ static const SeatVtable gtk_seat_vt = { gtk_seat_set_trust_status, nullseat_verbose_yes, nullseat_interactive_yes, + gtk_seat_get_cursor_position, }; static void gtk_eventlog(LogPolicy *lp, const char *string) @@ -5530,3 +5532,13 @@ static bool gtk_seat_set_trust_status(Seat *seat, bool trusted) term_set_trust_status(inst->term, trusted); return true; } + +static bool gtk_seat_get_cursor_position(Seat *seat, int *x, int *y) +{ + GtkFrontend *inst = container_of(seat, GtkFrontend, seat); + if (inst->term) { + term_get_cursor_position(inst->term, x, y); + return true; + } + return false; +} diff --git a/unix/uxplink.c b/unix/uxplink.c index 463c9a60..473a0c4b 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -407,6 +407,7 @@ static const SeatVtable plink_seat_vt = { console_set_trust_status, cmdline_seat_verbose, plink_seat_interactive, + nullseat_get_cursor_position, }; static Seat plink_seat[1] = {{ &plink_seat_vt }}; diff --git a/windows/window.c b/windows/window.c index aff506e3..0a375380 100644 --- a/windows/window.c +++ b/windows/window.c @@ -336,6 +336,7 @@ static void win_seat_connection_fatal(Seat *seat, const char *msg); static void win_seat_update_specials_menu(Seat *seat); static void win_seat_set_busy_status(Seat *seat, BusyStatus status); static bool win_seat_set_trust_status(Seat *seat, bool trusted); +static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y); static const SeatVtable win_seat_vt = { win_seat_output, @@ -358,6 +359,7 @@ static const SeatVtable win_seat_vt = { win_seat_set_trust_status, nullseat_verbose_yes, nullseat_interactive_yes, + win_seat_get_cursor_position, }; static WinGuiSeat wgs = { .seat.vt = &win_seat_vt, .logpolicy.vt = &win_gui_logpolicy_vt }; @@ -5801,3 +5803,9 @@ static bool win_seat_set_trust_status(Seat *seat, bool trusted) term_set_trust_status(term, trusted); return true; } + +static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y) +{ + term_get_cursor_position(term, x, y); + return true; +} diff --git a/windows/winplink.c b/windows/winplink.c index ec9c31e5..304e4873 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -101,6 +101,7 @@ static const SeatVtable plink_seat_vt = { console_set_trust_status, cmdline_seat_verbose, plink_seat_interactive, + nullseat_get_cursor_position, }; static Seat plink_seat[1] = {{ &plink_seat_vt }};