diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 3e807ffba4..afd9ada647 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1449,6 +1449,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; case LFUN_BOOKMARK_SAVE: + dr.screenUpdate(Update::Force); saveBookmark(convert(to_utf8(cmd.argument()))); break; diff --git a/src/Color.cpp b/src/Color.cpp index 627b62b4a7..6248e67b6a 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -331,8 +331,9 @@ ColorSet::ColorSet() { Color_buttonhoverbg, N_("button background under focus"), "buttonhoverbg", "#C7C7CA", "#C7C7CA", "buttonhoverbg" }, { Color_paragraphmarker, N_("paragraph marker"), "paragraphmarker", grey80, grey40, "paragraphmarker"}, { Color_previewframe, N_("preview frame"), "previewframe", black, Linen, "previewframe"}, - { Color_inherit, N_("inherit"), "inherit", black, Linen, "inherit" }, { Color_regexpframe, N_("regexp frame"), "regexpframe", Green, green, "regexpframe" }, + { Color_bookmark, N_("bookmark"), "bookmark", RoyalBlue, RoyalBlue, "bookmark" }, + { Color_inherit, N_("inherit"), "inherit", black, Linen, "inherit" }, { Color_ignore, N_("ignore"), "ignore", black, Linen, "ignore" }, { Color_ignore, nullptr, nullptr, nullptr, nullptr, nullptr } }; diff --git a/src/ColorCode.h b/src/ColorCode.h index 9badae91b5..c7253ff641 100644 --- a/src/ColorCode.h +++ b/src/ColorCode.h @@ -228,6 +228,8 @@ enum ColorCode { Color_paragraphmarker, /// Preview frame color Color_previewframe, + /// Bookmark indicator color + Color_bookmark, // Logical attributes diff --git a/src/Session.cpp b/src/Session.cpp index f8d611644c..16b6df7c61 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -339,6 +339,20 @@ BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) co } +BookmarksSection::BookmarkPosList +BookmarksSection::bookmarksInPar(FileName const & fn, int const par_id) const +{ + // FIXME: we do not consider the case of bottom_pit. + // This is probably not a problem. + BookmarksSection::BookmarkPosList bip; + for (size_t i = 1; i < bookmarks.size(); ++i) + if (bookmarks[i].filename == fn && bookmarks[i].top_id == par_id) + bip.push_back({i, bookmarks[i].top_pos}); + + return bip; +} + + LastCommandsSection::LastCommandsSection(unsigned int num) : default_num_last_commands(30), absolute_max_last_commands(100) diff --git a/src/Session.h b/src/Session.h index 09e9d7d13d..857e056100 100644 --- a/src/Session.h +++ b/src/Session.h @@ -262,6 +262,12 @@ public: */ BookmarkList & load() { return bookmarks; } + /// + typedef std::vector> BookmarkPosList; + + /// return a list of bookmarks and position for this paragraph + BookmarkPosList bookmarksInPar(support::FileName const & fn, int par_id) const; + private: /// allow 9 regular bookmarks, bookmark 0 is temporary diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 0f2ef90b9d..0f1814cab2 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -30,6 +30,7 @@ #include "MetricsInfo.h" #include "ParagraphParameters.h" #include "RowPainter.h" +#include "Session.h" #include "Text.h" #include "TextClass.h" #include "VSpace.h" @@ -877,6 +878,10 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const { LATTEST(row.empty()); Paragraph const & par = text_->getPar(row.pit()); + Buffer const & buf = text_->inset().buffer(); + BookmarksSection::BookmarkPosList bpl = + theSession().bookmarks().bookmarksInPar(buf.fileName(), par.id()); + pos_type const end = par.size(); pos_type const pos = row.pos(); pos_type const body_pos = par.beginOfBody(); @@ -903,7 +908,23 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const // or the end of the par, then build a representation of the row. pos_type i = pos; FontIterator fi = FontIterator(*this, par, row.pit(), pos); - while (i < end && (i == pos || row.width() <= width)) { + // The real stopping condition is a few lines below. + while (true) { + // Firstly, check whether there is a bookmark here. + for (auto const & bp_p : bpl) + if (bp_p.second == i) { + Font f = *fi; + f.fontInfo().setColor(Color_bookmark); + // ❶ U+2776 DINGBAT NEGATIVE CIRCLED DIGIT ONE + char_type const ch = 0x2775 + bp_p.first; + row.addVirtual(i, docstring(1, ch), f, Change()); + } + + // The stopping condition is here so that the display of a + // bookmark can take place at paragraph start too. + if (i >= end || (i != pos && row.width() > width)) + break; + char_type c = par.getChar(i); // The most special cases are handled first. if (par.isInset(i)) { @@ -997,9 +1018,7 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const // in the paragraph. Font f(text_->layoutFont(row.pit())); f.fontInfo().setColor(Color_paragraphmarker); - BufferParams const & bparams - = text_->inset().buffer().params(); - f.setLanguage(par.getParLanguage(bparams)); + f.setLanguage(par.getParLanguage(buf.params())); // ¶ U+00B6 PILCROW SIGN row.addVirtual(end, docstring(1, char_type(0x00B6)), f, change); } diff --git a/src/frontends/qt/GuiApplication.cpp b/src/frontends/qt/GuiApplication.cpp index 294787ff74..b0ec64ee09 100644 --- a/src/frontends/qt/GuiApplication.cpp +++ b/src/frontends/qt/GuiApplication.cpp @@ -2141,6 +2141,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_BOOKMARK_CLEAR: theSession().bookmarks().clear(); + dr.screenUpdate(Update::Force); break; case LFUN_DEBUG_LEVEL_SET: