]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insettabular.C
Implement copying of rows and columns in tables
[lyx.git] / src / insets / insettabular.C
index a8c9d8d95d60f3da4681e501e58a09adde5c6ca7..0774f66c3fd38245f1c2ff6437992557ffc5e80d 100644 (file)
 #include "support/convert.h"
 
 #include "frontends/Alert.h"
+#include "frontends/Application.h"
 #include "frontends/font_metrics.h"
-#include "frontends/LyXView.h"
+#include "frontends/Clipboard.h"
 #include "frontends/Painter.h"
+#include "frontends/Selection.h"
 #include "frontends/nullpainter.h"
 
 #include <sstream>
 #include <iostream>
 #include <limits>
 
+using lyx::docstring;
+
 using lyx::cap::dirtyTabularStack;
 using lyx::cap::tabularStackDirty;
 
@@ -54,6 +58,7 @@ using lyx::graphics::PreviewLoader;
 using lyx::support::ltrim;
 
 using lyx::frontend::Painter;
+using lyx::frontend::Clipboard;
 
 using boost::shared_ptr;
 
@@ -90,6 +95,8 @@ TabularFeature tabularFeature[] =
        { LyXTabular::APPEND_COLUMN, "append-column" },
        { LyXTabular::DELETE_ROW, "delete-row" },
        { LyXTabular::DELETE_COLUMN, "delete-column" },
