commit f4d3702d4d36569851065eed2e0ca88431bd24a2
Author: Jean-Marc Lasgouttes <[email protected]>
Date: Sun Jul 11 15:19:37 2021 +0200
Create new method TM::tokenizeParagraph
This contains large parts of breakRow, but creates a unique row for the
paragraph.
The parts taken or not in redoParagraph are annotated.
The new method is not used yet.
---
src/TextMetrics.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++++++-----
src/TextMetrics.h | 2 +
2 files changed, 142 insertions(+), 15 deletions(-)
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index a2a3e4b..f14fe1f 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -868,21 +868,142 @@ private:
} // namespace
+
+Row TextMetrics::tokenizeParagraph(pit_type const pit) const
+{
+ Row row;
+ row.pit(pit);
+ Paragraph const & par = text_->getPar(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 body_pos = par.beginOfBody();
+
+ // check for possible inline completion
+ DocIterator const & ic_it = bv_->inlineCompletionPos();
+ pos_type ic_pos = -1;
+ if (ic_it.inTexted() && ic_it.text() == text_ && ic_it.pit() == pit)
+ ic_pos = ic_it.pos();
+
+ // Now we iterate through until we reach the right margin
+ // or the end of the par, then build a representation of the row.
+ pos_type i = 0;
+ FontIterator fi = FontIterator(*this, par, pit, 0);
+ // The real stopping condition is a few lines below.
+ while (true) {
+ // Firstly, check whether there is a bookmark here.
+ if (lyxrc.bookmarks_visibility == LyXRC::BMK_INLINE)
+ 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)
+ break;
+
+ char_type c = par.getChar(i);
+ // The most special cases are handled first.
+ if (par.isInset(i)) {
+ Inset const * ins = par.getInset(i);
+ Dimension dim = bv_->coordCache().insets().dim(ins);
+ row.add(i, ins, dim, *fi, par.lookupChange(i));
+ } else if (c == ' ' && i + 1 == body_pos) {
+ // There is a space at i, but it should not be
+ // added as a separator, because it is just
+ // before body_pos. Instead, insert some spacing to
+ // align text
+ FontMetrics const & fm =
theFontMetrics(text_->labelFont(par));
+ // this is needed to make sure that the row width is
correct
+ row.finalizeLast();
+ int const add = max(fm.width(par.layout().labelsep),
+ labelEnd(pit) - row.width());
+ row.addSpace(i, add, *fi, par.lookupChange(i));
+ } else if (c == '\t')
+ row.addSpace(i, theFontMetrics(*fi).width(from_ascii("
")),
+ *fi, par.lookupChange(i));
+ else if (c == 0x2028 || c == 0x2029) {
+ /**
+ * U+2028 LINE SEPARATOR
+ * U+2029 PARAGRAPH SEPARATOR
+
+ * These are special unicode characters that break
+ * lines/pragraphs. Not handling them lead to trouble
wrt
+ * Qt QTextLayout formatting. We add a visible character
+ * on screen so that the user can see that something is
+ * happening.
+ */
+ row.finalizeLast();
+ // ⤶ U+2936 ARROW POINTING DOWNWARDS THEN CURVING
LEFTWARDS
+ // ¶ U+00B6 PILCROW SIGN
+ char_type const screen_char = (c == 0x2028) ? 0x2936 :
0x00B6;
+ row.add(i, screen_char, *fi, par.lookupChange(i));
+ } else
+ row.add(i, c, *fi, par.lookupChange(i));
+
+ // add inline completion width
+ // draw logically behind the previous character
+ if (ic_pos == i + 1 && !bv_->inlineCompletion().empty()) {
+ docstring const comp = bv_->inlineCompletion();
+ size_t const uniqueTo
=bv_->inlineCompletionUniqueChars();
+ Font f = *fi;
+
+ if (uniqueTo > 0) {
+ f.fontInfo().setColor(Color_inlinecompletion);
+ row.addVirtual(i + 1, comp.substr(0, uniqueTo),
f, Change());
+ }
+ f.fontInfo().setColor(Color_nonunique_inlinecompletion);
+ row.addVirtual(i + 1, comp.substr(uniqueTo), f,
Change());
+ }
+
+ ++i;
+ ++fi;
+ }
+ row.finalizeLast();
+ row.endpos(end);
+
+ // End of paragraph marker. The logic here is almost the
+ // same as in redoParagraph, remember keep them in sync.
+ ParagraphList const & pars = text_->paragraphs();
+ Change const & change = par.lookupChange(i);
+ if ((lyxrc.paragraph_markers || change.changed())
+ && i == end && size_type(pit + 1) < pars.size()) {
+ // add a virtual element for the end-of-paragraph
+ // marker; it is shown on screen, but does not exist
+ // in the paragraph.
+ Font f(text_->layoutFont(pit));
+ f.fontInfo().setColor(Color_paragraphmarker);
+ f.setLanguage(par.getParLanguage(buf.params()));
+ // ¶ U+00B6 PILCROW SIGN
+ row.addVirtual(end, docstring(1, char_type(0x00B6)), f, change);
+ }
+
+ return row;
+}
+
+
/** This is the function where the hard work is done. The code here is
* very sensitive to small changes :) Note that part of the
* intelligence is also in Row::shortenIfNeeded.
*/
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());
+ 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 end = par.size();//
pos_type const pos = row.pos();
- pos_type const body_pos = par.beginOfBody();
+ pos_type const body_pos = par.beginOfBody();//
bool const is_rtl = text_->isRTL(row.pit());
bool need_new_row = false;
@@ -897,14 +1018,14 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
int const width = max_width_ - row.right_margin;
// check for possible inline completion
- DocIterator const & ic_it = bv_->inlineCompletionPos();
- pos_type ic_pos = -1;
- if (ic_it.inTexted() && ic_it.text() == text_ && ic_it.pit() ==
row.pit())
- ic_pos = ic_it.pos();
+ DocIterator const & ic_it = bv_->inlineCompletionPos();//
+ pos_type ic_pos = -1;//
+ if (ic_it.inTexted() && ic_it.text() == text_ && ic_it.pit() ==
row.pit())//
+ ic_pos = ic_it.pos();//
// Now we iterate through until we reach the right margin
// or the end of the par, then build a representation of the row.
- pos_type i = pos;
+ pos_type i =
pos;//---------------------------------------------------vvv
FontIterator fi = FontIterator(*this, par, row.pit(), pos);
// The real stopping condition is a few lines below.
while (true) {
@@ -921,7 +1042,7 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
// 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))
+ if (i >= end || (i != pos && row.width() > width))//^width
break;
char_type c = par.getChar(i);
@@ -976,8 +1097,9 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
}
f.fontInfo().setColor(Color_nonunique_inlinecompletion);
row.addVirtual(i + 1, comp.substr(uniqueTo), f,
Change());
- }
+
}//---------------------------------------------------------------^^^
+ // FIXME: Handle when breaking the rows
// Handle some situations that abruptly terminate the row
// - Before an inset with BreakBefore
// - After an inset with BreakAfter
@@ -1002,6 +1124,7 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
++i;
++fi;
}
+
//--------------------------------------------------------------------vvv
row.finalizeLast();
row.endpos(i);
@@ -1010,7 +1133,7 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
ParagraphList const & pars = text_->paragraphs();
Change const & change = par.lookupChange(i);
if ((lyxrc.paragraph_markers || change.changed())
- && !need_new_row
+ && !need_new_row // not this
&& i == end && size_type(row.pit() + 1) < pars.size()) {
// add a virtual element for the end-of-paragraph
// marker; it is shown on screen, but does not exist
@@ -1025,6 +1148,8 @@ bool TextMetrics::breakRow(Row & row, int const
right_margin) const
// Is there a end-of-paragaph change?
if (i == end && par.lookupChange(end).changed() && !need_new_row)
row.needsChangeBar(true);
+ //--------------------------------------------------------------------^^^
+ // FIXME : nothing below this
// if the row is too large, try to cut at last separator. In case
// of success, reset indication that the row was broken abruptly.
diff --git a/src/TextMetrics.h b/src/TextMetrics.h
index 1501250..1666cd0 100644
--- a/src/TextMetrics.h
+++ b/src/TextMetrics.h
@@ -151,6 +151,8 @@ private:
/// FIXME??
int labelEnd(pit_type const pit) const;
+ Row tokenizeParagraph(pit_type pit) const;
+
/// sets row.end to the pos value *after* which a row should break.
/// for example, the pos after which isNewLine(pos) == true
/// \return true when another row is required (after a newline)
--
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs