]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView.cpp
Fix RTL inset painting.
[lyx.git] / src / BufferView.cpp
index 9a66db40140db5e8363898f3d2f6d585608553c7..cd147154b436fc941c3315f2429e1e0282610a44 100644 (file)
@@ -339,6 +339,7 @@ void BufferView::scrollDocView(int value)
        int const h = tm.parMetrics(anchor_ref_).height();
        offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h);
        updateMetrics(false);
+       buffer_.changed();
 }
 
 
@@ -477,7 +478,7 @@ void BufferView::translateAndInsert(char_type c, Text * t, Cursor & cur)
                                intl_->keyMapPrim();
                }
        }
-       
+
        intl_->getTransManager().translateAndInsert(c, t, cur);
 }
 
@@ -592,6 +593,18 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
                break;
        }
 
+       case LFUN_SCREEN_UP:
+       case LFUN_SCREEN_DOWN:
+               flag.enabled(true);
+               break;
+
+       // FIXME: LFUN_SCREEN_DOWN_SELECT should be removed from
+       // everywhere else before this can enabled:
+       case LFUN_SCREEN_UP_SELECT:
+       case LFUN_SCREEN_DOWN_SELECT:
+               flag.enabled(false);
+               break;
+
        default:
                flag.enabled(false);
        }
@@ -935,6 +948,47 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                break;
        }
 
+       case LFUN_SCREEN_UP:
+       case LFUN_SCREEN_DOWN: {
+               Point p = bv_funcs::getPos(*this, cur, cur.boundary());
+               if (p.y_ < 0 || p.y_ > height_) {
+                       // The cursor is off-screen so recenter before proceeding.
+                       center();
+                       updateMetrics(false);
+                       //FIXME: updateMetrics() does not update paragraph position
+                       // This is done at draw() time. So we need a redraw!
+                       buffer_.changed();
+                       p = bv_funcs::getPos(*this, cur, cur.boundary());
+               }
+               scroll(cmd.action == LFUN_SCREEN_UP? - height_ : height_);
+               cur.reset(buffer_.inset());
+               text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
+               //FIXME: what to do with cur.x_target()?
+               finishUndo();
+               // The metrics are already up to date. see scroll()
+               updateFlags = Update::None;
+               break;
+       }
+
+       case LFUN_SCREEN_UP_SELECT:
+       case LFUN_SCREEN_DOWN_SELECT: {
+               cur.selHandle(true);
+               size_t initial_depth = cur.depth();
+               Point const p = bv_funcs::getPos(*this, cur, cur.boundary());
+               scroll(cmd.action == LFUN_SCREEN_UP_SELECT? - height_ : height_);
+               // FIXME: We need to verify if the cursor stayed within an inset...
+               //cur.reset(buffer_.inset());
+               text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
+               finishUndo();
+               while (cur.depth() > initial_depth) {
+                       cur.forwardInset();
+               }
+               // FIXME: we need to do a redraw again because of the selection
+               buffer_.changed();
+               updateFlags = Update::Force | Update::FitCursor;
+               break;
+       }
+
        default:
                updateFlags = Update::None;
        }
