]> git.lyx.org Git - lyx.git/blobdiff - src/tabular.C
bug 2298: cursorTop/Bottom/Home/End does not redraw after dEPM
[lyx.git] / src / tabular.C
index 21eaa46ad68d1f04482d8ed60da55049aeafb1ba..212431cbb853936f54030a89bc002fff06bd89e2 100644 (file)
 
 #include "buffer.h"
 #include "bufferparams.h"
+#include "BufferView.h"
+#include "cursor.h"
 #include "debug.h"
 #include "LaTeXFeatures.h"
 #include "lyxlex.h"
 #include "outputparams.h"
 #include "paragraph.h"
+#include "paragraph_funcs.h"
 
 #include "insets/insettabular.h"
 
 #include "support/lstrings.h"
-#include "support/tostr.h"
+#include "support/convert.h"
 
 #include <sstream>
 
 using lyx::support::ltrim;
 using lyx::support::prefixIs;
 using lyx::support::rtrim;
-using lyx::support::strToInt;
 using lyx::support::suffixIs;
 
 using boost::shared_ptr;
@@ -70,36 +72,41 @@ string const write_attribute(string const & name, T const & t)
        return s.empty() ? s : " " + name + "=\"" + s + "\"";
 }
 
+template <>
 string const write_attribute(string const & name, string const & t)
 {
        return t.empty() ? t : " " + name + "=\"" + t + "\"";
 }
 
 
+template <>
 string const write_attribute(string const & name, bool const & b)
 {
        // we write only true attribute values so we remove a bit of the
        // file format bloat for tabulars.
-       return b ? write_attribute(name, tostr(b)) : string();
+       return b ? write_attribute(name, convert<string>(b)) : string();
 }
 
 
+template <>
 string const write_attribute(string const & name, int const & i)
 {
        // we write only true attribute values so we remove a bit of the
        // file format bloat for tabulars.
-       return i ? write_attribute(name, tostr(i)) : string();
+       return i ? write_attribute(name, convert<string>(i)) : string();
 }
 
 
+template <>
 string const write_attribute(string const & name, LyXTabular::idx_type const & i)
 {
        // we write only true attribute values so we remove a bit of the
        // file format bloat for tabulars.
-       return i ? write_attribute(name, tostr(i)) : string();
+       return i ? write_attribute(name, convert<string>(i)) : string();
 }
 
 
+template <>
 string const write_attribute(string const & name, LyXLength const & value)
 {
        // we write only the value if we really have one same reson as above.
@@ -244,7 +251,7 @@ bool getTokenValue(string const & str, char const * token, int & num)
        num = 0;
        if (!getTokenValue(str, token, tmp))
                return false;
-       num = strToInt(tmp);
+       num = convert<int>(tmp);
        return true;
 }
 
@@ -511,7 +518,7 @@ void LyXTabular::appendColumn(BufferParams const & bp, idx_type const cell)
        }
        //++column;
        for (row_type i = 0; i < rows_; ++i) {
-               cell_info[i][column + 1].inset->clear(false);
+               cell_info[i][column + 1].inset->clear();
                if (bp.tracking_changes)
                        cell_info[i][column + 1].inset->markNew(true);
        }
@@ -794,9 +801,9 @@ void LyXTabular::recalculateMulticolumnsOfColumn(col_type column)
        // 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))
+       if (columns_ < 2 || column > (columns_ - 2))
                return;
