]> git.lyx.org Git - lyx.git/blobdiff - src/tabular.C
More fixes to the autocollapsing of paragraphs.
[lyx.git] / src / tabular.C
index f681ee2533af66cbad3632767d333ebd6e0e044a..380e8b9d0841a7c16332d9112a927bfebe92ad3d 100644 (file)
@@ -16,6 +16,9 @@
 #pragma implementation
 #endif
 
+// temporary until verified (08/08/2001 Jug)
+#define SPECIAL_COLUM_HANDLING 1
+
 #include <algorithm>
 #include <cstdlib>
 
 #include "debug.h"
 #include "vspace.h"
 #include "layout.h"
-#include "lyx_gui_misc.h"
+#include "frontends/Alert.h"
 #include "buffer.h"
 #include "BufferView.h"
 #include "Painter.h"
 #include "LaTeXFeatures.h"
 #include "support/lstrings.h"
 #include "support/lyxmanip.h"
+#include "support/LAssert.h"
 #include "insets/insettabular.h"
 #include "insets/insettext.h"
 #include "gettext.h"
@@ -89,6 +93,14 @@ LyXTabular::columnstruct::columnstruct()
 }
 
 
+LyXTabular::lttype::lttype()
+{
+       row = 0;
+       topDL = false;
+       bottomDL = false;
+}
+
+
 /* konstruktor */
 LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
 {
@@ -98,11 +110,23 @@ LyXTabular::LyXTabular(InsetTabular * inset, int rows_arg, int columns_arg)
 }
 
 
-LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt)
+LyXTabular::LyXTabular(InsetTabular * inset, LyXTabular const & lt,
+                       bool same_id)
 {
        owner_ = inset;
        cur_cell = -1;
        Init(lt.rows_, lt.columns_, &lt);
+       // 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)
@@ -152,9 +176,9 @@ LyXTabular & LyXTabular::operator=(LyXTabular const & lt)
 }
 
 
-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!
@@ -207,10 +231,10 @@ void LyXTabular::Init(int rows_arg, int columns_arg, LyXTabular const * lt)
        set_row_column_number_info();
        is_long_tabular = false;
        rotate = false;
-       endhead = 0;
-       endfirsthead = 0;
-       endfoot = 0;
-       endlastfoot = 0;
+       endhead.row = 0;
+       endfirsthead.row = 0;
+       endfoot.row = 0;
+       endlastfoot.row = 0;
 }
 
 
@@ -254,9 +278,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]);
@@ -286,12 +307,12 @@ 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;
+                       c_info[i][column + 2].multicolumn != CELL_PART_OF_MULTICOLUMN) {
+                       c_info[i][column + 1].multicolumn = LyXTabular::CELL_NORMAL;
                }
        }
        cell_info = c_info;
@@ -320,12 +341,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_);
+                       }
                }
        }
   
@@ -383,7 +412,7 @@ void LyXTabular::set_row_column_number_info(bool oldformat)
                                        cell_info[row][column+cn-1].right_line;
                        }
                        cell_info[row][column].inset.setAutoBreakRows(
-                               !GetPWidth(GetCellNumber(row, column)).empty());
+                               !GetPWidth(GetCellNumber(row, column)).zero());
                }
        }
 }
@@ -434,17 +463,43 @@ 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
 }
 
 
@@ -477,7 +532,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;
 }
@@ -526,11 +585,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;
+       }
 }
 
 
@@ -607,17 +669,28 @@ 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) {
@@ -657,9 +730,9 @@ bool LyXTabular::SetVAlignment(int cell, VAlignment align, bool onlycolumn)
 }
 
 
-bool LyXTabular::SetColumnPWidth(int cell, string const & width)
+bool LyXTabular::SetColumnPWidth(int cell, LyXLength const & width)
 {
-       bool flag = !width.empty();
+       bool flag = !width.zero();
        int const j = column_of_cell(cell);
 
        column_info[j].p_width = width;
@@ -667,16 +740,16 @@ bool LyXTabular::SetColumnPWidth(int cell, string const & width)
                SetAlignment(cell, LYX_ALIGN_LEFT);
        for (int i = 0; i < rows_; ++i) {
                int c = GetCellNumber(i, j);
-               flag = !GetPWidth(c).empty(); // because of multicolumns!
+               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)) {
@@ -769,7 +842,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;
@@ -777,17 +850,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();
 }
 
 
