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