]> git.lyx.org Git - features.git/commitdiff
booktabs: support for \cmidrule trimming
authorJuergen Spitzmueller <spitz@lyx.org>
Wed, 3 Apr 2019 05:59:52 +0000 (07:59 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 18 Jun 2020 13:48:23 +0000 (15:48 +0200)
This has probably still some rough edges, so please test thoroughly.

Fixes: #3072
development/FORMAT
lib/lyx2lyx/lyx_2_4.py
src/LyXAction.cpp
src/frontends/qt4/GuiSetBorder.cpp
src/frontends/qt4/GuiSetBorder.h
src/frontends/qt4/GuiTabular.cpp
src/frontends/qt4/GuiTabular.h
src/insets/InsetTabular.cpp
src/insets/InsetTabular.h
src/tex2lyx/TODO.txt
src/version.h

index 3ec34e61f78078063b3f71cf20a5381010bc5dea..d38e809f1704e89cc0ad107714a96c576e90654b 100644 (file)
@@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be
 
 -----------------------
 
+2019-04-03  Jürgen Spitzmüller <spitz@lyx.org>
+       * format incremented to 571: Add \cmidrule trimming support
+          \cmidrule(lr){n-n}
+          <cell ... toplineltrim|toplinettrim|bottomlineltrim|bottomlinertrim true ...>
+
 2019-03-29  Jürgen Spitzmüller <spitz@lyx.org>
        * format incremented to 570: Add individual bib encodings for biblatex
           \begin_inset CommandInset bibtex
index 33b2a3984f54e0c194ef7f41cd1f03509bc667ac..3bf7a6b2d1531d237df28c23fd1fc668aac4d25f 100644 (file)
@@ -1555,6 +1555,26 @@ def revert_bibfileencodings(document):
         i = j + 1
 
 
+def revert_cmidruletrimming(document):
+    " Remove \\cmidrule trimming "
+
+    # FIXME: Revert to TeX code?
+    i = 0
+    while True:
+        # first, let's find out if we need to do anything
+        i = find_token(document.body, '<cell ', i)
+        if i == -1:
+            return
+        j = document.body[i].find('trim="')
+        if j == -1:
+             i += 1
+             continue
+        rgx = re.compile(r' (bottom|top)line[lr]trim="true"')
+        # remove trim option
+        document.body[i] = rgx.sub('', document.body[i])
+
+        i += 1
+
 
 ##
 # Conversion hub
@@ -1587,10 +1607,12 @@ convert = [
            [567, []],
            [568, []],
            [569, []],
-           [570, []]
+           [570, []],
+           [571, []]
           ]
 
 revert =  [
+           [570, [revert_cmidruletrimming]],
            [569, [revert_bibfileencodings]],
            [568, [revert_tablestyle]],
            [567, [revert_soul]],
index 59bdbe8d1c50b7b9bcf7b3c60092dac06a462900..a9422d3b1230923703e039365db9d58a19a8d745 100644 (file)
@@ -3752,7 +3752,10 @@ void LyXAction::init()
  * \li Params: Generally see #LFUN_INSET_INSERT for further details.\n
  *             <FEATURE>: append-row|append-column|delete-row|delete-column|copy-row|\n
                        copy-column|move-column-right|move-column-left|move-row-down|move-row-up|\n
+                       set-line-top|set-line-bottom|set-line-left|set-line-right|\n
                        toggle-line-top|toggle-line-bottom|toggle-line-left|toggle-line-right|\n
+                       set-ltrim-top|set-rtrim-top|set-ltrim-bottom|set-rtrim-bottom\n
+                       toggle-ltrim-top|toggle-rtrim-top|toggle-ltrim-bottom|toggle-rtrim-bottom\n
                        align-left|align-right|align-center|align-block|align-decimal|set-decimal-point|\n
                        valign-top|valign-bottom|valign-middle|longtabular-align-left|\n
                        longtabular-align-center|longtabular-align-right|m-align-left|m-align-right|\n
index f35a17df2b369e1631826c41338b2d574650ce37..30e25743fb99709a9f07e0c8a538fc4ec5436261 100644 (file)
@@ -5,6 +5,7 @@
  *
  * \author Edwin Leuven
  * \author John Levon
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "GuiSetBorder.h"
 
+#include "support/debug.h"
+
 #include <QPainter>
 #include <QMouseEvent>
 #include <QPaintEvent>
 
 
 GuiSetBorder::GuiSetBorder(QWidget * parent, Qt::WindowFlags fl)
-       : QWidget(parent, fl), buffer(75, 75)
+       : QWidget(parent, fl), buffer(75, 75), bottom_drawn_wide_(false),
+         top_drawn_wide_(false)
 {
        /* length of corner line */
-       l = buffer.width() / 10;
+       corner_length = buffer.width() / 10;
        /* margin */
-       m = buffer.height() / 10;
+       margin = buffer.height() / 10;
 
-       w = buffer.width();
-       h = buffer.height();
+       bwidth = buffer.width();
+       bheight = buffer.height();
 
        init();
 
-       setMinimumSize(w,h);
-       setMaximumSize(w,h);
+       setMinimumSize(bwidth, bheight);
+       setMaximumSize(bwidth, bheight);
 }
 
 
@@ -51,19 +55,26 @@ void GuiSetBorder::init()
 
        paint.setPen(Qt::black);
 
-       // FIXME: wow, readable !! :)
-
-       paint.drawLine(m + l , m, m + l, m + l);
-       paint.drawLine(w - (m + l), m, w - (m + l), m + l);
-
-       paint.drawLine(m, m + l , m + l, m + l);
-       paint.drawLine(m, h - (m + l), m + l, h - (m + l));
-
-       paint.drawLine(m + l ,h - m, m + l ,h - (m + l));
-       paint.drawLine(w - (m + l), h - m, w - (m + l), h - (m + l));
-
-       paint.drawLine(h - m, m+l, h - (m + l), m + l);
-       paint.drawLine(h - m, h - (m + l), h - (m + l),h - (m + l));
+       // Draw the corner marks
+       paint.drawLine(margin + corner_length, margin,
+                      margin + corner_length, margin + corner_length);
+       paint.drawLine(bwidth - (margin + corner_length), margin,
+                      bwidth - (margin + corner_length), margin + corner_length);
+
+       paint.drawLine(margin, margin + corner_length,
+                      margin + corner_length, margin + corner_length);
+       paint.drawLine(margin, bheight - (margin + corner_length),
+                      margin + corner_length, bheight - (margin + corner_length));
+
+       paint.drawLine(margin + corner_length ,bheight - margin,
+                      margin + corner_length ,bheight - (margin + corner_length));
+       paint.drawLine(bwidth - (margin + corner_length), bheight - margin,
+                      bwidth - (margin + corner_length), bheight - (margin + corner_length));
+
+       paint.drawLine(bheight - margin, margin+corner_length,
+                      bheight - (margin + corner_length), margin + corner_length);
+       paint.drawLine(bheight - margin, bheight - (margin + corner_length),
+                      bheight - (margin + corner_length),bheight - (margin + corner_length));
 }
 
 
@@ -77,7 +88,15 @@ void GuiSetBorder::mousePressEvent(QMouseEvent * e)
                                leftSet();
                        }
                } else {
-                       if (bottom_.enabled) {
+                       if (bottom_trim_left_.enabled && e->x() < margin + 4 + 2 * corner_length) {
+                               setBottomLeftTrim(bottom_trim_left_.set == LINE_SET ? LINE_UNSET : LINE_SET);
+                               // emit signal
+                               bottomLTSet();
+                       } else if (bottom_trim_right_.enabled && e->x() > bwidth - margin - 2 * corner_length - 4) {
+                                       setBottomRightTrim(bottom_trim_right_.set == LINE_SET ? LINE_UNSET : LINE_SET);
+                                       // emit signal
+                                       bottomRTSet();
+                       } else if (bottom_.enabled) {
                                setBottom(bottom_.set == LINE_SET ? LINE_UNSET : LINE_SET);
                                // emit signal
                                bottomSet();
@@ -85,7 +104,15 @@ void GuiSetBorder::mousePressEvent(QMouseEvent * e)
                }
        } else {
                if (e->y() < height() - e->x()) {
-                       if (top_.enabled) {
+                       if (top_trim_left_.enabled && e->x() < margin + 4 + 2 * corner_length) {
+                               setTopLeftTrim(top_trim_left_.set == LINE_SET ? LINE_UNSET : LINE_SET);
+                               // emit signal
+                               topLTSet();
+                       } else if (top_trim_right_.enabled && e->x() > bwidth - margin - 2 * corner_length - 4) {
+                                       setTopRightTrim(top_trim_right_.set == LINE_SET ? LINE_UNSET : LINE_SET);
+                                       // emit signal
+                                       topRTSet();
+                       } else if (top_.enabled) {
                                setTop(top_.set == LINE_SET ? LINE_UNSET : LINE_SET);
                                // emit signal
                                topSet();
@@ -132,7 +159,8 @@ void GuiSetBorder::drawLeft(BorderState draw)
        }
        if (!left_.enabled)
                col = QColor(Qt::lightGray);
-       drawLine(col, m + l, m + l + 2, m + l, h - m - l - 1);
+       drawLine(col, margin + corner_length, margin + corner_length + 2,
+                margin + corner_length, bheight - margin - corner_length - 1);
 }
 
 
@@ -153,7 +181,8 @@ void GuiSetBorder::drawRight(BorderState draw)
        }
        if (!right_.enabled)
                col = QColor(Qt::lightGray);
-       drawLine(col, h - m - l + 1, m + l + 2, h - m - l + 1, h - m - l - 1);
+       drawLine(col, bheight - margin - corner_length + 1, margin + corner_length + 2,
+                bheight - margin - corner_length + 1, bheight - margin - corner_length - 1);
 }
 
 
@@ -163,18 +192,84 @@ void GuiSetBorder::drawTop(BorderState draw)
        switch (draw) {
        case LINE_SET:
                col = Qt::black;
+               top_drawn_wide_ = true;
                break;
        case LINE_UNSET:
                col = Qt::white;
+               top_drawn_wide_ = false;
                break;
        case LINE_UNDECIDED:
        case LINE_UNDEF:
                col = Qt::lightGray;
+               top_drawn_wide_ = true;
                break;
        }
        if (!top_.enabled)
                col = QColor(Qt::lightGray);
-       drawLine(col, m + l + 2, m + l, w - m - l - 1, m + l);
+       int const lt = (top_trim_left_.enabled) ? corner_length + 4 : 0;
+       int const rt = (top_trim_right_.enabled) ? corner_length + 4 : 0;
+       drawLine(col, margin + corner_length + 2 + lt, margin + corner_length,
+                bwidth - margin - corner_length - 1 - rt, margin + corner_length);
+}
+
+
+void GuiSetBorder::undrawWideTopLine()
+{
+       if (!top_drawn_wide_)
+               return;
+
+       // Overpaint previous lines white
+       drawLine(Qt::white, margin + corner_length + 2, margin + corner_length,
+                bwidth - margin - corner_length - 1, margin + corner_length);
+       top_drawn_wide_ = false;
+}
+
+
+void GuiSetBorder::drawTopLeftTrim(BorderState draw)
+{
+       QColor col;
+       switch (draw) {
+       case LINE_SET:
+               col = Qt::black;
+               break;
+       case LINE_UNSET:
+               col = Qt::white;
+               break;
+       case LINE_UNDECIDED:
+       case LINE_UNDEF:
+               col = Qt::lightGray;
+               break;
+       }
+       if (!top_trim_left_.enabled)
+               col = QColor(Qt::white);
+       int const lt = corner_length;
+       if (top_trim_left_.enabled)
+               drawLine(col, margin + corner_length + 2, margin + corner_length,
+                        margin + corner_length + 2 + lt, margin + corner_length);
+}
+
+
+void GuiSetBorder::drawTopRightTrim(BorderState draw)
+{
+       QColor col;
+       switch (draw) {
+       case LINE_SET:
+               col = Qt::black;
+               break;
+       case LINE_UNSET:
+               col = Qt::white;
+               break;
+       case LINE_UNDECIDED:
+       case LINE_UNDEF:
+               col = Qt::lightGray;
+               break;
+       }
+       if (!top_trim_right_.enabled)
+               col = QColor(Qt::white);
+       int const rt = corner_length;
+       if (top_trim_right_.enabled)
+               drawLine(col, bwidth - margin - corner_length - 1 - rt, margin + corner_length,
+                       bwidth - margin - corner_length - 1, margin + corner_length);
 }
 
 