+       { LyXTabular::COPY_ROW, "copy-row" },
+       { LyXTabular::COPY_COLUMN, "copy-column" },
        { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
        { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
        { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
@@ -269,9 +276,15 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        tabular.getCellInset(cell)->metrics(m, dim);
                        if (!p_width.zero())
                                dim.wid = m.base.textwidth;
+                       tabular.setWidthOfCell(cell, dim.wid);
+                       if (p_width.zero()) {
+                               m.base.textwidth = dim.wid + 2 * ADD_TO_TABULAR_WIDTH;
+                               // FIXME there must be a way to get rid of
+                               // the second metrics call
+                               tabular.getCellInset(cell)->metrics(m, dim);
+                       }
                        maxAsc  = max(maxAsc, dim.asc);
                        maxDesc = max(maxDesc, dim.des);
-                       tabular.setWidthOfCell(cell, dim.wid);
                        ++cell;
                }
                int const top_space = tabular.row_info[i].top_space_default ?
@@ -436,7 +449,7 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
 }
 
 
-string const InsetTabular::editMessage() const
+docstring const InsetTabular::editMessage() const
 {
        return _("Opened table");
 }
@@ -481,7 +494,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
        case LFUN_MOUSE_PRESS:
                //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
 
-               if (cmd.button() == mouse_button::button1 
+               if (cmd.button() == mouse_button::button1
                    || cmd.button() == mouse_button::button3) {
                        cur.selection() = false;
                        setCursorFromCoordinates(cur, cmd.x, cmd.y);
@@ -598,7 +611,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
 //             //if (hasSelection())
 //             //      cur.selection() = false;
 //             col_type const col = tabular.column_of_cell(cur.idx());
-//             int const t =   cur.bv().top_y() + cur.bv().painter().paperHeight();
+//             int const t =   cur.bv().top_y() + cur.bv().height();
 //             if (t < yo() + tabular.getHeightOfTabular()) {
 //                     cur.bv().scrollDocView(t);
 //                     cur.idx() = tabular.getCellBelow(first_visible_cell) + col;
@@ -614,7 +627,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
 //             //if (hasSelection())
 //             //      cur.selection() = false;
 //             col_type const col = tabular.column_of_cell(cur.idx());
-//             int const t =   cur.bv().top_y() + cur.bv().painter().paperHeight();
+//             int const t =   cur.bv().top_y() + cur.bv().height();
 //             if (yo() < 0) {
 //                     cur.bv().scrollDocView(t);
 //                     if (yo() > 0)
@@ -638,15 +651,17 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
                break;
 
        case LFUN_TABULAR_FEATURE:
-               if (!tabularFeatures(cur, cmd.argument))
+               if (!tabularFeatures(cur, lyx::to_utf8(cmd.argument())))
                        cur.undispatched();
                break;
 
        // insert file functions
        case LFUN_FILE_INSERT_ASCII_PARA:
        case LFUN_FILE_INSERT_ASCII: {
-               string const tmpstr = getContentsOfAsciiFile(&cur.bv(), cmd.argument, false);
-               if (!tmpstr.empty() && !insertAsciiString(cur.bv(), tmpstr, false))
+               // FIXME: We don't know the encoding of filenames
+               string const tmpstr = getContentsOfAsciiFile(&cur.bv(), lyx::to_utf8(cmd.argument()), false);
+               // FIXME: We don't know the encoding of the file
+               if (!tmpstr.empty() && !insertAsciiString(cur.bv(), lyx::from_utf8(tmpstr), false))
                        cur.undispatched();
                break;
        }
@@ -682,13 +697,16 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
                        cell(cur.idx())->dispatch(cur, cmd);
                break;
 
+       case LFUN_CLIPBOARD_PASTE:
        case LFUN_PRIMARY_SELECTION_PASTE: {
-               string const clip = cur.bv().getClipboard();
+               docstring const clip = (cmd.action == LFUN_CLIPBOARD_PASTE) ?
+                       theApp->clipboard().get() :
+                       theApp->selection().get();
                if (clip.empty())
                        break;
                // pass to InsertAsciiString, but
                // only if we have multi-cell content
-               if (clip.find_first_of("\t\n") != string::npos) {
+               if (clip.find_first_of(lyx::from_ascii("\t\n")) != docstring::npos) {
                        if (insertAsciiString(cur.bv(), clip, false)) {
                                // content has been replaced,
                                // so cursor might be invalid
@@ -713,9 +731,6 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
                        break;
                }
                cell(cur.idx())->dispatch(cur, cmd);
-               // Reset pasted paragraphs:
-               if (tabular.getPWidth(cur.idx()).zero())
-                       cell(cur.idx())->forceParagraphsToDefault(cur);
                break;
 
        case LFUN_FONT_EMPH:
@@ -739,27 +754,22 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
                        row_type rs, re;
                        col_type cs, ce;
                        getSelection(cur, rs, re, cs, ce);
+                       LCursor tmpcur = cur;
                        for (row_type i = rs; i <= re; ++i) {
                                for (col_type j = cs; j <= ce; ++j) {
                                        // cursor follows cell:
-                                       cur.idx() = tabular.getCellNumber(i, j);
+                                       tmpcur.idx() = tabular.getCellNumber(i, j);
                                        // select this cell only:
-                                       cur.pos() = 0;
-                                       cur.resetAnchor();
-                                       cur.pos() = cur.top().lastpos();
-                                       cur.setCursor(cur);
-                                       cur.setSelection();
-                                       cell(cur.idx())->dispatch(cur, cmd);
+                                       tmpcur.pit() = 0;
+                                       tmpcur.pos() = 0;
+                                       tmpcur.resetAnchor();
+                                       tmpcur.pit() = tmpcur.lastpit();
+                                       tmpcur.pos() = tmpcur.top().lastpos();
+                                       tmpcur.setCursor(tmpcur);
+                                       tmpcur.setSelection();
+                                       cell(tmpcur.idx())->dispatch(tmpcur, cmd);
                                }
                        }
-                       // Restore original selection
-                       cur.idx() = tabular.getCellNumber(rs, cs);
-                       cur.pos() = 0;
-                       cur.resetAnchor();
-                       cur.idx() = tabular.getCellNumber(re, ce);
-                       cur.pos() = cur.top().lastpos();
-                       cur.setCursor(cur);
-                       cur.setSelection();
                        break;
                } else {
                        cell(cur.idx())->dispatch(cur, cmd);
@@ -787,7 +797,7 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd,
                int i = 0;
                for (; tabularFeature[i].action != LyXTabular::LAST_ACTION; ++i) {
                        string const tmp = tabularFeature[i].feature;
-                       if (tmp == cmd.argument.substr(0, tmp.length())) {
+                       if (tmp == lyx::to_utf8(cmd.argument()).substr(0, tmp.length())) {
                                action = tabularFeature[i].action;
                                break;
                        }
@@ -799,7 +809,7 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd,
                }
 
                string const argument
-                       = ltrim(cmd.argument.substr(tabularFeature[i].feature.length()));
+                       = ltrim(lyx::to_utf8(cmd.argument()).substr(tabularFeature[i].feature.length()));
 
                row_type sel_row_start = 0;
                row_type sel_row_end = 0;
@@ -818,6 +828,8 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd,
                case LyXTabular::APPEND_COLUMN:
                case LyXTabular::DELETE_ROW:
                case LyXTabular::DELETE_COLUMN:
+               case LyXTabular::COPY_ROW:
+               case LyXTabular::COPY_COLUMN:
                case LyXTabular::SET_ALL_LINES:
                case LyXTabular::UNSET_ALL_LINES:
                case LyXTabular::SET_TOP_SPACE:
@@ -961,11 +973,11 @@ bool InsetTabular::getStatus(LCursor & cur, FuncRequest const & cmd,
                case LyXTabular::SET_LTNEWPAGE:
                        status.setOnOff(tabular.getLTNewPage(sel_row_start));
                        break;
-                       
+
                case LyXTabular::SET_BOOKTABS:
                        status.setOnOff(tabular.useBookTabs());
                        break;
-                       
+
                case LyXTabular::UNSET_BOOKTABS:
                        status.setOnOff(!tabular.useBookTabs());
                        break;
@@ -1056,13 +1068,6 @@ int InsetTabular::plaintext(Buffer const & buf, ostream & os,
 }
 
 
-int InsetTabular::linuxdoc(Buffer const & buf, ostream & os,
-                          OutputParams const & runparams) const
-{
-       return tabular.linuxdoc(buf,os, runparams);
-}
-
-
 int InsetTabular::docbook(Buffer const & buf, ostream & os,
                          OutputParams const & runparams) const
 {
@@ -1152,7 +1157,7 @@ int InsetTabular::dist(idx_type const cell, int x, int y) const
        int const xend = xbeg + tabular.getWidthOfColumn(cell);
        row_type const row = tabular.row_of_cell(cell);
        int const ybeg = o.y_ - tabular.getAscentOfRow(row) -
-                        tabular.getAdditionalHeight(row);
+                        tabular.getAdditionalHeight(row);
        int const yend = o.y_ + tabular.getDescentOfRow(row);
 
        if (x < xbeg)
@@ -1460,6 +1465,15 @@ void InsetTabular::tabularFeatures(LCursor & cur,
                cur.selection() = false;
                break;
 
+       case LyXTabular::COPY_ROW:
+               tabular.copyRow(bv.buffer()->params(), row);
+               break;
+
+       case LyXTabular::COPY_COLUMN:
+               tabular.copyColumn(bv.buffer()->params(), column);
+               cur.idx() = tabular.getCellNumber(row, column);
+               break;
+
        case LyXTabular::M_TOGGLE_LINE_TOP:
                flag = false;
        case LyXTabular::TOGGLE_LINE_TOP: {
@@ -1546,8 +1560,9 @@ void InsetTabular::tabularFeatures(LCursor & cur,
 #ifdef WITH_WARNINGS
 #warning Need I say it ? This is horrible.
 #endif
+                       // FIXME UNICODE
                        Alert::error(_("Error setting multicolumn"),
-                                  _("You cannot set multicolumn vertically."));
+                                    _("You cannot set multicolumn vertically."));
                        return;
                }
                if (!cur.selection()) {
@@ -1776,7 +1791,7 @@ bool InsetTabular::copySelection(LCursor & cur)
        ostringstream os;
        OutputParams const runparams;
        paste_tabular->plaintext(cur.buffer(), os, runparams, 0, true, '\t');
-       cur.bv().stuffClipboard(os.str());
+       theApp->clipboard().put(lyx::from_utf8(os.str()));
        // mark tabular stack dirty
        // FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
        // when we (hopefully) have a one-for-all paste mechanism.
@@ -1840,7 +1855,10 @@ void InsetTabular::cutSelection(LCursor & cur)
        }
 
        // cursor position might be invalid now
-       cur.pos() = cur.lastpos();
+       if (cur.pit() > cur.lastpit())
+               cur.pit() = cur.lastpit();
+       if (cur.pos() > cur.lastpos())
+               cur.pos() = cur.lastpos();
        cur.clearSelection();
 }
 
@@ -1895,7 +1913,7 @@ bool InsetTabular::forceDefaultParagraphs(idx_type cell) const
 }
 
 
-bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf,
+bool InsetTabular::insertAsciiString(BufferView & bv, docstring const & buf,
                                     bool usePaste)
 {
        if (buf.length() <= 0)
@@ -1904,10 +1922,11 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf,
        col_type cols = 1;
        row_type rows = 1;
        col_type maxCols = 1;
-       string::size_type const len = buf.length();
-       string::size_type p = 0;
+       docstring::size_type const len = buf.length();
+       docstring::size_type p = 0;
 
-       while (p < len && (p = buf.find_first_of("\t\n", p)) != string::npos) {
+       while (p < len &&
+              (p = buf.find_first_of(lyx::from_ascii("\t\n"), p)) != docstring::npos) {
                switch (buf[p]) {
                case '\t':
                        ++cols;
@@ -1939,7 +1958,7 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf,
                row = tabular.row_of_cell(cell);
        }
 
-       string::size_type op = 0;
+       docstring::size_type op = 0;
        idx_type const cells = loctab->getNumberOfCells();
        p = 0;
        cols = ocol;
@@ -1947,7 +1966,7 @@ bool InsetTabular::insertAsciiString(BufferView & bv, string const & buf,
        col_type const columns = loctab->columns();
 
        while (cell < cells && p < len && row < rows &&
-              (p = buf.find_first_of("\t\n", p)) != string::npos)
+              (p = buf.find_first_of(lyx::from_ascii("\t\n"), p)) != docstring::npos)
        {
                if (p >= len)
                        break;