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"
52 using namespace lyx::support;
62 namespace grfx = 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)),
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),
181 the_locking_inset = 0;
182 old_locking_inset = 0;
185 actrow = actcell = 0;
194 InsetTabular::~InsetTabular()
196 InsetTabularMailer mailer(*this);
201 InsetBase * InsetTabular::clone() const
203 return new InsetTabular(*this);
207 Buffer const * InsetTabular::buffer() const
213 BufferView * InsetTabular::view() const
220 void InsetTabular::buffer(Buffer * b)
226 void InsetTabular::write(Buffer const * buf, ostream & os) const
228 os << " Tabular" << endl;
229 tabular.write(buf, os);
233 void InsetTabular::read(Buffer const * buf, LyXLex & lex)
235 bool const old_format = (lex.getString() == "\\LyXTable");
237 tabular.read(buf, lex);
245 string token = lex.getString();
246 while (lex.isOK() && (token != "\\end_inset")) {
248 token = lex.getString();
250 if (token != "\\end_inset") {
251 lex.printError("Missing \\end_inset at this point. "
257 void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
259 //lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " <<
260 // mi.base.textwidth << "\n";
262 lyxerr << "InsetTabular::metrics: need bv\n";
266 calculate_dimensions_of_cells(mi.base.bv);
267 //lyxerr << "InsetTabular::metrics, bv: " << mi.base.bv << endl;
268 for (int i = 0; i < tabular.getNumberOfCells(); ++i) {
269 LyXTabular::cellstruct * ci = tabular.cellinfo_of_cell(i);
270 int col = tabular.column_of_cell(i);
271 InsetText & cell = ci->inset;
272 cell.text_.bv_owner = mi.base.bv;
273 int wid = tabular.column_info[col].p_width.inPixels(mi.base.textwidth);
274 //lyxerr << " " << i << " - " << ci->width_of_cell << " - "
275 // << tabular.column_info[col].width_of_column << " - "
278 m.base.textwidth = wid;
284 dim.asc = tabular.getAscentOfRow(0);
285 dim.des = tabular.getHeightOfTabular() - tabular.getAscentOfRow(0) + 1;
286 dim.wid = tabular.getWidthOfTabular() + 2 * ADD_TO_TABULAR_WIDTH;
290 void InsetTabular::draw(PainterInfo & pi, int x, int y) const
292 lyxerr << "InsetTabular::draw: " << x << " " << y << "\n";
298 BufferView * bv = pi.base.bv;
304 UpdatableInset::draw(pi, x, y);
312 x += ADD_TO_TABULAR_WIDTH;
316 first_visible_cell = -1;
317 for (i = 0; i < tabular.rows(); ++i) {
319 cell = tabular.getCellNumber(i, 0);
320 if (!((y + tabular.getDescentOfRow(i)) > 0) &&
321 (y - tabular.getAscentOfRow(i)) < pi.pain.paperHeight())
323 y += tabular.getDescentOfRow(i) +
324 tabular.getAscentOfRow(i + 1) +
325 tabular.getAdditionalHeight(i + 1);
328 for (j = 0; j < tabular.columns(); ++j) {
329 if (nx > bv->workWidth())
331 if (tabular.isPartOfMultiColumn(i, j))
333 cx = nx + tabular.getBeginningOfTextInCell(cell);
334 if (first_visible_cell < 0)
335 first_visible_cell = cell;
336 if (hasSelection()) {
337 drawCellSelection(pi.pain, nx, y, i, j, cell);
340 tabular.getCellInset(cell)->draw(pi, cx, y);
341 drawCellLines(pi.pain, nx, y, i, cell);
342 nx += tabular.getWidthOfColumn(cell);
346 // Would be nice, but for some completely unfathomable reason,
347 // on a col resize to a new fixed width, even though the insettexts
348 // are resized, the cell isn't, but drawing all cells in a tall table
349 // has the desired effect somehow. Complete dark magic.
351 // avoiding drawing the rest of a long table is
352 // a pretty big speedup
353 if (y > bv->workHeight())
357 y += tabular.getDescentOfRow(i) +
358 tabular.getAscentOfRow(i + 1) +
359 tabular.getAdditionalHeight(i + 1);
366 void InsetTabular::drawCellLines(Painter & pain, int x, int y,
367 int row, int cell) const
369 int x2 = x + tabular.getWidthOfColumn(cell);
372 if (!tabular.topAlreadyDrawn(cell)) {
373 on_off = !tabular.topLine(cell);
374 pain.line(x, y - tabular.getAscentOfRow(row),
375 x2, y - tabular.getAscentOfRow(row),
376 on_off ? LColor::tabularonoffline : LColor::tabularline,
377 on_off ? Painter::line_onoffdash : Painter::line_solid);
379 on_off = !tabular.bottomLine(cell);
380 pain.line(x, y + tabular.getDescentOfRow(row),
381 x2, y + tabular.getDescentOfRow(row),
382 on_off ? LColor::tabularonoffline : LColor::tabularline,
383 on_off ? Painter::line_onoffdash : Painter::line_solid);
384 if (!tabular.leftAlreadyDrawn(cell)) {
385 on_off = !tabular.leftLine(cell);
386 pain.line(x, y - tabular.getAscentOfRow(row),
387 x, y + tabular.getDescentOfRow(row),
388 on_off ? LColor::tabularonoffline : LColor::tabularline,
389 on_off ? Painter::line_onoffdash : Painter::line_solid);
391 on_off = !tabular.rightLine(cell);
392 pain.line(x2 - tabular.getAdditionalWidth(cell),
393 y - tabular.getAscentOfRow(row),
394 x2 - tabular.getAdditionalWidth(cell),
395 y + tabular.getDescentOfRow(row),
396 on_off ? LColor::tabularonoffline : LColor::tabularline,
397 on_off ? Painter::line_onoffdash : Painter::line_solid);
401 void InsetTabular::drawCellSelection(Painter & pain, int x, int y,
402 int row, int column, int cell) const
404 Assert(hasSelection());
405 int cs = tabular.column_of_cell(sel_cell_start);
406 int ce = tabular.column_of_cell(sel_cell_end);
409 cs = tabular.column_of_cell(sel_cell_end);
411 ce = tabular.right_column_of_cell(sel_cell_end);
414 int rs = tabular.row_of_cell(sel_cell_start);
415 int re = tabular.row_of_cell(sel_cell_end);
419 if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
420 int w = tabular.getWidthOfColumn(cell);
421 int h = tabular.getAscentOfRow(row) + tabular.getDescentOfRow(row)-1;
422 pain.fillRectangle(x, y - tabular.getAscentOfRow(row) + 1,
423 w, h, LColor::selection);
428 string const InsetTabular::editMessage() const
430 return _("Opened table");
434 void InsetTabular::insetUnlock(BufferView * bv)
436 if (the_locking_inset) {
437 the_locking_inset->insetUnlock(bv);
438 updateLocal(bv, CELL);
439 the_locking_inset = 0;
444 if (scroll(false) || hasSelection()) {
449 updateLocal(bv, FULL);
454 void InsetTabular::updateLocal(BufferView * bv, UpdateCodes what) const
456 lyxerr << "InsetTabular::updateLocal: " << what << "\n";
458 calculate_dimensions_of_cells(bv);
460 if (!locked && what == CELL)
462 if (need_update < what) // only set this if it has greater update
465 if (need_update != NONE) {
466 bv->updateInset(const_cast<InsetTabular *>(this));
473 bool InsetTabular::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
475 lyxerr[Debug::INSETTEXT] << "InsetTabular::LockInsetInInset("
480 if (inset == tabular.getCellInset(actcell)) {
481 lyxerr[Debug::INSETTEXT] << "OK" << endl;
482 the_locking_inset = tabular.getCellInset(actcell);
485 } else if (!the_locking_inset) {
486 int const n = tabular.getNumberOfCells();
487 int const id = inset->id();
488 for (int i = 0; i < n; ++i) {
489 InsetText * in = tabular.getCellInset(i);
492 the_locking_inset = in;
497 if (in->getInsetFromID(id)) {
499 in->localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
500 return the_locking_inset->lockInsetInInset(bv, inset);
503 } else if (the_locking_inset && (the_locking_inset == inset)) {
504 lyxerr[Debug::INSETTEXT] << "OK" << endl;
506 } else if (the_locking_inset) {
507 lyxerr[Debug::INSETTEXT] << "MAYBE" << endl;
508 return the_locking_inset->lockInsetInInset(bv, inset);
510 lyxerr[Debug::INSETTEXT] << "NOT OK" << endl;
515 bool InsetTabular::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
518 if (!the_locking_inset)
520 if (the_locking_inset == inset) {
521 the_locking_inset->insetUnlock(bv);
523 #warning fix scrolling when cellinset has requested a scroll (Jug)!!!
529 updateLocal(bv, CELL);
530 // this has to be here otherwise we don't redraw the cell!
531 the_locking_inset = 0;
534 if (the_locking_inset->unlockInsetInInset(bv, inset, lr)) {
535 if (inset->lyxCode() == TABULAR_CODE &&
536 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) {
537 InsetTabularMailer mailer(*this);
538 mailer.updateDialog(bv);
547 bool InsetTabular::updateInsetInInset(BufferView * bv, Inset * inset)
549 Inset * tl_inset = inset;
550 // look if this inset is really inside myself!
551 while(tl_inset->owner() && tl_inset->owner() != this)
552 tl_inset = tl_inset->owner();
553 // if we enter here it's not ower inset
554 if (!tl_inset->owner())
556 // we only have to do this if this is a subinset of our cells
557 if (tl_inset != inset) {
558 if (!static_cast<InsetText *>(tl_inset)->updateInsetInInset(bv, inset))
561 updateLocal(bv, CELL);
566 int InsetTabular::insetInInsetY() const
568 if (!the_locking_inset)
570 return inset_y + the_locking_inset->insetInInsetY();
574 UpdatableInset * InsetTabular::getLockingInset() const
576 return the_locking_inset ? the_locking_inset->getLockingInset() :
577 const_cast<InsetTabular *>(this);
581 UpdatableInset * InsetTabular::getFirstLockingInsetOfType(Inset::Code c)
585 if (the_locking_inset)
586 return the_locking_inset->getFirstLockingInsetOfType(c);
591 bool InsetTabular::insertInset(BufferView * bv, Inset * inset)
593 if (the_locking_inset)
594 return the_locking_inset->insertInset(bv, inset);
599 void InsetTabular::lfunMousePress(FuncRequest const & cmd)
601 if (hasSelection() && cmd.button() == mouse_button::button3)
604 if (hasSelection()) {
606 updateLocal(cmd.view(), FULL);
609 int const ocell = actcell;
610 int const orow = actrow;
611 BufferView * bv = cmd.view();
615 the_locking_inset = 0;
619 setPos(bv, cmd.x, cmd.y);
621 updateLocal(bv, NONE);
624 if (cmd.button() == mouse_button::button3) {
625 if ((ocell != actcell) && the_locking_inset) {
626 the_locking_inset->insetUnlock(bv);
627 updateLocal(bv, CELL);
628 the_locking_inset = 0;
634 bool const inset_hit = insetHit(bv, cmd.x, cmd.y);
636 if ((ocell == actcell) && the_locking_inset && inset_hit) {
638 FuncRequest cmd1 = cmd;
641 the_locking_inset->localDispatch(cmd1);
645 if (the_locking_inset) {
646 the_locking_inset->insetUnlock(bv);
647 updateLocal(bv, CELL);
648 the_locking_inset = 0;
651 if (cmd.button() == mouse_button::button2) {
652 localDispatch(FuncRequest(bv, LFUN_PASTESELECTION, "paragraph"));
656 if (inset_hit && bv->theLockingInset()) {
657 if (!bv->lockInset(static_cast<UpdatableInset*>
658 (tabular.getCellInset(actcell))))
660 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
663 FuncRequest cmd1 = cmd;
666 the_locking_inset->localDispatch(cmd1);
672 bool InsetTabular::lfunMouseRelease(FuncRequest const & cmd)
675 if (the_locking_inset) {
676 FuncRequest cmd1 = cmd;
679 ret = the_locking_inset->localDispatch(cmd1);
681 if (cmd.button() == mouse_button::button3 && !ret) {
682 InsetTabularMailer(*this).showDialog(cmd.view());
689 void InsetTabular::lfunMouseMotion(FuncRequest const & cmd)
691 if (the_locking_inset) {
692 FuncRequest cmd1 = cmd;
695 the_locking_inset->localDispatch(cmd1);
699 BufferView * bv = cmd.view();
700 int const old_cell = actcell;
702 setPos(bv, cmd.x, cmd.y);
703 if (!hasSelection()) {
704 setSelection(actcell, actcell);
705 updateLocal(bv, FULL);
706 } else if (old_cell != actcell) {
707 setSelection(sel_cell_start, actcell);
708 updateLocal(bv, FULL);
713 Inset::RESULT InsetTabular::localDispatch(FuncRequest const & cmd)
715 // We need to save the value of the_locking_inset as the call to
716 // the_locking_inset->localDispatch might unlock it.
717 old_locking_inset = the_locking_inset;
718 RESULT result = UpdatableInset::localDispatch(cmd);
719 BufferView * bv = cmd.view();
721 if (cmd.action == LFUN_INSET_EDIT) {
723 if (!bv->lockInset(this)) {
724 lyxerr[Debug::INSETTEXT] << "InsetTabular::Cannot lock inset" << endl;
730 the_locking_inset = 0;
734 if (cmd.argument.size()) {
735 if (cmd.argument == "left") {
736 if (isRightToLeft(bv))
737 actcell = tabular.getLastCellInRow(0);
741 if (isRightToLeft(bv))
742 actcell = tabular.getFirstCellInRow(tabular.rows()-1);
744 actcell = tabular.getNumberOfCells() - 1;
752 setPos(bv, cmd.x, cmd.y);
755 if (insetHit(bv, cmd.x, cmd.y) && cmd.button() != mouse_button::button3) {
756 activateCellInsetAbs(bv, cmd.x, cmd.y, cmd.button());
762 if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
767 if (cmd.action < 0 && cmd.argument.empty())
770 bool hs = hasSelection();
773 // this one have priority over the locked InsetText, if we're not already
774 // inside another tabular then that one get's priority!
775 if (getFirstLockingInsetOfType(Inset::TABULAR_CODE) == this) {
776 switch (cmd.action) {
777 case LFUN_MOUSE_PRESS:
781 case LFUN_MOUSE_MOTION:
782 lfunMouseMotion(cmd);
785 case LFUN_MOUSE_RELEASE:
786 return lfunMouseRelease(cmd) ? DISPATCHED : UNDISPATCHED;
788 case LFUN_CELL_BACKWARD:
789 case LFUN_CELL_FORWARD:
790 unlockInsetInInset(bv, the_locking_inset);
791 if (cmd.action == LFUN_CELL_FORWARD)
792 moveNextCell(bv, old_locking_inset != 0);
794 movePrevCell(bv, old_locking_inset != 0);
797 updateLocal(bv, FULL);
798 if (!the_locking_inset) {
799 return DISPATCHED_NOUPDATE;
802 // this to avoid compiler warnings.
808 kb_action action = cmd.action;
809 string arg = cmd.argument;
810 if (the_locking_inset) {
811 result = the_locking_inset->localDispatch(cmd);
812 if (result == DISPATCHED_NOUPDATE) {
815 if (sc != scroll()) { // inset has been scrolled
816 updateLocal(bv, FULL);
819 } else if (result == DISPATCHED) {
820 updateLocal(bv, CELL);
822 } else if (result == FINISHED_UP) {
824 // Make sure to reset status message after
825 // exiting, e.g. math inset
826 bv->owner()->clearMessage();
827 } else if (result == FINISHED_DOWN) {
829 bv->owner()->clearMessage();
830 } else if (result == FINISHED_RIGHT) {
832 bv->owner()->clearMessage();
833 } else if (result == FINISHED) {
834 bv->owner()->clearMessage();
840 // --- Cursor Movements ----------------------------------
841 case LFUN_RIGHTSEL: {
842 int const start = hasSelection() ? sel_cell_start : actcell;
843 if (tabular.isLastCellInRow(actcell)) {
844 setSelection(start, actcell);
849 // if we are starting a selection, only select
850 // the current cell at the beginning
851 if (hasSelection()) {
852 moveRight(bv, false);
855 setSelection(start, end);
856 updateLocal(bv, FULL);
860 result = moveRight(bv);
863 updateLocal(bv, FULL);
866 int const start = hasSelection() ? sel_cell_start : actcell;
867 if (tabular.isFirstCellInRow(actcell)) {
868 setSelection(start, actcell);
873 // if we are starting a selection, only select
874 // the current cell at the beginning
875 if (hasSelection()) {
879 setSelection(start, end);
880 updateLocal(bv, FULL);
884 result = moveLeft(bv);
887 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.getCellBelow(sel_cell_end));
900 setSelection(start, tabular.getLastCellBelow(sel_cell_end));
902 setSelection(start, start);
904 updateLocal(bv, FULL);
908 result = moveDown(bv, old_locking_inset != 0);
911 updateLocal(bv, FULL);
915 int const start = hasSelection() ? sel_cell_start : actcell;
916 int const ocell = actcell;
917 // if we are starting a selection, only select
918 // the current cell at the beginning
919 if (hasSelection()) {
921 if ((ocell == sel_cell_end) ||
922 (tabular.column_of_cell(ocell)>tabular.column_of_cell(actcell)))
923 setSelection(start, tabular.getCellAbove(sel_cell_end));
925 setSelection(start, tabular.getLastCellAbove(sel_cell_end));
927 setSelection(start, start);
929 updateLocal(bv, FULL);
933 result = moveUp(bv, old_locking_inset != 0);
936 updateLocal(bv, FULL);
939 UpdateCodes code = CURSOR;
945 unlockInsetInInset(bv, the_locking_inset);
946 if (bv->text->top_y() + bv->painter().paperHeight() <
947 (top_baseline + tabular.getHeightOfTabular()))
949 bv->scrollDocView(bv->text->top_y() + bv->painter().paperHeight());
951 actcell = tabular.getCellBelow(first_visible_cell) + column;
953 actcell = tabular.getFirstCellInRow(tabular.rows() - 1) + column;
956 updateLocal(bv, code);
960 UpdateCodes code = CURSOR;
966 unlockInsetInInset(bv, the_locking_inset);
967 if (top_baseline < 0) {
968 bv->scrollDocView(bv->text->top_y() - bv->painter().paperHeight());
970 if (top_baseline > 0)
973 actcell = tabular.getCellBelow(first_visible_cell) + column;
978 updateLocal(bv, code);
981 // none of these make sense for insettabular,
982 // but we must catch them to prevent any
983 // selection from being confused
987 case LFUN_WORDLEFTSEL:
989 case LFUN_WORDRIGHTSEL:
991 case LFUN_DOWN_PARAGRAPH:
992 case LFUN_DOWN_PARAGRAPHSEL:
993 case LFUN_UP_PARAGRAPH:
994 case LFUN_UP_PARAGRAPHSEL:
1000 case LFUN_BEGINNINGBUF:
1001 case LFUN_BEGINNINGBUFSEL:
1003 case LFUN_ENDBUFSEL:
1005 case LFUN_LAYOUT_TABULAR: {
1006 InsetTabularMailer mailer(*this);
1007 mailer.showDialog(bv);
1010 case LFUN_INSET_DIALOG_UPDATE: {
1011 InsetTabularMailer mailer(*this);
1012 mailer.updateDialog(bv);
1015 case LFUN_TABULAR_FEATURE:
1016 if (!tabularFeatures(bv, arg))
1017 result = UNDISPATCHED;
1019 // insert file functions
1020 case LFUN_FILE_INSERT_ASCII_PARA:
1021 case LFUN_FILE_INSERT_ASCII:
1023 string tmpstr = getContentsOfAsciiFile(bv, arg, false);
1026 if (insertAsciiString(bv, tmpstr, false))
1027 updateLocal(bv, INIT);
1029 result = UNDISPATCHED;
1032 // cut and paste functions
1034 if (!copySelection(bv))
1038 setUndo(bv, Undo::DELETE);
1039 cutSelection(bv->buffer()->params);
1040 updateLocal(bv, INIT);
1043 if (!hasSelection())
1048 case LFUN_PASTESELECTION:
1050 string const clip(bv->getClipboard());
1054 if (clip.find('\t') != string::npos) {
1058 string::size_type len = clip.length();
1059 string::size_type p = 0;
1062 ((p = clip.find_first_of("\t\n", p)) != string::npos)) {
1070 maxCols = max(cols, maxCols);
1076 maxCols = max(cols, maxCols);
1077 delete paste_tabular;
1078 paste_tabular = new LyXTabular(bv->buffer()->params,
1079 this, rows, maxCols);
1080 string::size_type op = 0;
1082 int cells = paste_tabular->getNumberOfCells();
1084 while ((cell < cells) && (p < len) &&
1085 (p = clip.find_first_of("\t\n", p)) != string::npos) {
1090 paste_tabular->getCellInset(cell)->setText(clip.substr(op, p-op));
1095 paste_tabular->getCellInset(cell)->setText(clip.substr(op, p-op));
1096 while (cols++ < maxCols)
1104 // check for the last cell if there is no trailing '\n'
1105 if ((cell < cells) && (op < len))
1106 paste_tabular->getCellInset(cell)->setText(clip.substr(op, len-op));
1109 if (!insertAsciiString(bv, clip, true))
1112 // so that the clipboard is used and it goes on
1114 // and executes LFUN_PASTESELECTION in insettext!
1115 delete paste_tabular;
1120 if (hasPasteBuffer()) {
1121 setUndo(bv, Undo::INSERT);
1123 updateLocal(bv, INIT);
1126 // ATTENTION: the function above has to be PASTE and PASTESELECTION!!!
1128 // handle font changing stuff on selection before we lock the inset
1129 // in the default part!
1130 result = UNDISPATCHED;
1141 case LFUN_UNDERLINE:
1142 case LFUN_FONT_SIZE:
1143 if (bv->dispatch(FuncRequest(bv, action, arg)))
1144 result = DISPATCHED;
1150 // we try to activate the actual inset and put this event down to
1151 // the insets dispatch function.
1152 if ((result == DISPATCHED) || the_locking_inset)
1155 if (activateCellInset(bv)) {
1156 // reset need_update setted in above function!
1158 result = the_locking_inset->localDispatch(FuncRequest(bv, action, arg));
1159 if ((result == UNDISPATCHED) || (result >= FINISHED)) {
1160 unlockInsetInInset(bv, the_locking_inset);
1162 // we need to update if this was requested before
1163 updateLocal(bv, NONE);
1164 return UNDISPATCHED;
1167 // so the below CELL is not set because this is higher
1168 // priority and we get a full redraw
1172 updateLocal(bv, CELL);
1177 if (result < FINISHED) {
1178 if (!the_locking_inset) {
1179 if (bv->fitCursor())
1180 updateLocal(bv, FULL);
1183 bv->unlockInset(this);
1188 int InsetTabular::latex(Buffer const * buf, ostream & os,
1189 LatexRunParams const & runparams) const
1191 return tabular.latex(buf, os, runparams);
1195 int InsetTabular::ascii(Buffer const * buf, ostream & os, int ll) const
1198 return tabular.ascii(buf, os, (int)parOwner()->params().depth(),
1200 return tabular.ascii(buf, os, 0, false,0);
1204 int InsetTabular::linuxdoc(Buffer const * buf, ostream & os) const
1207 int const ret = tabular.ascii(buf,os,
1208 (int)parOwner()->params().depth(),
1215 int InsetTabular::docbook(Buffer const * buf, ostream & os, bool mixcont) const
1220 // if the table is inside a float it doesn't need the informaltable
1221 // wrapper. Search for it.
1222 for(master = owner();
1223 master && master->lyxCode() != Inset::FLOAT_CODE;
1224 master = master->owner());
1227 os << "<informaltable>";
1232 ret+= tabular.docbook(buf, os, mixcont);
1234 os << "</informaltable>";
1243 void InsetTabular::validate(LaTeXFeatures & features) const
1245 tabular.validate(features);
1249 void InsetTabular::calculate_dimensions_of_cells(BufferView * bv) const
1251 // FIXME: since InsetText ignores this anyway, it doesn't
1252 // matter what we pass it. Ugly
1255 // if we have a locking_inset we should have to check only this cell for
1256 // change so I'll try this to have a boost, but who knows ;)
1257 if (need_update != INIT &&
1258 the_locking_inset == tabular.getCellInset(actcell)) {
1261 for(int i = 0; i < tabular.columns(); ++i) {
1263 MetricsInfo mi(bv, font);
1264 tabular.getCellInset(actrow, i)->metrics(mi, dim);
1265 maxAsc = max(dim.asc, maxAsc);
1266 maxDesc = max(dim.des, maxDesc);
1268 tabular.setWidthOfCell(actcell, the_locking_inset->width(bv, font));
1269 tabular.setAscentOfRow(actrow, maxAsc + ADD_TO_HEIGHT);
1270 tabular.setDescentOfRow(actrow, maxDesc + ADD_TO_HEIGHT);
1275 bool changed = false;
1276 for (int i = 0; i < tabular.rows(); ++i) {
1279 for (int j = 0; j < tabular.columns(); ++j) {
1280 if (tabular.isPartOfMultiColumn(i, j))
1284 MetricsInfo mi(bv, font);
1285 tabular.getCellInset(cell)->metrics(mi, dim);
1286 maxAsc = max(maxAsc, dim.asc);
1287 maxDesc = max(maxDesc, dim.des);
1288 changed = tabular.setWidthOfCell(cell, dim.wid) || changed;
1290 changed = tabular.setAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
1291 changed = tabular.setDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
1298 void InsetTabular::getCursor(BufferView & bv, int & x, int & y) const
1300 if (the_locking_inset) {
1301 the_locking_inset->getCursor(bv, x, y);
1306 y = cursor_.y() + InsetTabular::y();
1309 int desc = tabular.getDescentOfRow(actrow);
1311 int ascdesc = tabular.getAscentOfRow(actrow) + desc;
1313 y += ADD_TO_HEIGHT * 2;
1314 y += TEXT_TO_INSET_OFFSET;
1318 void InsetTabular::getCursorPos(BufferView * bv, int & x, int & y) const
1320 if (the_locking_inset) {
1321 the_locking_inset->getCursorPos(bv, x, y);
1324 x = cursor_.x() - top_x;
1329 void InsetTabular::fitInsetCursor(BufferView * bv) const
1331 if (the_locking_inset) {
1332 int old_top_y = bv->text->top_y();
1333 the_locking_inset->fitInsetCursor(bv);
1334 if (old_top_y != bv->text->top_y())
1340 int const asc = font_metrics::maxAscent(font);
1341 int const desc = font_metrics::maxDescent(font);
1344 if (bv->fitLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc))
1349 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1353 actcell = actrow = actcol = 0;
1354 int ly = tabular.getDescentOfRow(actrow);
1356 // first search the right row
1357 while ((ly < y) && ((actrow+1) < tabular.rows())) {
1358 cursor_.y(cursor_.y() + tabular.getDescentOfRow(actrow) +
1359 tabular.getAscentOfRow(actrow + 1) +
1360 tabular.getAdditionalHeight(actrow + 1));
1362 ly = cursor_.y() + tabular.getDescentOfRow(actrow);
1364 actcell = tabular.getCellNumber(actrow, actcol);
1366 // now search the right column
1367 int lx = tabular.getWidthOfColumn(actcell) -
1368 tabular.getAdditionalWidth(actcell);
1369 for (; !tabular.isLastCellInRow(actcell) && lx < x; ++actcell) {
1370 lx += tabular.getWidthOfColumn(actcell + 1)
1371 + tabular.getAdditionalWidth(actcell);
1373 cursor_.x(lx - tabular.getWidthOfColumn(actcell) + top_x + 2);
1378 int InsetTabular::getCellXPos(int cell) const
1382 for (; !tabular.isFirstCellInRow(c); --c)
1384 int lx = tabular.getWidthOfColumn(cell);
1385 for (; c < cell; ++c) {
1386 lx += tabular.getWidthOfColumn(c);
1388 return (lx - tabular.getWidthOfColumn(cell) + top_x);
1392 void InsetTabular::resetPos(BufferView * bv) const
1394 #ifdef WITH_WARNINGS
1395 #warning This should be fixed in the right manner (20011128 Jug)
1397 // fast hack to fix infinite repaintings!
1398 if (in_reset_pos > 0)
1402 actcol = tabular.column_of_cell(actcell);
1405 for (; (cell < actcell) && !tabular.isLastRow(cell); ++cell) {
1406 if (tabular.isLastCellInRow(cell)) {
1407 cursor_.y(cursor_.y() + tabular.getDescentOfRow(actrow) +
1408 tabular.getAscentOfRow(actrow + 1) +
1409 tabular.getAdditionalHeight(actrow + 1));
1413 if (!locked || nodraw()) {
1414 if (the_locking_inset)
1415 inset_y = cursor_.y();
1418 // we need this only from here on!!!
1420 static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1421 int new_x = getCellXPos(actcell);
1422 int old_x = cursor_.x();
1425 // cursor.x(getCellXPos(actcell) + offset);
1426 if ((actcol < tabular.columns() - 1) && scroll(false) &&
1427 (tabular.getWidthOfTabular() < bv->workWidth()-20))
1430 updateLocal(bv, FULL);
1431 } else if (the_locking_inset &&
1432 (tabular.getWidthOfColumn(actcell) > bv->workWidth()-20))
1434 int xx = cursor_.x() - offset + bv->text->getRealCursorX();
1435 if (xx > (bv->workWidth()-20)) {
1436 scroll(bv, -(xx - bv->workWidth() + 60));
1437 updateLocal(bv, FULL);
1438 } else if (xx < 20) {
1444 updateLocal(bv, FULL);
1446 } else if ((cursor_.x() - offset) > 20 &&
1447 (cursor_.x() - offset + tabular.getWidthOfColumn(actcell))
1448 > (bv->workWidth() - 20)) {
1449 scroll(bv, -tabular.getWidthOfColumn(actcell) - 20);
1450 updateLocal(bv, FULL);
1451 } else if ((cursor_.x() - offset) < 20) {
1452 scroll(bv, 20 - cursor_.x() + offset);
1453 updateLocal(bv, FULL);
1454 } else if (scroll() && top_x > 20 &&
1455 (top_x + tabular.getWidthOfTabular()) > (bv->workWidth() - 20)) {
1456 scroll(bv, old_x - cursor_.x());
1457 updateLocal(bv, FULL);
1459 if (the_locking_inset) {
1460 inset_x = cursor_.x() - top_x + tabular.getBeginningOfTextInCell(actcell);
1461 inset_y = cursor_.y();
1463 if ((!the_locking_inset ||
1464 !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) &&
1465 actcell != oldcell) {
1466 InsetTabular * inset = const_cast<InsetTabular *>(this);
1467 InsetTabularMailer mailer(*inset);
1468 mailer.updateDialog(bv);
1475 Inset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1477 if (lock && !old_locking_inset) {
1478 if (activateCellInset(bv))
1481 bool moved = isRightToLeft(bv)
1482 ? movePrevCell(bv) : moveNextCell(bv);
1484 return FINISHED_RIGHT;
1485 if (lock && activateCellInset(bv))
1489 return DISPATCHED_NOUPDATE;
1493 Inset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1495 bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
1498 if (lock) { // behind the inset
1499 if (activateCellInset(bv, 0, 0, mouse_button::none, true))
1503 return DISPATCHED_NOUPDATE;
1507 Inset::RESULT InsetTabular::moveUp(BufferView * bv, bool lock)
1509 int const ocell = actcell;
1510 actcell = tabular.getCellAbove(actcell);
1511 if (actcell == ocell) // we moved out of the inset
1517 if (old_locking_inset) {
1518 old_locking_inset->getCursorPos(bv, x, y);
1519 x -= cursor_.x() + tabular.getBeginningOfTextInCell(actcell);
1521 if (activateCellInset(bv, x, 0))
1524 return DISPATCHED_NOUPDATE;
1528 Inset::RESULT InsetTabular::moveDown(BufferView * bv, bool lock)
1530 int const ocell = actcell;
1531 actcell = tabular.getCellBelow(actcell);
1532 if (actcell == ocell) // we moved out of the inset
1533 return FINISHED_DOWN;
1538 if (old_locking_inset) {
1539 old_locking_inset->getCursorPos(bv, x, y);
1540 x -= cursor_.x() + tabular.getBeginningOfTextInCell(actcell);
1542 if (activateCellInset(bv, x, 0))
1545 return DISPATCHED_NOUPDATE;
1549 bool InsetTabular::moveNextCell(BufferView * bv, bool lock)
1551 if (isRightToLeft(bv)) {
1552 if (tabular.isFirstCellInRow(actcell)) {
1553 int row = tabular.row_of_cell(actcell);
1554 if (row == tabular.rows() - 1)
1556 actcell = tabular.getLastCellInRow(row);
1557 actcell = tabular.getCellBelow(actcell);
1564 if (tabular.isLastCell(actcell))
1569 bool rtl = tabular.getCellInset(actcell)->paragraphs.begin()->
1570 isRightToLeftPar(bv->buffer()->params);
1571 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1578 bool InsetTabular::movePrevCell(BufferView * bv, bool lock)
1580 if (isRightToLeft(bv)) {
1581 if (tabular.isLastCellInRow(actcell)) {
1582 int row = tabular.row_of_cell(actcell);
1585 actcell = tabular.getFirstCellInRow(row);
1586 actcell = tabular.getCellAbove(actcell);
1588 if (tabular.isLastCell(actcell))
1593 if (!actcell) // first cell
1598 bool rtl = tabular.getCellInset(actcell)->paragraphs.begin()->
1599 isRightToLeftPar(bv->buffer()->params);
1600 activateCellInset(bv, 0, 0, mouse_button::none, !rtl);
1607 void InsetTabular::setFont(BufferView * bv, LyXFont const & font, bool tall,
1611 setSelection(0, tabular.getNumberOfCells() - 1);
1613 if (hasSelection()) {
1614 setUndo(bv, Undo::EDIT);
1615 bool const frozen = undo_frozen;
1618 // apply the fontchange on the whole selection
1623 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1624 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1625 for(int j = sel_col_start; j <= sel_col_end; ++j) {
1626 tabular.getCellInset(i, j)->setFont(bv, font, tall, true);
1633 updateLocal(bv, INIT);
1635 if (the_locking_inset)
1636 the_locking_inset->setFont(bv, font, tall);
1640 bool InsetTabular::tabularFeatures(BufferView * bv, string const & what)
1642 LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1645 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
1646 string const tmp = tabularFeature[i].feature;
1648 if (tmp == what.substr(0, tmp.length())) {
1649 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
1650 //tabularFeatures[i].feature.length())) {
1651 action = tabularFeature[i].action;
1655 if (action == LyXTabular::LAST_ACTION)
1659 ltrim(what.substr(tabularFeature[i].feature.length()));
1660 tabularFeatures(bv, action, val);
1666 void checkLongtableSpecial(LyXTabular::ltType & ltt,
1667 string const & special, bool & flag)
1669 if (special == "dl_above") {
1672 } else if (special == "dl_below") {
1673 ltt.bottomDL = flag;
1675 } else if (special == "empty") {
1687 void InsetTabular::tabularFeatures(BufferView * bv,
1688 LyXTabular::Feature feature,
1689 string const & value)
1695 bool setLines = false;
1696 LyXAlignment setAlign = LYX_ALIGN_LEFT;
1697 LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1700 case LyXTabular::M_ALIGN_LEFT:
1701 case LyXTabular::ALIGN_LEFT:
1702 setAlign = LYX_ALIGN_LEFT;
1704 case LyXTabular::M_ALIGN_RIGHT:
1705 case LyXTabular::ALIGN_RIGHT:
1706 setAlign = LYX_ALIGN_RIGHT;
1708 case LyXTabular::M_ALIGN_CENTER:
1709 case LyXTabular::ALIGN_CENTER:
1710 setAlign = LYX_ALIGN_CENTER;
1712 case LyXTabular::ALIGN_BLOCK:
1713 setAlign = LYX_ALIGN_BLOCK;
1715 case LyXTabular::M_VALIGN_TOP:
1716 case LyXTabular::VALIGN_TOP:
1717 setVAlign = LyXTabular::LYX_VALIGN_TOP;
1719 case LyXTabular::M_VALIGN_BOTTOM:
1720 case LyXTabular::VALIGN_BOTTOM:
1721 setVAlign = LyXTabular::LYX_VALIGN_BOTTOM;
1723 case LyXTabular::M_VALIGN_CENTER:
1724 case LyXTabular::VALIGN_CENTER:
1725 setVAlign = LyXTabular::LYX_VALIGN_CENTER;
1730 if (hasSelection()) {
1731 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1733 sel_col_start = sel_col_end = tabular.column_of_cell(actcell);
1734 sel_row_start = sel_row_end = tabular.row_of_cell(actcell);
1736 setUndo(bv, Undo::FINISH);
1738 int row = tabular.row_of_cell(actcell);
1739 int column = tabular.column_of_cell(actcell);
1741 LyXTabular::ltType ltt;
1744 case LyXTabular::SET_PWIDTH:
1746 LyXLength const vallen(value);
1747 LyXLength const & tmplen = tabular.getColumnPWidth(actcell);
1749 bool const update = (tmplen != vallen);
1750 tabular.setColumnPWidth(actcell, vallen);
1752 // We need this otherwise we won't resize
1753 // the insettext of the active cell (if any)
1754 // until later (see InsetText::do_resize)
1755 unlockInsetInInset(bv, the_locking_inset);
1758 for (int i = 0; i < tabular.rows(); ++i) {
1759 cell = tabular.getCellNumber(i,column);
1760 tabular.getCellInset(cell)->resizeLyXText(bv);
1762 updateLocal(bv, INIT);
1766 && tabular.getAlignment(actcell, true) == LYX_ALIGN_BLOCK)
1767 tabularFeatures(bv, LyXTabular::ALIGN_CENTER, string());
1768 else if (!vallen.zero()
1769 && tabular.getAlignment(actcell, true) != LYX_ALIGN_BLOCK)
1770 tabularFeatures(bv, LyXTabular::ALIGN_BLOCK, string());
1773 case LyXTabular::SET_MPWIDTH:
1775 LyXLength const vallen(value);
1776 LyXLength const & tmplen = tabular.getPWidth(actcell);
1778 bool const update = (tmplen != vallen);
1779 tabular.setMColumnPWidth(actcell, vallen);
1781 // We need this otherwise we won't resize
1782 // the insettext of the active cell (if any)
1783 // until later (see InsetText::do_resize)
1784 unlockInsetInInset(bv, the_locking_inset);
1786 for (int i = 0; i < tabular.rows(); ++i) {
1787 tabular.getCellInset(tabular.getCellNumber(i, column))->
1790 updateLocal(bv, INIT);
1794 case LyXTabular::SET_SPECIAL_COLUMN:
1795 case LyXTabular::SET_SPECIAL_MULTI:
1796 tabular.setAlignSpecial(actcell,value,feature);
1797 updateLocal(bv, FULL);
1799 case LyXTabular::APPEND_ROW:
1800 // append the row into the tabular
1801 unlockInsetInInset(bv, the_locking_inset);
1802 tabular.appendRow(bv->buffer()->params, actcell);
1803 updateLocal(bv, INIT);
1805 case LyXTabular::APPEND_COLUMN:
1806 // append the column into the tabular
1807 unlockInsetInInset(bv, the_locking_inset);
1808 tabular.appendColumn(bv->buffer()->params, actcell);
1809 actcell = tabular.getCellNumber(row, column);
1810 updateLocal(bv, INIT);
1812 case LyXTabular::DELETE_ROW:
1813 unlockInsetInInset(bv, the_locking_inset);
1814 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1815 tabular.deleteRow(sel_row_start);
1817 if (sel_row_start >= tabular.rows())
1819 actcell = tabular.getCellNumber(sel_row_start, column);
1821 updateLocal(bv, INIT);
1823 case LyXTabular::DELETE_COLUMN:
1824 unlockInsetInInset(bv, the_locking_inset);
1825 for(int i = sel_col_start; i <= sel_col_end; ++i) {
1826 tabular.deleteColumn(sel_col_start);
1828 if (sel_col_start >= tabular.columns())
1830 actcell = tabular.getCellNumber(row, sel_col_start);
1832 updateLocal(bv, INIT);
1834 case LyXTabular::M_TOGGLE_LINE_TOP:
1836 case LyXTabular::TOGGLE_LINE_TOP:
1838 bool lineSet = !tabular.topLine(actcell, flag);
1839 for (int i = sel_row_start; i <= sel_row_end; ++i)
1840 for (int j = sel_col_start; j <= sel_col_end; ++j)
1842 tabular.getCellNumber(i, j),
1844 updateLocal(bv, INIT);
1848 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1850 case LyXTabular::TOGGLE_LINE_BOTTOM:
1852 bool lineSet = !tabular.bottomLine(actcell, flag);
1853 for (int i = sel_row_start; i <= sel_row_end; ++i)
1854 for (int j = sel_col_start; j <= sel_col_end; ++j)
1855 tabular.setBottomLine(
1856 tabular.getCellNumber(i, j),
1859 updateLocal(bv, INIT);
1863 case LyXTabular::M_TOGGLE_LINE_LEFT:
1865 case LyXTabular::TOGGLE_LINE_LEFT:
1867 bool lineSet = !tabular.leftLine(actcell, flag);
1868 for (int i = sel_row_start; i <= sel_row_end; ++i)
1869 for (int j = sel_col_start; j <= sel_col_end; ++j)
1870 tabular.setLeftLine(
1871 tabular.getCellNumber(i,j),
1874 updateLocal(bv, INIT);
1878 case LyXTabular::M_TOGGLE_LINE_RIGHT:
1880 case LyXTabular::TOGGLE_LINE_RIGHT:
1882 bool lineSet = !tabular.rightLine(actcell, flag);
1883 for (int i = sel_row_start; i <= sel_row_end; ++i)
1884 for (int j = sel_col_start; j <= sel_col_end; ++j)
1885 tabular.setRightLine(
1886 tabular.getCellNumber(i,j),
1889 updateLocal(bv, INIT);
1893 case LyXTabular::M_ALIGN_LEFT:
1894 case LyXTabular::M_ALIGN_RIGHT:
1895 case LyXTabular::M_ALIGN_CENTER:
1897 case LyXTabular::ALIGN_LEFT:
1898 case LyXTabular::ALIGN_RIGHT:
1899 case LyXTabular::ALIGN_CENTER:
1900 case LyXTabular::ALIGN_BLOCK:
1901 for (int i = sel_row_start; i <= sel_row_end; ++i)
1902 for (int j = sel_col_start; j <= sel_col_end; ++j)
1903 tabular.setAlignment(
1904 tabular.getCellNumber(i, j),
1907 updateLocal(bv, INIT);
1909 case LyXTabular::M_VALIGN_TOP:
1910 case LyXTabular::M_VALIGN_BOTTOM:
1911 case LyXTabular::M_VALIGN_CENTER:
1913 case LyXTabular::VALIGN_TOP:
1914 case LyXTabular::VALIGN_BOTTOM:
1915 case LyXTabular::VALIGN_CENTER:
1916 for (int i = sel_row_start; i <= sel_row_end; ++i)
1917 for (int j = sel_col_start; j <= sel_col_end; ++j)
1918 tabular.setVAlignment(
1919 tabular.getCellNumber(i, j),
1921 updateLocal(bv, INIT);
1923 case LyXTabular::MULTICOLUMN:
1925 if (sel_row_start != sel_row_end) {
1926 #ifdef WITH_WARNINGS
1927 #warning Need I say it ? This is horrible.
1929 Alert::error(_("Error setting multicolumn"),
1930 _("You cannot set multicolumn vertically."));
1933 // just multicol for one Single Cell
1934 if (!hasSelection()) {
1935 // check wether we are completly in a multicol
1936 if (tabular.isMultiColumn(actcell)) {
1937 tabular.unsetMultiColumn(actcell);
1938 updateLocal(bv, INIT);
1940 tabular.setMultiColumn(bv->buffer(), actcell, 1);
1941 updateLocal(bv, CELL);
1945 // we have a selection so this means we just add all this
1946 // cells to form a multicolumn cell
1950 if (sel_cell_start > sel_cell_end) {
1951 s_start = sel_cell_end;
1952 s_end = sel_cell_start;
1954 s_start = sel_cell_start;
1955 s_end = sel_cell_end;
1957 tabular.setMultiColumn(bv->buffer(), s_start, s_end - s_start + 1);
1960 updateLocal(bv, INIT);
1963 case LyXTabular::SET_ALL_LINES:
1965 case LyXTabular::UNSET_ALL_LINES:
1966 for (int i = sel_row_start; i <= sel_row_end; ++i)
1967 for (int j = sel_col_start; j <= sel_col_end; ++j)
1968 tabular.setAllLines(
1969 tabular.getCellNumber(i,j), setLines);
1970 updateLocal(bv, INIT);
1972 case LyXTabular::SET_LONGTABULAR:
1973 tabular.setLongTabular(true);
1974 updateLocal(bv, INIT); // because this toggles displayed
1976 case LyXTabular::UNSET_LONGTABULAR:
1977 tabular.setLongTabular(false);
1978 updateLocal(bv, INIT); // because this toggles displayed
1980 case LyXTabular::SET_ROTATE_TABULAR:
1981 tabular.setRotateTabular(true);
1983 case LyXTabular::UNSET_ROTATE_TABULAR:
1984 tabular.setRotateTabular(false);
1986 case LyXTabular::SET_ROTATE_CELL:
1987 for (int i = sel_row_start; i <= sel_row_end; ++i)
1988 for (int j = sel_col_start; j<=sel_col_end; ++j)
1989 tabular.setRotateCell(
1990 tabular.getCellNumber(i, j),
1993 case LyXTabular::UNSET_ROTATE_CELL:
1994 for (int i = sel_row_start; i <= sel_row_end; ++i)
1995 for (int j = sel_col_start; j <= sel_col_end; ++j)
1996 tabular.setRotateCell(
1997 tabular.getCellNumber(i, j), false);
1999 case LyXTabular::SET_USEBOX:
2001 LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
2002 if (val == tabular.getUsebox(actcell))
2003 val = LyXTabular::BOX_NONE;
2004 for (int i = sel_row_start; i <= sel_row_end; ++i)
2005 for (int j = sel_col_start; j <= sel_col_end; ++j)
2007 tabular.getCellNumber(i, j), val);
2010 case LyXTabular::UNSET_LTFIRSTHEAD:
2012 case LyXTabular::SET_LTFIRSTHEAD:
2013 (void)tabular.getRowOfLTFirstHead(row, ltt);
2014 checkLongtableSpecial(ltt, value, flag);
2015 tabular.setLTHead(row, flag, ltt, true);
2017 case LyXTabular::UNSET_LTHEAD:
2019 case LyXTabular::SET_LTHEAD:
2020 (void)tabular.getRowOfLTHead(row, ltt);
2021 checkLongtableSpecial(ltt, value, flag);
2022 tabular.setLTHead(row, flag, ltt, false);
2024 case LyXTabular::UNSET_LTFOOT:
2026 case LyXTabular::SET_LTFOOT:
2027 (void)tabular.getRowOfLTFoot(row, ltt);
2028 checkLongtableSpecial(ltt, value, flag);
2029 tabular.setLTFoot(row, flag, ltt, false);
2031 case LyXTabular::UNSET_LTLASTFOOT:
2033 case LyXTabular::SET_LTLASTFOOT:
2034 (void)tabular.getRowOfLTLastFoot(row, ltt);
2035 checkLongtableSpecial(ltt, value, flag);
2036 tabular.setLTFoot(row, flag, ltt, true);
2038 case LyXTabular::SET_LTNEWPAGE:
2040 bool what = !tabular.getLTNewPage(row);
2041 tabular.setLTNewPage(row, what);
2044 // dummy stuff just to avoid warnings
2045 case LyXTabular::LAST_ACTION:
2049 InsetTabularMailer mailer(*this);
2050 mailer.updateDialog(bv);
2054 bool InsetTabular::activateCellInset(BufferView * bv, int x, int y, mouse_button::state button,
2057 UpdatableInset * inset =
2058 static_cast<UpdatableInset*>(tabular.getCellInset(actcell));
2059 LyXFont font(LyXFont::ALL_SANE);
2061 x = inset->x() + inset->width(bv, font);
2062 y = inset->descent(bv, font);
2064 //inset_x = cursor.x() - top_x + tabular.getBeginningOfTextInCell(actcell);
2065 //inset_y = cursor.y();
2066 inset->localDispatch(FuncRequest(bv, LFUN_INSET_EDIT, x, y, button));
2067 if (!the_locking_inset)
2069 updateLocal(bv, CELL);
2070 return (the_locking_inset != 0);
2074 bool InsetTabular::activateCellInsetAbs(BufferView * bv, int x, int y,
2075 mouse_button::state button)
2077 inset_x = cursor_.x()
2078 - top_x + tabular.getBeginningOfTextInCell(actcell);
2079 inset_y = cursor_.y();
2080 return activateCellInset(bv, x - inset_x, y - inset_y, button);
2084 bool InsetTabular::insetHit(BufferView *, int x, int) const
2087 > (cursor_.x() + tabular.getBeginningOfTextInCell(actcell));
2091 // This returns paperWidth() if the cell-width is unlimited or the width
2092 // in pixels if we have a pwidth for this cell.
2093 int InsetTabular::getMaxWidthOfCell(BufferView * bv, int cell) const
2095 LyXLength const len = tabular.getPWidth(cell);
2099 return len.inPixels(latexTextWidth(bv));
2103 int InsetTabular::getMaxWidth(BufferView * bv,
2104 UpdatableInset const * inset) const
2106 int cell = tabular.getCellFromInset(inset, actcell);
2109 lyxerr << "Own inset not found, shouldn't really happen!"
2114 int w = getMaxWidthOfCell(bv, cell);
2116 // because the inset then subtracts it's top_x and owner->x()
2117 w += (inset->x() - top_x);
2124 void InsetTabular::deleteLyXText(BufferView * bv, bool recursive) const
2126 resizeLyXText(bv, recursive);
2130 void InsetTabular::resizeLyXText(BufferView * bv, bool force) const
2133 for(int i = 0; i < tabular.rows(); ++i) {
2134 for(int j = 0; j < tabular.columns(); ++j) {
2135 tabular.getCellInset(i, j)->resizeLyXText(bv, true);
2143 LyXText * InsetTabular::getLyXText(BufferView const * bv,
2144 bool const recursive) const
2146 if (the_locking_inset)
2147 return the_locking_inset->getLyXText(bv, recursive);
2149 // if we're locked lock the actual insettext and return it's LyXText!!!
2151 UpdatableInset * inset =
2152 static_cast<UpdatableInset*>(tabular.getCellInset(actcell));
2153 inset->edit(const_cast<BufferView *>(bv), 0, 0, 0);
2154 return the_locking_inset->getLyXText(bv, recursive);
2157 return Inset::getLyXText(bv, recursive);
2161 bool InsetTabular::showInsetDialog(BufferView * bv) const
2163 if (!the_locking_inset || !the_locking_inset->showInsetDialog(bv)) {
2164 InsetTabular * tmp = const_cast<InsetTabular *>(this);
2165 InsetTabularMailer mailer(*tmp);
2166 mailer.showDialog(bv);
2172 void InsetTabular::openLayoutDialog(BufferView * bv) const
2174 if (the_locking_inset) {
2175 InsetTabular * i = static_cast<InsetTabular *>
2176 (the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE));
2178 i->openLayoutDialog(bv);
2182 InsetTabular * tmp = const_cast<InsetTabular *>(this);
2183 InsetTabularMailer mailer(*tmp);
2184 mailer.showDialog(bv);
2189 // function returns an object as defined in func_status.h:
2190 // states OK, Unknown, Disabled, On, Off.
2192 FuncStatus InsetTabular::getStatus(string const & what) const
2194 int action = LyXTabular::LAST_ACTION;
2198 for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
2199 string const tmp = tabularFeature[i].feature;
2200 if (tmp == what.substr(0, tmp.length())) {
2201 //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
2202 // tabularFeatures[i].feature.length())) {
2203 action = tabularFeature[i].action;
2207 if (action == LyXTabular::LAST_ACTION) {
2209 return status.unknown(true);
2212 string const argument = ltrim(what.substr(tabularFeature[i].feature.length()));
2217 LyXTabular::ltType dummyltt;
2220 if (hasSelection()) {
2221 getSelection(sel_row_start, sel_row_end, dummy, dummy);
2223 sel_row_start = sel_row_end = tabular.row_of_cell(actcell);
2227 case LyXTabular::SET_PWIDTH:
2228 case LyXTabular::SET_MPWIDTH:
2229 case LyXTabular::SET_SPECIAL_COLUMN:
2230 case LyXTabular::SET_SPECIAL_MULTI:
2231 case LyXTabular::APPEND_ROW:
2232 case LyXTabular::APPEND_COLUMN:
2233 case LyXTabular::DELETE_ROW:
2234 case LyXTabular::DELETE_COLUMN:
2235 case LyXTabular::SET_ALL_LINES:
2236 case LyXTabular::UNSET_ALL_LINES:
2237 return status.clear();
2239 case LyXTabular::MULTICOLUMN:
2240 status.setOnOff(tabular.isMultiColumn(actcell));
2242 case LyXTabular::M_TOGGLE_LINE_TOP:
2244 case LyXTabular::TOGGLE_LINE_TOP:
2245 status.setOnOff(tabular.topLine(actcell, flag));
2247 case LyXTabular::M_TOGGLE_LINE_BOTTOM:
2249 case LyXTabular::TOGGLE_LINE_BOTTOM:
2250 status.setOnOff(tabular.bottomLine(actcell, flag));
2252 case LyXTabular::M_TOGGLE_LINE_LEFT:
2254 case LyXTabular::TOGGLE_LINE_LEFT:
2255 status.setOnOff(tabular.leftLine(actcell, flag));
2257 case LyXTabular::M_TOGGLE_LINE_RIGHT:
2259 case LyXTabular::TOGGLE_LINE_RIGHT:
2260 status.setOnOff(tabular.rightLine(actcell, flag));
2262 case LyXTabular::M_ALIGN_LEFT:
2264 case LyXTabular::ALIGN_LEFT:
2265 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_LEFT);
2267 case LyXTabular::M_ALIGN_RIGHT:
2269 case LyXTabular::ALIGN_RIGHT:
2270 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_RIGHT);
2272 case LyXTabular::M_ALIGN_CENTER:
2274 case LyXTabular::ALIGN_CENTER:
2275 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_CENTER);
2277 case LyXTabular::ALIGN_BLOCK:
2278 status.disabled(tabular.getPWidth(actcell).zero());
2279 status.setOnOff(tabular.getAlignment(actcell, flag) == LYX_ALIGN_BLOCK);
2281 case LyXTabular::M_VALIGN_TOP:
2283 case LyXTabular::VALIGN_TOP:
2284 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP);
2286 case LyXTabular::M_VALIGN_BOTTOM:
2288 case LyXTabular::VALIGN_BOTTOM:
2289 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM);
2291 case LyXTabular::M_VALIGN_CENTER:
2293 case LyXTabular::VALIGN_CENTER:
2294 status.setOnOff(tabular.getVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER);
2296 case LyXTabular::SET_LONGTABULAR:
2297 status.setOnOff(tabular.isLongTabular());
2299 case LyXTabular::UNSET_LONGTABULAR:
2300 status.setOnOff(!tabular.isLongTabular());
2302 case LyXTabular::SET_ROTATE_TABULAR:
2303 status.setOnOff(tabular.getRotateTabular());
2305 case LyXTabular::UNSET_ROTATE_TABULAR:
2306 status.setOnOff(!tabular.getRotateTabular());
2308 case LyXTabular::SET_ROTATE_CELL:
2309 status.setOnOff(tabular.getRotateCell(actcell));
2311 case LyXTabular::UNSET_ROTATE_CELL:
2312 status.setOnOff(!tabular.getRotateCell(actcell));
2314 case LyXTabular::SET_USEBOX:
2315 status.setOnOff(strToInt(argument) == tabular.getUsebox(actcell));
2317 case LyXTabular::SET_LTFIRSTHEAD:
2318 status.setOnOff(tabular.getRowOfLTHead(sel_row_start, dummyltt));
2320 case LyXTabular::SET_LTHEAD:
2321 status.setOnOff(tabular.getRowOfLTHead(sel_row_start, dummyltt));
2323 case LyXTabular::SET_LTFOOT:
2324 status.setOnOff(tabular.getRowOfLTFoot(sel_row_start, dummyltt));
2326 case LyXTabular::SET_LTLASTFOOT:
2327 status.setOnOff(tabular.getRowOfLTFoot(sel_row_start, dummyltt));
2329 case LyXTabular::SET_LTNEWPAGE:
2330 status.setOnOff(tabular.getLTNewPage(sel_row_start));
2334 status.disabled(true);
2341 void InsetTabular::getLabelList(std::vector<string> & list) const
2343 tabular.getLabelList(list);
2347 bool InsetTabular::copySelection(BufferView * bv)
2349 if (!hasSelection())
2352 int sel_col_start = tabular.column_of_cell(sel_cell_start);
2353 int sel_col_end = tabular.column_of_cell(sel_cell_end);
2354 if (sel_col_start > sel_col_end) {
2355 sel_col_start = sel_col_end;
2356 sel_col_end = tabular.right_column_of_cell(sel_cell_start);
2358 sel_col_end = tabular.right_column_of_cell(sel_cell_end);
2360 int const columns = sel_col_end - sel_col_start + 1;
2362 int sel_row_start = tabular.row_of_cell(sel_cell_start);
2363 int sel_row_end = tabular.row_of_cell(sel_cell_end);
2364 if (sel_row_start > sel_row_end) {
2365 swap(sel_row_start, sel_row_end);
2367 int const rows = sel_row_end - sel_row_start + 1;
2369 delete paste_tabular;
2370 paste_tabular = new LyXTabular(bv->buffer()->params,
2371 this, tabular); // rows, columns);
2372 for (int i = 0; i < sel_row_start; ++i)
2373 paste_tabular->deleteRow(0);
2374 while (paste_tabular->rows() > rows)
2375 paste_tabular->deleteRow(rows);
2376 paste_tabular->setTopLine(0, true, true);
2377 paste_tabular->setBottomLine(paste_tabular->getFirstCellInRow(rows - 1),
2379 for (int i = 0; i < sel_col_start; ++i)
2380 paste_tabular->deleteColumn(0);
2381 while (paste_tabular->columns() > columns)
2382 paste_tabular->deleteColumn(columns);
2383 paste_tabular->setLeftLine(0, true, true);
2384 paste_tabular->setRightLine(paste_tabular->getLastCellInRow(0),
2388 paste_tabular->ascii(bv->buffer(), sstr,
2389 (int)parOwner()->params().depth(), true, '\t');
2390 bv->stuffClipboard(STRCONV(sstr.str()));
2395 bool InsetTabular::pasteSelection(BufferView * bv)
2400 for (int r1 = 0, r2 = actrow;
2401 (r1 < paste_tabular->rows()) && (r2 < tabular.rows());
2403 for(int c1 = 0, c2 = actcol;
2404 (c1 < paste_tabular->columns()) && (c2 < tabular.columns());
2406 if (paste_tabular->isPartOfMultiColumn(r1,c1) &&
2407 tabular.isPartOfMultiColumn(r2,c2))
2409 if (paste_tabular->isPartOfMultiColumn(r1,c1)) {
2413 if (tabular.isPartOfMultiColumn(r2,c2)) {
2417 int const n1 = paste_tabular->getCellNumber(r1, c1);
2418 int const n2 = tabular.getCellNumber(r2, c2);
2419 *(tabular.getCellInset(n2)) = *(paste_tabular->getCellInset(n1));
2420 tabular.getCellInset(n2)->setOwner(this);
2421 tabular.getCellInset(n2)->deleteLyXText(bv);
2422 tabular.getCellInset(n2)->markNew();
2429 bool InsetTabular::cutSelection(BufferParams const & bp)
2431 if (!hasSelection())
2434 int sel_col_start = tabular.column_of_cell(sel_cell_start);
2435 int sel_col_end = tabular.column_of_cell(sel_cell_end);
2436 if (sel_col_start > sel_col_end) {
2437 sel_col_start = sel_col_end;
2438 sel_col_end = tabular.right_column_of_cell(sel_cell_start);
2440 sel_col_end = tabular.right_column_of_cell(sel_cell_end);
2442 int sel_row_start = tabular.row_of_cell(sel_cell_start);
2443 int sel_row_end = tabular.row_of_cell(sel_cell_end);
2444 if (sel_row_start > sel_row_end) {
2445 swap(sel_row_start, sel_row_end);
2447 if (sel_cell_start > sel_cell_end) {
2448 swap(sel_cell_start, sel_cell_end);
2450 for (int i = sel_row_start; i <= sel_row_end; ++i) {
2451 for (int j = sel_col_start; j <= sel_col_end; ++j) {
2452 tabular.getCellInset(tabular.getCellNumber(i, j))->clear(bp.tracking_changes);
2459 bool InsetTabular::isRightToLeft(BufferView * bv)
2461 return bv->getParentLanguage(this)->RightToLeft();
2465 bool InsetTabular::nodraw() const
2467 if (!UpdatableInset::nodraw() && the_locking_inset)
2468 return the_locking_inset->nodraw();
2469 return UpdatableInset::nodraw();
2473 int InsetTabular::scroll(bool recursive) const
2475 int sx = UpdatableInset::scroll(false);
2477 if (recursive && the_locking_inset)
2478 sx += the_locking_inset->scroll(recursive);
2484 void InsetTabular::getSelection(int & srow, int & erow,
2485 int & scol, int & ecol) const
2487 int const start = hasSelection() ? sel_cell_start : actcell;
2488 int const end = hasSelection() ? sel_cell_end : actcell;
2490 srow = tabular.row_of_cell(start);
2491 erow = tabular.row_of_cell(end);
2496 scol = tabular.column_of_cell(start);
2497 ecol = tabular.column_of_cell(end);
2501 ecol = tabular.right_column_of_cell(end);
2506 ParagraphList * InsetTabular::getParagraphs(int i) const
2508 return (i < tabular.getNumberOfCells())
2509 ? tabular.getCellInset(i)->getParagraphs(0)
2514 LyXCursor const & InsetTabular::cursor(BufferView * bv) const
2516 if (the_locking_inset)
2517 return the_locking_inset->cursor(bv);
2518 return Inset::cursor(bv);
2522 Inset * InsetTabular::getInsetFromID(int id_arg) const
2525 return const_cast<InsetTabular *>(this);
2528 for(int i = 0; i < tabular.rows(); ++i) {
2529 for(int j = 0; j < tabular.columns(); ++j) {
2530 if ((result = tabular.getCellInset(i, j)->getInsetFromID(id_arg)))
2539 InsetTabular::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2542 if (the_locking_inset) {
2543 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2544 if (!word.word().empty()) {
2548 if (tabular.isLastCell(actcell)) {
2549 bv->unlockInset(const_cast<InsetTabular *>(this));
2551 return WordLangTuple();
2555 // otherwise we have to lock the next inset and ask for it's selecttion
2556 UpdatableInset * inset =
2557 static_cast<UpdatableInset*>(tabular.getCellInset(actcell));
2558 inset->localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
2559 WordLangTuple word(selectNextWordInt(bv, value));
2561 if (!word.word().empty())
2567 WordLangTuple InsetTabular::selectNextWordInt(BufferView * bv, float & value) const
2569 // when entering this function the inset should be ALWAYS locked!
2570 Assert(the_locking_inset);
2572 WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2573 if (!word.word().empty())
2576 if (tabular.isLastCell(actcell)) {
2577 bv->unlockInset(const_cast<InsetTabular *>(this));
2578 return WordLangTuple();
2581 // otherwise we have to lock the next inset and ask for it's selecttion
2582 UpdatableInset * inset =
2583 static_cast<UpdatableInset*>(tabular.getCellInset(++actcell));
2584 inset->localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
2585 return selectNextWordInt(bv, value);
2589 void InsetTabular::selectSelectedWord(BufferView * bv)
2591 if (the_locking_inset) {
2592 the_locking_inset->selectSelectedWord(bv);
2599 void InsetTabular::toggleSelection(BufferView * bv, bool kill_selection)
2601 if (the_locking_inset) {
2602 the_locking_inset->toggleSelection(bv, kill_selection);
2607 void InsetTabular::markErased()
2611 while (cell < tabular.getNumberOfCells()) {
2612 InsetText * inset = tabular.getCellInset(cell);
2613 inset->markErased();
2619 bool InsetTabular::nextChange(BufferView * bv, lyx::pos_type & length)
2621 if (the_locking_inset) {
2622 if (the_locking_inset->nextChange(bv, length)) {
2623 updateLocal(bv, CELL);
2626 if (tabular.isLastCell(actcell))
2630 InsetText * inset = tabular.getCellInset(actcell);
2631 if (inset->nextChange(bv, length)) {
2632 updateLocal(bv, FULL);
2635 while (!tabular.isLastCell(actcell)) {
2637 inset = tabular.getCellInset(actcell);
2638 if (inset->nextChange(bv, length)) {
2639 updateLocal(bv, FULL);
2647 bool InsetTabular::searchForward(BufferView * bv, string const & str,
2651 if (the_locking_inset) {
2652 if (the_locking_inset->searchForward(bv, str, cs, mw)) {
2653 updateLocal(bv, CELL);
2656 if (tabular.isLastCell(actcell))
2660 InsetText * inset = tabular.getCellInset(cell);
2661 if (inset->searchForward(bv, str, cs, mw)) {
2662 updateLocal(bv, FULL);
2665 while (!tabular.isLastCell(cell)) {
2667 inset = tabular.getCellInset(cell);
2668 if (inset->searchForward(bv, str, cs, mw)) {
2669 updateLocal(bv, FULL);
2677 bool InsetTabular::searchBackward(BufferView * bv, string const & str,
2680 int cell = tabular.getNumberOfCells();
2681 if (the_locking_inset) {
2682 if (the_locking_inset->searchBackward(bv, str, cs, mw)) {
2683 updateLocal(bv, CELL);
2691 InsetText * inset = tabular.getCellInset(cell);
2692 if (inset->searchBackward(bv, str, cs, mw)) {
2693 updateLocal(bv, CELL);
2701 bool InsetTabular::insetAllowed(Inset::Code code) const
2703 if (the_locking_inset)
2704 return the_locking_inset->insetAllowed(code);
2705 // we return true here because if the inset is not locked someone
2706 // wants to insert something in one of our insettexts and we generally
2712 bool InsetTabular::forceDefaultParagraphs(Inset const * in) const
2714 const int cell = tabular.getCellFromInset(in, actcell);
2717 return tabular.getPWidth(cell).zero();
2719 // well we didn't obviously find it so maybe our owner knows more
2721 return owner()->forceDefaultParagraphs(in);
2722 // if we're here there is really something strange going on!!!
2726 bool InsetTabular::insertAsciiString(BufferView * bv, string const & buf,
2729 if (buf.length() <= 0)
2735 string::size_type len = buf.length();
2736 string::size_type p = 0;
2739 ((p = buf.find_first_of("\t\n", p)) != string::npos))
2748 maxCols = max(cols, maxCols);
2754 maxCols = max(cols, maxCols);
2755 LyXTabular * loctab;
2760 delete paste_tabular;
2761 paste_tabular = new LyXTabular(bv->buffer()->params,
2762 this, rows, maxCols);
2763 loctab = paste_tabular;
2772 string::size_type op = 0;
2773 int cells = loctab->getNumberOfCells();
2776 rows = loctab->rows();
2777 int const columns = loctab->columns();
2779 while ((cell < cells) && (p < len) && (row < rows) &&
2780 (p = buf.find_first_of("\t\n", p)) != string::npos)
2786 // we can only set this if we are not too far right
2787 if (cols < columns) {
2788 InsetText * ti = loctab->getCellInset(cell);
2789 LyXFont const font = ti->getLyXText(bv)->
2790 getFont(bv->buffer(), ti->paragraphs.begin(), 0);
2791 ti->setText(buf.substr(op, p - op), font);
2797 // we can only set this if we are not too far right
2798 if (cols < columns) {
2799 InsetText * ti = loctab->getCellInset(cell);
2800 LyXFont const font = ti->getLyXText(bv)->
2801 getFont(bv->buffer(), ti->paragraphs.begin(), 0);
2802 ti->setText(buf.substr(op, p - op), font);
2807 cell = loctab->getCellNumber(row, cols);
2813 // check for the last cell if there is no trailing '\n'
2814 if ((cell < cells) && (op < len)) {
2815 InsetText * ti = loctab->getCellInset(cell);
2816 LyXFont const font = ti->getLyXText(bv)->
2817 getFont(bv->buffer(), ti->paragraphs.begin(), 0);
2818 ti->setText(buf.substr(op, len - op), font);
2825 void InsetTabular::addPreview(grfx::PreviewLoader & loader) const
2827 int const rows = tabular.rows();
2828 int const columns = tabular.columns();
2829 for (int i = 0; i < rows; ++i) {
2830 for (int j = 0; j < columns; ++j) {
2831 tabular.getCellInset(i,j)->addPreview(loader);
2837 string const InsetTabularMailer:: name_("tabular");
2839 InsetTabularMailer::InsetTabularMailer(InsetTabular & inset)
2844 string const InsetTabularMailer::inset2string() const
2846 return params2string(inset_);
2850 int InsetTabularMailer::string2params(string const & in, InsetTabular & inset)
2852 istringstream data(STRCONV(in));
2854 lex.setStream(data);
2856 #warning CHECK verify that this is a sane value to return.
2862 string const token = lex.getString();
2870 string const token = lex.getString();
2871 if (token != "\\active_cell")
2874 cell = lex.getInteger();
2877 // This is part of the inset proper that is usually swallowed
2878 // by Buffer::readInset
2881 string const token = lex.getString();
2882 if (token != "Tabular")
2889 Buffer const * const buffer = inset.buffer();
2891 inset.read(buffer, lex);
2893 // We can't set the active cell, but we can tell the frontend
2899 string const InsetTabularMailer::params2string(InsetTabular const & inset)
2901 Buffer const * const buffer = inset.buffer();
2906 data << name_ << " \\active_cell " << inset.getActCell() << '\n';
2907 inset.write(buffer, data);
2908 data << "\\end_inset\n";
2909 return STRCONV(data.str());