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