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