Compare commits

..
Author SHA1 Message Date
deepend 03c4e872c0 Fix timestamps when toggling nick indentation 2026-10-20 15:33:29 -06:00
18 changed files with 89 additions and 247 deletions
+1 -2
View File
@@ -35,7 +35,7 @@ jobs:
libxkbcommon0 \ libxkbcommon0 \
libgtk-3-bin libglib2.0-bin glib-networking shared-mime-info gsettings-desktop-schemas \ libgtk-3-bin libglib2.0-bin glib-networking shared-mime-info gsettings-desktop-schemas \
liblua5.4-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \ liblua5.4-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \
perl python3 python3-minimal python3-dev python3-cffi python3-sphinx mono-devel desktop-file-utils \ perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
breeze-gtk-theme \ breeze-gtk-theme \
patchelf file curl patchelf file curl
@@ -45,7 +45,6 @@ jobs:
rm -rf build rm -rf build
meson setup build \ meson setup build \
--prefix=/usr \ --prefix=/usr \
-Dinstall-docs=true \
-Dtext-frontend=true \ -Dtext-frontend=true \
-Dwith-perl=perl \ -Dwith-perl=perl \
-Dwith-python=python3 \ -Dwith-python=python3 \
+5 -11
View File
@@ -5,14 +5,10 @@ Unicode Emoji 17.0. It is vendored from Debian's
`fonts-noto-color-emoji` 2.051 package, built from the corresponding `fonts-noto-color-emoji` 2.051 package, built from the corresponding
Google Noto Emoji release. Google Noto Emoji release.
By default, GTK builds install this exact file, including Windows Every GTK build installs this exact file: Windows (installer and portable
(installer and portable builds), AppImage, Flatpak, and native Meson/RPM. build files), AppImage, Flatpak and native Meson/RPM builds. It is loaded
Meson packagers can set `-Dinstall-emoji-font=false` to omit the bundled into a private Pango/FreeType font map as `ZoiteChat Emoji`; an older system
font and its installed notices and use system emoji fonts instead. An Noto font cannot replace it. No font is installed globally on Windows.
explicit `ZOITECHAT_EMOJI_FONT` path still enables the private font map
in such builds. With the bundled font, it is registered privately as
`ZoiteChat Emoji`; an older system Noto font cannot replace it. No font
is installed globally on Windows.
Chat windows and the emoji picker share this map. Fontconfig still loads Chat windows and the emoji picker share this map. Fontconfig still loads
system fonts and configuration for ordinary text, and the configured text system fonts and configuration for ordinary text, and the configured text
@@ -33,9 +29,7 @@ directory; Windows resolves it relative to the executable. AppImage sets
ZOITECHAT_EMOJI_FONT="$PWD/data/fonts/NotoColorEmoji.ttf" build/src/fe-gtk/zoitechat ZOITECHAT_EMOJI_FONT="$PWD/data/fonts/NotoColorEmoji.ttf" build/src/fe-gtk/zoitechat
``` ```
An unexpectedly missing or unloadable bundled font logs a warning and retains A missing/unloadable file logs a warning and retains system-font fallback.
system-font fallback. When installation is disabled deliberately, fallback is
quiet unless an explicit `ZOITECHAT_EMOJI_FONT` override is invalid.
CI verifies the installed copy and tests catalog/font coverage; AppImage and CI verifies the installed copy and tests catalog/font coverage; AppImage and
Windows also run the interactive picker regression tests. Native themes, Windows also run the interactive picker regression tests. Native themes,
DPI and different Pango/Cairo versions can still affect pixel-level output. DPI and different Pango/Cairo versions can still affect pixel-level output.
+4 -6
View File
@@ -1,15 +1,13 @@
emoji_font_dir = join_paths(get_option('datadir'), 'fonts', 'zoitechat') emoji_font_dir = join_paths(get_option('datadir'), 'fonts', 'zoitechat')
emoji_font_doc_dir = join_paths(get_option('datadir'), 'doc', 'zoitechat', 'fonts') emoji_font_doc_dir = join_paths(get_option('datadir'), 'doc', 'zoitechat', 'fonts')
if get_option('install-emoji-font') install_data(
install_data(
'NotoColorEmoji.ttf', 'NotoColorEmoji.ttf',
install_dir: emoji_font_dir, install_dir: emoji_font_dir,
) )
install_data( install_data(
'OFL.txt', 'OFL.txt',
'README.md', 'README.md',
install_dir: emoji_font_doc_dir, install_dir: emoji_font_doc_dir,
) )
endif
-6
View File
@@ -71,12 +71,6 @@ Packagers may exclude `docs/_theme/basicstrap/` from the source package.
The default theme continues to build without that directory. No pre-minified The default theme continues to build without that directory. No pre-minified
third-party assets need to be added or rebuilt for this theme. third-party assets need to be added or rebuilt for this theme.
The Meson option `-Dinstall-docs` defaults to `false`, so platforms that
do not ship offline documentation do not need Sphinx just to build ZoiteChat.
Pass `-Dinstall-docs=true` when packaging local HTML documentation. Fedora
and AppImage enable it explicitly; the Debian documentation package can do
the same.
Build with the distribution's `python3-sphinx`. After installing the HTML Build with the distribution's `python3-sphinx`. After installing the HTML
into the package staging directory, use `dh_sphinxdoc` (or `dh --with into the package staging directory, use `dh_sphinxdoc` (or `dh --with
sphinxdoc`) to replace Sphinx's standard JavaScript files with system sphinxdoc`) to replace Sphinx's standard JavaScript files with system
+1 -1
View File
@@ -807,7 +807,7 @@ a.headerlink:focus-visible {
:root { :root {
--page: var(--bg); --page: var(--bg);
--panel: var(--chrome); --panel: var(--chrome);
--font: system-ui, -apple-system, "Segoe UI", "DejaVu Sans", sans-serif; --font: system-ui, -apple-system, "Segoe UI", sans-serif;
} }
.site-header { padding: 0; } .site-header { padding: 0; }
.appearance select { min-height: 0; border-radius: 3px; } .appearance select { min-height: 0; border-radius: 3px; }
+2 -2
View File
@@ -16,7 +16,7 @@
--success: #236741; --success: #236741;
--code: #f2f4f6; --code: #f2f4f6;
--shadow: none; --shadow: none;
--mono: Consolas,"DejaVu Sans Mono","Liberation Mono",monospace; --mono: Consolas,"Liberation Mono",monospace;
} }
html[data-theme=dark] { html[data-theme=dark] {
@@ -45,7 +45,7 @@ body {
margin: 0; margin: 0;
background: var(--bg); background: var(--bg);
color: var(--text); color: var(--text);
font: 15px/1.6 system-ui,-apple-system,"Segoe UI","DejaVu Sans",sans-serif; font: 15px/1.6 system-ui,-apple-system,"Segoe UI",sans-serif;
} }
a { a {
-2
View File
@@ -135,9 +135,7 @@
{{ js_tag(scriptfile) }} {{ js_tag(scriptfile) }}
{%- endif -%} {%- endif -%}
{%- endfor %} {%- endfor %}
{%- if theme_theme_preview|tobool %}
<script type="text/javascript" src="{{ pathto('_static/js/jquery.cookie.min.js', 1) }}"></script> <script type="text/javascript" src="{{ pathto('_static/js/jquery.cookie.min.js', 1) }}"></script>
{%- endif %}
<script type="text/javascript" src="{{ pathto('_static/js/basicstrap.js', 1) }}"></script> <script type="text/javascript" src="{{ pathto('_static/js/basicstrap.js', 1) }}"></script>
<script type="text/javascript"> <script type="text/javascript">
DOCUMENTATION_OPTIONS.FILE_SUFFIX = DOCUMENTATION_OPTIONS.FILE_SUFFIX || '.html'; DOCUMENTATION_OPTIONS.FILE_SUFFIX = DOCUMENTATION_OPTIONS.FILE_SUFFIX || '.html';
-73
View File
@@ -1,73 +0,0 @@
#!/usr/bin/env python3
import os
import shutil
import subprocess
import sys
def prune_unused_local_assets(output_dir):
index_path = os.path.join(output_dir, "index.html")
try:
with open(index_path, "r", encoding="utf-8") as index_file:
index_html = index_file.read()
except OSError:
return
if "bootswatch-" not in index_html:
for bootstrap_version in ("bootstrap2", "bootstrap3"):
css_dir = os.path.join(
output_dir, "_static", "css", bootstrap_version
)
if not os.path.isdir(css_dir):
continue
for filename in os.listdir(css_dir):
if filename.startswith("bootswatch-") and filename.endswith(".css"):
os.remove(os.path.join(css_dir, filename))
if "jquery.cookie.min.js" not in index_html:
js_dir = os.path.join(output_dir, "_static", "js")
for filename in ("jquery.cookie.min.js", "jquery.cookie-1.4.1.min.js"):
path = os.path.join(js_dir, filename)
if os.path.isfile(path):
os.remove(path)
def main():
if len(sys.argv) != 4:
raise SystemExit("usage: build-docs.py SOURCE_DIR OUTPUT_DIR STAMP_FILE")
source_dir = os.path.abspath(sys.argv[1])
output_dir = os.path.abspath(sys.argv[2])
stamp_file = os.path.abspath(sys.argv[3])
doctree_dir = output_dir + ".doctrees"
shutil.rmtree(output_dir, ignore_errors=True)
shutil.rmtree(doctree_dir, ignore_errors=True)
os.makedirs(output_dir, exist_ok=True)
subprocess.run(
[
sys.executable,
"-m",
"sphinx",
"-b",
"html",
"-d",
doctree_dir,
source_dir,
output_dir,
],
check=True,
)
prune_unused_local_assets(output_dir)
with open(stamp_file, "w", encoding="utf-8") as stamp:
stamp.write("built\n")
if __name__ == "__main__":
main()
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/env python3
import os
import shutil
import sys
def main():
if len(sys.argv) != 4:
raise SystemExit("usage: install-docs.py STAMP_FILE SOURCE_DIR DATADIR")
_, source_dir, datadir = sys.argv[1:]
source_dir = os.path.abspath(source_dir)
if not os.path.isfile(sys.argv[1]):
raise SystemExit("documentation build did not produce its stamp file")
if not os.path.isfile(os.path.join(source_dir, "index.html")):
raise SystemExit("documentation build did not produce index.html")
if os.path.isabs(datadir):
destdir = os.environ.get("DESTDIR", "")
if destdir:
data_root = os.path.join(destdir, datadir.lstrip("/\\"))
else:
data_root = datadir
else:
data_root = os.path.join(os.environ["MESON_INSTALL_DESTDIR_PREFIX"], datadir)
destination = os.path.join(data_root, "doc", "zoitechat", "html")
shutil.rmtree(destination, ignore_errors=True)
os.makedirs(os.path.dirname(destination), exist_ok=True)
shutil.copytree(source_dir, destination)
if __name__ == "__main__":
main()
-1
View File
@@ -59,7 +59,6 @@
], ],
"config-opts": [ "config-opts": [
"-Ddbus-service-use-appid=true", "-Ddbus-service-use-appid=true",
"-Dinstall-docs=false",
"-Dwith-perl=perl", "-Dwith-perl=perl",
"-Dwith-python=python3", "-Dwith-python=python3",
"-Dwith-lua=lua" "-Dwith-lua=lua"
-39
View File
@@ -38,15 +38,11 @@ endif
config_h = configuration_data() config_h = configuration_data()
config_h.set('HAVE_GTK_MAC', host_machine.system() == 'darwin' and gtk_mac_dep.found()) config_h.set('HAVE_GTK_MAC', host_machine.system() == 'darwin' and gtk_mac_dep.found())
config_h.set10('ZOITECHAT_INSTALL_EMOJI_FONT', get_option('install-emoji-font'))
config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
config_h.set_quoted('PACKAGE_NAME', meson.project_name()) config_h.set_quoted('PACKAGE_NAME', meson.project_name())
config_h.set_quoted('GETTEXT_PACKAGE', 'zoitechat') config_h.set_quoted('GETTEXT_PACKAGE', 'zoitechat')
config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'),
get_option('datadir'), 'locale')) get_option('datadir'), 'locale'))
config_h.set_quoted('ZOITECHAT_DOCDIR',
join_paths(get_option('prefix'), get_option('datadir'), 'doc', 'zoitechat', 'html')
)
config_h.set10('ENABLE_NLS', true) config_h.set10('ENABLE_NLS', true)
config_h.set_quoted('ZOITECHAT_DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) config_h.set_quoted('ZOITECHAT_DATADIR', join_paths(get_option('prefix'), get_option('datadir')))
@@ -183,41 +179,6 @@ if host_machine.system() == 'darwin'
endif endif
add_project_link_arguments(global_ldflags, language: 'c') add_project_link_arguments(global_ldflags, language: 'c')
if get_option('install-docs')
docs_python = find_program('python3', 'python')
docs_sphinx = run_command(docs_python, '-c', 'import sphinx', check: false)
if docs_sphinx.returncode() != 0
error('Sphinx is required to build the local HTML documentation. Install Sphinx or configure with -Dinstall-docs=false.')
endif
docs_source_dir = join_paths(meson.source_root(), 'docs')
docs_output_dir = join_paths(meson.build_root(), 'docs-html')
docs_build_script = join_paths(docs_source_dir, 'build-docs.py')
docs_install_script = join_paths(docs_source_dir, 'install-docs.py')
docs_target = custom_target(
'html-documentation',
output: 'html-documentation.stamp',
command: [
docs_python,
docs_build_script,
docs_source_dir,
docs_output_dir,
'@OUTPUT@',
],
build_by_default: true,
build_always_stale: true,
)
meson.add_install_script(
docs_python,
docs_install_script,
docs_target,
docs_output_dir,
get_option('datadir'),
)
endif
subdir('src') subdir('src')
if get_option('plugin') if get_option('plugin')
subdir('plugins') subdir('plugins')
-6
View File
@@ -37,12 +37,6 @@ option('install-appdata', type: 'boolean',
option('install-plugin-metainfo', type: 'boolean', value: false, option('install-plugin-metainfo', type: 'boolean', value: false,
description: 'Installs metainfo files for enabled plugins, useful when distros create split packages' description: 'Installs metainfo files for enabled plugins, useful when distros create split packages'
) )
option('install-emoji-font', type: 'boolean', value: true,
description: 'Install the bundled Noto Color Emoji font instead of using system emoji fonts'
)
option('install-docs', type: 'boolean', value: false,
description: 'Build and install the local HTML documentation'
)
# Plugins # Plugins
option('with-checksum', type: 'boolean', option('with-checksum', type: 'boolean',
-3
View File
@@ -15,7 +15,6 @@ BuildRequires: perl
BuildRequires: perl-devel BuildRequires: perl-devel
BuildRequires: python3 BuildRequires: python3
BuildRequires: python3-cffi BuildRequires: python3-cffi
BuildRequires: python3-sphinx
BuildRequires: publicsuffix-list BuildRequires: publicsuffix-list
BuildRequires: xwayland-run BuildRequires: xwayland-run
BuildRequires: weston BuildRequires: weston
@@ -53,7 +52,6 @@ systems.
%build %build
%meson \ %meson \
-Dinstall-docs=true \
-Dtext-frontend=false \ -Dtext-frontend=false \
-Dwith-checksum=true \ -Dwith-checksum=true \
-Dwith-fishlim=true \ -Dwith-fishlim=true \
@@ -96,7 +94,6 @@ xwfb-run -- /usr/bin/meson test -C %{_vpath_builddir} --num-processes %{_smp_bui
%{_datadir}/icons/hicolor/scalable/apps/net.zoite.Zoitechat.svg %{_datadir}/icons/hicolor/scalable/apps/net.zoite.Zoitechat.svg
%{_datadir}/metainfo/net.zoite.Zoitechat.appdata.xml %{_datadir}/metainfo/net.zoite.Zoitechat.appdata.xml
%{_datadir}/metainfo/net.zoite.Zoitechat*.metainfo.xml %{_datadir}/metainfo/net.zoite.Zoitechat*.metainfo.xml
%{_datadir}/doc/zoitechat/html/
%dir %{_libdir}/zoitechat %dir %{_libdir}/zoitechat
%dir %{_libdir}/zoitechat/plugins %dir %{_libdir}/zoitechat/plugins
%dir %{_libdir}/zoitechat/python %dir %{_libdir}/zoitechat/python
-1
View File
@@ -48,7 +48,6 @@ def main() -> None:
"--prefix=/", "--libdir=lib", "--buildtype=release", "-Dgtk-frontend=true", "--prefix=/", "--libdir=lib", "--buildtype=release", "-Dgtk-frontend=true",
"-Dtext-frontend=false", "-Dmac-integration=enabled", "-Ddbus=disabled", "-Dtext-frontend=false", "-Dmac-integration=enabled", "-Ddbus=disabled",
"-Dlibcanberra=disabled", "-Dappindicator=disabled", "-Dinstall-appdata=false", "-Dlibcanberra=disabled", "-Dappindicator=disabled", "-Dinstall-appdata=false",
"-Dinstall-docs=false",
"-Dwith-sysinfo=false", "-Dwith-python=false", "-Dwith-perl=false", "-Dwith-sysinfo=false", "-Dwith-python=false", "-Dwith-perl=false",
"-Dwith-lua=lua", "-Dwith-fishlim=true", "-Dwith-checksum=true", "-Dwith-lua=lua", "-Dwith-fishlim=true", "-Dwith-checksum=true",
"-Dplugin=" + ("false" if args.store_experimental else "true"), "-Dplugin=" + ("false" if args.store_experimental else "true"),
-10
View File
@@ -52,16 +52,6 @@ emoji_font_get_map (void)
return map; return map;
attempted = TRUE; attempted = TRUE;
#if defined(ZOITECHAT_INSTALL_EMOJI_FONT) && !ZOITECHAT_INSTALL_EMOJI_FONT
/* A distribution package can deliberately omit our private font. Keep
* its native/system emoji rendering unless an explicit font is given. */
{
const char *override = g_getenv ("ZOITECHAT_EMOJI_FONT");
if (!override || !*override)
return NULL;
}
#endif
path = emoji_font_path (); path = emoji_font_path ();
if (!path || !g_file_test (path, G_FILE_TEST_IS_REGULAR)) if (!path || !g_file_test (path, G_FILE_TEST_IS_REGULAR))
{ {
-41
View File
@@ -1810,50 +1810,9 @@ menu_ctcpguiopen (void)
editlist_gui_open (NULL, NULL, ctcp_list, buf, "ctcpreply", "ctcpreply.conf", ctcp_help); editlist_gui_open (NULL, NULL, ctcp_list, buf, "ctcpreply", "ctcpreply.conf", ctcp_help);
} }
static char *
menu_find_local_docs (void)
{
char *path;
#ifdef WIN32
char *base_path;
base_path = g_win32_get_package_installation_directory_of_module (NULL);
if (!base_path)
return NULL;
path = g_build_filename (base_path, "share", "doc", "zoitechat", "html", "index.html", NULL);
g_free (base_path);
#else
const char *appdir;
appdir = g_getenv ("APPDIR");
if (appdir && *appdir)
path = g_build_filename (appdir, "usr", "share", "doc", "zoitechat", "html", "index.html", NULL);
else
path = g_build_filename (ZOITECHAT_DOCDIR, "index.html", NULL);
#endif
if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
return path;
g_free (path);
return NULL;
}
static void static void
menu_docs (GtkWidget *wid, gpointer none) menu_docs (GtkWidget *wid, gpointer none)
{ {
char *path;
path = menu_find_local_docs ();
if (path)
{
fe_open_url (path);
g_free (path);
return;
}
fe_open_url ("https://docs.zoitechat.org/en/latest/"); fe_open_url ("https://docs.zoitechat.org/en/latest/");
} }
+65
View File
@@ -211,6 +211,70 @@ static void test_formatting (Fixture *f, gconstpointer data)
"nick a\002bold\002 \035italic\035 \00304,02red\017 \037u\037 \036s\036 \026r\026"); "nick a\002bold\002 \035italic\035 \00304,02red\017 \037u\037 \036s\036 \026r\026");
} }
static void
assert_same_xtext_pixels (cairo_surface_t *a, cairo_surface_t *b)
{
g_assert_cmpint (cairo_image_surface_get_width (a), ==, cairo_image_surface_get_width (b));
g_assert_cmpint (cairo_image_surface_get_height (a), ==, cairo_image_surface_get_height (b));
g_assert_cmpint (cairo_image_surface_get_stride (a), ==, cairo_image_surface_get_stride (b));
g_assert_cmpint (memcmp (cairo_image_surface_get_data (a), cairo_image_surface_get_data (b),
cairo_image_surface_get_stride (a) * cairo_image_surface_get_height (a)), ==, 0);
}
static void
test_timestamp_indent_toggle (Fixture *f, gconstpointer data)
{
xtext_buffer *buf = f->xtext->buffer;
cairo_surface_t *before, *after, *hidden;
char *selection;
int length;
/* Previously indented entries must retain their margin timestamps. */
gtk_xtext_set_indent (f->xtext, TRUE);
gtk_xtext_set_time_stamp (buf, TRUE);
buf->indent = 130;
gtk_xtext_append_indent (buf, (guchar *)"nick", -1, (guchar *)"hello", -1, 1234);
gtk_xtext_recalc_widths (buf, FALSE);
before = snapshot (f, FALSE);
gtk_xtext_set_indent (f->xtext, FALSE);
after = snapshot (f, FALSE);
assert_same_xtext_pixels (before, after);
/* Check that a visible stamp, not just an unchanged blank margin,
* was preserved. */
gtk_xtext_set_time_stamp (buf, FALSE);
hidden = snapshot (f, FALSE);
g_assert_cmpint (memcmp (cairo_image_surface_get_data (after),
cairo_image_surface_get_data (hidden),
cairo_image_surface_get_stride (after) * cairo_image_surface_get_height (after)), !=, 0);
cairo_surface_destroy (hidden);
cairo_surface_destroy (after);
cairo_surface_destroy (before);
/* Entries already containing an inline stamp must not gain a second
* margin stamp after enabling indentation. */
gtk_xtext_clear (buf, 0);
gtk_xtext_set_time_stamp (buf, TRUE);
gtk_xtext_append_wrap (buf, (guchar *)"[12:34] nick hello", -1, 1234, 8);
before = snapshot (f, FALSE);
gtk_xtext_set_indent (f->xtext, TRUE);
after = snapshot (f, FALSE);
assert_same_xtext_pixels (before, after);
cairo_surface_destroy (after);
cairo_surface_destroy (before);
/* The same inline stamp must not be duplicated when copied. */
buf->text_last->mark_start = 0;
buf->text_last->mark_end = buf->text_last->str_len;
buf->last_ent_start = buf->text_last;
buf->last_ent_end = buf->text_last;
f->xtext->selection_buffer = buf;
f->xtext->mark_stamp = TRUE;
selection = gtk_xtext_selection_get_text (f->xtext, &length);
g_assert_cmpstr (selection, ==, "[12:34] nick hello");
g_free (selection);
}
static void select_entries (Fixture *f, textentry *start, textentry *end) static void select_entries (Fixture *f, textentry *start, textentry *end)
{ {
textentry *ent; textentry *ent;
@@ -1078,6 +1142,7 @@ int main (int argc, char **argv)
ADD ("layout/font-isolation", test_font_isolation); ADD ("layout/font-isolation", test_font_isolation);
ADD ("layout/wide-metrics", test_wide_metrics); ADD ("layout/wide-metrics", test_wide_metrics);
ADD ("render/formatting-timestamps", test_formatting); ADD ("render/formatting-timestamps", test_formatting);
ADD ("render/timestamps-after-indent-toggle", test_timestamp_indent_toggle);
ADD ("selection/clipboard", test_selection_and_clipboard); ADD ("selection/clipboard", test_selection_and_clipboard);
ADD ("selection/macos-command-copy", test_macos_chat_copy); ADD ("selection/macos-command-copy", test_macos_chat_copy);
ADD ("search/navigation-regex-clear", test_search); ADD ("search/navigation-regex-clear", test_search);
+6 -2
View File
@@ -2713,7 +2713,7 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
first = FALSE; first = FALSE;
if (ent->mark_end > ent->mark_start) if (ent->mark_end > ent->mark_start)
{ {
if (ent->mark_start == 0 && xtext->mark_stamp) if (ent->mark_start == 0 && xtext->mark_stamp && ent->stamp_len == 0)
{ {
char *stamp; char *stamp;
int len = xtext_get_stamp_str (ent->stamp, &stamp); int len = xtext_get_stamp_str (ent->stamp, &stamp);
@@ -4038,7 +4038,11 @@ gtk_xtext_render_line (GtkXText * xtext, textentry * ent, int line,
xtext_draw_bg (xtext, bg_x, y - xtext->font->ascent, bg_w, xtext->fontsize); xtext_draw_bg (xtext, bg_x, y - xtext->font->ascent, bg_w, xtext->fontsize);
} }
if (entline == 1 && xtext->auto_indent && xtext->buffer->time_stamp && /* Preserve margin stamps across indent changes, including plain
* entries with no inline timestamp. Never draw a second stamp
* for entries that already contain an inline timestamp. */
if (entline == 1 && (xtext->auto_indent || ent->left_len != -1) &&
ent->stamp_len == 0 && xtext->buffer->time_stamp &&
(!xtext->skip_stamp || xtext->mark_stamp || xtext->force_stamp)) (!xtext->skip_stamp || xtext->mark_stamp || xtext->force_stamp))
{ {
char *time_str; char *time_str;