aboutsummaryrefslogtreecommitdiff
path: root/package/utils/ucode-mod-uline/src/uline.h
diff options
context:
space:
mode:
Diffstat (limited to 'package/utils/ucode-mod-uline/src/uline.h')
-rw-r--r--package/utils/ucode-mod-uline/src/uline.h152
1 files changed, 152 insertions, 0 deletions
diff --git a/package/utils/ucode-mod-uline/src/uline.h b/package/utils/ucode-mod-uline/src/uline.h
new file mode 100644
index 0000000000..514675e799
--- /dev/null
+++ b/package/utils/ucode-mod-uline/src/uline.h
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2025 Felix Fietkau <nbd@nbd.name>
+ */
+#ifndef __EDITLINE_H
+#define __EDITLINE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <termios.h>
+#include <stdio.h>
+
+#include <libubox/utils.h>
+
+struct uline_state;
+
+struct linebuf {
+ char *buf;
+ size_t len;
+ size_t bufsize;
+
+ char *prompt;
+ size_t pos;
+ size_t update_pos;
+};
+
+struct pos {
+ int16_t x;
+ int16_t y;
+};
+
+enum uline_event {
+ EDITLINE_EV_CURSOR_UP,
+ EDITLINE_EV_CURSOR_DOWN,
+
+ EDITLINE_EV_WINDOW_CHANGED,
+ EDITLINE_EV_LINE_INPUT,
+
+ EDITLINE_EV_INTERRUPT,
+ EDITLINE_EV_EOF,
+};
+
+struct uline_cb {
+ // called on every key input. return true if handled by callback
+ bool (*key_input)(struct uline_state *s, unsigned char c, unsigned int count);
+
+ void (*event)(struct uline_state *s, enum uline_event ev);
+
+ // line: called on newline, returns true to accept the line, false to keep
+ // editing a multi-line string
+ bool (*line)(struct uline_state *s, const char *str, size_t len);
+
+ // called on any changes to the buffer of the secondary line editor
+ void (*line2_update)(struct uline_state *s, const char *str, size_t len);
+
+ // called on cursor button press during line2 editing
+ // return true to handle in line2, false to handle in primary line
+ bool (*line2_cursor)(struct uline_state *s);
+
+ // called on newline on the secondary line editor
+ // return true to ignore, false to process as primary line newline event
+ bool (*line2_newline)(struct uline_state *s, const char *str, size_t len);
+};
+
+struct uline_state {
+ const struct uline_cb *cb;
+
+ int input;
+ FILE *output;
+
+ int sigwinch_count;
+
+ struct termios orig_termios;
+ bool has_termios;
+
+ struct linebuf line;
+ struct linebuf *line2;
+
+ unsigned int repeat_count;
+ char repeat_char;
+
+ unsigned int rows, cols;
+ struct pos cursor_pos;
+ struct pos end_pos;
+ bool ioctl_winsize;
+ bool full_update;
+ bool stop;
+
+ bool utf8;
+
+ char esc_seq[32];
+ int8_t esc_idx;
+ uint8_t utf8_cont;
+};
+
+void uline_init(struct uline_state *s, const struct uline_cb *cb,
+ int in_fd, FILE *out_stream, bool utf8);
+void uline_poll(struct uline_state *s);
+
+void uline_set_line(struct uline_state *s, const char *str, size_t len);
+void uline_set_prompt(struct uline_state *s, const char *str);
+static inline void
+uline_set_cursor(struct uline_state *s, size_t pos)
+{
+ s->line.pos = pos;
+ if (s->line.pos > s->line.len)
+ s->line.pos = s->line.len;
+}
+static inline void
+uline_get_line(struct uline_state *s, const char **str, size_t *len)
+{
+ if (s->line.buf) {
+ *str = s->line.buf;
+ *len = s->line.len;
+ } else{
+ *str = "";
+ *len = 0;
+ }
+}
+
+
+
+void uline_set_line2(struct uline_state *s, const char *str, size_t len);
+void uline_set_line2_prompt(struct uline_state *s, const char *str);
+static inline void
+uline_set_line2_cursor(struct uline_state *s, size_t pos)
+{
+ if (!s->line2)
+ return;
+
+ s->line2->pos = pos;
+ if (s->line2->pos > s->line2->len)
+ s->line2->pos = s->line2->len;
+}
+static inline void
+uline_get_line2(struct uline_state *s, const char **str, size_t *len)
+{
+ if (s->line2 && s->line2->buf) {
+ *str = s->line2->buf;
+ *len = s->line2->len;
+ } else{
+ *str = "";
+ *len = 0;
+ }
+}
+
+void uline_set_hint(struct uline_state *s, const char *str, size_t len);
+void uline_hide_prompt(struct uline_state *s);
+void uline_refresh_prompt(struct uline_state *s);
+void uline_free(struct uline_state *s);
+
+#endif