CoordBranch merge

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@9325 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Alfredo Braunstein 2004-11-30 01:59:49 +00:00
parent e171a6a69f
commit a2cd656e25
56 changed files with 1670 additions and 1342 deletions

View File

@ -21,6 +21,7 @@
#include "bufferparams.h"
#include "BufferView_pimpl.h"
#include "CutAndPaste.h"
#include "coordcache.h"
#include "debug.h"
#include "funcrequest.h"
#include "FuncStatus.h"
@ -141,9 +142,9 @@ bool BufferView::fitCursor()
}
void BufferView::update()
void BufferView::update(bool fitcursor, bool forceupdate)
{
pimpl_->update();
pimpl_->update(fitcursor, forceupdate);
}
@ -159,12 +160,6 @@ void BufferView::scrollDocView(int value)
}
void BufferView::redoCurrentBuffer()
{
pimpl_->redoCurrentBuffer();
}
bool BufferView::available() const
{
return pimpl_->available();
@ -213,18 +208,6 @@ void BufferView::center()
}
int BufferView::top_y() const
{
return pimpl_->top_y();
}
void BufferView::top_y(int y)
{
pimpl_->top_y(y);
}
string const BufferView::getClipboard() const
{
return pimpl_->workarea().getClipboard();
@ -336,13 +319,11 @@ LyXText * BufferView::text() const
void BufferView::setCursor(ParIterator const & par, lyx::pos_type pos)
{
int const last = par.size();
for (int i = 0; i < last; ++i)
for (int i = 0, n = par.size(); i < n; ++i)
par[i].inset().edit(cursor(), true);
cursor().setCursor(makeDocIterator(par, pos));
cursor().selection() = false;
par.bottom().text()->redoParagraph(par.bottom().pit());
}
@ -375,3 +356,15 @@ LCursor const & BufferView::cursor() const
{
return pimpl_->cursor_;
}
lyx::pit_type BufferView::anchor_ref() const
{
return pimpl_->anchor_ref_;
}
int BufferView::offset_ref() const
{
return pimpl_->offset_ref_;
}

View File

@ -65,12 +65,6 @@ public:
/// return the owning main view
LyXView * owner() const;
/// return the visible top y
int top_y() const;
/// set the visible top y
void top_y(int);
/// resize event has happened
void resize();
@ -82,14 +76,17 @@ public:
/// load a buffer into the view
bool loadLyXFile(std::string const & name, bool tolastfiles = true);
/// fit the user cursor within the visible view
/** perform pending painting updates. \c fitcursor means first
* to do a fitcursor, and to force an update if screen
* position changes. \c forceupdate means to force an update
* in any case.
*/
void update(bool fitcursor = true, bool forceupdate = true);
/// move the screen to fit the cursor. Only to be called with
/// good y coordinates (after a bv::metrics)
bool fitCursor();
/// perform pending painting updates
void update();
/// reset the scrollbar to reflect current view position
void updateScrollbar();
/// FIXME
void redoCurrentBuffer();
/// FIXME
bool available() const;
@ -153,6 +150,11 @@ public:
/// clear the X selection
void unsetXSel();
/// access to offset
int offset_ref() const;
/// access to anchor
lyx::pit_type anchor_ref() const;
/// access to full cursor
LCursor & cursor();
/// access to full cursor
@ -169,6 +171,7 @@ public:
void putSelectionAt(DocIterator const & cur,
int length, bool backwards);
private:
///
struct Pimpl;

View File

@ -41,6 +41,7 @@
#include "lyxtext.h"
#include "lyxrc.h"
#include "lastfiles.h"
#include "metricsinfo.h"
#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
@ -91,6 +92,7 @@ using std::endl;
using std::istringstream;
using std::make_pair;
using std::min;
using std::max;
using std::string;
using std::mem_fun_ref;
@ -136,7 +138,8 @@ T * getInsetByCode(LCursor & cur, InsetBase::Code code)
BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner,
int width, int height)
: bv_(&bv), owner_(owner), buffer_(0), cursor_timeout(400),
using_xterm_cursor(false), cursor_(bv)
using_xterm_cursor(false), cursor_(bv) ,
anchor_ref_(0), offset_ref_(0)
{
xsel_cache_.set = false;
@ -311,18 +314,6 @@ Painter & BufferView::Pimpl::painter() const
}
void BufferView::Pimpl::top_y(int y)
{
top_y_ = y;
}
int BufferView::Pimpl::top_y() const
{
return top_y_;
}
void BufferView::Pimpl::setBuffer(Buffer * b)
{
lyxerr[Debug::INFO] << "Setting buffer in BufferView ("
@ -343,8 +334,10 @@ void BufferView::Pimpl::setBuffer(Buffer * b)
}
// reset old cursor
top_y_ = 0;
cursor_ = LCursor(*bv_);
anchor_ref_ = 0;
offset_ref_ = 0;
// if we're quitting lyx, don't bother updating stuff
if (quitting)
@ -359,10 +352,6 @@ void BufferView::Pimpl::setBuffer(Buffer * b)
buffer_->text().init(bv_);
buffer_->text().setCurrentFont(cursor_);
// If we don't have a text object for this, we make one
//if (bv_->text() == 0)
// resizeCurrentBuffer();
// Buffer-dependent dialogs should be updated or
// hidden. This should go here because some dialogs (eg ToC)
// require bv_->text.
@ -385,32 +374,6 @@ void BufferView::Pimpl::setBuffer(Buffer * b)
}
bool BufferView::Pimpl::fitCursor()
{
// to get the correct y cursor info
lyxerr[Debug::DEBUG] << "BufferView::fitCursor" << std::endl;
lyx::pit_type const pit = bv_->cursor().bottom().pit();
bv_->text()->redoParagraph(pit);
refreshPar(*bv_, *bv_->text(), pit);
if (!screen().fitCursor(bv_))
return false;
updateScrollbar();
return true;
}
void BufferView::Pimpl::redoCurrentBuffer()
{
lyxerr[Debug::DEBUG] << "BufferView::redoCurrentBuffer" << endl;
if (buffer_ && bv_->text()) {
resizeCurrentBuffer();
updateScrollbar();
owner_->updateLayoutChoice();
}
}
void BufferView::Pimpl::resizeCurrentBuffer()
{
lyxerr[Debug::DEBUG] << "resizeCurrentBuffer" << endl;
@ -423,7 +386,6 @@ void BufferView::Pimpl::resizeCurrentBuffer()
text->init(bv_);
update();
fitCursor();
switchKeyMap();
owner_->busy(false);
@ -443,14 +405,23 @@ void BufferView::Pimpl::updateScrollbar()
return;
}
LyXText const & t = *bv_->text();
LyXText & t = *bv_->text();
if (anchor_ref_ > int(t.paragraphs().size()) - 1) {
anchor_ref_ = int(t.paragraphs().size()) - 1;
offset_ref_ = 0;
}
lyxerr[Debug::GUI]
<< "Updating scrollbar: height: " << t.height()
<< " top_y: " << top_y()
<< "Updating scrollbar: height: " << t.paragraphs().size()
<< " curr par: " << bv_->cursor().bottom().pit()
<< " default height " << defaultRowHeight() << endl;
workarea().setScrollbarParams(t.height(), top_y(), defaultRowHeight());
//it would be better to fix the scrollbar to understand
//values in [0..1] and divide everything by wh
int const wh = workarea().workHeight() / 4;
int const h = t.getPar(anchor_ref_).height();
workarea().setScrollbarParams(t.paragraphs().size() * wh, anchor_ref_ * wh + int(offset_ref_ * wh / float(h)), int (wh * defaultRowHeight() / float(h)));
// workarea().setScrollbarParams(t.paragraphs().size(), anchor_ref_, 1);
}
@ -463,48 +434,69 @@ void BufferView::Pimpl::scrollDocView(int value)
screen().hideCursor();
top_y(value);
screen().redraw(*bv_);
int const wh = workarea().workHeight() / 4;
LyXText & t = *bv_->text();
float const bar = value / float(wh * t.paragraphs().size());
anchor_ref_ = int(bar * t.paragraphs().size());
t.redoParagraph(anchor_ref_);
int const h = t.getPar(anchor_ref_).height();
offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h);
lyxerr << "scrolling: " << value << std::endl;
update();
if (!lyxrc.cursor_follows_scrollbar)
return;
int const height = defaultRowHeight();
int const first = top_y() + height;
int const last = top_y() + workarea().workHeight() - height;
int const height = 2 * defaultRowHeight();
int const first = height;
int const last = workarea().workHeight() - height;
LCursor & cur = bv_->cursor();
bv_->cursor().reset(bv_->buffer()->inset());
LyXText * text = bv_->text();
int y = text->cursorY(bv_->cursor().front());
if (y < first)
y = first;
if (y > last)
y = last;
text->setCursorFromCoordinates(bv_->cursor(), 0, y);
bv_funcs::CurStatus st = bv_funcs::status(bv_, cur);
switch (st) {
case bv_funcs::CUR_ABOVE:
t.setCursorFromCoordinates(cur, 0, first);
cur.clearSelection();
break;
case bv_funcs::CUR_BELOW:
t.setCursorFromCoordinates(cur, 0, last);
cur.clearSelection();
break;
case bv_funcs::CUR_INSIDE:
int const y = bv_funcs::getPos(cur).y_;
int const newy = min(last, max(y, first));
if (y != newy) {
cur.reset(bv_->buffer()->inset());
t.setCursorFromCoordinates(cur, 0, newy);
}
}
owner_->updateLayoutChoice();
}
void BufferView::Pimpl::scroll(int lines)
{
if (!buffer_)
return;
LyXText const * t = bv_->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);
// Update the scrollbar.
workarea().setScrollbarParams(t->height(), top_y(), defaultRowHeight());
// if (!buffer_)
// return;
//
// LyXText const * t = bv_->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);
//
// // Update the scrollbar.
// workarea().setScrollbarParams(t->height(), top_y(), defaultRowHeight());
}
@ -591,33 +583,50 @@ void BufferView::Pimpl::workAreaResize()
}
void BufferView::Pimpl::update()
bool BufferView::Pimpl::fitCursor()
{
//lyxerr << "BufferView::Pimpl::update(), buffer: " << buffer_ << endl;
// fix cursor coordinate cache in case something went wrong
if (bv_funcs::status(bv_, bv_->cursor()) == bv_funcs::CUR_INSIDE) {
int asc, des;
bv_->cursor().getDim(asc, des);
Point p = bv_funcs::getPos(bv_->cursor());
if (p.y_ - asc >= 0 && p.y_ + des < bv_->workHeight())
return false;
}
bv_->center();
return true;
}
void BufferView::Pimpl::update(bool fitcursor, bool forceupdate)
{
lyxerr << "BufferView::Pimpl::update(fc=" << fitcursor << ", fu="
<< forceupdate << ") buffer: " << buffer_ << endl;
// check needed to survive LyX startup
if (buffer_) {
// update macro store
buffer_->buildMacros();
// first drawing step
// update all 'visible' paragraphs
lyx::pit_type beg, end;
getParsInRange(buffer_->paragraphs(),
top_y(), top_y() + workarea().workHeight(),
beg, end);
bv_->text()->redoParagraphs(beg, end);
CoordCache backup;
std::swap(theCoords, backup);
//
ViewMetricsInfo vi = metrics();
if (fitcursor && fitCursor()) {
forceupdate = true;
vi = metrics();
}
if (forceupdate) {
// second drawing step
screen().redraw(*bv_, vi);
} else
std::swap(theCoords, backup);
} else
screen().greyOut();
// and the scrollbar
updateScrollbar();
}
// remove old position cache
theCoords.clear();
// The real, big redraw.
screen().redraw(*bv_);
bv_->owner()->view_state_changed();
}
@ -732,30 +741,19 @@ void BufferView::Pimpl::switchKeyMap()
void BufferView::Pimpl::center()
{
LyXText * text = bv_->text();
bv_->cursor().clearSelection();
int const half_height = workarea().workHeight() / 2;
int new_y = text->cursorY(bv_->cursor().front()) - half_height;
if (new_y < 0)
new_y = 0;
// FIXME: look at this comment again ...
// This updates top_y() but means the fitCursor() call
// from the update(FITCUR) doesn't realise that we might
// have moved (e.g. from GOTOPARAGRAPH), so doesn't cause
// the scrollbar to be updated as it should, so we have
// to do it manually. Any operation that does a center()
// and also might have moved top_y() must make sure to call
// updateScrollbar() currently. Never mind that this is a
// pretty obfuscated way of updating text->top_y()
top_y(new_y);
CursorSlice const & bot = bv_->cursor().bottom();
lyx::pit_type const pit = bot.pit();
bot.text()->redoParagraph(pit);
Paragraph const & par = bot.text()->paragraphs()[pit];
anchor_ref_ = pit;
offset_ref_ = bv_funcs::coordOffset(bv_->cursor()).y_ + par.ascent()
- workarea().workHeight() / 2;
}
void BufferView::Pimpl::stuffClipboard(string const & stuff) const
void BufferView::Pimpl::stuffClipboard(string const & content) const
{
workarea().putClipboard(stuff);
workarea().putClipboard(content);
}
@ -870,7 +868,6 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
return true;
}
cmd.y += bv_->top_y();
if (!bv_->buffer())
return false;
@ -891,8 +888,8 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
// surrounding LyXText will handle this event.
// Build temporary cursor.
cmd.y = min(max(cmd.y,-1), bv_->workHeight());
InsetBase * inset = bv_->text()->editXY(cur, cmd.x, cmd.y);
lyxerr << " * created temp cursor: " << inset << endl;
lyxerr << " * hit inset at tip: " << inset << endl;
lyxerr << " * created temp cursor:" << cur << endl;
@ -913,8 +910,7 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
if (cur.result().dispatched()) {
// Redraw if requested or necessary.
if (fitCursor() || cur.result().update())
update();
update(cur.result().update(), cur.result().update());
}
// see workAreaKeyPress
@ -962,12 +958,9 @@ FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd)
case LFUN_MARK_ON:
case LFUN_SETMARK:
case LFUN_CENTER:
case LFUN_BEGINNINGBUF:
case LFUN_ENDBUF:
case LFUN_BEGINNINGBUFSEL:
case LFUN_ENDBUFSEL:
flag.enabled(true);
break;
case LFUN_BOOKMARK_GOTO:
flag.enabled(bv_->isSavedPosition(strToUnsignedInt(cmd.argument)));
break;
@ -1137,25 +1130,80 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
bv_->center();
break;
case LFUN_BEGINNINGBUFSEL:
bv_->cursor().reset(bv_->buffer()->inset());
if (!cur.selection())
cur.resetAnchor();
bv_->text()->cursorTop(cur);
finishUndo();
break;
case LFUN_ENDBUFSEL:
bv_->cursor().reset(bv_->buffer()->inset());
if (!cur.selection())
cur.resetAnchor();
bv_->text()->cursorBottom(cur);
finishUndo();
break;
default:
return false;
}
return true;
}
ViewMetricsInfo BufferView::Pimpl::metrics()
{
// remove old position cache
theCoords.clear();
BufferView & bv = *bv_;
LyXText * const text = bv.text();
if (anchor_ref_ > int(text->paragraphs().size() - 1)) {
anchor_ref_ = int(text->paragraphs().size() - 1);
offset_ref_ = 0;
}
lyx::pit_type const pit = anchor_ref_;
int pit1 = pit;
int pit2 = pit;
size_t npit = text->paragraphs().size();
lyxerr << "npit: " << npit << " pit1: " << pit1
<< " pit2: " << pit2 << endl;
// rebreak anchor par
text->redoParagraph(pit);
int y0 = text->getPar(pit1).ascent() - offset_ref_;
// redo paragraphs above cursor if necessary
int y1 = y0;
while (y1 > 0 && pit1 > 0) {
y1 -= text->getPar(pit1).ascent();
--pit1;
text->redoParagraph(pit1);
y1 -= text->getPar(pit1).descent();
}
// take care of ascent of first line
y1 -= text->getPar(pit1).ascent();
//normalize anchor for next time
anchor_ref_ = pit1;
offset_ref_ = -y1;
// grey at the beginning is ugly
if (pit1 == 0 && y1 > 0) {
y0 -= y1;
y1 = 0;
anchor_ref_ = 0;
}
// redo paragraphs below cursor if necessary
int y2 = y0;
while (y2 < bv.workHeight() && pit2 < int(npit) - 1) {
y2 += text->getPar(pit2).descent();
++pit2;
text->redoParagraph(pit2);
y2 += text->getPar(pit2).ascent();
}
// take care of descent of last line
y2 += text->getPar(pit2).descent();
// the coordinates of all these paragraphs are correct, cache them
int y = y1;
for (lyx::pit_type pit = pit1; pit <= pit2; ++pit) {
y += text->getPar(pit).ascent();
theCoords.pars_[text][pit] = Point(0, y);
y += text->getPar(pit).descent();
}
lyxerr << "bv:metrics: y1: " << y1 << " y2: " << y2 << endl;
return ViewMetricsInfo(pit1, pit2, y1, y2);
}

View File

@ -41,6 +41,7 @@ class WorkArea;
class LyXScreen;
class FuncRequest;
class FuncStatus;
class ViewMetricsInfo;
///
@ -53,14 +54,12 @@ struct BufferView::Pimpl : public boost::signals::trackable {
LyXScreen & screen() const;
///
void setBuffer(Buffer * buf);
/// Return true if the cursor was fitted.
bool fitCursor();
///
void redoCurrentBuffer();
///
void resizeCurrentBuffer();
//
bool fitCursor();
///
void update();
void update(bool fitcursor = false, bool forceupdate = true);
///
void newFile(std::string const &, std::string const &, bool);
///
@ -103,13 +102,7 @@ struct BufferView::Pimpl : public boost::signals::trackable {
FuncStatus getStatus(FuncRequest const & cmd);
/// a function should be executed
bool dispatch(FuncRequest const & ev);
///
int top_y() const;
///
void top_y(int y);
private:
/// the y coordinate of the top of the screen
int top_y_;
/// An error list (replaces the error insets)
ErrorList errorlist_;
/// add an error to the list
@ -185,5 +178,14 @@ private:
} xsel_cache_;
///
LCursor cursor_;
///
///
lyx::pit_type anchor_ref_;
///
int offset_ref_;
///
ViewMetricsInfo metrics();
};
#endif // BUFFERVIEW_PIMPL_H

View File

@ -1,3 +1,58 @@
2004-11-24 Alfredo Braunstein <abraunst@lyx.org>
* BufferView.[Ch]: remove top_y, introduce anchor_ref,
offset_ref accessors
* BufferView_Pimpl.[Ch]: introduce anchor_ref_, offser_ref_, remove
top_y_, merge fitcursor with update
(updateScrollbar, scrollDocView, fitCursor, center, update): new
coord scheme
(metrics): introduce
(workAreaDispatch): adapt to new coord scheme
(redoCurrentBuffer): remove
* FontIterator.[Ch]: Use Paragraph & instead of pit_type
* bufferview_funcs.[Ch]: introduce coordOffset, getPos, status,
CurStatus enum.
* coordcache.[Ch]: add paragraph cache and helpers
* CursorSlice.[Ch]: rename CursorSlice::par to CursorSlice::pit,
adjust everywhere
* cursor.[Ch] (getDim): fix, (getPos) use coordOffset
(targetX, setTargetX): introduce
* lyxrow.[Ch]: simplify, remove ascent_of_text, y_offset, rename
baseline -> ascent, as the rest of lyx
* lyxtext.h: remove redoParagraphs, updateParPositions,
fullRebreak, redoParagraphInternal. move dist to anon namespace in
tabular.C (doesn't belong here), remove xo_, yo_ cache, makes it
have ascent/descent (ascent is ascent of first par)
* metricsinfo.h: add ViewMetricsInfo struct to use in the metrics
step of BufferView
* paragraph.[Ch]: unify dimension handling with the rest of lyx
* paragraph_funcs.[Ch] (getParsInRange, outerPar): remove.
* pariterator.C: fix infinite loop introduced in par->pit renaming
* rowPainter.[Ch]: big rewrite: separate drawSelection from draw
in insets and LyXText, draw two off-screen paragraphs using
NullPainter, and adapt to new coord scheme
* text.C:
* text2.C:
* text3.C: adapt lfun handlers to the new coord scheme, which
means: there's only guaranteed coord information for onscreen pars
plus one above and one below. This implies that one can do search
from y coordinates in the range [-1,workHeight]
2004-11-25 Lars Gullik Bjonnes <larsbj@gullik.net>
* rename a lot of InsetOld to InsetBase
@ -41,7 +96,6 @@
* text3.C:
* undo.C: par->pit renaming
2004-11-23 Lars Gullik Bjonnes <larsbj@gullik.net>
* tabular.C (cellstruct): use initialization, store a shared_ptr

View File

@ -466,7 +466,6 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut)
if (doclear)
text->paragraphs()[begpit].stripLeadingSpaces();
text->redoParagraphs(begpit, begpit + 1);
// cutSelection can invalidate the cursor so we need to set
// it anew. (Lgb)
// we prefer the end for when tracking changes
@ -564,8 +563,6 @@ void pasteSelection(LCursor & cur, size_t sel_index)
bufferErrors(cur.buffer(), el);
cur.bv().showErrorList(_("Paste"));
text->redoParagraphs(cur.pit(), endpit);
cur.clearSelection();
cur.resetAnchor();
text->setCursor(cur, ppp.first, ppp.second);

