aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-13 00:53:58 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-13 00:53:58 +0300
commit8c6de6cc718debf44f6056a4c34c4fbb13bc5020 (patch)
treea522cb6d5608b3a4ba08fdb8a3f840514eb07281
parent078c1927cffc6514168566c267151a8d6eca7367 (diff)
downloadsciteco-8c6de6cc718debf44f6056a4c34c4fbb13bc5020.tar.gz
allow changing the default clipboard by setting the `~` integer
* It continues to default to 67 (C), which is the system clipboard. But you can now overwrite it e.g. by adding `^^PU~` to the profile. * This fixes a minor memory leak: If you set one of the clipboard registers in the profile (initializing them as plain registers), the clipboard register had been leaked. The clipboard registers now replace any existing register, while at the same time preserving the numeric part. * All remaining Q-Reg table insertions use a new function teco_qreg_table_insert_unique() which adds an assertion, so that we notice any future possible memory leaks.
-rw-r--r--doc/sciteco.7.template11
-rw-r--r--fallback.teco_inibin2141 -> 2221 bytes
-rw-r--r--src/interface-curses/interface.c19
-rw-r--r--src/interface-gtk/interface.c16
-rw-r--r--src/main.c18
-rw-r--r--src/qreg.c75
-rw-r--r--src/qreg.h19
7 files changed, 122 insertions, 36 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template
index ba43ac2..16a54a6 100644
--- a/doc/sciteco.7.template
+++ b/doc/sciteco.7.template
@@ -1591,6 +1591,15 @@ The existence of a clipboard register can thus be checked
in macros to determine whether getting and modifying that
particular clipboard is supported natively.
.br
+If there are multiple clipboard registers, you can choose
+the default one via the ASCII code in the numeric cell of
+register \(lq~\(rq, which defaults to 67 (\(lq~C\(rq).
+For instance if setting \(lq^^PU~\(rq, register \(lq~\(rq
+and register \(lq~P\(rq will refer to the same primary
+clipboard.
+The numeric parts of all the other clipboard registers are
+currently not used by \*(ST.
+.br
\*(ST supports two ways of driving the clipboard on ncurses.
.SCITECO_TOPIC OSC-52 xterm
First of all, there is built-in support for OSC-52 escape sequences,
@@ -1638,8 +1647,6 @@ EOL normalization will take place (if enabled), so that pasting
clipboards does not introduce unexpected EOL sequences.
The Q-Register view's EOL mode will \fBnot\fP be guessed from
the original clipboard contents, though.
-The numeric parts of the clipboard registers are currently
-not used by \*(ST.
.TP
.BI ^K key
Key macro registers as documented in section
diff --git a/fallback.teco_ini b/fallback.teco_ini
index 72c13f7..cee87dc 100644
--- a/fallback.teco_ini
+++ b/fallback.teco_ini
Binary files differ
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c
index 54ed1d6..1b04f47 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -1239,7 +1239,8 @@ teco_interface_init_clipboard(void)
if (rc == PDC_CLIP_SUCCESS)
PDC_freeclipboard(contents);
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new(""));
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new(""), TRUE, NULL);
}
gboolean
@@ -1303,8 +1304,10 @@ get_selection_by_name(const gchar *name)
* (everything gets passed down), but currently we
* only register the three standard registers
* "~", "~P", "~S" and "~C".
+ * (We are never called with "~", though.)
*/
- return g_ascii_tolower(*name) ? : 'c';
+ g_assert(*name != '\0');
+ return g_ascii_tolower(*name);
}
/*
@@ -1503,10 +1506,14 @@ teco_interface_init_clipboard(void)
!teco_qreg_table_find(&teco_qreg_table_globals, "$SCITECO_CLIPBOARD_GET", 22)))
return;
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new(""));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("P"));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("S"));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("C"));
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new(""), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("P"), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("S"), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("C"), TRUE, NULL);
}
gboolean
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index 3d33972..6c22590 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -160,10 +160,14 @@ teco_interface_init(void)
* clipboards/selections are supported on this system,
* so we register only some default ones.
*/
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new(""));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("P"));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("S"));
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new("C"));
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new(""), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("P"), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("S"), TRUE, NULL);
+ teco_qreg_table_replace(&teco_qreg_table_globals,
+ teco_qreg_clipboard_new("C"), TRUE, NULL);
teco_interface.event_queue = g_queue_new();
@@ -606,6 +610,8 @@ teco_interface_cmdline_update(const teco_cmdline_t *cmdline)
static GdkAtom
teco_interface_get_selection_by_name(const gchar *name)
{
+ g_assert(*name != '\0');
+
/*
* We can use gdk_atom_intern() to support arbitrary X11 selection
* names. However, since we cannot find out which selections are
@@ -614,11 +620,9 @@ teco_interface_get_selection_by_name(const gchar *name)
* Checking them here avoids expensive X server roundtrips.
*/
switch (*name) {
- case '\0': return GDK_NONE;
case 'P': return GDK_SELECTION_PRIMARY;
case 'S': return GDK_SELECTION_SECONDARY;
case 'C': return GDK_SELECTION_CLIPBOARD;
- default: break;
}
return gdk_atom_intern(name, FALSE);
diff --git a/src/main.c b/src/main.c
index e57ab6f..1cedb9d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -419,15 +419,20 @@ main(int argc, char **argv)
* DEC TECO has them in the global table, though.
*/
/* search string and status register */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("_", 1));
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_plain_new("_", 1));
/* replacement string register */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("-", 1));
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_plain_new("-", 1));
/* current document's dot (":") */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_dot_new());
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_dot_new());
/* current buffer name and number ("*") */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_bufferinfo_new());
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_bufferinfo_new());
/* current working directory ("$") */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_workingdir_new());
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_workingdir_new());
/* environment defaults and registers */
teco_initialize_environment();
@@ -513,7 +518,8 @@ main(int argc, char **argv)
* If munged file didn't quit, switch into interactive mode
*/
/* commandline replacement string register */
- teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("\e", 1));
+ teco_qreg_table_insert_unique(&teco_qreg_table_globals,
+ teco_qreg_plain_new("\e", 1));
teco_undo_enabled = TRUE;
teco_ring_set_scintilla_undo(TRUE);
diff --git a/src/qreg.c b/src/qreg.c
index 9695f64..91f0deb 100644
--- a/src/qreg.c
+++ b/src/qreg.c
@@ -25,6 +25,8 @@
#include <Scintilla.h>
+//#include <rb3ptr.h>
+
#include "sciteco.h"
#include "string-utils.h"
#include "file-utils.h"
@@ -39,6 +41,7 @@
#include "ring.h"
#include "eol.h"
#include "error.h"
+#include "rb3str.h"
#include "qreg.h"
/**
@@ -794,19 +797,25 @@ teco_qreg_workingdir_new(void)
* the "\e" register also exists.
* Not to mention that environment variable regs also start with dollar.
* Perhaps "~" would be a better choice, although it is also already used?
- * Most logical would be ".", but this should probably map to to Dot and
- * is also ugly to write in practice.
+ * Most logical would be ".", but it is also ugly to write in practice.
* Perhaps "@"...
*/
return teco_qreg_new(&vtable, "$", 1);
}
+static inline gchar
+teco_qreg_clipboard_get_name(const teco_qreg_t *qreg)
+{
+ g_assert(1 <= qreg->head.name.len && qreg->head.name.len <= 2 &&
+ *qreg->head.name.data == '~');
+ return qreg->head.name.len < 2 ? qreg->integer : qreg->head.name.data[1];
+}
+
static gboolean
teco_qreg_clipboard_set_string(teco_qreg_t *qreg, const gchar *str, gsize len,
guint codepage, GError **error)
{
- g_assert(!teco_string_contains(&qreg->head.name, '\0'));
- const gchar *clipboard_name = qreg->head.name.data + 1;
+ gchar clipboard_name[] = {teco_qreg_clipboard_get_name(qreg), '\0'};
if (teco_ed & TECO_ED_AUTOEOL) {
/*
@@ -866,8 +875,7 @@ teco_qreg_clipboard_undo_set_string(teco_qreg_t *qreg, GError **error)
if (!teco_undo_enabled)
return TRUE;
- g_assert(!teco_string_contains(&qreg->head.name, '\0'));
- const gchar *clipboard_name = qreg->head.name.data + 1;
+ gchar clipboard_name[] = {teco_qreg_clipboard_get_name(qreg), '\0'};
/*
* Ownership of str is passed to the undo token.
@@ -885,8 +893,7 @@ static gboolean
teco_qreg_clipboard_get_string(teco_qreg_t *qreg, gchar **str, gsize *len,
guint *codepage, GError **error)
{
- g_assert(!teco_string_contains(&qreg->head.name, '\0'));
- const gchar *clipboard_name = qreg->head.name.data + 1;
+ gchar clipboard_name[] = {teco_qreg_clipboard_get_name(qreg), '\0'};
if (!(teco_ed & TECO_ED_AUTOEOL))
/*
@@ -930,8 +937,7 @@ teco_qreg_clipboard_get_string(teco_qreg_t *qreg, gchar **str, gsize *len,
static gboolean
teco_qreg_clipboard_load(teco_qreg_t *qreg, const gchar *filename, GError **error)
{
- g_assert(!teco_string_contains(&qreg->head.name, '\0'));
- const gchar *clipboard_name = qreg->head.name.data + 1;
+ gchar clipboard_name[] = {teco_qreg_clipboard_get_name(qreg), '\0'};
g_auto(teco_string_t) str = {NULL, 0};
@@ -954,6 +960,12 @@ teco_qreg_clipboard_new(const gchar *name)
teco_qreg_t *qreg = teco_qreg_new(&vtable, "~", 1);
teco_string_append(&qreg->head.name, name, strlen(name));
+ /*
+ * Register "~" is the default clipboard, which defaults to "~C".
+ * This is configurable via the integer cell.
+ */
+ if (qreg->head.name.len == 1)
+ qreg->integer = 'C';
return qreg;
}
@@ -967,9 +979,9 @@ teco_qreg_table_init(teco_qreg_table_t *table, gboolean must_undo)
/* general purpose registers */
for (gchar q = 'A'; q <= 'Z'; q++)
- teco_qreg_table_insert(table, teco_qreg_plain_new(&q, sizeof(q)));
+ teco_qreg_table_insert_unique(table, teco_qreg_plain_new(&q, sizeof(q)));
for (gchar q = '0'; q <= '9'; q++)
- teco_qreg_table_insert(table, teco_qreg_plain_new(&q, sizeof(q)));
+ teco_qreg_table_insert_unique(table, teco_qreg_plain_new(&q, sizeof(q)));
}
/** @memberof teco_qreg_table_t */
@@ -979,10 +991,43 @@ teco_qreg_table_init_locals(teco_qreg_table_t *table, gboolean must_undo)
teco_qreg_table_init(table, must_undo);
/* search mode ("^X") */
- teco_qreg_table_insert(table, teco_qreg_plain_new("\x18", 1));
+ teco_qreg_table_insert_unique(table, teco_qreg_plain_new("\x18", 1));
/* numeric radix ("^R") */
table->radix = teco_qreg_radix_new();
- teco_qreg_table_insert(table, table->radix);
+ teco_qreg_table_insert_unique(table, table->radix);
+}
+
+/**
+ * Insert Q-register into table, possibly replacing a register with the same name.
+ *
+ * This is useful for initializing Q-registers late when the user could have
+ * already created one in the profile.
+ *
+ * @param table Table to insert into
+ * @param qreg Q-Register to insert
+ * @param inherit_int Whether to preserve the numeric part of
+ * any Q-register found in the table.
+ * @param error GError
+ * @return TRUE if error occurred
+ * @memberof teco_qreg_table_t
+ */
+gboolean
+teco_qreg_table_replace(teco_qreg_table_t *table, teco_qreg_t *qreg,
+ gboolean inherit_int, GError **error)
+{
+ teco_qreg_t *found = teco_qreg_table_insert(table, qreg);
+ if (!found)
+ return TRUE;
+
+ teco_int_t v;
+ if (inherit_int &&
+ (!found->vtable->get_integer(found, &v, error) ||
+ !qreg->vtable->set_integer(qreg, v, error)))
+ return FALSE;
+
+ rb3_replace(&found->head.head, &qreg->head.head);
+ teco_qreg_free(found);
+ return TRUE;
}
static inline void
@@ -1409,7 +1454,7 @@ teco_state_qregspec_done(teco_machine_qregspec_t *ctx, GError **error)
case TECO_QREG_OPTIONAL_INIT:
if (!ctx->result) {
ctx->result = teco_qreg_plain_new(ctx->name.data, ctx->name.len);
- teco_qreg_table_insert(ctx->result_table, ctx->result);
+ teco_qreg_table_insert_unique(ctx->result_table, ctx->result);
teco_qreg_table_undo_remove(ctx->result);
}
break;
diff --git a/src/qreg.h b/src/qreg.h
index 7a9e13c..aaadb7a 100644
--- a/src/qreg.h
+++ b/src/qreg.h
@@ -156,7 +156,13 @@ struct teco_qreg_table_t {
void teco_qreg_table_init(teco_qreg_table_t *table, gboolean must_undo);
void teco_qreg_table_init_locals(teco_qreg_table_t *table, gboolean must_undo);
-/** @memberof teco_qreg_table_t */
+/**
+ * Insert Q-Register into table.
+ *
+ * @return If non-NULL a register with the same name as qreg already
+ * existed in table. In this case qreg is __not__ automatically freed.
+ * @memberof teco_qreg_table_t
+ */
static inline teco_qreg_t *
teco_qreg_table_insert(teco_qreg_table_t *table, teco_qreg_t *qreg)
{
@@ -165,6 +171,17 @@ teco_qreg_table_insert(teco_qreg_table_t *table, teco_qreg_t *qreg)
}
/** @memberof teco_qreg_table_t */
+static inline void
+teco_qreg_table_insert_unique(teco_qreg_table_t *table, teco_qreg_t *qreg)
+{
+ G_GNUC_UNUSED teco_qreg_t *found = teco_qreg_table_insert(table, qreg);
+ g_assert(found == NULL);
+}
+
+gboolean teco_qreg_table_replace(teco_qreg_table_t *table, teco_qreg_t *qreg,
+ gboolean inherit_int, GError **error);
+
+/** @memberof teco_qreg_table_t */
static inline teco_qreg_t *
teco_qreg_table_find(teco_qreg_table_t *table, const gchar *name, gsize len)
{