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
13 #include "insettabular.h"
14 #include "insettext.h"
17 #include "BufferView.h"
20 #include "dimension.h"
21 #include "funcrequest.h"
24 #include "LaTeXFeatures.h"
28 #include "lyxlength.h"
31 #include "ParagraphParameters.h"
32 #include "undo_funcs.h"
33 #include "WordLangTuple.h"
34 #include "metricsinfo.h"
36 #include "frontends/Alert.h"
37 #include "frontends/Dialogs.h"
38 #include "frontends/font_metrics.h"
39 #include "frontends/LyXView.h"
40 #include "frontends/Painter.h"
42 #include "support/LAssert.h"
43 #include "support/lstrings.h"
51 using namespace lyx::support;
52 using namespace lyx::graphics;
66 int const ADD_TO_HEIGHT = 2;
67 int const ADD_TO_TABULAR_WIDTH = 2;
70 LyXTabular * paste_tabular = 0;
73 struct TabularFeature {
74 LyXTabular::Feature action;
79 TabularFeature tabularFeature[] =
81 { LyXTabular::APPEND_ROW, "append-row" },
82 { LyXTabular::APPEND_COLUMN, "append-column" },
83 { LyXTabular::DELETE_ROW, "delete-row" },
84 { LyXTabular::DELETE_COLUMN, "delete-column" },
85 { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
86 { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
87 { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
88 { LyXTabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
89 { LyXTabular::ALIGN_LEFT, "align-left" },
90 { LyXTabular::ALIGN_RIGHT, "align-right" },
91 { LyXTabular::ALIGN_CENTER, "align-center" },
92 { LyXTabular::ALIGN_BLOCK, "align-block" },
93 { LyXTabular::VALIGN_TOP, "valign-top" },
94 { LyXTabular::VALIGN_BOTTOM, "valign-bottom" },
95 { LyXTabular::VALIGN_CENTER, "valign-center" },
96 { LyXTabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
97 { LyXTabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
98 { LyXTabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
99 { LyXTabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
100 { LyXTabular::M_ALIGN_LEFT, "m-align-left" },
101 { LyXTabular::M_ALIGN_RIGHT, "m-align-right" },
102 { LyXTabular::M_ALIGN_CENTER, "m-align-center" },
103 { LyXTabular::M_VALIGN_TOP, "m-valign-top" },
104 { LyXTabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
105 { LyXTabular::M_VALIGN_CENTER, "m-valign-center" },
106 { LyXTabular::MULTICOLUMN, "multicolumn" },
107 { LyXTabular::SET_ALL_LINES, "set-all-lines" },
108 { LyXTabular::UNSET_ALL_LINES, "unset-all-lines" },
109 { LyXTabular::SET_LONGTABULAR, "set-longtabular" },
110 { LyXTabular::UNSET_LONGTABULAR, "unset-longtabular" },
111 { LyXTabular::SET_PWIDTH, "set-pwidth" },
112 { LyXTabular::SET_MPWIDTH, "set-mpwidth" },
113 { LyXTabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
114 { LyXTabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
115 { LyXTabular::SET_ROTATE_CELL, "set-rotate-cell" },
116 { LyXTabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
117 { LyXTabular::SET_USEBOX, "set-usebox" },
118 { LyXTabular::SET_LTHEAD, "set-lthead" },
119 { LyXTabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
120 { LyXTabular::SET_LTFOOT, "set-ltfoot" },
121 { LyXTabular::SET_LTLASTFOOT, "set-ltlastfoot" },
122 { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" },
123 { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" },
124 { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" },
125 { LyXTabular::LAST_ACTION, "" }
129 FindFeature(LyXTabular::Feature feature) : feature_(feature) {}
130 bool operator()(TabularFeature & tf)
132 return tf.action == feature_;
135 LyXTabular::Feature feature_;
141 string const featureAsString(LyXTabular::Feature feature)
143 TabularFeature * it = tabularFeature;
144 TabularFeature * end = it +
145 sizeof(tabularFeature) / sizeof(TabularFeature);
146 it = std::find_if(it, end, FindFeature(feature));
147 return (it == end) ? string() : it->feature;
151 bool InsetTabular::hasPasteBuffer() const
153 return (paste_tabular != 0);
157 InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
158 : tabular(buf.params, this, max(rows, 1), max(columns, 1)),
159 buffer_(&buf), cursorx_(0), cursory_(0)
161 // for now make it always display as display() inset
163 the_locking_inset = 0;
164 old_locking_inset = 0;
167 actrow = actcell = 0;
176 InsetTabular::InsetTabular(InsetTabular const & tab)
177 : UpdatableInset(tab),
178 tabular(tab.buffer_->params, this, tab.tabular),
179 buffer_(tab.buffer_), cursorx_(0), cursory_(0)
181 the_locking_inset = 0;
182 old_locking_inset = 0;
185 actrow = actcell = 0;
194 InsetTabular::~InsetTabular()
196 InsetTabularMailer(*this).hideDialog();
200 auto_ptr<InsetBase> InsetTabular::clone() const
202 return auto_ptr<InsetBase>(new InsetTabular(*this));
206 Buffer const * InsetTabular::buffer() const
212 BufferView * InsetTabular::view() const
219 void InsetTabular::buffer(Buffer * b)
225 void InsetTabular::write(Buffer const * buf, ostream & os) const
227 os << "Tabular" << endl;
228 tabular.write(buf, os);
232 void InsetTabular::read(Buffer const * buf, LyXLex & lex)
234 bool const old_format = (lex.getString() == "\\LyXTable");
236 tabular.read(buf, lex);
244 string token = lex.getString();
245 while (lex.isOK() && (token != "\\end_inset")) {
247 token = lex.getString();
249 if (token != "\\end_inset") {
250 lex.printError("Missing \\end_inset at this point. "
256 void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
258 //lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " <<
259 // mi.base.textwidth << "\n";
261 lyxerr << "InsetTabular::metrics: need bv\n";
265 calculate_dimensions_of_cells(mi);
267 dim.asc = tabular.getAscentOfRow(0);
268 dim.des = tabular.getHeightOfTabular() - tabular.getAscentOfRow(0) + 1;
269 dim.wid = tabular.getWidthOfTabular() + 2 * ADD_TO_TABULAR_WIDTH;
274 void InsetTabular::draw(PainterInfo & pi, int x, int y) const
276 //lyxerr << "InsetTabular::draw: " << x << " " << y << "\n";
278 lyxerr << "InsetTabular::nodraw: " << x << " " << y << "\n";
283 BufferView * bv = pi.base.bv;
286 UpdatableInset::draw(pi, x, y);
294 x += ADD_TO_TABULAR_WIDTH;
297 first_visible_cell = -1;
298 for (int i = 0; i < tabular.rows(); ++i) {
300 cell = tabular.getCellNumber(i, 0);
301 if (y + tabular.getDescentOfRow(i) <= 0 &&
302 y - tabular.getAscentOfRow(i) < pi.pain.paperHeight())
304 y += tabular.getDescentOfRow(i) +
305 tabular.getAscentOfRow(i + 1) +
306 tabular.getAdditionalHeight(i + 1);
309 for (int j = 0; j < tabular.columns(); ++j) {
310 if (nx > bv->workWidth())
312 if (tabular.isPartOfMultiColumn(i, j))
314 int cx = nx + tabular.getBeginningOfTextInCell(cell);
315 if (first_visible_cell < 0)
316 first_visible_cell = cell;
317 if (hasSelection()) {
318 drawCellSelection(pi.pain, nx, y, i, j, cell);
321 tabular.getCellInset(cell).draw(pi, cx, y);
322 drawCellLines(pi.pain, nx, y, i, cell);
323 nx += tabular.getWidthOfColumn(cell);
327 // Would be nice, but for some completely unfathomable reason,
328 // on a col resize to a new fixed width, even though the insettexts
329 // are resized, the cell isn't, but drawing all cells in a tall table
330 // has the desired effect somehow. Complete dark magic.
332 // avoiding drawing the rest of a long table is
333 // a pretty big speedup
334 if (y > bv->workHeight())
338 y += tabular.getDescentOfRow(i) +
339 tabular.getAscentOfRow(i + 1) +
340 tabular.getAdditionalHeight(i + 1);
347 void InsetTabular::drawCellLines(Painter & pain, int x, int y,
348 int row, int cell) const
350 int x2 = x + tabular.getWidthOfColumn(cell);
353 if (!tabular.topAlreadyDrawn(cell)) {
354 on_off = !tabular.topLine(cell);
355 pain.line(x, y - tabular.getAscentOfRow(row),
356 x2, y - tabular.getAscentOfRow(row),
357 on_off ? LColor::tabularonoffline : LColor::tabularline,
358 on_off ? Painter::line_onoffdash : Painter::line_solid);
360 on_off = !tabular.bottomLine(cell);
361 pain.line(x, y + tabular.getDescentOfRow(row),
362 x2, y + tabular.getDescentOfRow(row),
363 on_off ? LColor::tabularonoffline : LColor::tabularline,
364 on_off ? Painter::line_onoffdash : Painter::line_solid);
365 if (!tabular.leftAlreadyDrawn(cell)) {
366 on_off = !tabular.leftLine(cell);
367 pain.line(x, y - tabular.getAscentOfRow(row),
368 x, y + tabular.getDescentOfRow(row),
369 on_off ? LColor::tabularonoffline : LColor::tabularline,
370 on_off ? Painter::line_onoffdash : Painter::line_solid);
372 on_off = !tabular.rightLine(cell);
373 pain.line(x2 - tabular.getAdditionalWidth(cell),
374 y - tabular.getAscentOfRow(row),
375 x2 - tabular.getAdditionalWidth(cell),
376 y + tabular.getDescentOfRow(row),
377 on_off ? LColor::tabularonoffline : LColor::tabularline,
378 on_off ? Painter::line_onoffdash : Painter::line_solid);
382 void InsetTabular::drawCellSelection(Painter & pain, int x, int y,
383 int row, int column, int cell) const
385 Assert(hasSelection());
386 int cs = tabular.column_of_cell(sel_cell_start);
387 int ce = tabular.column_of_cell(sel_cell_end);
390 cs = tabular.column_of_cell(sel_cell_end);
392 ce = tabular.right_column_of_cell(sel_cell_end);
395 int rs = tabular.row_of_cell(sel_cell_start);
396 int re = tabular.row_of_cell(sel_cell_end);
400 if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
401 int w = tabular.getWidthOfColumn(cell);
402 int h = tabular.getAscentOfRow(row) + tabular.getDescentOfRow(row)-1;
403 pain.fillRectangle(x, y - tabular.getAscentOfRow(row) + 1,
404 w, h, LColor::selection);
409 string const InsetTabular::editMessage() const
411 return _("Opened table");
415 void InsetTabular::insetUnlock(BufferView * bv)
417 if (the_locking_inset) {
418 the_locking_inset->insetUnlock(bv);
419 updateLocal(bv, CELL);
420 the_locking_inset = 0;
425 if (scroll(false) || hasSelection()) {
430 updateLocal(bv, FULL);
435 void InsetTabular::updateLocal(BufferView * bv, UpdateCodes what) const
437 lyxerr << "InsetTabular::updateLocal: " << what << "\n";
438 if (!locked && what == CELL)
440 if (need_update < what) // only set this if it has greater update
443 if (need_update != NONE) {
444 bv->updateInset(const_cast<InsetTabular *>(this));
451 bool InsetTabular::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
453 lyxerr[Debug::INSETTEXT] << "InsetTabular::LockInsetInInset("
458 if (inset == &tabular.getCellInset(actcell)) {
459 lyxerr[Debug::INSETTEXT] << "OK" << endl;
460 the_locking_inset = &tabular.getCellInset(actcell);
463 } else if (!the_locking_inset) {
464 int const n = tabular.getNumberOfCells();
465 int const id = inset->id();
466 for (int i = 0; i < n; ++i) {
467 InsetText * in = &tabular.getCellInset(i);
470 the_locking_inset = in;
475 if (in->getInsetFromID(id)) {
477 in->localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
478 return the_locking_inset->lockInsetInInset(bv, inset);
481 } else if (the_locking_inset && (the_locking_inset == inset)) {
482 lyxerr[Debug::INSETTEXT] << "OK" << endl;
484 } else if (the_locking_inset) {
485 lyxerr[Debug::INSETTEXT] << "MAYBE" << endl;
486 return the_locking_inset->lockInsetInInset(bv, inset);
488 lyxerr[Debug::INSETTEXT] << "NOT OK" << endl;
493 bool InsetTabular::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
496 if (!the_locking_inset)
498 if (the_locking_inset == inset) {
499 the_locking_inset->insetUnlock(bv);
501 #warning fix scrolling when cellinset has requested a scroll (Jug)!!!
507 updateLocal(bv, CELL);
508 // this has to be here otherwise we don't redraw the cell!
509 the_locking_inset = 0;
512 if (the_locking_inset->unlockInsetInInset(bv, inset, lr)) {
513 if (inset->lyxCode() == TABULAR_CODE &&
514 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) {
515 InsetTabularMailer(*this).updateDialog(bv);
524 bool InsetTabular::updateInsetInInset(BufferView * bv, InsetOld * inset)
526 InsetOld * tl_inset = inset;
527 // look if this inset is really inside myself!
528 while(tl_inset->owner() && tl_inset->owner() != this)
529 tl_inset = tl_inset->owner();
530 // if we enter here it's not ower inset
531 if (!tl_inset->owner())
533 // we only have to do this if this is a subinset of our cells
534 if (tl_inset != inset) {
535 if (!static_cast<InsetText *>(tl_inset)->updateInsetInInset(bv, inset))
538 updateLocal(bv, CELL);
543 int InsetTabular::insetInInsetY() const
545 if (!the_locking_inset)
547 return inset_y + the_locking_inset->insetInInsetY();
551 UpdatableInset * InsetTabular::getLockingInset() const
553 return the_locking_inset ? the_locking_inset->getLockingInset() :
554 const_cast<InsetTabular *>(this);
558 UpdatableInset * InsetTabular::getFirstLockingInsetOfType(InsetOld::Code c)
562 if (the_locking_inset)
563 return the_locking_inset->getFirstLockingInsetOfType(c);
568 bool InsetTabular::insertInset(BufferView * bv, InsetOld * inset)
570 if (the_locking_inset)
571 return the_locking_inset->insertInset(bv, inset);
576 void InsetTabular::lfunMousePress(FuncRequest const & cmd)
578 if (hasSelection() && cmd.button() == mouse_button::button3)
581 if (hasSelection()) {
583 updateLocal(cmd.view(), FULL);
586 int const ocell = actcell;
587 int const orow = actrow;
588 BufferView * bv = cmd.view();
592 the_locking_inset = 0;
596 setPos(bv, cmd.x, cmd.y);
598 updateLocal(bv, NONE);
601 if (cmd.button() == mouse_button::button3) {
602 if ((ocell != actcell) && the_locking_inset) {
603 the_locking_inset->insetUnlock(bv);
604 updateLocal(bv, CELL);
605 the_locking_inset = 0;
611 bool const inset_hit = insetHit(bv, cmd.x, cmd.y);
613 if ((ocell == actcell) && the_locking_inset && inset_hit) {
615 FuncRequest cmd1 = cmd;
618 the_locking_inset->localDispatch(cmd1);
622 if (the_locking_inset) {
623 the_locking_inset->insetUnlock(bv);
624 updateLocal(bv, CELL);
625 the_locking_inset = 0;
628 if (cmd.button() == mouse_button::button2) {
629 localDispatch(FuncRequest(bv, LFUN_PASTESELECTION, "paragraph"));
633 if (inset_hit && bv->theLockingInset()) {
634 if (!bv->lockInset(&tabular.getCellInset(actcell))) {
635 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
638 FuncRequest cmd1 = cmd;
641 the_locking_inset->localDispatch(cmd1);
647 bool InsetTabular::lfunMouseRelease(FuncRequest const & cmd)
650 if (the_locking_inset) {
651 FuncRequest cmd1 = cmd;
654 ret = the_locking_inset->localDispatch(cmd1);
656 if (cmd.button() == mouse_button::button3 && !ret) {
657 InsetTabularMailer(*this).showDialog(cmd.view());
664 void InsetTabular::lfunMouseMotion(FuncRequest const & cmd)
666 if (the_locking_inset) {
667 FuncRequest cmd1 = cmd;
670 the_locking_inset->localDispatch(cmd1);
674 BufferView * bv = cmd.view();
675 int const old_cell = actcell;
677 setPos(bv, cmd.x, cmd.y);
678 if (!hasSelection()) {
679 setSelection(actcell, actcell);
680 updateLocal(bv, FULL);
681 } else if (old_cell != actcell) {
682 setSelection(sel_cell_start, actcell);
683 updateLocal(bv, FULL);
688 InsetOld::RESULT InsetTabular::localDispatch(FuncRequest const & cmd)
690 // We need to save the value of the_locking_inset as the call to
691 // the_locking_inset->localDispatch might unlock it.
692 old_locking_inset = the_locking_inset;
693 RESULT result = UpdatableInset::localDispatch(cmd);
694 BufferView * bv = cmd.view();
696 if (cmd.action == LFUN_INSET_EDIT) {
698 if (!bv->lockInset(this)) {
699 lyxerr[Debug::INSETTEXT] << "InsetTabular::Cannot lock inset" << endl;
705 the_locking_inset = 0;
709 if (cmd.argument.size()) {
710 if (cmd.argument == "left") {
711 if (isRightToLeft(bv))
712 actcell = tabular.getLastCellInRow(0);
716 if (isRightToLeft(bv))
717 actcell = tabular.getFirstCellInRow(tabular.rows()-1);
719 actcell = tabular.getNumberOfCells() - 1;
727 setPos(bv, cmd.x, cmd.y);
730 if (insetHit(bv, cmd.x, cmd.y) && cmd.button() != mouse_button::button3) {
731 activateCellInsetAbs(bv, cmd.x, cmd.y, cmd.button());
737 if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
742 if (cmd.action < 0 && cmd.argument.empty())
745 bool hs = hasSelection();
748 // this one have priority over the locked InsetText, if we're not already
749 // inside another tabular then that one get's priority!
750 if (getFirstLockingInsetOfType(InsetOld::TABULAR_CODE) == this) {
751 switch (cmd.action) {
752 case LFUN_MOUSE_PRESS:
756 case LFUN_MOUSE_MOTION:
757 lfunMouseMotion(cmd);
760 case LFUN_MOUSE_RELEASE:
761 return lfunMouseRelease(cmd) ? DISPATCHED : UNDISPATCHED;
763 case LFUN_CELL_BACKWARD:
764 case LFUN_CELL_FORWARD:
765 unlockInsetInInset(bv, the_locking_inset);
766 if (cmd.action == LFUN_CELL_FORWARD)
767 moveNextCell(bv, old_locking_inset != 0);
769 movePrevCell(bv, old_locking_inset != 0);
772 updateLocal(bv, FULL);
773 if (!the_locking_inset) {
774 return DISPATCHED_NOUPDATE;
777 // this to avoid compiler warnings.
783 kb_action action = cmd.action;
784 string arg = cmd.argument;
785 if (the_locking_inset) {
786 result = the_locking_inset->localDispatch(cmd);
787 if (result == DISPATCHED_NOUPDATE) {
790 if (sc != scroll()) { // inset has been scrolled
791 updateLocal(bv, FULL);
794 } else if (result == DISPATCHED) {
795 updateLocal(bv, CELL);
797 } else if (result == FINISHED_UP) {
799 // Make sure to reset status message after
800 // exiting, e.g. math inset
801 bv->owner()->clearMessage();
802 } else if (result == FINISHED_DOWN) {
804 bv->owner()->clearMessage();
805 } else if (result == FINISHED_RIGHT) {
807 bv->owner()->clearMessage();
808 } else if (result == FINISHED) {
809 bv->owner()->clearMessage();
815 // --- Cursor Movements ----------------------------------
816 case LFUN_RIGHTSEL: {
817 int const start = hasSelection() ? sel_cell_start : actcell;
818 if (tabular.isLastCellInRow(actcell)) {
819 setSelection(start, actcell);
824 // if we are starting a selection, only select
825 // the current cell at the beginning
826 if (hasSelection()) {
827 moveRight(bv, false);
830 setSelection(start, end);
831 updateLocal(bv, FULL);
835 result = moveRight(bv);
838 updateLocal(bv, FULL);
841 int const start = hasSelection() ? sel_cell_start : actcell;
842 if (tabular.isFirstCellInRow(actcell)) {
843 setSelection(start, actcell);
848 // if we are starting a selection, only select
849 // the current cell at the beginning
850 if (hasSelection()) {
854 setSelection(start, end);
855 updateLocal(bv, FULL);
859 result = moveLeft(bv);
862 updateLocal(bv, FULL);
865 int const start = hasSelection() ? sel_cell_start : actcell;
866 int const ocell = actcell;
867 // if we are starting a selection, only select
868 // the current cell at the beginning
869 if (hasSelection()) {
871 if ((ocell == sel_cell_end) ||
872 (tabular.column_of_cell(ocell)>tabular.column_of_cell(actcell)))
873 setSelection(start, tabular.getCellBelow(sel_cell_end));
875 setSelection(start, tabular.getLastCellBelow(sel_cell_end));
877 setSelection(start, start);
879 updateLocal(bv, FULL);
883 result = moveDown(bv, old_locking_inset != 0);
886 updateLocal(bv, FULL);
890 int const start = hasSelection() ? sel_cell_start : actcell;
891 int const ocell = actcell;
892 // if we are starting a selection, only select
893 // the current cell at the beginning
894 if (hasSelection()) {
896 if ((ocell == sel_cell_end) ||
897 (tabular.column_of_cell(ocell)>tabular.column_of_cell(actcell)))
898 setSelection(start, tabular.getCellAbove(sel_cell_end));
900 setSelection(start, tabular.getLastCellAbove(sel_cell_end));
902 setSelection(start, start);
904 updateLocal(bv, FULL);
908 result = moveUp(bv, old_locking_inset != 0);
911 updateLocal(bv, FULL);
914 UpdateCodes code = CURSOR;
920 unlockInsetInInset(bv, the_locking_inset);
921 if (bv->text->top_y() + bv->painter().paperHeight() <
922 (top_baseline + tabular.getHeightOfTabular()))
924 bv->scrollDocView(bv->text->top_y() + bv->painter().paperHeight());
926 actcell = tabular.getCellBelow(first_visible_cell) + column;
928 actcell = tabular.getFirstCellInRow(tabular.rows() - 1) + column;
931 updateLocal(bv, code);
935 UpdateCodes code = CURSOR;
941 unlockInsetInInset(bv, the_locking_inset);
942 if (top_baseline < 0) {
943 bv->scrollDocView(bv->text->top_y() - bv->painter().paperHeight());
945 if (top_baseline > 0)
948 actcell = tabular.getCellBelow(first_visible_cell) + column;
953 updateLocal(bv, code);
956 // none of these make sense for insettabular,
957 // but we must catch them to prevent any
958 // selection from being confused
962 case LFUN_WORDLEFTSEL:
964 case LFUN_WORDRIGHTSEL:
966 case LFUN_DOWN_PARAGRAPH:
967 case LFUN_DOWN_PARAGRAPHSEL:
968 case LFUN_UP_PARAGRAPH:
969 case LFUN_UP_PARAGRAPHSEL:
975 case LFUN_BEGINNINGBUF:
976 case LFUN_BEGINNINGBUFSEL:
980 case LFUN_LAYOUT_TABULAR: {
981 InsetTabularMailer(*this).showDialog(bv);
984 case LFUN_INSET_DIALOG_UPDATE: {
985 InsetTabularMailer(*this).updateDialog(bv);
988 case LFUN_TABULAR_FEATURE:
989 if (!tabularFeatures(bv, arg))
990 result = UNDISPATCHED;
992 // insert file functions
993 case LFUN_FILE_INSERT_ASCII_PARA:
994 case LFUN_FILE_INSERT_ASCII:
996 string tmpstr = getContentsOfAsciiFile(bv, arg, false);
999 if (insertAsciiString(bv, tmpstr, false))
1000 updateLocal(bv, INIT);
1002 result = UNDISPATCHED;
1005 // cut and paste functions
1007 if (!copySelection(bv))
1011 recordUndo(bv, Undo::DELETE);
1012 cutSelection(bv->buffer()->params);
1013 updateLocal(bv, INIT);
1016 if (!hasSelection())
1021 case LFUN_PASTESELECTION:
1023 string const clip(bv->getClipboard());
1027 if (clip.find('\t') != string::npos) {
1031 string::size_type len = clip.length();
1032 string::size_type p = 0;
1035 ((p = clip.find_first_of("\t\n", p)) != string::npos)) {
1043 maxCols = max(cols, maxCols);
1049 maxCols = max(cols, maxCols);
1050 delete paste_tabular;
1051 paste_tabular = new LyXTabular(bv->buffer()->params,
1052 this, rows, maxCols);
1053 string::size_type op = 0;
1055 int cells = paste_tabular->getNumberOfCells();
1057 while ((cell < cells) && (p < len) &&
1058 (p = clip.find_first_of("\t\n", p)) != string::npos) {
1063 paste_tabular->getCellInset(cell)->setText(clip.substr(op, p-op));
1068 paste_tabular->getCellInset(cell)->setText(clip.substr(op, p-op));
1069 while (cols++ < maxCols)
1077 // check for the last cell if there is no trailing '\n'
1078 if ((cell < cells) && (op < len))
1079 paste_tabular->getCellInset(cell)->setText(clip.substr(op, len-op));
1082 if (!insertAsciiString(bv, clip, true))
1085 // so that the clipboard is used and it goes on
1087 // and executes LFUN_PASTESELECTION in insettext!
1088 delete paste_tabular;
1093 if (hasPasteBuffer()) {
1094 recordUndo(bv, Undo::INSERT);
1096 updateLocal(bv, INIT);
1099 // ATTENTION: the function above has to be PASTE and PASTESELECTION!!!
1101 // handle font changing stuff on selection before we lock the inset
1102 // in the default part!
1103 result = UNDISPATCHED;
1114 case LFUN_UNDERLINE:
1115 case LFUN_FONT_SIZE:
1116 if (bv->dispatch(FuncRequest(bv, action, arg)))
1117 result = DISPATCHED;
1123 // we try to activate the actual inset and put this event down to
1124 // the insets dispatch function.
1125 if ((result == DISPATCHED) || the_locking_inset)
1128 if (activateCellInset(bv)) {
1129 // reset need_update setted in above function!
1131 result = the_locking_inset->localDispatch(FuncRequest(bv, action, arg));
1132 if ((result == UNDISPATCHED) || (result >= FINISHED)) {
1133 unlockInsetInInset(bv, the_locking_inset);
1135 // we need to update if this was requested before
1136 updateLocal(bv, NONE);
1137 return UNDISPATCHED;
1140 // so the below CELL is not set because this is higher
1141 // priority and we get a full redraw
1145 updateLocal(bv, CELL);
1150 if (result < FINISHED) {
1151 if (!the_locking_inset) {
1152 if (bv->fitCursor())
1153 updateLocal(bv, FULL);
1156 bv->unlockInset(this);
1161 int InsetTabular::latex(Buffer const * buf, ostream & os,
1162 LatexRunParams const & runparams) const
1164 return tabular.latex(buf, os, runparams);
1168 int InsetTabular::ascii(Buffer const * buf, ostream & os, int ll) const
1171 return tabular.ascii(buf, os, (int)parOwner()->params().depth(),
1173 return tabular.ascii(buf, os, 0, false,0);
1177 int InsetTabular::linuxdoc(Buffer const * buf, ostream & os) const
1179 return tabular.linuxdoc(buf,os);
1183 int InsetTabular::docbook(Buffer const * buf, ostream & os, bool mixcont) const
1188 // if the table is inside a float it doesn't need the informaltable
1189 // wrapper. Search for it.
1190 for(master = owner();
1191 master && master->lyxCode() != InsetOld::FLOAT_CODE;
1192 master = master->owner());
1195 os << "<informaltable>";
1200 ret+= tabular.docbook(buf, os, mixcont);
1202 os << "</informaltable>";
1211 void InsetTabular::validate(LaTeXFeatures & features) const
1213 tabular.validate(features);
1217 void InsetTabular::calculate_dimensions_of_cells(MetricsInfo & mi) const
1220 // if we have a locking_inset we should have to check only this cell for
1221 // change so I'll try this to have a boost, but who knows ;) (Jug?)
1222 // This is _really_ important (André)
1223 if (need_update != INIT &&
1224 the_locking_inset == &tabular.getCellInset(actcell)) {
1227 for (int j = 0; j < tabular.columns(); ++j) {
1231 tabular.column_info[j].p_width.inPixels(mi.base.textwidth);
1232 tabular.getCellInset(actrow, j).metrics(m, dim);
1233 maxAsc = max(dim.asc, maxAsc);
1234 maxDesc = max(dim.des, maxDesc);
1236 tabular.setWidthOfCell(actcell, the_locking_inset->width());
1237 tabular.setAscentOfRow(actrow, maxAsc + ADD_TO_HEIGHT);
1238 tabular.setDescentOfRow(actrow, maxDesc + ADD_TO_HEIGHT);
1244 bool changed = false;
1245 for (int i = 0; i < tabular.rows(); ++i) {
1248 for (int j = 0; j < tabular.columns(); ++j) {
1249 if (tabular.isPartOfMultiColumn(i, j))
1255 tabular.column_info[j].p_width.inPixels(mi.base.textwidth);
1256 tabular.getCellInset(cell).metrics(m, dim);
1257 maxAsc = max(maxAsc, dim.asc);
1258 maxDesc = max(maxDesc, dim.des);
1259 changed = tabular.setWidthOfCell(cell, dim.wid) || changed;
1261 changed = tabular.setAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
1262 changed = tabular.setDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
1265 // tabular.reinit();
1269 void InsetTabular::getCursor(BufferView & bv, int & x, int & y) const
1271 if (the_locking_inset) {
1272 the_locking_inset->getCursor(bv, x, y);
1277 y = cursory_ + InsetTabular::y();
1280 int desc = tabular.getDescentOfRow(actrow);
1282 int ascdesc = tabular.getAscentOfRow(actrow) + desc;
1284 y += ADD_TO_HEIGHT * 2;
1285 y += TEXT_TO_INSET_OFFSET;
1289 void InsetTabular::getCursorPos(BufferView * bv, int & x, int & y) const
1291 if (the_locking_inset) {
1292 the_locking_inset->getCursorPos(bv, x, y);
1295 x = cursorx_ - top_x;
1300 void InsetTabular::fitInsetCursor(BufferView * bv) const
1302 if (the_locking_inset) {
1303 int old_top_y = bv->text->top_y();
1304 the_locking_inset->fitInsetCursor(bv);
1305 if (old_top_y != bv->text->top_y())
1311 int const asc = font_metrics::maxAscent(font);
1312 int const desc = font_metrics::maxDescent(font);
1315 if (bv->fitLockedInsetCursor(cursorx_, cursory_, asc, desc))
1320 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1323 actcell = actrow = actcol = 0;
1324 int ly = tabular.getDescentOfRow(actrow);
1326 // first search the right row
1327 while (ly < y && actrow + 1 < tabular.rows()) {
1328 cursory_ += tabular.getDescentOfRow(actrow) +
1329 tabular.getAscentOfRow(actrow + 1) +
1330 tabular.getAdditionalHeight(actrow + 1);
1332 ly = cursory_ + tabular.getDescentOfRow(actrow);
1334 actcell = tabular.getCellNumber(actrow, actcol);
1336 // now search the right column
1337 int lx = tabular.getWidthOfColumn(actcell) -
1338 tabular.getAdditionalWidth(actcell);
1339 for (; !tabular.isLastCellInRow(actcell) && lx < x; ++actcell) {
1340 lx += tabular.getWidthOfColumn(actcell + 1)
1341 + tabular.getAdditionalWidth(actcell);
1343 cursorx_ = lx - tabular.getWidthOfColumn(actcell) + top_x + 2;
1348 int InsetTabular::getCellXPos(int cell) const
1352 for (; !tabular.isFirstCellInRow(c); --c)
1354 int lx = tabular.getWidthOfColumn(cell);
1355 for (; c < cell; ++c) {
1356 lx += tabular.getWidthOfColumn(c);
1358 return (lx - tabular.getWidthOfColumn(cell) + top_x);
1362 void InsetTabular::resetPos(BufferView * bv) const
1364 #ifdef WITH_WARNINGS
1365 #warning This should be fixed in the right manner (20011128 Jug)
1367 // fast hack to fix infinite repaintings!
1368 if (in_reset_pos > 0)
1372 actcol = tabular.column_of_cell(actcell);
1375 for (; cell < actcell && !tabular.isLastRow(cell); ++cell) {
1376 if (tabular.isLastCellInRow(cell)) {
1377 cursory_ += tabular.getDescentOfRow(actrow) +
1378 tabular.getAscentOfRow(actrow + 1) +
1379 tabular.getAdditionalHeight(actrow + 1);
1383 if (!locked || nodraw()) {
1384 if (the_locking_inset)
1388 // we need this only from here on!!!
1390 static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1391 int new_x = getCellXPos(actcell);
1392 int old_x = cursorx_;
1395 // cursor.x(getCellXPos(actcell) + offset);
1396 if ((actcol < tabular.columns() - 1) && scroll(false) &&
1397 (tabular.getWidthOfTabular() < bv->workWidth()-20))
1400 updateLocal(bv, FULL);
1401 } else if (the_locking_inset &&
1402 tabular.getWidthOfColumn(actcell) > bv->workWidth() - 20)
1404 int xx = cursorx_ - offset + bv->text->getRealCursorX();
1405 if (xx > (bv->workWidth()-20)) {
1406 scroll(bv, -(xx - bv->workWidth() + 60));
1407 updateLocal(bv, FULL);
1408 } else if (xx < 20) {
1414 updateLocal(bv, FULL);
1416 } else if ((cursorx_ - offset) > 20 &&
1417 (cursorx_ - offset + tabular.getWidthOfColumn(actcell))
1418 > (bv->workWidth() - 20)) {
1419 scroll(bv, -tabular.getWidthOfColumn(actcell) - 20);
1420 updateLocal(bv, FULL);
1421 } else if ((cursorx_ - offset) < 20) {
1422 scroll(bv, 20 - cursorx_ + offset);
1423 updateLocal(bv, FULL);
1424 } else if (scroll() && top_x > 20 &&
1425 (top_x + tabular.getWidthOfTabular()) > (bv->workWidth() - 20)) {
1426 scroll(bv, old_x - cursorx_);
1427 updateLocal(bv, FULL);
1429 if (the_locking_inset) {
1430 inset_x = cursorx_ - top_x + tabular.getBeginningOfTextInCell(actcell);
1433 if ((!the_locking_inset ||
1434 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) &&
1435 actcell != oldcell) {
1436 InsetTabularMailer(*this).updateDialog(bv);
1443 InsetOld::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1445 if (lock && !old_locking_inset) {
1446 if (activateCellInset(bv))
1449 bool moved = isRightToLeft(bv)
1450 ? movePrevCell(bv) : moveNextCell(bv);
1452 return FINISHED_RIGHT;
1453 if (lock && activateCellInset(bv))
1457 return DISPATCHED_NOUPDATE;
1461 InsetOld::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1463 bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
1466 if (lock) { // behind the inset
1467 if (activateCellInset(bv, 0, 0, mouse_button::none, true))
1471 return DISPATCHED_NOUPDATE;
1475 InsetOld::RESULT InsetTabular::moveUp(BufferView * bv, bool lock)
1477 int const ocell = actcell;
1478 actcell = tabular.getCellAbove(actcell);
1479 if (actcell == ocell) // we moved out of the inset
1485 if (old_locking_inset) {
1486 old_locking_inset->getCursorPos(bv, x, y);
1487 x -= cursorx_ + tabular.getBeginningOfTextInCell(actcell);
1489 if (activateCellInset(bv, x, 0))
1492 return DISPATCHED_NOUPDATE;
1496 InsetOld::RESULT InsetTabular::moveDown(BufferView * bv, bool lock)
1498 int const ocell = actcell;
1499 actcell = tabular.getCellBelow(actcell);
1500 if (actcell == ocell) // we moved out of the inset
1501 return FINISHED_DOWN;
1506 if (old_locking_inset) {
1507 old_locking_inset->getCursorPos(bv, x, y);
1508 x -= cursorx_ + tabular.getBeginningOfTextInCell(actcell);
1510 if (activateCellInset(bv, x, 0))
1513 return DISPATCHED_NOUPDATE;
1517 bool InsetTabular::moveNextCell(BufferView * bv, bool lock)
1519 if (isRightToLeft(bv)) {
1520 if (tabular.isFirstCellInRow(actcell)) {
1521 int row = tabular.row_of_cell(actcell);
1522 if (row == tabular.rows() - 1)
1524 actcell = tabular.getLastCellInRow(row);
1525 actcell = tabular.getCellBelow(actcell);
1532 if (tabular.isLastCell(actcell))
1537 bool rtl = tabular.getCellInset(actcell).paragraphs.begin()->
1538 isRightToLeftPar(bv->buffer()->params);
1539 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1546 bool InsetTabular::movePrevCell(BufferView * bv, bool lock)
1548 if (isRightToLeft(bv)) {
1549 if (tabular.isLastCellInRow(actcell)) {
1550 int row = tabular.row_of_cell(actcell);
1553 actcell = tabular.getFirstCellInRow(row);
1554 actcell = tabular.getCellAbove(actcell);
1556 if (tabular.isLastCell(actcell))
1561 if (!actcell) // first cell
1566 bool rtl = tabular.getCellInset(actcell).paragraphs.begin()->
1567 isRightToLeftPar(bv->buffer()->params);
1568 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1575 void InsetTabular::setFont(BufferView * bv, LyXFont const & font, bool tall,
1579 setSelection(0, tabular.getNumberOfCells() - 1);
1581 if (hasSelection()) {
1582 recordUndo(bv, Undo::ATOMIC);
1583 bool const frozen = undo_frozen;
1586 // apply the fontchange on the whole selection
1591 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1592 for(int i = sel_row_start; i <= sel_row_end; ++i)
1593 for(int j = sel_col_start; j <= sel_col_end; ++j)
1594 tabular.getCellInset(i, j).setFont(bv, font, tall, true);
1600 updateLocal(bv, INIT);
1602 if (the_locking_inset)
1603 the_locking_inset->setFont(bv, font, tall);
1607 bool InsetTabular::tabularFeatures(BufferView * bv, string const & what)
1609 LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1612 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
1613 string const tmp = tabularFeature[i].feature;
1615 if (tmp == what.substr(0, tmp.length())) {
1616 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
1617 //tabularFeatures[i].feature.length())) {
1618 action = tabularFeature[i].action;
1622 if (action == LyXTabular::LAST_ACTION)
1626 ltrim(what.substr(tabularFeature[i].feature.length()));
1627 tabularFeatures(bv, action, val);
1633 void checkLongtableSpecial(LyXTabular::ltType & ltt,
1634 string const & special, bool & flag)
1636 if (special == "dl_above") {
1639 } else if (special == "dl_below") {
1640 ltt.bottomDL = flag;
1642 } else if (special == "empty") {
1654 void InsetTabular::tabularFeatures(BufferView * bv,
1655 LyXTabular::Feature feature,
1656 string const & value)
1662 bool setLines = false;
1663 LyXAlignment setAlign = LYX_ALIGN_LEFT;
1664 LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1667 case LyXTabular::M_ALIGN_LEFT:
1668 case LyXTabular::ALIGN_LEFT:
1669 setAlign = LYX_ALIGN_LEFT;
1671 case LyXTabular::M_ALIGN_RIGHT:
1672 case LyXTabular::ALIGN_RIGHT:
1673 setAlign = LYX_ALIGN_RIGHT;
1675 case LyXTabular::M_ALIGN_CENTER:
1676 case LyXTabular::ALIGN_CENTER:
1677 setAlign = LYX_ALIGN_CENTER;
1679 case LyXTabular::ALIGN_BLOCK:
1680 setAlign = LYX_ALIGN_BLOCK;
1682 case LyXTabular::M_VALIGN_TOP:
1683 case LyXTabular::VALIGN_TOP:
1684 setVAlign = LyXTabular::LYX_VALIGN_TOP;
1686 case LyXTabular::M_VALIGN_BOTTOM:
1687 case LyXTabular::VALIGN_BOTTOM:
1688 setVAlign = LyXTabular::LYX_VALIGN_BOTTOM;
1690 case LyXTabular::M_VALIGN_CENTER:
1691 case LyXTabular::VALIGN_CENTER:
1692 setVAlign = LyXTabular::LYX_VALIGN_CENTER;
1697 if (hasSelection()) {
1698 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1700 sel_col_start = sel_col_end = tabular.column_of_cell(actcell);
1701 sel_row_start = sel_row_end = tabular.row_of_cell(actcell);
1703 recordUndo(bv, Undo::ATOMIC);
1705 int row = tabular.row_of_cell(actcell);
1706 int column = tabular.column_of_cell(actcell);
1708 LyXTabular::ltType ltt;
1711 case LyXTabular::SET_PWIDTH:
1713 LyXLength const vallen(value);
1714 LyXLength const & tmplen = tabular.getColumnPWidth(actcell);
1716 bool const update = (tmplen != vallen);
1717 tabular.setColumnPWidth(actcell, vallen);
1719 // We need this otherwise we won't resize
1720 // the insettext of the active cell (if any)
1721 // until later (see InsetText::do_resize)
1722 unlockInsetInInset(bv, the_locking_inset);
1724 for (int i = 0; i < tabular.rows(); ++i)
1725 tabular.getCellInset(i, column).resizeLyXText(bv);
1726 updateLocal(bv, INIT);
1730 && tabular.getAlignment(actcell, true) == LYX_ALIGN_BLOCK)
1731 tabularFeatures(bv, LyXTabular::ALIGN_CENTER, string());
1732 else if (!vallen.zero()
1733 && tabular.getAlignment(actcell, true) != LYX_ALIGN_BLOCK)
1734 tabularFeatures(bv, LyXTabular::ALIGN_BLOCK, string());
1737 case LyXTabular::SET_MPWIDTH:
1739 LyXLength const vallen(value);
1740 LyXLength const & tmplen = tabular.getPWidth(actcell);
1742 bool const update = (tmplen != vallen);
1743 tabular.setMColumnPWidth(actcell, vallen);
1745 // We need this otherwise we won't resize
1746 // the insettext of the active cell (if any)
1747 // until later (see InsetText::do_resize)
1748 unlockInsetInInset(bv, the_locking_inset);
1750 for (int i = 0; i < tabular.rows(); ++i)
1751 tabular.getCellInset(i, column).resizeLyXText(bv);
1753 updateLocal(bv, INIT);
1757 case LyXTabular::SET_SPECIAL_COLUMN:
1758 case LyXTabular::SET_SPECIAL_MULTI:
1759 tabular.setAlignSpecial(actcell,value,feature);
1760 updateLocal(bv, FULL);
1762 case LyXTabular::APPEND_ROW:
1763 // append the row into the tabular
1764 unlockInsetInInset(bv, the_locking_inset);
1765 tabular.appendRow(bv->buffer()->params, actcell);
1766 updateLocal(bv, INIT);
1768 case LyXTabular::APPEND_COLUMN:
1769 // append the column into the tabular
1770 unlockInsetInInset(bv, the_locking_inset);
1771 tabular.appendColumn(bv->buffer()->params, actcell);
1772 actcell = tabular.getCellNumber(row, column);
1773 updateLocal(bv, INIT);
1775 case LyXTabular::DELETE_ROW:
1776 unlockInsetInInset(bv, the_locking_inset);
1777 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1778 tabular.deleteRow(sel_row_start);
1780 if (sel_row_start >= tabular.rows())
1782 actcell = tabular.getCellNumber(sel_row_start, column);
1784 updateLocal(bv, INIT);
1786 case LyXTabular::DELETE_COLUMN:
1787 unlockInsetInInset(bv, the_locking_inset);
1788 for(int i = sel_col_start; i <= sel_col_end; ++i) {
1789 tabular.deleteColumn(sel_col_start);
1791 if (sel_col_start >= tabular.columns())
1793 actcell = tabular.getCellNumber(row, sel_col_start);
1795 updateLocal(bv, INIT);
1797 case LyXTabular::M_TOGGLE_LINE_TOP:
1799 case LyXTabular::TOGGLE_LINE_TOP:
1801 bool lineSet = !tabular.topLine(actcell, flag);
1802 for (int i = sel_row_start; i <= sel_row_end; ++i)
1803 for (int j = sel_col_start; j <= sel_col_end; ++j)
1805 tabular.getCellNumber(i, j),
1807 updateLocal(bv, INIT);
1811 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1813 case LyXTabular::TOGGLE_LINE_BOTTOM:
1815 bool lineSet = !tabular.bottomLine(actcell, flag);
1816 for (int i = sel_row_start; i <= sel_row_end; ++i)
1817 for (int j = sel_col_start; j <= sel_col_end; ++j)
1818 tabular.setBottomLine(
1819 tabular.getCellNumber(i, j),
1822 updateLocal(bv, INIT);
1826 case LyXTabular::M_TOGGLE_LINE_LEFT:
1828 case LyXTabular::TOGGLE_LINE_LEFT:
1830 bool lineSet = !tabular.leftLine(actcell, flag);
1831 for (int i = sel_row_start; i <= sel_row_end; ++i)
1832 for (int j = sel_col_start; j <= sel_col_end; ++j)
1833 tabular.setLeftLine(
1834 tabular.getCellNumber(i,j),
1837 updateLocal(bv, INIT);
1841 case LyXTabular::M_TOGGLE_LINE_RIGHT:
1843 case LyXTabular::TOGGLE_LINE_RIGHT:
1845 bool lineSet = !tabular.rightLine(actcell, flag);
1846 for (int i = sel_row_start; i <= sel_row_end; ++i)
1847 for (int j = sel_col_start; j <= sel_col_end; ++j)
1848 tabular.setRightLine(
1849 tabular.getCellNumber(i,j),
1852 updateLocal(bv, INIT);
1856 case LyXTabular::M_ALIGN_LEFT:
1857 case LyXTabular::M_ALIGN_RIGHT:
1858 case LyXTabular::M_ALIGN_CENTER:
1860 case LyXTabular::ALIGN_LEFT:
1861 case LyXTabular::ALIGN_RIGHT:
1862 case LyXTabular::ALIGN_CENTER:
1863 case LyXTabular::ALIGN_BLOCK:
1864 for (int i = sel_row_start; i <= sel_row_end; ++i)
1865 for (int j = sel_col_start; j <= sel_col_end; ++j)
1866 tabular.setAlignment(
1867 tabular.getCellNumber(i, j),
1870 updateLocal(bv, INIT);
1872 case LyXTabular::M_VALIGN_TOP:
1873 case LyXTabular::M_VALIGN_BOTTOM:
1874 case LyXTabular::M_VALIGN_CENTER:
1876 case LyXTabular::VALIGN_TOP:
1877 case LyXTabular::VALIGN_BOTTOM:
1878 case LyXTabular::VALIGN_CENTER:
1879 for (int i = sel_row_start; i <= sel_row_end; ++i)
1880 for (int j = sel_col_start; j <= sel_col_end; ++j)
1881 tabular.setVAlignment(
1882 tabular.getCellNumber(i, j),
1884 updateLocal(bv, INIT);
1886 case LyXTabular::MULTICOLUMN:
1888 if (sel_row_start != sel_row_end) {
1889 #ifdef WITH_WARNINGS
1890 #warning Need I say it ? This is horrible.
1892 Alert::error(_("Error setting multicolumn"),
1893 _("You cannot set multicolumn vertically."));
1896 // just multicol for one Single Cell
1897 if (!hasSelection()) {
1898 // check wether we are completly in a multicol
1899 if (tabular.isMultiColumn(actcell)) {
1900 tabular.unsetMultiColumn(actcell);
1901 updateLocal(bv, INIT);
1903 tabular.setMultiColumn(bv->buffer(), actcell, 1);
1904 updateLocal(bv, CELL);
1908 // we have a selection so this means we just add all this
1909 // cells to form a multicolumn cell
1913 if (sel_cell_start > sel_cell_end) {
1914 s_start = sel_cell_end;
1915 s_end = sel_cell_start;
1917 s_start = sel_cell_start;
1918 s_end = sel_cell_end;
1920 tabular.setMultiColumn(bv->buffer(), s_start, s_end - s_start + 1);
1923 updateLocal(bv, INIT);
1926 case LyXTabular::SET_ALL_LINES:
1928 case LyXTabular::UNSET_ALL_LINES:
1929 for (int i = sel_row_start; i <= sel_row_end; ++i)
1930 for (int j = sel_col_start; j <= sel_col_end; ++j)
1931 tabular.setAllLines(
1932 tabular.getCellNumber(i,j), setLines);
1933 updateLocal(bv, INIT);
1935 case LyXTabular::SET_LONGTABULAR:
1936 tabular.setLongTabular(true);
1937 updateLocal(bv, INIT); // because this toggles displayed
1939 case LyXTabular::UNSET_LONGTABULAR:
1940 tabular.setLongTabular(false);
1941 updateLocal(bv, INIT); // because this toggles displayed
1943 case LyXTabular::SET_ROTATE_TABULAR:
1944 tabular.setRotateTabular(true);
1946 case LyXTabular::UNSET_ROTATE_TABULAR:
1947 tabular.setRotateTabular(false);
1949 case LyXTabular::SET_ROTATE_CELL:
1950 for (int i = sel_row_start; i <= sel_row_end; ++i)
1951 for (int j = sel_col_start; j<=sel_col_end; ++j)
1952 tabular.setRotateCell(
1953 tabular.getCellNumber(i, j),
1956 case LyXTabular::UNSET_ROTATE_CELL:
1957 for (int i = sel_row_start; i <= sel_row_end; ++i)
1958 for (int j = sel_col_start; j <= sel_col_end; ++j)
1959 tabular.setRotateCell(
1960 tabular.getCellNumber(i, j), false);
1962 case LyXTabular::SET_USEBOX:
1964 LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
1965 if (val == tabular.getUsebox(actcell))
1966 val = LyXTabular::BOX_NONE;
1967 for (int i = sel_row_start; i <= sel_row_end; ++i)
1968 for (int j = sel_col_start; j <= sel_col_end; ++j)
1970 tabular.getCellNumber(i, j), val);
1973 case LyXTabular::UNSET_LTFIRSTHEAD:
1975 case LyXTabular::SET_LTFIRSTHEAD:
1976 tabular.getRowOfLTFirstHead(row, ltt);
1977 checkLongtableSpecial(ltt, value, flag);
1978 tabular.setLTHead(row, flag, ltt, true);
1980 case LyXTabular::UNSET_LTHEAD:
1982 case LyXTabular::SET_LTHEAD:
1983 tabular.getRowOfLTHead(row, ltt);
1984 checkLongtableSpecial(ltt, value, flag);
1985 tabular.setLTHead(row, flag, ltt, false);
1987 case LyXTabular::UNSET_LTFOOT:
1989 case LyXTabular::SET_LTFOOT:
1990 tabular.getRowOfLTFoot(row, ltt);
1991 checkLongtableSpecial(ltt, value, flag);
1992 tabular.setLTFoot(row, flag, ltt, false);
1994 case LyXTabular::UNSET_LTLASTFOOT:
1996 case LyXTabular::SET_LTLASTFOOT:
1997 tabular.getRowOfLTLastFoot(row, ltt);
1998 checkLongtableSpecial(ltt, value, flag);
1999 tabular.setLTFoot(row, flag, ltt, true);
2001 case LyXTabular::SET_LTNEWPAGE:
2003 bool what = !tabular.getLTNewPage(row);
2004 tabular.setLTNewPage(row, what);
2007 // dummy stuff just to avoid warnings
2008 case LyXTabular::LAST_ACTION:
2012 InsetTabularMailer(*this).updateDialog(bv);
2016 bool InsetTabular::activateCellInset(BufferView * bv, int x, int y,
2017 mouse_button::state button, bool behind)
2019 UpdatableInset & inset = tabular.getCellInset(actcell);
2022 x = inset.x() + inset.width();
2023 y = inset.descent();
2025 //inset_x = cursorx_ - top_x + tabular.getBeginningOfTextInCell(actcell);
2026 //inset_y = cursory_;
2027 inset.localDispatch(FuncRequest(bv, LFUN_INSET_EDIT, x, y, button));
2028 if (!the_locking_inset)
2030 updateLocal(bv, CELL);
2031 return (the_locking_inset != 0);
2035 bool InsetTabular::activateCellInsetAbs(BufferView * bv, int x, int y,
2036 mouse_button::state button)
2038 inset_x = cursorx_ - top_x + tabular.getBeginningOfTextInCell(actcell);
2040 return activateCellInset(bv, x - inset_x, y - inset_y, button);
2044 bool InsetTabular::insetHit(BufferView *, int x, int) const
2047 > cursorx_ + tabular.getBeginningOfTextInCell(actcell);
2051 void InsetTabular::deleteLyXText(BufferView * bv, bool recursive) const
2053 resizeLyXText(bv, recursive);
2057 void InsetTabular::resizeLyXText(BufferView * bv, bool force) const
2060 for(int i = 0; i < tabular.rows(); ++i)
2061 for(int j = 0; j < tabular.columns(); ++j)
2062 tabular.getCellInset(i, j).resizeLyXText(bv, true);
2067 LyXText * InsetTabular::getLyXText(BufferView const * bv,
2068 bool const recursive) const
2070 if (the_locking_inset)
2071 return the_locking_inset->getLyXText(bv, recursive);
2072 return InsetOld::getLyXText(bv, recursive);
2076 bool InsetTabular::showInsetDialog(BufferView * bv) const
2078 if (!the_locking_inset || !the_locking_inset->showInsetDialog(bv))
2079 InsetTabularMailer(*this).showDialog(bv);
2084 void InsetTabular::openLayoutDialog(BufferView * bv) const
2086 if (the_locking_inset) {
2087 InsetTabular * inset = static_cast<InsetTabular *>
2088 (the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE));
2090 inset->openLayoutDialog(bv);
2094 InsetTabularMailer(*this).showDialog(bv);
2099 // function returns an object as defined in func_status.h:
2100 // states OK, Unknown, Disabled, On, Off.
2102 FuncStatus InsetTabular::getStatus(string const & what) const
2104 int action = LyXTabular::LAST_ACTION;
2108 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
2109 string const tmp = tabularFeature[i].feature;
2110 if (tmp == what.substr(0, tmp.length())) {
2111 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
2112 // tabularFeatures[i].feature.length())) {
2113 action = tabularFeature[i].action;
2117 if (action == LyXTabular::LAST_ACTION) {
2119 return status.unknown(true);
2122 string const argument = ltrim(what.substr(tabularFeature[i].feature.length()));
2127 LyXTabular::ltType dummyltt;
2130 if (hasSelection()) {
2131 getSelection(sel_row_start, sel_row_end, dummy, dummy);
2133 sel_row_start = sel_row_end = tabular.row_of_cell(actcell);
2137 case LyXTabular::SET_PWIDTH:
2138 case LyXTabular::SET_MPWIDTH:
2139 case LyXTabular::SET_SPECIAL_COLUMN:
2140 case LyXTabular::SET_SPECIAL_MULTI:
2141 case LyXTabular::APPEND_ROW:
2142 case LyXTabular::APPEND_COLUMN:
2143 case LyXTabular::DELETE_ROW:
2144 case LyXTabular::DELETE_COLUMN:
2145 case LyXTabular::SET_ALL_LINES:
2146 case LyXTabular::UNSET_ALL_LINES:
2147 return status.clear();
2149 case LyXTabular::MULTICOLUMN:
2150 status.setOnOff(tabular.isMultiColumn(actcell));
2152 case LyXTabular::M_TOGGLE_LINE_TOP:
2154 case LyXTabular::TOGGLE_LINE_TOP:
2155 status.setOnOff(tabular.topLine(actcell, flag));
2157 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
2159 case LyXTabular::TOGGLE_LINE_BOTTOM:
2160 status.setOnOff(tabular.bottomLine(actcell, flag));
2162 case LyXTabular::M_TOGGLE_LINE_LEFT:
2164 case LyXTabular::TOGGLE_LINE_LEFT:
2165 status.setOnOff(tabular.leftLine(actcell, flag));
2167 case LyXTabular::M_TOGGLE_LINE_RIGHT:
2169 case LyXTabular::TOGGLE_LINE_RIGHT:
2170 status.setOnOff(tabular.rightLine(actcell, flag));
2172 case LyXTabular::M_ALIGN_LEFT:
2174 case LyXTabular::ALIGN_LEFT:
2175 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_LEFT);
2177 case LyXTabular::M_ALIGN_RIGHT:
2179 case LyXTabular::ALIGN_RIGHT:
2180 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_RIGHT);
2182 case LyXTabular::M_ALIGN_CENTER:
2184 case LyXTabular::ALIGN_CENTER:
2185 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_CENTER);
2187 case LyXTabular::ALIGN_BLOCK:
2188 status.disabled(tabular.getPWidth(actcell).zero());
2189 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_BLOCK);
2191 case LyXTabular::M_VALIGN_TOP:
2193 case LyXTabular::VALIGN_TOP:
2194 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP);
2196 case LyXTabular::M_VALIGN_BOTTOM:
2198 case LyXTabular::VALIGN_BOTTOM:
2199 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM);
2201 case LyXTabular::M_VALIGN_CENTER:
2203 case LyXTabular::VALIGN_CENTER:
2204 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER);
2206 case LyXTabular::SET_LONGTABULAR:
2207 status.setOnOff(tabular.isLongTabular());
2209 case LyXTabular::UNSET_LONGTABULAR:
2210 status.setOnOff(!tabular.isLongTabular());
2212 case LyXTabular::SET_ROTATE_TABULAR:
2213 status.setOnOff(tabular.getRotateTabular());
2215 case LyXTabular::UNSET_ROTATE_TABULAR:
2216 status.setOnOff(!tabular.getRotateTabular());
2218 case LyXTabular::SET_ROTATE_CELL:
2219 status.setOnOff(tabular.getRotateCell(actcell));
2221 case LyXTabular::UNSET_ROTATE_CELL:
2222 status.setOnOff(!tabular.getRotateCell(actcell));
2224 case LyXTabular::SET_USEBOX:
2225 status.setOnOff(strToInt(argument) == tabular.getUsebox(actcell));
2227 case LyXTabular::SET_LTFIRSTHEAD:
2228 status.setOnOff(tabular.getRowOfLTHead(sel_row_start, dummyltt));
2230 case LyXTabular::SET_LTHEAD:
2231 status.setOnOff(tabular.getRowOfLTHead(sel_row_start, dummyltt));
2233 case LyXTabular::SET_LTFOOT:
2234 status.setOnOff(tabular.getRowOfLTFoot(sel_row_start, dummyltt));
2236 case LyXTabular::SET_LTLASTFOOT:
2237 status.setOnOff(tabular.getRowOfLTFoot(sel_row_start, dummyltt));
2239 case LyXTabular::SET_LTNEWPAGE:
2240 status.setOnOff(tabular.getLTNewPage(sel_row_start));
2244 status.disabled(true);
2251 void InsetTabular::getLabelList(std::vector<string> & list) const
2253 tabular.getLabelList(list);
2257 bool InsetTabular::copySelection(BufferView * bv)
2259 if (!hasSelection())
2262 int sel_col_start = tabular.column_of_cell(sel_cell_start);
2263 int sel_col_end = tabular.column_of_cell(sel_cell_end);
2264 if (sel_col_start > sel_col_end) {
2265 sel_col_start = sel_col_end;
2266 sel_col_end = tabular.right_column_of_cell(sel_cell_start);
2268 sel_col_end = tabular.right_column_of_cell(sel_cell_end);
2270 int const columns = sel_col_end - sel_col_start + 1;
2272 int sel_row_start = tabular.row_of_cell(sel_cell_start);
2273 int sel_row_end = tabular.row_of_cell(sel_cell_end);
2274 if (sel_row_start > sel_row_end) {
2275 swap(sel_row_start, sel_row_end);
2277 int const rows = sel_row_end - sel_row_start + 1;
2279 delete paste_tabular;
2280 paste_tabular = new LyXTabular(bv->buffer()->params,
2281 this, tabular); // rows, columns);
2282 for (int i = 0; i < sel_row_start; ++i)
2283 paste_tabular->deleteRow(0);
2284 while (paste_tabular->rows() > rows)
2285 paste_tabular->deleteRow(rows);
2286 paste_tabular->setTopLine(0, true, true);
2287 paste_tabular->setBottomLine(paste_tabular->getFirstCellInRow(rows - 1),
2289 for (int i = 0; i < sel_col_start; ++i)
2290 paste_tabular->deleteColumn(0);
2291 while (paste_tabular->columns() > columns)
2292 paste_tabular->deleteColumn(columns);
2293 paste_tabular->setLeftLine(0, true, true);
2294 paste_tabular->setRightLine(paste_tabular->getLastCellInRow(0),
2298 paste_tabular->ascii(bv->buffer(), sstr,
2299 (int)parOwner()->params().depth(), true, '\t');
2300 bv->stuffClipboard(STRCONV(sstr.str()));
2305 bool InsetTabular::pasteSelection(BufferView * bv)
2310 for (int r1 = 0, r2 = actrow;
2311 r1 < paste_tabular->rows() && r2 < tabular.rows();
2313 for (int c1 = 0, c2 = actcol;
2314 c1 < paste_tabular->columns() && c2 < tabular.columns();
2316 if (paste_tabular->isPartOfMultiColumn(r1, c1) &&
2317 tabular.isPartOfMultiColumn(r2, c2))
2319 if (paste_tabular->isPartOfMultiColumn(r1, c1)) {
2323 if (tabular.isPartOfMultiColumn(r2, c2)) {
2327 InsetText & inset = tabular.getCellInset(r2, c2);
2328 inset = paste_tabular->getCellInset(r1, c1);
2329 inset.setOwner(this);
2330 inset.deleteLyXText(bv);
2338 bool InsetTabular::cutSelection(BufferParams const & bp)
2340 if (!hasSelection())
2343 int sel_col_start = tabular.column_of_cell(sel_cell_start);
2344 int sel_col_end = tabular.column_of_cell(sel_cell_end);
2345 if (sel_col_start > sel_col_end) {
2346 sel_col_start = sel_col_end;
2347 sel_col_end = tabular.right_column_of_cell(sel_cell_start);
2349 sel_col_end = tabular.right_column_of_cell(sel_cell_end);
2351 int sel_row_start = tabular.row_of_cell(sel_cell_start);
2352 int sel_row_end = tabular.row_of_cell(sel_cell_end);
2353 if (sel_row_start > sel_row_end) {
2354 swap(sel_row_start, sel_row_end);
2356 if (sel_cell_start > sel_cell_end) {
2357 swap(sel_cell_start, sel_cell_end);
2359 for (int i = sel_row_start; i <= sel_row_end; ++i)
2360 for (int j = sel_col_start; j <= sel_col_end; ++j)
2361 tabular.getCellInset(tabular.getCellNumber(i, j)).clear(bp.tracking_changes);
2366 bool InsetTabular::isRightToLeft(BufferView * bv)
2368 return bv->getParentLanguage(this)->RightToLeft();
2372 bool InsetTabular::nodraw() const
2374 if (!UpdatableInset::nodraw() && the_locking_inset)
2375 return the_locking_inset->nodraw();
2376 return UpdatableInset::nodraw();
2380 int InsetTabular::scroll(bool recursive) const
2382 int sx = UpdatableInset::scroll(false);
2384 if (recursive && the_locking_inset)
2385 sx += the_locking_inset->scroll(recursive);
2391 void InsetTabular::getSelection(int & srow, int & erow,
2392 int & scol, int & ecol) const
2394 int const start = hasSelection() ? sel_cell_start : actcell;
2395 int const end = hasSelection() ? sel_cell_end : actcell;
2397 srow = tabular.row_of_cell(start);
2398 erow = tabular.row_of_cell(end);
2403 scol = tabular.column_of_cell(start);
2404 ecol = tabular.column_of_cell(end);
2408 ecol = tabular.right_column_of_cell(end);
2413 ParagraphList * InsetTabular::getParagraphs(int i) const
2415 return (i < tabular.getNumberOfCells())
2416 ? tabular.getCellInset(i).getParagraphs(0)
2421 LyXCursor const & InsetTabular::cursor(BufferView * bv) const
2423 if (the_locking_inset)
2424 return the_locking_inset->cursor(bv);
2425 return InsetOld::cursor(bv);
2429 InsetOld * InsetTabular::getInsetFromID(int id_arg) const
2432 return const_cast<InsetTabular *>(this);
2434 for (int i = 0; i < tabular.rows(); ++i) {
2435 for (int j = 0; j < tabular.columns(); ++j) {
2436 InsetOld * inset = tabular.getCellInset(i, j).getInsetFromID(id_arg);
2446 InsetTabular::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2449 if (the_locking_inset) {
2450 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2451 if (!word.word().empty()) {
2455 if (tabular.isLastCell(actcell)) {
2456 bv->unlockInset(const_cast<InsetTabular *>(this));
2458 return WordLangTuple();
2462 // otherwise we have to lock the next inset and ask for it's selecttion
2463 tabular.getCellInset(actcell)
2464 .localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
2465 WordLangTuple word(selectNextWordInt(bv, value));
2467 if (!word.word().empty())
2473 WordLangTuple InsetTabular::selectNextWordInt(BufferView * bv, float & value) const
2475 // when entering this function the inset should be ALWAYS locked!
2476 Assert(the_locking_inset);
2478 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2479 if (!word.word().empty())
2482 if (tabular.isLastCell(actcell)) {
2483 bv->unlockInset(const_cast<InsetTabular *>(this));
2484 return WordLangTuple();
2487 // otherwise we have to lock the next inset and ask for it's selecttion
2489 tabular.getCellInset(actcell)
2490 .localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
2491 return selectNextWordInt(bv, value);
2495 void InsetTabular::selectSelectedWord(BufferView * bv)
2497 if (the_locking_inset)
2498 the_locking_inset->selectSelectedWord(bv);
2502 void InsetTabular::toggleSelection(BufferView * bv, bool kill_selection)
2504 if (the_locking_inset)
2505 the_locking_inset->toggleSelection(bv, kill_selection);
2509 void InsetTabular::markErased()
2511 for (int cell = 0; cell < tabular.getNumberOfCells(); ++cell)
2512 tabular.getCellInset(cell).markErased();
2516 bool InsetTabular::nextChange(BufferView * bv, lyx::pos_type & length)
2518 if (the_locking_inset) {
2519 if (the_locking_inset->nextChange(bv, length)) {
2520 updateLocal(bv, CELL);
2523 if (tabular.isLastCell(actcell))
2527 InsetText & inset = tabular.getCellInset(actcell);
2528 if (inset.nextChange(bv, length)) {
2529 updateLocal(bv, FULL);
2532 while (!tabular.isLastCell(actcell)) {
2534 InsetText & inset = tabular.getCellInset(actcell);
2535 if (inset.nextChange(bv, length)) {
2536 updateLocal(bv, FULL);
2544 bool InsetTabular::searchForward(BufferView * bv, string const & str,
2548 if (the_locking_inset) {
2549 if (the_locking_inset->searchForward(bv, str, cs, mw)) {
2550 updateLocal(bv, CELL);
2553 if (tabular.isLastCell(actcell))
2557 InsetText & inset = tabular.getCellInset(cell);
2558 if (inset.searchForward(bv, str, cs, mw)) {
2559 updateLocal(bv, FULL);
2562 while (!tabular.isLastCell(cell)) {
2564 InsetText & inset = tabular.getCellInset(cell);
2565 if (inset.searchForward(bv, str, cs, mw)) {
2566 updateLocal(bv, FULL);
2574 bool InsetTabular::searchBackward(BufferView * bv, string const & str,
2577 int cell = tabular.getNumberOfCells();
2578 if (the_locking_inset) {
2579 if (the_locking_inset->searchBackward(bv, str, cs, mw)) {
2580 updateLocal(bv, CELL);
2588 InsetText & inset = tabular.getCellInset(cell);
2589 if (inset.searchBackward(bv, str, cs, mw)) {
2590 updateLocal(bv, CELL);
2598 bool InsetTabular::insetAllowed(InsetOld::Code code) const
2600 if (the_locking_inset)
2601 return the_locking_inset->insetAllowed(code);
2602 // we return true here because if the inset is not locked someone
2603 // wants to insert something in one of our insettexts and we generally
2609 bool InsetTabular::forceDefaultParagraphs(InsetOld const * in) const
2611 const int cell = tabular.getCellFromInset(in, actcell);
2614 return tabular.getPWidth(cell).zero();
2616 // well we didn't obviously find it so maybe our owner knows more
2618 return owner()->forceDefaultParagraphs(in);
2620 // if we're here there is really something strange going on!!!
2621 lyxerr << "if we're here there is really something strange going on!\n";
2626 bool InsetTabular::insertAsciiString(BufferView * bv, string const & buf,
2629 if (buf.length() <= 0)
2635 string::size_type len = buf.length();
2636 string::size_type p = 0;
2639 ((p = buf.find_first_of("\t\n", p)) != string::npos))
2648 maxCols = max(cols, maxCols);
2654 maxCols = max(cols, maxCols);
2655 LyXTabular * loctab;
2660 delete paste_tabular;
2661 paste_tabular = new LyXTabular(bv->buffer()->params,
2662 this, rows, maxCols);
2663 loctab = paste_tabular;
2672 string::size_type op = 0;
2673 int cells = loctab->getNumberOfCells();
2676 rows = loctab->rows();
2677 int const columns = loctab->columns();
2679 while (cell < cells && p < len && row < rows &&
2680 (p = buf.find_first_of("\t\n", p)) != string::npos)
2686 // we can only set this if we are not too far right
2687 if (cols < columns) {
2688 InsetText & inset = loctab->getCellInset(cell);
2689 LyXFont const font = inset.getLyXText(bv)->
2690 getFont(inset.paragraphs.begin(), 0);
2691 inset.setText(buf.substr(op, p - op), font);
2697 // we can only set this if we are not too far right
2698 if (cols < columns) {
2699 InsetText & inset = tabular.getCellInset(cell);
2700 LyXFont const font = inset.getLyXText(bv)->
2701 getFont(inset.paragraphs.begin(), 0);
2702 inset.setText(buf.substr(op, p - op), font);
2707 cell = loctab->getCellNumber(row, cols);
2713 // check for the last cell if there is no trailing '\n'
2714 if (cell < cells && op < len) {
2715 InsetText & inset = loctab->getCellInset(cell);
2716 LyXFont const font = inset.getLyXText(bv)->
2717 getFont(inset.paragraphs.begin(), 0);
2718 inset.setText(buf.substr(op, len - op), font);
2725 void InsetTabular::addPreview(PreviewLoader & loader) const
2727 int const rows = tabular.rows();
2728 int const columns = tabular.columns();
2729 for (int i = 0; i < rows; ++i)
2730 for (int j = 0; j < columns; ++j)
2731 tabular.getCellInset(i, j).addPreview(loader);
2735 string const InsetTabularMailer::name_("tabular");
2737 InsetTabularMailer::InsetTabularMailer(InsetTabular const & inset)
2738 : inset_(const_cast<InsetTabular &>(inset))
2742 string const InsetTabularMailer::inset2string(Buffer const &) const
2744 return params2string(inset_);
2748 int InsetTabularMailer::string2params(string const & in, InsetTabular & inset)
2750 istringstream data(STRCONV(in));
2752 lex.setStream(data);
2754 #warning CHECK verify that this is a sane value to return.
2760 string const token = lex.getString();
2768 string const token = lex.getString();
2769 if (token != "\\active_cell")
2772 cell = lex.getInteger();
2775 // This is part of the inset proper that is usually swallowed
2776 // by Buffer::readInset
2779 string const token = lex.getString();
2780 if (token != "Tabular")
2787 Buffer const * const buffer = inset.buffer();
2789 inset.read(buffer, lex);
2791 // We can't set the active cell, but we can tell the frontend
2797 string const InsetTabularMailer::params2string(InsetTabular const & inset)
2799 Buffer const * const buffer = inset.buffer();
2804 data << name_ << " \\active_cell " << inset.getActCell() << '\n';
2805 inset.write(buffer, data);
2806 data << "\\end_inset\n";
2807 return STRCONV(data.str());