]> git.lyx.org Git - lyx.git/blobdiff - src/text2.C
cleanup after svn hang-up, #undef CursorShape. Should be compilable ganin now.
[lyx.git] / src / text2.C
index 27c17921a23f79069954d75d81757cf41f333ba6..09b9a2ce93747ded3f0604b420cb6074e439c1fd 100644 (file)
 
 #include "insets/insetenv.h"
 
+#include "mathed/InsetMathHull.h"
+
 #include "support/textutils.h"
 
 #include <boost/current_function.hpp>
 
 #include <sstream>
 
+using lyx::docstring;
 using lyx::pit_type;
 using lyx::pos_type;
 
 using std::endl;
 using std::ostringstream;
 using std::string;
+using std::max;
 using std::min;
 
 
@@ -88,8 +92,7 @@ void LyXText::init(BufferView * bv)
        for (pit_type pit = 0; pit != end; ++pit)
                pars_[pit].rows().clear();
 
-       current_font = getFont(pars_[0], 0);
-       updateCounters(*bv->buffer());
+       updateLabels(*bv->buffer());
 }
 
 
@@ -172,10 +175,19 @@ LyXFont LyXText::getFont(Paragraph const & par, pos_type const pos) const
                LyXFont f = par.getFontSettings(params, pos);
                if (!isMainText())
                        applyOuterFont(f);
-               if (layout->labeltype == LABEL_MANUAL && pos < body_pos)
-                       return f.realize(layout->reslabelfont);
-               else
-                       return f.realize(layout->resfont);
+               LyXFont lf;
+               LyXFont rlf;
+               if (layout->labeltype == LABEL_MANUAL && pos < body_pos) {
+                       lf = layout->labelfont;
+                       rlf = layout->reslabelfont;
+               } else {
+                       lf = layout->font;
+                       rlf = layout->resfont;
+               }
+               // In case the default family has been customized
+               if (lf.family() == LyXFont::INHERIT_FAMILY)
+                       rlf.setFamily(params.getFont().family());
+               return f.realize(rlf);
        }
 
        // The uncommon case need not be optimized as much
@@ -191,8 +203,24 @@ LyXFont LyXText::getFont(Paragraph const & par, pos_type const pos) const
        if (!isMainText())
                applyOuterFont(font);
 
+       // Find the pit value belonging to paragraph. This will not break
+       // even if pars_ would not be a vector anymore.
+       // Performance appears acceptable.
+
+       pit_type pit = pars_.size();
+       for (pit_type it = 0; it < pit; ++it)
+               if (&pars_[it] == &par) {
+                       pit = it;
+                       break;
+               }
+       // Realize against environment font information
+       // NOTE: the cast to pit_type should be removed when pit_type
+       // changes to a unsigned integer.
+       if (pit < pit_type(pars_.size()))
+               font.realize(outerFont(pit, pars_));
+
        // Realize with the fonts of lesser depth.
-       font.realize(defaultfont_);
+       font.realize(params.getFont());
 
        return font;
 }
@@ -206,7 +234,7 @@ LyXFont LyXText::getFont(Paragraph const & par, pos_type const pos) const
 // font.
 void LyXText::applyOuterFont(LyXFont & font) const {
        LyXFont lf(font_);
-       lf.reduce(defaultfont_);
+       lf.reduce(bv()->buffer()->params().getFont());
        lf.realize(font);
        lf.setLanguage(font.language());
        font = lf;
@@ -217,13 +245,18 @@ LyXFont LyXText::getLayoutFont(pit_type const pit) const
 {
        LyXLayout_ptr const & layout = pars_[pit].layout();
 
-       if (!pars_[pit].getDepth())
-               return layout->resfont;
+       if (!pars_[pit].getDepth())  {
+               LyXFont lf = layout->resfont;
+               // In case the default family has been customized
+               if (layout->font.family() == LyXFont::INHERIT_FAMILY)
+                       lf.setFamily(bv()->buffer()->params().getFont().family());
+               return lf;
+       }
 
        LyXFont font = layout->font;
        // Realize with the fonts of lesser depth.
        //font.realize(outerFont(pit, paragraphs()));
-       font.realize(defaultfont_);
+       font.realize(bv()->buffer()->params().getFont());
 
        return font;
 }
@@ -233,12 +266,17 @@ LyXFont LyXText::getLabelFont(Paragraph const & par) const
 {
        LyXLayout_ptr const & layout = par.layout();
 
-       if (!par.getDepth())
-               return layout->reslabelfont;
+       if (!par.getDepth()) {
+               LyXFont lf = layout->reslabelfont;
+               // In case the default family has been customized
+               if (layout->labelfont.family() == LyXFont::INHERIT_FAMILY)
+                       lf.setFamily(bv()->buffer()->params().getFont().family());
+               return lf;
+       }
 
        LyXFont font = layout->labelfont;
        // Realize with the fonts of lesser depth.
-       font.realize(defaultfont_);
+       font.realize(bv()->buffer()->params().getFont());
 
        return font;
 }
@@ -269,7 +307,12 @@ void LyXText::setCharFont(pit_type pit, pos_type pos, LyXFont const & fnt)
                }
        }
 