@@ -991,49 +1045,30 @@ void BufferView::resize(int width, int height)
 
 Inset const * BufferView::getCoveringInset(Text const & text, int x, int y)
 {
-       pit_type pit = text_metrics_[&text].getPitNearY(y);
-       BOOST_ASSERT(pit != -1);
-       Paragraph const & par = text.getPar(pit);
-
-       LYXERR(Debug::DEBUG)
-               << BOOST_CURRENT_FUNCTION
-               << ": x: " << x
-               << " y: " << y
-               << "  pit: " << pit
-               << endl;
-       InsetList::const_iterator iit = par.insetlist.begin();
-       InsetList::const_iterator iend = par.insetlist.end();
-       for (; iit != iend; ++iit) {
-               Inset * const inset = iit->inset;
-               if (inset->covers(*this, x, y)) {
-                       if (!inset->descendable())
-                               // No need to go further down if the inset is not
-                               // descendable.
-                               return inset;
-
-                       size_t cell_number = inset->nargs();
-                       // Check all the inner cell.
-                       for (size_t i = 0; i != cell_number; ++i) {
-                               Text const * inner_text = inset->getText(i);
-                               if (inner_text) {
-                                       // Try deeper.
-                                       Inset const * inset_deeper =
-                                               getCoveringInset(*inner_text, x, y);
-                                       if (inset_deeper)
-                                               return inset_deeper;
-                               }
-                       }
-
-                       LYXERR(Debug::DEBUG)
-                               << BOOST_CURRENT_FUNCTION
-                               << ": Hit inset: " << inset << endl;
-                       return inset;
+       TextMetrics & tm = text_metrics_[&text];
+       Inset * inset = tm.checkInsetHit(x, y);
+       if (!inset)
+               return 0;
+
+       if (!inset->descendable())
+               // No need to go further down if the inset is not
+               // descendable.
+               return inset;
+
+       size_t cell_number = inset->nargs();
+       // Check all the inner cell.
+       for (size_t i = 0; i != cell_number; ++i) {
+               Text const * inner_text = inset->getText(i);
+               if (inner_text) {
+                       // Try deeper.
+                       Inset const * inset_deeper =
+                               getCoveringInset(*inner_text, x, y);
+                       if (inset_deeper)
+                               return inset_deeper;
                }
        }
-       LYXERR(Debug::DEBUG)
-               << BOOST_CURRENT_FUNCTION
-               << ": No inset hit. " << endl;
-       return 0;
+
+       return inset;
 }
 
 
@@ -1074,38 +1109,28 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
                        // Highlighted the newly hovered inset (if any).
                        need_redraw |= inset->setMouseHover(true);
                last_inset_ = inset;
+               if (!need_redraw)
+                       return false;
 
                // if last metrics update was in singlepar mode, WorkArea::redraw() will
                // not expose the button for redraw. We adjust here the metrics dimension
                // to enable a full redraw.
-               // FIXME: It is possible to redraw only the area around the button!
-               if (need_redraw
-                       && metrics_info_.update_strategy == SingleParUpdate) {
-                       // FIXME: It should be possible to redraw only the area around
-                       // the button by doing this:
-                       //
-                       //metrics_info_.singlepar = false;
-                       //metrics_info_.y1 = ymin of button;
-                       //metrics_info_.y2 = ymax of button;
-                       //
-                       // Unfortunately, BufferView::draw() does not distinguish
-                       // between background updates and text updates. So we use the hammer
-                       // solution for now. We could also avoid the updateMetrics() below
-                       // by using the first and last pit of the CoordCache. Have a look
-                       // at Text::getPitNearY() to see what I mean.
-                       //
-                       //metrics_info_.pit1 = first pit of CoordCache;
-                       //metrics_info_.pit2 = last pit of CoordCache;
-                       //metrics_info_.singlepar = false;
-                       //metrics_info_.y1 = 0;
-                       //metrics_info_.y2 = height_;
-                       //
-                       updateMetrics(false);
+               if (metrics_info_.update_strategy == SingleParUpdate) {
+                       // Build temporary cursor.
+                       TextMetrics & tm = text_metrics_[&buffer_.text()];
+                       tm.editXY(cur, cmd.x, cmd.y);
+                       // collect cursor paragraph iter bounds
+                       std::pair<pit_type, ParagraphMetrics const *> firstpm = tm.first();
+                       std::pair<pit_type, ParagraphMetrics const *> lastpm = tm.last();
+                       int y1 = firstpm.second->position() - firstpm.second->ascent();
+                       int y2 = lastpm.second->position() + lastpm.second->descent();
+                       metrics_info_ = ViewMetricsInfo(firstpm.first, lastpm.first, y1, y2,
+                               FullScreenUpdate, buffer_.text().paragraphs().size());
                }
 
                // This event (moving without mouse click) is not passed further.
                // This should be changed if it is further utilized.
-               return need_redraw;
+               return true;
        }
 
        // Build temporary cursor.
@@ -1138,20 +1163,60 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
 }
 
 
-void BufferView::scroll(int /*lines*/)
+void BufferView::scroll(int y)
 {
-//     Text const * t = buffer_.text();
-//     int const line_height = defaultRowHeight();
-//
-//     // The new absolute coordinate
-//     int new_top_y = top_y() + lines * line_height;
-//
-//     // Restrict to a valid value
-//     new_top_y = std::min(t->height() - 4 * line_height, new_top_y);
-//     new_top_y = std::max(0, new_top_y);
-//
-//     scrollDocView(new_top_y);
-//
+       if (y > 0)
+               scrollDown(y);
+       else if (y < 0)
+               scrollUp(-y);
+}
+
+
+void BufferView::scrollDown(int offset)
+{
+       Text * text = &buffer_.text();
+       TextMetrics & tm = text_metrics_[text];
+       int ymax = height_ + offset;
+       while (true) {
+               std::pair<pit_type, ParagraphMetrics const *> last = tm.last();
+               int bottom_pos = last.second->position() + last.second->descent();
+               if (last.first == text->paragraphs().size() - 1) {
+                       if (bottom_pos <= height_)
+                               return;
+                       offset = min(offset, bottom_pos - height_);
+                       break;
+               }
+               if (bottom_pos > ymax)
+                       break;
+               tm.newParMetricsDown();
+       }
+       offset_ref_ += offset;
+       updateMetrics(false);
+       buffer_.changed();
+}
+
+
+void BufferView::scrollUp(int offset)
+{
+       Text * text = &buffer_.text();
+       TextMetrics & tm = text_metrics_[text];
+       int ymin = - offset;
+       while (true) {
+               std::pair<pit_type, ParagraphMetrics const *> first = tm.first();
+               int top_pos = first.second->position() - first.second->ascent();
+               if (first.first == 0) {
+                       if (top_pos >= 0)
+                               return;
+                       offset = min(offset, - top_pos);
+                       break;
+               }
+               if (top_pos < ymin)
+                       break;
+               tm.newParMetricsUp();
+       }
+       offset_ref_ -= offset;
+       updateMetrics(false);
+       buffer_.changed();
 }
 
 
@@ -1253,7 +1318,7 @@ bool BufferView::mouseSetCursor(Cursor & cur)
 {
        BOOST_ASSERT(&cur.bv() == this);
 
-        // this event will clear selection so we save selection for
+       // this event will clear selection so we save selection for
        // persistent selection
        cap::saveSelection(cursor());
 
@@ -1351,7 +1416,7 @@ void BufferView::updateMetrics(bool singlepar)
        if (!singlepar) {
                // Clear out the position cache in case of full screen redraw,
                coord_cache_.clear();
-       
+
                // Clear out paragraph metrics to avoid having invalid metrics
                // in the cache from paragraphs not relayouted below
                // The complete text metrics will be redone.
@@ -1510,7 +1575,7 @@ void BufferView::menuInsertLyXFile(string const & filenm)
                el = buf.errorList("Parse");
                recordUndo(cursor_);
                cap::pasteParagraphList(cursor_, buf.paragraphs(),
-                                            buf.params().getTextClass_ptr(), el);
+                                            buf.params().getTextClassPtr(), el);
                res = _("Document %1$s inserted.");
        } else
                res = _("Could not insert document %1$s");
@@ -1549,13 +1614,13 @@ void BufferView::draw(frontend::Painter & pain)
 
        // and grey out above (should not happen later)
 //     lyxerr << "par ascent: " << text.getPar(metrics_info_.p1).ascent() << endl;
-       if (metrics_info_.y1 > 0 
+       if (metrics_info_.y1 > 0
                && metrics_info_.update_strategy == FullScreenUpdate)
                pain.fillRectangle(0, 0, width_, metrics_info_.y1, Color::bottomarea);
 
        // and possibly grey out below
 //     lyxerr << "par descent: " << text.getPar(metrics_info_.p1).ascent() << endl;
-       if (metrics_info_.y2 < height_ 
+       if (metrics_info_.y2 < height_
                && metrics_info_.update_strategy == FullScreenUpdate)
                pain.fillRectangle(0, metrics_info_.y2, width_,
                        height_ - metrics_info_.y2, Color::bottomarea);