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