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