Juergen Spitzmueller wrote:
> It is basically complete and already works. The feature is a dialog for
> InsetSpace similar to our VSpace dialog (bug 2078), which also merges HFill
> into InsetSpace (thus lets you switch between the diverse spaces and
> hfill). The boni are: support for \hspace and \hspace* (bug 2075), \dotfill
> and \hrulefill. Furthermore, it fixes bug 4555 (hfill drawing).
>
> The remaining problems are: one specific lyx2lyx reversion problem and some
> metrics problems (all non-fill spaces are drawn in the same width). I think
> these are trivial, I just need some time. I'll try to finish it at the
> weekend.

Here's the patch. Lyx2lyx works now, the metrics problem remains, and I'm 
stuck with that. Maybe someone has an idea.

Otherwise, objections?

Jürgen
Index: lib/lyx2lyx/LyX.py
===================================================================
--- lib/lyx2lyx/LyX.py	(Revision 23764)
+++ lib/lyx2lyx/LyX.py	(Arbeitskopie)
@@ -80,7 +80,7 @@
                    ("1_3",     [221], minor_versions("1.3" , 7)),
                    ("1_4", range(222,246), minor_versions("1.4" , 5)),
                    ("1_5", range(246,277), minor_versions("1.5" , 2)),
-                   ("1_6", range(277,319), minor_versions("1.6" , 0))]
+                   ("1_6", range(277,320), minor_versions("1.6" , 0))]
 
 
 def formats_list():
Index: lib/lyx2lyx/lyx_1_6.py
===================================================================
--- lib/lyx2lyx/lyx_1_6.py	(Revision 23764)
+++ lib/lyx2lyx/lyx_1_6.py	(Arbeitskopie)
@@ -1259,14 +1259,14 @@
             continue
         l = find_token(document.body, '\tsubcaptionText', i, j)
         caption = get_value(document.body, '\tsubcaptionText', i, j).strip('"')
-        savestr = document.body[i]
+        savebegin = document.body[i]
+        saveend = document.body[j]
+        document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + saveend
+        del document.body[k]
+        del document.body[l]
         document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
         'status open\n\n\\begin_layout PlainLayout\n\\begin_inset Caption\n\n\\begin_layout PlainLayout\n' \
-        + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n' + savestr
-        savestr = document.body[j]
-        document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
-        del document.body[k]
-        del document.body[l]
+        + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n' + savebegin
 
 
 def revert_subfig(document):
@@ -1388,6 +1388,53 @@
         return
     document.header.pop(i)
 
+
+def convert_hfill(document):
+    "Convert hfill to space inset"
+    i = 0
+    while True:
+        i = find_token(document.body, "\\hfill", i)
+        if i == -1:
+            return
+        document.body[i] = document.body[i].replace('\\hfill', '\\InsetSpace \\hfill{}')
+
+
+def revert_hfills(document):
+    'Revert \\hfill commands'
+    for i in range(len(document.body)):
+        document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
+        document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
+        '\\begin_inset ERT\nstatus collapsed\n\n' \
+        '\\begin_layout Standard\n\n\n\\backslash\n' \
+        'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
+        document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
+        '\\begin_inset ERT\nstatus collapsed\n\n' \
+        '\\begin_layout Standard\n\n\n\\backslash\n' \
+        'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
+
+
+def revert_hspace(document):
+    'Revert \\InsetSpace \\hspace{} to ERT'
+    i = 0
+    while True:
+        i = find_token(document.body, "\\InsetSpace \\hspace", i)
+        if i == -1:
+            return
+        length = get_value(document.body, '\\length', i+1)
+        if length == '':
+            document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
+            return
+        del document.body[i+1]
+        document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
+        '\\begin_inset ERT\nstatus collapsed\n\n' \
+        '\\begin_layout Standard\n\n\n\\backslash\n' \
+        'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
+        document.body[i] = document.body[i].replace('\\InsetSpace \\hspace{}', \
+        '\\begin_inset ERT\nstatus collapsed\n\n' \
+        '\\begin_layout Standard\n\n\n\\backslash\n' \
+        'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
+
+
 ##
 # Conversion hub
 #
@@ -1435,9 +1482,11 @@
            [316, [convert_subfig]],
            [317, []],
            [318, []],
+           [319, [convert_hfill]]
           ]
 