View File

@ -18,12 +18,12 @@
#include "paragraph.h"
FontIterator::FontIterator(LyXText const & text, lyx::pit_type pit,
FontIterator::FontIterator(LyXText const & text, Paragraph const & par,
lyx::pos_type pos)
: text_(text), pit_(pit), pos_(pos),
font_(text.getFont(text.getPar(pit), pos)),
endspan_(text.getPar(pit).getEndPosOfFontSpan(pos)),
bodypos_(text.getPar(pit).beginOfBody())
: text_(text), par_(par), pos_(pos),
font_(text.getFont(par, pos)),
endspan_(par.getEndPosOfFontSpan(pos)),
bodypos_(par.beginOfBody())
{}
@ -43,8 +43,8 @@ FontIterator & FontIterator::operator++()
{
++pos_;
if (pos_ > endspan_ || pos_ == bodypos_) {
font_ = text_.getFont(text_.getPar(pit_), pos_);
endspan_ = text_.getPar(pit_).getEndPosOfFontSpan(pos_);
font_ = text_.getFont(par_, pos_);
endspan_ = par_.getEndPosOfFontSpan(pos_);
}
return *this;
}

View File

@ -25,13 +25,14 @@
#include "support/types.h"
class LyXText;
class Paragraph;
class FontIterator : std::iterator<std::forward_iterator_tag, LyXFont>
{
public:
///
FontIterator(LyXText const & text, lyx::pit_type pit, lyx::pos_type pos);
FontIterator(LyXText const & text, Paragraph const & par, lyx::pos_type pos);
///
LyXFont operator*() const;
///
@ -43,7 +44,7 @@ private:
///
LyXText const & text_;
///
lyx::pit_type pit_;
Paragraph const & par_;
///
lyx::pos_type pos_;
///

View File

@ -20,6 +20,7 @@
#include "bufferparams.h"
#include "BufferView.h"
#include "cursor.h"
#include "coordcache.h"
#include "gettext.h"
#include "language.h"
#include "LColor.h"
@ -145,4 +146,64 @@ bool string2font(string const & data, LyXFont & font, bool & toggle)
return (nset > 0);
}
// the next two should probably go elsewhere
// this give the position relative to (0, baseline) of outermost
// paragraph
Point coordOffset(DocIterator const & dit)
{
int x = 0;
int y = 0;
// Contribution of nested insets
for (size_t i = 1; i != dit.size(); ++i) {
CursorSlice const & sl = dit[i];
int xx = 0, yy = 0;
sl.inset().getCursorPos(sl, xx, yy);
x += xx;
y += yy;
//lyxerr << "LCursor::getPos, i: " << i << " x: " << xx << " y: " << y << endl;
}
// Add contribution of initial rows of outermost paragraph
CursorSlice const & sl = dit[0];
Paragraph const & par = sl.text()->getPar(sl.pit());
y -= par.rows()[0].ascent();
for (size_t rit = 0, rend = par.pos2row(sl.pos()); rit != rend; ++rit)
y += par.rows()[rit].height();
y += par.rows()[par.pos2row(sl.pos())].ascent();
x += dit.bottom().text()->cursorX(dit.bottom());
return Point(x,y);
}
Point getPos(DocIterator const & dit)
{
CursorSlice const & bot = dit.bottom();
CoordCache::InnerParPosCache & cache = theCoords.pars_[bot.text()];
CoordCache::InnerParPosCache::iterator it = cache.find(bot.pit());
if (it == cache.end()) {
//lyxerr << "cursor out of view" << std::endl;
return Point(-1,-1);
}
Point p = coordOffset(dit); // offset from outer paragraph
p.y_ += it->second.y_;
return p;
}
// this could be used elsewhere as well?
CurStatus status(BufferView const * bv, DocIterator const & dit)
{
CoordCache::InnerParPosCache & cache = theCoords.pars_[dit.bottom().text()];
if (cache.find(dit.bottom().pit()) != cache.end())
return CUR_INSIDE;
else if (dit.bottom().pit() < bv->anchor_ref())
return CUR_ABOVE;
else
return CUR_BELOW;
}
} // namespace bv_funcs

View File

@ -17,6 +17,9 @@
#include <string>
class LyXFont;
class Point;
class DocIterator;
class BufferView;
namespace bv_funcs {
@ -32,6 +35,21 @@ bool string2font(std::string const & data, LyXFont & font, bool & toggle);
*/
std::string const freefont2string();
Point getPos(DocIterator const & dit);
enum CurStatus {
CUR_INSIDE,
CUR_ABOVE,
CUR_BELOW
};
CurStatus status(BufferView const * bv, DocIterator const & dit);
Point coordOffset(DocIterator const & dit);
} // namespace bv_funcs
#endif

View File

@ -2,6 +2,14 @@
#include "coordcache.h"
#include "debug.h"
#include "lyxtext.h"
#include "mathed/math_data.h"
#include "insets/insetbase.h"
#include <boost/assert.hpp>
CoordCache theCoords;
// just a helper to be able to set a breakpoint
@ -9,16 +17,30 @@ void lyxbreaker(void const * data, const char * hint, int size)
{
lyxerr << "break on pointer: " << data << " hint: " << hint
<< " size: " << size << std::endl;
BOOST_ASSERT(false);
}
void lyxaborter(int x, int y)
{
lyxerr << "abort on x: " << x << " y: " << y << std::endl;
BOOST_ASSERT(false);
}
void CoordCache::clear()
{
// lyxerr << "CoordCache: removing " << arrays_.data_.size()
// << " arrays" << std::endl;
// lyxerr << "CoordCache: removing " << insets_.data_.size()
// << " insets" << std::endl;
arrays_.clear();
insets_.clear();
pars_.clear();
}
Point CoordCache::get(LyXText const * text, lyx::pit_type pit)
{
ParPosCache::iterator const it = pars_.find(text);
BOOST_ASSERT(it != pars_.end());
InnerParPosCache::iterator const posit = it->second.find(pit);
BOOST_ASSERT(posit != it->second.end());
return posit->second;
}

View File

