]> git.lyx.org Git - features.git/blob - src/insets/insettabular.C
Some more fixes to insettabular/text! (my last as single :)
[features.git] / src / insets / insettabular.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2000 The LyX Team.
7  *
8  * ======================================================
9  */
10
11 #include <config.h>
12
13 #include <fstream>
14 #include <algorithm>
15
16 #include <cstdlib>
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22 #include "insettabular.h"
23
24 #include "buffer.h"
25 #include "commandtags.h"
26 #include "debug.h"
27 #include "LaTeXFeatures.h"
28 #include "Painter.h"
29 #include "font.h"
30 #include "lyxtext.h"
31 #include "lyx_gui_misc.h"
32 #include "LyXView.h"
33 #include "lyxfunc.h"
34 #include "insets/insettext.h"
35 #include "frontends/Dialogs.h"
36 #include "debug.h"
37 #include "lyxfunc.h"
38
39 const int ADD_TO_HEIGHT = 2;
40 const int ADD_TO_TABULAR_WIDTH = 2;
41 ///
42 static LyXTabular * paste_tabular = 0;
43 bool InsetTabular::hasPasteBuffer() const
44 {
45     return (paste_tabular != 0);
46 }
47
48 using std::ostream;
49 using std::ifstream;
50 using std::max;
51 using std::endl;
52 using std::swap;
53
54     
55 struct tabular_features {
56     LyXTabular::Feature action;
57     string feature;
58 };
59
60 //static tabular_features * tabularFeatures = 0;
61
62 static tabular_features tabularFeatures[] =
63 {
64     { LyXTabular::APPEND_ROW, "append-row" },
65     { LyXTabular::APPEND_COLUMN, "append-column" },
66     { LyXTabular::DELETE_ROW, "delete-row" },
67     { LyXTabular::DELETE_COLUMN, "delete-column" },
68     { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
69     { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
70     { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
71     { LyXTabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
72     { LyXTabular::ALIGN_LEFT, "align-left" },
73     { LyXTabular::ALIGN_RIGHT, "align-right" },
74     { LyXTabular::ALIGN_CENTER, "align-center" },
75     { LyXTabular::VALIGN_TOP, "valign-top" },
76     { LyXTabular::VALIGN_BOTTOM, "valign-bottom" },
77     { LyXTabular::VALIGN_CENTER, "valign-center" },
78     { LyXTabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
79     { LyXTabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
80     { LyXTabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
81     { LyXTabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
82     { LyXTabular::M_ALIGN_LEFT, "m-align-left" },
83     { LyXTabular::M_ALIGN_RIGHT, "m-align-right" },
84     { LyXTabular::M_ALIGN_CENTER, "m-align-center" },
85     { LyXTabular::M_VALIGN_TOP, "m-valign-top" },
86     { LyXTabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
87     { LyXTabular::M_VALIGN_CENTER, "m-valign-center" },
88     { LyXTabular::MULTICOLUMN, "multicolumn" },
89     { LyXTabular::SET_ALL_LINES, "set-all-lines" },
90     { LyXTabular::UNSET_ALL_LINES, "unset-all-lines" },
91     { LyXTabular::SET_LONGTABULAR, "set-longtabular" },
92     { LyXTabular::UNSET_LONGTABULAR, "unset-longtabular" },
93     { LyXTabular::SET_PWIDTH, "set-pwidth" },
94     { LyXTabular::SET_MPWIDTH, "set-mpwidth" },
95     { LyXTabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
96     { LyXTabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
97     { LyXTabular::SET_ROTATE_CELL, "set-rotate-cell" },
98     { LyXTabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
99     { LyXTabular::SET_USEBOX, "set-usebox" },
100     { LyXTabular::SET_LTHEAD, "set-lthead" },
101     { LyXTabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
102     { LyXTabular::SET_LTFOOT, "set-ltfoot" },
103     { LyXTabular::SET_LTLASTFOOT, "set-ltlastfoot" },
104     { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" },
105     { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" },
106     { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" },
107     { LyXTabular::LAST_ACTION, "" }
108 };
109
110
111 static inline
112 bool cellstart(LyXParagraph::size_type p) 
113 {
114         return ((p % 2) == 0);
115 }
116
117
118 InsetTabular::InsetTabular(Buffer * buf, int rows, int columns)
119         : buffer(buf)
120 {
121     if (rows <= 0)
122         rows = 1;
123     if (columns <= 0)
124         columns = 1;
125     tabular = new LyXTabular(this, rows,columns);
126     // for now make it always display as display() inset
127     // just for test!!!
128     the_locking_inset = 0;
129     locked = no_selection = cursor_visible = false;
130     cursor.x_fix(-1);
131     oldcell = -1;
132     actcell = 0;
133     cursor.pos(0);
134     sel_pos_start = sel_pos_end = sel_cell_start = sel_cell_end = 0;
135     dialogs_ = 0;
136     need_update = INIT;
137 }
138
139
140 InsetTabular::InsetTabular(InsetTabular const & tab, Buffer * buf)
141         : buffer(buf)
142 {
143     tabular = new LyXTabular(this, *(tab.tabular));
144     the_locking_inset = 0;
145     locked = no_selection = cursor_visible = false;
146     cursor.x_fix(-1);
147     oldcell = -1;
148     actcell = 0;
149     cursor.pos(0);
150     sel_pos_start = sel_pos_end = sel_cell_start = sel_cell_end = 0;
151     dialogs_ = 0;
152     need_update = INIT;
153 }
154
155
156 InsetTabular::~InsetTabular()
157 {
158     delete tabular;
159     if (dialogs_)
160         dialogs_->hideTabular(this);
161 }
162
163
164 Inset * InsetTabular::Clone() const
165 {
166     InsetTabular * t = new InsetTabular(*this, buffer);
167     delete t->tabular;
168     t->tabular = tabular->Clone(t);
169     return t;
170 }
171
172
173 void InsetTabular::Write(Buffer const * buf, ostream & os) const
174 {
175     os << " Tabular" << endl;
176     tabular->Write(buf, os);
177 }
178
179
180 void InsetTabular::Read(Buffer const * buf, LyXLex & lex)
181 {
182     bool old_format = (lex.GetString() == "\\LyXTable");
183     string token;
184
185     if (tabular)
186         delete tabular;
187     tabular = new LyXTabular(buf, this, lex);
188
189     need_update = INIT;
190
191     if (old_format)
192         return;
193
194     lex.nextToken();
195     token = lex.GetString();
196     while (lex.IsOK() && (token != "\\end_inset")) {
197         lex.nextToken();
198         token = lex.GetString();
199     }
200     if (token != "\\end_inset") {
201         lex.printError("Missing \\end_inset at this point. "
202                        "Read: `$$Token'");
203     }
204 }
205
206
207 int InsetTabular::ascent(BufferView *, LyXFont const &) const
208 {
209     return tabular->GetAscentOfRow(0);
210 }
211
212
213 int InsetTabular::descent(BufferView *, LyXFont const &) const
214 {
215     return tabular->GetHeightOfTabular() - tabular->GetAscentOfRow(0) + 1;
216 }
217
218
219 int InsetTabular::width(BufferView *, LyXFont const &) const
220 {
221     return tabular->GetWidthOfTabular() + (2 * ADD_TO_TABULAR_WIDTH);
222 }
223
224
225 void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
226                         float & x, bool cleared) const
227 {
228     Painter & pain = bv->painter();
229     int i, j, cell = 0;
230     int nx;
231     float cx;
232
233     UpdatableInset::draw(bv, font, baseline, x, cleared);
234     if (!cleared && ((need_update == INIT) || (need_update == FULL) ||
235                      (top_x != int(x)) || (top_baseline != baseline))) {
236         int h = ascent(bv, font) + descent(bv, font);
237         int tx = display() || !owner() ? 0 : top_x;
238         int w =  tx ? width(bv, font) : pain.paperWidth();
239         int ty = baseline - ascent(bv, font);
240         
241         if (ty < 0)
242             ty = 0;
243         if ((ty + h) > pain.paperHeight())
244             h = pain.paperHeight();
245         if ((top_x + w) > pain.paperWidth())
246             w = pain.paperWidth();
247         pain.fillRectangle(tx, ty, w, h);
248         need_update = FULL;
249         cleared = true;
250     }
251     top_x = int(x);
252     top_baseline = baseline;
253     if (bv->text->status == LyXText::CHANGED_IN_DRAW)
254         return;
255     bool dodraw;
256     x += ADD_TO_TABULAR_WIDTH;
257     if (cleared) {
258         for(i = 0; i < tabular->rows(); ++i) {
259             nx = int(x);
260             dodraw = ((baseline + tabular->GetDescentOfRow(i)) > 0) &&
261                     (baseline - tabular->GetAscentOfRow(i))<pain.paperHeight();
262             for(j = 0; j < tabular->columns(); ++j) {
263                 if (tabular->IsPartOfMultiColumn(i, j))
264                     continue;
265                 cx = nx + tabular->GetBeginningOfTextInCell(cell);
266                 if (dodraw) {
267                     if (hasSelection())
268                         DrawCellSelection(pain, nx, baseline, i, j, cell);
269                     tabular->GetCellInset(cell)->draw(bv, font, baseline, cx,
270                                                       cleared);
271                     DrawCellLines(pain, nx, baseline, i, cell);
272                 }
273                 nx += tabular->GetWidthOfColumn(cell);
274                 ++cell;
275             }
276             baseline += tabular->GetDescentOfRow(i) +
277                 tabular->GetAscentOfRow(i + 1) +
278                 tabular->GetAdditionalHeight(cell);
279         }
280     } else if (need_update == CELL) {
281         nx = int(x);
282         for(i = 0; (cell < actcell) && (i < tabular->rows()); ++i) {
283             nx = int(x);
284             for(j = 0; (cell < actcell) && (j < tabular->columns()); ++j) {
285                 if (tabular->IsPartOfMultiColumn(i, j))
286                     continue;
287                 nx += tabular->GetWidthOfColumn(cell);
288                 ++cell;
289             }
290             baseline += tabular->GetDescentOfRow(i) +
291                 tabular->GetAscentOfRow(i + 1) +
292                 tabular->GetAdditionalHeight(cell);
293         }
294         if (the_locking_inset == tabular->GetCellInset(cell)) {
295             LyXText::text_status st = bv->text->status;
296             do {
297                 cx = nx + tabular->GetBeginningOfTextInCell(cell);
298                 bv->text->status = st;
299                 if (need_update == CELL) {
300                     // clear before the inset
301                     pain.fillRectangle(
302                         nx + 1,
303                         baseline - tabular->GetAscentOfRow(i) + 1,
304                         int(cx - nx - 1),
305                         tabular->GetAscentOfRow(i) +
306                         tabular->GetDescentOfRow(i) - 1);
307                     // clear behind the inset
308                     pain.fillRectangle(
309                         int(cx + the_locking_inset->width(bv,font) + 1),
310                         baseline - tabular->GetAscentOfRow(i) + 1,
311                         tabular->GetWidthOfColumn(cell) -
312                         tabular->GetBeginningOfTextInCell(cell) -
313                         the_locking_inset->width(bv,font) - 1,
314                         tabular->GetAscentOfRow(i) +
315                         tabular->GetDescentOfRow(i) - 1);
316                 }
317                 tabular->GetCellInset(cell)->draw(bv,font,baseline, cx, false);
318             } while(bv->text->status == LyXText::CHANGED_IN_DRAW);
319         }
320     }
321     x -= ADD_TO_TABULAR_WIDTH;
322     x += width(bv, font);
323     if (bv->text->status == LyXText::CHANGED_IN_DRAW)
324         need_update = INIT;
325     else
326         need_update = NONE;
327 }
328
329
330 void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline,
331                                  int row, int cell) const
332 {
333     int  x2 = x + tabular->GetWidthOfColumn(cell);
334     bool on_off;
335
336     if (!tabular->TopAlreadyDrawed(cell)) {
337         on_off = !tabular->TopLine(cell);
338         pain.line(x, baseline - tabular->GetAscentOfRow(row),
339                   x2, baseline -  tabular->GetAscentOfRow(row),
340                   on_off ? LColor::tabularonoffline : LColor::tabularline,
341                   on_off ? Painter::line_onoffdash : Painter::line_solid);
342     }
343     on_off = !tabular->BottomLine(cell);
344     pain.line(x,baseline +  tabular->GetDescentOfRow(row),
345               x2, baseline +  tabular->GetDescentOfRow(row),
346               on_off ? LColor::tabularonoffline : LColor::tabularline,
347               on_off ? Painter::line_onoffdash : Painter::line_solid);
348     if (!tabular->LeftAlreadyDrawed(cell)) {
349         on_off = !tabular->LeftLine(cell);
350         pain.line(x, baseline -  tabular->GetAscentOfRow(row),
351                   x, baseline +  tabular->GetDescentOfRow(row),
352                   on_off ? LColor::tabularonoffline : LColor::tabularline,
353                   on_off ? Painter::line_onoffdash : Painter::line_solid);
354     }
355     on_off = !tabular->RightLine(cell);
356     pain.line(x2 - tabular->GetAdditionalWidth(cell),
357               baseline -  tabular->GetAscentOfRow(row),
358               x2 - tabular->GetAdditionalWidth(cell),
359               baseline +  tabular->GetDescentOfRow(row),
360               on_off ? LColor::tabularonoffline : LColor::tabularline,
361               on_off ? Painter::line_onoffdash : Painter::line_solid);
362 }
363
364
365 void InsetTabular::DrawCellSelection(Painter & pain, int x, int baseline,
366                                      int row, int column, int cell) const
367 {
368     int cs = tabular->column_of_cell(sel_cell_start);
369     int ce = tabular->column_of_cell(sel_cell_end);
370     if (cs > ce) {
371         ce = cs;
372         cs = tabular->column_of_cell(sel_cell_end);
373     } else {
374         ce = tabular->right_column_of_cell(sel_cell_end);
375     }
376
377     int rs = tabular->row_of_cell(sel_cell_start);
378     int re = tabular->row_of_cell(sel_cell_end);
379     if (rs > re) swap(rs, re);
380
381     if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
382         int w = tabular->GetWidthOfColumn(cell);
383         int h = tabular->GetAscentOfRow(row) + tabular->GetDescentOfRow(row);
384         pain.fillRectangle(x, baseline - tabular->GetAscentOfRow(row),
385                            w, h, LColor::selection);
386     }
387 }
388
389
390 void InsetTabular::update(BufferView * bv, LyXFont const & font, bool reinit)
391 {
392     if (reinit) {
393         need_update = INIT;
394         calculate_dimensions_of_cells(bv, font, true);
395         if (owner())
396             owner()->update(bv, font, true);
397         return;
398     }
399     if (the_locking_inset) {
400         the_locking_inset->update(bv, font, reinit);
401 //      resetPos(bv);
402 //      inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
403 //      inset_y = cursor.y();
404     }
405     switch(need_update) {
406     case INIT:
407     case FULL:
408     case CELL:
409         if (calculate_dimensions_of_cells(bv, font, false))
410             need_update = INIT;
411         break;
412     case SELECTION:
413         need_update = INIT;
414         break;
415     default:
416         break;
417     }
418 }
419
420
421 string const InsetTabular::EditMessage() const
422 {
423     return _("Opened Tabular Inset");
424 }
425
426
427 void InsetTabular::Edit(BufferView * bv, int x, int y, unsigned int button)
428 {
429     UpdatableInset::Edit(bv, x, y, button);
430
431     if (!bv->lockInset(this)) {
432         lyxerr[Debug::INSETS] << "InsetTabular::Cannot lock inset" << endl;
433         return;
434     }
435     locked = true;
436     the_locking_inset = 0;
437     inset_pos = inset_x = inset_y = 0;
438     setPos(bv, x, y);
439     sel_pos_start = sel_pos_end = cursor.pos();
440     sel_cell_start = sel_cell_end = actcell;
441     bv->text->FinishUndo();
442     if (InsetHit(bv, x, y)) {
443         ActivateCellInset(bv, x, y, button);
444     }
445     UpdateLocal(bv, NONE, false);
446 //    bv->getOwner()->getPopups().updateFormTabular();
447 }
448
449
450 void InsetTabular::InsetUnlock(BufferView * bv)
451 {
452     if (the_locking_inset) {
453         the_locking_inset->InsetUnlock(bv);
454         the_locking_inset = 0;
455     }
456     HideInsetCursor(bv);
457     no_selection = false;
458     oldcell = -1;
459     locked = false;
460     if (scroll() || hasSelection()) {
461         if (scroll()) {
462             scroll(bv, 0.0F);
463         } else {
464             sel_pos_start = sel_pos_end = 0;
465             sel_cell_start = sel_cell_end = 0;
466         }
467         UpdateLocal(bv, FULL, false);
468     }
469 }
470
471
472 void InsetTabular::UpdateLocal(BufferView * bv, UpdateCodes what,
473                                bool mark_dirty) const
474 {
475     need_update = what;
476     // Dirty Cast! (Lgb)
477     bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
478     if (locked && (what != NONE))
479         resetPos(bv);
480 }
481
482
483 bool InsetTabular::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
484 {
485     lyxerr[Debug::INSETS] << "InsetTabular::LockInsetInInset(" <<inset<< "): ";
486     if (!inset)
487         return false;
488     oldcell = -1;
489     if (inset == tabular->GetCellInset(actcell)) {
490         lyxerr[Debug::INSETS] << "OK" << endl;
491         the_locking_inset = tabular->GetCellInset(actcell);
492         resetPos(bv);
493         inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
494         inset_y = cursor.y();
495         inset_pos = cursor.pos();
496         return true;
497     } else if (the_locking_inset && (the_locking_inset == inset)) {
498         if (cursor.pos() == inset_pos) {
499             lyxerr[Debug::INSETS] << "OK" << endl;
500             resetPos(bv);
501             inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
502             inset_y = cursor.y();
503         } else {
504             lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
505         }
506     } else if (the_locking_inset) {
507         lyxerr[Debug::INSETS] << "MAYBE" << endl;
508         return the_locking_inset->LockInsetInInset(bv, inset);
509     }
510     lyxerr[Debug::INSETS] << "NOT OK" << endl;
511     return false;
512 }
513
514
515 bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
516                                    bool lr)
517 {
518     if (!the_locking_inset)
519         return false;
520     if (the_locking_inset == inset) {
521         the_locking_inset->InsetUnlock(bv);
522         the_locking_inset = 0;
523         if (lr)
524             moveRight(bv, false);
525         UpdateLocal(bv, CELL, false);
526         return true;
527     }
528     if (the_locking_inset->UnlockInsetInInset(bv, inset, lr)) {
529         if (inset->LyxCode() == TABULAR_CODE &&
530             !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))
531         {
532             dialogs_ = bv->owner()->getDialogs();
533             dialogs_->updateTabular(this);
534             oldcell = actcell;
535         }
536         return true;
537     }
538     return false;
539 }
540
541
542 bool InsetTabular::UpdateInsetInInset(BufferView * bv, Inset * inset)
543 {
544     if (!the_locking_inset)
545         return false;
546     if (the_locking_inset != inset)
547         return the_locking_inset->UpdateInsetInInset(bv, inset);
548     UpdateLocal(bv, CELL, false);
549     return true;
550 }
551
552
553 int InsetTabular::InsetInInsetY()
554 {
555     if (!the_locking_inset)
556         return 0;
557
558     return (inset_y + the_locking_inset->InsetInInsetY());
559 }
560
561
562 UpdatableInset * InsetTabular::GetLockingInset()
563 {
564     return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
565 }
566
567
568 UpdatableInset * InsetTabular::GetFirstLockingInsetOfType(Inset::Code c)
569 {
570     if (c == LyxCode())
571         return this;
572     if (the_locking_inset)
573         return the_locking_inset->GetFirstLockingInsetOfType(c);
574     return 0;
575 }
576
577
578 bool InsetTabular::InsertInset(BufferView * bv, Inset * inset)
579 {
580     if (the_locking_inset)
581         return the_locking_inset->InsertInset(bv, inset);
582     return false;
583 }
584
585
586 void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
587 {
588     if (hasSelection()) {
589         sel_pos_start = sel_pos_end = sel_cell_start = sel_cell_end = 0;
590         UpdateLocal(bv, SELECTION, false);
591     }
592     no_selection = false;
593
594     int const ocell = actcell;
595     int const orow = actrow;
596
597     HideInsetCursor(bv);
598     setPos(bv, x, y);
599     if (actrow != orow)
600         UpdateLocal(bv, NONE, false);
601     sel_pos_start = sel_pos_end = cursor.pos();
602     sel_cell_start = sel_cell_end = actcell;
603
604     bool const inset_hit = InsetHit(bv, x, y);
605
606     if ((ocell == actcell) && the_locking_inset && inset_hit) {
607         cursor.pos(0); // always before the inset!
608         resetPos(bv);
609         the_locking_inset->InsetButtonPress(bv,
610                                             x - inset_x, y - inset_y, button);
611         return;
612     } else if (the_locking_inset) {
613         the_locking_inset->InsetUnlock(bv);
614     }
615     the_locking_inset = 0;
616     if (inset_hit && bv->the_locking_inset) {
617         if (ActivateCellInset(bv, x, y, button))
618             the_locking_inset->InsetButtonPress(bv, x - inset_x,
619                                                 y - inset_y, button);
620         return;
621     }
622     ShowInsetCursor(bv);
623 }
624
625
626 void InsetTabular::InsetButtonRelease(BufferView * bv,
627                                       int x, int y, int button)
628 {
629     if (button == 3) {
630         if (the_locking_inset) {
631             UpdatableInset * i;
632             if ((i=the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))) {
633                 i->InsetButtonRelease(bv, x, y, button);
634                 return;
635             }
636         }
637         dialogs_ = bv->owner()->getDialogs();
638         dialogs_->showTabular(this);
639         return;
640     }
641     if (the_locking_inset) {
642         the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
643         return;
644     }
645     no_selection = false;
646 }
647
648
649 void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button)
650 {
651     if (the_locking_inset) {
652         the_locking_inset->InsetMotionNotify(bv, x - inset_x,
653                                              y - inset_y, button);
654         return;
655     }
656     if (!no_selection) {
657         HideInsetCursor(bv);
658         int const old_pos = sel_pos_end;
659         int const old_cell = actcell;
660
661         setPos(bv, x, y);
662         sel_pos_end = cursor.pos();
663         sel_cell_end = actcell;
664         if ((sel_cell_end != old_cell) || (old_pos != sel_pos_end))
665             UpdateLocal(bv, SELECTION, false);
666         ShowInsetCursor(bv);
667     }
668     no_selection = false;
669 }
670
671
672 void InsetTabular::InsetKeyPress(XKeyEvent * xke)
673 {
674     if (the_locking_inset) {
675         the_locking_inset->InsetKeyPress(xke);
676         return;
677     }
678 }
679
680
681 UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
682                                                    string const & arg)
683 {
684     UpdatableInset::RESULT 
685         result;
686
687     no_selection = false;
688     if (((result=UpdatableInset::LocalDispatch(bv, action, arg)) == DISPATCHED)
689         || (result == DISPATCHED_NOUPDATE)) {
690
691         resetPos(bv);
692         return result;
693     }
694
695     if ((action < 0) && arg.empty())
696         return FINISHED;
697
698     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
699         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
700         cursor.x_fix(-1);
701     if (the_locking_inset) {
702         result=the_locking_inset->LocalDispatch(bv, action, arg);
703         if (result == DISPATCHED_NOUPDATE)
704             return result;
705         else if (result == DISPATCHED) {
706             the_locking_inset->ToggleInsetCursor(bv);
707             UpdateLocal(bv, CELL, false);
708             the_locking_inset->ToggleInsetCursor(bv);
709             return result;
710         } else if (result == FINISHED) {
711             if ((action == LFUN_RIGHT) || (action == -1)) {
712                 cursor.pos(inset_pos + 1);
713                 resetPos(bv);
714             }
715             sel_pos_start = sel_pos_end = cursor.pos();
716             sel_cell_start = sel_cell_end = actcell;
717             the_locking_inset=0;
718             result = DISPATCHED;
719             return result;
720         }
721     }
722
723     bool hs = hasSelection();
724     HideInsetCursor(bv);
725     result=DISPATCHED;
726     switch (action) {
727         // Normal chars not handled here
728     case -1:
729         break;
730         // --- Cursor Movements ---------------------------------------------
731     case LFUN_RIGHTSEL:
732         if (tabular->IsLastCellInRow(actcell) && !cellstart(cursor.pos()))
733             break;
734         moveRight(bv, false);
735         sel_pos_end = cursor.pos();
736         if (!cellstart(cursor.pos())) {
737             if (tabular->right_column_of_cell(sel_cell_start) >
738                 tabular->right_column_of_cell(actcell))
739                 sel_cell_end = actcell+1;
740             else
741                 sel_cell_end = actcell;
742         }
743         UpdateLocal(bv, SELECTION, false);
744         break;
745     case LFUN_RIGHT:
746         result = moveRight(bv);
747         sel_pos_start = sel_pos_end = cursor.pos();
748         sel_cell_start = sel_cell_end = actcell;
749         if (hs)
750             UpdateLocal(bv, SELECTION, false);
751         break;
752     case LFUN_LEFTSEL:
753         if (tabular->IsFirstCellInRow(actcell) && cellstart(cursor.pos()))
754             break;
755         moveLeft(bv, false);
756         sel_pos_end = cursor.pos();
757         if (cellstart(cursor.pos())) {
758             if (tabular->column_of_cell(sel_cell_start) >=
759                 tabular->column_of_cell(actcell))
760                 sel_cell_end = actcell;
761             else
762                 sel_cell_end = actcell-1;
763         }
764         UpdateLocal(bv, SELECTION, false);
765         break;
766     case LFUN_LEFT:
767         result = moveLeft(bv);
768         sel_pos_start = sel_pos_end = cursor.pos();
769         sel_cell_start = sel_cell_end = actcell;
770         if (hs)
771             UpdateLocal(bv, SELECTION, false);
772         break;
773     case LFUN_DOWNSEL:
774     {
775         int const ocell = actcell;
776         moveDown(bv);
777         sel_pos_end = cursor.pos();
778         if ((ocell == sel_cell_end) ||
779             (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
780             sel_cell_end = tabular->GetCellBelow(sel_cell_end);
781         else
782             sel_cell_end = tabular->GetLastCellBelow(sel_cell_end);
783         UpdateLocal(bv, SELECTION, false);
784     }
785     break;
786     case LFUN_DOWN:
787         result = moveDown(bv);
788         sel_pos_start = sel_pos_end = cursor.pos();
789         sel_cell_start = sel_cell_end = actcell;
790         if (hs)
791             UpdateLocal(bv, SELECTION, false);
792         break;
793     case LFUN_UPSEL:
794     {
795         int const ocell = actcell;
796         moveUp(bv);
797         sel_pos_end = cursor.pos();
798         if ((ocell == sel_cell_end) ||
799             (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
800             sel_cell_end = tabular->GetCellAbove(sel_cell_end);
801         else
802             sel_cell_end = tabular->GetLastCellAbove(sel_cell_end);
803         UpdateLocal(bv, SELECTION, false);
804     }
805     break;
806     case LFUN_UP:
807         result = moveUp(bv);
808         sel_pos_start = sel_pos_end = cursor.pos();
809         sel_cell_start = sel_cell_end = actcell;
810         if (hs)
811             UpdateLocal(bv, SELECTION, false);
812         break;
813     case LFUN_BACKSPACE:
814         break;
815     case LFUN_DELETE:
816         break;
817     case LFUN_HOME:
818         break;
819     case LFUN_END:
820         break;
821     case LFUN_SHIFT_TAB:
822     case LFUN_TAB:
823         if (the_locking_inset) {
824             UnlockInsetInInset(bv, the_locking_inset);
825             the_locking_inset = 0;
826         }
827         if (action == LFUN_TAB)
828             moveNextCell(bv);
829         else
830             movePrevCell(bv);
831         sel_pos_start = sel_pos_end = cursor.pos();
832         sel_cell_start = sel_cell_end = actcell;
833         if (hs)
834             UpdateLocal(bv, SELECTION, false);
835         break;
836     case LFUN_LAYOUT_TABULAR:
837     {
838         dialogs_ = bv->owner()->getDialogs();
839         dialogs_->showTabular(this);
840     }
841     break;
842     case LFUN_TABULAR_FEATURE:
843         if (!TabularFeatures(bv, arg))
844             result = UNDISPATCHED;
845         break;
846     case LFUN_CUT:
847         if (!copySelection())
848             break;
849         bv->text->SetUndo(bv->buffer(), Undo::DELETE,
850 #ifndef NEW_INSETS
851           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
852           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
853 #else
854           bv->text->cursor.par()->previous,
855           bv->text->cursor.par()->next
856 #endif
857                 );
858         cutSelection();
859         UpdateLocal(bv, INIT, true);
860         break;
861     case LFUN_COPY:
862         if (!hasSelection())
863             break;
864         bv->text->FinishUndo();
865         copySelection();
866         break;
867     case LFUN_PASTE:
868         if (!hasPasteBuffer())
869             break;
870         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
871 #ifndef NEW_INSETS
872           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
873           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
874 #else
875           bv->text->cursor.par()->previous,
876           bv->text->cursor.par()->next
877 #endif
878                 );
879         pasteSelection(bv);
880         UpdateLocal(bv, INIT, true);
881         break;
882     default:
883         result = UNDISPATCHED;
884         break;
885     }
886     if (result!=FINISHED) {
887         if (!the_locking_inset) {
888 #if 0       
889             if (ocell != actcell)
890                 bview->getOwner()->getPopups().updateFormTabular();
891 #endif
892             ShowInsetCursor(bv);
893         }
894     } else
895         bv->unlockInset(this);
896     return result;
897 }
898
899
900 int InsetTabular::Latex(Buffer const * buf, ostream & os,
901                         bool fragile, bool fp) const
902 {
903     return tabular->Latex(buf, os, fragile, fp);
904 }
905
906
907 int InsetTabular::Ascii(Buffer const * buf, ostream & os, int) const
908 {
909     // This should be changed to a real ascii export
910     return tabular->Latex(buf, os, false, false);
911 }
912
913
914 int InsetTabular::Linuxdoc(Buffer const *, ostream &) const
915 {
916     return 0;
917 }
918
919
920 int InsetTabular::DocBook(Buffer const *, ostream &) const
921 {
922     return 0;
923 }
924
925
926 void InsetTabular::Validate(LaTeXFeatures & features) const
927 {
928     tabular->Validate(features);
929 }
930
931
932 bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
933                                                  LyXFont const & font,
934                                                  bool reinit) const
935 {
936     int cell = -1;
937     int maxAsc, maxDesc;
938     InsetText * inset;
939     bool changed = false;
940     
941     for(int i = 0; i < tabular->rows(); ++i) {
942         maxAsc = maxDesc = 0;
943         for(int j= 0; j < tabular->columns(); ++j) {
944             if (tabular->IsPartOfMultiColumn(i,j))
945                 continue;
946             ++cell;
947             inset = tabular->GetCellInset(cell);
948             if (!reinit)
949                 inset->update(bv, font, false);
950             maxAsc = max(maxAsc, inset->ascent(bv, font));
951             maxDesc = max(maxDesc, inset->descent(bv, font));
952             changed = tabular->SetWidthOfCell(cell, inset->width(bv, font)) || changed;
953         }
954         changed = tabular->SetAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
955         changed = tabular->SetDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
956     }
957     return changed;
958 }
959
960
961 void InsetTabular::GetCursorPos(BufferView *,
962                                 unsigned long & x, unsigned long & y) const
963 {
964     x = cursor.x() - top_x;
965     y = cursor.y();
966 }
967
968
969 void InsetTabular::ToggleInsetCursor(BufferView * bv)
970 {
971     if (the_locking_inset) {
972         the_locking_inset->ToggleInsetCursor(bv);
973         return;
974     }
975
976     LyXFont font; // = the_locking_inset->GetFont(par, cursor.pos);
977
978     int const asc = lyxfont::maxAscent(font);
979     int const desc = lyxfont::maxDescent(font);
980   
981     if (cursor_visible)
982         bv->hideLockedInsetCursor();
983     else
984         bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
985     cursor_visible = !cursor_visible;
986 }
987
988
989 void InsetTabular::ShowInsetCursor(BufferView * bv)
990 {
991     if (!cursor_visible) {
992         LyXFont font; // = GetFont(par, cursor.pos);
993     
994         int const asc = lyxfont::maxAscent(font);
995         int const desc = lyxfont::maxDescent(font);
996         bv->fitLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
997         bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
998         cursor_visible = true;
999     }
1000 }
1001
1002
1003 void InsetTabular::HideInsetCursor(BufferView * bv)
1004 {
1005     if (cursor_visible) {
1006         bv->hideLockedInsetCursor();
1007         cursor_visible = false;
1008     }
1009 //    if (cursor_visible)
1010 //        ToggleInsetCursor(bv);
1011 }
1012
1013
1014 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1015 {
1016     cursor.y(0);
1017     cursor.pos(0);
1018         
1019     actcell = actrow = actcol = 0;
1020     int ly = tabular->GetDescentOfRow(actrow);
1021
1022     // first search the right row
1023     while((ly < y) && (actrow < tabular->rows())) {
1024         cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
1025             tabular->GetAscentOfRow(actrow+1) +
1026             tabular->GetAdditionalHeight(tabular->GetCellNumber(actrow + 1,
1027                                                                 actcol)));
1028         ++actrow;
1029         ly = cursor.y() + tabular->GetDescentOfRow(actrow);
1030     }
1031     actcell = tabular->GetCellNumber(actrow, actcol);
1032
1033     // now search the right column
1034     int lx = tabular->GetWidthOfColumn(actcell) -
1035         tabular->GetAdditionalWidth(actcell);
1036     for(; !tabular->IsLastCellInRow(actcell) && (lx < x);
1037         ++actcell,lx += tabular->GetWidthOfColumn(actcell) +
1038             tabular->GetAdditionalWidth(actcell - 1));
1039     cursor.pos(0);
1040     resetPos(bv);
1041     if ((lx - (tabular->GetWidthOfColumn(actcell) / 2)) < x) {
1042         cursor.x(lx + top_x - 2);
1043         cursor.pos(1);
1044     } else {
1045         cursor.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
1046     }
1047     resetPos(bv);
1048 }
1049
1050
1051 int InsetTabular::getCellXPos(int cell) const
1052 {
1053     int c = cell;
1054
1055     for(; !tabular->IsFirstCellInRow(c); --c)
1056         ;
1057     int lx = tabular->GetWidthOfColumn(cell);
1058     for(; (c < cell); ++c) {
1059         lx += tabular->GetWidthOfColumn(c);
1060     }
1061     return (lx - tabular->GetWidthOfColumn(cell) + top_x);
1062 }
1063
1064
1065 void InsetTabular::resetPos(BufferView * bv) const
1066 {
1067     if (!locked)
1068         return;
1069     actcol = tabular->column_of_cell(actcell);
1070
1071     int cell = 0;
1072     actrow = 0;
1073     cursor.y(0);
1074     for(; (cell < actcell) && !tabular->IsLastRow(cell); ++cell) {
1075         if (tabular->IsLastCellInRow(cell)) {
1076             cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
1077                 tabular->GetAscentOfRow(actrow + 1) +
1078                 tabular->GetAdditionalHeight(cell + 1));
1079             ++actrow;
1080         }
1081     }
1082     static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1083     cursor.x(getCellXPos(actcell) + offset);
1084     if (((cursor.x() - offset) > 20) &&
1085         ((cursor.x()-offset+tabular->GetWidthOfColumn(actcell)) >
1086          (bv->workWidth()-20)))
1087     {
1088         scroll(bv, -tabular->GetWidthOfColumn(actcell)-20);
1089         UpdateLocal(bv, FULL, false);
1090     } else if ((cursor.x() - offset) < 20) {
1091         scroll(bv, 20 - cursor.x() + offset);
1092         UpdateLocal(bv, FULL, false);
1093     } else if (!cellstart(cursor.pos())) {
1094         LyXFont font(LyXFont::ALL_SANE);
1095         cursor.x(cursor.x() + tabular->GetCellInset(actcell)->width(bv,font) +
1096                 tabular->GetBeginningOfTextInCell(actcell));
1097     }
1098     if ((!the_locking_inset ||
1099          !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE)) &&
1100         (actcell != oldcell)) {
1101         dialogs_ = bv->owner()->getDialogs();
1102         dialogs_->updateTabular(const_cast<InsetTabular *>(this));
1103         oldcell = actcell;
1104     }
1105 }
1106
1107
1108 UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1109 {
1110     if (!cellstart(cursor.pos())) {
1111         if (tabular->IsLastCell(actcell))
1112             return FINISHED;
1113         ++actcell;
1114         cursor.pos((cursor.pos() + 1) % 2);
1115     } else if (lock) {
1116         if (ActivateCellInset(bv))
1117             return DISPATCHED;
1118     } else {              // before the inset
1119         cursor.pos((cursor.pos() + 1) % 2);
1120     }
1121     resetPos(bv);
1122     return DISPATCHED_NOUPDATE;
1123 }
1124
1125
1126 UpdatableInset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1127 {
1128     if (!cursor.pos()) {
1129         if (!actcell)
1130             return FINISHED;
1131         cursor.pos(0);
1132     }
1133     cursor.pos((cursor.pos() - 1) % 2);
1134     if (!cellstart(cursor.pos())) {
1135         --actcell;
1136     } else if (lock) {       // behind the inset
1137         if (ActivateCellInset(bv, 0, 0, 0, true))
1138             return DISPATCHED;
1139     }
1140     resetPos(bv);
1141     return DISPATCHED_NOUPDATE;
1142 }
1143
1144
1145 UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv)
1146 {
1147     int const ocell = actcell;
1148     actcell = tabular->GetCellAbove(actcell);
1149     if (actcell == ocell) // we moved out of the inset
1150         return FINISHED;
1151     resetPos(bv);
1152     return DISPATCHED_NOUPDATE;
1153 }
1154
1155
1156 UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv)
1157 {
1158     int const ocell = actcell;
1159     actcell = tabular->GetCellBelow(actcell);
1160     if (actcell == ocell) // we moved out of the inset
1161         return FINISHED;
1162     resetPos(bv);
1163     return DISPATCHED_NOUPDATE;
1164 }
1165
1166
1167 bool InsetTabular::moveNextCell(BufferView * bv)
1168 {
1169     if (tabular->IsLastCell(actcell))
1170         return false;
1171     ++actcell;
1172     cursor.pos((cursor.pos() + 1) % 2);
1173     if (!cellstart(cursor.pos()))
1174         cursor.pos((cursor.pos() + 1) % 2);
1175     resetPos(bv);
1176     return true;
1177 }
1178
1179
1180 bool InsetTabular::movePrevCell(BufferView * bv)
1181 {
1182     if (!actcell) // first cell
1183         return false;
1184     --actcell;
1185     cursor.pos((cursor.pos() - 1) % 2);
1186     if (cellstart(cursor.pos()))
1187         cursor.pos((cursor.pos() - 1) % 2);
1188     resetPos(bv);
1189     return true;
1190 }
1191
1192
1193 bool InsetTabular::Delete()
1194 {
1195     return true;
1196 }
1197
1198
1199 void InsetTabular::SetFont(BufferView * bv, LyXFont const & font, bool tall)
1200 {
1201     if (the_locking_inset)
1202         the_locking_inset->SetFont(bv, font, tall);
1203 }
1204
1205
1206 bool InsetTabular::TabularFeatures(BufferView * bv, string const & what)
1207 {
1208     LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1209
1210     int i = 0;
1211     for(; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
1212         string const tmp = tabularFeatures[i].feature;
1213             
1214         if (tmp == what.substr(0, tmp.length())) {
1215         //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
1216               //tabularFeatures[i].feature.length())) {
1217             action = tabularFeatures[i].action;
1218             break;
1219         }
1220     }
1221     if (action == LyXTabular::LAST_ACTION)
1222         return false;
1223
1224     string const val =
1225             frontStrip(what.substr(tabularFeatures[i].feature.length()));
1226     TabularFeatures(bv, action, val);
1227     return true;
1228 }
1229
1230
1231 void InsetTabular::TabularFeatures(BufferView * bv,
1232                                    LyXTabular::Feature feature,
1233                                    string const & value)
1234 {
1235     int i;
1236     int j;
1237     int sel_col_start;
1238     int sel_col_end;
1239     int sel_row_start;
1240     int sel_row_end;
1241     int setLines = 0;
1242     LyXAlignment setAlign = LYX_ALIGN_LEFT;
1243     LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1244     int lineSet;
1245     bool what;
1246
1247     switch (feature) {
1248       case LyXTabular::M_ALIGN_LEFT:
1249       case LyXTabular::ALIGN_LEFT:
1250           setAlign=LYX_ALIGN_LEFT;
1251           break;
1252       case LyXTabular::M_ALIGN_RIGHT:
1253       case LyXTabular::ALIGN_RIGHT:
1254           setAlign=LYX_ALIGN_RIGHT;
1255           break;
1256       case LyXTabular::M_ALIGN_CENTER:
1257       case LyXTabular::ALIGN_CENTER:
1258           setAlign=LYX_ALIGN_CENTER;
1259           break;
1260       case LyXTabular::M_VALIGN_TOP:
1261       case LyXTabular::VALIGN_TOP:
1262           setVAlign=LyXTabular::LYX_VALIGN_TOP;
1263           break;
1264       case LyXTabular::M_VALIGN_BOTTOM:
1265       case LyXTabular::VALIGN_BOTTOM:
1266           setVAlign=LyXTabular::LYX_VALIGN_BOTTOM;
1267           break;
1268       case LyXTabular::M_VALIGN_CENTER:
1269       case LyXTabular::VALIGN_CENTER:
1270           setVAlign=LyXTabular::LYX_VALIGN_CENTER;
1271           break;
1272       default:
1273           break;
1274     }
1275     if (hasSelection()) {
1276         sel_col_start = tabular->column_of_cell(sel_cell_start);
1277         sel_col_end = tabular->column_of_cell(sel_cell_end);
1278         if (sel_col_start > sel_col_end) {
1279             sel_col_end = sel_col_start;
1280             sel_col_start = tabular->column_of_cell(sel_cell_end);
1281         } else {
1282             sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1283         }
1284         
1285         sel_row_start = tabular->row_of_cell(sel_cell_start);
1286         sel_row_end = tabular->row_of_cell(sel_cell_end);
1287         if (sel_row_start > sel_row_end) {
1288                 //int tmp = sel_row_start;
1289                 //sel_row_start = sel_row_end;
1290                 //sel_row_end = tmp;
1291             swap(sel_row_start, sel_row_end);
1292         }
1293     } else {
1294         sel_col_start = sel_col_end = tabular->column_of_cell(actcell);
1295         sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1296     }
1297     bv->text->SetUndo(bv->buffer(), Undo::FINISH,
1298 #ifndef NEW_INSETS
1299               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
1300               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
1301 #else
1302               bv->text->cursor.par()->previous,
1303               bv->text->cursor.par()->next
1304 #endif
1305             );
1306
1307     int row = tabular->row_of_cell(actcell);
1308     int column = tabular->column_of_cell(actcell);
1309     bool flag = true;
1310     
1311     switch (feature) {
1312     case LyXTabular::SET_PWIDTH:
1313     {
1314         bool const update = (tabular->GetColumnPWidth(actcell) != value);
1315         tabular->SetColumnPWidth(actcell,value);
1316         if (update) {
1317             for (int i=0; i < tabular->rows(); ++i) {
1318                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1319                     resizeLyXText(bv);
1320             }
1321             UpdateLocal(bv, INIT, true);
1322         }
1323     }
1324     break;
1325     case LyXTabular::SET_MPWIDTH:
1326     {
1327         bool const update = (tabular->GetPWidth(actcell) != value);
1328         tabular->SetMColumnPWidth(actcell,value);
1329         if (update) {
1330             for (int i=0; i < tabular->rows(); ++i) {
1331                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1332                     resizeLyXText(bv);
1333             }
1334             UpdateLocal(bv, INIT, true);
1335         }
1336     }
1337     break;
1338     case LyXTabular::SET_SPECIAL_COLUMN:
1339     case LyXTabular::SET_SPECIAL_MULTI:
1340         tabular->SetAlignSpecial(actcell,value,feature);
1341         break;
1342     case LyXTabular::APPEND_ROW:
1343         // append the row into the tabular
1344         UnlockInsetInInset(bv, the_locking_inset);
1345         tabular->AppendRow(actcell);
1346         UpdateLocal(bv, INIT, true);
1347         break;
1348     case LyXTabular::APPEND_COLUMN:
1349         // append the column into the tabular
1350         tabular->AppendColumn(actcell);
1351         actcell = tabular->GetCellNumber(row, column);
1352         UpdateLocal(bv, INIT, true);
1353         break;
1354     case LyXTabular::DELETE_ROW:
1355         tabular->DeleteRow(tabular->row_of_cell(actcell));
1356         if ((row+1) > tabular->rows())
1357             --row;
1358         actcell = tabular->GetCellNumber(row, column);
1359         UpdateLocal(bv, INIT, true);
1360         break;
1361     case LyXTabular::DELETE_COLUMN:
1362         tabular->DeleteColumn(tabular->column_of_cell(actcell));
1363         if ((column+1) > tabular->columns())
1364             --column;
1365         actcell = tabular->GetCellNumber(row, column);
1366         UpdateLocal(bv, INIT, true);
1367         break;
1368     case LyXTabular::M_TOGGLE_LINE_TOP:
1369         flag = false;
1370     case LyXTabular::TOGGLE_LINE_TOP:
1371         lineSet = !tabular->TopLine(actcell, flag);
1372         for(i=sel_row_start; i<=sel_row_end; ++i)
1373             for(j=sel_col_start; j<=sel_col_end; ++j)
1374                 tabular->SetTopLine(tabular->GetCellNumber(i,j),lineSet, flag);
1375         UpdateLocal(bv, INIT, true);
1376         break;
1377     
1378     case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1379         flag = false;
1380     case LyXTabular::TOGGLE_LINE_BOTTOM:
1381         lineSet = !tabular->BottomLine(actcell, flag); 
1382         for(i=sel_row_start; i<=sel_row_end; ++i)
1383             for(j=sel_col_start; j<=sel_col_end; ++j)
1384                 tabular->SetBottomLine(tabular->GetCellNumber(i,j),lineSet,
1385                                        flag);
1386         UpdateLocal(bv, INIT, true);
1387         break;
1388                 
1389     case LyXTabular::M_TOGGLE_LINE_LEFT:
1390         flag = false;
1391     case LyXTabular::TOGGLE_LINE_LEFT:
1392         lineSet = !tabular->LeftLine(actcell, flag);
1393         for(i=sel_row_start; i<=sel_row_end; ++i)
1394             for(j=sel_col_start; j<=sel_col_end; ++j)
1395                 tabular->SetLeftLine(tabular->GetCellNumber(i,j),lineSet,
1396                                      flag);
1397         UpdateLocal(bv, INIT, true);
1398         break;
1399
1400     case LyXTabular::M_TOGGLE_LINE_RIGHT:
1401         flag = false;
1402     case LyXTabular::TOGGLE_LINE_RIGHT:
1403         lineSet = !tabular->RightLine(actcell, flag);
1404         for(i=sel_row_start; i<=sel_row_end; ++i)
1405             for(j=sel_col_start; j<=sel_col_end; ++j)
1406                 tabular->SetRightLine(tabular->GetCellNumber(i,j),lineSet,
1407                                       flag);
1408         UpdateLocal(bv, INIT, true);
1409         break;
1410     case LyXTabular::M_ALIGN_LEFT:
1411     case LyXTabular::M_ALIGN_RIGHT:
1412     case LyXTabular::M_ALIGN_CENTER:
1413         flag = false;
1414     case LyXTabular::ALIGN_LEFT:
1415     case LyXTabular::ALIGN_RIGHT:
1416     case LyXTabular::ALIGN_CENTER:
1417         for(i = sel_row_start; i <= sel_row_end; ++i)
1418             for(j = sel_col_start; j <= sel_col_end; ++j)
1419                 tabular->SetAlignment(tabular->GetCellNumber(i, j), setAlign,
1420                                       flag);
1421         if (hasSelection())
1422             UpdateLocal(bv, INIT, true);
1423         else
1424             UpdateLocal(bv, CELL, true);
1425         break;
1426     case LyXTabular::M_VALIGN_TOP:
1427     case LyXTabular::M_VALIGN_BOTTOM:
1428     case LyXTabular::M_VALIGN_CENTER:
1429         flag = false;
1430     case LyXTabular::VALIGN_TOP:
1431     case LyXTabular::VALIGN_BOTTOM:
1432     case LyXTabular::VALIGN_CENTER:
1433         for(i = sel_row_start; i <= sel_row_end; ++i)
1434             for(j = sel_col_start; j <= sel_col_end; ++j)
1435                 tabular->SetVAlignment(tabular->GetCellNumber(i, j),
1436                                        setVAlign, flag);
1437         if (hasSelection())
1438             UpdateLocal(bv, INIT, true);
1439         else
1440             UpdateLocal(bv, CELL, true);
1441         break;
1442     case LyXTabular::MULTICOLUMN:
1443     {
1444         if (sel_row_start != sel_row_end) {
1445             WriteAlert(_("Impossible Operation!"), 
1446                        _("Multicolumns can only be horizontally."), 
1447                        _("Sorry."));
1448             return;
1449         }
1450         // just multicol for one Single Cell
1451         if (!hasSelection()) {
1452             // check wether we are completly in a multicol
1453             if (tabular->IsMultiColumn(actcell)) {
1454                 tabular->UnsetMultiColumn(actcell);
1455                 UpdateLocal(bv, INIT, true);
1456             } else {
1457                 tabular->SetMultiColumn(actcell, 1);
1458                 UpdateLocal(bv, CELL, true);
1459             }
1460             return;
1461         }
1462         // we have a selection so this means we just add all this
1463         // cells to form a multicolumn cell
1464         int s_start;
1465         int s_end;
1466
1467         if (sel_cell_start > sel_cell_end) {
1468             s_start = sel_cell_end;
1469             s_end = sel_cell_start;
1470         } else {
1471             s_start = sel_cell_start;
1472             s_end = sel_cell_end;
1473         }
1474         tabular->SetMultiColumn(s_start, s_end - s_start + 1);
1475         actcell = s_start;
1476         cursor.pos(0);
1477         sel_cell_end = sel_cell_start;
1478         sel_pos_end = sel_pos_start;
1479         UpdateLocal(bv, INIT, true);
1480         break;
1481     }
1482     case LyXTabular::SET_ALL_LINES:
1483         setLines = 1;
1484     case LyXTabular::UNSET_ALL_LINES:
1485         for(i=sel_row_start; i<=sel_row_end; ++i)
1486             for(j=sel_col_start; j<=sel_col_end; ++j)
1487                 tabular->SetAllLines(tabular->GetCellNumber(i,j), setLines);
1488         UpdateLocal(bv, INIT, true);
1489         break;
1490     case LyXTabular::SET_LONGTABULAR:
1491         tabular->SetLongTabular(true);
1492         UpdateLocal(bv, INIT, true); // because this toggles displayed
1493         break;
1494     case LyXTabular::UNSET_LONGTABULAR:
1495         tabular->SetLongTabular(false);
1496         UpdateLocal(bv, INIT, true); // because this toggles displayed
1497         break;
1498     case LyXTabular::SET_ROTATE_TABULAR:
1499         tabular->SetRotateTabular(true);
1500         break;
1501     case LyXTabular::UNSET_ROTATE_TABULAR:
1502         tabular->SetRotateTabular(false);
1503         break;
1504     case LyXTabular::SET_ROTATE_CELL:
1505         for(i=sel_row_start; i<=sel_row_end; ++i)
1506             for(j=sel_col_start; j<=sel_col_end; ++j)
1507                 tabular->SetRotateCell(tabular->GetCellNumber(i,j),true);
1508         break;
1509     case LyXTabular::UNSET_ROTATE_CELL:
1510         for(i = sel_row_start; i <= sel_row_end; ++i)
1511             for(j = sel_col_start; j <= sel_col_end; ++j)
1512                 tabular->SetRotateCell(tabular->GetCellNumber(i, j), false);
1513         break;
1514     case LyXTabular::SET_USEBOX:
1515     {
1516         LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
1517         if (val == tabular->GetUsebox(actcell))
1518             val = LyXTabular::BOX_NONE;
1519         for(i = sel_row_start; i <= sel_row_end; ++i)
1520             for(j = sel_col_start; j <= sel_col_end; ++j)
1521                 tabular->SetUsebox(tabular->GetCellNumber(i, j), val);
1522         break;
1523     }
1524     case LyXTabular::SET_LTFIRSTHEAD:
1525         tabular->SetLTHead(actcell, true);
1526         break;
1527     case LyXTabular::SET_LTHEAD:
1528         tabular->SetLTHead(actcell, false);
1529         break;
1530     case LyXTabular::SET_LTFOOT:
1531         tabular->SetLTFoot(actcell, false);
1532         break;
1533     case LyXTabular::SET_LTLASTFOOT:
1534         tabular->SetLTFoot(actcell, true);
1535         break;
1536     case LyXTabular::SET_LTNEWPAGE:
1537         what = !tabular->GetLTNewPage(actcell);
1538         tabular->SetLTNewPage(actcell, what);
1539         break;
1540     // dummy stuff just to avoid warnings
1541     case LyXTabular::LAST_ACTION:
1542         break;
1543     }
1544 }
1545
1546
1547 bool InsetTabular::ActivateCellInset(BufferView * bv, int x, int y, int button,
1548                                      bool behind)
1549 {
1550     // the cursor.pos has to be before the inset so if it isn't now just
1551     // reset the curor pos first!
1552     if (!cellstart(cursor.pos())) {
1553         cursor.pos(0);
1554         resetPos(bv);
1555     }
1556     UpdatableInset * inset =
1557         static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
1558     LyXFont font(LyXFont::ALL_SANE);
1559     if (behind) {
1560         x = inset->x() + inset->width(bv, font);
1561         y = inset->descent(bv, font);
1562     }
1563     inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
1564     inset_y = cursor.y();
1565     inset->Edit(bv, x - inset_x, y - inset_y, button);
1566     if (!the_locking_inset)
1567         return false;
1568     UpdateLocal(bv, CELL, false);
1569     return (the_locking_inset != 0);
1570 }
1571
1572
1573 bool InsetTabular::InsetHit(BufferView * bv, int x, int ) const
1574 {
1575     InsetText * inset = tabular->GetCellInset(actcell);
1576     int x1 = x + top_x;
1577
1578     if (!cellstart(cursor.pos())) {
1579         return (((x + top_x) < cursor.x()) &&
1580                 ((x + top_x) > (cursor.x() - inset->width(bv,
1581                                                       LyXFont(LyXFont::ALL_SANE)))));
1582     } else {
1583         int x2 = cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
1584         return ((x1 > x2) &&
1585                 (x1 < (x2 + inset->width(bv, LyXFont(LyXFont::ALL_SANE)))));
1586     }
1587 }
1588
1589
1590 // This returns paperWidth() if the cell-width is unlimited or the width
1591 // in pixels if we have a pwidth for this cell.
1592 int InsetTabular::GetMaxWidthOfCell(Painter &, int cell) const
1593 {
1594     string const s = tabular->GetPWidth(cell);
1595
1596     if (s.empty())
1597         return -1;
1598     return VSpace(s).inPixels(0, 0);
1599 }
1600
1601
1602 int InsetTabular::getMaxWidth(Painter & pain,
1603                               UpdatableInset const * inset) const
1604 {
1605     int const n = tabular->GetNumberOfCells();
1606     int cell = 0;
1607     for(; cell < n; ++cell) {
1608         if (tabular->GetCellInset(cell) == inset)
1609             break;
1610     }
1611     if (cell >= n)
1612         return -1;
1613     int w = GetMaxWidthOfCell(pain, cell);
1614     if (w > 0)
1615         // because the inset then subtracts it's top_x and owner->x()
1616         w += (inset->x() - top_x);
1617     return w;
1618 }
1619
1620
1621 void InsetTabular::resizeLyXText(BufferView *) const
1622 {
1623     need_update = FULL;
1624 }
1625
1626
1627 LyXText * InsetTabular::getLyXText(BufferView * bv) const
1628 {
1629     if (the_locking_inset)
1630         return the_locking_inset->getLyXText(bv);
1631     return Inset::getLyXText(bv);
1632 }
1633
1634
1635 void InsetTabular::OpenLayoutDialog(BufferView * bv) const
1636 {
1637     if (the_locking_inset) {
1638         InsetTabular * i = static_cast<InsetTabular *>
1639             (the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE));
1640         if (i) {
1641             i->OpenLayoutDialog(bv);
1642             return;
1643         }
1644     }
1645     dialogs_ = bv->owner()->getDialogs();
1646     dialogs_->showTabular(const_cast<InsetTabular *>(this));
1647 }
1648
1649 //
1650 // functions returns:
1651 // 0 ... disabled
1652 // 1 ... enabled
1653 // 2 ... toggled on
1654 // 3 ... toggled off
1655 //
1656 LyXFunc::func_status InsetTabular::getStatus(string const & what) const
1657 {
1658     int action = LyXTabular::LAST_ACTION;
1659     LyXFunc::func_status status = LyXFunc::OK;
1660     
1661     int i = 0;
1662     for(; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
1663         string const tmp = tabularFeatures[i].feature;
1664         if (tmp == what.substr(0, tmp.length())) {                  
1665         //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
1666         //   tabularFeatures[i].feature.length())) {
1667             action = tabularFeatures[i].action;
1668             break;
1669         }
1670     }
1671     if (action == LyXTabular::LAST_ACTION)
1672         return LyXFunc::Unknown;
1673
1674     string const argument = frontStrip(what.substr(tabularFeatures[i].feature.length()));
1675
1676     int sel_row_start, sel_row_end;
1677     int dummy;
1678     bool flag = true;
1679
1680     if (hasSelection()) {
1681         sel_row_start = tabular->row_of_cell(sel_cell_start);
1682         sel_row_end = tabular->row_of_cell(sel_cell_end);
1683         if (sel_row_start > sel_row_end) {
1684                 //int tmp = sel_row_start;
1685                 //sel_row_start = sel_row_end;
1686                 //sel_row_end = tmp;
1687             swap(sel_row_start, sel_row_end);
1688         }
1689     } else {
1690         sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1691     }
1692
1693     switch (action) {
1694     case LyXTabular::SET_PWIDTH:
1695     case LyXTabular::SET_MPWIDTH:
1696     case LyXTabular::SET_SPECIAL_COLUMN:
1697     case LyXTabular::SET_SPECIAL_MULTI:
1698         status |= LyXFunc::Disabled;
1699         return status;
1700
1701     case LyXTabular::APPEND_ROW:
1702     case LyXTabular::APPEND_COLUMN:
1703     case LyXTabular::DELETE_ROW:
1704     case LyXTabular::DELETE_COLUMN:
1705     case LyXTabular::SET_ALL_LINES:
1706     case LyXTabular::UNSET_ALL_LINES:
1707         status |= LyXFunc::OK;
1708         return status;
1709
1710     case LyXTabular::MULTICOLUMN:
1711         if (tabular->IsMultiColumn(actcell))
1712             status |= LyXFunc::ToggleOn;
1713         else
1714             status |= LyXFunc::ToggleOff;
1715         break;
1716     case LyXTabular::M_TOGGLE_LINE_TOP:
1717         flag = false;
1718     case LyXTabular::TOGGLE_LINE_TOP:
1719         if (tabular->TopLine(actcell, flag))
1720             status |= LyXFunc::ToggleOn;
1721         else
1722             status |= LyXFunc::ToggleOff;
1723         break;
1724     case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1725         flag = false;
1726     case LyXTabular::TOGGLE_LINE_BOTTOM:
1727         if (tabular->BottomLine(actcell, flag))
1728             status |= LyXFunc::ToggleOn;
1729         else
1730             status |= LyXFunc::ToggleOff;
1731         break;
1732     case LyXTabular::M_TOGGLE_LINE_LEFT:
1733         flag = false;
1734     case LyXTabular::TOGGLE_LINE_LEFT:
1735         if (tabular->LeftLine(actcell, flag))
1736             status |= LyXFunc::ToggleOn;
1737         else
1738             status |= LyXFunc::ToggleOff;
1739         break;
1740     case LyXTabular::M_TOGGLE_LINE_RIGHT:
1741         flag = false;
1742     case LyXTabular::TOGGLE_LINE_RIGHT:
1743         if (tabular->RightLine(actcell, flag))
1744             status |= LyXFunc::ToggleOn;
1745         else
1746             status |= LyXFunc::ToggleOff;
1747         break;
1748     case LyXTabular::M_ALIGN_LEFT:
1749         flag = false;
1750     case LyXTabular::ALIGN_LEFT:
1751         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_LEFT)
1752             status |= LyXFunc::ToggleOn;
1753         else
1754             status |= LyXFunc::ToggleOff;
1755         break;
1756     case LyXTabular::M_ALIGN_RIGHT:
1757         flag = false;
1758     case LyXTabular::ALIGN_RIGHT:
1759         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_RIGHT)
1760             status |= LyXFunc::ToggleOn;
1761         else
1762             status |= LyXFunc::ToggleOff;
1763         break;
1764     case LyXTabular::M_ALIGN_CENTER:
1765         flag = false;
1766     case LyXTabular::ALIGN_CENTER:
1767         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_CENTER)
1768             status |= LyXFunc::ToggleOn;
1769         else
1770             status |= LyXFunc::ToggleOff;
1771         break;
1772     case LyXTabular::M_VALIGN_TOP:
1773         flag = false;
1774     case LyXTabular::VALIGN_TOP:
1775         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP)
1776             status |= LyXFunc::ToggleOn;
1777         else
1778             status |= LyXFunc::ToggleOff;
1779         break;
1780     case LyXTabular::M_VALIGN_BOTTOM:
1781         flag = false;
1782     case LyXTabular::VALIGN_BOTTOM:
1783         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM)
1784             status |= LyXFunc::ToggleOn;
1785         else
1786             status |= LyXFunc::ToggleOff;
1787         break;
1788     case LyXTabular::M_VALIGN_CENTER:
1789         flag = false;
1790     case LyXTabular::VALIGN_CENTER:
1791         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER)
1792             status |= LyXFunc::ToggleOn;
1793         else
1794             status |= LyXFunc::ToggleOff;
1795         break;
1796     case LyXTabular::SET_LONGTABULAR:
1797         if (tabular->IsLongTabular())
1798             status |= LyXFunc::ToggleOn;
1799         else
1800             status |= LyXFunc::ToggleOff;
1801         break;
1802     case LyXTabular::UNSET_LONGTABULAR:
1803         if (!tabular->IsLongTabular())
1804             status |= LyXFunc::ToggleOn;
1805         else
1806             status |= LyXFunc::ToggleOff;
1807         break;
1808     case LyXTabular::SET_ROTATE_TABULAR:
1809         if (tabular->GetRotateTabular())
1810             status |= LyXFunc::ToggleOn;
1811         else
1812             status |= LyXFunc::ToggleOff;
1813         break;
1814     case LyXTabular::UNSET_ROTATE_TABULAR:
1815         if (!tabular->GetRotateTabular())
1816             status |= LyXFunc::ToggleOn;
1817         else
1818             status |= LyXFunc::ToggleOff;
1819         break;
1820     case LyXTabular::SET_ROTATE_CELL:
1821         if (tabular->GetRotateCell(actcell))
1822             status |= LyXFunc::ToggleOn;
1823         else
1824             status |= LyXFunc::ToggleOff;
1825         break;
1826     case LyXTabular::UNSET_ROTATE_CELL:
1827         if (!tabular->GetRotateCell(actcell))
1828             status |= LyXFunc::ToggleOn;
1829         else
1830             status |= LyXFunc::ToggleOff;
1831         break;
1832     case LyXTabular::SET_USEBOX:
1833         if (strToInt(argument) == tabular->GetUsebox(actcell))
1834             status |= LyXFunc::ToggleOn;
1835         else
1836             status |= LyXFunc::ToggleOff;
1837         break;
1838     case LyXTabular::SET_LTFIRSTHEAD:
1839         if (tabular->GetRowOfLTHead(actcell, dummy))
1840             status |= LyXFunc::ToggleOn;
1841         else
1842             status |= LyXFunc::ToggleOff;
1843         break;
1844     case LyXTabular::SET_LTHEAD:
1845         if (tabular->GetRowOfLTHead(actcell, dummy))
1846             status |= LyXFunc::ToggleOn;
1847         else
1848             status |= LyXFunc::ToggleOff;
1849         break;
1850     case LyXTabular::SET_LTFOOT:
1851         if (tabular->GetRowOfLTFoot(actcell, dummy))
1852             status |= LyXFunc::ToggleOn;
1853         else
1854             status |= LyXFunc::ToggleOff;
1855         break;
1856     case LyXTabular::SET_LTLASTFOOT:
1857         if (tabular->GetRowOfLTFoot(actcell, dummy))
1858             status |= LyXFunc::ToggleOn;
1859         else
1860             status |= LyXFunc::ToggleOff;
1861         break;
1862     case LyXTabular::SET_LTNEWPAGE:
1863         if (tabular->GetLTNewPage(actcell))
1864             status |= LyXFunc::ToggleOn;
1865         else
1866             status |= LyXFunc::ToggleOff;
1867         break;
1868     default:
1869         status = LyXFunc::Disabled;
1870         break;
1871     }
1872     return status;
1873 }
1874
1875
1876 bool InsetTabular::copySelection()
1877 {
1878     if (!hasSelection())
1879         return false;
1880     delete paste_tabular;
1881
1882     int sel_col_start, sel_col_end;
1883     int sel_row_start, sel_row_end;
1884
1885     sel_col_start = tabular->column_of_cell(sel_cell_start);
1886     sel_col_end = tabular->column_of_cell(sel_cell_end);
1887     if (sel_col_start > sel_col_end) {
1888         sel_col_start = sel_col_end;
1889         sel_col_end = tabular->right_column_of_cell(sel_cell_start);
1890     } else {
1891         sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1892     }
1893     int columns = sel_col_end - sel_col_start + 1;
1894
1895     sel_row_start = tabular->row_of_cell(sel_cell_start);
1896     sel_row_end = tabular->row_of_cell(sel_cell_end);
1897     if (sel_row_start > sel_row_end) {
1898             //int tmp tmp = sel_row_start;
1899             //sel_row_start = sel_row_end;
1900             //sel_row_end = tmp;
1901         swap(sel_row_start, sel_row_end);
1902     }
1903     int rows = sel_row_end - sel_row_start + 1;
1904
1905     paste_tabular = new LyXTabular(this, rows, columns);
1906     
1907     if (sel_cell_start > sel_cell_end) {
1908             //int tmp = sel_cell_start;
1909             //sel_cell_start = sel_cell_end;
1910             //sel_cell_end = tmp;
1911         swap(sel_cell_start, sel_cell_end);
1912     }
1913     for(int i = sel_cell_start, j = 0; i <= sel_cell_end; ++i, ++j) {
1914         while(paste_tabular->row_of_cell(j) <
1915               (tabular->row_of_cell(i)-sel_row_start)) {
1916             ++j;
1917         }
1918         while(paste_tabular->row_of_cell(j) >
1919               (tabular->row_of_cell(i)-sel_row_start)) {
1920             ++i;
1921         }
1922         *(paste_tabular->GetCellInset(j)) = *(tabular->GetCellInset(i));
1923     }
1924     return true;
1925 }
1926
1927
1928 bool InsetTabular::pasteSelection(BufferView * bv)
1929 {
1930     if (!paste_tabular)
1931         return false;
1932     for(int j=0, i=actcell; j<paste_tabular->GetNumberOfCells(); ++j,++i) {
1933         while (paste_tabular->row_of_cell(j) > tabular->row_of_cell(i)-actrow)
1934             ++i;
1935         if (tabular->GetNumberOfCells() <= i)
1936             break;
1937         while (paste_tabular->row_of_cell(j) < tabular->row_of_cell(i)-actrow)
1938             ++j;
1939         if (paste_tabular->GetNumberOfCells() <= j)
1940             break;
1941         *(tabular->GetCellInset(i)) = *(paste_tabular->GetCellInset(j));
1942         tabular->GetCellInset(i)->setOwner(this);
1943         tabular->GetCellInset(i)->deleteLyXText(bv);
1944     }
1945     return true;
1946 }
1947
1948
1949 bool InsetTabular::cutSelection()
1950 {
1951     if (!hasSelection())
1952         return false;
1953
1954     int sel_col_start, sel_col_end;
1955     int sel_row_start, sel_row_end;
1956
1957     sel_col_start = tabular->column_of_cell(sel_cell_start);
1958     sel_col_end = tabular->column_of_cell(sel_cell_end);
1959     if (sel_col_start > sel_col_end) {
1960         sel_col_start = sel_col_end;
1961         sel_col_end = tabular->right_column_of_cell(sel_cell_start);
1962     } else {
1963         sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1964     }
1965     sel_row_start = tabular->row_of_cell(sel_cell_start);
1966     sel_row_end = tabular->row_of_cell(sel_cell_end);
1967     if (sel_row_start > sel_row_end) {
1968             //int tmp = sel_row_start;
1969             //sel_row_start = sel_row_end;
1970             //sel_row_end = tmp;
1971         swap(sel_row_start, sel_row_end);
1972     }
1973     if (sel_cell_start > sel_cell_end) {
1974             //int tmp = sel_cell_start;
1975             //sel_cell_start = sel_cell_end;
1976             //sel_cell_end = tmp;
1977         swap(sel_cell_start, sel_cell_end);
1978     }
1979     for(int i = sel_row_start; i <= sel_row_end; ++i) {
1980         for(int j = sel_col_start; j <= sel_col_end; ++j) {
1981             tabular->GetCellInset(tabular->GetCellNumber(i, j))->clear();
1982         }
1983     }
1984     return true;
1985 }
1986