@@ -934,6 +1007,7 @@ int LyXTabular::right_column_of_cell(int cell) const
 
 
 // Perfect case for a template... (Lgb)
+// or perhaps not...
 #if 1
 template<class T>
 string const write_attribute(string const & name, T const & t)
@@ -948,6 +1022,11 @@ string const write_attribute(string const & name, bool const & b)
        return write_attribute(name, int(b));
 }
 
+template <>
+string const write_attribute(string const & name, LyXLength const & value)
+{
+       return write_attribute(name, value.asString());
+}
 #else
 
 string const write_attribute(string const & name, int value)
@@ -969,6 +1048,13 @@ string const write_attribute(string const & name, bool value)
        string str = " " + name + "=\"" + tostr(static_cast<int>(value)) + "\"";
        return str;
 }
+
+
+string const write_attribute(string const & name, LyXLength const & value)
+{
+       string str = " " + name + "=\"" + value.asString() + "\"";
+       return str;
+}
 #endif
 
 
@@ -1040,10 +1126,10 @@ void LyXTabular::Write(Buffer const * buf, ostream & os) const
        os << "<features"
           << write_attribute("rotate", tostr(rotate))
           << write_attribute("islongtable", tostr(is_long_tabular))
-          << write_attribute("endhead", endhead)
-          << write_attribute("endfirsthead", endfirsthead)
-          << write_attribute("endfoot", endfoot)
-          << write_attribute("endlastfoot", endlastfoot)
+          << write_attribute("endhead", endhead.row)
+          << write_attribute("endfirsthead", endfirsthead.row)
+          << write_attribute("endfoot", endfoot.row)
+          << write_attribute("endlastfoot", endlastfoot.row)
           << ">\n";
        for (int j = 0; j < columns_; ++j) {
                os << "<column"
@@ -1051,9 +1137,7 @@ void LyXTabular::Write(Buffer const * buf, ostream & os) const
                   << write_attribute("valignment", tostr(column_info[j].valignment))
                   << write_attribute("leftline", tostr(column_info[j].left_line))
                   << write_attribute("rightline", tostr(column_info[j].right_line))
-                  << write_attribute("width",
-                                                         VSpace(column_info[j].p_width)
-                                                         .asLyXCommand())
+                  << write_attribute("width", column_info[j].p_width.asString())
                   << write_attribute("special", column_info[j].align_special)
                   << ">\n";
        }
@@ -1169,7 +1253,7 @@ bool getTokenValue(string const & str, const char * token, string & ret)
                ret += ch;
                ch = ' ';
        }
-       while((pos < str.length() - 1) && (str[++pos] != ch))
+       while ((pos < str.length() - 1) && (str[++pos] != ch))
                ret += str[pos];
 
        return true;
@@ -1224,6 +1308,15 @@ bool getTokenValue(string const & str, const char * token, bool & flag)
 }    
 
 
+bool getTokenValue(string const & str, const char * token, LyXLength & len)
+{
+       string tmp;
+       if (!getTokenValue(str, token, tmp))
+               return false;
+       return isValidLength(tmp, &len);
+}    
+
+
 inline
 void l_getline(istream & is, string & str)
 {
@@ -1279,11 +1372,14 @@ 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);
-
+       getTokenValue(line, "endhead", endhead.row);
+       getTokenValue(line, "endfirsthead", endfirsthead.row);
+       getTokenValue(line, "endfoot", endfoot.row);
+       getTokenValue(line, "endlastfoot", endlastfoot.row);
+       endhead.row = abs(endhead.row);
+       endfirsthead.row = abs(endfirsthead.row);
+       endfoot.row = abs(endfoot.row);
+       endlastfoot.row = abs(endlastfoot.row);
        for (int j = 0; j < columns_; ++j) {
                l_getline(is,line);
                if (!prefixIs(line,"<column")) {
@@ -1382,7 +1478,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) {
@@ -1414,10 +1510,10 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
                cont_row_info = vector<int>(rows_arg);
                SetLongTabular(is_long_tabular_arg);
                SetRotateTabular(rotate_arg);
-               endhead = a + 1;
-               endfirsthead = b + 1;
-               endfoot = c + 1;
-               endlastfoot = d + 1;
+               endhead.row = a + 1;
+               endfirsthead.row = b + 1;
+               endfoot.row = c + 1;
+               endlastfoot.row = d + 1;
                for (i = 0; i < rows_; ++i) {
                        a = b = c = d = e = f = g = 0;
                        is >> a >> b >> c >> d;
@@ -1448,7 +1544,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
                        column_info[i].alignment = static_cast<LyXAlignment>(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) {
@@ -1480,7 +1576,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
                                cell_info[i][j].rotate = static_cast<bool>(f);
                                cell_info[i][j].usebox = static_cast<BoxType>(g);
                                cell_info[i][j].align_special = s1;
-                               cell_info[i][j].p_width = s2;
+                               cell_info[i][j].p_width = LyXLength(s2);
                        }
                }
        }
@@ -1495,15 +1591,20 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
        LyXFont font(LyXFont::ALL_INHERIT);
        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, font);