@ -1,9 +1,12 @@
#ifndef COORDCACHE_H
#define COORDCACHE_H
#include "mathed/math_data.h"
#include "insets/insetbase.h"
#include "lyxtext.h"
class InsetBase;
class LyXText;
class MathArray;
class Paragraph;
#include "support/types.h"
#include <boost/assert.hpp>
@ -15,6 +18,7 @@
// to the right, y increases downwords.
void lyxbreaker(void const * data, const char * hint, int size);
void lyxaborter(int x, int y);
struct Point {
Point()
@ -79,10 +83,8 @@ private:
void check(T const * thing, char const * hint) const
{
if (!has(thing)) {
if (!has(thing))
lyxbreaker(thing, hint, data_.size());
BOOST_ASSERT(false);
}
}
typedef std::map<T const *, Point> cache_type;
@ -93,9 +95,17 @@ private:
class CoordCache {
public:
void clear();
Point get(LyXText const *, lyx::pit_type);
CoordCacheBase<MathArray> arrays_;
// all insets
CoordCacheBase<InsetBase> insets_;
// paragraph grouped by owning text
typedef std::map<lyx::pit_type, Point> InnerParPosCache;
typedef std::map<LyXText const *, InnerParPosCache> ParPosCache;
ParPosCache pars_;
};
extern CoordCache theCoords;

View File

@ -15,6 +15,7 @@
#include "BufferView.h"
#include "buffer.h"
#include "cursor.h"
#include "coordcache.h"
#include "CutAndPaste.h"
#include "debug.h"
#include "dispatchresult.h"
@ -42,6 +43,7 @@
#include "support/limited_stack.h"
#include "frontends/LyXView.h"
#include "frontends/font_metrics.h"
#include <boost/assert.hpp>
#include <boost/bind.hpp>
@ -80,9 +82,10 @@ namespace {
// Find position closest to (x, y) in cell given by iter.
// Used only in mathed
DocIterator bruteFind2(LCursor const & c, int x, int y)
{
double best_dist = 1e10;
double best_dist = std::numeric_limits<double>::max();
DocIterator result;
@ -94,11 +97,12 @@ namespace {
int xo, yo;
LCursor cur = c;
cur.setCursor(it);
cur.inset().getCursorPos(cur, xo, yo);
cur.inset().getCursorPos(cur.top(), xo, yo);
double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
// '<=' in order to take the last possible position
// this is important for clicking behind \sum in e.g. '\sum_i a'
lyxerr[Debug::DEBUG] << "i: " << i << " d: " << d << " best: " << best_dist << endl;
lyxerr[Debug::DEBUG] << "i: " << i << " d: " << d
<< " best: " << best_dist << endl;
if (d <= best_dist) {
best_dist = d;
result = it;
@ -120,27 +124,20 @@ namespace {
CursorSlice bottom = cursor[0];
LyXText * text = bottom.text();
BOOST_ASSERT(text);
getParsInRange(text->paragraphs(), ylow, yhigh, beg, end);
DocIterator it = doc_iterator_begin(cursor.bv().buffer()->inset());
DocIterator et = doc_iterator_end(cursor.bv().buffer()->inset());
//lyxerr << "x: " << x << " y: " << y << endl;
//lyxerr << "xlow: " << xlow << " ylow: " << ylow << endl;
//lyxerr << "xhigh: " << xhigh << " yhigh: " << yhigh << endl;
DocIterator it = doc_iterator_begin(bottom.inset());
DocIterator const et = doc_iterator_end(bottom.inset());
it.pit() = beg;
//et.pit() = text->parOffset(end);
double best_dist = 10e10;
DocIterator best_cursor = it;
double best_dist = std::numeric_limits<double>::max();;
DocIterator best_cursor = et;
for ( ; it != et; it.forwardPos()) {
// avoid invalid nesting when selecting
if (!cursor.selection() || positionable(it, cursor.anchor_)) {
int xo = 0, yo = 0;
LCursor cur = cursor;
cur.setCursor(it);
cur.inset().getCursorPos(cur, xo, yo);
if (bv_funcs::status(&cursor.bv(), it) == bv_funcs::CUR_INSIDE
&& (!cursor.selection() || positionable(it, cursor.anchor_))) {
Point p = bv_funcs::getPos(it);
int xo = p.x_;
int yo = p.y_;
if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
//lyxerr << "xo: " << xo << " yo: " << yo << " d: " << d << endl;
@ -156,15 +153,20 @@ namespace {
}
//lyxerr << "best_dist: " << best_dist << " cur:\n" << best_cursor << endl;
if (best_dist < 1e10)
if (best_cursor != et) {
cursor.setCursor(best_cursor);
return best_dist < 1e10;
return true;
}
return false;
}
} // namespace anon
// be careful: this is called from the bv's constructor, too, so
// bv functions are not yet available!
LCursor::LCursor(BufferView & bv)
: DocIterator(), bv_(&bv), anchor_(), x_target_(-1),
selection_(false), mark_(false)
@ -348,11 +350,11 @@ void LCursor::getDim(int & asc, int & des) const
BOOST_ASSERT(inset().asMathInset());
//inset().asMathInset()->getCursorDim(asc, des);
asc = 10;
des = 10;
des = 2;
} else if (inTexted()) {
Row const & row = textRow();
asc = row.baseline();
des = row.height() - asc;
LyXFont const & realfont = text()->real_current_font;
asc = font_metrics::maxAscent(realfont);
des = font_metrics::maxDescent(realfont);
} else {
lyxerr << "should this happen?" << endl;
asc = 10;
@ -363,10 +365,9 @@ void LCursor::getDim(int & asc, int & des) const
void LCursor::getPos(int & x, int & y) const
{
x = 0;
y = 0;
if (!empty())
inset().getCursorPos(*this, x, y);
Point p = bv_funcs::getPos(*this);
x = p.x_;
y = p.y_;
}
@ -857,6 +858,17 @@ int LCursor::targetX() const
}
void LCursor::setTargetX()
{
//for now this is good enough. A better solution would be to
//avoid this rebreak by setting cursorX only after drawing
bottom().text()->redoParagraph(bottom().pit());
int x, y;
getPos(x, y);
x_target_ = x;
}
bool LCursor::inMacroMode() const
{
if (pos() == 0)

View File

@ -22,6 +22,7 @@ class Buffer;
class BufferView;
class FuncStatus;
class FuncRequest;
class Point;
// these should go
class MathUnknownInset;
@ -119,10 +120,14 @@ public:
/// insert a string
void insert(std::string const & str);
/// in pixels from left of screen
int targetX() const;
/// write acess to target x position of cursor
int & x_target();
/// return target x position of cursor
int x_target() const;
/// set targetX in current position
void setTargetX();
/// clear target x position of cursor
void clearTargetX();
@ -165,6 +170,7 @@ public:
///
DispatchResult disp_;
private:
/**
* The target x position of the cursor. This is used for when
@ -184,11 +190,6 @@ private:
/// are we on the way to get one?
bool mark_;
public:
/// the actual cursor position
int xo_;
int yo_;
private:
//
@ -232,8 +233,6 @@ public:
/// in pixels from top of screen
void setScreenPos(int x, int y);
/// in pixels from left of screen
int targetX() const;
/// current offset in the top cell
/// interpret name a name of a macro
void macroModeClose();
@ -281,4 +280,6 @@ public:
Encoding const * getEncoding() const;
};
#endif // LYXCURSOR_H

View File

@ -64,9 +64,9 @@ public:
idx_type & idx() { return idx_; }
/// return the last cell in this inset
idx_type lastidx() const { return nargs() - 1; }
/// return the paragraph this cursor is in
/// return the offset of the paragraph this cursor is in
pit_type pit() const { return pit_; }
/// set the paragraph this cursor is in
/// set the offset of the paragraph this cursor is in
pit_type & pit() { return pit_; }
/// increments the paragraph this cursor is in
void incrementPar();

View File

@ -146,13 +146,13 @@ Paragraph const & DocIterator::paragraph() const
Row & DocIterator::textRow()
{
return *paragraph().getRow(pos());
return paragraph().getRow(pos());
}
Row const & DocIterator::textRow() const
{
return *paragraph().getRow(pos());
return paragraph().getRow(pos());
}
@ -168,18 +168,6 @@ DocIterator::pos_type DocIterator::lastpos() const
}
DocIterator::row_type DocIterator::crow() const
{
return paragraph().row(pos());
}
DocIterator::row_type DocIterator::lastcrow() const
{
return paragraph().rows.size();
}
DocIterator::idx_type DocIterator::lastidx() const
{
return top().lastidx();
@ -314,7 +302,7 @@ void DocIterator::forwardPos()
top.pos() = 0;
return;
}
//lyxerr << "... no next par" << endl;
//lyxerr << "... no next pit" << endl;
// otherwise try to move on one cell if possible
if (top.idx() < lastidx()) {

View File

@ -92,10 +92,6 @@ public:
pos_type & pos() { return back().pos(); }
/// return the last position within the paragraph
pos_type lastpos() const;
/// return the display row of the cursor with in the top par
row_type crow() const;
/// return the display row of the cursor with in the top par
row_type lastcrow() const;
/// return the number of embedded cells
size_t nargs() const;

View File

@ -1,3 +1,8 @@
2004-11-26 Alfredo Braunstein <abraunst@lyx.org>
* Painter.C: adjust * screen.[Ch] (fitCursor): remove,
(showCursor): adjust, (redraw): adjust
2004-11-20 Lars Gullik Bjonnes <larsbj@gullik.net>
* Dialogs.h: include <map> since it is used in this file, fixes

View File

@ -41,20 +41,20 @@ void Painter::buttonFrame(int x, int y, int w, int h)
int x1[4], y1[4];
x1[0] = x + d; y1[0] = y + d;
x1[1] = x + d; y1[1] = (y + h - d);
x1[1] = x + d; y1[1] = y + h - d;
x1[2] = x; y1[2] = y + h;
x1[3] = x; y1[3] = y;
fillPolygon(x1, y1, 4, LColor::left);
x1[0] = (x + w - d); y1[0] = y + d;
x1[1] = (x + w - d); y1[1] = (y + h - d);
x1[2] = x + w; y1[2] = (y + h - d);
x1[0] = x + w - d; y1[0] = y + d;
x1[1] = x + w - d; y1[1] = y + h - d;
x1[2] = x + w; y1[2] = y + h - d;
x1[3] = x + w; y1[3] = y;
fillPolygon(x1, y1, 4, LColor::right);
}
void Painter::rectText(int x, int baseline,
void Painter::rectText(int x, int y,
string const & str,
LyXFont const & font,
LColor_color back,
@ -66,22 +66,18 @@ void Painter::rectText(int x, int baseline,
font_metrics::rectText(str, font, width, ascent, descent);
if (back != LColor::none) {
fillRectangle(x + 1, baseline - ascent + 1, width - 1,
if (back != LColor::none)
fillRectangle(x + 1, y - ascent + 1, width - 1,
ascent + descent - 1, back);
}
if (frame != LColor::none) {
rectangle(x, baseline - ascent, width, ascent + descent, frame);
}
if (frame != LColor::none)
rectangle(x, y - ascent, width, ascent + descent, frame);
text(x + 3, baseline, str, font);
text(x + 3, y, str, font);
}
void Painter::buttonText(int x, int baseline,
string const & str,
LyXFont const & font)
void Painter::buttonText(int x, int y, string const & str, LyXFont const & font)
{
int width;
int ascent;
@ -89,8 +85,8 @@ void Painter::buttonText(int x, int baseline,
font_metrics::buttonText(str, font, width, ascent, descent);
button(x, baseline - ascent, width, descent + ascent);
text(x + 4, baseline, str, font);
button(x, y - ascent, width, descent + ascent);
text(x + 4, y, str, font);
}
@ -99,10 +95,8 @@ void Painter::underline(LyXFont const & f, int x, int y, int width)
int const below = max(font_metrics::maxDescent(f) / 2, 2);
int const height = max((font_metrics::maxDescent(f) / 4) - 1, 1);
if (height < 2) {
if (height < 2)
line(x, y + below, x + width, y + below, f.color());
} else {
fillRectangle(x, y + below, width, below + height,
f.color());
}
else
fillRectangle(x, y + below, width, below + height, f.color());
}

View File

@ -235,9 +235,6 @@ void ControlSpellchecker::check()
// if we used a lfun like in find/replace, dispatch would do
// that for us
kernel().bufferview()->update();
if (kernel().bufferview()->fitCursor())
kernel().bufferview()->update();
// set suggestions
if (res != SpellBase::OK && res != SpellBase::IGNORE) {

View File

@ -121,12 +121,12 @@ SplashScreen::SplashScreen()
LyXScreen::LyXScreen()
: cursor_visible_(false), greyed_out_(true)
: greyed_out_(true), cursor_visible_(false)
{
// Start loading the pixmap as soon as possible
if (lyxrc.show_banner) {
SplashScreen const & splash = SplashScreen::get();
splash.connect(boost::bind(&LyXScreen::greyOut, this));
splash.connect(boost::bind(&LyXScreen::checkAndGreyOut, this));
splash.startLoading();
}
}
@ -137,6 +137,13 @@ LyXScreen::~LyXScreen()
}
void LyXScreen::checkAndGreyOut()
{
if (greyed_out_)
greyOut();
}
void LyXScreen::showCursor(BufferView & bv)
{
// this is needed to make sure we copy back the right
@ -167,13 +174,13 @@ void LyXScreen::showCursor(BufferView & bv)
if (realfont.language() == latex_language)
shape = BAR_SHAPE;
int ascent = font_metrics::maxAscent(realfont);
int descent = font_metrics::maxDescent(realfont);
int ascent, descent;
bv.cursor().getDim(ascent, descent);
int h = ascent + descent;
int x = 0;
int y = 0;
bv.cursor().getPos(x, y);
y -= ascent + bv.top_y();
y -= ascent;
//lyxerr << "LyXScreen::showCursor x: " << x << " y: " << y << endl;
// if it doesn't fit entirely on the screen, don't try to show it
@ -204,84 +211,22 @@ void LyXScreen::toggleCursor(BufferView & bv)
}
bool LyXScreen::fitCursor(BufferView * bv)
void LyXScreen::redraw(BufferView & bv, ViewMetricsInfo const & vi)
{
int const top_y = bv->top_y();
int const h = workarea().workHeight();
int newtop = top_y;
int x, y, asc, desc;
bv->cursor().getPos(x, y);
bv->cursor().getDim(asc, desc);
lyxerr[Debug::DEBUG] << "LyXScreen::fitCursor: x: " << x
<< " y: " << y
<< " top_y: " << top_y
<< endl;
bool const big_row = h / 4 < asc + desc && asc + desc < h;
if (y + desc - top_y >= h) {
if (big_row)
newtop = y + desc - h;
else
newtop = y - h / 2;
} else if (top_y > max(y - asc, 0)) {
if (big_row)
newtop = y - asc;
else {
newtop = y - h / 2;
newtop = min(newtop, top_y);
}
}
newtop = max(newtop, 0);
if (newtop == top_y)
return false;
bv->top_y(newtop);
return true;
}
void LyXScreen::redraw(BufferView & bv)
{
greyed_out_ = !bv.text();
if (greyed_out_) {
greyOut();
return;
}
greyed_out_ = false;
workarea().getPainter().start();
hideCursor();
int const y = paintText(bv);
// maybe we have to clear the screen at the bottom
int const y2 = workarea().workHeight();
if (y < y2 && bv.text()->isMainText()) {
workarea().getPainter().fillRectangle(0, y,
workarea().workWidth(), y2 - y,
LColor::bottomarea);
}
paintText(bv, vi);
lyxerr[Debug::DEBUG] << "Redraw screen" << endl;
expose(0, 0, workarea().workWidth(), workarea().workHeight());
workarea().getPainter().end();
showCursor(bv);
}
void LyXScreen::greyOut()
{
if (!greyed_out_)
return;
greyed_out_ = true;
workarea().getPainter().start();
workarea().getPainter().fillRectangle(0, 0,

View File

@ -13,10 +13,13 @@
#ifndef SCREEN_H
#define SCREEN_H
class LyXText;
class CursorSlice;
class WorkArea;
class BufferView;
class ViewMetricsInfo;
/**
* LyXScreen - document rendering management
@ -37,16 +40,10 @@ public:
virtual ~LyXScreen();
/// redraw the screen, without using existing pixmap
virtual void redraw(BufferView & bv);
virtual void redraw(BufferView & bv, ViewMetricsInfo const & vi);
/**
* fitCursor - fit the cursor onto the work area
* @param bv the bufferview
* @return true if a change was necessary
*
* Scrolls the screen so that the cursor is visible
*/
virtual bool fitCursor(BufferView *);
/// grey out (no buffer)
void greyOut();
/// hide the visible cursor, if it is visible
void hideCursor();
@ -81,14 +78,14 @@ protected:
virtual void removeCursor() = 0;
private:
/// grey out (no buffer)
void greyOut();
///
void checkAndGreyOut();
///
bool greyed_out_;
/// is the cursor currently displayed
bool cursor_visible_;
/// is the screen displaying text or the splash screen?
bool greyed_out_;
};
#endif // SCREEN_H

View File

@ -1,3 +1,14 @@
2004-11-26 Alfredo Braunstein <abraunst@lyx.org>
* insettabular.[Ch]: adjust, introduce "do not draw
offscreen" optimization using NullPainter, (dist): introduce,
(getCursorPos): implement, (drawSelection): implement
* insetcollapsable.[Ch]: adjust
* insettext.C: adjust, (metrics): set the font before calling
LyXText::metrics
2004-11-25 Lars Gullik Bjonnes <larsbj@gullik.net>
* rename a lot of InsetOld to InsetBase

View File

@ -238,7 +238,7 @@ void InsetBase::markErased()
{}
void InsetBase::getCursorPos(LCursor const &, int & x, int & y) const
void InsetBase::getCursorPos(CursorSlice const &, int & x, int & y) const
{
lyxerr << "InsetBase::getCursorPos called directly" << std::endl;
x = 100;

View File

@ -115,7 +115,7 @@ public:
/// do we cover screen position x/y?
virtual bool covers(int x, int y) const;
/// get the screen positions of the cursor (see note in cursor.C)
virtual void getCursorPos(LCursor const & cur, int & x, int & y) const;
virtual void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
/// is this an inset that can be moved into?
virtual bool isActive() const { return nargs() > 0; }

View File

@ -62,11 +62,8 @@ void InsetBibitem::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandMailer::string2params("bibitem", cmd.argument, p);
if (p.getCmdName().empty())
break;
if (!p.getCmdName().empty())
setParams(p);
cur.bv().update();
cur.bv().fitCursor();
break;
}
@ -100,11 +97,10 @@ void InsetBibitem::write(Buffer const &, std::ostream & os) const
// This should be changed!!! (Jug)
void InsetBibitem::read(Buffer const &, LyXLex & lex)
{
if (lex.eatLine()) {
if (lex.eatLine())
scanCommand(lex.getString());
} else {
else
lex.printError("InsetCommand: Parse error: `$$Token'");
}
if (prefixIs(getContents(), key_prefix)) {
int key = strToInt(getContents().substr(key_prefix.length()));

View File

@ -50,8 +50,8 @@ void leaveInset(LCursor & cur, InsetBase const & in)
}
InsetCollapsable::InsetCollapsable(BufferParams const & bp,
CollapseStatus status)
InsetCollapsable::InsetCollapsable
(BufferParams const & bp, CollapseStatus status)
: InsetText(bp), label("Label"), status_(status), openinlined_(false)
{
setAutoBreakRows(true);
@ -122,9 +122,11 @@ void InsetCollapsable::read(Buffer const & buf, LyXLex & lex)
}
void InsetCollapsable::dimension_collapsed(Dimension & dim) const
Dimension InsetCollapsable::dimensionCollapsed() const
{
Dimension dim;
font_metrics::buttonText(label, labelfont_, dim.wid, dim.asc, dim.des);
return dim;
}
@ -134,14 +136,14 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
if (status_ == Inlined) {
InsetText::metrics(mi, dim);
} else {
dimension_collapsed(dim);
dim = dimensionCollapsed();
if (status_ == Open) {
InsetText::metrics(mi, textdim_);
openinlined_ = (textdim_.wid + dim.wid <= mi.base.textwidth);
if (openinlined_) {
dim.wid += textdim_.wid;
dim.des = max(dim.des, textdim_.des);
dim.asc = max(dim.asc, textdim_.asc);
dim.des = max(dim.des - textdim_.asc + dim.asc, textdim_.des);
dim.asc = textdim_.asc;
} else {
dim.des += textdim_.height() + TEXT_TO_BOTTOM_OFFSET;
dim.wid = max(dim.wid, textdim_.wid);
@ -156,42 +158,71 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
}
void InsetCollapsable::draw_collapsed(PainterInfo & pi, int x, int y) const
{
pi.pain.buttonText(x, y, label, labelfont_);
}
void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
{
x += TEXT_TO_INSET_OFFSET;
y += TEXT_TO_INSET_OFFSET;
const int xx = x + TEXT_TO_INSET_OFFSET;
if (status_ == Inlined) {
InsetText::draw(pi, x, y);
InsetText::draw(pi, xx, y);
} else {
Dimension dimc;
dimension_collapsed(dimc);
int const aa = ascent();
button_dim.x1 = x + 0;
button_dim.x2 = x + dimc.width();
button_dim.y1 = y - aa + pi.base.bv->top_y();
button_dim.y2 = y - aa + pi.base.bv->top_y() + dimc.height();
Dimension dimc = dimensionCollapsed();
int const top = y - ascent() + TEXT_TO_INSET_OFFSET;
button_dim.x1 = xx + 0;
button_dim.x2 = xx + dimc.width();
button_dim.y1 = top;
button_dim.y2 = top + dimc.height();
draw_collapsed(pi, x, y - aa + dimc.asc);
pi.pain.buttonText(xx, top + dimc.asc, label, labelfont_);
if (status_ == Open) {
if (openinlined_)
InsetText::draw(pi, x + dimc.width(),
y - aa + textdim_.asc);
else
InsetText::draw(pi, x, dimc.height()
+ y - aa + textdim_.asc);
int textx, texty;
if (openinlined_) {
textx = xx + dimc.width();
texty = top + textdim_.asc;
} else {
textx = xx;
texty = top + dimc.height() + textdim_.asc;
}
InsetText::draw(pi, textx, texty);
}
}
setPosCache(pi, x, y);
}
void InsetCollapsable::drawSelection(PainterInfo & pi, int x, int y) const
{
x += TEXT_TO_INSET_OFFSET;
if (status_ == Open) {
if (openinlined_)
x += dimensionCollapsed().wid;
else
y += dimensionCollapsed().des + textdim_.asc;
}
if (status_ != Collapsed)
InsetText::drawSelection(pi, x, y);
}
void InsetCollapsable::getCursorPos
(CursorSlice const & sl, int & x, int & y) const
{
if (status_ == Collapsed) {
x = xo();
y = yo();
return;
}
InsetText::getCursorPos(sl, x, y);
if (status_ == Open) {
if (openinlined_)
x += dimensionCollapsed().wid;
else
y += dimensionCollapsed().height() - ascent() + TEXT_TO_INSET_OFFSET + textdim_.asc;
}
x += TEXT_TO_INSET_OFFSET;
}
InsetBase::EDITABLE InsetCollapsable::editable() const
{
return status_ != Collapsed ? HIGHLY_EDITABLE : IS_EDITABLE;
@ -242,21 +273,17 @@ void InsetCollapsable::edit(LCursor & cur, bool left)
InsetBase * InsetCollapsable::editXY(LCursor & cur, int x, int y) const
{
cur.push(const_cast<InsetCollapsable&>(*this));
//lyxerr << "InsetCollapsable: edit xy" << endl;
if (status_ == Collapsed) {
return const_cast<InsetCollapsable*>(this);
}
cur.push(const_cast<InsetCollapsable&>(*this));
return InsetText::editXY(cur, x, y);
}
void InsetCollapsable::doDispatch(LCursor & cur, FuncRequest & cmd)
{
// lyxerr << "InsetCollapsable::doDispatch (begin): cmd: " << cmd
// << " button y: " << button_dim.y2
// << " coll/inline/open: " << status_ << endl;
lyxerr << "InsetCollapsable::doDispatch (begin): cmd: " << cmd
<< " cur: " << cur << " bvcur: " << cur.bv().cursor() << endl;
@ -275,6 +302,8 @@ void InsetCollapsable::doDispatch(LCursor & cur, FuncRequest & cmd)
InsetText::doDispatch(cur, cmd);
else if (status_ == Open && !hitButton(cmd))
InsetText::doDispatch(cur, cmd);
else
cur.undispatched();
break;
case LFUN_MOUSE_RELEASE:
@ -287,8 +316,7 @@ void InsetCollapsable::doDispatch(LCursor & cur, FuncRequest & cmd)
case Collapsed:
lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
open();
InsetText::edit(cur, true);
edit(cur, true);
cur.bv().cursor() = cur;
break;
@ -367,9 +395,9 @@ void InsetCollapsable::setLabel(string const & l)
}
void InsetCollapsable::setStatus(CollapseStatus st)
void InsetCollapsable::setStatus(CollapseStatus status)
{
status_ = st;
status_ = status;
setButtonLabel();
}
@ -391,8 +419,3 @@ void InsetCollapsable::scroll(BufferView & bv, int offset) const
UpdatableInset::scroll(bv, offset);
}
Box const & InsetCollapsable::buttonDim() const
{
return button_dim;
}

View File

@ -51,6 +51,10 @@ public:
///
void draw(PainterInfo & pi, int x, int y) const;
///
void drawSelection(PainterInfo & pi, int x, int y) const;
/// return x,y of given position relative to the inset's baseline
void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
///
bool hitButton(FuncRequest &) const;
///
std::string const getNewLabel(std::string const & l) const;
@ -91,9 +95,7 @@ protected:
///
virtual void doDispatch(LCursor & cur, FuncRequest & cmd);
///
void dimension_collapsed(Dimension &) const;
///
void draw_collapsed(PainterInfo & pi, int x, int y) const;
Dimension dimensionCollapsed() const;
///
int getMaxTextWidth(Painter & pain, UpdatableInset const *) const;
///

View File

@ -79,10 +79,12 @@ auto_ptr<InsetBase> InsetERT::doClone() const
InsetERT::InsetERT(BufferParams const & bp,
Language const * l, string const & contents, CollapseStatus status)
Language const *, string const & contents, CollapseStatus status)
: InsetCollapsable(bp, status)
{
LyXFont font(LyXFont::ALL_INHERIT, l);
//LyXFont font(LyXFont::ALL_INHERIT, lang);
LyXFont font;
getDrawFont(font);
string::const_iterator cit = contents.begin();
string::const_iterator end = contents.end();
pos_type pos = 0;
@ -259,7 +261,7 @@ bool InsetERT::getStatus(LCursor & cur, FuncRequest const & cmd,
void InsetERT::setButtonLabel()
{
setLabel(status() == Collapsed ? getNewLabel(_("P-ERT")) : _("P-ERT"));
setLabel(status() == Collapsed ? getNewLabel(_("ERT")) : _("ERT"));
}

View File

@ -16,6 +16,7 @@
#include "bufferparams.h"
#include "BufferView.h"
#include "cursor.h"
#include "coordcache.h"
#include "debug.h"
#include "dispatchresult.h"
#include "funcrequest.h"
@ -36,6 +37,7 @@
#include "frontends/font_metrics.h"
#include "frontends/LyXView.h"
#include "frontends/Painter.h"
#include "frontends/nullpainter.h"
#include <sstream>
#include <iostream>
@ -251,7 +253,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
}
dim.asc = tabular.getAscentOfRow(0);
dim.des = tabular.getHeightOfTabular() - tabular.getAscentOfRow(0) + 1;
dim.des = tabular.getHeightOfTabular() - dim.asc;
dim.wid = tabular.getWidthOfTabular() + 2 * ADD_TO_TABULAR_WIDTH;
dim_ = dim;
}
@ -260,8 +262,13 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetTabular::draw(PainterInfo & pi, int x, int y) const
{
//lyxerr << "InsetTabular::draw: " << x << " " << y << endl;
BufferView * bv = pi.base.bv;
static NullPainter nop;
static PainterInfo nullpi(bv, nop);
resetPos(bv->cursor());
setPosCache(pi, x, y);
x += scroll();
@ -271,49 +278,80 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
first_visible_cell = -1;
for (int i = 0; i < tabular.rows(); ++i) {
int nx = x;
int const a = tabular.getAscentOfRow(i);
int const d = tabular.getDescentOfRow(i);
idx = tabular.getCellNumber(i, 0);
if (y + tabular.getDescentOfRow(i) <= 0
&& y - tabular.getAscentOfRow(i) < pi.pain.paperHeight()) {
y += tabular.getDescentOfRow(i)
+ tabular.getAscentOfRow(i + 1)
if (y + d <= 0 && y - a < pi.pain.paperHeight()) {
y += d + tabular.getAscentOfRow(i + 1)
+ tabular.getAdditionalHeight(i + 1);
continue;
}
for (int j = 0; j < tabular.columns(); ++j) {
if (nx > bv->workWidth())
break;
if (tabular.isPartOfMultiColumn(i, j))
continue;
if (first_visible_cell < 0)
first_visible_cell = idx;
if (bv->cursor().selection())
drawCellSelection(pi, nx, y, i, j, idx);
int const cx = nx + tabular.getBeginningOfTextInCell(idx);
if (nx + tabular.getWidthOfColumn(idx) < 0
|| nx > bv->workWidth()
|| y - a > bv->workHeight()) {
cell(idx)->draw(nullpi, cx, y);
drawCellLines(nop, nx, y, i, idx);
} else {
cell(idx)->draw(pi, cx, y);
drawCellLines(pi.pain, nx, y, i, idx);
}
nx += tabular.getWidthOfColumn(idx);
++idx;
}
// Would be nice, but for some completely unfathomable reason,
// on a col resize to a new fixed width, even though the insettexts
// are resized, the cell isn't, but drawing all cells in a tall table
// has the desired effect somehow. Complete dark magic.
#if 0
// avoiding drawing the rest of a long table is
// a pretty big speedup
if (y > bv->workHeight())
break;
#endif
y += tabular.getDescentOfRow(i) +
tabular.getAscentOfRow(i + 1) +
if (i + 1 < tabular.rows())
y += d + tabular.getAscentOfRow(i + 1) +
tabular.getAdditionalHeight(i + 1);
}
}
void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
{
LCursor & cur = pi.base.bv->cursor();
if (!cur.selection())
return;
if (!ptr_cmp(&cur.inset(), this))
return;
x += scroll();
x += ADD_TO_TABULAR_WIDTH;
if (tablemode(cur)) {
int rs, re, cs, ce;
getSelection(cur, rs, re, cs, ce);
for (int j = 0; j < tabular.rows(); ++j) {
int const a = tabular.getAscentOfRow(j);
int const h = a + tabular.getDescentOfRow(j);
int xx = x;
y += tabular.getAdditionalHeight(j);
for (int i = 0; i < tabular.columns(); ++i) {
if (tabular.isPartOfMultiColumn(j, i))
continue;
int const cell = tabular.getCellNumber(j, i);
int const w = tabular.getWidthOfColumn(cell);
if (i >= cs && i <= ce && j >= rs && j <= re)
pi.pain.fillRectangle(xx, y - a, w, h,
LColor::selection);
xx += w;
}
y += h;
}
} else {
cur.text()->drawSelection(pi, x, y);
}
}
void InsetTabular::drawCellLines(Painter & pain, int x, int y,
int row, int cell) const
{
@ -349,24 +387,6 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
}
void InsetTabular::drawCellSelection(PainterInfo & pi, int x, int y,
int row, int column, int cell) const
{
LCursor & cur = pi.base.bv->cursor();
BOOST_ASSERT(cur.selection());
if (tablemode(cur)) {
int rs, re, cs, ce;
getSelection(cur, rs, re, cs, ce);
if (column >= cs && column <= ce && row >= rs && row <= re) {
int w = tabular.getWidthOfColumn(cell);
int h = tabular.getAscentOfRow(row) + tabular.getDescentOfRow(row)-1;
pi.pain.fillRectangle(x, y - tabular.getAscentOfRow(row) + 1,
w, h, LColor::selection);
}
}
}
string const InsetTabular::editMessage() const
{
return _("Opened table");
@ -446,7 +466,8 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
setPos(cur, cmd.x, cmd.y);
bvcur.setCursor(cur);
bvcur.selection() = true;
}
} else
cur.undispatched();
}
break;
@ -513,6 +534,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
if (sl == cur.top()) {
cmd = FuncRequest(LFUN_FINISHED_DOWN);
cur.undispatched();
resetPos(cur);
}
break;
@ -530,45 +552,46 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
if (sl == cur.top()) {
cmd = FuncRequest(LFUN_FINISHED_UP);
cur.undispatched();
resetPos(cur);
}
break;
case LFUN_NEXT: {
//if (hasSelection())
// cur.selection() = false;
int const col = tabular.column_of_cell(cur.idx());
int const t = cur.bv().top_y() + cur.bv().painter().paperHeight();
if (t < yo() + tabular.getHeightOfTabular()) {
cur.bv().scrollDocView(t);
cur.idx() = tabular.getCellBelow(first_visible_cell) + col;
} else {
cur.idx() = tabular.getFirstCellInRow(tabular.rows() - 1) + col;
}
cur.pit() = 0;
cur.pos() = 0;
resetPos(cur);
break;
}
case LFUN_PRIOR: {
//if (hasSelection())
// cur.selection() = false;
int const col = tabular.column_of_cell(cur.idx());
int const t = cur.bv().top_y() + cur.bv().painter().paperHeight();
if (yo() < 0) {
cur.bv().scrollDocView(t);
if (yo() > 0)
cur.idx() = col;
else
cur.idx() = tabular.getCellBelow(first_visible_cell) + col;
} else {
cur.idx() = col;
}
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
resetPos(cur);
break;
}
// case LFUN_NEXT: {
// //if (hasSelection())
// // cur.selection() = false;
// int const col = tabular.column_of_cell(cur.idx());
// int const t = cur.bv().top_y() + cur.bv().painter().paperHeight();
// if (t < yo() + tabular.getHeightOfTabular()) {
// cur.bv().scrollDocView(t);
// cur.idx() = tabular.getCellBelow(first_visible_cell) + col;
// } else {
// cur.idx() = tabular.getFirstCellInRow(tabular.rows() - 1) + col;
// }
// cur.par() = 0;
// cur.pos() = 0;
// resetPos(cur);
// break;
// }
//
// case LFUN_PRIOR: {
// //if (hasSelection())
// // cur.selection() = false;
// int const col = tabular.column_of_cell(cur.idx());
// int const t = cur.bv().top_y() + cur.bv().painter().paperHeight();
// if (yo() < 0) {
// cur.bv().scrollDocView(t);
// if (yo() > 0)
// cur.idx() = col;
// else
// cur.idx() = tabular.getCellBelow(first_visible_cell) + col;
// } else {
// cur.idx() = col;
// }
// cur.par() = cur.lastpar();
// cur.pos() = cur.lastpos();
// resetPos(cur);
// break;
// }
case LFUN_LAYOUT_TABULAR:
InsetTabularMailer(*this).showDialog(&cur.bv());
@ -955,28 +978,86 @@ shared_ptr<InsetText> InsetTabular::cell(int idx)
}
void InsetTabular::getCursorPos(LCursor const & cur, int & x, int & y) const
void InsetTabular::getCursorPos(CursorSlice const & sl, int & x, int & y) const
{
cell(cur.idx())->getCursorPos(cur, x, y);
cell(sl.idx())->getCursorPos(sl, x, y);
// y offset correction
int const row = tabular.row_of_cell(sl.idx());
for (int i = 0; i <= row; ++i) {
if (i != 0) {
y += tabular.getAscentOfRow(i);
y += tabular.getAdditionalHeight(i);
}
if (i != row)
y += tabular.getDescentOfRow(i);
}
// x offset correction
int const col = tabular.column_of_cell(sl.idx());
int idx = tabular.getCellNumber(row, 0);
for (int j = 0; j < col; ++j) {
if (tabular.isPartOfMultiColumn(row, j))
continue;
x += tabular.getWidthOfColumn(idx);
++idx;
}
x += tabular.getBeginningOfTextInCell(idx);
x += ADD_TO_TABULAR_WIDTH;
x += scroll();
}
namespace {
// Manhattan distance to nearest corner
int dist(InsetOld const & inset, int x, int y)
{
int xx = 0;
int yy = 0;
Point o = theCoords.insets_.xy(&inset);
int const xo = o.x_;
int const yo = o.y_;
if (x < xo)
xx = xo - x;
else if (x > xo + inset.width())
xx = x - xo - inset.width();
if (y < yo - inset.ascent())
yy = yo - inset.ascent() - y;
else if (y > yo + inset.descent())
yy = y - yo - inset.descent();
lyxerr << " xo_=" << xo << " yo_=" << yo
<< " width_=" << inset.width() << " ascent=" << inset.ascent()
<< " descent=" << inset.descent()
<< " dist=" << xx + yy << endl;
return xx + yy;
}
} //namespace anon
InsetBase * InsetTabular::setPos(LCursor & cur, int x, int y) const
{
lyxerr << "# InsetTabular::setPos() x=" << x << " y=" << y << endl;
int idx_min = 0;
int dist_min = 1000000;
int dist_min = std::numeric_limits<int>::max();
for (idx_type i = 0; i < nargs(); ++i) {
int d = getText(i)->dist(x, y);
if (theCoords.insets_.has(tabular.getCellInset(i).get())) {
int d = dist(*tabular.getCellInset(i), x, y);
if (d < dist_min) {
dist_min = d;
idx_min = i;
}
}
}
cur.idx() = idx_min;
InsetBase * inset = cell(cur.idx())->text_.editXY(cur, x, y);
//lyxerr << "# InsetTabular::setPos()\n" << cur << endl;
return inset;
return cell(cur.idx())->text_.editXY(cur, x, y);
}
@ -996,28 +1077,49 @@ int InsetTabular::getCellXPos(int const cell) const
void InsetTabular::resetPos(LCursor & cur) const
{
BufferView & bv = cur.bv();
int const actcol = tabular.column_of_cell(cur.idx());
int const offset = ADD_TO_TABULAR_WIDTH + 2;
int const new_x = getCellXPos(cur.idx()) + offset;
int const old_x = cursorx_;
int const col_width = tabular.getWidthOfColumn(cur.idx());
cursorx_ = new_x;
// int const actcol = tabular.column_of_cell(cur.idx());
// int const offset = ADD_TO_TABULAR_WIDTH + 2;
// int const new_x = getCellXPos(cur.idx()) + offset;
// int const old_x = cursorx_;
// int const col_width = tabular.getWidthOfColumn(cur.idx());
// cursorx_ = new_x;
// cursor.x(getCellXPos(cur.idx()) + offset);
if (actcol < tabular.columns() - 1 && scroll(false) &&
tabular.getWidthOfTabular() < bv.workWidth()-20)
{
scroll(bv, 0.0F);
} else if (cursorx_ - offset > 20 &&
cursorx_ - offset + col_width > bv.workWidth() - 20) {
scroll(bv, - col_width - 20);
} else if (cursorx_ - offset < 20) {
scroll(bv, 20 - cursorx_ + offset);
} else if (scroll() && xo() > 20 &&
xo() + tabular.getWidthOfTabular() > bv.workWidth() - 20) {
scroll(bv, old_x - cursorx_);
// if (actcol < tabular.columns() - 1 && scroll(false) &&
// tabular.getWidthOfTabular() < bv.workWidth()-20)
// {
// scroll(bv, 0.0F);
// } else if (cursorx_ - offset > 20 &&
// cursorx_ - offset + col_width > bv.workWidth() - 20) {
// scroll(bv, - col_width - 20);
// } else if (cursorx_ - offset < 20) {
// scroll(bv, 20 - cursorx_ + offset);
// } else if (scroll() && xo() > 20 &&
// xo() + tabular.getWidthOfTabular() > bv.workWidth() - 20) {
// scroll(bv, old_x - cursorx_);
// }
if (&cur.inset() != this) {
scroll(bv, 0);
} else {
int const X1 = 0;
int const X2 = bv.workWidth();
int const offset = ADD_TO_TABULAR_WIDTH + 2;
int const col_width = tabular.getWidthOfColumn(cur.idx());
int const x1 = getCellXPos(cur.idx()) + offset + scroll();
int const x2 = x1 + col_width;
if (x1 < X1 + 20)
scroll(bv, X1 + 20 - x1);
else if (x2 > X2 - 20)
scroll(bv, X2 - 20 - x2);
}
cur.needsUpdate();
InsetTabularMailer(*this).updateDialog(&bv);
}

View File

@ -60,6 +60,8 @@ public:
///
void draw(PainterInfo & pi, int x, int y) const;
///
void drawSelection(PainterInfo & pi, int x, int y) const;
///
std::string const editMessage() const;
///
bool insetAllowed(InsetBase::Code) const { return true; }
@ -87,8 +89,8 @@ public:
void validate(LaTeXFeatures & features) const;
///
Code lyxCode() const { return InsetBase::TABULAR_CODE; }
/// get the absolute screen x,y of the cursor
void getCursorPos(LCursor const & cur, int & x, int & y) const;
/// get offset of this cursor slice relative to our upper left corner
void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
///
bool tabularFeatures(LCursor & cur, std::string const & what);
///
@ -147,11 +149,7 @@ private:
virtual std::auto_ptr<InsetBase> doClone() const;
///
void drawCellLines(Painter &, int x, int baseline,
int row, int cell) const;
///
void drawCellSelection(PainterInfo &, int x, int baseline,
int row, int column, int cell) const;
void drawCellLines(Painter &, int x, int y, int row, int cell) const;
///
InsetBase * setPos(LCursor & cur, int x, int y) const;

View File

@ -102,7 +102,7 @@ void InsetText::init()
{
for_each(paragraphs().begin(), paragraphs().end(),
bind(&Paragraph::setInsetOwner, _1, this));
old_par = -1;
old_pit = -1;
}
@ -160,7 +160,7 @@ void InsetText::read(Buffer const & buf, LyXLex & lex)
}
// sanity check
// ensure we have at least one par.
// ensure we have at least one paragraph.
if (paragraphs().empty())
paragraphs().push_back(oldpar);
}
@ -170,16 +170,16 @@ void InsetText::metrics(MetricsInfo & mi, Dimension & dim) const
{
//lyxerr << "InsetText::metrics: width: " << mi.base.textwidth << endl;
setViewCache(mi.base.bv);
text_.metrics(mi, dim);
dim_ = dim;
font_ = mi.base.font;
text_.font_ = mi.base.font;
text_.metrics(mi, dim);
dim_ = dim;
}
void InsetText::draw(PainterInfo & pi, int x, int y) const
{
BOOST_ASSERT(!text_.paragraphs().begin()->rows.empty());
BOOST_ASSERT(!text_.paragraphs().front().rows().empty());
// update our idea of where we are
setPosCache(pi, x, y);
@ -187,13 +187,10 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const
bv->hideCursor();
x += scroll();
y -= text_.ascent();
//y -= text_.ascent();
// repaint the background if needed
if (backgroundColor() != LColor::background)
clearInset(pi.pain, x, y);
text_.draw(pi, x, y + bv->top_y());
text_.draw(pi, x, y);
if (drawFrame_)
drawFrame(pi.pain, x, y);
@ -202,15 +199,19 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const
void InsetText::drawSelection(PainterInfo & pi, int x, int y) const
{
// repaint the background if needed
if (backgroundColor() != LColor::background)
clearInset(pi.pain, x, y);
text_.drawSelection(pi, x, y);
}
void InsetText::drawFrame(Painter & pain, int x, int y) const
{
int const w = text_.width();
int const w = max(1, text_.width());
int const h = text_.height();
pain.rectangle(x, y, w, h, frameColor());
int const a = text_.ascent();
pain.rectangle(x, y - a, w, h, frameColor());
}
@ -218,14 +219,15 @@ void InsetText::clearInset(Painter & pain, int x, int y) const
{
int const w = text_.width();
int const h = text_.height();
pain.fillRectangle(x, y, w, h, backgroundColor());
int const a = text_.ascent();
pain.fillRectangle(x, y - a, w, h, backgroundColor());
}
void InsetText::updateLocal(LCursor & cur)
{
if (!autoBreakRows_ && paragraphs().size() > 1) {
// collapseParagraphs
// collapse paragraphs
while (paragraphs().size() > 1) {
ParagraphList::iterator const first = paragraphs().begin();
ParagraphList::iterator second = first;
@ -250,9 +252,9 @@ void InsetText::updateLocal(LCursor & cur)
lv->view_state_changed();
lv->updateMenubar();
lv->updateToolbars();
if (old_par != cur.pit()) {
if (old_pit != cur.pit()) {
lv->setLayout(text_.getPar(cur.pit()).layout()->name());
old_par = cur.pit();
old_pit = cur.pit();
}
}
@ -266,11 +268,11 @@ string const InsetText::editMessage() const
void InsetText::edit(LCursor & cur, bool left)
{
//lyxerr << "InsetText: edit left/right" << endl;
old_par = -1;
old_pit = -1;
setViewCache(&cur.bv());
int const par = left ? 0 : paragraphs().size() - 1;
int const pit = left ? 0 : paragraphs().size() - 1;
int const pos = left ? 0 : paragraphs().back().size();
text_.setCursor(cur.top(), par, pos);
text_.setCursor(cur.top(), pit, pos);
cur.clearSelection();
finishUndo();
#ifdef WITH_WARNINGS
@ -283,7 +285,7 @@ void InsetText::edit(LCursor & cur, bool left)
InsetBase * InsetText::editXY(LCursor & cur, int x, int y) const
{
old_par = -1;
old_pit = -1;
return text_.editXY(cur, x, y);
//sanitizeEmptyText(cur.bv());
//updateLocal(cur);
@ -354,10 +356,10 @@ void InsetText::validate(LaTeXFeatures & features) const
}
void InsetText::getCursorPos(LCursor const & cur, int & x, int & y) const
void InsetText::getCursorPos(CursorSlice const & sl, int & x, int & y) const
{
x = text_.cursorX(cur.top());
y = text_.cursorY(cur.top());
x = text_.cursorX(sl);
y = text_.cursorY(sl);
}

View File

@ -72,10 +72,11 @@ public:
OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const;
/// return x,y of given position relative to the inset's baseline
void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
///
Code lyxCode() const { return TEXT_CODE; }
/// FIXME, document
void getCursorPos(LCursor const & cur, int & x, int & y) const;
///
void setFont(BufferView *, LyXFont const &,
bool toggleall = false,
@ -165,7 +166,7 @@ private:
*/
int frame_color_;
///
mutable lyx::pit_type old_par;
mutable lyx::pit_type old_pit;
public:
///
mutable LyXText text_;

View File

@ -366,8 +366,6 @@ bool findNextChange(BufferView * bv)
// if we used a lfun like in find/replace, dispatch would do
// that for us
bv->update();
if (bv->fitCursor())
bv->update();
return true;
}

View File

@ -601,6 +601,7 @@ void loadTextclass(string const & name)
void LyXFunc::dispatch(FuncRequest const & cmd)
{
BOOST_ASSERT(view());
string const argument = cmd.argument;
kb_action const action = cmd.action;
@ -1450,7 +1451,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
update |= view()->cursor().result().update();
else
update |= view()->dispatch(cmd);
break;
}
}
@ -1459,14 +1459,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
// Redraw screen unless explicitly told otherwise.
// This also initializes the position cache for all insets
// in (at least partially) visible top-level paragraphs.
if (update)
view()->update();
view()->update(true, update);
// fitCursor() needs valid inset position. The previous call to
// update() makes sure we have such even for freshly created
// insets.
if (view()->fitCursor())
view()->update();
// if we executed a mutating lfun, mark the buffer as dirty
if (getStatus(cmd).enabled()
&& !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)

View File

@ -22,19 +22,18 @@
using lyx::pos_type;
RowMetrics::RowMetrics() : separator(0), hfill(0), label_hfill(0), x(0)
RowMetrics::RowMetrics()
: separator(0), hfill(0), label_hfill(0), x(0)
{}
Row::Row()
: pos_(0), end_(0), height_(0), width_(0), y_offset_(0),
ascent_of_text_(0), baseline_(0)
: pos_(0), end_(0), ascent_(0), descent_(0), width_(0)
{}
Row::Row(pos_type pos)
: pos_(pos), end_(0), height_(0), width_(0), y_offset_(0),
ascent_of_text_(0), baseline_(0)
: pos_(pos), end_(0), ascent_(0), descent_(0), width_(0)
{}
@ -62,65 +61,35 @@ pos_type Row::endpos() const
}
void Row::width(unsigned int w)
void Row::width(int w)
{
width_ = w;
}
unsigned int Row::width() const
int Row::width() const
{
return width_;
}
void Row::ascent_of_text(unsigned int a)
void Row::ascent(int b)
{
ascent_of_text_ = a;
ascent_ = b;
}
unsigned int Row::ascent_of_text() const
int Row::ascent() const
{
return ascent_of_text_;
}
void Row::top_of_text(unsigned int top)
{
top_of_text_ = top;
}
unsigned int Row::top_of_text() const
{
return top_of_text_;
}
void Row::baseline(unsigned int b)
{
baseline_ = b;
}
unsigned int Row::baseline() const
{
return baseline_;
}
bool Row::isParStart() const
{
return !pos();
return ascent_;
}
void Row::dump(const char * s) const
{
lyxerr << s << " pos: " << pos_ << " width: " << width_
<< " height: " << height_
<< " ascent_of_text: " << ascent_of_text_
<< " top_of_text: " << top_of_text_
<< " y_offset: " << y_offset_ << std::endl;
lyxerr << s << " pos: " << pos_ << " end: " << end_
<< " width: " << width_
<< " ascent: " << ascent_
<< " descent: " << descent_
<< std::endl;
}

View File

@ -33,31 +33,19 @@ public:
///
lyx::pos_type endpos() const;
///
void height(unsigned int h) { height_ = h; }
int height() const { return ascent_ + descent_; }
///
unsigned int height() const { return height_; }
void width(int w);
///
void width(unsigned int w);
int width() const;
///
unsigned int width() const;
void ascent(int b);
///
void ascent_of_text(unsigned int a);
int ascent() const;
///
unsigned int ascent_of_text() const;
void descent(int b) { descent_ = b; }
///
void top_of_text(unsigned int top);
///
unsigned int top_of_text() const;
///
void baseline(unsigned int b);
///
unsigned int baseline() const;
/// return true if this row is the start of a paragraph
bool isParStart() const;
/// return the cached y position
unsigned int y_offset() const { return y_offset_; }
/// cache the y position
void y_offset(unsigned int newy) { y_offset_ = newy; }
int descent() const { return descent_; }
/// current debugging only
void dump(const char * = "") const;
@ -67,17 +55,11 @@ private:
/// one behind last pos covered by this row
lyx::pos_type end_;
///
unsigned int height_;
int ascent_;
///
unsigned int width_;
/// cached y position
unsigned int y_offset_;
/// ascent from baseline including prelude space
unsigned short ascent_of_text_;
/// the top of the real text in the row
unsigned int top_of_text_;
int descent_;
///
unsigned int baseline_;
int width_;
};

View File

@ -17,6 +17,7 @@
#include "bufferview_funcs.h"
#include "Bidi.h"
#include "dispatchresult.h"
#include "dimension.h"
#include "lyxfont.h"
#include "layout.h"
#include "lyxlayout_ptr_fwd.h"
@ -56,8 +57,6 @@ public:
///
void init(BufferView *);
/// update y coordinate cache of all paragraphs
void updateParPositions();
///
LyXFont getFont(Paragraph const & par, pos_type pos) const;
///
@ -93,12 +92,8 @@ public:
/// Set font over selection paragraphs and rebreak.
void setFont(LCursor & cur, LyXFont const &, bool toggleall = false);
/// rebreaks all paragaphs between the given pars.
void redoParagraphs(pit_type begin, pit_type end);
/// rebreaks the given par
void redoParagraph(pit_type pit);
/// rebreaks the cursor par
void redoParagraph(LCursor & cur);
/// returns pos in given par at given x coord
pos_type x2pos(pit_type pit, int row, int x) const;
@ -115,17 +110,12 @@ public:
/// insert an inset at cursor position
void insertInset(LCursor & cur, InsetBase * inset);
/// a full rebreak of the whole text
void fullRebreak();
/// compute text metrics
void metrics(MetricsInfo & mi, Dimension & dim);
/// draw text (only used for insets)
void draw(PainterInfo & pi, int x, int y) const;
/// draw textselection
void drawSelection(PainterInfo & pi, int x, int y) const;
/// returns distance of this cell to the point given by x and y
// assumes valid position and size cache
int dist(int x, int y) const;
/// try to handle that request
void dispatch(LCursor & cur, FuncRequest & cmd);
@ -143,11 +133,11 @@ public:
// Returns the current font and depth as a message.
std::string LyXText::currentState(LCursor & cur);
/** returns an iterator pointing to the row near the specified
* y-coordinate (relative to the whole text). y is set to the
* real beginning of this row
/** returns row near the specified
* y-coordinate in given paragraph (relative to the screen).
*/
Row const & getRowNearY(int y, pit_type & pit) const;
Row const & getRowNearY(int y, pit_type pit) const;
pit_type getPitNearY(int y) const;
/** returns the column near the specified x-coordinate of the row
x is set to the real beginning of this column
@ -339,11 +329,9 @@ public:
public:
///
unsigned int width_;
Dimension dim_;
///
int maxwidth_;
///
int height_;
/// the current font settings
LyXFont current_font;
/// the current font
@ -361,10 +349,6 @@ public:
///
ParagraphList pars_;
/// absolute document pixel coordinates of this LyXText
mutable int xo_;
mutable int yo_;
/// our 'outermost' Font
LyXFont font_;
@ -373,8 +357,6 @@ private:
/// change on pit
pit_type undoSpan(pit_type pit);
/// rebreaks the given par
void redoParagraphInternal(pit_type pit);
/// used in setlayout
void makeFontEntriesLayoutSpecific(BufferParams const &, Paragraph & par);

View File

@ -1,3 +1,8 @@
2004-11-26 André Pönitz <poenitz@gmx.net>
* math_nestinset.C (getCursorPos): implement.
2004-11-26 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* math_hullinset.C (getStatus): add status messages

View File

@ -153,6 +153,3 @@ libmathed_la_SOURCES = \
command_inset.C \
ref_inset.h \
ref_inset.C
# math_tfracinset.C
# math_tfracinset.h

View File

@ -56,7 +56,7 @@ void MathMBoxInset::metrics(MetricsInfo & mi, Dimension & dim) const
void MathMBoxInset::draw(PainterInfo & pi, int x, int y) const
{
text_.draw(pi, x + 1, y - text_.ascent());
text_.draw(pi, x + 1, y);
drawMarkers(pi, x, y);
}
@ -102,8 +102,15 @@ LyXText * MathMBoxInset::getText(int) const
}
void MathMBoxInset::getCursorPos(LCursor const & cur, int & x, int & y) const
void MathMBoxInset::getCursorPos(CursorSlice const & sl, int & x, int & y) const
{
x = text_.cursorX(cur.top());
y = text_.cursorY(cur.top());
x = text_.cursorX(sl);
y = text_.cursorY(sl);
}
void MathMBoxInset::drawSelection(PainterInfo & pi, int x, int y) const
{
text_.drawSelection(pi, x, y);
}

View File

@ -27,6 +27,8 @@ public:
/// draw according to cached metrics
void draw(PainterInfo &, int x, int y) const;
///
void drawSelection(PainterInfo & pi, int x, int y) const;
///
bool inMathed() const { return false; }
///
bool isActive() const { return true; }
@ -39,7 +41,7 @@ public:
///
LyXText * getText(int) const;
///
void getCursorPos(LCursor const & cur, int & x, int & y) const;
void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
protected:
virtual void doDispatch(LCursor & cur, FuncRequest & cmd);

View File

@ -34,6 +34,7 @@
#include "FuncStatus.h"
#include "LColor.h"
#include "bufferview_funcs.h"
#include "coordcache.h"
#include "cursor.h"
#include "debug.h"
#include "dispatchresult.h"
@ -97,22 +98,51 @@ MathArray const & MathNestInset::cell(idx_type i) const
}
void MathNestInset::getCursorPos(LCursor const & cur, int & x, int & y) const
void MathNestInset::getCursorPos(CursorSlice const & sl,
int & x, int & y) const
{
BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
MathArray const & ar = cur.cell();
x = ar.xo() + ar.pos2x(cur.pos());
y = ar.yo() + cur.bv().top_y();
// FIXME: This is a hack. Ideally, the coord cache should not store
// absolute positions, but relative ones. This would mean to call
// setXY() not in MathArray::draw(), but in the parent insets' draw()
// with the correctly adjusted x,y values. But this means that we'd have
// to touch all (math)inset's draw() methods. Right now, we'll store
// absolute value, and make them here relative, only to make them
// absolute again when actually drawing the cursor. What a mess.
BOOST_ASSERT(ptr_cmp(&sl.inset(), this));
MathArray const & ar = sl.cell();
if (!theCoords.arrays_.has(&ar)) {
// this can (semi-)legally happen if we jsut created this cell
// and it never has been drawn before. So don't ASSERT.
//lyxerr << "no cached data for array " << &ar << endl;
x = 0;
y = 0;
return;
}
Point const pt = theCoords.arrays_.xy(&ar);
if (!theCoords.insets_.has(this)) {
// same as above
//lyxerr << "no cached data for inset " << this << endl;
x = 0;
y = 0;
return;
}
Point const pt2 = theCoords.insets_.xy(this);
//lyxerr << "retrieving position cache for MathArray "
// << pt.x_ << ' ' << pt.y_ << std::endl;
x = pt.x_ - pt2.x_ + ar.pos2x(sl.pos());
y = pt.y_ - pt2.y_;
// lyxerr << "pt.y_ : " << pt.y_ << " pt2_.y_ : " << pt2.y_
// << " asc: " << ascent() << " des: " << descent()
// << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl;
// move cursor visually into empty cells ("blue rectangles");
if (cur.cell().empty())
if (ar.empty())
x += 2;
}
void MathNestInset::metrics(MetricsInfo const & mi) const
{
MetricsInfo m = mi;
for (idx_type i = 0; i < nargs(); ++i)
for (idx_type i = 0, n = nargs(); i != n; ++i)
cell(i).metrics(m);
}
@ -179,7 +209,7 @@ void MathNestInset::dump() const
os << "---------------------------------------------\n";
write(os);
os << "\n";
for (idx_type i = 0; i < nargs(); ++i)
for (idx_type i = 0, n = nargs(); i != n; ++i)
os << cell(i) << "\n";
os << "---------------------------------------------\n";
}
@ -207,6 +237,7 @@ void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const
return;
if (!ptr_cmp(&cur.inset(), this))
return;
CursorSlice s1 = cur.selBegin();
CursorSlice s2 = cur.selEnd();
//lyxerr << "MathNestInset::drawing selection: "
@ -936,7 +967,8 @@ void MathNestInset::lfunMouseMotion(LCursor & cur, FuncRequest & cmd)
bvcur.setCursor(cur);
bvcur.selection() = true;
}
} else
cur.undispatched();
}
}

View File

@ -37,7 +37,7 @@ public:
/// identifies NestInsets
MathNestInset const * asNestInset() const { return this; }
/// get cursor position
void getCursorPos(LCursor const & cur, int & x, int & y) const;
void getCursorPos(CursorSlice const & sl, int & x, int & y) const;
///
void edit(LCursor & cur, bool left);
///

View File

@ -13,6 +13,7 @@
#define METRICSINFO_H
#include "lyxfont.h"
#include "support/types.h"
#include <string>
@ -88,10 +89,20 @@ struct PainterInfo {
bool ltr_pos;
};
struct TextMetricsInfo {};
struct ViewMetricsInfo
{
ViewMetricsInfo(lyx::pit_type p1, lyx::pit_type p2,
int y1, int y2) : p1(p1), p2(p2), y1(y1), y2(y2) {}
lyx::pit_type p1;
lyx::pit_type p2;
int y1;
int y2;
};
// Generic base for temporarily changing things.
// The original state gets restored when the Changer is destructed.

View File

@ -69,10 +69,8 @@ ParagraphList::ParagraphList()
Paragraph::Paragraph()
: y(0), height(0), begin_of_body_(0),
pimpl_(new Paragraph::Pimpl(this))
: begin_of_body_(0), pimpl_(new Paragraph::Pimpl(this))
{
//lyxerr << "sizeof Paragraph::Pimpl: " << sizeof(Paragraph::Pimpl) << endl;
itemdepth = 0;
params().clear();
}
@ -80,8 +78,8 @@ Paragraph::Paragraph()
Paragraph::Paragraph(Paragraph const & par)
: itemdepth(par.itemdepth), insetlist(par.insetlist),
rows(par.rows), y(par.y), height(par.height),
width(par.width), layout_(par.layout_),
dim_(par.dim_),
rows_(par.rows_), layout_(par.layout_),
text_(par.text_), begin_of_body_(par.begin_of_body_),
pimpl_(new Paragraph::Pimpl(*par.pimpl_, this))
{
@ -105,10 +103,8 @@ Paragraph & Paragraph::operator=(Paragraph const & par)
for (; it != end; ++it)
it->inset = it->inset->clone().release();
rows = par.rows;
y = par.y;
height = par.height;
width = par.width;
rows_ = par.rows_;
dim_ = par.dim_;
layout_ = par.layout();
text_ = par.text_;
begin_of_body_ = par.begin_of_body_;
@ -407,8 +403,8 @@ LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
}
LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
LyXFont const & outerfont) const
LyXFont const Paragraph::getLabelFont
(BufferParams const & bparams, LyXFont const & outerfont) const
{
LyXFont tmpfont = layout()->labelfont;
tmpfont.setLanguage(getParLanguage(bparams));
@ -418,8 +414,8 @@ LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
}
LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
LyXFont const & outerfont) const
LyXFont const Paragraph::getLayoutFont
(BufferParams const & bparams, LyXFont const & outerfont) const
{
LyXFont tmpfont = layout()->font;
tmpfont.setLanguage(getParLanguage(bparams));
@ -430,9 +426,8 @@ LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
/// Returns the height of the highest font in range
LyXFont_size
Paragraph::highestFontInRange(pos_type startpos, pos_type endpos,
LyXFont_size def_size) const
LyXFont_size Paragraph::highestFontInRange
(pos_type startpos, pos_type endpos, LyXFont_size def_size) const
{
if (pimpl_->fontlist.empty())
return def_size;
@ -1792,34 +1787,34 @@ bool Paragraph::allowEmpty() const
}
RowList::iterator Paragraph::getRow(pos_type pos)
Row & Paragraph::getRow(pos_type pos)
{
RowList::iterator rit = rows.end();
RowList::iterator const begin = rows.begin();
RowList::iterator rit = rows_.end();
RowList::iterator const begin = rows_.begin();
for (--rit; rit != begin && rit->pos() > pos; --rit)
;
return rit;
return *rit;
}
RowList::const_iterator Paragraph::getRow(pos_type pos) const
Row const & Paragraph::getRow(pos_type pos) const
{
RowList::const_iterator rit = rows.end();
RowList::const_iterator const begin = rows.begin();
RowList::const_iterator rit = rows_.end();
RowList::const_iterator const begin = rows_.begin();
for (--rit; rit != begin && rit->pos() > pos; --rit)
;
return rit;
return *rit;
}
size_t Paragraph::row(pos_type pos) const
size_t Paragraph::pos2row(pos_type pos) const
{
RowList::const_iterator rit = rows.end();
RowList::const_iterator const begin = rows.begin();
RowList::const_iterator rit = rows_.end();
RowList::const_iterator const begin = rows_.begin();
for (--rit; rit != begin && rit->pos() > pos; --rit)
;
@ -1861,3 +1856,23 @@ unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const
return Encodings::TransformChar(c, Encodings::FORM_ISOLATED);
}
}
void Paragraph::dump() const
{
lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl;
for (size_t i = 0; i != rows_.size(); ++i) {
lyxerr << " row " << i << ": ";
rows_[i].dump();
}
}
//void Paragraph::metrics(MetricsInfo & mi, Dimension & dim, LyXText & text)
//{
//}
//
//
//void draw(PainterInfo & pi, int x, int y, LyXText & text) const
//{
//}

View File

@ -17,6 +17,7 @@
#define PARAGRAPH_H
#include "changes.h"
#include "dimension.h"
#include "InsetList.h"
#include "lyxlayout_ptr_fwd.h"
#include "RowList_fwd.h"
@ -35,12 +36,14 @@ class BufferView;
class Counters;
class InsetBase;
class InsetBibitem;
class LaTeXFeatures;
class InsetBase_code;
class Language;
class LaTeXFeatures;
class OutputParams;
class LyXFont;
class LyXFont_size;
class MetricsInfo;
class OutputParams;
class PainterInfo;
class ParagraphParameters;
class TexRow;
class UpdatableInset;
@ -76,6 +79,7 @@ public:
///
int id() const;
///
Language const * getParLanguage(BufferParams const &) const;
///
@ -358,25 +362,39 @@ public:
ParagraphParameters const & params() const;
///
RowList::iterator getRow(lyx::pos_type pos);
Row & getRow(lyx::pos_type pos);
///
RowList::const_iterator getRow(lyx::pos_type pos) const;
Row const & getRow(lyx::pos_type pos) const;
///
size_t row(lyx::pos_type pos) const;
size_t pos2row(lyx::pos_type pos) const;
///
InsetList insetlist;
///
mutable RowList rows;
/// last draw y position (baseline of top row)
int y;
/// total height of paragraph
unsigned int height;
unsigned int height() const { return dim_.height(); }
/// total width of paragraph, may differ from workwidth
unsigned int width;
unsigned int width() const { return dim_.width(); }
unsigned int ascent() const { return dim_.ascent(); }
unsigned int descent() const { return dim_.descent(); }
///
RowList & rows() { return rows_; }
///
RowList const & rows() const { return rows_; }
// compute paragraph metrics
void metrics(MetricsInfo & mi, Dimension & dim, LyXText & text);
// draw paragraph
void draw(PainterInfo & pi, int x, int y, LyXText & text) const;
/// dump some information
void dump() const;
/// cached dimensions of paragraph
Dimension dim_;
private:
///
mutable RowList rows_;
///
LyXLayout_ptr layout_;
/// keeping this here instead of in the pimpl makes LyX >10% faster

View File

@ -19,6 +19,7 @@
#include "encoding.h"
#include "gettext.h"
#include "language.h"
#include "lyxrow.h"
#include "lyxtext.h"
#include "outputparams.h"
#include "paragraph_pimpl.h"
@ -96,6 +97,9 @@ void breakParagraph(BufferParams const & bparams,
Paragraph & par = pars[par_offset];
// we will invalidate the row cache
par.rows().clear();
// without doing that we get a crash when typing <Return> at the
// end of a paragraph
tmp->layout(bparams.getLyXTextClass().defaultLayout());
@ -316,45 +320,6 @@ LyXFont const outerFont(pit_type par_offset, ParagraphList const & pars)
}
pit_type outerPar(Buffer const & buf, InsetBase const * inset)
{
ParIterator pit = const_cast<Buffer &>(buf).par_iterator_begin();
ParIterator end = const_cast<Buffer &>(buf).par_iterator_end();
for ( ; pit != end; ++pit) {
LyXText * text;
// the second '=' below is intentional
for (int i = 0; (text = inset->getText(i)); ++i)
if (&text->paragraphs() == &pit.plist())
return pit.outerPar();
InsetList::const_iterator ii = pit->insetlist.begin();
InsetList::const_iterator iend = pit->insetlist.end();
for ( ; ii != iend; ++ii)
if (ii->inset == inset)
return pit.outerPar();
}
lyxerr << "outerPar: should not happen" << endl;
BOOST_ASSERT(false);
return buf.paragraphs().size(); // shut up compiler
}
/// return the range of pars [beg, end[ owning the range of y [ystart, yend]
void getParsInRange(ParagraphList & pars, int ystart, int yend,
pit_type & beg, pit_type & end)
{
BOOST_ASSERT(!pars.empty());
pit_type const endpar = pars.size();
pit_type const begpar = 0;
for (beg = endpar - 1; beg != begpar && pars[beg].y > ystart; --beg)
;
for (end = beg ; end != endpar && pars[end].y <= yend; ++end)
;
}
/// return the number of InsetOptArg in a paragraph
int numberOfOptArgs(Paragraph const & par)
{
@ -368,5 +333,3 @@ int numberOfOptArgs(Paragraph const & par)
}
return num;
}

View File

@ -56,19 +56,9 @@ bool isFirstInSequence(lyx::pit_type par, ParagraphList const & plist);
proof environment */
int getEndLabel(lyx::pit_type par, ParagraphList const & plist);
LyXFont const outerFont(lyx::pit_type par, ParagraphList const & plist);
/// find outermost paragraph containing an inset
lyx::pit_type outerPar(Buffer const & buf, InsetBase const * inset);
/// return the range of pars [beg, end[ owning the range of y [ystart, yend]
void getParsInRange(ParagraphList & plist,
int ystart, int yend,
lyx::pit_type & beg,
lyx::pit_type & end);
LyXFont const outerFont(lyx::pit_type par_offset, ParagraphList const & pars);
/// return the number of InsetOptArg in a paragraph
int numberOfOptArgs(Paragraph const & par);
#endif // PARAGRAPH_FUNCS_H

View File

@ -84,7 +84,7 @@ Paragraph & ParIterator::operator*() const
pit_type ParIterator::pit() const
{
return pit();
return DocIterator::pit();
}

View File

@ -45,6 +45,7 @@ using lyx::pit_type;
using std::endl;
using std::max;
using std::min;
using std::string;
@ -56,23 +57,23 @@ namespace {
class RowPainter {
public:
/// initialise and run painter
RowPainter(BufferView const & bv, Painter & pain, LyXText const & text,
pit_type pit, RowList::iterator rit, int y);
private:
RowPainter(PainterInfo & pi, LyXText const & text,
pit_type pit, Row & row, int x, int y);
// paint various parts
void paintBackground();
void paintSelection();
void paintAppendix();
void paintDepthBar();
void paintChangeBar();
void paintFirst();
void paintLast();
void paintText();
private:
void paintForeignMark(double orig_x, LyXFont const & orig_font);
void paintHebrewComposeChar(lyx::pos_type & vpos);
void paintArabicComposeChar(lyx::pos_type & vpos);
void paintChars(lyx::pos_type & vpos, bool hebrew, bool arabic);
int paintAppendixStart(int y);
void paintText();
void paintFromPos(lyx::pos_type & vpos);
void paintInset(lyx::pos_type const pos);
@ -100,7 +101,6 @@ private:
ParagraphList & pars_;
/// The row to paint
RowList::iterator const rit_;
Row & row_;
/// Row's paragraph
@ -108,8 +108,8 @@ private:
Paragraph const & par_;
// Looks ugly - is
double xo_;
int yo_;
double const xo_;
int const yo_; // current baseline
double x_;
int width_;
double separator_;
@ -118,48 +118,24 @@ private:
};
RowPainter::RowPainter(BufferView const & bv, Painter & pain,
LyXText const & text, pit_type pit, RowList::iterator rit, int y)
: bv_(bv), pain_(pain), text_(text), pars_(text.paragraphs()),
rit_(rit), row_(*rit), pit_(pit), par_(text.paragraphs()[pit]),
xo_(text_.xo_), yo_(y), width_(text_.width())
RowPainter::RowPainter(PainterInfo & pi,
LyXText const & text, pit_type pit, Row & row, int x, int y)
: bv_(*pi.base.bv), pain_(pi.pain), text_(text), pars_(text.paragraphs()),
row_(row), pit_(pit), par_(text.paragraphs()[pit]),
xo_(x), yo_(y), width_(text_.width())
{
//lyxerr << "RowPainter: x: " << x_ << " xo: " << xo << " yo: " << yo
// << " pit->y: " << pit_->y
// << " row: " << (par_.size() ? par_.getChar(row_.pos()) : 'X') << endl;
RowMetrics m = text_.computeRowMetrics(pit, row_);
x_ = m.x + xo_;
//lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl;
//row_.dump();
separator_ = m.separator;
hfill_ = m.hfill;
label_hfill_ = m.label_hfill;
// background has already been cleared.
if (&text_ == bv_.text())
paintBackground();
// paint the selection background
if (bv_.cursor().selection() && &text_ == bv_.cursor().text())
paintSelection();
// vertical lines for appendix
paintAppendix();
// environment depth brackets
paintDepthBar();
// changebar
paintChangeBar();
if (row_.pos() == 0)
paintFirst();
if (row_.endpos() >= par_.size())
paintLast();
// paint text
paintText();
BOOST_ASSERT(pit >= 0);
BOOST_ASSERT(pit < int(text.paragraphs().size()));
}
@ -202,9 +178,9 @@ void RowPainter::paintInset(pos_type const pos)
PainterInfo pi(const_cast<BufferView *>(&bv_), pain_);
pi.base.font = getFont(pos);
pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0);
theCoords.insets_.add(inset, int(x_), yo_ + row_.baseline());
inset->drawSelection(pi, int(x_), yo_ + row_.baseline());
inset->draw(pi, int(x_), yo_ + row_.baseline());
theCoords.insets_.add(inset, int(x_), yo_);
inset->drawSelection(pi, int(x_), yo_);
inset->draw(pi, int(x_), yo_);
x_ += inset->width();
}
@ -239,7 +215,7 @@ void RowPainter::paintHebrewComposeChar(pos_type & vpos)
}
// Draw nikud
pain_.text(int(x_) + dx, yo_ + row_.baseline(), str, font);
pain_.text(int(x_) + dx, yo_, str, font);
}
@ -269,7 +245,7 @@ void RowPainter::paintArabicComposeChar(pos_type & vpos)
}
}
// Draw nikud
pain_.text(int(x_) + dx, yo_ + row_.baseline(), str, font);
pain_.text(int(x_) + dx, yo_, str, font);
}
@ -324,9 +300,8 @@ void RowPainter::paintChars(pos_type & vpos, bool hebrew, bool arabic)
orig_font.setColor(LColor::newtext);
// Draw text and set the new x position
//lyxerr << "paint row: yo_ " << yo_ << " baseline: " << row_.baseline()
// << "\n";
pain_.text(int(x_), yo_ + row_.baseline(), str, orig_font);
//lyxerr << "paint row: yo_ " << yo_ << "\n";
pain_.text(int(x_), yo_, str, orig_font);
x_ += font_metrics::width(str, orig_font);
}
@ -340,7 +315,7 @@ void RowPainter::paintForeignMark(double orig_x, LyXFont const & orig_font)
if (orig_font.language() == bv_.buffer()->params().language)
return;
int const y = yo_ + row_.baseline() + 1;
int const y = yo_ + 1;
pain_.line(int(orig_x), y, int(x_), y, LColor::language);
}
@ -386,110 +361,6 @@ void RowPainter::paintFromPos(pos_type & vpos)
}
void RowPainter::paintBackground()
{
int const x = int(xo_);
int const y = yo_ < 0 ? 0 : yo_;
int const h = yo_ < 0 ? row_.height() + yo_ : row_.height();
pain_.fillRectangle(x, y, width_, h, text_.backgroundColor());
}
void RowPainter::paintSelection()
{
bool const is_rtl = text_.isRTL(par_);
// the current selection
LCursor const & cur = bv_.cursor();
int const starty = text_.cursorY(cur.selBegin());
int const endy = text_.cursorY(cur.selEnd());
pit_type startpit = cur.selBegin().pit();
pit_type endpit = cur.selEnd().pit();
RowList::iterator startrow = pars_[startpit].getRow(cur.selBegin().pos());
RowList::iterator endrow = pars_[endpit].getRow(cur.selEnd().pos());
int const h = row_.height();
int const row_y = text_.yo_ + par_.y + row_.y_offset();
bool const sel_starts_here = startpit == pit_ && startrow == rit_;
bool const sel_ends_here = endpit == pit_ && endrow == rit_;
bool const sel_on_one_row = sel_starts_here && sel_ends_here;
if (text_.bidi.same_direction()) {
if (sel_on_one_row) {
int const startx = text_.cursorX(cur.selBegin());
int const endx = text_.cursorX(cur.selEnd());
int const x1 = is_rtl ? endx : startx;
int const x2 = is_rtl ? startx : endx;
pain_.fillRectangle(x1, yo_, x2 - x1, h, LColor::selection);
} else if (sel_starts_here) {
int const startx = text_.cursorX(cur.selBegin());
int const x1 = is_rtl ? int(xo_) : startx;
int const x2 = is_rtl ? startx : int(xo_) + width_;
pain_.fillRectangle(x1, yo_, x2 - x1, h, LColor::selection);
} else if (sel_ends_here) {
int const endx = text_.cursorX(cur.selEnd());
int const x1 = is_rtl ? endx : int(xo_);
int const x2 = is_rtl ? int(xo_) + width_ : endx;
pain_.fillRectangle(x1, yo_, x2 - x1, h, LColor::selection);
} else if (row_y > starty && row_y < endy) {
pain_.fillRectangle(int(xo_), yo_, width_, h, LColor::selection);
}
return;
}
if ((startpit != pit_ && startrow != rit_ && !is_rtl)
|| (endpit != pit_ && endrow != rit_ && is_rtl))
pain_.fillRectangle(int(xo_), yo_,
int(x_), h, LColor::selection);
pos_type const body_pos = par_.beginOfBody();
pos_type const end = row_.endpos();
double tmpx = x_;
for (pos_type vpos = row_.pos(); vpos < end; ++vpos) {
pos_type pos = text_.bidi.vis2log(vpos);
double const old_tmpx = tmpx;
if (body_pos > 0 && pos == body_pos - 1) {
LyXLayout_ptr const & layout = par_.layout();
LyXFont const lfont = getLabelFont();
tmpx += label_hfill_ + font_metrics::width(layout->labelsep, lfont);
if (par_.isLineSeparator(body_pos - 1))
tmpx -= singleWidth(body_pos - 1);
}
tmpx += singleWidth(pos);
if (hfillExpansion(par_, row_, pos)) {
if (pos >= body_pos)
tmpx += hfill_;
else
tmpx += label_hfill_;
} else {
if (par_.isSeparator(pos) && pos >= body_pos)
tmpx += separator_;
}
if (((startpit != pit_ && startrow != rit_)
|| cur.selBegin().pos() <= pos) &&
((endpit != pit_ && endrow != rit_)
|| pos < cur.selEnd().pos())) {
// Here we do not use x_ as xo_ was added to x_.
pain_.fillRectangle(int(old_tmpx), yo_,
int(tmpx - old_tmpx + 1), h, LColor::selection);
}
}
if ((startpit != pit_ && startrow != rit_ && is_rtl) ||
(endpit != pit_ && endrow != rit_ && !is_rtl)) {
pain_.fillRectangle(int(xo_ + tmpx),
yo_, int(width_ - tmpx), h, LColor::selection);
}
}
void RowPainter::paintChangeBar()
{
pos_type const start = row_.pos();
@ -499,10 +370,10 @@ void RowPainter::paintChangeBar()
return;
int const height = text_.isLastRow(pit_, row_)
? row_.baseline()
: row_.height() + boost::next(rit_)->top_of_text();
? row_.ascent()
: row_.height();
pain_.fillRectangle(4, yo_, 5, height, LColor::changebar);
pain_.fillRectangle(4, yo_ - row_.ascent(), 5, height, LColor::changebar);
}
@ -511,7 +382,7 @@ void RowPainter::paintAppendix()
if (!par_.params().appendix())
return;
int y = yo_;
int y = yo_ - row_.ascent();
if (par_.params().startOfAppendix())
y += 2 * defaultRowHeight();
@ -551,14 +422,15 @@ void RowPainter::paintDepthBar()
if (text_.isMainText())
x += changebarMargin();
int const h = yo_ + row_.height() - 1 - (i - next_depth - 1) * 3;
int const starty = yo_ - row_.ascent();
int const h = row_.height() - 1 - (i - next_depth - 1) * 3;
pain_.line(x, yo_, x, h, LColor::depthbar);
pain_.line(x, starty, x, starty + h, LColor::depthbar);
if (i > prev_depth)
pain_.fillRectangle(x, yo_, w, 2, LColor::depthbar);
pain_.fillRectangle(x, starty, w, 2, LColor::depthbar);
if (i > next_depth)
pain_.fillRectangle(x, h, w, 2, LColor::depthbar);
pain_.fillRectangle(x, starty + h, w, 2, LColor::depthbar);
}
}
@ -643,9 +515,10 @@ void RowPainter::paintFirst()
} else {
spacing_val = buffer.params().spacing().getValue();
}
#warning Look is this correct?
int const labeladdon = int(font_metrics::maxHeight(font) * layout->spacing.getValue() * spacing_val);
int const maxdesc =
int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val)
int const maxdesc = int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val)
+ int(layout->parsep) * defaultRowHeight();
if (is_rtl) {
@ -653,10 +526,7 @@ void RowPainter::paintFirst()
font_metrics::width(str, font);
}
pain_.text(int(x),
yo_ + row_.baseline() -
row_.ascent_of_text() - maxdesc,
str, font);
pain_.text(int(x), yo_ - maxdesc - labeladdon, str, font);
}
} else {
if (is_rtl) {
@ -667,7 +537,7 @@ void RowPainter::paintFirst()
- font_metrics::width(str, font);
}
pain_.text(int(x), yo_ + row_.baseline(), str, font);
pain_.text(int(x), yo_, str, font);
}
}
@ -700,9 +570,7 @@ void RowPainter::paintFirst()
x = width_ - leftMargin() -
font_metrics::width(str, font);
}
pain_.text(int(x),
yo_ + row_.baseline() - row_.ascent_of_text() - maxdesc,
str, font);
pain_.text(int(x), yo_ - maxdesc, str, font);
}
}
}
@ -719,7 +587,7 @@ void RowPainter::paintLast()
case END_LABEL_FILLED_BOX: {
LyXFont const font = getLabelFont();
int const size = int(0.75 * font_metrics::maxAscent(font));
int const y = yo_ + row_.baseline() - size;
int const y = yo_ - size;
int x = is_rtl ? nestMargin() + changebarMargin() : width_ - size;
if (width_ - int(row_.width()) <= size)
@ -738,7 +606,7 @@ void RowPainter::paintLast()
double const x = is_rtl ?
x_ - font_metrics::width(str, font)
: - text_.rightMargin(par_) - row_.width();
pain_.text(int(x), yo_ + row_.baseline(), str, font);
pain_.text(int(x), yo_, str, font);
break;
}
@ -794,7 +662,10 @@ void RowPainter::paintText()
// if we reach the end of a struck out range, paint it
// we also don't paint across things like tables
if (running_strikeout && (highly_editable_inset || !is_struckout)) {
int const middle = yo_ + (row_.baseline() + row_.top_of_text()) / 2;
// FIXME this should take real text height into account, not
// the whole row including padding whitespace
//int const middle = yo_ + (- row_.ascent() + row_.top_of_text()) / 2;
int const middle = yo_ - row_.ascent() / 2;
pain_.line(last_strikeout_x, middle, int(x_), middle,
LColor::strikeout, Painter::line_solid, Painter::line_thin);
running_strikeout = false;
@ -810,7 +681,7 @@ void RowPainter::paintText()
if (par_.isHfill(pos)) {
x_ += 1;
int const y0 = yo_ + row_.baseline();
int const y0 = yo_;
int const y1 = y0 - defaultRowHeight() / 2;
pain_.line(int(x_), y1, int(x_), y0, LColor::added_space);
@ -845,7 +716,9 @@ void RowPainter::paintText()
// if we reach the end of a struck out range, paint it
if (running_strikeout) {
int const middle = yo_ + (row_.baseline() + row_.top_of_text()) / 2;
//top_of_text = font_metrics::maxAscent(font);
//int const middle = yo_ - top_of_text() / 2;
int const middle = yo_ - row_.ascent() / 2;
pain_.line(last_strikeout_x, middle, int(x_), middle,
LColor::strikeout, Painter::line_solid, Painter::line_thin);
running_strikeout = false;
@ -853,53 +726,98 @@ void RowPainter::paintText()
}
int paintPars(BufferView const & bv, Painter & pain,
LyXText const & text, pit_type pit, pit_type end)
void paintPar
(PainterInfo & pi, LyXText const & text, pit_type pit, int x, int y)
{
//lyxerr << " paintRows: pit: " << &*pit << endl;
ParagraphList & pars = text.paragraphs();
// lyxerr << " paintPar: pit: " << pit << " at y: " << y << endl;
static NullPainter nop;
static PainterInfo nullpi(pi.base.bv, nop);
int const ww = pi.base.bv->workHeight();
int y = pars[pit].y + text.yo_ - bv.top_y();
Paragraph & par = text.paragraphs()[pit];
for (; pit != end; ++pit) {
RowList::iterator row = pars[pit].rows.begin();
RowList::iterator rend = pars[pit].rows.end();
RowList::iterator const rb = par.rows().begin();
RowList::iterator const re = par.rows().end();
theCoords.pars_[&text][pit] = Point(x, y);
// We draw full paragraphs to get the (xo, yo) cache of all
// contained insets right. This is needed for properly working
// editXY. And maybe not even sufficient.
// FIXME: Alfredo, please have a look at the coordinate business
// again.
for ( ; row != rend; ++row) {
RowPainter(bv, pain, text, pit, row, y);
y += row->height();
y -= rb->ascent();
for (RowList::iterator rit = rb; rit != re; ++rit) {
y += rit->ascent();
bool const inside = (y + rit->descent() >= 0
&& y - rit->ascent() < ww);
RowPainter rp(inside ? pi : nullpi, text, pit, *rit, x, y);
y += rit->descent();
rp.paintAppendix();
rp.paintDepthBar();
rp.paintChangeBar();
if (rit == rb)
rp.paintFirst();
if (rit + 1 == re)
rp.paintLast();
rp.paintText();
}
}
return y;
}
} // namespace anon
void refreshPar(BufferView const & bv, LyXText const & text, pit_type pit)
void paintText(BufferView const & bv, ViewMetricsInfo const & vi)
{
static NullPainter nop;
paintPars(bv, nop, text, pit, pit + 1);
Painter & pain = bv.painter();
LyXText * const text = bv.text();
// clear background
pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1,
LColor::background);
// draw selection
PainterInfo pi(const_cast<BufferView *>(&bv), pain);
text->drawSelection(pi, 0, 0);
int yy = vi.y1;
// draw contents
for (pit_type pit = vi.p1; pit <= vi.p2; ++pit) {
yy += text->getPar(pit).ascent();
paintPar(pi, *bv.text(), pit, 0, yy);
yy += text->getPar(pit).descent();
}
int paintText(BufferView const & bv)
{
pit_type pit, end;
getParsInRange(bv.text()->paragraphs(), bv.top_y(),
bv.top_y() + bv.workHeight(), pit, end);
//lyxerr << "top_y: " << bv.top_y() << " y: " << pit->y << endl;
return paintPars(bv, bv.painter(), *bv.text(), pit, end);
// paint one paragraph above and one below
if (vi.p1 > 0) {
text->redoParagraph(vi.p1 - 1);
paintPar(pi, *bv.text(), vi.p1 - 1, 0,
vi.y1 - text->getPar(vi.p1 - 1).descent());
}
if (vi.p2 < text->paragraphs().size() - 1) {
text->redoParagraph(vi.p2 + 1);
paintPar(pi, *bv.text(), vi.p2 + 1, 0,
vi.y2 + text->getPar(vi.p2 + 1).ascent());
}
// and grey out above (should not happen later)
lyxerr << "par ascent: " << text->getPar(vi.p1).ascent() << endl;
if (vi.y1 > 0)
pain.fillRectangle(0, 0, bv.workWidth(), vi.y1, LColor::bottomarea);
// and possibly grey out below
lyxerr << "par descent: " << text->getPar(vi.p1).ascent() << endl;
if (vi.y2 < bv.workHeight())
pain.fillRectangle(0, vi.y2, bv.workWidth(), bv.workHeight() - vi.y2, LColor::bottomarea);
}
void paintTextInset(LyXText const & text, PainterInfo & pi)
void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y)
{
paintPars(*pi.base.bv, pi.pain, text, 0, text.paragraphs().size());
// lyxerr << " paintTextInset: y: " << y << endl;
y -= text.getPar(0).ascent();
for (int pit = 0; pit < int(text.paragraphs().size()); ++pit) {
y += text.getPar(pit).ascent();
paintPar(pi, text, pit, x, y);
y += text.getPar(pit).descent();
}
}

View File

@ -6,6 +6,7 @@
*
* \author various
* \author John Levon
* \author André Pönitz
*
* Full author contact details are available in file CREDITS.
*/
@ -18,36 +19,23 @@
class LyXText;
class BufferView;
class PainterInfo;
class ViewMetricsInfo;
/// paint the rows of the main text, return last drawn y value
int paintText(BufferView const & bv);
/// refresh a par of the main text
void refreshPar(BufferView const & bv, LyXText const & text,
lyx::pit_type pit);
/// paint visible paragraph of main text
void paintText(BufferView const & bv, ViewMetricsInfo const & vi);
/// paint the rows of a text inset
void paintTextInset(LyXText const & text, PainterInfo & pi);
void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y);
/// some space for drawing the 'nested' markers (in pixel)
inline int nestMargin()
{
return 15;
}
inline int nestMargin() { return 15; }
/// margin for changebar
inline int changebarMargin()
{
return 10;
}
inline int changebarMargin() { return 10; }
/// right margin
inline int rightMargin()
{
return 30;
}
inline int rightMargin() { return 30; }
#endif // ROWPAINTER_H