@@ -184,18 +279,84 @@ void GuiSetBorder::drawBottom(BorderState draw)
        switch (draw) {
        case LINE_SET:
                col = Qt::black;
+               bottom_drawn_wide_ = true;
                break;
        case LINE_UNSET:
                col = Qt::white;
+               bottom_drawn_wide_ = false;
                break;
        case LINE_UNDECIDED:
        case LINE_UNDEF:
                col = Qt::lightGray;
+               bottom_drawn_wide_ = true;
                break;
        }
        if (!bottom_.enabled)
                col = QColor(Qt::lightGray);
-       drawLine(col, m + l + 2, w - m - l + 1, w - m - l - 1, w - m - l + 1);
+       int const lt = (bottom_trim_left_.enabled) ? corner_length + 4 : 0;
+       int const rt = (bottom_trim_right_.enabled) ? corner_length + 4 : 0;
+       drawLine(col, margin + corner_length + 2 + lt, bwidth - margin - corner_length + 1,
+                bwidth - margin - corner_length - 1 - rt, bwidth - margin - corner_length + 1);
+}
+
+
+void GuiSetBorder::undrawWideBottomLine()
+{
+       if (!bottom_drawn_wide_)
+               return;
+
+       //Overpaint previous lines white
+       drawLine(Qt::white, margin + corner_length + 2, bwidth - margin - corner_length + 1,
+                bwidth - margin - corner_length - 1, bwidth - margin - corner_length + 1);
+       bottom_drawn_wide_ = false;
+}
+
+
+void GuiSetBorder::drawBottomLeftTrim(BorderState draw)
+{
+       QColor col;
+       switch (draw) {
+       case LINE_SET:
+               col = Qt::black;
+               break;
+       case LINE_UNSET:
+               col = Qt::white;
+               break;
+       case LINE_UNDECIDED:
+       case LINE_UNDEF:
+               col = Qt::lightGray;
+               break;
+       }
+       if (!bottom_trim_left_.enabled)
+               col = QColor(Qt::white);
+       int const lt = corner_length;
+       if (bottom_trim_left_.enabled)
+               drawLine(col, margin + corner_length + 2, bwidth - margin - corner_length + 1,
+                        margin + corner_length + 2 + lt, bwidth - margin - corner_length + 1);
+}
+
+
+void GuiSetBorder::drawBottomRightTrim(BorderState draw)
+{
+       QColor col;
+       switch (draw) {
+       case LINE_SET:
+               col = Qt::black;
+               break;
+       case LINE_UNSET:
+               col = Qt::white;
+               break;
+       case LINE_UNDECIDED:
+       case LINE_UNDEF:
+               col = Qt::lightGray;
+               break;
+       }
+       if (!bottom_trim_right_.enabled)
+               col = QColor(Qt::white);
+       int const rt = corner_length;
+       if (bottom_trim_right_.enabled)
+               drawLine(col, bwidth - margin - corner_length - 1 - rt, bwidth - margin - corner_length + 1,
+                        bwidth - margin - corner_length - 1, bwidth - margin - corner_length + 1);
 }
 
 
