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