-       layoutfont.realize(defaultfont_);
+       // Inside inset, apply the inset's font attributes if any
+       // (charstyle!)
+       if (!isMainText())
+               layoutfont.realize(font_);
+
+       layoutfont.realize(bv()->buffer()->params().getFont());
 
        // Now, reduce font against full layout font
        font.reduce(layoutfont);
@@ -323,8 +366,8 @@ void LyXText::setLayout(LCursor & cur, string const & layout)
        if (lyxlayout->is_environment) {
                // move everything in a new environment inset
                lyxerr[Debug::DEBUG] << "setting layout " << layout << endl;
-               bv.owner()->dispatch(FuncRequest(LFUN_HOME));
-               bv.owner()->dispatch(FuncRequest(LFUN_ENDSEL));
+               bv.owner()->dispatch(FuncRequest(LFUN_LINE_BEGIN));
+               bv.owner()->dispatch(FuncRequest(LFUN_LINE_END_SELECT));
                bv.owner()->dispatch(FuncRequest(LFUN_CUT));
                InsetBase * inset = new InsetEnvironment(params, layout);
                insertInset(cur, inset);
@@ -338,7 +381,7 @@ void LyXText::setLayout(LCursor & cur, string const & layout)
        pit_type undopit = undoSpan(end - 1);
        recUndo(start, undopit - 1);
        setLayout(start, end, layout);
-       updateCounters(cur.buffer());
+       updateLabels(cur.buffer());
 }
 
 
@@ -365,6 +408,10 @@ bool changeDepthAllowed(LyXText::DEPTH_CHANGE type,
 bool LyXText::changeDepthAllowed(LCursor & cur, DEPTH_CHANGE type) const
 {
        BOOST_ASSERT(this == cur.text());
+       // this happens when selecting several cells in tabular (bug 2630)
+       if (cur.selBegin().idx() != cur.selEnd().idx())
+               return false;
+
        pit_type const beg = cur.selBegin().pit();
        pit_type const end = cur.selEnd().pit() + 1;
        int max_depth = (beg != 0 ? pars_[beg - 1].getMaxDepthAfter() : 0);
@@ -399,7 +446,7 @@ void LyXText::changeDepth(LCursor & cur, DEPTH_CHANGE type)
        }
        // this handles the counter labels, and also fixes up
        // depth values for follow-on (child) paragraphs
-       updateCounters(cur.buffer());
+       updateLabels(cur.buffer());
 }
 
 
@@ -456,16 +503,16 @@ void LyXText::setFont(LCursor & cur, LyXFont const & font, bool toggleall)
 // the cursor set functions have a special mechanism. When they
 // realize you left an empty paragraph, they will delete it.
 
-void LyXText::cursorHome(LCursor & cur)
+bool LyXText::cursorHome(LCursor & cur)
 {
        BOOST_ASSERT(this == cur.text());
        Row const & row = cur.paragraph().getRow(cur.pos(),cur.boundary());
 
-       setCursor(cur, cur.pit(), row.pos());
+       return setCursor(cur, cur.pit(), row.pos());
 }
 
 
