]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/FormParagraph.C
doxygen fixes
[lyx.git] / src / frontends / xforms / FormParagraph.C
index da150ee707b24ff4751e8625d4b27d7ebb866fc7..dd5c4bb3151dffefeb08cf3fbbb08a50fb836d95 100644 (file)
@@ -1,13 +1,10 @@
-/* This file is part of
- * ======================================================
- * 
- *           LyX, The Document Processor
- *      
- *           Copyright 2000-2001 The LyX Team.
+/**
+ * \file FormParagraph.C
+ * Copyright 2000-2001 The LyX Team.
+ * See the file COPYING.
  *
- *           @author Jürgen Vigna
- *
- *======================================================*/
+ * \author Jürgen Vigna, jug@sad.it
+ */
 
 #include <config.h>
 
 #include "FormParagraph.h"
 #include "form_paragraph.h"
 #include "Dialogs.h"
-#include "support/lstrings.h" 
 #include "Liason.h"
 #include "LyXView.h"
 #include "buffer.h"
 #include "lyxtext.h"
 #include "xforms_helpers.h"
+#include "lyxrc.h" // to set the deafult length values
 #include "BufferView.h"
+#include "lyxtextclasslist.h"
 #include "Spacing.h"
 #include "ParagraphParameters.h"
 #include "input_validators.h"
+#include "helper_funcs.h"
+
+#include "support/lstrings.h"
+
+#include <functional>
 
 using Liason::setMinibuffer;
 using SigC::slot;
+using std::vector;
+using std::bind2nd;
+using std::remove_if;
 
 
 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
@@ -62,13 +68,7 @@ void FormParagraph::disconnect()
 
 Paragraph const * FormParagraph::getCurrentParagraph() const
 {
-       LyXText * text = 0;
-
-       if (lv_->view()->theLockingInset())
-               text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
-       if (!text)
-               text = lv_->view()->text;
-       return text->cursor.par();
+       return lv_->view()->getLyXText()->cursor.par();
 }
 
 
@@ -79,6 +79,12 @@ void FormParagraph::changedParagraph()
        if (p == 0 || p == par_)
                return;
 
+       // OBS FIX LOOK HERE
+
+       // shouldn't we chage the par_ pointer too?
+       // anyway for me the below function does just nothing!
+       // (Jug 20020108)
+
        // For now don't bother checking if the params are different,
        // just activate the Apply button
        bc().valid();
@@ -87,14 +93,8 @@ void FormParagraph::changedParagraph()
 
 void FormParagraph::redraw()
 {
-       if( form() && form()->visible )
-               fl_redraw_form( form() );
-       else
-               return;
-
-       FL_FORM * outer_form = fl_get_active_folder(dialog_->tabbed_folder);
-       if (outer_form && outer_form->visible)
-               fl_redraw_form( outer_form );
+       if (form() && form()->visible)
+               fl_redraw_form(form());
 }
 
 
@@ -108,86 +108,84 @@ FL_FORM * FormParagraph::form() const
 void FormParagraph::build()
 {
     // the tabbed folder
-    dialog_.reset(build_tabbed_paragraph());
+    dialog_.reset(build_paragraph());
 
-    // Manage the ok, apply, restore and cancel/close buttons
-    bc_.setOK(dialog_->button_ok);
-    bc_.setApply(dialog_->button_apply);
-    bc_.setCancel(dialog_->button_cancel);
-    bc_.setRestore(dialog_->button_restore);
-
-    // the general paragraph data form
-    general_.reset(build_paragraph_general());
-
-    fl_addto_choice(general_->choice_space_above,
+    fl_addto_choice(dialog_->choice_space_above,
                    _(" None | Defskip | Smallskip "
                      "| Medskip | Bigskip | VFill | Length "));
-    fl_addto_choice(general_->choice_space_below,
+    fl_addto_choice(dialog_->choice_space_below,
                    _(" None | Defskip | Smallskip "
                      "| Medskip | Bigskip | VFill | Length ")); 
 
-    fl_addto_choice(general_->choice_linespacing,
+    fl_addto_choice(dialog_->choice_linespacing,
                     _(" Default | Single | OneHalf | Double | Other "));
  
-    fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
-    fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
-    fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
-
-    bc_.addReadOnly (general_->group_radio_alignment);
-    // bc_.addReadOnly (general_->radio_align_right);
-    // bc_.addReadOnly (general_->radio_align_left);
-    // bc_.addReadOnly (general_->radio_align_block);
-    // bc_.addReadOnly (general_->radio_align_center);
-    bc_.addReadOnly (general_->check_lines_top);
-    bc_.addReadOnly (general_->check_lines_bottom);
-    bc_.addReadOnly (general_->check_pagebreaks_top);
-    bc_.addReadOnly (general_->check_pagebreaks_bottom);
-    bc_.addReadOnly (general_->choice_space_above);
-    bc_.addReadOnly (general_->input_space_above);
-    bc_.addReadOnly (general_->check_space_above);
-    bc_.addReadOnly (general_->choice_space_below);
-    bc_.addReadOnly (general_->input_space_below);
-    bc_.addReadOnly (general_->check_space_below);
-    bc_.addReadOnly (general_->choice_linespacing);
-    bc_.addReadOnly (general_->input_linespacing); 
-    bc_.addReadOnly (general_->check_noindent);
-    bc_.addReadOnly (general_->input_labelwidth);
-
-    fl_set_input_filter(general_->input_linespacing, fl_unsigned_float_filter);
-    // now make them fit together
-    fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
-}
-
+    fl_set_input_return(dialog_->input_space_above, FL_RETURN_CHANGED);
+    fl_set_input_return(dialog_->input_space_below, FL_RETURN_CHANGED);
+    fl_set_input_return(dialog_->input_labelwidth, FL_RETURN_CHANGED);
+    fl_set_input_return(dialog_->input_linespacing, FL_RETURN_CHANGED);
+    fl_set_input_filter(dialog_->input_linespacing, fl_unsigned_float_filter);
+
+    setPrehandler(dialog_->input_space_above);
+    setPrehandler(dialog_->input_space_below);
+    setPrehandler(dialog_->input_labelwidth);
+    setPrehandler(dialog_->input_linespacing);
+
+    // Create the contents of the unit choices
+    // Don't include the "%" terms...
+    vector<string> units_vec = getLatexUnits();
+#if 0
+    for (vector<string>::iterator it = units_vec.begin();
+       it != units_vec.end(); ++it) {
+       if (contains(*it, "%"))
+               it = units_vec.erase(it, it+1) - 1;
+    }
+#else
+    // Something similar to this is a better way to erase
+    vector<string>::iterator del =
+           remove_if(units_vec.begin(), units_vec.end(),
+                     bind2nd(contains_functor(), "%"));
+    units_vec.erase(del, units_vec.end());
+#endif
+    
+    string units = getStringFromVector(units_vec, "|");
 
-void FormParagraph::apply()
-{
-    if (!lv_->view()->available() || !dialog_.get())
-       return;
+    fl_addto_choice(dialog_->choice_value_space_above,  units.c_str());
+    fl_addto_choice(dialog_->choice_value_space_below, units.c_str());
 
-    general_apply();
+    // Manage the ok, apply, restore and cancel/close buttons
+    bc_.setOK(dialog_->button_ok);
+    bc_.setApply(dialog_->button_apply);
+    bc_.setCancel(dialog_->button_cancel);
+    bc_.setRestore(dialog_->button_restore);
 
-    lv_->view()->update(lv_->view()->text, 
-                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
-    lv_->buffer()->markDirty();
-    setMinibuffer(lv_, _("Paragraph layout set"));
+    bc_.addReadOnly (dialog_->group_radio_alignment);
+    // bc_.addReadOnly (dialog_->radio_align_right);
+    // bc_.addReadOnly (dialog_->radio_align_left);
+    // bc_.addReadOnly (dialog_->radio_align_block);
+    // bc_.addReadOnly (dialog_->radio_align_center);
+    bc_.addReadOnly (dialog_->check_lines_top);
+    bc_.addReadOnly (dialog_->check_lines_bottom);
+    bc_.addReadOnly (dialog_->check_pagebreaks_top);
+    bc_.addReadOnly (dialog_->check_pagebreaks_bottom);
+    bc_.addReadOnly (dialog_->choice_space_above);
+    bc_.addReadOnly (dialog_->input_space_above);
+    bc_.addReadOnly (dialog_->check_space_above);
+    bc_.addReadOnly (dialog_->choice_space_below);
+    bc_.addReadOnly (dialog_->input_space_below);
+    bc_.addReadOnly (dialog_->check_space_below);
+    bc_.addReadOnly (dialog_->choice_linespacing);
+    bc_.addReadOnly (dialog_->input_linespacing); 
+    bc_.addReadOnly (dialog_->check_noindent);
+    bc_.addReadOnly (dialog_->input_labelwidth);
 }
 
 
-void FormParagraph::update()
+void FormParagraph::apply()
 {
-    if (!dialog_.get())
-        return;
-
-    // Do this first; some objects may be de/activated subsequently.
-    bc_.readOnly(lv_->buffer()->isReadonly());
-
-    general_update();
-}
-
+    if (!lv_->view()->available() || !dialog_.get())
+       return;
 
-void FormParagraph::general_apply()
-{
     VSpace space_top, space_bottom;
     LyXAlignment align;
     string labelwidthstring;
@@ -195,23 +193,23 @@ void FormParagraph::general_apply()
 
     // If a vspace kind is "Length" but there's no text in
     // the input field, reset the kind to "None". 
-    if ((fl_get_choice (general_->choice_space_above) == 7) &&
-       !*(fl_get_input (general_->input_space_above)))
+    if ((fl_get_choice (dialog_->choice_space_above) == 7) &&
+       !*(fl_get_input (dialog_->input_space_above)))
     {
-       fl_set_choice (general_->choice_space_above, 1);
+       fl_set_choice (dialog_->choice_space_above, 1);
     }
-    if ((fl_get_choice (general_->choice_space_below) == 7) &&
-       !*(fl_get_input (general_->input_space_below)))
+    if ((fl_get_choice (dialog_->choice_space_below) == 7) &&
+       !*(fl_get_input (dialog_->input_space_below)))
     {
-       fl_set_choice (general_->choice_space_below, 1);
+       fl_set_choice (dialog_->choice_space_below, 1);
     }
    
-    bool line_top = fl_get_button(general_->check_lines_top);
-    bool line_bottom = fl_get_button(general_->check_lines_bottom);
-    bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
-    bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
+    bool line_top = fl_get_button(dialog_->check_lines_top);
+    bool line_bottom = fl_get_button(dialog_->check_lines_bottom);
+    bool pagebreak_top = fl_get_button(dialog_->check_pagebreaks_top);
+    bool pagebreak_bottom = fl_get_button(dialog_->check_pagebreaks_bottom);
     
-    switch (fl_get_choice (general_->choice_space_above)) {
+    switch (fl_get_choice (dialog_->choice_space_above)) {
     case 1:
        space_top = VSpace(VSpace::NONE);
        break;
@@ -231,13 +229,19 @@ void FormParagraph::general_apply()
        space_top = VSpace(VSpace::VFILL);
        break;
     case 7:
+    {
+           string const length =
+                   getLengthFromWidgets(dialog_->input_space_above,
+                                        dialog_->choice_value_space_above);
        space_top =
-               VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
+               VSpace(LyXGlueLength(length));
        break;
     }
-    if (fl_get_button (general_->check_space_above))
+    }
+
+    if (fl_get_button (dialog_->check_space_above))
        space_top.setKeep (true);
-    switch (fl_get_choice (general_->choice_space_below)) {
+    switch (fl_get_choice (dialog_->choice_space_below)) {
     case 1:
        space_bottom = VSpace(VSpace::NONE);
        break;
@@ -257,248 +261,287 @@ void FormParagraph::general_apply()
        space_bottom = VSpace(VSpace::VFILL);
        break;
     case 7:
-       space_bottom =
-               VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
+       string const length =
+               getLengthFromWidgets(dialog_->input_space_below,
+                                    dialog_->choice_value_space_below);
+       space_bottom = VSpace(LyXGlueLength(length));
        break;
     }
-    if (fl_get_button (general_->check_space_below))
+    if (fl_get_button (dialog_->check_space_below))
        space_bottom.setKeep (true);
 
-    if (fl_get_button(general_->radio_align_left))
+    if (fl_get_button(dialog_->radio_align_left))
        align = LYX_ALIGN_LEFT;
-    else if (fl_get_button(general_->radio_align_right))
+    else if (fl_get_button(dialog_->radio_align_right))
        align = LYX_ALIGN_RIGHT;
-    else if (fl_get_button(general_->radio_align_center))
+    else if (fl_get_button(dialog_->radio_align_center))
        align = LYX_ALIGN_CENTER;
     else 
        align = LYX_ALIGN_BLOCK;
    
-    labelwidthstring = fl_get_input(general_->input_labelwidth);
-    noindent = fl_get_button(general_->check_noindent);
-    Spacing::Space linespacing;
+    labelwidthstring = fl_get_input(dialog_->input_labelwidth);
+    noindent = fl_get_button(dialog_->check_noindent);
+    Spacing::Space linespacing = Spacing::Default;
     string other_linespacing;
-    switch (fl_get_choice(general_->choice_linespacing)) {
+    switch (fl_get_choice(dialog_->choice_linespacing)) {
         case 1: linespacing = Spacing::Default; break;
         case 2: linespacing = Spacing::Single; break;
         case 3: linespacing = Spacing::Onehalf; break;
         case 4: linespacing = Spacing::Double; break;
         case 5:
             linespacing = Spacing::Other;
-            other_linespacing = fl_get_input(general_->input_linespacing);
+            other_linespacing = fl_get_input(dialog_->input_linespacing);
             break;
     }
 
     Spacing const spacing(linespacing, other_linespacing);
-    LyXText * text = 0;
-    if (lv_->view()->theLockingInset())
-       text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
-    if (!text)
-       text = lv_->view()->text;
+    LyXText * text(lv_->view()->getLyXText());
     text->setParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
                       pagebreak_bottom, space_top, space_bottom, spacing,
                        align, labelwidthstring, noindent);
+
+
+    // Actually apply these settings
+    lv_->view()->update(text, 
+                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
+    lv_->buffer()->markDirty();
+    setMinibuffer(lv_, _("Paragraph layout set"));
 }
 
 
-void FormParagraph::general_update()
+void FormParagraph::update()
 {
-    if (!general_.get())
+    if (!dialog_.get())
         return;
 
+    // Do this first; some objects may be de/activated subsequently.
+    bc_.readOnly(lv_->buffer()->isReadonly());
+
     Buffer * buf = lv_->view()->buffer();
 
     /// Record the paragraph
     par_ = getCurrentParagraph();
 
-    fl_set_input(general_->input_labelwidth,
+    fl_set_input(dialog_->input_labelwidth,
                 par_->getLabelWidthString().c_str());
-    fl_set_button(general_->radio_align_right, 0);
-    fl_set_button(general_->radio_align_left, 0);
-    fl_set_button(general_->radio_align_center, 0);
-    fl_set_button(general_->radio_align_block, 0);
+    setEnabled(dialog_->input_labelwidth,
+              (par_->getLabelWidthString() != _("Senseless with this layout!")));
+
+    fl_set_button(dialog_->radio_align_right, 0);
+    fl_set_button(dialog_->radio_align_left, 0);
+    fl_set_button(dialog_->radio_align_center, 0);
+    fl_set_button(dialog_->radio_align_block, 0);
 
+    LyXTextClass const & tclass = textclasslist[buf->params.textclass];
+    
     int align = par_->getAlign();
     if (align == LYX_ALIGN_LAYOUT)
-       align = textclasslist.Style(buf->params.textclass,
-                                   par_->getLayout()).align;
+           align = tclass[par_->layout()].align;
 
     switch (align) {
     case LYX_ALIGN_RIGHT:
-       fl_set_button(general_->radio_align_right, 1);
+       fl_set_button(dialog_->radio_align_right, 1);
        break;
     case LYX_ALIGN_LEFT:
-       fl_set_button(general_->radio_align_left, 1);
+       fl_set_button(dialog_->radio_align_left, 1);
        break;
     case LYX_ALIGN_CENTER:
-       fl_set_button(general_->radio_align_center, 1);
+       fl_set_button(dialog_->radio_align_center, 1);
        break;
     default:
-       fl_set_button(general_->radio_align_block, 1);
+       fl_set_button(dialog_->radio_align_block, 1);
        break;
     }
 
-    LyXAlignment alignpos =
-           textclasslist.Style(buf->params.textclass,
-                               par_->getLayout()).alignpossible;
+    LyXAlignment alignpos = tclass[par_->layout()].alignpossible;
 
-    setEnabled(general_->radio_align_block,  bool(alignpos & LYX_ALIGN_BLOCK));
-    setEnabled(general_->radio_align_center, bool(alignpos & LYX_ALIGN_CENTER));
-    setEnabled(general_->radio_align_left,   bool(alignpos & LYX_ALIGN_LEFT));
-    setEnabled(general_->radio_align_right,  bool(alignpos & LYX_ALIGN_RIGHT));
+    setEnabled(dialog_->radio_align_block,  bool(alignpos & LYX_ALIGN_BLOCK));
+    setEnabled(dialog_->radio_align_center, bool(alignpos & LYX_ALIGN_CENTER));
+    setEnabled(dialog_->radio_align_left,   bool(alignpos & LYX_ALIGN_LEFT));
+    setEnabled(dialog_->radio_align_right,  bool(alignpos & LYX_ALIGN_RIGHT));
     
-    fl_set_button(general_->check_lines_top,
+    // no inset-text-owned paragraph may have pagebreaks
+    setEnabled(dialog_->check_pagebreaks_top, !par_->inInset());
+    setEnabled(dialog_->check_pagebreaks_bottom, !par_->inInset());
+
+    fl_set_button(dialog_->check_lines_top,
                  par_->params().lineTop());
-    fl_set_button(general_->check_lines_bottom,
+    fl_set_button(dialog_->check_lines_bottom,
                  par_->params().lineBottom());
-    fl_set_button(general_->check_pagebreaks_top,
+    fl_set_button(dialog_->check_pagebreaks_top,
                  par_->params().pagebreakTop());
-    fl_set_button(general_->check_pagebreaks_bottom,
+    fl_set_button(dialog_->check_pagebreaks_bottom,
                  par_->params().pagebreakBottom());
-    fl_set_button(general_->check_noindent,
+    fl_set_button(dialog_->check_noindent,
                  par_->params().noindent());
 
     int linespacing;
-    Spacing space = par_->params().spacing();
-
-    /* 
-    switch (lv_->buffer()->params.spacing.getSpace()) {
-        case Spacing::Default: linespacing = 1; break;
-        case Spacing::Single: linespacing = 2; break;
-        case Spacing::Onehalf: linespacing = 3; break;
-        case Spacing::Double: linespacing = 4; break;
-        case Spacing::Other: linespacing = 5; break;
-    }
-    */
+    Spacing const space = par_->params().spacing();
 
     switch (space.getSpace()) {
-        case Spacing::Default: linespacing = 1; break;
+        default: linespacing = 1; break;
         case Spacing::Single: linespacing = 2; break;
         case Spacing::Onehalf: linespacing = 3; break;
         case Spacing::Double: linespacing = 4; break;
         case Spacing::Other: linespacing = 5; break;
     }
-    fl_set_choice(general_->choice_linespacing, linespacing);
+    fl_set_choice(dialog_->choice_linespacing, linespacing);
     if (space.getSpace() == Spacing::Other) {
-        string sp;
-        
-        if (space.getSpace() == Spacing::Default)
-            sp = tostr(lv_->buffer()->params.spacing.getValue());
-        else 
-            sp = tostr(space.getValue());
-        fl_set_input(general_->input_linespacing, sp.c_str());
-        setEnabled(general_->input_linespacing, true);
+        string const sp = tostr(space.getValue());
+        fl_set_input(dialog_->input_linespacing, sp.c_str());
+        setEnabled(dialog_->input_linespacing, true);
     } else {
-        fl_set_input(general_->input_linespacing, "");
-        setEnabled(general_->input_linespacing, false);
+        fl_set_input(dialog_->input_linespacing, "");
+        setEnabled(dialog_->input_linespacing, false);
     }
 
-    fl_set_input (general_->input_space_above, "");
+    fl_set_input (dialog_->input_space_above, "");
 
+    setEnabled(dialog_->input_space_above, false);
+    setEnabled(dialog_->choice_value_space_above, false);
     switch (par_->params().spaceTop().kind()) {
     case VSpace::NONE:
-       fl_set_choice (general_->choice_space_above, 1);
+       fl_set_choice (dialog_->choice_space_above, 1);
        break;
     case VSpace::DEFSKIP:
-       fl_set_choice (general_->choice_space_above, 2);
+       fl_set_choice (dialog_->choice_space_above, 2);
        break;
     case VSpace::SMALLSKIP:
-       fl_set_choice (general_->choice_space_above, 3);
+       fl_set_choice (dialog_->choice_space_above, 3);
        break;
     case VSpace::MEDSKIP:
-       fl_set_choice (general_->choice_space_above, 4);
+       fl_set_choice (dialog_->choice_space_above, 4);
        break;
     case VSpace::BIGSKIP:
-       fl_set_choice (general_->choice_space_above, 5);
+       fl_set_choice (dialog_->choice_space_above, 5);
        break;
     case VSpace::VFILL:
-       fl_set_choice (general_->choice_space_above, 6);
+       fl_set_choice (dialog_->choice_space_above, 6);
        break;
     case VSpace::LENGTH:
-       fl_set_choice (general_->choice_space_above, 7);
-       fl_set_input(general_->input_space_above, par_->
-                    params().spaceTop().length().asString().c_str());
+    {
+        fl_set_choice (dialog_->choice_space_above, 7);
+        setEnabled(dialog_->input_space_above, true);
+        setEnabled(dialog_->choice_value_space_above, true);
+        bool const metric = lyxrc.default_papersize > 3;
+        string const default_unit = metric ? "cm" : "in";
+        string const length = par_->params().spaceTop().length().asString();
+       updateWidgetsFromLengthString(dialog_->input_space_above,
+                                             dialog_->choice_value_space_above,
+                                             length, default_unit);
        break;
     }
+    }
     
-    fl_set_button (general_->check_space_above,
-                  par_->params().spaceTop().keep());
-    fl_set_input (general_->input_space_below, "");
+    fl_set_button (dialog_->check_space_above,
+           par_->params().spaceTop().keep());
+    fl_set_input (dialog_->input_space_below, "");
 
+    setEnabled(dialog_->input_space_below, false);
+    setEnabled(dialog_->choice_value_space_below, false);
     switch (par_->params().spaceBottom().kind()) {
     case VSpace::NONE:
-       fl_set_choice (general_->choice_space_below, 1);
+       fl_set_choice (dialog_->choice_space_below, 1);
        break;
     case VSpace::DEFSKIP:
-       fl_set_choice (general_->choice_space_below, 2);
+       fl_set_choice (dialog_->choice_space_below, 2);
        break;
     case VSpace::SMALLSKIP:
-       fl_set_choice (general_->choice_space_below, 3);
+       fl_set_choice (dialog_->choice_space_below, 3);
        break;
     case VSpace::MEDSKIP:
-       fl_set_choice (general_->choice_space_below, 4);
+       fl_set_choice (dialog_->choice_space_below, 4);
        break;
     case VSpace::BIGSKIP:
-       fl_set_choice (general_->choice_space_below, 5);
+       fl_set_choice (dialog_->choice_space_below, 5);
        break;
     case VSpace::VFILL:
-       fl_set_choice (general_->choice_space_below, 6);
+       fl_set_choice (dialog_->choice_space_below, 6);
        break;
     case VSpace::LENGTH:
-       fl_set_choice (general_->choice_space_below, 7);
-        fl_set_input(general_->input_space_below, par_->
-                    params().spaceBottom().length().asString().c_str());
+    {
+        fl_set_choice (dialog_->choice_space_below, 7);
+        setEnabled(dialog_->input_space_below, true);
+        setEnabled(dialog_->choice_value_space_below, true);
+        bool const metric = lyxrc.default_papersize > 3;
+        string const default_unit = metric ? "cm" : "in";
+        string const length =
+               par_->params().spaceBottom().length().asString();
+       updateWidgetsFromLengthString(dialog_->input_space_below,
+                                             dialog_->choice_value_space_below,
+                                             length, default_unit);
        break;
     }
-    fl_set_button(general_->check_space_below,
-                  par_->params().spaceBottom().keep());
-    fl_set_button(general_->check_noindent,
+    }
+
+    fl_set_button(dialog_->check_space_below,
+                 par_->params().spaceBottom().keep());
+    fl_set_button(dialog_->check_noindent,
                  par_->params().noindent());
 }
 
 
 bool FormParagraph::input(FL_OBJECT * ob, long)
 {
-    bool ret = true;
+    bool valid = true; 
 
     fl_hide_object(dialog_->text_warning);
 
     // First check the buttons which are exclusive and you have to
     // check only the actuall de/activated button.
     //
-    // general form first
-    //
     // "Synchronize" the choices and input fields, making it
     // impossible to commit senseless data.
 
-    if (fl_get_choice (general_->choice_space_above) != 7)
-        fl_set_input (general_->input_space_above, "");
-
-    if (fl_get_choice (general_->choice_space_below) != 7)
-        fl_set_input (general_->input_space_below, "");
-
-    if (fl_get_choice (general_->choice_linespacing) == 4)
-        setEnabled (general_->input_linespacing, true);
-    else {
-        setEnabled (general_->input_linespacing, false);
-        fl_set_input (general_->input_linespacing, "");
+    if (ob == dialog_->choice_space_above) {
+        if (fl_get_choice (dialog_->choice_space_above) != 7) {
+            fl_set_input (dialog_->input_space_above, "");
+            setEnabled (dialog_->input_space_above, false);
+            setEnabled (dialog_->choice_value_space_above, false);
+        } else {
+            setEnabled (dialog_->input_space_above, !lv_->buffer()->isReadonly());
+           setEnabled (dialog_->choice_value_space_above, !lv_->buffer()->isReadonly());
+           bool const metric = lyxrc.default_papersize > 3;
+           int const default_unit = metric ? 8 : 9;
+           if (strip(fl_get_input(dialog_->input_space_above)).empty())
+                fl_set_choice(dialog_->choice_value_space_above,
+                             default_unit);
+        }
+    }
+    if (ob == dialog_->choice_space_below) {
+        if (fl_get_choice (dialog_->choice_space_below) != 7) {
+            fl_set_input (dialog_->input_space_below, "");
+            setEnabled (dialog_->input_space_below, false);
+            setEnabled (dialog_->choice_value_space_below, false);
+        } else {
+            setEnabled (dialog_->input_space_below, !lv_->buffer()->isReadonly());
+           setEnabled (dialog_->choice_value_space_below, !lv_->buffer()->isReadonly());
+           bool const metric = lyxrc.default_papersize > 3;
+           int const default_unit = metric ? 8 : 9;
+           if (strip(fl_get_input(dialog_->input_space_below)).empty())
+                   fl_set_choice(dialog_->choice_value_space_below,
+                                 default_unit);
+        }
     }
  
     //
-    // first the general form
+    // warnings if input is senseless
     //
-    string input = fl_get_input (general_->input_space_above);
+    string input = fl_get_input (dialog_->input_space_above);
     bool invalid = false;
-       
-    if (fl_get_choice(general_->choice_space_above)==7)
-        invalid = !input.empty() && !isValidGlueLength(input);
 
-    input = fl_get_input (general_->input_space_below);
+    if (fl_get_choice(dialog_->choice_space_above)==7)
+        invalid = !input.empty() && !isValidGlueLength(input) && !isStrDbl(input);
 
-    if (fl_get_choice(general_->choice_space_below)==7)
-        invalid = invalid || (!input.empty() && !isValidGlueLength(input));
-    
-    if (ob == general_->input_space_above || ob == general_->input_space_below) {
-        if (invalid) {
+    input = fl_get_input (dialog_->input_space_below);
+
+    if (fl_get_choice(dialog_->choice_space_below)==7)
+        invalid = invalid
+               || (!input.empty() && !isValidGlueLength(input) && !isStrDbl(input));
+
+    if (ob == dialog_->input_space_above || ob == dialog_->input_space_below) {
+       if (invalid) {
             fl_set_object_label(dialog_->text_warning,
                 _("Warning: Invalid Length (valid example: 10mm)"));
             fl_show_object(dialog_->text_warning);
@@ -509,6 +552,18 @@ bool FormParagraph::input(FL_OBJECT * ob, long)
         }
     }
 
-    return ret;
-}
+    if (fl_get_choice (dialog_->choice_linespacing) == 5)
+        setEnabled (dialog_->input_linespacing, true);
+    else {
+        setEnabled (dialog_->input_linespacing, false);
+        fl_set_input (dialog_->input_linespacing, "");
+    }
+
+    double spacing(strToDbl(fl_get_input(dialog_->input_linespacing)));
 
+    if (fl_get_choice (dialog_->choice_linespacing) == 5
+        && int(spacing) == 0)
+        valid = false;
+
+    return valid;
+}