]> git.lyx.org Git - lyx.git/blob - src/insets/insettabular.C
f14093d0706dfc795858e9f125be5ed9c59d9443
[lyx.git] / src / insets / insettabular.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright (C) 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 "LaTeXFeatures.h"
27 #include "Painter.h"
28 #include "font.h"
29 #include "insets/insettext.h"
30
31 const int ADD_TO_HEIGHT = 2;
32 const int ADD_TO_TABLE_WIDTH = 2;
33
34 using std::ostream;
35 using std::ifstream;
36
37 InsetTabular::InsetTabular(Buffer * buf, int rows=1, int columns=1)
38 {
39     if (rows <= 0)
40         rows = 1;
41     if (columns <= 0)
42         columns = 1;
43     tabular = new LyXTable(rows,columns,buf);
44     the_locking_inset = 0;
45     buffer = buf;
46     cursor_visible = false;
47     old_x = -1;
48     sel_pos_start = sel_pos_end = 0;
49     no_selection = false;
50     init = true;
51 }
52
53 InsetTabular::InsetTabular(InsetTabular const & tab, Buffer * buf)
54 {
55     tabular = new LyXTable(*(tab.tabular), buf);
56     the_locking_inset = 0;
57     buffer = buf;
58     cursor_visible = false;
59     old_x = -1;
60     sel_pos_start = sel_pos_end = 0;
61     no_selection = false;
62     init = true;
63 }
64
65 InsetTabular::~InsetTabular()
66 {
67     if (tabular)
68         delete tabular;
69 }
70
71
72 InsetTabular * InsetTabular::Clone() const
73 {
74     InsetTabular * t = new InsetTabular(*this, buffer);
75     return t;
76 }
77
78
79 void InsetTabular::Write(ostream & os) const
80 {
81     os << "\\begin_inset Tabular\n";
82     tabular->Write(os,false);
83     os << "\\end_inset\n";
84 }
85
86
87 void InsetTabular::Read(LyXLex & lex)
88 {
89     if (tabular)
90         delete tabular;
91
92 //    bool old_format = (lex.GetString() == "\\LyXTable");
93     tabular = new LyXTable(lex, buffer);
94     init = true;
95 }
96
97
98 int InsetTabular::ascent(Painter & pain, LyXFont const & font) const
99 {
100     if (init) {
101         calculate_width_of_cells(pain, font);
102         init = false;
103     }
104     return tabular->AscentOfRow(0);
105 }
106
107
108 int InsetTabular::descent(Painter & pain, LyXFont const & font) const
109 {
110     if (init) {
111         calculate_width_of_cells(pain, font);
112         init = false;
113     }
114     return tabular->HeightOfTable() - tabular->AscentOfRow(0);
115 }
116
117
118 int InsetTabular::width(Painter & pain, LyXFont const & font) const
119 {
120     if (init) {
121         calculate_width_of_cells(pain, font);
122         init = false;
123     }
124     return tabular->WidthOfTable() + (2 * ADD_TO_TABLE_WIDTH);
125 }
126
127
128 void InsetTabular::draw(Painter & pain, const LyXFont & font, int,
129                         float &) const
130 {
131     calculate_width_of_cells(pain, font);
132 }
133
134
135 const char * InsetTabular::EditMessage() const
136 {
137     return _("Opened Tabular Inset");
138 }
139
140
141 void InsetTabular::Edit(BufferView * bv, int x, int y, unsigned int button)
142 {
143     UpdatableInset::Edit(bv, x, y, button);
144
145     bv->lockInset(this);
146     the_locking_inset = 0;
147     inset_pos = inset_x = inset_y = 0;
148     no_selection = true;
149     setPos(x,y);
150     sel_pos_start = sel_pos_end = actpos;
151     sel_cell_start = sel_cell_end = actcell;
152 //    bv->getOwner()->getPopups().updateFormTable();
153 }
154
155
156 void InsetTabular::InsetUnlock(BufferView * bv)
157 {
158     if (the_locking_inset)
159         the_locking_inset->InsetUnlock(bv);
160     HideInsetCursor(bv);
161     the_locking_inset = 0;
162     if (hasCharSelection()) {
163         sel_pos_start = sel_pos_end = actpos;
164         UpdateLocal(bv, false);
165     } else
166         sel_pos_start = sel_pos_end = actpos;
167     no_selection = false;
168 }
169
170 bool InsetTabular::LockInsetInInset(UpdatableInset *)
171 {
172     return true;
173 }
174
175
176 bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
177                                       bool lr)
178 {
179     if (!the_locking_inset)
180         return false;
181     if (the_locking_inset == inset) {
182         the_locking_inset->InsetUnlock(bv);
183         the_locking_inset = 0;
184         if (lr)
185             moveRight(false);
186         return true;
187     }
188     return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
189 }
190
191
192 void InsetTabular::UpdateLocal(BufferView * bv, bool flag)
193 {
194     resetPos();
195     bv->updateInset(this, flag);
196 }
197
198 bool InsetTabular::UpdateInsetInInset(BufferView * bv, Inset * inset)
199 {
200     if (!the_locking_inset)
201         return false;
202     if (the_locking_inset != inset)
203         return the_locking_inset->UpdateInsetInInset(bv, inset);
204     UpdateLocal(bv);
205     return true;
206 }
207
208 void InsetTabular::InsetButtonRelease(BufferView *bv, int x, int y, int button)
209 {
210     if (the_locking_inset) {
211         the_locking_inset->InsetButtonRelease(bv, x-inset_x,y-inset_y,button);
212         return;
213     }
214     no_selection = false;
215 }
216
217 void InsetTabular::InsetButtonPress(BufferView *bv, int x, int y, int)
218 {
219     if (hasCharSelection()) {
220         sel_pos_start = sel_pos_end = 0;
221         UpdateLocal(bv, false);
222     }
223     no_selection = false;
224     setPos(x,y,false);
225     if (the_locking_inset) {
226 #if 0
227         UpdatableInset
228             * inset=0;
229         if (par->GetChar(actpos)==LYX_META_INSET)
230             inset=(UpdatableInset*)par->GetInset(actpos);
231         if (the_locking_inset == inset) {
232             the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
233             return;
234         } else if (inset) {
235             // otherwise unlock the_locking_inset and lock the new inset
236             inset_x = cx-top_x;
237             inset_y = cy;
238             inset_pos = actpos;
239             the_locking_inset->InsetUnlock(bv);
240             the_locking_inset = inset;
241             the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button);
242             return;
243         }
244 #endif
245         // otherwise only unlock the_locking_inset
246         the_locking_inset->InsetUnlock(bv);
247     }
248 #if 0
249     int
250         oldcell = actcell;
251 #endif
252     setPos(x,y);
253     the_locking_inset = 0;
254     sel_pos_start = sel_pos_end = actpos;
255     sel_cell_start = sel_cell_end = actcell;
256 #if 0
257     if (button == 3)
258         bview->getOwner()->getPopups().showFormTable();
259     else if (oldcell != actcell)
260         bview->getOwner()->getPopups().updateFormTable();
261 #endif
262 }
263
264
265 void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button)
266 {
267     if (the_locking_inset) {
268         the_locking_inset->InsetMotionNotify(bv, x-inset_x,y-inset_y,button);
269         return;
270     }
271     if (!no_selection) {
272         int
273 //          oldcell = actcell,
274             old = sel_pos_end;
275
276         setPos(x,y);
277         sel_pos_end = actpos;
278         sel_cell_end = actcell;
279         if (old != sel_pos_end)
280             UpdateLocal(bv, false);
281 #if 0
282         if (oldcell != actcell)
283             bview->getOwner()->getPopups().updateFormTable();
284 #endif
285     }
286     no_selection = false;
287 }
288
289
290 void InsetTabular::InsetKeyPress(XKeyEvent * xke)
291 {
292     if (the_locking_inset) {
293         the_locking_inset->InsetKeyPress(xke);
294         return;
295     }
296 }
297
298
299 UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView *bv, int action,
300                                                    string const & arg)
301 {
302     no_selection = false;
303     if (UpdatableInset::LocalDispatch(bv, action, arg)) {
304         resetPos();
305         return DISPATCHED;
306     }
307
308     UpdatableInset::RESULT 
309         result=DISPATCHED;
310     if ((action < 0) && arg.empty())
311         return FINISHED;
312
313     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
314         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
315         old_x = -1;
316     if (the_locking_inset) {
317         result=the_locking_inset->LocalDispatch(bv, action, arg);
318         if (result == DISPATCHED) {
319             setWidthOfCell(actpos,actcell,actrow);
320             the_locking_inset->ToggleInsetCursor(bv);
321             UpdateLocal(bv, false);
322             the_locking_inset->ToggleInsetCursor(bv);
323             return result;
324         } else if (result == FINISHED) {
325             if ((action == LFUN_RIGHT) || (action == -1)) {
326                 actpos = inset_pos + 1;
327                 resetPos();
328             }
329             the_locking_inset=0;
330             result = DISPATCHED;
331             return result;
332         }
333     }
334
335     HideInsetCursor(bv);
336     switch (action) {
337       // Normal chars not handled here
338       case -1:
339           break;
340       // --- Cursor Movements ---------------------------------------------
341       case LFUN_RIGHTSEL:
342           moveRight(false);
343           sel_pos_end = actpos;
344           UpdateLocal(bv, false);
345           break;
346       case LFUN_RIGHT:
347           result= DISPATCH_RESULT(moveRight());
348           if (hasCharSelection()) {
349               sel_pos_start = sel_pos_end = actpos;
350               UpdateLocal(bv, false);
351           } else
352               sel_pos_start = sel_pos_end = actpos;
353           break;
354       case LFUN_LEFTSEL:
355           moveLeft(false);
356           sel_pos_end = actpos;
357           UpdateLocal(bv, false);
358           break;
359       case LFUN_LEFT:
360           result= DISPATCH_RESULT(moveLeft());
361           if (hasCharSelection()) {
362               sel_pos_start = sel_pos_end = actpos;
363               UpdateLocal(bv, false);
364           } else
365               sel_pos_start = sel_pos_end = actpos;
366           break;
367       case LFUN_DOWNSEL:
368           moveDown(false);
369           sel_pos_end = actpos;
370           UpdateLocal(bv, false);
371           break;
372       case LFUN_DOWN:
373           result= DISPATCH_RESULT(moveDown());
374           if (hasCharSelection()) {
375               sel_pos_start = sel_pos_end = actpos;
376               UpdateLocal(bv, false);
377           } else
378               sel_pos_start = sel_pos_end = actpos;
379           break;
380       case LFUN_UPSEL:
381           moveUp(false);
382           sel_pos_end = actpos;
383           UpdateLocal(bv, false);
384           break;
385       case LFUN_UP:
386           result= DISPATCH_RESULT(moveUp());
387           if (hasCharSelection()) {
388               sel_pos_start = sel_pos_end = actpos;
389               UpdateLocal(bv, false);
390           } else
391               sel_pos_start = sel_pos_end = actpos;
392           break;
393       case LFUN_BACKSPACE:
394           break;
395       case LFUN_DELETE:
396           break;
397       case LFUN_HOME:
398           break;
399       case LFUN_END:
400           break;
401       case LFUN_TAB:
402           if (hasCharSelection()) {
403               sel_pos_start = sel_pos_end = actpos;
404               UpdateLocal(bv, false);
405           }
406           sel_pos_start = sel_pos_end = actpos;
407           moveNextCell();
408           break;
409       default:
410           result = UNDISPATCHED;
411           break;
412     }
413     if (result!=FINISHED) {
414         if (!the_locking_inset) {
415 #if 0       
416             if (oldcell != actcell)
417                 bview->getOwner()->getPopups().updateFormTable();
418 #endif
419             ShowInsetCursor(bv);
420         }
421     } else
422         bv->unlockInset(this);
423     return result;
424 }
425
426
427 int InsetTabular::Latex(ostream & os, bool, bool) const
428 {
429     return tabular->Latex(os);
430 }
431
432 int InsetTabular::Linuxdoc(ostream &) const
433 {
434     return 0;
435 }
436
437 int InsetTabular::DocBook(ostream &) const
438 {
439     return 0;
440 }
441
442 void InsetTabular::Validate(LaTeXFeatures & features) const
443 {
444     if (tabular->IsLongTable())
445         features.longtable = true;
446 }
447
448
449 void InsetTabular::calculate_width_of_cells(Painter & pain, LyXFont const & font) const
450 {
451     int
452         cell=-1,
453         i,j,
454         maxAsc, maxDesc;
455     InsetText
456         *inset;
457     
458     for(i=0; i < tabular->rows; ++i) {
459         maxAsc = maxDesc = 0;
460         for(j=0; j < tabular->columns; ++j) {
461             if (tabular->IsPartOfMultiColumn(i,j))
462                 continue;
463             ++cell;
464             inset = tabular->GetCellInset(cell);
465             maxAsc = max(maxAsc, inset->ascent(pain, font));
466             maxDesc = max(maxDesc, inset->descent(pain, font));
467             tabular->SetWidthOfCell(cell, inset->width(pain, font));
468         }
469         tabular->SetAscentOfRow(i,maxAsc+ADD_TO_HEIGHT);
470         tabular->SetDescentOfRow(i,maxDesc+ADD_TO_HEIGHT);
471     }
472 }
473
474
475 void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline,
476                                  int row, int cell)
477 {
478     // Juergen, have you thought about drawing the on-off lines in a
479     // different color (gray of some kind), especially since those
480     // lines will not be there on the hardcopy anyway. (Lgb)
481     int
482         x_old = x;
483     bool
484         on_off;
485
486     x_old -= tabular->WidthOfColumn(cell);
487     on_off = !tabular->TopLine(cell);
488     if ((!on_off || !tabular->TopAlreadyDrawed(cell)) &&
489         !tabular->IsContRow(cell))
490         pain.line(x_old, baseline - tabular->AscentOfRow(row),
491                   x, baseline -  tabular->AscentOfRow(row),
492                   LColor::tableline,
493                   on_off ? Painter::line_onoffdash:Painter::line_solid);
494     on_off = !tabular->BottomLine(cell);
495     if ((!on_off && !tabular->RowHasContRow(cell)) || 
496         tabular->VeryLastRow(cell))
497         pain.line(x_old ,baseline +  tabular->DescentOfRow(row),
498                   x, baseline +  tabular->DescentOfRow(row),
499                   LColor::tableline,
500                   on_off ? Painter::line_onoffdash:Painter::line_solid);
501     on_off = !tabular->LeftLine(cell);
502     pain.line(x_old, baseline -  tabular->AscentOfRow(row),
503               x_old, baseline +  tabular->DescentOfRow(row),
504               LColor::tableline,
505               on_off ? Painter::line_onoffdash:Painter::line_solid);
506     on_off = !tabular->RightLine(cell);
507     pain.line(x - tabular->AdditionalWidth(cell),
508               baseline -  tabular->AscentOfRow(row),
509               x - tabular->AdditionalWidth(cell),
510               baseline +  tabular->DescentOfRow(row),
511               LColor::tableline,
512               on_off ? Painter::line_onoffdash:Painter::line_solid);
513 }
514
515
516 void InsetTabular::GetCursorPos(int & x, int & y)
517 {
518     x = cx-top_x;
519     y = cy;
520 }
521
522
523 void InsetTabular::ToggleInsetCursor(BufferView * bv)
524 {
525     if (the_locking_inset) {
526         the_locking_inset->ToggleInsetCursor(bv);
527         return;
528     }
529     int
530         x=0,y=0,
531         asc,desc;
532
533     LyXFont
534         font; // = the_locking_inset->GetFont(par, actpos);
535
536     asc = lyxfont::maxAscent(font);
537     desc = lyxfont::maxDescent(font);
538   
539     if (cursor_visible)
540         bv->hideLockedInsetCursor();
541     else
542         bv->showLockedInsetCursor(cx+x, cy+y, asc, desc);
543     cursor_visible = !cursor_visible;
544 }
545
546
547 void InsetTabular::ShowInsetCursor(BufferView * bv)
548 {
549     if (!cursor_visible) {
550         int
551             asc,desc;
552         LyXFont
553             font; // = GetFont(par, actpos);
554     
555         asc = lyxfont::maxAscent(font);
556         desc = lyxfont::maxDescent(font);
557         bv->fitLockedInsetCursor(cx, cy, asc, desc);
558         bv->showLockedInsetCursor(cx, cy, asc, desc);
559         cursor_visible = true;
560     }
561 }
562
563
564 void InsetTabular::HideInsetCursor(BufferView * bv)
565 {
566     if (cursor_visible)
567         ToggleInsetCursor(bv);
568 }
569
570
571 void InsetTabular::setPos(int, int, bool)
572 {
573 }
574
575 void InsetTabular::setWidthOfCell(int, int, int)
576 {
577 }
578
579 bool InsetTabular::moveRight(bool)
580 {
581     return false;
582 }
583
584 bool InsetTabular::moveLeft(bool)
585 {
586     return false;
587 }
588
589 bool InsetTabular::moveUp(bool)
590 {
591     return false;
592 }
593
594 bool InsetTabular::moveDown(bool)
595 {
596     return false;
597 }
598
599 bool InsetTabular::moveNextCell()
600 {
601     return false;
602 }
603
604 bool InsetTabular::movePrevCell()
605 {
606     return false;
607 }
608
609 void InsetTabular::resetPos()
610 {
611 }
612
613 bool InsetTabular::Delete()
614 {
615     return true;
616 }
617
618 void  InsetTabular::SetFont(LyXFont const &)
619 {
620 }
621
622 void InsetTabular::TableFeatures(int, string)
623 {
624 #if 0
625     int
626         i,
627         selection_start,
628         selection_end,
629         setLines = 0,
630         setAlign = LYX_ALIGN_LEFT,
631         lineSet;
632     bool
633         what;
634
635     switch (feature) {
636       case LyXTable::ALIGN_LEFT:
637           setAlign=LYX_ALIGN_LEFT;
638           break;
639       case LyXTable::ALIGN_RIGHT:
640           setAlign=LYX_ALIGN_RIGHT;
641           break;
642       case LyXTable::ALIGN_CENTER:
643           setAlign=LYX_ALIGN_CENTER;
644           break;
645       default:
646           break;
647     }
648     if (hasCellSelection()) {
649         if (sel_cell_start > sel_cell_end) {
650             selection_start = sel_cell_end;
651             selection_end = sel_cell_start;
652         } else {
653             selection_start = sel_cell_start;
654             selection_end = sel_cell_end;
655         }
656     } else
657         selection_start = selection_end = actcell;
658     switch (feature) {
659       case LyXTable::SET_PWIDTH:
660           tabular->SetPWidth(actcell,val);
661           break;
662       case LyXTable::SET_SPECIAL_COLUMN:
663       case LyXTable::SET_SPECIAL_MULTI:
664           tabular->SetAlignSpecial(actcell,val,feature);
665           break;
666       case LyXTable::APPEND_ROW:
667       {
668           int
669               pos = actpos,
670               cell_org = actcell,
671               cell = actcell;
672
673           // if there is a ContRow following this row I have to add
674           // the row after the ContRow's
675           if ((pos < par->last()) && tabular->RowHasContRow(cell_org)) {
676               while((pos < par->last()) && !tabular->IsContRow(cell)) {
677                   while (pos < par->last() && !par->IsNewline(pos))
678                       ++pos;
679                   if (pos < par->last())
680                       ++pos;
681                   ++cell;
682               }
683               while((pos < par->last()) && tabular->IsContRow(cell)) {
684                   while (pos < par->last() && !par->IsNewline(pos))
685                       ++pos;
686                   if (pos < par->last())
687                       ++pos;
688                   ++cell;
689               }
690               cell_org = --cell;
691               if (pos < par->last())
692                   --pos;
693           }
694           while ((pos < par->last()) && 
695                  ((cell == cell_org) || !tabular->IsFirstCell(cell))) {
696               while ((pos < par->last()) && !par->IsNewline(pos))
697                   ++pos;
698               if (pos < par->last())
699                   ++pos;
700               ++cell;
701           }
702           // insert the new cells
703           int number = tabular->NumberOfCellsInRow(cell_org);
704           for (i=0; i<number; ++i)
705               par->InsertChar(pos, LYX_META_NEWLINE);
706                 
707           // append the row into the table
708           tabular->AppendRow(cell_org);
709           calculate_width_of_cells();
710           UpdateLocal();
711           return;
712       }
713       case LyXTable::APPEND_CONT_ROW:
714       {
715           int
716               pos = actpos,
717               cell_org = actcell,
718               cell = actcell;
719
720           // if there is already a controw but not for this cell
721           // the AppendContRow sets only the right values but does
722           // not actually add a row
723           if (tabular->RowHasContRow(cell_org) &&
724               (tabular->CellHasContRow(cell_org) < 0)) {
725               tabular->AppendContRow(cell_org);
726               calculate_width_of_cells();
727               UpdateLocal();
728               return;
729           }
730           while ((pos < par->last()) &&
731                  ((cell == cell_org) || !tabular->IsFirstCell(cell))) {
732               while (pos < par->last() && !par->IsNewline(pos))
733                   ++pos;
734               if (pos < par->last())
735                   ++pos;
736               ++cell;
737           }
738           // insert the new cells
739           int number = tabular->NumberOfCellsInRow(cell_org);
740           for (i=0; i<number; ++i)
741               par->InsertChar(pos, LYX_META_NEWLINE);
742           // append the row into the table
743           tabular->AppendContRow(cell_org);
744           calculate_width_of_cells();
745           UpdateLocal();
746           return;
747       }
748       case LyXTable::APPEND_COLUMN:
749       { 
750           int
751               pos = 0,
752               cell_org = actcell,
753               cell = 0;
754           do {
755               if (pos && (par->IsNewline(pos-1))) {
756                   if (tabular->AppendCellAfterCell(cell_org, cell)) {
757                       par->InsertChar(pos, LYX_META_NEWLINE);
758                       if (pos <= actpos)
759                           ++actpos;
760                       ++pos;
761                   }
762                   ++cell;
763               }
764               ++pos;
765           } while (pos <= par->last());
766           // remember that the very last cell doesn't end with a newline.
767           // This saves one byte memory per table ;-)
768           if (tabular->AppendCellAfterCell(cell_org, cell))
769               par->InsertChar(par->last(), LYX_META_NEWLINE);
770           // append the column into the table
771           tabular->AppendColumn(cell_org);
772           calculate_width_of_cells();
773           UpdateLocal();
774           return;
775       }
776       case LyXTable::DELETE_ROW:
777           RemoveTableRow();
778           calculate_width_of_cells();
779           UpdateLocal();
780           return;
781       case LyXTable::DELETE_COLUMN:
782       {
783           int pos = 0;
784           int cell = 0;
785           do {
786               if (!pos || (par->IsNewline(pos-1))){
787                   if (tabular->DeleteCellIfColumnIsDeleted(cell, actcell)) {
788                       // delete one cell
789                       while (pos < par->last() && !par->IsNewline(pos))
790                           par->Erase(pos);
791                       if (pos < par->last())
792                           par->Erase(pos);
793                       else 
794                           par->Erase(pos - 1); // the missing newline
795                                                // at the end of a table
796                       --pos; // because of ++pos below
797                   }
798                   ++cell;
799               }
800               ++pos;
801           } while (pos <= par->last());
802           /* delete the column from the table */ 
803           tabular->DeleteColumn(actcell);
804           calculate_width_of_cells();
805           UpdateLocal();
806           return;
807       }
808       case LyXTable::TOGGLE_LINE_TOP:
809           lineSet = !tabular->TopLine(actcell);
810           for(i=selection_start; i<=selection_end; ++i)
811               tabular->SetTopLine(i,lineSet);
812           calculate_width_of_cells();
813           UpdateLocal();
814           return;
815     
816       case LyXTable::TOGGLE_LINE_BOTTOM:
817           lineSet = !tabular->BottomLine(actcell); 
818           for(i=selection_start; i<=selection_end; ++i)
819               tabular->SetBottomLine(i,lineSet);
820           calculate_width_of_cells();
821           UpdateLocal();
822           return;
823                 
824       case LyXTable::TOGGLE_LINE_LEFT:
825           lineSet = !tabular->LeftLine(actcell);
826           for(i=selection_start; i<=selection_end; ++i)
827               tabular->SetLeftLine(i,lineSet);
828           calculate_width_of_cells();
829           UpdateLocal();
830           return;
831
832       case LyXTable::TOGGLE_LINE_RIGHT:
833           lineSet = !tabular->RightLine(actcell);
834           for(i=selection_start; i<=selection_end; ++i)
835               tabular->SetRightLine(i,lineSet);
836           calculate_width_of_cells();
837           UpdateLocal();
838           return;
839       case LyXTable::ALIGN_LEFT:
840       case LyXTable::ALIGN_RIGHT:
841       case LyXTable::ALIGN_CENTER:
842           for(i=selection_start; i<=selection_end; ++i)
843               tabular->SetAlignment(i,setAlign);
844           UpdateLocal();
845           return;
846       case LyXTable::MULTICOLUMN:
847       {
848           if (tabular->row_of_cell(selection_start) !=
849               tabular->row_of_cell(selection_end)) {
850               WriteAlert(_("Impossible Operation!"), 
851                          _("Multicolumns can only be horizontally."), 
852                          _("Sorry."));
853               return;
854           }
855           // just multicol for one Single Cell
856           if (!hasCellSelection()) {
857               // check wether we are completly in a multicol
858               if (tabular->IsMultiColumn(actcell)) {
859                   int
860                       newlines,
861                       pos = actpos;
862                   if ((newlines=tabular->UnsetMultiColumn(actcell))) {
863                       while ((pos < par->last()) && !par->IsNewline(pos))
864                           ++pos;
865                       for (;newlines;--newlines)
866                           par->InsertChar(pos, LYX_META_NEWLINE);
867                   }
868                   calculate_width_of_cells();
869               } else {
870                   tabular->SetMultiColumn(actcell, 1);
871               }
872               UpdateLocal();
873               return;
874           }
875           // we have a selection so this means we just add all this
876           // cells to form a multicolumn cell
877           int
878               number = 1,
879               s_start, s_end;
880
881           if (sel_pos_start > sel_pos_end) {
882               s_start = sel_pos_end;
883               s_end = sel_pos_start;
884           } else {
885               s_start = sel_pos_start;
886               s_end = sel_pos_end;
887           }
888           for(i=s_start; i < s_end; ++i) {
889               if (par->IsNewline(i)) {
890                   par->Erase(i);
891                   // check for double-blanks
892                   if ((i && !par->IsLineSeparator(i-1)) &&
893                       (i < par->last()) && !par->IsLineSeparator(i))
894                       par->InsertChar(i, ' ');
895                   else
896                       --i;
897                   ++number;
898               }
899           }
900           tabular->SetMultiColumn(selection_start,number);
901           actpos = s_start;
902           sel_cell_end = sel_cell_start;
903           calculate_width_of_cells();
904           UpdateLocal();
905           return;
906       }
907       case LyXTable::SET_ALL_LINES:
908           setLines = 1;
909       case LyXTable::UNSET_ALL_LINES:
910           for(i=selection_start; i<=selection_end; ++i)
911               tabular->SetAllLines(i, setLines);
912           calculate_width_of_cells();
913           UpdateLocal();
914           return;
915       case LyXTable::SET_LONGTABLE:
916           tabular->SetLongTable(true);
917           UpdateLocal(); // because this toggles displayed
918           return;
919       case LyXTable::UNSET_LONGTABLE:
920           tabular->SetLongTable(false);
921           UpdateLocal(); // because this toggles displayed
922           return;
923       case LyXTable::SET_ROTATE_TABLE:
924           tabular->SetRotateTable(true);
925           return;
926       case LyXTable::UNSET_ROTATE_TABLE:
927           tabular->SetRotateTable(false);
928           return;
929       case LyXTable::SET_ROTATE_CELL:
930           for(i=selection_start; i<=selection_end; ++i)
931               tabular->SetRotateCell(i,true);
932           return;
933       case LyXTable::UNSET_ROTATE_CELL:
934           for(i=selection_start; i<=selection_end; ++i)
935               tabular->SetRotateCell(i,false);
936           return;
937       case LyXTable::SET_LINEBREAKS:
938           what = !tabular->Linebreaks(tabular->FirstVirtualCell(actcell));
939           for(i=selection_start; i<=selection_end; ++i)
940               tabular->SetLinebreaks(i,what);
941           return;
942       case LyXTable::SET_LTFIRSTHEAD:
943           tabular->SetLTHead(actcell,true);
944           return;
945       case LyXTable::SET_LTHEAD:
946           tabular->SetLTHead(actcell,false);
947           return;
948       case LyXTable::SET_LTFOOT:
949           tabular->SetLTFoot(actcell,false);
950           return;
951       case LyXTable::SET_LTLASTFOOT:
952           tabular->SetLTFoot(actcell,true);
953           return;
954       case LyXTable::SET_LTNEWPAGE:
955           what = !tabular->LTNewPage(actcell);
956           tabular->SetLTNewPage(actcell,what);
957           return;
958     }
959 #endif
960 }
961
962 void InsetTabular::RemoveTableRow()
963 {
964 }