X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsettabular.C;h=202ac6fa44bb8495781e2a56dd4919f2a87029ff;hb=e28331ed63062dea10d0a21b9ec12034b4b17b9a;hp=51c4a7471da0b6192a6a810384fc54777f93a380;hpb=da65e2b7fbe29c5bca2812a56d5bbdb7efb702e5;p=lyx.git diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 51c4a7471d..202ac6fa44 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -37,21 +37,26 @@ #include "support/convert.h" #include "frontends/Alert.h" -#include "frontends/font_metrics.h" -#include "frontends/LyXView.h" +#include "frontends/Clipboard.h" #include "frontends/Painter.h" -#include "frontends/nullpainter.h" +#include "frontends/Selection.h" #include #include #include -using lyx::cap::dirtyTabularStack; -using lyx::cap::tabularStackDirty; -using lyx::graphics::PreviewLoader; +namespace lyx { -using lyx::support::ltrim; +using cap::dirtyTabularStack; +using cap::tabularStackDirty; + +using graphics::PreviewLoader; + +using support::ltrim; + +using frontend::Painter; +using frontend::Clipboard; using boost::shared_ptr; @@ -65,11 +70,14 @@ using std::ostringstream; using std::swap; using std::vector; +namespace Alert = frontend::Alert; + namespace { int const ADD_TO_HEIGHT = 2; int const ADD_TO_TABULAR_WIDTH = 2; +int const default_line_space = 10; /// boost::scoped_ptr paste_tabular; @@ -87,6 +95,8 @@ TabularFeature tabularFeature[] = { LyXTabular::APPEND_COLUMN, "append-column" }, { LyXTabular::DELETE_ROW, "delete-row" }, { LyXTabular::DELETE_COLUMN, "delete-column" }, + { LyXTabular::COPY_ROW, "copy-row" }, + { LyXTabular::COPY_COLUMN, "copy-column" }, { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" }, { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" }, { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" }, @@ -131,6 +141,11 @@ TabularFeature tabularFeature[] = { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" }, { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" }, { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" }, + { LyXTabular::SET_BOOKTABS, "set-booktabs" }, + { LyXTabular::UNSET_BOOKTABS, "unset-booktabs" }, + { LyXTabular::SET_TOP_SPACE, "set-top-space" }, + { LyXTabular::SET_BOTTOM_SPACE, "set-bottom-space" }, + { LyXTabular::SET_INTERLINE_SPACE, "set-interline-space" }, { LyXTabular::LAST_ACTION, "" } }; @@ -159,12 +174,6 @@ string const featureAsString(LyXTabular::Feature feature) } -bool InsetTabular::hasPasteBuffer() const -{ - return (paste_tabular.get() != 0); -} - - InsetTabular::InsetTabular(Buffer const & buf, row_type rows, col_type columns) : tabular(buf.params(), max(rows, row_type(1)), @@ -231,7 +240,7 @@ void InsetTabular::read(Buffer const & buf, LyXLex & lex) } -void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const +bool InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const { //lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " << // mi.base.textwidth << "\n"; @@ -261,19 +270,33 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const tabular.getCellInset(cell)->metrics(m, dim); if (!p_width.zero()) dim.wid = m.base.textwidth; + tabular.setWidthOfCell(cell, dim.wid); + if (p_width.zero()) { + m.base.textwidth = dim.wid + 2 * ADD_TO_TABULAR_WIDTH; + // FIXME there must be a way to get rid of + // the second metrics call + tabular.getCellInset(cell)->metrics(m, dim); + } maxAsc = max(maxAsc, dim.asc); maxDesc = max(maxDesc, dim.des); - tabular.setWidthOfCell(cell, dim.wid); ++cell; } - tabular.setAscentOfRow(i, maxAsc + ADD_TO_HEIGHT); - tabular.setDescentOfRow(i, maxDesc + ADD_TO_HEIGHT); + int const top_space = tabular.row_info[i].top_space_default ? + default_line_space : + tabular.row_info[i].top_space.inPixels(mi.base.textwidth); + tabular.setAscentOfRow(i, maxAsc + ADD_TO_HEIGHT + top_space); + int const bottom_space = tabular.row_info[i].bottom_space_default ? + default_line_space : + tabular.row_info[i].bottom_space.inPixels(mi.base.textwidth); + tabular.setDescentOfRow(i, maxDesc + ADD_TO_HEIGHT + bottom_space); } dim.asc = tabular.getAscentOfRow(0); dim.des = tabular.getHeightOfTabular() - dim.asc; dim.wid = tabular.getWidthOfTabular() + 2 * ADD_TO_TABULAR_WIDTH; + bool const changed = dim_ != dim; dim_ = dim; + return changed; } @@ -284,10 +307,7 @@ 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()); + resetPos(bv->cursor()); x += scx_; x += ADD_TO_TABULAR_WIDTH; @@ -310,8 +330,10 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const || nx > bv->workWidth() || y + d < 0 || y - a > bv->workHeight()) { - cell(idx)->draw(nullpi, cx, y); - drawCellLines(nop, nx, y, i, idx, pi.erased_); + pi.pain.setDrawingEnabled(false); + cell(idx)->draw(pi, cx, y); + drawCellLines(pi.pain, nx, y, i, idx, pi.erased_); + pi.pain.setDrawingEnabled(true); } else { cell(idx)->draw(pi, cx, y); drawCellLines(pi.pain, nx, y, i, idx, pi.erased_); @@ -332,6 +354,15 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const setPosCache(pi, x, y); LCursor & cur = pi.base.bv->cursor(); + + x += scx_ + ADD_TO_TABULAR_WIDTH; + + // Paint background of current tabular + int const w = tabular.getWidthOfTabular(); + int const h = tabular.getHeightOfTabular(); + int yy = y - tabular.getAscentOfRow(0); + pi.pain.fillRectangle(x, yy, w, h, backgroundColor()); + if (!cur.selection()) return; if (!ptr_cmp(&cur.inset(), this)) @@ -339,7 +370,6 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const //resetPos(cur); - x += scx_ + ADD_TO_TABULAR_WIDTH; if (tablemode(cur)) { row_type rs, re; @@ -414,7 +444,7 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y, } -string const InsetTabular::editMessage() const +docstring const InsetTabular::editMessage() const { return _("Opened table"); } @@ -441,7 +471,7 @@ void InsetTabular::edit(LCursor & cur, bool left) cur.pit() = 0; cur.pos() = cur.lastpos(); // FIXME crude guess } - // this accesses the position cache before it is initialized + // FIXME: this accesses the position cache before it is initialized //resetPos(cur); //cur.bv().fitCursor(); } @@ -459,23 +489,31 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) case LFUN_MOUSE_PRESS: //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl; - if (cmd.button() == mouse_button::button1) { + if (cmd.button() == mouse_button::button1 + || (cmd.button() == mouse_button::button3 + && (&bvcur.selBegin().inset() != this || !tablemode(bvcur)))) { + if (!bvcur.selection() && !cur.bv().mouseSetCursor(cur)) + cur.noUpdate(); cur.selection() = false; setCursorFromCoordinates(cur, cmd.x, cmd.y); - cur.resetAnchor(); - bvcur = cur; + cur.bv().mouseSetCursor(cur); break; } if (cmd.button() == mouse_button::button2) { - cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"); + if (bvcur.selection()) { + // See comment in LyXText::dispatch why we + // do this + // FIXME This does not use paste_tabular, + // another reason why paste_tabular should go. + cap::copySelectionToStack(bvcur); + cmd = FuncRequest(LFUN_PASTE, "0"); + } else { + cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, + "paragraph"); + } doDispatch(cur, cmd); - break; } - - // we'll pop up the table dialog on release - if (cmd.button() == mouse_button::button3) - cur.undispatched(); break; case LFUN_MOUSE_MOTION: @@ -483,6 +521,10 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) if (cmd.button() == mouse_button::button1) { // only accept motions to places not deeper nested than the real anchor if (bvcur.anchor_.hasPart(cur)) { + // only update if selection changes + if (bvcur.idx() == cur.idx() && + !(bvcur.anchor_.idx() == cur.idx() && bvcur.pos() != cur.pos())) + cur.noUpdate(); setCursorFromCoordinates(cur, cmd.x, cmd.y); bvcur.setCursor(cur); bvcur.selection() = true; @@ -493,7 +535,10 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) case LFUN_MOUSE_RELEASE: //lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl; - if (cmd.button() == mouse_button::button3) + if (cmd.button() == mouse_button::button1) { + if (bvcur.selection()) + theSelection().haveSelection(true); + } else if (cmd.button() == mouse_button::button3) InsetTabularMailer(*this).showDialog(&cur.bv()); break; @@ -507,11 +552,13 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) cur.selection() = false; break; - case LFUN_CHAR_FORWARDSEL: + case LFUN_CHAR_FORWARD_SELECT: case LFUN_CHAR_FORWARD: cell(cur.idx())->dispatch(cur, cmd); if (!cur.result().dispatched()) { isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur); + if (cmd.action == LFUN_CHAR_FORWARD_SELECT) + theSelection().haveSelection(cur.selection()); if (sl == cur.top()) cmd = FuncRequest(LFUN_FINISHED_RIGHT); else @@ -519,11 +566,13 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) } break; - case LFUN_BACKWARD_SELECT: + case LFUN_CHAR_BACKWARD_SELECT: case LFUN_CHAR_BACKWARD: cell(cur.idx())->dispatch(cur, cmd); if (!cur.result().dispatched()) { isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur); + if (cmd.action == LFUN_CHAR_BACKWARD_SELECT) + theSelection().haveSelection(cur.selection()); if (sl == cur.top()) cmd = FuncRequest(LFUN_FINISHED_LEFT); else @@ -542,8 +591,11 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) if (tabular.row_of_cell(cur.idx()) != tabular.rows() - 1) { cur.idx() = tabular.getCellBelow(cur.idx()); cur.pit() = 0; - cur.pos() = cell(cur.idx())->getText(0)->x2pos( - cur.pit(), 0, cur.targetX()); + TextMetrics const & tm = + cur.bv().textMetrics(cell(cur.idx())->getText(0)); + cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX()); + if (cmd.action == LFUN_DOWN_SELECT) + theSelection().haveSelection(cur.selection()); } if (sl == cur.top()) { // we trick it to go to the RIGHT after leaving the @@ -565,10 +617,12 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) cur.idx() = tabular.getCellAbove(cur.idx()); cur.pit() = cur.lastpit(); LyXText const * text = cell(cur.idx())->getText(0); - cur.pos() = text->x2pos( - cur.pit(), - text->paragraphs().back().rows().size()-1, - cur.targetX()); + TextMetrics const & tm = cur.bv().textMetrics(text); + ParagraphMetrics const & pm = + tm.parMetrics(cur.lastpit()); + cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX()); + if (cmd.action == LFUN_UP_SELECT) + theSelection().haveSelection(cur.selection()); } if (sl == cur.top()) { cmd = FuncRequest(LFUN_FINISHED_UP); @@ -580,7 +634,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) // //if (hasSelection()) // // cur.selection() = false; // col_type const col = tabular.column_of_cell(cur.idx()); -// int const t = cur.bv().top_y() + cur.bv().painter().paperHeight(); +// int const t = cur.bv().top_y() + cur.bv().height(); // if (t < yo() + tabular.getHeightOfTabular()) { // cur.bv().scrollDocView(t); // cur.idx() = tabular.getCellBelow(first_visible_cell) + col; @@ -596,7 +650,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) // //if (hasSelection()) // // cur.selection() = false; // col_type const col = tabular.column_of_cell(cur.idx()); -// int const t = cur.bv().top_y() + cur.bv().painter().paperHeight(); +// int const t = cur.bv().top_y() + cur.bv().height(); // if (yo() < 0) { // cur.bv().scrollDocView(t); // if (yo() > 0) @@ -620,15 +674,17 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_TABULAR_FEATURE: - if (!tabularFeatures(cur, cmd.argument)) + if (!tabularFeatures(cur, to_utf8(cmd.argument()))) cur.undispatched(); break; // insert file functions - case LFUN_FILE_INSERT_ASCII_PARA: - case LFUN_FILE_INSERT_ASCII: { - string const tmpstr = getContentsOfAsciiFile(&cur.bv(), cmd.argument, false); - if (!tmpstr.empty() && !insertAsciiString(cur.bv(), tmpstr, false)) + case LFUN_FILE_INSERT_PLAINTEXT_PARA: + case LFUN_FILE_INSERT_PLAINTEXT: { + // FIXME UNICODE + string const tmpstr = getContentsOfPlaintextFile(&cur.bv(), to_utf8(cmd.argument()), false); + // FIXME: We don't know the encoding of the file + if (!tmpstr.empty() && !insertPlaintextString(cur.bv(), from_utf8(tmpstr), false)) cur.undispatched(); break; } @@ -644,8 +700,8 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) cell(cur.idx())->dispatch(cur, cmd); break; - case LFUN_DELETE_FORWARD_BACKWARD: - case LFUN_DELETE_FORWARD: + case LFUN_CHAR_DELETE_BACKWARD: + case LFUN_CHAR_DELETE_FORWARD: if (tablemode(cur)) { recordUndoInset(cur, Undo::DELETE); cutSelection(cur); @@ -664,32 +720,36 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) cell(cur.idx())->dispatch(cur, cmd); break; + case LFUN_CLIPBOARD_PASTE: case LFUN_PRIMARY_SELECTION_PASTE: { - string const clip = cur.bv().getClipboard(); + docstring const clip = (cmd.action == LFUN_CLIPBOARD_PASTE) ? + theClipboard().getAsText() : + theSelection().get(); if (clip.empty()) break; - if (insertAsciiString(cur.bv(), clip, false)) - break; - else { - // so that the clipboard is used and it goes on - // to default - // and executes LFUN_PRIMARY_SELECTION_PASTE in insettext! - paste_tabular.reset(); - dirtyTabularStack(false); + // pass to InsertPlaintextString, but + // only if we have multi-cell content + if (clip.find_first_of(from_ascii("\t\n")) != docstring::npos) { + if (insertPlaintextString(cur.bv(), clip, false)) { + // content has been replaced, + // so cursor might be invalid + cur.pos() = cur.lastpos(); + bvcur.setCursor(cur); + break; + } } - // fall through + // Let the cell handle normal text + cell(cur.idx())->dispatch(cur, cmd); + break; } case LFUN_PASTE: - if (hasPasteBuffer() && tabularStackDirty()) { + if (tabularStackDirty() && theClipboard().isInternal()) { recordUndoInset(cur, Undo::INSERT); pasteSelection(cur); break; } cell(cur.idx())->dispatch(cur, cmd); - // Reset pasted paragraphs: - if (tabular.getPWidth(cur.idx()).zero()) - cell(cur.idx())->forceParagraphsToDefault(cur); break; case LFUN_FONT_EMPH: @@ -713,27 +773,22 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) row_type rs, re; col_type cs, ce; getSelection(cur, rs, re, cs, ce); + LCursor tmpcur = cur; for (row_type i = rs; i <= re; ++i) { for (col_type j = cs; j <= ce; ++j) { // cursor follows cell: - cur.idx() = tabular.getCellNumber(i, j); + tmpcur.idx() = tabular.getCellNumber(i, j); // select this cell only: - cur.pos() = 0; - cur.resetAnchor(); - cur.pos() = cur.top().lastpos(); - cur.setCursor(cur); - cur.setSelection(); - cell(cur.idx())->dispatch(cur, cmd); + tmpcur.pit() = 0; + tmpcur.pos() = 0; + tmpcur.resetAnchor(); + tmpcur.pit() = tmpcur.lastpit(); + tmpcur.pos() = tmpcur.top().lastpos(); + tmpcur.setCursor(tmpcur); + tmpcur.setSelection(); + cell(tmpcur.idx())->dispatch(tmpcur, cmd); } } - // Restore original selection - cur.idx() = tabular.getCellNumber(rs, cs); - cur.pos() = 0; - cur.resetAnchor(); - cur.idx() = tabular.getCellNumber(re, ce); - cur.pos() = cur.top().lastpos(); - cur.setCursor(cur); - cur.setSelection(); break; } else { cell(cur.idx())->dispatch(cur, cmd); @@ -745,7 +800,8 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd) break; } - resetPos(cur); + // FIXME: this accesses the position cache before it is initialized + //resetPos(cur); InsetTabularMailer(*this).updateDialog(&cur.bv()); } @@ -761,7 +817,7 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, int i = 0; for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) { string const tmp = tabularFeature[i].feature; - if (tmp == cmd.argument.substr(0, tmp.length())) { + if (tmp == to_utf8(cmd.argument()).substr(0, tmp.length())) { action = tabularFeature[i].action; break; } @@ -773,7 +829,7 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, } string const argument - = ltrim(cmd.argument.substr(tabularFeature[i].feature.length())); + = ltrim(to_utf8(cmd.argument()).substr(tabularFeature[i].feature.length())); row_type sel_row_start = 0; row_type sel_row_end = 0; @@ -792,8 +848,13 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, case LyXTabular::APPEND_COLUMN: case LyXTabular::DELETE_ROW: case LyXTabular::DELETE_COLUMN: + case LyXTabular::COPY_ROW: + case LyXTabular::COPY_COLUMN: case LyXTabular::SET_ALL_LINES: case LyXTabular::UNSET_ALL_LINES: + case LyXTabular::SET_TOP_SPACE: + case LyXTabular::SET_BOTTOM_SPACE: + case LyXTabular::SET_INTERLINE_SPACE: status.clear(); return true; @@ -933,6 +994,14 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, status.setOnOff(tabular.getLTNewPage(sel_row_start)); break; + case LyXTabular::SET_BOOKTABS: + status.setOnOff(tabular.useBookTabs()); + break; + + case LyXTabular::UNSET_BOOKTABS: + status.setOnOff(!tabular.useBookTabs()); + break; + default: status.clear(); status.enabled(false); @@ -975,7 +1044,7 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, // disable in non-fixed-width cells case LFUN_BREAK_LINE: case LFUN_BREAK_PARAGRAPH: - case LFUN_BREAK_PARAGRAPHKEEPLAYOUT: + case LFUN_BREAK_PARAGRAPH_KEEP_LAYOUT: case LFUN_BREAK_PARAGRAPH_SKIP: { if (tabular.getPWidth(cur.idx()).zero()) { status.enabled(false); @@ -985,10 +1054,11 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, } case LFUN_PASTE: - if (tabularStackDirty()) { + if (tabularStackDirty() && theClipboard().isInternal()) { status.enabled(true); return true; - } + } else + return cell(cur.idx())->getStatus(cur, cmd, status); case LFUN_INSET_MODIFY: if (translate(cmd.getArg(0)) == TABULAR_CODE) { @@ -1004,14 +1074,14 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd, } -int InsetTabular::latex(Buffer const & buf, ostream & os, +int InsetTabular::latex(Buffer const & buf, odocstream & os, OutputParams const & runparams) const { return tabular.latex(buf, os, runparams); } -int InsetTabular::plaintext(Buffer const & buf, ostream & os, +int InsetTabular::plaintext(Buffer const & buf, odocstream & os, OutputParams const & runparams) const { int const dp = runparams.linelen ? runparams.depth : 0; @@ -1019,14 +1089,7 @@ int InsetTabular::plaintext(Buffer const & buf, ostream & os, } -int InsetTabular::linuxdoc(Buffer const & buf, ostream & os, - OutputParams const & runparams) const -{ - return tabular.linuxdoc(buf,os, runparams); -} - - -int InsetTabular::docbook(Buffer const & buf, ostream & os, +int InsetTabular::docbook(Buffer const & buf, odocstream & os, OutputParams const & runparams) const { int ret = 0; @@ -1074,10 +1137,10 @@ shared_ptr InsetTabular::cell(idx_type idx) } -void InsetTabular::cursorPos - (CursorSlice const & sl, bool boundary, int & x, int & y) const +void InsetTabular::cursorPos(BufferView const & bv, + CursorSlice const & sl, bool boundary, int & x, int & y) const { - cell(sl.idx())->cursorPos(sl, boundary, x, y); + cell(sl.idx())->cursorPos(bv, sl, boundary, x, y); // y offset correction int const row = tabular.row_of_cell(sl.idx()); @@ -1105,19 +1168,18 @@ void InsetTabular::cursorPos } -int InsetTabular::dist(idx_type const cell, int x, int y) const +int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const { int xx = 0; int yy = 0; InsetBase const & inset = *tabular.getCellInset(cell); - Point o = theCoords.getInsets().xy(&inset); + Point o = bv.coordCache().getInsets().xy(&inset); int const xbeg = o.x_ - tabular.getBeginningOfTextInCell(cell); int const xend = xbeg + tabular.getWidthOfColumn(cell); - int const ybeg = o.y_ - inset.ascent(); row_type const row = tabular.row_of_cell(cell); - int const rowheight = tabular.getAscentOfRow(row) - + tabular.getDescentOfRow(row); - int const yend = ybeg + rowheight; + int const ybeg = o.y_ - tabular.getAscentOfRow(row) - + tabular.getAdditionalHeight(row); + int const yend = o.y_ + tabular.getDescentOfRow(row); if (x < xbeg) xx = xbeg - x; @@ -1142,7 +1204,7 @@ InsetBase * InsetTabular::editXY(LCursor & cur, int x, int y) //lyxerr << "InsetTabular::editXY: " << this << endl; cur.selection() = false; cur.push(*this); - cur.idx() = getNearestCell(x, y); + cur.idx() = getNearestCell(cur.bv(), x, y); resetPos(cur); return cell(cur.idx())->text_.editXY(cur, x, y); } @@ -1150,18 +1212,18 @@ InsetBase * InsetTabular::editXY(LCursor & cur, int x, int y) void InsetTabular::setCursorFromCoordinates(LCursor & cur, int x, int y) const { - cur.idx() = getNearestCell(x, y); + cur.idx() = getNearestCell(cur.bv(), x, y); cell(cur.idx())->text_.setCursorFromCoordinates(cur, x, y); } -InsetTabular::idx_type InsetTabular::getNearestCell(int x, int y) const +InsetTabular::idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int y) const { idx_type idx_min = 0; int dist_min = std::numeric_limits::max(); for (idx_type i = 0, n = nargs(); i != n; ++i) { - if (theCoords.getInsets().has(tabular.getCellInset(i).get())) { - int const d = dist(i, x, y); + if (bv.coordCache().getInsets().has(tabular.getCellInset(i).get())) { + int const d = dist(bv, i, x, y); if (d < dist_min) { dist_min = d; idx_min = i; @@ -1197,7 +1259,7 @@ void InsetTabular::resetPos(LCursor & cur) const int const X1 = 0; int const X2 = maxwidth; int const offset = ADD_TO_TABULAR_WIDTH + 2; - int const x1 = xo() + getCellXPos(cur.idx()) + offset; + int const x1 = xo(cur.bv()) + getCellXPos(cur.idx()) + offset; int const x2 = x1 + tabular.getWidthOfColumn(cur.idx()); if (x1 < X1) @@ -1208,9 +1270,7 @@ void InsetTabular::resetPos(LCursor & cur) const scx_ = 0; } - cur.needsUpdate(); - - InsetTabularMailer(*this).updateDialog(&bv); + cur.updateFlags(Update::Force | Update::FitCursor); } @@ -1259,7 +1319,9 @@ void InsetTabular::movePrevCell(LCursor & cur) } cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); - resetPos(cur); + + // FIXME: this accesses the position cache before it is initialized + //resetPos(cur); } @@ -1388,7 +1450,7 @@ void InsetTabular::tabularFeatures(LCursor & cur, case LyXTabular::SET_SPECIAL_COLUMN: case LyXTabular::SET_SPECIAL_MULTI: - tabular.setAlignSpecial(cur.idx(),value,feature); + tabular.setAlignSpecial(cur.idx(), from_utf8(value), feature); break; case LyXTabular::APPEND_ROW: @@ -1424,6 +1486,15 @@ void InsetTabular::tabularFeatures(LCursor & cur, cur.selection() = false; break; + case LyXTabular::COPY_ROW: + tabular.copyRow(bv.buffer()->params(), row); + break; + + case LyXTabular::COPY_COLUMN: + tabular.copyColumn(bv.buffer()->params(), column); + cur.idx() = tabular.getCellNumber(row, column); + break; + case LyXTabular::M_TOGGLE_LINE_TOP: flag = false; case LyXTabular::TOGGLE_LINE_TOP: { @@ -1510,8 +1581,9 @@ void InsetTabular::tabularFeatures(LCursor & cur, #ifdef WITH_WARNINGS #warning Need I say it ? This is horrible. #endif + // FIXME UNICODE Alert::error(_("Error setting multicolumn"), - _("You cannot set multicolumn vertically.")); + _("You cannot set multicolumn vertically.")); return; } if (!cur.selection()) { @@ -1620,12 +1692,72 @@ void InsetTabular::tabularFeatures(LCursor & cur, tabular.setLTNewPage(row, !tabular.getLTNewPage(row)); break; + case LyXTabular::SET_BOOKTABS: + tabular.setBookTabs(true); + break; + + case LyXTabular::UNSET_BOOKTABS: + tabular.setBookTabs(false); + break; + + case LyXTabular::SET_TOP_SPACE: { + LyXLength len; + if (value == "default") + for (row_type i = sel_row_start; i <= sel_row_end; ++i) + tabular.row_info[i].top_space_default = true; + else if (isValidLength(value, &len)) + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].top_space_default = false; + tabular.row_info[i].top_space = len; + } + else + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].top_space_default = false; + tabular.row_info[i].top_space = len; + } + break; + } + + case LyXTabular::SET_BOTTOM_SPACE: { + LyXLength len; + if (value == "default") + for (row_type i = sel_row_start; i <= sel_row_end; ++i) + tabular.row_info[i].bottom_space_default = true; + else if (isValidLength(value, &len)) + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].bottom_space_default = false; + tabular.row_info[i].bottom_space = len; + } + else + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].bottom_space_default = false; + tabular.row_info[i].bottom_space = len; + } + break; + } + + case LyXTabular::SET_INTERLINE_SPACE: { + LyXLength len; + if (value == "default") + for (row_type i = sel_row_start; i <= sel_row_end; ++i) + tabular.row_info[i].interline_space_default = true; + else if (isValidLength(value, &len)) + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].interline_space_default = false; + tabular.row_info[i].interline_space = len; + } + else + for (row_type i = sel_row_start; i <= sel_row_end; ++i) { + tabular.row_info[i].interline_space_default = false; + tabular.row_info[i].interline_space = len; + } + break; + } + // dummy stuff just to avoid warnings case LyXTabular::LAST_ACTION: break; } - - InsetTabularMailer(*this).updateDialog(&bv); } @@ -1675,14 +1807,17 @@ bool InsetTabular::copySelection(LCursor & cur) paste_tabular->setRightLine(paste_tabular->getLastCellInRow(0), true, true); - ostringstream os; + odocstringstream os; OutputParams const runparams; paste_tabular->plaintext(cur.buffer(), os, runparams, 0, true, '\t'); - cur.bv().stuffClipboard(os.str()); + // Needed for the "Edit->Paste recent" menu and the system clipboard. + cap::copySelection(cur, os.str()); + // mark tabular stack dirty // FIXME: this is a workaround for bug 1919. Should be removed for 1.5, // when we (hopefully) have a one-for-all paste mechanism. - lyx::cap::dirtyTabularStack(true); + // This must be called after cap::copySelection. + dirtyTabularStack(true); return true; } @@ -1714,7 +1849,9 @@ bool InsetTabular::pasteSelection(LCursor & cur) shared_ptr inset( new InsetText(*paste_tabular->getCellInset(r1, c1))); tabular.setCellInset(r2, c2, inset); - inset->markNew(); + // FIXME: change tracking (MG) + inset->setChange(Change(cur.buffer().params().trackChanges ? + Change::INSERTED : Change::UNCHANGED)); cur.pos() = 0; } } @@ -1734,16 +1871,21 @@ void InsetTabular::cutSelection(LCursor & cur) for (col_type j = cs; j <= ce; ++j) { shared_ptr t = cell(tabular.getCellNumber(i, j)); - if (cur.buffer().params().tracking_changes) - t->markErased(true); + if (cur.buffer().params().trackChanges) + // FIXME: Change tracking (MG) + t->setChange(Change(Change::DELETED)); else t->clear(); } } // cursor position might be invalid now - cur.pos() = cur.lastpos(); + if (cur.pit() > cur.lastpit()) + cur.pit() = cur.lastpit(); + if (cur.pos() > cur.lastpos()) + cur.pos() = cur.lastpos(); cur.clearSelection(); + theSelection().haveSelection(false); } @@ -1751,7 +1893,7 @@ bool InsetTabular::isRightToLeft(LCursor & cur) const { BOOST_ASSERT(cur.depth() > 1); Paragraph const & parentpar = cur[cur.depth() - 2].paragraph(); - LCursor::pos_type const parentpos = cur[cur.depth() - 2].pos(); + pos_type const parentpos = cur[cur.depth() - 2].pos(); return parentpar.getFontSettings(cur.bv().buffer()->params(), parentpos).language()->rightToLeft(); } @@ -1784,10 +1926,24 @@ LyXText * InsetTabular::getText(int idx) const } -void InsetTabular::markErased(bool erased) +void InsetTabular::setChange(Change const & change) { for (idx_type idx = 0; idx < nargs(); ++idx) - cell(idx)->markErased(erased); + cell(idx)->setChange(change); +} + + +void InsetTabular::acceptChanges() +{ + for (idx_type idx = 0; idx < nargs(); ++idx) + cell(idx)->acceptChanges(); +} + + +void InsetTabular::rejectChanges() +{ + for (idx_type idx = 0; idx < nargs(); ++idx) + cell(idx)->rejectChanges(); } @@ -1797,19 +1953,22 @@ bool InsetTabular::forceDefaultParagraphs(idx_type cell) const } -bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, +bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, bool usePaste) { if (buf.length() <= 0) return true; + Buffer const & buffer = *bv.buffer(); + col_type cols = 1; row_type rows = 1; col_type maxCols = 1; - string::size_type const len = buf.length(); - string::size_type p = 0; + docstring::size_type const len = buf.length(); + docstring::size_type p = 0; - while (p < len && (p = buf.find_first_of("\t\n", p)) != string::npos) { + while (p < len && + (p = buf.find_first_of(from_ascii("\t\n"), p)) != docstring::npos) { switch (buf[p]) { case '\t': ++cols; @@ -1830,7 +1989,7 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, row_type row = 0; if (usePaste) { paste_tabular.reset( - new LyXTabular(bv.buffer()->params(), rows, maxCols)); + new LyXTabular(buffer.params(), rows, maxCols)); loctab = paste_tabular.get(); cols = 0; dirtyTabularStack(true); @@ -1841,7 +2000,7 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, row = tabular.row_of_cell(cell); } - string::size_type op = 0; + docstring::size_type op = 0; idx_type const cells = loctab->getNumberOfCells(); p = 0; cols = ocol; @@ -1849,7 +2008,7 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, col_type const columns = loctab->columns(); while (cell < cells && p < len && row < rows && - (p = buf.find_first_of("\t\n", p)) != string::npos) + (p = buf.find_first_of(from_ascii("\t\n"), p)) != docstring::npos) { if (p >= len) break; @@ -1858,10 +2017,10 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, // we can only set this if we are not too far right if (cols < columns) { shared_ptr inset = loctab->getCellInset(cell); - inset->setViewCache(&bv); Paragraph & par = inset->text_.getPar(0); - LyXFont const font = inset->text_.getFont(par, 0); - inset->setText(buf.substr(op, p - op), font); + LyXFont const font = inset->text_.getFont(buffer, par, 0); + inset->setText(buf.substr(op, p - op), font, + buffer.params().trackChanges); ++cols; ++cell; } @@ -1870,10 +2029,10 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, // we can only set this if we are not too far right if (cols < columns) { shared_ptr inset = tabular.getCellInset(cell); - inset->setViewCache(&bv); Paragraph & par = inset->text_.getPar(0); - LyXFont const font = inset->text_.getFont(par, 0); - inset->setText(buf.substr(op, p - op), font); + LyXFont const font = inset->text_.getFont(buffer, par, 0); + inset->setText(buf.substr(op, p - op), font, + buffer.params().trackChanges); } cols = ocol; ++row; @@ -1887,10 +2046,10 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf, // check for the last cell if there is no trailing '\n' if (cell < cells && op < len) { shared_ptr inset = loctab->getCellInset(cell); - inset->setViewCache(&bv); Paragraph & par = inset->text_.getPar(0); - LyXFont const font = inset->text_.getFont(par, 0); - inset->setText(buf.substr(op, len - op), font); + LyXFont const font = inset->text_.getFont(buffer, par, 0); + inset->setText(buf.substr(op, len - op), font, + buffer.params().trackChanges); } return true; } @@ -1964,3 +2123,6 @@ string const InsetTabularMailer::params2string(InsetTabular const & inset) data << "\\end_inset\n"; return data.str(); } + + +} // namespace lyx