]> git.lyx.org Git - lyx.git/blob - src/insets/insettabular.C
Kayvan and Dekel's patch + some small fixes to xforms/
[lyx.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 = 0;
438     inset_x = 0;
439     inset_y = 0;
440     setPos(bv, x, y);
441     sel_pos_start = sel_pos_end = cursor.pos();
442     sel_cell_start = sel_cell_end = actcell;
443     bv->text->FinishUndo();
444     if (InsetHit(bv, x, y)) {
445         ActivateCellInset(bv, x, y, button);
446     }
447     UpdateLocal(bv, NONE, false);
448 //    bv->getOwner()->getPopups().updateFormTabular();
449 }
450
451
452 void InsetTabular::InsetUnlock(BufferView * bv)
453 {
454     if (the_locking_inset) {
455         the_locking_inset->InsetUnlock(bv);
456         the_locking_inset = 0;
457     }
458     HideInsetCursor(bv);
459     no_selection = false;
460     oldcell = -1;
461     locked = false;
462     if (scroll() || hasSelection()) {
463         if (scroll()) {
464             scroll(bv, 0.0F);
465         } else {
466             sel_pos_start = sel_pos_end = 0;
467             sel_cell_start = sel_cell_end = 0;
468         }
469         UpdateLocal(bv, FULL, false);
470     }
471 }
472
473
474 void InsetTabular::UpdateLocal(BufferView * bv, UpdateCodes what,
475                                bool mark_dirty) const
476 {
477     need_update = what;
478     // Dirty Cast! (Lgb)
479     bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
480     if (locked && (what != NONE))
481         resetPos(bv);
482 }
483
484
485 bool InsetTabular::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
486 {
487     lyxerr[Debug::INSETS] << "InsetTabular::LockInsetInInset(" <<inset<< "): ";
488     if (!inset)
489         return false;
490     oldcell = -1;
491     if (inset == tabular->GetCellInset(actcell)) {
492         lyxerr[Debug::INSETS] << "OK" << endl;
493         the_locking_inset = tabular->GetCellInset(actcell);
494         resetPos(bv);
495         inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
496         inset_y = cursor.y();
497         inset_pos = cursor.pos();
498         return true;
499     } else if (the_locking_inset && (the_locking_inset == inset)) {
500         if (cursor.pos() == inset_pos) {
501             lyxerr[Debug::INSETS] << "OK" << endl;
502             resetPos(bv);
503             inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
504             inset_y = cursor.y();
505         } else {
506             lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
507         }
508     } else if (the_locking_inset) {
509         lyxerr[Debug::INSETS] << "MAYBE" << endl;
510         return the_locking_inset->LockInsetInInset(bv, inset);
511     }
512     lyxerr[Debug::INSETS] << "NOT OK" << endl;
513     return false;
514 }
515
516
517 bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
518                                    bool lr)
519 {
520     if (!the_locking_inset)
521         return false;
522     if (the_locking_inset == inset) {
523         the_locking_inset->InsetUnlock(bv);
524         the_locking_inset = 0;
525         if (lr)
526             moveRight(bv, false);
527         UpdateLocal(bv, CELL, false);
528         return true;
529     }
530     if (the_locking_inset->UnlockInsetInInset(bv, inset, lr)) {
531         if (inset->LyxCode() == TABULAR_CODE &&
532             !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))
533         {
534             dialogs_ = bv->owner()->getDialogs();
535             dialogs_->updateTabular(this);
536             oldcell = actcell;
537         }
538         return true;
539     }
540     return false;
541 }
542
543
544 bool InsetTabular::UpdateInsetInInset(BufferView * bv, Inset * inset)
545 {
546     if (!the_locking_inset)
547         return false;
548     if (the_locking_inset != inset)
549         return the_locking_inset->UpdateInsetInInset(bv, inset);
550     UpdateLocal(bv, CELL, false);
551     return true;
552 }
553
554
555 unsigned int InsetTabular::InsetInInsetY()
556 {
557     if (!the_locking_inset)
558         return 0;
559
560     return (inset_y + the_locking_inset->InsetInInsetY());
561 }
562
563
564 UpdatableInset * InsetTabular::GetLockingInset()
565 {
566     return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
567 }
568
569
570 UpdatableInset * InsetTabular::GetFirstLockingInsetOfType(Inset::Code c)
571 {
572     if (c == LyxCode())
573         return this;
574     if (the_locking_inset)
575         return the_locking_inset->GetFirstLockingInsetOfType(c);
576     return 0;
577 }
578
579
580 bool InsetTabular::InsertInset(BufferView * bv, Inset * inset)
581 {
582     if (the_locking_inset)
583         return the_locking_inset->InsertInset(bv, inset);
584     return false;
585 }
586
587
588 void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
589 {
590     if (hasSelection()) {
591         sel_pos_start = sel_pos_end = sel_cell_start = sel_cell_end = 0;
592         UpdateLocal(bv, SELECTION, false);
593     }
594     no_selection = false;
595
596     int const ocell = actcell;
597     int const orow = actrow;
598
599     HideInsetCursor(bv);
600     setPos(bv, x, y);
601     if (actrow != orow)
602         UpdateLocal(bv, NONE, false);
603     sel_pos_start = sel_pos_end = cursor.pos();
604     sel_cell_start = sel_cell_end = actcell;
605
606     bool const inset_hit = InsetHit(bv, x, y);
607
608     if ((ocell == actcell) && the_locking_inset && inset_hit) {
609         cursor.pos(0); // always before the inset!
610         resetPos(bv);
611         the_locking_inset->InsetButtonPress(bv,
612                                             x - inset_x, y - inset_y, button);
613         return;
614     } else if (the_locking_inset) {
615         the_locking_inset->InsetUnlock(bv);
616     }
617     the_locking_inset = 0;
618     if (inset_hit && bv->the_locking_inset) {
619         if (ActivateCellInset(bv, x, y, button))
620             the_locking_inset->InsetButtonPress(bv, x - inset_x,
621                                                 y - inset_y, button);
622         return;
623     }
624     ShowInsetCursor(bv);
625 }
626
627
628 void InsetTabular::InsetButtonRelease(BufferView * bv,
629                                       int x, int y, int button)
630 {
631     if (button == 3) {
632         if (the_locking_inset) {
633             UpdatableInset * i;
634             if ((i=the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))) {
635                 i->InsetButtonRelease(bv, x, y, button);
636                 return;
637             }
638         }
639         dialogs_ = bv->owner()->getDialogs();
640         dialogs_->showTabular(this);
641         return;
642     }
643     if (the_locking_inset) {
644         the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
645         return;
646     }
647     no_selection = false;
648 }
649
650
651 void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button)
652 {
653     if (the_locking_inset) {
654         the_locking_inset->InsetMotionNotify(bv, x - inset_x,
655                                              y - inset_y, button);
656         return;
657     }
658     if (!no_selection) {
659         HideInsetCursor(bv);
660         int const old_pos = sel_pos_end;
661         int const old_cell = actcell;
662
663         setPos(bv, x, y);
664         sel_pos_end = cursor.pos();
665         sel_cell_end = actcell;
666         if ((sel_cell_end != old_cell) || (old_pos != sel_pos_end))
667             UpdateLocal(bv, SELECTION, false);
668         ShowInsetCursor(bv);
669     }
670     no_selection = false;
671 }
672
673
674 void InsetTabular::InsetKeyPress(XKeyEvent * xke)
675 {
676     if (the_locking_inset) {
677         the_locking_inset->InsetKeyPress(xke);
678         return;
679     }
680 }
681
682
683 UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
684                                                    string const & arg)
685 {
686     UpdatableInset::RESULT 
687         result;
688
689     no_selection = false;
690     if (((result=UpdatableInset::LocalDispatch(bv, action, arg)) == DISPATCHED)
691         || (result == DISPATCHED_NOUPDATE)) {
692
693         resetPos(bv);
694         return result;
695     }
696
697     if ((action < 0) && arg.empty())
698         return FINISHED;
699
700     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
701         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
702         cursor.x_fix(-1);
703     if (the_locking_inset) {
704         result=the_locking_inset->LocalDispatch(bv, action, arg);
705         if (result == DISPATCHED_NOUPDATE)
706             return result;
707         else if (result == DISPATCHED) {
708             the_locking_inset->ToggleInsetCursor(bv);
709             UpdateLocal(bv, CELL, false);
710             the_locking_inset->ToggleInsetCursor(bv);
711             return result;
712         } else if (result == FINISHED) {
713             if ((action == LFUN_RIGHT) || (action == -1)) {
714                 cursor.pos(inset_pos + 1);
715                 resetPos(bv);
716             }
717             sel_pos_start = sel_pos_end = cursor.pos();
718             sel_cell_start = sel_cell_end = actcell;
719             the_locking_inset=0;
720             result = DISPATCHED;
721             return result;
722         }
723     }
724
725     bool hs = hasSelection();
726     HideInsetCursor(bv);
727     result=DISPATCHED;
728     switch (action) {
729         // Normal chars not handled here
730     case -1:
731         break;
732         // --- Cursor Movements ---------------------------------------------
733     case LFUN_RIGHTSEL:
734         if (tabular->IsLastCellInRow(actcell) && !cellstart(cursor.pos()))
735             break;
736         moveRight(bv, false);
737         sel_pos_end = cursor.pos();
738         if (!cellstart(cursor.pos())) {
739             if (tabular->right_column_of_cell(sel_cell_start) >
740                 tabular->right_column_of_cell(actcell))
741                 sel_cell_end = actcell+1;
742             else
743                 sel_cell_end = actcell;
744         }
745         UpdateLocal(bv, SELECTION, false);
746         break;
747     case LFUN_RIGHT:
748         result = moveRight(bv);
749         sel_pos_start = sel_pos_end = cursor.pos();
750         sel_cell_start = sel_cell_end = actcell;
751         if (hs)
752             UpdateLocal(bv, SELECTION, false);
753         break;
754     case LFUN_LEFTSEL:
755         if (tabular->IsFirstCellInRow(actcell) && cellstart(cursor.pos()))
756             break;
757         moveLeft(bv, false);
758         sel_pos_end = cursor.pos();
759         if (cellstart(cursor.pos())) {
760             if (tabular->column_of_cell(sel_cell_start) >=
761                 tabular->column_of_cell(actcell))
762                 sel_cell_end = actcell;
763             else
764                 sel_cell_end = actcell-1;
765         }
766         UpdateLocal(bv, SELECTION, false);
767         break;
768     case LFUN_LEFT:
769         result = moveLeft(bv);
770         sel_pos_start = sel_pos_end = cursor.pos();
771         sel_cell_start = sel_cell_end = actcell;
772         if (hs)
773             UpdateLocal(bv, SELECTION, false);
774         break;
775     case LFUN_DOWNSEL:
776     {
777         int const ocell = actcell;
778         moveDown(bv);
779         sel_pos_end = cursor.pos();
780         if ((ocell == sel_cell_end) ||
781             (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
782             sel_cell_end = tabular->GetCellBelow(sel_cell_end);
783         else
784             sel_cell_end = tabular->GetLastCellBelow(sel_cell_end);
785         UpdateLocal(bv, SELECTION, false);
786     }
787     break;
788     case LFUN_DOWN:
789         result = moveDown(bv);
790         sel_pos_start = sel_pos_end = cursor.pos();
791         sel_cell_start = sel_cell_end = actcell;
792         if (hs)
793             UpdateLocal(bv, SELECTION, false);
794         break;
795     case LFUN_UPSEL:
796     {
797         int const ocell = actcell;
798         moveUp(bv);
799         sel_pos_end = cursor.pos();
800         if ((ocell == sel_cell_end) ||
801             (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
802             sel_cell_end = tabular->GetCellAbove(sel_cell_end);
803         else
804             sel_cell_end = tabular->GetLastCellAbove(sel_cell_end);
805         UpdateLocal(bv, SELECTION, false);
806     }
807     break;
808     case LFUN_UP:
809         result = moveUp(bv);
810         sel_pos_start = sel_pos_end = cursor.pos();
811         sel_cell_start = sel_cell_end = actcell;
812         if (hs)
813             UpdateLocal(bv, SELECTION, false);
814         break;
815     case LFUN_BACKSPACE:
816         break;
817     case LFUN_DELETE:
818         break;
819     case LFUN_HOME:
820         break;
821     case LFUN_END:
822         break;
823     case LFUN_SHIFT_TAB:
824     case LFUN_TAB:
825         if (the_locking_inset) {
826             UnlockInsetInInset(bv, the_locking_inset);
827             the_locking_inset = 0;
828         }
829         if (action == LFUN_TAB)
830             moveNextCell(bv);
831         else
832             movePrevCell(bv);
833         sel_pos_start = sel_pos_end = cursor.pos();
834         sel_cell_start = sel_cell_end = actcell;
835         if (hs)
836             UpdateLocal(bv, SELECTION, false);
837         break;
838     case LFUN_LAYOUT_TABULAR:
839     {
840         dialogs_ = bv->owner()->getDialogs();
841         dialogs_->showTabular(this);
842     }
843     break;
844     case LFUN_TABULAR_FEATURE:
845         if (!TabularFeatures(bv, arg))
846             result = UNDISPATCHED;
847         break;
848     case LFUN_CUT:
849         if (!copySelection())
850             break;
851         bv->text->SetUndo(bv->buffer(), Undo::DELETE,
852 #ifndef NEW_INSETS
853           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
854           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
855 #else
856           bv->text->cursor.par()->previous,
857           bv->text->cursor.par()->next
858 #endif
859                 );
860         cutSelection();
861         UpdateLocal(bv, INIT, true);
862         break;
863     case LFUN_COPY:
864         if (!hasSelection())
865             break;
866         bv->text->FinishUndo();
867         copySelection();
868         break;
869     case LFUN_PASTE:
870         if (!hasPasteBuffer())
871             break;
872         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
873 #ifndef NEW_INSETS
874           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
875           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
876 #else
877           bv->text->cursor.par()->previous,
878           bv->text->cursor.par()->next
879 #endif
880                 );
881         pasteSelection(bv);
882         UpdateLocal(bv, INIT, true);
883         break;
884     default:
885         result = UNDISPATCHED;
886         break;
887     }
888     if (result!=FINISHED) {
889         if (!the_locking_inset) {
890 #if 0       
891             if (ocell != actcell)
892                 bview->getOwner()->getPopups().updateFormTabular();
893 #endif
894             ShowInsetCursor(bv);
895         }
896     } else
897         bv->unlockInset(this);
898     return result;
899 }
900
901
902 int InsetTabular::Latex(Buffer const * buf, ostream & os,
903                         bool fragile, bool fp) const
904 {
905     return tabular->Latex(buf, os, fragile, fp);
906 }
907
908
909 int InsetTabular::Ascii(Buffer const * buf, ostream & os, int) const
910 {
911     // This should be changed to a real ascii export
912     return tabular->Latex(buf, os, false, false);
913 }
914
915
916 int InsetTabular::Linuxdoc(Buffer const *, ostream &) const
917 {
918     return 0;
919 }
920
921
922 int InsetTabular::DocBook(Buffer const *, ostream &) const
923 {
924     return 0;
925 }
926
927
928 void InsetTabular::Validate(LaTeXFeatures & features) const
929 {
930     tabular->Validate(features);
931 }
932
933
934 bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
935                                                  LyXFont const & font,
936                                                  bool reinit) const
937 {
938     int cell = -1;
939     int maxAsc, maxDesc;
940     InsetText * inset;
941     bool changed = false;
942     
943     for(int i = 0; i < tabular->rows(); ++i) {
944         maxAsc = maxDesc = 0;
945         for(int j= 0; j < tabular->columns(); ++j) {
946             if (tabular->IsPartOfMultiColumn(i,j))
947                 continue;
948             ++cell;
949             inset = tabular->GetCellInset(cell);
950             if (!reinit)
951                 inset->update(bv, font, false);
952             maxAsc = max(maxAsc, inset->ascent(bv, font));
953             maxDesc = max(maxDesc, inset->descent(bv, font));
954             changed = tabular->SetWidthOfCell(cell, inset->width(bv, font)) || changed;
955         }
956         changed = tabular->SetAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
957         changed = tabular->SetDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
958     }
959     return changed;
960 }
961
962
963 void InsetTabular::GetCursorPos(BufferView *,
964                                 int & x, int & y) const
965 {
966     x = cursor.x() - top_x;
967     y = cursor.y();
968 }
969
970
971 void InsetTabular::ToggleInsetCursor(BufferView * bv)
972 {
973     if (the_locking_inset) {
974         the_locking_inset->ToggleInsetCursor(bv);
975         return;
976     }
977
978     LyXFont font; // = the_locking_inset->GetFont(par, cursor.pos);
979
980     int const asc = lyxfont::maxAscent(font);
981     int const desc = lyxfont::maxDescent(font);
982   
983     if (cursor_visible)
984         bv->hideLockedInsetCursor();
985     else
986         bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
987     cursor_visible = !cursor_visible;
988 }
989
990
991 void InsetTabular::ShowInsetCursor(BufferView * bv)
992 {
993     if (!cursor_visible) {
994         LyXFont font; // = GetFont(par, cursor.pos);
995     
996         int const asc = lyxfont::maxAscent(font);
997         int const desc = lyxfont::maxDescent(font);
998         bv->fitLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
999         bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
1000         cursor_visible = true;
1001     }
1002 }
1003
1004
1005 void InsetTabular::HideInsetCursor(BufferView * bv)
1006 {
1007     if (cursor_visible) {
1008         bv->hideLockedInsetCursor();
1009         cursor_visible = false;
1010     }
1011 //    if (cursor_visible)
1012 //        ToggleInsetCursor(bv);
1013 }
1014
1015
1016 void InsetTabular::setPos(BufferView * bv, int x, int y) const
1017 {
1018     cursor.y(0);
1019     cursor.pos(0);
1020         
1021     actcell = actrow = actcol = 0;
1022     unsigned int ly = tabular->GetDescentOfRow(actrow);
1023
1024     // first search the right row
1025     while((ly < y) && (actrow < tabular->rows())) {
1026         cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
1027             tabular->GetAscentOfRow(actrow + 1) +
1028             tabular->GetAdditionalHeight(tabular->GetCellNumber(actrow + 1,
1029                                                                 actcol)));
1030         ++actrow;
1031         ly = cursor.y() + tabular->GetDescentOfRow(actrow);
1032     }
1033     actcell = tabular->GetCellNumber(actrow, actcol);
1034
1035     // now search the right column
1036     unsigned int lx = tabular->GetWidthOfColumn(actcell) -
1037         tabular->GetAdditionalWidth(actcell);
1038     for(; !tabular->IsLastCellInRow(actcell) && (lx < x);
1039         ++actcell,lx += tabular->GetWidthOfColumn(actcell) +
1040             tabular->GetAdditionalWidth(actcell - 1));
1041     cursor.pos(0);
1042     resetPos(bv);
1043     if ((lx - (tabular->GetWidthOfColumn(actcell) / 2)) < x) {
1044         cursor.x(lx + top_x - 2);
1045         cursor.pos(1);
1046     } else {
1047         cursor.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
1048     }
1049     resetPos(bv);
1050 }
1051
1052
1053 int InsetTabular::getCellXPos(int cell) const
1054 {
1055     int c = cell;
1056
1057     for(; !tabular->IsFirstCellInRow(c); --c)
1058         ;
1059     int lx = tabular->GetWidthOfColumn(cell);
1060     for(; (c < cell); ++c) {
1061         lx += tabular->GetWidthOfColumn(c);
1062     }
1063     return (lx - tabular->GetWidthOfColumn(cell) + top_x);
1064 }
1065
1066
1067 void InsetTabular::resetPos(BufferView * bv) const
1068 {
1069     if (!locked)
1070         return;
1071     actcol = tabular->column_of_cell(actcell);
1072
1073     int cell = 0;
1074     actrow = 0;
1075     cursor.y(0);
1076     for(; (cell < actcell) && !tabular->IsLastRow(cell); ++cell) {
1077         if (tabular->IsLastCellInRow(cell)) {
1078             cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
1079                 tabular->GetAscentOfRow(actrow + 1) +
1080                 tabular->GetAdditionalHeight(cell + 1));
1081             ++actrow;
1082         }
1083     }
1084     static int const offset = ADD_TO_TABULAR_WIDTH + 2;
1085     cursor.x(getCellXPos(actcell) + offset);
1086     if (((cursor.x() - offset) > 20) &&
1087         ((cursor.x()-offset+tabular->GetWidthOfColumn(actcell)) >
1088          (bv->workWidth()-20)))
1089     {
1090         scroll(bv, -tabular->GetWidthOfColumn(actcell)-20);
1091         UpdateLocal(bv, FULL, false);
1092     } else if ((cursor.x() - offset) < 20) {
1093         scroll(bv, 20 - cursor.x() + offset);
1094         UpdateLocal(bv, FULL, false);
1095     } else if (!cellstart(cursor.pos())) {
1096         LyXFont font(LyXFont::ALL_SANE);
1097         cursor.x(cursor.x() + tabular->GetCellInset(actcell)->width(bv,font) +
1098                 tabular->GetBeginningOfTextInCell(actcell));
1099     }
1100     if ((!the_locking_inset ||
1101          !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE)) &&
1102         (actcell != oldcell)) {
1103         dialogs_ = bv->owner()->getDialogs();
1104         dialogs_->updateTabular(const_cast<InsetTabular *>(this));
1105         oldcell = actcell;
1106     }
1107 }
1108
1109
1110 UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
1111 {
1112     if (!cellstart(cursor.pos())) {
1113         if (tabular->IsLastCell(actcell))
1114             return FINISHED;
1115         ++actcell;
1116         cursor.pos((cursor.pos() + 1) % 2);
1117     } else if (lock) {
1118         if (ActivateCellInset(bv))
1119             return DISPATCHED;
1120     } else {              // before the inset
1121         cursor.pos((cursor.pos() + 1) % 2);
1122     }
1123     resetPos(bv);
1124     return DISPATCHED_NOUPDATE;
1125 }
1126
1127
1128 UpdatableInset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
1129 {
1130     if (!cursor.pos()) {
1131         if (!actcell)
1132             return FINISHED;
1133         cursor.pos(0);
1134     }
1135     cursor.pos((cursor.pos() - 1) % 2);
1136     if (!cellstart(cursor.pos())) {
1137         --actcell;
1138     } else if (lock) {       // behind the inset
1139         if (ActivateCellInset(bv, 0, 0, 0, true))
1140             return DISPATCHED;
1141     }
1142     resetPos(bv);
1143     return DISPATCHED_NOUPDATE;
1144 }
1145
1146
1147 UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv)
1148 {
1149     int const ocell = actcell;
1150     actcell = tabular->GetCellAbove(actcell);
1151     if (actcell == ocell) // we moved out of the inset
1152         return FINISHED;
1153     resetPos(bv);
1154     return DISPATCHED_NOUPDATE;
1155 }
1156
1157
1158 UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv)
1159 {
1160     int const ocell = actcell;
1161     actcell = tabular->GetCellBelow(actcell);
1162     if (actcell == ocell) // we moved out of the inset
1163         return FINISHED;
1164     resetPos(bv);
1165     return DISPATCHED_NOUPDATE;
1166 }
1167
1168
1169 bool InsetTabular::moveNextCell(BufferView * bv)
1170 {
1171     if (tabular->IsLastCell(actcell))
1172         return false;
1173     ++actcell;
1174     cursor.pos((cursor.pos() + 1) % 2);
1175     if (!cellstart(cursor.pos()))
1176         cursor.pos((cursor.pos() + 1) % 2);
1177     resetPos(bv);
1178     return true;
1179 }
1180
1181
1182 bool InsetTabular::movePrevCell(BufferView * bv)
1183 {
1184     if (!actcell) // first cell
1185         return false;
1186     --actcell;
1187     cursor.pos((cursor.pos() - 1) % 2);
1188     if (cellstart(cursor.pos()))
1189         cursor.pos((cursor.pos() - 1) % 2);
1190     resetPos(bv);
1191     return true;
1192 }
1193
1194
1195 bool InsetTabular::Delete()
1196 {
1197     return true;
1198 }
1199
1200
1201 void InsetTabular::SetFont(BufferView * bv, LyXFont const & font, bool tall)
1202 {
1203     if (the_locking_inset)
1204         the_locking_inset->SetFont(bv, font, tall);
1205 }
1206
1207
1208 bool InsetTabular::TabularFeatures(BufferView * bv, string const & what)
1209 {
1210     LyXTabular::Feature action = LyXTabular::LAST_ACTION;
1211
1212     int i = 0;
1213     for(; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
1214         string const tmp = tabularFeatures[i].feature;
1215             
1216         if (tmp == what.substr(0, tmp.length())) {
1217         //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
1218               //tabularFeatures[i].feature.length())) {
1219             action = tabularFeatures[i].action;
1220             break;
1221         }
1222     }
1223     if (action == LyXTabular::LAST_ACTION)
1224         return false;
1225
1226     string const val =
1227             frontStrip(what.substr(tabularFeatures[i].feature.length()));
1228     TabularFeatures(bv, action, val);
1229     return true;
1230 }
1231
1232
1233 void InsetTabular::TabularFeatures(BufferView * bv,
1234                                    LyXTabular::Feature feature,
1235                                    string const & value)
1236 {
1237     int i;
1238     int j;
1239     int sel_col_start;
1240     int sel_col_end;
1241     int sel_row_start;
1242     int sel_row_end;
1243     int setLines = 0;
1244     LyXAlignment setAlign = LYX_ALIGN_LEFT;
1245     LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
1246     int lineSet;
1247     bool what;
1248
1249     switch (feature) {
1250       case LyXTabular::M_ALIGN_LEFT:
1251       case LyXTabular::ALIGN_LEFT:
1252           setAlign=LYX_ALIGN_LEFT;
1253           break;
1254       case LyXTabular::M_ALIGN_RIGHT:
1255       case LyXTabular::ALIGN_RIGHT:
1256           setAlign=LYX_ALIGN_RIGHT;
1257           break;
1258       case LyXTabular::M_ALIGN_CENTER:
1259       case LyXTabular::ALIGN_CENTER:
1260           setAlign=LYX_ALIGN_CENTER;
1261           break;
1262       case LyXTabular::M_VALIGN_TOP:
1263       case LyXTabular::VALIGN_TOP:
1264           setVAlign=LyXTabular::LYX_VALIGN_TOP;
1265           break;
1266       case LyXTabular::M_VALIGN_BOTTOM:
1267       case LyXTabular::VALIGN_BOTTOM:
1268           setVAlign=LyXTabular::LYX_VALIGN_BOTTOM;
1269           break;
1270       case LyXTabular::M_VALIGN_CENTER:
1271       case LyXTabular::VALIGN_CENTER:
1272           setVAlign=LyXTabular::LYX_VALIGN_CENTER;
1273           break;
1274       default:
1275           break;
1276     }
1277     if (hasSelection()) {
1278         sel_col_start = tabular->column_of_cell(sel_cell_start);
1279         sel_col_end = tabular->column_of_cell(sel_cell_end);
1280         if (sel_col_start > sel_col_end) {
1281             sel_col_end = sel_col_start;
1282             sel_col_start = tabular->column_of_cell(sel_cell_end);
1283         } else {
1284             sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1285         }
1286         
1287         sel_row_start = tabular->row_of_cell(sel_cell_start);
1288         sel_row_end = tabular->row_of_cell(sel_cell_end);
1289         if (sel_row_start > sel_row_end) {
1290                 //int tmp = sel_row_start;
1291                 //sel_row_start = sel_row_end;
1292                 //sel_row_end = tmp;
1293             swap(sel_row_start, sel_row_end);
1294         }
1295     } else {
1296         sel_col_start = sel_col_end = tabular->column_of_cell(actcell);
1297         sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1298     }
1299     bv->text->SetUndo(bv->buffer(), Undo::FINISH,
1300 #ifndef NEW_INSETS
1301               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
1302               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
1303 #else
1304               bv->text->cursor.par()->previous,
1305               bv->text->cursor.par()->next
1306 #endif
1307             );
1308
1309     int row = tabular->row_of_cell(actcell);
1310     int column = tabular->column_of_cell(actcell);
1311     bool flag = true;
1312     
1313     switch (feature) {
1314     case LyXTabular::SET_PWIDTH:
1315     {
1316         bool const update = (tabular->GetColumnPWidth(actcell) != value);
1317         tabular->SetColumnPWidth(actcell,value);
1318         if (update) {
1319             for (int i=0; i < tabular->rows(); ++i) {
1320                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1321                     resizeLyXText(bv);
1322             }
1323             UpdateLocal(bv, INIT, true);
1324         }
1325     }
1326     break;
1327     case LyXTabular::SET_MPWIDTH:
1328     {
1329         bool const update = (tabular->GetPWidth(actcell) != value);
1330         tabular->SetMColumnPWidth(actcell,value);
1331         if (update) {
1332             for (int i=0; i < tabular->rows(); ++i) {
1333                 tabular->GetCellInset(tabular->GetCellNumber(i, column))->
1334                     resizeLyXText(bv);
1335             }
1336             UpdateLocal(bv, INIT, true);
1337         }
1338     }
1339     break;
1340     case LyXTabular::SET_SPECIAL_COLUMN:
1341     case LyXTabular::SET_SPECIAL_MULTI:
1342         tabular->SetAlignSpecial(actcell,value,feature);
1343         break;
1344     case LyXTabular::APPEND_ROW:
1345         // append the row into the tabular
1346         UnlockInsetInInset(bv, the_locking_inset);
1347         tabular->AppendRow(actcell);
1348         UpdateLocal(bv, INIT, true);
1349         break;
1350     case LyXTabular::APPEND_COLUMN:
1351         // append the column into the tabular
1352         tabular->AppendColumn(actcell);
1353         actcell = tabular->GetCellNumber(row, column);
1354         UpdateLocal(bv, INIT, true);
1355         break;
1356     case LyXTabular::DELETE_ROW:
1357         tabular->DeleteRow(tabular->row_of_cell(actcell));
1358         if ((row+1) > tabular->rows())
1359             --row;
1360         actcell = tabular->GetCellNumber(row, column);
1361         UpdateLocal(bv, INIT, true);
1362         break;
1363     case LyXTabular::DELETE_COLUMN:
1364         tabular->DeleteColumn(tabular->column_of_cell(actcell));
1365         if ((column+1) > tabular->columns())
1366             --column;
1367         actcell = tabular->GetCellNumber(row, column);
1368         UpdateLocal(bv, INIT, true);
1369         break;
1370     case LyXTabular::M_TOGGLE_LINE_TOP:
1371         flag = false;
1372     case LyXTabular::TOGGLE_LINE_TOP:
1373         lineSet = !tabular->TopLine(actcell, flag);
1374         for(i=sel_row_start; i<=sel_row_end; ++i)
1375             for(j=sel_col_start; j<=sel_col_end; ++j)
1376                 tabular->SetTopLine(tabular->GetCellNumber(i,j),lineSet, flag);
1377         UpdateLocal(bv, INIT, true);
1378         break;
1379     
1380     case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1381         flag = false;
1382     case LyXTabular::TOGGLE_LINE_BOTTOM:
1383         lineSet = !tabular->BottomLine(actcell, flag); 
1384         for(i=sel_row_start; i<=sel_row_end; ++i)
1385             for(j=sel_col_start; j<=sel_col_end; ++j)
1386                 tabular->SetBottomLine(tabular->GetCellNumber(i,j),lineSet,
1387                                        flag);
1388         UpdateLocal(bv, INIT, true);
1389         break;
1390                 
1391     case LyXTabular::M_TOGGLE_LINE_LEFT:
1392         flag = false;
1393     case LyXTabular::TOGGLE_LINE_LEFT:
1394         lineSet = !tabular->LeftLine(actcell, flag);
1395         for(i=sel_row_start; i<=sel_row_end; ++i)
1396             for(j=sel_col_start; j<=sel_col_end; ++j)
1397                 tabular->SetLeftLine(tabular->GetCellNumber(i,j),lineSet,
1398                                      flag);
1399         UpdateLocal(bv, INIT, true);
1400         break;
1401
1402     case LyXTabular::M_TOGGLE_LINE_RIGHT:
1403         flag = false;
1404     case LyXTabular::TOGGLE_LINE_RIGHT:
1405         lineSet = !tabular->RightLine(actcell, flag);
1406         for(i=sel_row_start; i<=sel_row_end; ++i)
1407             for(j=sel_col_start; j<=sel_col_end; ++j)
1408                 tabular->SetRightLine(tabular->GetCellNumber(i,j),lineSet,
1409                                       flag);
1410         UpdateLocal(bv, INIT, true);
1411         break;
1412     case LyXTabular::M_ALIGN_LEFT:
1413     case LyXTabular::M_ALIGN_RIGHT:
1414     case LyXTabular::M_ALIGN_CENTER:
1415         flag = false;
1416     case LyXTabular::ALIGN_LEFT:
1417     case LyXTabular::ALIGN_RIGHT:
1418     case LyXTabular::ALIGN_CENTER:
1419         for(i = sel_row_start; i <= sel_row_end; ++i)
1420             for(j = sel_col_start; j <= sel_col_end; ++j)
1421                 tabular->SetAlignment(tabular->GetCellNumber(i, j), setAlign,
1422                                       flag);
1423         if (hasSelection())
1424             UpdateLocal(bv, INIT, true);
1425         else
1426             UpdateLocal(bv, CELL, true);
1427         break;
1428     case LyXTabular::M_VALIGN_TOP:
1429     case LyXTabular::M_VALIGN_BOTTOM:
1430     case LyXTabular::M_VALIGN_CENTER:
1431         flag = false;
1432     case LyXTabular::VALIGN_TOP:
1433     case LyXTabular::VALIGN_BOTTOM:
1434     case LyXTabular::VALIGN_CENTER:
1435         for(i = sel_row_start; i <= sel_row_end; ++i)
1436             for(j = sel_col_start; j <= sel_col_end; ++j)
1437                 tabular->SetVAlignment(tabular->GetCellNumber(i, j),
1438                                        setVAlign, flag);
1439         if (hasSelection())
1440             UpdateLocal(bv, INIT, true);
1441         else
1442             UpdateLocal(bv, CELL, true);
1443         break;
1444     case LyXTabular::MULTICOLUMN:
1445     {
1446         if (sel_row_start != sel_row_end) {
1447             WriteAlert(_("Impossible Operation!"), 
1448                        _("Multicolumns can only be horizontally."), 
1449                        _("Sorry."));
1450             return;
1451         }
1452         // just multicol for one Single Cell
1453         if (!hasSelection()) {
1454             // check wether we are completly in a multicol
1455             if (tabular->IsMultiColumn(actcell)) {
1456                 tabular->UnsetMultiColumn(actcell);
1457                 UpdateLocal(bv, INIT, true);
1458             } else {
1459                 tabular->SetMultiColumn(actcell, 1);
1460                 UpdateLocal(bv, CELL, true);
1461             }
1462             return;
1463         }
1464         // we have a selection so this means we just add all this
1465         // cells to form a multicolumn cell
1466         int s_start;
1467         int s_end;
1468
1469         if (sel_cell_start > sel_cell_end) {
1470             s_start = sel_cell_end;
1471             s_end = sel_cell_start;
1472         } else {
1473             s_start = sel_cell_start;
1474             s_end = sel_cell_end;
1475         }
1476         tabular->SetMultiColumn(s_start, s_end - s_start + 1);
1477         actcell = s_start;
1478         cursor.pos(0);
1479         sel_cell_end = sel_cell_start;
1480         sel_pos_end = sel_pos_start;
1481         UpdateLocal(bv, INIT, true);
1482         break;
1483     }
1484     case LyXTabular::SET_ALL_LINES:
1485         setLines = 1;
1486     case LyXTabular::UNSET_ALL_LINES:
1487         for(i=sel_row_start; i<=sel_row_end; ++i)
1488             for(j=sel_col_start; j<=sel_col_end; ++j)
1489                 tabular->SetAllLines(tabular->GetCellNumber(i,j), setLines);
1490         UpdateLocal(bv, INIT, true);
1491         break;
1492     case LyXTabular::SET_LONGTABULAR:
1493         tabular->SetLongTabular(true);
1494         UpdateLocal(bv, INIT, true); // because this toggles displayed
1495         break;
1496     case LyXTabular::UNSET_LONGTABULAR:
1497         tabular->SetLongTabular(false);
1498         UpdateLocal(bv, INIT, true); // because this toggles displayed
1499         break;
1500     case LyXTabular::SET_ROTATE_TABULAR:
1501         tabular->SetRotateTabular(true);
1502         break;
1503     case LyXTabular::UNSET_ROTATE_TABULAR:
1504         tabular->SetRotateTabular(false);
1505         break;
1506     case LyXTabular::SET_ROTATE_CELL:
1507         for(i=sel_row_start; i<=sel_row_end; ++i)
1508             for(j=sel_col_start; j<=sel_col_end; ++j)
1509                 tabular->SetRotateCell(tabular->GetCellNumber(i,j),true);
1510         break;
1511     case LyXTabular::UNSET_ROTATE_CELL:
1512         for(i = sel_row_start; i <= sel_row_end; ++i)
1513             for(j = sel_col_start; j <= sel_col_end; ++j)
1514                 tabular->SetRotateCell(tabular->GetCellNumber(i, j), false);
1515         break;
1516     case LyXTabular::SET_USEBOX:
1517     {
1518         LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
1519         if (val == tabular->GetUsebox(actcell))
1520             val = LyXTabular::BOX_NONE;
1521         for(i = sel_row_start; i <= sel_row_end; ++i)
1522             for(j = sel_col_start; j <= sel_col_end; ++j)
1523                 tabular->SetUsebox(tabular->GetCellNumber(i, j), val);
1524         break;
1525     }
1526     case LyXTabular::SET_LTFIRSTHEAD:
1527         tabular->SetLTHead(actcell, true);
1528         break;
1529     case LyXTabular::SET_LTHEAD:
1530         tabular->SetLTHead(actcell, false);
1531         break;
1532     case LyXTabular::SET_LTFOOT:
1533         tabular->SetLTFoot(actcell, false);
1534         break;
1535     case LyXTabular::SET_LTLASTFOOT:
1536         tabular->SetLTFoot(actcell, true);
1537         break;
1538     case LyXTabular::SET_LTNEWPAGE:
1539         what = !tabular->GetLTNewPage(actcell);
1540         tabular->SetLTNewPage(actcell, what);
1541         break;
1542     // dummy stuff just to avoid warnings
1543     case LyXTabular::LAST_ACTION:
1544         break;
1545     }
1546 }
1547
1548
1549 bool InsetTabular::ActivateCellInset(BufferView * bv, int x, int y, int button,
1550                                      bool behind)
1551 {
1552     // the cursor.pos has to be before the inset so if it isn't now just
1553     // reset the curor pos first!
1554     if (!cellstart(cursor.pos())) {
1555         cursor.pos(0);
1556         resetPos(bv);
1557     }
1558     UpdatableInset * inset =
1559         static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
1560     LyXFont font(LyXFont::ALL_SANE);
1561     if (behind) {
1562         x = inset->x() + inset->width(bv, font);
1563         y = inset->descent(bv, font);
1564     }
1565     inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
1566     inset_y = cursor.y();
1567     inset->Edit(bv, x - inset_x, y - inset_y, button);
1568     if (!the_locking_inset)
1569         return false;
1570     UpdateLocal(bv, CELL, false);
1571     return (the_locking_inset != 0);
1572 }
1573
1574
1575 bool InsetTabular::InsetHit(BufferView * bv, int x, int ) const
1576 {
1577     InsetText * inset = tabular->GetCellInset(actcell);
1578     int x1 = x + top_x;
1579
1580     if (!cellstart(cursor.pos())) {
1581         return (((x + top_x) < cursor.x()) &&
1582                 ((x + top_x) > (cursor.x() - inset->width(bv,
1583                                                       LyXFont(LyXFont::ALL_SANE)))));
1584     } else {
1585         int x2 = cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
1586         return ((x1 > x2) &&
1587                 (x1 < (x2 + inset->width(bv, LyXFont(LyXFont::ALL_SANE)))));
1588     }
1589 }
1590
1591
1592 // This returns paperWidth() if the cell-width is unlimited or the width
1593 // in pixels if we have a pwidth for this cell.
1594 int InsetTabular::GetMaxWidthOfCell(Painter &, int cell) const
1595 {
1596     string const s = tabular->GetPWidth(cell);
1597
1598     if (s.empty())
1599         return -1;
1600     return VSpace(s).inPixels(0, 0);
1601 }
1602
1603
1604 int InsetTabular::getMaxWidth(Painter & pain,
1605                               UpdatableInset const * inset) const
1606 {
1607     int const n = tabular->GetNumberOfCells();
1608     int cell = 0;
1609     for(; cell < n; ++cell) {
1610         if (tabular->GetCellInset(cell) == inset)
1611             break;
1612     }
1613     if (cell >= n)
1614         return -1;
1615     int w = GetMaxWidthOfCell(pain, cell);
1616     if (w > 0)
1617         // because the inset then subtracts it's top_x and owner->x()
1618         w += (inset->x() - top_x);
1619     return w;
1620 }
1621
1622
1623 void InsetTabular::resizeLyXText(BufferView *) const
1624 {
1625     need_update = FULL;
1626 }
1627
1628
1629 LyXText * InsetTabular::getLyXText(BufferView * bv) const
1630 {
1631     if (the_locking_inset)
1632         return the_locking_inset->getLyXText(bv);
1633     return Inset::getLyXText(bv);
1634 }
1635
1636
1637 void InsetTabular::OpenLayoutDialog(BufferView * bv) const
1638 {
1639     if (the_locking_inset) {
1640         InsetTabular * i = static_cast<InsetTabular *>
1641             (the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE));
1642         if (i) {
1643             i->OpenLayoutDialog(bv);
1644             return;
1645         }
1646     }
1647     dialogs_ = bv->owner()->getDialogs();
1648     dialogs_->showTabular(const_cast<InsetTabular *>(this));
1649 }
1650
1651 //
1652 // functions returns:
1653 // 0 ... disabled
1654 // 1 ... enabled
1655 // 2 ... toggled on
1656 // 3 ... toggled off
1657 //
1658 LyXFunc::func_status InsetTabular::getStatus(string const & what) const
1659 {
1660     int action = LyXTabular::LAST_ACTION;
1661     LyXFunc::func_status status = LyXFunc::OK;
1662     
1663     int i = 0;
1664     for(; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
1665         string const tmp = tabularFeatures[i].feature;
1666         if (tmp == what.substr(0, tmp.length())) {                  
1667         //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
1668         //   tabularFeatures[i].feature.length())) {
1669             action = tabularFeatures[i].action;
1670             break;
1671         }
1672     }
1673     if (action == LyXTabular::LAST_ACTION)
1674         return LyXFunc::Unknown;
1675
1676     string const argument = frontStrip(what.substr(tabularFeatures[i].feature.length()));
1677
1678     int sel_row_start, sel_row_end;
1679     int dummy;
1680     bool flag = true;
1681
1682     if (hasSelection()) {
1683         sel_row_start = tabular->row_of_cell(sel_cell_start);
1684         sel_row_end = tabular->row_of_cell(sel_cell_end);
1685         if (sel_row_start > sel_row_end) {
1686                 //int tmp = sel_row_start;
1687                 //sel_row_start = sel_row_end;
1688                 //sel_row_end = tmp;
1689             swap(sel_row_start, sel_row_end);
1690         }
1691     } else {
1692         sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
1693     }
1694
1695     switch (action) {
1696     case LyXTabular::SET_PWIDTH:
1697     case LyXTabular::SET_MPWIDTH:
1698     case LyXTabular::SET_SPECIAL_COLUMN:
1699     case LyXTabular::SET_SPECIAL_MULTI:
1700         status |= LyXFunc::Disabled;
1701         return status;
1702
1703     case LyXTabular::APPEND_ROW:
1704     case LyXTabular::APPEND_COLUMN:
1705     case LyXTabular::DELETE_ROW:
1706     case LyXTabular::DELETE_COLUMN:
1707     case LyXTabular::SET_ALL_LINES:
1708     case LyXTabular::UNSET_ALL_LINES:
1709         status |= LyXFunc::OK;
1710         return status;
1711
1712     case LyXTabular::MULTICOLUMN:
1713         if (tabular->IsMultiColumn(actcell))
1714             status |= LyXFunc::ToggleOn;
1715         else
1716             status |= LyXFunc::ToggleOff;
1717         break;
1718     case LyXTabular::M_TOGGLE_LINE_TOP:
1719         flag = false;
1720     case LyXTabular::TOGGLE_LINE_TOP:
1721         if (tabular->TopLine(actcell, flag))
1722             status |= LyXFunc::ToggleOn;
1723         else
1724             status |= LyXFunc::ToggleOff;
1725         break;
1726     case LyXTabular::M_TOGGLE_LINE_BOTTOM:
1727         flag = false;
1728     case LyXTabular::TOGGLE_LINE_BOTTOM:
1729         if (tabular->BottomLine(actcell, flag))
1730             status |= LyXFunc::ToggleOn;
1731         else
1732             status |= LyXFunc::ToggleOff;
1733         break;
1734     case LyXTabular::M_TOGGLE_LINE_LEFT:
1735         flag = false;
1736     case LyXTabular::TOGGLE_LINE_LEFT:
1737         if (tabular->LeftLine(actcell, flag))
1738             status |= LyXFunc::ToggleOn;
1739         else
1740             status |= LyXFunc::ToggleOff;
1741         break;
1742     case LyXTabular::M_TOGGLE_LINE_RIGHT:
1743         flag = false;
1744     case LyXTabular::TOGGLE_LINE_RIGHT:
1745         if (tabular->RightLine(actcell, flag))
1746             status |= LyXFunc::ToggleOn;
1747         else
1748             status |= LyXFunc::ToggleOff;
1749         break;
1750     case LyXTabular::M_ALIGN_LEFT:
1751         flag = false;
1752     case LyXTabular::ALIGN_LEFT:
1753         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_LEFT)
1754             status |= LyXFunc::ToggleOn;
1755         else
1756             status |= LyXFunc::ToggleOff;
1757         break;
1758     case LyXTabular::M_ALIGN_RIGHT:
1759         flag = false;
1760     case LyXTabular::ALIGN_RIGHT:
1761         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_RIGHT)
1762             status |= LyXFunc::ToggleOn;
1763         else
1764             status |= LyXFunc::ToggleOff;
1765         break;
1766     case LyXTabular::M_ALIGN_CENTER:
1767         flag = false;
1768     case LyXTabular::ALIGN_CENTER:
1769         if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_CENTER)
1770             status |= LyXFunc::ToggleOn;
1771         else
1772             status |= LyXFunc::ToggleOff;
1773         break;
1774     case LyXTabular::M_VALIGN_TOP:
1775         flag = false;
1776     case LyXTabular::VALIGN_TOP:
1777         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP)
1778             status |= LyXFunc::ToggleOn;
1779         else
1780             status |= LyXFunc::ToggleOff;
1781         break;
1782     case LyXTabular::M_VALIGN_BOTTOM:
1783         flag = false;
1784     case LyXTabular::VALIGN_BOTTOM:
1785         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM)
1786             status |= LyXFunc::ToggleOn;
1787         else
1788             status |= LyXFunc::ToggleOff;
1789         break;
1790     case LyXTabular::M_VALIGN_CENTER:
1791         flag = false;
1792     case LyXTabular::VALIGN_CENTER:
1793         if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER)
1794             status |= LyXFunc::ToggleOn;
1795         else
1796             status |= LyXFunc::ToggleOff;
1797         break;
1798     case LyXTabular::SET_LONGTABULAR:
1799         if (tabular->IsLongTabular())
1800             status |= LyXFunc::ToggleOn;
1801         else
1802             status |= LyXFunc::ToggleOff;
1803         break;
1804     case LyXTabular::UNSET_LONGTABULAR:
1805         if (!tabular->IsLongTabular())
1806             status |= LyXFunc::ToggleOn;
1807         else
1808             status |= LyXFunc::ToggleOff;
1809         break;
1810     case LyXTabular::SET_ROTATE_TABULAR:
1811         if (tabular->GetRotateTabular())
1812             status |= LyXFunc::ToggleOn;
1813         else
1814             status |= LyXFunc::ToggleOff;
1815         break;
1816     case LyXTabular::UNSET_ROTATE_TABULAR:
1817         if (!tabular->GetRotateTabular())
1818             status |= LyXFunc::ToggleOn;
1819         else
1820             status |= LyXFunc::ToggleOff;
1821         break;
1822     case LyXTabular::SET_ROTATE_CELL:
1823         if (tabular->GetRotateCell(actcell))
1824             status |= LyXFunc::ToggleOn;
1825         else
1826             status |= LyXFunc::ToggleOff;
1827         break;
1828     case LyXTabular::UNSET_ROTATE_CELL:
1829         if (!tabular->GetRotateCell(actcell))
1830             status |= LyXFunc::ToggleOn;
1831         else
1832             status |= LyXFunc::ToggleOff;
1833         break;
1834     case LyXTabular::SET_USEBOX:
1835         if (strToInt(argument) == tabular->GetUsebox(actcell))
1836             status |= LyXFunc::ToggleOn;
1837         else
1838             status |= LyXFunc::ToggleOff;
1839         break;
1840     case LyXTabular::SET_LTFIRSTHEAD:
1841         if (tabular->GetRowOfLTHead(actcell, dummy))
1842             status |= LyXFunc::ToggleOn;
1843         else
1844             status |= LyXFunc::ToggleOff;
1845         break;
1846     case LyXTabular::SET_LTHEAD:
1847         if (tabular->GetRowOfLTHead(actcell, dummy))
1848             status |= LyXFunc::ToggleOn;
1849         else
1850             status |= LyXFunc::ToggleOff;
1851         break;
1852     case LyXTabular::SET_LTFOOT:
1853         if (tabular->GetRowOfLTFoot(actcell, dummy))
1854             status |= LyXFunc::ToggleOn;
1855         else
1856             status |= LyXFunc::ToggleOff;
1857         break;
1858     case LyXTabular::SET_LTLASTFOOT:
1859         if (tabular->GetRowOfLTFoot(actcell, dummy))
1860             status |= LyXFunc::ToggleOn;
1861         else
1862             status |= LyXFunc::ToggleOff;
1863         break;
1864     case LyXTabular::SET_LTNEWPAGE:
1865         if (tabular->GetLTNewPage(actcell))
1866             status |= LyXFunc::ToggleOn;
1867         else
1868             status |= LyXFunc::ToggleOff;
1869         break;
1870     default:
1871         status = LyXFunc::Disabled;
1872         break;
1873     }
1874     return status;
1875 }
1876
1877
1878 bool InsetTabular::copySelection()
1879 {
1880     if (!hasSelection())
1881         return false;
1882     delete paste_tabular;
1883
1884     int sel_col_start, sel_col_end;
1885     int sel_row_start, sel_row_end;
1886
1887     sel_col_start = tabular->column_of_cell(sel_cell_start);
1888     sel_col_end = tabular->column_of_cell(sel_cell_end);
1889     if (sel_col_start > sel_col_end) {
1890         sel_col_start = sel_col_end;
1891         sel_col_end = tabular->right_column_of_cell(sel_cell_start);
1892     } else {
1893         sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1894     }
1895     int columns = sel_col_end - sel_col_start + 1;
1896
1897     sel_row_start = tabular->row_of_cell(sel_cell_start);
1898     sel_row_end = tabular->row_of_cell(sel_cell_end);
1899     if (sel_row_start > sel_row_end) {
1900             //int tmp tmp = sel_row_start;
1901             //sel_row_start = sel_row_end;
1902             //sel_row_end = tmp;
1903         swap(sel_row_start, sel_row_end);
1904     }
1905     int rows = sel_row_end - sel_row_start + 1;
1906
1907     paste_tabular = new LyXTabular(this, rows, columns);
1908     
1909     if (sel_cell_start > sel_cell_end) {
1910             //int tmp = sel_cell_start;
1911             //sel_cell_start = sel_cell_end;
1912             //sel_cell_end = tmp;
1913         swap(sel_cell_start, sel_cell_end);
1914     }
1915     for(int i = sel_cell_start, j = 0; i <= sel_cell_end; ++i, ++j) {
1916         while(paste_tabular->row_of_cell(j) <
1917               (tabular->row_of_cell(i)-sel_row_start)) {
1918             ++j;
1919         }
1920         while(paste_tabular->row_of_cell(j) >
1921               (tabular->row_of_cell(i)-sel_row_start)) {
1922             ++i;
1923         }
1924         *(paste_tabular->GetCellInset(j)) = *(tabular->GetCellInset(i));
1925     }
1926     return true;
1927 }
1928
1929
1930 bool InsetTabular::pasteSelection(BufferView * bv)
1931 {
1932     if (!paste_tabular)
1933         return false;
1934     for(int j=0, i=actcell; j<paste_tabular->GetNumberOfCells(); ++j,++i) {
1935         while (paste_tabular->row_of_cell(j) > tabular->row_of_cell(i)-actrow)
1936             ++i;
1937         if (tabular->GetNumberOfCells() <= i)
1938             break;
1939         while (paste_tabular->row_of_cell(j) < tabular->row_of_cell(i)-actrow)
1940             ++j;
1941         if (paste_tabular->GetNumberOfCells() <= j)
1942             break;
1943         *(tabular->GetCellInset(i)) = *(paste_tabular->GetCellInset(j));
1944         tabular->GetCellInset(i)->setOwner(this);
1945         tabular->GetCellInset(i)->deleteLyXText(bv);
1946     }
1947     return true;
1948 }
1949
1950
1951 bool InsetTabular::cutSelection()
1952 {
1953     if (!hasSelection())
1954         return false;
1955
1956     int sel_col_start, sel_col_end;
1957     int sel_row_start, sel_row_end;
1958
1959     sel_col_start = tabular->column_of_cell(sel_cell_start);
1960     sel_col_end = tabular->column_of_cell(sel_cell_end);
1961     if (sel_col_start > sel_col_end) {
1962         sel_col_start = sel_col_end;
1963         sel_col_end = tabular->right_column_of_cell(sel_cell_start);
1964     } else {
1965         sel_col_end = tabular->right_column_of_cell(sel_cell_end);
1966     }
1967     sel_row_start = tabular->row_of_cell(sel_cell_start);
1968     sel_row_end = tabular->row_of_cell(sel_cell_end);
1969     if (sel_row_start > sel_row_end) {
1970             //int tmp = sel_row_start;
1971             //sel_row_start = sel_row_end;
1972             //sel_row_end = tmp;
1973         swap(sel_row_start, sel_row_end);
1974     }
1975     if (sel_cell_start > sel_cell_end) {
1976             //int tmp = sel_cell_start;
1977             //sel_cell_start = sel_cell_end;
1978             //sel_cell_end = tmp;
1979         swap(sel_cell_start, sel_cell_end);
1980     }
1981     for(int i = sel_row_start; i <= sel_row_end; ++i) {
1982         for(int j = sel_col_start; j <= sel_col_end; ++j) {
1983             tabular->GetCellInset(tabular->GetCellNumber(i, j))->clear();
1984         }
1985     }
1986     return true;
1987 }
1988