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