]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetSpecialChar.cpp
Fix bug #12795
[lyx.git] / src / insets / InsetSpecialChar.cpp
index 01007f6651390331b6719f5d537251dca4ef29ce..5983c07d649906ad69c225ae005c2b8c2fa801a5 100644 (file)
@@ -22,6 +22,7 @@
 #include "Lexer.h"
 #include "MetricsInfo.h"
 #include "output_xhtml.h"
+#include "xml.h"
 #include "texstream.h"
 
 #include "frontends/FontMetrics.h"
@@ -37,7 +38,7 @@ namespace lyx {
 
 
 InsetSpecialChar::InsetSpecialChar(Kind k)
-       : Inset(0), kind_(k)
+       : Inset(nullptr), kind_(k)
 {}
 
 
@@ -82,6 +83,29 @@ docstring InsetSpecialChar::toolTip(BufferView const &, int, int) const
 }
 
 
+int InsetSpecialChar::rowFlags() const
+{
+       switch (kind_) {
+       case ALLOWBREAK:
+       case HYPHENATION:
+       case SLASH:
+               // these are the elements that allow line breaking
+               return CanBreakAfter;
+       case NOBREAKDASH:
+       case END_OF_SENTENCE:
+       case LIGATURE_BREAK:
+       case LDOTS:
+       case MENU_SEPARATOR:
+       case PHRASE_LYX:
+       case PHRASE_TEX:
+       case PHRASE_LATEX2E:
+       case PHRASE_LATEX:
+               break;
+       }
+       return Inline;
+}
+
+
 namespace {
 
 // helper function: draw text and update x.
@@ -167,8 +191,7 @@ void drawLogo(PainterInfo & pi, int & x, int const y, InsetSpecialChar::Kind kin
 
 void InsetSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-       frontend::FontMetrics const & fm =
-               theFontMetrics(mi.base.font);
+       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
        dim.asc = fm.maxAscent();
        dim.des = 0;
        dim.wid = 0;
@@ -186,9 +209,14 @@ void InsetSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
                case END_OF_SENTENCE:
                        s = from_ascii(".");
                        break;
-               case LDOTS:
-                       s = from_ascii(". . .");
+               case LDOTS: {
+                       // see comment in draw().
+                       auto const fam = mi.base.font.family();
+                       // Multiplication by 3 is done here to limit rounding effects.
+                       int const spc3 = fam == TYPEWRITER_FAMILY ? 0 : 3 * fm.width(char_type(' ')) / 2;
+                       dim.wid = 3 * fm.width(char_type('.')) + spc3;
                        break;
+               }
                case MENU_SEPARATOR:
                        // ▹  U+25B9 WHITE RIGHT-POINTING SMALL TRIANGLE
                        // There is a \thinspace on each side of the triangle
@@ -261,15 +289,22 @@ void InsetSpecialChar::draw(PainterInfo & pi, int x, int y) const
        case LDOTS:
        {
                font.setColor(Color_special);
-               string ell = ". . . ";
-               docstring dell(ell.begin(), ell.end());
-               pi.pain.text(x, y, dell, font);
+               /* \textellipsis uses a \fontdimen3 is spacing. The TeXbook
+                * tells us that \fontdimen3 is the interword stretch, and
+                * that this is usually half a space.
+                */
+               frontend::FontMetrics const & fm = theFontMetrics(font);
+               auto const fam = pi.base.font.family();
+               int const spc = fam == TYPEWRITER_FAMILY ? 0 : fm.width(char_type(' ')) / 2;
+               int wid1 = fm.width(char_type('.')) + spc;
+               pi.pain.text(x, y, char_type('.'), font);
+               pi.pain.text(x + wid1, y, char_type('.'), font);
+               pi.pain.text(x + 2 * wid1, y, char_type('.'), font);
                break;
        }
        case MENU_SEPARATOR:
        {
-               frontend::FontMetrics const & fm =
-                       theFontMetrics(font);
+               frontend::FontMetrics const & fm = theFontMetrics(font);
 
                // There is a \thinspace on each side of the triangle
                x += fm.em() / 6;
@@ -506,90 +541,57 @@ int InsetSpecialChar::plaintext(odocstringstream & os,
 }
 
 
-int InsetSpecialChar::docbook(odocstream & os, OutputParams const &) const
-{
-       switch (kind_) {
-       case HYPHENATION:
-               break;
-       case ALLOWBREAK:
-               // U+200B ZERO WIDTH SPACE (ZWSP)
-               os.put(0x200b);
-               break;
-       case LIGATURE_BREAK:
-               break;
-       case END_OF_SENTENCE:
-               os << '.';
-               break;
-       case LDOTS:
-               os << "&hellip;";
-               break;
-       case MENU_SEPARATOR:
-               os << "&lyxarrow;";
-               break;
-       case SLASH:
-               os << '/';
-               break;
-       case NOBREAKDASH:
-               os << '-';
-               break;
-       case PHRASE_LYX:
-               os << "LyX";
-               break;
-       case PHRASE_TEX:
-               os << "TeX";
-               break;
-       case PHRASE_LATEX2E:
-               os << "LaTeX2";
-               // ε U+03B5 GREEK SMALL LETTER EPSILON
-               os.put(0x03b5);
-               break;
-       case PHRASE_LATEX:
-               os << "LaTeX";
-               break;
+namespace {
+string specialCharKindToXMLEntity(InsetSpecialChar::Kind kind) {
+       switch (kind) {
+       case InsetSpecialChar::Kind::HYPHENATION:
+               // Soft hyphen.
+               return "&#xAD;";
+       case InsetSpecialChar::Kind::ALLOWBREAK:
+               // Zero-width space
+               return "&#x200B;";
+       case InsetSpecialChar::Kind::LIGATURE_BREAK:
+               // Zero width non-joiner
+               return "&#x200C;";
+       case InsetSpecialChar::Kind::END_OF_SENTENCE:
+               return ".";
+       case InsetSpecialChar::Kind::LDOTS:
+               // &hellip;
+               return "&#x2026;";
+       case InsetSpecialChar::Kind::MENU_SEPARATOR:
+               // &rArr;, right arrow.
+               return "&#x21D2;";
+       case InsetSpecialChar::Kind::SLASH:
+               // &frasl;, fractional slash.
+               return "&#x2044;";
+       case InsetSpecialChar::Kind::NOBREAKDASH:
+               // Non-breaking hyphen.
+               return "&#x2011;";
+       case InsetSpecialChar::Kind::PHRASE_LYX:
+               return "LyX";
+       case InsetSpecialChar::Kind::PHRASE_TEX:
+               return "TeX";
+       case InsetSpecialChar::Kind::PHRASE_LATEX2E:
+               // Lower-case epsilon.
+               return "LaTeX2&#x03b5;";
+       case InsetSpecialChar::Kind::PHRASE_LATEX:
+               return "LaTeX";
+       default:
+               return "";
        }
-       return 0;
+}
+}
+
+
+void InsetSpecialChar::docbook(XMLStream & xs, OutputParams const &) const
+{
+       xs << XMLStream::ESCAPE_NONE << from_ascii(specialCharKindToXMLEntity(kind_));
 }
 
 
 docstring InsetSpecialChar::xhtml(XMLStream & xs, OutputParams const &) const
 {
-       switch (kind_) {
-       case HYPHENATION:
-               break;
-       case ALLOWBREAK:
-               xs << XMLStream::ESCAPE_NONE << "&#8203;";
-               break;
-       case LIGATURE_BREAK:
-               xs << XMLStream::ESCAPE_NONE << "&#8204;";
-               break;
-       case END_OF_SENTENCE:
-               xs << '.';
-               break;
-       case LDOTS:
-               xs << XMLStream::ESCAPE_NONE << "&hellip;";
-               break;
-       case MENU_SEPARATOR:
-               xs << XMLStream::ESCAPE_NONE << "&rArr;";
-               break;
-       case SLASH:
-               xs << XMLStream::ESCAPE_NONE << "&frasl;";
-               break;
-       case NOBREAKDASH:
-               xs << XMLStream::ESCAPE_NONE << "&#8209;";
-               break;
-       case PHRASE_LYX:
-               xs << "LyX";
-               break;
-       case PHRASE_TEX:
-               xs << "TeX";
-               break;
-       case PHRASE_LATEX2E:
-               xs << "LaTeX2" << XMLStream::ESCAPE_NONE << "&#x3b5;";
-               break;
-       case PHRASE_LATEX:
-               xs << "LaTeX";
-               break;
-       }
+       xs << XMLStream::ESCAPE_NONE << from_ascii(specialCharKindToXMLEntity(kind_));
        return docstring();
 }
 
@@ -606,7 +608,7 @@ void InsetSpecialChar::toString(odocstream & os) const
                break;
        }
        odocstringstream ods;
-       plaintext(ods, OutputParams(0));
+       plaintext(ods, OutputParams(nullptr));
        os << ods.str();
 }
 
@@ -615,7 +617,7 @@ void InsetSpecialChar::forOutliner(docstring & os, size_t const,
                                                                   bool const) const
 {
        odocstringstream ods;
-       plaintext(ods, OutputParams(0));
+       plaintext(ods, OutputParams(nullptr));
        os += ods.str();
 }
 
@@ -642,7 +644,9 @@ bool InsetSpecialChar::isChar() const
 bool InsetSpecialChar::isLetter() const
 {
        return kind_ == HYPHENATION || kind_ == LIGATURE_BREAK
-               || kind_ == NOBREAKDASH;
+               || kind_ == NOBREAKDASH
+               || kind_ == PHRASE_LYX || kind_ == PHRASE_LATEX
+               || kind_ == PHRASE_TEX || kind_ == PHRASE_LATEX2E;
 }