@@ -227,6 +388,46 @@ void GuiSetBorder::setBottomEnabled(bool enabled)
 }
 
 
+void GuiSetBorder::setTopLeftTrimEnabled(bool enabled)
+{
+       top_trim_left_.enabled = enabled;
+       undrawWideTopLine();
+       drawTopLeftTrim(top_trim_left_.set);
+       drawTop(top_.set);
+       top_drawn_wide_ = !enabled;
+}
+
+
+void GuiSetBorder::setTopRightTrimEnabled(bool enabled)
+{
+       top_trim_right_.enabled = enabled;
+       undrawWideTopLine();
+       drawTopRightTrim(top_trim_right_.set);
+       drawTop(top_.set);
+       top_drawn_wide_ = !enabled;;
+}
+
+
+void GuiSetBorder::setBottomLeftTrimEnabled(bool enabled)
+{
+       bottom_trim_left_.enabled = enabled;
+       undrawWideBottomLine();
+       drawBottomLeftTrim(bottom_trim_left_.set);
+       drawBottom(bottom_.set);
+       bottom_drawn_wide_ = !enabled;;
+}
+
+
+void GuiSetBorder::setBottomRightTrimEnabled(bool enabled)
+{
+       bottom_trim_right_.enabled = enabled;
+       undrawWideBottomLine();
+       drawBottomRightTrim(bottom_trim_right_.set);
+       drawBottom(bottom_.set);
+       bottom_drawn_wide_ = !enabled;;
+}
+
+
 void GuiSetBorder::setLeft(BorderState border)
 {
        left_.set = border;
@@ -255,12 +456,43 @@ void GuiSetBorder::setBottom(BorderState border)
 }
 
 
+void GuiSetBorder::setTopLeftTrim(BorderState border)
+{
+       top_trim_left_.set = border;
+       drawTopLeftTrim(border);
+}
+
+
+void GuiSetBorder::setTopRightTrim(BorderState border)
+{
+       top_trim_right_.set = border;
+       drawTopRightTrim(border);
+}
+
+
+void GuiSetBorder::setBottomLeftTrim(BorderState border)
+{
+       bottom_trim_left_.set = border;
+       drawBottomLeftTrim(border);
+}
+
+void GuiSetBorder::setBottomRightTrim(BorderState border)
+{
+       bottom_trim_right_.set = border;
+       drawBottomRightTrim(border);
+}
+
+
 void GuiSetBorder::setAll(BorderState border)
 {
        setLeft(border);
        setRight(border);
        setTop(border);
        setBottom(border);
+       setTopLeftTrim(border);
+       setTopRightTrim(border);
+       setBottomLeftTrim(border);
+       setBottomRightTrim(border);
 }
 
 
@@ -287,4 +519,28 @@ GuiSetBorder::BorderState GuiSetBorder::getBottom()
        return bottom_.set;
 }
 
+
+GuiSetBorder::BorderState GuiSetBorder::getTopLeftTrim()
+{
+       return top_trim_left_.set;
+}
+
+
+GuiSetBorder::BorderState GuiSetBorder::getTopRightTrim()
+{
+       return top_trim_right_.set;
+}
+
+
+GuiSetBorder::BorderState GuiSetBorder::getBottomLeftTrim()
+{
+       return bottom_trim_left_.set;
+}
+
+
+GuiSetBorder::BorderState GuiSetBorder::getBottomRightTrim()
+{
+       return bottom_trim_right_.set;
+}
+
 #include "moc_GuiSetBorder.cpp"
