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