]> git.lyx.org Git - lyx.git/blob - src/lyxfont.C
Look for mathed xpms. Doesn't do anything yet due to lack of workable XPMs
[lyx.git] / src / lyxfont.C
1 /* This file is part of
2  * ======================================================
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2001 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12 #include <clocale>
13 #include <cctype>
14
15 #ifdef __GNUG__
16 #pragma implementation
17 #endif
18
19
20 #include "gettext.h"
21 #include "lyxfont.h"
22 #include "debug.h"
23 #include "lyxrc.h"
24 #include "lyxlex.h"
25 #include "language.h"
26 #include "support/lstrings.h"
27 #include "bufferparams.h" // stateText
28
29 using std::ostream;
30 using std::endl;
31
32 #ifndef CXX_GLOBAL_CSTD
33 using std::strlen;
34 #endif
35
36 //
37 // Names for the GUI
38 //
39
40 namespace {
41
42 char const * GUIFamilyNames[LyXFont::NUM_FAMILIES + 2 /* default & error */] =
43 { N_("Roman"), N_("Sans serif"), N_("Typewriter"), N_("Symbol"),
44   "cmr", "cmsy", "cmm", "cmex", "msa", "msb", "eufrak", "wasy",
45   N_("Inherit"), N_("Ignore") };
46
47 char const * GUISeriesNames[4] =
48 { N_("Medium"), N_("Bold"), N_("Inherit"), N_("Ignore") };
49
50 char const * GUIShapeNames[6] =
51 { N_("Upright"), N_("Italic"), N_("Slanted"), N_("Smallcaps"), N_("Inherit"),
52   N_("Ignore") };
53
54 char const * GUISizeNames[14] =
55 { N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"),
56   N_("Larger"), N_("Largest"), N_("Huge"), N_("Huger"), N_("Increase"), N_("Decrease"),
57   N_("Inherit"), N_("Ignore") };
58
59 char const * GUIMiscNames[5] =
60 { N_("Off"), N_("On"), N_("Toggle"), N_("Inherit"), N_("Ignore") };
61
62
63 //
64 // Strings used to read and write .lyx format files
65 //
66 char const * LyXFamilyNames[LyXFont::NUM_FAMILIES + 2 /* default & error */] =
67 { "roman", "sans", "typewriter", "symbol",
68   "cmr", "cmsy", "cmm", "cmex", "msa", "msb", "eufrak", "wasy",
69   "default", "error" };
70
71 char const * LyXSeriesNames[4] =
72 { "medium", "bold", "default", "error" };
73
74 char const * LyXShapeNames[6] =
75 { "up", "italic", "slanted", "smallcaps", "default", "error" };
76
77 char const * LyXSizeNames[14] =
78 { "tiny", "scriptsize", "footnotesize", "small", "normal", "large",
79   "larger", "largest", "huge", "giant",
80   "increase", "decrease", "default", "error" };
81
82 char const * LyXMiscNames[5] =
83 { "off", "on", "toggle", "default", "error" };
84
85 //
86 // Strings used to write LaTeX files
87 //
88 char const * LaTeXFamilyNames[6] =
89 { "textrm", "textsf", "texttt", "error1", "error2", "error3" };
90
91 char const * LaTeXSeriesNames[4] =
92 { "textmd", "textbf", "error4", "error5" };
93
94 char const * LaTeXShapeNames[6] =
95 { "textup", "textit", "textsl", "textsc", "error6", "error7" };
96
97 char const * LaTeXSizeNames[14] =
98 { "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
99   "Large", "LARGE", "huge", "Huge", "error8", "error9", "error10", "error11" };
100
101 } // namespace anon
102
103
104 // Initialize static member
105 LyXFont::FontBits LyXFont::sane = {
106         ROMAN_FAMILY,
107         MEDIUM_SERIES,
108         UP_SHAPE,
109         SIZE_NORMAL,
110         LColor::none,
111         OFF,
112         OFF,
113         OFF,
114         OFF };
115
116 // Initialize static member
117 LyXFont::FontBits LyXFont::inherit = {
118         INHERIT_FAMILY,
119         INHERIT_SERIES,
120         INHERIT_SHAPE,
121         INHERIT_SIZE,
122         LColor::inherit,
123         INHERIT,
124         INHERIT,
125         INHERIT,
126         OFF };
127
128 // Initialize static member
129 LyXFont::FontBits LyXFont::ignore = {
130         IGNORE_FAMILY,
131         IGNORE_SERIES,
132         IGNORE_SHAPE,
133         IGNORE_SIZE,
134         LColor::ignore,
135         IGNORE,
136         IGNORE,
137         IGNORE,
138         IGNORE };
139
140
141 bool operator==(LyXFont::FontBits const & lhs,
142                 LyXFont::FontBits const & rhs)
143 {
144         return lhs.family == rhs.family &&
145                 lhs.series == rhs.series &&
146                 lhs.shape == rhs.shape &&
147                 lhs.size == rhs.size &&
148                 lhs.color == rhs.color &&
149                 lhs.emph == rhs.emph &&
150                 lhs.underbar == rhs.underbar &&
151                 lhs.noun == rhs.noun &&
152                 lhs.number == rhs.number;
153 }
154
155
156 LyXFont::LyXFont()
157         : bits(sane), lang(default_language)
158 {}
159
160
161 LyXFont::LyXFont(LyXFont::FONT_INIT1)
162 #ifndef INHERIT_LANGUAGE
163         : bits(inherit), lang(default_language)
164 #else
165         : bits(inherit), lang(inherit_language)
166 #endif
167 {}
168
169
170 LyXFont::LyXFont(LyXFont::FONT_INIT2)
171         : bits(ignore), lang(ignore_language)
172 {}
173
174
175 LyXFont::LyXFont(LyXFont::FONT_INIT3)
176         : bits(sane), lang(default_language)
177 {}
178
179
180 LyXFont::LyXFont(LyXFont::FONT_INIT1, Language const * l)
181         : bits(inherit), lang(l)
182 {}
183
184
185 LyXFont::LyXFont(LyXFont::FONT_INIT2, Language const * l)
186         : bits(ignore), lang(l)
187 {}
188
189
190 LyXFont::LyXFont(LyXFont::FONT_INIT3, Language const * l)
191         : bits(sane), lang(l)
192 {}
193
194
195 LyXFont::FONT_MISC_STATE LyXFont::underbar() const
196 {
197         return bits.underbar;
198 }
199
200
201 LColor::color LyXFont::color() const
202 {
203         return bits.color;
204 }
205
206
207 Language const * LyXFont::language() const
208 {
209         return lang;
210 }
211
212
213 LyXFont::FONT_MISC_STATE LyXFont::number() const
214 {
215         return bits.number;
216 }
217
218
219 bool LyXFont::isRightToLeft() const
220 {
221         return lang->RightToLeft();
222 }
223
224
225 bool LyXFont::isVisibleRightToLeft() const
226 {
227         return (lang->RightToLeft() &&
228                 number() != ON);
229 }
230
231
232 LyXFont & LyXFont::setFamily(LyXFont::FONT_FAMILY f)
233 {
234         bits.family = f;
235         return *this;
236 }
237
238
239 LyXFont & LyXFont::setSeries(LyXFont::FONT_SERIES s)
240 {
241         bits.series = s;
242         return *this;
243 }
244
245
246 LyXFont & LyXFont::setShape(LyXFont::FONT_SHAPE s)
247 {
248         bits.shape = s;
249         return *this;
250 }
251
252
253 LyXFont & LyXFont::setSize(LyXFont::FONT_SIZE s)
254 {
255         bits.size = s;
256         return *this;
257 }
258
259
260 LyXFont & LyXFont::setEmph(LyXFont::FONT_MISC_STATE e)
261 {
262         bits.emph = e;
263         return *this;
264 }
265
266
267 LyXFont & LyXFont::setUnderbar(LyXFont::FONT_MISC_STATE u)
268 {
269         bits.underbar = u;
270         return *this;
271 }
272
273
274 LyXFont & LyXFont::setNoun(LyXFont::FONT_MISC_STATE n)
275 {
276         bits.noun = n;
277         return *this;
278 }
279
280
281 LyXFont & LyXFont::setColor(LColor::color c)
282 {
283         bits.color = c;
284         return *this;
285 }
286
287
288 LyXFont & LyXFont::setLanguage(Language const * l)
289 {
290         lang = l;
291         return *this;
292 }
293
294
295 LyXFont & LyXFont::setNumber(LyXFont::FONT_MISC_STATE n)
296 {
297         bits.number = n;
298         return *this;
299 }
300
301
302 /// Decreases font size by one
303 LyXFont & LyXFont::decSize()
304 {
305         switch (size()) {
306         case SIZE_HUGER:        setSize(SIZE_HUGE);     break;
307         case SIZE_HUGE:         setSize(SIZE_LARGEST);  break;
308         case SIZE_LARGEST:      setSize(SIZE_LARGER);   break;
309         case SIZE_LARGER:       setSize(SIZE_LARGE);    break;
310         case SIZE_LARGE:        setSize(SIZE_NORMAL);   break;
311         case SIZE_NORMAL:       setSize(SIZE_SMALL);    break;
312         case SIZE_SMALL:        setSize(SIZE_FOOTNOTE); break;
313         case SIZE_FOOTNOTE:     setSize(SIZE_SCRIPT);   break;
314         case SIZE_SCRIPT:       setSize(SIZE_TINY);     break;
315         case SIZE_TINY:         break;
316         case INCREASE_SIZE:
317                 lyxerr << "Can't LyXFont::decSize on INCREASE_SIZE" << endl;
318                 break;
319         case DECREASE_SIZE:
320                 lyxerr <<"Can't LyXFont::decSize on DECREASE_SIZE" << endl;
321                 break;
322         case INHERIT_SIZE:
323                 lyxerr <<"Can't LyXFont::decSize on INHERIT_SIZE" << endl;
324                 break;
325         case IGNORE_SIZE:
326                 lyxerr <<"Can't LyXFont::decSize on IGNORE_SIZE" << endl;
327                 break;
328         }
329         return *this;
330 }
331
332
333 /// Increases font size by one
334 LyXFont & LyXFont::incSize()
335 {
336         switch (size()) {
337         case SIZE_HUGER:        break;
338         case SIZE_HUGE:         setSize(SIZE_HUGER);    break;
339         case SIZE_LARGEST:      setSize(SIZE_HUGE);     break;
340         case SIZE_LARGER:       setSize(SIZE_LARGEST);  break;
341         case SIZE_LARGE:        setSize(SIZE_LARGER);   break;
342         case SIZE_NORMAL:       setSize(SIZE_LARGE);    break;
343         case SIZE_SMALL:        setSize(SIZE_NORMAL);   break;
344         case SIZE_FOOTNOTE:     setSize(SIZE_SMALL);    break;
345         case SIZE_SCRIPT:       setSize(SIZE_FOOTNOTE); break;
346         case SIZE_TINY:         setSize(SIZE_SCRIPT);   break;
347         case INCREASE_SIZE:
348                 lyxerr <<"Can't LyXFont::incSize on INCREASE_SIZE" << endl;
349                 break;
350         case DECREASE_SIZE:
351                 lyxerr <<"Can't LyXFont::incSize on DECREASE_SIZE" << endl;
352                 break;
353         case INHERIT_SIZE:
354                 lyxerr <<"Can't LyXFont::incSize on INHERIT_SIZE" << endl;
355                 break;
356         case IGNORE_SIZE:
357                 lyxerr <<"Can't LyXFont::incSize on IGNORE_SIZE" << endl;
358                 break;
359         }
360         return *this;
361 }
362
363
364 /// Updates a misc setting according to request
365 LyXFont::FONT_MISC_STATE LyXFont::setMisc(FONT_MISC_STATE newfont,
366                                           FONT_MISC_STATE org)
367 {
368         if (newfont == TOGGLE) {
369                 if (org == ON)
370                         return OFF;
371                 else if (org == OFF)
372                         return ON;
373                 else {
374                         lyxerr <<"LyXFont::setMisc: Need state"
375                                 " ON or OFF to toggle. Setting to ON" << endl;
376                         return ON;
377                 }
378         } else if (newfont == IGNORE)
379                 return org;
380         else
381                 return newfont;
382 }
383
384
385 /// Updates font settings according to request
386 void LyXFont::update(LyXFont const & newfont,
387                      Language const * document_language,
388                      bool toggleall)
389 {
390         if (newfont.family() == family() && toggleall)
391                 setFamily(INHERIT_FAMILY); // toggle 'back'
392         else if (newfont.family() != IGNORE_FAMILY)
393                 setFamily(newfont.family());
394         // else it's IGNORE_SHAPE
395
396         // "Old" behaviour: "Setting" bold will toggle bold on/off.
397         switch (newfont.series()) {
398         case BOLD_SERIES:
399                 // We toggle...
400                 if (series() == BOLD_SERIES && toggleall)
401                         setSeries(MEDIUM_SERIES);
402                 else
403                         setSeries(BOLD_SERIES);
404                 break;
405         case MEDIUM_SERIES:
406         case INHERIT_SERIES:
407                 setSeries(newfont.series());
408                 break;
409         case IGNORE_SERIES:
410                 break;
411         }
412
413         if (newfont.shape() == shape() && toggleall)
414                 setShape(INHERIT_SHAPE); // toggle 'back'
415         else if (newfont.shape() != IGNORE_SHAPE)
416                 setShape(newfont.shape());
417         // else it's IGNORE_SHAPE
418
419         if (newfont.size() != IGNORE_SIZE) {
420                 if (newfont.size() == INCREASE_SIZE)
421                         incSize();
422                 else if (newfont.size() == DECREASE_SIZE)
423                         decSize();
424                 else
425                         setSize(newfont.size());
426         }
427
428         setEmph(setMisc(newfont.emph(), emph()));
429         setUnderbar(setMisc(newfont.underbar(), underbar()));
430         setNoun(setMisc(newfont.noun(), noun()));
431
432         setNumber(setMisc(newfont.number(), number()));
433         if (newfont.language() == language() && toggleall)
434                 if (language() == document_language)
435                         setLanguage(default_language);
436                 else
437 #ifndef INHERIT_LANGUAGE
438                         setLanguage(document_language);
439 #else
440                         setLanguage(inherit_language);
441 #endif
442         else if (newfont.language() != ignore_language)
443                 setLanguage(newfont.language());
444
445         if (newfont.color() == color() && toggleall)
446                 setColor(LColor::inherit); // toggle 'back'
447         else if (newfont.color() != LColor::ignore)
448                 setColor(newfont.color());
449 }
450
451
452 /// Reduce font to fall back to template where possible
453 void LyXFont::reduce(LyXFont const & tmplt)
454 {
455         if (family() == tmplt.family())
456                 setFamily(INHERIT_FAMILY);
457         if (series() == tmplt.series())
458                 setSeries(INHERIT_SERIES);
459         if (shape() == tmplt.shape())
460                 setShape(INHERIT_SHAPE);
461         if (size() == tmplt.size())
462                 setSize(INHERIT_SIZE);
463         if (emph() == tmplt.emph())
464                 setEmph(INHERIT);
465         if (underbar() == tmplt.underbar())
466                 setUnderbar(INHERIT);
467         if (noun() == tmplt.noun())
468                 setNoun(INHERIT);
469         if (color() == tmplt.color())
470                 setColor(LColor::inherit);
471 #ifdef INHERIT_LANGUAGE
472         if (language() == tmplt.language())
473                 setLanguage(inherit_language);
474 #endif
475 }
476
477
478 /// Realize font from a template
479 #ifndef INHERIT_LANGUAGE
480 LyXFont & LyXFont::realize(LyXFont const & tmplt)
481 #else
482 LyXFont & LyXFont::realize(LyXFont const & tmplt, Language const * deflang)
483 #endif
484 {
485 #ifdef INHERIT_LANGUAGE
486         if (language() == inherit_language) {
487                 if (tmplt.language() == inherit_language ||
488                         tmplt.language() == ignore_language ||
489                         tmplt.language() == default_language)
490                 {
491                         setLanguage(deflang);
492                 } else {
493                         setLanguage(tmplt.language());
494                 }
495         }
496 #endif
497         if (bits == inherit) {
498                 bits = tmplt.bits;
499                 return *this;
500         }
501
502         if (bits.family == INHERIT_FAMILY) {
503                 bits.family = tmplt.bits.family;
504         }
505         if (bits.series == INHERIT_SERIES) {
506                 bits.series = tmplt.bits.series;
507         }
508         if (bits.shape == INHERIT_SHAPE) {
509                 bits.shape = tmplt.bits.shape;
510         }
511         if (bits.size == INHERIT_SIZE) {
512                 bits.size = tmplt.bits.size;
513         }
514         if (bits.emph == INHERIT) {
515                 bits.emph = tmplt.bits.emph;
516         }
517         if (bits.underbar == INHERIT) {
518                 bits.underbar = tmplt.bits.underbar;
519         }
520         if (bits.noun == INHERIT) {
521                 bits.noun = tmplt.bits.noun;
522         }
523         if (bits.color == LColor::inherit) {
524                 bits.color = tmplt.bits.color;
525         }
526         return *this;
527 }
528
529
530 /// Is font resolved?
531 bool LyXFont::resolved() const
532 {
533         return (family() != INHERIT_FAMILY && series() != INHERIT_SERIES &&
534                 shape() != INHERIT_SHAPE && size() != INHERIT_SIZE &&
535                 emph() != INHERIT && underbar() != INHERIT &&
536                 noun() != INHERIT &&
537 #ifdef INHERIT_LANGUAGE
538                 language() != inherit_language &&
539 #endif
540                 color() != LColor::inherit);
541 }
542
543
544 /// Build GUI description of font state
545 string const LyXFont::stateText(BufferParams * params) const
546 {
547         ostringstream ost;
548         if (family() != INHERIT_FAMILY)
549                 ost << _(GUIFamilyNames[family()]) << ", ";
550         if (series() != INHERIT_SERIES)
551                 ost << _(GUISeriesNames[series()]) << ", ";
552         if (shape() != INHERIT_SHAPE)
553                 ost << _(GUIShapeNames[shape()]) << ", ";
554         if (size() != INHERIT_SIZE)
555                 ost << _(GUISizeNames[size()]) << ", ";
556         if (color() != LColor::inherit)
557                 ost << lcolor.getGUIName(color()) << ", ";
558         if (emph() != INHERIT)
559                 ost << _("Emphasis ")
560                     << _(GUIMiscNames[emph()]) << ", ";
561         if (underbar() != INHERIT)
562                 ost << _("Underline ")
563                     << _(GUIMiscNames[underbar()]) << ", ";
564         if (noun() != INHERIT)
565                 ost << _("Noun ") << _(GUIMiscNames[noun()]) << ", ";
566         if (bits == inherit)
567                 ost << _("Default") << ", ";
568         if (!params || (language() != params->language))
569                 ost << _("Language: ") << _(language()->display()) << ", ";
570         if (number() != OFF)
571                 ost << _("  Number ") << _(GUIMiscNames[number()]);
572
573         string buf(ost.str().c_str());
574         buf = rtrim(buf, ", ");
575         return buf;
576 }
577
578
579 // Set family according to lyx format string
580 LyXFont & LyXFont::setLyXFamily(string const & fam)
581 {
582         string const s = ascii_lowercase(fam);
583
584         int i = 0;
585         while (s != LyXFamilyNames[i] && LyXFamilyNames[i] != "error") ++i;
586         if (s == LyXFamilyNames[i]) {
587                 setFamily(LyXFont::FONT_FAMILY(i));
588         } else
589                 lyxerr << "LyXFont::setLyXFamily: Unknown family `"
590                        << s << '\'' << endl;
591         return *this;
592 }
593
594
595 // Set series according to lyx format string
596 LyXFont & LyXFont::setLyXSeries(string const & ser)
597 {
598         string const s = ascii_lowercase(ser);
599
600         int i = 0;
601         while (s != LyXSeriesNames[i] && LyXSeriesNames[i] != "error") ++i;
602         if (s == LyXSeriesNames[i]) {
603                 setSeries(LyXFont::FONT_SERIES(i));
604         } else
605                 lyxerr << "LyXFont::setLyXSeries: Unknown series `"
606                        << s << '\'' << endl;
607         return *this;
608 }
609
610
611 // Set shape according to lyx format string
612 LyXFont & LyXFont::setLyXShape(string const & sha)
613 {
614         string const s = ascii_lowercase(sha);
615
616         int i = 0;
617         while (s != LyXShapeNames[i] && LyXShapeNames[i] != "error") ++i;
618         if (s == LyXShapeNames[i]) {
619                 setShape(LyXFont::FONT_SHAPE(i));
620         } else
621                 lyxerr << "LyXFont::setLyXShape: Unknown shape `"
622                        << s << '\'' << endl;
623         return *this;
624 }
625
626
627 // Set size according to lyx format string
628 LyXFont & LyXFont::setLyXSize(string const & siz)
629 {
630         string const s = ascii_lowercase(siz);
631         int i = 0;
632         while (s != LyXSizeNames[i] && LyXSizeNames[i] != "error") ++i;
633         if (s == LyXSizeNames[i]) {
634                 setSize(LyXFont::FONT_SIZE(i));
635         } else
636                 lyxerr << "LyXFont::setLyXSize: Unknown size `"
637                        << s << '\'' << endl;
638         return *this;
639 }
640
641
642 // Set size according to lyx format string
643 LyXFont::FONT_MISC_STATE LyXFont::setLyXMisc(string const & siz)
644 {
645         string const s = ascii_lowercase(siz);
646         int i = 0;
647         while (s != LyXMiscNames[i] && LyXMiscNames[i] != "error") ++i;
648         if (s == LyXMiscNames[i])
649                 return FONT_MISC_STATE(i);
650         lyxerr << "LyXFont::setLyXMisc: Unknown misc flag `"
651                << s << '\'' << endl;
652         return OFF;
653 }
654
655
656 /// Sets color after LyX text format
657 LyXFont & LyXFont::setLyXColor(string const & col)
658 {
659         setColor(lcolor.getFromLyXName(col));
660         return *this;
661 }
662
663
664 // Returns size in latex format
665 string const LyXFont::latexSize() const
666 {
667         return LaTeXSizeNames[size()];
668 }
669
670
671 // Read a font definition from given file in lyx format
672 // Used for layouts
673 LyXFont & LyXFont::lyxRead(LyXLex & lex)
674 {
675         bool error = false;
676         bool finished = false;
677         while (!finished && lex.isOK() && !error) {
678                 lex.next();
679                 string const tok = ascii_lowercase(lex.getString());
680
681                 if (tok.empty()) {
682                         continue;
683                 } else if (tok == "endfont") {
684                         finished = true;
685                 } else if (tok == "family") {
686                         lex.next();
687                         string const ttok = lex.getString();
688                         setLyXFamily(ttok);
689                 } else if (tok == "series") {
690                         lex.next();
691                         string const ttok = lex.getString();
692                         setLyXSeries(ttok);
693                 } else if (tok == "shape") {
694                         lex.next();
695                         string const ttok = lex.getString();
696                         setLyXShape(ttok);
697                 } else if (tok == "size") {
698                         lex.next();
699                         string const ttok = lex.getString();
700                         setLyXSize(ttok);
701                 } else if (tok == "misc") {
702                         lex.next();
703                         string const ttok = ascii_lowercase(lex.getString());
704
705                         if (ttok == "no_bar") {
706                                 setUnderbar(OFF);
707                         } else if (ttok == "no_emph") {
708                                 setEmph(OFF);
709                         } else if (ttok == "no_noun") {
710                                 setNoun(OFF);
711                         } else if (ttok == "emph") {
712                                 setEmph(ON);
713                         } else if (ttok == "underbar") {
714                                 setUnderbar(ON);
715                         } else if (ttok == "noun") {
716                                 setNoun(ON);
717                         } else {
718                                 lex.printError("Illegal misc type `$$Token´");
719                         }
720                 } else if (tok == "color") {
721                         lex.next();
722                         string const ttok = lex.getString();
723                         setLyXColor(ttok);
724                 } else {
725                         lex.printError("Unknown tag `$$Token'");
726                         error = true;
727                 }
728         }
729         return *this;
730 }
731
732
733 /// Writes the changes from this font to orgfont in .lyx format in file
734 void LyXFont::lyxWriteChanges(LyXFont const & orgfont,
735 #ifdef INHERIT_LANGUAGE
736                               Language const * doclang,
737 #endif
738                               ostream & os) const
739 {
740         os << "\n";
741         if (orgfont.family() != family()) {
742                 os << "\\family " << LyXFamilyNames[family()] << " \n";
743         }
744         if (orgfont.series() != series()) {
745                 os << "\\series " << LyXSeriesNames[series()] << " \n";
746         }
747         if (orgfont.shape() != shape()) {
748                 os << "\\shape " << LyXShapeNames[shape()] << " \n";
749         }
750         if (orgfont.size() != size()) {
751                 os << "\\size " << LyXSizeNames[size()] << " \n";
752         }
753         if (orgfont.emph() != emph()) {
754                 os << "\\emph " << LyXMiscNames[emph()] << " \n";
755         }
756         if (orgfont.number() != number()) {
757                 os << "\\numeric " << LyXMiscNames[number()] << " \n";
758         }
759         if (orgfont.underbar() != underbar()) {
760                 // This is only for backwards compatibility
761                 switch (underbar()) {
762                 case OFF:       os << "\\bar no \n"; break;
763                 case ON:        os << "\\bar under \n"; break;
764                 case TOGGLE:    lyxerr << "LyXFont::lyxWriteFontChanges: "
765                                         "TOGGLE should not appear here!"
766                                        << endl;
767                 break;
768                 case INHERIT:   os << "\\bar default \n"; break;
769                 case IGNORE:    lyxerr << "LyXFont::lyxWriteFontChanges: "
770                                         "IGNORE should not appear here!"
771                                        << endl;
772                 break;
773                 }
774         }
775         if (orgfont.noun() != noun()) {
776                 os << "\\noun " << LyXMiscNames[noun()] << " \n";
777         }
778         if (orgfont.color() != color()) {
779                 // To make us file compatible with older
780                 // lyx versions we emit "default" instead
781                 // of "inherit"
782                 string col_str(lcolor.getLyXName(color()));
783                 if (col_str == "inherit") col_str = "default";
784                 os << "\\color " << col_str << "\n";
785         }
786         if (orgfont.language() != language()) {
787 #ifndef INHERIT_LANGUAGE
788                 if (language())
789 #else
790                 if (language() == inherit_language)
791                         os << "\\lang " << doclang->lang() << "\n";
792                 else if (language())
793 #endif
794                         os << "\\lang " << language()->lang() << "\n";
795                 else
796                         os << "\\lang unknown\n";
797         }
798 }
799
800
801 /// Writes the head of the LaTeX needed to impose this font
802 // Returns number of chars written.
803 int LyXFont::latexWriteStartChanges(ostream & os, LyXFont const & base,
804                                     LyXFont const & prev) const
805 {
806         int count = 0;
807         bool env = false;
808
809         if (language()->babel() != base.language()->babel() &&
810             language() != prev.language()) {
811                 if (isRightToLeft() != prev.isRightToLeft()) {
812                         if (isRightToLeft()) {
813                                 os << "\\R{";
814                                 count += 3;
815                         } else {
816                                 os << "\\L{";
817                                 count += 3;
818                         }
819                 } else {
820                         string const tmp =
821                                 subst(lyxrc.language_command_local,
822                                       "$$lang", language()->babel());
823                         os << tmp;
824                         count += tmp.length();
825                 }
826         }
827
828         if (number() == ON && prev.number() != ON &&
829             language()->lang() == "hebrew") {
830                 os << "{\\beginL ";
831                 count += 9;
832         }
833
834         LyXFont f = *this;
835         f.reduce(base);
836
837         if (f.family() != INHERIT_FAMILY) {
838                 os << '\\'
839                    << LaTeXFamilyNames[f.family()]
840                    << '{';
841                 count += strlen(LaTeXFamilyNames[f.family()]) + 2;
842                 env = true; //We have opened a new environment
843         }
844         if (f.series() != INHERIT_SERIES) {
845                 os << '\\'
846                    << LaTeXSeriesNames[f.series()]
847                    << '{';
848                 count += strlen(LaTeXSeriesNames[f.series()]) + 2;
849                 env = true; //We have opened a new environment
850         }
851         if (f.shape() != INHERIT_SHAPE) {
852                 os << '\\'
853                    << LaTeXShapeNames[f.shape()]
854                    << '{';
855                 count += strlen(LaTeXShapeNames[f.shape()]) + 2;
856                 env = true; //We have opened a new environment
857         }
858         if (f.color() != LColor::inherit && f.color() != LColor::ignore) {
859                 os << "\\textcolor{"
860                    << lcolor.getLaTeXName(f.color())
861                    << "}{";
862                 count += lcolor.getLaTeXName(f.color()).length() + 13;
863                 env = true; //We have opened a new environment
864         }
865         if (f.emph() == ON) {
866                 os << "\\emph{";
867                 count += 6;
868                 env = true; //We have opened a new environment
869         }
870         if (f.underbar() == ON) {
871                 os << "\\underbar{";
872                 count += 10;
873                 env = true; //We have opened a new environment
874         }
875         // \noun{} is a LyX special macro
876         if (f.noun() == ON) {
877                 os << "\\noun{";
878                 count += 8;
879                 env = true; //We have opened a new environment
880         }
881         if (f.size() != INHERIT_SIZE) {
882                 // If we didn't open an environment above, we open one here
883                 if (!env) {
884                         os << '{';
885                         ++count;
886                 }
887                 os << '\\'
888                    << LaTeXSizeNames[f.size()]
889                    << ' ';
890                 count += strlen(LaTeXSizeNames[f.size()]) + 2;
891         }
892         return count;
893 }
894
895
896 /// Writes ending block of LaTeX needed to close use of this font
897 // Returns number of chars written
898 // This one corresponds to latexWriteStartChanges(). (Asger)
899 int LyXFont::latexWriteEndChanges(ostream & os, LyXFont const & base,
900                                   LyXFont const & next) const
901 {
902         int count = 0;
903         bool env = false;
904
905         // reduce the current font to changes against the base
906         // font (of the layout). We use a temporary for this to
907         // avoid changing this font instance, as that would break
908         LyXFont f = *this;
909         f.reduce(base);
910
911         if (f.family() != INHERIT_FAMILY) {
912                 os << '}';
913                 ++count;
914                 env = true; // Size change need not bother about closing env.
915         }
916         if (f.series() != INHERIT_SERIES) {
917                 os << '}';
918                 ++count;
919                 env = true; // Size change need not bother about closing env.
920         }
921         if (f.shape() != INHERIT_SHAPE) {
922                 os << '}';
923                 ++count;
924                 env = true; // Size change need not bother about closing env.
925         }
926         if (f.color() != LColor::inherit && f.color() != LColor::ignore) {
927                 os << '}';
928                 ++count;
929                 env = true; // Size change need not bother about closing env.
930         }
931         if (f.emph() == ON) {
932                 os << '}';
933                 ++count;
934                 env = true; // Size change need not bother about closing env.
935         }
936         if (f.underbar() == ON) {
937                 os << '}';
938                 ++count;
939                 env = true; // Size change need not bother about closing env.
940         }
941         if (f.noun() == ON) {
942                 os << '}';
943                 ++count;
944                 env = true; // Size change need not bother about closing env.
945         }
946         if (f.size() != INHERIT_SIZE) {
947                 // We only have to close if only size changed
948                 if (!env) {
949                         os << '}';
950                         ++count;
951                 }
952         }
953
954         if (number() == ON && next.number() != ON &&
955             language()->lang() == "hebrew") {
956                 os << "\\endL}";
957                 count += 6;
958         }
959
960         if (language() != base.language() && language() != next.language()) {
961                 os << "}";
962                 ++count;
963         }
964
965         return count;
966 }
967
968
969 LColor::color LyXFont::realColor() const
970 {
971         if (color() == LColor::none)
972                 return LColor::foreground;
973         return color();
974 }
975
976
977 // Convert logical attributes to concrete shape attribute
978 LyXFont::FONT_SHAPE LyXFont::realShape() const
979 {
980         register FONT_SHAPE s = shape();
981
982         if (emph() == ON) {
983                 if (s == UP_SHAPE)
984                         s = ITALIC_SHAPE;
985                 else
986                         s = UP_SHAPE;
987         }
988         if (noun() == ON)
989                 s = SMALLCAPS_SHAPE;
990         return s;
991 }
992
993
994 ostream & operator<<(ostream & o, LyXFont::FONT_MISC_STATE fms)
995 {
996         return o << int(fms);
997 }