index 7230e4d11b9f0212cb4550827a9089c96c379316..1abfa9608ee8c91f0233530bad70f03444b50684 100644 (file)
@@ -6,6 +6,7 @@
  *
  * \author Edwin Leuven
  * \author John Levon
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -26,7 +27,7 @@ class GuiSetBorder : public QWidget
 {
        Q_OBJECT
 public:
-       GuiSetBorder(QWidget * parent = 0, Qt::WindowFlags fl = 0);
+       GuiSetBorder(QWidget * parent = nullptr, Qt::WindowFlags fl = nullptr);
 
        // We need tristate for multi-cell selection
        enum BorderState {
@@ -40,6 +41,10 @@ public:
        BorderState getRight();
        BorderState getTop();
        BorderState getBottom();
+       BorderState getTopLeftTrim();
+       BorderState getTopRightTrim();
+       BorderState getBottomLeftTrim();
+       BorderState getBottomRightTrim();
 
        bool leftLineSet() { return getLeft() ==  LINE_SET; }
        bool rightLineSet() { return getRight() ==  LINE_SET; }
@@ -51,11 +56,25 @@ public:
        bool topLineUnset() { return getTop() ==  LINE_UNSET; }
        bool bottomLineUnset() { return getBottom() ==  LINE_UNSET; }
 
+       bool topLineLTSet() { return getTopLeftTrim() ==  LINE_SET; }
+       bool bottomLineLTSet() { return getBottomLeftTrim() ==  LINE_SET; }
+       bool topLineRTSet() { return getTopRightTrim() ==  LINE_SET; }
+       bool bottomLineRTSet() { return getBottomRightTrim() ==  LINE_SET; }
+
+       bool topLineLTUnset() { return getTopLeftTrim() ==  LINE_UNSET; }
+       bool bottomLineLTUnset() { return getBottomLeftTrim() ==  LINE_UNSET; }
+       bool topLineRTUnset() { return getTopRightTrim() ==  LINE_UNSET; }
+       bool bottomLineRTUnset() { return getBottomRightTrim() ==  LINE_UNSET; }
+
 Q_SIGNALS:
        void rightSet();
        void leftSet();
        void topSet();
        void bottomSet();
+       void topLTSet();
+       void bottomLTSet();
+       void topRTSet();
+       void bottomRTSet();
        void clicked();
 
 public Q_SLOTS:
@@ -63,10 +82,18 @@ public Q_SLOTS:
        void setRightEnabled(bool);
        void setTopEnabled(bool);
        void setBottomEnabled(bool);
+       void setTopLeftTrimEnabled(bool);
+       void setTopRightTrimEnabled(bool);
+       void setBottomLeftTrimEnabled(bool);
+       void setBottomRightTrimEnabled(bool);
        void setLeft(BorderState);
        void setRight(BorderState);
        void setTop(BorderState);
        void setBottom(BorderState);
+       void setTopLeftTrim(BorderState);
+       void setTopRightTrim(BorderState);
+       void setBottomLeftTrim(BorderState);
+       void setBottomRightTrim(BorderState);
        void setAll(BorderState);
 
 protected:
@@ -81,7 +108,13 @@ private:
        void drawLeft(BorderState);
        void drawRight(BorderState);
        void drawTop(BorderState);
+       void undrawWideTopLine();
        void drawBottom(BorderState);
+       void undrawWideBottomLine();
+       void drawTopLeftTrim(BorderState);
+       void drawTopRightTrim(BorderState);
+       void drawBottomLeftTrim(BorderState);
+       void drawBottomRightTrim(BorderState);
 
        class Border {
        public:
@@ -94,13 +127,21 @@ private:
        Border right_;
        Border top_;
        Border bottom_;
+       /// trim areas
+       Border top_trim_left_;
+       Border top_trim_right_;
+       Border bottom_trim_left_;
+       Border bottom_trim_right_;
 
-       int m;
-       int l;
-       int w;
-       int h;
+       int margin;
+       int corner_length;
+       int bwidth;
+       int bheight;
 
        QPixmap buffer;
+
+       bool bottom_drawn_wide_;
+       bool top_drawn_wide_;
 };
 
 
index b162458b3ed62e02d1a86c3f8ca8caead8828977..633982c86fc26bee0fcdc82e52eb71ac6275b836 100644 (file)
@@ -48,7 +48,7 @@ namespace frontend {
 GuiTabular::GuiTabular(QWidget * parent)
        : InsetParamsWidget(parent), firstheader_suppressable_(false),
          lastfooter_suppressable_(false), orig_leftborder_(GuiSetBorder::LINE_UNDEF),
-         orig_rightborder_(GuiSetBorder::LINE_UNDEF)
+         orig_rightborder_(GuiSetBorder::LINE_UNDEF), lastrow_(0)
 
 {
        setupUi(this);
@@ -147,6 +147,14 @@ GuiTabular::GuiTabular(QWidget * parent)
                this, SLOT(checkEnabled()));
        connect(borders, SIGNAL(leftSet()),
                this, SLOT(checkEnabled()));
+       connect(borders, SIGNAL(topLTSet()),
+               this, SLOT(checkEnabled()));
+       connect(borders, SIGNAL(topRTSet()),
+               this, SLOT(checkEnabled()));
+       connect(borders, SIGNAL(bottomLTSet()),
+               this, SLOT(checkEnabled()));
+       connect(borders, SIGNAL(bottomRTSet()),
+               this, SLOT(checkEnabled()));
        connect(rotateTabularCB, SIGNAL(clicked()),
                this, SLOT(checkEnabled()));
        connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
@@ -344,6 +352,20 @@ void GuiTabular::enableWidgets() const
        // Vertical lines cannot be set in formal tables
        borders->setLeftEnabled(!booktabsRB->isChecked());
        borders->setRightEnabled(!booktabsRB->isChecked());
+       // Trimming is only allowed in booktabs and if the line is set
+       int const row = tabularRowED->text().toInt();
+       borders->setTopLeftTrimEnabled(booktabsRB->isChecked()
+                                      && borders->topLineSet()
+                                      && row > 1);
+       borders->setTopRightTrimEnabled(booktabsRB->isChecked()
+                                       && borders->topLineSet()
+                                       && row > 1);
+       borders->setBottomLeftTrimEnabled(booktabsRB->isChecked()
+                                         && borders->bottomLineSet()
+                                         && row < lastrow_);
+       borders->setBottomRightTrimEnabled(booktabsRB->isChecked()
+                                          && borders->bottomLineSet()
+                                          && row < lastrow_);
 }
 
 
@@ -360,6 +382,10 @@ void GuiTabular::borderSet_clicked()
        borders->setBottom(GuiSetBorder::LINE_SET);
        borders->setLeft(GuiSetBorder::LINE_SET);
        borders->setRight(GuiSetBorder::LINE_SET);
+       borders->setTopLeftTrim(GuiSetBorder::LINE_SET);
+       borders->setBottomLeftTrim(GuiSetBorder::LINE_SET);
+       borders->setTopRightTrim(GuiSetBorder::LINE_SET);
+       borders->setBottomRightTrim(GuiSetBorder::LINE_SET);
        // repaint the setborder widget
        borders->update();
        checkEnabled();
@@ -372,6 +398,10 @@ void GuiTabular::borderUnset_clicked()
        borders->setBottom(GuiSetBorder::LINE_UNSET);
        borders->setLeft(GuiSetBorder::LINE_UNSET);
        borders->setRight(GuiSetBorder::LINE_UNSET);
+       borders->setTopLeftTrim(GuiSetBorder::LINE_UNSET);
+       borders->setBottomLeftTrim(GuiSetBorder::LINE_UNSET);
+       borders->setTopRightTrim(GuiSetBorder::LINE_UNSET);
+       borders->setBottomRightTrim(GuiSetBorder::LINE_UNSET);
        // repaint the setborder widget
        borders->update();
        checkEnabled();
@@ -603,6 +633,22 @@ docstring GuiTabular::dialogToParams() const
                        setParam(param_str, Tabular::SET_LINE_BOTTOM,
                                 borders->bottomLineSet() ? "true" : "false");
        }
+       if (borders->topLineLTSet())
+               setParam(param_str, Tabular::SET_LTRIM_TOP, "false");
+       else if (borders->topLineLTUnset())
+               setParam(param_str, Tabular::SET_LTRIM_TOP, "true");
+       if (borders->topLineRTSet())
+               setParam(param_str, Tabular::SET_RTRIM_TOP, "false");
+       else if (borders->topLineRTUnset())
+               setParam(param_str, Tabular::SET_RTRIM_TOP, "true");
+       if (borders->bottomLineLTSet())
+               setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "false");
+       else if (borders->bottomLineRTUnset())
+               setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "true");
+       if (borders->bottomLineRTSet())
+               setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "false");
+       else if (borders->bottomLineRTUnset())
+               setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "true");
 
        // apply the special alignment
        string special = fromqstr(specialAlignmentED->text());
@@ -784,6 +830,7 @@ void GuiTabular::paramsToDialog(Inset const * inset)
 
        tabularRowED->setText(QString::number(row + 1));
        tabularColumnED->setText(QString::number(col + 1));
+       lastrow_ = int(tabular.nrows());
 
        bool const multicol = tabular.isMultiColumn(cell);
        multicolumnCB->setChecked(multicol);
@@ -810,12 +857,16 @@ void GuiTabular::paramsToDialog(Inset const * inset)
        }
 
        // In what follows, we check the borders of all selected cells,
-       // and if there are diverging settings, we use the LINE_UNDEF
+       // and if there are diverging settings, we use the LINE_UNDECIDED
        // border status.
-       GuiSetBorder::BorderState lt = GuiSetBorder::LINE_UNDEF;
-       GuiSetBorder::BorderState lb = GuiSetBorder::LINE_UNDEF;
-       GuiSetBorder::BorderState ll = GuiSetBorder::LINE_UNDEF;
-       GuiSetBorder::BorderState lr = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState ltop = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState lbottom = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState lleft = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState lright = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState ltop_ltrim = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState ltop_rtrim = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState lbottom_ltrim = GuiSetBorder::LINE_UNDEF;
+       GuiSetBorder::BorderState lbottom_rtrim = GuiSetBorder::LINE_UNDEF;
        CursorSlice const & beg = bv->cursor().selBegin();
        CursorSlice const & end = bv->cursor().selEnd();
        if (beg != end) {
@@ -830,27 +881,39 @@ void GuiTabular::paramsToDialog(Inset const * inset)
                for (Tabular::row_type r = rs; r <= re; ++r)
                        for (Tabular::col_type c = cs; c <= ce; ++c) {
                                idx_type const cc = tabular.cellIndex(r, c);
-                               lt = borderState(lt, tabular.topLine(cc));
-                               lb = borderState(lb, tabular.bottomLine(cc));
-                               ll = borderState(ll, tabular.leftLine(cc));
-                               lr = borderState(lr, tabular.rightLine(cc));
+                               ltop = borderState(ltop, tabular.topLine(cc));
+                               lbottom = borderState(lbottom, tabular.bottomLine(cc));
+                               lleft = borderState(lleft, tabular.leftLine(cc));
+                               lright = borderState(lright, tabular.rightLine(cc));
+                               ltop_ltrim = borderState(ltop_ltrim, !tabular.topLineTrim(cc).first);
+                               ltop_rtrim = borderState(ltop_rtrim, !tabular.topLineTrim(cc).second);
+                               lbottom_ltrim = borderState(lbottom_ltrim, !tabular.bottomLineTrim(cc).first);
+                               lbottom_rtrim = borderState(lbottom_rtrim, !tabular.bottomLineTrim(cc).second);
                                // store left/right borders for the case of formal/nonformal switch
-                               orig_leftborder_ = borderState(ll, tabular.leftLine(cc, true));
-                               orig_rightborder_ = borderState(lr, tabular.rightLine(cc, true));
+                               orig_leftborder_ = borderState(lleft, tabular.leftLine(cc, true));
+                               orig_rightborder_ = borderState(lright, tabular.rightLine(cc, true));
                        }
        } else {
-               lt = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
-               lb = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
-               ll = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
-               lr = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
+               ltop = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
+               lbottom = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
+               lleft = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
+               lright = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
+               ltop_ltrim = tabular.topLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
+               ltop_rtrim = tabular.topLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
+               lbottom_ltrim = tabular.bottomLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
+               lbottom_rtrim = tabular.bottomLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
                // store left/right borders for the case of formal/nonformal switch
                orig_leftborder_ = tabular.leftLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
                orig_rightborder_ = tabular.rightLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
        }
