1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
8 * ======================================================
17 #pragma implementation
24 #include "lyx_gui_misc.h"
26 #include "BufferView.h"
28 #include "LaTeXFeatures.h"
29 #include "support/lstrings.h"
30 #include "support/lyxmanip.h"
31 #include "insets/insettabular.h"
32 #include "insets/insettext.h"
41 static int const WIDTH_OF_LINE = 5;
43 extern BufferView * current_view;
45 /// Define a few methods for the inner structs
47 LyXTabular::cellstruct::cellstruct()
49 cellno = 0; //should be initilaized correctly later.
51 multicolumn = LyXTabular::CELL_NORMAL;
52 alignment = LYX_ALIGN_CENTER;
61 LyXTabular::cellstruct::~cellstruct()
67 LyXTabular::cellstruct::cellstruct(cellstruct const & cs)
70 width_of_cell = cs.width_of_cell;
71 multicolumn = cs.multicolumn;
72 alignment = cs.alignment;
73 top_line = cs.top_line;
74 bottom_line = cs.bottom_line;
76 linebreaks = cs.linebreaks;
79 // inset = static_cast<InsetText *>(cs.inset->Clone());
83 LyXTabular::cellstruct &
84 LyXTabular::cellstruct::operator=(cellstruct const & cs)
87 width_of_cell = cs.width_of_cell;
88 multicolumn = cs.multicolumn;
89 alignment = cs.alignment;
90 top_line = cs.top_line;
91 bottom_line = cs.bottom_line;
93 linebreaks = cs.linebreaks;
95 inset = static_cast<InsetText *>(cs.inset->Clone());
100 LyXTabular::rowstruct::rowstruct()
110 LyXTabular::columnstruct::columnstruct()
114 alignment = LYX_ALIGN_CENTER;
120 LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
123 Init(rows_arg, columns_arg);
127 LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt)
130 Init(lt.rows_, lt.columns_);
136 LyXTabular::LyXTabular(InsetTabular * inset, LyXLex & lex)
143 LyXTabular::~LyXTabular()
146 delete[] columnofcell;
150 LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
152 // If this and lt is not of the same size we have a serious bug
153 // So then it is ok to throw an exception, or for now
155 Assert(rows_ == lt.rows_ && columns_ == lt.columns_);
157 cell_info = lt.cell_info;
158 row_info = lt.row_info;
159 column_info = lt.column_info;
161 // long tabular stuff
162 SetLongTabular(lt.is_long_tabular);
163 endhead = lt.endhead;
164 endfoot = lt.endfoot;
165 endfirsthead = lt.endfirsthead;
166 endlastfoot = lt.endlastfoot;
176 LyXTabular * LyXTabular::Clone(InsetTabular * inset)
178 LyXTabular * result = new LyXTabular(inset, *this);
180 // don't know if this is good but I need to Clone also
181 // the text-insets here, this is for the Undo-facility!
184 for(i=0; i < rows_; ++i) {
185 for(j=0; j < columns_; ++j) {
186 delete result->cell_info[i][j].inset;
187 result->cell_info[i][j].inset=new InsetText(*cell_info[i][j].inset,
188 inset->BufferOwner());
189 result->cell_info[i][j].inset->setOwner(inset);
196 /* activates all lines and sets all widths to 0 */
197 void LyXTabular::Init(int rows_arg, int columns_arg)
203 columns_ = columns_arg;
204 row_info = vector<rowstruct>(rows_, rowstruct());
205 column_info = vector<columnstruct>(columns_, columnstruct());
206 cell_info = vector<vector<cellstruct> >
207 (rows_, vector<cellstruct>(columns_, cellstruct()));
209 // Jürgen, use iterators.
210 for (i = 0; i < rows_; ++i) {
211 for (j = 0; j < columns_; ++j) {
212 if (!cell_info[i][j].inset)
213 cell_info[i][j].inset = new InsetText(owner_->BufferOwner());
214 cell_info[i][j].inset->setOwner(owner_);
215 cell_info[i][j].inset->SetDrawLockedFrame(true);
216 cell_info[i][j].cellno = cellno++;
219 row_info[i-1].bottom_line = true;
220 row_info[0].bottom_line = true;
222 for (i = 0; i < columns_; ++i) {
223 calculate_width_of_column(i);
225 column_info[columns_-1].right_line = true;
227 calculate_width_of_tabular();
231 set_row_column_number_info();
232 is_long_tabular = false;
241 void LyXTabular::AppendRow(int cell )
243 // cell_vector::iterator cit = cell_info.begin() + row;
244 // cell_info.insert(cit, vector<cellstruct>(columns_, cellstruct()));
245 // cell_info.insert(cell_info.begin(), vector<cellstruct>(columns_, cellstruct()));
249 // row_vector r_info = row_vector(rows_, rowstruct());
251 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
253 int row = row_of_cell(cell);
256 row_vector::iterator rit = row_info.begin() + row;
257 row_info.insert(rit, rowstruct());
259 for(i = 0; i <= row; ++i) {
260 // r_info[i] = row_info[i];
261 for(int j = 0; j < columns_; ++j) {
262 c_info[i][j] = cell_info[i][j];
265 for(i = row+1; i < rows_; ++i) {
266 // r_info[i] = row_info[i-1];
267 for(int j = 0; j < columns_; ++j) {
268 c_info[i][j] = cell_info[i-1][j];
271 // row_info = r_info;
273 for(i = 0; i < rows_; ++i) {
274 for(int j = 0; j < columns_; ++j) {
275 cell_info[i][j].inset = static_cast<InsetText *>(c_info[i][j].inset->Clone());
279 for (int j = 0; j < columns_; ++j) {
280 cell_info[row][j].inset->clear();
286 void LyXTabular::DeleteRow(int row)
290 row_info.erase(row_info.begin() + row); //&row_info[row]);
291 cell_info.erase(cell_info.begin() + row); //&cell_info[row]);
297 void LyXTabular::AppendColumn(int cell)
301 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
303 int column = column_of_cell(cell);
305 column_vector::iterator cit = column_info.begin() + column;
306 column_info.insert(cit, columnstruct());
308 for (i = 0; i < rows_; ++i) {
309 for (j = 0; j <= column; ++j) {
310 c_info[i][j] = cell_info[i][j];
312 for (j = column+1; j < columns_; ++j) {
313 c_info[i][j] = cell_info[i][j-1];
315 // care about multicolumns
316 if (cell_info[i][column+1].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
317 cell_info[i][column+1].multicolumn = CELL_PART_OF_MULTICOLUMN;
319 if (((column+1) == columns_) ||
320 (cell_info[i][column+2].multicolumn != CELL_PART_OF_MULTICOLUMN)) {
321 cell_info[i][column+1].multicolumn = LyXTabular::CELL_NORMAL;
325 for(i = 0; i < rows_; ++i) {
326 for(j = 0; j < columns_; ++j) {
327 cell_info[i][j].inset = static_cast<InsetText *>(c_info[i][j].inset->Clone());
331 for (i = 0; i < rows_; ++i) {
332 cell_info[i][column].inset->clear();
338 void LyXTabular::DeleteColumn(int column)
342 column_info.erase(column_info.begin() + column);
343 for (int i = 0; i < rows_; ++i) {
344 cell_info[i].erase(cell_info[i].begin() + column);
351 void LyXTabular::Reinit()
357 // Jürgen, use iterators.
358 for (; i < rows_; ++i) {
359 for (j = 0; j < columns_; ++j) {
360 cell_info[i][j].width_of_cell = 0;
364 for (i = 0; i < columns_; ++i) {
365 calculate_width_of_column(i);
367 calculate_width_of_tabular();
369 set_row_column_number_info();
373 void LyXTabular::set_row_column_number_info()
379 for (; row < rows_; ++row) {
380 for (column = 0; column<columns_; ++column) {
381 if (cell_info[row][column].multicolumn
382 != LyXTabular::CELL_PART_OF_MULTICOLUMN)
384 cell_info[row][column].cellno = numberofcells;
387 ++numberofcells; // because this is one more than as we start from 0
392 rowofcell = new int[numberofcells];
393 delete [] columnofcell;
394 columnofcell = new int[numberofcells];
396 while (c < numberofcells && row < rows_ && column < columns_) {
398 columnofcell[c] = column;
402 } while (column < columns_ &&
403 cell_info[row][column].multicolumn
404 == LyXTabular::CELL_PART_OF_MULTICOLUMN);
405 if (column == columns_) {
410 for (row = 0; row < rows_; ++row) {
411 for (column = 0; column<columns_; ++column) {
412 if (IsPartOfMultiColumn(row,column))
414 cell_info[row][column].inset->SetAutoBreakRows(
415 !GetPWidth(GetCellNumber(row, column)).empty());
421 int LyXTabular::GetNumberOfCells() const
423 return numberofcells;
427 int LyXTabular::NumberOfCellsInRow(int cell) const
429 int row = row_of_cell(cell);
431 for (int i = 0; i < columns_; ++i) {
432 if (cell_info[row][i].multicolumn != LyXTabular::CELL_PART_OF_MULTICOLUMN)
439 /* returns 1 if there is a topline, returns 0 if not */
440 bool LyXTabular::TopLine(int cell) const
442 int row = row_of_cell(cell);
444 if (IsMultiColumn(cell))
445 return cellinfo_of_cell(cell)->top_line;
446 return row_info[row].top_line;
450 bool LyXTabular::BottomLine(int cell) const
452 //no bottom line underneath non-existent cells if you please
453 if(cell >= numberofcells)
456 if (IsMultiColumn(cell))
457 return cellinfo_of_cell(cell)->bottom_line;
458 return row_info[row_of_cell(cell)].bottom_line;
462 bool LyXTabular::LeftLine(int cell) const
464 return column_info[column_of_cell(cell)].left_line;
468 bool LyXTabular::RightLine(int cell) const
470 return column_info[right_column_of_cell(cell)].right_line;
474 bool LyXTabular::TopAlreadyDrawed(int cell) const
476 if (GetAdditionalHeight(cell))
478 int row = row_of_cell(cell);
480 int column = column_of_cell(cell);
483 && cell_info[row][column].multicolumn
484 == LyXTabular::CELL_PART_OF_MULTICOLUMN)
486 if (cell_info[row][column].multicolumn == LyXTabular::CELL_NORMAL)
487 return row_info[row].bottom_line;
489 return cell_info[row][column].bottom_line;
495 bool LyXTabular::LeftAlreadyDrawed(int cell) const
497 int column = column_of_cell(cell);
499 int row = row_of_cell(cell);
501 (cell_info[row][column].multicolumn ==
502 LyXTabular::CELL_PART_OF_MULTICOLUMN));
503 if (GetAdditionalWidth(cell_info[row][column].cellno))
505 return column_info[column].right_line;
511 bool LyXTabular::IsLastRow(int cell) const
513 return (row_of_cell(cell) == rows_ - 1);
517 int LyXTabular::GetAdditionalHeight(int cell) const
519 int row = row_of_cell(cell);
522 int top = 1; // bool top = true; ??
523 int bottom = 1; // bool bottom = true; ??
526 for (column = 0; column < columns_ - 1 && bottom; ++column) {
527 switch (cell_info[row - 1][column].multicolumn) {
528 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
529 bottom = cell_info[row - 1][column].bottom_line;
531 case LyXTabular::CELL_NORMAL:
532 bottom = row_info[row - 1].bottom_line;
535 for (column = 0; column < columns_ - 1 && top; ++column) {
536 switch (cell_info[row][column].multicolumn){
537 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
538 top = cell_info[row][column].top_line;
540 case LyXTabular::CELL_NORMAL:
541 top = row_info[row].top_line;
545 return WIDTH_OF_LINE;
550 int LyXTabular::GetAdditionalWidth(int cell) const
552 // internally already set in SetWidthOfCell
553 // used to get it back in text.C
554 int col = right_column_of_cell(cell);
555 if (col < columns_ - 1 && column_info[col].right_line &&
556 column_info[col+1].left_line)
557 return WIDTH_OF_LINE;
563 // returns the maximum over all rows
564 int LyXTabular::GetWidthOfColumn(int cell) const
566 int column1 = column_of_cell(cell);
567 int column2 = right_column_of_cell(cell);
570 for (; i <= column2; ++i) {
571 result += column_info[i].width_of_column;
577 int LyXTabular::GetWidthOfTabular() const
579 return width_of_tabular;
583 /* returns 1 if a complete update is necessary, otherwise 0 */
584 bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width)
586 if (!IsMultiColumn(cell))
589 int row = row_of_cell(cell);
590 int column1 = column_of_cell(cell);
591 int column2 = right_column_of_cell(cell);
593 // first set columns to 0 so we can calculate the right width
595 for (; i <= column2; ++i) {
596 cell_info[row][i].width_of_cell = 0;
598 // set the width to MAX_WIDTH until width > 0
599 int width = (new_width + 2 * WIDTH_OF_LINE);
600 for (i = column1; (i < column2) && (width > 0); ++i) {
601 cell_info[row][i].width_of_cell = column_info[i].width_of_column;
602 width -= column_info[i].width_of_column;
605 cell_info[row][i].width_of_cell = width;
611 void LyXTabular::recalculateMulticolCells(int cell, int new_width)
613 int row = row_of_cell(cell);
614 int column1 = column_of_cell(cell);
615 int column2 = right_column_of_cell(cell);
617 // first set columns to 0 so we can calculate the right width
619 for (; i <= column2; ++i)
620 cell_info[row][i].width_of_cell = 0;
621 for(i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i)
623 if (i < numberofcells)
624 recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE));
625 SetWidthOfMulticolCell(cell, new_width);
629 /* returns 1 if a complete update is necessary, otherwise 0 */
630 bool LyXTabular::SetWidthOfCell(int cell, int new_width)
632 int row = row_of_cell(cell);
633 int column1 = column_of_cell(cell);
637 if (IsMultiColumn(cell)) {
638 tmp = SetWidthOfMulticolCell(cell, new_width);
640 width = (new_width + 2*WIDTH_OF_LINE);
641 cell_info[row][column1].width_of_cell = width;
642 if (column_info[column1].right_line && (column1 < columns_-1) &&
643 column_info[column1+1].left_line) // additional width
644 cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
645 tmp = calculate_width_of_column_NMC(column1);
649 for(i = 0; i<columns_;++i)
650 calculate_width_of_column_NMC(i);
651 for(i = 0; (i<numberofcells) && !IsMultiColumn(i); ++i)
654 recalculateMulticolCells(i, GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
655 for(i = 0; i<columns_;++i)
656 calculate_width_of_column(i);
657 calculate_width_of_tabular();
664 bool LyXTabular::SetAlignment(int cell, char align)
666 if (!IsMultiColumn(cell))
667 column_info[column_of_cell(cell)].alignment = align;
668 cellinfo_of_cell(cell)->alignment = align;
673 bool LyXTabular::SetPWidth(int cell, string const & width)
675 bool flag = !width.empty();
677 if (IsMultiColumn(cell)) {
678 cellinfo_of_cell(cell)->p_width = width;
679 GetCellInset(cell)->SetAutoBreakRows(flag);
681 int j = column_of_cell(cell);
683 column_info[j].p_width = width;
684 if (flag) // do this only if there is a width
685 SetAlignment(cell, LYX_ALIGN_LEFT);
686 for(int i=0; i < rows_; ++i) {
687 c = GetCellNumber(i, j);
688 flag = !GetPWidth(c).empty(); // because of multicolumns!
689 GetCellInset(c)->SetAutoBreakRows(flag);
696 bool LyXTabular::SetAlignSpecial(int cell, string const & special, int what)
698 if (what == SET_SPECIAL_MULTI)
699 cellinfo_of_cell(cell)->align_special = special;
701 column_info[column_of_cell(cell)].align_special = special;
706 bool LyXTabular::SetAllLines(int cell, bool line)
708 SetTopLine(cell, line);
709 SetBottomLine(cell, line);
710 SetRightLine(cell, line);
711 SetLeftLine(cell, line);
716 bool LyXTabular::SetTopLine(int cell, bool line)
718 int row = row_of_cell(cell);
720 if (!IsMultiColumn(cell))
721 row_info[row].top_line = line;
723 cellinfo_of_cell(cell)->top_line = line;
728 bool LyXTabular::SetBottomLine(int cell, bool line)
730 if (!IsMultiColumn(cell))
731 row_info[row_of_cell(cell)].bottom_line = line;
733 cellinfo_of_cell(cell)->bottom_line = line;
738 bool LyXTabular::SetLeftLine(int cell, bool line)
740 column_info[column_of_cell(cell)].left_line = line;
745 bool LyXTabular::SetRightLine(int cell, bool line)
747 column_info[right_column_of_cell(cell)].right_line = line;
752 char LyXTabular::GetAlignment(int cell) const
754 if (IsMultiColumn(cell))
755 return cellinfo_of_cell(cell)->alignment;
757 return column_info[column_of_cell(cell)].alignment;
761 string LyXTabular::GetPWidth(int cell) const
763 if (IsMultiColumn(cell))
764 return cellinfo_of_cell(cell)->p_width;
765 return column_info[column_of_cell(cell)].p_width;
769 string LyXTabular::GetAlignSpecial(int cell, int what) const
771 if (what == SET_SPECIAL_MULTI)
772 return cellinfo_of_cell(cell)->align_special;
773 return column_info[column_of_cell(cell)].align_special;
777 int LyXTabular::GetWidthOfCell(int cell) const
779 int row = row_of_cell(cell);
780 int column1 = column_of_cell(cell);
781 int column2 = right_column_of_cell(cell);
784 for (; i <= column2; ++i) {
785 result += cell_info[row][i].width_of_cell;
788 // result += GetAdditionalWidth(cell);
793 int LyXTabular::GetBeginningOfTextInCell(int cell) const
797 switch (GetAlignment(cell)){
798 case LYX_ALIGN_CENTER:
799 x += (GetWidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
801 case LYX_ALIGN_RIGHT:
802 x += GetWidthOfColumn(cell) - GetWidthOfCell(cell);
803 // + GetAdditionalWidth(cell);
805 default: /* LYX_ALIGN_LEFT: nothing :-) */
815 bool LyXTabular::IsFirstCellInRow(int cell) const
817 return (column_of_cell(cell) == 0);
821 int LyXTabular::GetFirstCellInRow(int row) const
825 return cell_info[row][0].cellno;
828 bool LyXTabular::IsLastCellInRow(int cell) const
830 return (right_column_of_cell(cell) == (columns_ - 1));
834 int LyXTabular::GetLastCellInRow(int row) const
838 return cell_info[row][columns_-1].cellno;
842 bool LyXTabular::calculate_width_of_column(int column)
844 int old_column_width = column_info[column].width_of_column;
847 for (int i = 0; i < rows_; ++i) {
848 maximum = max(cell_info[i][column].width_of_cell, maximum);
850 column_info[column].width_of_column = maximum;
851 return (column_info[column].width_of_column != old_column_width);
855 bool LyXTabular::calculate_width_of_column_NMC(int column)
857 int old_column_width = column_info[column].width_of_column;
859 for (int i = 0; i < rows_; ++i) {
860 if (!IsMultiColumn(GetCellNumber(i, column)) &&
861 (cell_info[i][column].width_of_cell > max)) {
862 max = cell_info[i][column].width_of_cell;
865 column_info[column].width_of_column = max;
866 return (column_info[column].width_of_column != old_column_width);
870 void LyXTabular::calculate_width_of_tabular()
872 width_of_tabular = 0;
873 for (int i = 0; i < columns_; ++i) {
874 width_of_tabular += column_info[i].width_of_column;
879 int LyXTabular::row_of_cell(int cell) const
881 if (cell >= numberofcells)
885 return rowofcell[cell];
889 int LyXTabular::column_of_cell(int cell) const
891 if (cell >= numberofcells)
895 return columnofcell[cell];
899 int LyXTabular::right_column_of_cell(int cell) const
901 int row = row_of_cell(cell);
902 int column = column_of_cell(cell);
903 while (column < (columns_ - 1) &&
904 cell_info[row][column+1].multicolumn == LyXTabular::CELL_PART_OF_MULTICOLUMN)
910 void LyXTabular::Write(ostream & os) const
915 os << "<LyXTabular version=1 rows=" << rows_ << " columns=" << columns_ <<
917 // global longtable options
918 os << "<Features rotate=" << rotate <<
919 " islongtable=" << is_long_tabular <<
920 " endhead=" << endhead << " endfirsthead=" << endfirsthead <<
921 " endfoot=" << endfoot << " endlastfoot=" << endlastfoot <<
923 for (i = 0; i < rows_; ++i) {
924 os << "<Row topline=" << row_info[i].top_line <<
925 " bottomline=" << row_info[i].bottom_line <<
926 " newpage=" << row_info[i].newpage <<
928 for (j = 0; j < columns_; ++j) {
930 os << "<Column alignment=" << column_info[j].alignment <<
931 " leftline=" << column_info[j].left_line <<
932 " rightline=" << column_info[j].right_line <<
933 " width=\"" << VSpace(column_info[j].p_width).asLyXCommand() <<
934 "\" special=\"" << column_info[j].align_special <<
937 os << "<Column>" << endl;
939 os << "<Cell multicolumn=" << cell_info[i][j].multicolumn <<
940 " alignment=" << cell_info[i][j].alignment <<
941 " topline=" << cell_info[i][j].top_line <<
942 " bottomline=" << cell_info[i][j].bottom_line <<
943 " rotate=" << cell_info[i][j].rotate <<
944 " linebreaks=" << cell_info[i][j].linebreaks <<
945 " width=\"" << cell_info[i][j].p_width <<
946 "\" special=\"" << cell_info[i][j].align_special <<
948 os << "\\begin_inset ";
949 cell_info[i][j].inset->Write(os);
950 os << "\n\\end_inset " << endl;
951 os << "</Cell>" << endl;
952 os << "</Column>" << endl;
954 os << "</Row>" << endl;
956 os << "</LyXTabular>" << endl;
961 bool getTokenValue(string const str, const char * token, string & ret)
963 int pos = str.find(token);
964 char ch = str[pos+strlen(token)];
966 if ((pos < 0) || (ch != '='))
969 pos += strlen(token)+1;
971 if ((ch != '"') && (ch != '\'')) { // only read till next space
975 while((pos < int(str.length()-1)) && (str[++pos] != ch))
983 bool getTokenValue(string const str, const char * token, int & num)
986 int pos = str.find(token);
987 char ch = str[pos+strlen(token)];
989 if ((pos < 0) || (ch != '='))
992 pos += strlen(token)+1;
994 if ((ch != '"') && (ch != '\'')) { // only read till next space
1000 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1003 num = strToInt(ret);
1009 bool getTokenValue(string const str, const char * token, bool & flag)
1012 int pos = str.find(token);
1013 char ch = str[pos+strlen(token)];
1015 if ((pos < 0) || (ch != '='))
1018 pos += strlen(token)+1;
1020 if ((ch != '"') && (ch != '\'')) { // only read till next space
1026 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1029 flag = strToInt(ret);
1034 void l_getline(istream & is, string & str)
1042 void LyXTabular::Read(LyXLex & lex)
1045 istream & is = lex.getStream();
1047 l_getline(is, line);
1048 if (!prefixIs(line, "<LyXTabular ")) {
1049 OldFormatRead(lex, line);
1056 if (!getTokenValue(line, "version", version))
1058 if (!getTokenValue(line, "rows", rows_arg))
1060 if (!getTokenValue(line, "columns", columns_arg))
1062 Init(rows_arg, columns_arg);
1063 l_getline(is, line);
1064 if (!prefixIs(line, "<Features ")) {
1065 lyxerr << "Wrong tabular format (expected <Feture ...> got" <<
1066 line << ")" << endl;
1069 (void)getTokenValue(line, "islongtable", is_long_tabular);
1070 (void)getTokenValue(line, "endhead", endhead);
1071 (void)getTokenValue(line, "endfirsthead", endfirsthead);
1072 (void)getTokenValue(line, "endfoot", endfoot);
1073 (void)getTokenValue(line, "endlastfoot", endlastfoot);
1075 for(i = 0; i < rows_; ++i) {
1076 l_getline(is, line);
1077 if (!prefixIs(line, "<Row ")) {
1078 lyxerr << "Wrong tabular format (expected <Row ...> got" <<
1079 line << ")" << endl;
1082 (void)getTokenValue(line, "topline", row_info[i].top_line);
1083 (void)getTokenValue(line, "bottomline", row_info[i].bottom_line);
1084 (void)getTokenValue(line, "newpage", row_info[i].newpage);
1085 for (j = 0; j < columns_; ++j) {
1087 if (!prefixIs(line,"<Column")) {
1088 lyxerr << "Wrong tabular format (expected <Column ...> got" <<
1089 line << ")" << endl;
1093 (void)getTokenValue(line, "alignment", column_info[j].alignment);
1094 (void)getTokenValue(line, "leftline", column_info[j].left_line);
1095 (void)getTokenValue(line, "rightline", column_info[j].right_line);
1096 (void)getTokenValue(line, "width", column_info[j].p_width);
1097 (void)getTokenValue(line, "special", column_info[j].align_special);
1099 l_getline(is, line);
1100 if (!prefixIs(line, "<Cell")) {
1101 lyxerr << "Wrong tabular format (expected <Cell ...> got" <<
1102 line << ")" << endl;
1105 (void)getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
1106 (void)getTokenValue(line, "alignment", cell_info[i][j].alignment);
1107 (void)getTokenValue(line, "topline", cell_info[i][j].top_line);
1108 (void)getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
1109 (void)getTokenValue(line, "rotate", cell_info[i][j].rotate);
1110 (void)getTokenValue(line, "linebreaks", cell_info[i][j].linebreaks);
1111 (void)getTokenValue(line, "width", cell_info[i][j].p_width);
1112 (void)getTokenValue(line, "special", cell_info[i][j].align_special);
1113 l_getline(is, line);
1114 if (prefixIs(line, "\\begin_inset")) {
1115 cell_info[i][j].inset->Read(lex);
1116 l_getline(is, line);
1118 if (line != "</Cell>") {
1119 lyxerr << "Wrong tabular format (expected </Cell> got" <<
1120 line << ")" << endl;
1123 l_getline(is, line);
1124 if (line != "</Column>") {
1125 lyxerr << "Wrong tabular format (expected </Column> got" <<
1126 line << ")" << endl;
1130 l_getline(is, line);
1131 if (line != "</Row>") {
1132 lyxerr << "Wrong tabular format (expected </Row> got" <<
1133 line << ")" << endl;
1137 while (line != "</LyXTabular>") {
1138 l_getline(is, line);
1140 set_row_column_number_info();
1144 void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
1149 int columns_arg = 0;
1150 int is_long_tabular_arg = false;
1151 int rotate_arg = false;
1161 istream & is = lex.getStream();
1164 version = atoi(s.c_str() + 8);
1168 vector<int> cont_row_info;
1171 lyxerr << "Tabular format < 5 is not supported anymore\n"
1172 "Get an older version of LyX (< 1.1.x) for conversion!"
1174 WriteAlert(_("Warning:"),
1175 _("Tabular format < 5 is not supported anymore\n"),
1176 _("Get an older version of LyX (< 1.1.x) for conversion!"));
1178 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1179 >> rotate_arg >> a >> b >> c >> d;
1181 is >> rows_arg >> columns_arg;
1182 Init(rows_arg, columns_arg);
1183 cont_row_info = vector<int>(rows_arg);
1184 SetLongTabular(is_long_tabular_arg);
1185 SetRotateTabular(rotate_arg);
1187 for (i = 0; i < rows_; ++i) {
1189 cont_row_info[i] = false;
1191 for (i = 0; i < columns_; ++i) {
1194 for (i = 0; i < rows_; ++i) {
1195 for (j = 0; j < columns_; ++j) {
1200 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1201 >> rotate_arg >> a >> b >> c >> d;
1202 Init(rows_arg, columns_arg);
1203 cont_row_info = vector<int>(rows_arg);
1204 SetLongTabular(is_long_tabular_arg);
1205 SetRotateTabular(rotate_arg);
1210 for (i = 0; i < rows_; ++i) {
1211 a = b = c = d = e = f = g = h = 0;
1212 is >> a >> b >> c >> d;
1213 row_info[i].top_line = a;
1214 row_info[i].bottom_line = b;
1215 cont_row_info[i] = c;
1216 row_info[i].newpage = d;
1218 for (i = 0; i < columns_; ++i) {
1222 char ch; // skip '"'
1224 getline(is, s1, '"');
1225 is >> ch; // skip '"'
1226 getline(is, s2, '"');
1227 column_info[i].alignment = static_cast<char>(a);
1228 column_info[i].left_line = b;
1229 column_info[i].right_line = c;
1230 column_info[i].p_width = s1;
1231 column_info[i].align_special = s2;
1233 for (i = 0; i < rows_; ++i) {
1234 for (j = 0; j < columns_; ++j) {
1237 is >> a >> b >> c >> d >> e >> f >> g;
1239 is >> ch; // skip '"'
1240 getline(is, s1, '"');
1241 is >> ch; // skip '"'
1242 getline(is, s2, '"');
1243 cell_info[i][j].multicolumn = static_cast<char>(a);
1244 cell_info[i][j].alignment = static_cast<char>(b);
1245 cell_info[i][j].top_line = static_cast<char>(c);
1246 cell_info[i][j].bottom_line = static_cast<char>(d);
1247 cell_info[i][j].rotate = static_cast<bool>(f);
1248 cell_info[i][j].linebreaks = static_cast<bool>(g);
1249 cell_info[i][j].align_special = s1;
1250 cell_info[i][j].p_width = s2;
1254 set_row_column_number_info();
1256 LyXParagraph * par = new LyXParagraph;
1257 LyXParagraph * return_par = 0;
1258 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
1259 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
1260 string token, tmptok;
1263 LyXFont font(LyXFont::ALL_SANE);
1265 while (lex.IsOK()) {
1267 token = lex.GetString();
1270 if ((token == "\\layout") || (token == "\\end_float") ||
1271 (token == "\\end_deeper"))
1273 lex.pushToken(token);
1276 if (owner_->BufferOwner()->parseSingleLyXformat2Token(lex, par,
1284 lex.pushToken(token);
1288 lex.printError("New Paragraph allocated! This should not happen!");
1289 lex.pushToken(token);
1295 // now we have the par we should fill the insets with this!
1297 InsetText * inset = GetCellInset(cell);
1300 for(int i = 0; i < par->Last(); ++i) {
1301 if (par->IsNewline(i)) {
1303 if (cell > GetNumberOfCells()) {
1304 lyxerr << "Some error in reading old table format occured!" <<
1305 endl << "Terminating when reading cell[" << cell << "]!" <<
1309 row = row_of_cell(cell);
1310 if (cont_row_info[row]) {
1312 cont_row_info.erase(cont_row_info.begin() + row); //&cont_row_info[row]);
1313 while(!IsFirstCellInRow(--cell));
1315 inset = GetCellInset(cell);
1318 inset = GetCellInset(cell);
1319 row = row_of_cell(cell);
1320 if (!cell_info[row_of_cell(cell)][column_of_cell(cell)].linebreaks)
1322 // insert a space instead
1324 par->InsertChar(i, ' ');
1327 par->CopyIntoMinibuffer(current_view->buffer()->params, i);
1328 inset->par->InsertFromMinibuffer(inset->par->Last());
1334 char const * LyXTabular::GetDocBookAlign(int cell, bool isColumn) const
1336 int i = isColumn ? cell : column_of_cell(cell);
1341 //i = column_of_cell(cell);
1342 if (!isColumn && IsMultiColumn(cell)) {
1343 if (!cellinfo_of_cell(cell)->align_special.empty()) {
1344 return cellinfo_of_cell(cell)->align_special.c_str();
1346 switch (GetAlignment(cell)) {
1347 case LYX_ALIGN_LEFT:
1349 case LYX_ALIGN_RIGHT:
1356 if (!column_info[i].align_special.empty()) {
1357 return column_info[i].align_special.c_str();
1359 #ifdef IGNORE_THIS_FOR_NOW
1360 else if (!column_info[i].p_width.empty()) {
1362 file += column_info[i].p_width;
1367 switch (column_info[i].alignment) {
1368 case LYX_ALIGN_LEFT:
1370 case LYX_ALIGN_RIGHT:
1380 // cell <0 will tex the preamble
1381 // returns the number of printed newlines
1382 int LyXTabular::DocBookEndOfCell(ostream & os, int cell, int & depth) const
1386 //int tmp; // tmp2; // unused
1387 int nvcell; // fcell; // unused
1388 if (IsLastCell(cell)) {
1389 os << newlineAndDepth(--depth)
1391 << newlineAndDepth(--depth)
1393 << newlineAndDepth(--depth)
1395 << newlineAndDepth(--depth);
1396 if (is_long_tabular)
1400 << newlineAndDepth(--depth);
1406 if (is_long_tabular)
1412 << "' COLSEP='1' ROWSEP='1'>"
1413 << newlineAndDepth(++depth);
1415 for (i = 0; i < columns_; ++i) {
1416 os << "<COLSPEC ALIGN='"
1417 << GetDocBookAlign(i, true)
1423 if (i == (columns_-1)) {
1426 if (column_info[i].right_line ||
1427 column_info[i+1].left_line)
1433 << newlineAndDepth(depth);
1435 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1436 if (column_info[i].left_line)
1441 << newlineAndDepth(++depth)
1443 << newlineAndDepth(++depth)
1445 << GetDocBookAlign(0)
1447 if (IsMultiColumn(0)) {
1448 os << " NAMEST='col1' NAMEEND='col"
1449 << cells_in_multicolumn(0)
1453 << newlineAndDepth(++depth);
1456 if (IsLastCellInRow(cell)) {
1457 os << newlineAndDepth(--depth)
1459 << newlineAndDepth(--depth)
1461 << newlineAndDepth(depth)
1463 << newlineAndDepth(++depth)
1465 << GetDocBookAlign(cell + 1)
1466 << "' VALIGN='middle'";
1467 if (IsMultiColumn(cell + 1)) {
1468 os << " NAMEST='col"
1469 << column_of_cell(cell+1) + 1
1471 << column_of_cell(cell + 1) +
1472 cells_in_multicolumn(cell + 1)
1476 << newlineAndDepth(++depth);
1479 os << newlineAndDepth(--depth)
1481 << newlineAndDepth(depth)
1483 << GetDocBookAlign(cell + 1)
1484 << "' VALIGN='middle'";
1485 if (IsMultiColumn(cell + 1)) {
1486 os << " NAMEST='col"
1487 << column_of_cell(cell+1) + 1
1489 << column_of_cell(cell+1) +
1490 cells_in_multicolumn(cell+1)
1494 << newlineAndDepth(++depth);
1503 bool LyXTabular::IsMultiColumn(int cell) const
1505 return (cellinfo_of_cell(cell)->multicolumn != LyXTabular::CELL_NORMAL);
1509 LyXTabular::cellstruct * LyXTabular::cellinfo_of_cell(int cell) const
1511 int row = row_of_cell(cell);
1512 int column = column_of_cell(cell);
1513 return &cell_info[row][column];
1517 void LyXTabular::SetMultiColumn(int cell, int number)
1519 cellinfo_of_cell(cell)->multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
1520 cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
1521 cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
1522 cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
1523 for (number--; number > 0; --number) {
1524 cellinfo_of_cell(cell+number)->multicolumn = CELL_PART_OF_MULTICOLUMN;
1526 set_row_column_number_info();
1530 int LyXTabular::cells_in_multicolumn(int cell) const
1532 int row = row_of_cell(cell);
1533 int column = column_of_cell(cell);
1536 while ((column < columns_) &&
1537 cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN)
1546 int LyXTabular::UnsetMultiColumn(int cell)
1548 int row = row_of_cell(cell);
1549 int column = column_of_cell(cell);
1553 if (cell_info[row][column].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
1554 cell_info[row][column].multicolumn = CELL_NORMAL;
1556 while ((column < columns_) &&
1557 (cell_info[row][column].multicolumn ==CELL_PART_OF_MULTICOLUMN))
1559 cell_info[row][column].multicolumn = CELL_NORMAL;
1564 set_row_column_number_info();
1569 void LyXTabular::SetLongTabular(int what)
1571 is_long_tabular = what;
1575 bool LyXTabular::IsLongTabular() const
1577 return is_long_tabular;
1581 void LyXTabular::SetRotateTabular(int what)
1587 bool LyXTabular::GetRotateTabular() const
1593 void LyXTabular::SetRotateCell(int cell, int what)
1595 cellinfo_of_cell(cell)->rotate = what;
1599 bool LyXTabular::GetRotateCell(int cell) const
1601 return cellinfo_of_cell(cell)->rotate;
1605 bool LyXTabular::NeedRotating() const
1609 for (int i = 0; i < rows_; ++i) {
1610 for (int j = 0; j < columns_; ++j) {
1611 if (cell_info[i][j].rotate)
1619 bool LyXTabular::IsLastCell(int cell) const
1621 if ((cell+1) < GetNumberOfCells())
1627 int LyXTabular::GetCellAbove(int cell) const
1629 if (row_of_cell(cell) > 0)
1630 return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
1635 int LyXTabular::GetCellBelow(int cell) const
1637 if (row_of_cell(cell)+1 < rows_)
1638 return cell_info[row_of_cell(cell)+1][column_of_cell(cell)].cellno;
1643 int LyXTabular::GetLastCellAbove(int cell) const
1645 if (row_of_cell(cell) <= 0)
1647 if (!IsMultiColumn(cell))
1648 return GetCellAbove(cell);
1649 return cell_info[row_of_cell(cell)-1][right_column_of_cell(cell)].cellno;
1653 int LyXTabular::GetLastCellBelow(int cell) const
1655 if (row_of_cell(cell)+1 >= rows_)
1657 if (!IsMultiColumn(cell))
1658 return GetCellBelow(cell);
1659 return cell_info[row_of_cell(cell)+1][right_column_of_cell(cell)].cellno;
1663 int LyXTabular::GetCellNumber(int row, int column) const
1665 if (column >= columns_)
1666 column = columns_ - 1;
1667 else if (column < 0)
1674 return cell_info[row][column].cellno;
1678 void LyXTabular::SetLinebreaks(int cell, bool what)
1680 cellinfo_of_cell(cell)->linebreaks = what;
1684 bool LyXTabular::GetLinebreaks(int cell) const
1686 if (column_info[column_of_cell(cell)].p_width.empty() &&
1687 !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty()))
1689 return cellinfo_of_cell(cell)->linebreaks;
1693 void LyXTabular::SetLTHead(int cell, bool first)
1695 int row = row_of_cell(cell);
1698 if (row == endfirsthead)
1711 bool LyXTabular::GetRowOfLTHead(int cell) const
1713 if ((endhead+1) > rows_)
1715 return (row_of_cell(cell) == endhead);
1719 bool LyXTabular::GetRowOfLTFirstHead(int cell) const
1721 if ((endfirsthead+1) > rows_)
1723 return (row_of_cell(cell) == endfirsthead);
1727 void LyXTabular::SetLTFoot(int cell, bool last)
1729 int row = row_of_cell(cell);
1732 if (row == endlastfoot)
1745 bool LyXTabular::GetRowOfLTFoot(int cell) const
1747 if ((endfoot+1) > rows_)
1749 return (row_of_cell(cell) == endfoot);
1752 bool LyXTabular::GetRowOfLTLastFoot(int cell) const
1754 if ((endlastfoot+1) > rows_)
1756 return (row_of_cell(cell) == endlastfoot);
1760 void LyXTabular::SetLTNewPage(int cell, bool what)
1762 row_info[row_of_cell(cell)].newpage = what;
1766 bool LyXTabular::GetLTNewPage(int cell) const
1768 return row_info[row_of_cell(cell)].newpage;
1772 void LyXTabular::SetAscentOfRow(int row, int height)
1776 row_info[row].ascent_of_row = height;
1780 void LyXTabular::SetDescentOfRow(int row, int height)
1784 row_info[row].descent_of_row = height;
1788 int LyXTabular::GetAscentOfRow(int row) const
1792 return row_info[row].ascent_of_row;
1796 int LyXTabular::GetDescentOfRow(int row) const
1800 return row_info[row].descent_of_row;
1804 int LyXTabular::GetHeightOfTabular() const
1808 for(int row = 0; row < rows_; ++row)
1809 height += GetAscentOfRow(row) + GetDescentOfRow(row) +
1810 GetAdditionalHeight(GetCellNumber(row, 0));
1815 bool LyXTabular::IsPartOfMultiColumn(int row, int column) const
1817 if ((row >= rows_) || (column >= columns_))
1819 return (cell_info[row][column].multicolumn==CELL_PART_OF_MULTICOLUMN);
1823 int LyXTabular::TeXTopHLine(ostream & os, int row) const
1825 int fcell = GetFirstCellInRow(row);
1826 int n = NumberOfCellsInRow(fcell) + fcell;
1830 for (i = fcell; i < n; ++i) {
1834 if (tmp == (n - fcell)){
1837 for (i = fcell; i < n; ++i) {
1840 << column_of_cell(i) + 1
1842 << right_column_of_cell(i) + 1
1855 int LyXTabular::TeXBottomHLine(ostream & os, int row) const
1857 int fcell = GetFirstCellInRow(row);
1858 int n = NumberOfCellsInRow(fcell) + fcell;
1862 for (i = fcell; i < n; ++i) {
1866 if (tmp == (n-fcell)){
1869 for (i = fcell; i < n; ++i) {
1870 if (BottomLine(i)) {
1872 << column_of_cell(i) + 1
1874 << right_column_of_cell(i) + 1
1887 int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
1891 if (GetRotateCell(cell)) {
1892 os << "\\begin{sideways}" << endl;
1895 if (IsMultiColumn(cell)) {
1896 os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
1897 if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1898 os << cellinfo_of_cell(cell+1)->align_special << "}{";
1902 if (!GetPWidth(cell).empty()) {
1903 os << "p{" << GetPWidth(cell) << '}';
1905 switch (GetAlignment(cell)) {
1906 case LYX_ALIGN_LEFT:
1909 case LYX_ALIGN_RIGHT:
1917 if (RightLine(cell))
1919 if (((cell + 1) < numberofcells) && !IsFirstCellInRow(cell+1) &&
1925 if (GetLinebreaks(cell)) {
1926 os << "\\parbox[t]{" << GetPWidth(cell) << "}{\\smallskip{}";
1932 int LyXTabular::TeXCellPostamble(ostream & os, int cell) const
1937 if (GetLinebreaks(cell))
1938 os << "\\smallskip{}}";
1939 if (IsMultiColumn(cell)){
1942 if (GetRotateCell(cell)) {
1943 os << endl << "\\end{sideways}";
1950 int LyXTabular::Latex(ostream & os, bool fragile, bool fp) const
1956 //+---------------------------------------------------------------------
1957 //+ first the opening preamble +
1958 //+---------------------------------------------------------------------
1961 os << "\\begin{sideways}" << endl;
1964 if (is_long_tabular)
1965 os << "\\begin{longtable}{";
1967 os << "\\begin{tabular}{";
1968 for (i = 0; i < columns_; ++i) {
1969 if (column_info[i].left_line)
1971 if (!column_info[i].align_special.empty()) {
1972 os << column_info[i].align_special;
1973 } else if (!column_info[i].p_width.empty()) {
1975 << column_info[i].p_width
1978 switch (column_info[i].alignment) {
1979 case LYX_ALIGN_LEFT:
1982 case LYX_ALIGN_RIGHT:
1990 if (column_info[i].right_line)
1996 //+---------------------------------------------------------------------
1997 //+ the single row and columns (cells) +
1998 //+---------------------------------------------------------------------
2000 for(i=0; i < rows_; ++i) {
2001 ret += TeXTopHLine(os, i);
2002 for(j=0; j < columns_; ++j) {
2003 if (IsPartOfMultiColumn(i,j))
2005 ret += TeXCellPreamble(os, cell);
2006 ret += GetCellInset(cell)->Latex(os, fragile, fp);
2007 ret += TeXCellPostamble(os, cell);
2008 if (!IsLastCellInRow(cell)) { // not last cell in row
2014 os << "\\\\" << endl;
2015 ret += TeXBottomHLine(os, i);
2016 if (IsLongTabular()) {
2018 os << "\\endhead\n";
2021 if (i == endfirsthead) {
2022 os << "\\endfirsthead\n";
2026 os << "\\endfoot\n";
2029 if (i == endlastfoot) {
2030 os << "\\endlastfoot\n";
2033 if (row_info[i].newpage) {
2034 os << "\\newpage\n";
2040 //+---------------------------------------------------------------------
2041 //+ the closing of the tabular +
2042 //+---------------------------------------------------------------------
2044 if (is_long_tabular)
2045 os << "\\end{longtable}";
2047 os << "\\end{tabular}";
2049 os << "\n\\end{sideways}";
2057 InsetText * LyXTabular::GetCellInset(int cell) const
2059 return cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;
2062 void LyXTabular::Validate(LaTeXFeatures & features) const
2064 if (IsLongTabular())
2065 features.longtable = true;
2067 features.rotating = true;
2068 for(int cell = 0; cell < numberofcells; ++cell)
2069 GetCellInset(cell)->Validate(features);