>> Pavel Sanda wrote:
>>
>> i just tried this patch and seems to work correctly.

Works fine for me too. Attached is the patch against current trunk.

>> if there are no other comments, i'll put it in.
>> lfuns will be sorted later.
>
> I wonder if something needs to be done on reversion to 1.5.x. IOW, is this a
> file format change?

This is not really a fileformat change. When you revert a listing to LyX 1.5, the TABs will be erased as LyX 1.5 doesn't support TABs. But what I can do is to try to convert the TABs via lyx2lyx to 4 spaces. Should I do this? If not, the patch should go in, if yes I'll try to provide a lyx2lyx patch.
Attached is a LyX testfile generated with the new TAB support to test lyx2lyx.

regards Uwe

Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(revision 26575)
+++ 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/insets/InsetListings.cpp
===================================================================
--- src/insets/InsetListings.cpp	(revision 26575)
+++ 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,87 @@
 	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 @@
 		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/Lexer.cpp
===================================================================
--- src/Lexer.cpp	(revision 26575)
+++ 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 == '\\')
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp	(revision 26575)
+++ src/Paragraph.cpp	(working copy)
@@ -2389,7 +2389,7 @@
 
 	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: src/ParagraphMetrics.cpp
===================================================================
--- src/ParagraphMetrics.cpp	(revision 26575)
+++ src/ParagraphMetrics.cpp	(working copy)
@@ -220,6 +220,9 @@
 
 	char_type c = par_->getChar(pos);
 
+	if (c == '\t')
+		return 4 * theFontMetrics(font).width(' ');
+	
 	if (!isPrintable(c))
 		return theFontMetrics(font).width(c);
 
Index: src/rowpainter.cpp
===================================================================
--- src/rowpainter.cpp	(revision 26575)
+++ src/rowpainter.cpp	(working copy)
@@ -246,6 +246,7 @@
 	// 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 @@
 
 		char_type c = par_.getChar(pos);
 
+		if (c == '\t' || prev_char == '\t') {
+			prev_char = c;
+			break;
+		}
+
 		if (!isPrintableNonspace(c))
 			break;
 
@@ -308,6 +314,9 @@
 
 	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;

Attachment: newfile2.lyx
Description: application/lyx

Reply via email to