commit f4d3702d4d36569851065eed2e0ca88431bd24a2
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
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
lyx-cvs@lists.lyx.org
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to