PTYForwardHangupHandler hangup_handler;
void *hangup_userdata;
+ PTYForwardHotkeyHandler hotkey_handler;
+ void *hotkey_userdata;
char *background_color;
AnsiColorState ansi_color_state;
return sd_event_exit(e, rcode < 0 ? EXIT_FAILURE : rcode);
}
-static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) {
- const char *p;
-
+typedef enum RequestOperation {
+ REQUEST_NOP,
+ REQUEST_EXIT,
+ REQUEST_HOTKEY_BASE,
+ REQUEST_HOTKEY_A = REQUEST_HOTKEY_BASE + 'a',
+ REQUEST_HOTKEY_Z = REQUEST_HOTKEY_BASE + 'z',
+ _REQUEST_OPERATION_MAX,
+ _REQUEST_OPERATION_INVALID = -EINVAL,
+} RequestOperation;
+
+static RequestOperation look_for_escape(PTYForward *f, const char *buffer, size_t n) {
assert(f);
assert(buffer);
assert(n > 0);
- for (p = buffer; p < buffer + n; p++) {
+ for (const char *p = buffer; p < buffer + n; p++) {
+
+ switch (*p) {
- /* Check for ^] */
- if (*p == 0x1D) {
+ case 0x1D: { /* Check for ^] */
usec_t nw = now(CLOCK_MONOTONIC);
if (f->escape_counter == 0 || nw > f->escape_timestamp + ESCAPE_USEC) {
(f->escape_counter)++;
if (f->escape_counter >= 3)
- return true;
+ return REQUEST_EXIT;
}
- } else {
+
+ break;
+ }
+
+ case 'a'...'z':
+ if (f->escape_counter == 2 &&
+ now(CLOCK_MONOTONIC) <= f->escape_timestamp + ESCAPE_USEC) {
+ f->escape_timestamp = 0;
+ f->escape_counter = 0;
+ return REQUEST_HOTKEY_BASE + *p;
+ }
+
+ _fallthrough_;
+
+ default:
f->escape_timestamp = 0;
f->escape_counter = 0;
}
}
- return false;
+ return REQUEST_NOP;
}
static bool ignore_vhangup(PTYForward *f) {
} else {
/* Check if ^] has been pressed three times within one second. If we get this we quite
* immediately. */
- if (look_for_escape(f, f->in_buffer + f->in_buffer_full, k))
- return -ECANCELED;
-
+ RequestOperation q = look_for_escape(f, f->in_buffer + f->in_buffer_full, k);
f->in_buffer_full += (size_t) k;
+ if (q < 0)
+ return q;
+ if (q == REQUEST_EXIT)
+ return -ECANCELED;
+ if (q >= REQUEST_HOTKEY_A && q <= REQUEST_HOTKEY_Z && f->hotkey_handler) {
+ r = f->hotkey_handler(f, q - REQUEST_HOTKEY_BASE, f->hotkey_userdata);
+ if (r < 0)
+ return r;
+ }
}
did_something = true;
f->hangup_userdata = userdata;
}
+void pty_forward_set_hotkey_handler(PTYForward *f, PTYForwardHotkeyHandler cb, void *userdata) {
+ assert(f);
+
+ f->hotkey_handler = cb;
+ f->hotkey_userdata = userdata;
+}
+
bool pty_forward_drain(PTYForward *f) {
assert(f);
} PTYForwardFlags;
typedef int (*PTYForwardHangupHandler)(PTYForward *f, int rcode, void *userdata);
+typedef int (*PTYForwardHotkeyHandler)(PTYForward *f, char key, void *userdata);
#define N_PTY_FORWARD_SIGNALS 7
extern const int pty_forward_signals[N_PTY_FORWARD_SIGNALS];
bool pty_forward_get_ignore_vhangup(PTYForward *f);
void pty_forward_set_hangup_handler(PTYForward *f, PTYForwardHangupHandler handler, void *userdata);
+void pty_forward_set_hotkey_handler(PTYForward *f, PTYForwardHotkeyHandler handler, void *userdata);
bool pty_forward_drain(PTYForward *f);