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