aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/doc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc.c')
-rw-r--r--src/doc.c116
1 files changed, 92 insertions, 24 deletions
diff --git a/src/doc.c b/src/doc.c
index a69896c..a1ebe2c 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2023 Robin Haberkorn
+ * Copyright (C) 2012-2024 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,17 +30,49 @@
#include "doc.h"
static inline teco_doc_scintilla_t *
+teco_doc_scintilla_ref(teco_doc_scintilla_t *doc)
+{
+ if (doc)
+ teco_view_ssm(teco_qreg_view, SCI_ADDREFDOCUMENT, 0, (sptr_t)doc);
+ return doc;
+}
+
+static inline void
+teco_doc_scintilla_release(teco_doc_scintilla_t *doc)
+{
+ if (doc)
+ teco_view_ssm(teco_qreg_view, SCI_RELEASEDOCUMENT, 0, (sptr_t)doc);
+}
+
+TECO_DEFINE_UNDO_OBJECT(doc_scintilla, teco_doc_scintilla_t *,
+ teco_doc_scintilla_ref, teco_doc_scintilla_release);
+
+static inline teco_doc_scintilla_t *
teco_doc_get_scintilla(teco_doc_t *ctx)
{
+ /*
+ * FIXME: Perhaps we should always specify SC_DOCUMENTOPTION_TEXT_LARGE?
+ * SC_DOCUMENTOPTION_STYLES_NONE is unfortunately also not safe to set
+ * always as the Q-Reg might well be used for styling even in batch mode.
+ */
if (G_UNLIKELY(!ctx->doc))
ctx->doc = (teco_doc_scintilla_t *)teco_view_ssm(teco_qreg_view, SCI_CREATEDOCUMENT, 0, 0);
return ctx->doc;
}
-/** @memberof teco_doc_t */
+/**
+ * Edit the given document in the Q-Register view.
+ *
+ * @param ctx The document to edit.
+ * @param default_cp The codepage to configure if the document is new.
+ *
+ * @memberof teco_doc_t
+ */
void
-teco_doc_edit(teco_doc_t *ctx)
+teco_doc_edit(teco_doc_t *ctx, guint default_cp)
{
+ gboolean new_doc = ctx->doc == NULL;
+
teco_view_ssm(teco_qreg_view, SCI_SETDOCPOINTER, 0,
(sptr_t)teco_doc_get_scintilla(ctx));
teco_view_ssm(teco_qreg_view, SCI_SETFIRSTVISIBLELINE, ctx->first_line, 0);
@@ -48,11 +80,39 @@ teco_doc_edit(teco_doc_t *ctx)
teco_view_ssm(teco_qreg_view, SCI_SETSEL, ctx->anchor, (sptr_t)ctx->dot);
/*
- * NOTE: Thanks to a custom Scintilla patch, se representations
+ * NOTE: Thanks to a custom Scintilla patch, representations
* do not get reset after SCI_SETDOCPOINTER, so they have to be
* initialized only once.
*/
//teco_view_set_representations(teco_qreg_view);
+
+ if (new_doc && default_cp != SC_CP_UTF8) {
+ /*
+ * There is a chance the user will see this buffer even if we
+ * are currently in batch mode.
+ */
+ for (gint style = 0; style <= STYLE_LASTPREDEFINED; style++)
+ teco_view_ssm(teco_qreg_view, SCI_STYLESETCHARACTERSET,
+ style, default_cp);
+ /* 0 is used for ALL single-byte encodings */
+ teco_view_ssm(teco_qreg_view, SCI_SETCODEPAGE, 0, 0);
+ } else if (!(teco_view_ssm(teco_qreg_view, SCI_GETLINECHARACTERINDEX, 0, 0)
+ & SC_LINECHARACTERINDEX_UTF32)) {
+ /*
+ * All UTF-8 documents are expected to have a character index.
+ * This allocates nothing if the document is not UTF-8.
+ * But it is reference counted, so it must not be allocated
+ * more than once.
+ *
+ * FIXME: This apparently gets reset with every SCI_SETDOCPOINTER
+ * (although I don't know why and where).
+ * Recalculating it could be inefficient.
+ * The index is reference-counted. Perhaps we could just allocate
+ * one more time, so it doesn't get freed when changing documents.
+ */
+ teco_view_ssm(teco_qreg_view, SCI_ALLOCATELINECHARACTERINDEX,
+ SC_LINECHARACTERINDEX_UTF32, 0);
+ }
}
/** @memberof teco_doc_t */
@@ -68,26 +128,26 @@ teco_doc_undo_edit(teco_doc_t *ctx)
undo__teco_view_ssm(teco_qreg_view, SCI_SETXOFFSET, ctx->xoffset, 0);
undo__teco_view_ssm(teco_qreg_view, SCI_SETFIRSTVISIBLELINE, ctx->first_line, 0);
undo__teco_view_ssm(teco_qreg_view, SCI_SETDOCPOINTER, 0,
- (sptr_t)teco_doc_get_scintilla(ctx));
+ (sptr_t)teco_doc_get_scintilla(ctx));
}
/** @memberof teco_doc_t */
void
-teco_doc_set_string(teco_doc_t *ctx, const gchar *str, gsize len)
+teco_doc_set_string(teco_doc_t *ctx, const gchar *str, gsize len, guint codepage)
{
if (teco_qreg_current)
teco_doc_update(&teco_qreg_current->string, teco_qreg_view);
+ teco_doc_scintilla_release(ctx->doc);
+ ctx->doc = NULL;
+
teco_doc_reset(ctx);
- teco_doc_edit(ctx);
+ teco_doc_edit(ctx, codepage);
- teco_view_ssm(teco_qreg_view, SCI_BEGINUNDOACTION, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_CLEARALL, 0, 0);
teco_view_ssm(teco_qreg_view, SCI_APPENDTEXT, len, (sptr_t)(str ? : ""));
- teco_view_ssm(teco_qreg_view, SCI_ENDUNDOACTION, 0, 0);
if (teco_qreg_current)
- teco_doc_edit(&teco_qreg_current->string);
+ teco_doc_edit(&teco_qreg_current->string, 0);
}
/** @memberof teco_doc_t */
@@ -100,13 +160,13 @@ teco_doc_undo_set_string(teco_doc_t *ctx)
*/
teco_doc_update(ctx, teco_qreg_view);
- if (teco_qreg_current && teco_qreg_current->must_undo) // FIXME
+ if (teco_qreg_current && teco_qreg_current->must_undo && // FIXME
+ ctx == &teco_qreg_current->string)
+ /* load old document into view */
teco_doc_undo_edit(&teco_qreg_current->string);
teco_doc_undo_reset(ctx);
- undo__teco_view_ssm(teco_qreg_view, SCI_UNDO, 0, 0);
-
- teco_doc_undo_edit(ctx);
+ teco_undo_object_doc_scintilla_push(&ctx->doc);
}
/**
@@ -117,33 +177,42 @@ teco_doc_undo_set_string(teco_doc_t *ctx)
* It can be NULL if you are interested only in the string's length.
* Strings must be freed via g_free().
* @param len Where to store the string's length (mandatory).
+ * @param codepage Where to store the document's codepage or NULL
+ * if that information is not necessary.
*
* @see teco_qreg_vtable_t::get_string()
* @memberof teco_doc_t
*/
void
-teco_doc_get_string(teco_doc_t *ctx, gchar **str, gsize *len)
+teco_doc_get_string(teco_doc_t *ctx, gchar **str, gsize *outlen, guint *codepage)
{
if (!ctx->doc) {
if (str)
*str = NULL;
- *len = 0;
+ if (outlen)
+ *outlen = 0;
+ if (codepage)
+ *codepage = teco_default_codepage();
return;
}
if (teco_qreg_current)
teco_doc_update(&teco_qreg_current->string, teco_qreg_view);
- teco_doc_edit(ctx);
+ teco_doc_edit(ctx, teco_default_codepage());
- *len = teco_view_ssm(teco_qreg_view, SCI_GETLENGTH, 0, 0);
+ gsize len = teco_view_ssm(teco_qreg_view, SCI_GETLENGTH, 0, 0);
if (str) {
- *str = g_malloc(*len + 1);
- teco_view_ssm(teco_qreg_view, SCI_GETTEXT, *len + 1, (sptr_t)*str);
+ *str = g_malloc(len + 1);
+ teco_view_ssm(teco_qreg_view, SCI_GETTEXT, len + 1, (sptr_t)*str);
}
+ if (outlen)
+ *outlen = len;
+ if (codepage)
+ *codepage = teco_view_get_codepage(teco_qreg_view);
if (teco_qreg_current)
- teco_doc_edit(&teco_qreg_current->string);
+ teco_doc_edit(&teco_qreg_current->string, 0);
}
/** @memberof teco_doc_t */
@@ -185,6 +254,5 @@ teco_doc_exchange(teco_doc_t *ctx, teco_doc_t *other)
void
teco_doc_clear(teco_doc_t *ctx)
{
- if (ctx->doc)
- teco_view_ssm(teco_qreg_view, SCI_RELEASEDOCUMENT, 0, (sptr_t)ctx->doc);
+ teco_doc_scintilla_release(ctx->doc);
}