]> git.lyx.org Git - lyx.git/blobdiff - src/Encoding.cpp
Fix initial focus problem with outline and view-source panes.
[lyx.git] / src / Encoding.cpp
index 3dcd05c5ab7b0ce8db99db3159dbca090b0e6e09..e08095cf2d82831a06e16c28887f420cef47ef19 100644 (file)
@@ -222,15 +222,22 @@ char_type const arabic_end = 0x06cc;
 
 /// Information about a single UCS4 character
 struct CharInfo {
-       /// LaTeX command for this character
-       docstring command;
-       /// Needed LaTeX preamble (or feature)
-       string preamble;
+       /// LaTeX command (text mode) for this character
+       docstring textcommand;
+       /// LaTeX command (math mode) for this character
+       docstring mathcommand;
+       /// Needed LaTeX preamble (or feature) for text mode
+       string textpreamble;
+       /// Needed LaTeX preamble (or feature) for math mode
+       string mathpreamble;
        /// Is this a combining character?
        bool combining;
-       /// Is \c preamble a feature known by LaTeXFeatures, or a raw LaTeX
+       /// Is \c textpreamble a feature known by LaTeXFeatures, or a raw LaTeX
        /// command?
-       bool feature;
+       bool textfeature;
+       /// Is \c mathpreamble a feature known by LaTeXFeatures, or a raw LaTeX
+       /// command?
+       bool mathfeature;
        /// Always force the LaTeX command, even if the encoding contains
        /// this character?
        bool force;
@@ -261,7 +268,7 @@ const char * EncodingException::what() const throw()
 
 Encoding::Encoding(string const & n, string const & l, string const & i,
                   bool f, Encoding::Package p)
-       : Name_(n), LatexName_(l), iconvName_(i), fixedwidth_(f), package_(p)
+       : name_(n), latexName_(l), iconvName_(i), fixedwidth_(f), package_(p)
 {
        if (n == "ascii") {
                // ASCII can encode 128 code points and nothing else
@@ -333,11 +340,14 @@ docstring Encoding::latexChar(char_type c) const
        if (encodable_.find(c) != encodable_.end())
                return docstring(1, c);
 
-       // c cannot be encoded in this encoding
+       // c cannot (or should not) be encoded in this encoding
        CharInfoMap::const_iterator const it = unicodesymbols.find(c);
        if (it == unicodesymbols.end())
                throw EncodingException(c);
-       return it->second.command;
+       // at least one of mathcommand and textcommand is nonempty
+       if (it->second.textcommand.empty())
+               return "\\ensuremath{" + it->second.mathcommand + '}';
+       return it->second.textcommand;
 }
 
 
@@ -360,19 +370,53 @@ vector<char_type> Encoding::symbolsList() const
 }
 
 
-void Encodings::validate(char_type c, LaTeXFeatures & features)
+bool Encodings::latexMathChar(char_type c, docstring & command)
 {
        CharInfoMap::const_iterator const it = unicodesymbols.find(c);
-       if (it != unicodesymbols.end() && !it->second.preamble.empty()) {
-               if (it->second.feature)
-                       features.require(it->second.preamble);
-               else
-                       features.addPreambleSnippet(it->second.preamble);
+       if (it == unicodesymbols.end())
+               throw EncodingException(c);
+       if (it->second.mathcommand.empty()) {
+               if (it->second.textcommand.empty())
+                       throw EncodingException(c);
+               command = it->second.textcommand;
+               return false;
        }
+       command = it->second.mathcommand;
+       return true;
 }
 
 
-bool Encodings::isComposeChar_hebrew(char_type c)
+void Encodings::validate(char_type c, LaTeXFeatures & features, bool for_mathed)
+{
+       CharInfoMap::const_iterator const it = unicodesymbols.find(c);
+       if (it != unicodesymbols.end()) {
+               // at least one of mathcommand and textcommand is nonempty
+               bool const use_math = (for_mathed && !it->second.mathcommand.empty()) ||
+                                     (!for_mathed && it->second.textcommand.empty());
+               if (use_math) {
+                       if (!it->second.mathpreamble.empty()) {
+                               if (it->second.mathfeature)
+                                       features.require(it->second.mathpreamble);
+                               else
+                                       features.addPreambleSnippet(it->second.mathpreamble);
+                       }
+               } else {
+                       if (!it->second.textpreamble.empty()) {
+                               if (it->second.textfeature)
+                                       features.require(it->second.textpreamble);
+                               else
+                                       features.addPreambleSnippet(it->second.textpreamble);
+                       }
+                       if (for_mathed) {
+                               features.require("relsize");
+                               features.require("lyxmathsym");
+                       }
+               }
+       }
+}
+
+
+bool Encodings::isHebrewComposeChar(char_type c)
 {
        return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0;
 }
@@ -382,7 +426,7 @@ bool Encodings::isComposeChar_hebrew(char_type c)
 // they are hamza, alef_madda, alef_hamza, waw_hamza, alef_hamza_under,
 // alef, tah_marbota, dal, thal, rah, zai, wow, alef_maksoura
 
-bool Encodings::is_arabic_special(char_type c)
+bool Encodings::isArabicSpecialChar(char_type c)
 {
        return (c >= 0x0621 && c <= 0x0625) || (c >= 0x0630 && c <= 0x0632)
                || c == 0x0627 || c == 0x0629 || c == 0x062f || c == 0x0648
@@ -390,22 +434,22 @@ bool Encodings::is_arabic_special(char_type c)
 }
 
 
-bool Encodings::isComposeChar_arabic(char_type c)
+bool Encodings::isArabicComposeChar(char_type c)
 {
        return c >= 0x064b && c <= 0x0652;
 }
 
 
-bool Encodings::is_arabic(char_type c)
+bool Encodings::isArabicChar(char_type c)
 {
        return c >= arabic_start && c <= arabic_end
                && arabic_table[c-arabic_start][0];
 }
 
 
-char_type Encodings::transformChar(char_type c, Encodings::Letter_Form form)
+char_type Encodings::transformChar(char_type c, Encodings::LetterForm form)
 {
-       return is_arabic(c) ? arabic_table[c-arabic_start][form] : c;
+       return isArabicChar(c) ? arabic_table[c-arabic_start][form] : c;
 }
 
 
@@ -425,25 +469,25 @@ bool Encodings::isKnownScriptChar(char_type const c, string & preamble)
        if (it == unicodesymbols.end())
                return false;
 
-       if (it->second.preamble != "textgreek" && it->second.preamble != "textcyr")
+       if (it->second.textpreamble != "textgreek" && it->second.textpreamble != "textcyr")
                return false;
 
        if (preamble.empty()) {
-               preamble = it->second.preamble;
+               preamble = it->second.textpreamble;
                return true;
        }
-       return it->second.preamble == preamble;
+       return it->second.textpreamble == preamble;
 }
 
 
-Encoding const * Encodings::getFromLyXName(string const & name) const
+Encoding const * Encodings::fromLyXName(string const & name) const
 {
        EncodingList::const_iterator const it = encodinglist.find(name);
        return it != encodinglist.end() ? &it->second : 0;
 }
 
 
-Encoding const * Encodings::getFromLaTeXName(string const & name) const
+Encoding const * Encodings::fromLaTeXName(string const & name) const
 {
        // We don't use find_if because it makes copies of the pairs in
        // the map.
@@ -467,15 +511,19 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 {
        // We must read the symbolsfile first, because the Encoding
        // constructor depends on it.
-       Lexer symbolslex(0, 0);
+       Lexer symbolslex;
        symbolslex.setFile(symbolsfile);
+       bool getNextToken = true;
        while (symbolslex.isOK()) {
                char_type symbol;
                CharInfo info;
                string flags;
 
-               if (!symbolslex.next(true))
-                       break;
+               if (getNextToken) {
+                       if (!symbolslex.next(true))
+                               break;
+               } else
+                       getNextToken = true;
 
                istringstream is(symbolslex.getString());
                // reading symbol directly does not work if
@@ -487,16 +535,16 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 
                if (!symbolslex.next(true))
                        break;
-               info.command = symbolslex.getDocString();
+               info.textcommand = symbolslex.getDocString();
                if (!symbolslex.next(true))
                        break;
-               info.preamble = symbolslex.getString();
+               info.textpreamble = symbolslex.getString();
                if (!symbolslex.next(true))
                        break;
                flags = symbolslex.getString();
 
                info.combining = false;
-               info.feature = false;
+               info.textfeature = false;
                info.force = false;
                while (!flags.empty()) {
                        string flag;
@@ -511,30 +559,64 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
                                       << hex << symbol << dec
                                       << "'." << endl;
                }
+               // mathcommand and mathpreamble have been added for 1.6.0.
+               // make them optional so that old files still work.
+               int const lineno = symbolslex.lineNumber();
+               bool breakout = false;
+               if (symbolslex.next(true)) {
+                       if (symbolslex.lineNumber() != lineno) {
+                               // line in old format without mathcommand and mathpreamble
+                               getNextToken = false;
+                       } else {
+                               info.mathcommand = symbolslex.getDocString();
+                               if (symbolslex.next(true)) {
+                                       if (symbolslex.lineNumber() != lineno) {
+                                               // line in new format with mathcommand only
+                                               getNextToken = false;
+                                       } else {
+                                               // line in new format with mathcommand and mathpreamble
+                                               info.mathpreamble = symbolslex.getString();
+                                       }
+                               } else
+                                       breakout = true;
+                       }
+               } else {
+                       breakout = true;
+               }
 
-               if (!info.preamble.empty())
-                       info.feature = info.preamble[0] != '\\';
+               if (!info.textpreamble.empty())
+                       info.textfeature = info.textpreamble[0] != '\\';
+               if (!info.mathpreamble.empty())
+                       info.mathfeature = info.mathpreamble[0] != '\\';
 
                LYXERR(Debug::INFO, "Read unicode symbol " << symbol << " '"
-                       << to_utf8(info.command) << "' '" << info.preamble
-                       << "' " << info.combining << ' ' << info.feature);
-               unicodesymbols[symbol] = info;
+                       << to_utf8(info.textcommand) << "' '" << info.textpreamble
+                       << "' " << info.combining << ' ' << info.textfeature
+                       << " '" << to_utf8(info.mathcommand) << "' '"
+                       << info.mathpreamble << "' " << info.mathfeature);
+
+               // we assume that at least one command is nonempty when using unicodesymbols
+               if (!info.textcommand.empty() || !info.mathcommand.empty())
+                       unicodesymbols[symbol] = info;
+
+               if (breakout)
+                       break;
        }
 
        // Now read the encodings
-       enum Encodingtags {
+       enum {
                et_encoding = 1,
                et_end,
-               et_last
        };
 
-       struct keyword_item encodingtags[et_last - 1] = {
+       LexerKeyword encodingtags[] = {
                { "encoding", et_encoding },
                { "end", et_end }
        };
 
-       Lexer lex(encodingtags, et_last - 1);
+       Lexer lex(encodingtags);
        lex.setFile(encfile);
+       lex.setContext("Encodings::read");
        while (lex.isOK()) {
                switch (lex.lex()) {
                case et_encoding:
@@ -553,39 +635,35 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
                        else if (width == "variable")
                                fixedwidth = false;
                        else
-                               lex.printError("Encodings::read: "
-                                              "Unknown width: `$$Token'");
+                               lex.printError("Unknown width");
 
                        lex.next();
                        string const p = lex.getString();
                        Encoding::Package package = Encoding::none;
                        if (p == "none")
-                                package = Encoding::none;
+                               package = Encoding::none;
                        else if (p == "inputenc")
                                package = Encoding::inputenc;
                        else if (p == "CJK")
                                package = Encoding::CJK;
                        else
-                               lex.printError("Encodings::read: "
-                                              "Unknown package: `$$Token'");
+                               lex.printError("Unknown package");
 
                        LYXERR(Debug::INFO, "Reading encoding " << name);
                        encodinglist[name] = Encoding(name, latexname,
                                iconvname, fixedwidth, package);
 
                        if (lex.lex() != et_end)
-                               lex.printError("Encodings::read: "
-                                              "missing end");
+                               lex.printError("Missing end");
                        break;
                }
                case et_end:
-                       lex.printError("Encodings::read: Misplaced end");
+                       lex.printError("Misplaced end");
                        break;
                case Lexer::LEX_FEOF:
                        break;
                default:
-                       lex.printError("Encodings::read: "
-                                      "Unknown tag: `$$Token'");
+                       lex.printError("Unknown tag");
                        break;
                }
        }