+#endif
                        break;
                }
                if (owner_->bufferOwner()->parseSingleLyXformat2Token(lex, par,
@@ -1530,7 +1631,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
        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;
@@ -1541,7 +1642,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;
@@ -1556,7 +1657,7 @@ void LyXTabular::OldFormatRead(LyXLex & lex, string const & fl)
                        }
                }
                par->copyIntoMinibuffer(*owner_->bufferOwner(), i);
-               inset->par->insertFromMinibuffer(inset->par->size());
+               inset->paragraph()->insertFromMinibuffer(inset->paragraph()->size());
        }
        delete par;
        Reinit();
@@ -1682,7 +1783,7 @@ bool LyXTabular::NeedRotating() const
 
 bool LyXTabular::IsLastCell(int cell) const
 {
-       if ((cell + 1) < GetNumberOfCells())
+       if ((cell + 1) < numberofcells)
                return false;
        return true;
 }
@@ -1726,6 +1827,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)
@@ -1734,7 +1836,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;
 }
 
@@ -1747,86 +1851,67 @@ 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;
        return UseParbox(cell);
 }
 
-
-void LyXTabular::SetLTHead(int cell, bool first)
+bool LyXTabular::checkLTType(int row, ltType const & ltt) const
 {
-       int const row = row_of_cell(cell);
-       int const val = (row + 1) * (column_of_cell(cell) ? 1 : -1);
+       if (!ltt.row || (ltt.row > rows_))
+               return false;
+       return (row == (ltt.row - 1));
+}
+
 
+void LyXTabular::SetLTHead(ltType const & hd, bool first)
+{
        if (first) {
-               if (endfirsthead == val)
-                       endfirsthead = 0;
-               else
-                       endfirsthead = val;
+               endfirsthead = hd;
        } else {
-               if (endhead == val)
-                       endhead = 0;
-               else
-                       endhead = val;
+               endhead = hd;
        }
 }
 
 
-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;
+       return checkLTType(row, hd);
 }
 
 
-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;
+       return checkLTType(row, hd);
 }
 
 
-void LyXTabular::SetLTFoot(int cell, bool last)
+void LyXTabular::SetLTFoot(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;
        } else {
-               if (endfoot == val)
-                       endfoot = 0;
-               else
-                       endfoot = val;
+               endfoot = fd;
        }
 }
 
 
-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;
+       return checkLTType(row, fd);
 }
 
 
-bool LyXTabular::GetRowOfLTLastFoot(int cell, int & row) const
+bool LyXTabular::GetRowOfLTLastFoot(int row, ltType & fd) const
 {
-       row = endlastfoot;
-       if (abs(endlastfoot) > rows_)
-               return false;
-       return (row_of_cell(cell) == (abs(endlastfoot)-1));
+       fd = endlastfoot;
+       return checkLTType(row, fd);
 }
 
 
@@ -1981,7 +2066,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
                        {
                                os << '|';
                        }
-                       if (!GetPWidth(cell).empty()) {
+                       if (!GetPWidth(cell).zero()) {
                                switch (GetVAlignment(cell)) {
                                case LYX_VALIGN_TOP:
                                        os << "p";
@@ -1993,7 +2078,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:
@@ -2028,7 +2113,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)) {
@@ -2042,7 +2127,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
                        os << "b";
                        break;
                }
-               os << "]{" << GetPWidth(cell) << "}\n";
+               os << "]{" << GetPWidth(cell).asLatexString() << "}\n";
                ++ret;
        }
        return ret;
@@ -2090,40 +2175,42 @@ 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;
@@ -2134,37 +2221,21 @@ int LyXTabular::Latex(Buffer const * buf,
 
        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;
-                       }
-               }
+#warning Implement top double lines for LT Header/Footers
+#if 0
                if (ret > bret) {
                        ret += TeXBottomHLine(os, i-1);
                        ret += TeXTopHLine(os, i);
                }
