3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS
14 #include "insettabular.h"
15 #include "insettext.h"
18 #include "BufferView.h"
21 #include "funcrequest.h"
24 #include "LaTeXFeatures.h"
27 #include "lyxlength.h"
30 #include "ParagraphParameters.h"
31 #include "undo_funcs.h"
32 #include "WordLangTuple.h"
34 #include "frontends/Alert.h"
35 #include "frontends/Dialogs.h"
36 #include "frontends/font_metrics.h"
37 #include "frontends/LyXView.h"
38 #include "frontends/Painter.h"
40 #include "support/LAssert.h"
41 #include "support/lstrings.h"
60 int const ADD_TO_HEIGHT = 2;
61 int const ADD_TO_TABULAR_WIDTH = 2;
64 LyXTabular * paste_tabular = 0;
67 struct TabularFeature {
68 LyXTabular::Feature action;
73 TabularFeature tabularFeature[] =
75 { LyXTabular::APPEND_ROW, "append-row" },
76 { LyXTabular::APPEND_COLUMN, "append-column" },
77 { LyXTabular::DELETE_ROW, "delete-row" },
78 { LyXTabular::DELETE_COLUMN, "delete-column" },
79 { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
80 { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
81 { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
82 { LyXTabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
83 { LyXTabular::ALIGN_LEFT, "align-left" },
84 { LyXTabular::ALIGN_RIGHT, "align-right" },
85 { LyXTabular::ALIGN_CENTER, "align-center" },
86 { LyXTabular::ALIGN_BLOCK, "align-block" },
87 { LyXTabular::VALIGN_TOP, "valign-top" },
88 { LyXTabular::VALIGN_BOTTOM, "valign-bottom" },
89 { LyXTabular::VALIGN_CENTER, "valign-center" },
90 { LyXTabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
91 { LyXTabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
92 { LyXTabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
93 { LyXTabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
94 { LyXTabular::M_ALIGN_LEFT, "m-align-left" },
95 { LyXTabular::M_ALIGN_RIGHT, "m-align-right" },
96 { LyXTabular::M_ALIGN_CENTER, "m-align-center" },
97 { LyXTabular::M_VALIGN_TOP, "m-valign-top" },
98 { LyXTabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
99 { LyXTabular::M_VALIGN_CENTER, "m-valign-center" },
100 { LyXTabular::MULTICOLUMN, "multicolumn" },
101 { LyXTabular::SET_ALL_LINES, "set-all-lines" },
102 { LyXTabular::UNSET_ALL_LINES, "unset-all-lines" },
103 { LyXTabular::SET_LONGTABULAR, "set-longtabular" },
104 { LyXTabular::UNSET_LONGTABULAR, "unset-longtabular" },
105 { LyXTabular::SET_PWIDTH, "set-pwidth" },
106 { LyXTabular::SET_MPWIDTH, "set-mpwidth" },
107 { LyXTabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
108 { LyXTabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
109 { LyXTabular::SET_ROTATE_CELL, "set-rotate-cell" },
110 { LyXTabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
111 { LyXTabular::SET_USEBOX, "set-usebox" },
112 { LyXTabular::SET_LTHEAD, "set-lthead" },
113 { LyXTabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
114 { LyXTabular::SET_LTFOOT, "set-ltfoot" },
115 { LyXTabular::SET_LTLASTFOOT, "set-ltlastfoot" },
116 { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" },
117 { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" },
118 { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" },
119 { LyXTabular::LAST_ACTION, "" }
123 FindFeature(LyXTabular::Feature feature) : feature_(feature) {}
124 bool operator()(TabularFeature & tf)
126 return tf.action == feature_;
129 LyXTabular::Feature feature_;
135 string const featureAsString(LyXTabular::Feature feature)
137 TabularFeature * it = tabularFeature;
138 TabularFeature * end = it +
139 sizeof(tabularFeature) / sizeof(TabularFeature);
140 it = std::find_if(it, end, FindFeature(feature));
141 return (it == end) ? string() : it->feature;
145 bool InsetTabular::hasPasteBuffer() const
147 return (paste_tabular != 0);
151 InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
158 tabular.reset(new LyXTabular(buf.params, this, rows, columns));
159 // for now make it always display as display() inset
161 the_locking_inset = 0;
162 old_locking_inset = 0;
165 actrow = actcell = 0;
175 InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf,
177 : UpdatableInset(tab, same_id), buffer(&buf)
179 tabular.reset(new LyXTabular(buf.params,
180 this, *(tab.tabular), same_id));
181 the_locking_inset = 0;
182 old_locking_inset = 0;
185 actrow = actcell = 0;
195 InsetTabular::~InsetTabular()
197 InsetTabularMailer mailer(*this);
202 Inset * InsetTabular::clone(Buffer const & buf, bool same_id) const
204 return new InsetTabular(*this, buf, same_id);
208 BufferView * InsetTabular::view() const
210 return buffer->getUser();
214 void InsetTabular::write(Buffer const * buf, ostream & os) const
216 os << " Tabular" << endl;
217 tabular->Write(buf, os);
221 void InsetTabular::read(Buffer const * buf, LyXLex & lex)
223 bool const old_format = (lex.getString() == "\\LyXTable");
225 tabular.reset(new LyXTabular(buf, this, lex));
233 string token = lex.getString();
234 while (lex.isOK() && (token != "\\end_inset")) {
236 token = lex.getString();
238 if (token != "\\end_inset") {
239 lex.printError("Missing \\end_inset at this point. "
245 int InsetTabular::ascent(BufferView *, LyXFont const &) const
247 return tabular->GetAscentOfRow(0);
251 int InsetTabular::descent(BufferView *, LyXFont const &) const
253 return tabular->GetHeightOfTabular() - tabular->GetAscentOfRow(0) + 1;
257 int InsetTabular::width(BufferView *, LyXFont const &) const
259 return tabular->GetWidthOfTabular() + (2 * ADD_TO_TABULAR_WIDTH);
263 void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
271 Painter & pain = bv->painter();
277 UpdatableInset::draw(bv, font, baseline, x);
280 x += static_cast<float>(scroll());
285 top_baseline = baseline;
286 x += ADD_TO_TABULAR_WIDTH;
290 first_visible_cell = -1;
291 for (i = 0; i < tabular->rows(); ++i) {
293 cell = tabular->GetCellNumber(i, 0);
294 if (!((baseline + tabular->GetDescentOfRow(i)) > 0) &&
295 (baseline - tabular->GetAscentOfRow(i))<pain.paperHeight())
297 baseline += tabular->GetDescentOfRow(i) +
298 tabular->GetAscentOfRow(i + 1) +
299 tabular->GetAdditionalHeight(i + 1);
302 for (j = 0; j < tabular->columns(); ++j) {
303 if (nx > bv->workWidth())
305 if (tabular->IsPartOfMultiColumn(i, j))
307 cx = nx + tabular->GetBeginningOfTextInCell(cell);
308 if (first_visible_cell < 0)
309 first_visible_cell = cell;
310 if (hasSelection()) {
311 drawCellSelection(pain, nx, baseline, i, j, cell);
314 tabular->GetCellInset(cell)->draw(bv, font, baseline, cx);
315 drawCellLines(pain, nx, baseline, i, cell);
316 nx += tabular->GetWidthOfColumn(cell);
319 baseline += tabular->GetDescentOfRow(i) +
320 tabular->GetAscentOfRow(i + 1) +
321 tabular->GetAdditionalHeight(i + 1);
324 x -= ADD_TO_TABULAR_WIDTH;
325 x += width(bv, font);
326 if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
328 for(Inset * inset = owner(); inset; ++i)
329 inset = inset->owner();
330 if (calculate_dimensions_of_cells(bv, false))
338 void InsetTabular::drawCellLines(Painter & pain, int x, int baseline,
339 int row, int cell) const
341 int x2 = x + tabular->GetWidthOfColumn(cell);
344 if (!tabular->topAlreadyDrawn(cell)) {
345 on_off = !tabular->TopLine(cell);
346 pain.line(x, baseline - tabular->GetAscentOfRow(row),
347 x2, baseline - tabular->GetAscentOfRow(row),
348 on_off ? LColor::tabularonoffline : LColor::tabularline,
349 on_off ? Painter::line_onoffdash : Painter::line_solid);
351 on_off = !tabular->BottomLine(cell);
352 pain.line(x, baseline + tabular->GetDescentOfRow(row),
353 x2, baseline + tabular->GetDescentOfRow(row),
354 on_off ? LColor::tabularonoffline : LColor::tabularline,
355 on_off ? Painter::line_onoffdash : Painter::line_solid);
356 if (!tabular->leftAlreadyDrawn(cell)) {
357 on_off = !tabular->LeftLine(cell);
358 pain.line(x, baseline - tabular->GetAscentOfRow(row),
359 x, baseline + tabular->GetDescentOfRow(row),
360 on_off ? LColor::tabularonoffline : LColor::tabularline,
361 on_off ? Painter::line_onoffdash : Painter::line_solid);
363 on_off = !tabular->RightLine(cell);
364 pain.line(x2 - tabular->GetAdditionalWidth(cell),
365 baseline - tabular->GetAscentOfRow(row),
366 x2 - tabular->GetAdditionalWidth(cell),
367 baseline + tabular->GetDescentOfRow(row),
368 on_off ? LColor::tabularonoffline : LColor::tabularline,
369 on_off ? Painter::line_onoffdash : Painter::line_solid);
373 void InsetTabular::drawCellSelection(Painter & pain, int x, int baseline,
374 int row, int column, int cell) const
376 lyx::Assert(hasSelection());
377 int cs = tabular->column_of_cell(sel_cell_start);
378 int ce = tabular->column_of_cell(sel_cell_end);
381 cs = tabular->column_of_cell(sel_cell_end);
383 ce = tabular->right_column_of_cell(sel_cell_end);
386 int rs = tabular->row_of_cell(sel_cell_start);
387 int re = tabular->row_of_cell(sel_cell_end);
391 if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
392 int w = tabular->GetWidthOfColumn(cell);
393 int h = tabular->GetAscentOfRow(row) + tabular->GetDescentOfRow(row)-1;
394 pain.fillRectangle(x, baseline - tabular->GetAscentOfRow(row) + 1,
395 w, h, LColor::selection);
400 void InsetTabular::update(BufferView * bv, bool reinit)
406 owner()->update(bv, true);
413 if (calculate_dimensions_of_cells(bv, true))
416 owner()->update(bv, true);
420 if (the_locking_inset)
421 the_locking_inset->update(bv, reinit);
422 if (need_update < FULL &&
423 bv->text->status() == LyXText::NEED_MORE_REFRESH)
428 switch (need_update) {
432 if (calculate_dimensions_of_cells(bv, false)) {
447 string const InsetTabular::editMessage() const
449 return _("Opened Tabular Inset");
453 void InsetTabular::edit(BufferView * bv, int x, int y, mouse_button::state button)
455 UpdatableInset::edit(bv, x, y, button);
457 if (!bv->lockInset(this)) {
458 lyxerr[Debug::INSETTEXT] << "InsetTabular::Cannot lock inset" << endl;
462 the_locking_inset = 0;
468 if (insetHit(bv, x, y) && (button != mouse_button::button3)) {
469 activateCellInsetAbs(bv, x, y, button);
474 void InsetTabular::edit(BufferView * bv, bool front)
476 UpdatableInset::edit(bv, front);
478 if (!bv->lockInset(this)) {
479 lyxerr[Debug::INSETTEXT] << "InsetTabular::Cannot lock inset" << endl;
484 the_locking_inset = 0;
488 if (isRightToLeft(bv))
489 actcell = tabular->GetLastCellInRow(0);
493 if (isRightToLeft(bv))
494 actcell = tabular->GetFirstCellInRow(tabular->rows()-1);
496 actcell = tabular->GetNumberOfCells() - 1;
504 void InsetTabular::insetUnlock(BufferView * bv)
506 if (the_locking_inset) {
507 the_locking_inset->insetUnlock(bv);
508 updateLocal(bv, CELL);
509 the_locking_inset = 0;
515 if (scroll(false) || hasSelection()) {
520 updateLocal(bv, FULL);
525 void InsetTabular::updateLocal(BufferView * bv, UpdateCodes what) const
528 calculate_dimensions_of_cells(bv, true);
530 if (!locked && what == CELL)
532 if (need_update < what) // only set this if it has greater update
535 if (need_update != NONE) {
536 bv->updateInset(const_cast<InsetTabular *>(this));
543 bool InsetTabular::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
545 lyxerr[Debug::INSETTEXT] << "InsetTabular::LockInsetInInset("
550 if (inset == tabular->GetCellInset(actcell)) {
551 lyxerr[Debug::INSETTEXT] << "OK" << endl;
552 the_locking_inset = tabular->GetCellInset(actcell);
555 } else if (!the_locking_inset) {
556 int const n = tabular->GetNumberOfCells();
557 int const id = inset->id();
558 for (int i = 0; i < n; ++i) {
559 InsetText * in = tabular->GetCellInset(i);
562 the_locking_inset = in;
567 if (in->getInsetFromID(id)) {
570 return the_locking_inset->lockInsetInInset(bv, inset);
573 } else if (the_locking_inset && (the_locking_inset == inset)) {
574 lyxerr[Debug::INSETTEXT] << "OK" << endl;
576 } else if (the_locking_inset) {
577 lyxerr[Debug::INSETTEXT] << "MAYBE" << endl;
578 return the_locking_inset->lockInsetInInset(bv, inset);
580 lyxerr[Debug::INSETTEXT] << "NOT OK" << endl;
585 bool InsetTabular::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
588 if (!the_locking_inset)
590 if (the_locking_inset == inset) {
591 the_locking_inset->insetUnlock(bv);
593 #warning fix scrolling when cellinset has requested a scroll (Jug)!!!
599 updateLocal(bv, CELL);
600 // this has to be here otherwise we don't redraw the cell!
601 the_locking_inset = 0;
602 // showInsetCursor(bv, false);
605 if (the_locking_inset->unlockInsetInInset(bv, inset, lr)) {
606 if (inset->lyxCode() == TABULAR_CODE &&
607 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) {
608 InsetTabularMailer mailer(*this);
609 mailer.updateDialog(bv);
618 bool InsetTabular::updateInsetInInset(BufferView * bv, Inset * inset)
620 Inset * tl_inset = inset;
621 // look if this inset is really inside myself!
622 while(tl_inset->owner() && tl_inset->owner() != this)
623 tl_inset = tl_inset->owner();
624 // if we enter here it's not ower inset
625 if (!tl_inset->owner())
627 // we only have to do this if this is a subinset of our cells
628 if (tl_inset != inset) {
629 if (!static_cast<InsetText *>(tl_inset)->updateInsetInInset(bv, inset))
632 updateLocal(bv, CELL);
637 int InsetTabular::insetInInsetY() const
639 if (!the_locking_inset)
641 return inset_y + the_locking_inset->insetInInsetY();
645 UpdatableInset * InsetTabular::getLockingInset() const
647 return the_locking_inset ? the_locking_inset->getLockingInset() :
648 const_cast<InsetTabular *>(this);
652 UpdatableInset * InsetTabular::getFirstLockingInsetOfType(Inset::Code c)
656 if (the_locking_inset)
657 return the_locking_inset->getFirstLockingInsetOfType(c);
662 bool InsetTabular::insertInset(BufferView * bv, Inset * inset)
664 if (the_locking_inset)
665 return the_locking_inset->insertInset(bv, inset);
670 void InsetTabular::lfunMousePress(FuncRequest const & cmd)
672 if (hasSelection() && cmd.button() == mouse_button::button3)
675 if (hasSelection()) {
677 updateLocal(cmd.view(), SELECTION);
680 int const ocell = actcell;
681 int const orow = actrow;
682 BufferView * bv = cmd.view();
687 the_locking_inset = 0;
691 setPos(bv, cmd.x, cmd.y);
693 updateLocal(bv, NONE);
696 if (cmd.button() == mouse_button::button3) {
697 if ((ocell != actcell) && the_locking_inset) {
698 the_locking_inset->insetUnlock(bv);
699 updateLocal(bv, CELL);
700 the_locking_inset = 0;
707 bool const inset_hit = insetHit(bv, cmd.x, cmd.y);
709 if ((ocell == actcell) && the_locking_inset && inset_hit) {
711 FuncRequest cmd1 = cmd;
714 the_locking_inset->localDispatch(cmd1);
718 if (the_locking_inset) {
719 the_locking_inset->insetUnlock(bv);
720 updateLocal(bv, CELL);
721 the_locking_inset = 0;
724 if (cmd.button() == mouse_button::button2) {
725 localDispatch(FuncRequest(bv, LFUN_PASTESELECTION, "paragraph"));
729 if (inset_hit && bv->theLockingInset()) {
730 if (!bv->lockInset(static_cast<UpdatableInset*>
731 (tabular->GetCellInset(actcell))))
733 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
736 FuncRequest cmd1 = cmd;
739 the_locking_inset->localDispatch(cmd1);
746 bool InsetTabular::lfunMouseRelease(FuncRequest const & cmd)
749 if (the_locking_inset) {
750 FuncRequest cmd1 = cmd;
753 ret = the_locking_inset->localDispatch(cmd1);
755 if (cmd.button() == mouse_button::button3 && !ret) {
756 InsetTabularMailer mailer(*this);
757 mailer.showDialog(cmd.view());
764 void InsetTabular::lfunMouseMotion(FuncRequest const & cmd)
766 if (the_locking_inset) {
767 FuncRequest cmd1 = cmd;
770 the_locking_inset->localDispatch(cmd1);
774 BufferView * bv = cmd.view();
776 int const old_cell = actcell;
778 setPos(bv, cmd.x, cmd.y);
779 if (!hasSelection()) {
780 setSelection(actcell, actcell);
781 updateLocal(bv, SELECTION);
782 } else if (old_cell != actcell) {
783 setSelection(sel_cell_start, actcell);
784 updateLocal(bv, SELECTION);
790 Inset::RESULT InsetTabular::localDispatch(FuncRequest const & cmd)
792 // We need to save the value of the_locking_inset as the call to
793 // the_locking_inset->localDispatch might unlock it.
794 old_locking_inset = the_locking_inset;
795 RESULT result = UpdatableInset::localDispatch(cmd);
797 BufferView * bv = cmd.view();
798 if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
803 if (cmd.action < 0 && cmd.argument.empty())
806 bool hs = hasSelection();
809 // this one have priority over the locked InsetText, if we're not already
810 // inside another tabular then that one get's priority!
811 if (getFirstLockingInsetOfType(Inset::TABULAR_CODE) == this) {
812 switch (cmd.action) {
813 case LFUN_MOUSE_PRESS:
817 case LFUN_MOUSE_MOTION:
818 lfunMouseMotion(cmd);
821 case LFUN_MOUSE_RELEASE:
822 return lfunMouseRelease(cmd) ? DISPATCHED : UNDISPATCHED;
827 unlockInsetInInset(bv, the_locking_inset);
828 if (cmd.action == LFUN_TAB)
829 moveNextCell(bv, old_locking_inset != 0);
831 movePrevCell(bv, old_locking_inset != 0);
834 updateLocal(bv, SELECTION);
835 if (!the_locking_inset) {
837 return DISPATCHED_NOUPDATE;
840 // this to avoid compiler warnings.
846 kb_action action = cmd.action;
847 string arg = cmd.argument;
848 if (the_locking_inset) {
849 result = the_locking_inset->localDispatch(cmd);
850 if (result == DISPATCHED_NOUPDATE) {
853 if (sc != scroll()) { // inset has been scrolled
854 the_locking_inset->toggleInsetCursor(bv);
855 updateLocal(bv, FULL);
856 the_locking_inset->toggleInsetCursor(bv);
859 } else if (result == DISPATCHED) {
860 the_locking_inset->toggleInsetCursor(bv);
861 updateLocal(bv, CELL);
862 the_locking_inset->toggleInsetCursor(bv);
864 } else if (result == FINISHED_UP) {
866 } else if (result == FINISHED_DOWN) {
868 } else if (result == FINISHED_RIGHT) {
876 // --- Cursor Movements ----------------------------------
877 case LFUN_RIGHTSEL: {
878 int const start = hasSelection() ? sel_cell_start : actcell;
879 if (tabular->IsLastCellInRow(actcell)) {
880 setSelection(start, actcell);
885 // if we are starting a selection, only select
886 // the current cell at the beginning
887 if (hasSelection()) {
888 moveRight(bv, false);
891 setSelection(start, end);
892 updateLocal(bv, SELECTION);
896 result = moveRight(bv);
899 updateLocal(bv, SELECTION);
902 int const start = hasSelection() ? sel_cell_start : actcell;
903 if (tabular->IsFirstCellInRow(actcell)) {
904 setSelection(start, actcell);
909 // if we are starting a selection, only select
910 // the current cell at the beginning
911 if (hasSelection()) {
915 setSelection(start, end);
916 updateLocal(bv, SELECTION);
920 result = moveLeft(bv);
923 updateLocal(bv, SELECTION);
926 int const start = hasSelection() ? sel_cell_start : actcell;
927 int const ocell = actcell;
928 // if we are starting a selection, only select
929 // the current cell at the beginning
930 if (hasSelection()) {
932 if ((ocell == sel_cell_end) ||
933 (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
934 setSelection(start, tabular->GetCellBelow(sel_cell_end));
936 setSelection(start, tabular->GetLastCellBelow(sel_cell_end));
938 setSelection(start, start);
940 updateLocal(bv, SELECTION);
944 result = moveDown(bv, old_locking_inset != 0);
947 updateLocal(bv, SELECTION);
951 int const start = hasSelection() ? sel_cell_start : actcell;
952 int const ocell = actcell;
953 // if we are starting a selection, only select
954 // the current cell at the beginning
955 if (hasSelection()) {
957 if ((ocell == sel_cell_end) ||
958 (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
959 setSelection(start, tabular->GetCellAbove(sel_cell_end));
961 setSelection(start, tabular->GetLastCellAbove(sel_cell_end));
963 setSelection(start, start);
965 updateLocal(bv, SELECTION);
969 result = moveUp(bv, old_locking_inset != 0);
972 updateLocal(bv, SELECTION);
975 UpdateCodes code = CURSOR;
981 unlockInsetInInset(bv, the_locking_inset);
982 if (bv->text->top_y() + bv->painter().paperHeight() <
983 (top_baseline + tabular->GetHeightOfTabular()))
985 bv->scrollDocView(bv->text->top_y() + bv->painter().paperHeight());
987 actcell = tabular->GetCellBelow(first_visible_cell) + column;
989 actcell = tabular->GetFirstCellInRow(tabular->rows() - 1) + column;
992 updateLocal(bv, code);
996 UpdateCodes code = CURSOR;
1001 int column = actcol;
1002 unlockInsetInInset(bv, the_locking_inset);
1003 if (top_baseline < 0) {
1004 bv->scrollDocView(bv->text->top_y() - bv->painter().paperHeight());
1006 if (top_baseline > 0)
1009 actcell = tabular->GetCellBelow(first_visible_cell) + column;
1014 updateLocal(bv, code);
1017 // none of these make sense for insettabular,
1018 // but we must catch them to prevent any
1019 // selection from being confused
1023 case LFUN_WORDLEFTSEL:
1024 case LFUN_WORDRIGHT:
1025 case LFUN_WORDRIGHTSEL:
1027 case LFUN_DOWN_PARAGRAPH:
1028 case LFUN_DOWN_PARAGRAPHSEL:
1029 case LFUN_UP_PARAGRAPH:
1030 case LFUN_UP_PARAGRAPHSEL:
1031 case LFUN_BACKSPACE:
1036 case LFUN_BEGINNINGBUF:
1037 case LFUN_BEGINNINGBUFSEL:
1039 case LFUN_ENDBUFSEL:
1041 case LFUN_LAYOUT_TABULAR: {
1042 InsetTabularMailer mailer(*this);
1043 mailer.showDialog(bv);
1046 case LFUN_INSET_DIALOG_UPDATE: {
1047 InsetTabularMailer mailer(*this);
1048 mailer.updateDialog(bv);
1051 case LFUN_TABULAR_FEATURE:
1052 if (!tabularFeatures(bv, arg))
1053 result = UNDISPATCHED;
1055 // insert file functions
1056 case LFUN_FILE_INSERT_ASCII_PARA:
1057 case LFUN_FILE_INSERT_ASCII:
1059 string tmpstr = getContentsOfAsciiFile(bv, arg, false);
1062 if (insertAsciiString(bv, tmpstr, false))
1063 updateLocal(bv, INIT);
1065 result = UNDISPATCHED;
1068 // cut and paste functions
1070 if (!copySelection(bv))
1074 setUndo(bv, Undo::DELETE,
1075 bv->text->cursor.par(),
1076 bv->text->cursor.par()->next());
1077 cutSelection(bv->buffer()->params);
1078 updateLocal(bv, INIT);
1081 if (!hasSelection())
1086 case LFUN_PASTESELECTION:
1088 string const clip(bv->getClipboard());
1092 if (clip.find('\t') != string::npos) {
1096 string::size_type len = clip.length();
1097 string::size_type p = 0;
1100 ((p = clip.find_first_of("\t\n", p)) != string::npos)) {
1108 maxCols = max(cols, maxCols);
1114 maxCols = max(cols, maxCols);
1115 delete paste_tabular;
1116 paste_tabular = new LyXTabular(bv->buffer()->params,
1117 this, rows, maxCols);
1118 string::size_type op = 0;
1120 int cells = paste_tabular->GetNumberOfCells();
1122 while ((cell < cells) && (p < len) &&
1123 (p = clip.find_first_of("\t\n", p)) != string::npos) {
1128 paste_tabular->GetCellInset(cell)->setText(clip.substr(op, p-op));
1133 paste_tabular->GetCellInset(cell)->setText(clip.substr(op, p-op));
1134 while (cols++ < maxCols)
1142 // check for the last cell if there is no trailing '\n'
1143 if ((cell < cells) && (op < len))
1144 paste_tabular->GetCellInset(cell)->setText(clip.substr(op, len-op));
1147 if (!insertAsciiString(bv, clip, true))
1150 // so that the clipboard is used and it goes on
1152 // and executes LFUN_PASTESELECTION in insettext!
1153 delete paste_tabular;
1158 if (hasPasteBuffer()) {
1159 setUndo(bv, Undo::INSERT,
1160 bv->text->cursor.par(),
1161 bv->text->cursor.par()->next());
1163 updateLocal(bv, INIT);
1166 // ATTENTION: the function above has to be PASTE and PASTESELECTION!!!
1168 // handle font changing stuff on selection before we lock the inset
1169 // in the default part!
1170 result = UNDISPATCHED;
1181 case LFUN_UNDERLINE:
1182 case LFUN_FONT_SIZE:
1183 if (bv->dispatch(FuncRequest(bv, action, arg)))
1184 result = DISPATCHED;
1190 // we try to activate the actual inset and put this event down to
1191 // the insets dispatch function.
1192 if ((result == DISPATCHED) || the_locking_inset)
1195 if (activateCellInset(bv)) {
1196 // reset need_update setted in above function!
1198 result = the_locking_inset->localDispatch(FuncRequest(bv, action, arg));
1199 if ((result == UNDISPATCHED) || (result >= FINISHED)) {
1200 unlockInsetInInset(bv, the_locking_inset);
1202 // we need to update if this was requested before
1203 updateLocal(bv, NONE);
1204 return UNDISPATCHED;
1207 // so the below CELL is not set because this is higher
1208 // priority and we get a full redraw
1209 need_update = SELECTION;
1212 updateLocal(bv, CELL);
1217 if (result < FINISHED) {
1218 if (!the_locking_inset) {
1219 if (bv->fitCursor())
1220 updateLocal(bv, FULL);
1222 showInsetCursor(bv);
1225 bv->unlockInset(this);
1230 int InsetTabular::latex(Buffer const * buf, ostream & os,
1231 bool fragile, bool fp) const
1233 return tabular->latex(buf, os, fragile, fp);
1237 int InsetTabular::ascii(Buffer const * buf, ostream & os, int ll) const
1240 return tabular->ascii(buf, os, (int)parOwner()->params().depth(),
1242 return tabular->ascii(buf, os, 0, false,0);
1246 int InsetTabular::linuxdoc(Buffer const * buf, ostream & os) const
1249 int const ret = tabular->ascii(buf,os,
1250 (int)parOwner()->params().depth(),
1257 int InsetTabular::docbook(Buffer const * buf, ostream & os, bool mixcont) const
1262 // if the table is inside a float it doesn't need the informaltable
1263 // wrapper. Search for it.
1264 for(master = owner();
1265 master && master->lyxCode() != Inset::FLOAT_CODE;
1266 master = master->owner());
1269 os << "<informaltable>";
1274 ret+= tabular->docbook(buf, os, mixcont);
1276 os << "</informaltable>";
1285 void InsetTabular::validate(LaTeXFeatures & features) const
1287 tabular->Validate(features);
1291 bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv, bool reinit) const
1297 bool changed = false;
1299 // FIXME: since InsetText ignores this anyway, it doesn't
1300 // matter what we pass it. Ugly
1303 // if we have a locking_inset we should have to check only this cell for
1304 // change so I'll try this to have a boost, but who knows ;)
1305 if ((need_update != INIT) &&
1306 (the_locking_inset == tabular->GetCellInset(actcell))) {
1307 for(int i = 0; i < tabular->columns(); ++i) {
1308 maxAsc = max(tabular->GetCellInset(actrow, i)->ascent(bv, font),
1310 maxDesc = max(tabular->GetCellInset(actrow, i)->descent(bv, font),
1313 changed = tabular->SetWidthOfCell(actcell, the_locking_inset->width(bv, font));
1314 changed = tabular->SetAscentOfRow(actrow, maxAsc + ADD_TO_HEIGHT) || changed;
1315 changed = tabular->SetDescentOfRow(actrow, maxDesc + ADD_TO_HEIGHT) || changed;
1318 for (int i = 0; i < tabular->rows(); ++i) {
1321 for (int j = 0; j < tabular->columns(); ++j) {
1322 if (tabular->IsPartOfMultiColumn(i,j))
1325 inset = tabular->GetCellInset(cell);
1326 if (!reinit && !tabular->GetPWidth(cell).zero())
1327 inset->update(bv, false);
1328 maxAsc = max(maxAsc, inset->ascent(bv, font));
1329 maxDesc = max(maxDesc, inset->descent(bv, font));
1330 changed = tabular->SetWidthOfCell(cell, inset->width(bv, font)) || changed;
1332 changed = tabular->SetAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
1333 changed = tabular->SetDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
1341 void InsetTabular::getCursorPos(BufferView * bv, int & x, int & y) const
1343 if (the_locking_inset) {
1344 the_locking_inset->getCursorPos(bv, x, y);
1347 x = cursor_.x() - top_x;
1352 void InsetTabular::toggleInsetCursor(BufferView * bv)
1355 if (isCursorVisible())
1356 bv->hideLockedInsetCursor();
1359 if (the_locking_inset) {
1360 the_locking_inset->toggleInsetCursor(bv);
1364 LyXFont font; // = the_locking_inset->GetFont(par, cursor.pos);
1366 int const asc = font_metrics::maxAscent(font);
1367 int const desc = font_metrics::maxDescent(font);
1369 if (isCursorVisible())
1370 bv->hideLockedInsetCursor();
1372 bv->showLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1373 toggleCursorVisible();
1377 void InsetTabular::showInsetCursor(BufferView * bv, bool show)
1381 if (!isCursorVisible()) {
1382 LyXFont font; // = GetFont(par, cursor.pos);
1384 int const asc = font_metrics::maxAscent(font);
1385 int const desc = font_metrics::maxDescent(font);
1386 bv->fitLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1388 bv->showLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1389 setCursorVisible(true);
1394 void InsetTabular::hideInsetCursor(BufferView * bv)
1396 if (isCursorVisible()) {
1397 bv->hideLockedInsetCursor();
1398 setCursorVisible(false);
1403 void InsetTabular::fitInsetCursor(BufferView * bv) const
1405 if (the_locking_inset) {
1406 int old_top_y = bv->text->top_y();
1407 the_locking_inset->fitInsetCursor(bv);
1408 if (old_top_y != bv->text->top_y())
1414 int const asc = font_metrics::maxAscent(font);
1415 int const desc = font_metrics::maxDescent(font);
1418 if (bv->fitLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc))
1423 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1427 actcell = actrow = actcol = 0;
1428 int ly = tabular->GetDescentOfRow(actrow);
1430 // first search the right row
1431 while ((ly < y) && ((actrow+1) < tabular->rows())) {
1432 cursor_.y(cursor_.y() + tabular->GetDescentOfRow(actrow) +
1433 tabular->GetAscentOfRow(actrow + 1) +
1434 tabular->GetAdditionalHeight(actrow + 1));
1436 ly = cursor_.y() + tabular->GetDescentOfRow(actrow);
1438 actcell = tabular->GetCellNumber(actrow, actcol);
1440 // now search the right column
1441 int lx = tabular->GetWidthOfColumn(actcell) -
1442 tabular->GetAdditionalWidth(actcell);
1443 for (; !tabular->IsLastCellInRow(actcell) && lx < x; ++actcell) {
1444 lx += tabular->GetWidthOfColumn(actcell + 1)
1445 + tabular->GetAdditionalWidth(actcell);
1447 cursor_.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
1452 int InsetTabular::getCellXPos(int cell) const
1456 for (; !tabular->IsFirstCellInRow(c); --c)
1458 int lx = tabular->GetWidthOfColumn(cell);
1459 for (; c < cell; ++c) {
1460 lx += tabular->GetWidthOfColumn(c);
1462 return (lx - tabular->GetWidthOfColumn(cell) + top_x);
1466 void InsetTabular::resetPos(BufferView * bv) const
1468 #ifdef WITH_WARNINGS
1469 #warning This should be fixed in the right manner (20011128 Jug)
1471 // fast hack to fix infinite repaintings!
1472 if (in_reset_pos > 0)
1476 actcol = tabular->column_of_cell(actcell);
1479 for (; (cell < actcell) && !tabular->IsLastRow(cell); ++cell) {
1480 if (tabular->IsLastCellInRow(cell)) {
1481 cursor_.y(cursor_.y() + tabular->GetDescentOfRow(actrow) +
1482 tabular->GetAscentOfRow(actrow + 1) +
1483 tabular->GetAdditionalHeight(actrow + 1));
1487 if (!locked || nodraw()) {
1488 if (the_locking_inset)
1489 inset_y = cursor_.y();
1492 // we need this only from here on!!!
1494 static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1495 int new_x = getCellXPos(actcell);
1496 int old_x = cursor_.x();
1499 // cursor.x(getCellXPos(actcell) + offset);
1500 if ((actcol < tabular->columns() - 1) && scroll(false) &&
1501 (tabular->GetWidthOfTabular() < bv->workWidth()-20))
1504 updateLocal(bv, FULL);
1505 } else if (the_locking_inset &&
1506 (tabular->GetWidthOfColumn(actcell) > bv->workWidth()-20))
1508 int xx = cursor_.x() - offset + bv->text->getRealCursorX();
1509 if (xx > (bv->workWidth()-20)) {
1510 scroll(bv, -(xx - bv->workWidth() + 60));
1511 updateLocal(bv, FULL);
1512 } else if (xx < 20) {
1518 updateLocal(bv, FULL);
1520 } else if ((cursor_.x() - offset) > 20 &&
1521 (cursor_.x() - offset + tabular->GetWidthOfColumn(actcell))
1522 > (bv->workWidth() - 20)) {
1523 scroll(bv, -tabular->GetWidthOfColumn(actcell) - 20);
1524 updateLocal(bv, FULL);
1525 } else if ((cursor_.x() - offset) < 20) {
1526 scroll(bv, 20 - cursor_.x() + offset);
1527 updateLocal(bv, FULL);
1528 } else if (scroll() && top_x > 20 &&
1529 (top_x + tabular->GetWidthOfTabular()) > (bv->workWidth() - 20)) {
1530 scroll(bv, old_x - cursor_.x());
1531 updateLocal(bv, FULL);
1533 if (the_locking_inset) {
1534 inset_x = cursor_.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
1535 inset_y = cursor_.y();
1537 if ((!the_locking_inset ||
1538 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) &&
1539 actcell != oldcell) {
1540 InsetTabular * inset = const_cast<InsetTabular *>(this);
1541 InsetTabularMailer mailer(*inset);
1542 mailer.updateDialog(bv);
1549 Inset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1551 if (lock && !old_locking_inset) {
1552 if (activateCellInset(bv))
1555 bool moved = isRightToLeft(bv)
1556 ? movePrevCell(bv) : moveNextCell(bv);
1558 return FINISHED_RIGHT;
1559 if (lock && activateCellInset(bv))
1563 return DISPATCHED_NOUPDATE;
1567 Inset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1569 bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
1572 if (lock) { // behind the inset
1573 if (activateCellInset(bv, 0, 0, mouse_button::none, true))
1577 return DISPATCHED_NOUPDATE;
1581 Inset::RESULT InsetTabular::moveUp(BufferView * bv, bool lock)
1583 int const ocell = actcell;
1584 actcell = tabular->GetCellAbove(actcell);
1585 if (actcell == ocell) // we moved out of the inset
1591 if (old_locking_inset) {
1592 old_locking_inset->getCursorPos(bv, x, y);
1593 x -= cursor_.x() + tabular->GetBeginningOfTextInCell(actcell);
1595 if (activateCellInset(bv, x, 0))
1598 return DISPATCHED_NOUPDATE;
1602 Inset::RESULT InsetTabular::moveDown(BufferView * bv, bool lock)
1604 int const ocell = actcell;
1605 actcell = tabular->GetCellBelow(actcell);
1606 if (actcell == ocell) // we moved out of the inset
1607 return FINISHED_DOWN;
1612 if (old_locking_inset) {
1613 old_locking_inset->getCursorPos(bv, x, y);
1614 x -= cursor_.x() + tabular->GetBeginningOfTextInCell(actcell);
1616 if (activateCellInset(bv, x, 0))
1619 return DISPATCHED_NOUPDATE;
1623 bool InsetTabular::moveNextCell(BufferView * bv, bool lock)
1625 if (isRightToLeft(bv)) {
1626 if (tabular->IsFirstCellInRow(actcell)) {
1627 int row = tabular->row_of_cell(actcell);
1628 if (row == tabular->rows() - 1)
1630 actcell = tabular->GetLastCellInRow(row);
1631 actcell = tabular->GetCellBelow(actcell);
1638 if (tabular->IsLastCell(actcell))
1643 bool rtl = tabular->GetCellInset(actcell)->paragraph()->
1644 isRightToLeftPar(bv->buffer()->params);
1645 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1652 bool InsetTabular::movePrevCell(BufferView * bv, bool lock)
1654 if (isRightToLeft(bv)) {
1655 if (tabular->IsLastCellInRow(actcell)) {
1656 int row = tabular->row_of_cell(actcell);
1659 actcell = tabular->GetFirstCellInRow(row);
1660 actcell = tabular->GetCellAbove(actcell);
1662 if (tabular->IsLastCell(actcell))
1667 if (!actcell) // first cell
1672 bool rtl = tabular->GetCellInset(actcell)->paragraph()->
1673 isRightToLeftPar(bv->buffer()->params);
1674 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1681 void InsetTabular::setFont(BufferView * bv, LyXFont const & font, bool tall,
1685 setSelection(0, tabular->GetNumberOfCells() - 1);
1687 if (hasSelection()) {
1688 setUndo(bv, Undo::EDIT,
1689 bv->text->cursor.par(),
1690 bv->text->cursor.par()->next());
1691 bool const frozen = undo_frozen;
1694 // apply the fontchange on the whole selection
1699 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1700 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1701 for(int j = sel_col_start; j <= sel_col_end; ++j) {
1702 tabular->GetCellInset(i, j)->setFont(bv, font, tall, true);
1709 updateLocal(bv, INIT);
1711 if (the_locking_inset)
1712 the_locking_inset->setFont(bv, font, tall);
1716 bool InsetTabular::tabularFeatures(BufferView * bv, string const & what)
1718 LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1721 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
1722 string const tmp = tabularFeature[i].feature;
1724 if (tmp == what.substr(0, tmp.length())) {
1725 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
1726 //tabularFeatures[i].feature.length())) {
1727 action = tabularFeature[i].action;
1731 if (action == LyXTabular::LAST_ACTION)
1735 ltrim(what.substr(tabularFeature[i].feature.length()));
1736 tabularFeatures(bv, action, val);
1742 void checkLongtableSpecial(LyXTabular::ltType & ltt,
1743 string const & special, bool & flag)
1745 if (special == "dl_above") {
1748 } else if (special == "dl_below") {
1749 ltt.bottomDL = flag;
1751 } else if (special == "empty") {
1763 void InsetTabular::tabularFeatures(BufferView * bv,
1764 LyXTabular::Feature feature,
1765 string const & value)
1771 bool setLines = false;
1772 LyXAlignment setAlign = LYX_ALIGN_LEFT;
1773 LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1776 case LyXTabular::M_ALIGN_LEFT:
1777 case LyXTabular::ALIGN_LEFT:
1778 setAlign = LYX_ALIGN_LEFT;
1780 case LyXTabular::M_ALIGN_RIGHT:
1781 case LyXTabular::ALIGN_RIGHT:
1782 setAlign = LYX_ALIGN_RIGHT;
1784 case LyXTabular::M_ALIGN_CENTER:
1785 case LyXTabular::ALIGN_CENTER:
1786 setAlign = LYX_ALIGN_CENTER;
1788 case LyXTabular::ALIGN_BLOCK:
1789 setAlign = LYX_ALIGN_BLOCK;
1791 case LyXTabular::M_VALIGN_TOP:
1792 case LyXTabular::VALIGN_TOP:
1793 setVAlign = LyXTabular::LYX_VALIGN_TOP;
1795 case LyXTabular::M_VALIGN_BOTTOM:
1796 case LyXTabular::VALIGN_BOTTOM:
1797 setVAlign = LyXTabular::LYX_VALIGN_BOTTOM;
1799 case LyXTabular::M_VALIGN_CENTER:
1800 case LyXTabular::VALIGN_CENTER:
1801 setVAlign = LyXTabular::LYX_VALIGN_CENTER;
1806 if (hasSelection()) {
1807 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1809 sel_col_start = sel_col_end = tabular->column_of_cell(actcell);
1810 sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1812 setUndo(bv, Undo::FINISH,
1813 bv->text->cursor.par(),
1814 bv->text->cursor.par()->next());
1816 int row = tabular->row_of_cell(actcell);
1817 int column = tabular->column_of_cell(actcell);
1819 LyXTabular::ltType ltt;
1822 case LyXTabular::SET_PWIDTH:
1824 LyXLength const vallen(value);
1825 LyXLength const & tmplen = tabular->GetColumnPWidth(actcell);
1827 bool const update = (tmplen != vallen);
1828 tabular->SetColumnPWidth(actcell, vallen);
1831 for (int i = 0; i < tabular->rows(); ++i) {
1832 cell = tabular->GetCellNumber(i,column);
1833 tabular->GetCellInset(cell)->resizeLyXText(bv);
1835 updateLocal(bv, INIT);
1839 && tabular->GetAlignment(actcell, true) == LYX_ALIGN_BLOCK)
1840 tabularFeatures(bv, LyXTabular::ALIGN_CENTER, string());
1841 else if (!vallen.zero()
1842 && tabular->GetAlignment(actcell, true) != LYX_ALIGN_BLOCK)
1843 tabularFeatures(bv, LyXTabular::ALIGN_BLOCK, string());
1846 case LyXTabular::SET_MPWIDTH:
1848 LyXLength const vallen(value);
1849 LyXLength const & tmplen = tabular->GetPWidth(actcell);
1851 bool const update = (tmplen != vallen);
1852 tabular->SetMColumnPWidth(actcell, vallen);
1854 for (int i = 0; i < tabular->rows(); ++i) {
1855 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1858 updateLocal(bv, INIT);
1862 case LyXTabular::SET_SPECIAL_COLUMN:
1863 case LyXTabular::SET_SPECIAL_MULTI:
1864 tabular->SetAlignSpecial(actcell,value,feature);
1865 updateLocal(bv, FULL);
1867 case LyXTabular::APPEND_ROW:
1868 // append the row into the tabular
1869 unlockInsetInInset(bv, the_locking_inset);
1870 tabular->AppendRow(bv->buffer()->params, actcell);
1871 updateLocal(bv, INIT);
1873 case LyXTabular::APPEND_COLUMN:
1874 // append the column into the tabular
1875 unlockInsetInInset(bv, the_locking_inset);
1876 tabular->AppendColumn(bv->buffer()->params, actcell);
1877 actcell = tabular->GetCellNumber(row, column);
1878 updateLocal(bv, INIT);
1880 case LyXTabular::DELETE_ROW:
1881 unlockInsetInInset(bv, the_locking_inset);
1882 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1883 tabular->DeleteRow(sel_row_start);
1885 if (sel_row_start >= tabular->rows())
1887 actcell = tabular->GetCellNumber(sel_row_start, column);
1889 updateLocal(bv, INIT);
1891 case LyXTabular::DELETE_COLUMN:
1892 unlockInsetInInset(bv, the_locking_inset);
1893 for(int i = sel_col_start; i <= sel_col_end; ++i) {
1894 tabular->DeleteColumn(sel_col_start);
1896 if (sel_col_start >= tabular->columns())
1898 actcell = tabular->GetCellNumber(row, sel_col_start);
1900 updateLocal(bv, INIT);
1902 case LyXTabular::M_TOGGLE_LINE_TOP:
1904 case LyXTabular::TOGGLE_LINE_TOP:
1906 bool lineSet = !tabular->TopLine(actcell, flag);
1907 for (int i = sel_row_start; i <= sel_row_end; ++i)
1908 for (int j = sel_col_start; j <= sel_col_end; ++j)
1909 tabular->SetTopLine(
1910 tabular->GetCellNumber(i, j),
1912 updateLocal(bv, INIT);
1916 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1918 case LyXTabular::TOGGLE_LINE_BOTTOM:
1920 bool lineSet = !tabular->BottomLine(actcell, flag);
1921 for (int i = sel_row_start; i <= sel_row_end; ++i)
1922 for (int j = sel_col_start; j <= sel_col_end; ++j)
1923 tabular->SetBottomLine(
1924 tabular->GetCellNumber(i, j),
1927 updateLocal(bv, INIT);
1931 case LyXTabular::M_TOGGLE_LINE_LEFT:
1933 case LyXTabular::TOGGLE_LINE_LEFT:
1935 bool lineSet = !tabular->LeftLine(actcell, flag);
1936 for (int i = sel_row_start; i <= sel_row_end; ++i)
1937 for (int j = sel_col_start; j <= sel_col_end; ++j)
1938 tabular->SetLeftLine(
1939 tabular->GetCellNumber(i,j),
1942 updateLocal(bv, INIT);
1946 case LyXTabular::M_TOGGLE_LINE_RIGHT:
1948 case LyXTabular::TOGGLE_LINE_RIGHT:
1950 bool lineSet = !tabular->RightLine(actcell, flag);
1951 for (int i = sel_row_start; i <= sel_row_end; ++i)
1952 for (int j = sel_col_start; j <= sel_col_end; ++j)
1953 tabular->SetRightLine(
1954 tabular->GetCellNumber(i,j),
1957 updateLocal(bv, INIT);
1961 case LyXTabular::M_ALIGN_LEFT:
1962 case LyXTabular::M_ALIGN_RIGHT:
1963 case LyXTabular::M_ALIGN_CENTER:
1965 case LyXTabular::ALIGN_LEFT:
1966 case LyXTabular::ALIGN_RIGHT:
1967 case LyXTabular::ALIGN_CENTER:
1968 case LyXTabular::ALIGN_BLOCK:
1969 for (int i = sel_row_start; i <= sel_row_end; ++i)
1970 for (int j = sel_col_start; j <= sel_col_end; ++j)
1971 tabular->SetAlignment(
1972 tabular->GetCellNumber(i, j),
1975 updateLocal(bv, INIT);
1977 case LyXTabular::M_VALIGN_TOP:
1978 case LyXTabular::M_VALIGN_BOTTOM:
1979 case LyXTabular::M_VALIGN_CENTER:
1981 case LyXTabular::VALIGN_TOP:
1982 case LyXTabular::VALIGN_BOTTOM:
1983 case LyXTabular::VALIGN_CENTER:
1984 for (int i = sel_row_start; i <= sel_row_end; ++i)
1985 for (int j = sel_col_start; j <= sel_col_end; ++j)
1986 tabular->SetVAlignment(
1987 tabular->GetCellNumber(i, j),
1989 updateLocal(bv, INIT);
1991 case LyXTabular::MULTICOLUMN:
1993 if (sel_row_start != sel_row_end) {
1994 Alert::alert(_("Impossible operation!"),
1995 _("Multicolumns can only be horizontally."),
1999 // just multicol for one Single Cell
2000 if (!hasSelection()) {
2001 // check wether we are completly in a multicol
2002 if (tabular->IsMultiColumn(actcell)) {
2003 tabular->UnsetMultiColumn(actcell);
2004 updateLocal(bv, INIT);
2006 tabular->SetMultiColumn(bv->buffer(), actcell, 1);
2007 updateLocal(bv, CELL);
2011 // we have a selection so this means we just add all this
2012 // cells to form a multicolumn cell
2016 if (sel_cell_start > sel_cell_end) {
2017 s_start = sel_cell_end;
2018 s_end = sel_cell_start;
2020 s_start = sel_cell_start;
2021 s_end = sel_cell_end;
2023 tabular->SetMultiColumn(bv->buffer(), s_start, s_end - s_start + 1);
2026 updateLocal(bv, INIT);
2029 case LyXTabular::SET_ALL_LINES:
2031 case LyXTabular::UNSET_ALL_LINES:
2032 for (int i = sel_row_start; i <= sel_row_end; ++i)
2033 for (int j = sel_col_start; j <= sel_col_end; ++j)
2034 tabular->SetAllLines(
2035 tabular->GetCellNumber(i,j), setLines);
2036 updateLocal(bv, INIT);
2038 case LyXTabular::SET_LONGTABULAR:
2039 tabular->SetLongTabular(true);
2040 updateLocal(bv, INIT); // because this toggles displayed
2042 case LyXTabular::UNSET_LONGTABULAR:
2043 tabular->SetLongTabular(false);
2044 updateLocal(bv, INIT); // because this toggles displayed
2046 case LyXTabular::SET_ROTATE_TABULAR:
2047 tabular->SetRotateTabular(true);
2049 case LyXTabular::UNSET_ROTATE_TABULAR:
2050 tabular->SetRotateTabular(false);
2052 case LyXTabular::SET_ROTATE_CELL:
2053 for (int i = sel_row_start; i <= sel_row_end; ++i)
2054 for (int j = sel_col_start; j<=sel_col_end; ++j)
2055 tabular->SetRotateCell(
2056 tabular->GetCellNumber(i, j),
2059 case LyXTabular::UNSET_ROTATE_CELL:
2060 for (int i = sel_row_start; i <= sel_row_end; ++i)
2061 for (int j = sel_col_start; j <= sel_col_end; ++j)
2062 tabular->SetRotateCell(
2063 tabular->GetCellNumber(i, j), false);
2065 case LyXTabular::SET_USEBOX:
2067 LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
2068 if (val == tabular->GetUsebox(actcell))
2069 val = LyXTabular::BOX_NONE;
2070 for (int i = sel_row_start; i <= sel_row_end; ++i)
2071 for (int j = sel_col_start; j <= sel_col_end; ++j)
2073 tabular->GetCellNumber(i, j), val);
2076 case LyXTabular::UNSET_LTFIRSTHEAD:
2078 case LyXTabular::SET_LTFIRSTHEAD:
2079 (void)tabular->GetRowOfLTFirstHead(row, ltt);
2080 checkLongtableSpecial(ltt, value, flag);
2081 tabular->SetLTHead(row, flag, ltt, true);
2083 case LyXTabular::UNSET_LTHEAD:
2085 case LyXTabular::SET_LTHEAD:
2086 (void)tabular->GetRowOfLTHead(row, ltt);
2087 checkLongtableSpecial(ltt, value, flag);
2088 tabular->SetLTHead(row, flag, ltt, false);
2090 case LyXTabular::UNSET_LTFOOT:
2092 case LyXTabular::SET_LTFOOT:
2093 (void)tabular->GetRowOfLTFoot(row, ltt);
2094 checkLongtableSpecial(ltt, value, flag);
2095 tabular->SetLTFoot(row, flag, ltt, false);
2097 case LyXTabular::UNSET_LTLASTFOOT:
2099 case LyXTabular::SET_LTLASTFOOT:
2100 (void)tabular->GetRowOfLTLastFoot(row, ltt);
2101 checkLongtableSpecial(ltt, value, flag);
2102 tabular->SetLTFoot(row, flag, ltt, true);
2104 case LyXTabular::SET_LTNEWPAGE:
2106 bool what = !tabular->GetLTNewPage(row);
2107 tabular->SetLTNewPage(row, what);
2110 // dummy stuff just to avoid warnings
2111 case LyXTabular::LAST_ACTION:
2117 bool InsetTabular::activateCellInset(BufferView * bv, int x, int y, mouse_button::state button,
2120 UpdatableInset * inset =
2121 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2122 LyXFont font(LyXFont::ALL_SANE);
2124 x = inset->x() + inset->width(bv, font);
2125 y = inset->descent(bv, font);
2127 //inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
2128 //inset_y = cursor.y();
2129 inset->edit(bv, x, y, button);
2130 if (!the_locking_inset)
2132 updateLocal(bv, CELL);
2133 return (the_locking_inset != 0);
2137 bool InsetTabular::activateCellInsetAbs(BufferView * bv, int x, int y,
2138 mouse_button::state button)
2140 inset_x = cursor_.x()
2141 - top_x + tabular->GetBeginningOfTextInCell(actcell);
2142 inset_y = cursor_.y();
2143 return activateCellInset(bv, x - inset_x, y - inset_y, button);
2147 bool InsetTabular::insetHit(BufferView *, int x, int) const
2150 > (cursor_.x() + tabular->GetBeginningOfTextInCell(actcell));
2154 // This returns paperWidth() if the cell-width is unlimited or the width
2155 // in pixels if we have a pwidth for this cell.
2156 int InsetTabular::getMaxWidthOfCell(BufferView * bv, int cell) const
2158 LyXLength const len = tabular->GetPWidth(cell);
2162 return len.inPixels(latexTextWidth(bv));
2166 int InsetTabular::getMaxWidth(BufferView * bv,
2167 UpdatableInset const * inset) const
2169 int cell = tabular->GetCellFromInset(inset, actcell);
2172 lyxerr << "Own inset not found, shouldn't really happen!"
2177 int w = getMaxWidthOfCell(bv, cell);
2179 // because the inset then subtracts it's top_x and owner->x()
2180 w += (inset->x() - top_x);
2187 void InsetTabular::deleteLyXText(BufferView * bv, bool recursive) const
2189 resizeLyXText(bv, recursive);
2193 void InsetTabular::resizeLyXText(BufferView * bv, bool force) const
2196 for(int i = 0; i < tabular->rows(); ++i) {
2197 for(int j = 0; j < tabular->columns(); ++j) {
2198 tabular->GetCellInset(i, j)->resizeLyXText(bv, true);
2206 LyXText * InsetTabular::getLyXText(BufferView const * bv,
2207 bool const recursive) const
2209 if (the_locking_inset)
2210 return the_locking_inset->getLyXText(bv, recursive);
2212 // if we're locked lock the actual insettext and return it's LyXText!!!
2214 UpdatableInset * inset =
2215 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2216 inset->edit(const_cast<BufferView *>(bv), 0, 0, 0);
2217 return the_locking_inset->getLyXText(bv, recursive);
2220 return Inset::getLyXText(bv, recursive);
2224 bool InsetTabular::showInsetDialog(BufferView * bv) const
2226 if (!the_locking_inset || !the_locking_inset->showInsetDialog(bv)) {
2227 InsetTabular * tmp = const_cast<InsetTabular *>(this);
2228 InsetTabularMailer mailer(*tmp);
2229 mailer.showDialog(bv);
2235 void InsetTabular::openLayoutDialog(BufferView * bv) const
2237 if (the_locking_inset) {
2238 InsetTabular * i = static_cast<InsetTabular *>
2239 (the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE));
2241 i->openLayoutDialog(bv);
2245 InsetTabular * tmp = const_cast<InsetTabular *>(this);
2246 InsetTabularMailer mailer(*tmp);
2247 mailer.showDialog(bv);
2252 // function returns an object as defined in func_status.h:
2253 // states OK, Unknown, Disabled, On, Off.
2255 FuncStatus InsetTabular::getStatus(string const & what) const
2257 int action = LyXTabular::LAST_ACTION;
2261 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
2262 string const tmp = tabularFeature[i].feature;
2263 if (tmp == what.substr(0, tmp.length())) {
2264 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
2265 // tabularFeatures[i].feature.length())) {
2266 action = tabularFeature[i].action;
2270 if (action == LyXTabular::LAST_ACTION) {
2272 return status.unknown(true);
2275 string const argument = ltrim(what.substr(tabularFeature[i].feature.length()));
2280 LyXTabular::ltType dummyltt;
2283 if (hasSelection()) {
2284 getSelection(sel_row_start, sel_row_end, dummy, dummy);
2286 sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
2290 case LyXTabular::SET_PWIDTH:
2291 case LyXTabular::SET_MPWIDTH:
2292 case LyXTabular::SET_SPECIAL_COLUMN:
2293 case LyXTabular::SET_SPECIAL_MULTI:
2294 return status.disabled(true);
2296 case LyXTabular::APPEND_ROW:
2297 case LyXTabular::APPEND_COLUMN:
2298 case LyXTabular::DELETE_ROW:
2299 case LyXTabular::DELETE_COLUMN:
2300 case LyXTabular::SET_ALL_LINES:
2301 case LyXTabular::UNSET_ALL_LINES:
2302 return status.clear();
2304 case LyXTabular::MULTICOLUMN:
2305 status.setOnOff(tabular->IsMultiColumn(actcell));
2307 case LyXTabular::M_TOGGLE_LINE_TOP:
2309 case LyXTabular::TOGGLE_LINE_TOP:
2310 status.setOnOff(tabular->TopLine(actcell, flag));
2312 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
2314 case LyXTabular::TOGGLE_LINE_BOTTOM:
2315 status.setOnOff(tabular->BottomLine(actcell, flag));
2317 case LyXTabular::M_TOGGLE_LINE_LEFT:
2319 case LyXTabular::TOGGLE_LINE_LEFT:
2320 status.setOnOff(tabular->LeftLine(actcell, flag));
2322 case LyXTabular::M_TOGGLE_LINE_RIGHT:
2324 case LyXTabular::TOGGLE_LINE_RIGHT:
2325 status.setOnOff(tabular->RightLine(actcell, flag));
2327 case LyXTabular::M_ALIGN_LEFT:
2329 case LyXTabular::ALIGN_LEFT:
2330 status.setOnOff(tabular->GetAlignment(actcell, flag) == LYX_ALIGN_LEFT);
2332 case LyXTabular::M_ALIGN_RIGHT:
2334 case LyXTabular::ALIGN_RIGHT:
2335 status.setOnOff(tabular->GetAlignment(actcell, flag) == LYX_ALIGN_RIGHT);
2337 case LyXTabular::M_ALIGN_CENTER:
2339 case LyXTabular::ALIGN_CENTER:
2340 status.setOnOff(tabular->GetAlignment(actcell, flag) == LYX_ALIGN_CENTER);
2342 case LyXTabular::ALIGN_BLOCK:
2343 status.disabled(tabular->GetPWidth(actcell).zero());
2344 status.setOnOff(tabular->GetAlignment(actcell, flag) == LYX_ALIGN_BLOCK);
2346 case LyXTabular::M_VALIGN_TOP:
2348 case LyXTabular::VALIGN_TOP:
2349 status.setOnOff(tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP);
2351 case LyXTabular::M_VALIGN_BOTTOM:
2353 case LyXTabular::VALIGN_BOTTOM:
2354 status.setOnOff(tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM);
2356 case LyXTabular::M_VALIGN_CENTER:
2358 case LyXTabular::VALIGN_CENTER:
2359 status.setOnOff(tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER);
2361 case LyXTabular::SET_LONGTABULAR:
2362 status.setOnOff(tabular->IsLongTabular());
2364 case LyXTabular::UNSET_LONGTABULAR:
2365 status.setOnOff(!tabular->IsLongTabular());
2367 case LyXTabular::SET_ROTATE_TABULAR:
2368 status.setOnOff(tabular->GetRotateTabular());
2370 case LyXTabular::UNSET_ROTATE_TABULAR:
2371 status.setOnOff(!tabular->GetRotateTabular());
2373 case LyXTabular::SET_ROTATE_CELL:
2374 status.setOnOff(tabular->GetRotateCell(actcell));
2376 case LyXTabular::UNSET_ROTATE_CELL:
2377 status.setOnOff(!tabular->GetRotateCell(actcell));
2379 case LyXTabular::SET_USEBOX:
2380 status.setOnOff(strToInt(argument) == tabular->GetUsebox(actcell));
2382 case LyXTabular::SET_LTFIRSTHEAD:
2383 status.setOnOff(tabular->GetRowOfLTHead(sel_row_start, dummyltt));
2385 case LyXTabular::SET_LTHEAD:
2386 status.setOnOff(tabular->GetRowOfLTHead(sel_row_start, dummyltt));
2388 case LyXTabular::SET_LTFOOT:
2389 status.setOnOff(tabular->GetRowOfLTFoot(sel_row_start, dummyltt));
2391 case LyXTabular::SET_LTLASTFOOT:
2392 status.setOnOff(tabular->GetRowOfLTFoot(sel_row_start, dummyltt));
2394 case LyXTabular::SET_LTNEWPAGE:
2395 status.setOnOff(tabular->GetLTNewPage(sel_row_start));
2399 status.disabled(true);
2406 vector<string> const InsetTabular::getLabelList() const
2408 return tabular->getLabelList();
2412 bool InsetTabular::copySelection(BufferView * bv)
2414 if (!hasSelection())
2417 int sel_col_start = tabular->column_of_cell(sel_cell_start);
2418 int sel_col_end = tabular->column_of_cell(sel_cell_end);
2419 if (sel_col_start > sel_col_end) {
2420 sel_col_start = sel_col_end;
2421 sel_col_end = tabular->right_column_of_cell(sel_cell_start);
2423 sel_col_end = tabular->right_column_of_cell(sel_cell_end);
2425 int const columns = sel_col_end - sel_col_start + 1;
2427 int sel_row_start = tabular->row_of_cell(sel_cell_start);
2428 int sel_row_end = tabular->row_of_cell(sel_cell_end);
2429 if (sel_row_start > sel_row_end) {
2430 swap(sel_row_start, sel_row_end);
2432 int const rows = sel_row_end - sel_row_start + 1;
2434 delete paste_tabular;
2435 paste_tabular = new LyXTabular(bv->buffer()->params,
2436 this, *tabular); // rows, columns);
2437 for (int i = 0; i < sel_row_start; ++i)
2438 paste_tabular->DeleteRow(0);
2439 while (paste_tabular->rows() > rows)
2440 paste_tabular->DeleteRow(rows);
2441 paste_tabular->SetTopLine(0, true, true);
2442 paste_tabular->SetBottomLine(paste_tabular->GetFirstCellInRow(rows - 1),
2444 for (int i = 0; i < sel_col_start; ++i)
2445 paste_tabular->DeleteColumn(0);
2446 while (paste_tabular->columns() > columns)
2447 paste_tabular->DeleteColumn(columns);
2448 paste_tabular->SetLeftLine(0, true, true);
2449 paste_tabular->SetRightLine(paste_tabular->GetLastCellInRow(0),
2453 paste_tabular->ascii(bv->buffer(), sstr,
2454 (int)parOwner()->params().depth(), true, '\t');
2455 bv->stuffClipboard(STRCONV(sstr.str()));
2460 bool InsetTabular::pasteSelection(BufferView * bv)
2465 for (int r1 = 0, r2 = actrow;
2466 (r1 < paste_tabular->rows()) && (r2 < tabular->rows());
2468 for(int c1 = 0, c2 = actcol;
2469 (c1 < paste_tabular->columns()) && (c2 < tabular->columns());
2471 if (paste_tabular->IsPartOfMultiColumn(r1,c1) &&
2472 tabular->IsPartOfMultiColumn(r2,c2))
2474 if (paste_tabular->IsPartOfMultiColumn(r1,c1)) {
2478 if (tabular->IsPartOfMultiColumn(r2,c2)) {
2482 int const n1 = paste_tabular->GetCellNumber(r1, c1);
2483 int const n2 = tabular->GetCellNumber(r2, c2);
2484 *(tabular->GetCellInset(n2)) = *(paste_tabular->GetCellInset(n1));
2485 tabular->GetCellInset(n2)->setOwner(this);
2486 tabular->GetCellInset(n2)->deleteLyXText(bv);
2487 tabular->GetCellInset(n2)->markNew();
2494 bool InsetTabular::cutSelection(BufferParams const & bp)
2496 if (!hasSelection())
2499 int sel_col_start = tabular->column_of_cell(sel_cell_start);
2500 int sel_col_end = tabular->column_of_cell(sel_cell_end);
2501 if (sel_col_start > sel_col_end) {
2502 sel_col_start = sel_col_end;
2503 sel_col_end = tabular->right_column_of_cell(sel_cell_start);
2505 sel_col_end = tabular->right_column_of_cell(sel_cell_end);
2507 int sel_row_start = tabular->row_of_cell(sel_cell_start);
2508 int sel_row_end = tabular->row_of_cell(sel_cell_end);
2509 if (sel_row_start > sel_row_end) {
2510 swap(sel_row_start, sel_row_end);
2512 if (sel_cell_start > sel_cell_end) {
2513 swap(sel_cell_start, sel_cell_end);
2515 for (int i = sel_row_start; i <= sel_row_end; ++i) {
2516 for (int j = sel_col_start; j <= sel_col_end; ++j) {
2517 tabular->GetCellInset(tabular->GetCellNumber(i, j))->clear(bp.tracking_changes);
2524 bool InsetTabular::isRightToLeft(BufferView * bv)
2526 return bv->getParentLanguage(this)->RightToLeft();
2530 bool InsetTabular::nodraw() const
2532 if (!UpdatableInset::nodraw() && the_locking_inset)
2533 return the_locking_inset->nodraw();
2534 return UpdatableInset::nodraw();
2538 int InsetTabular::scroll(bool recursive) const
2540 int sx = UpdatableInset::scroll(false);
2542 if (recursive && the_locking_inset)
2543 sx += the_locking_inset->scroll(recursive);
2549 void InsetTabular::getSelection(int & srow, int & erow,
2550 int & scol, int & ecol) const
2552 int const start = hasSelection() ? sel_cell_start : actcell;
2553 int const end = hasSelection() ? sel_cell_end : actcell;
2555 srow = tabular->row_of_cell(start);
2556 erow = tabular->row_of_cell(end);
2561 scol = tabular->column_of_cell(start);
2562 ecol = tabular->column_of_cell(end);
2566 ecol = tabular->right_column_of_cell(end);
2571 Paragraph * InsetTabular::firstParagraph() const
2573 if (the_locking_inset)
2574 return the_locking_inset->firstParagraph();
2579 Paragraph * InsetTabular::getFirstParagraph(int i) const
2581 return (i < tabular->GetNumberOfCells())
2582 ? tabular->GetCellInset(i)->getFirstParagraph(0)
2587 LyXCursor const & InsetTabular::cursor(BufferView * bv) const
2589 if (the_locking_inset)
2590 return the_locking_inset->cursor(bv);
2591 return Inset::cursor(bv);
2595 Inset * InsetTabular::getInsetFromID(int id_arg) const
2598 return const_cast<InsetTabular *>(this);
2601 for(int i = 0; i < tabular->rows(); ++i) {
2602 for(int j = 0; j < tabular->columns(); ++j) {
2603 if ((result = tabular->GetCellInset(i, j)->getInsetFromID(id_arg)))
2612 InsetTabular::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2615 if (the_locking_inset) {
2616 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2617 if (!word.word().empty()) {
2621 if (tabular->IsLastCell(actcell)) {
2622 bv->unlockInset(const_cast<InsetTabular *>(this));
2624 return WordLangTuple();
2628 // otherwise we have to lock the next inset and ask for it's selecttion
2629 UpdatableInset * inset =
2630 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2631 inset->edit(bv, 0, 0, mouse_button::none);
2632 WordLangTuple word(selectNextWordInt(bv, value));
2634 if (!word.word().empty())
2640 WordLangTuple InsetTabular::selectNextWordInt(BufferView * bv, float & value) const
2642 // when entering this function the inset should be ALWAYS locked!
2643 lyx::Assert(the_locking_inset);
2645 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2646 if (!word.word().empty())
2649 if (tabular->IsLastCell(actcell)) {
2650 bv->unlockInset(const_cast<InsetTabular *>(this));
2651 return WordLangTuple();
2654 // otherwise we have to lock the next inset and ask for it's selecttion
2655 UpdatableInset * inset =
2656 static_cast<UpdatableInset*>(tabular->GetCellInset(++actcell));
2658 return selectNextWordInt(bv, value);
2662 void InsetTabular::selectSelectedWord(BufferView * bv)
2664 if (the_locking_inset) {
2665 the_locking_inset->selectSelectedWord(bv);
2672 void InsetTabular::toggleSelection(BufferView * bv, bool kill_selection)
2674 if (the_locking_inset) {
2675 the_locking_inset->toggleSelection(bv, kill_selection);
2680 void InsetTabular::markErased()
2684 while (!tabular->IsLastCell(cell)) {
2686 InsetText * inset = tabular->GetCellInset(cell);
2687 inset->markErased();
2692 bool InsetTabular::nextChange(BufferView * bv, lyx::pos_type & length)
2694 if (the_locking_inset) {
2695 if (the_locking_inset->nextChange(bv, length)) {
2696 updateLocal(bv, CELL);
2699 if (tabular->IsLastCell(actcell))
2703 InsetText * inset = tabular->GetCellInset(actcell);
2704 if (inset->nextChange(bv, length)) {
2705 updateLocal(bv, FULL);
2708 while (!tabular->IsLastCell(actcell)) {
2710 inset = tabular->GetCellInset(actcell);
2711 if (inset->nextChange(bv, length)) {
2712 updateLocal(bv, FULL);
2720 bool InsetTabular::searchForward(BufferView * bv, string const & str,
2723 if (the_locking_inset) {
2724 if (the_locking_inset->searchForward(bv, str, cs, mw)) {
2725 updateLocal(bv, CELL);
2728 if (tabular->IsLastCell(actcell))
2732 InsetText * inset = tabular->GetCellInset(actcell);
2733 if (inset->searchForward(bv, str, cs, mw)) {
2734 updateLocal(bv, FULL);
2737 while (!tabular->IsLastCell(actcell)) {
2739 inset = tabular->GetCellInset(actcell);
2740 if (inset->searchForward(bv, str, cs, mw)) {
2741 updateLocal(bv, FULL);
2749 bool InsetTabular::searchBackward(BufferView * bv, string const & str,
2752 if (the_locking_inset) {
2753 if (the_locking_inset->searchBackward(bv, str, cs, mw)) {
2754 updateLocal(bv, CELL);
2759 actcell = tabular->GetNumberOfCells();
2763 InsetText * inset = tabular->GetCellInset(actcell);
2764 if (inset->searchBackward(bv, str, cs, mw)) {
2765 updateLocal(bv, CELL);
2773 bool InsetTabular::insetAllowed(Inset::Code code) const
2775 if (the_locking_inset)
2776 return the_locking_inset->insetAllowed(code);
2777 // we return true here because if the inset is not locked someone
2778 // wants to insert something in one of our insettexts and we generally
2784 bool InsetTabular::forceDefaultParagraphs(Inset const * in) const
2786 const int cell = tabular->GetCellFromInset(in, actcell);
2789 return tabular->GetPWidth(cell).zero();
2791 // well we didn't obviously find it so maybe our owner knows more
2793 return owner()->forceDefaultParagraphs(in);
2794 // if we're here there is really something strange going on!!!
2798 bool InsetTabular::insertAsciiString(BufferView * bv, string const & buf,
2801 if (buf.length() <= 0)
2807 string::size_type len = buf.length();
2808 string::size_type p = 0;
2811 ((p = buf.find_first_of("\t\n", p)) != string::npos))
2820 maxCols = max(cols, maxCols);
2826 maxCols = max(cols, maxCols);
2827 LyXTabular * loctab;
2832 delete paste_tabular;
2833 paste_tabular = new LyXTabular(bv->buffer()->params,
2834 this, rows, maxCols);
2835 loctab = paste_tabular;
2838 loctab = tabular.get();
2844 string::size_type op = 0;
2845 int cells = loctab->GetNumberOfCells();
2848 rows = loctab->rows();
2849 int const columns = loctab->columns();
2851 while ((cell < cells) && (p < len) && (row < rows) &&
2852 (p = buf.find_first_of("\t\n", p)) != string::npos)
2858 // we can only set this if we are not too far right
2859 if (cols < columns) {
2860 InsetText * ti = loctab->GetCellInset(cell);
2861 LyXFont const font = ti->getLyXText(bv)->
2862 getFont(bv->buffer(), ti->paragraph(), 0);
2863 ti->setText(buf.substr(op, p-op), font);
2869 // we can only set this if we are not too far right
2870 if (cols < columns) {
2871 InsetText * ti = loctab->GetCellInset(cell);
2872 LyXFont const font = ti->getLyXText(bv)->
2873 getFont(bv->buffer(), ti->paragraph(), 0);
2874 ti->setText(buf.substr(op, p-op), font);
2879 cell = loctab->GetCellNumber(row, cols);
2885 // check for the last cell if there is no trailing '\n'
2886 if ((cell < cells) && (op < len)) {
2887 InsetText * ti = loctab->GetCellInset(cell);
2888 LyXFont const font = ti->getLyXText(bv)->
2889 getFont(bv->buffer(), ti->paragraph(), 0);
2890 ti->setText(buf.substr(op, len-op), font);
2897 void InsetTabular::addPreview(grfx::PreviewLoader & loader) const
2899 int const rows = tabular->rows();
2900 int const columns = tabular->columns();
2901 for (int i = 0; i < rows; ++i) {
2902 for (int j = 0; j < columns; ++j) {
2903 tabular->GetCellInset(i,j)->addPreview(loader);
2909 string const InsetTabularMailer:: name_("tabular");
2911 InsetTabularMailer::InsetTabularMailer(InsetTabular & inset)
2916 string const InsetTabularMailer::inset2string() const
2918 return params2string(inset_);
2922 int InsetTabularMailer::string2params(string const & in, InsetTabular & inset)
2924 istringstream data(in);
2926 lex.setStream(data);
2930 string const token = lex.getString();
2938 string const token = lex.getString();
2939 if (token != "\\active_cell")
2942 cell = lex.getInteger();
2945 // This is part of the inset proper that is usually swallowed
2946 // by Buffer::readInset
2949 string const token = lex.getString();
2950 if (token != "Tabular")
2957 BufferView * const bv = inset.view();
2958 Buffer const * const buffer = bv ? bv->buffer() : 0;
2960 inset.read(buffer, lex);
2962 // We can't set the active cell, but we can tell the frontend
2969 InsetTabularMailer::params2string(InsetTabular const & inset)
2971 BufferView * const bv = inset.view();
2972 Buffer const * const buffer = bv ? bv->buffer() : 0;
2977 data << name_ << " \\active_cell " << inset.getActCell() << '\n';
2978 inset.write(buffer, data);
2979 data << "\\end_inset\n";