]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView.cpp
Keep dialog connected to cross-ref inset after Apply.
[lyx.git] / src / BufferView.cpp
index bb4175987063f5950e1943684315f46faeeb2148..ec89084de756cf3699efcf3297d2f8d27d75672c 100644 (file)
 #include "insets/InsetRef.h"
 #include "insets/InsetText.h"
 
+#include "mathed/InsetMath.h"
 #include "mathed/MathData.h"
+#include "mathed/MathRow.h"
 
 #include "frontends/alert.h"
+#include "frontends/CaretGeometry.h"
 #include "frontends/Delegates.h"
 #include "frontends/FontMetrics.h"
 #include "frontends/NullPainter.h"
@@ -288,6 +291,8 @@ struct BufferView::Private
        CursorSlice current_row_slice_;
        /// are we hovering something that we can click
        bool clickable_inset_;
+       /// shape of the caret
+       frontend::CaretGeometry caret_geometry_;
 };
 
 
@@ -348,15 +353,15 @@ int BufferView::leftMargin() const
 
 int BufferView::topMargin() const
 {
-       // original value was 20px, which is 0.2in at 100dpi
-       return zoomedPixels(20);
+       // Original value was 20px at 100dpi. For internal buffers like in
+       // advanced search and replace, a value of 5px is enough.
+       return zoomedPixels(buffer().isInternal() ? 5 : 20);
 }
 
 
 int BufferView::bottomMargin() const
 {
-       // original value was 20px, which is 0.2in at 100dpi
-       return zoomedPixels(20);
+       return topMargin();
 }
 
 
@@ -791,23 +796,24 @@ void BufferView::bookmarkEditPosition()
 
 void BufferView::saveBookmark(unsigned int idx)
 {
+       if (buffer().isInternal())
+               return;
+
        // tentatively save bookmark, id and pos will be used to
        // acturately locate a bookmark in a 'live' lyx session.
        // pit and pos will be updated with bottom level pit/pos
        // when lyx exits.
-       if (!buffer_.isInternal()) {
-               theSession().bookmarks().save(
-                       buffer_.fileName(),
-                       d->cursor_.bottom().pit(),
-                       d->cursor_.bottom().pos(),
-                       d->cursor_.paragraph().id(),
-                       d->cursor_.pos(),
-                       idx
-                       );
-               if (idx)
-                       // emit message signal.
-                       message(_("Save bookmark"));
-       }
+       theSession().bookmarks().save(
+               buffer_.fileName(),
+               d->cursor_.bottom().pit(),
+               d->cursor_.bottom().pos(),
+               d->cursor_.paragraph().id(),
+               d->cursor_.pos(),
+               idx
+       );
+       if (idx)
+               // emit message signal.
+               message(_("Save bookmark"));
 }
 
 
@@ -1018,7 +1024,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter)
 void BufferView::makeDocumentClass()
 {
        DocumentClassConstPtr olddc = buffer_.params().documentClassPtr();
-       buffer_.params().makeDocumentClass();
+       buffer_.params().makeDocumentClass(buffer_.isClone(), buffer_.isInternal());
        updateDocumentClass(olddc);
 }
 
@@ -1245,6 +1251,10 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
        }
 
+       case LFUN_COPY:
+               flag.setEnabled(cur.selection());
+               break;
+
        default:
                return false;
        }
@@ -1443,6 +1453,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                break;
 
        case LFUN_BOOKMARK_SAVE:
+               dr.screenUpdate(Update::Force);
                saveBookmark(convert<unsigned int>(to_utf8(cmd.argument())));
                break;
 
@@ -1619,6 +1630,8 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data));
                if (found)
                        dr.screenUpdate(Update::Force | Update::FitCursor);
+               else
+                       dr.setMessage(_("Search string not found!"));
                break;
        }
 
@@ -1632,29 +1645,20 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                }
                if (lyxfind(this, req))
                        dr.screenUpdate(Update::Force | Update::FitCursor);