+#endif
                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) &&
-                                       inset->par->size() > 0 && GetPWidth(cell).empty();
+                       bool rtl = inset->paragraph()->isRightToLeftPar(buf->params) &&
+                                       inset->paragraph()->size() > 0 && GetPWidth(cell).zero();
 
                        if (rtl)
                                os << "\\R{";
@@ -2180,27 +2251,33 @@ int LyXTabular::Latex(Buffer const * buf,
                        ++cell;
                }
                os << "\\\\\n";
+               ++ret;
                ret += TeXBottomHLine(os, i);
-               bret = ret;
                if (IsLongTabular()) {
-                       if ((endhead > 0) && (i == (endhead - 1))) {
+                       if (i == (endhead.row - 1)) {
+                               if (endhead.bottomDL)
+                                       ret += TeXBottomHLine(os, i);
                                os << "\\endhead\n";
                                ++ret;
                        }
-                       if ((endfirsthead > 0) && (i == (endfirsthead - 1))) {
+                       if (i == (endfirsthead.row - 1)) {
+                               if (endfirsthead.bottomDL)
+                                       ret += TeXBottomHLine(os, i);
                                os << "\\endfirsthead\n";
                                ++ret;
                        }
-                       if ((endfoot > 0) && (i == (endfoot - 1))) {
+                       if (i == (endfoot.row - 1)) {
+                               if (endfoot.bottomDL)
+                                       ret += TeXBottomHLine(os, i);
                                os << "\\endfoot\n";
                                ++ret;
                        }
-                       if ((endlastfoot > 0) && (i == (endlastfoot - 1))) {
+                       if (i == (endlastfoot.row - 1)) {
+                               if (endlastfoot.bottomDL)
+                                       ret += TeXBottomHLine(os, i);
                                os << "\\endlastfoot\n";
                                ++ret;
                        }
-//         if (ret > bret)
-//             ret += TeXBottomHLine(os, i);
                        if (row_info[i].newpage) {
                                os << "\\newpage\n";
                                ++ret;
@@ -2225,6 +2302,57 @@ int LyXTabular::Latex(Buffer const * buf,
 }
 
 
+int LyXTabular::docbookRow(Buffer const * buf, ostream & os, int row) const
+{
+       int ret = 0;
+       int cell = GetFirstCellInRow(row);
+       
+       os << "<row>\n";
+       for (int j = 0; j < columns_; ++j) {
+               if (IsPartOfMultiColumn(row, j))
+                       continue;
+
+               os << "<entry align=\"";
+               switch (GetAlignment(cell)) {
+               case LYX_ALIGN_LEFT:
+                       os << "left";
+                       break;
+               case LYX_ALIGN_RIGHT:
+                       os << "right";
+                       break;
+               default:
+                       os << "center";
+                       break;
+               }
+
+               os << "\" valign=\"";
+               switch (GetVAlignment(cell)) {
+               case LYX_VALIGN_TOP:
+                       os << "top";
+                       break;
+               case LYX_VALIGN_BOTTOM:
+                       os << "bottom";
+                       break;
+               case LYX_VALIGN_CENTER:
+                       os << "middle";
+               }
+               os << "\"";
+
+               if (IsMultiColumn(cell)) {
+                       os << " namest=\"col" << j << "\" ";
+                       os << "nameend=\"col" << j + cells_in_multicolumn(cell) - 1<< "\"";
+               }
+
+               os << ">";
+               ret += GetCellInset(cell)->docbook(buf, os);
+               os << "</entry>\n";
+               ++cell;
+       }
+       os << "</row>\n";
+       return ret;
+}      
+
+
 int LyXTabular::DocBook(Buffer const * buf, ostream & os) const
 {
        int ret = 0;
@@ -2249,59 +2377,50 @@ int LyXTabular::DocBook(Buffer const * buf, ostream & os) const
                        os << "center";
                        break;
                }
-               os << "\"/>\n";
+               os << "\">\n";
                ++ret;
        }
 
        //+---------------------------------------------------------------------
-       //+                      the single row and columns (cells)            +
+       //+                      Long Tabular case                             +
        //+---------------------------------------------------------------------
 
-       int cell = 0;
-       os << "<tbody>\n";
-       for (int i = 0; i < rows_; ++i) {
-               os << "<row>\n";
-               for (int j = 0; j < columns_; ++j) {
-                       if (IsPartOfMultiColumn(i, j))
-                               continue;
-               
-                       os << "<entry align=\"";
-                       switch (GetAlignment(cell)) {
-                       case LYX_ALIGN_LEFT:
-                               os << "left";
-                               break;
-                       case LYX_ALIGN_RIGHT:
-                               os << "right";
-                               break;
-                       default:
-                               os << "center";
-                               break;
+       if ( IsLongTabular() ) {
+               // Header
+               if( endhead.row || endfirsthead.row ) {
+                       os << "<thead>\n";
+                       if( endfirsthead.row ) {
+                               docbookRow( buf, os, endfirsthead.row - 1);
                        }
-               
-                       os << "\" valign=\"";
-                       switch (GetVAlignment(cell)) {
-                       case LYX_VALIGN_TOP:
-                               os << "top";
-                               break;
-                       case LYX_VALIGN_BOTTOM:
-                               os << "bottom";
-                               break;
-                       case LYX_VALIGN_CENTER:
-                               os << "middle";
+                       if( endhead.row && endhead.row != endfirsthead.row) {
+                               docbookRow(buf, os, endhead.row - 1);
                        }
-                       os << "\"";
-               
-                       if (IsMultiColumn(cell)) {
-                               os << " namest=\"col" << j << "\" ";
-                               os << "nameend=\"col" << j + cells_in_multicolumn(cell) - 1<< "\"";
+                       os << "</thead>\n";
+               }
+
+               // Footer
+               if( endfoot.row || endlastfoot.row ) {
+                       os << "<tfoot>\n";
+                       if( endfoot.row ) {
+                               docbookRow( buf, os, endfoot.row - 1);
                        }
-               
-                       os << ">";
-                       ret += GetCellInset(cell)->docBook(buf, os);
-                       os << "</entry>";
-                       ++cell;
+                       if( endlastfoot.row && endlastfoot.row != endfoot.row) {
+                               docbookRow( buf, os, endlastfoot.row - 1);
+                       }
+                       os << "</tfoot>\n";
+               }
+       }
+       //+---------------------------------------------------------------------
+       //+                      the single row and columns (cells)            +
+       //+---------------------------------------------------------------------
+
+       os << "<tbody>\n";
+       for (int i = 0; i < rows_; ++i) {
+               if(!IsLongTabular() || (
+                  i != endhead.row - 1 && i != endfirsthead.row - 1 &&
+                  i != endfoot.row - 1 && i != endlastfoot.row - 1)) {
+                       docbookRow( buf, os, i);
                }
-               os << "</row>\n";
        }
        os << "</tbody>\n";
        //+---------------------------------------------------------------------
@@ -2356,7 +2475,7 @@ 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);
                if (TopLine(i)) {
@@ -2403,7 +2522,7 @@ 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);
                if (BottomLine(i)) {
@@ -2421,8 +2540,8 @@ int LyXTabular::AsciiBottomHLine(ostream & os, int row,
 
 
 int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os,
-                                                          int cell, int row, int column,
-                                                          vector<unsigned int> const & clen) const
+                              int cell, int row, int column,
+                              vector<unsigned int> const & clen) const
 {
        ostringstream sstr;
        int ret = GetCellInset(cell)->ascii(buf, sstr, 0);
@@ -2434,7 +2553,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;
 
@@ -2530,6 +2649,7 @@ InsetText * LyXTabular::GetCellInset(int cell) const
 
 InsetText * LyXTabular::GetCellInset(int row, int column) const
 {
+       cur_cell = GetCellNumber(row, column);
        return & cell_info[row][column].inset;
 }
 
@@ -2537,12 +2657,12 @@ InsetText * LyXTabular::GetCellInset(int row, int column) const
 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; !features.isRequired("array") && (cell < numberofcells); ++cell) {
                if (GetVAlignment(cell) != LYX_VALIGN_TOP)
-                       features.array = true;
+                       features.require("array");
                GetCellInset(cell)->validate(features);
        }
 }
@@ -2564,20 +2684,13 @@ std::vector<string> const LyXTabular::getLabelList() const
                        
 LyXTabular::BoxType LyXTabular::UseParbox(int cell) const
 {
-       Paragraph * 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)     == Paragraph::META_NEWLINE)
+                       if (par->getChar(i) == Paragraph::META_NEWLINE)
                                return BOX_PARBOX;
                }
        }
        return BOX_NONE;
 }
-
-/* Emacs:
- * Local variables:
- * tab-width: 4
- * End:
- * vi:set tabstop=4:
- */