From 7ed78a31debb0250bae16d8b4098a4689f29bb60 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Thu, 15 Oct 2026 12:30:14 +0300 Subject: Take the terminal name from term_options.name The core hard-coded "wsap_term" for XTVERSION, the XTGETTCAP TN and name default, and the OSC 9 notification title. A headless library should take its identity from the host. term_options.name sets the name. NULL or "" selects "term". term_new() copies it and returns NULL unless it is 1 to 63 printable ASCII bytes, since DCS replies echo it. A DCS +p still changes the TN value, and the XTVERSION and notification defaults keep the host name. Co-Authored-By: Claude Haiku 5.5 --- src/escape.c | 4 +++- src/internal.h | 2 ++ src/osc/misc.c | 2 +- src/screen.c | 17 ++++++++++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) (limited to 'src') 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 8c02c91..5da114d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -208,6 +208,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/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 87d6f2c..e728cec 100644 --- a/src/screen.c +++ b/src/screen.c @@ -841,12 +841,26 @@ 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; + const char *name = opt->name && *opt->name ? opt->name : "term"; + if (!name_valid(name)) + return NULL; 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) @@ -856,6 +870,7 @@ struct term *term_new(const struct term_options *opt) struct term *t = calloc(1, sizeof(*t)); if (!t) return NULL; + memcpy(t->name, name, strlen(name) + 1); atomic_init(&t->seq, 0); atomic_init(&t->writer_tid, 0); t->write_depth = 0; @@ -902,7 +917,7 @@ struct term *term_new(const struct term_options *opt) 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)); -- cgit v1.2.3