Felix Fietkau 8835ecf29b ucode-mod-uline: add support for querying window size from terminal if ioctl fails
This is useful for running the cli on a serial console

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2025-02-28 17:36:01 +01:00

207 lines
4.8 KiB
C

// SPDX-License-Identifier: ISC
/*
* Copyright (C) 2025 Felix Fietkau <nbd@nbd.name>
*/
#ifndef __EDITLINE_PRIVATE_H
#define __EDITLINE_PRIVATE_H
#include <stdio.h>
#define KEY_NUL 0 // ^@ Null character
#define KEY_SOH 1 // ^A Start of heading, = console interrupt
#define KEY_STX 2 // ^B Start of text, maintenance mode on HP console
#define KEY_ETX 3 // ^C End of text
#define KEY_EOT 4 // ^D End of transmission, not the same as ETB
#define KEY_ENQ 5 // ^E Enquiry, goes with ACK; old HP flow control
#define KEY_ACK 6 // ^F Acknowledge, clears ENQ logon hand
#define KEY_BEL 7 // ^G Bell, rings the bell
#define KEY_BS 8 // ^H Backspace, works on HP terminals/computers
#define KEY_HT 9 // ^I Horizontal tab, move to next tab stop
#define KEY_LF 10 // ^J Line Feed
#define KEY_VT 11 // ^K Vertical tab
#define KEY_FF 12 // ^L Form Feed, page eject
#define KEY_CR 13 // ^M Carriage Return
#define KEY_SO 14 // ^N Shift Out, alternate character set
#define KEY_SI 15 // ^O Shift In, resume defaultn character set
#define KEY_DLE 16 // ^P Data link escape
#define KEY_DC1 17 // ^Q XON, with XOFF to pause listings; "okay to send"
#define KEY_DC2 18 // ^R Device control 2, block-mode flow control
#define KEY_DC3 19 // ^S XOFF, with XON is TERM=18 flow control
#define KEY_DC4 20 // ^T Device control 4
#define KEY_NAK 21 // ^U Negative acknowledge
#define KEY_SYN 22 // ^V Synchronous idle
#define KEY_ETB 23 // ^W End transmission block, not the same as EOT
#define KEY_CAN 24 // ^X Cancel line, MPE echoes !!!
#define KEY_EM 25 // ^Y End of medium, Control-Y interrupt
#define KEY_SUB 26 // ^Z Substitute
#define KEY_ESC 27 // ^[ Escape, next character is not echoed
#define KEY_FS 28 // ^\ File separator
#define KEY_GS 29 // ^] Group separator
#define KEY_RS 30 // ^^ Record separator, block-mode terminator
#define KEY_US 31 // ^_ Unit separator
#define KEY_DEL 127 // Delete (not a real control character)
// Types of escape code
enum vt100_escape {
VT100_INCOMPLETE,
VT100_UNKNOWN,
VT100_IGNORE,
VT100_CURSOR_UP,
VT100_CURSOR_DOWN,
VT100_CURSOR_LEFT,
VT100_CURSOR_WORD_LEFT,
VT100_CURSOR_RIGHT,
VT100_CURSOR_WORD_RIGHT,
VT100_CURSOR_POS,
VT100_HOME,
VT100_END,
VT100_INSERT,
VT100_DELETE,
VT100_DELETE_LEFT,
VT100_DELETE_LEFT_WORD,
VT100_PAGE_UP,
VT100_PAGE_DOWN,
};
ssize_t utf8_nsyms(const char *str, size_t len);
enum vt100_escape vt100_esc_decode(const char *str, uint32_t *data);
// helpers:
void __vt100_csi_num(FILE *out, int num, char code);
void __vt100_csi2(FILE *out, char c1, char c2);
void __vt100_esc(FILE *out, char c);
static inline void __vt100_sgr(FILE *out, int code)
{
__vt100_csi2(out, code + '0', 'm');
}
static inline void vt100_attr_reset(FILE *out)
{
__vt100_sgr(out, 0);
}
static inline void vt100_attr_bright(FILE *out)
{
__vt100_sgr(out, 1);
}
static inline void vt100_attr_dim(FILE *out)
{
__vt100_sgr(out, 2);
}
static inline void vt100_attr_underscore(FILE *out)
{
__vt100_sgr(out, 4);
}
static inline void vt100_attr_blink(FILE *out)
{
__vt100_sgr(out, 5);
}
static inline void vt100_attr_reverse(FILE *out)
{
__vt100_sgr(out, 7);
}
static inline void vt100_attr_hidden(FILE *out)
{
__vt100_sgr(out, 8);
}
static inline void vt100_erase_line(FILE *out)
{
__vt100_csi2(out, '2', 'K');
}
static inline void vt100_clear_screen(FILE *out)
{
__vt100_csi2(out, '2', 'J');
}
static inline void vt100_cursor_save(FILE *out)
{
__vt100_esc(out, '7');
}
static inline void vt100_cursor_restore(FILE *out)
{
__vt100_esc(out, '8');
}
static inline void vt100_scroll_up(FILE *out)
{
__vt100_esc(out, 'D');
}
static inline void vt100_scroll_down(FILE *out)
{
__vt100_esc(out, 'M');
}
static inline void vt100_next_line(FILE *out)
{
__vt100_esc(out, 'E');
}
static inline void vt100_cursor_up(FILE *out, int count)
{
__vt100_csi_num(out, count, 'A');
}
static inline void vt100_cursor_down(FILE *out, int count)
{
__vt100_csi_num(out, count, 'B');
}
static inline void vt100_cursor_forward(FILE *out, int count)
{
__vt100_csi_num(out, count, 'C');
}
static inline void vt100_cursor_back(FILE *out, int count)
{
__vt100_csi_num(out, count, 'D');
}
static inline void vt100_cursor_home(FILE *out)
{
__vt100_csi2(out, 'H', 0);
}
static inline void vt100_erase(FILE *out, int count)
{
__vt100_csi_num(out, count, 'P');
}
static inline void vt100_erase_down(FILE *out)
{
__vt100_csi2(out, 'J', 0);
}
static inline void vt100_erase_right(FILE *out)
{
__vt100_csi2(out, 'K', 0);
}
static inline void vt100_ding(FILE *out)
{
fputc(7, out);
fflush(out);
}
static inline void vt100_request_window_size(FILE *out)
{
fputs(
"\e7" /* save cursor position */
"\e[r" /* reset margins */
"\e[999;999H" /* move cursor to bottom right */
"\e[6n" /* report cursor position */
"\e8", /* restore cursor position */
out);
}
#endif