1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
8 * ======================================================
17 #pragma implementation
24 #include "support/lstrings.h"
25 #include "support/lyxmanip.h"
26 #include "lyx_gui_misc.h"
27 #include "insets/insettext.h"
34 static int const WIDTH_OF_LINE = 5;
36 /// Define a few methods for the inner structs
38 LyXTabular::cellstruct::cellstruct(Buffer * buf)
40 cellno = 0; //should be initilaized correctly later.
42 multicolumn = LyXTabular::CELL_NORMAL;
43 alignment = LYX_ALIGN_CENTER;
48 buf ? inset = new InsetText(buf): inset = 0;
52 LyXTabular::cellstruct::~cellstruct()
58 LyXTabular::cellstruct &
59 LyXTabular::cellstruct::operator=(cellstruct const & cs)
62 width_of_cell = cs.width_of_cell;
63 multicolumn = cs.multicolumn;
64 alignment = cs.alignment;
65 top_line = cs.top_line;
66 bottom_line = cs.bottom_line;
68 linebreaks = cs.linebreaks;
72 LyXTabular::rowstruct::rowstruct()
81 // Nothing to do, but gcc 2.7.2.3 wants one... (JMarc)
82 LyXTabular::rowstruct::~rowstruct()
86 LyXTabular::rowstruct &
87 LyXTabular::rowstruct::operator=(rowstruct const & rs)
89 top_line = rs.top_line;
90 bottom_line = rs.bottom_line;
91 ascent_of_row = rs.ascent_of_row;
92 descent_of_row = rs.descent_of_row;
97 LyXTabular::columnstruct::columnstruct()
101 alignment = LYX_ALIGN_CENTER;
105 LyXTabular::columnstruct::~columnstruct()
109 LyXTabular::columnstruct &
110 LyXTabular::columnstruct::operator=(columnstruct const & cs)
112 left_line = cs.left_line;
113 right_line = cs.right_line;
114 alignment = cs.alignment;
115 width_of_column = cs.width_of_column;
116 p_width = cs.p_width;
117 align_special = cs.align_special;
122 LyXTabular::LyXTabular(int rows_arg, int columns_arg, Buffer *buf)
125 Init(rows_arg, columns_arg);
129 LyXTabular::LyXTabular(LyXTabular const & lt, Buffer * buf)
132 Init(lt.rows_, lt.columns_);
137 LyXTabular::LyXTabular(LyXLex & lex, Buffer *buf)
139 istream & is = lex.getStream();
145 LyXTabular::~LyXTabular()
148 delete[] columnofcell;
149 delete[] column_info;
151 for (int i = 0; i < rows_; ++i) {
152 delete[] cell_info[i];
158 LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
160 // If this and lt is not of the same size we have a serious bug
161 // So then it is ok to throw an exception, or for now
163 Assert(rows_ == lt.rows_ && columns_ == lt.columns_);
165 int row = 0, column = 0;
167 for (row = 0; row < rows_; ++row) {
168 for (column = 0; column < columns_; ++column) {
169 cell_info[row][column] = lt.cell_info[row][column];
173 for (row = 0; row < rows_; ++row) {
174 row_info[row] = lt.row_info[row];
177 for (column = 0; column < columns_; ++column) {
178 column_info[column] = lt.column_info[column];
181 SetLongTabular(lt.is_long_tabular);
188 LyXTabular * LyXTabular::Clone()
190 LyXTabular * result = new LyXTabular(rows_, columns_);
193 for (row = 0; row < rows_; ++row) {
194 for (column = 0; column < columns_; ++column) {
195 result->cell_info[row][column] = cell_info[row][column];
199 for (row = 0; row < rows_; ++row) {
200 result->row_info[row] = row_info[row];
203 for (column = 0; column < columns_; ++column) {
204 result->column_info[column].left_line = column_info[column].left_line;
205 result->column_info[column].right_line = column_info[column].right_line;
206 result->column_info[column].alignment = column_info[column].alignment;
207 result->column_info[column].p_width = column_info[column].p_width;
208 result->column_info[column].align_special = column_info[column].align_special;
211 result->SetLongTabular(is_long_tabular);
212 result->rotate = rotate;
218 /* activates all lines and sets all widths to 0 */
219 void LyXTabular::Init(int rows_arg, int columns_arg)
223 columns_ = columns_arg;
224 column_info = new columnstruct[columns_];
225 row_info = new rowstruct[rows_];
226 cell_info = new cellstruct*[rows_];
229 for (i = 0; i < rows_; ++i) {
230 cell_info[i] = new cellstruct[columns_](buffer);
231 for (j = 0; j < columns_; ++j) {
232 cell_info[i][j].cellno = cellno++;
235 row_info[i-1].bottom_line = true;
236 row_info[0].bottom_line = true;
238 for (i = 0; i < columns_; ++i) {
239 calculate_width_of_column(i);
241 column_info[columns_-1].right_line = true;
243 calculate_width_of_tabular();
247 set_row_column_number_info();
248 is_long_tabular = false;
257 void LyXTabular::AppendRow(int cell)
259 int row = row_of_cell(cell);
260 rowstruct * row_info2 = new rowstruct[rows_ + 1];
261 cellstruct ** cell_info2 = new cellstruct * [rows_ + 1];
264 for (i = 0; i <= row; ++i) {
265 cell_info2[i] = cell_info[i];
266 row_info2[i] = row_info[i];
268 for (i = rows_ - 1; i >= row; --i) {
269 cell_info2[i + 1] = cell_info[i];
270 row_info2[i + 1] = row_info[i];
272 row_info2[row + 1].top_line = row_info[i].top_line;
273 cell_info2[row + 1] = new cellstruct[columns_];
274 for (i = 0; i < columns_; ++i) {
275 cell_info2[row + 1][i].width_of_cell = 0;
276 cell_info2[row + 1][i] = cell_info2[row][i];
280 cell_info = cell_info2;
282 row_info = row_info2;
290 void LyXTabular::DeleteRow(int cell)
292 int row = row_of_cell(cell);
293 rowstruct * row_info2 = new rowstruct[rows_ - 1];
294 cellstruct ** cell_info2 = new cellstruct * [rows_ - 1];
296 delete[] cell_info[row];
298 for (; i < row; ++i) {
299 cell_info2[i] = cell_info[i];
300 row_info2[i] = row_info[i];
302 for (i = row; i < rows_ - 1; ++i) {
303 cell_info2[i] = cell_info[i + 1];
304 row_info2[i] = row_info[i + 1];
308 cell_info = cell_info2;
310 row_info = row_info2;
318 void LyXTabular::AppendColumn(int cell)
321 columnstruct * column_info2 = new columnstruct[columns_ + 1];
322 int column = right_column_of_cell(cell);
325 for (; i <= column; ++i) {
326 column_info2[i] = column_info[i];
328 for (i = columns_ - 1; i >= column; --i) {
329 column_info2[i + 1] = column_info[i];
332 delete[] column_info;
333 column_info = column_info2;
335 for (i = 0; i < rows_; ++i) {
336 cellstruct * tmp = cell_info[i];
337 cell_info[i] = new cellstruct[columns_ + 1];
338 for (j = 0; j <= column; ++j) {
339 cell_info[i][j] = tmp[j];
341 for (j = column; j < columns_; ++j) {
342 cell_info[i][j + 1] = tmp[j];
344 // care about multicolumns
345 if (cell_info[i][column + 1].multicolumn
346 == LyXTabular::CELL_BEGIN_OF_MULTICOLUMN){
347 cell_info[i][column + 1].multicolumn =
348 LyXTabular::CELL_PART_OF_MULTICOLUMN;
350 if (column + 1 == columns_
351 || cell_info[i][column + 2].multicolumn
352 != LyXTabular::CELL_PART_OF_MULTICOLUMN){
353 cell_info[i][column + 1].multicolumn =
354 LyXTabular::CELL_NORMAL;
364 void LyXTabular::Reinit()
369 for (; i < rows_; ++i) {
370 for (j = 0; j < columns_; ++j) {
371 cell_info[i][j].width_of_cell = 0;
375 for (i = 0; i < columns_; ++i) {
376 calculate_width_of_column(i);
378 calculate_width_of_tabular();
380 set_row_column_number_info();
384 void LyXTabular::set_row_column_number_info()
390 for (; row < rows_; ++row) {
391 for (column = 0; column<columns_; ++column) {
392 if (cell_info[row][column].multicolumn
393 != LyXTabular::CELL_PART_OF_MULTICOLUMN)
395 cell_info[row][column].cellno = numberofcells;
398 ++numberofcells; // because this is one more than as we start from 0
403 rowofcell = new int[numberofcells];
404 delete [] columnofcell;
405 columnofcell = new int[numberofcells];
407 while (c < numberofcells && row < rows_ && column < columns_) {
409 columnofcell[c] = column;
413 } while (column < columns_ &&
414 cell_info[row][column].multicolumn
415 == LyXTabular::CELL_PART_OF_MULTICOLUMN);
416 if (column == columns_) {
424 void LyXTabular::DeleteColumn(int cell)
426 int column1 = column_of_cell(cell);
427 int column2 = right_column_of_cell(cell);
429 if (column1 == 0 && column2 == columns_ - 1)
432 for (int column = column1; column <= column2; ++column) {
433 delete_column(column1);
439 int LyXTabular::GetNumberOfCells()
441 return numberofcells;
445 int LyXTabular::NumberOfCellsInRow(int cell)
447 int row = row_of_cell(cell);
449 for (int i = 0; i < columns_; ++i) {
450 if (cell_info[row][i].multicolumn != LyXTabular::CELL_PART_OF_MULTICOLUMN)
457 int LyXTabular::AppendCellAfterCell(int append_cell, int question_cell)
459 return (right_column_of_cell(append_cell) ==
460 right_column_of_cell(question_cell));
464 int LyXTabular::DeleteCellIfColumnIsDeleted(int cell, int delete_column_cell)
466 if (column_of_cell(delete_column_cell) == 0 &&
467 right_column_of_cell(delete_column_cell) == columns_ - 1)
471 (column_of_cell(cell) >= column_of_cell(delete_column_cell) &&
472 column_of_cell(cell) <= right_column_of_cell(delete_column_cell));
476 /* returns 1 if there is a topline, returns 0 if not */
477 bool LyXTabular::TopLine(int cell)
479 int row = row_of_cell(cell);
481 if (IsMultiColumn(cell))
482 return cellinfo_of_cell(cell)->top_line;
483 return row_info[row].top_line;
487 bool LyXTabular::BottomLine(int cell)
489 //no bottom line underneath non-existent cells if you please
490 if(cell >= numberofcells)
493 if (IsMultiColumn(cell))
494 return cellinfo_of_cell(cell)->bottom_line;
495 return row_info[row_of_cell(cell)].bottom_line;
499 bool LyXTabular::LeftLine(int cell)
501 return column_info[column_of_cell(cell)].left_line;
505 bool LyXTabular::RightLine(int cell)
507 return column_info[right_column_of_cell(cell)].right_line;
511 bool LyXTabular::TopAlreadyDrawed(int cell)
513 if (AdditionalHeight(cell))
515 int row = row_of_cell(cell);
517 int column = column_of_cell(cell);
519 && cell_info[row-1][column].multicolumn
520 == LyXTabular::CELL_PART_OF_MULTICOLUMN)
522 if (cell_info[row-1][column].multicolumn
523 == LyXTabular::CELL_NORMAL)
524 return row_info[row-1].bottom_line;
526 return cell_info[row-1][column].bottom_line;
532 bool LyXTabular::VeryLastRow(int cell)
534 return (row_of_cell(cell) == rows_ - 1);
538 int LyXTabular::AdditionalHeight(int cell)
540 int row = row_of_cell(cell);
543 int top = 1; // bool top = true; ??
544 int bottom = 1; // bool bottom = true; ??
547 for (column = 0; column < columns_ - 1 && bottom; ++column) {
548 switch (cell_info[row - 1][column].multicolumn) {
549 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
550 bottom = cell_info[row - 1][column].bottom_line;
552 case LyXTabular::CELL_NORMAL:
553 bottom = row_info[row - 1].bottom_line;
556 for (column = 0; column < columns_ - 1 && top; ++column) {
557 switch (cell_info[row][column].multicolumn){
558 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
559 top = cell_info[row][column].top_line;
561 case LyXTabular::CELL_NORMAL:
562 top = row_info[row].top_line;
566 return WIDTH_OF_LINE;
571 int LyXTabular::AdditionalWidth(int cell)
573 // internally already set in SetWidthOfCell
574 // used to get it back in text.C
575 int col = right_column_of_cell(cell);
576 if (col < columns_ - 1 && column_info[col].right_line &&
577 column_info[col+1].left_line)
578 return WIDTH_OF_LINE;
584 // returns the maximum over all rows
585 int LyXTabular::WidthOfColumn(int cell)
587 int column1 = column_of_cell(cell);
588 int column2 = right_column_of_cell(cell);
591 for (; i <= column2; ++i) {
592 result += column_info[i].width_of_column;
598 int LyXTabular::WidthOfTabular()
600 return width_of_tabular;
603 /* returns 1 if a complete update is necessary, otherwise 0 */
604 bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width)
606 if (!IsMultiColumn(cell))
609 int row = row_of_cell(cell);
610 int column1 = column_of_cell(cell);
611 int column2 = right_column_of_cell(cell);
613 // first set columns to 0 so we can calculate the right width
615 for (; i <= column2; ++i) {
616 cell_info[row][i].width_of_cell = 0;
618 // set the width to MAX_WIDTH until width > 0
619 int width = (new_width + 2 * WIDTH_OF_LINE);
620 for (i = column1; (i < column2) && (width > 0); ++i) {
621 cell_info[row][i].width_of_cell = column_info[i].width_of_column;
622 width -= column_info[i].width_of_column;
625 cell_info[row][i].width_of_cell = width;
631 void LyXTabular::recalculateMulticolCells(int cell, int new_width)
633 int row = row_of_cell(cell);
634 int column1 = column_of_cell(cell);
635 int column2 = right_column_of_cell(cell);
637 // first set columns to 0 so we can calculate the right width
639 for (; i <= column2; ++i)
640 cell_info[row][i].width_of_cell = 0;
641 for(i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i)
643 if (i < numberofcells)
644 recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE));
645 SetWidthOfMulticolCell(cell, new_width);
649 /* returns 1 if a complete update is necessary, otherwise 0 */
650 bool LyXTabular::SetWidthOfCell(int cell, int new_width)
652 int row = row_of_cell(cell);
653 int column1 = column_of_cell(cell);
657 if (IsMultiColumn(cell)) {
658 tmp = SetWidthOfMulticolCell(cell, new_width);
660 width = (new_width + 2*WIDTH_OF_LINE);
661 cell_info[row][column1].width_of_cell = width;
662 if (column_info[column1].right_line && (column1 < columns_-1) &&
663 column_info[column1+1].left_line) // additional width
664 cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
665 tmp = calculate_width_of_column_NMC(column1);
669 for(i = 0; i<columns_;++i)
670 calculate_width_of_column_NMC(i);
671 for(i = 0; (i<numberofcells) && !IsMultiColumn(i); ++i)
674 recalculateMulticolCells(i, GetWidthOfCell(i)-(2*WIDTH_OF_LINE));
675 for(i = 0; i<columns_;++i)
676 calculate_width_of_column(i);
677 calculate_width_of_tabular();
684 bool LyXTabular::SetAlignment(int cell, char align)
686 if (!IsMultiColumn(cell))
687 column_info[column_of_cell(cell)].alignment = align;
688 cellinfo_of_cell(cell)->alignment = align;
692 bool LyXTabular::SetPWidth(int cell, string width)
694 if (IsMultiColumn(cell)) {
695 // if (column_info[column_of_cell(cell)].p_width.empty())
696 // column_info[column_of_cell(cell)].p_width = width;
697 cellinfo_of_cell(cell)->p_width = width;
699 column_info[column_of_cell(cell)].p_width = width;
700 if (!width.empty()) // do this only if there is a width
701 SetAlignment(cell, LYX_ALIGN_LEFT);
706 bool LyXTabular::SetAlignSpecial(int cell, string special, int what)
708 if (what == SET_SPECIAL_MULTI)
709 cellinfo_of_cell(cell)->align_special = special;
711 column_info[column_of_cell(cell)].align_special = special;
715 bool LyXTabular::SetAllLines(int cell, bool line)
717 SetTopLine(cell, line);
718 SetBottomLine(cell, line);
719 SetRightLine(cell, line);
720 SetLeftLine(cell, line);
724 bool LyXTabular::SetTopLine(int cell, bool line)
726 int row = row_of_cell(cell);
728 if (!IsMultiColumn(cell))
729 row_info[row].top_line = line;
731 cellinfo_of_cell(cell)->top_line = line;
736 bool LyXTabular::SetBottomLine(int cell, bool line)
738 if (!IsMultiColumn(cell))
739 row_info[row_of_cell(cell)].bottom_line = line;
741 cellinfo_of_cell(cell)->bottom_line = line;
746 bool LyXTabular::SetLeftLine(int cell, bool line)
748 column_info[column_of_cell(cell)].left_line = line;
753 bool LyXTabular::SetRightLine(int cell, bool line)
755 column_info[right_column_of_cell(cell)].right_line = line;
760 char LyXTabular::GetAlignment(int cell)
762 if (IsMultiColumn(cell))
763 return cellinfo_of_cell(cell)->alignment;
765 return column_info[column_of_cell(cell)].alignment;
768 string LyXTabular::GetPWidth(int cell)
770 if (IsMultiColumn(cell))
771 return cellinfo_of_cell(cell)->p_width;
772 return column_info[column_of_cell(cell)].p_width;
775 string LyXTabular::GetAlignSpecial(int cell, int what)
777 if (what == SET_SPECIAL_MULTI)
778 return cellinfo_of_cell(cell)->align_special;
779 return column_info[column_of_cell(cell)].align_special;
782 int LyXTabular::GetWidthOfCell(int cell)
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;
793 result += AdditionalWidth(cell);
799 int LyXTabular::GetBeginningOfTextInCell(int cell)
803 switch (GetAlignment(cell)){
804 case LYX_ALIGN_CENTER:
805 x += (WidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
807 case LYX_ALIGN_RIGHT:
808 x += WidthOfColumn(cell) - GetWidthOfCell(cell) + AdditionalWidth(cell);
810 default: /* LYX_ALIGN_LEFT: nothing :-) */
820 bool LyXTabular::IsFirstCellInRow(int cell)
822 return (column_of_cell(cell) == 0);
825 bool LyXTabular::IsLastCellInRow(int cell)
827 return (right_column_of_cell(cell) == (columns_ - 1));
831 bool LyXTabular::calculate_width_of_column(int column)
833 int old_column_width = column_info[column].width_of_column;
836 for (int i = 0; i < rows_; ++i) {
837 maximum = max(cell_info[i][column].width_of_cell, maximum);
839 column_info[column].width_of_column = maximum;
840 return (column_info[column].width_of_column != old_column_width);
843 bool LyXTabular::calculate_width_of_column_NMC(int column)
845 int old_column_width = column_info[column].width_of_column;
847 for (int i = 0; i < rows_; ++i) {
848 if (!IsMultiColumn(GetCellNumber(column, i)) &&
849 (cell_info[i][column].width_of_cell > max)) {
850 max = cell_info[i][column].width_of_cell;
853 column_info[column].width_of_column = max;
854 return (column_info[column].width_of_column != old_column_width);
857 void LyXTabular::calculate_width_of_tabular()
859 width_of_tabular = 0;
860 for (int i = 0; i < columns_; ++i) {
861 width_of_tabular += column_info[i].width_of_column;
866 int LyXTabular::row_of_cell(int cell) const
868 if (cell >= numberofcells)
872 return rowofcell[cell];
876 int LyXTabular::column_of_cell(int cell) const
878 if (cell >= numberofcells)
882 return columnofcell[cell];
886 int LyXTabular::right_column_of_cell(int cell)
888 int row = row_of_cell(cell);
889 int column = column_of_cell(cell);
890 while (column < (columns_ - 1) &&
891 cell_info[row][column+1].multicolumn == LyXTabular::CELL_PART_OF_MULTICOLUMN)
897 void LyXTabular::Write(ostream & os, bool old_format)
902 << rows_ << " " << columns_ << " " << is_long_tabular << " "
903 << rotate << " " << endhead << " " << endfirsthead << " "
904 << endfoot << " " << endlastfoot << "\n";
905 for (i = 0; i < rows_; ++i) {
906 os << row_info[i].top_line << " "
907 << row_info[i].bottom_line << " "
908 << row_info[i].newpage << "\n";
910 for (i = 0; i < columns_; ++i) {
911 os << column_info[i].alignment << " "
912 << column_info[i].left_line << " "
913 << column_info[i].right_line << " \""
914 << VSpace(column_info[i].p_width).asLyXCommand() << "\" \""
915 << column_info[i].align_special << "\"\n";
918 for (i = 0; i < rows_; ++i) {
919 for (j = 0; j < columns_; ++j) {
920 os << cell_info[i][j].multicolumn << " "
921 << cell_info[i][j].alignment << " "
922 << cell_info[i][j].top_line << " "
923 << cell_info[i][j].bottom_line << " "
924 << cell_info[i][j].rotate << " "
925 << cell_info[i][j].linebreaks << " \""
926 << cell_info[i][j].align_special << "\" \""
927 << cell_info[i][j].p_width << "\"\n";
931 lyxerr << "New format type not yet implemented!!!\n" << endl;
936 void LyXTabular::Read(istream & is)
942 int is_long_tabular_arg = false;
943 int rotate_arg = false;
956 version = atoi(s.c_str() + 8);
960 lyxerr << "Tabular format < 5 is not supported anymore\n"
961 "Get an older version of LyX (< 1.1.x) for conversion!"
963 WriteAlert(_("Warning:"),
964 _("Tabular format < 5 is not supported anymore\n"),
965 _("Get an older version of LyX (< 1.1.x) for conversion!"));
967 is >> rows_arg >> columns_arg >> is_long_tabular_arg
968 >> rotate_arg >> a >> b >> c >> d;
970 is >> rows_arg >> columns_arg;
971 Init(rows_arg, columns_arg);
972 SetLongTabular(is_long_tabular_arg);
973 SetRotateTabular(rotate_arg);
975 for (i = 0; i < rows_; ++i) {
978 for (i = 0; i < columns_; ++i) {
981 for (i = 0; i < rows_; ++i) {
982 for (j = 0; j < columns_; ++j) {
986 set_row_column_number_info();
989 is >> rows_arg >> columns_arg >> is_long_tabular_arg
990 >> rotate_arg >> a >> b >> c >> d;
991 Init(rows_arg, columns_arg);
992 SetLongTabular(is_long_tabular_arg);
993 SetRotateTabular(rotate_arg);
998 for (i = 0; i < rows_; ++i) {
999 a = b = c = d = e = f = g = h = 0;
1000 is >> a >> b >> c >> d;
1001 row_info[i].top_line = a;
1002 row_info[i].bottom_line = b;
1003 // row_info[i].is_cont_row = c;
1004 row_info[i].newpage = d;
1006 for (i = 0; i < columns_; ++i) {
1010 char ch; // skip '"'
1012 getline(is, s1, '"');
1013 is >> ch; // skip '"'
1014 getline(is, s2, '"');
1015 column_info[i].alignment = static_cast<char>(a);
1016 column_info[i].left_line = b;
1017 column_info[i].right_line = c;
1018 column_info[i].p_width = s1;
1019 column_info[i].align_special = s2;
1021 for (i = 0; i < rows_; ++i) {
1022 for (j = 0; j < columns_; ++j) {
1025 is >> a >> b >> c >> d >> e >> f >> g;
1027 is >> ch; // skip '"'
1028 getline(is, s1, '"');
1029 is >> ch; // skip '"'
1030 getline(is, s2, '"');
1031 cell_info[i][j].multicolumn = static_cast<char>(a);
1032 cell_info[i][j].alignment = static_cast<char>(b);
1033 cell_info[i][j].top_line = static_cast<char>(c);
1034 cell_info[i][j].bottom_line = static_cast<char>(d);
1035 // cell_info[i][j].has_cont_row = static_cast<bool>(e);
1036 cell_info[i][j].rotate = static_cast<bool>(f);
1037 cell_info[i][j].linebreaks = static_cast<bool>(g);
1038 cell_info[i][j].align_special = s1;
1039 cell_info[i][j].p_width = s2;
1042 set_row_column_number_info();
1046 // cell <0 will tex the preamble
1047 // returns the number of printed newlines
1048 int LyXTabular::TexEndOfCell(ostream & os, int cell)
1054 if (ShouldBeVeryLastCell(cell)) {
1055 // the very end at the very beginning
1056 if (Linebreaks(cell))
1057 os << "\\smallskip{}}";
1058 if (IsMultiColumn(cell))
1060 if (RotateCell(cell)) {
1061 os << "\n\\end{sideways}";
1069 while (!IsFirstCellInRow(fcell)) --fcell;
1070 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1071 if (BottomLine(fcell + i))
1074 if (tmp == NumberOfCellsInRow(fcell)) {
1078 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1079 if (BottomLine(fcell + i)) {
1081 << column_of_cell(fcell + i) + 1
1083 << right_column_of_cell(fcell + i) + 1
1093 if (is_long_tabular)
1094 os << "\\end{longtable}";
1096 os << "\\end{tabular}";
1098 os << "\n\\end{sideways}";
1106 os << "\\begin{sideways}\n";
1109 if (is_long_tabular)
1110 os << "\\begin{longtable}{";
1112 os << "\\begin{tabular}{";
1113 for (i = 0; i < columns_; ++i) {
1114 if (column_info[i].left_line)
1116 if (!column_info[i].align_special.empty()) {
1117 os << column_info[i].align_special;
1118 } else if (!column_info[i].p_width.empty()) {
1120 << column_info[i].p_width
1123 switch (column_info[i].alignment) {
1124 case LYX_ALIGN_LEFT:
1127 case LYX_ALIGN_RIGHT:
1135 if (column_info[i].right_line)
1141 if (GetNumberOfCells()) {
1143 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1144 if (TopLine(fcell + i))
1147 if (tmp == NumberOfCellsInRow(fcell)){
1151 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1152 if (TopLine(fcell + i)) {
1154 << column_of_cell(fcell + i) + 1
1156 << right_column_of_cell(fcell + i) + 1
1167 if (RotateCell(0)) {
1168 os << "\\begin{sideways}\n";
1173 if (Linebreaks(cell))
1174 os << "\\smallskip{}}";
1175 if (IsMultiColumn(cell)){
1178 if (RotateCell(cell)) {
1179 os << "\n\\end{sideways}";
1182 if (IsLastCellInRow(cell)) {
1183 int row = row_of_cell(cell);
1184 string hline1, hline2;
1185 bool print_hline = true;
1186 bool flag1 = IsLongTabular() &&
1187 ((row == endhead) || (row == endfirsthead) ||
1188 (row == endfoot) || (row == endlastfoot));
1190 bool flag2 = IsLongTabular() &&
1191 ((row <= endhead) || (row <= endfirsthead) ||
1192 (row <= endfoot) || (row <= endlastfoot));
1194 // print the bottom hline only if (otherwise it is doubled):
1195 // - is no LongTabular
1196 // - there IS a first-header
1197 // - the next row is no special header/footer
1198 // & this row is no special header/footer
1199 // - the next row is a special header/footer
1200 // & this row is a special header/footer
1201 bool pr_top_hline = (flag1 && flag2) || (!flag1 && !flag2) ||
1202 (endfirsthead == endhead);
1207 while (!IsFirstCellInRow(fcell))
1209 for (i = 0; i < NumberOfCellsInRow(cell); ++i) {
1210 if (BottomLine(fcell + i))
1213 if (tmp == NumberOfCellsInRow(cell)){
1215 hline1 = "\\hline ";
1218 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1219 if (BottomLine(fcell + i)){
1221 << column_of_cell(fcell + i) + 1
1223 << right_column_of_cell(fcell + i) + 1
1225 hline1 += "\\cline{";
1226 hline1 += tostr(column_of_cell(fcell + i) + 1);
1228 hline1 += tostr(right_column_of_cell(fcell + i) + 1);
1238 if (IsLongTabular() && (row == endfoot)) {
1239 os << "\\endfoot\n";
1241 print_hline = false; // no double line below footer
1243 if (IsLongTabular() && (row == endlastfoot)) {
1244 os << "\\endlastfoot\n";
1246 print_hline = false; // no double line below footer
1248 if (IsLongTabular() && row_info[row].newpage) {
1249 os << "\\newpage\n";
1251 print_hline = false; // no line below a \\newpage-command
1254 if (nvcell < numberofcells
1255 && (cell < GetNumberOfCells() - 1)
1256 && !ShouldBeVeryLastCell(cell)) {
1258 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1259 if (TopLine(fcell + i))
1262 if (tmp == NumberOfCellsInRow(fcell)) {
1265 hline2 = "\\hline ";
1268 for (i = 0; i < NumberOfCellsInRow(fcell); ++i) {
1269 if (TopLine(fcell + i)) {
1272 << column_of_cell(fcell + i) + 1
1274 << right_column_of_cell(fcell + i) + 1
1277 hline2 += "\\cline{";
1278 hline2 += tostr(column_of_cell(fcell+i)+1);
1280 hline2 += tostr(right_column_of_cell(fcell+i)+1);
1286 if (tmp && print_hline){
1291 // the order here is important as if one defines two
1292 // or more things in one line only the first entry is
1293 // displayed the other are set to an empty-row. This
1294 // is important if I have a footer and want that the
1295 // lastfooter is NOT displayed!!!
1296 bool sflag2 = (row == endhead) || (row == endfirsthead) ||
1297 (row == endfoot) || (row == endlastfoot);
1299 // sflag2 = IsLongTabular() && (row >= 0) &&
1300 // (sflag2 || (row == endhead) || (row == endfirsthead));
1302 bool sflag1 = IsLongTabular() && (row != endhead) &&
1303 (row != endfirsthead) &&
1304 ((row == endfoot) || (row == endlastfoot));
1306 if (IsLongTabular() && (row == endhead)) {
1307 os << "\\endhead\n";
1310 if (IsLongTabular() && (row == endfirsthead)) {
1311 os << "\\endfirsthead\n";
1314 if (sflag1) { // add the \hline for next foot row
1315 if (!hline1.empty()) {
1316 os << hline1 + '\n';
1320 // add the \hline for the first row
1321 if (pr_top_hline && sflag2) {
1322 if (!hline2.empty()) {
1323 os << hline2 + '\n';
1327 if (nvcell < numberofcells && RotateCell(nvcell)) {
1328 os << "\\begin{sideways}\n";
1334 if (nvcell < numberofcells && RotateCell(nvcell)) {
1335 os << "\\begin{sideways}\n";
1340 if (nvcell < numberofcells && IsMultiColumn(nvcell)) {
1341 os << "\\multicolumn{"
1342 << cells_in_multicolumn(nvcell)
1344 if (!cellinfo_of_cell(cell+1)->align_special.empty()) {
1345 os << cellinfo_of_cell(cell+1)->align_special
1348 if (LeftLine(nvcell))
1350 if (!GetPWidth(nvcell).empty()) {
1352 << GetPWidth(nvcell)
1355 switch (GetAlignment(nvcell)) {
1356 case LYX_ALIGN_LEFT: os << 'l'; break;
1357 case LYX_ALIGN_RIGHT: os << 'r'; break;
1358 default: os << 'c'; break;
1361 if (RightLine(nvcell))
1363 //if (column_of_cell(cell+2)!= 0 && LeftLine(cell+2))
1364 if (((nvcell + 1) < numberofcells) &&
1365 ((nvcell+1) < numberofcells) &&
1366 (column_of_cell(nvcell+1)!= 0) &&
1373 if (nvcell < numberofcells && Linebreaks(nvcell)) {
1374 // !column_info[column_of_cell(nvcell)].p_width.empty()) {
1376 << GetPWidth(nvcell)
1377 << "}{\\smallskip{}";
1385 // cell <0 will tex the preamble
1386 // returns the number of printed newlines
1387 int LyXTabular::RoffEndOfCell(ostream & os, int cell)
1391 if (cell == GetNumberOfCells() - 1){
1392 // the very end at the very beginning
1393 // if (CellHasContRow(cell) >= 0) {
1399 if (row_info[row_of_cell(cell)].bottom_line) {
1403 os << ".TE\n.pl 1c";
1408 os << "\n.pl 500c\n.TS\n";
1409 for (int j = 0; j < rows_; ++j) {
1410 for (int i = 0; i < columns_; ++i, ++fcell) {
1411 if (column_info[i].left_line)
1413 if (cell_info[j][i].multicolumn == CELL_PART_OF_MULTICOLUMN)
1416 switch (column_info[i].alignment) {
1417 case LYX_ALIGN_LEFT:
1420 case LYX_ALIGN_RIGHT:
1428 if (!column_info[i].p_width.empty())
1429 os << "w(" << column_info[i].p_width << ")";
1430 if (column_info[i].right_line)
1433 if ((j + 1) < rows_) {
1440 if (row_info[0].top_line) {
1444 // if (CellHasContRow(0) >= 0) {
1450 // if (CellHasContRow(cell) >= 0) {
1454 if (right_column_of_cell(cell) == columns_ -1){
1457 int row = row_of_cell(cell);
1458 if (row_info[row++].bottom_line) {
1462 if ((row < rows_) && row_info[row].top_line) {
1468 // if ((cell < GetNumberOfCells() - 1) &&
1469 // (CellHasContRow(cell+1) >= 0)) {
1480 char const *LyXTabular::getDocBookAlign(int cell, bool isColumn)
1486 i = column_of_cell(cell);
1487 if (!isColumn && IsMultiColumn(cell)) {
1488 if (!cellinfo_of_cell(cell)->align_special.empty()) {
1489 return cellinfo_of_cell(cell)->align_special.c_str();
1491 switch (GetAlignment(cell)) {
1492 case LYX_ALIGN_LEFT:
1494 case LYX_ALIGN_RIGHT:
1501 if (!column_info[i].align_special.empty()) {
1502 return column_info[i].align_special.c_str();
1504 #ifdef IGNORE_THIS_FOR_NOW
1505 else if (!column_info[i].p_width.empty()) {
1507 file += column_info[i].p_width;
1512 switch (column_info[i].alignment) {
1513 case LYX_ALIGN_LEFT:
1515 case LYX_ALIGN_RIGHT:
1525 // cell <0 will tex the preamble
1526 // returns the number of printed newlines
1527 int LyXTabular::DocBookEndOfCell(ostream & os, int cell, int & depth)
1531 //int tmp; // tmp2; //Â unused
1532 int nvcell; // fcell; //Â unused
1533 if (ShouldBeVeryLastCell(cell)) {
1534 os << newlineAndDepth(--depth)
1536 << newlineAndDepth(--depth)
1538 << newlineAndDepth(--depth)
1540 << newlineAndDepth(--depth);
1541 if (is_long_tabular)
1545 << newlineAndDepth(--depth);
1551 if (is_long_tabular)
1557 << "' COLSEP='1' ROWSEP='1'>"
1558 << newlineAndDepth(++depth);
1560 for (i = 0; i < columns_; ++i) {
1561 os << "<COLSPEC ALIGN='"
1562 << getDocBookAlign(i, true)
1568 if (i == (columns_-1)) {
1571 if (column_info[i].right_line ||
1572 column_info[i+1].left_line)
1578 << newlineAndDepth(depth);
1580 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1581 if (column_info[i].left_line)
1586 << newlineAndDepth(++depth)
1588 << newlineAndDepth(++depth)
1590 << getDocBookAlign(0)
1592 if (IsMultiColumn(0)) {
1593 os << " NAMEST='col1' NAMEEND='col"
1594 << cells_in_multicolumn(0)
1598 << newlineAndDepth(++depth);
1601 if (IsLastCellInRow(cell)) {
1602 os << newlineAndDepth(--depth)
1604 << newlineAndDepth(--depth)
1606 << newlineAndDepth(depth)
1608 << newlineAndDepth(++depth)
1610 << getDocBookAlign(cell + 1)
1611 << "' VALIGN='middle'";
1612 if (IsMultiColumn(cell + 1)) {
1613 os << " NAMEST='col"
1614 << column_of_cell(cell+1) + 1
1616 << column_of_cell(cell + 1) +
1617 cells_in_multicolumn(cell + 1)
1621 << newlineAndDepth(++depth);
1624 os << newlineAndDepth(--depth)
1626 << newlineAndDepth(depth)
1628 << getDocBookAlign(cell + 1)
1629 << "' VALIGN='middle'";
1630 if (IsMultiColumn(cell + 1)) {
1631 os << " NAMEST='col"
1632 << column_of_cell(cell+1) + 1
1634 << column_of_cell(cell+1) +
1635 cells_in_multicolumn(cell+1)
1639 << newlineAndDepth(++depth);
1648 bool LyXTabular::IsMultiColumn(int cell)
1650 return (cellinfo_of_cell(cell)->multicolumn != LyXTabular::CELL_NORMAL);
1654 LyXTabular::cellstruct* LyXTabular::cellinfo_of_cell(int cell)
1656 int row = row_of_cell(cell);
1657 int column = column_of_cell(cell);
1658 return &cell_info[row][column];
1662 void LyXTabular::SetMultiColumn(int cell, int number)
1664 int new_width = cellinfo_of_cell(cell)->width_of_cell;
1666 cellinfo_of_cell(cell)->multicolumn = LyXTabular::CELL_BEGIN_OF_MULTICOLUMN;
1667 cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
1668 cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
1669 cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
1670 for (number--; number > 0; --number) {
1671 cellinfo_of_cell(cell+number)->multicolumn =
1672 LyXTabular::CELL_PART_OF_MULTICOLUMN;
1673 new_width += cellinfo_of_cell(cell+number)->width_of_cell;
1675 set_row_column_number_info();
1676 SetWidthOfCell(cell, new_width);
1680 int LyXTabular::cells_in_multicolumn(int cell)
1682 int row = row_of_cell(cell);
1683 int column = column_of_cell(cell);
1686 while (column < columns_ && cell_info[row][column].multicolumn
1687 == LyXTabular::CELL_PART_OF_MULTICOLUMN){
1695 int LyXTabular::UnsetMultiColumn(int cell)
1697 int row = row_of_cell(cell);
1698 int column = column_of_cell(cell);
1702 if (cell_info[row][column].multicolumn
1703 == LyXTabular::CELL_BEGIN_OF_MULTICOLUMN){
1704 cell_info[row][column].multicolumn = LyXTabular::CELL_NORMAL;
1706 while (column < columns_ &&
1707 cell_info[row][column].multicolumn
1708 == LyXTabular::CELL_PART_OF_MULTICOLUMN){
1709 cell_info[row][column].multicolumn =
1710 LyXTabular::CELL_NORMAL;
1715 set_row_column_number_info();
1720 void LyXTabular::delete_column(int column)
1723 columnstruct * column_info2 = new columnstruct[columns_-1];
1725 for (i = 0; i < column; ++i) {
1726 column_info2[i] = column_info[i];
1728 for (i = column; i < columns_ - 1; ++i) {
1729 column_info2[i] = column_info[i + 1];
1732 delete[] column_info;
1733 column_info = column_info2;
1735 for (i = 0; i < rows_; ++i) {
1736 cellstruct * tmp = cell_info[i];
1737 cell_info[i] = new cellstruct[columns_ - 1];
1738 for (j = 0; j < column; ++j) {
1739 cell_info[i][j] = tmp[j];
1741 for (j = column; j < columns_ - 1; ++j) {
1742 cell_info[i][j] = tmp[j + 1];
1752 void LyXTabular::SetLongTabular(int what)
1754 is_long_tabular = what;
1758 bool LyXTabular::IsLongTabular()
1760 return is_long_tabular;
1763 void LyXTabular::SetRotateTabular(int what)
1768 bool LyXTabular::RotateTabular()
1773 void LyXTabular::SetRotateCell(int cell, int what)
1775 cellinfo_of_cell(cell)->rotate = what;
1778 bool LyXTabular::RotateCell(int cell)
1780 return cellinfo_of_cell(cell)->rotate;
1783 bool LyXTabular::NeedRotating()
1787 for (int i = 0; i < rows_; ++i) {
1788 for (int j = 0; j < columns_; ++j) {
1789 if (cell_info[i][j].rotate)
1797 bool LyXTabular::ShouldBeVeryLastCell(int cell)
1798 // "very last cell" ..of what? the row? the tabular?
1799 // "Cell" in this context appears to not count `virtual' cells
1801 if (cell < GetNumberOfCells())
1806 bool LyXTabular::IsLastRow(int cell)
1808 if (row_of_cell(cell) < rows_)
1813 int LyXTabular::GetCellAbove(int cell)
1815 if (row_of_cell(cell) > 0)
1816 return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
1820 int LyXTabular::GetCellNumber(int column, int row)
1822 if (column >= columns_)
1823 column = columns_ - 1;
1824 else if (column < 0)
1831 return cell_info[row][column].cellno;
1834 void LyXTabular::SetLinebreaks(int cell, bool what)
1836 cellinfo_of_cell(cell)->linebreaks = what;
1839 bool LyXTabular::Linebreaks(int cell)
1841 if (column_info[column_of_cell(cell)].p_width.empty() &&
1842 !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty()))
1844 return cellinfo_of_cell(cell)->linebreaks;
1847 void LyXTabular::SetLTHead(int cell, bool first)
1849 int row = row_of_cell(cell);
1852 if (row == endfirsthead)
1864 bool LyXTabular::RowOfLTHead(int cell)
1866 if ((endhead+1) > rows_)
1868 return (row_of_cell(cell) == endhead);
1871 bool LyXTabular::RowOfLTFirstHead(int cell)
1873 if ((endfirsthead+1) > rows_)
1875 return (row_of_cell(cell) == endfirsthead);
1878 void LyXTabular::SetLTFoot(int cell, bool last)
1880 int row = row_of_cell(cell);
1883 if (row == endlastfoot)
1895 bool LyXTabular::RowOfLTFoot(int cell)
1897 if ((endfoot+1) > rows_) {
1901 return (row_of_cell(cell) == endfoot);
1904 bool LyXTabular::RowOfLTLastFoot(int cell)
1906 if ((endlastfoot+1) > rows_)
1908 return (row_of_cell(cell) == endlastfoot);
1911 void LyXTabular::SetLTNewPage(int cell, bool what)
1913 row_info[row_of_cell(cell)].newpage = what;
1916 bool LyXTabular::LTNewPage(int cell)
1918 return row_info[row_of_cell(cell)].newpage;
1921 void LyXTabular::SetAscentOfRow(int row, int height)
1925 row_info[row].ascent_of_row = height;
1928 void LyXTabular::SetDescentOfRow(int row, int height)
1932 row_info[row].descent_of_row = height;
1935 int LyXTabular::AscentOfRow(int row)
1939 return row_info[row].ascent_of_row;
1942 int LyXTabular::DescentOfRow(int row)
1946 return row_info[row].descent_of_row;
1949 int LyXTabular::HeightOfTabular()
1955 for(row=0,height=0;(row<rows_); ++row)
1956 height += AscentOfRow(row) + DescentOfRow(row) +
1957 AdditionalHeight(GetCellNumber(0,row));
1961 bool LyXTabular::IsPartOfMultiColumn(int row, int column)
1963 if ((row >= rows_) || (column >= columns_))
1965 return (cell_info[row][column].multicolumn==CELL_PART_OF_MULTICOLUMN);
1968 int LyXTabular::Latex(ostream &)
1973 InsetText * LyXTabular::GetCellInset(int cell) const
1975 return cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;