]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathSpace.cpp
Update it.po
[lyx.git] / src / mathed / InsetMathSpace.cpp
index 4aa9ed58c1d025a70f8f1a5b8f9077ae4a47eb11..f4c4d25f1ce117ab5fdbe58df7b9e7b0ea3109a2 100644 (file)
@@ -3,7 +3,7 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "InsetMathSpace.h"
 #include "MathData.h"
+#include "MathFactory.h"
 #include "MathStream.h"
+#include "MathSupport.h"
 
+#include "BufferView.h"
+#include "Cursor.h"
+#include "FuncRequest.h"
+#include "FuncStatus.h"
 #include "LaTeXFeatures.h"
+#include "MetricsInfo.h"
 
+#include "insets/InsetSpace.h"
+
+#include "frontends/Application.h"
 #include "frontends/Painter.h"
 
+#include "support/lassert.h"
+
 using namespace std;
 
 namespace lyx {
 
-char const * latex_mathspace[] = {
-       "!", "negmedspace", "negthickspace",  // negative space
-       ",", ":", ";", "quad", "qquad",       // positive space
-       "lyxnegspace", "lyxposspace"          // LyX special ("unvisible space")
+namespace {
+
+struct SpaceInfo {
+       string name;
+       int width;
+       InsetSpaceParams::Kind kind;
+       bool negative;
+       bool visible;
+       bool custom;
+       bool escape; ///< whether a backslash needs to be added for writing
 };
 
-int const nSpace = sizeof(latex_mathspace)/sizeof(char *);
+SpaceInfo space_info[] = {
+       // name           width kind                            negative visible custom escape
+       {"!",                6, InsetSpaceParams::NEGTHIN,         true,  true,  false, true},
+       {"negthinspace",     6, InsetSpaceParams::NEGTHIN,         true,  true,  false, true},
+       {"negmedspace",      8, InsetSpaceParams::NEGMEDIUM,       true,  true,  false, true},
+       {"negthickspace",   10, InsetSpaceParams::NEGTHICK,        true,  true,  false, true},
+       {",",                6, InsetSpaceParams::THIN,            false, true,  false, true},
+       {"thinspace",        6, InsetSpaceParams::THIN,            false, true,  false, true},
+       {":",                8, InsetSpaceParams::MEDIUM,          false, true,  false, true},
+       {"medspace",         8, InsetSpaceParams::MEDIUM,          false, true,  false, true},
+       {";",               10, InsetSpaceParams::THICK,           false, true,  false, true},
+       {"thickspace",      10, InsetSpaceParams::THICK,           false, true,  false, true},
+       {"enskip",          10, InsetSpaceParams::ENSKIP,          false, true,  false, true},
+       {"enspace",         10, InsetSpaceParams::ENSPACE,         false, true,  false, true},
+       {"quad",            20, InsetSpaceParams::QUAD,            false, true,  false, true},
+       {"qquad",           40, InsetSpaceParams::QQUAD,           false, true,  false, true},
+       {"lyxnegspace",     -2, InsetSpaceParams::NEGTHIN,         true,  false, false, true},
+       {"lyxposspace",      2, InsetSpaceParams::THIN,            false, false, false, true},
+       {"hfill",           80, InsetSpaceParams::HFILL,           false, true,  false, true},
+       {"hspace*{\\fill}", 80, InsetSpaceParams::HFILL_PROTECTED, false, true,  false, true},
+       {"hspace*",          0, InsetSpaceParams::CUSTOM_PROTECTED,false, true,  true,  true},
+       {"hspace",           0, InsetSpaceParams::CUSTOM,          false, true,  true,  true},
+       {" ",               10, InsetSpaceParams::NORMAL,          false, true,  false, true},
+       {"~",               10, InsetSpaceParams::PROTECTED,       false, true,  false, false},
+};
 
-namespace {
+int const nSpace = sizeof(space_info)/sizeof(SpaceInfo);
+int const defaultSpace = 4;
 
-int spaceToWidth(int space)
-{
-       switch (space) {
-               case 0: return 6;
-               case 1: return 8;
-               case 2: return 10;
-               case 3: return 6;
-               case 4: return 8;
-               case 5: return 10;
-               case 6: return 20;
-               case 7: return 40;
-               case 8: return -2;
-               case 9: return  2;
-               default: return 6;
-       }
+} // namespace
+
+InsetMathSpace::InsetMathSpace()
+       : space_(defaultSpace)
+{
 }
 
-} // anon namespace
 
-InsetMathSpace::InsetMathSpace(int sp)
-       : space_(sp)
+InsetMathSpace::InsetMathSpace(string const & name, string const & length)
+       : space_(defaultSpace)
 {
-       dim_.asc = 4;
-       dim_.des = 0;
-       dim_.wid = spaceToWidth(space_);
+       for (int i = 0; i < nSpace; ++i)
+               if (space_info[i].name == name) {
+                       space_ = i;
+                       break;
+               }
+       if (space_info[space_].custom) {
+               length_ = Length(length);
+               if (length_.zero() || length_.empty()) {
+                       length_.value(1.0);
+                       length_.unit(Length::EM);
+               }
+       }
 }
 
 
-InsetMathSpace::InsetMathSpace(docstring const & name)
-       : space_(1)
+InsetMathSpace::InsetMathSpace(Length const & length, bool const prot)
+       : space_(defaultSpace), length_(length)
 {
-       dim_.asc = 4;
-       dim_.des = 0;
        for (int i = 0; i < nSpace; ++i)
-               if (latex_mathspace[i] == name)
+               if ((prot && space_info[i].name == "hspace*")
+                       || (!prot && space_info[i].name == "hspace")) {
                        space_ = i;
-       dim_.wid = spaceToWidth(space_);
+                       break;
+               }
 }
 
 
@@ -78,46 +119,62 @@ Inset * InsetMathSpace::clone() const
 }
 
 
-void InsetMathSpace::metrics(MetricsInfo &, Dimension & dim) const
+void InsetMathSpace::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-       dim = dim_;
+       Changer dummy = mi.base.changeEnsureMath();
+       dim.asc = 4;
+       dim.des = 0;
+       if (space_info[space_].custom)
+               dim.wid = abs(mi.base.inPixels(length_));
+       else
+               dim.wid = space_info[space_].width;
 }
 
 
 void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
 {
+       Changer dummy = pi.base.changeEnsureMath();
        // Sadly, HP-UX CC can't handle that kind of initialization.
        // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
-       if (space_ >= nSpace - 2)
+       if (!space_info[space_].visible)
                return;
 
+       Dimension const dim = dimension(*pi.base.bv);
        int xp[4];
        int yp[4];
-       int w = dim_.wid;
+       int w = dim.wid;
 
        xp[0] = ++x;        yp[0] = y - 3;
        xp[1] = x;          yp[1] = y;
        xp[2] = x + w - 2;  yp[2] = y;
        xp[3] = x + w - 2;  yp[3] = y - 3;
 
-       pi.pain.lines(xp, yp, 4, (space_ < 3) ? Color_latex : Color_math);
+       pi.pain.lines(xp, yp, 4,
+                       space_info[space_].custom ?
+                       Color_special :
+                       (isNegative() ? Color_latex : Color_math));
 }
 
 
 void InsetMathSpace::incSpace()
 {
-       space_ = (space_ + 1) % (nSpace - 2);
-       dim_.wid = spaceToWidth(space_);
+       int const oldwidth = space_info[space_].width;
+       do
+               space_ = (space_ + 1) % nSpace;
+       while ((space_info[space_].width == oldwidth && !space_info[space_].custom) ||
+              !space_info[space_].visible);
+       if (space_info[space_].custom && (length_.zero() || length_.empty())) {
+               length_.value(1.0);
+               length_.unit(Length::EM);
+       }
 }
 
 
 void InsetMathSpace::validate(LaTeXFeatures & features) const
 {
-       if (space_ >= 0 && space_< nSpace) {
-               if ((latex_mathspace[space_] == string("negmedspace"))
-                || (latex_mathspace[space_] == string("negthickspace")))
-                       features.require("amsmath");
-       }
+       if (space_info[space_].name == "negmedspace" ||
+           space_info[space_].name == "negthickspace")
+               features.require("amsmath");
 }
 
 
@@ -138,21 +195,163 @@ void InsetMathSpace::octave(OctaveStream & os) const
 }
 
 
