]> git.lyx.org Git - features.git/blob - src/insets/insettabular.C
new alert code
[features.git] / src / insets / insettabular.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2001 The LyX Team.
7  *
8  * ======================================================
9  */
10
11 #include <config.h>
12
13 #include <fstream>
14 #include <algorithm>
15
16 #include <cstdlib>
17 #include <map>
18 //#include <signal.h>
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "insettabular.h"
24
25 #include "buffer.h"
26 #include "commandtags.h"
27 #include "lyxfunc.h"
28 #include "debug.h"
29 #include "LaTeXFeatures.h"
30 #include "Painter.h"
31 #include "font.h"
32 #include "lyxtext.h"
33 #include "lyx_gui_misc.h"
34 #include "LyXView.h"
35 #include "insets/insettext.h"
36 #include "frontends/Dialogs.h"
37 #include "frontends/Alert.h"
38 #include "debug.h"
39 #include "WorkArea.h"
40 #include "gettext.h"
41 #include "language.h"
42 #include "BufferView.h"
43 #include "undo_funcs.h"
44 #include "support/LAssert.h"
45 #include "support/lstrings.h"
46
47 using std::ostream;
48 using std::ifstream;
49 using std::max;
50 using std::endl;
51 using std::swap;
52 using std::max;
53
54 namespace {
55
56 const int ADD_TO_HEIGHT = 2;
57 const int ADD_TO_TABULAR_WIDTH = 2;
58 ///
59 LyXTabular * paste_tabular = 0;
60
61
62 struct TabularFeature {
63         LyXTabular::Feature action;
64         string feature;
65 };
66
67 //tabular_features * tabularFeatures = 0;
68
69 TabularFeature tabularFeature[] =
70 {
71         { LyXTabular::APPEND_ROW, "append-row" },
72         { LyXTabular::APPEND_COLUMN, "append-column" },
73         { LyXTabular::DELETE_ROW, "delete-row" },
74         { LyXTabular::DELETE_COLUMN, "delete-column" },
75         { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
76         { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
77         { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
78         { LyXTabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
79         { LyXTabular::ALIGN_LEFT, "align-left" },
80         { LyXTabular::ALIGN_RIGHT, "align-right" },
81         { LyXTabular::ALIGN_CENTER, "align-center" },
82         { LyXTabular::VALIGN_TOP, "valign-top" },
83         { LyXTabular::VALIGN_BOTTOM, "valign-bottom" },
84         { LyXTabular::VALIGN_CENTER, "valign-center" },
85         { LyXTabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
86         { LyXTabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
87         { LyXTabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
88         { LyXTabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
89         { LyXTabular::M_ALIGN_LEFT, "m-align-left" },
90         { LyXTabular::M_ALIGN_RIGHT, "m-align-right" },
91         { LyXTabular::M_ALIGN_CENTER, "m-align-center" },
92         { LyXTabular::M_VALIGN_TOP, "m-valign-top" },
93         { LyXTabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
94         { LyXTabular::M_VALIGN_CENTER, "m-valign-center" },
95         { LyXTabular::MULTICOLUMN, "multicolumn" },
96         { LyXTabular::SET_ALL_LINES, "set-all-lines" },
97         { LyXTabular::UNSET_ALL_LINES, "unset-all-lines" },
98         { LyXTabular::SET_LONGTABULAR, "set-longtabular" },
99         { LyXTabular::UNSET_LONGTABULAR, "unset-longtabular" },
100         { LyXTabular::SET_PWIDTH, "set-pwidth" },
101         { LyXTabular::SET_MPWIDTH, "set-mpwidth" },
102         { LyXTabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
103         { LyXTabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
104         { LyXTabular::SET_ROTATE_CELL, "set-rotate-cell" },
105         { LyXTabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
106         { LyXTabular::SET_USEBOX, "set-usebox" },
107         { LyXTabular::SET_LTHEAD, "set-lthead" },
108         { LyXTabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
109         { LyXTabular::SET_LTFOOT, "set-ltfoot" },
110         { LyXTabular::SET_LTLASTFOOT, "set-ltlastfoot" },
111         { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" },
112         { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" },
113         { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" },
114         { LyXTabular::LAST_ACTION, "" }
115 };
116
117 } // namespace anon
118
119
120 bool InsetTabular::hasPasteBuffer() const
121 {
122         return (paste_tabular != 0);
123 }
124
125
126 InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
127         : buffer(&buf)
128 {
129         if (rows <= 0)
130                 rows = 1;
131         if (columns <= 0)
132                 columns = 1;
133         tabular.reset(new LyXTabular(this, rows, columns));
134         // for now make it always display as display() inset
135         // just for test!!!
136         the_locking_inset = 0;
137         locked = no_selection = false;
138         oldcell = -1;
139         actrow = actcell = 0;
140         clearSelection();
141         need_update = INIT;
142         in_update = false;
143 }
144
145
146 InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf,
147                                                    bool same_id)
148         : UpdatableInset(tab, same_id), buffer(&buf)
149 {
150         tabular.reset(new LyXTabular(this, *(tab.tabular)));
151         the_locking_inset = 0;
152         locked = no_selection = false;
153         oldcell = -1;
154         actrow = actcell = 0;
155         sel_cell_start = sel_cell_end = 0;
156         need_update = INIT;
157         in_update = false;
158 }
159
160
161 InsetTabular::~InsetTabular()
162 {
163         hideDialog();
164 }
165
166
167 Inset * InsetTabular::clone(Buffer const & buf, bool same_id) const
168 {
169         return new InsetTabular(*this, buf, same_id);
170 }
171
172
173 void InsetTabular::write(Buffer const * buf, ostream & os) const
174 {
175         os << " Tabular" << endl;
176         tabular->Write(buf, os);
177 }
178
179
180 void InsetTabular::read(Buffer const * buf, LyXLex & lex)
181 {
182         bool const old_format = (lex.getString() == "\\LyXTable");
183
184         //if (tabular)
185         //delete tabular;
186         //tabular = new LyXTabular(buf, this, lex);
187         tabular.reset(new LyXTabular(buf, this, lex));
188
189         need_update = INIT;
190
191         if (old_format)
192                 return;
193
194         lex.nextToken();
195         string token = lex.getString();
196         while (lex.isOK() && (token != "\\end_inset")) {
197                 lex.nextToken();
198                 token = lex.getString();
199         }
200         if (token != "\\end_inset") {
201                 lex.printError("Missing \\end_inset at this point. "
202                                "Read: `$$Token'");
203         }
204 }
205
206
207 int InsetTabular::ascent(BufferView *, LyXFont const &) const
208 {
209         return tabular->GetAscentOfRow(0);
210 }
211
212
213 int InsetTabular::descent(BufferView *, LyXFont const &) const
214 {
215         return tabular->GetHeightOfTabular() - tabular->GetAscentOfRow(0) + 1;
216 }
217
218
219 int InsetTabular::width(BufferView *, LyXFont const &) const
220 {
221         return tabular->GetWidthOfTabular() + (2 * ADD_TO_TABULAR_WIDTH);
222 }
223
224
225 void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
226                         float & x, bool cleared) const
227 {
228         if (nodraw()) {
229                 if (cleared)
230                         need_update = FULL;
231                 return;
232         }
233 #if 0
234         if (need_update == INIT) {
235                 if (calculate_dimensions_of_cells(bv, font, true))
236                         bv->text->status = LyXText::CHANGED_IN_DRAW;
237                 need_update = FULL;
238         }
239 #endif
240
241         Painter & pain = bv->painter();
242         int i;
243         int j;
244         int nx;
245
246 #if 0
247         UpdatableInset::draw(bv, font, baseline, x, cleared);
248 #else
249         if (!owner())
250                 x += static_cast<float>(scroll());
251 #endif
252         if (!cleared && ((need_update == INIT) || (need_update == FULL) ||
253                          (top_x != int(x)) || (top_baseline != baseline)))
254         {
255                 int h = ascent(bv, font) + descent(bv, font);
256                 int const tx = display() || !owner() ? 0 : top_x;
257                 int w =  tx ? width(bv, font) : pain.paperWidth();
258                 int ty = baseline - ascent(bv, font);
259         
260                 if (ty < 0)
261                         ty = 0;
262                 if ((ty + h) > pain.paperHeight())
263                         h = pain.paperHeight();
264                 if ((top_x + w) > pain.paperWidth())
265                         w = pain.paperWidth();
266                 pain.fillRectangle(tx, ty, w, h, backgroundColor());
267                 need_update = FULL;
268                 cleared = true;
269         }
270         top_x = int(x);
271         topx_set = true;
272         top_baseline = baseline;
273         x += ADD_TO_TABULAR_WIDTH;
274         if (cleared) {
275                 int cell = 0;
276                 float cx;
277                 first_visible_cell = -1;
278                 for (i = 0; i < tabular->rows(); ++i) {
279                         nx = int(x);
280                         cell = tabular->GetCellNumber(i, 0);
281                         if (!((baseline + tabular->GetDescentOfRow(i)) > 0) &&
282                                 (baseline - tabular->GetAscentOfRow(i))<pain.paperHeight())
283                         {
284                                 baseline += tabular->GetDescentOfRow(i) +
285                                         tabular->GetAscentOfRow(i + 1) +
286                                         tabular->GetAdditionalHeight(i + 1);
287                                 continue;
288                         }
289                         for (j = 0; j < tabular->columns(); ++j) {
290                                 if (nx > bv->workWidth())
291                                         break;
292                                 if (tabular->IsPartOfMultiColumn(i, j))
293                                         continue;
294                                 cx = nx + tabular->GetBeginningOfTextInCell(cell);
295                                 if (first_visible_cell < 0)
296                                         first_visible_cell = cell;
297                                 if (hasSelection())
298                                         drawCellSelection(pain, nx, baseline, i, j, cell);
299                                 
300                                 tabular->GetCellInset(cell)->draw(bv, font, baseline, cx,
301                                                                                                   cleared);
302                                 drawCellLines(pain, nx, baseline, i, cell);
303                                 nx += tabular->GetWidthOfColumn(cell);
304                                 ++cell;
305                         }
306                         baseline += tabular->GetDescentOfRow(i) +
307                                 tabular->GetAscentOfRow(i + 1) +
308                                 tabular->GetAdditionalHeight(i + 1);
309                 }
310         } else if (need_update == CELL) {
311                 int cell = 0;
312                 nx = int(x);
313                 if (the_locking_inset &&
314                         tabular->GetCellInset(actcell) != the_locking_inset)
315                 {
316                         Inset * inset = tabular->GetCellInset(cell);
317                         for (i = 0;
318                              inset != the_locking_inset && i < tabular->rows();
319                              ++i)
320                         {
321                                 for (j = 0;
322                                      inset != the_locking_inset && j < tabular->columns();
323                                      ++j)
324                                 {
325                                         if (tabular->IsPartOfMultiColumn(i, j))
326                                                 continue;
327                                         nx += tabular->GetWidthOfColumn(cell);
328                                         ++cell;
329                                         inset = tabular->GetCellInset(cell);
330                                 }
331                                 if (tabular->row_of_cell(cell) > i) {
332                                         nx = int(x);
333                                         baseline += tabular->GetDescentOfRow(i) +
334                                                 tabular->GetAscentOfRow(i + 1) +
335                                                 tabular->GetAdditionalHeight(i + 1);
336                                 }
337                         }
338                 } else {
339                         // compute baseline for actual row
340                         for (i = 0; i < actrow; ++i) {
341                                 baseline += tabular->GetDescentOfRow(i) +
342                                         tabular->GetAscentOfRow(i + 1) +
343                                         tabular->GetAdditionalHeight(i + 1);
344                         }
345                         // now compute the right x position
346                         cell = tabular->GetCellNumber(actrow, 0);
347                         for (j = 0; (cell < actcell) && (j < tabular->columns()); ++j) {
348                                         if (tabular->IsPartOfMultiColumn(actrow, j))
349                                                 continue;
350                                         nx += tabular->GetWidthOfColumn(cell);
351                                         ++cell;
352                         }
353                 }
354                 i = tabular->row_of_cell(cell);
355                 if (the_locking_inset != tabular->GetCellInset(cell)) {
356                         lyxerr[Debug::INSETS] << "ERROR this shouldn't happen\n";
357                         return;
358                 }
359                 float dx = nx + tabular->GetBeginningOfTextInCell(cell);
360                 float cx = dx;
361                 tabular->GetCellInset(cell)->draw(bv, font, baseline, dx, false);
362                 // clear only if we didn't have a change
363                 if (bv->text->status() != LyXText::CHANGED_IN_DRAW) {
364                         // clear before the inset
365                         pain.fillRectangle(
366                                 nx + 1,
367                                 baseline - tabular->GetAscentOfRow(i) + 1,
368                                 int(cx - nx - 1),
369                                 tabular->GetAscentOfRow(i) +
370                                 tabular->GetDescentOfRow(i) - 1,
371                                 backgroundColor());
372                         // clear behind the inset
373                         pain.fillRectangle(
374                                 int(cx + the_locking_inset->width(bv,font) + 1),
375                                 baseline - tabular->GetAscentOfRow(i) + 1,
376                                 tabular->GetWidthOfColumn(cell) -
377                                 tabular->GetBeginningOfTextInCell(cell) -
378                                 the_locking_inset->width(bv,font) -
379                                 tabular->GetAdditionalWidth(cell) - 1,
380                                 tabular->GetAscentOfRow(i) +
381                                 tabular->GetDescentOfRow(i) - 1,
382                                 backgroundColor());
383                         // clear below the inset
384                         pain.fillRectangle(
385                                 nx + 1,
386                                 baseline + the_locking_inset->descent(bv, font) + 1,
387                                 tabular->GetWidthOfColumn(cell) -
388                                 tabular->GetAdditionalWidth(cell) - 1,
389                                 tabular->GetAscentOfRow(i) +
390                                 tabular->GetDescentOfRow(i) -
391                                 the_locking_inset->ascent(bv, font) -
392                                 the_locking_inset->descent(bv, font) -
393                                 TEXT_TO_INSET_OFFSET - 1,
394                                 backgroundColor());
395                 }
396         }
397         x -= ADD_TO_TABULAR_WIDTH;
398         x += width(bv, font);
399         if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
400                 int i = 0;
401                 for(Inset * inset=owner(); inset; ++i)
402                         inset = inset->owner();
403                 if (calculate_dimensions_of_cells(bv, font, false))
404                         need_update = INIT;
405         } else {
406                 need_update = NONE;
407         }
408 }
409
410
411 void InsetTabular::drawCellLines(Painter & pain, int x, int baseline,
412                                  int row, int cell) const
413 {
414         int x2 = x + tabular->GetWidthOfColumn(cell);
415         bool on_off;
416         
417         if (!tabular->TopAlreadyDrawed(cell)) {
418                 on_off = !tabular->TopLine(cell);
419                 pain.line(x, baseline - tabular->GetAscentOfRow(row),
420                           x2, baseline -  tabular->GetAscentOfRow(row),
421                           on_off ? LColor::tabularonoffline : LColor::tabularline,
422                           on_off ? Painter::line_onoffdash : Painter::line_solid);
423         }
424         on_off = !tabular->BottomLine(cell);
425         pain.line(x,baseline +  tabular->GetDescentOfRow(row),
426                   x2, baseline +  tabular->GetDescentOfRow(row),
427                   on_off ? LColor::tabularonoffline : LColor::tabularline,
428                   on_off ? Painter::line_onoffdash : Painter::line_solid);
429         if (!tabular->LeftAlreadyDrawed(cell)) {
430                 on_off = !tabular->LeftLine(cell);
431                 pain.line(x, baseline -  tabular->GetAscentOfRow(row),
432                           x, baseline +  tabular->GetDescentOfRow(row),
433                           on_off ? LColor::tabularonoffline : LColor::tabularline,
434                           on_off ? Painter::line_onoffdash : Painter::line_solid);
435         }
436         on_off = !tabular->RightLine(cell);
437         pain.line(x2 - tabular->GetAdditionalWidth(cell),
438                   baseline -  tabular->GetAscentOfRow(row),
439                   x2 - tabular->GetAdditionalWidth(cell),
440                   baseline +  tabular->GetDescentOfRow(row),
441                   on_off ? LColor::tabularonoffline : LColor::tabularline,
442                   on_off ? Painter::line_onoffdash : Painter::line_solid);
443 }
444
445
446 void InsetTabular::drawCellSelection(Painter & pain, int x, int baseline,
447                                      int row, int column, int cell) const
448 {
449         int cs = tabular->column_of_cell(sel_cell_start);
450         int ce = tabular->column_of_cell(sel_cell_end);
451         if (cs > ce) {
452                 ce = cs;
453                 cs = tabular->column_of_cell(sel_cell_end);
454         } else {
455                 ce = tabular->right_column_of_cell(sel_cell_end);
456         }
457         
458         int rs = tabular->row_of_cell(sel_cell_start);
459         int re = tabular->row_of_cell(sel_cell_end);
460         if (rs > re) swap(rs, re);
461         
462         if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
463                 int w = tabular->GetWidthOfColumn(cell);
464                 int h = tabular->GetAscentOfRow(row) + tabular->GetDescentOfRow(row);
465                 pain.fillRectangle(x, baseline - tabular->GetAscentOfRow(row),
466                                    w, h, LColor::selection);
467         }
468 }
469
470
471 void InsetTabular::update(BufferView * bv, LyXFont const & font, bool reinit)
472 {
473         if (in_update) {
474                 if (reinit) {
475                         resetPos(bv);
476                         if (owner())
477                                 owner()->update(bv, font, true);
478                 }
479                 return;
480         }
481         in_update = true;
482         if (reinit) {
483                 need_update = INIT;
484                 if (calculate_dimensions_of_cells(bv, font, true))
485                         resetPos(bv);
486                 if (owner())
487                         owner()->update(bv, font, true);
488                 in_update = false;
489                 return;
490         }
491         if (the_locking_inset)
492                 the_locking_inset->update(bv, font, reinit);
493         if (need_update < FULL &&
494                 bv->text->status() == LyXText::NEED_MORE_REFRESH)
495         {
496                 need_update = FULL;
497         }
498
499         switch (need_update) {
500         case INIT:
501         case FULL:
502         case CELL:
503                 if (calculate_dimensions_of_cells(bv, font, false))
504                         need_update = INIT;
505                 break;
506         case SELECTION:
507                 need_update = INIT;
508                 break;
509         default:
510                 break;
511         }
512         in_update = false;
513 }
514
515
516 string const InsetTabular::editMessage() const
517 {
518         return _("Opened Tabular Inset");
519 }
520
521
522 void InsetTabular::edit(BufferView * bv, int x, int y, unsigned int button)
523 {
524         UpdatableInset::edit(bv, x, y, button);
525         
526         if (!bv->lockInset(this)) {
527                 lyxerr[Debug::INSETS] << "InsetTabular::Cannot lock inset" << endl;
528                 return;
529         }
530         locked = true;
531         the_locking_inset = 0;
532         inset_x = 0;
533         inset_y = 0;
534         setPos(bv, x, y);
535         sel_cell_start = sel_cell_end = actcell;
536         finishUndo();
537         if (insetHit(bv, x, y) && (button != 3)) {
538                 activateCellInsetAbs(bv, x, y, button);
539         }
540 }
541
542
543 void InsetTabular::edit(BufferView * bv, bool front)
544 {
545         UpdatableInset::edit(bv, front);
546         
547         if (!bv->lockInset(this)) {
548                 lyxerr[Debug::INSETS] << "InsetTabular::Cannot lock inset" << endl;
549                 return;
550         }
551         locked = true;
552         the_locking_inset = 0;
553         inset_x = 0;
554         inset_y = 0;
555         if (front)
556                 actcell = 0;
557         else
558                 actcell = tabular->GetNumberOfCells() - 1;
559         sel_cell_start = sel_cell_end = actcell;
560         resetPos(bv);
561         finishUndo();
562 }
563
564
565 void InsetTabular::insetUnlock(BufferView * bv)
566 {
567         if (the_locking_inset) {
568                 the_locking_inset->insetUnlock(bv);
569                 the_locking_inset = 0;
570         }
571         hideInsetCursor(bv);
572         no_selection = false;
573         oldcell = -1;
574         locked = false;
575         if (scroll(false) || hasSelection()) {
576                 sel_cell_start = sel_cell_end = 0;
577                 if (scroll(false)) {
578                         scroll(bv, 0.0F);
579                 }
580                 updateLocal(bv, FULL, false);
581         }
582 }
583
584
585 void InsetTabular::updateLocal(BufferView * bv, UpdateCodes what,
586                                bool mark_dirty) const
587 {
588         if (need_update < what) // only set this if it has greater update
589                 need_update = what;
590         if ((what == INIT) && hasSelection())
591                 clearSelection();
592         // Dirty Cast! (Lgb)
593         if (need_update != NONE) {
594                 bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
595                 if (locked) // && (what != NONE))
596                         resetPos(bv);
597         }
598 }
599
600
601 bool InsetTabular::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
602 {
603         lyxerr[Debug::INSETS] << "InsetTabular::LockInsetInInset("
604                               << inset << "): ";
605         if (!inset)
606                 return false;
607         oldcell = -1;
608         if (inset == tabular->GetCellInset(actcell)) {
609                 lyxerr[Debug::INSETS] << "OK" << endl;
610                 the_locking_inset = tabular->GetCellInset(actcell);
611                 resetPos(bv);
612                 return true;
613         } else if (the_locking_inset && (the_locking_inset == inset)) {
614                 lyxerr[Debug::INSETS] << "OK" << endl;
615                 resetPos(bv);
616         } else if (the_locking_inset) {
617                 lyxerr[Debug::INSETS] << "MAYBE" << endl;
618                 return the_locking_inset->lockInsetInInset(bv, inset);
619         }
620         lyxerr[Debug::INSETS] << "NOT OK" << endl;
621         return false;
622 }
623
624
625 bool InsetTabular::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
626                                       bool lr)
627 {
628         if (!the_locking_inset)
629                 return false;
630         if (the_locking_inset == inset) {
631                 the_locking_inset->insetUnlock(bv);
632                 the_locking_inset = 0;
633 #ifdef WITH_WARNINGS
634 #warning fix scrolling when cellinset has requested a scroll (Jug)!!!
635 #endif
636 #if 0
637                 if (scroll(false))
638                         scroll(bv, 0.0F);
639 #endif
640                 updateLocal(bv, CELL, false);
641                 showInsetCursor(bv, false);
642                 return true;
643         }
644         if (the_locking_inset->unlockInsetInInset(bv, inset, lr)) {
645                 if (inset->lyxCode() == TABULAR_CODE &&
646                     !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) {
647                         bv->owner()->getDialogs()->updateTabular(this);
648                         oldcell = actcell;
649                 }
650                 return true;
651         }
652         return false;
653 }
654
655
656 bool InsetTabular::updateInsetInInset(BufferView * bv, Inset * inset)
657 {
658         if (!the_locking_inset)
659                 return false;
660         if (the_locking_inset != inset) {
661                 if (!the_locking_inset->updateInsetInInset(bv, inset))
662                         return false;
663         }
664         updateLocal(bv, CELL, false);
665         return true;
666 }
667
668
669 unsigned int InsetTabular::insetInInsetY()
670 {
671         if (!the_locking_inset)
672                 return 0;
673         
674         return inset_y + the_locking_inset->insetInInsetY();
675 }
676
677
678 UpdatableInset * InsetTabular::getLockingInset() const
679 {
680         return the_locking_inset ? the_locking_inset->getLockingInset() :
681                 const_cast<InsetTabular *>(this);
682 }
683
684
685 UpdatableInset * InsetTabular::getFirstLockingInsetOfType(Inset::Code c)
686 {
687         if (c == lyxCode())
688                 return this;
689         if (the_locking_inset)
690                 return the_locking_inset->getFirstLockingInsetOfType(c);
691         return 0;
692 }
693
694
695 bool InsetTabular::insertInset(BufferView * bv, Inset * inset)
696 {
697         if (the_locking_inset)
698                 return the_locking_inset->insertInset(bv, inset);
699         return false;
700 }
701
702
703 void InsetTabular::insetButtonPress(BufferView * bv, int x, int y, int button)
704 {
705         if (hasSelection() && (button == 3))
706                 return;
707
708         if (hasSelection()) {
709                 clearSelection();
710                 updateLocal(bv, SELECTION, false);
711         }
712
713         no_selection = false;
714
715         int const ocell = actcell;
716         int const orow = actrow;
717
718         hideInsetCursor(bv);
719         setPos(bv, x, y);
720         if (actrow != orow)
721                 updateLocal(bv, NONE, false);
722         sel_cell_start = sel_cell_end = actcell;
723         if (button == 3) {
724                 if ((ocell != actcell) && the_locking_inset) {
725                         the_locking_inset->insetUnlock(bv);
726                         the_locking_inset = 0;
727                 }
728                 showInsetCursor(bv);
729                 return;
730         }
731
732         bool const inset_hit = insetHit(bv, x, y);
733
734         if ((ocell == actcell) && the_locking_inset && inset_hit) {
735                 resetPos(bv);
736                 the_locking_inset->insetButtonPress(bv,
737                                                     x - inset_x, y - inset_y,
738                                                     button);
739                 return;
740         } else if (the_locking_inset) {
741                 the_locking_inset->insetUnlock(bv);
742         }
743         the_locking_inset = 0;
744         if (button == 2) {
745                 localDispatch(bv, LFUN_PASTESELECTION, "paragraph");
746                 return;
747         }
748         if (inset_hit && bv->theLockingInset()) {
749                 if (activateCellInsetAbs(bv, x, y, button))
750                         the_locking_inset->insetButtonPress(bv,
751                                                             x - inset_x,
752                                                             y - inset_y,
753                                                             button);
754                 return;
755         }
756         showInsetCursor(bv);
757 }
758
759
760 void InsetTabular::insetButtonRelease(BufferView * bv,
761                                       int x, int y, int button)
762 {
763         if (button == 3) {
764                 if (the_locking_inset) {
765                         UpdatableInset * i;
766                         if ((i = the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE))) {
767                                 i->insetButtonRelease(bv, x, y, button);
768                                 return;
769                         }
770                 }
771                 bv->owner()->getDialogs()->showTabular(this);
772                 return;
773         }
774         if (the_locking_inset) {
775                 the_locking_inset->insetButtonRelease(bv,
776                                                       x - inset_x, y - inset_y,
777                                                       button);
778                 return;
779         }
780         no_selection = false;
781 }
782
783
784 void InsetTabular::insetMotionNotify(BufferView * bv, int x, int y, int button)
785 {
786         if (the_locking_inset) {
787                 the_locking_inset->insetMotionNotify(bv,
788                                                      x - inset_x,
789                                                      y - inset_y,
790                                                      button);
791                 return;
792         }
793         if (!no_selection) {
794                 hideInsetCursor(bv);
795                 int const old_cell = actcell;
796                 
797                 setPos(bv, x, y);
798                 sel_cell_end = actcell;
799                 if (sel_cell_end != old_cell)
800                         updateLocal(bv, SELECTION, false);
801                 showInsetCursor(bv);
802         }
803         no_selection = false;
804 }
805
806
807 void InsetTabular::insetKeyPress(XKeyEvent * xke)
808 {
809         if (the_locking_inset) {
810                 the_locking_inset->insetKeyPress(xke);
811                 return;
812         }
813 }
814
815
816 UpdatableInset::RESULT
817 InsetTabular::localDispatch(BufferView * bv, kb_action action,
818                             string const & arg)
819 {
820         // We need to save the value of the_locking_inset as the call to 
821         // the_locking_inset->LocalDispatch might unlock it.
822         old_locking_inset = the_locking_inset;
823         no_selection = false;
824         UpdatableInset::RESULT result =
825                 UpdatableInset::localDispatch(bv, action, arg);
826         if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
827                 resetPos(bv);
828                 return result;
829         }
830
831         if ((action < 0) && arg.empty())
832                 return FINISHED;
833
834         bool hs = hasSelection();
835
836         result = DISPATCHED;
837         // this one have priority over the locked InsetText, if we're not already
838         // inside another tabular then that one get's priority!
839         if (getFirstLockingInsetOfType(Inset::TABULAR_CODE) == this) {
840                 switch (action) {
841                 case LFUN_SHIFT_TAB:
842                 case LFUN_TAB:
843                         hideInsetCursor(bv);
844                         if (the_locking_inset) {
845                                 unlockInsetInInset(bv, the_locking_inset);
846                                 the_locking_inset = 0;
847                         }
848                         if (action == LFUN_TAB)
849                                 moveNextCell(bv, old_locking_inset != 0);
850                         else
851                                 movePrevCell(bv, old_locking_inset != 0);
852                         sel_cell_start = sel_cell_end = actcell;
853                         if (hs)
854                                 updateLocal(bv, SELECTION, false);
855                         if (!the_locking_inset) {
856                                 showInsetCursor(bv);
857                                 return DISPATCHED_NOUPDATE;
858                         }
859                         return result;
860                 // this to avoid compiler warnings.
861                 default:
862                         break;
863                 }
864         }
865
866         if (the_locking_inset) {
867                 result = the_locking_inset->localDispatch(bv, action, arg);
868                 if (result == DISPATCHED_NOUPDATE) {
869                         int sc = scroll();
870                         resetPos(bv);
871                         if (sc != scroll()) { // inset has been scrolled
872                                 the_locking_inset->toggleInsetCursor(bv);
873                                 updateLocal(bv, FULL, false);
874                                 the_locking_inset->toggleInsetCursor(bv);
875                         }
876                         return result;
877                 } else if (result == DISPATCHED) {
878                         the_locking_inset->toggleInsetCursor(bv);
879                         updateLocal(bv, CELL, false);
880                         the_locking_inset->toggleInsetCursor(bv);
881                         return result;
882                 } else if (result == FINISHED_UP) {
883                         action = LFUN_UP;
884                 } else if (result == FINISHED_DOWN) {
885                         action = LFUN_DOWN;
886                 } else if (result == FINISHED_RIGHT) {
887                         action = LFUN_RIGHT;
888                 }
889         }
890
891         hideInsetCursor(bv);
892         result=DISPATCHED;
893         switch (action) {
894                 // --- Cursor Movements ----------------------------------
895         case LFUN_RIGHTSEL:
896                 if (tabular->IsLastCellInRow(actcell))
897                         break;
898                 moveRight(bv, false);
899                 sel_cell_end = actcell;
900                 updateLocal(bv, SELECTION, false);
901                 break;
902         case LFUN_RIGHT:
903                 result = moveRight(bv);
904                 sel_cell_start = sel_cell_end = actcell;
905                 if (hs)
906                         updateLocal(bv, SELECTION, false);
907                 break;
908         case LFUN_LEFTSEL:
909                 if (tabular->IsFirstCellInRow(actcell))
910                         break;
911                 moveLeft(bv, false);
912                 sel_cell_end = actcell;
913                 updateLocal(bv, SELECTION, false);
914                 break;
915         case LFUN_LEFT:
916                 result = moveLeft(bv);
917                 sel_cell_start = sel_cell_end = actcell;
918                 if (hs)
919                         updateLocal(bv, SELECTION, false);
920                 break;
921         case LFUN_DOWNSEL:
922         {
923                 int const ocell = actcell;
924                 moveDown(bv, false);
925                 if ((ocell == sel_cell_end) ||
926                     (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
927                         sel_cell_end = tabular->GetCellBelow(sel_cell_end);
928                 else
929                         sel_cell_end = tabular->GetLastCellBelow(sel_cell_end);
930                 updateLocal(bv, SELECTION, false);
931         }
932         break;
933         case LFUN_DOWN:
934                 result = moveDown(bv, old_locking_inset != 0);
935                 sel_cell_start = sel_cell_end = actcell;
936                 if (hs)
937                         updateLocal(bv, SELECTION, false);
938                 break;
939         case LFUN_UPSEL:
940         {
941                 int const ocell = actcell;
942                 moveUp(bv, false);
943                 if ((ocell == sel_cell_end) ||
944                     (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
945                         sel_cell_end = tabular->GetCellAbove(sel_cell_end);
946                 else
947                         sel_cell_end = tabular->GetLastCellAbove(sel_cell_end);
948                 updateLocal(bv, SELECTION, false);
949         }
950         break;
951         case LFUN_UP:
952                 result = moveUp(bv, old_locking_inset != 0);
953                 sel_cell_start = sel_cell_end = actcell;
954                 if (hs)
955                         updateLocal(bv, SELECTION, false);
956                 break;
957         case LFUN_NEXT: {
958                 int column = actcol;
959                 if (the_locking_inset) {
960                         unlockInsetInInset(bv, the_locking_inset);
961                         the_locking_inset = 0;
962                 }
963                 if (bv->text->first + bv->painter().paperHeight() <
964                     (top_baseline + tabular->GetHeightOfTabular()))
965                         {
966                                 bv->scrollCB(bv->text->first + bv->painter().paperHeight());
967                                 updateLocal(bv, FULL, false);
968                                 actcell = tabular->GetCellBelow(first_visible_cell) + column;
969                         } else {
970                                 actcell = tabular->GetFirstCellInRow(tabular->rows() - 1) + column;
971                         }
972                 resetPos(bv);
973                 updateLocal(bv, CURSOR, false);
974                 break;
975         }
976         case LFUN_PRIOR: {
977                 int column = actcol;
978                 if (the_locking_inset) {
979                         unlockInsetInInset(bv, the_locking_inset);
980                         the_locking_inset = 0;
981                 }
982                 if (top_baseline < 0) {
983                         bv->scrollCB(bv->text->first - bv->painter().paperHeight());
984                         updateLocal(bv, FULL, false);
985                         if (top_baseline > 0)
986                                 actcell = column;
987                         else
988                                 actcell = tabular->GetCellBelow(first_visible_cell) + column;
989                 } else {
990                         actcell = column;
991                 }
992                 resetPos(bv);
993                 updateLocal(bv, CURSOR, false);
994                 break;
995         }
996         case LFUN_BACKSPACE:
997                 break;
998         case LFUN_DELETE:
999                 break;
1000         case LFUN_HOME:
1001                 break;
1002         case LFUN_END:
1003                 break;
1004         case LFUN_LAYOUT_TABULAR:
1005         {
1006                 bv->owner()->getDialogs()->showTabular(this);
1007         }
1008         break;
1009         case LFUN_TABULAR_FEATURE:
1010                 if (!tabularFeatures(bv, arg))
1011                         result = UNDISPATCHED;
1012                 break;
1013         case LFUN_CUT:
1014                 if (!copySelection(bv))
1015                         break;
1016                 setUndo(bv, Undo::DELETE,
1017                         bv->text->cursor.par(),
1018                         bv->text->cursor.par()->next());
1019                 cutSelection();
1020                 updateLocal(bv, INIT, true);
1021                 break;
1022         case LFUN_COPY:
1023                 if (!hasSelection())
1024                         break;
1025                 finishUndo();
1026                 copySelection(bv);
1027                 break;
1028         case LFUN_PASTESELECTION:
1029         {
1030                 string const clip(bv->getClipboard());
1031         
1032                 if (clip.empty())
1033                         break;
1034                 if (clip.find('\t') != string::npos) {
1035                         int cols = 1;
1036                         int rows = 1;
1037                         int maxCols = 1;
1038                         string::size_type len = clip.length();
1039                         string::size_type p = 0;
1040
1041                         while(p < len &&
1042                               ((p = clip.find_first_of("\t\n", p)) != string::npos)) {
1043                                 switch(clip[p]) {
1044                                 case '\t':
1045                                         ++cols;
1046                                         break;
1047                                 case '\n':
1048                                         if ((p+1) < len)
1049                                                 ++rows;
1050                                         maxCols = max(cols, maxCols);
1051                                         cols = 1;
1052                                         break;
1053                                 }
1054                                 ++p;
1055                         }
1056                         maxCols = max(cols, maxCols);
1057                         delete paste_tabular;
1058                         paste_tabular = new LyXTabular(this, rows, maxCols);
1059                         string::size_type op = 0;
1060                         int cell = 0;
1061                         int cells = paste_tabular->GetNumberOfCells();
1062                         p = cols = 0;
1063                         while((cell < cells) && (p < len) &&
1064                               (p = clip.find_first_of("\t\n", p)) != string::npos) {
1065                                 if (p >= len)
1066                                         break;
1067                                 switch(clip[p]) {
1068                                 case '\t':
1069                                         paste_tabular->GetCellInset(cell)->setText(clip.substr(op, p-op));
1070                                         ++cols;
1071                                         ++cell;
1072                                         break;
1073                                 case '\n':
1074                                         paste_tabular->GetCellInset(cell)->setText(clip.substr(op, p-op));
1075                                         while(cols++ < maxCols)
1076                                                 ++cell;
1077                                         cols = 0;
1078                                         break;
1079                                 }
1080                                 ++p;
1081                                 op = p;
1082                         }
1083                         // check for the last cell if there is no trailing '\n'
1084                         if ((cell < cells) && (op < len))
1085                                 paste_tabular->GetCellInset(cell)->setText(clip.substr(op, len-op));
1086                 } else {
1087                         // so that the clipboard is used and it goes on
1088                         // to default
1089                         // and executes LFUN_PASTESELECTION in insettext!
1090                         delete paste_tabular;
1091                         paste_tabular = 0;
1092                 }
1093         }
1094         case LFUN_PASTE:
1095                 if (hasPasteBuffer()) {
1096                         setUndo(bv, Undo::INSERT,
1097                                 bv->text->cursor.par(),
1098                                 bv->text->cursor.par()->next());
1099                         pasteSelection(bv);
1100                         updateLocal(bv, INIT, true);
1101                         break;
1102                 }
1103                 // ATTENTION: the function above has to be PASTE and PASTESELECTION!!!
1104         default:
1105                 // we try to activate the actual inset and put this event down to
1106                 // the insets dispatch function.
1107                 result = UNDISPATCHED;
1108                 if (the_locking_inset)
1109                         break;
1110                 nodraw(true);
1111                 if (activateCellInset(bv)) {
1112                         // reset need_update setted in above function!
1113                         need_update = NONE;
1114                         result = the_locking_inset->localDispatch(bv, action, arg);
1115                         if ((result == UNDISPATCHED) || (result >= FINISHED)) {
1116                                 unlockInsetInInset(bv, the_locking_inset);
1117                                 nodraw(false);
1118                                 the_locking_inset = 0;
1119                                 // we need to update if this was requested before
1120                                 updateLocal(bv, NONE, false);
1121                                 return UNDISPATCHED;
1122                         } else if (hs) {
1123                                 clearSelection();
1124                         }
1125                         nodraw(false);
1126                         updateLocal(bv, CELL, false);
1127                         return result;
1128                 }
1129                 break;
1130         }
1131         if (result < FINISHED) {
1132                 if (!the_locking_inset) {
1133                         showInsetCursor(bv);
1134                 }
1135         } else
1136                 bv->unlockInset(this);
1137         return result;
1138 }
1139
1140
1141 int InsetTabular::latex(Buffer const * buf, ostream & os,
1142                         bool fragile, bool fp) const
1143 {
1144         return tabular->Latex(buf, os, fragile, fp);
1145 }
1146
1147
1148 int InsetTabular::ascii(Buffer const * buf, ostream & os, int) const
1149 {
1150         // This should be changed to a real ascii export
1151         return tabular->Ascii(buf, os);
1152 }
1153
1154
1155 int InsetTabular::linuxdoc(Buffer const * buf, ostream & os) const
1156 {
1157         return tabular->Ascii(buf,os);
1158 }
1159
1160
1161 int InsetTabular::docbook(Buffer const * buf, ostream & os) const
1162 {
1163         int ret = 0;
1164         Inset * master;
1165
1166         // if the table is inside a float it doesn't need the informaltable
1167         // wrapper. Search for it.
1168         for(master = owner();
1169             master && master->lyxCode() != Inset::FLOAT_CODE;
1170             master = master->owner());
1171
1172         if (!master) {
1173                 os << "<informaltable>\n";
1174                 ret++;
1175         }
1176         ret+= tabular->DocBook(buf,os);
1177         if (!master) {
1178                 os << "</informaltable>\n";
1179                 ret++;
1180         }
1181         return ret;
1182 }
1183
1184
1185 void InsetTabular::validate(LaTeXFeatures & features) const
1186 {
1187         tabular->Validate(features);
1188 }
1189
1190
1191 bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
1192                                                  LyXFont const & font,
1193                                                  bool reinit) const
1194 {
1195         int cell = -1;
1196         int maxAsc = 0;
1197         int maxDesc = 0;
1198         InsetText * inset;
1199         bool changed = false;
1200         
1201         // if we have a locking_inset we should have to check only this cell for
1202         // change so I'll try this to have a boost, but who knows ;)
1203         if ((need_update != INIT) &&
1204             (the_locking_inset == tabular->GetCellInset(actcell))) {
1205                 for(int i = 0; i < tabular->columns(); ++i) {
1206                         maxAsc = max(tabular->GetCellInset(actrow, i)->ascent(bv, font),
1207                                      maxAsc);
1208                         maxDesc = max(tabular->GetCellInset(actrow, i)->descent(bv, font),
1209                                       maxDesc);
1210                 }
1211                 changed = tabular->SetWidthOfCell(actcell, the_locking_inset->width(bv, font));
1212                 changed = tabular->SetAscentOfRow(actrow, maxAsc + ADD_TO_HEIGHT) || changed;
1213                 changed = tabular->SetDescentOfRow(actrow, maxDesc + ADD_TO_HEIGHT) || changed;
1214                 return changed;
1215         }
1216         for (int i = 0; i < tabular->rows(); ++i) {
1217                 maxAsc = 0;
1218                 maxDesc = 0;
1219                 for (int j = 0; j < tabular->columns(); ++j) {
1220                         if (tabular->IsPartOfMultiColumn(i,j))
1221                                 continue;
1222                         ++cell;
1223                         inset = tabular->GetCellInset(cell);
1224                         if (!reinit && !tabular->GetPWidth(cell).empty())
1225                                 inset->update(bv, font, false);
1226                         maxAsc = max(maxAsc, inset->ascent(bv, font));
1227                         maxDesc = max(maxDesc, inset->descent(bv, font));
1228                         changed = tabular->SetWidthOfCell(cell, inset->width(bv, font)) || changed;
1229                 }
1230                 changed = tabular->SetAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
1231                 changed = tabular->SetDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
1232         }
1233         return changed;
1234 }
1235
1236
1237 void InsetTabular::getCursorPos(BufferView * bv, int & x, int & y) const
1238 {
1239         if (the_locking_inset) {
1240                 the_locking_inset->getCursorPos(bv, x, y);
1241                 return;
1242         }
1243         x = cursor_.x() - top_x;
1244         y = cursor_.y();
1245 }
1246
1247
1248 void InsetTabular::toggleInsetCursor(BufferView * bv)
1249 {
1250         if (the_locking_inset) {
1251                 the_locking_inset->toggleInsetCursor(bv);
1252                 return;
1253         }
1254         
1255         LyXFont font; // = the_locking_inset->GetFont(par, cursor.pos);
1256         
1257         int const asc = lyxfont::maxAscent(font);
1258         int const desc = lyxfont::maxDescent(font);
1259         
1260         if (isCursorVisible())
1261                 bv->hideLockedInsetCursor();
1262         else
1263                 bv->showLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1264         toggleCursorVisible();
1265 }
1266
1267
1268 void InsetTabular::showInsetCursor(BufferView * bv, bool show)
1269 {
1270         if (!isCursorVisible()) {
1271                 LyXFont font; // = GetFont(par, cursor.pos);
1272         
1273                 int const asc = lyxfont::maxAscent(font);
1274                 int const desc = lyxfont::maxDescent(font);
1275                 bv->fitLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1276                 if (show)
1277                         bv->showLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1278                 setCursorVisible(true);
1279         }
1280 }
1281
1282
1283 void InsetTabular::hideInsetCursor(BufferView * bv)
1284 {
1285         if (isCursorVisible()) {
1286                 bv->hideLockedInsetCursor();
1287                 setCursorVisible(false);
1288         }
1289 }
1290
1291
1292 void InsetTabular::fitInsetCursor(BufferView * bv) const
1293 {
1294         if (the_locking_inset) {
1295                 the_locking_inset->fitInsetCursor(bv);
1296                 return;
1297         }
1298         LyXFont font;
1299         
1300         int const asc = lyxfont::maxAscent(font);
1301         int const desc = lyxfont::maxDescent(font);
1302         bv->fitLockedInsetCursor(cursor_.x(), cursor_.y(), asc, desc);
1303 }
1304
1305
1306 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1307 {
1308         cursor_.y(0);
1309         
1310         actcell = actrow = actcol = 0;
1311         int ly = tabular->GetDescentOfRow(actrow);
1312
1313         // first search the right row
1314         while((ly < y) && ((actrow+1) < tabular->rows())) {
1315                 cursor_.y(cursor_.y() + tabular->GetDescentOfRow(actrow) +
1316                                  tabular->GetAscentOfRow(actrow + 1) +
1317                                  tabular->GetAdditionalHeight(actrow + 1));
1318                 ++actrow;
1319                 ly = cursor_.y() + tabular->GetDescentOfRow(actrow);
1320         }
1321         actcell = tabular->GetCellNumber(actrow, actcol);
1322
1323         // now search the right column
1324         int lx = tabular->GetWidthOfColumn(actcell) -
1325                 tabular->GetAdditionalWidth(actcell);
1326         for (; !tabular->IsLastCellInRow(actcell) && lx < x; ++actcell) {
1327                 lx += tabular->GetWidthOfColumn(actcell + 1)
1328                         + tabular->GetAdditionalWidth(actcell);
1329         }
1330         cursor_.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
1331         resetPos(bv);
1332 }
1333
1334
1335 int InsetTabular::getCellXPos(int cell) const
1336 {
1337         int c = cell;
1338         
1339         for (; !tabular->IsFirstCellInRow(c); --c)
1340                 ;
1341         int lx = tabular->GetWidthOfColumn(cell);
1342         for (; c < cell; ++c) {
1343                 lx += tabular->GetWidthOfColumn(c);
1344         }
1345         return (lx - tabular->GetWidthOfColumn(cell) + top_x);
1346 }
1347
1348
1349 void InsetTabular::resetPos(BufferView * bv) const
1350 {
1351         if (!locked || nodraw())
1352                 return;
1353         actcol = tabular->column_of_cell(actcell);
1354
1355         int cell = 0;
1356         actrow = 0;
1357         cursor_.y(0);
1358         for (; (cell < actcell) && !tabular->IsLastRow(cell); ++cell) {
1359                 if (tabular->IsLastCellInRow(cell)) {
1360                         cursor_.y(cursor_.y() + tabular->GetDescentOfRow(actrow) +
1361                                          tabular->GetAscentOfRow(actrow + 1) +
1362                                          tabular->GetAdditionalHeight(actrow + 1));
1363                         ++actrow;
1364                 }
1365         }
1366         static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1367         int new_x = getCellXPos(actcell);
1368         int old_x = cursor_.x();
1369         new_x += offset;
1370         cursor_.x(new_x);
1371 //    cursor.x(getCellXPos(actcell) + offset);
1372         if ((actcol < tabular->columns()-1) && scroll(false) &&
1373                 (tabular->GetWidthOfTabular() < bv->workWidth()-20))
1374         {
1375                 scroll(bv, 0.0F);
1376                 updateLocal(bv, FULL, false);
1377         } else if (the_locking_inset &&
1378                  (tabular->GetWidthOfColumn(actcell) > bv->workWidth()-20))
1379         {
1380                 int xx = cursor_.x() - offset + bv->text->getRealCursorX(bv);
1381                 if (xx > (bv->workWidth()-20)) {
1382                         scroll(bv, -(xx - bv->workWidth() + 60));
1383                         updateLocal(bv, FULL, false);
1384                 } else if (xx < 20) {
1385                         if (xx < 0)
1386                                 xx = -xx + 60;
1387                         else
1388                                 xx = 60;
1389                         scroll(bv, xx);
1390                         updateLocal(bv, FULL, false);
1391                 }
1392         } else if ((cursor_.x() - offset) > 20 &&
1393                    (cursor_.x() - offset + tabular->GetWidthOfColumn(actcell))
1394                    > (bv->workWidth() - 20)) {
1395                 scroll(bv, -tabular->GetWidthOfColumn(actcell) - 20);
1396                 updateLocal(bv, FULL, false);
1397         } else if ((cursor_.x() - offset) < 20) {
1398                 scroll(bv, 20 - cursor_.x() + offset);
1399                 updateLocal(bv, FULL, false);
1400         } else if (scroll(false) && top_x > 20 &&
1401                    (top_x + tabular->GetWidthOfTabular()) > (bv->workWidth() - 20)) {
1402                 scroll(bv, old_x - cursor_.x());
1403                 updateLocal(bv, FULL, false);
1404         }
1405         if (the_locking_inset) {
1406                 inset_x = cursor_.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
1407                 inset_y = cursor_.y();
1408         }
1409         if ((!the_locking_inset ||
1410              !the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE)) &&
1411             actcell != oldcell) {
1412                 InsetTabular * inset = const_cast<InsetTabular *>(this);
1413                 bv->owner()->getDialogs()->updateTabular(inset);
1414                 oldcell = actcell;
1415         }
1416 }
1417
1418
1419 UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1420 {
1421         if (lock && !old_locking_inset) {
1422                 if (activateCellInset(bv))
1423                         return DISPATCHED;
1424         } else {
1425                 bool moved = isRightToLeft(bv)
1426                         ? movePrevCell(bv) : moveNextCell(bv);
1427                 if (!moved)
1428                         return FINISHED_RIGHT;
1429                 if (lock && activateCellInset(bv))
1430                         return DISPATCHED;
1431         }
1432         resetPos(bv);
1433         return DISPATCHED_NOUPDATE;
1434 }
1435
1436
1437 UpdatableInset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1438 {
1439         bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
1440         if (!moved)
1441                 return FINISHED;
1442         if (lock) {       // behind the inset
1443                 if (activateCellInset(bv, 0, 0, 0, true))
1444                         return DISPATCHED;
1445         }
1446         resetPos(bv);
1447         return DISPATCHED_NOUPDATE;
1448 }
1449
1450
1451 UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv, bool lock)
1452 {
1453         int const ocell = actcell;
1454         actcell = tabular->GetCellAbove(actcell);
1455         if (actcell == ocell) // we moved out of the inset
1456                 return FINISHED_UP;
1457         resetPos(bv);
1458         if (lock) {
1459                 int x = 0;
1460                 int y = 0;
1461                 if (old_locking_inset) {
1462                         old_locking_inset->getCursorPos(bv, x, y);
1463                         x -= cursor_.x() + tabular->GetBeginningOfTextInCell(actcell);
1464                 }
1465                 if (activateCellInset(bv, x, 0))
1466                         return DISPATCHED;
1467         }
1468         return DISPATCHED_NOUPDATE;
1469 }
1470
1471
1472 UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv, bool lock)
1473 {
1474         int const ocell = actcell;
1475         actcell = tabular->GetCellBelow(actcell);
1476         if (actcell == ocell) // we moved out of the inset
1477                 return FINISHED_DOWN;
1478         resetPos(bv);
1479         if (lock) {
1480                 int x = 0;
1481                 int y = 0;
1482                 if (old_locking_inset) {
1483                         old_locking_inset->getCursorPos(bv, x, y);
1484                         x -= cursor_.x() + tabular->GetBeginningOfTextInCell(actcell);
1485                 }
1486                 if (activateCellInset(bv, x, 0))
1487                         return DISPATCHED;
1488         }
1489         return DISPATCHED_NOUPDATE;
1490 }
1491
1492
1493 bool InsetTabular::moveNextCell(BufferView * bv, bool lock)
1494 {
1495         if (isRightToLeft(bv)) {
1496                 if (tabular->IsFirstCellInRow(actcell)) {
1497                         int row = tabular->row_of_cell(actcell);
1498                         if (row == tabular->rows() - 1)
1499                                 return false;
1500                         actcell = tabular->GetLastCellInRow(row);
1501                         actcell = tabular->GetCellBelow(actcell);
1502                 } else {
1503                         if (!actcell)
1504                                 return false;
1505                         --actcell;
1506                 }
1507         } else {
1508                 if (tabular->IsLastCell(actcell))
1509                         return false;
1510                 ++actcell;
1511         }
1512         if (lock) {
1513                 bool rtl = tabular->GetCellInset(actcell)->paragraph()->
1514                         isRightToLeftPar(bv->buffer()->params);
1515                 activateCellInset(bv, 0, 0, 0, !rtl);
1516         }
1517         resetPos(bv);
1518         return true;
1519 }
1520
1521
1522 bool InsetTabular::movePrevCell(BufferView * bv, bool lock)
1523 {
1524         if (isRightToLeft(bv)) {
1525                 if (tabular->IsLastCellInRow(actcell)) {
1526                         int row = tabular->row_of_cell(actcell);
1527                         if (row == 0)
1528                                 return false;
1529                         actcell = tabular->GetFirstCellInRow(row);
1530                         actcell = tabular->GetCellAbove(actcell);
1531                 } else {
1532                         if (tabular->IsLastCell(actcell))
1533                                 return false;
1534                         ++actcell;
1535                 }
1536         } else {
1537                 if (!actcell) // first cell
1538                         return false;
1539                 --actcell;
1540         }
1541         if (lock) {
1542                 bool rtl = tabular->GetCellInset(actcell)->paragraph()->
1543                         isRightToLeftPar(bv->buffer()->params);
1544                 activateCellInset(bv, 0, 0, 0, !rtl);
1545         }
1546         resetPos(bv);
1547         return true;
1548 }
1549
1550
1551 bool InsetTabular::deletable() const
1552 {
1553         return true;
1554 }
1555
1556
1557 void InsetTabular::setFont(BufferView * bv, LyXFont const & font, bool tall,
1558                            bool selectall)
1559 {
1560         if (selectall) {
1561                 sel_cell_start = 0;
1562                 sel_cell_end = tabular->GetNumberOfCells() - 1;
1563         }
1564         if (hasSelection()) {
1565                 setUndo(bv, Undo::EDIT,
1566                         bv->text->cursor.par(),
1567                         bv->text->cursor.par()->next());
1568                 bool frozen = undo_frozen;
1569                 if (!frozen)
1570                         freezeUndo();
1571                 // apply the fontchange on the whole selection
1572                 int sel_row_start;
1573                 int sel_row_end;
1574                 int sel_col_start;
1575                 int sel_col_end;
1576                 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1577                 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1578                         for(int j = sel_col_start; j <= sel_col_end; ++j) {
1579                                 tabular->GetCellInset(i, j)->setFont(bv, font, tall, true);
1580                         }
1581                 }
1582                 if (!frozen)
1583                         unFreezeUndo();
1584                 updateLocal(bv, INIT, true);
1585         }
1586         if (the_locking_inset)
1587                 the_locking_inset->setFont(bv, font, tall);
1588 }
1589
1590
1591 bool InsetTabular::tabularFeatures(BufferView * bv, string const & what)
1592 {
1593         LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1594         
1595         int i = 0;
1596         for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
1597                 string const tmp = tabularFeature[i].feature;
1598                 
1599                 if (tmp == what.substr(0, tmp.length())) {
1600                         //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
1601                         //tabularFeatures[i].feature.length())) {
1602                         action = tabularFeature[i].action;
1603                         break;
1604                 }
1605         }
1606         if (action == LyXTabular::LAST_ACTION)
1607                 return false;
1608
1609         string const val =
1610                 frontStrip(what.substr(tabularFeature[i].feature.length()));
1611         tabularFeatures(bv, action, val);
1612         return true;
1613 }
1614
1615
1616 void InsetTabular::tabularFeatures(BufferView * bv,
1617                                    LyXTabular::Feature feature,
1618                                    string const & value)
1619 {
1620         int sel_col_start;
1621         int sel_col_end;
1622         int sel_row_start;
1623         int sel_row_end;
1624         bool setLines = false;
1625         LyXAlignment setAlign = LYX_ALIGN_LEFT;
1626         LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1627
1628         switch (feature) {
1629         case LyXTabular::M_ALIGN_LEFT:
1630         case LyXTabular::ALIGN_LEFT:
1631                 setAlign=LYX_ALIGN_LEFT;
1632                 break;
1633         case LyXTabular::M_ALIGN_RIGHT:
1634         case LyXTabular::ALIGN_RIGHT:
1635                 setAlign=LYX_ALIGN_RIGHT;
1636                 break;
1637         case LyXTabular::M_ALIGN_CENTER:
1638         case LyXTabular::ALIGN_CENTER:
1639                 setAlign=LYX_ALIGN_CENTER;
1640                 break;
1641         case LyXTabular::M_VALIGN_TOP:
1642         case LyXTabular::VALIGN_TOP:
1643                 setVAlign=LyXTabular::LYX_VALIGN_TOP;
1644                 break;
1645         case LyXTabular::M_VALIGN_BOTTOM:
1646         case LyXTabular::VALIGN_BOTTOM:
1647                 setVAlign=LyXTabular::LYX_VALIGN_BOTTOM;
1648                 break;
1649         case LyXTabular::M_VALIGN_CENTER:
1650         case LyXTabular::VALIGN_CENTER:
1651                 setVAlign=LyXTabular::LYX_VALIGN_CENTER;
1652                 break;
1653         default:
1654                 break;
1655         }
1656         if (hasSelection()) {
1657                 getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
1658         } else {
1659                 sel_col_start = sel_col_end = tabular->column_of_cell(actcell);
1660                 sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1661         }
1662         setUndo(bv, Undo::FINISH,
1663                 bv->text->cursor.par(),
1664                 bv->text->cursor.par()->next());
1665
1666         LyXTabular::ltType ltt;
1667         int row = ltt.row = tabular->row_of_cell(actcell);
1668         int column = tabular->column_of_cell(actcell);
1669         bool flag = true;
1670
1671         switch (feature) {
1672         case LyXTabular::SET_PWIDTH:
1673         {
1674                 bool const update = (tabular->GetColumnPWidth(actcell) != value);
1675                 tabular->SetColumnPWidth(actcell,value);
1676                 if (update) {
1677                         for (int i = 0; i < tabular->rows(); ++i) {
1678                                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1679                                         resizeLyXText(bv);
1680                         }
1681                         updateLocal(bv, INIT, true);
1682                 }
1683         }
1684         break;
1685         case LyXTabular::SET_MPWIDTH:
1686         {
1687                 bool const update = (tabular->GetPWidth(actcell) != value);
1688                 tabular->SetMColumnPWidth(actcell,value);
1689                 if (update) {
1690                         for (int i = 0; i < tabular->rows(); ++i) {
1691                                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1692                                         resizeLyXText(bv);
1693                         }
1694                         updateLocal(bv, INIT, true);
1695                 }
1696         }
1697         break;
1698         case LyXTabular::SET_SPECIAL_COLUMN:
1699         case LyXTabular::SET_SPECIAL_MULTI:
1700                 tabular->SetAlignSpecial(actcell,value,feature);
1701                 updateLocal(bv, FULL, true);
1702                 break;
1703         case LyXTabular::APPEND_ROW:
1704                 // append the row into the tabular
1705                 unlockInsetInInset(bv, the_locking_inset);
1706                 tabular->AppendRow(actcell);
1707                 updateLocal(bv, INIT, true);
1708                 break;
1709         case LyXTabular::APPEND_COLUMN:
1710                 // append the column into the tabular
1711                 unlockInsetInInset(bv, the_locking_inset);
1712                 tabular->AppendColumn(actcell);
1713                 actcell = tabular->GetCellNumber(row, column);
1714                 updateLocal(bv, INIT, true);
1715                 break;
1716         case LyXTabular::DELETE_ROW:
1717                 unlockInsetInInset(bv, the_locking_inset);
1718                 for(int i = sel_row_start; i <= sel_row_end; ++i) {
1719                         tabular->DeleteRow(sel_row_start);
1720                 }
1721                 if (sel_row_start >= tabular->rows())
1722                         --sel_row_start;
1723                 actcell = tabular->GetCellNumber(sel_row_start, column);
1724                 clearSelection();
1725                 updateLocal(bv, INIT, true);
1726                 break;
1727         case LyXTabular::DELETE_COLUMN:
1728                 unlockInsetInInset(bv, the_locking_inset);
1729                 for(int i = sel_col_start; i <= sel_col_end; ++i) {
1730                         tabular->DeleteColumn(sel_col_start);
1731                 }
1732                 if (sel_col_start >= tabular->columns())
1733                         --sel_col_start;
1734                 actcell = tabular->GetCellNumber(row, sel_col_start);
1735                 clearSelection();
1736                 updateLocal(bv, INIT, true);
1737                 break;
1738         case LyXTabular::M_TOGGLE_LINE_TOP:
1739                 flag = false;
1740         case LyXTabular::TOGGLE_LINE_TOP:
1741         {
1742                 bool lineSet = !tabular->TopLine(actcell, flag);
1743                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1744                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1745                                 tabular->SetTopLine(
1746                                         tabular->GetCellNumber(i, j),
1747                                         lineSet, flag);
1748                 updateLocal(bv, INIT, true);
1749                 break;
1750         }
1751         
1752         case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1753                 flag = false;
1754         case LyXTabular::TOGGLE_LINE_BOTTOM:
1755         {
1756                 bool lineSet = !tabular->BottomLine(actcell, flag); 
1757                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1758                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1759                                 tabular->SetBottomLine(
1760                                         tabular->GetCellNumber(i, j),
1761                                         lineSet,
1762                                         flag);
1763                 updateLocal(bv, INIT, true);
1764                 break;
1765         }
1766         
1767         case LyXTabular::M_TOGGLE_LINE_LEFT:
1768                 flag = false;
1769         case LyXTabular::TOGGLE_LINE_LEFT:
1770         {
1771                 bool lineSet = !tabular->LeftLine(actcell, flag);
1772                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1773                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1774                                 tabular->SetLeftLine(
1775                                         tabular->GetCellNumber(i,j),
1776                                         lineSet,
1777                                         flag);
1778                 updateLocal(bv, INIT, true);
1779                 break;
1780         }
1781         
1782         case LyXTabular::M_TOGGLE_LINE_RIGHT:
1783                 flag = false;
1784         case LyXTabular::TOGGLE_LINE_RIGHT:
1785         {
1786                 bool lineSet = !tabular->RightLine(actcell, flag);
1787                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1788                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1789                                 tabular->SetRightLine(
1790                                         tabular->GetCellNumber(i,j),
1791                                         lineSet,
1792                                         flag);
1793                 updateLocal(bv, INIT, true);
1794                 break;
1795         }
1796         
1797         case LyXTabular::M_ALIGN_LEFT:
1798         case LyXTabular::M_ALIGN_RIGHT:
1799         case LyXTabular::M_ALIGN_CENTER:
1800                 flag = false;
1801         case LyXTabular::ALIGN_LEFT:
1802         case LyXTabular::ALIGN_RIGHT:
1803         case LyXTabular::ALIGN_CENTER:
1804                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1805                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1806                                 tabular->SetAlignment(
1807                                         tabular->GetCellNumber(i, j),
1808                                         setAlign,
1809                                         flag);
1810                 updateLocal(bv, INIT, true);
1811                 break;
1812         case LyXTabular::M_VALIGN_TOP:
1813         case LyXTabular::M_VALIGN_BOTTOM:
1814         case LyXTabular::M_VALIGN_CENTER:
1815                 flag = false;
1816         case LyXTabular::VALIGN_TOP:
1817         case LyXTabular::VALIGN_BOTTOM:
1818         case LyXTabular::VALIGN_CENTER:
1819                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1820                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1821                                 tabular->SetVAlignment(
1822                                         tabular->GetCellNumber(i, j),
1823                                         setVAlign, flag);
1824                 updateLocal(bv, INIT, true);
1825                 break;
1826         case LyXTabular::MULTICOLUMN:
1827         {
1828                 if (sel_row_start != sel_row_end) {
1829                         Alert::alert(_("Impossible Operation!"), 
1830                                    _("Multicolumns can only be horizontally."), 
1831                                    _("Sorry."));
1832                         return;
1833                 }
1834                 // just multicol for one Single Cell
1835                 if (!hasSelection()) {
1836                         // check wether we are completly in a multicol
1837                         if (tabular->IsMultiColumn(actcell)) {
1838                                 tabular->UnsetMultiColumn(actcell);
1839                                 updateLocal(bv, INIT, true);
1840                         } else {
1841                                 tabular->SetMultiColumn(actcell, 1);
1842                                 updateLocal(bv, CELL, true);
1843                         }
1844                         return;
1845                 }
1846                 // we have a selection so this means we just add all this
1847                 // cells to form a multicolumn cell
1848                 int s_start;
1849                 int s_end;
1850
1851                 if (sel_cell_start > sel_cell_end) {
1852                         s_start = sel_cell_end;
1853                         s_end = sel_cell_start;
1854                 } else {
1855                         s_start = sel_cell_start;
1856                         s_end = sel_cell_end;
1857                 }
1858                 tabular->SetMultiColumn(s_start, s_end - s_start + 1);
1859                 actcell = s_start;
1860                 sel_cell_end = sel_cell_start;
1861                 updateLocal(bv, INIT, true);
1862                 break;
1863         }
1864         case LyXTabular::SET_ALL_LINES:
1865                 setLines = true;
1866         case LyXTabular::UNSET_ALL_LINES:
1867                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1868                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1869                                 tabular->SetAllLines(
1870                                         tabular->GetCellNumber(i,j), setLines);
1871                 updateLocal(bv, INIT, true);
1872                 break;
1873         case LyXTabular::SET_LONGTABULAR:
1874                 tabular->SetLongTabular(true);
1875                 updateLocal(bv, INIT, true); // because this toggles displayed
1876                 break;
1877         case LyXTabular::UNSET_LONGTABULAR:
1878                 tabular->SetLongTabular(false);
1879                 updateLocal(bv, INIT, true); // because this toggles displayed
1880                 break;
1881         case LyXTabular::SET_ROTATE_TABULAR:
1882                 tabular->SetRotateTabular(true);
1883                 break;
1884         case LyXTabular::UNSET_ROTATE_TABULAR:
1885                 tabular->SetRotateTabular(false);
1886                 break;
1887         case LyXTabular::SET_ROTATE_CELL:
1888                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1889                         for (int j = sel_col_start; j<=sel_col_end; ++j)
1890                                 tabular->SetRotateCell(
1891                                         tabular->GetCellNumber(i, j),
1892                                         true);
1893                 break;
1894         case LyXTabular::UNSET_ROTATE_CELL:
1895                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1896                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1897                                 tabular->SetRotateCell(
1898                                         tabular->GetCellNumber(i, j), false);
1899                 break;
1900         case LyXTabular::SET_USEBOX:
1901         {
1902                 LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
1903                 if (val == tabular->GetUsebox(actcell))
1904                         val = LyXTabular::BOX_NONE;
1905                 for (int i = sel_row_start; i <= sel_row_end; ++i)
1906                         for (int j = sel_col_start; j <= sel_col_end; ++j)
1907                                 tabular->SetUsebox(
1908                                         tabular->GetCellNumber(i, j), val);
1909                 break;
1910         }
1911         case LyXTabular::UNSET_LTFIRSTHEAD:
1912                 ltt.row = 0;
1913         case LyXTabular::SET_LTFIRSTHEAD:
1914                 tabular->SetLTHead(ltt, true);
1915                 break;
1916         case LyXTabular::UNSET_LTHEAD:
1917                 ltt.row = 0;
1918         case LyXTabular::SET_LTHEAD:
1919                 tabular->SetLTHead(ltt, false);
1920                 break;
1921         case LyXTabular::UNSET_LTFOOT:
1922                 ltt.row = 0;
1923         case LyXTabular::SET_LTFOOT:
1924                 tabular->SetLTFoot(ltt, false);
1925                 break;
1926         case LyXTabular::UNSET_LTLASTFOOT:
1927                 ltt.row = 0;
1928         case LyXTabular::SET_LTLASTFOOT:
1929                 tabular->SetLTFoot(ltt, true);
1930                 break;
1931         case LyXTabular::SET_LTNEWPAGE:
1932         {
1933                 bool what = !tabular->GetLTNewPage(actcell);
1934                 tabular->SetLTNewPage(actcell, what);
1935                 break;
1936         }
1937         // dummy stuff just to avoid warnings
1938         case LyXTabular::LAST_ACTION:
1939                 break;
1940         }
1941 }
1942
1943
1944 bool InsetTabular::activateCellInset(BufferView * bv, int x, int y, int button,
1945                                      bool behind)
1946 {
1947         UpdatableInset * inset =
1948                 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
1949         LyXFont font(LyXFont::ALL_SANE);
1950         if (behind) {
1951                 x = inset->x() + inset->width(bv, font);
1952                 y = inset->descent(bv, font);
1953         }
1954         //inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
1955         //inset_y = cursor.y();
1956         inset->edit(bv, x,  y, button);
1957         if (!the_locking_inset)
1958                 return false;
1959         updateLocal(bv, CELL, false);
1960         return (the_locking_inset != 0);
1961 }
1962
1963
1964 bool InsetTabular::activateCellInsetAbs(BufferView * bv, int x, int y,
1965                                         int button)
1966 {
1967         inset_x = cursor_.x()
1968                 - top_x + tabular->GetBeginningOfTextInCell(actcell);
1969         inset_y = cursor_.y();
1970         return activateCellInset(bv, x - inset_x, y - inset_y, button);
1971 }
1972
1973
1974 bool InsetTabular::insetHit(BufferView *, int x, int) const
1975 {
1976         return (x + top_x)
1977                 > (cursor_.x() + tabular->GetBeginningOfTextInCell(actcell));
1978 }
1979
1980
1981 // This returns paperWidth() if the cell-width is unlimited or the width
1982 // in pixels if we have a pwidth for this cell.
1983 int InsetTabular::getMaxWidthOfCell(BufferView * bv, int cell) const
1984 {
1985         string const s = tabular->GetPWidth(cell);
1986         
1987         if (s.empty())
1988                 return -1;
1989         return VSpace(s).inPixels(bv);
1990 }
1991
1992
1993 int InsetTabular::getMaxWidth(BufferView * bv,
1994                               UpdatableInset const * inset) const
1995 {
1996         int cell = tabular->cur_cell;
1997         if (tabular->GetCellInset(cell) != inset) {
1998                 cell = actcell;
1999                 if (tabular->GetCellInset(cell) != inset) {
2000                         
2001                         lyxerr << "Actcell not equal to actual cell!\n";
2002                         cell = -1;
2003                 }
2004         }
2005         
2006         int const n = tabular->GetNumberOfCells();
2007
2008         if (cell == -1) {
2009                 for (cell = 0; cell < n; ++cell) {
2010                         if (tabular->GetCellInset(cell) == inset)
2011                                 break;
2012                 }
2013         }
2014         
2015         if (cell >= n) {
2016                 lyxerr << "Own inset not found, shouldn't really happen!\n";
2017                 return -1;
2018         }
2019         
2020         int w = getMaxWidthOfCell(bv, cell);
2021         if (w > 0) {
2022                 // because the inset then subtracts it's top_x and owner->x()
2023                 w += (inset->x() - top_x);
2024         }
2025         
2026         return w;
2027 }
2028
2029
2030 void InsetTabular::deleteLyXText(BufferView * bv, bool recursive) const
2031 {
2032         resizeLyXText(bv, recursive);
2033 }
2034
2035
2036 void InsetTabular::resizeLyXText(BufferView * bv, bool force) const
2037 {
2038         if (force) {
2039                 for(int i = 0; i < tabular->rows(); ++i) {
2040                         for(int j = 0; j < tabular->columns(); ++j) {
2041                                 tabular->GetCellInset(i, j)->resizeLyXText(bv, true);
2042                         }
2043                 }
2044         }
2045         need_update = FULL;
2046 }
2047
2048
2049 LyXText * InsetTabular::getLyXText(BufferView const * bv,
2050                                    bool const recursive) const
2051 {
2052         if (the_locking_inset)
2053                 return the_locking_inset->getLyXText(bv, recursive);
2054 #if 0
2055         // if we're locked lock the actual insettext and return it's LyXText!!!
2056         if (locked) {
2057                 UpdatableInset * inset =
2058                         static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2059                 inset->edit(const_cast<BufferView *>(bv), 0,  0, 0);
2060                 return the_locking_inset->getLyXText(bv, recursive);
2061         }
2062 #endif
2063         return Inset::getLyXText(bv, recursive);
2064 }
2065
2066
2067 bool InsetTabular::showInsetDialog(BufferView * bv) const
2068 {
2069         if (!the_locking_inset || !the_locking_inset->showInsetDialog(bv))
2070                 bv->owner()->getDialogs()
2071                         ->showTabular(const_cast<InsetTabular *>(this));
2072         return true;
2073 }
2074
2075
2076 void InsetTabular::openLayoutDialog(BufferView * bv) const
2077 {
2078         if (the_locking_inset) {
2079                 InsetTabular * i = static_cast<InsetTabular *>
2080                         (the_locking_inset->getFirstLockingInsetOfType(TABULAR_CODE));
2081                 if (i) {
2082                         i->openLayoutDialog(bv);
2083                         return;
2084                 }
2085         }
2086         bv->owner()->getDialogs()->showTabular(
2087                 const_cast<InsetTabular *>(this));
2088 }
2089
2090
2091 //
2092 // functions returns:
2093 // 0 ... disabled
2094 // 1 ... enabled
2095 // 2 ... toggled on
2096 // 3 ... toggled off
2097 //
2098 func_status::value_type InsetTabular::getStatus(string const & what) const
2099 {
2100         int action = LyXTabular::LAST_ACTION;
2101         func_status::value_type status = func_status::OK;
2102         
2103         int i = 0;
2104         for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
2105                 string const tmp = tabularFeature[i].feature;
2106                 if (tmp == what.substr(0, tmp.length())) {                  
2107                         //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
2108                         //   tabularFeatures[i].feature.length())) {
2109                         action = tabularFeature[i].action;
2110                         break;
2111                 }
2112         }
2113         if (action == LyXTabular::LAST_ACTION)
2114                 return func_status::Unknown;
2115
2116         string const argument = frontStrip(what.substr(tabularFeature[i].feature.length()));
2117
2118         int sel_row_start;
2119         int sel_row_end;
2120         int dummy;
2121         LyXTabular::ltType dummyltt;
2122         bool flag = true;
2123
2124         if (hasSelection()) {
2125                 getSelection(sel_row_start, sel_row_end, dummy, dummy);
2126         } else {
2127                 sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
2128         }
2129
2130         switch (action) {
2131         case LyXTabular::SET_PWIDTH:
2132         case LyXTabular::SET_MPWIDTH:
2133         case LyXTabular::SET_SPECIAL_COLUMN:
2134         case LyXTabular::SET_SPECIAL_MULTI:
2135                 status |= func_status::Disabled;
2136                 return status;
2137
2138         case LyXTabular::APPEND_ROW:
2139         case LyXTabular::APPEND_COLUMN:
2140         case LyXTabular::DELETE_ROW:
2141         case LyXTabular::DELETE_COLUMN:
2142         case LyXTabular::SET_ALL_LINES:
2143         case LyXTabular::UNSET_ALL_LINES:
2144                 status |= func_status::OK;
2145                 return status;
2146
2147         case LyXTabular::MULTICOLUMN:
2148                 if (tabular->IsMultiColumn(actcell))
2149                         status |= func_status::ToggleOn;
2150                 else
2151                         status |= func_status::ToggleOff;
2152                 break;
2153         case LyXTabular::M_TOGGLE_LINE_TOP:
2154                 flag = false;
2155         case LyXTabular::TOGGLE_LINE_TOP:
2156                 if (tabular->TopLine(actcell, flag))
2157                         status |= func_status::ToggleOn;
2158                 else
2159                         status |= func_status::ToggleOff;
2160                 break;
2161         case LyXTabular::M_TOGGLE_LINE_BOTTOM:
2162                 flag = false;
2163         case LyXTabular::TOGGLE_LINE_BOTTOM:
2164                 if (tabular->BottomLine(actcell, flag))
2165                         status |= func_status::ToggleOn;
2166                 else
2167                         status |= func_status::ToggleOff;
2168                 break;
2169         case LyXTabular::M_TOGGLE_LINE_LEFT:
2170                 flag = false;
2171         case LyXTabular::TOGGLE_LINE_LEFT:
2172                 if (tabular->LeftLine(actcell, flag))
2173                         status |= func_status::ToggleOn;
2174                 else
2175                         status |= func_status::ToggleOff;
2176                 break;
2177         case LyXTabular::M_TOGGLE_LINE_RIGHT:
2178                 flag = false;
2179         case LyXTabular::TOGGLE_LINE_RIGHT:
2180                 if (tabular->RightLine(actcell, flag))
2181                         status |= func_status::ToggleOn;
2182                 else
2183                         status |= func_status::ToggleOff;
2184                 break;
2185         case LyXTabular::M_ALIGN_LEFT:
2186                 flag = false;
2187         case LyXTabular::ALIGN_LEFT:
2188                 if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_LEFT)
2189                         status |= func_status::ToggleOn;
2190                 else
2191                         status |= func_status::ToggleOff;
2192                 break;
2193         case LyXTabular::M_ALIGN_RIGHT:
2194                 flag = false;
2195         case LyXTabular::ALIGN_RIGHT:
2196                 if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_RIGHT)
2197                         status |= func_status::ToggleOn;
2198                 else
2199                         status |= func_status::ToggleOff;
2200                 break;
2201         case LyXTabular::M_ALIGN_CENTER:
2202                 flag = false;
2203         case LyXTabular::ALIGN_CENTER:
2204                 if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_CENTER)
2205                         status |= func_status::ToggleOn;
2206                 else
2207                         status |= func_status::ToggleOff;
2208                 break;
2209         case LyXTabular::M_VALIGN_TOP:
2210                 flag = false;
2211         case LyXTabular::VALIGN_TOP:
2212                 if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP)
2213                         status |= func_status::ToggleOn;
2214                 else
2215                         status |= func_status::ToggleOff;
2216                 break;
2217         case LyXTabular::M_VALIGN_BOTTOM:
2218                 flag = false;
2219         case LyXTabular::VALIGN_BOTTOM:
2220                 if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM)
2221                         status |= func_status::ToggleOn;
2222                 else
2223                         status |= func_status::ToggleOff;
2224                 break;
2225         case LyXTabular::M_VALIGN_CENTER:
2226                 flag = false;
2227         case LyXTabular::VALIGN_CENTER:
2228                 if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER)
2229                         status |= func_status::ToggleOn;
2230                 else
2231                         status |= func_status::ToggleOff;
2232                 break;
2233         case LyXTabular::SET_LONGTABULAR:
2234                 if (tabular->IsLongTabular())
2235                         status |= func_status::ToggleOn;
2236                 else
2237                         status |= func_status::ToggleOff;
2238                 break;
2239         case LyXTabular::UNSET_LONGTABULAR:
2240                 if (!tabular->IsLongTabular())
2241                         status |= func_status::ToggleOn;
2242                 else
2243                         status |= func_status::ToggleOff;
2244                 break;
2245         case LyXTabular::SET_ROTATE_TABULAR:
2246                 if (tabular->GetRotateTabular())
2247                         status |= func_status::ToggleOn;
2248                 else
2249                         status |= func_status::ToggleOff;
2250                 break;
2251         case LyXTabular::UNSET_ROTATE_TABULAR:
2252                 if (!tabular->GetRotateTabular())
2253                         status |= func_status::ToggleOn;
2254                 else
2255                         status |= func_status::ToggleOff;
2256                 break;
2257         case LyXTabular::SET_ROTATE_CELL:
2258                 if (tabular->GetRotateCell(actcell))
2259                         status |= func_status::ToggleOn;
2260                 else
2261                         status |= func_status::ToggleOff;
2262                 break;
2263         case LyXTabular::UNSET_ROTATE_CELL:
2264                 if (!tabular->GetRotateCell(actcell))
2265                         status |= func_status::ToggleOn;
2266                 else
2267                         status |= func_status::ToggleOff;
2268                 break;
2269         case LyXTabular::SET_USEBOX:
2270                 if (strToInt(argument) == tabular->GetUsebox(actcell))
2271                         status |= func_status::ToggleOn;
2272                 else
2273                         status |= func_status::ToggleOff;
2274                 break;
2275         case LyXTabular::SET_LTFIRSTHEAD:
2276                 if (tabular->GetRowOfLTHead(actcell, dummyltt))
2277                         status |= func_status::ToggleOn;
2278                 else
2279                         status |= func_status::ToggleOff;
2280                 break;
2281         case LyXTabular::SET_LTHEAD:
2282                 if (tabular->GetRowOfLTHead(actcell, dummyltt))
2283                         status |= func_status::ToggleOn;
2284                 else
2285                         status |= func_status::ToggleOff;
2286                 break;
2287         case LyXTabular::SET_LTFOOT:
2288                 if (tabular->GetRowOfLTFoot(actcell, dummyltt))
2289                         status |= func_status::ToggleOn;
2290                 else
2291                         status |= func_status::ToggleOff;
2292                 break;
2293         case LyXTabular::SET_LTLASTFOOT:
2294                 if (tabular->GetRowOfLTFoot(actcell, dummyltt))
2295                         status |= func_status::ToggleOn;
2296                 else
2297                         status |= func_status::ToggleOff;
2298                 break;
2299         case LyXTabular::SET_LTNEWPAGE:
2300                 if (tabular->GetLTNewPage(actcell))
2301                         status |= func_status::ToggleOn;
2302                 else
2303                         status |= func_status::ToggleOff;
2304                 break;
2305         default:
2306                 status = func_status::Disabled;
2307                 break;
2308         }
2309         return status;
2310 }
2311
2312
2313 std::vector<string> const InsetTabular::getLabelList() const
2314 {
2315         return tabular->getLabelList();
2316 }
2317
2318
2319 bool InsetTabular::copySelection(BufferView * bv)
2320 {
2321         if (!hasSelection())
2322                 return false;
2323
2324         int sel_col_start = tabular->column_of_cell(sel_cell_start);
2325         int sel_col_end = tabular->column_of_cell(sel_cell_end);
2326         if (sel_col_start > sel_col_end) {
2327                 sel_col_start = sel_col_end;
2328                 sel_col_end = tabular->right_column_of_cell(sel_cell_start);
2329         } else {
2330                 sel_col_end = tabular->right_column_of_cell(sel_cell_end);
2331         }
2332         int const columns = sel_col_end - sel_col_start + 1;
2333
2334         int sel_row_start = tabular->row_of_cell(sel_cell_start);
2335         int sel_row_end = tabular->row_of_cell(sel_cell_end);
2336         if (sel_row_start > sel_row_end) {
2337                 swap(sel_row_start, sel_row_end);
2338         }
2339         int const rows = sel_row_end - sel_row_start + 1;
2340
2341         delete paste_tabular;
2342         paste_tabular = new LyXTabular(this, *tabular); // rows, columns);
2343         for (int i = 0; i < sel_row_start; ++i)
2344                 paste_tabular->DeleteRow(0);
2345         while(paste_tabular->rows() > rows)
2346                 paste_tabular->DeleteRow(rows);
2347         paste_tabular->SetTopLine(0, true, true);
2348         paste_tabular->SetBottomLine(paste_tabular->GetFirstCellInRow(rows-1),
2349                                      true, true);
2350         for (int i = 0; i < sel_col_start; ++i)
2351                 paste_tabular->DeleteColumn(0);
2352         while (paste_tabular->columns() > columns)
2353                 paste_tabular->DeleteColumn(columns);
2354         paste_tabular->SetLeftLine(0, true, true);
2355         paste_tabular->SetRightLine(paste_tabular->GetLastCellInRow(0),
2356                                     true, true);
2357
2358         ostringstream sstr;
2359         paste_tabular->Ascii(bv->buffer(), sstr);
2360         bv->stuffClipboard(sstr.str().c_str());
2361         return true;
2362 }
2363
2364
2365 bool InsetTabular::pasteSelection(BufferView * bv)
2366 {
2367         if (!paste_tabular)
2368                 return false;
2369
2370         for (int r1 = 0, r2 = actrow;
2371              (r1 < paste_tabular->rows()) && (r2 < tabular->rows());
2372              ++r1, ++r2) {
2373                 for(int c1 = 0, c2 = actcol;
2374                     (c1 < paste_tabular->columns()) && (c2 < tabular->columns());
2375                     ++c1, ++c2) {
2376                         if (paste_tabular->IsPartOfMultiColumn(r1,c1) &&
2377                             tabular->IsPartOfMultiColumn(r2,c2))
2378                                 continue;
2379                         if (paste_tabular->IsPartOfMultiColumn(r1,c1)) {
2380                                 --c2;
2381                                 continue;
2382                         }
2383                         if (tabular->IsPartOfMultiColumn(r2,c2)) {
2384                                 --c1;
2385                                 continue;
2386                         }
2387                         int const n1 = paste_tabular->GetCellNumber(r1, c1);
2388                         int const n2 = tabular->GetCellNumber(r2, c2);
2389                         *(tabular->GetCellInset(n2)) = *(paste_tabular->GetCellInset(n1));
2390                         tabular->GetCellInset(n2)->setOwner(this);
2391                         tabular->GetCellInset(n2)->deleteLyXText(bv);
2392                 }
2393         }
2394         return true;
2395 }
2396
2397
2398 bool InsetTabular::cutSelection()
2399 {
2400         if (!hasSelection())
2401                 return false;
2402
2403         int sel_col_start = tabular->column_of_cell(sel_cell_start);
2404         int sel_col_end = tabular->column_of_cell(sel_cell_end);
2405         if (sel_col_start > sel_col_end) {
2406                 sel_col_start = sel_col_end;
2407                 sel_col_end = tabular->right_column_of_cell(sel_cell_start);
2408         } else {
2409                 sel_col_end = tabular->right_column_of_cell(sel_cell_end);
2410         }
2411         int sel_row_start = tabular->row_of_cell(sel_cell_start);
2412         int sel_row_end = tabular->row_of_cell(sel_cell_end);
2413         if (sel_row_start > sel_row_end) {
2414                 swap(sel_row_start, sel_row_end);
2415         }
2416         if (sel_cell_start > sel_cell_end) {
2417                 swap(sel_cell_start, sel_cell_end);
2418         }
2419         for (int i = sel_row_start; i <= sel_row_end; ++i) {
2420                 for (int j = sel_col_start; j <= sel_col_end; ++j) {
2421                         tabular->GetCellInset(tabular->GetCellNumber(i, j))->clear();
2422                 }
2423         }
2424         return true;
2425 }
2426
2427
2428 bool InsetTabular::isRightToLeft(BufferView *bv )
2429 {
2430         return bv->getParentLanguage(this)->RightToLeft();
2431 }
2432
2433
2434 bool InsetTabular::nodraw() const
2435 {
2436         if (!UpdatableInset::nodraw() && the_locking_inset)
2437                 return the_locking_inset->nodraw();
2438         return UpdatableInset::nodraw();
2439 }
2440
2441
2442 int InsetTabular::scroll(bool recursive) const
2443 {
2444         int sx = UpdatableInset::scroll(false);
2445
2446         if (recursive && the_locking_inset)
2447                 sx += the_locking_inset->scroll(recursive);
2448
2449         return sx;
2450 }
2451
2452
2453 bool InsetTabular::doClearArea() const
2454 {
2455         return !locked || (need_update & (FULL|INIT));
2456 }
2457
2458
2459 void InsetTabular::getSelection(int & srow, int & erow, int & scol, int & ecol) const
2460 {
2461                 srow = tabular->row_of_cell(sel_cell_start);
2462                 erow = tabular->row_of_cell(sel_cell_end);
2463                 if (srow > erow)
2464                         swap(srow, erow);
2465
2466                 scol = tabular->column_of_cell(sel_cell_start);
2467                 ecol = tabular->column_of_cell(sel_cell_end);
2468                 if (scol > ecol)
2469                         swap(scol, ecol);
2470                 else
2471                         ecol = tabular->right_column_of_cell(sel_cell_end);
2472 }
2473
2474
2475 Paragraph * InsetTabular::getParFromID(int id) const
2476 {
2477         Paragraph * result;
2478         for(int i = 0; i < tabular->rows(); ++i) {
2479                 for(int j = 0; j < tabular->columns(); ++j) {
2480                         if ((result = tabular->GetCellInset(i, j)->getParFromID(id)))
2481                                 return result;
2482                 }
2483         }
2484         return 0;
2485 }
2486
2487
2488 Paragraph * InsetTabular::firstParagraph() const
2489 {
2490         if (the_locking_inset)
2491                 return the_locking_inset->firstParagraph();
2492         return 0;
2493 }
2494
2495
2496 Paragraph * InsetTabular::getFirstParagraph(int i) const
2497 {
2498         return (i < tabular->GetNumberOfCells())
2499                 ? tabular->GetCellInset(i)->getFirstParagraph(0)
2500                 : 0;
2501 }
2502
2503
2504 LyXCursor const & InsetTabular::cursor(BufferView * bv) const
2505 {
2506         if (the_locking_inset)
2507                 return the_locking_inset->cursor(bv);
2508         return Inset::cursor(bv);
2509 }
2510
2511
2512 Inset * InsetTabular::getInsetFromID(int id_arg) const
2513 {
2514         if (id_arg == id())
2515                 return const_cast<InsetTabular *>(this);
2516
2517         Inset * result;
2518         for(int i=0; i < tabular->rows(); ++i) {
2519                 for(int j=0; j < tabular->columns(); ++j) {
2520                         if ((result = tabular->GetCellInset(i, j)->getInsetFromID(id_arg)))
2521                                 return result;
2522                 }
2523         }
2524         return 0;
2525 }
2526
2527
2528 string const InsetTabular::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2529 {
2530         if (the_locking_inset) {
2531                 string const str(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2532                 if (!str.empty())
2533                         return str;
2534                 if (tabular->IsLastCell(actcell)) {
2535                         bv->unlockInset(const_cast<InsetTabular *>(this));
2536                         return string();
2537                 }
2538                 ++actcell;
2539         }
2540         nodraw(true);
2541         // otherwise we have to lock the next inset and ask for it's selecttion
2542         UpdatableInset * inset =
2543                 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2544         inset->edit(bv, 0,  0, 0);
2545         string const str(selectNextWordInt(bv, value));
2546         nodraw(false);
2547         if (!str.empty())
2548                 resetPos(bv);
2549         return str;
2550 }
2551
2552
2553 string InsetTabular::selectNextWordInt(BufferView * bv, float & value) const
2554 {
2555         // when entering this function the inset should be ALWAYS locked!
2556         lyx::Assert(the_locking_inset);
2557
2558         string const str(the_locking_inset->selectNextWordToSpellcheck(bv, value));
2559         if (!str.empty())
2560                 return str;
2561
2562         if (tabular->IsLastCell(actcell)) {
2563                 bv->unlockInset(const_cast<InsetTabular *>(this));
2564                 return string();
2565         }
2566         
2567         // otherwise we have to lock the next inset and ask for it's selecttion
2568         UpdatableInset * inset =
2569                 static_cast<UpdatableInset*>(tabular->GetCellInset(++actcell));
2570         inset->edit(bv);
2571         return selectNextWordInt(bv, value);
2572 }
2573
2574
2575 void InsetTabular::selectSelectedWord(BufferView * bv)
2576 {
2577         if (the_locking_inset) {
2578                 the_locking_inset->selectSelectedWord(bv);
2579                 return;
2580         }
2581         return;
2582 }
2583
2584
2585 void InsetTabular::toggleSelection(BufferView * bv, bool kill_selection)
2586 {
2587         if (the_locking_inset) {
2588                 the_locking_inset->toggleSelection(bv, kill_selection);
2589         }
2590 }
2591
2592
2593 bool InsetTabular::searchForward(BufferView * bv, string const & str,
2594                                  bool const & cs, bool const & mw)
2595 {
2596         if (the_locking_inset) {
2597                 if (the_locking_inset->searchForward(bv, str, cs, mw))
2598                         return true;
2599                 if (tabular->IsLastCell(actcell)) {
2600                         bv->unlockInset(const_cast<InsetTabular *>(this));
2601                         return false;
2602                 }
2603                 ++actcell;
2604         }
2605         // otherwise we have to lock the next inset and search there
2606         UpdatableInset * inset =
2607                 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2608         inset->edit(bv);
2609 #if 0
2610         bool const res = searchForward(bv, str, cs, mw);
2611         updateLocal(bv, NONE, false);
2612         bv->updateInset(const_cast<InsetTabular *>(this), false);
2613         return res;
2614 #else
2615         return searchForward(bv, str, cs, mw);
2616 #endif
2617 }
2618
2619
2620 bool InsetTabular::searchBackward(BufferView * bv, string const & str,
2621                                bool const & cs, bool const & mw)
2622 {
2623         if (the_locking_inset) {
2624                 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2625                         return true;
2626                 if (!actcell) { // we are already in the first cell
2627                         bv->unlockInset(const_cast<InsetTabular *>(this));
2628                         return false;
2629                 }
2630                 --actcell;
2631         }
2632         // otherwise we have to lock the next inset and search there
2633         UpdatableInset * inset =
2634                 static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
2635         inset->edit(bv, false);
2636 #if 0
2637         bool const res = searchBackward(bv, str, cs, mw);
2638         bv->updateInset(const_cast<InsetTabular *>(this), false);
2639         return res;
2640 #else
2641         return searchBackward(bv, str, cs, mw);
2642 #endif
2643 }
2644
2645
2646 bool InsetTabular::insetAllowed(Inset::Code code) const
2647 {
2648         if (the_locking_inset)
2649                 return the_locking_inset->insetAllowed(code);
2650         return false;
2651 }