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