]> git.lyx.org Git - features.git/blob - src/table.C
Initial revision
[features.git] / src / table.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *        Copyright (C) 1995 Matthias Ettrich
7  *        Copyright (C) 1995-1998 The LyX Team.
8  *
9  *======================================================
10  */
11
12 #include <stdlib.h>
13 #include "table.h"
14 #include "vspace.h"
15 #include "layout.h"
16
17 //      $Id: table.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $     
18
19 #if !defined(lint) && !defined(WITH_WARNINGS)
20 static char vcid[] = "$Id: table.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $";
21 #endif /* lint */
22
23 #ifdef __GNUG__
24 #pragma implementation
25 #endif
26
27 extern void addNewlineAndDepth(LString &file, int const depth); // Jug 990923
28
29 #define WIDTH_OF_LINE 5
30
31 /* konstruktor */
32 LyXTable::LyXTable(int rows_arg, int columns_arg)
33 {
34         Init(rows_arg, columns_arg);
35 }
36
37
38 LyXTable::LyXTable(LyXLex &lex)
39 {
40         FILE *file = lex.getFile();
41         Read(file);
42 }
43
44
45 LyXTable::~LyXTable() {
46         int i;
47         delete[] rowofcell;
48         delete[] columnofcell;
49         delete[] column_info;
50         delete[] row_info;
51         for (i=0; i<rows; i++) {
52                 delete[] cell_info[i]; // verify that this shoudn't be freed with delete
53         }
54         delete[] cell_info;
55 }
56
57
58 LyXTable* LyXTable::Clone()
59 {
60     LyXTable *result = new LyXTable(rows, columns);
61     int row, column;;
62
63     for (row=0; row<rows; row++){
64         for (column=0; column<columns;column++){
65             result->cell_info[row][column] = cell_info[row][column];
66         }
67     }
68
69     for (row=0; row<rows; row++){
70         result->row_info[row] = row_info[row];
71     }
72
73     for (column=0; column<columns; column++){
74         result->column_info[column].left_line = column_info[column].left_line;
75         result->column_info[column].right_line = column_info[column].right_line;
76         result->column_info[column].alignment = column_info[column].alignment;
77         result->column_info[column].p_width = column_info[column].p_width;
78         result->column_info[column].align_special = column_info[column].align_special;
79     }
80   
81     result->SetLongTable(is_long_table);
82     result->rotate=rotate;
83     result->Reinit();
84     return result;
85 }
86
87
88 /* activates all lines and sets all widths to 0 */ 
89 void LyXTable::Init(int rows_arg, int columns_arg)
90 {
91     int i,j,cellno;
92     rows = rows_arg;
93     columns = columns_arg;
94     column_info = new columnstruct[columns];
95     row_info = new rowstruct[rows];
96     cell_info = new cellstruct*[rows];
97
98     cellno = 0;
99     for (i=0; i<rows;i++) {
100         cell_info[i] = new cellstruct[columns];
101         row_info[i].top_line = true;
102         row_info[i].bottom_line = false;
103         row_info[i].is_cont_row = false;
104         row_info[i].newpage = false;
105         for (j=0; j<columns; j++) {
106             cell_info[i][j].cellno = cellno++;
107             cell_info[i][j].width_of_cell = 0;
108             cell_info[i][j].multicolumn = LyXTable::CELL_NORMAL;
109             cell_info[i][j].alignment = LYX_ALIGN_CENTER;
110             cell_info[i][j].top_line = row_info[i].top_line;
111             cell_info[i][j].bottom_line = row_info[i].bottom_line;
112             cell_info[i][j].has_cont_row = false;
113             cell_info[i][j].rotate = false;
114             cell_info[i][j].linebreaks = false;
115         }
116     }
117     row_info[i-1].bottom_line = true;
118     row_info[0].bottom_line = true;
119
120     for (i=0; i<columns;i++) {
121         column_info[i].left_line = true;
122         column_info[i].right_line = false;
123         column_info[i].alignment = LYX_ALIGN_CENTER;
124         // set width_of_column to zero before it is used in
125         // calculate_width_of_column() (thornley)
126         column_info[i].width_of_column = 0;
127         calculate_width_of_column(i);
128     }
129     column_info[i-1].right_line = true;
130    
131     calculate_width_of_table();
132
133     rowofcell = NULL;
134     columnofcell = NULL;
135     set_row_column_number_info();
136     is_long_table = false;
137     rotate = 0;
138     endhead = -1;
139     endfirsthead = -1;
140     endfoot = -1;
141     endlastfoot = -1;
142 }
143
144
145 void LyXTable::AppendRow(int cell)
146 {
147     int row = row_of_cell(cell);
148     rowstruct *row_info2 = new rowstruct[rows+1];
149     cellstruct** cell_info2 = new cellstruct*[rows+1];
150     int i;
151
152     for (i=0; i <= row; i++) {
153         cell_info2[i] = cell_info[i];
154         row_info2[i] = row_info[i];
155     }
156     for (i=rows-1; i >= row; i--) {
157         cell_info2[i+1] = cell_info[i];
158         row_info2[i+1] = row_info[i];
159     }
160     for (i=row;row_info[i].is_cont_row;i--);
161     if (((row+1)>=rows) || !row_info[row+1].is_cont_row)
162         row_info2[row+1].is_cont_row = false;
163     row_info2[row+1].top_line = row_info[i].top_line;
164     cell_info2[row+1] = new cellstruct[columns];
165     for (i=0; i<columns; i++) {
166         cell_info2[row+1][i].width_of_cell = 0;
167         cell_info2[row+1][i] = cell_info2[row][i];
168     }
169    
170     delete[] cell_info;
171     cell_info = cell_info2;
172     delete[] row_info;
173     row_info = row_info2;
174    
175     rows++;
176    
177     Reinit();
178 }
179
180
181 void LyXTable::DeleteRow(int cell)
182 {
183         int row = row_of_cell(cell);
184         while(!row_info[row].is_cont_row && RowHasContRow(cell))
185             DeleteRow(cell_info[row+1][0].cellno);
186         rowstruct *row_info2 = new rowstruct[rows-1];
187         cellstruct** cell_info2 = new cellstruct*[rows-1];
188         int i;
189
190         delete[] cell_info[row];
191         for (i=0; i < row; i++) {
192                 cell_info2[i] = cell_info[i];
193                 row_info2[i] = row_info[i];
194         }
195         if (row_info[i].is_cont_row)
196             row_info2[i-1].bottom_line = row_info[i].bottom_line;
197         for (i=row; i < rows - 1; i++) {
198                 cell_info2[i] = cell_info[i+1];
199                 row_info2[i] = row_info[i+1];
200         }
201    
202
203         delete[] cell_info;
204         cell_info = cell_info2;
205         delete[] row_info;
206         row_info = row_info2;
207    
208         rows--;
209
210         Reinit();
211 }
212
213
214 void LyXTable::AppendColumn(int cell)
215 {
216     int i,j;
217     columnstruct *column_info2 = new columnstruct[columns+1];
218     int column = right_column_of_cell(cell);
219    
220     for (i=0; i<=column; i++){
221         column_info2[i] = column_info[i];
222     }
223     for (i=columns-1; i>=column; i--){
224         column_info2[i+1] = column_info[i];
225     }
226     
227     delete[] column_info;
228     column_info = column_info2;
229     
230     for (i=0; i<rows;i++){
231         cellstruct* tmp = cell_info[i];
232         cell_info[i] = new cellstruct[columns+1];
233         for (j=0; j<=column; j++){
234             cell_info[i][j]=tmp[j];
235         }
236         for (j=column; j<columns; j++){
237             cell_info[i][j+1]=tmp[j];
238         }
239         // care about multicolumns
240         if (cell_info[i][column+1].multicolumn
241             ==LyXTable::CELL_BEGIN_OF_MULTICOLUMN){
242             cell_info[i][column+1].multicolumn =
243                 LyXTable::CELL_PART_OF_MULTICOLUMN;
244         }
245         if (column + 1 == columns
246             || cell_info[i][column+2].multicolumn
247             !=LyXTable::CELL_PART_OF_MULTICOLUMN){
248             cell_info[i][column+1].multicolumn =
249                 LyXTable::CELL_NORMAL;
250         }
251         
252         delete[] tmp;
253     }
254     
255     columns++;
256     Reinit();
257 }
258
259
260 void LyXTable::Reinit()
261 {   
262         int i,j;
263
264         for (i=0; i<rows;i++) {
265                 for (j=0; j<columns; j++) {
266                         cell_info[i][j].width_of_cell = 0;
267                         if ((i+1 < rows) && !row_info[i+1].is_cont_row)
268                             cell_info[i][j].has_cont_row = false;
269                 }
270         }
271   
272         for (i=0; i<columns;i++) {
273                 calculate_width_of_column(i);
274         }
275         calculate_width_of_table();
276
277         set_row_column_number_info();
278 }
279
280
281 void LyXTable::set_row_column_number_info()
282 {
283         int row = 0;
284         int c= 0;
285         int column = 0;
286         numberofcells = -1;
287         for (row=0; row<rows; ++row) {
288                 for (column=0; column<columns; ++column) {
289                         if (cell_info[row][column].multicolumn
290                             != LyXTable::CELL_PART_OF_MULTICOLUMN)
291                                 ++numberofcells;
292                         cell_info[row][column].cellno = numberofcells;
293                 }
294         }
295         ++numberofcells; // because this is one more than as we start from 0
296         row = 0;
297         column = 0;
298
299         if (rowofcell)
300                 delete [] rowofcell;
301         rowofcell = new int[numberofcells];
302         if (columnofcell)
303                 delete [] columnofcell;
304         columnofcell = new int[numberofcells];
305   
306         while (c < numberofcells && row < rows && column < columns) {
307                 rowofcell[c]=row;
308                 columnofcell[c]=column;
309                 c++;
310                 do{
311                         column++;
312                 } while (column < columns &&
313                          cell_info[row][column].multicolumn
314                          == LyXTable::CELL_PART_OF_MULTICOLUMN);
315                 if (column == columns){
316                         column = 0;
317                         row++;
318                 }
319         }
320 }
321
322
323 void LyXTable::DeleteColumn(int cell)
324 {
325         int column1 = column_of_cell(cell);
326         int column2 = right_column_of_cell(cell);
327         int column;
328    
329         if (column1 == 0 && column2 == columns - 1)
330                 return;
331    
332         for (column = column1; column <= column2;column++){
333                 delete_column(column1);
334         }
335         Reinit();
336 }
337
338
339 int LyXTable::GetNumberOfCells()
340 {
341         return numberofcells;
342 }
343
344
345 int LyXTable::NumberOfCellsInRow(int cell)
346 {
347         int row = row_of_cell(cell);
348         int i=0;
349         int result = 0;
350         for (i=0; i<columns; i++){
351                 if (cell_info[row][i].multicolumn != LyXTable::CELL_PART_OF_MULTICOLUMN)
352                         result++;
353         }
354         return result;
355 }
356
357
358 int LyXTable::AppendCellAfterCell(int append_cell, int question_cell)
359 {
360         return (right_column_of_cell(append_cell) == 
361                 right_column_of_cell(question_cell));
362 }
363
364
365 int LyXTable::DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell)
366 {
367     if (column_of_cell(delete_column_cell) == 0 && 
368         right_column_of_cell(delete_column_cell) == columns - 1)
369         return 0;
370     else
371         return
372             (column_of_cell(cell) >= column_of_cell(delete_column_cell) &&
373              column_of_cell(cell) <= right_column_of_cell(delete_column_cell));
374 }
375
376
377 /* returns 1 if there is a topline, returns 0 if not */ 
378 bool LyXTable::TopLine(int cell)
379 {
380     int row=row_of_cell(cell);
381     
382     if (IsContRow(cell))
383         return TopLine(cell_info[row-1][column_of_cell(cell)].cellno);
384     if (IsMultiColumn(cell))
385         return cellinfo_of_cell(cell)->top_line;
386     return row_info[row].top_line;
387 }
388
389
390 bool LyXTable::BottomLine(int cell)
391 {
392     //no bottom line underneath non-existent cells if you please
393     if(cell >= numberofcells)
394         return false;
395
396     int row=row_of_cell(cell);
397     
398     if (RowHasContRow(cell))
399         return BottomLine(cell_info[row+1][column_of_cell(cell)].cellno);
400     if (IsMultiColumn(cell))
401         return cellinfo_of_cell(cell)->bottom_line;
402     return row_info[row_of_cell(cell)].bottom_line;
403 }
404
405
406 bool LyXTable::LeftLine(int cell)
407 {
408         return column_info[column_of_cell(cell)].left_line;
409 }
410
411 bool LyXTable::RightLine(int cell)
412 {
413         return column_info[right_column_of_cell(cell)].right_line;
414 }
415
416
417 bool LyXTable::TopAlreadyDrawed(int cell)
418 {
419         if (AdditionalHeight(cell))
420                 return false;
421         int row = row_of_cell(cell);
422         if (row > 0){
423                 int column = column_of_cell(cell);
424                 while (column
425                        && cell_info[row-1][column].multicolumn
426                        == LyXTable::CELL_PART_OF_MULTICOLUMN)
427                         column--;
428                 if (cell_info[row-1][column].multicolumn
429                     == LyXTable::CELL_NORMAL)
430                         return row_info[row-1].bottom_line;
431                 else
432                         return cell_info[row-1][column].bottom_line;
433         }
434         return false;
435 }
436
437
438 bool LyXTable::VeryLastRow(int cell)
439 {
440         return (row_of_cell(cell) == rows-1);
441 }
442
443
444 int LyXTable::AdditionalHeight(int cell)
445 {
446         int row = row_of_cell(cell);
447         int top = 1;
448         int bottom = 1;
449         int column;
450         if (row){
451                 for (column=0;column < columns-1 && bottom;column++){
452                         switch (cell_info[row-1][column].multicolumn){
453                         case LyXTable::CELL_BEGIN_OF_MULTICOLUMN:
454                                 bottom = cell_info[row-1][column].bottom_line;
455                                 break;
456                         case LyXTable::CELL_NORMAL:
457                                 bottom = row_info[row-1].bottom_line;
458                         }
459                 }
460                 for (column=0;column < columns-1 && top;column++){
461                         switch (cell_info[row][column].multicolumn){
462                         case LyXTable::CELL_BEGIN_OF_MULTICOLUMN:
463                                 top = cell_info[row][column].top_line;
464                                 break;
465                         case LyXTable::CELL_NORMAL:
466                                 top = row_info[row].top_line;
467                         }
468                 }
469                 if (top && bottom)
470                         return WIDTH_OF_LINE;
471         }
472         return 0;
473 }
474
475
476 int LyXTable::AdditionalWidth(int cell)
477 {
478         // internally already set in SetWidthOfCell
479         // used to get it back in text.C
480         int col = right_column_of_cell(cell);
481         if (col < columns - 1 && column_info[col].right_line &&
482             column_info[col+1].left_line)
483                 return WIDTH_OF_LINE;
484         else
485                 return 0;
486 }
487
488
489 // returns the maximum over all rows 
490 int LyXTable::WidthOfColumn(int cell)
491 {
492         int column1 = column_of_cell(cell);
493         int column2 = right_column_of_cell(cell);
494         int i;
495         int result=0;
496         for (i=column1; i<=column2;i++){
497                 result += column_info[i].width_of_column;
498         }
499         return result;
500 }
501
502
503 int LyXTable::WidthOfTable()
504 {
505         return width_of_table;
506 }
507
508 /* returns 1 if a complete update is necessary, otherwise 0 */ 
509 bool LyXTable::SetWidthOfMulticolCell(int cell, int new_width)
510 {
511     if (!IsMultiColumn(cell))
512         return false;
513     
514     int row = row_of_cell(cell);
515     int column1 = column_of_cell(cell);
516     int column2 = right_column_of_cell(cell);
517     int i;
518     int width=0;
519
520     // first set columns to 0 so we can calculate the right width
521     for (i=column1; i<=column2;i++) {
522         cell_info[row][i].width_of_cell = 0;
523     }
524     // set the width to MAX_WIDTH until width > 0
525     width = (new_width + 2*WIDTH_OF_LINE);
526     for (i=column1; (i<column2) && (width > 0);i++){
527         cell_info[row][i].width_of_cell = column_info[i].width_of_column;
528         width -= column_info[i].width_of_column;
529     }
530     if (i==column2) {
531         cell_info[row][i].width_of_cell = width;
532     }
533     return true;
534 }
535
536 void LyXTable::recalculateMulticolCells(int cell, int new_width)
537 {
538     int
539         row = row_of_cell(cell),
540         column1 = column_of_cell(cell),
541         column2 = right_column_of_cell(cell),
542         i;
543
544     // first set columns to 0 so we can calculate the right width
545     for (i=column1; i<=column2;++i)
546         cell_info[row][i].width_of_cell = 0;
547     for(i=cell+1;(i<numberofcells) && (!IsMultiColumn(i));++i)
548         ;
549     if (i < numberofcells)
550         recalculateMulticolCells(i,GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
551     SetWidthOfMulticolCell(cell,new_width);
552 }
553
554 /* returns 1 if a complete update is necessary, otherwise 0 */ 
555 bool LyXTable::SetWidthOfCell(int cell, int new_width)
556 {
557     int row = row_of_cell(cell);
558     int column1 = column_of_cell(cell);
559     int tmp=0;
560     int width=0;
561
562     if (IsMultiColumn(cell)) {
563         tmp = SetWidthOfMulticolCell(cell, new_width);
564     } else {
565         width = (new_width + 2*WIDTH_OF_LINE);
566         cell_info[row][column1].width_of_cell = width;
567         if (column_info[column1].right_line && (column1 < columns-1) &&
568             column_info[column1+1].left_line) // additional width
569             cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
570         tmp = calculate_width_of_column_NMC(column1);
571     }
572     if (tmp) {
573         int i;
574         for(i=0; i<columns;++i)
575             calculate_width_of_column_NMC(i);
576         for(i=0; (i<numberofcells) && !IsMultiColumn(i); ++i)
577             ;
578         if (i<numberofcells)
579             recalculateMulticolCells(i,GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
580         for(i=0; i<columns;++i)
581             calculate_width_of_column(i);
582         calculate_width_of_table();
583         return true;
584     }
585     return false;
586 }
587
588
589 bool LyXTable::SetAlignment(int cell, char align)
590 {
591     if (!IsMultiColumn(cell))
592         column_info[column_of_cell(cell)].alignment = align;
593     cellinfo_of_cell(cell)->alignment = align;
594     return true;
595 }
596
597 bool LyXTable::SetPWidth(int cell, LString width)
598 {
599     int fvcell = FirstVirtualCell(cell);
600
601     if (IsMultiColumn(fvcell)) {
602 //        if (column_info[column_of_cell(cell)].p_width.empty())
603 //            column_info[column_of_cell(cell)].p_width = width;
604         cellinfo_of_cell(fvcell)->p_width = width;
605     } else {
606         column_info[column_of_cell(fvcell)].p_width = width;
607         SetAlignment(cell,LYX_ALIGN_LEFT);
608     }
609     return true;
610 }
611
612 bool LyXTable::SetAlignSpecial(int cell, LString special, int what)
613 {
614     if (what == SET_SPECIAL_MULTI)
615         cellinfo_of_cell(cell)->align_special = special;
616     else
617         column_info[column_of_cell(cell)].align_special = special;
618     return true;
619 }
620
621 bool LyXTable::SetAllLines(int cell, bool line)
622 {
623     SetTopLine(cell,line);
624     SetBottomLine(cell,line);
625     SetRightLine(cell,line);
626     SetLeftLine(cell,line);
627     return true;
628 }
629
630 bool LyXTable::SetTopLine(int cell, bool line)
631 {
632     int row = row_of_cell(cell);
633
634     if (IsContRow(cell))
635         SetTopLine(cell_info[row-1][column_of_cell(cell)].cellno,line);
636     else if (!IsMultiColumn(cell))
637         row_info[row].top_line = line;
638     else
639         cellinfo_of_cell(cell)->top_line = line;
640     return true;
641 }
642
643
644 bool LyXTable::SetBottomLine(int cell, bool line)
645 {
646     int row = row_of_cell(cell);
647
648     if (RowHasContRow(cell))
649         SetBottomLine(cell_info[row+1][column_of_cell(cell)].cellno,line);
650     else if (!IsMultiColumn(cell))
651         row_info[row_of_cell(cell)].bottom_line = line;
652     else
653         cellinfo_of_cell(cell)->bottom_line = line;
654     return true;
655 }
656
657
658 bool LyXTable::SetLeftLine(int cell, bool line)
659 {
660         column_info[column_of_cell(cell)].left_line = line;
661         return true;
662 }
663
664
665 bool LyXTable::SetRightLine(int cell, bool line)
666 {
667         column_info[right_column_of_cell(cell)].right_line = line;
668         return true;
669 }
670
671
672 char LyXTable::GetAlignment(int cell)
673 {
674         if (IsMultiColumn(cell))
675                 return cellinfo_of_cell(cell)->alignment;
676         else
677                 return column_info[column_of_cell(cell)].alignment;
678 }
679
680 LString LyXTable::GetPWidth(int cell)
681 {
682         int fvcell = FirstVirtualCell(cell);
683         
684         if (IsMultiColumn(fvcell)) // && !cellinfo_of_cell(cell)->p_width.empty())
685                 return cellinfo_of_cell(fvcell)->p_width;
686         return column_info[column_of_cell(fvcell)].p_width;
687 }
688
689 LString LyXTable::GetAlignSpecial(int cell, int what)
690 {
691     if (what == SET_SPECIAL_MULTI)
692         return cellinfo_of_cell(cell)->align_special;
693     return column_info[column_of_cell(cell)].align_special;
694 }
695
696 int LyXTable::GetWidthOfCell(int cell)
697 {
698         int row = row_of_cell(cell);
699         int column1 = column_of_cell(cell);
700         int column2 = right_column_of_cell(cell);
701         int i;
702         int result=0;
703         for (i=column1; i<=column2;i++){
704                 result += cell_info[row][i].width_of_cell;
705         }
706   
707         result += AdditionalWidth(cell);
708   
709         return result;
710 }
711
712
713 int LyXTable::GetBeginningOfTextInCell(int cell)
714 {
715         int x = 0;
716    
717         switch (GetAlignment(cell)){
718         case LYX_ALIGN_CENTER:
719                 x += (WidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
720                 break;
721         case LYX_ALIGN_RIGHT:
722                 x += WidthOfColumn(cell) - GetWidthOfCell(cell) + AdditionalWidth(cell);
723                 break;
724         default: /* LYX_ALIGN_LEFT: nothing :-) */ 
725                 break;
726         }
727
728         // the LaTeX Way :-(
729         x += WIDTH_OF_LINE;
730         return x;
731 }
732
733
734 bool LyXTable::IsFirstCell(int cell)
735 {
736         return (column_of_cell(cell) == 0);
737 }
738
739 bool LyXTable::IsLastCell(int cell)
740 {
741         return (right_column_of_cell(cell) == (columns-1));
742 }
743
744
745 bool LyXTable::calculate_width_of_column(int column)
746 {
747         int i, max;
748         int old_column_width = column_info[column].width_of_column;
749         max = 0;
750         for (i=0; i<rows; i++) {
751                 if (cell_info[i][column].width_of_cell > max) {
752                         max = cell_info[i][column].width_of_cell;
753                 }
754         }
755         column_info[column].width_of_column = max;
756         return (column_info[column].width_of_column != old_column_width);
757 }
758
759 bool LyXTable::calculate_width_of_column_NMC(int column)
760 {
761     int i, max;
762     int old_column_width = column_info[column].width_of_column;
763     max = 0;
764     for (i=0; i<rows; ++i) {
765         if (!IsMultiColumn(GetCellNumber(column,i)) &&
766             (cell_info[i][column].width_of_cell > max)) {
767             max = cell_info[i][column].width_of_cell;
768         }
769     }
770     column_info[column].width_of_column = max;
771     return (column_info[column].width_of_column != old_column_width);
772 }
773
774 void LyXTable::calculate_width_of_table()
775 {
776         int i;
777         width_of_table = 0;
778         for (i=0; i<columns;i++) {
779                 width_of_table += column_info[i].width_of_column;
780         }
781 }
782
783
784 int LyXTable::row_of_cell(int cell) 
785 {
786     if (cell >= numberofcells)
787         return rows-1;
788     else if (cell < 0)
789         return 0;
790     return rowofcell[cell];
791 }
792
793
794 int LyXTable::column_of_cell(int cell)
795 {
796     if (cell >= numberofcells)
797         return columns-1;
798     else if (cell < 0)
799         return 0;
800     return columnofcell[cell];
801 }
802
803
804 int LyXTable::right_column_of_cell(int cell) 
805 {
806         int row = row_of_cell(cell);
807         int column = column_of_cell(cell);
808         while (column < columns - 1 &&
809                cell_info[row][column+1].multicolumn == LyXTable::CELL_PART_OF_MULTICOLUMN)
810                 column++;
811         return column;
812 }
813
814
815 void LyXTable::Write(FILE* file)
816 {
817     int i,j;
818     fprintf(file, "multicol5\n");
819     fprintf(file, "%d %d %d %d %d %d %d %d\n", rows, columns, is_long_table,
820             rotate, endhead, endfirsthead, endfoot, endlastfoot);
821     for (i=0; i<rows; i++){
822         fprintf(file, "%d %d %d %d\n", row_info[i].top_line,
823                 row_info[i].bottom_line, row_info[i].is_cont_row,
824                 row_info[i].newpage);
825     }
826     for (i=0; i<columns; i++){
827         fprintf(file, "%d %d %d \"%s\" \"%s\"\n",
828                 column_info[i].alignment, column_info[i].left_line,
829                 column_info[i].right_line,
830                 VSpace(column_info[i].p_width).asLyXCommand().c_str(),
831                 column_info[i].align_special.c_str());
832     }
833
834     for (i=0; i<rows;i++){
835         for (j=0;j<columns;j++){
836             fprintf(file, "%d %d %d %d %d %d %d \"%s\" \"%s\"\n",
837                     cell_info[i][j].multicolumn,
838                     cell_info[i][j].alignment,
839                     cell_info[i][j].top_line,
840                     cell_info[i][j].bottom_line,
841                     cell_info[i][j].has_cont_row,
842                     cell_info[i][j].rotate,
843                     cell_info[i][j].linebreaks,
844                     cell_info[i][j].align_special.c_str(),
845                     cell_info[i][j].p_width.c_str());
846         }
847     }
848 }
849
850 #ifdef WITH_WARNINGS
851 #warning Clean up this code in 0.13 (Jug)
852 #endif
853 void LyXTable::Read(FILE* file)
854 {
855     int version;
856     int i,j;
857     int rows_arg = 0;
858     int columns_arg = 0;
859     int is_long_table_arg = false;
860     int rotate_arg = false;
861     LString s;
862     int a = 0;
863     int b = 0;
864     int c = 0;
865     int d = 0;
866     int e = 0;
867     int f = 0;
868     int g = 0;
869     int h = 0;
870     char vtmp[100], stmp[100], atmp[100];
871
872     fscanf(file, "%s\n", vtmp);
873     s = vtmp;
874     if (s.length() > 8)
875         version = atoi(s.c_str()+8);
876     else
877         version = 1;
878     a=b=c=d=-1;
879     if (version > 2) {
880         fgets(vtmp,sizeof(vtmp),file);
881         sscanf(vtmp, "%d %d %d %d %d %d %d %d\n", &rows_arg, &columns_arg,
882                &is_long_table_arg, &rotate_arg, &a, &b, &c, &d);
883     } else
884         fscanf(file, "%d %d\n",
885                &rows_arg, &columns_arg);
886     Init(rows_arg, columns_arg);
887     SetLongTable(is_long_table_arg);
888     SetRotateTable(rotate_arg);
889     endhead = a;
890     endfirsthead = b;
891     endfoot = c;
892     endlastfoot = d;
893     for (i=0; i<rows; i++){
894         a=b=c=d=e=f=g=h=0;
895         fgets(vtmp,sizeof(vtmp),file);
896         sscanf(vtmp, "%d %d %d %d\n",
897                &a, &b, &c, &d);
898         row_info[i].top_line = a;
899         row_info[i].bottom_line = b;
900         row_info[i].is_cont_row = c;
901         row_info[i].newpage = d;
902     }
903     for (i=0; i<columns; i++){
904         *stmp = 0;
905         *atmp = 0;
906         fgets(vtmp,sizeof(vtmp),file);
907         sscanf(vtmp, "%d %d %d %s %s", &a, &b, &c, stmp, atmp);
908         column_info[i].alignment = (char) a;
909         column_info[i].left_line = b;
910         column_info[i].right_line = c;
911         if (*stmp == '"') { /* strip quotes if they exists */
912             *stmp = 0;
913             *atmp = 0;
914             // there are quotes so I have to reread the string correctly
915             // this is only because the old format did not have "
916             // this means also that atmp is ONLY set here!!!
917             if (stmp[1] == '"')
918                 sscanf(vtmp, "%*d %*d %*d %*s \"%[^\"]\"", atmp);
919             else // otherwise after the first empty "" read is aborded
920                 sscanf(vtmp, "%*d %*d %*d \"%[^\"]\" \"%[^\"]\"", stmp, atmp);
921             column_info[i].p_width = stmp;
922             column_info[i].align_special = atmp;
923         } else if (*stmp)
924             column_info[i].p_width = stmp;
925     }
926     if (version == 1){
927         for (i=0; i<rows;i++){
928             for (j=0;j<columns;j++){
929                 fscanf(file, "%d %d\n", &a, &b);
930                 cell_info[i][j].multicolumn = (char) a;
931                 cell_info[i][j].alignment = (char) b;
932             }
933         }
934     } else if (version < 4) {
935         for (i=0; i<rows;i++){
936             for (j=0;j<columns;j++){
937                 fscanf(file, "%d %d %d %d\n", &a, &b, &c, &d);
938                 cell_info[i][j].multicolumn = (char) a;
939                 cell_info[i][j].alignment = (char) b;
940                 cell_info[i][j].top_line = (char) c;
941                 cell_info[i][j].bottom_line = (char) d;
942             }
943         }
944     } else {
945         for (i=0; i<rows;i++){
946             for (j=0;j<columns;j++){
947                 *stmp = 0;
948                 *atmp = 0;
949                 a=b=c=d=e=f=g=0;
950                 fgets(vtmp,sizeof(vtmp),file);
951                 sscanf(vtmp, "%d %d %d %d %d %d %d %s %s\n",
952                        &a, &b, &c, &d, &e, &f, &g, stmp, atmp);
953                 cell_info[i][j].multicolumn = (char) a;
954                 cell_info[i][j].alignment = (char) b;
955                 cell_info[i][j].top_line = (char) c;
956                 cell_info[i][j].bottom_line = (char) d;
957                 cell_info[i][j].has_cont_row = (bool) e;
958                 cell_info[i][j].rotate = (bool) f;
959                 cell_info[i][j].linebreaks = (bool) g;
960                 // this is only to see if I have an empty string first
961                 // this clause should be always TRUE!!!
962                 if (*stmp == '"') {
963                     *stmp = 0;
964                     *atmp = 0;
965                     if (stmp[1] == '"')
966                         sscanf(vtmp,"%*d %*d %*d %*d %*d %*d %*d %*s \"%[^\"]\"",
967                                atmp);
968                     else // otherwise after the first empty "" read is aborded
969                         sscanf(vtmp,"%*d %*d %*d %*d %*d %*d %*d \"%[^\"]\" \"%[^\"]\"",
970                                stmp, atmp);
971                     cell_info[i][j].align_special = stmp;
972                     cell_info[i][j].p_width = atmp;
973                 } else if (*stmp)
974                     cell_info[i][j].align_special = stmp;
975             }
976         }
977     }
978     set_row_column_number_info();
979 }
980
981
982 // cell <0 will tex the preamble
983 // returns the number of printed newlines
984 int LyXTable::TexEndOfCell(LString& file, int cell)
985 {
986     int i;
987     int ret = 0;
988     int tmp; // tmp2;
989     int fcell,nvcell;
990     if (ShouldBeVeryLastCell(cell)) {
991         // the very end at the very beginning
992         if (Linebreaks(cell))
993             file += "\\smallskip{}}";
994         if (IsMultiColumn(cell))
995             file += '}';
996         if (RotateCell(cell)) {
997             file += "\n\\end{sideways}";
998             ret++;
999         }
1000         file += "\\\\\n";
1001         ret++;
1002     
1003         tmp = 0;
1004         fcell = cell; 
1005         while (!IsFirstCell(fcell))fcell--;
1006         for (i=0; i < NumberOfCellsInRow(fcell); i++){
1007             if (BottomLine(fcell+i))
1008                 tmp++;
1009         }
1010         if (tmp == NumberOfCellsInRow(fcell)){
1011             file += "\\hline ";
1012         } else {
1013             tmp = 0;
1014             for (i=0; i < NumberOfCellsInRow(fcell); i++){
1015                 if (BottomLine(fcell+i)){
1016                     file += "\\cline{";
1017                     file += column_of_cell(fcell+i)+1;
1018                     file += '-';
1019                     file += right_column_of_cell(fcell+i)+1;
1020                     file += "} ";
1021                     tmp = 1;
1022                 }
1023             }
1024         }
1025         if (tmp){
1026             file += '\n';
1027             ret++;
1028         }
1029         if (is_long_table)
1030             file += "\\end{longtable}";
1031         else
1032             file += "\\end{tabular}";
1033         if (rotate) {
1034             file += "\n\\end{sideways}";
1035             ret++;
1036         }
1037     } else {
1038         nvcell = NextVirtualCell(cell+1);
1039         if (cell < 0){
1040             // preamble
1041             if (rotate) {
1042                 file += "\\begin{sideways}\n";
1043                 ret++;
1044             }
1045             if (is_long_table)
1046                 file += "\\begin{longtable}{";
1047             else
1048                 file += "\\begin{tabular}{";
1049             for (i=0; i<columns;i++){
1050                 if (column_info[i].left_line)
1051                     file += '|';
1052                 if (!column_info[i].align_special.empty()) {
1053                     file += column_info[i].align_special.c_str();
1054                 } else if (!column_info[i].p_width.empty()) {
1055                     file += "p{";
1056                     file += column_info[i].p_width;
1057                     file += '}';
1058                 } else {
1059                     switch (column_info[i].alignment) {
1060                       case LYX_ALIGN_LEFT:
1061                           file += 'l';
1062                           break;
1063                       case LYX_ALIGN_RIGHT:
1064                           file += 'r';
1065                           break;
1066                       default:
1067                           file += 'c';
1068                           break;
1069                     }
1070                 }
1071                 if (column_info[i].right_line)
1072                     file += '|';
1073             }
1074             file += "}\n";
1075             ret++;
1076             tmp = 0;
1077             if (GetNumberOfCells()){
1078                 fcell = 0;
1079                 for (i=0; i < NumberOfCellsInRow(fcell); i++){
1080                     if (TopLine(fcell+i))
1081                         tmp++;
1082                 }
1083                 if (tmp == NumberOfCellsInRow(fcell)){
1084                     file += "\\hline ";
1085                 } else {
1086                     tmp = 0;
1087                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1088                         if (TopLine(fcell+i)){
1089                             file += "\\cline{";
1090                             file += column_of_cell(fcell+i)+1;
1091                             file += '-';
1092                             file += right_column_of_cell(fcell+i)+1;
1093                             file += "} ";
1094                             tmp = 1;
1095                         }
1096                     }
1097                 }
1098                 if (tmp){
1099                     file += '\n';
1100                     ret++;
1101                 }
1102             }
1103             if (RotateCell(0)) {
1104                 file += "\\begin{sideways}\n";
1105                 ret++;
1106             }
1107         } else {
1108             // usual cells
1109             if (Linebreaks(cell))
1110                 file += "\\smallskip{}}";
1111             if (IsMultiColumn(cell)){
1112                 file += '}';
1113             }
1114             if (RotateCell(cell)) {
1115                 file += "\n\\end{sideways}";
1116                 ret++;
1117             }
1118             if (IsLastCell(cell)) {
1119                 int row = row_of_cell(cell);
1120                 LString hline1,hline2;
1121                 bool print_hline = true;
1122                 bool pr_top_hline,flag1,flag2;
1123                 flag1 = IsLongTable() &&
1124                     ((row == endhead) || (row == endfirsthead) ||
1125                      (row == endfoot) || (row == endlastfoot));
1126                 row++;
1127                 flag2 = IsLongTable() &&
1128                     ((row <= endhead) || (row <= endfirsthead) ||
1129                      (row <= endfoot) || (row <= endlastfoot));
1130                 row--;
1131                 // print the bottom hline only if (otherwise it is doubled):
1132                 // - is no LongTable
1133                 // - there IS a first-header
1134                 // - the next row is no special header/footer
1135                 //   & this row is no special header/footer
1136                 // - the next row is a special header/footer
1137                 //   & this row is a special header/footer
1138                 pr_top_hline = (flag1 && flag2) || (!flag1 && !flag2) ||
1139                     (endfirsthead == endhead);
1140                 file += "\\\\\n";
1141                 ret++;
1142                 tmp = 0;
1143                 fcell = cell;
1144                 while (!IsFirstCell(fcell))
1145                     fcell--;
1146                 for (i=0; i < NumberOfCellsInRow(cell); i++){
1147                     if (BottomLine(fcell+i))
1148                         tmp++;
1149                 }
1150                 if (tmp == NumberOfCellsInRow(cell)){
1151                     file += "\\hline ";
1152                     hline1 = "\\hline ";
1153                 } else {
1154                     tmp = 0;
1155                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1156                         if (BottomLine(fcell+i)){
1157                             file += "\\cline{";
1158                             file += column_of_cell(fcell+i)+1;
1159                             file += '-';
1160                             file += right_column_of_cell(fcell+i)+1;
1161                             file += "} ";
1162                             hline1 += "\\cline{";
1163                             hline1 += column_of_cell(fcell+i)+1;
1164                             hline1 += '-';
1165                             hline1 += right_column_of_cell(fcell+i)+1;
1166                             hline1 += "} ";
1167                             tmp = 1;
1168                         }
1169                     }
1170                 }
1171                 if (tmp){
1172                     file += '\n';
1173                     ret++;
1174                 }
1175                 if (IsLongTable() && (row == endfoot)) {
1176                     file += "\\endfoot\n";
1177                     ret++;
1178                     print_hline = false; // no double line below footer
1179                 }
1180                 if (IsLongTable() && (row == endlastfoot)) {
1181                     file += "\\endlastfoot\n";
1182                     ret++;
1183                     print_hline = false; // no double line below footer
1184                 }
1185                 if (IsLongTable() && row_info[row].newpage) {
1186                     file += "\\newpage\n";
1187                     ret++;
1188                     print_hline = false; // no line below a \\newpage-command
1189                 }
1190                 tmp = 0;
1191                 if (nvcell < numberofcells && (cell < GetNumberOfCells()-1) &&
1192                     !ShouldBeVeryLastCell(cell)) {
1193                     fcell = nvcell;
1194 #if 0
1195                     // Now jump all ContRows
1196                     while (IsContRow(fcell))
1197                         fcell++;
1198                     while (!IsFirstCell(fcell))
1199                         fcell--;
1200 #endif
1201                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1202                         if (TopLine(fcell+i))
1203                             tmp++;
1204                     }
1205                     if (tmp == NumberOfCellsInRow(fcell)){
1206                         if (print_hline)
1207                             file += "\\hline ";
1208                         hline2 = "\\hline ";
1209                     }
1210                     else {
1211                         tmp = 0;
1212                         for (i=0; i < NumberOfCellsInRow(fcell); i++){
1213                             if (TopLine(fcell+i)){
1214                                 if (print_hline) {
1215                                     file += "\\cline{";
1216                                     file += column_of_cell(fcell+i)+1;
1217                                     file += '-';
1218                                     file += right_column_of_cell(fcell+i)+1;
1219                                     file += "} ";
1220                                 }
1221                                 hline2 += "\\cline{";
1222                                 hline2 += column_of_cell(fcell+i)+1;
1223                                 hline2 += '-';
1224                                 hline2 += right_column_of_cell(fcell+i)+1;
1225                                 hline2 += "} ";
1226                                 tmp = 1;
1227                             }
1228                         }
1229                     }
1230                     if (tmp && print_hline){
1231                         file += '\n';
1232                         ret++;
1233                     }
1234                 }
1235                 // the order here is important as if one defines two
1236                 // or more things in one line only the first entry is
1237                 // displayed the other are set to an empty-row. This
1238                 // is important if I have a footer and want that the
1239                 // lastfooter is NOT displayed!!!
1240                 bool sflag2 = (row == endhead) || (row == endfirsthead) ||
1241                     (row == endfoot) || (row == endlastfoot);
1242                 row--;
1243 //                sflag2 = IsLongTable() && (row >= 0) &&
1244 //                    (sflag2 || (row == endhead) || (row == endfirsthead));
1245                 row += 2;
1246                 bool sflag1 = IsLongTable() && (row != endhead) &&
1247                     (row != endfirsthead) &&
1248                     ((row == endfoot) || (row == endlastfoot));
1249                 row--;
1250                 if (IsLongTable() && (row == endhead)) {
1251                     file += "\\endhead\n";
1252                     ret++;
1253                 }
1254                 if (IsLongTable() && (row == endfirsthead)) {
1255                     file += "\\endfirsthead\n";
1256                     ret++;
1257                 }
1258                 if (sflag1) { // add the \hline for next foot row
1259                     if (!hline1.empty()) {
1260                         file += hline1 + '\n';
1261                         ret++;
1262                     }
1263                 }
1264                 // add the \hline for the first row
1265                 if (pr_top_hline && sflag2) {
1266                     if (!hline2.empty()) {
1267                         file += hline2 + '\n';
1268                         ret++;
1269                     }
1270                 }
1271                 if (nvcell < numberofcells && RotateCell(nvcell)) {
1272                     file += "\\begin{sideways}\n";
1273                     ret++;
1274                 }
1275             } else {
1276                 file += "&\n";
1277                 ret++;
1278                 if (nvcell < numberofcells && RotateCell(nvcell)) {
1279                     file += "\\begin{sideways}\n";
1280                     ret++;
1281                 }
1282             }
1283         }
1284         if (nvcell < numberofcells && IsMultiColumn(nvcell)) {
1285             file += "\\multicolumn{";
1286             file += cells_in_multicolumn(nvcell);
1287             file += "}{";
1288             if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1289                 file += cellinfo_of_cell(cell+1)->align_special;
1290                 file += "}{";
1291             } else {
1292                 if (LeftLine(nvcell))
1293                     file += '|';
1294                 if (!GetPWidth(nvcell).empty()) {
1295                     file += "p{";
1296                     file += GetPWidth(nvcell);
1297                     file += '}';
1298                 } else {
1299                     switch (GetAlignment(nvcell)) {
1300                       case LYX_ALIGN_LEFT: file += 'l'; break;
1301                       case LYX_ALIGN_RIGHT: file += 'r'; break;
1302                       default:  file += 'c'; break;
1303                     }
1304                 }
1305                 if (RightLine(nvcell))
1306                     file += '|';
1307                 //if (column_of_cell(cell+2)!=0 && LeftLine(cell+2))
1308                 if (((nvcell+1) < numberofcells) &&
1309                     (NextVirtualCell(nvcell+1) < numberofcells) &&
1310                     (column_of_cell(NextVirtualCell(nvcell+1))!=0) &&
1311                     LeftLine(NextVirtualCell(nvcell+1)))
1312                     file += '|';
1313                 file += "}{";
1314             }
1315         }
1316         if (nvcell < numberofcells && Linebreaks(nvcell)) {
1317 //            !column_info[column_of_cell(nvcell)].p_width.empty()) {
1318             file += "\\parbox{";
1319             file += GetPWidth(nvcell);
1320             file += "}{\\smallskip{}";
1321         }
1322     }
1323     return ret;
1324 }
1325
1326
1327 // cell <0 will tex the preamble
1328 // returns the number of printed newlines
1329 int LyXTable::RoffEndOfCell(FILE* file, int cell)
1330 {
1331     int i,j;
1332     int ret = 0;
1333
1334     if (cell == GetNumberOfCells() - 1){
1335         // the very end at the very beginning
1336         if (CellHasContRow(cell) >= 0) {
1337             fprintf(file,"\nT}");
1338             ret++;
1339         }
1340         fprintf(file, "\n");
1341         ret++;
1342         if (row_info[row_of_cell(cell)].bottom_line) {
1343             fprintf(file, "_\n");
1344             ret++;
1345         }
1346         fprintf(file, ".TE\n.pl 1c");
1347     } else {  
1348         if (cell < 0){
1349             int fcell=0;
1350             // preamble
1351             fprintf(file, "\n.pl 500c\n.TS\n");
1352             for (j=0; j<rows; j++) {
1353                 for (i=0; i<columns;i++,fcell++) {
1354                     if (column_info[i].left_line)
1355                         fprintf(file, " | ");
1356                     if (cell_info[j][i].multicolumn==CELL_PART_OF_MULTICOLUMN)
1357                         fprintf(file, "s");
1358                     else {
1359                         switch (column_info[i].alignment) {
1360                           case LYX_ALIGN_LEFT:
1361                               fprintf(file, "l");
1362                               break;
1363                           case LYX_ALIGN_RIGHT:
1364                               fprintf(file, "r");
1365                               break;
1366                           default:
1367                               fprintf(file, "c");
1368                               break;
1369                         }
1370                     }
1371                     if (!column_info[i].p_width.empty())
1372                         fprintf(file, "w(%s)", column_info[i].p_width.c_str());
1373                     if (column_info[i].right_line)
1374                         fprintf(file, " | ");
1375                 }
1376                 if ((j+1) < rows) {
1377                     fprintf(file, "\n");
1378                     ret++;
1379                 }
1380             }
1381             fprintf(file, ".\n");
1382             ret++;
1383             if (row_info[0].top_line) {
1384                 fprintf(file,"_\n");
1385                 ret++;
1386             }
1387             if (CellHasContRow(0) >= 0) {
1388                 fprintf(file,"T{\n");
1389                 ret++;
1390             }
1391         } else {
1392             // usual cells
1393             if (CellHasContRow(cell) >= 0) {
1394                 fprintf(file,"\nT}");
1395                 ret++;
1396             }
1397             if (right_column_of_cell(cell) == columns -1){
1398                 fprintf(file, "\n");
1399                 ret++;
1400                 int row = row_of_cell(cell);
1401                 if (row_info[row++].bottom_line) {
1402                     fprintf(file, "_\n");
1403                     ret++;
1404                 }
1405                 if ((row < rows) && row_info[row].top_line) {
1406                     fprintf(file, "_\n");
1407                     ret++;
1408                 }
1409             } else
1410                 fprintf(file, "\t");
1411             if ((cell < GetNumberOfCells() - 1) &&
1412                 (CellHasContRow(cell+1) >= 0)) {
1413                 fprintf(file,"T{\n");
1414                 ret++;
1415             }
1416         }
1417     }
1418     return ret;
1419 }
1420
1421 const char *LyXTable::getDocBookAlign(int cell, bool isColumn=false)
1422 {
1423     int i;
1424     if (isColumn)
1425        i = cell;
1426     else
1427        i = column_of_cell(cell);
1428     if (!isColumn && IsMultiColumn(cell)) {
1429        if (!cellinfo_of_cell(cell)->align_special.empty()) {
1430            return cellinfo_of_cell(cell)->align_special.c_str();
1431        } else {
1432            switch (GetAlignment(cell)) {
1433            case LYX_ALIGN_LEFT:
1434                return "left";
1435            case LYX_ALIGN_RIGHT:
1436                return "right";
1437            default:
1438                return "center";
1439            }
1440        }
1441     } else {
1442        if (!column_info[i].align_special.empty()) {
1443            return column_info[i].align_special.c_str();
1444        }
1445 #ifdef IGNORE_THIS_FOR_NOW
1446        else if (!column_info[i].p_width.empty()) {
1447            file += "p{";
1448            file += column_info[i].p_width;
1449            file += '}';
1450        }
1451 #endif
1452        else {
1453            switch (column_info[i].alignment) {
1454            case LYX_ALIGN_LEFT:
1455                return "left";
1456            case LYX_ALIGN_RIGHT:
1457                return "right";
1458            default:
1459                return "center";
1460            }
1461        }
1462     }
1463 }
1464
1465 // cell <0 will tex the preamble
1466 // returns the number of printed newlines
1467 int LyXTable::DocBookEndOfCell(LString& file, int cell, int &depth)
1468 {
1469     int i;
1470     int ret = 0;
1471     int tmp; // tmp2;
1472     int fcell,nvcell;
1473     if (ShouldBeVeryLastCell(cell)) {
1474 #if 0
1475         // the very end at the very beginning
1476         if (Linebreaks(cell))
1477             file += "\\smallskip{}}";
1478         if (IsMultiColumn(cell))
1479             file += '}';
1480         if (RotateCell(cell)) {
1481             file += "\n\\end{sideways}";
1482             ret++;
1483         }
1484         file += "\\\\\n";
1485         ret++;
1486     
1487         tmp = 0;
1488         fcell = cell; 
1489         while (!IsFirstCell(fcell))fcell--;
1490         for (i=0; i < NumberOfCellsInRow(fcell); i++){
1491             if (BottomLine(fcell+i))
1492                 tmp++;
1493         }
1494         if (tmp == NumberOfCellsInRow(fcell)){
1495             file += "\\hline ";
1496         } else {
1497             tmp = 0;
1498             for (i=0; i < NumberOfCellsInRow(fcell); i++){
1499                 if (BottomLine(fcell+i)){
1500                    file += "\\cline{";
1501                    file += column_of_cell(fcell+i)+1;
1502                    file += '-';
1503                    file += right_column_of_cell(fcell+i)+1;
1504                    file += "} ";
1505                     tmp = 1;
1506                 }
1507             }
1508         }
1509         if (tmp){
1510             file += '\n';
1511             ret++;
1512         }
1513 #endif
1514        addNewlineAndDepth(file,--depth);
1515         file += "</ENTRY>";
1516        addNewlineAndDepth(file,--depth);
1517         file += "</ROW>";
1518        addNewlineAndDepth(file,--depth);
1519         file += "</TBODY>";
1520        addNewlineAndDepth(file,--depth);
1521         if (is_long_table)
1522             file += "</TGROUP>";
1523         else
1524             file += "</TGROUP>";
1525        addNewlineAndDepth(file,--depth);
1526 #if 0
1527         if (rotate) {
1528             file += "\n\\end{sideways}";
1529             ret++;
1530         }
1531 #endif
1532         ret += 4;
1533     } else {
1534         nvcell = NextVirtualCell(cell+1);
1535         if (cell < 0) {
1536             // preamble
1537             if (is_long_table)
1538                 file += "<TGROUP ";
1539             else
1540                 file += "<TGROUP ";
1541             file += "COLS='";
1542             file += columns;
1543             file += "' COLSEP='1' ROWSEP='1'>";
1544            addNewlineAndDepth(file,++depth);
1545             ret++;
1546             for (i=0; i<columns;i++) {
1547                 file += "<COLSPEC ALIGN='";
1548                file += getDocBookAlign(i, true);
1549                file += "' COLNAME='col";
1550                 file += i+1;
1551                 file += "' COLNUM='";
1552                 file += i+1;
1553                file += "' COLSEP='";
1554                if (i == (columns-1)) {
1555                     file += '1';
1556                } else {
1557                    if (column_info[i].right_line ||
1558                        column_info[i+1].left_line)
1559                        file += '1';
1560                    else
1561                        file += '0';
1562                }
1563                file += "'>";
1564                addNewlineAndDepth(file,depth);
1565                 ret++;
1566 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1567                 if (column_info[i].left_line)
1568                     file += '|';
1569 #endif
1570             }
1571 #if 0
1572             tmp = 0;
1573             if (GetNumberOfCells()) {
1574                 fcell = 0;
1575                 for (i=0; i < NumberOfCellsInRow(fcell); i++){
1576                     if (TopLine(fcell+i))
1577                         tmp++;
1578                 }
1579                 if (tmp == NumberOfCellsInRow(fcell)){
1580                     file += "\\hline ";
1581                 } else {
1582                     tmp = 0;
1583                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1584                         if (TopLine(fcell+i)){
1585                            file += "\\cline{";
1586                            file += column_of_cell(fcell+i)+1;
1587                            file += '-';
1588                            file += right_column_of_cell(fcell+i)+1;
1589                            file += "} ";
1590                             tmp = 1;
1591                         }
1592                     }
1593                 }
1594                 if (tmp){
1595                     file += '\n';
1596                     ret++;
1597                 }
1598             }
1599             if (RotateCell(0)) {
1600                 file += "\\begin{sideways}\n";
1601                 ret++;
1602             }
1603 #endif
1604             file += "<TBODY>";
1605            addNewlineAndDepth(file,++depth);
1606             file += "<ROW>";
1607            addNewlineAndDepth(file,++depth);
1608             file += "<ENTRY ALIGN='";
1609             file += getDocBookAlign(0);
1610            file += "'";
1611            if (IsMultiColumn(0)) {
1612                file += " NAMEST='col1' NAMEEND='col";
1613                file += cells_in_multicolumn(0);
1614                file += "'";
1615            }
1616             file += ">";
1617            addNewlineAndDepth(file,++depth);
1618             ret += 3;
1619         } else {
1620 #if 0
1621             // usual cells
1622             if (Linebreaks(cell))
1623                 file += "\\smallskip{}}";
1624             if (IsMultiColumn(cell)){
1625                 file += '}';
1626             }
1627             if (RotateCell(cell)) {
1628                 file += "\n\\end{sideways}";
1629                 ret++;
1630             }
1631 #endif
1632             if (IsLastCell(cell)) {
1633                addNewlineAndDepth(file,--depth);
1634                 file += "</ENTRY>";
1635                addNewlineAndDepth(file,--depth);
1636                 file += "</ROW>";
1637                addNewlineAndDepth(file,depth);
1638                file += "<ROW>";
1639                addNewlineAndDepth(file,++depth);
1640                 file += "<ENTRY ALIGN='";
1641                 file += getDocBookAlign(cell+1);
1642                 file += "' VALIGN='middle'";
1643                if (IsMultiColumn(cell+1)) {
1644                    file += " NAMEST='col";
1645                    file += column_of_cell(cell+1) + 1;
1646                    file += "' NAMEEND='col";
1647                    file += column_of_cell(cell+1) +
1648                        cells_in_multicolumn(cell+1);
1649                    file += "'";
1650                }
1651                file += ">";
1652                addNewlineAndDepth(file,++depth);
1653                 ret += 4;
1654 #if 0
1655                 int row = row_of_cell(cell);
1656                 LString hline1,hline2;
1657                 bool print_hline = true;
1658                 bool pr_top_hline,flag1,flag2;
1659                 flag1 = IsLongTable() &&
1660                     ((row == endhead) || (row == endfirsthead) ||
1661                      (row == endfoot) || (row == endlastfoot));
1662                 row++;
1663                 flag2 = IsLongTable() &&
1664                     ((row <= endhead) || (row <= endfirsthead) ||
1665                      (row <= endfoot) || (row <= endlastfoot));
1666                 row--;
1667                 // print the bottom hline only if (otherwise it is doubled):
1668                 // - is no LongTable
1669                 // - there IS a first-header
1670                 // - the next row is no special header/footer
1671                 //   & this row is no special header/footer
1672                 // - the next row is a special header/footer
1673                 //   & this row is a special header/footer
1674                 pr_top_hline = (flag1 && flag2) || (!flag1 && !flag2) ||
1675                     (endfirsthead == endhead);
1676                 file += "\\\\\n";
1677                 ret++;
1678                 tmp = 0;
1679                 fcell = cell;
1680                 while (!IsFirstCell(fcell))
1681                     fcell--;
1682                 for (i=0; i < NumberOfCellsInRow(cell); i++){
1683                     if (BottomLine(fcell+i))
1684                         tmp++;
1685                 }
1686                 if (tmp == NumberOfCellsInRow(cell)){
1687                     file += "\\hline ";
1688                     hline1 = "\\hline ";
1689                 } else {
1690                     tmp = 0;
1691                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1692                         if (BottomLine(fcell+i)){
1693                             file += "\\cline{";
1694                             file += column_of_cell(fcell+i)+1;
1695                             file += '-';
1696                             file += right_column_of_cell(fcell+i)+1;
1697                             file += "} ";
1698                             hline1 += "\\cline{";
1699                             hline1 += column_of_cell(fcell+i)+1;
1700                             hline1 += '-';
1701                             hline1 += right_column_of_cell(fcell+i)+1;
1702                             hline1 += "} ";
1703                             tmp = 1;
1704                         }
1705                     }
1706                 }
1707                 if (tmp){
1708                     file += '\n';
1709                     ret++;
1710                 }
1711                 if (IsLongTable() && (row == endfoot)) {
1712                     file += "\\endfoot\n";
1713                     ret++;
1714                     print_hline = false; // no double line below footer
1715                 }
1716                 if (IsLongTable() && (row == endlastfoot)) {
1717                     file += "\\endlastfoot\n";
1718                     ret++;
1719                     print_hline = false; // no double line below footer
1720                 }
1721                 if (IsLongTable() && row_info[row].newpage) {
1722                     file += "\\newpage\n";
1723                     ret++;
1724                     print_hline = false; // no line below a \\newpage-command
1725                 }
1726                 tmp = 0;
1727                 if (nvcell < numberofcells && (cell < GetNumberOfCells()-1) &&
1728                     !ShouldBeVeryLastCell(cell)) {
1729                     fcell = nvcell;
1730                     for (i=0; i < NumberOfCellsInRow(fcell); i++){
1731                         if (TopLine(fcell+i))
1732                             tmp++;
1733                     }
1734                     if (tmp == NumberOfCellsInRow(fcell)){
1735                         if (print_hline)
1736                             file += "\\hline ";
1737                         hline2 = "\\hline ";
1738                     }
1739                     else {
1740                         tmp = 0;
1741                         for (i=0; i < NumberOfCellsInRow(fcell); i++){
1742                             if (TopLine(fcell+i)){
1743                                 if (print_hline) {
1744                                    file += "\\cline{";
1745                                    file += column_of_cell(fcell+i)+1;
1746                                    file += '-';
1747                                    file += right_column_of_cell(fcell+i)+1;
1748                                    file += "} ";
1749                                }
1750                                 hline2 += "\\cline{";
1751                                 hline2 += column_of_cell(fcell+i)+1;
1752                                 hline2 += '-';
1753                                 hline2 += right_column_of_cell(fcell+i)+1;
1754                                 hline2 += "} ";
1755                                 tmp = 1;
1756                             }
1757                         }
1758                     }
1759                     if (tmp && print_hline){
1760                         file += '\n';
1761                         ret++;
1762                     }
1763                 }
1764                 // the order here is important as if one defines two
1765                 // or more things in one line only the first entry is
1766                 // displayed the other are set to an empty-row. This
1767                 // is important if I have a footer and want that the
1768                 // lastfooter is NOT displayed!!!
1769                 bool sflag2 = (row == endhead) || (row == endfirsthead) ||
1770                     (row == endfoot) || (row == endlastfoot);
1771                 row--;
1772 //                sflag2 = IsLongTable() && (row >= 0) &&
1773 //                    (sflag2 || (row == endhead) || (row == endfirsthead));
1774                 row += 2;
1775                 bool sflag1 = IsLongTable() && (row != endhead) &&
1776                     (row != endfirsthead) &&
1777                     ((row == endfoot) || (row == endlastfoot));
1778                 row--;
1779                 if (IsLongTable() && (row == endhead)) {
1780                     file += "\\endhead\n";
1781                     ret++;
1782                 }
1783                 if (IsLongTable() && (row == endfirsthead)) {
1784                     file += "\\endfirsthead\n";
1785                     ret++;
1786                 }
1787                 if (sflag1) { // add the \hline for next foot row
1788                     if (!hline1.empty()) {
1789                         file += hline1 + '\n';
1790                         ret++;
1791                     }
1792                 }
1793                 // add the \hline for the first row
1794                 if (pr_top_hline && sflag2) {
1795                     if (!hline2.empty()) {
1796                         file += hline2 + '\n';
1797                         ret++;
1798                     }
1799                 }
1800                 if (nvcell < numberofcells && RotateCell(nvcell)) {
1801                     file += "\\begin{sideways}\n";
1802                     ret++;
1803                 }
1804 #endif
1805             } else {
1806                addNewlineAndDepth(file,--depth);
1807                 file += "</ENTRY>";
1808                addNewlineAndDepth(file,depth);
1809                 file += "<ENTRY ALIGN='";
1810                 file += getDocBookAlign(cell+1);
1811                 file += "' VALIGN='middle'";
1812                if (IsMultiColumn(cell+1)) {
1813                    file += " NAMEST='col";
1814                    file += column_of_cell(cell+1) + 1;
1815                    file += "' NAMEEND='col";
1816                    file += column_of_cell(cell+1) +
1817                        cells_in_multicolumn(cell+1);
1818                    file += "'";
1819                }
1820                file += ">";
1821                addNewlineAndDepth(file,++depth);
1822                 ret += 3;
1823 #if 0
1824                 if (nvcell < numberofcells && RotateCell(nvcell)) {
1825                     file += "\\begin{sideways}\n";
1826                     ret++;
1827                 }
1828 #endif
1829             }
1830         }
1831 #if 0
1832         if (nvcell < numberofcells && IsMultiColumn(nvcell)) {
1833             file += "\\multicolumn{";
1834             file += cells_in_multicolumn(nvcell);
1835             file += "}{";
1836             if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1837                 file += cellinfo_of_cell(cell+1)->align_special;
1838                 file += "}{";
1839             } else {
1840                 if (LeftLine(nvcell))
1841                     file += '|';
1842                 if (!GetPWidth(nvcell).empty()) {
1843                     file += "p{";
1844                     file += GetPWidth(nvcell);
1845                     file += '}';
1846                 } else {
1847                     switch (GetAlignment(nvcell)) {
1848                       case LYX_ALIGN_LEFT: file += 'l'; break;
1849                       case LYX_ALIGN_RIGHT: file += 'r'; break;
1850                       default:  file += 'c'; break;
1851                     }
1852                 }
1853                 if (RightLine(nvcell))
1854                     file += '|';
1855                 //if (column_of_cell(cell+2)!=0 && LeftLine(cell+2))
1856                 if (((nvcell+1) < numberofcells) &&
1857                     (NextVirtualCell(nvcell+1) < numberofcells) &&
1858                     (column_of_cell(NextVirtualCell(nvcell+1))!=0) &&
1859                     LeftLine(NextVirtualCell(nvcell+1)))
1860                     file += '|';
1861                 file += "}{";
1862             }
1863         }
1864         if (nvcell < numberofcells && Linebreaks(nvcell)) {
1865 //            !column_info[column_of_cell(nvcell)].p_width.empty()) {
1866             file += "\\parbox{";
1867             file += GetPWidth(nvcell);
1868             file += "}{\\smallskip{}";
1869         }
1870 #endif
1871     }
1872     return ret;
1873 }
1874
1875
1876 bool LyXTable::IsMultiColumn(int cell)
1877 {
1878     int fvcell = FirstVirtualCell(cell);
1879
1880     return (cellinfo_of_cell(fvcell)->multicolumn != LyXTable::CELL_NORMAL);
1881 }
1882
1883
1884 LyXTable::cellstruct* LyXTable::cellinfo_of_cell(int cell)
1885 {
1886     int row = row_of_cell(cell);
1887     int column = column_of_cell(cell);
1888     return  &cell_info[row][column];
1889 }
1890    
1891
1892 void LyXTable::SetMultiColumn(int cell, int number)
1893 {
1894     int fvcell = FirstVirtualCell(cell);
1895     int new_width = cellinfo_of_cell(fvcell)->width_of_cell;
1896     
1897     cellinfo_of_cell(fvcell)->multicolumn = LyXTable::CELL_BEGIN_OF_MULTICOLUMN;
1898     cellinfo_of_cell(fvcell)->alignment = column_info[column_of_cell(fvcell)].alignment;
1899     cellinfo_of_cell(fvcell)->top_line = row_info[row_of_cell(fvcell)].top_line;
1900     cellinfo_of_cell(fvcell)->bottom_line = row_info[row_of_cell(fvcell)].bottom_line;
1901     for (number--;number>0;number--){
1902         cellinfo_of_cell(fvcell+number)->multicolumn =
1903             LyXTable::CELL_PART_OF_MULTICOLUMN;
1904         new_width += cellinfo_of_cell(fvcell+number)->width_of_cell;
1905     }
1906     set_row_column_number_info();
1907     SetWidthOfCell(fvcell,new_width);
1908 }
1909
1910
1911 int LyXTable::cells_in_multicolumn(int cell)
1912 {
1913     int row = row_of_cell(cell);
1914     int column = column_of_cell(cell);
1915     int result = 1;
1916     column++;
1917     while (column < columns && cell_info[row][column].multicolumn
1918            == LyXTable::CELL_PART_OF_MULTICOLUMN){
1919         result++;
1920         column++;
1921     }
1922     return result;
1923 }
1924
1925
1926 int  LyXTable::UnsetMultiColumn(int cell)
1927 {
1928     int fvcell = FirstVirtualCell(cell);
1929     int row = row_of_cell(fvcell);
1930     int column = column_of_cell(fvcell);
1931     
1932     int result = 0;
1933     
1934     if (cell_info[row][column].multicolumn
1935         == LyXTable::CELL_BEGIN_OF_MULTICOLUMN){
1936         cell_info[row][column].multicolumn = LyXTable::CELL_NORMAL;
1937         column++;
1938         while (column < columns &&
1939                cell_info[row][column].multicolumn
1940                == LyXTable::CELL_PART_OF_MULTICOLUMN){
1941             cell_info[row][column].multicolumn =
1942                 LyXTable::CELL_NORMAL;
1943             column++;
1944             result++;
1945         }
1946     }
1947     set_row_column_number_info();
1948     return result;
1949 }
1950
1951
1952 void LyXTable::delete_column(int column)
1953 {
1954     int i,j;
1955     columnstruct *column_info2 = new columnstruct[columns-1];
1956    
1957     for (i=0; i<column; i++){
1958         column_info2[i] = column_info[i];
1959     }
1960     for (i=column; i<columns-1; i++){
1961         column_info2[i] = column_info[i+1];
1962     }
1963    
1964     delete[] column_info;
1965     column_info = column_info2;
1966
1967     for (i=0; i<rows;i++){
1968         cellstruct* tmp = cell_info[i];
1969         cell_info[i] = new cellstruct[columns-1];
1970         for (j=0; j<column; j++){
1971             cell_info[i][j]=tmp[j];
1972         }
1973         for (j=column; j<columns-1; j++){
1974             cell_info[i][j]=tmp[j+1];
1975         }
1976         delete[] tmp;
1977     }
1978
1979     columns--;
1980     Reinit();
1981 }
1982
1983 void LyXTable::SetLongTable(int what)
1984 {
1985     is_long_table = what;
1986 }
1987
1988 bool LyXTable::IsLongTable()
1989 {
1990     return is_long_table;
1991 }
1992
1993 void LyXTable::SetRotateTable(int what)
1994 {
1995     rotate = what;
1996 }
1997
1998 bool LyXTable::RotateTable()
1999 {
2000     return rotate;
2001 }
2002
2003 void LyXTable::SetRotateCell(int cell, int what)
2004 {
2005     cellinfo_of_cell(cell)->rotate = what;
2006 }
2007
2008 bool LyXTable::RotateCell(int cell)
2009 {
2010     return cellinfo_of_cell(cell)->rotate;
2011 }
2012
2013 bool LyXTable::NeedRotating()
2014 {
2015     if (rotate)
2016         return true;
2017     for (int i=0; i<rows;i++){
2018         for (int j=0;j<columns;j++){
2019             if (cell_info[i][j].rotate)
2020                 return true;
2021         }
2022     }
2023     return false;
2024 }
2025
2026 void LyXTable::AppendContRow(int cell)
2027 {
2028     int row = row_of_cell(cell)+1;
2029
2030     if (!RowHasContRow(cell) || (CellHasContRow(cell)>=0))
2031         AppendRow(cell);
2032     row_info[row].is_cont_row = true;
2033     row_info[row].top_line = false;
2034     cell_info[row-1][column_of_cell(cell)].has_cont_row = true;
2035     Reinit();
2036 }
2037
2038 bool LyXTable::IsContRow(int cell)
2039 {
2040     return row_info[row_of_cell(cell)].is_cont_row;
2041 }
2042
2043 int LyXTable::CellHasContRow(int cell)
2044 {
2045     int row = row_of_cell(cell);
2046
2047     if (VeryLastRow(cell))
2048         return -1;
2049     if (cell_info[row][column_of_cell(cell)].has_cont_row)
2050         return cell_info[row+1][column_of_cell(cell)].cellno;
2051     return -1;
2052 }
2053
2054 bool LyXTable::RowHasContRow(int cell)
2055 {
2056     int row = row_of_cell(cell) + 1;
2057
2058     if (row < rows)
2059         return row_info[row].is_cont_row;
2060     return false;
2061 }
2062
2063 int LyXTable::FirstVirtualCell(int cell)
2064 {
2065     if (!IsContRow(cell))
2066         return cell;
2067     int row = row_of_cell(cell);
2068     int column = column_of_cell(cell);
2069     for(;(row>0) && IsContRow(cell_info[row][column].cellno); row--)
2070         ;
2071     return cell_info[row][column].cellno;
2072 }
2073
2074
2075 int LyXTable::NextVirtualCell(int cell)
2076 {
2077     if (!IsContRow(cell))
2078         return cell;
2079     int row = row_of_cell(cell);
2080     for(;(row < rows - 1) && IsContRow(cell_info[row][0].cellno); ++row)
2081         ;
2082     // what if(row >= rows) ?
2083     return cell_info[row][0].cellno;
2084 }
2085
2086
2087 bool LyXTable::ShouldBeVeryLastCell(int cell)
2088 // "very last cell" ..of what? the row? the table?
2089 // "Cell" in this context appears to not count `virtual' cells
2090 {
2091     int fcell = cell + 1;
2092
2093     if (cell == GetNumberOfCells() - 1)
2094         return true; // not really sure if I should return false here
2095     if (!IsContRow(fcell))
2096         return false;
2097     while((fcell < GetNumberOfCells() - 1) && IsContRow(fcell))
2098         fcell++;
2099     if (fcell < GetNumberOfCells() - 1)
2100         return false;
2101     return true;
2102 }
2103
2104 bool LyXTable::ShouldBeVeryLastRow(int cell)
2105 {
2106     if (CellHasContRow(cell)>=0)
2107         return false;
2108     int row = row_of_cell(cell)+1;
2109     int column = column_of_cell(cell);
2110     while((row < rows) && IsContRow(cell_info[row][column].cellno))
2111         row++;
2112     if (row < rows)
2113         return false; // found another valid row
2114     // I do not have any valid row after the actual
2115     return true;
2116 }
2117
2118 int LyXTable::GetCellAbove(int cell)
2119 {
2120     int row = row_of_cell(cell);
2121     
2122     if (row > 0)
2123         return cell_info[row-1][column_of_cell(cell)].cellno;
2124     return cell;
2125 }
2126
2127 int LyXTable::GetCellNumber(int column, int row)
2128 {
2129     if (column >= columns)
2130         column = columns - 1;
2131     else if (column < 0)
2132         column = 0;
2133     if (row >= rows)
2134         row = rows - 1;
2135     else if (row < 0)
2136         row = 0;
2137     
2138     return cell_info[row][column].cellno;
2139 }
2140
2141 void LyXTable::SetLinebreaks(int cell, bool what)
2142 {
2143     cellinfo_of_cell(FirstVirtualCell(cell))->linebreaks = what;
2144 }
2145
2146 bool LyXTable::Linebreaks(int cell)
2147 {
2148     int fvcell = FirstVirtualCell(cell);
2149
2150     if (column_info[column_of_cell(fvcell)].p_width.empty() &&
2151         !(IsMultiColumn(fvcell) && !cellinfo_of_cell(fvcell)->p_width.empty()))
2152         return false;
2153     return cellinfo_of_cell(fvcell)->linebreaks;
2154 }
2155
2156 void LyXTable::SetLTHead(int cell, bool first)
2157 {
2158     int row = row_of_cell(cell);
2159
2160     if (first) {
2161         if (row == endfirsthead)
2162             endfirsthead = -1;
2163         else
2164             endfirsthead = row;
2165     } else {
2166         if (row == endhead)
2167             endhead = -1;
2168         else
2169             endhead = row;
2170     }
2171 }
2172
2173 bool LyXTable::RowOfLTHead(int cell)
2174 {
2175     if ((endhead+1) > rows)
2176         endhead = -1;
2177     return (row_of_cell(cell) == endhead);
2178 }
2179
2180 bool LyXTable::RowOfLTFirstHead(int cell)
2181 {
2182     if ((endfirsthead+1) > rows)
2183         endfirsthead = -1;
2184     return (row_of_cell(cell) == endfirsthead);
2185 }
2186
2187 void LyXTable::SetLTFoot(int cell, bool last)
2188 {
2189     int row = row_of_cell(cell);
2190
2191     if (last) {
2192         if (row == endlastfoot)
2193             endlastfoot = -1;
2194         else
2195             endlastfoot = row;
2196     } else {
2197         if (row == endfoot)
2198             endfoot = -1;
2199         else
2200             endfoot = row;
2201     }
2202 }
2203
2204 bool LyXTable::RowOfLTFoot(int cell)
2205 {
2206     if ((endfoot+1) > rows) {
2207         endfoot = -1;
2208         return false;
2209     }
2210     return (row_of_cell(cell) == endfoot);
2211 }
2212
2213 bool LyXTable::RowOfLTLastFoot(int cell)
2214 {
2215     if ((endlastfoot+1) > rows)
2216         endlastfoot = -1;
2217     return (row_of_cell(cell) == endlastfoot);
2218 }
2219
2220 void LyXTable::SetLTNewPage(int cell, bool what)
2221 {
2222     row_info[row_of_cell(cell)].newpage = what;
2223 }
2224
2225 bool LyXTable::LTNewPage(int cell)
2226 {
2227     return row_info[row_of_cell(cell)].newpage;
2228 }