+void InsetMathSpace::mathmlize(MathMLStream & ms) const
+{
+       SpaceInfo const & si = space_info[space_];
+       if (si.negative || !si.visible)
+               return;
+       string l;
+       if (si.custom)
+               l = length_.asHTMLString();
+       else if (si.kind != InsetSpaceParams::MEDIUM) {
+               stringstream ss;
+               ss << si.width;
+               l = ss.str() + "px";
+       }
+
+       std::string attr;
+       if (!l.empty())
+               attr = "width=\"" + l + "\"";
+
+       ms << CTag("mspace", attr);
+}
+
+
+void InsetMathSpace::htmlize(HtmlStream & ms) const
+{
+       SpaceInfo const & si = space_info[space_];
+       switch (si.kind) {
+       case InsetSpaceParams::THIN:
+               ms << from_ascii("&thinsp;");
+               break;
+       case InsetSpaceParams::MEDIUM:
+               ms << from_ascii("&nbsp;");
+               break;
+       case InsetSpaceParams::THICK:
+               ms << from_ascii("&emsp;");
+               break;
+       case InsetSpaceParams::ENSKIP:
+       case InsetSpaceParams::ENSPACE:
+               ms << from_ascii("&ensp;");
+               break;
+       case InsetSpaceParams::QUAD:
+               ms << from_ascii("&emsp;");
+               break;
+       case InsetSpaceParams::QQUAD:
+               ms << from_ascii("&emsp;&emsp;");
+               break;
+       case InsetSpaceParams::HFILL:
+       case InsetSpaceParams::HFILL_PROTECTED:
+               // FIXME: is there a useful HTML entity?
+               break;
+       case InsetSpaceParams::CUSTOM:
+       case InsetSpaceParams::CUSTOM_PROTECTED: {
+               string l = length_.asHTMLString();
+               ms << MTag("span", "width='" + l + "'")
+                  << from_ascii("&nbsp;") << ETag("span");
+               break;
+       }
+       case InsetSpaceParams::NORMAL:
+       case InsetSpaceParams::PROTECTED:
+               ms << from_ascii("&nbsp;");
+               break;
+       default:
+               break;
+       }
+}
+
+
 void InsetMathSpace::normalize(NormalStream & os) const
 {
        os << "[space " << int(space_) << "] ";
 }
 
 
