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