View File

@ -23,6 +23,7 @@
#include "bufferparams.h"
#include "BufferView.h"
#include "cursor.h"
#include "coordcache.h"
#include "CutAndPaste.h"
#include "debug.h"
#include "dispatchresult.h"
@ -50,6 +51,7 @@
#include "frontends/font_metrics.h"
#include "frontends/LyXView.h"
#include "frontends/Painter.h"
#include "insets/insettext.h"
#include "insets/insetbibitem.h"
@ -105,17 +107,6 @@ int numberOfSeparators(Paragraph const & par, Row const & row)
}
unsigned int maxParagraphWidth(ParagraphList const & plist)
{
unsigned int width = 0;
ParagraphList::const_iterator pit = plist.begin();
ParagraphList::const_iterator end = plist.end();
for (; pit != end; ++pit)
width = std::max(width, pit->width);
return width;
}
int numberOfLabelHfills(Paragraph const & par, Row const & row)
{
pos_type last = row.endpos() - 1;
@ -407,26 +398,15 @@ double LyXText::spacing(Paragraph const & par) const
}
void LyXText::updateParPositions()
{
pit_type pit = 0;
pit_type end = pars_.size();
for (height_ = 0; pit != end; ++pit) {
pars_[pit].y = height_;
height_ += pars_[pit].height;
}
}
int LyXText::width() const
{
return width_;
return dim_.wid;
}
int LyXText::height() const
{
return height_;
return dim_.height();
}
@ -449,7 +429,6 @@ int LyXText::singleWidth(Paragraph const & par,
&& font.language()->lang() == "arabic") {
if (Encodings::IsComposeChar_arabic(c))
return 0;
else
c = par.transformChar(c, pos);
} else if (font.language()->lang() == "hebrew" &&
Encodings::IsComposeChar_hebrew(c))
@ -469,13 +448,20 @@ int LyXText::singleWidth(Paragraph const & par,
int LyXText::leftMargin(pit_type pit) const
{
BOOST_ASSERT(pit >= 0);
BOOST_ASSERT(pit < int(pars_.size()));
return leftMargin(pit, pars_[pit].size());
}
int LyXText::leftMargin(pit_type const pit, pos_type const pos) const
{
BOOST_ASSERT(pit >= 0);
BOOST_ASSERT(pit < int(pars_.size()));
Paragraph const & par = pars_[pit];
BOOST_ASSERT(pos >= 0);
BOOST_ASSERT(pos <= par.size());
//lyxerr << "LyXText::leftMargin: pit: " << pit << " pos: " << pos << endl;
LyXTextClass const & tclass =
bv()->buffer()->params().getLyXTextClass();
LyXLayout_ptr const & layout = par.layout();
@ -484,7 +470,7 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const
int l_margin = 0;
if (xo_ == 0)
if (isMainText())
l_margin += changebarMargin();
l_margin += font_metrics::signedWidth(tclass.leftmargin(), tclass.defaultfont());
@ -570,8 +556,8 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const
#if 0
// ok, a terrible hack. The left margin depends on the widest
// row in this paragraph.
RowList::iterator rit = par.rows.begin();
RowList::iterator end = par.rows.end();
RowList::iterator rit = par.rows().begin();
RowList::iterator end = par.rows().end();
#ifdef WITH_WARNINGS
#warning This is wrong.
#endif
@ -707,7 +693,7 @@ void LyXText::rowBreakPoint(pit_type const pit, Row & row) const
// pixel width since last breakpoint
int chunkwidth = 0;
FontIterator fi = FontIterator(*this, pit, pos);
FontIterator fi = FontIterator(*this, par, pos);
pos_type point = end;
pos_type i = pos;
for ( ; i < end; ++i, ++fi) {
@ -799,7 +785,7 @@ void LyXText::setRowWidth(pit_type const pit, Row & row) const
pos_type i = row.pos();
if (i < end) {
FontIterator fi = FontIterator(*this, pit, i);
FontIterator fi = FontIterator(*this, par, i);
for ( ; i < end; ++i, ++fi) {
if (body_pos > 0 && i == body_pos) {
w += font_metrics::width(labelsep, getLabelFont(par));
@ -914,7 +900,7 @@ void LyXText::setHeightOfRow(pit_type const pit, Row & row)
++maxasc;
++maxdesc;
row.ascent_of_text(maxasc);
row.ascent(maxasc);
// is it a top line?
if (row.pos() == 0) {
@ -1014,9 +1000,8 @@ void LyXText::setHeightOfRow(pit_type const pit, Row & row)
maxasc += int(layoutasc * 2 / (2 + pars_[pit].getDepth()));
maxdesc += int(layoutdesc * 2 / (2 + pars_[pit].getDepth()));
row.height(maxasc + maxdesc + labeladdon);
row.baseline(maxasc + labeladdon);
row.top_of_text(row.baseline() - font_metrics::maxAscent(font));
row.ascent(maxasc + labeladdon);
row.descent(maxdesc);
}
@ -1093,8 +1078,6 @@ void LyXText::breakParagraph(LCursor & cur, char keep_layout)
pars_[next_par].erase(0);
updateCounters();
redoParagraph(cpit);
redoParagraph(next_par);
// This check is necessary. Otherwise the new empty paragraph will
// be deleted automatically. And it is more friendly for the user!
@ -1105,16 +1088,6 @@ void LyXText::breakParagraph(LCursor & cur, char keep_layout)
}
// convenience function
void LyXText::redoParagraph(LCursor & cur)
{
BOOST_ASSERT(this == cur.text());
cur.clearSelection();
redoParagraph(cur.pit());
setCursorIntern(cur, cur.pit(), cur.pos());
}
// insert a character, moves all the following breaks in the
// same Paragraph one to the right and make a rebreak
void LyXText::insertChar(LCursor & cur, char c)
@ -1211,7 +1184,6 @@ void LyXText::insertChar(LCursor & cur, char c)
current_font = rawtmpfont;
real_current_font = realtmpfont;
redoParagraph(cur);
setCursor(cur, cur.pit(), cur.pos() + 1, false, cur.boundary());
charInserted();
}
@ -1231,12 +1203,13 @@ void LyXText::charInserted()
}
RowMetrics LyXText::computeRowMetrics(pit_type const pit, Row const & row) const
RowMetrics
LyXText::computeRowMetrics(pit_type const pit, Row const & row) const
{
RowMetrics result;
Paragraph const & par = pars_[pit];
double w = width_ - row.width();
double w = dim_.wid - row.width();
bool const is_rtl = isRTL(par);
if (is_rtl)
@ -1425,7 +1398,6 @@ void LyXText::acceptChange(LCursor & cur)
pars_[startc.pit()].acceptChange(startc.pos(), endc.pos());
finishUndo();
cur.clearSelection();
redoParagraph(startc.pit());
setCursorIntern(cur, startc.pit(), 0);
}
#ifdef WITH_WARNINGS
@ -1447,7 +1419,6 @@ void LyXText::rejectChange(LCursor & cur)
pars_[startc.pit()].rejectChange(startc.pos(), endc.pos());
finishUndo();
cur.clearSelection();
redoParagraph(startc.pit());
setCursorIntern(cur, startc.pit(), 0);
}
#ifdef WITH_WARNINGS
@ -1597,8 +1568,6 @@ void LyXText::backspace(LCursor & cur)
if (cur.pit() != 0) {
cursorLeft(cur);
// the layout things can change the height of a row !
redoParagraph(cur);
return;
}
}
@ -1656,7 +1625,6 @@ void LyXText::backspace(LCursor & cur)
if (cur.pos() == cur.lastpos())
setCurrentFont(cur);
redoParagraph(cur);
setCursor(cur, cur.pit(), cur.pos(), false, cur.boundary());
}
@ -1672,20 +1640,14 @@ Paragraph & LyXText::getPar(pit_type par) const
Row const & LyXText::firstRow() const
{
return *paragraphs().front().rows.begin();
return *paragraphs().front().rows().begin();
}
void LyXText::redoParagraphInternal(pit_type const pit)
void LyXText::redoParagraph(pit_type const pit)
{
// remove rows of paragraph, keep track of height changes
Paragraph & par = pars_[pit];
height_ -= par.height;
// clear old data
par.rows.clear();
par.height = 0;
par.width = 0;
// redo insets
InsetList::iterator ii = par.insetlist.begin();
@ -1698,6 +1660,9 @@ void LyXText::redoParagraphInternal(pit_type const pit)
}
// rebreak the paragraph
par.rows().clear();
Dimension dim;
par.setBeginOfBody();
pos_type z = 0;
do {
@ -1705,38 +1670,16 @@ void LyXText::redoParagraphInternal(pit_type const pit)
rowBreakPoint(pit, row);
setRowWidth(pit, row);
setHeightOfRow(pit, row);
row.y_offset(par.height);
par.rows.push_back(row);
par.width = std::max(par.width, row.width());
par.height += row.height();
par.rows().push_back(row);
dim.wid = std::max(dim.wid, row.width());
dim.des += row.height();
z = row.endpos();
} while (z < par.size());
height_ += par.height;
//lyxerr << "redoParagraph: " << par.rows.size() << " rows\n";
}
void LyXText::redoParagraphs(pit_type pit, pit_type end)
{
for (; pit != end; ++pit)
redoParagraphInternal(pit);
updateParPositions();
updateCounters();
}
void LyXText::redoParagraph(pit_type pit)
{
redoParagraphInternal(pit);
updateParPositions();
}
void LyXText::fullRebreak()
{
redoParagraphs(0, paragraphs().size());
bv()->cursor().resetAnchor();
dim.asc += par.rows()[0].ascent();
dim.des -= par.rows()[0].ascent();
par.dim_ = dim;
//lyxerr << "redoParagraph: " << par.rows().size() << " rows\n";
}
@ -1746,36 +1689,183 @@ void LyXText::metrics(MetricsInfo & mi, Dimension & dim)
if (mi.base.textwidth)
maxwidth_ = mi.base.textwidth;
//lyxerr << "LyXText::metrics: width: " << mi.base.textwidth
//<< " maxWidth: " << maxwidth << "\nfont: " << mi.base.font
//<< endl;
// << " maxWidth: " << maxwidth_ << "\nfont: " << mi.base.font << endl;
// Rebuild row cache. This recomputes height as well.
redoParagraphs(0, paragraphs().size());
unsigned int h = 0;
unsigned int w = 0;
for (pit_type pit = 0, n = paragraphs().size(); pit != n; ++pit) {
redoParagraph(pit);
Paragraph & par = paragraphs()[pit];
h += par.height();
if (w < par.width())
w = par.width();
}
width_ = maxParagraphWidth(paragraphs());
dim.wid = w;
dim.asc = pars_[0].ascent();
dim.des = h - dim.asc;
// final dimension
dim.asc = firstRow().ascent_of_text();
dim.des = height_ - dim.asc;
dim.wid = width_;
dim_ = dim;
}
// only used for inset right now. should also be used for main text
void LyXText::draw(PainterInfo & pi, int x, int y) const
{
xo_ = x;
yo_ = y;
paintTextInset(*this, pi);
paintTextInset(*this, pi, x, y);
}
/*
// only used for inset right now. should also be used for main text
void LyXText::drawSelection(PainterInfo &, int, int) const
void LyXText::drawSelection(PainterInfo & pi, int x , int) const
{
//lyxerr << "LyXText::drawSelection at " << x << " " << y << endl;
LCursor & cur = pi.base.bv->cursor();
if (!cur.selection())
return;
if (!ptr_cmp(cur.text(), this))
return;
lyxerr << "draw selection at " << x << endl;
// is there a better way of getting these two iterators?
DocIterator beg = cur;
DocIterator end = cur;
beg.top() = cur.selBegin();
end.top() = cur.selEnd();
// the selection doesn't touch the visible screen
if (bv_funcs::status(pi.base.bv, beg) == bv_funcs::CUR_BELOW
|| bv_funcs::status(pi.base.bv, end) == bv_funcs::CUR_ABOVE)
return;
Paragraph const & par1 = pars_[beg.pit()];
Paragraph const & par2 = pars_[end.pit()];
Row const & row1 = par1.getRow(beg.pos());
Row const & row2 = par2.getRow(end.pos());
int y1,x1,x2;
if (bv_funcs::status(pi.base.bv, beg) == bv_funcs::CUR_ABOVE) {
y1 = 0;
x1 = 0;
x2 = 0;
} else {
y1 = bv_funcs::getPos(beg).y_ - row1.ascent();
int const startx = cursorX(beg.top());
x1 = isRTL(par1) ? startx : 0;
x2 = isRTL(par1) ? 0 + dim_.wid : startx;
}
int y2,X1,X2;
if (bv_funcs::status(pi.base.bv, end) == bv_funcs::CUR_BELOW) {
y2 = pi.base.bv->workHeight();
X1 = 0;
X2 = 0;
} else {
y2 = bv_funcs::getPos(end).y_ + row2.descent();
int const endx = cursorX(end.top());
X1 = isRTL(par2) ? 0 : endx;
X2 = isRTL(par2) ? endx : 0 + dim_.wid;
}
lyxerr << " y1: " << y1 << " y2: " << y2
<< " xo: " << xo_ << " wid: " << dim_.wid
<< endl;
// paint big rectangle in one go
pi.pain.fillRectangle(x, y1, dim_.wid, y2 - y1, LColor::selection);
// reset background at begin of first selected line
pi.pain.fillRectangle(x + x1, y1, x2 - x1, row1.height(),
LColor::background);
// reset background at end of last selected line
pi.pain.fillRectangle(x + X1, y2 - row2.height(),
X2 - X1, row2.height(), LColor::background);
}
*/
void LyXText::drawSelection(PainterInfo & pi, int x, int) const
{
LCursor & cur = pi.base.bv->cursor();
if (!cur.selection())
return;
if (!ptr_cmp(cur.text(), this))
return;
lyxerr << "draw selection at " << x << endl;
// is there a better way of getting these two iterators?
DocIterator beg = cur;
DocIterator end = cur;
beg.top() = cur.selBegin();
end.top() = cur.selEnd();
// the selection doesn't touch the visible screen
if (bv_funcs::status(pi.base.bv, beg) == bv_funcs::CUR_BELOW
|| bv_funcs::status(pi.base.bv, end) == bv_funcs::CUR_ABOVE)
return;
Paragraph const & par1 = pars_[beg.pit()];
Paragraph const & par2 = pars_[end.pit()];
bool const above = (bv_funcs::status(pi.base.bv, beg)
== bv_funcs::CUR_ABOVE);
bool const below = (bv_funcs::status(pi.base.bv, end)
== bv_funcs::CUR_BELOW);
int y1,y2,x1,x2;
if (above) {
y1 = 0;
y2 = 0;
x1 = 0;
x2 = dim_.wid;
} else {
Row const & row1 = par1.getRow(beg.pos());
y1 = bv_funcs::getPos(beg).y_ - row1.ascent();
y2 = y1 + row1.height();
int const startx = cursorX(beg.top());
x1 = !isRTL(par1) ? startx : 0;
x2 = !isRTL(par1) ? 0 + dim_.wid : startx;
}
int Y1,Y2,X1,X2;
if (below) {
Y1 = pi.base.bv->workHeight();
Y2 = pi.base.bv->workHeight();
X1 = 0;
X2 = dim_.wid;
} else {
Row const & row2 = par2.getRow(end.pos());
Y1 = bv_funcs::getPos(end).y_ - row2.ascent();
Y2 = Y1 + row2.height();
int const endx = cursorX(end.top());
X1 = !isRTL(par2) ? 0 : endx;
X2 = !isRTL(par2) ? endx : 0 + dim_.wid;
}
if (!above && !below && &par1.getRow(beg.pos())
== &par2.getRow(end.pos()))
{
// paint only one rectangle
pi.pain.fillRectangle(x + x1, y1, X2 - x1, y2 - y1,
LColor::selection);
return;
}
// paint upper rectangle
pi.pain.fillRectangle(x + x1, y1, x2 - x1, y2 - y1,
LColor::selection);
// paint bottom rectangle
pi.pain.fillRectangle(x + X1, Y1, X2 - X1, Y2 - Y1,
LColor::selection);
// paint center rectangle
pi.pain.fillRectangle(x, y2, dim_.wid,
Y1 - y2, LColor::selection);
}
bool LyXText::isLastRow(pit_type pit, Row const & row) const
{
@ -1902,13 +1992,13 @@ bool LyXText::read(Buffer const & buf, LyXLex & lex)
int LyXText::ascent() const
{
return firstRow().ascent_of_text();
return dim_.asc;
}
int LyXText::descent() const
{
return height_ - firstRow().ascent_of_text();
return dim_.des;
}
@ -1916,10 +2006,10 @@ int LyXText::cursorX(CursorSlice const & cur) const
{
pit_type const pit = cur.pit();
Paragraph const & par = pars_[pit];
if (par.rows.empty())
return xo_;
if (par.rows().empty())
return 0;
Row const & row = *par.getRow(cur.pos());
Row const & row = par.getRow(cur.pos());
pos_type pos = cur.pos();
pos_type cursor_vpos = 0;
@ -1971,15 +2061,21 @@ int LyXText::cursorX(CursorSlice const & cur) const
} else
x += singleWidth(par, pos);
}
return xo_ + int(x);
return int(x);
}
int LyXText::cursorY(CursorSlice const & cur) const
{
Paragraph const & par = getPar(cur.pit());
Row const & row = *par.getRow(cur.pos());
return yo_ + par.y + row.y_offset() + row.baseline();
int h = 0;
h -= pars_[0].rows()[0].ascent();
for (pit_type pit = 0; pit < cur.pit(); ++pit)
h += pars_[pit].height();
for (size_t rit = 0, rend = par.pos2row(cur.pos()); rit != rend; ++rit)
h += par.rows()[rit].height();
h += par.rows()[par.pos2row(cur.pos())].ascent();
return h;
}
@ -2051,8 +2147,8 @@ string LyXText::currentState(LCursor & cur)
os << _(", Paragraph: ") << cur.pit();
os << _(", Id: ") << par.id();
os << _(", Position: ") << cur.pos();
Row & row = cur.textRow();
os << bformat(_(", Row b:%1$d e:%2$d"), row.pos(), row.endpos());
// Row & row = cur.textRow();
// os << bformat(_(", Row b:%1$d e:%2$d"), row.pos(), row.endpos());
#endif
return os.str();
}
@ -2096,25 +2192,66 @@ string LyXText::getPossibleLabel(LCursor & cur) const
}
// Manhattan distance to nearest corner
int LyXText::dist(int x, int y) const
//pos_type LyXText::x2pos(pit_type pit, int row, int x) const
//{
// int lastx = 0;
// int currx = 0;
// Paragraph const & par = pars_[pit];
// Row const & r = par.rows()[row];
// int pos = r.pos();
// for (; currx < x && pos < r.endpos(); ++pos) {
// lastx = currx;
// currx += singleWidth(par, pos);
// }
// if (abs(lastx - x) < abs(currx - x) && pos != r.pos())
// --pos;
// return pos;
//}
pos_type LyXText::x2pos(pit_type pit, int row, int x) const
{
int xx = 0;
int yy = 0;
if (x < xo_)
xx = xo_ - x;
else if (x > xo_ + int(width_))
xx = x - xo_ - width_;
if (y < yo_ - ascent())
yy = yo_ - ascent() - y;
else if (y > yo_ + descent())
yy = y - yo_ - descent();
lyxerr << " xo_=" << xo_ << " yo_=" << yo_
<< " width_=" << width_ << " ascent=" << ascent()
<< " descent=" << descent()
<< " dist=" << xx+yy <<endl;
return xx + yy;
bool bound = false;
Row const & r = pars_[pit].rows()[row];
return r.pos() + getColumnNearX(pit, r, x, bound);
}
//int LyXText::pos2x(pit_type pit, pos_type pos) const
//{
// Paragraph const & par = pars_[pit];
// Row const & r = par.rows()[row];
// int x = 0;
// pos -= r.pos();
//}
// x,y are screen coordinates
// sets cursor only within this LyXText
void LyXText::setCursorFromCoordinates(LCursor & cur, int const x, int const y)
{
pit_type pit = getPitNearY(y);
int yy = theCoords.get(this, pit).y_ - pars_[pit].ascent();
lyxerr << "setCursorFromCoordinates: x: " << x << " y: " << y
<< " pit: " << pit << " yy: " << yy << endl;
Paragraph const & par = pars_[pit];
int r = 0;
BOOST_ASSERT(par.rows().size());
for (; r < int(par.rows().size()) - 1; ++r) {
Row const & row = par.rows()[r];
if (int(yy + row.height()) > y)
break;
yy += row.height();
}
Row const & row = par.rows()[r];
lyxerr << "setCursorFromCoordinates: row " << r
<< " from pos: " << row.pos() << endl;
bool bound = false;
int xx = x;
pos_type const pos = row.pos() + getColumnNearX(pit, row, xx, bound);
setCursor(cur, pit, pos, true, bound);
}

