1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
8 * @author: Jürgen Vigna
10 * ======================================================
16 #pragma implementation
26 #include "lyx_gui_misc.h"
28 #include "BufferView.h"
30 #include "LaTeXFeatures.h"
31 #include "support/lstrings.h"
32 #include "support/lyxmanip.h"
33 #include "insets/insettabular.h"
34 #include "insets/insettext.h"
43 static int const WIDTH_OF_LINE = 5;
45 /// Define a few methods for the inner structs
47 LyXTabular::cellstruct::cellstruct()
51 multicolumn = LyXTabular::CELL_NORMAL;
52 alignment = LYX_ALIGN_CENTER;
53 valignment = LYX_VALIGN_TOP;
63 LyXTabular::rowstruct::rowstruct()
73 LyXTabular::columnstruct::columnstruct()
77 alignment = LYX_ALIGN_CENTER;
78 valignment = LYX_VALIGN_TOP;
84 LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
87 Init(rows_arg, columns_arg);
91 LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt)
94 Init(lt.rows_, lt.columns_);
96 #warning Jürgen, can you make it the other way round. So that copy assignment depends on the copy constructor and not the other way. (Lgb)
102 LyXTabular::LyXTabular(Buffer const * buf, InsetTabular * inset, LyXLex & lex)
109 LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
111 // If this and lt is not of the same size we have a serious bug
112 // So then it is ok to throw an exception, or for now
114 Assert(rows_ == lt.rows_ && columns_ == lt.columns_);
116 cell_info = lt.cell_info;
117 row_info = lt.row_info;
118 column_info = lt.column_info;
120 // long tabular stuff
121 SetLongTabular(lt.is_long_tabular);
122 endhead = lt.endhead;
123 endfoot = lt.endfoot;
124 endfirsthead = lt.endfirsthead;
125 endlastfoot = lt.endlastfoot;
135 LyXTabular * LyXTabular::Clone(InsetTabular * inset)
137 LyXTabular * result = new LyXTabular(inset, *this);
138 // don't know if this is good but I need to Clone also
139 // the text-insets here, this is for the Undo-facility!
140 for (int i = 0; i < rows_; ++i) {
141 for (int j = 0; j < columns_; ++j) {
142 result->cell_info[i][j].inset = cell_info[i][j].inset;
143 result->cell_info[i][j].inset.setOwner(inset);
150 /* activates all lines and sets all widths to 0 */
151 void LyXTabular::Init(int rows_arg, int columns_arg)
154 columns_ = columns_arg;
155 row_info = row_vector(rows_, rowstruct());
156 column_info = column_vector(columns_, columnstruct());
157 cell_info = cell_vvector(rows_, cell_vector(columns_, cellstruct()));
160 for (int i = 0; i < rows_; ++i) {
161 for (int j = 0; j < columns_; ++j) {
162 cell_info[i][j].inset.setOwner(owner_);
163 cell_info[i][j].inset.SetDrawFrame(0, InsetText::LOCKED);
164 cell_info[i][j].cellno = cellno++;
166 cell_info[i].back().right_line = true;
168 row_info.back().bottom_line = true;
169 row_info.front().bottom_line = true;
171 for (int i = 0; i < columns_; ++i) {
172 calculate_width_of_column(i);
174 column_info.back().right_line = true;
176 calculate_width_of_tabular();
178 rowofcell = vector<int>();
179 columnofcell = vector<int>();
180 set_row_column_number_info();
181 is_long_tabular = false;
190 void LyXTabular::AppendRow(int cell)
194 int row = row_of_cell(cell);
196 row_vector::iterator rit = row_info.begin() + row;
197 row_info.insert(rit, rowstruct());
200 cell_vvector::iterator cit = cell_info.begin() + row;
201 cell_info.insert(cit, vector<cellstruct>(columns_, cellstruct()));
203 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
206 for (int i = 0; i <= row; ++i) {
207 for (int j = 0; j < columns_; ++j) {
208 c_info[i][j] = cell_info[i][j];
211 for (int i = row + 1; i < rows_; ++i) {
212 for (int j = 0; j < columns_; ++j) {
213 c_info[i][j] = cell_info[i-1][j];
218 for (int j = 0; j < columns_; ++j) {
219 cell_info[row][j].inset.clear();
226 void LyXTabular::DeleteRow(int row)
228 // Why make it so hard? (Lgb)
231 if (rows_ == 1) return; // Not allowed to delete last row
233 row_info.erase(row_info.begin() + row); //&row_info[row]);
234 cell_info.erase(cell_info.begin() + row); //&cell_info[row]);
240 void LyXTabular::AppendColumn(int cell)
244 cell_vvector c_info = cell_vvector(rows_, cell_vector(columns_,
246 int const column = column_of_cell(cell);
247 column_vector::iterator cit = column_info.begin() + column + 1;
248 column_info.insert(cit, columnstruct());
250 for (int i = 0; i < rows_; ++i) {
251 for (int j = 0; j <= column; ++j) {
252 c_info[i][j] = cell_info[i][j];
254 for (int j = column + 1; j < columns_; ++j) {
255 c_info[i][j] = cell_info[i][j - 1];
257 // care about multicolumns
258 if (cell_info[i][column + 1].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
259 cell_info[i][column + 1].multicolumn = CELL_PART_OF_MULTICOLUMN;
261 if ((column + 1) == columns_ ||
262 cell_info[i][column + 2].multicolumn != CELL_PART_OF_MULTICOLUMN) {
263 cell_info[i][column + 1].multicolumn = LyXTabular::CELL_NORMAL;
268 for (int i = 0; i < rows_; ++i) {
269 //cell_info[i][column].inset.clear();
270 cell_info[i][column + 1].inset.clear();
276 void LyXTabular::DeleteColumn(int column)
278 // Similar to DeleteRow
279 //if (!(columns_ - 1))
281 if (columns_ == 1) return; // Not allowed to delete last column
283 column_info.erase(column_info.begin() + column);
284 for (int i = 0; i < rows_; ++i) {
285 cell_info[i].erase(cell_info[i].begin() + column);
292 void LyXTabular::Reinit()
294 for (int i = 0; i < rows_; ++i) {
295 for (int j = 0; j < columns_; ++j) {
296 cell_info[i][j].width_of_cell = 0;
297 cell_info[i][j].inset.setOwner(owner_);
301 for (int i = 0; i < columns_; ++i) {
302 calculate_width_of_column(i);
304 calculate_width_of_tabular();
306 set_row_column_number_info();
310 void LyXTabular::set_row_column_number_info(bool oldformat)
313 for (int row = 0; row < rows_; ++row) {
314 for (int column = 0; column<columns_; ++column) {
315 if (cell_info[row][column].multicolumn
316 != LyXTabular::CELL_PART_OF_MULTICOLUMN)
318 cell_info[row][column].cellno = numberofcells;
321 ++numberofcells; // because this is one more than as we start from 0
323 rowofcell.resize(numberofcells);
324 columnofcell.resize(numberofcells);
326 for (int row = 0, column = 0, c = 0;
327 c < numberofcells && row < rows_ && column < columns_;) {
329 columnofcell[c] = column;
333 } while (column < columns_ &&
334 cell_info[row][column].multicolumn
335 == LyXTabular::CELL_PART_OF_MULTICOLUMN);
336 if (column == columns_) {
342 for (int row = 0; row < rows_; ++row) {
343 for (int column = 0; column < columns_; ++column) {
344 if (IsPartOfMultiColumn(row,column))
346 // now set the right line of multicolumns right for oldformat read
348 cell_info[row][column].multicolumn==CELL_BEGIN_OF_MULTICOLUMN)
350 int cn=cells_in_multicolumn(cell_info[row][column].cellno);
351 cell_info[row][column].right_line =
352 cell_info[row][column+cn-1].right_line;
354 cell_info[row][column].inset.SetAutoBreakRows(
355 !GetPWidth(GetCellNumber(row, column)).empty());
361 int LyXTabular::GetNumberOfCells() const
363 return numberofcells;
367 int LyXTabular::NumberOfCellsInRow(int cell) const
369 int const row = row_of_cell(cell);
371 for (int i = 0; i < columns_; ++i) {
372 if (cell_info[row][i].multicolumn != LyXTabular::CELL_PART_OF_MULTICOLUMN)
379 /* returns 1 if there is a topline, returns 0 if not */
380 bool LyXTabular::TopLine(int cell, bool onlycolumn) const
382 int const row = row_of_cell(cell);
384 if (!onlycolumn && IsMultiColumn(cell))
385 return cellinfo_of_cell(cell)->top_line;
386 return row_info[row].top_line;
390 bool LyXTabular::BottomLine(int cell, bool onlycolumn) const
392 // no bottom line underneath non-existent cells if you please
393 // Isn't that a programming error? Is so this should
394 // be an Assert instead. (Lgb)
395 if (cell >= numberofcells)
398 if (!onlycolumn && IsMultiColumn(cell))
399 return cellinfo_of_cell(cell)->bottom_line;
400 return row_info[row_of_cell(cell)].bottom_line;
404 bool LyXTabular::LeftLine(int cell, bool onlycolumn) const
406 if (!onlycolumn && IsMultiColumn(cell))
407 return cellinfo_of_cell(cell)->left_line;
408 return column_info[column_of_cell(cell)].left_line;
412 bool LyXTabular::RightLine(int cell, bool onlycolumn) const
414 if (!onlycolumn && IsMultiColumn(cell))
415 return cellinfo_of_cell(cell)->right_line;
416 return column_info[right_column_of_cell(cell)].right_line;
420 bool LyXTabular::TopAlreadyDrawed(int cell) const
422 if (GetAdditionalHeight(cell))
424 int row = row_of_cell(cell);
426 int column = column_of_cell(cell);
429 && cell_info[row][column].multicolumn
430 == LyXTabular::CELL_PART_OF_MULTICOLUMN)
432 if (cell_info[row][column].multicolumn == LyXTabular::CELL_NORMAL)
433 return row_info[row].bottom_line;
435 return cell_info[row][column].bottom_line;
441 bool LyXTabular::LeftAlreadyDrawed(int cell) const
443 int column = column_of_cell(cell);
445 int row = row_of_cell(cell);
447 (cell_info[row][column].multicolumn ==
448 LyXTabular::CELL_PART_OF_MULTICOLUMN));
449 if (GetAdditionalWidth(cell_info[row][column].cellno))
451 return column_info[column].right_line;
457 bool LyXTabular::IsLastRow(int cell) const
459 return (row_of_cell(cell) == rows_ - 1);
463 int LyXTabular::GetAdditionalHeight(int cell) const
465 int const row = row_of_cell(cell);
471 for (int column = 0; column < columns_ - 1 && bottom; ++column) {
472 switch (cell_info[row - 1][column].multicolumn) {
473 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
474 bottom = cell_info[row - 1][column].bottom_line;
476 case LyXTabular::CELL_NORMAL:
477 bottom = row_info[row - 1].bottom_line;
480 for (int column = 0; column < columns_ - 1 && top; ++column) {
481 switch (cell_info[row][column].multicolumn){
482 case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN:
483 top = cell_info[row][column].top_line;
485 case LyXTabular::CELL_NORMAL:
486 top = row_info[row].top_line;
490 return WIDTH_OF_LINE;
495 int LyXTabular::GetAdditionalWidth(int cell) const
497 // internally already set in SetWidthOfCell
498 // used to get it back in text.C
499 int const col = right_column_of_cell(cell);
500 if (col < columns_ - 1 && column_info[col].right_line &&
501 column_info[col+1].left_line)
502 return WIDTH_OF_LINE;
508 // returns the maximum over all rows
509 int LyXTabular::GetWidthOfColumn(int cell) const
511 int const column1 = column_of_cell(cell);
512 int const column2 = right_column_of_cell(cell);
514 for (int i = column1; i <= column2; ++i) {
515 result += column_info[i].width_of_column;
521 int LyXTabular::GetWidthOfTabular() const
523 return width_of_tabular;
527 /* returns 1 if a complete update is necessary, otherwise 0 */
528 bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width)
530 if (!IsMultiColumn(cell))
533 int const row = row_of_cell(cell);
534 int const column1 = column_of_cell(cell);
535 int const column2 = right_column_of_cell(cell);
537 // first set columns to 0 so we can calculate the right width
538 for (int i = column1; i <= column2; ++i) {
539 cell_info[row][i].width_of_cell = 0;
541 // set the width to MAX_WIDTH until width > 0
542 int width = (new_width + 2 * WIDTH_OF_LINE);
545 for (; i < column2 && width > column_info[i].width_of_column; ++i) {
546 cell_info[row][i].width_of_cell = column_info[i].width_of_column;
547 width -= column_info[i].width_of_column;
550 cell_info[row][i].width_of_cell = width;
556 void LyXTabular::recalculateMulticolCells(int cell, int new_width)
558 int const row = row_of_cell(cell);
559 int const column1 = column_of_cell(cell);
560 int const column2 = right_column_of_cell(cell);
562 // first set columns to 0 so we can calculate the right width
564 for (; i <= column2; ++i)
565 cell_info[row][i].width_of_cell = 0;
566 for (i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i)
568 if (i < numberofcells)
569 recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE));
570 SetWidthOfMulticolCell(cell, new_width);
574 /* returns 1 if a complete update is necessary, otherwise 0 */
575 bool LyXTabular::SetWidthOfCell(int cell, int new_width)
577 int const row = row_of_cell(cell);
578 int const column1 = column_of_cell(cell);
582 if (GetWidthOfCell(cell) == (new_width+2*WIDTH_OF_LINE))
584 if (IsMultiColumn(cell, true)) {
585 tmp = SetWidthOfMulticolCell(cell, new_width);
587 width = (new_width + 2*WIDTH_OF_LINE);
588 cell_info[row][column1].width_of_cell = width;
589 if (column_info[column1].right_line && (column1 < columns_-1) &&
590 column_info[column1+1].left_line) // additional width
591 cell_info[row][column1].width_of_cell += WIDTH_OF_LINE;
592 tmp = calculate_width_of_column_NMC(column1);
596 for (; i<columns_; ++i)
597 calculate_width_of_column_NMC(i);
598 for (i = 0; (i < numberofcells) && !IsMultiColumn(i); ++i)
600 if (i < numberofcells)
601 recalculateMulticolCells(i, GetWidthOfCell(i)-(2 * WIDTH_OF_LINE));
602 for (i = 0; i < columns_; ++i)
603 calculate_width_of_column(i);
604 calculate_width_of_tabular();
611 bool LyXTabular::SetAlignment(int cell, LyXAlignment align, bool onlycolumn)
613 if (!IsMultiColumn(cell) || onlycolumn)
614 column_info[column_of_cell(cell)].alignment = align;
616 cellinfo_of_cell(cell)->alignment = align;
621 bool LyXTabular::SetVAlignment(int cell, VAlignment align, bool onlycolumn)
623 if (!IsMultiColumn(cell) || onlycolumn)
624 column_info[column_of_cell(cell)].valignment = align;
626 cellinfo_of_cell(cell)->valignment = align;
631 bool LyXTabular::SetColumnPWidth(int cell, string const & width)
633 bool flag = !width.empty();
634 int const j = column_of_cell(cell);
636 column_info[j].p_width = width;
637 if (flag) // do this only if there is a width
638 SetAlignment(cell, LYX_ALIGN_LEFT);
639 for (int i = 0; i < rows_; ++i) {
640 int c = GetCellNumber(i, j);
641 flag = !GetPWidth(c).empty(); // because of multicolumns!
642 GetCellInset(c)->SetAutoBreakRows(flag);
648 bool LyXTabular::SetMColumnPWidth(int cell, string const & width)
650 bool const flag = !width.empty();
652 cellinfo_of_cell(cell)->p_width = width;
653 if (IsMultiColumn(cell)) {
654 GetCellInset(cell)->SetAutoBreakRows(flag);
661 bool LyXTabular::SetAlignSpecial(int cell, string const & special,
662 LyXTabular::Feature what)
664 if (what == SET_SPECIAL_MULTI)
665 cellinfo_of_cell(cell)->align_special = special;
667 column_info[column_of_cell(cell)].align_special = special;
672 bool LyXTabular::SetAllLines(int cell, bool line)
674 SetTopLine(cell, line);
675 SetBottomLine(cell, line);
676 SetRightLine(cell, line);
677 SetLeftLine(cell, line);
682 bool LyXTabular::SetTopLine(int cell, bool line, bool onlycolumn)
684 int const row = row_of_cell(cell);
686 if (onlycolumn || !IsMultiColumn(cell))
687 row_info[row].top_line = line;
689 cellinfo_of_cell(cell)->top_line = line;
694 bool LyXTabular::SetBottomLine(int cell, bool line, bool onlycolumn)
696 if (onlycolumn || !IsMultiColumn(cell))
697 row_info[row_of_cell(cell)].bottom_line = line;
699 cellinfo_of_cell(cell)->bottom_line = line;
704 bool LyXTabular::SetLeftLine(int cell, bool line, bool onlycolumn)
706 if (onlycolumn || !IsMultiColumn(cell))
707 column_info[column_of_cell(cell)].left_line = line;
709 cellinfo_of_cell(cell)->left_line = line;
714 bool LyXTabular::SetRightLine(int cell, bool line, bool onlycolumn)
716 if (onlycolumn || !IsMultiColumn(cell))
717 column_info[right_column_of_cell(cell)].right_line = line;
719 cellinfo_of_cell(cell)->right_line = line;
724 LyXAlignment LyXTabular::GetAlignment(int cell, bool onlycolumn) const
726 if (!onlycolumn && IsMultiColumn(cell))
727 return cellinfo_of_cell(cell)->alignment;
729 return column_info[column_of_cell(cell)].alignment;
733 LyXTabular::VAlignment
734 LyXTabular::GetVAlignment(int cell, bool onlycolumn) const
736 if (!onlycolumn && IsMultiColumn(cell))
737 return cellinfo_of_cell(cell)->valignment;
739 return column_info[column_of_cell(cell)].valignment;
743 string const LyXTabular::GetPWidth(int cell) const
745 if (IsMultiColumn(cell))
746 return cellinfo_of_cell(cell)->p_width;
747 return column_info[column_of_cell(cell)].p_width;
751 string const LyXTabular::GetColumnPWidth(int cell) const
753 return column_info[column_of_cell(cell)].p_width;
757 string const LyXTabular::GetMColumnPWidth(int cell) const
759 if (IsMultiColumn(cell))
760 return cellinfo_of_cell(cell)->p_width;
765 string const LyXTabular::GetAlignSpecial(int cell, int what) const
767 if (what == SET_SPECIAL_MULTI)
768 return cellinfo_of_cell(cell)->align_special;
769 return column_info[column_of_cell(cell)].align_special;
773 int LyXTabular::GetWidthOfCell(int cell) const
775 int const row = row_of_cell(cell);
776 int const column1 = column_of_cell(cell);
777 int const column2 = right_column_of_cell(cell);
779 for (int i = column1; i <= column2; ++i) {
780 result += cell_info[row][i].width_of_cell;
786 int LyXTabular::GetBeginningOfTextInCell(int cell) const
790 switch (GetAlignment(cell)){
791 case LYX_ALIGN_CENTER:
792 x += (GetWidthOfColumn(cell) - GetWidthOfCell(cell)) / 2;
794 case LYX_ALIGN_RIGHT:
795 x += GetWidthOfColumn(cell) - GetWidthOfCell(cell);
796 // + GetAdditionalWidth(cell);
798 default: /* LYX_ALIGN_LEFT: nothing :-) */
808 bool LyXTabular::IsFirstCellInRow(int cell) const
810 return column_of_cell(cell) == 0;
814 int LyXTabular::GetFirstCellInRow(int row) const
818 return cell_info[row][0].cellno;
821 bool LyXTabular::IsLastCellInRow(int cell) const
823 return (right_column_of_cell(cell) == (columns_ - 1));
827 int LyXTabular::GetLastCellInRow(int row) const
831 return cell_info[row][columns_-1].cellno;
835 bool LyXTabular::calculate_width_of_column(int column)
837 int const old_column_width = column_info[column].width_of_column;
840 for (int i = 0; i < rows_; ++i) {
841 maximum = max(cell_info[i][column].width_of_cell, maximum);
843 column_info[column].width_of_column = maximum;
844 return (column_info[column].width_of_column != old_column_width);
849 // calculate the with of the column without regarding REAL MultiColumn
850 // cells. This means MultiColumn-cells spanning more than 1 column.
852 bool LyXTabular::calculate_width_of_column_NMC(int column)
854 int const old_column_width = column_info[column].width_of_column;
856 for (int i = 0; i < rows_; ++i) {
857 if (!IsMultiColumn(GetCellNumber(i, column), true) &&
858 (cell_info[i][column].width_of_cell > max)) {
859 max = cell_info[i][column].width_of_cell;
862 column_info[column].width_of_column = max;
863 return (column_info[column].width_of_column != old_column_width);
867 void LyXTabular::calculate_width_of_tabular()
869 width_of_tabular = 0;
870 for (int i = 0; i < columns_; ++i) {
871 width_of_tabular += column_info[i].width_of_column;
876 int LyXTabular::row_of_cell(int cell) const
878 if (cell >= numberofcells)
882 return rowofcell[cell];
886 int LyXTabular::column_of_cell(int cell) const
888 if (cell >= numberofcells)
892 return columnofcell[cell];
896 int LyXTabular::right_column_of_cell(int cell) const
898 int const row = row_of_cell(cell);
899 int column = column_of_cell(cell);
900 while (column < (columns_ - 1) &&
901 cell_info[row][column + 1].multicolumn == LyXTabular::CELL_PART_OF_MULTICOLUMN)
907 // Perfect case for a template... (Lgb)
910 string const write_attribute(string const & name, T const & t)
912 string str = " " + name + "=\"" + tostr(t) + "\"";
917 string const write_attribute(string const & name, bool const & b)
919 return write_attribute(name, int(b));
924 string const write_attribute(string const & name, int value)
926 string str = " " + name + "=\"" + tostr(value) + "\"";
931 string const write_attribute(string const & name, string const & value)
933 string str = " " + name + "=\"" + value + "\"";
938 string const write_attribute(string const & name, bool value)
940 string str = " " + name + "=\"" + tostr(static_cast<int>(value)) + "\"";
946 string const type2string(LyXAlignment num)
951 case LYX_ALIGN_BLOCK:
955 case LYX_ALIGN_CENTER:
957 case LYX_ALIGN_RIGHT:
959 case LYX_ALIGN_LAYOUT:
961 case LYX_ALIGN_SPECIAL:
968 string const type2string(LyXTabular::VAlignment num)
971 case LyXTabular::LYX_VALIGN_TOP:
973 case LyXTabular::LYX_VALIGN_CENTER:
975 case LyXTabular::LYX_VALIGN_BOTTOM:
982 string const type2string(LyXTabular::BoxType num)
985 case LyXTabular::BOX_NONE:
987 case LyXTabular::BOX_PARBOX:
989 case LyXTabular::BOX_MINIPAGE:
996 string const type2string(bool flag)
998 return (flag ? "true" : "false");
1002 void LyXTabular::Write(Buffer const * buf, ostream & os) const
1006 << write_attribute("version", 1)
1007 << write_attribute("rows", rows_)
1008 << write_attribute("columns", columns_)
1010 // global longtable options
1012 << write_attribute("rotate", type2string(rotate))
1013 << write_attribute("islongtable", type2string(is_long_tabular))
1014 << write_attribute("endhead", endhead)
1015 << write_attribute("endfirsthead", endfirsthead)
1016 << write_attribute("endfoot", endfoot)
1017 << write_attribute("endlastfoot", endlastfoot)
1019 for (int j = 0; j < columns_; ++j) {
1021 << write_attribute("alignment", type2string(column_info[j].alignment))
1022 << write_attribute("valignment", type2string(column_info[j].valignment))
1023 << write_attribute("leftline", type2string(column_info[j].left_line))
1024 << write_attribute("rightline", type2string(column_info[j].right_line))
1025 << write_attribute("width",
1026 VSpace(column_info[j].p_width)
1028 << write_attribute("special", column_info[j].align_special)
1031 for (int i = 0; i < rows_; ++i) {
1033 << write_attribute("topline", type2string(row_info[i].top_line))
1034 << write_attribute("bottomline", type2string(row_info[i].bottom_line))
1035 << write_attribute("newpage", type2string(row_info[i].newpage))
1037 for (int j = 0; j < columns_; ++j) {
1041 << write_attribute("alignment", type2string(column_info[j].alignment))
1042 << write_attribute("valignment", type2string(column_info[j].valignment))
1043 << write_attribute("leftline", type2string(column_info[j].left_line))
1044 << write_attribute("rightline", type2string(column_info[j].right_line))
1045 << write_attribute("width",
1046 VSpace(column_info[j].p_width)
1048 << write_attribute("special", column_info[j].align_special)
1055 << write_attribute("multicolumn", cell_info[i][j].multicolumn)
1056 << write_attribute("alignment", type2string(cell_info[i][j].alignment))
1057 << write_attribute("valignment", type2string(cell_info[i][j].valignment))
1058 << write_attribute("topline", type2string(cell_info[i][j].top_line))
1059 << write_attribute("bottomline", type2string(cell_info[i][j].bottom_line))
1060 << write_attribute("leftline", type2string(cell_info[i][j].left_line))
1061 << write_attribute("rightline", type2string(cell_info[i][j].right_line))
1062 << write_attribute("rotate", type2string(cell_info[i][j].rotate))
1063 << write_attribute("usebox", type2string(cell_info[i][j].usebox))
1064 << write_attribute("width", cell_info[i][j].p_width)
1065 << write_attribute("special", cell_info[i][j].align_special)
1067 os << "\\begin_inset ";
1068 cell_info[i][j].inset.Write(buf, os);
1069 os << "\n\\end_inset \n"
1077 os << "</LyXTabular>\n";
1081 bool string2type(string const str, LyXAlignment & num)
1084 num = LYX_ALIGN_NONE;
1085 else if (str == "block")
1086 num = LYX_ALIGN_BLOCK;
1087 else if (str == "left")
1088 num = LYX_ALIGN_LEFT;
1089 else if (str == "center")
1090 num = LYX_ALIGN_CENTER;
1091 else if (str == "right")
1092 num = LYX_ALIGN_RIGHT;
1099 bool string2type(string const str, LyXTabular::VAlignment & num)
1102 num = LyXTabular::LYX_VALIGN_TOP;
1103 else if (str == "center")
1104 num = LyXTabular::LYX_VALIGN_CENTER;
1105 else if (str == "bottom")
1106 num = LyXTabular::LYX_VALIGN_BOTTOM;
1113 bool string2type(string const str, LyXTabular::BoxType & num)
1116 num = LyXTabular::BOX_NONE;
1117 else if (str == "parbox")
1118 num = LyXTabular::BOX_PARBOX;
1119 else if (str == "minipage")
1120 num = LyXTabular::BOX_MINIPAGE;
1127 bool string2type(string const str, bool & num)
1131 else if (str == "false")
1139 bool getTokenValue(string const & str, const char * token, string & ret)
1141 size_t token_length = strlen(token);
1142 string::size_type pos = str.find(token);
1144 if (pos == string::npos || pos+token_length+1 >= str.length()
1145 || str[pos+token_length] != '=')
1148 pos += token_length + 1;
1150 if ((ch != '"') && (ch != '\'')) { // only read till next space
1154 while((pos < str.length() - 1) && (str[++pos] != ch))
1161 //#define USE_OLD_READFORMAT
1163 #ifndef USE_OLD_READFORMAT
1165 bool getTokenValue(string const & str, const char * token, int & num)
1168 if (!getTokenValue(str, token, tmp))
1170 num = strToInt(tmp);
1176 bool getTokenValue(string const & str, const char * token, LyXAlignment & num)
1179 if (!getTokenValue(str, token, tmp))
1181 return string2type(tmp, num);
1186 bool getTokenValue(string const & str, const char * token,
1187 LyXTabular::VAlignment & num)
1190 if (!getTokenValue(str, token, tmp))
1192 return string2type(tmp, num);
1197 bool getTokenValue(string const & str, const char * token,
1198 LyXTabular::BoxType & num)
1201 if (!getTokenValue(str, token, tmp))
1203 return string2type(tmp, num);
1208 bool getTokenValue(string const & str, const char * token, bool & flag)
1211 if (!getTokenValue(str, token, tmp))
1213 return string2type(tmp, flag);
1219 bool getTokenValue(string const & str, const char * token, int & num)
1221 string::size_type pos = str.find(token);
1222 char ch = str[pos + strlen(token)];
1224 if ((pos == string::npos) || (ch != '='))
1227 pos += strlen(token) + 1;
1229 if ((ch != '"') && (ch != '\'')) { // only read till next space
1235 while((pos < str.length() - 1) && isdigit(str[pos]))
1238 num = strToInt(ret);
1244 bool getTokenValue(string const & str, const char * token, LyXAlignment & num)
1247 bool const ret = getTokenValue(str, token, tmp);
1248 num = static_cast<LyXAlignment>(tmp);
1254 bool getTokenValue(string const & str, const char * token,
1255 LyXTabular::VAlignment & num)
1258 bool const ret = getTokenValue(str, token, tmp);
1259 num = static_cast<LyXTabular::VAlignment>(tmp);
1265 bool getTokenValue(string const & str, const char * token,
1266 LyXTabular::BoxType & num)
1269 bool ret = getTokenValue(str, token, tmp);
1270 num = static_cast<LyXTabular::BoxType>(tmp);
1276 bool getTokenValue(string const & str, const char * token, bool & flag)
1278 string::size_type pos = str.find(token);
1279 char ch = str[pos + strlen(token)];
1281 if ((pos == string::npos) || (ch != '='))
1284 pos += strlen(token) + 1;
1286 if ((ch != '"') && (ch != '\'')) { // only read till next space
1292 while((pos < str.length() - 1) && isdigit(str[pos]))
1295 flag = strToInt(ret);
1302 void l_getline(istream & is, string & str)
1310 #ifndef USE_OLD_READFORMAT
1312 void LyXTabular::Read(Buffer const * buf, LyXLex & lex)
1315 istream & is = lex.getStream();
1317 l_getline(is, line);
1318 if (!prefixIs(line, "<LyXTabular ")) {
1319 OldFormatRead(lex, line);
1326 if (!getTokenValue(line, "version", version))
1328 if (!getTokenValue(line, "rows", rows_arg))
1330 if (!getTokenValue(line, "columns", columns_arg))
1332 Init(rows_arg, columns_arg);
1333 l_getline(is, line);
1334 if (!prefixIs(line, "<Features")) {
1335 lyxerr << "Wrong tabular format (expected <Feture ...> got" <<
1336 line << ")" << endl;
1339 getTokenValue(line, "rotate", rotate);
1340 getTokenValue(line, "islongtable", is_long_tabular);
1341 getTokenValue(line, "endhead", endhead);
1342 getTokenValue(line, "endfirsthead", endfirsthead);
1343 getTokenValue(line, "endfoot", endfoot);
1344 getTokenValue(line, "endlastfoot", endlastfoot);
1346 for (int j = 0; j < columns_; ++j) {
1348 if (!prefixIs(line,"<Column")) {
1349 lyxerr << "Wrong tabular format (expected <Column ...> got" <<
1350 line << ")" << endl;
1353 getTokenValue(line, "alignment", column_info[j].alignment);
1354 getTokenValue(line, "valignment", column_info[j].valignment);
1355 getTokenValue(line, "leftline", column_info[j].left_line);
1356 getTokenValue(line, "rightline", column_info[j].right_line);
1357 getTokenValue(line, "width", column_info[j].p_width);
1358 getTokenValue(line, "special", column_info[j].align_special);
1361 for (int i = 0; i < rows_; ++i) {
1362 l_getline(is, line);
1363 if (!prefixIs(line, "<Row")) {
1364 lyxerr << "Wrong tabular format (expected <Row ...> got" <<
1365 line << ")" << endl;
1368 getTokenValue(line, "topline", row_info[i].top_line);
1369 getTokenValue(line, "bottomline", row_info[i].bottom_line);
1370 getTokenValue(line, "newpage", row_info[i].newpage);
1371 for (int j = 0; j < columns_; ++j) {
1372 l_getline(is, line);
1373 if (!prefixIs(line, "<Cell")) {
1374 lyxerr << "Wrong tabular format (expected <Cell ...> got" <<
1375 line << ")" << endl;
1378 getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
1379 getTokenValue(line, "alignment", cell_info[i][j].alignment);
1380 getTokenValue(line, "valignment", cell_info[i][j].valignment);
1381 getTokenValue(line, "topline", cell_info[i][j].top_line);
1382 getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
1383 getTokenValue(line, "leftline", cell_info[i][j].left_line);
1384 getTokenValue(line, "rightline", cell_info[i][j].right_line);
1385 getTokenValue(line, "rotate", cell_info[i][j].rotate);
1386 getTokenValue(line, "usebox", cell_info[i][j].usebox);
1387 getTokenValue(line, "width", cell_info[i][j].p_width);
1388 getTokenValue(line, "special", cell_info[i][j].align_special);
1389 l_getline(is, line);
1390 if (prefixIs(line, "\\begin_inset")) {
1391 cell_info[i][j].inset.Read(buf, lex);
1392 l_getline(is, line);
1394 if (line != "</Cell>") {
1395 lyxerr << "Wrong tabular format (expected </Cell> got" <<
1396 line << ")" << endl;
1400 l_getline(is, line);
1401 if (line != "</Row>") {
1402 lyxerr << "Wrong tabular format (expected </Row> got" <<
1403 line << ")" << endl;
1407 while (line != "</LyXTabular>") {
1408 l_getline(is, line);
1410 set_row_column_number_info();
1415 void LyXTabular::Read(Buffer const * buf, LyXLex & lex)
1418 istream & is = lex.getStream();
1420 l_getline(is, line);
1421 if (!prefixIs(line, "<LyXTabular ")) {
1422 OldFormatRead(lex, line);
1429 if (!getTokenValue(line, "version", version))
1431 if (!getTokenValue(line, "rows", rows_arg))
1433 if (!getTokenValue(line, "columns", columns_arg))
1435 Init(rows_arg, columns_arg);
1436 l_getline(is, line);
1437 if (!prefixIs(line, "<Features ")) {
1438 lyxerr << "Wrong tabular format (expected <Feture ...> got" <<
1439 line << ")" << endl;
1442 getTokenValue(line, "islongtable", is_long_tabular);
1443 getTokenValue(line, "endhead", endhead);
1444 getTokenValue(line, "endfirsthead", endfirsthead);
1445 getTokenValue(line, "endfoot", endfoot);
1446 getTokenValue(line, "endlastfoot", endlastfoot);
1448 for (int i = 0; i < rows_; ++i) {
1449 l_getline(is, line);
1450 if (!prefixIs(line, "<Row ")) {
1451 lyxerr << "Wrong tabular format (expected <Row ...> got" <<
1452 line << ")" << endl;
1455 getTokenValue(line, "topline", row_info[i].top_line);
1456 getTokenValue(line, "bottomline", row_info[i].bottom_line);
1457 getTokenValue(line, "newpage", row_info[i].newpage);
1458 for (int j = 0; j < columns_; ++j) {
1460 if (!prefixIs(line,"<Column")) {
1461 lyxerr << "Wrong tabular format (expected <Column ...> got" <<
1462 line << ")" << endl;
1466 getTokenValue(line, "alignment", column_info[j].alignment);
1467 getTokenValue(line, "valignment", column_info[j].valignment);
1468 getTokenValue(line, "leftline", column_info[j].left_line);
1469 getTokenValue(line, "rightline", column_info[j].right_line);
1470 getTokenValue(line, "width", column_info[j].p_width);
1471 getTokenValue(line, "special", column_info[j].align_special);
1473 l_getline(is, line);
1474 if (!prefixIs(line, "<Cell")) {
1475 lyxerr << "Wrong tabular format (expected <Cell ...> got" <<
1476 line << ")" << endl;
1479 getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
1480 getTokenValue(line, "alignment", cell_info[i][j].alignment);
1481 getTokenValue(line, "valignment", cell_info[i][j].valignment);
1482 getTokenValue(line, "topline", cell_info[i][j].top_line);
1483 getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
1484 getTokenValue(line, "leftline", cell_info[i][j].left_line);
1485 getTokenValue(line, "rightline", cell_info[i][j].right_line);
1486 getTokenValue(line, "rotate", cell_info[i][j].rotate);
1487 getTokenValue(line, "usebox", cell_info[i][j].usebox);
1488 getTokenValue(line, "width", cell_info[i][j].p_width);
1489 getTokenValue(line, "special", cell_info[i][j].align_special);
1490 l_getline(is, line);
1491 if (prefixIs(line, "\\begin_inset")) {
1492 cell_info[i][j].inset.Read(buf, lex);
1493 l_getline(is, line);
1495 if (line != "</Cell>") {
1496 lyxerr << "Wrong tabular format (expected </Cell> got" <<
1497 line << ")" << endl;
1500 l_getline(is, line);
1501 if (line != "</Column>") {
1502 lyxerr << "Wrong tabular format (expected </Column> got" <<
1503 line << ")" << endl;
1507 l_getline(is, line);
1508 if (line != "</Row>") {
1509 lyxerr << "Wrong tabular format (expected </Row> got" <<
1510 line << ")" << endl;
1514 while (line != "</LyXTabular>") {
1515 l_getline(is, line);
1517 set_row_column_number_info();
1521 void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
1526 int columns_arg = 0;
1527 int is_long_tabular_arg = false;
1528 int rotate_arg = false;
1537 istream & is = lex.getStream();
1540 version = lyx::atoi(s.substr(8, string::npos));
1544 vector<int> cont_row_info;
1547 lyxerr << "Tabular format < 5 is not supported anymore\n"
1548 "Get an older version of LyX (< 1.1.x) for conversion!"
1550 WriteAlert(_("Warning:"),
1551 _("Tabular format < 5 is not supported anymore\n"),
1552 _("Get an older version of LyX (< 1.1.x) for conversion!"));
1554 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1555 >> rotate_arg >> a >> b >> c >> d;
1557 is >> rows_arg >> columns_arg;
1558 Init(rows_arg, columns_arg);
1559 cont_row_info = vector<int>(rows_arg);
1560 SetLongTabular(is_long_tabular_arg);
1561 SetRotateTabular(rotate_arg);
1563 for (i = 0; i < rows_; ++i) {
1565 cont_row_info[i] = false;
1567 for (i = 0; i < columns_; ++i) {
1570 for (i = 0; i < rows_; ++i) {
1571 for (j = 0; j < columns_; ++j) {
1576 is >> rows_arg >> columns_arg >> is_long_tabular_arg
1577 >> rotate_arg >> a >> b >> c >> d;
1578 Init(rows_arg, columns_arg);
1579 cont_row_info = vector<int>(rows_arg);
1580 SetLongTabular(is_long_tabular_arg);
1581 SetRotateTabular(rotate_arg);
1583 endfirsthead = b + 1;
1585 endlastfoot = d + 1;
1586 for (i = 0; i < rows_; ++i) {
1587 a = b = c = d = e = f = g = 0;
1588 is >> a >> b >> c >> d;
1589 row_info[i].top_line = a;
1590 row_info[i].bottom_line = b;
1591 cont_row_info[i] = c;
1592 row_info[i].newpage = d;
1594 for (i = 0; i < columns_; ++i) {
1599 char ch; // skip '"'
1602 // ignore is buggy but we will use it later (Lgb)
1603 is.ignore(); // skip '"'
1605 getline(is, s1, '"');
1607 is >> ch; // skip '"'
1609 // ignore is buggy but we will use it later (Lgb)
1610 is.ignore(); // skip '"'
1612 getline(is, s2, '"');
1613 column_info[i].alignment = static_cast<LyXAlignment>(a);
1614 column_info[i].left_line = b;
1615 column_info[i].right_line = c;
1616 column_info[i].p_width = s1;
1617 column_info[i].align_special = s2;
1619 for (i = 0; i < rows_; ++i) {
1620 for (j = 0; j < columns_; ++j) {
1623 is >> a >> b >> c >> d >> e >> f >> g;
1626 is >> ch; // skip '"'
1628 // ignore is buggy but we will use it later (Lgb)
1629 is.ignore(); // skip '"'
1631 getline(is, s1, '"');
1633 is >> ch; // skip '"'
1635 // ignore is buggy but we will use it later (Lgb)
1636 is.ignore(); // skip '"'
1638 getline(is, s2, '"');
1639 cell_info[i][j].multicolumn = static_cast<char>(a);
1640 cell_info[i][j].alignment = static_cast<LyXAlignment>(b);
1641 cell_info[i][j].top_line = static_cast<char>(c);
1642 cell_info[i][j].bottom_line = static_cast<char>(d);
1643 cell_info[i][j].left_line = column_info[j].left_line;
1644 cell_info[i][j].right_line = column_info[j].right_line;
1645 cell_info[i][j].rotate = static_cast<bool>(f);
1646 cell_info[i][j].usebox = static_cast<BoxType>(g);
1647 cell_info[i][j].align_special = s1;
1648 cell_info[i][j].p_width = s2;
1652 set_row_column_number_info(true);
1654 LyXParagraph * par = new LyXParagraph;
1655 LyXParagraph * return_par = 0;
1657 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
1658 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
1663 LyXFont font(LyXFont::ALL_INHERIT);
1664 font.setLanguage(owner_->BufferOwner()->GetLanguage());
1666 while (lex.IsOK()) {
1668 string const token = lex.GetString();
1671 if (token == "\\layout"
1672 || token == "\\end_float"
1673 || token == "\\end_deeper") {
1674 lex.pushToken(token);
1677 if (owner_->BufferOwner()->parseSingleLyXformat2Token(lex, par,
1689 lex.pushToken(token);
1693 lex.printError("New Paragraph allocated! This should not happen!");
1694 lex.pushToken(token);
1700 // now we have the par we should fill the insets with this!
1702 InsetText * inset = GetCellInset(cell);
1705 for (int i = 0; i < par->Last(); ++i) {
1706 if (par->IsNewline(i)) {
1708 if (cell > GetNumberOfCells()) {
1709 lyxerr << "Some error in reading old table format occured!" <<
1710 endl << "Terminating when reading cell[" << cell << "]!" <<
1715 row = row_of_cell(cell);
1716 if (cont_row_info[row]) {
1718 cont_row_info.erase(cont_row_info.begin() + row); //&cont_row_info[row]);
1719 while(!IsFirstCellInRow(--cell));
1721 inset = GetCellInset(cell);
1724 inset = GetCellInset(cell);
1725 row = row_of_cell(cell);
1726 if (!cell_info[row_of_cell(cell)][column_of_cell(cell)].usebox)
1728 // insert a space instead
1730 par->InsertChar(i, ' ');
1733 par->CopyIntoMinibuffer(*owner_->BufferOwner(), i);
1734 inset->par->InsertFromMinibuffer(inset->par->Last());
1741 string const LyXTabular::GetDocBookAlign(int cell, bool isColumn) const
1743 int const i = isColumn ? cell : column_of_cell(cell);
1745 if (!isColumn && IsMultiColumn(cell)) {
1746 if (!cellinfo_of_cell(cell)->align_special.empty()) {
1747 return cellinfo_of_cell(cell)->align_special;
1749 switch (GetAlignment(cell)) {
1750 case LYX_ALIGN_LEFT:
1752 case LYX_ALIGN_RIGHT:
1759 if (!column_info[i].align_special.empty()) {
1760 return column_info[i].align_special;
1762 #ifdef IGNORE_THIS_FOR_NOW
1763 else if (!column_info[i].p_width.empty()) {
1765 file += column_info[i].p_width;
1770 switch (column_info[i].alignment) {
1771 case LYX_ALIGN_LEFT:
1773 case LYX_ALIGN_RIGHT:
1783 // cell <0 will tex the preamble
1784 // returns the number of printed newlines
1785 int LyXTabular::DocBookEndOfCell(ostream & os, int cell, int & depth) const
1788 if (IsLastCell(cell)) {
1789 os << newlineAndDepth(--depth)
1791 << newlineAndDepth(--depth)
1793 << newlineAndDepth(--depth)
1795 << newlineAndDepth(--depth);
1796 if (is_long_tabular)
1800 << newlineAndDepth(--depth);
1805 if (is_long_tabular)
1811 << "' COLSEP='1' ROWSEP='1'>"
1812 << newlineAndDepth(++depth);
1814 for (int i = 0; i < columns_; ++i) {
1815 os << "<COLSPEC ALIGN='"
1816 << GetDocBookAlign(i, true)
1822 if (i == (columns_-1)) {
1825 if (column_info[i].right_line ||
1826 column_info[i+1].left_line)
1832 << newlineAndDepth(depth);
1834 #ifdef NOT_HANDLED_YET_AS_I_DONT_KNOW_HOW
1835 if (column_info[i].left_line)
1840 << newlineAndDepth(++depth)
1842 << newlineAndDepth(++depth)
1844 << GetDocBookAlign(0)
1846 if (IsMultiColumn(0)) {
1847 os << " NAMEST='col1' NAMEEND='col"
1848 << cells_in_multicolumn(0)
1852 << newlineAndDepth(++depth);
1855 if (IsLastCellInRow(cell)) {
1856 os << newlineAndDepth(--depth)
1858 << newlineAndDepth(--depth)
1860 << newlineAndDepth(depth)
1862 << newlineAndDepth(++depth)
1864 << GetDocBookAlign(cell + 1)
1865 << "' VALIGN='middle'";
1866 if (IsMultiColumn(cell + 1)) {
1867 os << " NAMEST='col"
1868 << column_of_cell(cell + 1) + 1
1870 << column_of_cell(cell + 1) +
1871 cells_in_multicolumn(cell + 1)
1875 << newlineAndDepth(++depth);
1878 os << newlineAndDepth(--depth)
1880 << newlineAndDepth(depth)
1882 << GetDocBookAlign(cell + 1)
1883 << "' VALIGN='middle'";
1884 if (IsMultiColumn(cell + 1)) {
1885 os << " NAMEST='col"
1886 << column_of_cell(cell + 1) + 1
1888 << column_of_cell(cell + 1) +
1889 cells_in_multicolumn(cell + 1)
1893 << newlineAndDepth(++depth);
1902 bool LyXTabular::IsMultiColumn(int cell, bool real) const
1904 return ((!real || (column_of_cell(cell) != right_column_of_cell(cell))) &&
1905 (cellinfo_of_cell(cell)->multicolumn != LyXTabular::CELL_NORMAL));
1909 LyXTabular::cellstruct * LyXTabular::cellinfo_of_cell(int cell) const
1911 int const row = row_of_cell(cell);
1912 int const column = column_of_cell(cell);
1913 return &cell_info[row][column];
1917 void LyXTabular::SetMultiColumn(int cell, int number)
1919 cellinfo_of_cell(cell)->multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
1920 cellinfo_of_cell(cell)->alignment = column_info[column_of_cell(cell)].alignment;
1921 cellinfo_of_cell(cell)->top_line = row_info[row_of_cell(cell)].top_line;
1922 cellinfo_of_cell(cell)->bottom_line = row_info[row_of_cell(cell)].bottom_line;
1923 for (number--; number > 0; --number) {
1924 cellinfo_of_cell(cell+number)->multicolumn = CELL_PART_OF_MULTICOLUMN;
1926 set_row_column_number_info();
1930 int LyXTabular::cells_in_multicolumn(int cell) const
1932 int const row = row_of_cell(cell);
1933 int column = column_of_cell(cell);
1936 while ((column < columns_) &&
1937 cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN)
1946 int LyXTabular::UnsetMultiColumn(int cell)
1948 int const row = row_of_cell(cell);
1949 int column = column_of_cell(cell);
1953 if (cell_info[row][column].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
1954 cell_info[row][column].multicolumn = CELL_NORMAL;
1956 while ((column < columns_) &&
1957 (cell_info[row][column].multicolumn ==CELL_PART_OF_MULTICOLUMN))
1959 cell_info[row][column].multicolumn = CELL_NORMAL;
1964 set_row_column_number_info();
1969 void LyXTabular::SetLongTabular(bool what)
1971 is_long_tabular = what;
1975 bool LyXTabular::IsLongTabular() const
1977 return is_long_tabular;
1981 void LyXTabular::SetRotateTabular(bool flag)
1987 bool LyXTabular::GetRotateTabular() const
1993 void LyXTabular::SetRotateCell(int cell, bool flag)
1995 cellinfo_of_cell(cell)->rotate = flag;
1999 bool LyXTabular::GetRotateCell(int cell) const
2001 return cellinfo_of_cell(cell)->rotate;
2005 bool LyXTabular::NeedRotating() const
2009 for (int i = 0; i < rows_; ++i) {
2010 for (int j = 0; j < columns_; ++j) {
2011 if (cell_info[i][j].rotate)
2019 bool LyXTabular::IsLastCell(int cell) const
2021 if ((cell + 1) < GetNumberOfCells())
2027 int LyXTabular::GetCellAbove(int cell) const
2029 if (row_of_cell(cell) > 0)
2030 return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
2035 int LyXTabular::GetCellBelow(int cell) const
2037 if (row_of_cell(cell) + 1 < rows_)
2038 return cell_info[row_of_cell(cell)+1][column_of_cell(cell)].cellno;
2043 int LyXTabular::GetLastCellAbove(int cell) const
2045 if (row_of_cell(cell) <= 0)
2047 if (!IsMultiColumn(cell))
2048 return GetCellAbove(cell);
2049 return cell_info[row_of_cell(cell) - 1][right_column_of_cell(cell)].cellno;
2053 int LyXTabular::GetLastCellBelow(int cell) const
2055 if (row_of_cell(cell) + 1 >= rows_)
2057 if (!IsMultiColumn(cell))
2058 return GetCellBelow(cell);
2059 return cell_info[row_of_cell(cell) + 1][right_column_of_cell(cell)].cellno;
2063 int LyXTabular::GetCellNumber(int row, int column) const
2065 if (column >= columns_)
2066 column = columns_ - 1;
2067 else if (column < 0)
2074 return cell_info[row][column].cellno;
2078 void LyXTabular::SetUsebox(int cell, BoxType type)
2080 cellinfo_of_cell(cell)->usebox = type;
2084 LyXTabular::BoxType LyXTabular::GetUsebox(int cell) const
2086 if (column_info[column_of_cell(cell)].p_width.empty() &&
2087 !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty()))
2089 if (cellinfo_of_cell(cell)->usebox > 1)
2090 return cellinfo_of_cell(cell)->usebox;
2091 return UseParbox(cell);
2095 void LyXTabular::SetLTHead(int cell, bool first)
2097 int const row = row_of_cell(cell);
2098 int const val = (row + 1) * (column_of_cell(cell) ? 1 : -1);
2101 if (endfirsthead == val)
2114 bool LyXTabular::GetRowOfLTHead(int cell, int & row) const
2117 if (abs(endhead) > rows_)
2119 return (row_of_cell(cell) == abs(endhead) - 1);
2123 bool LyXTabular::GetRowOfLTFirstHead(int cell, int & row) const
2126 if (abs(endfirsthead) > rows_)
2128 return (row_of_cell(cell) == abs(endfirsthead) - 1);
2132 void LyXTabular::SetLTFoot(int cell, bool last)
2134 int const row = row_of_cell(cell);
2135 int const val = (row + 1) * (column_of_cell(cell) ? 1 : -1);
2138 if (endlastfoot == val)
2151 bool LyXTabular::GetRowOfLTFoot(int cell, int & row) const
2154 if ((endfoot + 1) > rows_)
2156 return (row_of_cell(cell) == abs(endfoot) - 1);
2160 bool LyXTabular::GetRowOfLTLastFoot(int cell, int & row) const
2163 if (abs(endlastfoot) > rows_)
2165 return (row_of_cell(cell) == (abs(endlastfoot)-1));
2169 void LyXTabular::SetLTNewPage(int cell, bool what)
2171 row_info[row_of_cell(cell)].newpage = what;
2175 bool LyXTabular::GetLTNewPage(int cell) const
2177 return row_info[row_of_cell(cell)].newpage;
2181 bool LyXTabular::SetAscentOfRow(int row, int height)
2183 if ((row >= rows_) || (row_info[row].ascent_of_row == height))
2185 row_info[row].ascent_of_row = height;
2190 bool LyXTabular::SetDescentOfRow(int row, int height)
2192 if ((row >= rows_) || (row_info[row].descent_of_row == height))
2194 row_info[row].descent_of_row = height;
2199 int LyXTabular::GetAscentOfRow(int row) const
2203 return row_info[row].ascent_of_row;
2207 int LyXTabular::GetDescentOfRow(int row) const
2211 return row_info[row].descent_of_row;
2215 int LyXTabular::GetHeightOfTabular() const
2219 for (int row = 0; row < rows_; ++row)
2220 height += GetAscentOfRow(row) + GetDescentOfRow(row) +
2221 GetAdditionalHeight(GetCellNumber(row, 0));
2226 bool LyXTabular::IsPartOfMultiColumn(int row, int column) const
2228 if ((row >= rows_) || (column >= columns_))
2230 return (cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN);
2234 int LyXTabular::TeXTopHLine(ostream & os, int row) const
2236 if ((row < 0) || (row >= rows_))
2239 int const fcell = GetFirstCellInRow(row);
2240 int const n = NumberOfCellsInRow(fcell) + fcell;
2243 for (int i = fcell; i < n; ++i) {
2247 if (tmp == (n - fcell)){
2250 for (int i = fcell; i < n; ++i) {
2253 << column_of_cell(i) + 1
2255 << right_column_of_cell(i) + 1
2267 int LyXTabular::TeXBottomHLine(ostream & os, int row) const
2269 if ((row < 0) || (row >= rows_))
2272 int const fcell = GetFirstCellInRow(row);
2273 int const n = NumberOfCellsInRow(fcell) + fcell;
2276 for (int i = fcell; i < n; ++i) {
2280 if (tmp == (n-fcell)){
2283 for (int i = fcell; i < n; ++i) {
2284 if (BottomLine(i)) {
2286 << column_of_cell(i) + 1
2288 << right_column_of_cell(i) + 1
2300 int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
2304 if (GetRotateCell(cell)) {
2305 os << "\\begin{sideways}\n";
2308 if (IsMultiColumn(cell)) {
2309 os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
2310 if (!cellinfo_of_cell(cell)->align_special.empty()) {
2311 os << cellinfo_of_cell(cell)->align_special << "}{";
2315 if (!GetPWidth(cell).empty()) {
2316 switch (GetVAlignment(cell)) {
2317 case LYX_VALIGN_TOP:
2320 case LYX_VALIGN_CENTER:
2323 case LYX_VALIGN_BOTTOM:
2327 os << "{" << GetPWidth(cell) << '}';
2329 switch (GetAlignment(cell)) {
2330 case LYX_ALIGN_LEFT:
2333 case LYX_ALIGN_RIGHT:
2341 if (RightLine(cell))
2343 if (((cell + 1) < numberofcells) && !IsFirstCellInRow(cell+1) &&
2349 if (GetUsebox(cell) == BOX_PARBOX) {
2351 switch (GetVAlignment(cell)) {
2352 case LYX_VALIGN_TOP:
2355 case LYX_VALIGN_CENTER:
2358 case LYX_VALIGN_BOTTOM:
2362 os << "]{" << GetPWidth(cell) << "}{";
2363 } else if (GetUsebox(cell) == BOX_MINIPAGE) {
2364 os << "\\begin{minipage}[";
2365 switch (GetVAlignment(cell)) {
2366 case LYX_VALIGN_TOP:
2369 case LYX_VALIGN_CENTER:
2372 case LYX_VALIGN_BOTTOM:
2376 os << "]{" << GetPWidth(cell) << "}\n";
2383 int LyXTabular::TeXCellPostamble(ostream & os, int cell) const
2388 if (GetUsebox(cell) == BOX_PARBOX)
2390 else if (GetUsebox(cell) == BOX_MINIPAGE) {
2391 os << "%\n\\end{minipage}";
2394 if (IsMultiColumn(cell)){
2397 if (GetRotateCell(cell)) {
2398 os << "%\n\\end{sideways}";
2405 int LyXTabular::Latex(Buffer const * buf,
2406 ostream & os, bool fragile, bool fp) const
2411 //+---------------------------------------------------------------------
2412 //+ first the opening preamble +
2413 //+---------------------------------------------------------------------
2416 os << "\\begin{sideways}\n";
2419 if (is_long_tabular)
2420 os << "\\begin{longtable}{";
2422 os << "\\begin{tabular}{";
2423 for (int i = 0; i < columns_; ++i) {
2424 if (column_info[i].left_line)
2426 if (!column_info[i].align_special.empty()) {
2427 os << column_info[i].align_special;
2428 } else if (!column_info[i].p_width.empty()) {
2429 switch (column_info[i].valignment) {
2430 case LYX_VALIGN_TOP:
2433 case LYX_VALIGN_CENTER:
2436 case LYX_VALIGN_BOTTOM:
2441 << column_info[i].p_width
2444 switch (column_info[i].alignment) {
2445 case LYX_ALIGN_LEFT:
2448 case LYX_ALIGN_RIGHT:
2456 if (column_info[i].right_line)
2462 //+---------------------------------------------------------------------
2463 //+ the single row and columns (cells) +
2464 //+---------------------------------------------------------------------
2467 for (int i = 0; i < rows_; ++i) {
2468 ret += TeXTopHLine(os, i);
2470 if (IsLongTabular()) {
2471 if ((endhead < 0) && (i == (abs(endhead)-1))) {
2472 os << "\\endhead\n";
2475 if ((endfirsthead < 0) && (i == (abs(endfirsthead)-1))) {
2476 os << "\\endfirsthead\n";
2479 if ((endfoot < 0) && (i == (abs(endfoot)-1))) {
2480 os << "\\endfoot\n";
2483 if ((endlastfoot < 0) && (i == (abs(endlastfoot)-1))) {
2484 os << "\\endlastfoot\n";
2489 ret += TeXBottomHLine(os, i-1);
2490 ret += TeXTopHLine(os, i);
2492 for (int j = 0; j < columns_; ++j) {
2493 if (IsPartOfMultiColumn(i,j))
2495 ret += TeXCellPreamble(os, cell);
2496 InsetText * inset = GetCellInset(cell);
2498 bool rtl = inset->par->isRightToLeftPar(buf->params) &&
2499 inset->par->Last() > 0 && GetPWidth(cell).empty();
2502 ret += inset->Latex(buf, os, fragile, fp);
2506 ret += TeXCellPostamble(os, cell);
2507 if (!IsLastCellInRow(cell)) { // not last cell in row
2514 ret += TeXBottomHLine(os, i);
2516 if (IsLongTabular()) {
2517 if ((endhead > 0) && (i == (endhead - 1))) {
2518 os << "\\endhead\n";
2521 if ((endfirsthead > 0) && (i == (endfirsthead - 1))) {
2522 os << "\\endfirsthead\n";
2525 if ((endfoot > 0) && (i == (endfoot - 1))) {
2526 os << "\\endfoot\n";
2529 if ((endlastfoot > 0) && (i == (endlastfoot - 1))) {
2530 os << "\\endlastfoot\n";
2534 // ret += TeXBottomHLine(os, i);
2535 if (row_info[i].newpage) {
2536 os << "\\newpage\n";
2542 //+---------------------------------------------------------------------
2543 //+ the closing of the tabular +
2544 //+---------------------------------------------------------------------
2546 if (is_long_tabular)
2547 os << "\\end{longtable}";
2549 os << "\\end{tabular}";
2551 os << "\n\\end{sideways}";
2559 int LyXTabular::DocBook(Buffer const * buf, ostream & os) const
2563 //+---------------------------------------------------------------------
2564 //+ first the opening preamble +
2565 //+---------------------------------------------------------------------
2567 os << "<tgroup cols=\"" << columns_
2568 << "\" colsep=\"1\" rowsep=\"1\">\n";
2570 for (int i = 0; i < columns_; ++i) {
2571 os << "<colspec colname=\"col" << i << "\" align=\"";
2572 switch (column_info[i].alignment) {
2573 case LYX_ALIGN_LEFT:
2576 case LYX_ALIGN_RIGHT:
2587 //+---------------------------------------------------------------------
2588 //+ the single row and columns (cells) +
2589 //+---------------------------------------------------------------------
2593 for (int i = 0; i < rows_; ++i) {
2595 for (int j = 0; j < columns_; ++j) {
2596 if (IsPartOfMultiColumn(i, j))
2599 os << "<entry align=\"";
2600 switch (GetAlignment(cell)) {
2601 case LYX_ALIGN_LEFT:
2604 case LYX_ALIGN_RIGHT:
2612 os << "\" valign=\"";
2613 switch (GetVAlignment(cell)) {
2614 case LYX_VALIGN_TOP:
2617 case LYX_VALIGN_BOTTOM:
2620 case LYX_VALIGN_CENTER:
2625 if (IsMultiColumn(cell)) {
2626 os << " namest=\"col" << j << "\" ";
2627 os << "nameend=\"col" << j + cells_in_multicolumn(cell) - 1<< "\"";
2631 ret += GetCellInset(cell)->DocBook(buf, os);
2638 //+---------------------------------------------------------------------
2639 //+ the closing of the tabular +
2640 //+---------------------------------------------------------------------
2651 void print_n_chars(ostream & os, unsigned char ch, int n)
2653 os << string(n, ch);
2657 int LyXTabular::AsciiTopHLine(ostream & os, int row,
2658 vector<unsigned int> const & clen) const
2660 int const fcell = GetFirstCellInRow(row);
2661 int const n = NumberOfCellsInRow(fcell) + fcell;
2664 for (int i = fcell; i < n; ++i) {
2674 for (int i = fcell; i < n; ++i) {
2685 int column = column_of_cell(i);
2686 int len = clen[column];
2687 while(IsPartOfMultiColumn(row, ++column))
2688 len += clen[column] + 4;
2689 print_n_chars(os, ch, len);
2704 int LyXTabular::AsciiBottomHLine(ostream & os, int row,
2705 vector<unsigned int> const & clen) const
2707 int const fcell = GetFirstCellInRow(row);
2708 int const n = NumberOfCellsInRow(fcell) + fcell;
2711 for (int i = fcell; i < n; ++i) {
2712 if (BottomLine(i)) {
2721 for (int i = fcell; i < n; ++i) {
2722 if (BottomLine(i)) {
2732 int column = column_of_cell(i);
2733 int len = clen[column];
2734 while(IsPartOfMultiColumn(row, ++column))
2735 len += clen[column] + 4;
2736 print_n_chars(os, ch, len);
2737 if (BottomLine(i)) {
2751 int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os,
2752 int cell, int row, int column,
2753 vector<unsigned int> const & clen) const
2756 int ret = GetCellInset(cell)->Ascii(buf, sstr, 0);
2763 unsigned int len1 = sstr.str().length();
2764 unsigned int len2 = clen[column];
2765 while(IsPartOfMultiColumn(row, ++column))
2766 len2 += clen[column] + 4;
2769 switch (GetAlignment(cell)) {
2771 case LYX_ALIGN_LEFT:
2774 case LYX_ALIGN_RIGHT:
2778 case LYX_ALIGN_CENTER:
2784 for (unsigned int i = 0; i < len1; ++i)
2787 for (unsigned int i = 0; i < len2; ++i)
2789 if (RightLine(cell))
2794 return ret * 0; // eh? (Lgb)
2798 int LyXTabular::Ascii(Buffer const * buf, ostream & os) const
2802 //+---------------------------------------------------------------------
2803 //+ first calculate the width of the single columns +
2804 //+---------------------------------------------------------------------
2805 vector<unsigned int> clen(columns_);
2807 // first all non (real) multicolumn cells!
2808 for (int j = 0; j < columns_; ++j) {
2810 for (int i = 0; i < rows_; ++i) {
2811 int cell = GetCellNumber(i, j);
2812 if (IsMultiColumn(cell, true))
2815 GetCellInset(cell)->Ascii(buf, sstr, 0);
2816 if (clen[j] < sstr.str().length())
2817 clen[j] = sstr.str().length();
2820 // then all (real) multicolumn cells!
2821 for (int j = 0; j < columns_; ++j) {
2822 for (int i = 0; i < rows_; ++i) {
2823 int cell = GetCellNumber(i, j);
2824 if (!IsMultiColumn(cell, true) || IsPartOfMultiColumn(i, j))
2827 GetCellInset(cell)->Ascii(buf, sstr, 0);
2828 int len = int(sstr.str().length());
2829 int const n = cells_in_multicolumn(cell);
2830 for (int k = j; (len > 0) && (k < (j + n - 1)); ++k)
2832 if (len > int(clen[j + n - 1]))
2833 clen[j + n - 1] = len;
2837 for (int i = 0; i < rows_; ++i) {
2838 AsciiTopHLine(os, i, clen);
2839 for (int j = 0; j < columns_; ++j) {
2840 if (IsPartOfMultiColumn(i,j))
2842 ret += AsciiPrintCell(buf, os, cell, i, j, clen);
2846 AsciiBottomHLine(os, i, clen);
2852 InsetText * LyXTabular::GetCellInset(int cell) const
2854 return & cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;
2858 InsetText * LyXTabular::GetCellInset(int row, int column) const
2860 return GetCellInset(GetCellNumber(row, column));
2864 void LyXTabular::Validate(LaTeXFeatures & features) const
2866 if (IsLongTabular())
2867 features.longtable = true;
2869 features.rotating = true;
2870 for (int cell = 0; cell < numberofcells; ++cell) {
2871 if (GetVAlignment(cell) != LYX_VALIGN_TOP)
2872 features.array = true;
2873 GetCellInset(cell)->Validate(features);
2878 LyXTabular::BoxType LyXTabular::UseParbox(int cell) const
2880 LyXParagraph * par = GetCellInset(cell)->par;
2882 for (; par; par = par->next) {
2883 for (int i = 0; i < par->Last(); ++i) {
2884 if (par->GetChar(i) == LyXParagraph::META_NEWLINE)