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