-       borders->setTop(lt);
-       borders->setBottom(lb);
-       borders->setLeft(ll);
-       borders->setRight(lr);
+       borders->setTop(ltop);
+       borders->setBottom(lbottom);
+       borders->setLeft(lleft);
+       borders->setRight(lright);
+       borders->setTopLeftTrim(ltop_ltrim);
+       borders->setTopRightTrim(ltop_rtrim);
+       borders->setBottomLeftTrim(lbottom_ltrim);
+       borders->setBottomRightTrim(lbottom_rtrim);
        // repaint the setborder widget
        borders->update();
 
index 692e331d28387fdf3658e5c22bd5c1eec029f1f1..5890c520660312caad762636456643ba27a242f7 100644 (file)
@@ -74,6 +74,8 @@ private:
        GuiSetBorder::BorderState orig_leftborder_;
        ///
        GuiSetBorder::BorderState orig_rightborder_;
+       ///
+       int lastrow_;
 };
 
 } // namespace frontend
index 007f0910a8aed9d30c623aa0aef3491fc723232a..43795e7d40a09a7b2bff3d0bf9ee931baa5c7719 100644 (file)
@@ -127,12 +127,20 @@ TabularFeature tabularFeature[] =
        { Tabular::MOVE_ROW_UP, "move-row-up", false },
        { Tabular::SET_LINE_TOP, "set-line-top", true },
        { Tabular::SET_LINE_BOTTOM, "set-line-bottom", true },
+       { Tabular::SET_LTRIM_TOP, "set-ltrim-top", true },
+       { Tabular::SET_LTRIM_BOTTOM, "set-ltrim-bottom", true },
+       { Tabular::SET_RTRIM_TOP, "set-rtrim-top", true },
+       { Tabular::SET_RTRIM_BOTTOM, "set-rtrim-bottom", true },
        { Tabular::SET_LINE_LEFT, "set-line-left", true },
        { Tabular::SET_LINE_RIGHT, "set-line-right", true },
        { Tabular::TOGGLE_LINE_TOP, "toggle-line-top", false },
        { Tabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom", false },
        { Tabular::TOGGLE_LINE_LEFT, "toggle-line-left", false },
        { Tabular::TOGGLE_LINE_RIGHT, "toggle-line-right", false },
+       { Tabular::TOGGLE_LTRIM_TOP, "toggle-ltrim-top", true },
+       { Tabular::TOGGLE_LTRIM_BOTTOM, "toggle-ltrim-bottom", true },
+       { Tabular::TOGGLE_RTRIM_TOP, "toggle-rtrim-top", true },
+       { Tabular::TOGGLE_RTRIM_BOTTOM, "toggle-rtrim-bottom", true },
        { Tabular::ALIGN_LEFT, "align-left", false },
        { Tabular::ALIGN_RIGHT, "align-right", false },
        { Tabular::ALIGN_CENTER, "align-center", false },
@@ -585,6 +593,10 @@ Tabular::CellData::CellData(Buffer * buf)
          bottom_line(false),
          left_line(false),
          right_line(false),
+         top_line_rtrimmed(false),
+         top_line_ltrimmed(false),
+         bottom_line_rtrimmed(false),
+         bottom_line_ltrimmed(false),
          usebox(BOX_NONE),
          rotate(0),
          inset(new InsetTableCell(buf))
@@ -608,6 +620,10 @@ Tabular::CellData::CellData(CellData const & cs)
          bottom_line(cs.bottom_line),
          left_line(cs.left_line),
          right_line(cs.right_line),
+         top_line_rtrimmed(cs.top_line_rtrimmed),
+         top_line_ltrimmed(cs.top_line_ltrimmed),
+         bottom_line_rtrimmed(cs.bottom_line_rtrimmed),
+         bottom_line_ltrimmed(cs.bottom_line_ltrimmed),
          usebox(cs.usebox),
          rotate(cs.rotate),
          align_special(cs.align_special),
@@ -634,6 +650,10 @@ Tabular::CellData & Tabular::CellData::operator=(CellData const & cs)
        bottom_line = cs.bottom_line;
        left_line = cs.left_line;
        right_line = cs.right_line;
+       top_line_rtrimmed = cs.top_line_rtrimmed;
+       top_line_ltrimmed = cs.top_line_ltrimmed;
+       bottom_line_rtrimmed = cs.bottom_line_rtrimmed;
+       bottom_line_rtrimmed = cs.bottom_line_rtrimmed;
        usebox = cs.usebox;
        rotate = cs.rotate;
        align_special = cs.align_special;
@@ -981,6 +1001,24 @@ bool Tabular::rightLine(idx_type cell, bool const ignore_bt) const
 }
 
 
+pair<bool, bool> Tabular::topLineTrim(idx_type const cell) const
+{
+       if (!use_booktabs)
+               return make_pair(false, false);
+       return make_pair(cellInfo(cell).top_line_ltrimmed,
+                        cellInfo(cell).top_line_rtrimmed);
+}
+
+
+pair<bool, bool> Tabular::bottomLineTrim(idx_type const cell) const
+{
+       if (!use_booktabs)
+               return make_pair(false, false);
+       return make_pair(cellInfo(cell).bottom_line_ltrimmed,
+                        cellInfo(cell).bottom_line_rtrimmed);
+}
+
+
 int Tabular::interRowSpace(row_type row) const
 {
        if (!row || row >= nrows())
@@ -1321,6 +1359,42 @@ void Tabular::setBottomLine(idx_type i, bool line)
 }
 
 
