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"
25 #include "support/lstrings.h"
26 #include "support/lyxmanip.h"
27 #include "insets/insettabular.h"
28 #include "insets/insettext.h"
37 static int const WIDTH_OF_LINE = 5;
39 /// Define a few methods for the inner structs
41 LyXTabular::cellstruct::cellstruct()
43 cellno = 0; //should be initilaized correctly later.
45 multicolumn = LyXTabular::CELL_NORMAL;
46 alignment = LYX_ALIGN_CENTER;
55 LyXTabular::cellstruct::~cellstruct()
61 LyXTabular::cellstruct::cellstruct(cellstruct const & cs)
64 width_of_cell = cs.width_of_cell;
65 multicolumn = cs.multicolumn;
66 alignment = cs.alignment;
67 top_line = cs.top_line;
68 bottom_line = cs.bottom_line;
70 linebreaks = cs.linebreaks;
75 LyXTabular::cellstruct &
76 LyXTabular::cellstruct::operator=(cellstruct const & cs)
79 width_of_cell = cs.width_of_cell;
80 multicolumn = cs.multicolumn;
81 alignment = cs.alignment;
82 top_line = cs.top_line;
83 bottom_line = cs.bottom_line;
85 linebreaks = cs.linebreaks;
90 LyXTabular::rowstruct::rowstruct()
100 // Nothing to do, but gcc 2.7.2.3 wants one... (JMarc)
101 //LyXTabular::rowstruct::~rowstruct()
105 //LyXTabular::rowstruct &
106 // LyXTabular::rowstruct::operator=(rowstruct const & rs)
108 // top_line = rs.top_line;
109 // bottom_line = rs.bottom_line;
110 // ascent_of_row = rs.ascent_of_row;
111 // descent_of_row = rs.descent_of_row;
112 // newpage = rs.newpage;
117 LyXTabular::columnstruct::columnstruct()
121 alignment = LYX_ALIGN_CENTER;
126 //LyXTabular::columnstruct::~columnstruct()
131 //LyXTabular::columnstruct &
132 // LyXTabular::columnstruct::operator=(columnstruct const & cs)
134 // left_line = cs.left_line;
135 // right_line = cs.right_line;
136 // alignment = cs.alignment;
137 // width_of_column = cs.width_of_column;
138 // p_width = cs.p_width;
139 // align_special = cs.align_special;
145 LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
148 Init(rows_arg, columns_arg);
152 LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt)
155 Init(lt.rows_, lt.columns_);
161 LyXTabular::LyXTabular(InsetTabular * inset, LyXLex & lex)
168 LyXTabular::~LyXTabular()
171 delete[] columnofcell;
175 LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
177 // If this and lt is not of the same size we have a serious bug
178 // So then it is ok to throw an exception, or for now
180 Assert(rows_ == lt.rows_ && columns_ == lt.columns_);
182 // int row = 0, column = 0;
184 cell_info = lt.cell_info;
185 // for (row = 0; row < rows_; ++row) {
186 // for (column = 0; column < columns_; ++column) {
187 // cell_info[row][column] = lt.cell_info[row][column];
191 row_info = lt.row_info;
192 // for (row = 0; row < rows_; ++row) {
193 // row_info[row] = lt.row_info[row];
196 column_info = lt.column_info;
197 // for (column = 0; column < columns_; ++column) {
198 // column_info[column] = lt.column_info[column];
201 // long tabular stuff
202 SetLongTabular(lt.is_long_tabular);
203 endhead = lt.endhead;
204 endfoot = lt.endfoot;
205 endfirsthead = lt.endfirsthead;
206 endlastfoot = lt.endlastfoot;
216 LyXTabular * LyXTabular::Clone(InsetTabular * inset)
218 LyXTabular * result = new LyXTabular(inset, *this);
223 /* activates all lines and sets all widths to 0 */
224 void LyXTabular::Init(int rows_arg, int columns_arg)
230 columns_ = columns_arg;
231 row_info = vector<rowstruct>(rows_, rowstruct());
232 column_info = vector<columnstruct>(columns_, columnstruct());
233 cell_info = vector<vector<cellstruct> >
234 (rows_, vector<cellstruct>(columns_, cellstruct()));
236 // Jürgen, use iterators.
237 for (i = 0; i < rows_; ++i) {
238 for (j = 0; j < columns_; ++j) {
239 cell_info[i][j].inset = new InsetText(owner_->BufferOwner());
240 cell_info[i][j].inset->setOwner(owner_);
241 cell_info[i][j].inset->SetDrawLockedFrame(true);
242 cell_info[i][j].cellno = cellno++;
245 row_info[i-1].bottom_line = true;
246 row_info[0].bottom_line = true;
248 for (i = 0; i < columns_; ++i) {
249 calculate_width_of_column(i);
251 column_info[columns_-1].right_line = true;
253 calculate_width_of_tabular();
257 set_row_column_number_info();
258 is_long_tabular = false;
267 void LyXTabular::AppendRow(int /* cell */)
270 int row = row_of_cell(cell);
271 rowstruct * row_info2 = new rowstruct[rows_ + 1];
272 cellstruct ** cell_info2 = new cellstruct * [rows_ + 1];
275 for (i = 0; i <= row; ++i) {
276 cell_info2[i] = cell_info[i];
277 row_info2[i] = row_info[i];
279 for (i = rows_ - 1; i >= row; --i) {
280 cell_info2[i + 1] = cell_info[i];
281 row_info2[i + 1] = row_info[i];
283 row_info2[row + 1].top_line = row_info[i].top_line;
284 cell_info2[row + 1] = new cellstruct[columns_](owner_->BufferOwner());
285 for (i = 0; i < columns_; ++i) {
286 cell_info2[row + 1][i].width_of_cell = 0;
287 cell_info2[row + 1][i] = cell_info2[row][i];
291 cell_info = cell_info2;
293 row_info = row_info2;
302 void LyXTabular::DeleteRow(int /*cell*/)
305 int row = row_of_cell(cell);
306 rowstruct * row_info2 = new rowstruct[rows_ - 1];
307 cellstruct ** cell_info2 = new cellstruct * [rows_ - 1];
309 delete[] cell_info[row];
311 for (; i < row; ++i) {
312 cell_info2[i] = cell_info[i];
313 row_info2[i] = row_info[i];
315 for (i = row; i < rows_ - 1; ++i) {
316 cell_info2[i] = cell_info[i + 1];
317 row_info2[i] = row_info[i + 1];
321 cell_info = cell_info2;
323 row_info = row_info2;
332 void LyXTabular::AppendColumn(int /*cell*/)
336 columnstruct * column_info2 = new columnstruct[columns_ + 1];
337 int column = right_column_of_cell(cell);
340 for (; i <= column; ++i) {
341 column_info2[i] = column_info[i];
343 for (i = columns_ - 1; i >= column; --i) {
344 column_info2[i + 1] = column_info[i];
347 delete[] column_info;
348 column_info = column_info2;
350 for (i = 0; i < rows_; ++i) {
351 cellstruct * tmp = cell_info[i];
352 cell_info[i] = new cellstruct[columns_ + 1](owner_->BufferOwner());
353 for (j = 0; j <= column; ++j) {
354 cell_info[i][j] = tmp[j];
356 for (j = column; j < columns_; ++j) {
357 cell_info[i][j + 1] = tmp[j];
359 // care about multicolumns
360 if (cell_info[i][column + 1].multicolumn
361 == LyXTabular::CELL_BEGIN_OF_MULTICOLUMN){
362 cell_info[i][column + 1].multicolumn =
363 LyXTabular::CELL_PART_OF_MULTICOLUMN;
365 if (column + 1 == columns_
366 || cell_info[i][column + 2].multicolumn
367 != LyXTabular::CELL_PART_OF_MULTICOLUMN){
368 cell_info[i][column + 1].multicolumn =
369 LyXTabular::CELL_NORMAL;
380 void LyXTabular::DeleteColumn(int /*cell*/)
383 int column1 = column_of_cell(cell);
384 int column2 = right_column_of_cell(cell);
386 if (column1 == 0 && column2 == columns_ - 1)
389 for (int column = column1; column <= column2; ++column) {
390 delete_column(column1);
397 void LyXTabular::delete_column(int /*column*/)
401 columnstruct * column_info2 = new columnstruct[columns_-1];
403 for (i = 0; i < column; ++i) {
404 column_info2[i] = column_info[i];
406 for (i = column; i < columns_ - 1; ++i) {
407 column_info2[i] = column_info[i + 1];
410 delete[] column_info;
411 column_info = column_info2;
413 for (i = 0; i < rows_; ++i) {
414 cellstruct * tmp = cell_info[i];
415 cell_info[i] = new cellstruct[columns_ - 1](owner_->BufferOwner());
416 for (j = 0; j < column; ++j) {
417 cell_info[i][j] = tmp[j];
419 for (j = column; j < columns_ - 1; ++j) {
420 cell_info[i][j] = tmp[j + 1];
431 void LyXTabular::Reinit()
437 // Jürgen, use iterators.
438 for (; i < rows_; ++i) {
439 for (j = 0; j < columns_; ++j) {
440 cell_info[i][j].width_of_cell = 0;
444 for (i = 0; i < columns_; ++i) {
445 calculate_width_of_column(i);
447 calculate_width_of_tabular();
449 set_row_column_number_info();
453 void LyXTabular::set_row_column_number_info()
459 for (; row < rows_; ++row) {
460 for (column = 0; column<columns_; ++column) {
461 if (cell_info[row][column].multicolumn
462 != LyXTabular::CELL_PART_OF_MULTICOLUMN)
464 cell_info[row][column].cellno = numberofcells;
467 ++numberofcells; // because this is one more than as we start from 0
472 rowofcell = new int[numberofcells];
473 delete [] columnofcell;
474 columnofcell = new int[numberofcells];
476 while (c < numberofcells && row < rows_ && column < columns_) {
478 columnofcell[c] = column;
482 } while (column < columns_ &&
483 cell_info[row][column].multicolumn
484 == LyXTabular::CELL_PART_OF_MULTICOLUMN);
485 if (column == columns_) {
493 int LyXTabular::GetNumberOfCells() const
495 return numberofcells;
499 int LyXTabular::NumberOfCellsInRow(int cell) const
501 int row = row_of_cell(cell);
503 for (int i = 0; i < columns_; ++i) {
504 if (cell_info[row][i].multicolumn != LyXTabular::CELL_PART_OF_MULTICOLUMN)
511 int LyXTabular::AppendCellAfterCell(int append_cell, int question_cell)
513 return (right_column_of_cell(append_cell) ==
514 right_column_of_cell(question_cell));
518 int LyXTabular::DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell)
520 if (column_of_cell(delete_column_cell) == 0 &&
521 right_column_of_cell(delete_column_cell) == columns_ - 1)
525 (column_of_cell(cell) >= column_of_cell(delete_column_cell) &&
526 column_of_cell(cell) <= right_column_of_cell(delete_column_cell));
530 /* returns 1 if there is a topline, returns 0 if not */
531 bool LyXTabular::TopLine(int cell) const
533 int row = row_of_cell(cell);
535 if (IsMultiColumn(cell))
536 return cellinfo_of_cell(cell)->top_line;
537 return row_info[row].top_line;
541 bool LyXTabular::BottomLine(int cell) const
543 //no bottom line underneath non-existent cells if you please
544 if(cell >= numberofcells)
547 if (IsMultiColumn(cell))
548 return cellinfo_of_cell(cell)->bottom_line;
549 return row_info[row_of_cell(cell)].bottom_line;
553 bool LyXTabular::LeftLine(int cell) const
555 return column_info[column_of_cell(cell)].left_line;
559 bool LyXTabular::RightLine(int cell) const
561 return column_info[right_column_of_cell(cell)].right_line;
565 bool LyXTabular::TopAlreadyDrawed(int cell) const
567 if (GetAdditionalHeight(cell))
569 int row = row_of_cell(cell);
571 int column = column_of_cell(cell);
574 && cell_info[row][column].multicolumn
575 == LyXTabular::CELL_PART_OF_MULTICOLUMN)
577 if (cell_info[row][column].multicolumn == LyXTabular::CELL_NORMAL)
578 return row_info[row].bottom_line;
580 return cell_info[row][column].bottom_line;
586 bool LyXTabular::LeftAlreadyDrawed(int cell) const
588 int column = column_of_cell(cell);
590 int row = row_of_cell(cell);
592 (cell_info[row][column].multicolumn ==
593 LyXTabular::CELL_PART_OF_MULTICOLUMN));
594 if (GetAdditionalWidth(cell_info[row][column].cellno))
596 return column_info[column].right_line;
602 bool LyXTabular::IsLastRow(int cell) const
604 return (row_of_cell(cell) == rows_ - 1);
608 int LyXTabular::GetAdditionalHeight(int cell) const
610 int row = row_of_cell(cell);
613 int top = 1; // bool top = true; ??
614 int bottom = 1; // bool bottom = true; ??
617 for (column = 0; column < columns_ - 1 && bottom; ++column) {
618 switch (cell_info[row - 1][column].multicolumn) {
619 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
620 bottom = cell_info[row - 1][column].bottom_line;
622 case LyXTabular::CELL_NORMAL:
623 bottom = row_info[row - 1].bottom_line;
626 for (column = 0; column < columns_ - 1 && top; ++column) {
627 switch (cell_info[row][column].multicolumn){
628 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
629 top = cell_info[row][column].top_line;
631 case LyXTabular::CELL_NORMAL:
632 top = row_info[row].top_line;
636 return WIDTH_OF_LINE;
641 int LyXTabular::GetAdditionalWidth(int cell) const
643 // internally already set in SetWidthOfCell
644 // used to get it back in text.C
645 int col = right_column_of_cell(cell);
646 if (col < columns_ - 1 && column_info[col].right_line &&
647 column_info[col+1].left_line)
648 return WIDTH_OF_LINE;
654 // returns the maximum over all rows
655 int LyXTabular::GetWidthOfColumn(int cell) const
657 int column1 = column_of_cell(cell);
658 int column2 = right_column_of_cell(cell);
661 for (; i <= column2; ++i) {
662 result += column_info[i].width_of_column;
668 int LyXTabular::GetWidthOfTabular() const
670 return width_of_tabular;
674 /* returns 1 if a complete update is necessary, otherwise 0 */
675 bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width)
677 if (!IsMultiColumn(cell))
680 int row = row_of_cell(cell);
681 int column1 = column_of_cell(cell);
682 int column2 = right_column_of_cell(cell);
684 // first set columns to 0 so we can calculate the right width
686 for (; i <= column2; ++i) {
687 cell_info[row][i].width_of_cell = 0;
689 // set the width to MAX_WIDTH until width > 0
690 int width = (new_width + 2 * WIDTH_OF_LINE);
691 for (i = column1; (i < column2) && (width > 0); ++i) {
692 cell_info[row][i].width_of_cell = column_info[i].width_of_column;
693 width -= column_info[i].width_of_column;
696 cell_info[row][i].width_of_cell = width;
702 void LyXTabular::recalculateMulticolCells(int cell, int new_width)
704 int row = row_of_cell(cell);
705 int column1 = column_of_cell(cell);
706 int column2 = right_column_of_cell(cell);
708 // first set columns to 0 so we can calculate the right width
710 for (; i <= column2; ++i)
711 cell_info[row][i].width_of_cell = 0;
712 for(i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i)
714 if (i < numberofcells)
715 recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE));
716 SetWidthOfMulticolCell(cell, new_width);
720 /* returns 1 if a complete update is necessary, otherwise 0 */
721 bool LyXTabular::SetWidthOfCell(int cell, int new_width)
723 int row = row_of_cell(cell);
724 int column1 = column_of_cell(cell);
728 if (IsMultiColumn(cell)) {
729 tmp = SetWidthOfMulticolCell(cell, new_width);
731 width = (new_width + 2*WIDTH_OF_LINE);
732 cell_info[row][column1].width_of_cell = width;
733 if (column_info[column1].right_line && (column1 < columns_-1) &&
734 column_info[column1+1].left_line) // additional width
735 cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
736 tmp = calculate_width_of_column_NMC(column1);
740 for(i = 0; i<columns_;++i)
741 calculate_width_of_column_NMC(i);
742 for(i = 0; (i<numberofcells) && !IsMultiColumn(i); ++i)
745 recalculateMulticolCells(i, GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
746 for(i = 0; i<columns_;++i)
747 calculate_width_of_column(i);
748 calculate_width_of_tabular();
755 bool LyXTabular::SetAlignment(int cell, char align)
757 if (!IsMultiColumn(cell))
758 column_info[column_of_cell(cell)].alignment = align;
759 cellinfo_of_cell(cell)->alignment = align;
764 bool LyXTabular::SetPWidth(int cell, string width)
766 bool flag = !width.empty();
768 if (IsMultiColumn(cell)) {
769 cellinfo_of_cell(cell)->p_width = width;
770 GetCellInset(cell)->SetAutoBreakRows(flag);
772 int j = column_of_cell(cell);
774 column_info[j].p_width = width;
775 if (flag) // do this only if there is a width
776 SetAlignment(cell, LYX_ALIGN_LEFT);
777 for(int i=0; i < rows_; ++i) {
778 c = GetCellNumber(i, j);
779 flag = !GetPWidth(c).empty(); // because of multicolumns!
780 GetCellInset(c)->SetAutoBreakRows(flag);
787 bool LyXTabular::SetAlignSpecial(int cell, string special, int what)
789 if (what == SET_SPECIAL_MULTI)
790 cellinfo_of_cell(cell)->align_special = special;
792 column_info[column_of_cell(cell)].align_special = special;
797 bool LyXTabular::SetAllLines(int cell, bool line)
799 SetTopLine(cell, line);
800 SetBottomLine(cell, line);
801 SetRightLine(cell, line);
802 SetLeftLine(cell, line);
807 bool LyXTabular::SetTopLine(int cell, bool line)
809 int row = row_of_cell(cell);
811 if (!IsMultiColumn(cell))
812 row_info[row].top_line = line;
814 cellinfo_of_cell(cell)->top_line = line;
819 bool LyXTabular::SetBottomLine(int cell, bool line)
821 if (!IsMultiColumn(cell))
822 row_info[row_of_cell(cell)].bottom_line = line;
824 cellinfo_of_cell(cell)->bottom_line = line;
829 bool LyXTabular::SetLeftLine(int cell, bool line)
831 column_info[column_of_cell(cell)].left_line = line;
836 bool LyXTabular::SetRightLine(int cell, bool line)
838 column_info[right_column_of_cell(cell)].right_line = line;
843 char LyXTabular::GetAlignment(int cell) const
845 if (IsMultiColumn(cell))
846 return cellinfo_of_cell(cell)->alignment;
848 return column_info[column_of_cell(cell)].alignment;
852 string LyXTabular::GetPWidth(int cell) const
854 if (IsMultiColumn(cell))
855 return cellinfo_of_cell(cell)->p_width;
856 return column_info[column_of_cell(cell)].p_width;
860 string LyXTabular::GetAlignSpecial(int cell, int what) const
862 if (what == SET_SPECIAL_MULTI)
863 return cellinfo_of_cell(cell)->align_special;
864 return column_info[column_of_cell(cell)].align_special;
868 int LyXTabular::GetWidthOfCell(int cell) const
870 int row = row_of_cell(cell);
871 int column1 = column_of_cell(cell);
872 int column2 = right_column_of_cell(cell);
875 for (; i <= column2; ++i) {
876 result += cell_info[row][i].width_of_cell;
879 // result += GetAdditionalWidth(cell);
884 int LyXTabular::GetBeginningOfTextInCell(int cell) const
888 switch (GetAlignment(cell)){
889 case LYX_ALIGN_CENTER:
890 x += (GetWidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
892 case LYX_ALIGN_RIGHT:
893 x += GetWidthOfColumn(cell) - GetWidthOfCell(cell);
894 // + GetAdditionalWidth(cell);
896 default: /* LYX_ALIGN_LEFT: nothing :-) */
906 bool LyXTabular::IsFirstCellInRow(int cell) const
908 return (column_of_cell(cell) == 0);
912 int LyXTabular::GetFirstCellInRow(int row) const
916 return cell_info[row][0].cellno;
919 bool LyXTabular::IsLastCellInRow(int cell) const
921 return (right_column_of_cell(cell) == (columns_ - 1));
925 int LyXTabular::GetLastCellInRow(int row) const
929 return cell_info[row][columns_-1].cellno;
933 bool LyXTabular::calculate_width_of_column(int column)
935 int old_column_width = column_info[column].width_of_column;
938 for (int i = 0; i < rows_; ++i) {
939 maximum = max(cell_info[i][column].width_of_cell, maximum);
941 column_info[column].width_of_column = maximum;
942 return (column_info[column].width_of_column != old_column_width);
946 bool LyXTabular::calculate_width_of_column_NMC(int column)
948 int old_column_width = column_info[column].width_of_column;
950 for (int i = 0; i < rows_; ++i) {
951 if (!IsMultiColumn(GetCellNumber(i, column)) &&
952 (cell_info[i][column].width_of_cell > max)) {
953 max = cell_info[i][column].width_of_cell;
956 column_info[column].width_of_column = max;
957 return (column_info[column].width_of_column != old_column_width);
961 void LyXTabular::calculate_width_of_tabular()
963 width_of_tabular = 0;
964 for (int i = 0; i < columns_; ++i) {
965 width_of_tabular += column_info[i].width_of_column;
970 int LyXTabular::row_of_cell(int cell) const
972 if (cell >= numberofcells)
976 return rowofcell[cell];
980 int LyXTabular::column_of_cell(int cell) const
982 if (cell >= numberofcells)
986 return columnofcell[cell];
990 int LyXTabular::right_column_of_cell(int cell) const
992 int row = row_of_cell(cell);
993 int column = column_of_cell(cell);
994 while (column < (columns_ - 1) &&
995 cell_info[row][column+1].multicolumn == LyXTabular::CELL_PART_OF_MULTICOLUMN)
1001 void LyXTabular::Write(ostream & os) const
1006 os << "<LyXTabular version=1 rows=" << rows_ << " columns=" << columns_ <<
1008 // global longtable options
1009 os << "<Features rotate=" << rotate <<
1010 " islongtable=" << is_long_tabular <<
1011 " endhead=" << endhead << " endfirsthead=" << endfirsthead <<
1012 " endfoot=" << endfoot << " endlastfoot=" << endlastfoot <<
1013 ">" << endl << endl;
1014 for (i = 0; i < rows_; ++i) {
1015 os << "<Row topline=" << row_info[i].top_line <<
1016 " bottomline=" << row_info[i].bottom_line <<
1017 " newpage=" << row_info[i].newpage <<
1019 for (j = 0; j < columns_; ++j) {
1021 os << "<Column alignment=" << column_info[j].alignment <<
1022 " leftline=" << column_info[j].left_line <<
1023 " rightline=" << column_info[j].right_line <<
1024 " width=\"" << VSpace(column_info[j].p_width).asLyXCommand() <<
1025 "\" special=\"" << column_info[j].align_special <<
1028 os << "<Column>" << endl;
1030 os << "<Cell multicolumn=" << cell_info[i][j].multicolumn <<
1031 " alignment=" << cell_info[i][j].alignment <<
1032 " topline=" << cell_info[i][j].top_line <<
1033 " bottomline=" << cell_info[i][j].bottom_line <<
1034 " rotate=" << cell_info[i][j].rotate <<
1035 " linebreaks=" << cell_info[i][j].linebreaks <<
1036 " width=\"" << cell_info[i][j].p_width <<
1037 "\" special=\"" << cell_info[i][j].align_special <<
1039 os << "\\begin_inset ";
1040 cell_info[i][j].inset->Write(os);
1041 os << "\n\\end_inset " << endl;
1042 os << "</Cell>" << endl;
1043 os << "</Column>" << endl;
1045 os << "</Row>" << endl;
1047 os << "</LyXTabular>" << endl;
1052 bool getTokenValue(string const str, const char * token, string & ret)
1054 int pos = str.find(token);
1055 char ch = str[pos+strlen(token)];
1057 if ((pos < 0) || (ch != '='))
1060 pos += strlen(token)+1;
1062 if ((ch != '"') && (ch != '\'')) { // only read till next space
1066 while((pos < int(str.length()-1)) && (str[++pos] != ch))
1074 bool getTokenValue(string const str, const char * token, int & num)
1077 int pos = str.find(token);
1078 char ch = str[pos+strlen(token)];
1080 if ((pos < 0) || (ch != '='))
1083 pos += strlen(token)+1;
1085 if ((ch != '"') && (ch != '\'')) { // only read till next space
1091 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1094 num = strToInt(ret);
1100 bool getTokenValue(string const str, const char * token, bool & flag)
1103 int pos = str.find(token);
1104 char ch = str[pos+strlen(token)];
1106 if ((pos < 0) || (ch != '='))
1109 pos += strlen(token)+1;
1111 if ((ch != '"') && (ch != '\'')) { // only read till next space
1117 while((pos < int(str.length()-1)) && isdigit(str[pos]))
1120 flag = strToInt(ret);
1125 void l_getline(istream & is, string & str)
1133 void LyXTabular::Read(LyXLex & lex)
1136 istream & is = lex.getStream();
1138 l_getline(is, line);
1139 if (!prefixIs(line, "<LyXTabular ")) {
1140 OldFormatRead(is, line);
1147 if (!getTokenValue(line, "version", version))
1149 if (!getTokenValue(line, "rows", rows_arg))
1151 if (!getTokenValue(line, "columns", columns_arg))
1153 Init(rows_arg, columns_arg);
1154 l_getline(is, line);
1155 if (!prefixIs(line, "<Features ")) {
1156 lyxerr << "Wrong tabular format (expected <Feture ...> got" <<
1157 line << ")" << endl;
1160 (void)getTokenValue(line, "islongtable", is_long_tabular);
1161 (void)getTokenValue(line, "endhead", endhead);
1162 (void)getTokenValue(line, "endfirsthead", endfirsthead);
1163 (void)getTokenValue(line, "endfoot", endfoot);
1164 (void)getTokenValue(line, "endlastfoot", endlastfoot);
1166 for(i = 0; i < rows_; ++i) {
1167 l_getline(is, line);
1168 if (!prefixIs(line, "<Row ")) {
1169 lyxerr << "Wrong tabular format (expected <Row ...> got" <<
1170 line << ")" << endl;
1173 (void)getTokenValue(line, "topline", row_info[i].top_line);
1174 (void)getTokenValue(line, "bottomline", row_info[i].bottom_line);
1175 (void)getTokenValue(line, "newpage", row_info[i].newpage);
1176 for (j = 0; j < columns_; ++j) {
1178 if (!prefixIs(line,"<Column")) {
1179 lyxerr << "Wrong tabular format (expected <Column ...> got" <<
1180 line << ")" << endl;
1184 (void)getTokenValue(line, "alignment", column_info[j].alignment);
1185 (void)getTokenValue(line, "leftline", column_info[j].left_line);
1186 (void)getTokenValue(line, "rightline", column_info[j].right_line);
1187 (void)getTokenValue(line, "width", column_info[j].p_width);
1188 (void)getTokenValue(line, "special", column_info[j].align_special);
1190 l_getline(is, line);
1191 if (!prefixIs(line, "<Cell")) {
1192 lyxerr << "Wrong tabular format (expected <Cell ...> got" <<
1193 line << ")" << endl;
1196 (void)getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
1197 (void)getTokenValue(line, "alignment", cell_info[i][j].alignment);
1198 (void)getTokenValue(line, "topline", cell_info[i][j].top_line);
1199 (void)getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
1200 (void)getTokenValue(line, "rotate", cell_info[i][j].rotate);
1201 (void)getTokenValue(line, "linebreaks", cell_info[i][j].linebreaks);
1202 (void)getTokenValue(line, "width", cell_info[i][j].p_width);
1203 if (!(cell_info[i][j].p_width.empty() &&
1204 column_info[j].p_width.empty()))
1205 cell_info[i][j].inset->SetAutoBreakRows(true);
1206 (void)getTokenValue(line, "special", cell_info[i][j].align_special);
1207 l_getline(is, line);
1208 if (prefixIs(line, "\\begin_inset")) {
1209 cell_info[i][j].inset->Read(lex);
1210 l_getline(is, line);
1212 if (line != "</Cell>") {
1213 lyxerr << "Wrong tabular format (expected </Cell> got" <<
1214 line << ")" << endl;
1217 l_getline(is, line);
1218 if (line != "</Column>") {
1219 lyxerr << "Wrong tabular format (expected </Column> got" <<
1220 line << ")" << endl;
1224 l_getline(is, line);
1225 if (line != "</Row>") {
1226 lyxerr << "Wrong tabular format (expected </Row> got" <<
1227 line << ")" << endl;
1231 while (line != "</LyXTabular>") {
1232 l_getline(is, line);
1234 set_row_column_number_info();
1238 void LyXTabular::OldFormatRead(istream & is, string fl)
1243 int columns_arg = 0;
1244 int is_long_tabular_arg = false;
1245 int rotate_arg = false;
1258 version = atoi(s.c_str() + 8);
1262 lyxerr << "Tabular format < 5 is not supported anymore\n"
1263 "Get an older version of LyX (< 1.1.x) for conversion!"
1265 WriteAlert(_("Warning:"),
1266 _("Tabular format < 5 is not supported anymore\n"),
1267 _("Get an older version of LyX (< 1.1.x) for conversion!"));
1269 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1270 >> rotate_arg >> a >> b >> c >> d;
1272 is >> rows_arg >> columns_arg;
1273 Init(rows_arg, columns_arg);
1274 SetLongTabular(is_long_tabular_arg);
1275 SetRotateTabular(rotate_arg);
1277 for (i = 0; i < rows_; ++i) {
1280 for (i = 0; i < columns_; ++i) {
1283 for (i = 0; i < rows_; ++i) {
1284 for (j = 0; j < columns_; ++j) {
1288 set_row_column_number_info();
1291 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1292 >> rotate_arg >> a >> b >> c >> d;
1293 Init(rows_arg, columns_arg);
1294 SetLongTabular(is_long_tabular_arg);
1295 SetRotateTabular(rotate_arg);
1300 for (i = 0; i < rows_; ++i) {
1301 a = b = c = d = e = f = g = h = 0;
1302 is >> a >> b >> c >> d;
1303 row_info[i].top_line = a;
1304 row_info[i].bottom_line = b;
1305 // row_info[i].is_cont_row = c;
1306 row_info[i].newpage = d;
1308 for (i = 0; i < columns_; ++i) {
1312 char ch; // skip '"'
1314 getline(is, s1, '"');
1315 is >> ch; // skip '"'
1316 getline(is, s2, '"');
1317 column_info[i].alignment = static_cast<char>(a);
1318 column_info[i].left_line = b;
1319 column_info[i].right_line = c;
1320 column_info[i].p_width = s1;
1321 column_info[i].align_special = s2;
1323 for (i = 0; i < rows_; ++i) {
1324 for (j = 0; j < columns_; ++j) {
1327 is >> a >> b >> c >> d >> e >> f >> g;
1329 is >> ch; // skip '"'
1330 getline(is, s1, '"');
1331 is >> ch; // skip '"'
1332 getline(is, s2, '"');
1333 cell_info[i][j].multicolumn = static_cast<char>(a);
1334 cell_info[i][j].alignment = static_cast<char>(b);
1335 cell_info[i][j].top_line = static_cast<char>(c);
1336 cell_info[i][j].bottom_line = static_cast<char>(d);
1337 // cell_info[i][j].has_cont_row = static_cast<bool>(e);
1338 cell_info[i][j].rotate = static_cast<bool>(f);
1339 cell_info[i][j].linebreaks = static_cast<bool>(g);
1340 cell_info[i][j].align_special = s1;
1341 cell_info[i][j].p_width = s2;
1344 set_row_column_number_info();
1349 // cell < 0 will tex the preamble
1350 // returns the number of printed newlines
1351 int LyXTabular::TexEndOfCell(ostream & os, int cell) const
1357 if (IsLastCell(cell)) {
1358 // the very end at the very beginning
1359 if (GetLinebreaks(cell))
1360 os << "\\smallskip{}}";
1361 if (IsMultiColumn(cell))
1363 if (GetRotateCell(cell)) {
1364 os << "\n\\end{sideways}";
1372 while (!IsFirstCellInRow(fcell)) --fcell;
1373 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1374 if (BottomLine(fcell + i))
1377 if (tmp == NumberOfCellsInRow(fcell)) {
1381 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1382 if (BottomLine(fcell + i)) {
1384 << column_of_cell(fcell + i) + 1
1386 << right_column_of_cell(fcell + i) + 1
1396 if (is_long_tabular)
1397 os << "\\end{longtable}";
1399 os << "\\end{tabular}";
1401 os << "\n\\end{sideways}";
1409 os << "\\begin{sideways}\n";
1412 if (is_long_tabular)
1413 os << "\\begin{longtable}{";
1415 os << "\\begin{tabular}{";
1416 for (i = 0; i < columns_; ++i) {
1417 if (column_info[i].left_line)
1419 if (!column_info[i].align_special.empty()) {
1420 os << column_info[i].align_special;
1421 } else if (!column_info[i].p_width.empty()) {
1423 << column_info[i].p_width
1426 switch (column_info[i].alignment) {
1427 case LYX_ALIGN_LEFT:
1430 case LYX_ALIGN_RIGHT:
1438 if (column_info[i].right_line)
1444 if (GetNumberOfCells()) {
1446 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1447 if (TopLine(fcell + i))
1450 if (tmp == NumberOfCellsInRow(fcell)){
1454 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1455 if (TopLine(fcell + i)) {
1457 << column_of_cell(fcell + i) + 1
1459 << right_column_of_cell(fcell + i) + 1
1470 if (GetRotateCell(0)) {
1471 os << "\\begin{sideways}\n";
1476 if (GetLinebreaks(cell))
1477 os << "\\smallskip{}}";
1478 if (IsMultiColumn(cell)){
1481 if (GetRotateCell(cell)) {
1482 os << "\n\\end{sideways}";
1485 if (IsLastCellInRow(cell)) {
1486 int row = row_of_cell(cell);
1487 string hline1, hline2;
1488 bool print_hline = true;
1489 bool flag1 = IsLongTabular() &&
1490 ((row == endhead) || (row == endfirsthead) ||
1491 (row == endfoot) || (row == endlastfoot));
1493 bool flag2 = IsLongTabular() &&
1494 ((row <= endhead) || (row <= endfirsthead) ||
1495 (row <= endfoot) || (row <= endlastfoot));
1497 // print the bottom hline only if (otherwise it is doubled):
1498 // - is no LongTabular
1499 // - there IS a first-header
1500 // - the next row is no special header/footer
1501 // & this row is no special header/footer
1502 // - the next row is a special header/footer
1503 // & this row is a special header/footer
1504 bool pr_top_hline = (flag1 && flag2) || (!flag1 && !flag2) ||
1505 (endfirsthead == endhead);
1510 while (!IsFirstCellInRow(fcell))
1512 for (i = 0; i < NumberOfCellsInRow(cell); ++i) {
1513 if (BottomLine(fcell + i))
1516 if (tmp == NumberOfCellsInRow(cell)){
1518 hline1 = "\\hline ";
1521 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1522 if (BottomLine(fcell + i)){
1524 << column_of_cell(fcell + i) + 1
1526 << right_column_of_cell(fcell + i) + 1
1528 hline1 += "\\cline{";
1529 hline1 += tostr(column_of_cell(fcell + i) + 1);
1531 hline1 += tostr(right_column_of_cell(fcell + i) + 1);
1541 if (IsLongTabular() && (row == endfoot)) {
1542 os << "\\endfoot\n";
1544 print_hline = false; // no double line below footer
1546 if (IsLongTabular() && (row == endlastfoot)) {
1547 os << "\\endlastfoot\n";
1549 print_hline = false; // no double line below footer
1551 if (IsLongTabular() && row_info[row].newpage) {
1552 os << "\\newpage\n";
1554 print_hline = false; // no line below a \\newpage-command
1557 if ((nvcell < numberofcells) &&
1558 (cell < GetNumberOfCells() - 1) && !IsLastCell(cell)) {
1560 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1561 if (TopLine(fcell + i))
1564 if (tmp == NumberOfCellsInRow(fcell)) {
1567 hline2 = "\\hline ";
1570 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1571 if (TopLine(fcell + i)) {
1574 << column_of_cell(fcell + i) + 1
1576 << right_column_of_cell(fcell + i) + 1
1579 hline2 += "\\cline{";
1580 hline2 += tostr(column_of_cell(fcell+i)+1);
1582 hline2 += tostr(right_column_of_cell(fcell+i)+1);
1588 if (tmp && print_hline){
1593 // the order here is important as if one defines two
1594 // or more things in one line only the first entry is
1595 // displayed the other are set to an empty-row. This
1596 // is important if I have a footer and want that the
1597 // lastfooter is NOT displayed!!!
1598 bool sflag2 = (row == endhead) || (row == endfirsthead) ||
1599 (row == endfoot) || (row == endlastfoot);
1602 bool sflag1 = IsLongTabular() && (row != endhead) &&
1603 (row != endfirsthead) &&
1604 ((row == endfoot) || (row == endlastfoot));
1606 if (IsLongTabular() && (row == endhead)) {
1607 os << "\\endhead\n";
1610 if (IsLongTabular() && (row == endfirsthead)) {
1611 os << "\\endfirsthead\n";
1614 if (sflag1) { // add the \hline for next foot row
1615 if (!hline1.empty()) {
1616 os << hline1 + '\n';
1620 // add the \hline for the first row
1621 if (pr_top_hline && sflag2) {
1622 if (!hline2.empty()) {
1623 os << hline2 + '\n';
1627 if (nvcell < numberofcells && GetRotateCell(nvcell)) {
1628 os << "\\begin{sideways}\n";
1634 if (nvcell < numberofcells && GetRotateCell(nvcell)) {
1635 os << "\\begin{sideways}\n";
1640 if (nvcell < numberofcells && IsMultiColumn(nvcell)) {
1641 os << "\\multicolumn{"
1642 << cells_in_multicolumn(nvcell)
1644 if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1645 os << cellinfo_of_cell(cell+1)->align_special
1648 if (LeftLine(nvcell))
1650 if (!GetPWidth(nvcell).empty()) {
1652 << GetPWidth(nvcell)
1655 switch (GetAlignment(nvcell)) {
1656 case LYX_ALIGN_LEFT: os << 'l'; break;
1657 case LYX_ALIGN_RIGHT: os << 'r'; break;
1658 default: os << 'c'; break;
1661 if (RightLine(nvcell))
1663 //if (column_of_cell(cell+2)!= 0 && LeftLine(cell+2))
1664 if (((nvcell + 1) < numberofcells) &&
1665 ((nvcell+1) < numberofcells) &&
1666 (column_of_cell(nvcell+1)!= 0) &&
1673 if (nvcell < numberofcells && GetLinebreaks(nvcell)) {
1674 os << "\\parbox[t]{"
1675 << GetPWidth(nvcell)
1676 << "}{\\smallskip{}";
1683 // cell <0 will tex the preamble
1684 // returns the number of printed newlines
1685 int LyXTabular::RoffEndOfCell(ostream & os, int cell)
1689 if (cell == GetNumberOfCells() - 1){
1690 // the very end at the very beginning
1691 // if (CellHasContRow(cell) >= 0) {
1697 if (row_info[row_of_cell(cell)].bottom_line) {
1701 os << ".TE\n.pl 1c";
1706 os << "\n.pl 500c\n.TS\n";
1707 for (int j = 0; j < rows_; ++j) {
1708 for (int i = 0; i < columns_; ++i, ++fcell) {
1709 if (column_info[i].left_line)
1711 if (cell_info[j][i].multicolumn == CELL_PART_OF_MULTICOLUMN)
1714 switch (column_info[i].alignment) {
1715 case LYX_ALIGN_LEFT:
1718 case LYX_ALIGN_RIGHT:
1726 if (!column_info[i].p_width.empty())
1727 os << "w(" << column_info[i].p_width << ")";
1728 if (column_info[i].right_line)
1731 if ((j + 1) < rows_) {
1738 if (row_info[0].top_line) {
1742 // if (CellHasContRow(0) >= 0) {
1748 // if (CellHasContRow(cell) >= 0) {
1752 if (right_column_of_cell(cell) == columns_ -1){
1755 int row = row_of_cell(cell);
1756 if (row_info[row++].bottom_line) {
1760 if ((row < rows_) && row_info[row].top_line) {
1766 // if ((cell < GetNumberOfCells() - 1) &&
1767 // (CellHasContRow(cell+1) >= 0)) {
1779 char const * LyXTabular::GetDocBookAlign(int cell, bool isColumn) const
1781 int i = isColumn ? cell : column_of_cell(cell);
1786 //i = column_of_cell(cell);
1787 if (!isColumn && IsMultiColumn(cell)) {
1788 if (!cellinfo_of_cell(cell)->align_special.empty()) {
1789 return cellinfo_of_cell(cell)->align_special.c_str();
1791 switch (GetAlignment(cell)) {
1792 case LYX_ALIGN_LEFT:
1794 case LYX_ALIGN_RIGHT:
1801 if (!column_info[i].align_special.empty()) {
1802 return column_info[i].align_special.c_str();
1804 #ifdef IGNORE_THIS_FOR_NOW
1805 else if (!column_info[i].p_width.empty()) {
1807 file += column_info[i].p_width;
1812 switch (column_info[i].alignment) {
1813 case LYX_ALIGN_LEFT:
1815 case LYX_ALIGN_RIGHT:
1825 // cell <0 will tex the preamble
1826 // returns the number of printed newlines
1827 int LyXTabular::DocBookEndOfCell(ostream & os, int cell, int & depth) const
1831 //int tmp; // tmp2; // unused
1832 int nvcell; // fcell; // unused
1833 if (IsLastCell(cell)) {
1834 os << newlineAndDepth(--depth)
1836 << newlineAndDepth(--depth)
1838 << newlineAndDepth(--depth)
1840 << newlineAndDepth(--depth);
1841 if (is_long_tabular)
1845 << newlineAndDepth(--depth);
1851 if (is_long_tabular)
1857 << "' COLSEP='1' ROWSEP='1'>"
1858 << newlineAndDepth(++depth);
1860 for (i = 0; i < columns_; ++i) {
1861 os << "<COLSPEC ALIGN='"
1862 << GetDocBookAlign(i, true)
1868 if (i == (columns_-1)) {
1871 if (column_info[i].right_line ||
1872 column_info[i+1].left_line)
1878 << newlineAndDepth(depth);
1880 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1881 if (column_info[i].left_line)
1886 << newlineAndDepth(++depth)
1888 << newlineAndDepth(++depth)
1890 << GetDocBookAlign(0)
1892 if (IsMultiColumn(0)) {
1893 os << " NAMEST='col1' NAMEEND='col"
1894 << cells_in_multicolumn(0)
1898 << newlineAndDepth(++depth);
1901 if (IsLastCellInRow(cell)) {
1902 os << newlineAndDepth(--depth)
1904 << newlineAndDepth(--depth)
1906 << newlineAndDepth(depth)
1908 << newlineAndDepth(++depth)
1910 << GetDocBookAlign(cell + 1)
1911 << "' VALIGN='middle'";
1912 if (IsMultiColumn(cell + 1)) {
1913 os << " NAMEST='col"
1914 << column_of_cell(cell+1) + 1
1916 << column_of_cell(cell + 1) +
1917 cells_in_multicolumn(cell + 1)
1921 << newlineAndDepth(++depth);
1924 os << newlineAndDepth(--depth)
1926 << newlineAndDepth(depth)
1928 << GetDocBookAlign(cell + 1)
1929 << "' VALIGN='middle'";
1930 if (IsMultiColumn(cell + 1)) {
1931 os << " NAMEST='col"
1932 << column_of_cell(cell+1) + 1
1934 << column_of_cell(cell+1) +
1935 cells_in_multicolumn(cell+1)
1939 << newlineAndDepth(++depth);
1948 bool LyXTabular::IsMultiColumn(int cell) const
1950 return (cellinfo_of_cell(cell)->multicolumn != LyXTabular::CELL_NORMAL);
1954 LyXTabular::cellstruct * LyXTabular::cellinfo_of_cell(int cell) const
1956 int row = row_of_cell(cell);
1957 int column = column_of_cell(cell);
1958 return &cell_info[row][column];
1962 void LyXTabular::SetMultiColumn(int cell, int number)
1964 int new_width = cellinfo_of_cell(cell)->width_of_cell;
1966 cellinfo_of_cell(cell)->multicolumn = LyXTabular::CELL_BEGIN_OF_MULTICOLUMN;
1967 cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
1968 cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
1969 cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
1970 for (number--; number > 0; --number) {
1971 cellinfo_of_cell(cell+number)->multicolumn =
1972 LyXTabular::CELL_PART_OF_MULTICOLUMN;
1973 new_width += cellinfo_of_cell(cell+number)->width_of_cell;
1975 set_row_column_number_info();
1976 SetWidthOfCell(cell, new_width);
1977 if (GetPWidth(cell).empty())
1978 GetCellInset(cell)->SetAutoBreakRows(false);
1982 int LyXTabular::cells_in_multicolumn(int cell) const
1984 int row = row_of_cell(cell);
1985 int column = column_of_cell(cell);
1988 while (column < columns_ && cell_info[row][column].multicolumn
1989 == LyXTabular::CELL_PART_OF_MULTICOLUMN){
1997 int LyXTabular::UnsetMultiColumn(int cell)
1999 int row = row_of_cell(cell);
2000 int column = column_of_cell(cell);
2004 if (cell_info[row][column].multicolumn
2005 == LyXTabular::CELL_BEGIN_OF_MULTICOLUMN){
2006 cell_info[row][column].multicolumn = LyXTabular::CELL_NORMAL;
2008 while (column < columns_ &&
2009 cell_info[row][column].multicolumn
2010 == LyXTabular::CELL_PART_OF_MULTICOLUMN){
2011 cell_info[row][column].multicolumn =
2012 LyXTabular::CELL_NORMAL;
2017 set_row_column_number_info();
2018 if (GetPWidth(cell).empty())
2019 GetCellInset(cell)->SetAutoBreakRows(false);
2024 void LyXTabular::SetLongTabular(int what)
2026 is_long_tabular = what;
2030 bool LyXTabular::IsLongTabular() const
2032 return is_long_tabular;
2036 void LyXTabular::SetRotateTabular(int what)
2042 bool LyXTabular::GetRotateTabular() const
2048 void LyXTabular::SetRotateCell(int cell, int what)
2050 cellinfo_of_cell(cell)->rotate = what;
2054 bool LyXTabular::GetRotateCell(int cell) const
2056 return cellinfo_of_cell(cell)->rotate;
2060 bool LyXTabular::NeedRotating() const
2064 for (int i = 0; i < rows_; ++i) {
2065 for (int j = 0; j < columns_; ++j) {
2066 if (cell_info[i][j].rotate)
2074 bool LyXTabular::IsLastCell(int cell) const
2076 if (cell < GetNumberOfCells())
2082 int LyXTabular::GetCellAbove(int cell) const
2084 if (row_of_cell(cell) > 0)
2085 return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
2090 int LyXTabular::GetCellNumber(int row, int column) const
2092 if (column >= columns_)
2093 column = columns_ - 1;
2094 else if (column < 0)
2101 return cell_info[row][column].cellno;
2105 void LyXTabular::SetLinebreaks(int cell, bool what)
2107 cellinfo_of_cell(cell)->linebreaks = what;
2111 bool LyXTabular::GetLinebreaks(int cell) const
2113 if (column_info[column_of_cell(cell)].p_width.empty() &&
2114 !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty()))
2116 return cellinfo_of_cell(cell)->linebreaks;
2120 void LyXTabular::SetLTHead(int cell, bool first)
2122 int row = row_of_cell(cell);
2125 if (row == endfirsthead)
2138 bool LyXTabular::GetRowOfLTHead(int cell) const
2140 if ((endhead+1) > rows_)
2142 return (row_of_cell(cell) == endhead);
2146 bool LyXTabular::GetRowOfLTFirstHead(int cell) const
2148 if ((endfirsthead+1) > rows_)
2150 return (row_of_cell(cell) == endfirsthead);
2154 void LyXTabular::SetLTFoot(int cell, bool last)
2156 int row = row_of_cell(cell);
2159 if (row == endlastfoot)
2172 bool LyXTabular::GetRowOfLTFoot(int cell) const
2174 if ((endfoot+1) > rows_)
2176 return (row_of_cell(cell) == endfoot);
2179 bool LyXTabular::GetRowOfLTLastFoot(int cell) const
2181 if ((endlastfoot+1) > rows_)
2183 return (row_of_cell(cell) == endlastfoot);
2187 void LyXTabular::SetLTNewPage(int cell, bool what)
2189 row_info[row_of_cell(cell)].newpage = what;
2193 bool LyXTabular::GetLTNewPage(int cell) const
2195 return row_info[row_of_cell(cell)].newpage;
2199 void LyXTabular::SetAscentOfRow(int row, int height)
2203 row_info[row].ascent_of_row = height;
2207 void LyXTabular::SetDescentOfRow(int row, int height)
2211 row_info[row].descent_of_row = height;
2215 int LyXTabular::GetAscentOfRow(int row) const
2219 return row_info[row].ascent_of_row;
2223 int LyXTabular::GetDescentOfRow(int row) const
2227 return row_info[row].descent_of_row;
2231 int LyXTabular::GetHeightOfTabular() const
2235 for(int row = 0; row < rows_; ++row)
2236 height += GetAscentOfRow(row) + GetDescentOfRow(row) +
2237 GetAdditionalHeight(GetCellNumber(row, 0));
2242 bool LyXTabular::IsPartOfMultiColumn(int row, int column) const
2244 if ((row >= rows_) || (column >= columns_))
2246 return (cell_info[row][column].multicolumn==CELL_PART_OF_MULTICOLUMN);
2250 int LyXTabular::TeXTopHLine(ostream & os, int row) const
2252 int fcell = GetFirstCellInRow(row);
2253 int n = NumberOfCellsInRow(fcell) + fcell;
2257 for (i = fcell; i < n; ++i) {
2261 if (tmp == (n - fcell)){
2264 for (i = fcell; i < n; ++i) {
2267 << column_of_cell(i) + 1
2269 << right_column_of_cell(i) + 1
2282 int LyXTabular::TeXBottomHLine(ostream & os, int row) const
2284 int fcell = GetFirstCellInRow(row);
2285 int n = NumberOfCellsInRow(fcell) + fcell;
2289 for (i = fcell; i < n; ++i) {
2293 if (tmp == (n-fcell)){
2296 for (i = fcell; i < n; ++i) {
2297 if (BottomLine(i)) {
2299 << column_of_cell(i) + 1
2301 << right_column_of_cell(i) + 1
2314 int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
2318 if (GetRotateCell(cell)) {
2319 os << "\\begin{sideways}" << endl;
2322 if (IsMultiColumn(cell)) {
2323 os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
2324 if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
2325 os << cellinfo_of_cell(cell+1)->align_special << "}{";
2329 if (!GetPWidth(cell).empty()) {
2330 os << "p{" << GetPWidth(cell) << '}';
2332 switch (GetAlignment(cell)) {
2333 case LYX_ALIGN_LEFT:
2336 case LYX_ALIGN_RIGHT:
2344 if (RightLine(cell))
2346 if (((cell + 1) < numberofcells) && !IsFirstCellInRow(cell+1) &&
2352 if (GetLinebreaks(cell)) {
2353 os << "\\parbox[t]{" << GetPWidth(cell) << "}{\\smallskip{}";
2359 int LyXTabular::TeXCellPostamble(ostream & os, int cell) const
2364 if (GetLinebreaks(cell))
2365 os << "\\smallskip{}}";
2366 if (IsMultiColumn(cell)){
2369 if (GetRotateCell(cell)) {
2370 os << endl << "\\end{sideways}";
2377 int LyXTabular::Latex(ostream & os, bool fragile, bool fp) const
2383 //+---------------------------------------------------------------------
2384 //+ first the opening preamble +
2385 //+---------------------------------------------------------------------
2388 os << "\\begin{sideways}" << endl;
2391 if (is_long_tabular)
2392 os << "\\begin{longtable}{";
2394 os << "\\begin{tabular}{";
2395 for (i = 0; i < columns_; ++i) {
2396 if (column_info[i].left_line)
2398 if (!column_info[i].align_special.empty()) {
2399 os << column_info[i].align_special;
2400 } else if (!column_info[i].p_width.empty()) {
2402 << column_info[i].p_width
2405 switch (column_info[i].alignment) {
2406 case LYX_ALIGN_LEFT:
2409 case LYX_ALIGN_RIGHT:
2417 if (column_info[i].right_line)
2423 //+---------------------------------------------------------------------
2424 //+ the single row and columns (cells) +
2425 //+---------------------------------------------------------------------
2427 for(i=0; i < rows_; ++i) {
2428 ret += TeXTopHLine(os, i);
2429 for(j=0; j < columns_; ++j) {
2430 if (IsPartOfMultiColumn(i,j))
2432 ret += TeXCellPreamble(os, cell);
2433 ret += GetCellInset(cell)->Latex(os, fragile, fp);
2434 ret += TeXCellPostamble(os, cell);
2435 if (j < (columns_ - 1)) { // not last cell in row
2441 os << "\\\\" << endl;
2442 ret += TeXBottomHLine(os, i);
2443 if (IsLongTabular()) {
2445 os << "\\endhead\n";
2448 if (i == endfirsthead) {
2449 os << "\\endfirsthead\n";
2453 os << "\\endfoot\n";
2456 if (i == endlastfoot) {
2457 os << "\\endlastfoot\n";
2460 if (row_info[i].newpage) {
2461 os << "\\newpage\n";
2467 //+---------------------------------------------------------------------
2468 //+ the closing of the tabular +
2469 //+---------------------------------------------------------------------
2471 if (is_long_tabular)
2472 os << "\\end{longtable}";
2474 os << "\\end{tabular}";
2476 os << "\n\\end{sideways}";
2484 InsetText * LyXTabular::GetCellInset(int cell) const
2486 return cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;