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