+void Tabular::setTopLineLTrim(idx_type i, bool val)
+{
+       cellInfo(i).top_line_ltrimmed = val;
+}
+
+
+void Tabular::setTopLineRTrim(idx_type i, bool val)
+{
+       cellInfo(i).top_line_rtrimmed = val;
+}
+
+
+void Tabular::setBottomLineLTrim(idx_type i, bool val)
+{
+       cellInfo(i).bottom_line_ltrimmed = val;
+}
+
+
+void Tabular::setBottomLineRTrim(idx_type i, bool val)
+{
+       cellInfo(i).bottom_line_rtrimmed = val;
+}
+
+
+void Tabular::setTopLineTrim(idx_type i, pair<bool, bool> trim)
+{
+       setTopLineLTrim(i, trim.first);
+       setTopLineRTrim(i, trim.second);
+}
+
+void Tabular::setBottomLineTrim(idx_type i, pair<bool, bool> trim)
+{
+       setBottomLineLTrim(i, trim.first);
+       setBottomLineRTrim(i, trim.second);
+}
+
 void Tabular::setLeftLine(idx_type cell, bool line)
 {
        cellInfo(cell).left_line = line;
@@ -1615,7 +1689,11 @@ void Tabular::write(ostream & os) const
                           << write_attribute("alignment", cell_info[r][c].alignment)
                           << write_attribute("valignment", cell_info[r][c].valignment)
                           << write_attribute("topline", cell_info[r][c].top_line)
+                          << write_attribute("toplineltrim", cell_info[r][c].top_line_ltrimmed)
+                          << write_attribute("toplinertrim", cell_info[r][c].top_line_rtrimmed)
                           << write_attribute("bottomline", cell_info[r][c].bottom_line)
+                          << write_attribute("bottomlineltrim", cell_info[r][c].bottom_line_ltrimmed)
+                          << write_attribute("bottomlinertrim", cell_info[r][c].bottom_line_rtrimmed)
                           << write_attribute("leftline", cell_info[r][c].left_line)
                           << write_attribute("rightline", cell_info[r][c].right_line)
                           << write_attribute("rotate", cell_info[r][c].rotate)
@@ -1729,7 +1807,11 @@ void Tabular::read(Lexer & lex)
                        getTokenValue(line, "alignment", cell_info[i][j].alignment);
                        getTokenValue(line, "valignment", cell_info[i][j].valignment);
                        getTokenValue(line, "topline", cell_info[i][j].top_line);
+                       getTokenValue(line, "toplineltrim", cell_info[i][j].top_line_ltrimmed);
+                       getTokenValue(line, "toplinertrim", cell_info[i][j].top_line_rtrimmed);
                        getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
+                       getTokenValue(line, "bottomlineltrim", cell_info[i][j].bottom_line_ltrimmed);
+                       getTokenValue(line, "bottomlinertrim", cell_info[i][j].bottom_line_rtrimmed);
                        getTokenValue(line, "leftline", cell_info[i][j].left_line);
                        getTokenValue(line, "rightline", cell_info[i][j].right_line);
                        getTokenValue(line, "rotate", cell_info[i][j].rotate);
@@ -2305,18 +2387,27 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, string const & lang,
        // is done in Tabular::TeXBottomHLine(...)
 
        // get for each column the topline (if any)
-       map<col_type, bool> topline;
+       map<col_type, bool> topline, topltrims, toprtrims;
        col_type nset = 0;
+       bool have_trims = false;
        for (auto const & c : columns) {
                topline[c] = topLine(cellIndex(row, c));
+               topltrims[c] = topLineTrim(cellIndex(row, c)).first;
+               toprtrims[c] = topLineTrim(cellIndex(row, c)).second;
                // If cell is part of a multirow and not the first cell of the
                // multirow, no line must be drawn.
                if (row != 0)
                        if (isMultiRow(cellIndex(row, c))
-                           && cell_info[row][c].multirow != CELL_BEGIN_OF_MULTIROW)
+                           && cell_info[row][c].multirow != CELL_BEGIN_OF_MULTIROW) {
                                topline[c] = false;
+                               topltrims[c] = false;
+                               toprtrims[c] = false;
+                       }
                if (topline.find(c) != topline.end() && topline.find(c)->second)
                        ++nset;
+               if ((topltrims.find(c) != topltrims.end() && topltrims.find(c)->second)
+                    || (toprtrims.find(c) != toprtrims.end() && toprtrims.find(c)->second))
+                       have_trims = true;
        }
 
        // do nothing if empty first row, or incomplete row line after
@@ -2324,36 +2415,57 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, string const & lang,
                return;
 
        // only output complete row lines and the 1st row's clines
-       if (nset == ncols()) {
+       if (nset == ncols() && !have_trims) {
                if (use_booktabs) {
                        os << (row == 0 ? "\\toprule " : "\\midrule ");
                } else {
                        os << "\\hline ";
                }
-       } else if (row == 0) {
+       } else if (row == 0 || have_trims) {
+               string const cline = use_booktabs ? "\\cmidrule" : "\\cline";
                for (auto & c : columns) {
                        if (topline.find(c)->second) {
                                col_type offset = 0;
-                               for (col_type j = 0 ; j < c; ++j)
-                                       if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
-                                               ++offset;
-
-                               //babel makes the "-" character an active one, so we have to suppress this here
-                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
-                               if (lang == "slovak" || lang == "czech")
-                                       os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline")
-                                       << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
-                               else
-                                       os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
-
+                               string trim;
+                               if (topltrims.find(c) != topltrims.end()
+                                    && topltrims.find(c)->second)
+                                       trim = "l";
+                               string const firstcol = convert<string>(c + 1 + offset);
                                col_type cstart = c;
-                               for ( ; c < ncols() && topline.find(c)->second; ++c) {}
+                               for ( ; c < ncols() - 1 && topline.find(c)->second ; ++c) {
+                                       if (c > cstart && topltrims.find(c) != topltrims.end()
+                                                       && topltrims.find(c)->second) {
+                                               --c;
+                                               break;
+                                       } else if (toprtrims.find(c) != toprtrims.end()
+                                                  && toprtrims.find(c)->second)
+                                               break;
+                               }
 
                                for (col_type j = cstart ; j < c ; ++j)
                                        if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
                                                ++offset;
+                               col_type const lastcol = c + 1 + offset;
+                               if (toprtrims.find(c) != toprtrims.end()
+                                   && toprtrims.find(c)->second)
+                                       trim += "r";
 
-                               os << c + offset << "} ";
+                               //babel makes the "-" character an active one, so we have to suppress this here
+                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
+                               if (lang == "slovak" || lang == "czech") {
+                                       os << "\\expandafter" << cline;
+                                       if (!trim.empty())
+                                               os << "(" << trim << ")";
+                                       os << "\\expandafter{\\expandafter" << firstcol << "\\string-";
+                               } else {
+                                       os << cline;
+                                       if (!trim.empty())
+                                               os << "(" << trim << ")";
+                                       os << "{" << firstcol << '-';
+                               }
+                               os << lastcol << "}";
+                               if (c == ncols() - 1)
+                                       break;
                        }
                }
        }
@@ -2369,11 +2481,16 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
 
        // get the bottomlines of row r, and toplines in next row
        bool lastrow = row == nrows() - 1;
-       map<col_type, bool> bottomline, topline;
+       map<col_type, bool> bottomline, topline, topltrims, toprtrims, bottomltrims, bottomrtrims;
        bool nextrowset = true;
        for (auto const & c : columns) {
+               idx_type const idx = cellIndex(row, c);
                bottomline[c] = bottomLine(cellIndex(row, c));
+               bottomltrims[c] = bottomLineTrim(idx).first;
+               bottomrtrims[c] = bottomLineTrim(idx).second;
                topline[c] =  !lastrow && topLine(cellIndex(row + 1, c));
+               topltrims[c] = !lastrow && topLineTrim(cellIndex(row + 1, c)).first;
+               toprtrims[c] = !lastrow && topLineTrim(cellIndex(row + 1, c)).second;
                // If cell is part of a multirow and not the last cell of the
                // multirow, no line must be drawn.
                if (!lastrow)
@@ -2382,29 +2499,42 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
                            && cell_info[row + 1][c].multirow != CELL_BEGIN_OF_MULTIROW) {
                                bottomline[c] = false;
                                topline[c] = false;
-                               }
+                               bottomltrims[c] = false;
+                               bottomrtrims[c] = false;
+                               topltrims[c] = false;
+                               toprtrims[c] = false;
+                       }
                nextrowset &= topline.find(c) != topline.end() && topline.find(c)->second;
        }
 
        // combine this row's bottom lines and next row's toplines if necessary
        col_type nset = 0;
