]> git.lyx.org Git - lyx.git/blob - src/FontInfo.cpp
de.po
[lyx.git] / src / FontInfo.cpp
1 /**
2  * \file src/FontInfo.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Jean-Marc Lasgouttes
8  * \author Angus Leeming
9  * \author André Pönitz
10  * \author Dekel Tsur
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "ColorSet.h"
18 #include "FontInfo.h"
19 #include "Lexer.h"
20 #include "LyXRC.h"
21
22 #include "support/convert.h"
23 #include "support/debug.h"
24 #include "support/docstring.h"
25 #include "support/lstrings.h"
26 #include "support/RefChanger.h"
27
28 #include <algorithm>
29 #include <ostream>
30 #include <sstream>
31
32 using namespace std;
33 using namespace lyx::support;
34
35 namespace lyx {
36
37 //
38 // Strings used to read and write .lyx format files
39 //
40 char const * LyXFamilyNames[NUM_FAMILIES + 2 /* default & error */] =
41 { "roman", "sans", "typewriter", "symbol",
42   "cmr", "cmsy", "cmm", "cmex", "msa", "msb", "eufrak", "rsfs", "stmry",
43   "wasy", "esint", "default", "error" };
44
45 char const * LyXSeriesNames[NUM_SERIES + 2 /* default & error */] =
46 { "medium", "bold", "default", "error" };
47
48 char const * LyXShapeNames[NUM_SHAPE + 2 /* default & error */] =
49 { "up", "italic", "slanted", "smallcaps", "default", "error" };
50
51 char const * LyXSizeNames[NUM_SIZE + 4 /* increase, decrease, default & error */] =
52 { "tiny", "scriptsize", "footnotesize", "small", "normal", "large",
53   "larger", "largest", "huge", "giant",
54   "increase", "decrease", "default", "error" };
55
56 char const * LyXMiscNames[5] =
57 { "off", "on", "toggle", "default", "error" };
58
59
60 FontInfo const sane_font(
61         ROMAN_FAMILY,
62         MEDIUM_SERIES,
63         UP_SHAPE,
64         FONT_SIZE_NORMAL,
65         Color_none,
66         Color_background,
67         FONT_OFF,
68         FONT_OFF,
69         FONT_OFF,
70         FONT_OFF,
71         FONT_OFF,
72         FONT_OFF,
73         FONT_OFF,
74         FONT_OFF,
75         FONT_OFF);
76
77 FontInfo const inherit_font(
78         INHERIT_FAMILY,
79         INHERIT_SERIES,
80         INHERIT_SHAPE,
81         FONT_SIZE_INHERIT,
82         Color_inherit,
83         Color_inherit,
84         FONT_INHERIT,
85         FONT_INHERIT,
86         FONT_INHERIT,
87         FONT_INHERIT,
88         FONT_INHERIT,
89         FONT_INHERIT,
90         FONT_INHERIT,
91         FONT_OFF,
92         FONT_INHERIT);
93
94 FontInfo const ignore_font(
95         IGNORE_FAMILY,
96         IGNORE_SERIES,
97         IGNORE_SHAPE,
98         FONT_SIZE_IGNORE,
99         Color_ignore,
100         Color_ignore,
101         FONT_IGNORE,
102         FONT_IGNORE,
103         FONT_IGNORE,
104         FONT_IGNORE,
105         FONT_IGNORE,
106         FONT_IGNORE,
107         FONT_IGNORE,
108         FONT_IGNORE,
109         FONT_IGNORE);
110
111
112 FontInfo::FontInfo()
113 {
114         *this = sane_font;
115 }
116
117
118 /// Decreases font size_ by one
119 FontInfo & FontInfo::decSize()
120 {
121         switch (size_) {
122         case FONT_SIZE_HUGER:        size_ = FONT_SIZE_HUGE;     break;
123         case FONT_SIZE_HUGE:         size_ = FONT_SIZE_LARGEST;  break;
124         case FONT_SIZE_LARGEST:      size_ = FONT_SIZE_LARGER;   break;
125         case FONT_SIZE_LARGER:       size_ = FONT_SIZE_LARGE;    break;
126         case FONT_SIZE_LARGE:        size_ = FONT_SIZE_NORMAL;   break;
127         case FONT_SIZE_NORMAL:       size_ = FONT_SIZE_SMALL;    break;
128         case FONT_SIZE_SMALL:        size_ = FONT_SIZE_FOOTNOTE; break;
129         case FONT_SIZE_FOOTNOTE:     size_ = FONT_SIZE_SCRIPT;   break;
130         case FONT_SIZE_SCRIPT:       size_ = FONT_SIZE_TINY;     break;
131         case FONT_SIZE_TINY:         break;
132         case FONT_SIZE_INCREASE:
133                 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_INCREASE");
134                 break;
135         case FONT_SIZE_DECREASE:
136                 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_DECREASE");
137                 break;
138         case FONT_SIZE_INHERIT:
139                 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_INHERIT");
140                 break;
141         case FONT_SIZE_IGNORE:
142                 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_IGNORE");
143                 break;
144         }
145         return *this;
146 }
147
148
149 /// Increases font size_ by one
150 FontInfo & FontInfo::incSize()
151 {
152         switch (size_) {
153         case FONT_SIZE_HUGER:   break;
154         case FONT_SIZE_HUGE:         size_ = FONT_SIZE_HUGER;    break;
155         case FONT_SIZE_LARGEST:      size_ = FONT_SIZE_HUGE;     break;
156         case FONT_SIZE_LARGER:       size_ = FONT_SIZE_LARGEST;  break;
157         case FONT_SIZE_LARGE:        size_ = FONT_SIZE_LARGER;   break;
158         case FONT_SIZE_NORMAL:       size_ = FONT_SIZE_LARGE;    break;
159         case FONT_SIZE_SMALL:        size_ = FONT_SIZE_NORMAL;   break;
160         case FONT_SIZE_FOOTNOTE:     size_ = FONT_SIZE_SMALL;    break;
161         case FONT_SIZE_SCRIPT:       size_ = FONT_SIZE_FOOTNOTE; break;
162         case FONT_SIZE_TINY:         size_ = FONT_SIZE_SCRIPT;   break;
163         case FONT_SIZE_INCREASE:
164                 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_INCREASE");
165                 break;
166         case FONT_SIZE_DECREASE:
167                 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_DECREASE");
168                 break;
169         case FONT_SIZE_INHERIT:
170                 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_INHERIT");
171                 break;
172         case FONT_SIZE_IGNORE:
173                 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_IGNORE");
174                 break;
175         }
176         return *this;
177 }
178
179
180 double FontInfo::realSize() const
181 {
182         double d = convert<double>(lyxrc.font_sizes[size()]);
183         // The following is according to the average of the values in the
184         // definitions of \defaultscriptratio and \defaultscriptscriptratio in LaTeX
185         // font packages. No attempt is made to implement the actual values from
186         // \DefineMathSizes.
187         switch (style()) {
188         case LM_ST_DISPLAY:
189         case LM_ST_TEXT:
190                 break;
191         case LM_ST_SCRIPT:
192                 d *= .73;
193                 break;
194         case LM_ST_SCRIPTSCRIPT:
195                 d *= .55;
196                 break;
197         }
198         // Never go below the smallest size
199         return max(d, convert<double>(lyxrc.font_sizes[FONT_SIZE_TINY]));
200 }
201
202
203 /// Reduce font to fall back to template where possible
204 void FontInfo::reduce(FontInfo const & tmplt)
205 {
206         if (family_ == tmplt.family_)
207                 family_ = INHERIT_FAMILY;
208         if (series_ == tmplt.series_)
209                 series_ = INHERIT_SERIES;
210         if (shape_ == tmplt.shape_)
211                 shape_ = INHERIT_SHAPE;
212         if (size_ == tmplt.size_)
213                 size_ = FONT_SIZE_INHERIT;
214         if (emph_ == tmplt.emph_)
215                 emph_ = FONT_INHERIT;
216         if (underbar_ == tmplt.underbar_)
217                 underbar_ = FONT_INHERIT;
218         if (strikeout_ == tmplt.strikeout_)
219                 strikeout_ = FONT_INHERIT;
220         if (xout_ == tmplt.xout_)
221                 xout_ = FONT_INHERIT;
222         if (uuline_ == tmplt.uuline_)
223                 uuline_ = FONT_INHERIT;
224         if (uwave_ == tmplt.uwave_)
225                 uwave_ = FONT_INHERIT;
226         if (noun_ == tmplt.noun_)
227                 noun_ = FONT_INHERIT;
228         if (color_ == tmplt.color_)
229                 color_ = Color_inherit;
230         if (background_ == tmplt.background_)
231                 background_ = Color_inherit;
232         if (nospellcheck_ == tmplt.nospellcheck_)
233                 nospellcheck_ = FONT_INHERIT;
234 }
235
236
237 /// Realize font from a template
238 FontInfo & FontInfo::realize(FontInfo const & tmplt)
239 {
240         if ((*this) == inherit_font) {
241                 operator=(tmplt);
242                 return *this;
243         }
244
245         if (family_ == INHERIT_FAMILY)
246                 family_ = tmplt.family_;
247
248         if (series_ == INHERIT_SERIES)
249                 series_ = tmplt.series_;
250
251         if (shape_ == INHERIT_SHAPE)
252                 shape_ = tmplt.shape_;
253
254         if (size_ == FONT_SIZE_INHERIT)
255                 size_ = tmplt.size_;
256
257         if (emph_ == FONT_INHERIT)
258                 emph_ = tmplt.emph_;
259
260         if (underbar_ == FONT_INHERIT)
261                 underbar_ = tmplt.underbar_;
262
263         if (strikeout_ == FONT_INHERIT)
264                 strikeout_ = tmplt.strikeout_;
265
266         if (xout_ == FONT_INHERIT)
267                 xout_ = tmplt.xout_;
268
269         if (uuline_ == FONT_INHERIT)
270                 uuline_ = tmplt.uuline_;
271
272         if (uwave_ == FONT_INHERIT)
273                 uwave_ = tmplt.uwave_;
274
275         if (noun_ == FONT_INHERIT)
276                 noun_ = tmplt.noun_;
277
278         if (color_ == Color_inherit)
279                 color_ = tmplt.color_;
280
281         if (background_ == Color_inherit)
282                 background_ = tmplt.background_;
283
284         if (nospellcheck_ == FONT_INHERIT)
285                 nospellcheck_ = tmplt.nospellcheck_;
286
287         return *this;
288 }
289
290
291 Changer FontInfo::changeColor(ColorCode const color)
292 {
293         return make_change(color_, color);
294 }
295
296
297 Changer FontInfo::changeShape(FontShape const shape)
298 {
299         return make_change(shape_, shape);
300 }
301
302
303 Changer FontInfo::changeStyle(MathStyle const new_style)
304 {
305         return make_change(style_, new_style);
306 }
307
308
309 Changer FontInfo::change(FontInfo font, bool realiz)
310 {
311         if (realiz)
312                 font.realize(*this);
313         return make_change(*this, font);
314 }
315
316
317 /// Updates a misc setting according to request
318 static FontState setMisc(FontState newfont,
319         FontState org)
320 {
321         if (newfont == FONT_TOGGLE) {
322                 if (org == FONT_ON)
323                         return FONT_OFF;
324                 else if (org == FONT_OFF)
325                         return FONT_ON;
326                 else {
327                         LYXERR0("Font::setMisc: Need state"
328                                 " FONT_ON or FONT_OFF to toggle. Setting to FONT_ON");
329                         return FONT_ON;
330                 }
331         } else if (newfont == FONT_IGNORE)
332                 return org;
333         else
334                 return newfont;
335 }
336
337 /// Updates font settings according to request
338 void FontInfo::update(FontInfo const & newfont, bool toggleall)
339 {
340         if (newfont.family_ == family_ && toggleall)
341                 setFamily(INHERIT_FAMILY); // toggle 'back'
342         else if (newfont.family_ != IGNORE_FAMILY)
343                 setFamily(newfont.family_);
344         // else it's IGNORE_SHAPE
345
346         // "Old" behaviour: "Setting" bold will toggle bold on/off.
347         switch (newfont.series_) {
348         case BOLD_SERIES:
349                 // We toggle...
350                 if (series_ == BOLD_SERIES && toggleall)
351                         setSeries(MEDIUM_SERIES);
352                 else
353                         setSeries(BOLD_SERIES);
354                 break;
355         case MEDIUM_SERIES:
356         case INHERIT_SERIES:
357                 setSeries(newfont.series_);
358                 break;
359         case IGNORE_SERIES:
360                 break;
361         }
362
363         if (newfont.shape_ == shape_ && toggleall)
364                 shape_ = INHERIT_SHAPE; // toggle 'back'
365         else if (newfont.shape_ != IGNORE_SHAPE)
366                 shape_ = newfont.shape_;
367         // else it's IGNORE_SHAPE
368
369         if (newfont.size_ != FONT_SIZE_IGNORE) {
370                 if (newfont.size_ == FONT_SIZE_INCREASE)
371                         incSize();
372                 else if (newfont.size_ == FONT_SIZE_DECREASE)
373                         decSize();
374                 else
375                         size_ = newfont.size_;
376         }
377
378         setEmph(setMisc(newfont.emph_, emph_));
379         setUnderbar(setMisc(newfont.underbar_, underbar_));
380         setStrikeout(setMisc(newfont.strikeout_, strikeout_));
381         setXout(setMisc(newfont.xout_, xout_));
382         setUuline(setMisc(newfont.uuline_, uuline_));
383         setUwave(setMisc(newfont.uwave_, uwave_));
384         setNoun(setMisc(newfont.noun_, noun_));
385         setNumber(setMisc(newfont.number_, number_));
386         setNoSpellcheck(setMisc(newfont.nospellcheck_, nospellcheck_));
387
388         if (newfont.color_ == color_ && toggleall)
389                 setColor(Color_inherit); // toggle 'back'
390         else if (newfont.color_ != Color_ignore)
391                 setColor(newfont.color_);
392
393         if (newfont.background_ == background_ && toggleall)
394                 setBackground(Color_inherit); // toggle 'back'
395         else if (newfont.background_ != Color_ignore)
396                 setBackground(newfont.background_);
397 }
398
399 /// Is font resolved?
400 bool FontInfo::resolved() const
401 {
402         return (family_ != INHERIT_FAMILY && series_ != INHERIT_SERIES
403                 && shape_ != INHERIT_SHAPE && size_ != FONT_SIZE_INHERIT
404                 && emph_ != FONT_INHERIT && underbar_ != FONT_INHERIT
405                 && uuline_ != FONT_INHERIT && uwave_ != FONT_INHERIT
406                 && strikeout_ != FONT_INHERIT && xout_ != FONT_INHERIT
407                 && noun_ != FONT_INHERIT && color_ != Color_inherit
408                 && background_ != Color_inherit && nospellcheck_ != FONT_INHERIT);
409 }
410
411
412 Color FontInfo::realColor() const
413 {
414         if (paint_color_ != Color_none)
415                 return paint_color_;
416         if (color_ == Color_none)
417                 return Color_foreground;
418         return color_;
419 }
420
421
422 namespace {
423
424 void appendSep(string & s1, string const & s2)
425 {
426         if (s2.empty())
427                 return;
428         s1 += s1.empty() ? "" : "\n";
429         s1 += s2;
430 }
431
432
433 string makeCSSTag(string const & key, string const & val)
434 {
435         return key + ": " + val + ";";
436 }
437
438
439 string getFamilyCSS(FontFamily const & f)
440 {
441         switch (f) {
442         case ROMAN_FAMILY:
443                 return "serif";
444         case SANS_FAMILY:
445                 return "sans-serif";
446         case TYPEWRITER_FAMILY:
447                 return "monospace";
448         case SYMBOL_FAMILY:
449         case CMR_FAMILY:
450         case CMSY_FAMILY:
451         case CMM_FAMILY:
452         case CMEX_FAMILY:
453         case MSA_FAMILY:
454         case MSB_FAMILY:
455         case EUFRAK_FAMILY:
456         case RSFS_FAMILY:
457         case STMARY_FAMILY:
458         case WASY_FAMILY:
459         case ESINT_FAMILY:
460         case INHERIT_FAMILY:
461         case IGNORE_FAMILY:
462                 break;
463         }
464         return "";
465 }
466
467
468 string getSeriesCSS(FontSeries const & s)
469 {
470         switch (s) {
471         case MEDIUM_SERIES:
472                 return "normal";
473         case BOLD_SERIES:
474                 return "bold";
475         case INHERIT_SERIES:
476         case IGNORE_SERIES:
477                 break;
478         }
479         return "";
480 }
481
482
483 string getShapeCSS(FontShape const & s)
484 {
485         string fs = "normal";
486         string fv = "normal";
487         switch (s) {
488         case UP_SHAPE: break;
489         case ITALIC_SHAPE: fs = "italic"; break;
490         case SLANTED_SHAPE: fs = "oblique"; break;
491         case SMALLCAPS_SHAPE: fv = "small-caps"; break;
492         case IGNORE_SHAPE:
493         case INHERIT_SHAPE:
494                 fs = ""; fv = ""; break;
495         }
496         string retval;
497         if (!fs.empty())
498                 appendSep(retval, makeCSSTag("font-style", fs));
499         if (!fv.empty())
500                 appendSep(retval, makeCSSTag("font-variant", fv));
501         return retval;
502 }
503
504
505 string getSizeCSS(FontSize const & s)
506 {
507         switch (s) {
508         case FONT_SIZE_TINY:
509                 return "xx-small";
510         case FONT_SIZE_SCRIPT:
511                 return "x-small";
512         case FONT_SIZE_FOOTNOTE:
513         case FONT_SIZE_SMALL:
514                 return "small";
515         case FONT_SIZE_NORMAL:
516                 return "medium";
517         case FONT_SIZE_LARGE:
518                 return "large";
519         case FONT_SIZE_LARGER:
520         case FONT_SIZE_LARGEST:
521                 return "x-large";
522         case FONT_SIZE_HUGE:
523         case FONT_SIZE_HUGER:
524                 return "xx-large";
525         case FONT_SIZE_INCREASE:
526                 return "larger";
527         case FONT_SIZE_DECREASE:
528                 return "smaller";
529         case FONT_SIZE_IGNORE:
530         case FONT_SIZE_INHERIT:
531                 break;
532         }
533         return "";
534 }
535
536 } // namespace
537
538
539 // FIXME This does not yet handle color
540 docstring FontInfo::asCSS() const
541 {
542         string retval;
543         string tmp = getFamilyCSS(family_);
544         if (!tmp.empty())
545                 appendSep(retval, makeCSSTag("font-family", tmp));
546         tmp = getSeriesCSS(series_);
547         if (!tmp.empty())
548                 appendSep(retval, makeCSSTag("font-weight", tmp));
549         appendSep(retval, getShapeCSS(shape_));
550         tmp = getSizeCSS(size_);
551         if (!tmp.empty())
552                 appendSep(retval, makeCSSTag("font-size", tmp));
553         return from_ascii(retval);
554 }
555
556
557 // Set family according to lyx format string
558 void setLyXFamily(string const & fam, FontInfo & f)
559 {
560         string const s = ascii_lowercase(fam);
561
562         int i = 0;
563         while (LyXFamilyNames[i] != s &&
564                LyXFamilyNames[i] != string("error"))
565                 ++i;
566         if (s == LyXFamilyNames[i])
567                 f.setFamily(FontFamily(i));
568         else
569                 LYXERR0("Unknown family `" << s << '\'');
570 }
571
572
573 // Set series according to lyx format string
574 void setLyXSeries(string const & ser, FontInfo & f)
575 {
576         string const s = ascii_lowercase(ser);
577
578         int i = 0;
579         while (LyXSeriesNames[i] != s &&
580                LyXSeriesNames[i] != string("error")) ++i;
581         if (s == LyXSeriesNames[i]) {
582                 f.setSeries(FontSeries(i));
583         } else
584                 LYXERR0("Unknown series `" << s << '\'');
585 }
586
587
588 // Set shape according to lyx format string
589 void setLyXShape(string const & sha, FontInfo & f)
590 {
591         string const s = ascii_lowercase(sha);
592
593         int i = 0;
594         while (LyXShapeNames[i] != s && LyXShapeNames[i] != string("error"))
595                         ++i;
596         if (s == LyXShapeNames[i])
597                 f.setShape(FontShape(i));
598         else
599                 LYXERR0("Unknown shape `" << s << '\'');
600 }
601
602
603 // Set size according to lyx format string
604 void setLyXSize(string const & siz, FontInfo & f)
605 {
606         string const s = ascii_lowercase(siz);
607         int i = 0;
608         while (LyXSizeNames[i] != s && LyXSizeNames[i] != string("error"))
609                 ++i;
610         if (s == LyXSizeNames[i]) {
611                 f.setSize(FontSize(i));
612         } else
613                 LYXERR0("Unknown size `" << s << '\'');
614 }
615
616
617 // Set size according to lyx format string
618 FontState setLyXMisc(string const & siz)
619 {
620         string const s = ascii_lowercase(siz);
621         int i = 0;
622         while (LyXMiscNames[i] != s &&
623                LyXMiscNames[i] != string("error")) ++i;
624         if (s == LyXMiscNames[i])
625                 return FontState(i);
626         LYXERR0("Unknown misc flag `" << s << '\'');
627         return FONT_OFF;
628 }
629
630
631 /// Sets color after LyX text format
632 void setLyXColor(string const & col, FontInfo & f)
633 {
634         f.setColor(lcolor.getFromLyXName(col));
635 }
636
637
638 // Read a font definition from given file in lyx format
639 // Used for layouts
640 FontInfo lyxRead(Lexer & lex, FontInfo const & fi)
641 {
642         FontInfo f = fi;
643         bool error = false;
644         bool finished = false;
645         while (!finished && lex.isOK() && !error) {
646                 lex.next();
647                 string const tok = ascii_lowercase(lex.getString());
648
649                 if (tok.empty()) {
650                         continue;
651                 } else if (tok == "endfont") {
652                         finished = true;
653                 } else if (tok == "family") {
654                         lex.next();
655                         string const ttok = lex.getString();
656                         setLyXFamily(ttok, f);
657                 } else if (tok == "series") {
658                         lex.next();
659                         string const ttok = lex.getString();
660                         setLyXSeries(ttok, f);
661                 } else if (tok == "shape") {
662                         lex.next();
663                         string const ttok = lex.getString();
664                         setLyXShape(ttok, f);
665                 } else if (tok == "size") {
666                         lex.next();
667                         string const ttok = lex.getString();
668                         setLyXSize(ttok, f);
669                 } else if (tok == "misc") {
670                         lex.next();
671                         string const ttok = ascii_lowercase(lex.getString());
672
673                         if (ttok == "no_bar") {
674                                 f.setUnderbar(FONT_OFF);
675                         } else if (ttok == "no_strikeout") {
676                                 f.setStrikeout(FONT_OFF);
677                         } else if (ttok == "no_xout") {
678                                 f.setXout(FONT_OFF);
679                         } else if (ttok == "no_uuline") {
680                                 f.setUuline(FONT_OFF);
681                         } else if (ttok == "no_uwave") {
682                                 f.setUwave(FONT_OFF);
683                         } else if (ttok == "no_emph") {
684                                 f.setEmph(FONT_OFF);
685                         } else if (ttok == "no_noun") {
686                                 f.setNoun(FONT_OFF);
687                         } else if (ttok == "emph") {
688                                 f.setEmph(FONT_ON);
689                         } else if (ttok == "underbar") {
690                                 f.setUnderbar(FONT_ON);
691                         } else if (ttok == "strikeout") {
692                                 f.setStrikeout(FONT_ON);
693                         } else if (ttok == "xout") {
694                                 f.setXout(FONT_ON);
695                         } else if (ttok == "uuline") {
696                                 f.setUuline(FONT_ON);
697                         } else if (ttok == "uwave") {
698                                 f.setUwave(FONT_ON);
699                         } else if (ttok == "noun") {
700                                 f.setNoun(FONT_ON);
701                         } else if (ttok == "nospellcheck") {
702                                 f.setNoSpellcheck(FONT_ON);
703                         } else if (ttok == "no_nospellcheck") {
704                                 f.setNoSpellcheck(FONT_OFF);
705                         } else {
706                                 lex.printError("Illegal misc type");
707                         }
708                 } else if (tok == "color") {
709                         lex.next();
710                         string const ttok = lex.getString();
711                         setLyXColor(ttok, f);
712                 } else {
713                         lex.printError("Unknown tag");
714                         error = true;
715                 }
716         }
717         return f;
718 }
719
720
721 void lyxWrite(ostream & os, FontInfo const & f, string const & start, int level)
722 {
723         string indent;
724         for (int i = 0; i < level; ++i)
725                 indent += '\t';
726         ostringstream oss;
727         if (f.family() != INHERIT_FAMILY)
728                 oss << indent << "\tFamily " << LyXFamilyNames[f.family()]
729                     << '\n';
730         if (f.series() != INHERIT_SERIES)
731                 oss << indent << "\tSeries " << LyXSeriesNames[f.series()]
732                     << '\n';
733         if (f.shape() != INHERIT_SHAPE)
734                 oss << indent << "\tShape " << LyXShapeNames[f.shape()]
735                     << '\n';
736         if (f.size() != FONT_SIZE_INHERIT)
737                 oss << indent << "\tSize " << LyXSizeNames[f.size()]
738                     << '\n';
739         if (f.underbar() == FONT_ON)
740                 oss << indent << "\tMisc Underbar\n";
741         else if (f.underbar() == FONT_OFF)
742                 oss << indent << "\tMisc No_Bar\n";
743         if (f.strikeout() == FONT_ON)
744                 oss << indent << "\tMisc Strikeout\n";
745         else if (f.strikeout() == FONT_OFF)
746                 oss << indent << "\tMisc No_Strikeout\n";
747         if (f.xout() == FONT_ON)
748                 oss << indent << "\tMisc Xout\n";
749         else if (f.xout() == FONT_OFF)
750                 oss << indent << "\tMisc No_Xout\n";
751         if (f.uuline() == FONT_ON)
752                 oss << indent << "\tMisc Uuline\n";
753         else if (f.uuline() == FONT_OFF)
754                 oss << indent << "\tMisc No_Uuline\n";
755         if (f.uwave() == FONT_ON)
756                 oss << indent << "\tMisc Uwave\n";
757         else if (f.uwave() == FONT_OFF)
758                 oss << indent << "\tMisc No_Uwave\n";
759         if (f.emph() == FONT_ON)
760                 oss << indent << "\tMisc Emph\n";
761         else if (f.emph() == FONT_OFF)
762                 oss << indent << "\tMisc No_Emph\n";
763         if (f.noun() == FONT_ON)
764                 oss << indent << "\tMisc Noun\n";
765         else if (f.noun() == FONT_OFF)
766                 oss << indent << "\tMisc No_Noun\n";
767         if (f.nospellcheck() == FONT_ON)
768                 oss << indent << "\tMisc NoSpellcheck\n";
769         else if (f.nospellcheck() == FONT_OFF)
770                 oss << indent << "\tMisc No_NoSpellcheck\n";
771         if (f.color() != Color_inherit && f.color() != Color_none)
772                 oss << indent << "\tColor " << lcolor.getLyXName(f.color())
773                     << '\n';
774         if (!oss.str().empty()) {
775                 os << indent << start << '\n'
776                    << oss.str()
777                    << indent << "EndFont\n";
778         }
779 }
780
781
782 } // namespace lyx