summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/escape.c4
-rw-r--r--src/internal.h2
-rw-r--r--src/meson.build6
-rw-r--r--src/osc/misc.c2
-rw-r--r--src/screen.c39
-rw-r--r--src/snapshot.c14
-rw-r--r--src/term.c5
-rw-r--r--src/text.c14
8 files changed, 62 insertions, 24 deletions
diff --git a/src/escape.c b/src/escape.c
index da0449a..dceb7a6 100644
--- a/src/escape.c
+++ b/src/escape.c
@@ -834,7 +834,9 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct
case 'q': {
if (csi->prefix == '>' && !csi->intermediate &&
(!csi->nparams || !csi->params[0])) {
- send_response(t, "\033P>|wsap_term\033\\");
+ char resp[96];
+ snprintf(resp, sizeof(resp), "\033P>|%s\033\\", t->name);
+ send_response(t, resp);
} else if (!csi->prefix && csi->intermediate == ' ') {
term_sc_set_cursor_style(t, csi->nparams > 0 ? csi->params[0] : 0);
}
diff --git a/src/internal.h b/src/internal.h
index d67e67e..676413c 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -209,6 +209,8 @@ struct term {
bool custom_tabs;
char osc_buf[256];
+ /* The host's name. A DCS sequence can change tcap_name, not this. */
+ char name[64];
char tcap_name[64];
char *osc_heap;
diff --git a/src/meson.build b/src/meson.build
index 6ce27ce..7684275 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,5 +1,9 @@
subdir('osc')
+# The SONAME carries the major version. An ABI break bumps it, so an old
+# binary keeps the old library.
+term_soversion = meson.project_version().split('.')[0]
+
# The x86-64 SIMD kernels pick their level at run time (see simd.h), so the
# library needs no ISA flags. -march in c_args sets the lowest level.
term_lib = both_libraries('term',
@@ -23,6 +27,8 @@ term_lib = both_libraries('term',
include_directories: term_private_inc,
dependencies: [m_dep, thread_dep],
gnu_symbol_visibility: 'hidden',
+ version: meson.project_version(),
+ soversion: term_soversion,
install: true
)
diff --git a/src/osc/misc.c b/src/osc/misc.c
index 5d6b506..74b35cf 100644
--- a/src/osc/misc.c
+++ b/src/osc/misc.c
@@ -53,7 +53,7 @@ void term_osc_misc_dispatch(struct term *t, long code, const char *params)
break;
case 9:
if (t->cb.notify && strncmp(params, "4;", 2))
- t->cb.notify(t->cb.ud, "wsap_term", params);
+ t->cb.notify(t->cb.ud, t->name, params);
break;
case 22:
free(t->pointer_shape);
diff --git a/src/screen.c b/src/screen.c
index 82cd6d3..b99948d 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -808,12 +808,11 @@ void term_screen_set_alternate(struct term *t, bool enabled)
}
}
+/* The caller has checked that requested is not negative. */
static int scrollback_lines(int requested)
{
if (requested == 0)
return TERM_SCROLLBACK_DEFAULT;
- if (requested < 0)
- return 0;
return requested > 1000000 ? 1000000 : requested;
}
@@ -841,16 +840,35 @@ bool term_tables_ready(void)
return atomic_load_explicit(&tables_state, memory_order_relaxed) == 2;
}
+/* A name is 1 to 63 printable ASCII bytes. DCS replies echo it. */
+static bool name_valid(const char *s)
+{
+ for (size_t i = 0; s[i]; i++) {
+ unsigned char c = (unsigned char)s[i];
+ if (i >= 63 || c < 0x20 || c > 0x7e)
+ return false;
+ }
+ return true;
+}
+
struct term *term_new(const struct term_options *opt)
{
tables_init();
static const struct term_options defaults;
if (!opt)
opt = &defaults;
- int cols = opt->size.x < 1 ? 80 : opt->size.x;
- int rows = opt->size.y < 1 ? 24 : opt->size.y;
- if (cols > TERM_MAX_COLS)
- cols = TERM_MAX_COLS;
+ for (size_t i = 0; i < sizeof(opt->reserved) / sizeof(opt->reserved[0]); i++)
+ if (opt->reserved[i])
+ return NULL;
+ if (opt->size.x < 0 || opt->size.y < 0 || opt->size.x > TERM_MAX_COLS)
+ return NULL;
+ if (opt->scrollback < 0 || (unsigned)opt->cursor_style > TERM_CURSOR_BAR)
+ return NULL;
+ const char *name = opt->name && *opt->name ? opt->name : "term";
+ if (!name_valid(name))
+ return NULL;
+ int cols = opt->size.x == 0 ? 80 : opt->size.x;
+ int rows = opt->size.y == 0 ? 24 : opt->size.y;
static _Atomic uint64_t next_serial = 1;
struct term *t = calloc(1, sizeof(*t));
@@ -860,6 +878,7 @@ struct term *term_new(const struct term_options *opt)
free(t);
return NULL;
}
+ memcpy(t->name, name, strlen(name) + 1);
atomic_init(&t->writer_tid, 0);
t->write_depth = 0;
t->serial = atomic_fetch_add_explicit(&next_serial, 1, memory_order_relaxed);
@@ -900,14 +919,14 @@ struct term *term_new(const struct term_options *opt)
t->cur_fg = TERM_COLOR_FG;
t->cur_bg = TERM_COLOR_BG;
t->cursor_visible = true;
- t->default_cursor_style = opt->cursor_style > TERM_CURSOR_BAR ? TERM_CURSOR_BLOCK : opt->cursor_style;
+ t->default_cursor_style = opt->cursor_style;
t->default_cursor_blink = !opt->cursor_steady;
t->cursor_style = t->default_cursor_style;
t->cursor_blink = t->default_cursor_blink;
t->autowrap = true;
t->charsets[0] = t->charsets[1] = 'B';
t->saved = term_saved_cursor_initial();
- memcpy(t->tcap_name, "wsap_term", sizeof("wsap_term"));
+ memcpy(t->tcap_name, t->name, sizeof(t->name));
term_tabs_default(t);
t->full_gen = 1;
memset(t->text_width.lo, 0xFF, sizeof(t->text_width.lo));
@@ -1529,10 +1548,8 @@ bool term_resize(struct term *t, struct term_vector2i size)
return false;
int cols = size.x;
int rows = size.y;
- if (cols < 1 || rows < 1)
+ if (cols < 1 || rows < 1 || cols > TERM_MAX_COLS)
return false;
- if (cols > TERM_MAX_COLS)
- cols = TERM_MAX_COLS;
term_write_begin(t);
if (cols == t->cols && rows == t->rows) {
term_write_end(t);
diff --git a/src/snapshot.c b/src/snapshot.c
index 8dbb498..c578f18 100644
--- a/src/snapshot.c
+++ b/src/snapshot.c
@@ -314,34 +314,36 @@ bool term_snapshot_update(struct term_snapshot *s, struct term *t)
const struct term_view *term_snapshot_view(const struct term_snapshot *s)
{
- return &s->view;
+ return s ? &s->view : NULL;
}
const struct term_cell *term_snapshot_row(const struct term_snapshot *s, int y)
{
- if (y < 0 || y >= s->view.size.y)
+ if (!s || y < 0 || y >= s->view.size.y)
return NULL;
return s->cells + (size_t)y * s->view.size.x;
}
uint64_t term_snapshot_row_key(const struct term_snapshot *s, int y)
{
- if (y < 0 || y >= s->view.size.y)
+ if (!s || y < 0 || y >= s->view.size.y)
return 0;
return s->keys[y];
}
struct term_span term_snapshot_row_selection(const struct term_snapshot *s, int y)
{
- if (y < 0 || y >= s->view.size.y)
+ if (!s || y < 0 || y >= s->view.size.y)
return (struct term_span){ 0 };
return s->selection[y];
}
int term_snapshot_cluster(const struct term_snapshot *s, uint32_t text, uint32_t *cps, int cap)
{
+ if (!s)
+ return 0;
if (!(text & TERM_TEXT_CLUSTER)) {
- if (cap > 0)
+ if (cps && cap > 0)
cps[0] = text;
return 1;
}
@@ -350,7 +352,7 @@ int term_snapshot_cluster(const struct term_snapshot *s, uint32_t text, uint32_t
return 0;
int n = (int)s->arena[off];
int copy = n < cap ? n : cap;
- if (copy > 0)
+ if (cps && copy > 0)
memcpy(cps, &s->arena[off + 1], (size_t)copy * sizeof(*cps));
return n;
}
diff --git a/src/term.c b/src/term.c
index 1b16670..bf8f3cf 100644
--- a/src/term.c
+++ b/src/term.c
@@ -8,6 +8,11 @@ const char *term_unicode_version(void)
return UNICODE_DATA_VERSION;
}
+unsigned term_version(void)
+{
+ return TERM_VERSION_CODE;
+}
+
void term_lock(struct term *t)
{
term_write_begin(t);
diff --git a/src/text.c b/src/text.c
index 43c3ef5..a646195 100644
--- a/src/text.c
+++ b/src/text.c
@@ -190,10 +190,11 @@ static inline bool try_text_run(struct term *t, const char *buf, size_t len,
return wrote;
}
+/* The feed flags this build knows. term_feed() rejects any other bit. */
+#define TERM_FEED_KNOWN TERM_FEED_ONLCR
+
static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigned flags)
{
- if (!t || !buf || len == 0)
- return;
t->transport_newline = (flags & TERM_FEED_ONLCR) != 0;
uint16_t cur_flags = term_current_flags(t);
@@ -366,13 +367,16 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
}
}
-void term_feed(struct term *t, const char *buf, size_t len, unsigned flags)
+bool term_feed(struct term *t, const char *buf, size_t len, unsigned flags)
{
- if (!t || !buf || len == 0)
- return;
+ if (!t || (!buf && len > 0) || (flags & ~TERM_FEED_KNOWN))
+ return false;
+ if (len == 0)
+ return true;
term_write_begin(t);
term_feed_inner(t, buf, len, flags);
term_write_end(t);
+ return true;
}
void term_text_repeat(struct term *t, int count)