+               else
+                       dr.setMessage(_("Search string not found!"));
 
                d->search_request_cache_ = req;
                break;
        }
 
        case LFUN_WORD_REPLACE: {
-               bool has_deleted = false;
-               if (cur.selection()) {
-                       DocIterator beg = cur.selectionBegin();
-                       DocIterator end = cur.selectionEnd();
-                       if (beg.pit() == end.pit()) {
-                               for (pos_type p = beg.pos() ; p < end.pos() ; ++p) {
-                                       if (!cur.inMathed() && cur.paragraph().isDeleted(p)) {
-                                               has_deleted = true;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               if (lyxreplace(this, cmd, has_deleted)) {
+               if (lyxreplace(this, cmd)) {
                        dr.forceBufferUpdate();
                        dr.screenUpdate(Update::Force | Update::FitCursor);
                }
+               else
+                       dr.setMessage(_("Search string not found!"));
                break;
        }
 
@@ -2174,6 +2178,11 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                break;
        }
 
+       case LFUN_COPY:
+               cap::copySelection(cur);
+               cur.message(_("Copy"));
+               break;
+
        default:
                // OK, so try the Buffer itself...
                buffer_.dispatch(cmd, dr);
@@ -3065,10 +3074,93 @@ void BufferView::caretPosAndDim(Point & p, Dimension & dim) const
                dim.wid = lyxrc.cursor_width;
 
        p = getPos(cur);
+       // center fat carets horizontally
+       p.x_ -= dim.wid / 2;
+       // p is top-left
        p.y_ -= dim.asc;
 }
 
 
+void BufferView::buildCaretGeometry(bool complet)
+{
+       Point p;
+       Dimension dim;
+       caretPosAndDim(p, dim);
+
+       Cursor const & cur = d->cursor_;
+       Font const & realfont = cur.real_current_font;
+       frontend::FontMetrics const & fm = theFontMetrics(realfont.fontInfo());
+       bool const isrtl = realfont.isVisibleRightToLeft();
+       int const dir = isrtl ? -1 : 1;
+
+       frontend::CaretGeometry & cg = d->caret_geometry_;
+       cg.shapes.clear();
+
+       // The caret itself, slanted for italics in text edit mode except
+       // for selections because the selection rect does not slant
+       bool const slant = fm.italic() && cur.inTexted() && !cur.selection();
+       double const slope = slant ? fm.italicSlope() : 0;
+       cg.shapes.push_back(
+               {{iround(p.x_ + dim.asc * slope), p.y_},
+                {iround(p.x_ - dim.des * slope), p.y_ + dim.height()},
+                {iround(p.x_ + dir * dim.wid - dim.des * slope), p.y_ + dim.height()},
+                {iround(p.x_ + dir * dim.wid + dim.asc * slope), p.y_}}
+               );
+
+       // The language indicator _| (if needed)
+       Language const * doclang = buffer().params().language;
+       if (!((realfont.language() == doclang && isrtl == doclang->rightToLeft())
+                 || realfont.language() == latex_language)) {
+               int const lx = dim.height() / 3;
+               int const xx = iround(p.x_ - dim.des * slope);
+               int const yy = p.y_ + dim.height();
+               cg.shapes.push_back(
+                       {{xx, yy - dim.wid},
+                        {xx + dir * (dim.wid + lx - 1), yy - dim.wid},
+                        {xx + dir * (dim.wid + lx - 1), yy},
+                        {xx, yy}}
+                       );
+       }
+
+       // The completion triangle |> (if needed)
+       if (complet) {
+               int const m = p.y_ + dim.height() / 2;
+               int const d = dim.height() / 8;
+               // offset for slanted carret
+               int const sx = iround((dim.asc - (dim.height() / 2 - d)) * slope);
+               // starting position x
+               int const xx = p.x_ + dir * dim.wid + sx;
+               cg.shapes.push_back(
+                       {{xx, m - d},
+                        {xx + dir * d, m},
+                        {xx, m + d},
+                        {xx, m + d - dim.wid},
+                        {xx + dir * d - dim.wid, m},
+                        {xx, m - d + dim.wid}}
+                       );
+       }
+
+       // compute extremal x values
+       cg.left = 1000000;
+       cg.right = -1000000;
+       cg.top = 1000000;
+       cg.bottom = -1000000;
+       for (auto const & shape : cg.shapes)
+               for (Point const & p : shape) {
+                       cg.left = min(cg.left, p.x_);
+                       cg.right = max(cg.right, p.x_);
+                       cg.top = min(cg.top, p.y_);
+                       cg.bottom = max(cg.bottom, p.y_);
+               }
+}
+
+
+frontend::CaretGeometry const &  BufferView::caretGeometry() const
+{
+       return d->caret_geometry_;
+}
+
+
 bool BufferView::caretInView() const
 {
        if (!paragraphVisible(cursor()))
@@ -3293,8 +3385,17 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret)
         * move at all
         */
        if (paint_caret) {
-               Row const & caret_row = d->cursor_.textRow();
-               caret_row.changed(true);
+               Cursor cur(d->cursor_);
+               while (cur.depth() > 1) {
+                       if (!cur.inTexted())
+                               break;
+                       TextMetrics const & tm = textMetrics(cur.text());
+                       if (d->caret_geometry_.left >= tm.origin().x_
+                               && d->caret_geometry_.right <= tm.origin().x_ + tm.dim().width())
+                               break;
+                       cur.pop();
+               }
+               cur.textRow().changed(true);
        }
 }