]> git.lyx.org Git - features.git/commitdiff
add support for TABs in Listings, fileformat change, fixes http://bugzilla.lyx.org...
authorUwe Stöhr <uwestoehr@web.de>
Tue, 30 Sep 2008 18:00:02 +0000 (18:00 +0000)
committerUwe Stöhr <uwestoehr@web.de>
Tue, 30 Sep 2008 18:00:02 +0000 (18:00 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@26647 a592a061-630c-0410-9148-cb99ea01b6c8

development/FORMAT
lib/lyx2lyx/lyx_1_6.py
src/Buffer.cpp
src/Lexer.cpp
src/Paragraph.cpp
src/ParagraphMetrics.cpp
src/frontends/qt4/GuiListings.cpp
src/frontends/qt4/ui/ListingsUi.ui
src/insets/InsetListings.cpp
src/rowpainter.cpp

index 2611f9c50a998909ea47386f020bb9651066a17b..84539258657383f99d6da46590eac8dbb012bf70 100644 (file)
@@ -1,6 +1,9 @@
 LyX file-format changes
 -----------------------
 
+2008-09-30 Uwe Stöhr <uwestoehr@web.de>
+       * Format incremented to 341: support for TABs in listings".
+
 2008-08-01 José Matos <jamatos@fc.up.pt>
        * Format incremented to 340: move empty layouts to "Plain Layout".
 
@@ -1023,5 +1026,3 @@ renamed as "size_kind" and "lyxsize_kind" respectively.
 
  \end_inset
 
-
-
index d7c2c2043d608c95a008df31e6e543365d973ade..057780496106cc7a69b243fed4b49746f2bc821b 100644 (file)
@@ -2906,6 +2906,37 @@ def add_plain_layout(document):
             document.body[i] = "\\begin_layout Plain Layout"
         i += 1
 
+
+def revert_tabulators(document):
+    "Revert tabulators to 4 spaces"
+    i = 0
+    while True:
+        i = find_token(document.body, "\t", i)
+        if i == -1:
+            return
+        document.body[i] = document.body[i].replace("\t", "    ")
+        i += 1
+
+
+def revert_tabsize(document):
+    "Revert the tabsize parameter of listings"
+    i = 0
+    j = 0
+    while True:
+        # either it is the only parameter
+        i = find_token(document.body, 'lstparams "tabsize=4"', i)
+        if i != -1:
+            del document.body[i]
+        # or the last one
+        j = find_token(document.body, "lstparams", j)
+        if j == -1:
+            return
+        pos = document.body[j].find(",tabsize=")
+        document.body[j] = document.body[j][:pos] + '"'
+        i += 1
+        j += 1
+
+
 ##
 # Conversion hub
 #
@@ -2974,10 +3005,12 @@ convert = [[277, [fix_wrong_tables]],
            [337, [convert_display_enum]],
            [338, []],
            [339, []],
-           [340, [add_plain_layout]]
+           [340, [add_plain_layout]],
+           [341, []]
           ]
 
-revert =  [[339, []],
+revert =  [[340, [revert_tabulators, revert_tabsize]],
+           [339, []],
            [338, [revert_removed_modules]],
            [337, [revert_polytonicgreek]],
            [336, [revert_display_enum]],
index 434f56103ab63027f257b7ced4414aed19612e63..9db261dec7f0c085b8c7044c07d74f951bdfc389 100644 (file)
@@ -115,7 +115,7 @@ namespace os = support::os;
 
 namespace {
 
-int const LYX_FORMAT = 340; //jamatos: add plain layout
+int const LYX_FORMAT = 341; //uwestoehr: TAB support for listings
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -619,11 +619,8 @@ void Buffer::insertStringAsLines(ParagraphList & pars,
                                ++pos;
                                space_inserted = true;
                        } else {
-                               const pos_type n = 8 - pos % 8;
-                               for (pos_type i = 0; i < n; ++i) {
-                                       par.insertChar(pos, ' ', font, params().trackChanges);
-                                       ++pos;
-                               }
+                               par.insertChar(pos, *cit, font, params().trackChanges);
+                               ++pos;
                                space_inserted = true;
                        }
                } else if (!isPrintable(*cit)) {
index 108d26ba2caacd77194429203808638eeb6e6bcf..9061d7c0b3ab0ac7a23a25681900a720baa3f452 100644 (file)
@@ -499,7 +499,7 @@ bool Lexer::Pimpl::nextToken()
                char cc = 0;
                is.get(cc);
                c = cc;
-               if (c >= ' ' && is) {
+               if ((c >= ' ' || c == '\t') && is) {
                        buff.clear();
 
                        if (c == '\\') { // first char == '\\'
@@ -513,7 +513,7 @@ bool Lexer::Pimpl::nextToken()
                                        buff.push_back(c);
                                        is.get(cc);
                                        c = cc;
-                               } while (c >= ' ' && c != '\\' && is);
+                               } while ((c >= ' ' || c == '\t') && c != '\\' && is);
                        }
 
                        if (c == '\\')
index 5f138fead8d2e678c41cc4244e263fa6c750f4e1..ba3ee8e0d8d16fbcf4642675b1ad1e5a0d4c1293 100644 (file)
@@ -2396,7 +2396,7 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
 
        for (pos_type i = beg; i < end; ++i) {
                char_type const c = d->text_[i];
-               if (isPrintable(c))
+               if (isPrintable(c) || c == '\t')
                        os.put(c);
                else if (c == META_INSET && options & AS_STR_INSETS)
                        getInset(i)->textString(os);
index 1e4410644c4c67ab22e1e096af5d0b307b9c79b1..15ed5f5d026b3f16c2906c465cf9d313531d792a 100644 (file)
@@ -220,6 +220,9 @@ int ParagraphMetrics::singleWidth(pos_type pos, Font const & font) const
 
        char_type c = par_->getChar(pos);
 
+       if (c == '\t')
+               return 4 * theFontMetrics(font).width(' ');
+       
        if (!isPrintable(c))
                return theFontMetrics(font).width(c);
 
index 38077d434cb08da1703274a01dd539fd97e8e45d..7ce3c39888f68c476e52856b369d5b793cfa8823 100644 (file)
@@ -20,6 +20,7 @@
 #include "insets/InsetListings.h"
 #include "insets/InsetListingsParams.h"
 
+#include "support/convert.h"
 #include "support/debug.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
@@ -198,6 +199,8 @@ GuiListings::GuiListings(GuiView & lv)
                this, SLOT(change_adaptor()));
        connect(spaceInStringCB, SIGNAL(clicked()),
                this, SLOT(change_adaptor()));
+       connect(tabsizeSB, SIGNAL(valueChanged(int)),
+               this, SLOT(change_adaptor()));
        connect(extendedcharsCB, SIGNAL(clicked()),
                this, SLOT(change_adaptor()));
 
@@ -296,6 +299,7 @@ string GuiListings::construct_params()
                basicstyle += "\\" + fontstyle;
        bool breakline = breaklinesCB->isChecked();
        bool space = spaceCB->isChecked();
+       int tabsize = tabsizeSB->value();
        bool spaceInString = spaceInStringCB->isChecked();
        bool extendedchars = extendedcharsCB->isChecked();
        string extra = fromqstr(listingsED->toPlainText());
@@ -331,6 +335,8 @@ string GuiListings::construct_params()
                par.addParam("showspaces", "true");
        if (!spaceInString)
                par.addParam("showstringspaces", "false");
+       if (tabsize != 8)
+               par.addParam("tabsize", convert<string>(tabsize));
        if (extendedchars)
                par.addParam("extendedchars", "true");
        par.addParams(extra);
@@ -456,6 +462,7 @@ void GuiListings::updateContents()
        breaklinesCB->setChecked(false);
        spaceCB->setChecked(false);
        spaceInStringCB->setChecked(true);
+       tabsizeSB->setValue(8);
        extendedcharsCB->setChecked(false);
 
        // set values from param string
@@ -583,6 +590,9 @@ void GuiListings::updateContents()
                } else if (prefixIs(*it, "showstringspaces=")) {
                        spaceInStringCB->setChecked(contains(*it, "true"));
                        *it = "";
+               } else if (prefixIs(*it, "tabsize=")) {
+                       tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
+                       *it = "";
                } else if (prefixIs(*it, "extendedchars=")) {
                        extendedcharsCB->setChecked(contains(*it, "true"));
                        *it = "";
index cd7075bfcb0972865b55869759084fee208846a9..3ec370663b8447956e16786e45210621d770f84f 100644 (file)
@@ -8,8 +8,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>612</width>
-    <height>317</height>
+    <width>654</width>
+    <height>349</height>
    </rect>
   </property>
   <property name="windowTitle" >
@@ -28,9 +28,7 @@
    <item row="0" column="0" >
     <widget class="QTabWidget" name="listingsTW" >
      <property name="sizePolicy" >
-      <sizepolicy>
-       <hsizetype>3</hsizetype>
-       <vsizetype>3</vsizetype>
+      <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
        <property name="spacing" >
         <number>6</number>
        </property>
-       <item rowspan="2" row="0" column="2" >
-        <widget class="QGroupBox" name="basicstyleGB" >
-         <property name="title" >
-          <string>Style</string>
-         </property>
-         <layout class="QGridLayout" >
-          <property name="margin" >
-           <number>9</number>
-          </property>
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <item row="0" column="1" >
-           <widget class="QComboBox" name="fontsizeCO" >
-            <property name="sizePolicy" >
-             <sizepolicy>
-              <hsizetype>7</hsizetype>
-              <vsizetype>0</vsizetype>
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="toolTip" >
-             <string>The content's base font size</string>
-            </property>
-            <property name="editable" >
-             <bool>false</bool>
-            </property>
-            <property name="autoCompletion" >
-             <bool>true</bool>
-            </property>
-            <property name="duplicatesEnabled" >
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="0" >
-           <widget class="QLabel" name="fontsize_label_3" >
-            <property name="text" >
-             <string>F&amp;ont size:</string>
-            </property>
-            <property name="wordWrap" >
-             <bool>false</bool>
-            </property>
-            <property name="buddy" >
-             <cstring>fontsizeCO</cstring>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1" >
-           <widget class="QComboBox" name="fontstyleCO" >
-            <property name="sizePolicy" >
-             <sizepolicy>
-              <hsizetype>7</hsizetype>
-              <vsizetype>0</vsizetype>
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="toolTip" >
-             <string>The content's base font style</string>
-            </property>
-            <property name="editable" >
-             <bool>false</bool>
-            </property>
-            <property name="autoCompletion" >
-             <bool>true</bool>
-            </property>
-            <property name="duplicatesEnabled" >
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="0" >
-           <widget class="QLabel" name="fontstyle_label_3" >
-            <property name="text" >
-             <string>Font Famil&amp;y:</string>
-            </property>
-            <property name="wordWrap" >
-             <bool>false</bool>
-            </property>
-            <property name="buddy" >
-             <cstring>fontstyleCO</cstring>
-            </property>
-           </widget>
-          </item>
-          <item row="5" column="0" colspan="2" >
-           <widget class="QCheckBox" name="extendedcharsCB" >
-            <property name="enabled" >
-             <bool>true</bool>
-            </property>
-            <property name="toolTip" >
-             <string>Use extended character table</string>
-            </property>
-            <property name="text" >
-             <string>&amp;Extended character table</string>
-            </property>
-            <property name="shortcut" >
-             <number>276824133</number>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="0" colspan="2" >
-           <widget class="QCheckBox" name="spaceInStringCB" >
-            <property name="toolTip" >
-             <string>Make spaces in strings visible by a special symbol</string>
-            </property>
-            <property name="text" >
-             <string>Space i&amp;n string as symbol</string>
-            </property>
-            <property name="shortcut" >
-             <number>276824147</number>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="0" colspan="2" >
-           <widget class="QCheckBox" name="spaceCB" >
-            <property name="toolTip" >
-             <string>Make spaces visible by a special symbol</string>
-            </property>
-            <property name="text" >
-             <string>S&amp;pace as symbol</string>
-            </property>
-            <property name="shortcut" >
-             <number>276824147</number>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0" colspan="2" >
-           <widget class="QCheckBox" name="breaklinesCB" >
-            <property name="toolTip" >
-             <string>Break lines longer than the linewidth</string>
-            </property>
-            <property name="text" >
-             <string>&amp;Break long lines</string>
-            </property>
-            <property name="shortcut" >
-             <number>276824130</number>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
        <item row="0" column="0" >
         <widget class="QGroupBox" name="placementGB" >
          <property name="title" >
           <item row="2" column="1" >
            <widget class="QComboBox" name="numberFontSizeCO" >
             <property name="sizePolicy" >
-             <sizepolicy>
-              <hsizetype>7</hsizetype>
-              <vsizetype>0</vsizetype>
+             <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
               <horstretch>0</horstretch>
               <verstretch>0</verstretch>
              </sizepolicy>
            </widget>
           </item>
          </layout>
+         <zorder>numberfontsizeL_2</zorder>
+         <zorder>lastlineLE</zorder>
+         <zorder>firstlineLE</zorder>
+         <zorder>numberfontsizeL_3</zorder>
+         <zorder>basicstyleGB</zorder>
+        </widget>
+       </item>
+       <item rowspan="2" row="0" column="2" >
+        <widget class="QGroupBox" name="basicstyleGB" >
+         <property name="title" >
+          <string>Style</string>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="sizeConstraint" >
+           <enum>QLayout::SetDefaultConstraint</enum>
+          </property>
+          <property name="margin" >
+           <number>9</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="0" column="0" >
+           <widget class="QLabel" name="fontsize_label_3" >
+            <property name="text" >
+             <string>F&amp;ont size:</string>
+            </property>
+            <property name="wordWrap" >
+             <bool>false</bool>
+            </property>
+            <property name="buddy" >
+             <cstring>fontsizeCO</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <widget class="QComboBox" name="fontsizeCO" >
+            <property name="sizePolicy" >
+             <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip" >
+             <string>The content's base font size</string>
+            </property>
+            <property name="editable" >
+             <bool>false</bool>
+            </property>
+            <property name="autoCompletion" >
+             <bool>true</bool>
+            </property>
+            <property name="duplicatesEnabled" >
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0" >
+           <widget class="QLabel" name="fontstyle_label_3" >
+            <property name="text" >
+             <string>Font Famil&amp;y:</string>
+            </property>
+            <property name="wordWrap" >
+             <bool>false</bool>
+            </property>
+            <property name="buddy" >
+             <cstring>fontstyleCO</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1" >
+           <widget class="QComboBox" name="fontstyleCO" >
+            <property name="sizePolicy" >
+             <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip" >
+             <string>The content's base font style</string>
+            </property>
+            <property name="editable" >
+             <bool>false</bool>
+            </property>
+            <property name="autoCompletion" >
+             <bool>true</bool>
+            </property>
+            <property name="duplicatesEnabled" >
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" colspan="2" >
+           <widget class="QCheckBox" name="breaklinesCB" >
+            <property name="toolTip" >
+             <string>Break lines longer than the linewidth</string>
+            </property>
+            <property name="text" >
+             <string>&amp;Break long lines</string>
+            </property>
+            <property name="shortcut" >
+             <number>276824130</number>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0" colspan="2" >
+           <widget class="QCheckBox" name="spaceCB" >
+            <property name="toolTip" >
+             <string>Make spaces visible by a special symbol</string>
+            </property>
+            <property name="text" >
+             <string>S&amp;pace as symbol</string>
+            </property>
+            <property name="shortcut" >
+             <number>276824147</number>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="2" >
+           <widget class="QCheckBox" name="spaceInStringCB" >
+            <property name="toolTip" >
+             <string>Make spaces in strings visible by a special symbol</string>
+            </property>
+            <property name="text" >
+             <string>Space i&amp;n string as symbol</string>
+            </property>
+            <property name="shortcut" >
+             <number>276824147</number>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0" >
+           <widget class="QLabel" name="tabsizeL" >
+            <property name="text" >
+             <string>Tabulator size</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="1" >
+           <widget class="QSpinBox" name="tabsizeSB" />
+          </item>
+          <item row="7" column="0" colspan="2" >
+           <widget class="QCheckBox" name="extendedcharsCB" >
+            <property name="enabled" >
+             <bool>true</bool>
+            </property>
+            <property name="toolTip" >
+             <string>Use extended character table</string>
+            </property>
+            <property name="text" >
+             <string>&amp;Extended character table</string>
+            </property>
+            <property name="shortcut" >
+             <number>276824133</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+         <zorder>fontsizeCO</zorder>
+         <zorder>fontsize_label_3</zorder>
+         <zorder>fontstyleCO</zorder>
+         <zorder>fontstyle_label_3</zorder>
+         <zorder>extendedcharsCB</zorder>
+         <zorder>spaceCB</zorder>
+         <zorder>breaklinesCB</zorder>
+         <zorder>label_2</zorder>
+         <zorder>tabsizeL</zorder>
+         <zorder>tabsizeSB</zorder>
+         <zorder>horizontalSpacer</zorder>
         </widget>
        </item>
       </layout>
        <item row="0" column="0" >
         <widget class="QGroupBox" name="listingsGB" >
          <property name="sizePolicy" >
-          <sizepolicy>
-           <hsizetype>3</hsizetype>
-           <vsizetype>3</vsizetype>
+          <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
                <height>16777215</height>
               </size>
              </property>
-             <property name="cursor" >
-              <cursor>0</cursor>
+             <property name="cursor" stdset="0" >
+              <cursorShape>ArrowCursor</cursorShape>
              </property>
              <property name="acceptDrops" >
               <bool>false</bool>
             </widget>
             <widget class="QTextEdit" name="listingsED" >
              <property name="sizePolicy" >
-              <sizepolicy>
-               <hsizetype>3</hsizetype>
-               <vsizetype>3</vsizetype>
+              <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
    </item>
    <item row="1" column="0" >
     <layout class="QHBoxLayout" >
-     <property name="margin" >
-      <number>0</number>
-     </property>
      <property name="spacing" >
       <number>6</number>
      </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
      <item>
       <spacer>
        <property name="orientation" >
        <property name="sizeType" >
         <enum>QSizePolicy::Expanding</enum>
        </property>
-       <property name="sizeHint" >
+       <property name="sizeHint" stdset="0" >
         <size>
          <width>221</width>
          <height>27</height>
index 38dc99c1e02b240522f62d6ff6412ac8d1b740d2..95f98a5b560e026d9f5b62007846d347c5a1716d 100644 (file)
@@ -33,6 +33,7 @@
 #include "support/docstream.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
+#include "support/lassert.h"
 
 #include "frontends/alert.h"
 #include "frontends/Application.h"
@@ -289,6 +290,87 @@ void InsetListings::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_INSET_DIALOG_UPDATE:
                cur.bv().updateDialog("listings", params2string(params()));
                break;
+       case LFUN_CELL_FORWARD:
+               if (cur.selection()) {
+                       // If there is a selection, a tab is inserted at the
+                       // beginning of each paragraph.
+                       cur.recordUndoSelection();
+                       pit_type const pit_end = cur.selEnd().pit();
+                       for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+                               LASSERT(pit < paragraphs().size(), /**/);
+                               paragraphs()[pit].insertChar(0, '\t', 
+                                       buffer().params().trackChanges);
+                               // Update the selection pos to make sure the selection does not
+                               // change as the inserted tab will increase the logical pos.
+                               if (cur.anchor_.pit() == pit)
+                                       cur.anchor_.forwardPos();
+                               if (cur.pit() == pit)
+                                       cur.forwardPos();
+                       }
+                       cur.finishUndo();
+               } else {
+                       // Maybe we shouldn't allow tabs within a line, because they
+                       // are not (yet) aligned as one might do expect.
+                       cur.recordUndo();
+                       cur.insert(from_ascii("\t"));
+                       cur.finishUndo();
+               }
+               break;
+       case LFUN_CELL_BACKWARD:
+               if (cur.selection()) {
+                       // If there is a selection, a tab (if present) is removed from
+                       // the beginning of each paragraph.
+                       cur.recordUndoSelection();
+                       pit_type const pit_end = cur.selEnd().pit();
+                       for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+                               LASSERT( pit < paragraphs().size(), /**/ );
+                               Paragraph & par = paragraphs()[pit];
+                               if (par.getChar(0) == '\t') {
+                                       if (cur.pit() == pit)
+                                               cur.posBackward();
+                                       if (cur.anchor_.pit() == pit && cur.anchor_.pos() > 0 )
+                                               cur.anchor_.backwardPos();
+
+                                       par.eraseChar(0, buffer().params().trackChanges);
+                               } else 
+                                       // If no tab was present, try to remove up to four spaces.
+                                       for (int n_spaces = 0;
+                                               par.getChar(0) == ' ' && n_spaces < 4; ++n_spaces) {
+                                                       if (cur.pit() == pit)
+                                                               cur.posBackward();
+                                                       if (cur.anchor_.pit() == pit && cur.anchor_.pos() > 0 )
+                                                               cur.anchor_.backwardPos();
+
+                                                       par.eraseChar(0, buffer().params().trackChanges);
+                                       }
+                       }
+                       cur.finishUndo();
+               } else {
+                       // If there is no selection, try to remove a tab or some spaces 
+                       // before the position of the cursor.
+                       LASSERT(cur.pit() >= 0 && cur.pit() < paragraphs().size(), /**/);
+
+                       Paragraph & par = paragraphs()[cur.pit()];
+                       pos_type const pos = cur.pos();
+
+                       if (pos == 0)
+                               break;
+
+                       char_type const c = par.getChar(pos - 1);
+                       cur.recordUndo();
+                       if (c == '\t') {
+                               cur.posBackward();
+                               par.eraseChar(cur.pos(), buffer().params().trackChanges);
+                       } else
+                               for (int n_spaces = 0; cur.pos() > 0
+                                       && par.getChar(cur.pos() - 1) == ' ' && n_spaces < 4;
+                                       ++n_spaces) {
+                                               cur.posBackward();
+                                               par.eraseChar(cur.pos(), buffer().params().trackChanges);
+                               }
+                               cur.finishUndo();
+               }
+               break;
        default:
                InsetCollapsable::doDispatch(cur, cmd);
                break;
@@ -307,6 +389,10 @@ bool InsetListings::getStatus(Cursor & cur, FuncRequest const & cmd,
                case LFUN_CAPTION_INSERT:
                        status.setEnabled(!params().isInline());
                        return true;
+                       case LFUN_CELL_BACKWARD:
+                       case LFUN_CELL_FORWARD:
+                               status.setEnabled(true);
+                               return true;
                default:
                        return InsetCollapsable::getStatus(cur, cmd, status);
        }
index d36916126fddcfe38521a9b2282051e5d8c834fc..0a097ed9f257edd0308bae09e473db4025b64e4d 100644 (file)
@@ -246,6 +246,7 @@ void RowPainter::paintChars(pos_type & vpos, FontInfo const & font,
        // selected text?
        bool const selection = pos >= row_.sel_beg && pos < row_.sel_end;
 
+       char_type prev_char = ' ';
        // collect as much similar chars as we can
        for (++vpos ; vpos < end ; ++vpos) {
                pos = bidi_.vis2log(vpos);
@@ -264,6 +265,11 @@ void RowPainter::paintChars(pos_type & vpos, FontInfo const & font,
 
                char_type c = par_.getChar(pos);
 
+               if (c == '\t' || prev_char == '\t') {
+                       prev_char = c;
+                       break;
+               }
+
                if (!isPrintableNonspace(c))
                        break;
 
@@ -308,6 +314,9 @@ void RowPainter::paintChars(pos_type & vpos, FontInfo const & font,
 
        docstring s(&str[0], str.size());
 
+       if (s[0] == '\t')
+               s.replace(0,1,from_ascii("    "));
+
        if (!selection && !change_running.changed()) {
                x_ += pi_.pain.text(int(x_), yo_, s, font);
                return;