View File

@ -72,9 +72,9 @@ using std::string;
LyXText::LyXText(BufferView * bv)
: width_(0), maxwidth_(bv ? bv->workWidth() : 100), height_(0),
: maxwidth_(bv ? bv->workWidth() : 100),
background_color_(LColor::background),
bv_owner(bv), xo_(0), yo_(0)
bv_owner(bv)
{}
@ -83,15 +83,15 @@ void LyXText::init(BufferView * bv)
BOOST_ASSERT(bv);
bv_owner = bv;
maxwidth_ = bv->workWidth();
width_ = maxwidth_;
height_ = 0;
dim_.wid = maxwidth_;
dim_.asc = 10;
dim_.des = 10;
pit_type const end = paragraphs().size();
for (pit_type pit = 0; pit != end; ++pit)
pars_[pit].rows.clear();
pars_[pit].rows().clear();
current_font = getFont(pars_[0], 0);
redoParagraphs(0, end);
updateCounters();
}
@ -102,42 +102,37 @@ bool LyXText::isMainText() const
}
// takes absolute x,y coordinates
//takes screen x,y coordinates
InsetBase * LyXText::checkInsetHit(int x, int y) const
{
pit_type pit;
pit_type end;
pit_type pit = getPitNearY(y);
BOOST_ASSERT(pit != -1);
getParsInRange(paragraphs(),
bv()->top_y() - yo_,
bv()->top_y() - yo_ + bv()->workHeight(),
pit, end);
Paragraph const & par = pars_[pit];
// convert to screen-absolute y coordinate
y -= bv()->top_y();
lyxerr << "checkInsetHit: x: " << x << " y: " << y << endl;
lyxerr << " pit: " << pit << " end: " << end << endl;
for (; pit != end; ++pit) {
InsetList::const_iterator iit = pars_[pit].insetlist.begin();
InsetList::const_iterator iend = pars_[pit].insetlist.end();
lyxerr << " pit: " << pit << endl;
InsetList::const_iterator iit = par.insetlist.begin();
InsetList::const_iterator iend = par.insetlist.end();
for (; iit != iend; ++iit) {
InsetBase * inset = iit->inset;
#if 1
lyxerr << "examining inset " << inset << endl;
if (theCoords.insets_.has(inset))
lyxerr
<< " xo: " << inset->xo() << "..." << inset->xo() + inset->width()
<< " yo: " << inset->yo() - inset->ascent() << "..."
<< " xo: " << inset->xo() << "..."
<< inset->xo() + inset->width()
<< " yo: " << inset->yo() - inset->ascent()
<< "..."
<< inset->yo() + inset->descent() << endl;
else
lyxerr << " inset has no cached position";
lyxerr << " inset has no cached position" << endl;
#endif
if (inset->covers(x, y)) {
lyxerr << "Hit inset: " << inset << endl;
return inset;
}
}
}
lyxerr << "No inset hit. " << endl;
return 0;
}
@ -341,7 +336,6 @@ void LyXText::setLayout(LCursor & cur, string const & layout)
pit_type start = cur.selBegin().pit();
pit_type end = cur.selEnd().pit() + 1;
pit_type endpit = setLayout(start, end, layout);
redoParagraphs(start, endpit);
updateCounters();
}
@ -408,14 +402,15 @@ void LyXText::changeDepth(LCursor & cur, DEPTH_CHANGE type)
max_depth = pars_[beg - 1].getMaxDepthAfter();
for (pit_type pit = beg; pit != end; ++pit) {
if (::changeDepthAllowed(type, pars_[pit], max_depth)) {
int const depth = pars_[pit].params().depth();
Paragraph & par = pars_[pit];
if (::changeDepthAllowed(type, par, max_depth)) {
int const depth = par.params().depth();
if (type == INC_DEPTH)
pars_[pit].params().depth(depth + 1);
par.params().depth(depth + 1);
else
pars_[pit].params().depth(depth - 1);
par.params().depth(depth - 1);
}
max_depth = pars_[pit].getMaxDepthAfter();
max_depth = par.getMaxDepthAfter();
}
// this handles the counter labels, and also fixes up
// depth values for follow-on (child) paragraphs
@ -454,9 +449,6 @@ void LyXText::setFont(LCursor & cur, LyXFont const & font, bool toggleall)
// Ok, we have a selection.
recordUndoSelection(cur);
pit_type const beg = cur.selBegin().pit();
pit_type const end = cur.selEnd().pit();
DocIterator dit = cur.selectionBegin();
DocIterator ditend = cur.selectionEnd();
@ -471,8 +463,6 @@ void LyXText::setFont(LCursor & cur, LyXFont const & font, bool toggleall)
setCharFont(dit.pit(), dit.pos(), f);
}
}
redoParagraphs(beg, end + 1);
}
@ -491,6 +481,7 @@ void LyXText::cursorEnd(LCursor & cur)
BOOST_ASSERT(this == cur.text());
// if not on the last row of the par, put the cursor before
// the final space
// FIXME: does this final space exist?
pos_type const end = cur.textRow().endpos();
setCursor(cur, cur.pit(), end == cur.lastpos() ? end : end - 1);
}
@ -602,8 +593,6 @@ void LyXText::setParagraph(LCursor & cur,
par.setLabelWidthString(labelwidthstring);
params.noindent(noindent);
}
redoParagraphs(cur.selBegin().pit(), undopit);
}
@ -897,12 +886,9 @@ void LyXText::updateCounters()
if (oldLabel != newLabel) {
//lyxerr[Debug::DEBUG] << "changing labels: old: " << oldLabel << " new: "
// << newLabel << endl;
redoParagraphInternal(pit);
update_pos = true;
}
}
if (update_pos)
updateParPositions();
}
@ -912,7 +898,6 @@ void LyXText::insertInset(LCursor & cur, InsetBase * inset)
BOOST_ASSERT(this == cur.text());
BOOST_ASSERT(inset);
cur.paragraph().insertInset(cur.pos(), inset);
redoParagraph(cur);
}
@ -920,7 +905,6 @@ void LyXText::insertInset(LCursor & cur, InsetBase * inset)
void LyXText::insertStringAsLines(LCursor & cur, string const & str)
{
pit_type pit = cur.pit();
pit_type endpit = cur.pit() + 1;
pos_type pos = cur.pos();
recordUndo(cur);
@ -928,7 +912,6 @@ void LyXText::insertStringAsLines(LCursor & cur, string const & str)
cur.clearSelection();
cur.buffer().insertStringAsLines(pars_, pit, pos, current_font, str);
redoParagraphs(cur.pit(), endpit);
cur.resetAnchor();
setCursor(cur, cur.pit(), pos);
cur.setSelection();
@ -975,19 +958,12 @@ void LyXText::setCursor(CursorSlice & cur, pit_type par,
pos_type pos, bool boundary)
{
BOOST_ASSERT(par != int(paragraphs().size()));
cur.pit() = par;
cur.pos() = pos;
cur.boundary() = boundary;
// no rows, no fun...
if (paragraphs().begin()->rows.empty())
return;
// now some strict checking
Paragraph & para = getPar(par);
Row const & row = *para.getRow(pos);
pos_type const end = row.endpos();
// None of these should happen, but we're scaredy-cats
if (pos < 0) {
@ -998,24 +974,6 @@ void LyXText::setCursor(CursorSlice & cur, pit_type par,
if (pos > para.size()) {
lyxerr << "dont like 1, pos: " << pos
<< " size: " << para.size()
<< " row.pos():" << row.pos()
<< " par: " << par << endl;
BOOST_ASSERT(false);
}
if (pos > end) {
lyxerr << "dont like 2, pos: " << pos
<< " size: " << para.size()
<< " row.pos():" << row.pos()
<< " par: " << par << endl;
// This shouldn't happen.
BOOST_ASSERT(false);
}
if (pos < row.pos()) {
lyxerr << "dont like 3 please report pos:" << pos
<< " size: " << para.size()
<< " row.pos():" << row.pos()
<< " par: " << par << endl;
BOOST_ASSERT(false);
}
@ -1026,7 +984,7 @@ void LyXText::setCursorIntern(LCursor & cur,
pit_type par, pos_type pos, bool setfont, bool boundary)
{
setCursor(cur.top(), par, pos, boundary);
cur.x_target() = cursorX(cur.top());
cur.setTargetX();
if (setfont)
setCurrentFont(cur);
}
@ -1077,7 +1035,8 @@ void LyXText::setCurrentFont(LCursor & cur)
pos_type LyXText::getColumnNearX(pit_type const pit,
Row const & row, int & x, bool & boundary) const
{
x -= xo_;
int const xo = theCoords.get(this, pit).x_;
x -= xo;
RowMetrics const r = computeRowMetrics(pit, row);
Paragraph const & par = pars_[pit];
@ -1099,7 +1058,7 @@ pos_type LyXText::getColumnNearX(pit_type const pit,
// check for empty row
if (vc == end) {
x = int(tmpx) + xo_;
x = int(tmpx) + xo;
return 0;
}
@ -1169,55 +1128,59 @@ pos_type LyXText::getColumnNearX(pit_type const pit,
c = end - 1;
}
x = int(tmpx) + xo_;
x = int(tmpx) + xo;
return c - row.pos();
}
// y is relative to this LyXText's top
// this is only used in the two functions below
Row const & LyXText::getRowNearY(int y, pit_type & pit) const
// y is screen coordinate
pit_type LyXText::getPitNearY(int y) const
{
BOOST_ASSERT(!paragraphs().empty());
BOOST_ASSERT(!paragraphs().begin()->rows.empty());
pit_type const pend = paragraphs().size() - 1;
pit = 0;
while (int(pars_[pit].y + pars_[pit].height) < y && pit != pend)
++pit;
BOOST_ASSERT(theCoords.pars_.find(this) != theCoords.pars_.end());
CoordCache::InnerParPosCache const & cc = theCoords.pars_[this];
lyxerr << "LyXText::getPitNearY: y: " << y << " cache size: "
<< cc.size() << endl;
RowList::iterator rit = pars_[pit].rows.end();
RowList::iterator const rbegin = pars_[pit].rows.begin();
do {
--rit;
} while (rit != rbegin && int(pars_[pit].y + rit->y_offset()) > y);
// look for highest numbered paragraph with y coordinate less than given y
pit_type pit = 0;
int yy = -1;
CoordCache::InnerParPosCache::const_iterator it = cc.begin();
CoordCache::InnerParPosCache::const_iterator et = cc.end();
for (; it != et; ++it) {
lyxerr << " examining: pit: " << it->first << " y: "
<< it->second.y_ << endl;
if (it->first >= pit && int(it->second.y_) - int(pars_[it->first].ascent()) <= y) {
pit = it->first;
yy = it->second.y_;
}
}
lyxerr << " found best y: " << yy << " for pit: " << pit << endl;
return pit;
}
Row const & LyXText::getRowNearY(int y, pit_type pit) const
{
Paragraph const & par = pars_[pit];
int yy = theCoords.get(this, pit).y_ - par.ascent();
BOOST_ASSERT(!par.rows().empty());
RowList::const_iterator rit = par.rows().begin();
RowList::const_iterator const rlast = boost::prior(par.rows().end());
for (; rit != rlast; yy += rit->height(), ++rit)
if (yy + rit->height() > y)
break;
return *rit;
}
// x,y are absolute coordinates
// sets cursor only within this LyXText
void LyXText::setCursorFromCoordinates(LCursor & cur, int x, int y)
{
x -= xo_;
y -= yo_;
pit_type pit;
Row const & row = getRowNearY(y, pit);
lyxerr[Debug::DEBUG] << "setCursorFromCoordinates:: hit row at: "
<< row.pos() << endl;
bool bound = false;
int xx = x + xo_; // getRowNearX get absolute x coords
pos_type const pos = row.pos() + getColumnNearX(pit, row, xx, bound);
setCursor(cur, pit, pos, true, bound);
}
// x,y are absolute screen coordinates
// sets cursor recursively descending into nested editable insets
InsetBase * LyXText::editXY(LCursor & cur, int x, int y) const
{
pit_type pit;
Row const & row = getRowNearY(y - yo_, pit);
pit_type pit = getPitNearY(y);
BOOST_ASSERT(pit != -1);
Row const & row = getRowNearY(y, pit);
bool bound = false;
int xx = x; // is modified by getColumnNearX
@ -1225,12 +1188,17 @@ InsetBase * LyXText::editXY(LCursor & cur, int x, int y) const
cur.pit() = pit;
cur.pos() = pos;
cur.boundary() = bound;
cur.x_target() = x;
// try to descend into nested insets
InsetBase * inset = checkInsetHit(x, y);
lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl;
if (!inset)
if (!inset) {
//either we deconst editXY or better we move current_font
//and real_current_font to LCursor
const_cast<LyXText *>(this)->setCurrentFont(cur);
return 0;
}
// This should be just before or just behind the
// cursor position set above.
@ -1240,7 +1208,10 @@ InsetBase * LyXText::editXY(LCursor & cur, int x, int y) const
// this inset.
if (inset == pars_[pit].getInset(pos - 1))
--cur.pos();
return inset->editXY(cur, x, y);
inset = inset->editXY(cur, x, y);
if (cur.top().text() == this)
const_cast<LyXText *>(this)->setCurrentFont(cur);
return inset;
}
@ -1302,31 +1273,50 @@ void LyXText::cursorRight(LCursor & cur)
void LyXText::cursorUp(LCursor & cur)
{
Row const & row = cur.textRow();
int x = cur.x_target();
int y = cursorY(cur.top()) - row.baseline() - 1;
setCursorFromCoordinates(cur, x, y);
Paragraph const & par = cur.paragraph();
int const row = par.pos2row(cur.pos());
int const x = cur.targetX();
if (!cur.selection()) {
InsetBase * inset_hit = checkInsetHit(cur.x_target(), y);
if (inset_hit && isHighlyEditableInset(inset_hit))
inset_hit->editXY(cur, cur.x_target(), y);
int const y = bv_funcs::getPos(cur).y_;
editXY(cur, x, y - par.rows()[row].ascent() - 1);
return;
}
if (row > 0) {
setCursor(cur, cur.pit(), x2pos(cur.pit(), row - 1, x));
} else if (cur.pit() > 0) {
--cur.pit();
setCursor(cur, cur.pit(), x2pos(cur.pit(), cur.paragraph().rows().size() - 1, x));
}
cur.x_target() = x;
}
void LyXText::cursorDown(LCursor & cur)
{
Row const & row = cur.textRow();
int x = cur.x_target();
int y = cursorY(cur.top()) - row.baseline() + row.height() + 1;
setCursorFromCoordinates(cur, x, y);
Paragraph const & par = cur.paragraph();
int const row = par.pos2row(cur.pos());
int const x = cur.targetX();
if (!cur.selection()) {
InsetBase * inset_hit = checkInsetHit(cur.x_target(), y);
if (inset_hit && isHighlyEditableInset(inset_hit))
inset_hit->editXY(cur, cur.x_target(), y);
int const y = bv_funcs::getPos(cur).y_;
editXY(cur, x, y + par.rows()[row].descent() + 1);
return;
}
if (row + 1 < int(par.rows().size())) {
setCursor(cur, cur.pit(), x2pos(cur.pit(), row + 1, x));
} else if (cur.pit() + 1 < int(paragraphs().size())) {
++cur.pit();
setCursor(cur, cur.pit(), x2pos(cur.pit(), 0, x));
}
cur.x_target() = x;
}

View File

@ -143,15 +143,17 @@ namespace {
BOOST_ASSERT(old_pos == cur.pos());
cur.nextInset()->edit(cur, true);
cur.dispatch(FuncRequest(LFUN_MATH_MUTATE, "simple"));
// don't do that also for LFUN_MATH_MODE unless you want end up with
// always changing to mathrm when opening an inlined inset
// -- I really hate "LyXfunc overloading"...
// don't do that also for LFUN_MATH_MODE
// unless you want end up with always changing
// to mathrm when opening an inlined inset --
// I really hate "LyXfunc overloading"...
if (display)
cur.dispatch(FuncRequest(LFUN_MATH_DISPLAY));
cur.dispatch(FuncRequest(LFUN_INSERT_MATH, cmd.argument));
} else {
// create a macro if we see "\\newcommand" somewhere, and an ordinary
// formula otherwise
// create a macro if we see "\\newcommand"
// somewhere, and an ordinary formula
// otherwise
cutSelection(cur, true, true);
if (sel.find("\\newcommand") == string::npos
&& sel.find("\\def") == string::npos)
@ -261,8 +263,9 @@ void LyXText::cursorPrevious(LCursor & cur)
lyx::pit_type cpar = cur.pit();
int x = cur.x_target();
int y = cur.bv().top_y();
setCursorFromCoordinates(cur, x, y);
setCursorFromCoordinates(cur, x, 0);
cursorUp(cur);
if (cpar == cur.pit() && cpos == cur.pos()) {
// we have a row which is taller than the workarea. The
@ -281,8 +284,8 @@ void LyXText::cursorNext(LCursor & cur)
lyx::pit_type cpar = cur.pit();
int x = cur.x_target();
int y = cur.bv().top_y() + cur.bv().workHeight();
setCursorFromCoordinates(cur, x, y);
setCursorFromCoordinates(cur, x, cur.bv().workHeight() - 1);
cursorDown(cur);
if (cpar == cur.pit() && cpos == cur.pos()) {
// we have a row which is taller than the workarea. The
@ -327,6 +330,15 @@ void doInsertInset(LCursor & cur, LyXText * text,
cur.bv().owner()->dispatch(FuncRequest(LFUN_PASTE));
}
void update(LCursor & cur)
{
//we don't call update(true, false) directly to save a metrics call
if (cur.bv().fitCursor())
cur.bv().update(false, true);
}
} // anon namespace
@ -366,7 +378,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
if (pars_[tmp].params().startOfAppendix()) {
recUndo(tmp);
pars_[tmp].params().startOfAppendix(false);
redoParagraph(tmp);
break;
}
}
@ -376,7 +387,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
// we can set the refreshing parameters now
updateCounters();
redoParagraph(cur);
break;
}
@ -431,6 +441,17 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
}
break;
case LFUN_BEGINNINGBUFSEL:
if (cur.size() == 1) {
if (!cur.selection())
cur.resetAnchor();
cursorTop(cur);
finishChange(cur, true);
} else {
cur.undispatched();
}
break;
case LFUN_ENDBUF:
if (cur.size() == 1) {
if (!cur.mark())
@ -442,6 +463,17 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
}
break;
case LFUN_ENDBUFSEL:
if (cur.size() == 1) {
if (!cur.selection())
cur.resetAnchor();
cursorBottom(cur);
finishChange(cur, true);
} else {
cur.undispatched();
}
break;
case LFUN_RIGHT:
moving = true;
case LFUN_RIGHTSEL:
@ -475,6 +507,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_UP:
moving = true;
case LFUN_UPSEL:
update(cur);
//lyxerr << "handle LFUN_UP[SEL]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_UPSEL);
cursorUp(cur);
@ -487,6 +520,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_DOWN:
moving = true;
case LFUN_DOWNSEL:
update(cur);
//lyxerr << "handle LFUN_DOWN[SEL]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_DOWNSEL);
cursorDown(cur);
@ -511,6 +545,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_PRIORSEL:
update(cur);
if (!cur.selection())
cur.resetAnchor();
cursorPrevious(cur);
@ -518,6 +553,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_NEXTSEL:
update(cur);
if (!cur.selection())
cur.resetAnchor();
cursorNext(cur);
@ -525,6 +561,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_HOMESEL:
update(cur);
if (!cur.selection())
cur.resetAnchor();
cursorHome(cur);
@ -532,6 +569,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_ENDSEL:
update(cur);
if (!cur.selection())
cur.resetAnchor();
cursorEnd(cur);
@ -581,6 +619,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_PRIOR:
update(cur);
moving = true;
if (!cur.mark())
cur.clearSelection();
@ -594,6 +633,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_NEXT:
update(cur);
moving = true;
if (!cur.mark())
cur.clearSelection();
@ -748,10 +788,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
lyxerr << _("Unknown spacing argument: ")
<< cmd.argument << endl;
}
if (cur_spacing != new_spacing || cur_value != new_value) {
if (cur_spacing != new_spacing || cur_value != new_value)
par.params().spacing(Spacing(new_spacing, new_value));
redoParagraph(cur);
}
break;
}
@ -843,7 +881,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_TRANSPOSE_CHARS:
recordUndo(cur);
redoParagraph(cur);
break;
case LFUN_PASTE:
@ -1091,7 +1128,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
setCursorFromCoordinates(cur, cmd.x, cmd.y);
cur.resetAnchor();
finishUndo();
cur.x_target() = cursorX(cur.top());
cur.setTargetX();
// Has the cursor just left the inset?
if (bv->cursor().inMathed() && !cur.inMathed())
@ -1101,8 +1138,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
bv->cursor() = cur;
// Don't allow selection after a big jump.
if (bv->fitCursor())
selection_possible = false;
//if (bv->fitCursor())
// selection_possible = false;
// Insert primary selection with middle mouse
// if there is a local selection in the current buffer,
@ -1134,23 +1171,36 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
// ignore motions deeper nested than the real anchor
LCursor & bvcur = cur.bv().cursor();
if (bvcur.anchor_.hasPart(cur)) {
CursorSlice old = cur.top();
setCursorFromCoordinates(cur, cmd.x, cmd.y);
CursorSlice old = bvcur.top();
// This is to allow jumping over large insets
// FIXME: shouldn't be top-text-specific
if (isMainText() && cur.top() == old) {
if (cmd.y - bv->top_y() >= bv->workHeight())
int const wh = bv->workHeight();
int const y = std::max(0, std::min(wh - 1, cmd.y));
setCursorFromCoordinates(cur, cmd.x, y);
cur.x_target() = cmd.x;
if (cmd.y >= wh)
cursorDown(cur);
else if (cmd.y - bv->top_y() < 0)
else if (cmd.y < 0)
cursorUp(cur);
// This is to allow jumping over large insets
if (cur.top() == old) {
if (cmd.y >= wh)
cursorDown(cur);
else if (cmd.y < 0)
cursorUp(cur);
}
if (cur.top() == old)
cur.noUpdate();
else {
// don't set anchor_
bv->cursor().setCursor(cur);
bv->cursor().selection() = true;
bvcur.setCursor(cur);
bvcur.selection() = true;
lyxerr << "MOTION: " << bv->cursor() << endl;
}
} else
cur.undispatched();
break;
}
@ -1910,12 +1960,11 @@ bool LyXText::getStatus(LCursor & cur, FuncRequest const & cmd,
case LFUN_PARAGRAPH_APPLY:
case LFUN_ESCAPE:
case LFUN_KEYMAP_TOGGLE:
// these are handled in our dispatch()
enable = true;
break;
case LFUN_ENDBUF:
case LFUN_BEGINNINGBUF:
case LFUN_BEGINNINGBUFSEL:
case LFUN_ENDBUFSEL:
// these are handled in our dispatch()
enable = true;
break;

View File

@ -55,7 +55,6 @@ void recordUndo(Undo::undo_kind kind,
{
if (first_pit > last_pit)
std::swap(first_pit, last_pit);
// create the position information of the Undo entry
Undo undo;
undo.kind = kind;
@ -105,6 +104,7 @@ void recordUndo(Undo::undo_kind kind,
undo_finished = false;
}
void recordUndo(Undo::undo_kind kind,
LCursor & cur, pit_type first_pit, pit_type last_pit,
limited_stack<Undo> & stack)
@ -281,8 +281,8 @@ void recordUndo(LCursor & cur, Undo::undo_kind kind,
}
void recordUndoFullDocument(LCursor &)
void recordUndoFullDocument(LCursor & cur)
{
//recordUndo(Undo::ATOMIC,
// cur, 0, cur.bv().text()->paragraphs().size() - 1);
recordUndo(Undo::ATOMIC, cur, 0,
cur.bv().text()->paragraphs().size() - 1);
}