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