From 66b8da36b811703c77bc528d650cc27d90bd262b Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 2 Nov 2026 22:42:13 +0100 Subject: [PATCH] Use double underscores for italic chat markup --- tools/chatgui/src/message_text.cpp | 13 +++++++------ tools/chatgui/src/message_text.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/chatgui/src/message_text.cpp b/tools/chatgui/src/message_text.cpp index 05e6349a5..7dccd0f33 100644 --- a/tools/chatgui/src/message_text.cpp +++ b/tools/chatgui/src/message_text.cpp @@ -24,7 +24,7 @@ bool MessageText::isCode(int position) const { namespace { struct Marker { - int position, length, kind; // Позиция в строке после escapes; kind: 0=**, 1=*, 2=~~. + int position, length, kind; // Позиция в строке после escapes; kind: 0=**, 1=__, 2=~~. bool open, close; // Открытие/закрытие допустимо только около непустого текста. int nextClose = -1; // Следующий закрывающий маркер того же вида; поиск за O(n). }; @@ -39,19 +39,19 @@ void appendInline(MessageText& result, const QString& source) { while (linkIndex < links.size() && links[linkIndex].start + links[linkIndex].length <= i) ++linkIndex; const bool inLink = linkIndex < links.size() && links[linkIndex].start <= i; const QChar ch = source[i]; - if (!inLink && ch == '\\' && i + 1 < source.size() && QStringLiteral("*~`\\").contains(source[i + 1])) { + if (!inLink && ch == '\\' && i + 1 < source.size() && QStringLiteral("*_~`\\").contains(source[i + 1])) { line += source[i + 1]; i += 2; result.changed = true; continue; } int count = 1; - if (ch == '*' || ch == '~') { + if (ch == '*' || ch == '_' || ch == '~') { while (i + count < source.size() && source[i + count] == ch) ++count; - if ((ch == '*' && count <= 2) || (ch == '~' && count == 2)) { + if (count == 2) { const bool open = !inLink && i + count < source.size() && !source[i + count].isSpace() && (i == 0 || !source[i - 1].isLetterOrNumber()); const bool close = i > 0 && !source[i - 1].isSpace() && (!inLink || i + count == links[linkIndex].start + links[linkIndex].length) && (i + count == source.size() || !source[i + count].isLetterOrNumber()); - markers.append({int(line.size()), count, ch == '~' ? 2 : count == 2 ? 0 : 1, open, close}); + markers.append({int(line.size()), count, ch == '*' ? 0 : ch == '_' ? 1 : 2, open, close}); } } line += source.mid(i, count); i += count; @@ -152,7 +152,8 @@ QSharedPointer formattedMessageText(const QModelIndex& index) const QString type = index.data(MsgContentTypeRole).toString(); if ((!type.isEmpty() && type != "text/plain") || !index.data(MsgInviteLinkRole).toString().isEmpty()) return {}; const QString source = index.data(MsgTextRole).toString(); - if (!source.contains('*') && !source.contains("~~") && !source.contains('`') && !source.contains('\\')) return {}; + if (!source.contains("**") && !source.contains("__") && !source.contains("~~") && !source.contains('`') && !source.contains('\\')) + return {}; // Ограничение учитывает текст ключа, видимый текст и диапазоны; shared pointer жив до конца paint/hit-test. static QCache> cache(8 * 1024 * 1024); if (const auto* cached = cache.object(source)) return *cached; diff --git a/tools/chatgui/src/message_text.h b/tools/chatgui/src/message_text.h index 9281110b3..356dc63d5 100644 --- a/tools/chatgui/src/message_text.h +++ b/tools/chatgui/src/message_text.h @@ -1,4 +1,4 @@ -/* Разметка текста сообщений: **жирный**, *курсив*, ~~зачёркнутый~~ и отдельные строки ```[язык]/```. +/* Разметка текста сообщений: **жирный**, __курсив__, ~~зачёркнутый~~ и отдельные строки ```[язык]/```. * Исходник модели не меняется. GUI-поток получает кешированный видимый текст, ссылки и цвета синтаксиса. * Один QTextLayout используется для размеров, рисования и выделения; clipboard берёт MessageText::text. */ #pragma once