-void InsetMathSpace::write(WriteStream & os) const
+void InsetMathSpace::write(TeXMathStream & os) const
 {
-       if (space_ >= 0 && space_ < nSpace) {
-               bool brace = ensureMath(os);
-               os << '\\' << latex_mathspace[space_];
+       // All kinds work in text and math mode, so simply suspend
+       // writing a possibly pending mode closing brace.
+       MathEnsurer ensurer(os, false);
+       if (space_info[space_].escape)
+               os << '\\';
+       os << space_info[space_].name.c_str();
+       if (space_info[space_].custom)
+               os << '{' << length_.asLatexString().c_str() << '}';
+       else if (space_info[space_].escape && space_info[space_].name.length() > 1)
                os.pendingSpace(true);
-               os.pendingBrace(brace);
+}
+
+
+InsetSpaceParams InsetMathSpace::params() const
+{
+       InsetSpaceParams isp(true);
+       LASSERT(space_info[space_].visible, return isp);
+       isp.kind = space_info[space_].kind;
+       isp.length = GlueLength(length_);
+       return isp;
+}
+
+
+string InsetMathSpace::contextMenuName() const
+{
+       return "context-mathspace";
+}
+
+
+bool InsetMathSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
+                               FuncStatus & status) const
+{
+       switch (cmd.action()) {
+       // we handle these
+       case LFUN_INSET_MODIFY:
+       case LFUN_INSET_DIALOG_UPDATE:
+       case LFUN_MOUSE_RELEASE:
+               status.setEnabled(true);
+               return true;
+       default:
+               bool retval = InsetMath::getStatus(cur, cmd, status);
+               return retval;
+       }
+}
+
+
+void InsetMathSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
+{
+       switch (cmd.action()) {
+       case LFUN_INSET_MODIFY:
+               if (cmd.getArg(0) == "mathspace") {
+                       MathData ar;
+                       if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
+                               Buffer * buf = buffer_;
+                               cur.recordUndo();
+                               *this = *ar[0].nucleus()->asSpaceInset();
+                               buffer_ = buf;
+                               break;
+                       }
+               }
+               cur.undispatched();
+               break;
+
+       case LFUN_MOUSE_RELEASE:
+               if (cmd.button() == mouse_button::button1 && !cur.selection()) {
+                       showInsetDialog(&cur.bv());
+                       break;
+               }
+               cur.undispatched();
+               break;
+
+       default:
+               InsetMath::doDispatch(cur, cmd);
+               break;
        }
 }
 
 
+bool InsetMathSpace::isNegative() const
+{
+       if (space_info[space_].custom)
+               return length_.value() < 0;
+       return space_info[space_].negative;
+}
+
 } // namespace lyx