+       bool have_trims = false;
        for (auto const & c : columns) {
                if (!nextrowset)
                        bottomline[c] = bottomline.find(c)->second || topline.find(c)->second;
+               bottomltrims[c] = (bottomltrims.find(c) != bottomltrims.end() && bottomltrims.find(c)->second)
+                               || (topltrims.find(c) != topltrims.end() && topltrims.find(c)->second);
+               bottomrtrims[c] =(bottomrtrims.find(c) != bottomrtrims.end() && bottomrtrims.find(c)->second)
+                               || (toprtrims.find(c) != toprtrims.end() && toprtrims.find(c)->second);
                if (bottomline.find(c)->second)
                        ++nset;
+               if ((bottomltrims.find(c) != bottomltrims.end() && bottomltrims.find(c)->second)
+                    || (bottomrtrims.find(c) != bottomrtrims.end() && bottomrtrims.find(c)->second))
+                       have_trims = true;
        }
 
        // do nothing if empty, OR incomplete row line with a topline in next row
        if (nset == 0 || (nextrowset && nset != ncols()))
                return;
 
-       if (nset == ncols()) {
+       if (nset == ncols() && !have_trims) {
                if (use_booktabs)
                        os << (lastrow ? "\\bottomrule" : "\\midrule");
                else
                        os << "\\hline ";
        } else {
+               string const cline = use_booktabs ? "\\cmidrule" : "\\cline";
                for (auto & c : columns) {
                        if (bottomline.find(c)->second) {
                                col_type offset = 0;
@@ -2412,22 +2542,46 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
                                        if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
                                                ++offset;
 
-                               //babel makes the "-" character an active one, so we have to suppress this here
-                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
-                               if (lang == "slovak" || lang == "czech")
-                                       os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline")
-                                       << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
-                               else
-                                       os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
-
+                               string trim;
+                               if (bottomltrims.find(c) != bottomltrims.end()
+                                    && bottomltrims.find(c)->second)
+                                       trim = "l";
+                               string const firstcol = convert<string>(c + 1 + offset);
                                col_type cstart = c;
-                               for ( ; c < ncols() && bottomline.find(c)->second; ++c) {}
+                               for ( ; c < ncols() - 1 && bottomline.find(c)->second ; ++c) {
+                                       if (c > cstart && bottomltrims.find(c) != bottomltrims.end()
+                                                       && bottomltrims.find(c)->second) {
+                                               --c;
+                                               break;
+                                       } else if (bottomrtrims.find(c) != bottomrtrims.end()
+                                                  && bottomrtrims.find(c)->second)
+                                               break;
+                               }
 
                                for (col_type j = cstart ; j < c ; ++j)
                                        if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
                                                ++offset;
+                               col_type const lastcol = c + 1 + offset;
+                               if (bottomrtrims.find(c) != bottomrtrims.end()
+                                   && bottomrtrims.find(c)->second)
+                                       trim += "r";
 
-                               os << c + offset << "} ";
+                               //babel makes the "-" character an active one, so we have to suppress this here
+                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
+                               if (lang == "slovak" || lang == "czech") {
+                                       os << "\\expandafter" << cline;
+                                       if (!trim.empty())
+                                               os << "(" << trim << ")";
+                                       os << "\\expandafter{\\expandafter" << firstcol << "\\string-";
+                               } else {
+                                       os << cline;
+                                       if (!trim.empty())
+                                               os << "(" << trim << ")";
+                                       os << "{" << firstcol << '-';
+                               }
+                               os << lastcol << "}";
+                               if (c == ncols() - 1)
+                                       break;
                        }
                }
        }
@@ -4215,13 +4369,21 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 
 namespace {
 
-void tabline(PainterInfo const & pi, int x1, int y1, int x2, int y2,
+void tabline(PainterInfo const & pi, int x1, int y1, int x2, int y2, int lt, int rt,
              bool drawline, bool heavy = false)
 {
        ColorCode const col = drawline ? Color_tabularline : Color_tabularonoffline;
-       pi.pain.line(x1, y1, x2, y2, pi.textColor(col),
+       if (drawline && lt > 0)
+               pi.pain.line(x1, y1, x1 + lt, y2, pi.textColor(Color_tabularonoffline),
+                                        Painter::line_onoffdash,
+                                        Painter::thin_line);
+       pi.pain.line(x1 + lt, y1, x2 - rt, y2, pi.textColor(col),
                                 drawline ? Painter::line_solid : Painter::line_onoffdash,
                                 (heavy ? 2 : 1) * Painter::thin_line);
+       if (drawline && rt > 0)
+               pi.pain.line(x2 - rt, y1, x2, y2, pi.textColor(Color_tabularonoffline),
+                                        Painter::line_onoffdash,
+                                        Painter::thin_line);
 }
 
 }
@@ -4233,6 +4395,8 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        y -= tabular.rowAscent(row);
        int const w = tabular.cellWidth(cell);
        int const h = tabular.cellHeight(cell);
+       int lt = 0;
+       int rt = 0;
 
        col_type const col = tabular.cellColumn(cell);
 
@@ -4240,9 +4404,16 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        bool drawline = tabular.topLine(cell)
                || (row > 0 && tabular.bottomLine(tabular.cellAbove(cell)));
        bool heavy = tabular.use_booktabs && row == 0 && tabular.rowTopLine(row);
-       tabline(pi, x, y, x + w, y, drawline, heavy);
+       if (tabular.topLineTrim(cell).first
+           || (row > 0 && tabular.bottomLineTrim(tabular.cellIndex(row - 1, col)).first))
+               lt = 10;
+       if (tabular.topLineTrim(cell).second
+           || (row > 0 && tabular.bottomLineTrim(tabular.cellIndex(row - 1, col)).second))
+               rt = 10;
+       tabline(pi, x, y, x + w, y, lt, rt, drawline, heavy);
 
        // Bottom
+       lt = rt = 0;
        drawline = tabular.bottomLine(cell);
        row_type const lastrow = tabular.nrows() - 1;
        // Consider multi-rows
@@ -4253,12 +4424,16 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        heavy = tabular.use_booktabs
                && ((row == lastrow && tabular.rowBottomLine(row))
                    || (r == lastrow && tabular.rowBottomLine(r)));
-       tabline(pi, x, y + h, x + w, y + h, drawline, heavy);
+       if (tabular.bottomLineTrim(cell).first)
+               lt = 10;
+       if (tabular.bottomLineTrim(cell).second)
+               rt = 10;
+       tabline(pi, x, y + h, x + w, y + h, lt, rt, drawline, heavy);
 
        // Left
        drawline = tabular.leftLine(cell)
                || (col > 0 && tabular.rightLine(tabular.cellIndex(row, col - 1)));
-       tabline(pi, x, y, x, y + h, drawline);
+       tabline(pi, x, y, x, y + h, 0, 0, drawline);
 
        // Right
        x -= tabular.interColumnSpace(cell);
@@ -4269,7 +4444,7 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        drawline = tabular.rightLine(cell)
                   || (next_cell_col < tabular.ncols()
                       && tabular.leftLine(tabular.cellIndex(row, next_cell_col)));
-       tabline(pi, x + w, y, x + w, y + h, drawline);
+       tabline(pi, x + w, y, x + w, y + h, 0, 0, drawline);
 }
 
 
@@ -4999,6 +5174,20 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
                                          && !tabular.ltCaption(tabular.cellRow(cur.idx())));
                        break;
 
+               case Tabular::SET_LTRIM_TOP:
+               case Tabular::SET_RTRIM_TOP:
+                       status.setEnabled(tabular.use_booktabs
+                                         && tabular.cellRow(cur.idx()) != 0
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       break;
+
+               case Tabular::SET_LTRIM_BOTTOM:
+               case Tabular::SET_RTRIM_BOTTOM:
+                       status.setEnabled(tabular.use_booktabs
+                                         && tabular.cellRow(cur.idx()) != tabular.nrows() - 1
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       break;
+
                case Tabular::TOGGLE_LINE_TOP:
                        status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
                        status.setOnOff(tabular.topLine(cur.idx()));
@@ -5021,6 +5210,30 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
                        status.setOnOff(tabular.rightLine(cur.idx()));
                        break;
 
+               case Tabular::TOGGLE_LTRIM_TOP:
+                       status.setEnabled(tabular.use_booktabs
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       status.setOnOff(tabular.topLineTrim(cur.idx()).first);
+                       break;
+
+               case Tabular::TOGGLE_RTRIM_TOP:
+                       status.setEnabled(tabular.use_booktabs
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       status.setOnOff(tabular.topLineTrim(cur.idx()).second);
+                       break;
+
+               case Tabular::TOGGLE_LTRIM_BOTTOM:
+                       status.setEnabled(tabular.use_booktabs
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       status.setOnOff(tabular.bottomLineTrim(cur.idx()).first);
+                       break;
+
+               case Tabular::TOGGLE_RTRIM_BOTTOM:
+                       status.setEnabled(tabular.use_booktabs
+                                         && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       status.setOnOff(tabular.bottomLineTrim(cur.idx()).second);
+                       break;
+
                // multirow cells only inherit the alignment of the column if the column has
                // no width, otherwise they are left-aligned
                // therefore allow always left but right and center only if there is no width
@@ -5901,9 +6114,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 
        case Tabular::DELETE_ROW:
                if (sel_row_end == tabular.nrows() - 1 && sel_row_start != 0) {
-                       for (col_type c = 0; c < tabular.ncols(); c++)
+                       for (col_type c = 0; c < tabular.ncols(); c++) {
                                tabular.setBottomLine(tabular.cellIndex(sel_row_start - 1, c),
                                        tabular.bottomLine(tabular.cellIndex(sel_row_end, c)));
+                               tabular.setBottomLineTrim(tabular.cellIndex(sel_row_start - 1, c),
+                                       tabular.bottomLineTrim(tabular.cellIndex(sel_row_end, c)));
+                       }
                }
 
                for (row_type r = sel_row_start; r <= sel_row_end; ++r)
@@ -5988,6 +6204,46 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
        }
 
+       case Tabular::SET_LTRIM_TOP:
+       case Tabular::TOGGLE_LTRIM_TOP: {
+               bool l = (feature == Tabular::SET_LTRIM_TOP)
+                              ? (value == "true") : !tabular.topLineTrim(cur.idx()).first;
+               for (row_type r = sel_row_start; r <= sel_row_end; ++r)
+                       for (col_type c = sel_col_start; c <= sel_col_end; ++c)
+                               tabular.setTopLineLTrim(tabular.cellIndex(r, c), l);
+               break;
+       }
+
+       case Tabular::SET_RTRIM_TOP:
+       case Tabular::TOGGLE_RTRIM_TOP: {
+               bool l = (feature == Tabular::SET_RTRIM_TOP)
+                              ? (value == "true") : !tabular.topLineTrim(cur.idx()).second;
+               for (row_type r = sel_row_start; r <= sel_row_end; ++r)
+                       for (col_type c = sel_col_start; c <= sel_col_end; ++c)
+                               tabular.setTopLineRTrim(tabular.cellIndex(r, c), l);
+               break;
+       }
+
+       case Tabular::SET_LTRIM_BOTTOM:
+       case Tabular::TOGGLE_LTRIM_BOTTOM: {
+               bool l = (feature == Tabular::SET_LTRIM_BOTTOM)
+                              ? (value == "true") : !tabular.bottomLineTrim(cur.idx()).first;
+               for (row_type r = sel_row_start; r <= sel_row_end; ++r)
+                       for (col_type c = sel_col_start; c <= sel_col_end; ++c)
+                               tabular.setBottomLineLTrim(tabular.cellIndex(r, c), l);
+               break;
+       }
+
+       case Tabular::SET_RTRIM_BOTTOM:
+       case Tabular::TOGGLE_RTRIM_BOTTOM: {
+               bool l = (feature == Tabular::SET_RTRIM_BOTTOM)
+                              ? (value == "true") : !tabular.bottomLineTrim(cur.idx()).second;
+               for (row_type r = sel_row_start; r <= sel_row_end; ++r)
+                       for (col_type c = sel_col_start; c <= sel_col_end; ++c)
+                               tabular.setBottomLineRTrim(tabular.cellIndex(r, c), l);
+               break;
+       }
+
        case Tabular::SET_LINE_LEFT:
        case Tabular::TOGGLE_LINE_LEFT: {
                bool lineSet = (feature == Tabular::SET_LINE_LEFT)
index 182b419bdd84ba8eeac53f7eaea08f5878f46a3e..fac2660fe6a98adce9677c6d7c786eb2b465f1cc 100644 (file)
@@ -179,6 +179,22 @@ public:
                ///FIXME: remove
                TOGGLE_LINE_RIGHT,
                ///
+               SET_LTRIM_TOP,
+               ///
+               SET_RTRIM_TOP,
+               ///
+               SET_LTRIM_BOTTOM,
+               ///
+               SET_RTRIM_BOTTOM,
+               ///
+               TOGGLE_LTRIM_TOP,
+               ///
+               TOGGLE_RTRIM_TOP,
+               ///
+               TOGGLE_LTRIM_BOTTOM,
+               ///
+               TOGGLE_RTRIM_BOTTOM,
+               ///
                ALIGN_LEFT,
                ///
                ALIGN_RIGHT,
@@ -420,6 +436,10 @@ public:
        /// If \p ignore_bt is true, we return the state as if booktabs was
        /// not used
        bool rightLine(idx_type cell, bool const ignore_bt = false) const;
+       /// Returns whether the top line is trimmed left and/or right
+       std::pair<bool, bool> topLineTrim(idx_type const cell) const;
+       /// Returns whether the bottom line is trimmed left and/or right
+       std::pair<bool, bool> bottomLineTrim(idx_type const cell) const;
 
        /// return space occupied by the second horizontal line and
        /// interline space above row \p row in pixels
@@ -453,6 +473,18 @@ public:
        ///
        void setBottomLine(idx_type cell, bool line);
        ///
+       void setTopLineLTrim(idx_type cell, bool val);
+       ///
+       void setBottomLineLTrim(idx_type cell, bool val);
+       ///
+       void setTopLineRTrim(idx_type cell, bool val);
+       ///
+       void setBottomLineRTrim(idx_type cell, bool val);
+       ///
+       void setTopLineTrim(idx_type cell, std::pair<bool, bool>);
+       ///
+       void setBottomLineTrim(idx_type cell, std::pair<bool, bool>);
+       ///
        void setLeftLine(idx_type cell, bool line);
        ///
        void setRightLine(idx_type cell, bool line);
@@ -692,6 +724,14 @@ public:
                ///
                bool right_line;
                ///
+               bool top_line_rtrimmed;
+               ///
+               bool top_line_ltrimmed;
+               ///
+               bool bottom_line_rtrimmed;
+               ///
+               bool bottom_line_ltrimmed;
+               ///
                BoxType usebox;
                ///
                int rotate;
index 1706ef4f54aab8bde8bb32216a321832e6b4b942..b360bc0e417684628c7fce9bb8da8bea503c364c 100644 (file)
@@ -34,6 +34,8 @@ Format LaTeX feature                        LyX feature
 443    unicode-math.sty                     InsetMath*
 453    automatic stmaryrd loading           \use_package stmaryrd
 457    automatic stackrel loading           \use_package stackrel
+571    cmirule trimming (booktabs)
+       \cmidrule(lr){n-n}                   <cell ... toplineltrim|toplinettrim|bottomlineltrim|bottomlinertrim true ...>
 
 
 
index 7783fd75e75b0044553cb438c690ef3106a769b8..2b900966ca054b660c64e8ed60ee6ed886a24e84 100644 (file)
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 570 // spitz: biblatex bibencodings
-#define LYX_FORMAT_TEX2LYX 570
+#define LYX_FORMAT_LYX 571 // spitz: cmidrule trimming
+#define LYX_FORMAT_TEX2LYX 571
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER