]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetSpace.cpp
revert r37459 and add a note to the sources:
[lyx.git] / src / insets / InsetSpace.cpp
index d1b89ddd0798cc89e45377f36fb08ef695359b08..023da440289f3b62150a7e214f37e9ad5ba981f6 100644 (file)
@@ -5,8 +5,8 @@
  *
  * \author Asger Alstrup Nielsen
  * \author Jean-Marc Lasgouttes
- * \author Lars Gullik Bjønnes
- * \author Jürgen Spitzmüller
+ * \author Lars Gullik Bjønnes
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
 #include "Dimension.h"
 #include "FuncRequest.h"
 #include "FuncStatus.h"
+#include "Language.h"
+#include "LaTeXFeatures.h"
 #include "Length.h"
 #include "Lexer.h"
 #include "MetricsInfo.h"
 #include "OutputParams.h"
+#include "output_xhtml.h"
 
 #include "support/debug.h"
 #include "support/docstream.h"
 #include "support/gettext.h"
+#include "support/lassert.h"
 #include "support/lstrings.h"
 
 #include "frontends/Application.h"
@@ -40,7 +44,7 @@ namespace lyx {
 
 
 InsetSpace::InsetSpace(InsetSpaceParams const & params)
-       : params_(params)
+       : Inset(0), params_(params)
 {}
 
 
@@ -50,18 +54,12 @@ InsetSpaceParams::Kind InsetSpace::kind() const
 }
 
 
-Length InsetSpace::length() const
+GlueLength InsetSpace::length() const
 {
        return params_.length;
 }
 
 
-InsetSpace::~InsetSpace()
-{
-       hideDialogs("space", this);
-}
-
-
 docstring InsetSpace::toolTip(BufferView const &, int, int) const
 {
        docstring message;
@@ -75,11 +73,17 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
        case InsetSpaceParams::THIN:
                message = _("Thin Space");
                break;
+       case InsetSpaceParams::MEDIUM:
+               message = _("Medium Space");
+               break;
+       case InsetSpaceParams::THICK:
+               message = _("Thick Space");
+               break;
        case InsetSpaceParams::QUAD:
                message = _("Quad Space");
                break;
        case InsetSpaceParams::QQUAD:
-               message = _("QQuad Space");
+               message = _("Double Quad Space");
                break;
        case InsetSpaceParams::ENSPACE:
                message = _("Enspace");
@@ -90,6 +94,12 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
        case InsetSpaceParams::NEGTHIN:
                message = _("Negative Thin Space");
                break;
+       case InsetSpaceParams::NEGMEDIUM:
+               message = _("Negative Medium Space");
+               break;
+       case InsetSpaceParams::NEGTHICK:
+               message = _("Negative Thick Space");
+               break;
        case InsetSpaceParams::HFILL:
                message = _("Horizontal Fill");
                break;
@@ -115,12 +125,14 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
                message = _("Horizontal Fill (Down Brace)");
                break;
        case InsetSpaceParams::CUSTOM:
+               // FIXME unicode
                message = support::bformat(_("Horizontal Space (%1$s)"),
-                               params_.length.asDocstring());
+                               from_ascii(params_.length.asString()));
                break;
        case InsetSpaceParams::CUSTOM_PROTECTED:
+               // FIXME unicode
                message = support::bformat(_("Protected Horizontal Space (%1$s)"),
-                               params_.length.asDocstring());
+                               from_ascii(params_.length.asString()));
                break;
        }
        return message;
@@ -129,16 +141,15 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
 
 void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
-       switch (cmd.action) {
+       switch (cmd.action()) {
 
-       case LFUN_INSET_MODIFY: {
+       case LFUN_INSET_MODIFY:
+               cur.recordUndo();
                string2params(to_utf8(cmd.argument()), params_);
                break;
-       }
 
-       case LFUN_MOUSE_RELEASE:
-               if (!cur.selection() && cmd.button() == mouse_button::button1)
-                       cur.bv().showDialog("space", params2string(params()), this);
+       case LFUN_INSET_DIALOG_UPDATE:
+               cur.bv().updateDialog("space", params2string(params()));
                break;
 
        default:
@@ -151,14 +162,19 @@ void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
 bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
-       switch (cmd.action) {
+       switch (cmd.action()) {
        // we handle these
        case LFUN_INSET_MODIFY:
                if (cmd.getArg(0) == "space") {
                        InsetSpaceParams params;
                        string2params(to_utf8(cmd.argument()), params);
                        status.setOnOff(params_.kind == params.kind);
-               }
+                       status.setEnabled(true);        
+               } else
+                       status.setEnabled(false);
+               return true;
+
+       case LFUN_INSET_DIALOG_UPDATE:
                status.setEnabled(true);
                return true;
        default:
@@ -167,9 +183,8 @@ bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
 }
 
 
-void InsetSpace::edit(Cursor & cur, bool, EntryDirection)
-{
-       cur.bv().showDialog("space", params2string(params()), this);
+namespace {
+int const arrow_size = 8;
 }
 
 
@@ -191,6 +206,14 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
                case InsetSpaceParams::NEGTHIN:
                        dim.wid = fm.width(char_type('M')) / 6;
                        break;
+               case InsetSpaceParams::MEDIUM:
+               case InsetSpaceParams::NEGMEDIUM:
+                       dim.wid = fm.width(char_type('M')) / 4;
+                       break;
+               case InsetSpaceParams::THICK:
+               case InsetSpaceParams::NEGTHICK:
+                       dim.wid = fm.width(char_type('M')) / 2;
+                       break;
                case InsetSpaceParams::PROTECTED:
                case InsetSpaceParams::NORMAL:
                        dim.wid = fm.width(char_type(' '));
@@ -206,9 +229,14 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
                        dim.wid = int(0.5 * fm.width(char_type('M')));
                        break;
                case InsetSpaceParams::CUSTOM:
-               case InsetSpaceParams::CUSTOM_PROTECTED:
-                       dim.wid = max(4, abs(params_.length.inBP()));
+               case InsetSpaceParams::CUSTOM_PROTECTED: {
+                       int const w = 
+                               params_.length.len().inPixels(mi.base.textwidth,
+                                                       fm.width(char_type('M')));
+                       int const minw = (w < 0) ? 3 * arrow_size : 4;
+                       dim.wid = max(minw, abs(w));
                        break;
+               }
                case InsetSpaceParams::HFILL:
                case InsetSpaceParams::HFILL_PROTECTED:
                case InsetSpaceParams::DOTFILL:
@@ -229,7 +257,7 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
 {
        Dimension const dim = dimension(*pi.base.bv);
 
-       if (isStretchableSpace()) {
+       if (isStretchableSpace() || params_.length.len().value() < 0) {
                int const asc = theFontMetrics(pi.base.font).ascent('M');
                int const desc = theFontMetrics(pi.base.font).descent('M');
                // Pixel height divisible by 2 for prettier fill graphics:
@@ -259,12 +287,12 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
 
                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,
+                       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::HFILL_PROTECTED) {
                        pi.pain.line(x0, y1, x0, y0, Color_latex);
-                       pi.pain.line(x0, y2 , x1, y2, Color_latex,
+                       pi.pain.line(x0, y2, x1, y2, Color_latex,
                                frontend::Painter::line_onoffdash);
                        pi.pain.line(x1, y1, x1, y0, Color_latex);
                } else if (params_.kind == InsetSpaceParams::DOTFILL) {
@@ -298,6 +326,18 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
                        pi.pain.line(xm + 1, y1 + 1 , xmr, y2, Color_special);
                        pi.pain.line(xmr, y2 , x3, y2, Color_special);
                        pi.pain.line(x3 + 1, y2 + 1 , x1, y0, Color_special);
+               } else if (params_.kind == InsetSpaceParams::CUSTOM) {
+                       pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_special);
+                       pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_special);
+                       pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_special);
+                       pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_special);
+                       pi.pain.line(x2, y2 , x3, y2, Color_special);
+               } else if (params_.kind == InsetSpaceParams::CUSTOM_PROTECTED) {
+                       pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_latex);
+                       pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_latex);
+                       pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_latex);
+                       pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_latex);
+                       pi.pain.line(x2, y2 , x3, y2, Color_latex);
                }
                return;
        }
@@ -319,14 +359,11 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
        xp[3] = x + w;
        yp[3] = y - max(h / 4, 1);
 
-       if (params_.length.inBP() < 0) {
-               // turn symbol upside down
-               swap(yp[0], yp[1]);
-               swap(yp[2], yp[3]);
-       }
        if (params_.kind == InsetSpaceParams::PROTECTED ||
            params_.kind == InsetSpaceParams::ENSPACE ||
            params_.kind == InsetSpaceParams::NEGTHIN ||
+           params_.kind == InsetSpaceParams::NEGMEDIUM ||
+           params_.kind == InsetSpaceParams::NEGTHICK ||
            params_.kind == InsetSpaceParams::CUSTOM_PROTECTED)
                pi.pain.lines(xp, yp, 4, Color_latex);
        else
@@ -347,6 +384,12 @@ void InsetSpaceParams::write(ostream & os) const
        case InsetSpaceParams::THIN:
                os <<  "\\thinspace{}";
                break;
+       case InsetSpaceParams::MEDIUM:
+               os <<  "\\medspace{}";
+               break;
+       case InsetSpaceParams::THICK:
+               os <<  "\\thickspace{}";
+               break;
        case InsetSpaceParams::QUAD:
                os <<  "\\quad{}";
                break;
@@ -362,6 +405,12 @@ void InsetSpaceParams::write(ostream & os) const
        case InsetSpaceParams::NEGTHIN:
                os <<  "\\negthinspace{}";
                break;
+       case InsetSpaceParams::NEGMEDIUM:
+               os <<  "\\negmedspace{}";
+               break;
+       case InsetSpaceParams::NEGTHICK:
+               os <<  "\\negthickspace{}";
+               break;
        case InsetSpaceParams::HFILL:
                os <<  "\\hfill{}";
                break;
@@ -394,7 +443,7 @@ void InsetSpaceParams::write(ostream & os) const
                break;
        }
        
-       if (!length.empty())
+       if (!length.len().empty())
                os << "\n\\length " << length.asString();
 }
 
@@ -405,12 +454,17 @@ void InsetSpaceParams::read(Lexer & lex)
        string command;
        lex >> command;
 
+       // The tests for math might be disabled after a file format change
        if (command == "\\space{}")
                kind = InsetSpaceParams::NORMAL;
        else if (command == "~")
                kind = InsetSpaceParams::PROTECTED;
        else if (command == "\\thinspace{}")
                kind = InsetSpaceParams::THIN;
+       else if (math && command == "\\medspace{}")
+               kind = InsetSpaceParams::MEDIUM;
+       else if (math && command == "\\thickspace{}")
+               kind = InsetSpaceParams::THICK;
        else if (command == "\\quad{}")
                kind = InsetSpaceParams::QUAD;
        else if (command == "\\qquad{}")
@@ -421,6 +475,10 @@ void InsetSpaceParams::read(Lexer & lex)
                kind = InsetSpaceParams::ENSKIP;
        else if (command == "\\negthinspace{}")
                kind = InsetSpaceParams::NEGTHIN;
+       else if (math && command == "\\negmedspace{}")
+               kind = InsetSpaceParams::NEGMEDIUM;
+       else if (math && command == "\\negthickspace{}")
+               kind = InsetSpaceParams::NEGTHICK;
        else if (command == "\\hfill{}")
                kind = InsetSpaceParams::HFILL;
        else if (command == "\\hspace*{\\fill}")
@@ -463,18 +521,29 @@ void InsetSpace::read(Lexer & lex)
 }
 
 
-int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const
+int InsetSpace::latex(otexstream & os, OutputParams const & runparams) const
 {
        switch (params_.kind) {
        case InsetSpaceParams::NORMAL:
                os << (runparams.free_spacing ? " " : "\\ ");
                break;
        case InsetSpaceParams::PROTECTED:
-               os << (runparams.free_spacing ? ' ' : '~');
+               if (runparams.local_font &&
+                   runparams.local_font->language()->lang() == "polutonikogreek")
+                       // in babel's polutonikogreek, ~ is active
+                       os << (runparams.free_spacing ? " " : "\\nobreakspace{}");
+               else
+                       os << (runparams.free_spacing ? ' ' : '~');
                break;
        case InsetSpaceParams::THIN:
                os << (runparams.free_spacing ? " " : "\\,");
                break;
+       case InsetSpaceParams::MEDIUM:
+               os << (runparams.free_spacing ? " " : "\\:");
+               break;
+       case InsetSpaceParams::THICK:
+               os << (runparams.free_spacing ? " " : "\\;");
+               break;
        case InsetSpaceParams::QUAD:
                os << (runparams.free_spacing ? " " : "\\quad{}");
                break;
@@ -490,6 +559,12 @@ int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const
        case InsetSpaceParams::NEGTHIN:
                os << (runparams.free_spacing ? " " : "\\negthinspace{}");
                break;
+       case InsetSpaceParams::NEGMEDIUM:
+               os << (runparams.free_spacing ? " " : "\\negmedspace{}");
+               break;
+       case InsetSpaceParams::NEGTHICK:
+               os << (runparams.free_spacing ? " " : "\\negthickspace{}");
+               break;
        case InsetSpaceParams::HFILL:
                os << (runparams.free_spacing ? " " : "\\hfill{}");
                break;
@@ -575,7 +650,11 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const
        case InsetSpaceParams::PROTECTED:
        case InsetSpaceParams::ENSPACE:
        case InsetSpaceParams::THIN:
+       case InsetSpaceParams::MEDIUM:
+       case InsetSpaceParams::THICK:
        case InsetSpaceParams::NEGTHIN:
+       case InsetSpaceParams::NEGMEDIUM:
+       case InsetSpaceParams::NEGTHICK:
                os << "&nbsp;";
                break;
        case InsetSpaceParams::HFILL:
@@ -600,12 +679,77 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const
 }
 
 
-void InsetSpace::textString(odocstream & os) const
+docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const
+{
+       string output;
+       switch (params_.kind) {
+       case InsetSpaceParams::NORMAL:
+               output = " ";
+               break;
+       case InsetSpaceParams::ENSKIP:
+       case InsetSpaceParams::ENSPACE:
+               output ="&ensp;";
+               break;
+       case InsetSpaceParams::QQUAD:
+               output ="&emsp;";
+       case InsetSpaceParams::THICK:
+       case InsetSpaceParams::QUAD:
+               output ="&emsp;";
+               break;
+       case InsetSpaceParams::THIN:
+               output ="&thinsp;";
+               break;
+       case InsetSpaceParams::PROTECTED:
+       case InsetSpaceParams::MEDIUM:
+       case InsetSpaceParams::NEGTHIN:
+       case InsetSpaceParams::NEGMEDIUM:
+       case InsetSpaceParams::NEGTHICK:
+               output ="&nbsp;";
+               break;
+       case InsetSpaceParams::HFILL:
+       case InsetSpaceParams::HFILL_PROTECTED:
+       case InsetSpaceParams::DOTFILL:
+       case InsetSpaceParams::HRULEFILL:
+       case InsetSpaceParams::LEFTARROWFILL:
+       case InsetSpaceParams::RIGHTARROWFILL:
+       case InsetSpaceParams::UPBRACEFILL:
+       case InsetSpaceParams::DOWNBRACEFILL:
+               // FIXME XHTML
+               // Can we do anything with those in HTML?
+               break;
+       case InsetSpaceParams::CUSTOM:
+       case InsetSpaceParams::CUSTOM_PROTECTED:
+               // FIXME XHTML
+               // Probably we could do some sort of blank span?
+               break;
+       }
+       // don't escape the entities!
+       xs << XHTMLStream::ESCAPE_NONE << from_ascii(output);
+       return docstring();
+}
+
+
+void InsetSpace::validate(LaTeXFeatures & features) const
+{
+       if (params_.kind == InsetSpaceParams::NEGMEDIUM ||
+           params_.kind == InsetSpaceParams::NEGTHICK) 
+               features.require("amsmath");
+}
+
+
+void InsetSpace::toString(odocstream & os) const
 {
        plaintext(os, OutputParams(0));
 }
 
 
+void InsetSpace::forToc(docstring & os, size_t) const
+{
+       // There's no need to be cute here.
+       os += " ";
+}
+
+
 bool InsetSpace::isStretchableSpace() const
 {
        return params_.kind == InsetSpaceParams::HFILL
@@ -619,7 +763,7 @@ bool InsetSpace::isStretchableSpace() const
 }
 
 
-docstring InsetSpace::contextMenu(BufferView const &, int, int) const
+docstring InsetSpace::contextMenuName() const
 {
        return from_ascii("context-space");
 }
@@ -635,7 +779,14 @@ void InsetSpace::string2params(string const & in, InsetSpaceParams & params)
        Lexer lex;
        lex.setStream(data);
        lex.setContext("InsetSpace::string2params");
-       lex >> "space";
+       lex.next();
+       string const name = lex.getString();
+       if (name == "mathspace")
+               params.math = true;
+       else {
+               params.math = false;
+               LASSERT(name == "space", /**/);
+       }
 
        // There are cases, such as when we are called via getStatus() from
        // Dialog::canApply(), where we are just called with "space" rather
@@ -648,6 +799,8 @@ void InsetSpace::string2params(string const & in, InsetSpaceParams & params)
 string InsetSpace::params2string(InsetSpaceParams const & params)
 {
        ostringstream data;
+       if (params.math)
+               data << "math";
        data << "space" << ' ';
        params.write(data);
        return data.str();