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