Uwe stoehr wrote: >> What I still miss in our listings support is this: >> http://bugzilla.lyx.org/show_bug.cgi?id=3629 >> <https://webmail.tudelft.nl/exchweb/bin/redir.asp?URL=http://bugzilla.lyx.org/show_bug.cgi?id=3629> >> > > When you have the patch ready, I'll test it. > Here it is. It allows : - inserting tabs, - removing tabs and spacing by backtab, - copying code with tabs from other applications. Some notes (please check whether these are ok): src/frontends/qt4/GuiFontMetrics.cpp : The line "metrics_.width(ucs4_to_qchar(c))" wasn't working properly for tabs (returned the size of a single space instead of 8). That's why {&& c != '\t'} is necessary in the following: if (is_utf16(c) && c != '\t') value = metrics_.width(ucs4_to_qchar(c)); else value = metrics_.width(toqstr(docstring(1, c)));
src/frontends/qt4/Buffer.cpp : allowing to paste text with tabs. This is now also allowed for ERTs ? Is this a problem or should I create something similar to Paragraph::isFreeSpacing() ? for instance Paragraph::isAllowedTabbing() ? src/Lexer.cpp : Tabs were neglected when reading in the LyX file.
Index: src/insets/InsetListings.cpp =================================================================== --- src/insets/InsetListings.cpp (revision 26320) +++ src/insets/InsetListings.cpp (working copy) @@ -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,71 @@ case LFUN_INSET_DIALOG_UPDATE: cur.bv().updateDialog("listings", params2string(params())); break; + case LFUN_CELL_FORWARD: + if (cur.selection()) { + cur.recordUndoSelection(); + pit_type 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); + cur.posForward(); + } + 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()) { + cur.recordUndoSelection(); + pit_type 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') { + cur.posBackward(); + par.eraseChar(0, buffer().params().trackChanges); + } else + // 8 spaces is the default tab-width as defined in Qt and + // which is now used in the painting and cursor movement. + for (int n_spaces = 0; + par.getChar(0) == ' ' && n_spaces < 8; ++n_spaces) { + cur.posBackward(); + par.eraseChar(0, buffer().params().trackChanges); + } + } + cur.finishUndo(); + } else { + LASSERT(cur.pit() >= 0 && cur.pit() < paragraphs().size(), /**/); + + Paragraph & par = paragraphs()[cur.pit()]; + pos_type pos = cur.pos(); + + if (pos == 0) + break; + + char_type c = par.getChar(pos - 1); + cur.recordUndo(); + if (c == '\t') { + cur.posBackward(); + par.eraseChar(cur.pos(), buffer().params().trackChanges); + } else + // 8 spaces is the default tab-width as defined in Qt and + // which is now used in the painting and cursor movement. + for (int n_spaces = 0; cur.pos() > 0 + && par.getChar(cur.pos() - 1) == ' ' && n_spaces < 8; + ++n_spaces) { + cur.posBackward(); + par.eraseChar(cur.pos(), buffer().params().trackChanges); + } + cur.finishUndo(); + } + break; default: InsetCollapsable::doDispatch(cur, cmd); break; @@ -307,6 +373,10 @@ 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: src/frontends/qt4/GuiFontMetrics.cpp =================================================================== --- src/frontends/qt4/GuiFontMetrics.cpp (revision 26320) +++ src/frontends/qt4/GuiFontMetrics.cpp (working copy) @@ -236,7 +236,7 @@ if (value != outOfLimitMetric) return value; - if (is_utf16(c)) + if (is_utf16(c) && c != '\t') value = metrics_.width(ucs4_to_qchar(c)); else value = metrics_.width(toqstr(docstring(1, c))); Index: src/Buffer.cpp =================================================================== --- src/Buffer.cpp (revision 26320) +++ src/Buffer.cpp (working copy) @@ -619,11 +619,8 @@ ++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: src/Lexer.cpp =================================================================== --- src/Lexer.cpp (revision 26320) +++ src/Lexer.cpp (working copy) @@ -499,7 +499,7 @@ 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 @@ buff.push_back(c); is.get(cc); c = cc; - } while (c >= ' ' && c != '\\' && is); + } while ((c >= ' ' || c == '\t') && c != '\\' && is); } if (c == '\\')