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