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