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