summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/meson.build6
-rw-r--r--src/screen.c22
-rw-r--r--src/snapshot.c14
-rw-r--r--src/term.c5
-rw-r--r--src/text.c14
5 files changed, 40 insertions, 21 deletions
diff --git a/src/meson.build b/src/meson.build
index 694ee0e..7223caa 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],
gnu_symbol_visibility: 'hidden',
+ version: meson.project_version(),
+ soversion: term_soversion,
install: true
)
diff --git a/src/screen.c b/src/screen.c
index e728cec..0857f17 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;
}
@@ -858,13 +857,18 @@ struct term *term_new(const struct term_options *opt)
static const struct term_options defaults;
if (!opt)
opt = &defaults;
+ 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 < 1 ? 80 : opt->size.x;
- int rows = opt->size.y < 1 ? 24 : opt->size.y;
- if (cols > TERM_MAX_COLS)
- cols = TERM_MAX_COLS;
+ 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));
@@ -910,7 +914,7 @@ 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;
@@ -1538,10 +1542,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)