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