X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftabular.C;h=de046eab704aa1c857b73908c6622541cd75f10e;hb=57bb1b916ccf60ea4120e83cc20192300c83c7f7;hp=b06f5b9a91c25dbe2b75b7fceb5f31357458a92d;hpb=d1b90146494561edc89497bb1037efd6065f2c51;p=lyx.git diff --git a/src/tabular.C b/src/tabular.C index b06f5b9a91..de046eab70 100644 --- a/src/tabular.C +++ b/src/tabular.C @@ -3,7 +3,7 @@ * * LyX, The Document Processor * - * Copyright 2000 The LyX Team. + * Copyright 2000-2002 The LyX Team. * * @author: Jürgen Vigna * @@ -16,22 +16,28 @@ #pragma implementation #endif -#include -#include +// temporary until verified (08/08/2001 Jug) +#define SPECIAL_COLUM_HANDLING 1 #include "tabular.h" #include "debug.h" #include "vspace.h" #include "layout.h" -#include "lyx_gui_misc.h" #include "buffer.h" #include "BufferView.h" #include "Painter.h" #include "LaTeXFeatures.h" -#include "support/lstrings.h" -#include "support/lyxmanip.h" #include "insets/insettabular.h" #include "insets/insettext.h" +#include "support/lstrings.h" +#include "support/lyxmanip.h" +#include "support/LAssert.h" +#include "frontends/Alert.h" +#include "gettext.h" +#include "tabular_funcs.h" + +#include +#include using std::ostream; using std::istream; @@ -40,6 +46,10 @@ using std::max; using std::endl; using std::vector; +#ifndef CXX_GLOBAL_CSTD +using std::strlen; +#endif + namespace { int const WIDTH_OF_LINE = 5; @@ -70,6 +80,10 @@ LyXTabular::rowstruct::rowstruct() bottom_line = false; ascent_of_row = 0; descent_of_row = 0; + endhead = false; + endfirsthead = false; + endfoot = false; + endlastfoot = false; newpage = false; } @@ -84,61 +98,86 @@ LyXTabular::columnstruct::columnstruct() } +LyXTabular::lttype::lttype() +{ + topDL = false; + bottomDL = false; + empty = false; +} + + /* konstruktor */ LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg) { owner_ = inset; + cur_cell = -1; Init(rows_arg, columns_arg); } -LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt) +LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt, + bool same_id) { owner_ = inset; - Init(lt.rows_, lt.columns_); + cur_cell = -1; + Init(lt.rows_, lt.columns_, <); + // we really should change again to have InsetText as a pointer + // and allocate it then we would not have to do this stuff all + // double! + if (same_id) { + for (int i = 0; i < rows_; ++i) { + for (int j = 0; j < columns_; ++j) { + cell_info[i][j].inset.id(lt.cell_info[i][j].inset.id()); + cell_info[i][j].inset.setParagraphData(lt.cell_info[i][j].inset.paragraph(),true); + } + } + } +#if 0 #ifdef WITH_WARNINGS #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) #endif operator=(lt); +#endif } LyXTabular::LyXTabular(Buffer const * buf, InsetTabular * inset, LyXLex & lex) { owner_ = inset; + cur_cell = -1; Read(buf, lex); } LyXTabular & LyXTabular::operator=(LyXTabular const & lt) { +#if 0 +#warning This while method should look like this: (Lgb) + + LyXTabular tmp(lt); + tmp.swap(*this); +#else // If this and lt is not of the same size we have a serious bug // So then it is ok to throw an exception, or for now // call abort() - Assert(rows_ == lt.rows_ && columns_ == lt.columns_); - + lyx::Assert(rows_ == lt.rows_ && columns_ == lt.columns_); + cur_cell = -1; cell_info = lt.cell_info; row_info = lt.row_info; column_info = lt.column_info; - - // long tabular stuff SetLongTabular(lt.is_long_tabular); - endhead = lt.endhead; - endfoot = lt.endfoot; - endfirsthead = lt.endfirsthead; - endlastfoot = lt.endlastfoot; - rotate = lt.rotate; Reinit(); - +#endif return *this; } -LyXTabular * LyXTabular::Clone(InsetTabular * inset) +LyXTabular * LyXTabular::clone(InsetTabular * inset, bool same_id) { - LyXTabular * result = new LyXTabular(inset, *this); + LyXTabular * result = new LyXTabular(inset, *this, same_id); +#if 0 // don't know if this is good but I need to Clone also // the text-insets here, this is for the Undo-facility! for (int i = 0; i < rows_; ++i) { @@ -147,12 +186,13 @@ LyXTabular * LyXTabular::Clone(InsetTabular * inset) result->cell_info[i][j].inset.setOwner(inset); } } +#endif return result; } /* activates all lines and sets all widths to 0 */ -void LyXTabular::Init(int rows_arg, int columns_arg) +void LyXTabular::Init(int rows_arg, int columns_arg, LyXTabular const * lt) { rows_ = rows_arg; columns_ = columns_arg; @@ -160,11 +200,16 @@ void LyXTabular::Init(int rows_arg, int columns_arg) column_info = column_vector(columns_, columnstruct()); cell_info = cell_vvector(rows_, cell_vector(columns_, cellstruct())); + if (lt) { + operator=(*lt); + return; + } + int cellno = 0; for (int i = 0; i < rows_; ++i) { for (int j = 0; j < columns_; ++j) { cell_info[i][j].inset.setOwner(owner_); - cell_info[i][j].inset.SetDrawFrame(0, InsetText::LOCKED); + cell_info[i][j].inset.setDrawFrame(0, InsetText::LOCKED); cell_info[i][j].cellno = cellno++; } cell_info[i].back().right_line = true; @@ -184,10 +229,6 @@ void LyXTabular::Init(int rows_arg, int columns_arg) set_row_column_number_info(); is_long_tabular = false; rotate = false; - endhead = 0; - endfirsthead = 0; - endfoot = 0; - endlastfoot = 0; } @@ -231,9 +272,6 @@ void LyXTabular::AppendRow(int cell) void LyXTabular::DeleteRow(int row) { - // Why make it so hard? (Lgb) - //if (!(rows_ - 1)) - //return; if (rows_ == 1) return; // Not allowed to delete last row row_info.erase(row_info.begin() + row); //&row_info[row]); @@ -263,12 +301,14 @@ void LyXTabular::AppendColumn(int cell) c_info[i][j] = cell_info[i][j - 1]; } // care about multicolumns - if (cell_info[i][column + 1].multicolumn==CELL_BEGIN_OF_MULTICOLUMN) { - cell_info[i][column + 1].multicolumn = CELL_PART_OF_MULTICOLUMN; + if (c_info[i][column + 1].multicolumn==CELL_BEGIN_OF_MULTICOLUMN) + { + c_info[i][column + 1].multicolumn = CELL_PART_OF_MULTICOLUMN; } - if ((column + 1) == columns_ || - cell_info[i][column + 2].multicolumn != CELL_PART_OF_MULTICOLUMN) { - cell_info[i][column + 1].multicolumn = LyXTabular::CELL_NORMAL; + if ((column + 2) >= columns_ || + c_info[i][column + 2].multicolumn != CELL_PART_OF_MULTICOLUMN) + { + c_info[i][column + 1].multicolumn = LyXTabular::CELL_NORMAL; } } cell_info = c_info; @@ -297,12 +337,20 @@ void LyXTabular::DeleteColumn(int column) } -void LyXTabular::Reinit() -{ - for (int i = 0; i < rows_; ++i) { - for (int j = 0; j < columns_; ++j) { - cell_info[i][j].width_of_cell = 0; - cell_info[i][j].inset.setOwner(owner_); +void LyXTabular::reinit() +{ + Reinit(false); +} + + +void LyXTabular::Reinit(bool reset_widths) +{ + if (reset_widths) { + for (int i = 0; i < rows_; ++i) { + for (int j = 0; j < columns_; ++j) { + cell_info[i][j].width_of_cell = 0; + cell_info[i][j].inset.setOwner(owner_); + } } } @@ -359,8 +407,8 @@ void LyXTabular::set_row_column_number_info(bool oldformat) cell_info[row][column].right_line = cell_info[row][column+cn-1].right_line; } - cell_info[row][column].inset.SetAutoBreakRows( - !GetPWidth(GetCellNumber(row, column)).empty()); + cell_info[row][column].inset.setAutoBreakRows( + !GetPWidth(GetCellNumber(row, column)).zero()); } } } @@ -411,26 +459,50 @@ bool LyXTabular::BottomLine(int cell, bool onlycolumn) const bool LyXTabular::LeftLine(int cell, bool onlycolumn) const { - if (!onlycolumn && IsMultiColumn(cell)) + if (!onlycolumn && IsMultiColumn(cell)) { +#ifdef SPECIAL_COLUM_HANDLING + if (cellinfo_of_cell(cell)->align_special.empty()) + return cellinfo_of_cell(cell)->left_line; + return prefixIs(frontStrip(cellinfo_of_cell(cell)->align_special), "|"); +#else return cellinfo_of_cell(cell)->left_line; +#endif + } +#ifdef SPECIAL_COLUM_HANDLING + if (column_info[column_of_cell(cell)].align_special.empty()) + return column_info[column_of_cell(cell)].left_line; + return prefixIs(frontStrip(column_info[column_of_cell(cell)].align_special), "|"); +#else return column_info[column_of_cell(cell)].left_line; +#endif } bool LyXTabular::RightLine(int cell, bool onlycolumn) const { - if (!onlycolumn && IsMultiColumn(cell)) + if (!onlycolumn && IsMultiColumn(cell)) { +#ifdef SPECIAL_COLUM_HANDLING + if (cellinfo_of_cell(cell)->align_special.empty()) + return cellinfo_of_cell(cell)->right_line; + return suffixIs(strip(cellinfo_of_cell(cell)->align_special), "|"); +#else return cellinfo_of_cell(cell)->right_line; +#endif + } +#ifdef SPECIAL_COLUM_HANDLING + if (column_info[column_of_cell(cell)].align_special.empty()) + return column_info[right_column_of_cell(cell)].right_line; + return suffixIs(strip(column_info[column_of_cell(cell)].align_special), "|"); +#else return column_info[right_column_of_cell(cell)].right_line; +#endif } bool LyXTabular::TopAlreadyDrawed(int cell) const { - if (GetAdditionalHeight(cell)) - return false; int row = row_of_cell(cell); - if (row > 0) { + if ((row > 0) && !GetAdditionalHeight(row)) { int column = column_of_cell(cell); --row; while (column @@ -456,7 +528,11 @@ bool LyXTabular::LeftAlreadyDrawed(int cell) const LyXTabular::CELL_PART_OF_MULTICOLUMN)); if (GetAdditionalWidth(cell_info[row][column].cellno)) return false; +#ifdef SPECIAL_COLUM_HANDLING return column_info[column].right_line; +#else + return RightLine(cell_info[row][column].cellno, true); +#endif } return false; } @@ -468,15 +544,15 @@ bool LyXTabular::IsLastRow(int cell) const } -int LyXTabular::GetAdditionalHeight(int cell) const +int LyXTabular::GetAdditionalHeight(int row) const { - int const row = row_of_cell(cell); - if (!row) return 0; + if (!row || row >= rows_) + return 0; bool top = true; bool bottom = true; - for (int column = 0; column < columns_ - 1 && bottom; ++column) { + for (int column = 0; column < columns_ && bottom; ++column) { switch (cell_info[row - 1][column].multicolumn) { case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN: bottom = cell_info[row - 1][column].bottom_line; @@ -485,8 +561,8 @@ int LyXTabular::GetAdditionalHeight(int cell) const bottom = row_info[row - 1].bottom_line; } } - for (int column = 0; column < columns_ - 1 && top; ++column) { - switch (cell_info[row][column].multicolumn){ + for (int column = 0; column < columns_ && top; ++column) { + switch (cell_info[row][column].multicolumn) { case LyXTabular::CELL_BEGIN_OF_MULTICOLUMN: top = cell_info[row][column].top_line; break; @@ -505,11 +581,14 @@ int LyXTabular::GetAdditionalWidth(int cell) const // internally already set in SetWidthOfCell // used to get it back in text.C int const col = right_column_of_cell(cell); - if (col < columns_ - 1 && column_info[col].right_line && - column_info[col+1].left_line) + int const row = row_of_cell(cell); + if (col < columns_ - 1 && RightLine(cell, true) && + LeftLine(cell_info[row][col+1].cellno, true)) // column_info[col+1].left_line) + { return WIDTH_OF_LINE; - else + } else { return 0; + } } @@ -541,14 +620,14 @@ bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width) int const row = row_of_cell(cell); int const column1 = column_of_cell(cell); int const column2 = right_column_of_cell(cell); - + int const old_val = cell_info[row][column2].width_of_cell; + // first set columns to 0 so we can calculate the right width for (int i = column1; i <= column2; ++i) { cell_info[row][i].width_of_cell = 0; } // set the width to MAX_WIDTH until width > 0 int width = (new_width + 2 * WIDTH_OF_LINE); - int i = column1; for (; i < column2 && width > column_info[i].width_of_column; ++i) { cell_info[row][i].width_of_cell = column_info[i].width_of_column; @@ -557,25 +636,36 @@ bool LyXTabular::SetWidthOfMulticolCell(int cell, int new_width) if (width > 0) { cell_info[row][i].width_of_cell = width; } + if (old_val != cell_info[row][column2].width_of_cell) { + // in this case we have to recalculate all multicolumn cells which + // have this column as one of theirs but not as last one + recalculateMulticolumnsOfColumn(i); + } return true; } -void LyXTabular::recalculateMulticolCells(int cell, int new_width) +void LyXTabular::recalculateMulticolumnsOfColumn(int column) { - int const row = row_of_cell(cell); - int const column1 = column_of_cell(cell); - int const column2 = right_column_of_cell(cell); - - // first set columns to 0 so we can calculate the right width - int i = column1; - for (; i <= column2; ++i) - cell_info[row][i].width_of_cell = 0; - for (i = cell + 1; (i < numberofcells) && (!IsMultiColumn(i)); ++i) - ; - if (i < numberofcells) - recalculateMulticolCells(i, GetWidthOfCell(i) - (2 * WIDTH_OF_LINE)); - SetWidthOfMulticolCell(cell, new_width); + // the last column does not have to be recalculated because all + // multicolumns will have here there last multicolumn cell which + // always will have the whole rest of the width of the cell. + if (column > (columns_ - 2)) + return; + for(int row = 0; row < rows_; ++row) { + int mc = cell_info[row][column].multicolumn; + int nmc = cell_info[row][column+1].multicolumn; + // we only have to update multicolumns which do not have this + // column as their last column! + if (mc == CELL_BEGIN_OF_MULTICOLUMN || + ((mc == CELL_PART_OF_MULTICOLUMN) && + (nmc == CELL_PART_OF_MULTICOLUMN))) + { + int const cellno = cell_info[row][column].cellno; + SetWidthOfMulticolCell(cellno, + GetWidthOfCell(cellno)-(2 * WIDTH_OF_LINE)); + } + } } @@ -586,28 +676,34 @@ bool LyXTabular::SetWidthOfCell(int cell, int new_width) int const column1 = column_of_cell(cell); bool tmp = false; int width = 0; + int add_width = 0; - if (GetWidthOfCell(cell) == (new_width+2*WIDTH_OF_LINE)) +#ifdef SPECIAL_COLUM_HANDLING + if (RightLine(cell_info[row][column1].cellno, true) && + (column1 < columns_-1) && + LeftLine(cell_info[row][column1+1].cellno, true)) +#else + if (column_info[column1].right_line && (column1 < columns_-1) && + column_info[column1+1].left_line) // additional width +#endif + { + // additional width + add_width = WIDTH_OF_LINE; + } + if (GetWidthOfCell(cell) == (new_width+2*WIDTH_OF_LINE+add_width)) { return false; + } if (IsMultiColumn(cell, true)) { tmp = SetWidthOfMulticolCell(cell, new_width); } else { - width = (new_width + 2*WIDTH_OF_LINE); + width = (new_width + 2*WIDTH_OF_LINE + add_width); cell_info[row][column1].width_of_cell = width; - if (column_info[column1].right_line && (column1 < columns_-1) && - column_info[column1+1].left_line) // additional width - cell_info[row][column1].width_of_cell += WIDTH_OF_LINE; tmp = calculate_width_of_column_NMC(column1); + if (tmp) + recalculateMulticolumnsOfColumn(column1); } if (tmp) { - int i = 0; - for (; iSetAutoBreakRows(flag); + flag = !GetPWidth(c).zero(); // because of multicolumns! + GetCellInset(c)->setAutoBreakRows(flag); } return true; } -bool LyXTabular::SetMColumnPWidth(int cell, string const & width) +bool LyXTabular::SetMColumnPWidth(int cell, LyXLength const & width) { - bool const flag = !width.empty(); + bool const flag = !width.zero(); cellinfo_of_cell(cell)->p_width = width; if (IsMultiColumn(cell)) { - GetCellInset(cell)->SetAutoBreakRows(flag); + GetCellInset(cell)->setAutoBreakRows(flag); return true; } return false; @@ -667,7 +763,7 @@ bool LyXTabular::SetMColumnPWidth(int cell, string const & width) bool LyXTabular::SetAlignSpecial(int cell, string const & special, - LyXTabular::Feature what) + LyXTabular::Feature what) { if (what == SET_SPECIAL_MULTI) cellinfo_of_cell(cell)->align_special = special; @@ -748,7 +844,7 @@ LyXTabular::GetVAlignment(int cell, bool onlycolumn) const } -string const LyXTabular::GetPWidth(int cell) const +LyXLength const LyXTabular::GetPWidth(int cell) const { if (IsMultiColumn(cell)) return cellinfo_of_cell(cell)->p_width; @@ -756,17 +852,17 @@ string const LyXTabular::GetPWidth(int cell) const } -string const LyXTabular::GetColumnPWidth(int cell) const +LyXLength const LyXTabular::GetColumnPWidth(int cell) const { return column_info[column_of_cell(cell)].p_width; } -string const LyXTabular::GetMColumnPWidth(int cell) const +LyXLength const LyXTabular::GetMColumnPWidth(int cell) const { if (IsMultiColumn(cell)) return cellinfo_of_cell(cell)->p_width; - return string(); + return LyXLength(); } @@ -795,7 +891,7 @@ int LyXTabular::GetBeginningOfTextInCell(int cell) const { int x = 0; - switch (GetAlignment(cell)){ + switch (GetAlignment(cell)) { case LYX_ALIGN_CENTER: x += (GetWidthOfColumn(cell) - GetWidthOfCell(cell)) / 2; break; @@ -912,152 +1008,65 @@ int LyXTabular::right_column_of_cell(int cell) const } -// Perfect case for a template... (Lgb) -#if 1 -template -string const write_attribute(string const & name, T const & t) -{ - string str = " " + name + "=\"" + tostr(t) + "\""; - return str; -} - -template <> -string const write_attribute(string const & name, bool const & b) -{ - return write_attribute(name, int(b)); -} - -#else - -string const write_attribute(string const & name, int value) -{ - string str = " " + name + "=\"" + tostr(value) + "\""; - return str; -} - - -string const write_attribute(string const & name, string const & value) -{ - string str = " " + name + "=\"" + value + "\""; - return str; -} - - -string const write_attribute(string const & name, bool value) -{ - string str = " " + name + "=\"" + tostr(static_cast(value)) + "\""; - return str; -} -#endif - - -template<> -inline -string const tostr(LyXAlignment const & num) -{ - switch(num) { - case LYX_ALIGN_NONE: - return "none"; - case LYX_ALIGN_BLOCK: - return "block"; - case LYX_ALIGN_LEFT: - return "left"; - case LYX_ALIGN_CENTER: - return "center"; - case LYX_ALIGN_RIGHT: - return "right"; - case LYX_ALIGN_LAYOUT: - return "layout"; - case LYX_ALIGN_SPECIAL: - return "special"; - } - return string(); -} - - -template<> -inline -string const tostr(LyXTabular::VAlignment const & num) -{ - switch(num) { - case LyXTabular::LYX_VALIGN_TOP: - return "top"; - case LyXTabular::LYX_VALIGN_CENTER: - return "center"; - case LyXTabular::LYX_VALIGN_BOTTOM: - return "bottom"; - } - return string(); -} - - -template<> -inline -string const tostr(LyXTabular::BoxType const & num) -{ - switch(num) { - case LyXTabular::BOX_NONE: - return "none"; - case LyXTabular::BOX_PARBOX: - return "parbox"; - case LyXTabular::BOX_MINIPAGE: - return "minipage"; - } - return string(); -} - - void LyXTabular::Write(Buffer const * buf, ostream & os) const { // header line os << "\n"; // global longtable options os << "\n"; for (int j = 0; j < columns_; ++j) { os << "\n"; } for (int i = 0; i < rows_; ++i) { os << "\n"; for (int j = 0; j < columns_; ++j) { os << "\n"; os << "\\begin_inset "; - cell_info[i][j].inset.Write(buf, os); + cell_info[i][j].inset.write(buf, os); os << "\n\\end_inset \n" << "\n"; } @@ -1067,156 +1076,6 @@ void LyXTabular::Write(Buffer const * buf, ostream & os) const } -namespace { - -// I would have liked a fromstr template a lot better. (Lgb) - -inline -bool string2type(string const str, LyXAlignment & num) -{ - if (str == "none") - num = LYX_ALIGN_NONE; - else if (str == "block") - num = LYX_ALIGN_BLOCK; - else if (str == "left") - num = LYX_ALIGN_LEFT; - else if (str == "center") - num = LYX_ALIGN_CENTER; - else if (str == "right") - num = LYX_ALIGN_RIGHT; - else - return false; - return true; -} - - -inline -bool string2type(string const str, LyXTabular::VAlignment & num) -{ - if (str == "top") - num = LyXTabular::LYX_VALIGN_TOP; - else if (str == "center") - num = LyXTabular::LYX_VALIGN_CENTER; - else if (str == "bottom") - num = LyXTabular::LYX_VALIGN_BOTTOM; - else - return false; - return true; -} - - -inline -bool string2type(string const str, LyXTabular::BoxType & num) -{ - if (str == "none") - num = LyXTabular::BOX_NONE; - else if (str == "parbox") - num = LyXTabular::BOX_PARBOX; - else if (str == "minipage") - num = LyXTabular::BOX_MINIPAGE; - else - return false; - return true; -} - - -inline -bool string2type(string const str, bool & num) -{ - if (str == "true") - num = true; - else if (str == "false") - num = false; - else - return false; - return true; -} - - -bool getTokenValue(string const & str, const char * token, string & ret) -{ - size_t token_length = strlen(token); - string::size_type pos = str.find(token); - - if (pos == string::npos || pos+token_length+1 >= str.length() - || str[pos+token_length] != '=') - return false; - ret.erase(); - pos += token_length + 1; - char ch = str[pos]; - if ((ch != '"') && (ch != '\'')) { // only read till next space - ret += ch; - ch = ' '; - } - while((pos < str.length() - 1) && (str[++pos] != ch)) - ret += str[pos]; - - return true; -} - - -bool getTokenValue(string const & str, const char * token, int & num) -{ - string tmp; - if (!getTokenValue(str, token, tmp)) - return false; - num = strToInt(tmp); - return true; -} - - -bool getTokenValue(string const & str, const char * token, LyXAlignment & num) -{ - string tmp; - if (!getTokenValue(str, token, tmp)) - return false; - return string2type(tmp, num); -} - - -bool getTokenValue(string const & str, const char * token, - LyXTabular::VAlignment & num) -{ - string tmp; - if (!getTokenValue(str, token, tmp)) - return false; - return string2type(tmp, num); -} - - -bool getTokenValue(string const & str, const char * token, - LyXTabular::BoxType & num) -{ - string tmp; - if (!getTokenValue(str, token, tmp)) - return false; - return string2type(tmp, num); -} - - -bool getTokenValue(string const & str, const char * token, bool & flag) -{ - string tmp; - if (!getTokenValue(str, token, tmp)) - return false; - return string2type(tmp, flag); -} - - -inline -void l_getline(istream & is, string & str) -{ - str.erase(); - while (str.empty()) { - getline(is, str); - if (!str.empty() && str[str.length() - 1] == '\r') - str.erase(str.length() - 1); - } -} - -} // namespace anon - - void LyXTabular::Read(Buffer const * buf, LyXLex & lex) { string line; @@ -1234,13 +1093,87 @@ void LyXTabular::Read(Buffer const * buf, LyXLex & lex) return; if (version == 1) ReadOld(buf, is, lex, line); - else if (version == 2) - ReadNew(buf, is, lex, line); + else if (version >= 2) + ReadNew(buf, is, lex, line, version); } +void LyXTabular::setHeaderFooterRows(int hr, int fhr, int fr, int lfr) +{ + // set header info + while(hr > 0) { + row_info[--hr].endhead = true; + } + // set firstheader info + if (fhr && (fhr < rows_)) { + if (row_info[fhr].endhead) { + while(fhr > 0) { + row_info[--fhr].endfirsthead = true; + row_info[fhr].endhead = false; + } + } else if (row_info[fhr-1].endhead) { + endfirsthead.empty = true; + } else { + while((fhr > 0) && !row_info[--fhr].endhead) { + row_info[fhr].endfirsthead = true; + } + } + } + // set footer info + if (fr && (fr < rows_)) { + if (row_info[fr].endhead && row_info[fr-1].endhead) { + while((fr > 0) && !row_info[--fr].endhead) { + row_info[fr].endfoot = true; + row_info[fr].endhead = false; + } + } else if (row_info[fr].endfirsthead && row_info[fr-1].endfirsthead) { + while((fr > 0) && !row_info[--fr].endfirsthead) { + row_info[fr].endfoot = true; + row_info[fr].endfirsthead = false; + } + } else if (!row_info[fr-1].endhead && !row_info[fr-1].endfirsthead) { + while((fr > 0) && !row_info[--fr].endhead && + !row_info[fr].endfirsthead) + { + row_info[fr].endfoot = true; + } + } + } + // set lastfooter info + if (lfr && (lfr < rows_)) { + if (row_info[lfr].endhead && row_info[lfr-1].endhead) { + while((lfr > 0) && !row_info[--lfr].endhead) { + row_info[lfr].endlastfoot = true; + row_info[lfr].endhead = false; + } + } else if (row_info[lfr].endfirsthead && + row_info[lfr-1].endfirsthead) + { + while((lfr > 0) && !row_info[--lfr].endfirsthead) { + row_info[lfr].endlastfoot = true; + row_info[lfr].endfirsthead = false; + } + } else if (row_info[lfr].endfoot && row_info[lfr-1].endfoot) { + while((lfr > 0) && !row_info[--lfr].endfoot) { + row_info[lfr].endlastfoot = true; + row_info[lfr].endfoot = false; + } + } else if (!row_info[fr-1].endhead && !row_info[fr-1].endfirsthead && + !row_info[fr-1].endfoot) + { + while((lfr > 0) && + !row_info[--lfr].endhead && !row_info[lfr].endfirsthead && + !row_info[lfr].endfoot) + { + row_info[lfr].endlastfoot = true; + } + } else if (haveLTFoot()) { + endlastfoot.empty = true; + } + } +} void LyXTabular::ReadNew(Buffer const * buf, istream & is, - LyXLex & lex, string const & l) + LyXLex & lex, string const & l, int const version) { string line(l); int rows_arg; @@ -1258,11 +1191,37 @@ void LyXTabular::ReadNew(Buffer const * buf, istream & is, } getTokenValue(line, "rotate", rotate); getTokenValue(line, "islongtable", is_long_tabular); - getTokenValue(line, "endhead", endhead); - getTokenValue(line, "endfirsthead", endfirsthead); - getTokenValue(line, "endfoot", endfoot); - getTokenValue(line, "endlastfoot", endlastfoot); - + // compatibility read for old longtable options. Now we can make any + // row part of the header/footer type we want before it was strict + // sequential from the first row down (as LaTeX does it!). So now when + // we find a header/footer line we have to go up the rows and set it + // on all preceding rows till the first or one with already a h/f option + // set. If we find a firstheader on the same line as a header or a + // lastfooter on the same line as a footer then this should be set empty. + // (Jug 20011220) + if (version < 3) { + int hrow; + int fhrow; + int frow; + int lfrow; + + getTokenValue(line, "endhead", hrow); + getTokenValue(line, "endfirsthead", fhrow); + getTokenValue(line, "endfoot", frow); + getTokenValue(line, "endlastfoot", lfrow); + setHeaderFooterRows(abs(hrow), abs(fhrow), abs(frow), abs(lfrow)); + } else { + getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL); + getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL); + getTokenValue(line, "firstHeadEmpty", endfirsthead.empty); + getTokenValue(line, "headTopDL", endhead.topDL); + getTokenValue(line, "headBottomDL", endhead.bottomDL); + getTokenValue(line, "footTopDL", endfoot.topDL); + getTokenValue(line, "footBottomDL", endfoot.bottomDL); + getTokenValue(line, "lastFootTopDL", endlastfoot.topDL); + getTokenValue(line, "lastFootBottomDL", endlastfoot.bottomDL); + getTokenValue(line, "lastFootEmpty", endlastfoot.empty); + } for (int j = 0; j < columns_; ++j) { l_getline(is,line); if (!prefixIs(line,"")) { @@ -1361,7 +1324,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) lyxerr << "Tabular format < 5 is not supported anymore\n" "Get an older version of LyX (< 1.1.x) for conversion!" << endl; - WriteAlert(_("Warning:"), + Alert::alert(_("Warning:"), _("Tabular format < 5 is not supported anymore\n"), _("Get an older version of LyX (< 1.1.x) for conversion!")); if (version > 2) { @@ -1393,10 +1356,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) cont_row_info = vector(rows_arg); SetLongTabular(is_long_tabular_arg); SetRotateTabular(rotate_arg); - endhead = a + 1; - endfirsthead = b + 1; - endfoot = c + 1; - endlastfoot = d + 1; + setHeaderFooterRows(a+1, b+1 , c+1, d+1); for (i = 0; i < rows_; ++i) { a = b = c = d = e = f = g = 0; is >> a >> b >> c >> d; @@ -1427,7 +1387,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) column_info[i].alignment = static_cast(a); column_info[i].left_line = b; column_info[i].right_line = c; - column_info[i].p_width = s1; + column_info[i].p_width = LyXLength(s1); column_info[i].align_special = s2; } for (i = 0; i < rows_; ++i) { @@ -1459,46 +1419,41 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) cell_info[i][j].rotate = static_cast(f); cell_info[i][j].usebox = static_cast(g); cell_info[i][j].align_special = s1; - cell_info[i][j].p_width = s2; + cell_info[i][j].p_width = LyXLength(s2); } } } set_row_column_number_info(true); - LyXParagraph * par = new LyXParagraph; - LyXParagraph * return_par = 0; -#ifndef NEW_INSETS - LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE; - LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE; -#endif + Paragraph * par = new Paragraph; + Paragraph * return_par = 0; + string tmptok; int pos = 0; - char depth = 0; + Paragraph::depth_type depth = 0; LyXFont font(LyXFont::ALL_INHERIT); - font.setLanguage(owner_->BufferOwner()->GetLanguage()); + font.setLanguage(owner_->bufferOwner()->getLanguage()); - while (lex.IsOK()) { + while (lex.isOK()) { lex.nextToken(); - string const token = lex.GetString(); + string const token = lex.getString(); if (token.empty()) continue; if (token == "\\layout" || token == "\\end_float" || token == "\\end_deeper") { lex.pushToken(token); +#ifndef NO_COMPABILITY + // Here we need to insert the inset_ert_contents into the last + // cell of the tabular. + owner_->bufferOwner()->insertErtContents(par, pos); +#endif break; } - if (owner_->BufferOwner()->parseSingleLyXformat2Token(lex, par, + if (owner_->bufferOwner()->parseSingleLyXformat2Token(lex, par, return_par, token, pos, - depth, font -#ifndef NEW_INSETS - , - footnoteflag, - footnotekind -#endif - )) - { + depth, font)) { // the_end read lex.pushToken(token); break; @@ -1516,15 +1471,10 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) InsetText * inset = GetCellInset(cell); int row; -#ifndef NEW_INSETS - for (int i = 0; i < par->Last(); ++i) -#else - for (int i = 0; i < par->size(); ++i) -#endif - { - if (par->IsNewline(i)) { + for (int i = 0; i < par->size(); ++i) { + if (par->isNewline(i)) { ++cell; - if (cell > GetNumberOfCells()) { + if (cell > numberofcells) { lyxerr << "Some error in reading old table format occured!" << endl << "Terminating when reading cell[" << cell << "]!" << endl; @@ -1535,7 +1485,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) if (cont_row_info[row]) { DeleteRow(row); cont_row_info.erase(cont_row_info.begin() + row); //&cont_row_info[row]); - while(!IsFirstCellInRow(--cell)); + while (!IsFirstCellInRow(--cell)); } else { inset = GetCellInset(cell); continue; @@ -1545,16 +1495,12 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl) if (!cell_info[row_of_cell(cell)][column_of_cell(cell)].usebox) { // insert a space instead - par->Erase(i); - par->InsertChar(i, ' '); + par->erase(i); + par->insertChar(i, ' '); } } - par->CopyIntoMinibuffer(*owner_->BufferOwner(), i); -#ifndef NEW_INSETS - inset->par->InsertFromMinibuffer(inset->par->Last()); -#else - inset->par->InsertFromMinibuffer(inset->par->size()); -#endif + par->copyIntoMinibuffer(*owner_->bufferOwner(), i); + inset->paragraph()->insertFromMinibuffer(inset->paragraph()->size()); } delete par; Reinit(); @@ -1680,7 +1626,7 @@ bool LyXTabular::NeedRotating() const bool LyXTabular::IsLastCell(int cell) const { - if ((cell + 1) < GetNumberOfCells()) + if ((cell + 1) < numberofcells) return false; return true; } @@ -1724,6 +1670,7 @@ int LyXTabular::GetLastCellBelow(int cell) const int LyXTabular::GetCellNumber(int row, int column) const { +#if 0 if (column >= columns_) column = columns_ - 1; else if (column < 0) @@ -1732,7 +1679,9 @@ int LyXTabular::GetCellNumber(int row, int column) const row = rows_ - 1; else if (row < 0) row = 0; - +#else + lyx::Assert(column >= 0 || column < columns_ || row >= 0 || row < rows_); +#endif return cell_info[row][column].cellno; } @@ -1745,8 +1694,8 @@ void LyXTabular::SetUsebox(int cell, BoxType type) LyXTabular::BoxType LyXTabular::GetUsebox(int cell) const { - if (column_info[column_of_cell(cell)].p_width.empty() && - !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.empty())) + if (column_info[column_of_cell(cell)].p_width.zero() && + !(IsMultiColumn(cell) && !cellinfo_of_cell(cell)->p_width.zero())) return BOX_NONE; if (cellinfo_of_cell(cell)->usebox > 1) return cellinfo_of_cell(cell)->usebox; @@ -1754,92 +1703,127 @@ LyXTabular::BoxType LyXTabular::GetUsebox(int cell) const } -void LyXTabular::SetLTHead(int cell, bool first) +/// +// This are functions used for the longtable support +/// +void LyXTabular::SetLTHead(int row, bool flag, ltType const & hd, bool first) { - int const row = row_of_cell(cell); - int const val = (row + 1) * (column_of_cell(cell) ? 1 : -1); - if (first) { - if (endfirsthead == val) - endfirsthead = 0; - else - endfirsthead = val; + endfirsthead = hd; + if (hd.set) + row_info[row].endfirsthead = flag; } else { - if (endhead == val) - endhead = 0; - else - endhead = val; + endhead = hd; + if (hd.set) + row_info[row].endhead = flag; } } -bool LyXTabular::GetRowOfLTHead(int cell, int & row) const +bool LyXTabular::GetRowOfLTHead(int row, ltType & hd) const { - row = endhead; - if (abs(endhead) > rows_) - return false; - return (row_of_cell(cell) == abs(endhead) - 1); + hd = endhead; + hd.set = haveLTHead(); + return row_info[row].endhead; } -bool LyXTabular::GetRowOfLTFirstHead(int cell, int & row) const +bool LyXTabular::GetRowOfLTFirstHead(int row, ltType & hd) const { - row = endfirsthead; - if (abs(endfirsthead) > rows_) - return false; - return (row_of_cell(cell) == abs(endfirsthead) - 1); + hd = endfirsthead; + hd.set = haveLTFirstHead(); + return row_info[row].endfirsthead; } -void LyXTabular::SetLTFoot(int cell, bool last) +void LyXTabular::SetLTFoot(int row, bool flag, ltType const & fd, bool last) { - int const row = row_of_cell(cell); - int const val = (row + 1) * (column_of_cell(cell) ? 1 : -1); - if (last) { - if (endlastfoot == val) - endlastfoot = 0; - else - endlastfoot = val; + endlastfoot = fd; + if (fd.set) + row_info[row].endlastfoot = flag; } else { - if (endfoot == val) - endfoot = 0; - else - endfoot = val; + endfoot = fd; + if (fd.set) + row_info[row].endfoot = flag; } } -bool LyXTabular::GetRowOfLTFoot(int cell, int & row) const +bool LyXTabular::GetRowOfLTFoot(int row, ltType & fd) const { - row = endfoot; - if ((endfoot + 1) > rows_) - return false; - return (row_of_cell(cell) == abs(endfoot) - 1); + fd = endfoot; + fd.set = haveLTFoot(); + return row_info[row].endfoot; } -bool LyXTabular::GetRowOfLTLastFoot(int cell, int & row) const +bool LyXTabular::GetRowOfLTLastFoot(int row, ltType & fd) const { - row = endlastfoot; - if (abs(endlastfoot) > rows_) + fd = endlastfoot; + fd.set = haveLTLastFoot(); + return row_info[row].endlastfoot; +} + + +void LyXTabular::SetLTNewPage(int row, bool what) +{ + row_info[row].newpage = what; +} + + +bool LyXTabular::GetLTNewPage(int row) const +{ + return row_info[row].newpage; +} + + +bool LyXTabular::haveLTHead() const +{ + for(int i=0; i < rows_; ++i) { + if (row_info[i].endhead) + return true; + } + return false; +} + + +bool LyXTabular::haveLTFirstHead() const +{ + if (endfirsthead.empty) return false; - return (row_of_cell(cell) == (abs(endlastfoot)-1)); + for(int i=0; i < rows_; ++i) { + if (row_info[i].endfirsthead) + return true; + } + return false; } -void LyXTabular::SetLTNewPage(int cell, bool what) +bool LyXTabular::haveLTFoot() const { - row_info[row_of_cell(cell)].newpage = what; + for(int i=0; i < rows_; ++i) { + if (row_info[i].endfoot) + return true; + } + return false; } -bool LyXTabular::GetLTNewPage(int cell) const +bool LyXTabular::haveLTLastFoot() const { - return row_info[row_of_cell(cell)].newpage; + if (endlastfoot.empty) + return false; + for(int i=0; i < rows_; ++i) { + if (row_info[i].endlastfoot) + return true; + } + return false; } +// end longtable support functions + bool LyXTabular::SetAscentOfRow(int row, int height) { if ((row >= rows_) || (row_info[row].ascent_of_row == height)) @@ -1880,7 +1864,7 @@ int LyXTabular::GetHeightOfTabular() const for (int row = 0; row < rows_; ++row) height += GetAscentOfRow(row) + GetDescentOfRow(row) + - GetAdditionalHeight(GetCellNumber(row, 0)); + GetAdditionalHeight(row); return height; } @@ -1906,7 +1890,7 @@ int LyXTabular::TeXTopHLine(ostream & os, int row) const if (TopLine(i)) ++tmp; } - if (tmp == (n - fcell)){ + if (tmp == (n - fcell)) { os << "\\hline "; } else if (tmp) { for (int i = fcell; i < n; ++i) { @@ -1939,7 +1923,7 @@ int LyXTabular::TeXBottomHLine(ostream & os, int row) const if (BottomLine(i)) ++tmp; } - if (tmp == (n-fcell)){ + if (tmp == (n - fcell)) { os << "\\hline"; } else if (tmp) { for (int i = fcell; i < n; ++i) { @@ -1972,9 +1956,14 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const if (!cellinfo_of_cell(cell)->align_special.empty()) { os << cellinfo_of_cell(cell)->align_special << "}{"; } else { - if (LeftLine(cell)) + if (LeftLine(cell) && + (IsFirstCellInRow(cell) || + (!IsMultiColumn(cell-1) && !LeftLine(cell, true) && + !RightLine(cell-1, true)))) + { os << '|'; - if (!GetPWidth(cell).empty()) { + } + if (!GetPWidth(cell).zero()) { switch (GetVAlignment(cell)) { case LYX_VALIGN_TOP: os << "p"; @@ -1986,7 +1975,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const os << "b"; break; } - os << "{" << GetPWidth(cell) << '}'; + os << "{" << GetPWidth(cell).asLatexString() << '}'; } else { switch (GetAlignment(cell)) { case LYX_ALIGN_LEFT: @@ -2021,7 +2010,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const os << "b"; break; } - os << "]{" << GetPWidth(cell) << "}{"; + os << "]{" << GetPWidth(cell).asLatexString() << "}{"; } else if (GetUsebox(cell) == BOX_MINIPAGE) { os << "\\begin{minipage}["; switch (GetVAlignment(cell)) { @@ -2035,7 +2024,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const os << "b"; break; } - os << "]{" << GetPWidth(cell) << "}\n"; + os << "]{" << GetPWidth(cell).asLatexString() << "}\n"; ++ret; } return ret; @@ -2053,7 +2042,7 @@ int LyXTabular::TeXCellPostamble(ostream & os, int cell) const os << "%\n\\end{minipage}"; ret += 2; } - if (IsMultiColumn(cell)){ + if (IsMultiColumn(cell)) { os << '}'; } if (GetRotateCell(cell)) { @@ -2064,11 +2053,146 @@ int LyXTabular::TeXCellPostamble(ostream & os, int cell) const } -int LyXTabular::Latex(Buffer const * buf, +int LyXTabular::TeXLongtableHeaderFooter(ostream & os, Buffer const * buf, + bool fragile, bool fp) const +{ + if (!is_long_tabular) + return 0; + + int ret = 0; + // output header info + if (haveLTHead()) { + if (endhead.topDL) { + os << "\\hline\n"; + ++ret; + } + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endhead) { + ret += TeXRow(os, i, buf, fragile, fp); + } + } + if (endhead.bottomDL) { + os << "\\hline\n"; + ++ret; + } + os << "\\endhead\n"; + ++ret; + if (endfirsthead.empty) { + os << "\\endfirsthead\n"; + ++ret; + } + } + // output firstheader info + if (haveLTFirstHead()) { + if (endfirsthead.topDL) { + os << "\\hline\n"; + ++ret; + } + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endfirsthead) { + ret += TeXRow(os, i, buf, fragile, fp); + } + } + if (endfirsthead.bottomDL) { + os << "\\hline\n"; + ++ret; + } + os << "\\endfirsthead\n"; + ++ret; + } + // output footer info + if (haveLTFoot()) { + if (endfoot.topDL) { + os << "\\hline\n"; + ++ret; + } + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endfoot) { + ret += TeXRow(os, i, buf, fragile, fp); + } + } + if (endfoot.bottomDL) { + os << "\\hline\n"; + ++ret; + } + os << "\\endfoot\n"; + ++ret; + if (endlastfoot.empty) { + os << "\\endlastfoot\n"; + ++ret; + } + } + // output lastfooter info + if (haveLTLastFoot()) { + if (endlastfoot.topDL) { + os << "\\hline\n"; + ++ret; + } + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endlastfoot) { + ret += TeXRow(os, i, buf, fragile, fp); + } + } + if (endlastfoot.bottomDL) { + os << "\\hline\n"; + ++ret; + } + os << "\\endlastfoot\n"; + ++ret; + } + return ret; +} + + +bool LyXTabular::isValidRow(int const row) const +{ + if (!is_long_tabular) + return true; + return (!row_info[row].endhead && !row_info[row].endfirsthead && + !row_info[row].endfoot && !row_info[row].endlastfoot); +} + + +int LyXTabular::TeXRow(ostream & os, int const i, Buffer const * buf, + bool fragile, bool fp) const +{ + int ret = 0; + int cell = GetCellNumber(i, 0); + + ret += TeXTopHLine(os, i); + for (int j = 0; j < columns_; ++j) { + if (IsPartOfMultiColumn(i,j)) + continue; + ret += TeXCellPreamble(os, cell); + InsetText * inset = GetCellInset(cell); + + bool rtl = inset->paragraph()->isRightToLeftPar(buf->params) && + inset->paragraph()->size() > 0 && GetPWidth(cell).zero(); + + if (rtl) + os << "\\R{"; + ret += inset->latex(buf, os, fragile, fp); + if (rtl) + os << "}"; + + ret += TeXCellPostamble(os, cell); + if (!IsLastCellInRow(cell)) { // not last cell in row + os << "&\n"; + ++ret; + } + ++cell; + } + os << "\\\\\n"; + ++ret; + ret += TeXBottomHLine(os, i); + return ret; +} + + +int LyXTabular::latex(Buffer const * buf, ostream & os, bool fragile, bool fp) const { int ret = 0; - int cell = 0; //+--------------------------------------------------------------------- //+ first the opening preamble + @@ -2083,121 +2207,56 @@ int LyXTabular::Latex(Buffer const * buf, else os << "\\begin{tabular}{"; for (int i = 0; i < columns_; ++i) { - if (column_info[i].left_line) - os << '|'; if (!column_info[i].align_special.empty()) { os << column_info[i].align_special; - } else if (!column_info[i].p_width.empty()) { - switch (column_info[i].valignment) { - case LYX_VALIGN_TOP: - os << "p"; - break; - case LYX_VALIGN_CENTER: - os << "m"; - break; - case LYX_VALIGN_BOTTOM: - os << "b"; - break; + } else { + if (column_info[i].left_line) + os << '|'; + if (!column_info[i].p_width.zero()) { + switch (column_info[i].valignment) { + case LYX_VALIGN_TOP: + os << "p"; + break; + case LYX_VALIGN_CENTER: + os << "m"; + break; + case LYX_VALIGN_BOTTOM: + os << "b"; + break; } - os << "{" - << column_info[i].p_width - << '}'; - } else { - switch (column_info[i].alignment) { - case LYX_ALIGN_LEFT: - os << 'l'; - break; - case LYX_ALIGN_RIGHT: + os << "{" + << column_info[i].p_width.asLatexString() + << '}'; + } else { + switch (column_info[i].alignment) { + case LYX_ALIGN_LEFT: + os << 'l'; + break; + case LYX_ALIGN_RIGHT: os << 'r'; break; - default: - os << 'c'; - break; + default: + os << 'c'; + break; + } } + if (column_info[i].right_line) + os << '|'; } - if (column_info[i].right_line) - os << '|'; } os << "}\n"; ++ret; + ret += TeXLongtableHeaderFooter(os, buf, fragile, fp); + //+--------------------------------------------------------------------- //+ the single row and columns (cells) + //+--------------------------------------------------------------------- for (int i = 0; i < rows_; ++i) { - ret += TeXTopHLine(os, i); - int bret = ret; - if (IsLongTabular()) { - if ((endhead < 0) && (i == (abs(endhead)-1))) { - os << "\\endhead\n"; - ++ret; - } - if ((endfirsthead < 0) && (i == (abs(endfirsthead)-1))) { - os << "\\endfirsthead\n"; - ++ret; - } - if ((endfoot < 0) && (i == (abs(endfoot)-1))) { - os << "\\endfoot\n"; - ++ret; - } - if ((endlastfoot < 0) && (i == (abs(endlastfoot)-1))) { - os << "\\endlastfoot\n"; - ++ret; - } - } - if (ret > bret) { - ret += TeXBottomHLine(os, i-1); - ret += TeXTopHLine(os, i); - } - for (int j = 0; j < columns_; ++j) { - if (IsPartOfMultiColumn(i,j)) - continue; - ret += TeXCellPreamble(os, cell); - InsetText * inset = GetCellInset(cell); - - bool rtl = inset->par->isRightToLeftPar(buf->params) && -#ifndef NEW_INSETS - inset->par->Last() > 0 && GetPWidth(cell).empty(); -#else - inset->par->size() > 0 && GetPWidth(cell).empty(); -#endif - if (rtl) - os << "\\R{"; - ret += inset->Latex(buf, os, fragile, fp); - if (rtl) - os << "}"; - - ret += TeXCellPostamble(os, cell); - if (!IsLastCellInRow(cell)) { // not last cell in row - os << "&\n"; - ++ret; - } - ++cell; - } - os << "\\\\\n"; - ret += TeXBottomHLine(os, i); - bret = ret; - if (IsLongTabular()) { - if ((endhead > 0) && (i == (endhead - 1))) { - os << "\\endhead\n"; - ++ret; - } - if ((endfirsthead > 0) && (i == (endfirsthead - 1))) { - os << "\\endfirsthead\n"; - ++ret; - } - if ((endfoot > 0) && (i == (endfoot - 1))) { - os << "\\endfoot\n"; - ++ret; - } - if ((endlastfoot > 0) && (i == (endlastfoot - 1))) { - os << "\\endlastfoot\n"; - ++ret; - } -// if (ret > bret) -// ret += TeXBottomHLine(os, i); - if (row_info[i].newpage) { + if (isValidRow(i)) { + ret += TeXRow(os, i, buf, fragile, fp); + if (is_long_tabular && row_info[i].newpage) { os << "\\newpage\n"; ++ret; } @@ -2221,7 +2280,58 @@ int LyXTabular::Latex(Buffer const * buf, } -int LyXTabular::DocBook(Buffer const * buf, ostream & os) const +int LyXTabular::docbookRow(Buffer const * buf, ostream & os, int row) const +{ + int ret = 0; + int cell = GetFirstCellInRow(row); + + os << "\n"; + for (int j = 0; j < columns_; ++j) { + if (IsPartOfMultiColumn(row, j)) + continue; + + os << ""; + ret += GetCellInset(cell)->docbook(buf, os); + os << "\n"; + ++cell; + } + os << "\n"; + return ret; +} + + +int LyXTabular::docBook(Buffer const * buf, ostream & os) const { int ret = 0; @@ -2245,7 +2355,36 @@ int LyXTabular::DocBook(Buffer const * buf, ostream & os) const os << "center"; break; } - os << "\"/>\n"; + os << "\">\n"; + ++ret; + } + + //+--------------------------------------------------------------------- + //+ Long Tabular case + + //+--------------------------------------------------------------------- + + // output header info + if (haveLTHead() || haveLTFirstHead()) { + os << "\n"; + ++ret; + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endhead || row_info[i].endfirsthead) { + ret += docbookRow(buf, os, i); + } + } + os << "\n"; + ++ret; + } + // output footer info + if (haveLTFoot() || haveLTLastFoot()) { + os << "\n"; + ++ret; + for (int i = 0; i < rows_; ++i) { + if (row_info[i].endfoot || row_info[i].endlastfoot) { + ret += docbookRow(buf, os, i); + } + } + os << "\n"; ++ret; } @@ -2253,53 +2392,15 @@ int LyXTabular::DocBook(Buffer const * buf, ostream & os) const //+ the single row and columns (cells) + //+--------------------------------------------------------------------- - int cell = 0; os << "\n"; + ++ret; for (int i = 0; i < rows_; ++i) { - os << "\n"; - for (int j = 0; j < columns_; ++j) { - if (IsPartOfMultiColumn(i, j)) - continue; - - os << ""; - ret += GetCellInset(cell)->DocBook(buf, os); - os << ""; - ++cell; + if (isValidRow(i)) { + ret += docbookRow(buf, os, i); } - os << "\n"; } os << "\n"; + ++ret; //+--------------------------------------------------------------------- //+ the closing of the tabular + //+--------------------------------------------------------------------- @@ -2310,20 +2411,11 @@ int LyXTabular::DocBook(Buffer const * buf, ostream & os) const return ret; } - -namespace { - - inline - void print_n_chars(ostream & os, unsigned char ch, int n) - { - os << string(n, ch); - } - -} // namespace anon - - -int LyXTabular::AsciiTopHLine(ostream & os, int row, - vector const & clen) const +//-- +// ASCII export function and helpers +//-- +int LyXTabular::asciiTopHLine(ostream & os, int row, + vector const & clen) const { int const fcell = GetFirstCellInRow(row); int const n = NumberOfCellsInRow(fcell) + fcell; @@ -2352,9 +2444,9 @@ int LyXTabular::AsciiTopHLine(ostream & os, int row, } int column = column_of_cell(i); int len = clen[column]; - while(IsPartOfMultiColumn(row, ++column)) + while (IsPartOfMultiColumn(row, ++column)) len += clen[column] + 4; - print_n_chars(os, ch, len); + os << string(len, ch); if (TopLine(i)) { if (RightLine(i)) os << "-+"; @@ -2369,8 +2461,8 @@ int LyXTabular::AsciiTopHLine(ostream & os, int row, } -int LyXTabular::AsciiBottomHLine(ostream & os, int row, - vector const & clen) const +int LyXTabular::asciiBottomHLine(ostream & os, int row, + vector const & clen) const { int const fcell = GetFirstCellInRow(row); int const n = NumberOfCellsInRow(fcell) + fcell; @@ -2399,9 +2491,9 @@ int LyXTabular::AsciiBottomHLine(ostream & os, int row, } int column = column_of_cell(i); int len = clen[column]; - while(IsPartOfMultiColumn(row, ++column)) + while (IsPartOfMultiColumn(row, ++column)) len += clen[column] + 4; - print_n_chars(os, ch, len); + os << string(len, ch); if (BottomLine(i)) { if (RightLine(i)) os << "-+"; @@ -2416,13 +2508,19 @@ int LyXTabular::AsciiBottomHLine(ostream & os, int row, } -int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os, - int cell, int row, int column, - vector const & clen) const +int LyXTabular::asciiPrintCell(Buffer const * buf, ostream & os, + int cell, int row, int column, + vector const & clen, + bool onlydata) const { ostringstream sstr; - int ret = GetCellInset(cell)->Ascii(buf, sstr, 0); + int ret = GetCellInset(cell)->ascii(buf, sstr, 0); + if (onlydata) { + os << sstr.str(); + return ret; + } + if (LeftLine(cell)) os << "| "; else @@ -2430,7 +2528,7 @@ int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os, unsigned int len1 = sstr.str().length(); unsigned int len2 = clen[column]; - while(IsPartOfMultiColumn(row, ++column)) + while (IsPartOfMultiColumn(row, ++column)) len2 += clen[column] + 4; len2 -= len1; @@ -2463,7 +2561,8 @@ int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os, } -int LyXTabular::Ascii(Buffer const * buf, ostream & os) const +int LyXTabular::ascii(Buffer const * buf, ostream & os, int const depth, + bool onlydata, unsigned char delim) const { int ret = 0; @@ -2472,101 +2571,161 @@ int LyXTabular::Ascii(Buffer const * buf, ostream & os) const //+--------------------------------------------------------------------- vector clen(columns_); - // first all non (real) multicolumn cells! - for (int j = 0; j < columns_; ++j) { - clen[j] = 0; - for (int i = 0; i < rows_; ++i) { - int cell = GetCellNumber(i, j); - if (IsMultiColumn(cell, true)) - continue; - ostringstream sstr; - GetCellInset(cell)->Ascii(buf, sstr, 0); - if (clen[j] < sstr.str().length()) - clen[j] = sstr.str().length(); + if (!onlydata) { + // first all non (real) multicolumn cells! + for (int j = 0; j < columns_; ++j) { + clen[j] = 0; + for (int i = 0; i < rows_; ++i) { + int cell = GetCellNumber(i, j); + if (IsMultiColumn(cell, true)) + continue; + ostringstream sstr; + GetCellInset(cell)->ascii(buf, sstr, 0); + if (clen[j] < sstr.str().length()) + clen[j] = sstr.str().length(); + } } - } - // then all (real) multicolumn cells! - for (int j = 0; j < columns_; ++j) { - for (int i = 0; i < rows_; ++i) { - int cell = GetCellNumber(i, j); - if (!IsMultiColumn(cell, true) || IsPartOfMultiColumn(i, j)) - continue; - ostringstream sstr; - GetCellInset(cell)->Ascii(buf, sstr, 0); - int len = int(sstr.str().length()); - int const n = cells_in_multicolumn(cell); - for (int k = j; (len > 0) && (k < (j + n - 1)); ++k) - len -= clen[k]; - if (len > int(clen[j + n - 1])) - clen[j + n - 1] = len; + // then all (real) multicolumn cells! + for (int j = 0; j < columns_; ++j) { + for (int i = 0; i < rows_; ++i) { + int cell = GetCellNumber(i, j); + if (!IsMultiColumn(cell, true) || IsPartOfMultiColumn(i, j)) + continue; + ostringstream sstr; + GetCellInset(cell)->ascii(buf, sstr, 0); + int len = int(sstr.str().length()); + int const n = cells_in_multicolumn(cell); + for (int k = j; (len > 0) && (k < (j + n - 1)); ++k) + len -= clen[k]; + if (len > int(clen[j + n - 1])) + clen[j + n - 1] = len; + } } } int cell = 0; for (int i = 0; i < rows_; ++i) { - AsciiTopHLine(os, i, clen); + if (!onlydata) { + if (asciiTopHLine(os, i, clen)) { + for (int j = 0; j < depth; ++j) + os << " "; + } + } for (int j = 0; j < columns_; ++j) { if (IsPartOfMultiColumn(i,j)) continue; - ret += AsciiPrintCell(buf, os, cell, i, j, clen); + if (onlydata && j > 0) + os << delim; + ret += asciiPrintCell(buf, os, cell, i, j, clen, onlydata); ++cell; } os << endl; - AsciiBottomHLine(os, i, clen); + if (!onlydata) { + for (int j = 0; j < depth; ++j) + os << " "; + if (asciiBottomHLine(os, i, clen)) { + for (int j = 0; j < depth; ++j) + os << " "; + } + } } return ret; } +//-- +// end ascii export +//-- InsetText * LyXTabular::GetCellInset(int cell) const { + cur_cell = cell; return & cell_info[row_of_cell(cell)][column_of_cell(cell)].inset; } InsetText * LyXTabular::GetCellInset(int row, int column) const { - return GetCellInset(GetCellNumber(row, column)); + cur_cell = GetCellNumber(row, column); + return & cell_info[row][column].inset; +} + + +int LyXTabular::GetCellFromInset(Inset const * inset, int maybe_cell) const +{ + // is this inset part of the tabular? + if (!inset || inset->owner() != owner_) { + lyxerr[Debug::INSETTEXT] + << "this is not a cell of the tabular!" << endl; + return -1; + } + + const int save_cur_cell = cur_cell; + int cell = cur_cell; + if (GetCellInset(cell) != inset) { + cell = maybe_cell; + if (cell == -1 || GetCellInset(cell) != inset) { + cell = -1; + } + } + + if (cell == -1) { + for (cell = GetNumberOfCells(); cell >= 0; --cell) { + if (GetCellInset(cell) == inset) + break; + } + lyxerr[Debug::INSETTEXT] + << "LyXTabular::GetCellFromInset: " + << "cell=" << cell + << ", cur_cell=" << save_cur_cell + << ", maybe_cell=" << maybe_cell + << endl; + // We should have found a cell at this point + if (cell == -1) { + lyxerr << "LyXTabular::GetCellFromInset: " + << "Cell not found!" << endl; + } + } + + return cell; } void LyXTabular::Validate(LaTeXFeatures & features) const { if (IsLongTabular()) - features.longtable = true; + features.require("longtable"); if (NeedRotating()) - features.rotating = true; - for (int cell = 0; !features.array && (cell < numberofcells); ++cell) { + features.require("rotating"); + for (int cell = 0; cell < numberofcells; ++cell) { if (GetVAlignment(cell) != LYX_VALIGN_TOP) - features.array = true; - GetCellInset(cell)->Validate(features); + features.require("array"); + GetCellInset(cell)->validate(features); } } -#ifndef NEW_INSETS -LyXTabular::BoxType LyXTabular::UseParbox(int cell) const +vector const LyXTabular::getLabelList() const { - LyXParagraph * par = GetCellInset(cell)->par; - - for (; par; par = par->next_) { - for (int i = 0; i < par->Last(); ++i) { - if (par->GetChar(i) == LyXParagraph::META_NEWLINE) - return BOX_PARBOX; + vector label_list; + for (int i = 0; i < rows_; ++i) + for (int j = 0; j < columns_; ++j) { + vector const l = + GetCellInset(i, j)->getLabelList(); + label_list.insert(label_list.end(), + l.begin(), l.end()); } - } - return BOX_NONE; + return label_list; } -#else + + LyXTabular::BoxType LyXTabular::UseParbox(int cell) const { - LyXParagraph * par = GetCellInset(cell)->par; + Paragraph * par = GetCellInset(cell)->paragraph(); for (; par; par = par->next()) { for (int i = 0; i < par->size(); ++i) { - if (par->GetChar(i) == LyXParagraph::META_NEWLINE) + if (par->getChar(i) == Paragraph::META_NEWLINE) return BOX_PARBOX; } } return BOX_NONE; } -#endif