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