1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
8 * @author: Jürgen Vigna
10 * ======================================================
16 #pragma implementation
26 #include "lyx_gui_misc.h"
28 #include "BufferView.h"
30 #include "LaTeXFeatures.h"
31 #include "support/lstrings.h"
32 #include "support/lyxmanip.h"
33 #include "insets/insettabular.h"
34 #include "insets/insettext.h"
43 static int const WIDTH_OF_LINE = 5;
45 extern BufferView * current_view;
47 /// Define a few methods for the inner structs
49 LyXTabular::cellstruct::cellstruct()
53 multicolumn = LyXTabular::CELL_NORMAL;
54 alignment = LYX_ALIGN_CENTER;
55 valignment = LYX_VALIGN_TOP;
65 LyXTabular::rowstruct::rowstruct()
75 LyXTabular::columnstruct::columnstruct()
79 alignment = LYX_ALIGN_CENTER;
80 valignment = LYX_VALIGN_TOP;
86 LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
89 Init(rows_arg, columns_arg);
93 LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt)
96 Init(lt.rows_, lt.columns_);
102 LyXTabular::LyXTabular(Buffer const * buf, InsetTabular * inset, LyXLex & lex)
109 LyXTabular::~LyXTabular()
112 delete[] columnofcell;
116 LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
118 // If this and lt is not of the same size we have a serious bug
119 // So then it is ok to throw an exception, or for now
121 Assert(rows_ == lt.rows_ && columns_ == lt.columns_);
123 cell_info = lt.cell_info;
124 row_info = lt.row_info;
125 column_info = lt.column_info;
127 // long tabular stuff
128 SetLongTabular(lt.is_long_tabular);
129 endhead = lt.endhead;
130 endfoot = lt.endfoot;
131 endfirsthead = lt.endfirsthead;
132 endlastfoot = lt.endlastfoot;
142 LyXTabular * LyXTabular::Clone(InsetTabular * inset)
144 LyXTabular * result = new LyXTabular(inset, *this);
146 // don't know if this is good but I need to Clone also
147 // the text-insets here, this is for the Undo-facility!
150 for(i=0; i < rows_; ++i) {
151 for(j=0; j < columns_; ++j) {
152 result->cell_info[i][j].inset = cell_info[i][j].inset;
153 result->cell_info[i][j].inset.setOwner(inset);
160 /* activates all lines and sets all widths to 0 */
161 void LyXTabular::Init(int rows_arg, int columns_arg)
167 columns_ = columns_arg;
168 row_info = vector<rowstruct>(rows_, rowstruct());
169 column_info = vector<columnstruct>(columns_, columnstruct());
170 cell_info = vector<vector<cellstruct> >
171 (rows_, vector<cellstruct>(columns_, cellstruct()));
173 // Jürgen, use iterators.
174 for (i = 0; i < rows_; ++i) {
175 for (j = 0; j < columns_; ++j) {
176 cell_info[i][j].inset.setOwner(owner_);
177 cell_info[i][j].inset.SetDrawFrame(0, InsetText::LOCKED);
178 cell_info[i][j].cellno = cellno++;
181 row_info[i-1].bottom_line = true;
182 row_info[0].bottom_line = true;
184 for (i = 0; i < columns_; ++i) {
185 calculate_width_of_column(i);
187 column_info[columns_-1].right_line = true;
189 calculate_width_of_tabular();
193 set_row_column_number_info();
194 is_long_tabular = false;
203 void LyXTabular::AppendRow(int cell )
207 int row = row_of_cell(cell);
209 row_vector::iterator rit = row_info.begin() + row;
210 row_info.insert(rit, rowstruct());
213 cell_vvector::iterator cit = cell_info.begin() + row;
214 cell_info.insert(cit, vector<cellstruct>(columns_, cellstruct()));
216 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
219 for(int i = 0; i <= row; ++i) {
220 for(int j = 0; j < columns_; ++j) {
221 c_info[i][j] = cell_info[i][j];
224 for(int i = row+1; i < rows_; ++i) {
225 for(int j = 0; j < columns_; ++j) {
226 c_info[i][j] = cell_info[i-1][j];
231 for (int j = 0; j < columns_; ++j) {
232 cell_info[row][j].inset.clear();
239 void LyXTabular::DeleteRow(int row)
243 row_info.erase(row_info.begin() + row); //&row_info[row]);
244 cell_info.erase(cell_info.begin() + row); //&cell_info[row]);
250 void LyXTabular::AppendColumn(int cell)
254 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
256 int column = column_of_cell(cell);
258 column_vector::iterator cit = column_info.begin() + column + 1;
259 column_info.insert(cit, columnstruct());
261 for (i = 0; i < rows_; ++i) {
262 for (j = 0; j <= column; ++j) {
263 c_info[i][j] = cell_info[i][j];
265 for (j = column+1; j < columns_; ++j) {
266 c_info[i][j] = cell_info[i][j-1];
268 // care about multicolumns
269 if (cell_info[i][column+1].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
270 cell_info[i][column+1].multicolumn = CELL_PART_OF_MULTICOLUMN;
272 if (((column+1) == columns_) ||
273 (cell_info[i][column+2].multicolumn != CELL_PART_OF_MULTICOLUMN)) {
274 cell_info[i][column+1].multicolumn = LyXTabular::CELL_NORMAL;
279 for (i = 0; i < rows_; ++i) {
280 cell_info[i][column].inset.clear();
286 void LyXTabular::DeleteColumn(int column)
290 column_info.erase(column_info.begin() + column);
291 for (int i = 0; i < rows_; ++i) {
292 cell_info[i].erase(cell_info[i].begin() + column);
299 void LyXTabular::Reinit()
305 // Jürgen, use iterators.
306 for (; i < rows_; ++i) {
307 for (j = 0; j < columns_; ++j) {
308 cell_info[i][j].width_of_cell = 0;
309 cell_info[i][j].inset.setOwner(owner_);
313 for (i = 0; i < columns_; ++i) {
314 calculate_width_of_column(i);
316 calculate_width_of_tabular();
318 set_row_column_number_info();
322 void LyXTabular::set_row_column_number_info()
328 for (; row < rows_; ++row) {
329 for (column = 0; column<columns_; ++column) {
330 if (cell_info[row][column].multicolumn
331 != LyXTabular::CELL_PART_OF_MULTICOLUMN)
333 cell_info[row][column].cellno = numberofcells;
336 ++numberofcells; // because this is one more than as we start from 0
341 rowofcell = new int[numberofcells];
342 delete [] columnofcell;
343 columnofcell = new int[numberofcells];
345 while (c < numberofcells && row < rows_ && column < columns_) {
347 columnofcell[c] = column;
351 } while (column < columns_ &&
352 cell_info[row][column].multicolumn
353 == LyXTabular::CELL_PART_OF_MULTICOLUMN);
354 if (column == columns_) {
359 for (row = 0; row < rows_; ++row) {
360 for (column = 0; column<columns_; ++column) {
361 if (IsPartOfMultiColumn(row,column))
363 cell_info[row][column].inset.SetAutoBreakRows(
364 !GetPWidth(GetCellNumber(row, column)).empty());
370 int LyXTabular::GetNumberOfCells() const
372 return numberofcells;
376 int LyXTabular::NumberOfCellsInRow(int cell) const
378 int row = row_of_cell(cell);
380 for (int i = 0; i < columns_; ++i) {
381 if (cell_info[row][i].multicolumn != LyXTabular::CELL_PART_OF_MULTICOLUMN)
388 /* returns 1 if there is a topline, returns 0 if not */
389 bool LyXTabular::TopLine(int cell, bool onlycolumn) const
391 int row = row_of_cell(cell);
393 if (!onlycolumn && IsMultiColumn(cell))
394 return cellinfo_of_cell(cell)->top_line;
395 return row_info[row].top_line;
399 bool LyXTabular::BottomLine(int cell, bool onlycolumn) const
401 //no bottom line underneath non-existent cells if you please
402 if(cell >= numberofcells)
405 if (!onlycolumn && IsMultiColumn(cell))
406 return cellinfo_of_cell(cell)->bottom_line;
407 return row_info[row_of_cell(cell)].bottom_line;
411 bool LyXTabular::LeftLine(int cell, bool onlycolumn) const
413 if (!onlycolumn && IsMultiColumn(cell))
414 return cellinfo_of_cell(cell)->left_line;
415 return column_info[column_of_cell(cell)].left_line;
419 bool LyXTabular::RightLine(int cell, bool onlycolumn) const
421 if (!onlycolumn && IsMultiColumn(cell))
422 return cellinfo_of_cell(cell)->right_line;
423 return column_info[right_column_of_cell(cell)].right_line;
427 bool LyXTabular::TopAlreadyDrawed(int cell) const
429 if (GetAdditionalHeight(cell))
431 int row = row_of_cell(cell);
433 int column = column_of_cell(cell);
436 && cell_info[row][column].multicolumn
437 == LyXTabular::CELL_PART_OF_MULTICOLUMN)
439 if (cell_info[row][column].multicolumn == LyXTabular::CELL_NORMAL)
440 return row_info[row].bottom_line;
442 return cell_info[row][column].bottom_line;
448 bool LyXTabular::LeftAlreadyDrawed(int cell) const
450 int column = column_of_cell(cell);
452 int row = row_of_cell(cell);
454 (cell_info[row][column].multicolumn ==
455 LyXTabular::CELL_PART_OF_MULTICOLUMN));
456 if (GetAdditionalWidth(cell_info[row][column].cellno))
458 return column_info[column].right_line;
464 bool LyXTabular::IsLastRow(int cell) const
466 return (row_of_cell(cell) == rows_ - 1);
470 int LyXTabular::GetAdditionalHeight(int cell) const
472 int row = row_of_cell(cell);
475 int top = 1; // bool top = true; ??
476 int bottom = 1; // bool bottom = true; ??
479 for (column = 0; column < columns_ - 1 && bottom; ++column) {
480 switch (cell_info[row - 1][column].multicolumn) {
481 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
482 bottom = cell_info[row - 1][column].bottom_line;
484 case LyXTabular::CELL_NORMAL:
485 bottom = row_info[row - 1].bottom_line;
488 for (column = 0; column < columns_ - 1 && top; ++column) {
489 switch (cell_info[row][column].multicolumn){
490 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
491 top = cell_info[row][column].top_line;
493 case LyXTabular::CELL_NORMAL:
494 top = row_info[row].top_line;
498 return WIDTH_OF_LINE;
503 int LyXTabular::GetAdditionalWidth(int cell) const
505 // internally already set in SetWidthOfCell
506 // used to get it back in text.C
507 int col = right_column_of_cell(cell);
508 if (col < columns_ - 1 && column_info[col].right_line &&
509 column_info[col+1].left_line)
510 return WIDTH_OF_LINE;
516 // returns the maximum over all rows
517 int LyXTabular::GetWidthOfColumn(int cell) const
519 int column1 = column_of_cell(cell);
520 int column2 = right_column_of_cell(cell);
523 for (; i <= column2; ++i) {
524 result += column_info[i].width_of_column;
530 int LyXTabular::GetWidthOfTabular() const
532 return width_of_tabular;
536 /* returns 1 if a complete update is necessary, otherwise 0 */
537 bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width)
539 if (!IsMultiColumn(cell))
542 int row = row_of_cell(cell);
543 int column1 = column_of_cell(cell);
544 int column2 = right_column_of_cell(cell);
546 // first set columns to 0 so we can calculate the right width
548 for (; i <= column2; ++i) {
549 cell_info[row][i].width_of_cell = 0;
551 // set the width to MAX_WIDTH until width > 0
552 int width = (new_width + 2 * WIDTH_OF_LINE);
553 for (i = column1; (i < column2) && (width>column_info[i].width_of_column);
556 cell_info[row][i].width_of_cell = column_info[i].width_of_column;
557 width -= column_info[i].width_of_column;
560 cell_info[row][i].width_of_cell = width;
566 void LyXTabular::recalculateMulticolCells(int cell, int new_width)
568 int row = row_of_cell(cell);
569 int column1 = column_of_cell(cell);
570 int column2 = right_column_of_cell(cell);
572 // first set columns to 0 so we can calculate the right width
574 for (; i <= column2; ++i)
575 cell_info[row][i].width_of_cell = 0;
576 for(i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i)
578 if (i < numberofcells)
579 recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE));
580 SetWidthOfMulticolCell(cell, new_width);
584 /* returns 1 if a complete update is necessary, otherwise 0 */
585 bool LyXTabular::SetWidthOfCell(int cell, int new_width)
587 int row = row_of_cell(cell);
588 int column1 = column_of_cell(cell);
592 if (GetWidthOfCell(cell) == (new_width+2*WIDTH_OF_LINE))
594 if (IsMultiColumn(cell, true)) {
595 tmp = SetWidthOfMulticolCell(cell, new_width);
597 width = (new_width + 2*WIDTH_OF_LINE);
598 cell_info[row][column1].width_of_cell = width;
599 if (column_info[column1].right_line && (column1 < columns_-1) &&
600 column_info[column1+1].left_line) // additional width
601 cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
602 tmp = calculate_width_of_column_NMC(column1);
606 for(i = 0; i<columns_;++i)
607 calculate_width_of_column_NMC(i);
608 for(i = 0; (i<numberofcells) && !IsMultiColumn(i); ++i)
611 recalculateMulticolCells(i, GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
612 for(i = 0; i<columns_;++i)
613 calculate_width_of_column(i);
614 calculate_width_of_tabular();
621 bool LyXTabular::SetAlignment(int cell, char align, bool onlycolumn)
623 if (!IsMultiColumn(cell) || onlycolumn)
624 column_info[column_of_cell(cell)].alignment = align;
626 cellinfo_of_cell(cell)->alignment = align;
631 bool LyXTabular::SetVAlignment(int cell, char align, bool onlycolumn)
633 if (!IsMultiColumn(cell) || onlycolumn)
634 column_info[column_of_cell(cell)].valignment = align;
636 cellinfo_of_cell(cell)->valignment = align;
641 bool LyXTabular::SetColumnPWidth(int cell, string const & width)
643 bool flag = !width.empty();
645 int j = column_of_cell(cell);
647 column_info[j].p_width = width;
648 if (flag) // do this only if there is a width
649 SetAlignment(cell, LYX_ALIGN_LEFT);
650 for(int i=0; i < rows_; ++i) {
651 c = GetCellNumber(i, j);
652 flag = !GetPWidth(c).empty(); // because of multicolumns!
653 GetCellInset(c)->SetAutoBreakRows(flag);
659 bool LyXTabular::SetMColumnPWidth(int cell, string const & width)
661 bool flag = !width.empty();
663 cellinfo_of_cell(cell)->p_width = width;
664 if (IsMultiColumn(cell)) {
665 GetCellInset(cell)->SetAutoBreakRows(flag);
672 bool LyXTabular::SetAlignSpecial(int cell, string const & special, int what)
674 if (what == SET_SPECIAL_MULTI)
675 cellinfo_of_cell(cell)->align_special = special;
677 column_info[column_of_cell(cell)].align_special = special;
682 bool LyXTabular::SetAllLines(int cell, bool line)
684 SetTopLine(cell, line);
685 SetBottomLine(cell, line);
686 SetRightLine(cell, line);
687 SetLeftLine(cell, line);
692 bool LyXTabular::SetTopLine(int cell, bool line, bool onlycolumn)
694 int row = row_of_cell(cell);
696 if (onlycolumn || !IsMultiColumn(cell))
697 row_info[row].top_line = line;
699 cellinfo_of_cell(cell)->top_line = line;
704 bool LyXTabular::SetBottomLine(int cell, bool line, bool onlycolumn)
706 if (onlycolumn || !IsMultiColumn(cell))
707 row_info[row_of_cell(cell)].bottom_line = line;
709 cellinfo_of_cell(cell)->bottom_line = line;
714 bool LyXTabular::SetLeftLine(int cell, bool line, bool onlycolumn)
716 if (onlycolumn || !IsMultiColumn(cell))
717 column_info[column_of_cell(cell)].left_line = line;
719 cellinfo_of_cell(cell)->left_line = line;
724 bool LyXTabular::SetRightLine(int cell, bool line, bool onlycolumn)
726 if (onlycolumn || !IsMultiColumn(cell))
727 column_info[right_column_of_cell(cell)].right_line = line;
729 cellinfo_of_cell(cell)->right_line = line;
734 char LyXTabular::GetAlignment(int cell, bool onlycolumn) const
736 if (!onlycolumn && IsMultiColumn(cell))
737 return cellinfo_of_cell(cell)->alignment;
739 return column_info[column_of_cell(cell)].alignment;
743 char LyXTabular::GetVAlignment(int cell, bool onlycolumn) const
745 if (!onlycolumn && IsMultiColumn(cell))
746 return cellinfo_of_cell(cell)->valignment;
748 return column_info[column_of_cell(cell)].valignment;
752 string LyXTabular::GetPWidth(int cell) const
754 if (IsMultiColumn(cell))
755 return cellinfo_of_cell(cell)->p_width;
756 return column_info[column_of_cell(cell)].p_width;
760 string LyXTabular::GetColumnPWidth(int cell) const
762 return column_info[column_of_cell(cell)].p_width;
766 string LyXTabular::GetMColumnPWidth(int cell) const
768 if (IsMultiColumn(cell))
769 return cellinfo_of_cell(cell)->p_width;
774 string LyXTabular::GetAlignSpecial(int cell, int what) const
776 if (what == SET_SPECIAL_MULTI)
777 return cellinfo_of_cell(cell)->align_special;
778 return column_info[column_of_cell(cell)].align_special;
782 int LyXTabular::GetWidthOfCell(int cell) const
784 int row = row_of_cell(cell);
785 int column1 = column_of_cell(cell);
786 int column2 = right_column_of_cell(cell);
789 for (; i <= column2; ++i) {
790 result += cell_info[row][i].width_of_cell;
795 int LyXTabular::GetBeginningOfTextInCell(int cell) const
799 switch (GetAlignment(cell)){
800 case LYX_ALIGN_CENTER:
801 x += (GetWidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
803 case LYX_ALIGN_RIGHT:
804 x += GetWidthOfColumn(cell) - GetWidthOfCell(cell);
805 // + GetAdditionalWidth(cell);
807 default: /* LYX_ALIGN_LEFT: nothing :-) */
817 bool LyXTabular::IsFirstCellInRow(int cell) const
819 return (column_of_cell(cell) == 0);
823 int LyXTabular::GetFirstCellInRow(int row) const
827 return cell_info[row][0].cellno;
830 bool LyXTabular::IsLastCellInRow(int cell) const
832 return (right_column_of_cell(cell) == (columns_ - 1));
836 int LyXTabular::GetLastCellInRow(int row) const
840 return cell_info[row][columns_-1].cellno;
844 bool LyXTabular::calculate_width_of_column(int column)
846 int old_column_width = column_info[column].width_of_column;
849 for (int i = 0; i < rows_; ++i) {
850 maximum = max(cell_info[i][column].width_of_cell, maximum);
852 column_info[column].width_of_column = maximum;
853 return (column_info[column].width_of_column != old_column_width);
858 /// calculate the with of the column without regarding REAL MultiColumn
859 /// cells. This means MultiColumn-cells spanning more than 1 column.
861 bool LyXTabular::calculate_width_of_column_NMC(int column)
863 int old_column_width = column_info[column].width_of_column;
865 for (int i = 0; i < rows_; ++i) {
866 if (!IsMultiColumn(GetCellNumber(i, column), true) &&
867 (cell_info[i][column].width_of_cell > max)) {
868 max = cell_info[i][column].width_of_cell;
871 column_info[column].width_of_column = max;
872 return (column_info[column].width_of_column != old_column_width);
876 void LyXTabular::calculate_width_of_tabular()
878 width_of_tabular = 0;
879 for (int i = 0; i < columns_; ++i) {
880 width_of_tabular += column_info[i].width_of_column;
885 int LyXTabular::row_of_cell(int cell) const
887 if (cell >= numberofcells)
891 return rowofcell[cell];
895 int LyXTabular::column_of_cell(int cell) const
897 if (cell >= numberofcells)
901 return columnofcell[cell];
905 int LyXTabular::right_column_of_cell(int cell) const
907 int row = row_of_cell(cell);
908 int column = column_of_cell(cell);
909 while (column < (columns_ - 1) &&
910 cell_info[row][column+1].multicolumn == LyXTabular::CELL_PART_OF_MULTICOLUMN)
916 void LyXTabular::Write(Buffer const * buf, ostream & os) const
921 os << "<LyXTabular version=1 rows=" << rows_ << " columns=" << columns_ <<
923 // global longtable options
924 os << "<Features rotate=" << rotate <<
925 " islongtable=" << is_long_tabular <<
926 " endhead=" << endhead << " endfirsthead=" << endfirsthead <<
927 " endfoot=" << endfoot << " endlastfoot=" << endlastfoot <<
929 for (i = 0; i < rows_; ++i) {
930 os << "<Row topline=" << row_info[i].top_line <<
931 " bottomline=" << row_info[i].bottom_line <<
932 " newpage=" << row_info[i].newpage <<
934 for (j = 0; j < columns_; ++j) {
936 os << "<Column alignment=" << column_info[j].alignment <<
937 " valignment=" << column_info[j].valignment <<
938 " leftline=" << column_info[j].left_line <<
939 " rightline=" << column_info[j].right_line <<
940 " width=\"" << VSpace(column_info[j].p_width).asLyXCommand() <<
941 "\" special=\"" << column_info[j].align_special <<
944 os << "<Column>" << endl;
946 os << "<Cell multicolumn=" << cell_info[i][j].multicolumn <<
947 " alignment=" << cell_info[i][j].alignment <<
948 " valignment=" << cell_info[i][j].valignment <<
949 " topline=" << cell_info[i][j].top_line <<
950 " bottomline=" << cell_info[i][j].bottom_line <<
951 " leftline=" << cell_info[i][j].left_line <<
952 " rightline=" << cell_info[i][j].right_line <<
953 " rotate=" << cell_info[i][j].rotate <<
954 " usebox=" << (int)cell_info[i][j].usebox <<
955 " width=\"" << cell_info[i][j].p_width <<
956 "\" special=\"" << cell_info[i][j].align_special <<
958 os << "\\begin_inset ";
959 cell_info[i][j].inset.Write(buf, os);
960 os << "\n\\end_inset " << endl;
961 os << "</Cell>" << endl;
962 os << "</Column>" << endl;
964 os << "</Row>" << endl;
966 os << "</LyXTabular>" << endl;
971 bool getTokenValue(string const str, const char * token, string & ret)
973 int pos = str.find(token);
974 char ch = str[pos+strlen(token)];
976 if ((pos < 0) || (ch != '='))
979 pos += strlen(token)+1;
981 if ((ch != '"') && (ch != '\'')) { // only read till next space
985 while((pos < int(str.length()-1)) && (str[++pos] != ch))
993 bool getTokenValue(string const str, const char * token, int & num)
996 int pos = str.find(token);
997 char ch = str[pos+strlen(token)];
999 if ((pos < 0) || (ch != '='))
1002 pos += strlen(token)+1;
1004 if ((ch != '"') && (ch != '\'')) { // only read till next space
1010 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1013 num = strToInt(ret);
1019 bool getTokenValue(string const str, const char * token, bool & flag)
1022 int pos = str.find(token);
1023 char ch = str[pos+strlen(token)];
1025 if ((pos < 0) || (ch != '='))
1028 pos += strlen(token)+1;
1030 if ((ch != '"') && (ch != '\'')) { // only read till next space
1036 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1039 flag = strToInt(ret);
1044 void l_getline(istream & is, string & str)
1052 void LyXTabular::Read(Buffer const * buf, LyXLex & lex)
1055 istream & is = lex.getStream();
1057 l_getline(is, line);
1058 if (!prefixIs(line, "<LyXTabular ")) {
1059 OldFormatRead(lex, line);
1066 if (!getTokenValue(line, "version", version))
1068 if (!getTokenValue(line, "rows", rows_arg))
1070 if (!getTokenValue(line, "columns", columns_arg))
1072 Init(rows_arg, columns_arg);
1073 l_getline(is, line);
1074 if (!prefixIs(line, "<Features ")) {
1075 lyxerr << "Wrong tabular format (expected <Feture ...> got" <<
1076 line << ")" << endl;
1079 (void)getTokenValue(line, "islongtable", is_long_tabular);
1080 (void)getTokenValue(line, "endhead", endhead);
1081 (void)getTokenValue(line, "endfirsthead", endfirsthead);
1082 (void)getTokenValue(line, "endfoot", endfoot);
1083 (void)getTokenValue(line, "endlastfoot", endlastfoot);
1085 for(i = 0; i < rows_; ++i) {
1086 l_getline(is, line);
1087 if (!prefixIs(line, "<Row ")) {
1088 lyxerr << "Wrong tabular format (expected <Row ...> got" <<
1089 line << ")" << endl;
1092 (void)getTokenValue(line, "topline", row_info[i].top_line);
1093 (void)getTokenValue(line, "bottomline", row_info[i].bottom_line);
1094 (void)getTokenValue(line, "newpage", row_info[i].newpage);
1095 for (j = 0; j < columns_; ++j) {
1097 if (!prefixIs(line,"<Column")) {
1098 lyxerr << "Wrong tabular format (expected <Column ...> got" <<
1099 line << ")" << endl;
1103 (void)getTokenValue(line, "alignment", column_info[j].alignment);
1104 (void)getTokenValue(line, "valignment", column_info[j].valignment);
1105 (void)getTokenValue(line, "leftline", column_info[j].left_line);
1106 (void)getTokenValue(line, "rightline", column_info[j].right_line);
1107 (void)getTokenValue(line, "width", column_info[j].p_width);
1108 (void)getTokenValue(line, "special", column_info[j].align_special);
1110 l_getline(is, line);
1111 if (!prefixIs(line, "<Cell")) {
1112 lyxerr << "Wrong tabular format (expected <Cell ...> got" <<
1113 line << ")" << endl;
1116 (void)getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
1117 (void)getTokenValue(line, "alignment", cell_info[i][j].alignment);
1118 (void)getTokenValue(line, "valignment", cell_info[i][j].valignment);
1119 (void)getTokenValue(line, "topline", cell_info[i][j].top_line);
1120 (void)getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
1121 (void)getTokenValue(line, "leftline", cell_info[i][j].left_line);
1122 (void)getTokenValue(line, "rightline", cell_info[i][j].right_line);
1123 (void)getTokenValue(line, "rotate", cell_info[i][j].rotate);
1124 (void)getTokenValue(line, "usebox", cell_info[i][j].usebox);
1125 (void)getTokenValue(line, "width", cell_info[i][j].p_width);
1126 (void)getTokenValue(line, "special", cell_info[i][j].align_special);
1127 l_getline(is, line);
1128 if (prefixIs(line, "\\begin_inset")) {
1129 cell_info[i][j].inset.Read(buf, lex);
1130 l_getline(is, line);
1132 if (line != "</Cell>") {
1133 lyxerr << "Wrong tabular format (expected </Cell> got" <<
1134 line << ")" << endl;
1137 l_getline(is, line);
1138 if (line != "</Column>") {
1139 lyxerr << "Wrong tabular format (expected </Column> got" <<
1140 line << ")" << endl;
1144 l_getline(is, line);
1145 if (line != "</Row>") {
1146 lyxerr << "Wrong tabular format (expected </Row> got" <<
1147 line << ")" << endl;
1151 while (line != "</LyXTabular>") {
1152 l_getline(is, line);
1154 set_row_column_number_info();
1158 void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
1163 int columns_arg = 0;
1164 int is_long_tabular_arg = false;
1165 int rotate_arg = false;
1175 istream & is = lex.getStream();
1178 version = atoi(s.c_str() + 8);
1182 vector<int> cont_row_info;
1185 lyxerr << "Tabular format < 5 is not supported anymore\n"
1186 "Get an older version of LyX (< 1.1.x) for conversion!"
1188 WriteAlert(_("Warning:"),
1189 _("Tabular format < 5 is not supported anymore\n"),
1190 _("Get an older version of LyX (< 1.1.x) for conversion!"));
1192 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1193 >> rotate_arg >> a >> b >> c >> d;
1195 is >> rows_arg >> columns_arg;
1196 Init(rows_arg, columns_arg);
1197 cont_row_info = vector<int>(rows_arg);
1198 SetLongTabular(is_long_tabular_arg);
1199 SetRotateTabular(rotate_arg);
1201 for (i = 0; i < rows_; ++i) {
1203 cont_row_info[i] = false;
1205 for (i = 0; i < columns_; ++i) {
1208 for (i = 0; i < rows_; ++i) {
1209 for (j = 0; j < columns_; ++j) {
1214 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1215 >> rotate_arg >> a >> b >> c >> d;
1216 Init(rows_arg, columns_arg);
1217 cont_row_info = vector<int>(rows_arg);
1218 SetLongTabular(is_long_tabular_arg);
1219 SetRotateTabular(rotate_arg);
1224 for (i = 0; i < rows_; ++i) {
1225 a = b = c = d = e = f = g = h = 0;
1226 is >> a >> b >> c >> d;
1227 row_info[i].top_line = a;
1228 row_info[i].bottom_line = b;
1229 cont_row_info[i] = c;
1230 row_info[i].newpage = d;
1232 for (i = 0; i < columns_; ++i) {
1236 char ch; // skip '"'
1238 getline(is, s1, '"');
1239 is >> ch; // skip '"'
1240 getline(is, s2, '"');
1241 column_info[i].alignment = static_cast<char>(a);
1242 column_info[i].left_line = b;
1243 column_info[i].right_line = c;
1244 column_info[i].p_width = s1;
1245 column_info[i].align_special = s2;
1247 for (i = 0; i < rows_; ++i) {
1248 for (j = 0; j < columns_; ++j) {
1251 is >> a >> b >> c >> d >> e >> f >> g;
1253 is >> ch; // skip '"'
1254 getline(is, s1, '"');
1255 is >> ch; // skip '"'
1256 getline(is, s2, '"');
1257 cell_info[i][j].multicolumn = static_cast<char>(a);
1258 cell_info[i][j].alignment = static_cast<char>(b);
1259 cell_info[i][j].top_line = static_cast<char>(c);
1260 cell_info[i][j].bottom_line = static_cast<char>(d);
1261 cell_info[i][j].rotate = static_cast<bool>(f);
1262 cell_info[i][j].usebox = static_cast<bool>(g);
1263 cell_info[i][j].align_special = s1;
1264 cell_info[i][j].p_width = s2;
1268 set_row_column_number_info();
1270 LyXParagraph * par = new LyXParagraph;
1271 LyXParagraph * return_par = 0;
1273 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
1274 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
1276 string token, tmptok;
1279 LyXFont font(LyXFont::ALL_SANE);
1281 while (lex.IsOK()) {
1283 token = lex.GetString();
1286 if ((token == "\\layout") || (token == "\\end_float") ||
1287 (token == "\\end_deeper"))
1289 lex.pushToken(token);
1292 if (owner_->BufferOwner()->parseSingleLyXformat2Token(lex, par,
1304 lex.pushToken(token);
1308 lex.printError("New Paragraph allocated! This should not happen!");
1309 lex.pushToken(token);
1315 // now we have the par we should fill the insets with this!
1317 InsetText * inset = GetCellInset(cell);
1320 for(int i = 0; i < par->Last(); ++i) {
1321 if (par->IsNewline(i)) {
1323 if (cell > GetNumberOfCells()) {
1324 lyxerr << "Some error in reading old table format occured!" <<
1325 endl << "Terminating when reading cell[" << cell << "]!" <<
1329 row = row_of_cell(cell);
1330 if (cont_row_info[row]) {
1332 cont_row_info.erase(cont_row_info.begin() + row); //&cont_row_info[row]);
1333 while(!IsFirstCellInRow(--cell));
1335 inset = GetCellInset(cell);
1338 inset = GetCellInset(cell);
1339 row = row_of_cell(cell);
1340 if (!cell_info[row_of_cell(cell)][column_of_cell(cell)].usebox)
1342 // insert a space instead
1344 par->InsertChar(i, ' ');
1347 par->CopyIntoMinibuffer(current_view->buffer()->params, i);
1348 inset->par->InsertFromMinibuffer(inset->par->Last());
1354 char const * LyXTabular::GetDocBookAlign(int cell, bool isColumn) const
1356 int i = isColumn ? cell : column_of_cell(cell);
1361 //i = column_of_cell(cell);
1362 if (!isColumn && IsMultiColumn(cell)) {
1363 if (!cellinfo_of_cell(cell)->align_special.empty()) {
1364 return cellinfo_of_cell(cell)->align_special.c_str();
1366 switch (GetAlignment(cell)) {
1367 case LYX_ALIGN_LEFT:
1369 case LYX_ALIGN_RIGHT:
1376 if (!column_info[i].align_special.empty()) {
1377 return column_info[i].align_special.c_str();
1379 #ifdef IGNORE_THIS_FOR_NOW
1380 else if (!column_info[i].p_width.empty()) {
1382 file += column_info[i].p_width;
1387 switch (column_info[i].alignment) {
1388 case LYX_ALIGN_LEFT:
1390 case LYX_ALIGN_RIGHT:
1400 // cell <0 will tex the preamble
1401 // returns the number of printed newlines
1402 int LyXTabular::DocBookEndOfCell(ostream & os, int cell, int & depth) const
1406 //int tmp; // tmp2; // unused
1407 int nvcell; // fcell; // unused
1408 if (IsLastCell(cell)) {
1409 os << newlineAndDepth(--depth)
1411 << newlineAndDepth(--depth)
1413 << newlineAndDepth(--depth)
1415 << newlineAndDepth(--depth);
1416 if (is_long_tabular)
1420 << newlineAndDepth(--depth);
1426 if (is_long_tabular)
1432 << "' COLSEP='1' ROWSEP='1'>"
1433 << newlineAndDepth(++depth);
1435 for (i = 0; i < columns_; ++i) {
1436 os << "<COLSPEC ALIGN='"
1437 << GetDocBookAlign(i, true)
1443 if (i == (columns_-1)) {
1446 if (column_info[i].right_line ||
1447 column_info[i+1].left_line)
1453 << newlineAndDepth(depth);
1455 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1456 if (column_info[i].left_line)
1461 << newlineAndDepth(++depth)
1463 << newlineAndDepth(++depth)
1465 << GetDocBookAlign(0)
1467 if (IsMultiColumn(0)) {
1468 os << " NAMEST='col1' NAMEEND='col"
1469 << cells_in_multicolumn(0)
1473 << newlineAndDepth(++depth);
1476 if (IsLastCellInRow(cell)) {
1477 os << newlineAndDepth(--depth)
1479 << newlineAndDepth(--depth)
1481 << newlineAndDepth(depth)
1483 << newlineAndDepth(++depth)
1485 << GetDocBookAlign(cell + 1)
1486 << "' VALIGN='middle'";
1487 if (IsMultiColumn(cell + 1)) {
1488 os << " NAMEST='col"
1489 << column_of_cell(cell+1) + 1
1491 << column_of_cell(cell + 1) +
1492 cells_in_multicolumn(cell + 1)
1496 << newlineAndDepth(++depth);
1499 os << newlineAndDepth(--depth)
1501 << newlineAndDepth(depth)
1503 << GetDocBookAlign(cell + 1)
1504 << "' VALIGN='middle'";
1505 if (IsMultiColumn(cell + 1)) {
1506 os << " NAMEST='col"
1507 << column_of_cell(cell+1) + 1
1509 << column_of_cell(cell+1) +
1510 cells_in_multicolumn(cell+1)
1514 << newlineAndDepth(++depth);
1523 bool LyXTabular::IsMultiColumn(int cell, bool real) const
1525 return ((!real || (column_of_cell(cell) != right_column_of_cell(cell))) &&
1526 (cellinfo_of_cell(cell)->multicolumn !=LyXTabular::CELL_NORMAL));
1530 LyXTabular::cellstruct * LyXTabular::cellinfo_of_cell(int cell) const
1532 int row = row_of_cell(cell);
1533 int column = column_of_cell(cell);
1534 return &cell_info[row][column];
1538 void LyXTabular::SetMultiColumn(int cell, int number)
1540 cellinfo_of_cell(cell)->multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
1541 cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
1542 cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
1543 cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
1544 for (number--; number > 0; --number) {
1545 cellinfo_of_cell(cell+number)->multicolumn = CELL_PART_OF_MULTICOLUMN;
1547 set_row_column_number_info();
1551 int LyXTabular::cells_in_multicolumn(int cell) const
1553 int row = row_of_cell(cell);
1554 int column = column_of_cell(cell);
1557 while ((column < columns_) &&
1558 cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN)
1567 int LyXTabular::UnsetMultiColumn(int cell)
1569 int row = row_of_cell(cell);
1570 int column = column_of_cell(cell);
1574 if (cell_info[row][column].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
1575 cell_info[row][column].multicolumn = CELL_NORMAL;
1577 while ((column < columns_) &&
1578 (cell_info[row][column].multicolumn ==CELL_PART_OF_MULTICOLUMN))
1580 cell_info[row][column].multicolumn = CELL_NORMAL;
1585 set_row_column_number_info();
1590 void LyXTabular::SetLongTabular(int what)
1592 is_long_tabular = what;
1596 bool LyXTabular::IsLongTabular() const
1598 return is_long_tabular;
1602 void LyXTabular::SetRotateTabular(bool flag)
1608 bool LyXTabular::GetRotateTabular() const
1614 void LyXTabular::SetRotateCell(int cell, bool flag)
1616 cellinfo_of_cell(cell)->rotate = flag;
1620 bool LyXTabular::GetRotateCell(int cell) const
1622 return cellinfo_of_cell(cell)->rotate;
1626 bool LyXTabular::NeedRotating() const
1630 for (int i = 0; i < rows_; ++i) {
1631 for (int j = 0; j < columns_; ++j) {
1632 if (cell_info[i][j].rotate)
1640 bool LyXTabular::IsLastCell(int cell) const
1642 if ((cell+1) < GetNumberOfCells())
1648 int LyXTabular::GetCellAbove(int cell) const
1650 if (row_of_cell(cell) > 0)
1651 return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
1656 int LyXTabular::GetCellBelow(int cell) const
1658 if (row_of_cell(cell)+1 < rows_)
1659 return cell_info[row_of_cell(cell)+1][column_of_cell(cell)].cellno;
1664 int LyXTabular::GetLastCellAbove(int cell) const
1666 if (row_of_cell(cell) <= 0)
1668 if (!IsMultiColumn(cell))
1669 return GetCellAbove(cell);
1670 return cell_info[row_of_cell(cell)-1][right_column_of_cell(cell)].cellno;
1674 int LyXTabular::GetLastCellBelow(int cell) const
1676 if (row_of_cell(cell)+1 >= rows_)
1678 if (!IsMultiColumn(cell))
1679 return GetCellBelow(cell);
1680 return cell_info[row_of_cell(cell)+1][right_column_of_cell(cell)].cellno;
1684 int LyXTabular::GetCellNumber(int row, int column) const
1686 if (column >= columns_)
1687 column = columns_ - 1;
1688 else if (column < 0)
1695 return cell_info[row][column].cellno;
1699 void LyXTabular::SetUsebox(int cell, BoxType type)
1701 cellinfo_of_cell(cell)->usebox = type;
1705 int LyXTabular::GetUsebox(int cell) const
1707 if (column_info[column_of_cell(cell)].p_width.empty() &&
1708 !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty()))
1710 if (cellinfo_of_cell(cell)->usebox > 1)
1711 return cellinfo_of_cell(cell)->usebox;
1712 return UseParbox(cell);
1716 void LyXTabular::SetLTHead(int cell, bool first)
1718 int row = row_of_cell(cell);
1719 int val = (row+1) * (column_of_cell(cell)? 1:-1);
1722 if (endfirsthead == val)
1735 bool LyXTabular::GetRowOfLTHead(int cell, int & row) const
1738 if (abs(endhead) > rows_)
1740 return (row_of_cell(cell) == (abs(endhead)-1));
1744 bool LyXTabular::GetRowOfLTFirstHead(int cell, int & row) const
1747 if (abs(endfirsthead) > rows_)
1749 return (row_of_cell(cell) == (abs(endfirsthead)-1));
1753 void LyXTabular::SetLTFoot(int cell, bool last)
1755 int row = row_of_cell(cell);
1756 int val = (row + 1) * (column_of_cell(cell)? 1:-1);
1759 if (endlastfoot == val)
1772 bool LyXTabular::GetRowOfLTFoot(int cell, int & row) const
1775 if ((endfoot+1) > rows_)
1777 return (row_of_cell(cell) == (abs(endfoot)-1));
1780 bool LyXTabular::GetRowOfLTLastFoot(int cell, int & row) const
1783 if (abs(endlastfoot) > rows_)
1785 return (row_of_cell(cell) == (abs(endlastfoot)-1));
1789 void LyXTabular::SetLTNewPage(int cell, bool what)
1791 row_info[row_of_cell(cell)].newpage = what;
1795 bool LyXTabular::GetLTNewPage(int cell) const
1797 return row_info[row_of_cell(cell)].newpage;
1801 bool LyXTabular::SetAscentOfRow(int row, int height)
1803 if ((row >= rows_) || (row_info[row].ascent_of_row == height))
1805 row_info[row].ascent_of_row = height;
1810 bool LyXTabular::SetDescentOfRow(int row, int height)
1812 if ((row >= rows_) || (row_info[row].descent_of_row == height))
1814 row_info[row].descent_of_row = height;
1819 int LyXTabular::GetAscentOfRow(int row) const
1823 return row_info[row].ascent_of_row;
1827 int LyXTabular::GetDescentOfRow(int row) const
1831 return row_info[row].descent_of_row;
1835 int LyXTabular::GetHeightOfTabular() const
1839 for(int row = 0; row < rows_; ++row)
1840 height += GetAscentOfRow(row) + GetDescentOfRow(row) +
1841 GetAdditionalHeight(GetCellNumber(row, 0));
1846 bool LyXTabular::IsPartOfMultiColumn(int row, int column) const
1848 if ((row >= rows_) || (column >= columns_))
1850 return (cell_info[row][column].multicolumn==CELL_PART_OF_MULTICOLUMN);
1854 int LyXTabular::TeXTopHLine(ostream & os, int row) const
1856 int fcell = GetFirstCellInRow(row);
1857 int n = NumberOfCellsInRow(fcell) + fcell;
1861 for (i = fcell; i < n; ++i) {
1865 if (tmp == (n - fcell)){
1868 for (i = fcell; i < n; ++i) {
1871 << column_of_cell(i) + 1
1873 << right_column_of_cell(i) + 1
1886 int LyXTabular::TeXBottomHLine(ostream & os, int row) const
1888 int fcell = GetFirstCellInRow(row);
1889 int n = NumberOfCellsInRow(fcell) + fcell;
1893 for (i = fcell; i < n; ++i) {
1897 if (tmp == (n-fcell)){
1900 for (i = fcell; i < n; ++i) {
1901 if (BottomLine(i)) {
1903 << column_of_cell(i) + 1
1905 << right_column_of_cell(i) + 1
1918 int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
1922 if (GetRotateCell(cell)) {
1923 os << "\\begin{sideways}" << endl;
1926 if (IsMultiColumn(cell)) {
1927 os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
1928 if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1929 os << cellinfo_of_cell(cell+1)->align_special << "}{";
1933 if (!GetPWidth(cell).empty()) {
1934 switch(GetVAlignment(cell)) {
1935 case LYX_VALIGN_TOP:
1938 case LYX_VALIGN_CENTER:
1941 case LYX_VALIGN_BOTTOM:
1945 os << "{" << GetPWidth(cell) << '}';
1947 switch (GetAlignment(cell)) {
1948 case LYX_ALIGN_LEFT:
1951 case LYX_ALIGN_RIGHT:
1959 if (RightLine(cell))
1961 if (((cell + 1) < numberofcells) && !IsFirstCellInRow(cell+1) &&
1967 if (GetUsebox(cell) == BOX_PARBOX) {
1969 switch(GetVAlignment(cell)) {
1970 case LYX_VALIGN_TOP:
1973 case LYX_VALIGN_CENTER:
1976 case LYX_VALIGN_BOTTOM:
1980 os << "]{" << GetPWidth(cell) << "}{";
1981 } else if (GetUsebox(cell) == BOX_MINIPAGE) {
1982 os << "\\begin{minipage}[";
1983 switch(GetVAlignment(cell)) {
1984 case LYX_VALIGN_TOP:
1987 case LYX_VALIGN_CENTER:
1990 case LYX_VALIGN_BOTTOM:
1994 os << "]{" << GetPWidth(cell) << "}\n";
2001 int LyXTabular::TeXCellPostamble(ostream & os, int cell) const
2006 if (GetUsebox(cell) == BOX_PARBOX)
2008 else if (GetUsebox(cell) == BOX_MINIPAGE) {
2009 os << "%\n\\end{minipage}";
2012 if (IsMultiColumn(cell)){
2015 if (GetRotateCell(cell)) {
2016 os << "%\n\\end{sideways}";
2023 int LyXTabular::Latex(Buffer const * buf, ostream & os, bool fragile, bool fp) const
2029 //+---------------------------------------------------------------------
2030 //+ first the opening preamble +
2031 //+---------------------------------------------------------------------
2034 os << "\\begin{sideways}" << endl;
2037 if (is_long_tabular)
2038 os << "\\begin{longtable}{";
2040 os << "\\begin{tabular}{";
2041 for (i = 0; i < columns_; ++i) {
2042 if (column_info[i].left_line)
2044 if (!column_info[i].align_special.empty()) {
2045 os << column_info[i].align_special;
2046 } else if (!column_info[i].p_width.empty()) {
2047 switch(column_info[i].valignment) {
2048 case LYX_VALIGN_TOP:
2051 case LYX_VALIGN_CENTER:
2054 case LYX_VALIGN_BOTTOM:
2059 << column_info[i].p_width
2062 switch (column_info[i].alignment) {
2063 case LYX_ALIGN_LEFT:
2066 case LYX_ALIGN_RIGHT:
2074 if (column_info[i].right_line)
2080 //+---------------------------------------------------------------------
2081 //+ the single row and columns (cells) +
2082 //+---------------------------------------------------------------------
2085 for(i=0; i < rows_; ++i) {
2086 ret += TeXTopHLine(os, i);
2088 if (IsLongTabular()) {
2089 if ((endhead < 0) && (i == (abs(endhead)-1))) {
2090 os << "\\endhead\n";
2093 if ((endfirsthead < 0) && (i == (abs(endfirsthead)-1))) {
2094 os << "\\endfirsthead\n";
2097 if ((endfoot < 0) && (i == (abs(endfoot)-1))) {
2098 os << "\\endfoot\n";
2101 if ((endlastfoot < 0) && (i == (abs(endlastfoot)-1))) {
2102 os << "\\endlastfoot\n";
2108 ret += TeXBottomHLine(os, i-1);
2109 ret += TeXTopHLine(os, i);
2111 for(j=0; j < columns_; ++j) {
2112 if (IsPartOfMultiColumn(i,j))
2114 ret += TeXCellPreamble(os, cell);
2115 ret += GetCellInset(cell)->Latex(buf, os, fragile, fp);
2116 ret += TeXCellPostamble(os, cell);
2117 if (!IsLastCellInRow(cell)) { // not last cell in row
2123 os << "\\\\" << endl;
2124 ret += TeXBottomHLine(os, i);
2126 if (IsLongTabular()) {
2127 if ((endhead > 0) && (i == (endhead-1))) {
2128 os << "\\endhead\n";
2131 if ((endfirsthead > 0) && (i == (endfirsthead-1))) {
2132 os << "\\endfirsthead\n";
2135 if ((endfoot > 0) && (i == (endfoot-1))) {
2136 os << "\\endfoot\n";
2139 if ((endlastfoot > 0) && (i == (endlastfoot-1))) {
2140 os << "\\endlastfoot\n";
2144 ret += TeXBottomHLine(os, i);
2145 if (row_info[i].newpage) {
2146 os << "\\newpage\n";
2152 //+---------------------------------------------------------------------
2153 //+ the closing of the tabular +
2154 //+---------------------------------------------------------------------
2156 if (is_long_tabular)
2157 os << "\\end{longtable}";
2159 os << "\\end{tabular}";
2161 os << "\n\\end{sideways}";
2169 InsetText * LyXTabular::GetCellInset(int cell) const
2171 return & cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;
2174 void LyXTabular::Validate(LaTeXFeatures & features) const
2176 if (IsLongTabular())
2177 features.longtable = true;
2179 features.rotating = true;
2180 for(int cell = 0; cell < numberofcells; ++cell) {
2181 if (GetVAlignment(cell) != LYX_VALIGN_TOP)
2182 features.array = true;
2183 GetCellInset(cell)->Validate(features);
2188 bool LyXTabular::UseParbox(int cell) const
2190 LyXParagraph *par = GetCellInset(cell)->par;
2192 for(;par; par = par->next) {
2193 for(int i = 0; i < par->Last(); ++i) {
2194 if (par->GetChar(i) == LyXParagraph::META_NEWLINE)