-void LyXText::cursorEnd(LCursor & cur)
+bool LyXText::cursorEnd(LCursor & cur)
 {
        BOOST_ASSERT(this == cur.text());
        // if not on the last row of the par, put the cursor before
@@ -474,7 +521,7 @@ void LyXText::cursorEnd(LCursor & cur)
        pos_type end = cur.textRow().endpos();
        if (end == 0)
                // empty text, end-1 is no valid position
-               return;
+               return false;
        bool boundary = false;
        if (end != cur.lastpos()) {
                if (!cur.paragraph().isLineSeparator(end-1)
@@ -483,21 +530,21 @@ void LyXText::cursorEnd(LCursor & cur)
                else
                        --end;
        }
-       setCursor(cur, cur.pit(), end, true, boundary);
+       return setCursor(cur, cur.pit(), end, true, boundary);
 }
 
 
-void LyXText::cursorTop(LCursor & cur)
+bool LyXText::cursorTop(LCursor & cur)
 {
        BOOST_ASSERT(this == cur.text());
-       setCursor(cur, 0, 0);
+       return setCursor(cur, 0, 0);
 }
 
 
-void LyXText::cursorBottom(LCursor & cur)
+bool LyXText::cursorBottom(LCursor & cur)
 {
        BOOST_ASSERT(this == cur.text());
-       setCursor(cur, cur.lastpit(), boost::prior(paragraphs().end())->size());
+       return setCursor(cur, cur.lastpit(), boost::prior(paragraphs().end())->size());
 }
 
 
@@ -508,7 +555,7 @@ void LyXText::toggleFree(LCursor & cur, LyXFont const & font, bool toggleall)
        if (font == LyXFont(LyXFont::ALL_IGNORE)) {
                // Could only happen with user style
                cur.message(_("No font change defined. "
-                             "Use Character under the Layout menu to define font change."));
+                                          "Use Character under the Layout menu to define font change."));
                return;
        }
 
