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