-       for(row_type row = 0; row < rows_; ++row) {
+       for (row_type 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
@@ -813,7 +820,6 @@ void LyXTabular::recalculateMulticolumnsOfColumn(col_type column)
 }
 
 
-// returns 1 if a complete update is necessary, otherwise 0
 void LyXTabular::setWidthOfCell(idx_type cell, int new_width)
 {
        row_type const row = row_of_cell(cell);
@@ -869,7 +875,38 @@ void LyXTabular::setVAlignment(idx_type cell, VAlignment align,
 }
 
 
-void LyXTabular::setColumnPWidth(idx_type cell, LyXLength const & width)
+namespace {
+
+/**
+ * Allow line and paragraph breaks for fixed width cells or disallow them,
+ * merge cell paragraphs and reset layout to standard for variable width
+ * cells.
+ */
+void toggleFixedWidth(LCursor & cur, InsetText * inset, bool fixedWidth)
+{
+       inset->setAutoBreakRows(fixedWidth);
+       if (fixedWidth)
+               return;
+
+       // merge all paragraphs to one
+       BufferParams const & bp =
+               inset->getText(0)->bv_owner->buffer()->params();
+       while (inset->paragraphs().size() > 1)
+               mergeParagraph(bp, inset->paragraphs(), 0);
+
+       // reset layout
+       cur.push(*inset);
+       // undo information has already been recorded
+       inset->getText(0)->setLayout(0, cur.lastpit() + 1,
+                       bp.getLyXTextClass().defaultLayoutName());
+       cur.pop();
+}
+
+}
+
+
+void LyXTabular::setColumnPWidth(LCursor & cur, idx_type cell,
+               LyXLength const & width)
 {
        col_type const j = column_of_cell(cell);
 
@@ -877,18 +914,32 @@ void LyXTabular::setColumnPWidth(idx_type cell, LyXLength const & width)
        for (row_type i = 0; i < rows_; ++i) {
                idx_type const cell = getCellNumber(i, j);
                // because of multicolumns
-               getCellInset(cell)->setAutoBreakRows(!getPWidth(cell).zero());
+               toggleFixedWidth(cur, getCellInset(cell).get(),
+                                !getPWidth(cell).zero());
        }
+       // cur paragraph can become invalid after paragraphs were merged
+       if (cur.pit() > cur.lastpit())
+               cur.pit() = cur.lastpit();
+       // cur position can become invalid after newlines were removed
+       if (cur.pos() > cur.lastpos())
+               cur.pos() = cur.lastpos();
 }
 
 
-bool LyXTabular::setMColumnPWidth(idx_type cell, LyXLength const & width)
+bool LyXTabular::setMColumnPWidth(LCursor & cur, idx_type cell,
+               LyXLength const & width)
 {
        if (!isMultiColumn(cell))
                return false;
 
        cellinfo_of_cell(cell).p_width = width;
-       getCellInset(cell)->setAutoBreakRows(!width.zero());
+       toggleFixedWidth(cur, getCellInset(cell).get(), !width.zero());
+       // cur paragraph can become invalid after paragraphs were merged
+       if (cur.pit() > cur.lastpit())
+               cur.pit() = cur.lastpit();
+       // cur position can become invalid after newlines were removed
+       if (cur.pos() > cur.lastpos())
+               cur.pos() = cur.lastpos();
        return true;
 }
 
@@ -1199,85 +1250,6 @@ void LyXTabular::write(Buffer const & buf, ostream & os) const
 }
 
 
-void LyXTabular::setHeaderFooterRows(row_type hr, row_type fhr,
-                                     row_type fr, row_type 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::read(Buffer const & buf, LyXLex & lex)
 {
        string line;
@@ -1310,37 +1282,17 @@ void LyXTabular::read(Buffer const & buf, LyXLex & lex)
        }
        getTokenValue(line, "rotate", rotate);
        getTokenValue(line, "islongtable", is_long_tabular);
-       // 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);
-       }
+       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 (col_type j = 0; j < columns_; ++j) {
                l_getline(is,line);
                if (!prefixIs(line,"<column")) {
@@ -1440,12 +1392,13 @@ void LyXTabular::setMultiColumn(Buffer * buffer, idx_type cell,
        cs.alignment = column_info[column_of_cell(cell)].alignment;
        cs.top_line = row_info[row_of_cell(cell)].top_line;
        cs.bottom_line = row_info[row_of_cell(cell)].bottom_line;
+       cs.left_line = column_info[column_of_cell(cell)].left_line;
        cs.right_line = column_info[column_of_cell(cell+number-1)].right_line;
        for (idx_type i = 1; i < number; ++i) {
                cellstruct & cs1 = cellinfo_of_cell(cell + i);
                cs1.multicolumn = CELL_PART_OF_MULTICOLUMN;
                cs.inset->appendParagraphs(buffer, cs1.inset->paragraphs());
-               cs1.inset->clear(false);
+               cs1.inset->clear();
        }
        set_row_column_number_info();
 }
@@ -2606,6 +2559,13 @@ shared_ptr<InsetText> LyXTabular::getCellInset(row_type row,
 }
 
 
+void LyXTabular::setCellInset(row_type row, col_type column,
+                             shared_ptr<InsetText> ins) const
+{
+       cell_info[row][column].inset = ins;
+}
+
+
 LyXTabular::idx_type
 LyXTabular::getCellFromInset(InsetBase const * inset) const
 {
@@ -2647,15 +2607,6 @@ void LyXTabular::validate(LaTeXFeatures & features) const
 }
 
 
-void LyXTabular::getLabelList(Buffer const & buffer,
-                             std::vector<string> & list) const
-{
-       for (row_type i = 0; i < rows_; ++i)
-               for (col_type j = 0; j < columns_; ++j)
-                       getCellInset(i, j)->getLabelList(buffer, list);
-}
-
-
 LyXTabular::BoxType LyXTabular::useParbox(idx_type cell) const
 {
        ParagraphList const & parlist = getCellInset(cell)->paragraphs();