-revert =  [[317, [remove_extra_embedded_files]],
+revert =  [[318, [revert_hfills, revert_hspace]],
+           [317, [remove_extra_embedded_files]],
            [316, [revert_wrapplacement]],
            [315, [revert_subfig]],
            [314, [revert_colsep]],
Index: development/scons/scons_manifest.py
===================================================================
--- development/scons/scons_manifest.py	(Revision 23764)
+++ development/scons/scons_manifest.py	(Arbeitskopie)
@@ -734,6 +734,7 @@
     GuiFontLoader.h
     GuiGraphics.h
     GuiGraphicsUi.h
+    GuiHSpace.h
     GuiHyperlink.h
     GuiIdListModel.h
     GuiImage.h
@@ -822,6 +823,7 @@
     GuiFontLoader.cpp
     GuiFontMetrics.cpp
     GuiGraphics.cpp
+    GuiHSpace.cpp
     GuiHyperlink.cpp
     GuiIdListModel.cpp 
     GuiImage.cpp
@@ -905,6 +907,7 @@
     FloatUi.ui
     FontUi.ui
     GraphicsUi.ui
+    HSpaceUi.ui
     HyperlinkUi.ui
     IncludeUi.ui
     LabelUi.ui
@@ -990,7 +993,6 @@
     InsetFootlike.h
     InsetGraphics.h
     InsetGraphicsParams.h
-    InsetHFill.h
     InsetHyperlink.h
     InsetInclude.h
     InsetIndex.h
@@ -1047,7 +1049,6 @@
     InsetFootlike.cpp
     InsetGraphics.cpp
     InsetGraphicsParams.cpp
-    InsetHFill.cpp
     InsetHyperlink.cpp
     InsetInclude.cpp
     InsetIndex.cpp
Index: development/FORMAT
===================================================================
--- development/FORMAT	(Revision 23764)
+++ development/FORMAT	(Arbeitskopie)
@@ -1,6 +1,9 @@
 LyX file-format changes
 -----------------------
 
+2008-03-10 JÃŒrgen SpitzmÃŒller <[EMAIL PROTECTED]>
+	* Format incremented to 319: hspace and extended hfill support.
+
 2008-03-09 Bo Peng <[EMAIL PROTECTED]>
 	* Format incremented to 318: add \extra_embedded_files to buffer params
 
Index: src/LyXAction.cpp
===================================================================
--- src/LyXAction.cpp	(Revision 23764)
+++ src/LyXAction.cpp	(Arbeitskopie)
@@ -274,13 +274,6 @@
 		{ LFUN_FLOAT_WIDE_INSERT, "float-wide-insert", Noop, Edit },
 		{ LFUN_WRAP_INSERT, "wrap-insert", Noop, Edit },
 /*!
- * \var lyx::FuncCode lyx::LFUN_HFILL_INSERT
- * \li Action: Inserts an hfill inset.
- * \li Syntax: hfill-insert
- * \endvar
- */
-		{ LFUN_HFILL_INSERT, "hfill-insert", Noop, Edit },
-/*!
  * \var lyx::FuncCode lyx::LFUN_OPTIONAL_INSERT
  * \li Action: Inserts an optional-argument (short title) inset.
  * \li Syntax: optional-insert
Index: src/insets/InsetSpace.cpp
===================================================================
--- src/insets/InsetSpace.cpp	(Revision 23764)
+++ src/insets/InsetSpace.cpp	(Arbeitskopie)
@@ -15,7 +15,10 @@
 
 #include "InsetSpace.h"
 
+#include "Cursor.h"
 #include "Dimension.h"
+#include "FuncRequest.h"
+#include "Length.h"
 #include "Lexer.h"
 #include "MetricsInfo.h"
 #include "OutputParams.h"
@@ -25,6 +28,8 @@
 
 #include "support/debug.h"
 #include "support/docstream.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
 
 using namespace std;
 
@@ -35,44 +40,149 @@
 {}
 
 
-InsetSpace::InsetSpace(Kind k)
-	: kind_(k)
-{}
+InsetSpace::InsetSpace(InsetSpaceParams::Kind k)
+{
+	params_.kind = k;
+}
 
 
-InsetSpace::Kind InsetSpace::kind() const
+InsetSpaceParams::Kind InsetSpace::kind() const
 {
-	return kind_;
+	return params_.kind;
 }
 
 
+Length InsetSpace::length() const
+{
+	return params_.length;
+}
+
+
+InsetSpace::~InsetSpace()
+{
+	InsetSpaceMailer(*this).hideDialog();
+}
+
+
+docstring InsetSpace::toolTip(BufferView const &, int, int) const
+{
+	docstring message;
+	switch (params_.kind) {
+	case InsetSpaceParams::NORMAL:
+		message = _("Interword Space");
+		break;
+	case InsetSpaceParams::PROTECTED:
+		message = _("Protected Space");
+		break;
+	case InsetSpaceParams::THIN:
+		message = _("Thin Space");
+		break;
+	case InsetSpaceParams::QUAD:
+		message = _("Quad Space");
+		break;
+	case InsetSpaceParams::QQUAD:
+		message = _("QQuad Space");
+		break;
+	case InsetSpaceParams::ENSPACE:
+		message = _("Enspace");
+		break;
+	case InsetSpaceParams::ENSKIP:
+		message = _("Enskip");
+		break;
+	case InsetSpaceParams::NEGTHIN:
+		message = _("Negative Thin Space");
+		break;
+	case InsetSpaceParams::HFILL:
+		message = _("Horizontal Fill");
+		break;
+	case InsetSpaceParams::DOTFILL:
+		message = _("Horizontal Fill (Dots)");
+		break;
+	case InsetSpaceParams::HRULEFILL:
+		message = _("Horizontal Fill (Rule)");
+		break;
+	case InsetSpaceParams::CUSTOM:
+		message = support::bformat(_("Horizontal Space (%1$s)"),
+				params_.length.asDocstring());
+		break;
+	case InsetSpaceParams::CUSTOM_PROTECTED:
+		message = support::bformat(_("Protected Horizontal Space (%1$s)"),
+				params_.length.asDocstring());
+		break;
+	}
+	return message;
+}
+
+
+void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
+{
+	switch (cmd.action) {
+
+	case LFUN_INSET_MODIFY: {
+		InsetSpaceParams params;
+		InsetSpaceMailer::string2params(to_utf8(cmd.argument()), params);
+		params_.kind = params.kind;
+		params_.length = params.length;
+		break;
+	}
+
+	case LFUN_MOUSE_RELEASE:
+		if (!cur.selection())
+			InsetSpaceMailer(*this).showDialog(&cur.bv());
+		break;
+
+	default:
+		Inset::doDispatch(cur, cmd);
+		break;
+	}
+}
+
+
 void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
 {
+	if (params_.kind == InsetSpaceParams::HFILL ||
+	    params_.kind == InsetSpaceParams::DOTFILL ||
+	    params_.kind == InsetSpaceParams::HRULEFILL) {
+		// The metrics for this kinds are calculated externally in
+		// \c TextMetrics::computeRowMetrics. Those are dummy value:
+		dim = Dimension(10, 10, 10);
+		return;
+	}
+
 	frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
 	dim.asc = fm.maxAscent();
 	dim.des = fm.maxDescent();
 
-	switch (kind_) {
-		case THIN:
-		case NEGTHIN:
-		    dim.wid = fm.width(char_type('M')) / 6;
+	switch (params_.kind) {
+		case InsetSpaceParams::THIN:
+		case InsetSpaceParams::NEGTHIN:
+			dim.wid = fm.width(char_type('M')) / 6;
 			break;
-		case PROTECTED:
-		case NORMAL:
-		    dim.wid = fm.width(char_type(' '));
+		case InsetSpaceParams::PROTECTED:
+		case InsetSpaceParams::NORMAL:
+			dim.wid = fm.width(char_type(' '));
 			break;
-		case QUAD:
+		case InsetSpaceParams::QUAD:
 			dim.wid = fm.width(char_type('M'));
 			break;
-		case QQUAD:
+		case InsetSpaceParams::QQUAD:
 			dim.wid = 2 * fm.width(char_type('M'));
 			break;
-		case ENSPACE:
-		case ENSKIP:
+		case InsetSpaceParams::ENSPACE:
+		case InsetSpaceParams::ENSKIP:
 			dim.wid = int(0.5 * fm.width(char_type('M')));
 			break;
+		case InsetSpaceParams::CUSTOM:
+		case InsetSpaceParams::CUSTOM_PROTECTED:
+			dim.wid = params_.length.inBP();
+			break;
+		case InsetSpaceParams::HFILL:
+		case InsetSpaceParams::DOTFILL:
+		case InsetSpaceParams::HRULEFILL:
+			// shut up compiler
+			break;
 	}
-	// Cache the inset dimension. 
+	// Cache the inset dimension.
 	setDimCache(mi, dim);
 }
 
@@ -80,14 +190,44 @@
 void InsetSpace::draw(PainterInfo & pi, int x, int y) const
 {
 	Dimension const dim = dimension(*pi.base.bv);
+
+	if (params_.kind == InsetSpaceParams::HFILL ||
+	    params_.kind == InsetSpaceParams::DOTFILL ||
+	    params_.kind == InsetSpaceParams::HRULEFILL) {
+		int const asc = theFontMetrics(pi.base.font).ascent('M');
+		int const desc = theFontMetrics(pi.base.font).descent('M');
+		int const x0 = x + 1;
+		int const x1 = x + dim.wid - 2;
+		int const y0 = y + desc;
+		int const y1 = y - asc;
+		int const y2 = y - asc / 2;
+
+		if (params_.kind == InsetSpaceParams::HFILL) {
+			pi.pain.line(x0, y1, x0, y0, Color_added_space);
+			pi.pain.line(x0, y2 , x1, y2, Color_added_space,
+				frontend::Painter::line_onoffdash);
+			pi.pain.line(x1, y1, x1, y0, Color_added_space);
+		} else if (params_.kind == InsetSpaceParams::DOTFILL) {
+			pi.pain.line(x0, y1, x0, y0, Color_special);
+			pi.pain.line(x0, y, x1, y, Color_special,
+				frontend::Painter::line_onoffdash);
+			pi.pain.line(x1, y1, x1, y0, Color_special);
+		} if (params_.kind == InsetSpaceParams::HRULEFILL) {
+			pi.pain.line(x0, y1, x0, y0, Color_special);
+			pi.pain.line(x0, y, x1, y, Color_special);
+			pi.pain.line(x1, y1, x1, y0, Color_special);
+		}
+		return;
+	}
+
 	int const w = dim.wid;
-	int const h = theFontMetrics(pi.base.font)
-		.ascent('x');
+	int const h = theFontMetrics(pi.base.font).ascent('x');
 	int xp[4], yp[4];
 
 	xp[0] = x;
 	yp[0] = y - max(h / 4, 1);
-	if (kind_ == NORMAL || kind_ == PROTECTED) {
+	if (params_.kind == InsetSpaceParams::NORMAL ||
+	    params_.kind == InsetSpaceParams::PROTECTED) {
 		xp[1] = x;     yp[1] = y;
 		xp[2] = x + w; yp[2] = y;
 	} else {
@@ -97,99 +237,174 @@
 	xp[3] = x + w;
 	yp[3] = y - max(h / 4, 1);
 
-	if (kind_ == PROTECTED || kind_ == ENSPACE || kind_ == NEGTHIN)
+	if (params_.kind == InsetSpaceParams::PROTECTED ||
+	    params_.kind == InsetSpaceParams::ENSPACE ||
+	    params_.kind == InsetSpaceParams::NEGTHIN ||
+	    params_.kind == InsetSpaceParams::CUSTOM_PROTECTED)
 		pi.pain.lines(xp, yp, 4, Color_latex);
 	else
 		pi.pain.lines(xp, yp, 4, Color_special);
 }
 
 
-void InsetSpace::write(ostream & os) const
+void InsetSpaceParams::write(ostream & os) const
 {
 	string command;
-	switch (kind_) {
-	case NORMAL:
-		command = "\\space{}";
+	switch (kind) {
+	case InsetSpaceParams::NORMAL:
+		os << "\\space{}\n";
 		break;
-	case PROTECTED:
-		command = "~";
+	case InsetSpaceParams::PROTECTED:
+		os <<  "~\n";
 		break;
-	case THIN:
-		command = "\\thinspace{}";
+	case InsetSpaceParams::THIN:
+		os <<  "\\thinspace{}\n";
 		break;
-	case QUAD:
-		command = "\\quad{}";
+	case InsetSpaceParams::QUAD:
+		os <<  "\\quad{}\n";
 		break;
-	case QQUAD:
-		command = "\\qquad{}";
+	case InsetSpaceParams::QQUAD:
+		os <<  "\\qquad{}\n";
 		break;
-	case ENSPACE:
-		command = "\\enspace{}";
+	case InsetSpaceParams::ENSPACE:
+		os <<  "\\enspace{}\n";
 		break;
-	case ENSKIP:
-		command = "\\enskip{}";
+	case InsetSpaceParams::ENSKIP:
+		os <<  "\\enskip{}\n";
 		break;
-	case NEGTHIN:
-		command = "\\negthinspace{}";
+	case InsetSpaceParams::NEGTHIN:
+		os <<  "\\negthinspace{}\n";
 		break;
+	case InsetSpaceParams::HFILL:
+		os <<  "\\hfill{}\n";
+		break;
+	case InsetSpaceParams::DOTFILL:
+		os <<  "\\dotfill{}\n";
+		break;
+	case InsetSpaceParams::HRULEFILL:
+		os <<  "\\hrulefill{}\n";
+		break;
+	case InsetSpaceParams::CUSTOM:
+		os <<  "\\hspace{}\n";
+		break;
+	case InsetSpaceParams::CUSTOM_PROTECTED:
+		os <<  "\\hspace*{}\n";
+		break;
 	}
-	os << "\\InsetSpace " << command << "\n";
+	
+	if (!length.empty())
+		os << "\\length " << length.asString() << "\n";
 }
 
 
-void InsetSpace::read(Lexer & lex)
+void InsetSpaceParams::read(Lexer & lex)
 {
 	lex.next();
 	string const command = lex.getString();
 
 	if (command == "\\space{}")
-		kind_ = NORMAL;
+		kind = InsetSpaceParams::NORMAL;
 	else if (command == "~")
-		kind_ = PROTECTED;
+		kind = InsetSpaceParams::PROTECTED;
 	else if (command == "\\thinspace{}")
-		kind_ = THIN;
+		kind = InsetSpaceParams::THIN;
 	else if (command == "\\quad{}")
-		kind_ = QUAD;
+		kind = InsetSpaceParams::QUAD;
 	else if (command == "\\qquad{}")
-		kind_ = QQUAD;
+		kind = InsetSpaceParams::QQUAD;
 	else if (command == "\\enspace{}")
-		kind_ = ENSPACE;
+		kind = InsetSpaceParams::ENSPACE;
 	else if (command == "\\enskip{}")
-		kind_ = ENSKIP;
+		kind = InsetSpaceParams::ENSKIP;
 	else if (command == "\\negthinspace{}")
-		kind_ = NEGTHIN;
+		kind = InsetSpaceParams::NEGTHIN;
+	else if (command == "\\hfill{}")
+		kind = InsetSpaceParams::HFILL;
+	else if (command == "\\dotfill{}")
+		kind = InsetSpaceParams::DOTFILL;
+	else if (command == "\\hrulefill{}")
+		kind = InsetSpaceParams::HRULEFILL;
+	else if (command == "\\hspace{}")
+		kind = InsetSpaceParams::CUSTOM;
+	else if (command == "\\hspace*{}")
+		kind = InsetSpaceParams::CUSTOM_PROTECTED;
 	else
 		lex.printError("InsetSpace: Unknown kind: `$$Token'");
+
+
+	string token;
+	lex >> token;
+	if (token == "\\length") {
+		lex.next();
+		string const len = lex.getString();
+		length = Length(len);
+	} else
+		// take countermeasures
+		lex.pushToken(token);
 }
 
 
+void InsetSpace::write(ostream & os) const
+{
+	os << "\n\\InsetSpace ";
+	params_.write(os);
+}
+
+
+void InsetSpace::read(Lexer & lex)
+{
+	params_.read(lex);
+}
+
+
 int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const
 {
-	switch (kind_) {
-	case NORMAL:
+	switch (params_.kind) {
+	case InsetSpaceParams::NORMAL:
 		os << (runparams.free_spacing ? " " : "\\ ");
 		break;
-	case PROTECTED:
+	case InsetSpaceParams::PROTECTED:
 		os << (runparams.free_spacing ? ' ' : '~');
 		break;
-	case THIN:
+	case InsetSpaceParams::THIN:
 		os << (runparams.free_spacing ? " " : "\\,");
 		break;
-	case QUAD:
+	case InsetSpaceParams::QUAD:
 		os << (runparams.free_spacing ? " " : "\\quad{}");
 		break;
-	case QQUAD:
+	case InsetSpaceParams::QQUAD:
 		os << (runparams.free_spacing ? " " : "\\qquad{}");
 		break;
-	case ENSPACE:
+	case InsetSpaceParams::ENSPACE:
 		os << (runparams.free_spacing ? " " : "\\enspace{}");
 		break;
-	case ENSKIP:
+	case InsetSpaceParams::ENSKIP:
 		os << (runparams.free_spacing ? " " : "\\enskip{}");
 		break;
-	case NEGTHIN:
+	case InsetSpaceParams::NEGTHIN:
 		os << (runparams.free_spacing ? " " : "\\negthinspace{}");
 		break;
+	case InsetSpaceParams::HFILL:
+		os << (runparams.free_spacing ? " " : "\\hfill{}");
+		break;
+	case InsetSpaceParams::DOTFILL:
+		os << (runparams.free_spacing ? " " : "\\dotfill{}");
+		break;
+	case InsetSpaceParams::HRULEFILL:
+		os << (runparams.free_spacing ? " " : "\\hrulefill{}");
+		break;
+	case InsetSpaceParams::CUSTOM:
+		if (runparams.free_spacing)
+			os << " ";
+		else
+			os << "\\hspace{" << from_ascii(params_.length.asLatexString()) << "}";
+		break;
+	case InsetSpaceParams::CUSTOM_PROTECTED:
+		if (runparams.free_spacing)
+			os << " ";
+		else
+			os << "\\hspace*{" << from_ascii(params_.length.asLatexString()) << "}";
+		break;
 	}
 	return 0;
 }
@@ -197,26 +412,50 @@
 
 int InsetSpace::plaintext(odocstream & os, OutputParams const &) const
 {
-	os << ' ';
-	return 1;
+	switch (params_.kind) {
+	case InsetSpaceParams::HFILL:
+		os << "     ";
+		return 5;
+	case InsetSpaceParams::DOTFILL:
+		os << ".....";
+		return 5;
+	case InsetSpaceParams::HRULEFILL:
+		os << "_____";
+		return 5;
+	default:
+		os << ' ';
+		return 1;
+	}
 }
 
 
 int InsetSpace::docbook(odocstream & os, OutputParams const &) const
 {
-	switch (kind_) {
-	case NORMAL:
-	case QUAD:
-	case QQUAD:
-	case ENSKIP:
+	switch (params_.kind) {
+	case InsetSpaceParams::NORMAL:
+	case InsetSpaceParams::QUAD:
+	case InsetSpaceParams::QQUAD:
+	case InsetSpaceParams::ENSKIP:
 		os << " ";
 		break;
-	case PROTECTED:
-	case ENSPACE:
-	case THIN:
-	case NEGTHIN:
+	case InsetSpaceParams::PROTECTED:
+	case InsetSpaceParams::ENSPACE:
+	case InsetSpaceParams::THIN:
+	case InsetSpaceParams::NEGTHIN:
 		os << "&nbsp;";
 		break;
+	case InsetSpaceParams::HFILL:
+		os << '\n';
+	case InsetSpaceParams::DOTFILL:
+		// FIXME
+		os << '\n';
+	case InsetSpaceParams::HRULEFILL:
+		// FIXME
+		os << '\n';
+	case InsetSpaceParams::CUSTOM:
+	case InsetSpaceParams::CUSTOM_PROTECTED:
+		// FIXME
+		os << '\n';
 	}
 	return 0;
 }
@@ -228,4 +467,54 @@
 }
 
 
+bool InsetSpace::isStretchableSpace() const
+{
+	return (params_.kind == InsetSpaceParams::HFILL ||
+		params_.kind == InsetSpaceParams::DOTFILL ||
+		params_.kind == InsetSpaceParams::HRULEFILL);
+}
+
+
+string const InsetSpaceMailer::name_ = "space";
+
+
+InsetSpaceMailer::InsetSpaceMailer(InsetSpace & inset)
+	: inset_(inset)
+{}
+
+
+string const InsetSpaceMailer::inset2string(Buffer const &) const
+{
+	return params2string(inset_.params());
+}
+
+
+void InsetSpaceMailer::string2params(string const & in, InsetSpaceParams & params)
+{
+	params = InsetSpaceParams();
+	if (in.empty())
+		return;
+
+	istringstream data(in);
+	Lexer lex(0,0);
+	lex.setStream(data);
+
+	string name;
+	lex >> name;
+	if (!lex || name != name_)
+		return print_mailer_error("InsetSpaceMailer", in, 1, name_);
+
+	params.read(lex);
+}
+
+
+string const InsetSpaceMailer::params2string(InsetSpaceParams const & params)
+{
+	ostringstream data;
+	data << name_ << ' ';
+	params.write(data);
+	return data.str();
+}
+
+
 } // namespace lyx
Index: src/insets/Inset.cpp
===================================================================
--- src/insets/Inset.cpp	(Revision 23764)
+++ src/insets/Inset.cpp	(Arbeitskopie)
@@ -93,7 +93,6 @@
 		InsetName("nomencl_print", NOMENCL_PRINT_CODE),
 		InsetName("optarg", OPTARG_CODE),
 		InsetName("environment", ENVIRONMENT_CODE),
-		InsetName("hfill", HFILL_CODE),
 		InsetName("newline", NEWLINE_CODE),
 		InsetName("line", LINE_CODE),
 		InsetName("branch", BRANCH_CODE),
Index: src/insets/InsetSpace.h
===================================================================
--- src/insets/InsetSpace.h	(Revision 23764)
+++ src/insets/InsetSpace.h	(Arbeitskopie)
@@ -17,16 +17,16 @@
 
 
 #include "Inset.h"
+#include "Length.h"
+#include "MailInset.h"
 
 
 namespace lyx {
 
 class LaTeXFeatures;
 
-///  Used to insert different kinds of spaces
-class InsetSpace : public Inset {
+class InsetSpaceParams {
 public:
-
 	/// The different kinds of spaces we support
 	enum Kind {
 		/// Normal space ('\ ')
@@ -44,18 +44,50 @@
 		/// \enspace (0.5em breakable)
 		ENSKIP,
 		/// Negative thin space ('\negthinspace')
-		NEGTHIN
+		NEGTHIN,
+		/// rubber length
+		HFILL,
+		/// rubber length, filled with dots
+		DOTFILL,
+		/// rubber length, filled with a rule
+		HRULEFILL,
+		/// \hspace{length}
+		CUSTOM,
+		/// \hspace*{length}
+		CUSTOM_PROTECTED
 	};
+	///
+	InsetSpaceParams() : kind(NORMAL), length(Length()) {}
+	///
+	void write(std::ostream & os) const;
+	///
+	void read(Lexer & lex);
+	///
+	Kind kind;
+	///
+	Length length;
+};
 
+///  Used to insert different kinds of spaces
+class InsetSpace : public Inset {
+public:
 	///
 	InsetSpace();
+	///
+	~InsetSpace();
 
 	///
 	explicit
-	InsetSpace(Kind k);
+	InsetSpace(InsetSpaceParams::Kind k);
 	///
-	Kind kind() const;
+	InsetSpaceParams params() const { return params_; }
 	///
+	InsetSpaceParams::Kind kind() const;
+	///
+	Length length() const;
+	///
+	docstring toolTip(BufferView const & bv, int x, int y) const;
+	///
 	void metrics(MetricsInfo &, Dimension &) const;
 	///
 	void draw(PainterInfo & pi, int x, int y) const;
@@ -75,6 +107,8 @@
 	InsetCode lyxCode() const { return SPACE_CODE; }
 	/// We don't need \begin_inset and \end_inset
 	bool directWrite() const { return true; }
+	/// is this an expandible space (rubber length)?
+	bool isStretchableSpace() const;
 
 	// should this inset be handled like a normal charater
 	bool isChar() const { return true; }
@@ -85,12 +119,36 @@
 	bool isSpace() const { return true; }
 private:
 	virtual Inset * clone() const { return new InsetSpace(*this); }
+	///
+	void doDispatch(Cursor & cur, FuncRequest & cmd);
 
-	/// And which kind is this?
-	Kind kind_;
+	///
+	InsetSpaceParams params_;
 };
 
 
+class InsetSpaceMailer : public MailInset {
+public:
+	///
+	InsetSpaceMailer(InsetSpace & inset);
+	///
+	virtual Inset & inset() const { return inset_; }
+	///
+	virtual std::string const & name() const { return name_; }
+	///
+	virtual std::string const inset2string(Buffer const &) const;
+	///
+	static void string2params(std::string const &, InsetSpaceParams &);
+	///
+	static std::string const params2string(InsetSpaceParams const &);
+private:
+	///
+	static std::string const name_;
+	///
+	InsetSpace & inset_;
+};
+
+
 } // namespace lyx
 
 #endif // INSET_SPACE_H
Index: src/insets/InsetHFill.h
===================================================================
--- src/insets/InsetHFill.h	(Revision 23764)
+++ src/insets/InsetHFill.h	(Arbeitskopie)
@@ -1,59 +0,0 @@
-// -*- C++ -*-
-/**
- * \file InsetHFill.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef INSET_HFILL_H
-#define INSET_HFILL_H
-
-
-#include "InsetCommand.h"
-
-
-namespace lyx {
-
-class InsetHFill : public InsetCommand {
-public:
-	///
-	InsetHFill();
-	///
-	void metrics(MetricsInfo &, Dimension &) const;
-	///
-	void draw(PainterInfo & pi, int x, int y) const;
-	///
-	docstring screenLabel() const;
-	///
-	InsetCode lyxCode() const { return HFILL_CODE; }
-	///
-	int plaintext(odocstream &, OutputParams const &) const;
-	///
-	int docbook(odocstream &, OutputParams const &) const;
-	///
-	void write(std::ostream & os) const;
-	/// We don't need \begin_inset and \end_inset
-	bool directWrite() const { return true; }
-	/// is this equivalent to a space (which is BTW different from
-	// a line separator)?
-	bool isSpace() const;
-	///
-	static ParamInfo const & findInfo(std::string const &);
-	///
-	static std::string defaultCommand() { return "hfill"; };
-	///
-	static bool isCompatibleCommand(std::string const & s) 
-		{ return s == "hfill"; }
-private:
-	///
-	Inset * clone() const { return new InsetHFill(*this); }
-};
-
-
-} // namespace lyx
-
-#endif
Index: src/insets/Inset.h
===================================================================
--- src/insets/Inset.h	(Revision 23764)
+++ src/insets/Inset.h	(Arbeitskopie)
@@ -381,6 +381,8 @@
 	/// is this equivalent to a space (which is BTW different from
 	/// a line separator)?
 	virtual bool isSpace() const { return false; }
+	/// is this an expandible space (rubber length)?
+	virtual bool isStretchableSpace() const { return false; }
 
 	enum DisplayType {
 		Inline = 0,
Index: src/insets/InsetHFill.cpp
===================================================================
--- src/insets/InsetHFill.cpp	(Revision 23764)
+++ src/insets/InsetHFill.cpp	(Arbeitskopie)
@@ -1,95 +0,0 @@
-/**
- * \file InsetHFill.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author André Pönitz
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "InsetHFill.h"
-
-#include "MetricsInfo.h"
-
-#include "frontends/Painter.h"
-
-#include "support/gettext.h"
-
-#include <ostream>
-
-using namespace std;
-
-namespace lyx {
-
-
-InsetHFill::InsetHFill()
-	: InsetCommand(InsetCommandParams(HFILL_CODE), string())
-{}
-
-
-ParamInfo const & InsetHFill::findInfo(string const & /* cmdName */)
-{
-	static ParamInfo param_info_;
-	return param_info_;
-}
-
-
-void InsetHFill::metrics(MetricsInfo &, Dimension & dim) const
-{
-	// The metrics for this inset are calculated externally in
-	// \c TextMetrics::computeRowMetrics. Those are dummy value:
-	dim = Dimension(10, 10, 10);
-}
-
-
-void InsetHFill::draw(PainterInfo & pi, int x, int y) const
-{
-	Dimension const dim = Inset::dimension(*pi.base.bv);
-	int const x0 = x + 1;
-	int const x1 = x + dim.wid - 2;
-	int const y0 = y + dim.des - 1;
-	int const y1 = y - dim.asc + 1;
-
-	pi.pain.line(x0, y1, x0, y0, Color_added_space);
-	pi.pain.line(x0, y, x1, y, Color_added_space,
-		frontend::Painter::line_onoffdash);
-	pi.pain.line(x1, y1, x1, y0, Color_added_space);
-}
-
-
-docstring InsetHFill::screenLabel() const
-{
-	return _("Horizontal Fill");
-}
-
-
-int InsetHFill::plaintext(odocstream & os, OutputParams const &) const
-{
-	os << "     ";
-	return 5;
-}
-
-
-int InsetHFill::docbook(odocstream & os, OutputParams const &) const
-{
-	os << '\n';
-	return 0;
-}
-
-
-void InsetHFill::write(ostream & os) const
-{
-	os << "\n\\hfill\n";
-}
-
-
-bool InsetHFill::isSpace() const
-{
-	return true;
-}
-
-
-} // namespace lyx
Index: src/insets/InsetCode.h
===================================================================
--- src/insets/InsetCode.h	(Revision 23764)
+++ src/insets/InsetCode.h	(Arbeitskopie)
@@ -87,21 +87,19 @@
 	///
 	ENVIRONMENT_CODE,
 	///