@@ -538,10 +585,10 @@ string LyXText::getStringToIndex(LCursor const & cur)
 {
        BOOST_ASSERT(this == cur.text());
 
-       string idxstring;
-       if (cur.selection()) {
+       docstring idxstring;
+       if (cur.selection())
                idxstring = cur.selectionAsString(false);
-       else {
+       else {
                // Try implicit word selection. If there is a change
                // in the language the implicit word selection is
                // disabled.
@@ -556,7 +603,7 @@ string LyXText::getStringToIndex(LCursor const & cur)
                        idxstring = tmpcur.selectionAsString(false);
        }
 
-       return idxstring;
+       return lyx::to_utf8(idxstring);
 }
 
 
@@ -602,7 +649,7 @@ void LyXText::insertInset(LCursor & cur, InsetBase * inset)
 
 
 // needed to insert the selection
-void LyXText::insertStringAsLines(LCursor & cur, string const & str)
+void LyXText::insertStringAsLines(LCursor & cur, docstring const & str)
 {
        cur.buffer().insertStringAsLines(pars_, cur.pit(), cur.pos(),
                                         current_font, str, autoBreakRows_);
@@ -611,9 +658,9 @@ void LyXText::insertStringAsLines(LCursor & cur, string const & str)
 
 // turn double CR to single CR, others are converted into one
 // blank. Then insertStringAsLines is called
-void LyXText::insertStringAsParagraphs(LCursor & cur, string const & str)
+void LyXText::insertStringAsParagraphs(LCursor & cur, docstring const & str)
 {
-       string linestr = str;
+       docstring linestr = str;
        bool newline_inserted = false;
 
        for (string::size_type i = 0, siz = linestr.size(); i < siz; ++i) {
@@ -628,7 +675,7 @@ void LyXText::insertStringAsParagraphs(LCursor & cur, string const & str)
                                linestr[i] = ' ';
                                newline_inserted = true;
                        }
-               } else if (IsPrintable(linestr[i])) {
+               } else if (isPrintable(linestr[i])) {
                        newline_inserted = false;
                }
        }
@@ -672,6 +719,7 @@ void LyXText::setCursor(CursorSlice & cur, pit_type par, pos_type pos)
 void LyXText::setCursorIntern(LCursor & cur,
                              pit_type par, pos_type pos, bool setfont, bool boundary)
 {
+       BOOST_ASSERT(this == cur.text());
        cur.boundary(boundary);
        setCursor(cur.top(), par, pos);
        cur.setTargetX();
@@ -756,8 +804,10 @@ pos_type LyXText::getColumnNearX(pit_type const pit,
                c = bidi.vis2log(vc);
                last_tmpx = tmpx;
                if (body_pos > 0 && c == body_pos - 1) {
+                       string lsep = layout->labelsep;
+                       docstring dlsep(lsep.begin(), lsep.end());
                        tmpx += r.label_hfill +
-                               font_metrics::width(layout->labelsep, getLabelFont(par));
+                               font_metrics::width(dlsep, getLabelFont(par));
                        if (par.isLineSeparator(body_pos - 1))
                                tmpx -= singleWidth(par, body_pos - 1);
                }
@@ -934,7 +984,7 @@ InsetBase * LyXText::editXY(LCursor & cur, int x, int y)
        // This should be just before or just behind the
        // cursor position set above.
        BOOST_ASSERT((pos != 0 && inset == pars_[pit].getInset(pos - 1))
-                    || inset == pars_[pit].getInset(pos));
+                    || inset == pars_[pit].getInset(pos));
        // Make sure the cursor points to the position before
        // this inset.
        if (inset == pars_[pit].getInset(pos - 1))
@@ -1031,7 +1081,10 @@ bool LyXText::cursorUp(LCursor & cur)
        if (!cur.selection()) {
                int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
                LCursor old = cur;
-               editXY(cur, x, y - par.rows()[row].ascent() - 1);
+               // Go to middle of previous row. 16 found to work OK;
+               // 12 = top/bottom margin of display math
+               int const margin = 3 * InsetMathHull::displayMargin() / 2;
+               editXY(cur, x, y - par.rows()[row].ascent() - margin);
                cur.clearSelection();
 
                // This happens when you move out of an inset.
@@ -1077,7 +1130,9 @@ bool LyXText::cursorDown(LCursor & cur)
        if (!cur.selection()) {
                int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
                LCursor old = cur;
-               editXY(cur, x, y + par.rows()[row].descent() + 1);
+               // To middle of next row
+               int const margin = 3 * InsetMathHull::displayMargin() / 2;
+               editXY(cur, x, y + par.rows()[row].descent() + margin);
                cur.clearSelection();
 
                // This happens when you move out of an inset.
@@ -1234,15 +1289,16 @@ bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor & old)
 
        if (oldpar.empty() || (oldpar.size() == 1 && oldpar.isLineSeparator(0))) {
                // Delete old par.
-               recordUndo(old, Undo::ATOMIC, 
-                          old.pit(), min(old.pit() + 1, old.lastpit()));
+               recordUndo(old, Undo::ATOMIC,
+                          max(old.pit() - 1, pit_type(0)),
+                          min(old.pit() + 1, old.lastpit()));
                ParagraphList & plist = old.text()->paragraphs();
-               plist.erase(plist.begin() + old.pit());
+               plist.erase(boost::next(plist.begin(), old.pit()));
 
                // see #warning above
                if (cur.depth() >= old.depth()) {
                        CursorSlice & curslice = cur[old.depth() - 1];
-                       if (&curslice.inset() == &old.inset() 
+                       if (&curslice.inset() == &old.inset()
                            && curslice.pit() > old.pit()) {
                                --curslice.pit();
                                // since a paragraph has been deleted, all the
@@ -1253,7 +1309,11 @@ bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor & old)
                                cur.resetAnchor();
                        }
                }
-               updateCounters(old.buffer());
+               // There is a crash reported by Edwin Leuven (16/04/2006) because of:
+               //ParIterator par_it(old);
+               //updateLabels(old.buffer(), par_it);
+               // So for now we do the full update:
+               updateLabels(old.buffer());
                return true;
        }