]> git.lyx.org Git - lyx.git/blob - src/LaTeXFonts.cpp
1e89e4c63fc3dfd7a675b7c569490ea905593e9f
[lyx.git] / src / LaTeXFonts.cpp
1 /**
2  * \file LaTeXFonts.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Spitzmüller
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "LaTeXFonts.h"
14
15 #include "LaTeXFeatures.h"
16 #include "Lexer.h"
17
18 #include "frontends/alert.h"
19
20 #include "support/convert.h"
21 #include "support/debug.h"
22 #include "support/FileName.h"
23 #include "support/filetools.h"
24 #include "support/gettext.h"
25 #include "support/lstrings.h"
26
27
28 using namespace std;
29 using namespace lyx::support;
30
31
32 namespace lyx {
33
34 LaTeXFonts latexfonts;
35
36
37 bool LaTeXFont::available(bool ot1) const
38 {
39         return ot1 ? available_ot1_ : available_;
40 }
41
42
43 bool LaTeXFont::providesOSF(bool ot1) const
44 {
45         if (!osfpackage_.empty())
46                 return LaTeXFeatures::isAvailable(to_ascii(osfpackage_));
47
48         if (ot1 && !ot1package_.empty() && ot1package_ != "none")
49                 return false;
50
51         if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
52                 return false;
53
54         return (!osfoption_.empty() || !osfscoption_.empty());
55 }
56
57
58 bool LaTeXFont::providesSC(bool ot1) const
59 {
60         if (ot1 && !ot1package_.empty() && ot1package_ != "none")
61                 return false;
62
63         if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
64                 return false;
65
66         return (!scoption_.empty() || !osfscoption_.empty());
67 }
68
69
70 bool LaTeXFont::providesScale(bool ot1) const
71 {
72         if (ot1 && !ot1package_.empty() && ot1package_ != "none")
73                 return false;
74
75         if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
76                 return false;
77
78         return (!scaleoption_.empty());
79 }
80
81
82 string const LaTeXFont::getAvailablePackage(bool dryrun, bool ot1, bool complete)
83 {
84         if (ot1 && !ot1package_.empty()) {
85                 if (ot1package_ != "none"
86                     && (LaTeXFeatures::isAvailable(to_ascii(ot1package_)) || dryrun))
87                         return to_ascii(ot1package_);
88                 if (!dryrun && ot1package_ != "none")
89                         frontend::Alert::warning(_("Font not available"),
90                                         bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n"
91                                                   "is not available on your system. LyX will fall back to the default font."),
92                                                 ot1package_, guiname_), true);
93                 return string();
94         }
95         if (complete && !completepackage_.empty()) {
96                 if (LaTeXFeatures::isAvailable(to_ascii(completepackage_)) || dryrun)
97                         return to_ascii(completepackage_);
98         }
99         if (!package_.empty()) {
100                 if (!requires_.empty() && LaTeXFeatures::isAvailable(to_ascii(requires_)))
101                         return to_ascii(package_);
102                 if (LaTeXFeatures::isAvailable(to_ascii(package_)))
103                         return to_ascii(package_);
104                 else if (!altpackages_.empty()) {
105                         for (size_t i = 0; i < altpackages_.size(); ++i) {
106                                 if (LaTeXFeatures::isAvailable(to_ascii(altpackages_[i])))
107                                         return to_ascii(altpackages_[i]);
108                         }
109                 }
110                 // Output unavailable packages in source preview
111                 if (dryrun)
112                         return to_ascii(package_);
113                 docstring const req = requires_.empty() ? package_ : requires_;
114                         frontend::Alert::warning(_("Font not available"),
115                                         bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n"
116                                                   "is not available on your system. LyX will fall back to the default font."),
117                                                 req, guiname_), true);
118         }
119         return string();
120 }
121
122
123 string const LaTeXFont::getPackageOptions(bool const & ot1, bool const & sc,
124                                           bool const & osf, int const & scale)
125 {
126         if (ot1 && !ot1package_.empty())
127                 return string();
128
129         ostringstream os;
130         if (sc && osf && providesOSF() && providesSC()) {
131                 if (!osfscoption_.empty())
132                         os << to_ascii(osfscoption_);
133                 else
134                         os << to_ascii(osfoption_) << ',' << to_ascii(scoption_);
135         } else if (osf && providesOSF())
136                 os << to_ascii(osfoption_);
137         else if (sc && providesSC())
138                 os << to_ascii(scoption_);
139         if (scale != 100 && !scaleoption_.empty()) {
140                 if (!os.str().empty())
141                         os << ',';
142                 os << subst(to_ascii(scaleoption_), "$$val",
143                             convert<std::string>(float(scale) / 100));
144         }
145         return os.str();
146 }
147
148
149 bool LaTeXFont::readFont(Lexer & lex)
150 {
151         enum LaTeXFontTags {
152                 LF_ALT_PACKAGES = 1,
153                 LF_COMPLETE_PACKAGE,
154                 LF_END,
155                 LF_FAMILY,
156                 LF_GUINAME,
157                 LF_OSFOPTION,
158                 LF_OSFPACKAGE,
159                 LF_OSFSCOPTION,
160                 LF_OT1_PACKAGE,
161                 LF_PACKAGE,
162                 LF_REQUIRES,
163                 LF_SCALEOPTION,
164                 LF_SCOPTION,
165                 LF_SWITCHDEFAULT
166         };
167
168         // Keep these sorted alphabetically!
169         LexerKeyword latexFontTags[] = {
170                 { "altpackages",          LF_ALT_PACKAGES },
171                 { "completepackage",      LF_COMPLETE_PACKAGE },
172                 { "endfont",              LF_END },
173                 { "family",               LF_FAMILY },
174                 { "guiname",              LF_GUINAME },
175                 { "osfoption",            LF_OSFOPTION },
176                 { "osfpackage",           LF_OSFPACKAGE },
177                 { "osfscoption",          LF_OSFSCOPTION },
178                 { "ot1package",           LF_OT1_PACKAGE },
179                 { "package",              LF_PACKAGE },
180                 { "requires",             LF_REQUIRES },
181                 { "scaleoption",          LF_SCALEOPTION },
182                 { "scoption",             LF_SCOPTION },
183                 { "switchdefault",        LF_SWITCHDEFAULT }
184         };
185
186         bool error = false;
187         bool finished = false;
188         lex.pushTable(latexFontTags);
189         // parse style section
190         while (!finished && lex.isOK() && !error) {
191                 int le = lex.lex();
192                 // See comment in LyXRC.cpp.
193                 switch (le) {
194                 case Lexer::LEX_FEOF:
195                         continue;
196
197                 case Lexer::LEX_UNDEF: // parse error
198                         lex.printError("Unknown LaTeXFont tag `$$Token'");
199                         error = true;
200                         continue;
201
202                 default: 
203                         break;
204                 }
205                 switch (static_cast<LaTeXFontTags>(le)) {
206                 case LF_END: // end of structure
207                         finished = true;
208                         break;
209                 case LF_ALT_PACKAGES: {
210                         docstring altp;
211                         lex >> altp;
212                         altpackages_ = getVectorFromString(altp);
213                         break;
214                 }
215                 case LF_COMPLETE_PACKAGE:
216                         lex >> completepackage_;
217                         break;
218                 case LF_FAMILY:
219                         lex >> family_;
220                         break;
221                 case LF_GUINAME:
222                         lex >> guiname_;
223                         break;
224                 case LF_OSFOPTION:
225                         lex >> osfoption_;
226                         break;
227                 case LF_OSFPACKAGE:
228                         lex >> osfpackage_;
229                         break;
230                 case LF_OSFSCOPTION:
231                         lex >> osfscoption_;
232                         break;
233                 case LF_OT1_PACKAGE:
234                         lex >> ot1package_;
235                         break;
236                 case LF_PACKAGE:
237                         lex >> package_;
238                         break;
239                 case LF_REQUIRES:
240                         lex >> requires_;
241                         break;
242                 case LF_SCALEOPTION:
243                         lex >> scaleoption_;
244                         break;
245                 case LF_SCOPTION:
246                         lex >> scoption_;
247                         break;
248                 case LF_SWITCHDEFAULT:
249                         lex >> switchdefault_;
250                         break;
251                 }
252         }
253         if (!finished) {
254                 lex.printError("No End tag found for LaTeXFont tag `$$Token'");
255                 return false;
256         }
257         lex.popTable();
258         return finished && !error;
259 }
260
261
262 bool LaTeXFont::read(Lexer & lex)
263 {
264         switchdefault_ = 0;
265
266         if (!lex.next()) {
267                 lex.printError("No name given for LaTeX font: `$$Token'.");
268                 return false;
269         }
270
271         name_ = lex.getDocString();
272         LYXERR(Debug::INFO, "Reading LaTeX font " << name_);
273         if (!readFont(lex)) {
274                 LYXERR0("Error parsing LaTeX font `" << name_ << '\'');
275                 return false;
276         }
277
278         bool available = true;
279         if (!requires_.empty())
280                 available = LaTeXFeatures::isAvailable(to_ascii(requires_));
281         else if (!package_.empty()) {
282                 available = LaTeXFeatures::isAvailable(to_ascii(package_));
283                 if (!available && !altpackages_.empty()) {
284                         for (size_t i = 0; i < altpackages_.size(); ++i) {
285                                 available = LaTeXFeatures::isAvailable(to_ascii(altpackages_[i]));
286                                 if (available)
287                                         break;
288                         }
289                 }
290         }
291         available_ = available;
292
293         if (!ot1package_.empty() && ot1package_ != "none")
294                 available_ot1_ = LaTeXFeatures::isAvailable(to_ascii(ot1package_));
295         else
296                 available_ot1_ = available;
297
298         return true;
299 }
300
301
302 void LaTeXFonts::readLaTeXFonts()
303 {
304         // Read latexfonts file
305         FileName filename = libFileSearch(string(), "latexfonts");
306         if (filename.empty()) {
307                 LYXERR0("Error: latexfonts file not found!");
308                 return;
309         }
310         Lexer lex;
311         lex.setFile(filename);
312         lex.setContext("LaTeXFeatures::readLaTeXFonts");
313         while (lex.isOK()) {
314                 int le = lex.lex();
315                 switch (le) {
316                 case Lexer::LEX_FEOF:
317                         continue;
318
319                 default:
320                         break;
321                 }
322                 if (lex.getString() != "Font") {
323                         lex.printError("Unknown LaTeXFont tag `$$Token'");
324                         continue;
325                 }
326                 LaTeXFont f;
327                 f.read(lex);
328                 if (!lex)
329                         break;
330
331                 texfontmap_[f.name()] = f;
332         }
333 }
334
335
336 LaTeXFonts::TexFontMap LaTeXFonts::getLaTeXFonts()
337 {
338         if (texfontmap_.empty())
339                 readLaTeXFonts();
340         return texfontmap_;
341 }
342
343
344 LaTeXFont LaTeXFonts::getLaTeXFont(docstring const & name)
345 {
346         if (texfontmap_.empty())
347                 readLaTeXFonts();
348         return texfontmap_[name];
349 }
350
351
352 } // namespace lyx