-	HFILL_CODE,
+	NEWLINE_CODE,
 	///
-	NEWLINE_CODE, // 35
+	LINE_CODE, // 35
 	///
-	LINE_CODE,
-	///
 	BRANCH_CODE,
 	///
 	BOX_CODE,
 	///
 	FLEX_CODE,
 	///
-	VSPACE_CODE, // 40
+	VSPACE_CODE,
 	///
-	MATHMACROARG_CODE,
+	MATHMACROARG_CODE, // 40
 	///
 	NOMENCL_CODE,
 	///
@@ -109,9 +107,9 @@
 	///
 	NEWPAGE_CODE,
 	///
-	LISTINGS_CODE, // 45
+	LISTINGS_CODE,
 	///
-	INFO_CODE,
+	INFO_CODE, // 45
 	///
 	COLLAPSABLE_CODE,
 #if 0
Index: src/insets/InsetCollapsable.cpp
===================================================================
--- src/insets/InsetCollapsable.cpp	(Revision 23764)
+++ src/insets/InsetCollapsable.cpp	(Arbeitskopie)
@@ -704,7 +704,6 @@
 	case LFUN_FONT_STATE:
 	case LFUN_FONT_UNDERLINE:
 	case LFUN_FOOTNOTE_INSERT:
-	case LFUN_HFILL_INSERT:
 	case LFUN_HYPERLINK_INSERT:
 	case LFUN_INDEX_INSERT:
 	case LFUN_INDEX_PRINT:
Index: src/insets/InsetCommandParams.cpp
===================================================================
--- src/insets/InsetCommandParams.cpp	(Revision 23764)
+++ src/insets/InsetCommandParams.cpp	(Arbeitskopie)
@@ -18,7 +18,6 @@
 #include "InsetBibtex.h"
 #include "InsetCitation.h"
 #include "InsetFloatList.h"
-#include "InsetHFill.h"
 #include "InsetHyperlink.h"
 #include "InsetInclude.h"
 #include "InsetIndex.h"
@@ -149,8 +148,6 @@
 		return InsetCitation::findInfo(cmdName);	
 	case FLOAT_LIST_CODE:
 		return InsetFloatList::findInfo(cmdName);
-	case HFILL_CODE:
-		return InsetHFill::findInfo(cmdName);
 	case HYPERLINK_CODE:
 		return InsetHyperlink::findInfo(cmdName);
 	case INCLUDE_CODE:
@@ -191,8 +188,6 @@
 			return InsetCitation::defaultCommand();
 		case FLOAT_LIST_CODE:
 			return InsetFloatList::defaultCommand();
-		case HFILL_CODE:
-			return InsetHFill::defaultCommand();
 		case HYPERLINK_CODE:
 			return InsetHyperlink::defaultCommand();
 		case INCLUDE_CODE:
@@ -228,8 +223,6 @@
 			return InsetCitation::isCompatibleCommand(s);
 		case FLOAT_LIST_CODE:
 			return InsetFloatList::isCompatibleCommand(s);
-		case HFILL_CODE:
-			return InsetHFill::isCompatibleCommand(s);
 		case HYPERLINK_CODE:
 			return InsetHyperlink::isCompatibleCommand(s);
 		case INCLUDE_CODE:
Index: src/TextMetrics.cpp
===================================================================
--- src/TextMetrics.cpp	(Revision 23764)
+++ src/TextMetrics.cpp	(Arbeitskopie)
@@ -626,7 +626,8 @@
 	InsetList::const_iterator iend = par.insetList().end();
 	for ( ; ii != iend; ++ii) {
 		if (ii->pos >= endpos || ii->pos < row.pos()
-			|| ii->inset->lyxCode() != HFILL_CODE)
+			|| (ii->inset->lyxCode() != SPACE_CODE &&
+			    ii->inset->isStretchableSpace()))
 			continue;
 		Dimension dim = row.dimension();
 		if (pm.hfillExpansion(row, ii->pos))
Index: src/Text.cpp
===================================================================
--- src/Text.cpp	(Revision 23764)
+++ src/Text.cpp	(Arbeitskopie)
@@ -52,7 +52,6 @@
 #include "insets/InsetText.h"
 #include "insets/InsetBibitem.h"
 #include "insets/InsetCaption.h"
