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