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