-#include "insets/InsetHFill.h"
 #include "insets/InsetLine.h"
 #include "insets/InsetNewline.h"
 #include "insets/InsetNewpage.h"
@@ -240,8 +239,6 @@
 		auto_ptr<Inset> inset(new InsetTabular(buf));
 		inset->read(lex);
 		par.insertInset(par.size(), inset.release(), font, change);
-	} else if (token == "\\hfill") {
-		par.insertInset(par.size(), new InsetHFill, font, change);
 	} else if (token == "\\lyxline") {
 		par.insertInset(par.size(), new InsetLine, font, change);
 	} else if (token == "\\newpage") {
Index: src/frontends/qt4/GuiHSpace.h
===================================================================
--- src/frontends/qt4/GuiHSpace.h	(Revision 0)
+++ src/frontends/qt4/GuiHSpace.h	(Revision 0)
@@ -0,0 +1,60 @@
+// -*- C++ -*-
+/**
+ * \file GuiHSpace.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef GUIHSPACE_H
+#define GUIHSPACE_H
+
+#include "GuiDialog.h"
+#include "ui_HSpaceUi.h"
+#include "insets/InsetSpace.h"
+
+namespace lyx {
+namespace frontend {
+
+class GuiHSpace : public GuiDialog, public Ui::HSpaceUi
+{
+	Q_OBJECT
+
+public:
+	GuiHSpace(GuiView & lv);
+
+private Q_SLOTS:
+	///
+	void change_adaptor();
+	///
+	void enableWidgets(int);
+
+private:
+	/// Apply from dialog
+	void applyView();
+	/// Update the dialog
+	void updateContents();
+	///
+	bool isValid();
+	///
+	bool initialiseParams(std::string const & data);
+	/// clean-up on hide.
+	void clearParams();
+	/// clean-up on hide.
+	void dispatchParams();
+	///
+	bool isBufferDependent() const { return true; }
+	///
+	bool inInset() const;
+
+	///
+	InsetSpaceParams params_;
+};
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // GUIHSPACE_H
Index: src/frontends/qt4/GuiView.cpp
===================================================================
--- src/frontends/qt4/GuiView.cpp	(Revision 23764)
+++ src/frontends/qt4/GuiView.cpp	(Arbeitskopie)
@@ -2015,7 +2015,7 @@
 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print", 
-"ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
+"ref", "sendto", "space", "spellchecker", "symbols", "tabular", "tabularcreate",
 
 #ifdef HAVE_LIBAIKSAURUS
 "thesaurus",
@@ -2219,6 +2219,7 @@
 Dialog * createGuiExternal(GuiView & lv);
 Dialog * createGuiFloat(GuiView & lv);
 Dialog * createGuiGraphics(GuiView & lv);
+Dialog * createGuiHSpace(GuiView & lv);
 Dialog * createGuiInclude(GuiView & lv);
 Dialog * createGuiLabel(GuiView & lv);
 Dialog * createGuiListings(GuiView & lv);
@@ -2308,6 +2309,8 @@
 		return createGuiRef(*this);
 	if (name == "sendto")
 		return createGuiSendTo(*this);
+	if (name == "space")
+		return createGuiHSpace(*this);
 	if (name == "spellchecker")
 		return createGuiSpellchecker(*this);
 	if (name == "symbols")
Index: src/frontends/qt4/Makefile.am
===================================================================
--- src/frontends/qt4/Makefile.am	(Revision 23764)
+++ src/frontends/qt4/Makefile.am	(Arbeitskopie)
@@ -84,6 +84,7 @@
 	GuiFontLoader.cpp \
 	GuiFontMetrics.cpp \
 	GuiGraphics.cpp \
+	GuiHSpace.cpp \
 	GuiHyperlink.cpp \
 	GuiIdListModel.cpp \
 	GuiImage.cpp \
@@ -179,6 +180,7 @@
 	GuiExternal.h \
 	GuiFloat.h \
 	GuiGraphics.h \
+	GuiHSpace.h \
 	GuiHyperlink.h \
 	GuiInclude.h \
 	GuiLabel.h \
@@ -244,6 +246,7 @@
 	FloatUi.ui \
 	FontUi.ui \
 	GraphicsUi.ui \
+	HSpaceUi.ui \
 	HyperlinkUi.ui \
 	IncludeUi.ui \
 	LabelUi.ui \
Index: src/frontends/qt4/ui/HSpaceUi.ui
===================================================================
--- src/frontends/qt4/ui/HSpaceUi.ui	(Revision 0)
+++ src/frontends/qt4/ui/HSpaceUi.ui	(Revision 0)
@@ -0,0 +1,287 @@
+<ui version="4.0" >
+ <class>HSpaceUi</class>
+ <widget class="QDialog" name="HSpaceUi" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>263</width>
+    <height>198</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string/>
+  </property>
+  <property name="sizeGripEnabled" >
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="3" column="1" >
+    <widget class="QCheckBox" name="keepCB" >
+     <property name="toolTip" >
+      <string>Insert the spacing even after a line break</string>
+     </property>
+     <property name="text" >
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" >
+    <widget class="QLabel" name="fillPatternL" >
+     <property name="text" >
+      <string>&amp;Fill Pattern:</string>
+     </property>
+     <property name="buddy" >
+      <cstring>fillPatternCO</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" >
+    <widget class="QComboBox" name="fillPatternCO" >
+     <property name="toolTip" >
+      <string>Select a fill pattern style for HFills</string>
+     </property>
+     <item>
+      <property name="text" >
+       <string>None</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>...............</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>________</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="0" column="0" >
+    <widget class="QLabel" name="spacingL" >
+     <property name="text" >
+      <string>&amp;Spacing:</string>
+     </property>
+     <property name="buddy" >
+      <cstring>spacingCO</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="3" column="0" >
+    <widget class="QLabel" name="keepL" >
+     <property name="toolTip" >
+      <string/>
+     </property>
+     <property name="text" >
+      <string>&amp;Protect:</string>
+     </property>
+     <property name="buddy" >
+      <cstring>keepCB</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="4" column="1" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="5" column="0" colspan="3" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="okPB" >
+       <property name="text" >
+        <string>&amp;OK</string>
+       </property>
+       <property name="autoDefault" >
+        <bool>false</bool>
+       </property>
+       <property name="default" >
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="applyPB" >
+       <property name="text" >
+        <string>&amp;Apply</string>
+       </property>
+       <property name="autoDefault" >
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="closePB" >
+       <property name="text" >
+        <string>&amp;Close</string>
+       </property>
+       <property name="autoDefault" >
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="0" column="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="2" >
+    <widget class="LengthCombo" native="1" name="unitCO" />
+   </item>
+   <item row="0" column="1" >
+    <widget class="QComboBox" name="spacingCO" >
+     <property name="toolTip" >
+      <string>Supported spacing types</string>
+     </property>
+     <item>
+      <property name="text" >
+       <string>Inter-word space</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Thin space</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Negative thin space</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Enspace (0.5 em)</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Quad (1 em)</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>QQuad (2 em)</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Horizontal Fill</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Custom</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="1" column="1" >
+    <widget class="QLineEdit" name="valueLE" >
+     <property name="enabled" >
+      <bool>false</bool>
+     </property>
+     <property name="toolTip" >
+      <string>Custom value. Needs spacing type "Custom".</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" >
+    <widget class="QLabel" name="valueL" >
+     <property name="text" >
+      <string>&amp;Value:</string>
+     </property>
+     <property name="buddy" >
+      <cstring>valueLE</cstring>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>LengthCombo</class>
+   <extends>QWidget</extends>
+   <header>LengthCombo.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>spacingCO</tabstop>
+  <tabstop>valueLE</tabstop>
+  <tabstop>unitCO</tabstop>
+  <tabstop>okPB</tabstop>
+  <tabstop>applyPB</tabstop>
+  <tabstop>closePB</tabstop>
+  <tabstop>keepCB</tabstop>
+ </tabstops>
+ <includes>
+  <include location="local" >qt_helpers.h</include>
+ </includes>
+ <resources/>
+ <connections/>
+</ui>
Index: src/frontends/qt4/GuiHSpace.cpp
===================================================================
--- src/frontends/qt4/GuiHSpace.cpp	(Revision 0)
+++ src/frontends/qt4/GuiHSpace.cpp	(Revision 0)
@@ -0,0 +1,267 @@
+/**
+ * \file GuiHSpace.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "GuiHSpace.h"
+
+#include "LengthCombo.h"
+#include "qt_helpers.h"
+#include "Validator.h"
+
+#include "LyXRC.h"
+#include "Spacing.h"
+#include "FuncRequest.h"
+#include "insets/InsetSpace.h"
+
+#include "support/gettext.h"
+#include "support/lstrings.h"
+
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QValidator>
+
+using namespace std;
+
+namespace lyx {
+namespace frontend {
+
+GuiHSpace::GuiHSpace(GuiView & lv)
+	: GuiDialog(lv, "space", qt_("Horizontal Space Settings"))
+{
+	setupUi(this);
+
+	connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
+	connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
+	connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
+
+	connect(spacingCO, SIGNAL(highlighted(QString)),
+		this, SLOT(change_adaptor()));
+	connect(valueLE, SIGNAL(textChanged(QString)),
+		this, SLOT(change_adaptor()));
+	connect(spacingCO, SIGNAL(activated(int)),
+		this, SLOT(enableWidgets(int)));
+	connect(keepCB, SIGNAL(clicked()),
+		this, SLOT(change_adaptor()));
+	connect(unitCO, SIGNAL(selectionChanged(lyx::Length::UNIT)),
+		this, SLOT(change_adaptor()));
+	connect(fillPatternCO, SIGNAL(activated(int)),
+		this, SLOT(change_adaptor()));
+
+	valueLE->setValidator(unsignedLengthValidator(valueLE));
+
+	// Manage the ok, apply, restore and cancel/close buttons
+	bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
+	bc().setOK(okPB);
+	bc().setApply(applyPB);
+	bc().setCancel(closePB);
+
+	// disable for read-only documents
+	bc().addReadOnly(spacingCO);
+	bc().addReadOnly(valueLE);
+	bc().addReadOnly(unitCO);
+	bc().addReadOnly(keepCB);
+	bc().addReadOnly(fillPatternCO);
+
+	// initialize the length validator
+	bc().addCheckedLineEdit(valueLE, valueL);
+
+	// remove the %-items from the unit choice
+	unitCO->noPercents();
+}
+
+
+void GuiHSpace::change_adaptor()
+{
+	changed();
+}
+
+
+void GuiHSpace::enableWidgets(int selection)
+{
+	valueLE->setEnabled(selection == 7);
+	unitCO->setEnabled(selection == 7);
+	fillPatternCO->setEnabled(selection == 6);
+	bool const enable_keep =
+		selection == 0 || selection == 3  || selection == 7;
+	keepCB->setEnabled(enable_keep);
+}
+
+
+static void setWidgetsFromHSpace(InsetSpaceParams const & params,
+			  QComboBox * spacing,
+			  QLineEdit * value,
+			  LengthCombo * unit,
+			  QCheckBox * keep,
+			  QComboBox * fillPattern)
+{
+	int item = 0;
+	int pattern = 0;
+	bool protect = false;
+	switch (params.kind) {
+		case InsetSpaceParams::NORMAL:
+			item = 0;
+			break;
+		case InsetSpaceParams::PROTECTED:
+			item = 0;
+			protect = true;
+			break;
+		case InsetSpaceParams::THIN:
+			item = 1;
+			break;
+		case InsetSpaceParams::NEGTHIN:
+			item = 2;
+			break;
+		case InsetSpaceParams::ENSKIP:
+			item = 3;
+			break;
+		case InsetSpaceParams::ENSPACE:
+			item = 3;
+			protect = true;
+			break;
+		case InsetSpaceParams::QUAD:
+			item = 4;
+			break;
+		case InsetSpaceParams::QQUAD:
+			item = 5;
+			break;
+		case InsetSpaceParams::HFILL:
+			item = 6;
+			break;
+		case InsetSpaceParams::DOTFILL:
+			item = 6;
+			pattern = 1;
+			break;
+		case InsetSpaceParams::HRULEFILL:
+			item = 6;
+			pattern = 2;
+			break;
+		case InsetSpaceParams::CUSTOM:
+			item = 7;
+			break;
+		case InsetSpaceParams::CUSTOM_PROTECTED:
+			item = 7;
+			protect = true;
+			break;
+	}
+	spacing->setCurrentIndex(item);
+	fillPattern->setCurrentIndex(pattern);
+	keep->setChecked(protect);
+
+	Length::UNIT default_unit =
+			(lyxrc.default_papersize > 3) ? Length::CM : Length::IN;
+	if (item == 7)
+		lengthToWidgets(value, unit, params.length, default_unit);
+	else
+		lengthToWidgets(value, unit, "", default_unit);
+}
+
+
+static InsetSpaceParams setHSpaceFromWidgets(int spacing,
+	QLineEdit * value, LengthCombo * unit, bool keep, int fill)
+{
+	InsetSpaceParams params;
+	switch (spacing) {
+		case 0:
+			if (keep)
+				params.kind = InsetSpaceParams::PROTECTED;
+			else
+				params.kind = InsetSpaceParams::NORMAL;
+			break;
+		case 1:
+			params.kind = InsetSpaceParams::THIN;
+			break;
+		case 2:
+			params.kind = InsetSpaceParams::NEGTHIN;
+			break;
+		case 3:
+			if (keep)
+				params.kind = InsetSpaceParams::ENSPACE;
+			else
+				params.kind = InsetSpaceParams::ENSKIP;
+			break;
+		case 4:
+			params.kind = InsetSpaceParams::QUAD;
+			break;
+		case 5:
+			params.kind = InsetSpaceParams::QQUAD;
+			break;
+		case 6:
+			if (fill == 1)
+				params.kind = InsetSpaceParams::DOTFILL;
+			else if (fill == 2)
+				params.kind = InsetSpaceParams::HRULEFILL;
+			else
+				params.kind = InsetSpaceParams::HFILL;
+			break;
+		case 7:
+			if (keep)
+				params.kind = InsetSpaceParams::CUSTOM_PROTECTED;
+			else
+				params.kind = InsetSpaceParams::CUSTOM;
+			params.length = Length(widgetsToLength(value, unit));
+			break;
+	}
+	return params;
+}
+
+
+void GuiHSpace::applyView()
+{
+	params_ = setHSpaceFromWidgets(spacingCO->currentIndex(),
+			valueLE, unitCO, keepCB->isChecked(),
+			fillPatternCO->currentIndex());
+}
+
+
+void GuiHSpace::updateContents()
+{
+	setWidgetsFromHSpace(params_, spacingCO, valueLE, unitCO, keepCB,
+		fillPatternCO);
+	enableWidgets(spacingCO->currentIndex());
+}
+
+
+bool GuiHSpace::initialiseParams(string const & data)
+{
+	InsetSpaceMailer::string2params(data, params_);
+	setButtonsValid(true);
+
+	return true;
+}
+
+
+void GuiHSpace::clearParams()
+{
+	params_ = InsetSpaceParams();
+}
+
+
+void GuiHSpace::dispatchParams()
+{
+	dispatch(FuncRequest(getLfun(), InsetSpaceMailer::params2string(params_)));
+}
+
+
+bool GuiHSpace::isValid()
+{
+	return (spacingCO->currentIndex() != 7 || !valueLE->text().isEmpty());
+}
+
+
+Dialog * createGuiHSpace(GuiView & lv) { return new GuiHSpace(lv); }
+
+
+} // namespace frontend
+} // namespace lyx
+
+
+#include "GuiHSpace_moc.cpp"
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(Revision 23764)
+++ src/Makefile.am	(Arbeitskopie)
@@ -503,7 +503,6 @@
 	insets/InsetFootlike.cpp \
 	insets/InsetGraphicsParams.cpp \
 	insets/InsetGraphics.cpp \
-	insets/InsetHFill.cpp \
 	insets/InsetHyperlink.cpp \
 	insets/InsetInclude.cpp \
 	insets/InsetIndex.cpp \
@@ -559,7 +558,6 @@
 	insets/InsetFootlike.h \
 	insets/InsetGraphicsParams.h \
 	insets/InsetGraphics.h \
-	insets/InsetHFill.h \
 	insets/InsetHyperlink.h \
 	insets/InsetInclude.h \
 	insets/InsetIndex.h \
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp	(Revision 23764)
+++ src/Paragraph.cpp	(Arbeitskopie)
@@ -2239,7 +2239,8 @@
 bool Paragraph::isHfill(pos_type pos) const
 {
 	Inset const * inset = getInset(pos);
-	return inset && inset->lyxCode() == HFILL_CODE;
+	return inset && (inset->lyxCode() == SPACE_CODE &&
+			 inset->isStretchableSpace());
 }
 
 
Index: src/factory.cpp
===================================================================
--- src/factory.cpp	(Revision 23764)
+++ src/factory.cpp	(Arbeitskopie)
@@ -33,7 +33,6 @@
 #include "insets/InsetFloatList.h"
 #include "insets/InsetFoot.h"
 #include "insets/InsetGraphics.h"
-#include "insets/InsetHFill.h"
 #include "insets/InsetInclude.h"
 #include "insets/InsetIndex.h"
 #include "insets/InsetInfo.h"
@@ -82,8 +81,6 @@
 	try {
 
 		switch (cmd.action) {
-		case LFUN_HFILL_INSERT:
-			return new InsetHFill;
 
 		case LFUN_LINE_INSERT:
 			return new InsetLine;
@@ -322,21 +319,31 @@
 		case LFUN_SPACE_INSERT: {
 			string const name = to_utf8(cmd.argument());
 			if (name == "normal")
-				return new InsetSpace(InsetSpace::NORMAL);
+				return new InsetSpace(InsetSpaceParams::NORMAL);
 			if (name == "protected")
-				return new InsetSpace(InsetSpace::PROTECTED);
+				return new InsetSpace(InsetSpaceParams::PROTECTED);
 			if (name == "thin")
-				return new InsetSpace(InsetSpace::THIN);
+				return new InsetSpace(InsetSpaceParams::THIN);
 			if (name == "quad")
-				return new InsetSpace(InsetSpace::QUAD);
+				return new InsetSpace(InsetSpaceParams::QUAD);
 			if (name == "qquad")
-				return new InsetSpace(InsetSpace::QQUAD);
+				return new InsetSpace(InsetSpaceParams::QQUAD);
 			if (name == "enspace")
-				return new InsetSpace(InsetSpace::ENSPACE);
+				return new InsetSpace(InsetSpaceParams::ENSPACE);
 			if (name == "enskip")
-				return new InsetSpace(InsetSpace::ENSKIP);
+				return new InsetSpace(InsetSpaceParams::ENSKIP);
 			if (name == "negthinspace")
-				return new InsetSpace(InsetSpace::NEGTHIN);
+				return new InsetSpace(InsetSpaceParams::NEGTHIN);
+			if (name == "hfill")
+				return new InsetSpace(InsetSpaceParams::HFILL);
+			if (name == "dotfill")
+				return new InsetSpace(InsetSpaceParams::DOTFILL);
+			if (name == "hrulefill")
+				return new InsetSpace(InsetSpaceParams::HRULEFILL);
+			if (name == "custom")
+				return new InsetSpace(InsetSpaceParams::CUSTOM);
+			if (name == "custom*")
+				return new InsetSpace(InsetSpaceParams::CUSTOM_PROTECTED);
 			if (name.empty())
 				lyxerr << "LyX function 'space' needs an argument." << endl;
 			else
Index: src/Text3.cpp
===================================================================
--- src/Text3.cpp	(Revision 23764)
+++ src/Text3.cpp	(Arbeitskopie)
@@ -1408,7 +1408,6 @@
 	case LFUN_INDEX_PRINT:
 	case LFUN_NOMENCL_PRINT:
 	case LFUN_TOC_INSERT:
-	case LFUN_HFILL_INSERT:
 	case LFUN_LINE_INSERT:
 	case LFUN_NEWPAGE_INSERT:
 	case LFUN_PAGEBREAK_INSERT:
@@ -1966,7 +1965,6 @@
 		// always allow this, since we will inset a raw quote
 		// if an inset is not allowed.
 		break;
-	case LFUN_HFILL_INSERT:
 	case LFUN_SPECIALCHAR_INSERT:
 		code = SPECIALCHAR_CODE;
 		break;
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(Revision 23764)
+++ src/Buffer.cpp	(Arbeitskopie)
@@ -116,7 +116,7 @@
 
 namespace {
 
-int const LYX_FORMAT = 318;
+int const LYX_FORMAT = 319;
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;

Reply via email to