diff options
Diffstat (limited to 'src/doc.c')
-rw-r--r-- | src/doc.c | 116 |
1 files changed, 92 insertions, 24 deletions
@@ -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); } |