]> git.lyx.org Git - lyx.git/blob - src/bufferparams.C
The "I want this in now" patch.
[lyx.git] / src / bufferparams.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
13 #include "bufferparams.h"
14 #include "tex-strings.h"
15 #include "encoding.h"
16 #include "layout.h"
17 #include "vspace.h"
18 #include "debug.h"
19 #include "lyxrc.h"
20 #include "language.h"
21 #include "lyxtextclasslist.h"
22 #include "lyxlex.h"
23 #include "Lsstream.h"
24 #include "author.h"
25 #include "gettext.h"
26
27 #include "support/lyxalgo.h" // for lyx::count
28 #include "support/lyxlib.h"
29 #include "support/lstrings.h"
30 #include "support/types.h"
31
32 #include "frontends/Alert.h"
33
34 #include <cstdlib>
35 #include <algorithm>
36
37 using std::ostream;
38 using std::endl;
39 using std::pair;
40
41 #ifdef WITH_WARNINGS
42 #warning Do we need this horrible thing? (JMarc)
43 #endif
44 bool use_babel;
45
46
47 BufferParams::BufferParams()
48         // Initialize textclass to point to article. if `first' is
49         // true in the returned pair, then `second' is the textclass
50         // number; if it is false, second is 0. In both cases, second
51         // is what we want.
52         : textclass(textclasslist.NumberOfClass("article").second)
53 {
54         paragraph_separation = PARSEP_INDENT;
55         defskip = VSpace(VSpace::MEDSKIP);
56         quotes_language = InsetQuotes::EnglishQ;
57         quotes_times = InsetQuotes::DoubleQ;
58         fontsize = "default";
59
60         /*  PaperLayout */
61         papersize = PAPER_DEFAULT;
62         papersize2 = VM_PAPER_DEFAULT; /* DEFAULT */
63         paperpackage = PACKAGE_NONE;
64         orientation = ORIENTATION_PORTRAIT;
65         use_geometry = false;
66         use_amsmath = AMS_AUTO;
67         use_natbib = false;
68         use_numerical_citations = false;
69         tracking_changes = false;
70         secnumdepth = 3;
71         tocdepth = 3;
72         language = default_language;
73         fonts = "default";
74         inputenc = "auto";
75         graphicsDriver = "default";
76         sides = LyXTextClass::OneSide;
77         columns = 1;
78         pagestyle = "default";
79         for (int iter = 0; iter < 4; ++iter) {
80                 user_defined_bullets[iter] = ITEMIZE_DEFAULTS[iter];
81                 temp_bullets[iter] = ITEMIZE_DEFAULTS[iter];
82         }
83 }
84
85
86 string const BufferParams::readToken(LyXLex & lex, string const & token)
87 {
88         if (token == "\\textclass") {
89                 lex.eatLine();
90                 string const classname = lex.getString();
91                 pair<bool, lyx::textclass_type> pp =
92                         textclasslist.NumberOfClass(classname);
93                 if (pp.first) {
94                         textclass = pp.second;
95                 } else {
96                         textclass = 0;
97                         return classname;
98                 }
99                 if (!getLyXTextClass().isTeXClassAvailable()) {
100                         string msg = bformat(_("The document uses a missing "
101                                 "TeX class \"%1$s\".\n"), classname);
102                         Alert::warning(_("Document class not available"),
103                                        msg + _("LyX will not be able to produce output."));
104                 }
105         } else if (token == "\\begin_preamble") {
106                 readPreamble(lex);
107         } else if (token == "\\options") {
108                 lex.eatLine();
109                 options = lex.getString();
110         } else if (token == "\\language") {
111                 readLanguage(lex);
112         } else if (token == "\\inputencoding") {
113                 lex.eatLine();
114                 inputenc = lex.getString();
115         } else if (token == "\\graphics") {
116                 readGraphicsDriver(lex);
117         } else if (token == "\\fontscheme") {
118                 lex.eatLine();
119                 fonts = lex.getString();
120         } else if (token == "\\paragraph_separation") {
121                 int tmpret = lex.findToken(string_paragraph_separation);
122                 if (tmpret == -1)
123                         ++tmpret;
124                 paragraph_separation =
125                         static_cast<BufferParams::PARSEP>(tmpret);
126         } else if (token == "\\defskip") {
127                 lex.nextToken();
128                 defskip = VSpace(lex.getString());
129         } else if (token == "\\quotes_language") {
130                 // FIXME: should be params.readQuotes()
131                 int tmpret = lex.findToken(string_quotes_language);
132                 if (tmpret == -1)
133                         ++tmpret;
134                 InsetQuotes::quote_language tmpl =
135                         InsetQuotes::EnglishQ;
136                 switch (tmpret) {
137                 case 0:
138                         tmpl = InsetQuotes::EnglishQ;
139                         break;
140                 case 1:
141                         tmpl = InsetQuotes::SwedishQ;
142                         break;
143                 case 2:
144                         tmpl = InsetQuotes::GermanQ;
145                         break;
146                 case 3:
147                         tmpl = InsetQuotes::PolishQ;
148                         break;
149                 case 4:
150                         tmpl = InsetQuotes::FrenchQ;
151                         break;
152                 case 5:
153                         tmpl = InsetQuotes::DanishQ;
154                         break;
155                 }
156                 quotes_language = tmpl;
157         } else if (token == "\\quotes_times") {
158                 // FIXME: should be params.readQuotes()
159                 lex.nextToken();
160                 switch (lex.getInteger()) {
161                 case 1:
162                         quotes_times = InsetQuotes::SingleQ;
163                         break;
164                 case 2:
165                         quotes_times = InsetQuotes::DoubleQ;
166                         break;
167                 }
168         } else if (token == "\\papersize") {
169                 int tmpret = lex.findToken(string_papersize);
170                 if (tmpret == -1)
171                         ++tmpret;
172                 else
173                         papersize2 = tmpret;
174         } else if (token == "\\paperpackage") {
175                 int tmpret = lex.findToken(string_paperpackages);
176                 if (tmpret == -1) {
177                         ++tmpret;
178                         paperpackage = BufferParams::PACKAGE_NONE;
179                 } else
180                         paperpackage = tmpret;
181         } else if (token == "\\use_geometry") {
182                 lex.nextToken();
183                 use_geometry = lex.getInteger();
184         } else if (token == "\\use_amsmath") {
185                 lex.nextToken();
186                 use_amsmath = static_cast<BufferParams::AMS>(
187                         lex.getInteger());
188         } else if (token == "\\use_natbib") {
189                 lex.nextToken();
190                 use_natbib = lex.getInteger();
191         } else if (token == "\\use_numerical_citations") {
192                 lex.nextToken();
193                 use_numerical_citations = lex.getInteger();
194         } else if (token == "\\tracking_changes") {
195                 lex.nextToken();
196                 tracking_changes = lex.getInteger();
197         } else if (token == "\\author") {
198                 lex.nextToken();
199                 istringstream ss(STRCONV(lex.getString()));
200                 Author a;
201                 ss >> a;
202                 author_map.push_back(authorlist.record(a));
203         } else if (token == "\\paperorientation") {
204                 int tmpret = lex.findToken(string_orientation);
205                 if (tmpret == -1)
206                         ++tmpret;
207                 orientation =
208                         static_cast<BufferParams::PAPER_ORIENTATION>(tmpret);
209         } else if (token == "\\paperwidth") {
210                 lex.next();
211                 paperwidth = lex.getString();
212         } else if (token == "\\paperheight") {
213                 lex.next();
214                 paperheight = lex.getString();
215         } else if (token == "\\leftmargin") {
216                 lex.next();
217                 leftmargin = lex.getString();
218         } else if (token == "\\topmargin") {
219                 lex.next();
220                 topmargin = lex.getString();
221         } else if (token == "\\rightmargin") {
222                 lex.next();
223                 rightmargin = lex.getString();
224         } else if (token == "\\bottommargin") {
225                 lex.next();
226                 bottommargin = lex.getString();
227         } else if (token == "\\headheight") {
228                 lex.next();
229                 headheight = lex.getString();
230         } else if (token == "\\headsep") {
231                 lex.next();
232                 headsep = lex.getString();
233         } else if (token == "\\footskip") {
234                 lex.next();
235                 footskip = lex.getString();
236         } else if (token == "\\paperfontsize") {
237                 lex.nextToken();
238                 fontsize = rtrim(lex.getString());
239         } else if (token == "\\papercolumns") {
240                 lex.nextToken();
241                 columns = lex.getInteger();
242         } else if (token == "\\papersides") {
243                 lex.nextToken();
244                 switch (lex.getInteger()) {
245                 default:
246                 case 1: sides = LyXTextClass::OneSide; break;
247                 case 2: sides = LyXTextClass::TwoSides; break;
248                 }
249         } else if (token == "\\paperpagestyle") {
250                 lex.nextToken();
251                 pagestyle = rtrim(lex.getString());
252         } else if (token == "\\bullet") {
253                 // FIXME: should be params.readBullets()
254                 lex.nextToken();
255                 int const index = lex.getInteger();
256                 lex.nextToken();
257                 int temp_int = lex.getInteger();
258                 user_defined_bullets[index].setFont(temp_int);
259                 temp_bullets[index].setFont(temp_int);
260                 lex.nextToken();
261                 temp_int = lex.getInteger();
262                 user_defined_bullets[index].setCharacter(temp_int);
263                 temp_bullets[index].setCharacter(temp_int);
264                 lex.nextToken();
265                 temp_int = lex.getInteger();
266                 user_defined_bullets[index].setSize(temp_int);
267                 temp_bullets[index].setSize(temp_int);
268                 lex.nextToken();
269                 string const temp_str = lex.getString();
270                 if (temp_str != "\\end_bullet") {
271                                 // this element isn't really necessary for
272                                 // parsing but is easier for humans
273                                 // to understand bullets. Put it back and
274                                 // set a debug message?
275                         lex.printError("\\end_bullet expected, got" + temp_str);
276                                 //how can I put it back?
277                 }
278         } else if (token == "\\bulletLaTeX") {
279                 // The bullet class should be able to read this.
280                 lex.nextToken();
281                 int const index = lex.getInteger();
282                 lex.next();
283                 string temp_str = lex.getString();
284                 string sum_str;
285                 while (temp_str != "\\end_bullet") {
286                                 // this loop structure is needed when user
287                                 // enters an empty string since the first
288                                 // thing returned will be the \\end_bullet
289                                 // OR
290                                 // if the LaTeX entry has spaces. Each element
291                                 // therefore needs to be read in turn
292                         sum_str += temp_str;
293                         lex.next();
294                         temp_str = lex.getString();
295                 }
296
297                 user_defined_bullets[index].setText(sum_str);
298                 temp_bullets[index].setText(sum_str);
299         } else if (token == "\\secnumdepth") {
300                 lex.nextToken();
301                 secnumdepth = lex.getInteger();
302         } else if (token == "\\tocdepth") {
303                 lex.nextToken();
304                 tocdepth = lex.getInteger();
305         } else if (token == "\\spacing") {
306                 lex.next();
307                 string const tmp = rtrim(lex.getString());
308                 Spacing::Space tmp_space = Spacing::Default;
309                 float tmp_val = 0.0;
310                 if (tmp == "single") {
311                         tmp_space = Spacing::Single;
312                 } else if (tmp == "onehalf") {
313                         tmp_space = Spacing::Onehalf;
314                 } else if (tmp == "double") {
315                         tmp_space = Spacing::Double;
316                 } else if (tmp == "other") {
317                         lex.next();
318                         tmp_space = Spacing::Other;
319                         tmp_val = lex.getFloat();
320                 } else {
321                         lex.printError("Unknown spacing token: '$$Token'");
322                 }
323 #if 0 // FIXME: Handled in lyx2lyx ?
324                 // Small hack so that files written with klyx will be
325                 // parsed correctly.
326                 if (first_par)
327                         par->params().spacing(Spacing(tmp_space, tmp_val));
328 #endif
329                 spacing.set(tmp_space, tmp_val);
330         } else if (token == "\\float_placement") {
331                 lex.nextToken();
332                 float_placement = lex.getString();
333         } else {
334                 return token;
335         }
336
337         return string();
338 }
339
340
341 void BufferParams::writeFile(ostream & os) const
342 {
343         // The top of the file is written by the buffer.
344         // Prints out the buffer info into the .lyx file given by file
345
346         // the textclass
347         os << "\\textclass " << textclasslist[textclass].name() << '\n';
348
349         // then the the preamble
350         if (!preamble.empty()) {
351                 // remove '\n' from the end of preamble
352                 string const tmppreamble = rtrim(preamble, "\n");
353                 os << "\\begin_preamble\n"
354                    << tmppreamble
355                    << "\n\\end_preamble\n";
356         }
357
358         /* the options */
359         if (!options.empty()) {
360                 os << "\\options " << options << '\n';
361         }
362
363         /* then the text parameters */
364         if (language != ignore_language)
365                 os << "\\language " << language->lang() << '\n';
366         os << "\\inputencoding " << inputenc
367            << "\n\\fontscheme " << fonts
368            << "\n\\graphics " << graphicsDriver << '\n';
369
370         if (!float_placement.empty()) {
371                 os << "\\float_placement " << float_placement << '\n';
372         }
373         os << "\\paperfontsize " << fontsize << '\n';
374
375         spacing.writeFile(os);
376
377         os << "\\papersize " << string_papersize[papersize2]
378            << "\n\\paperpackage " << string_paperpackages[paperpackage]
379            << "\n\\use_geometry " << use_geometry
380            << "\n\\use_amsmath " << use_amsmath
381            << "\n\\use_natbib " << use_natbib
382            << "\n\\use_numerical_citations " << use_numerical_citations
383            << "\n\\paperorientation " << string_orientation[orientation]
384            << '\n';
385         if (!paperwidth.empty())
386                 os << "\\paperwidth "
387                    << VSpace(paperwidth).asLyXCommand() << '\n';
388         if (!paperheight.empty())
389                 os << "\\paperheight "
390                    << VSpace(paperheight).asLyXCommand() << '\n';
391         if (!leftmargin.empty())
392                 os << "\\leftmargin "
393                    << VSpace(leftmargin).asLyXCommand() << '\n';
394         if (!topmargin.empty())
395                 os << "\\topmargin "
396                    << VSpace(topmargin).asLyXCommand() << '\n';
397         if (!rightmargin.empty())
398                 os << "\\rightmargin "
399                    << VSpace(rightmargin).asLyXCommand() << '\n';
400         if (!bottommargin.empty())
401                 os << "\\bottommargin "
402                    << VSpace(bottommargin).asLyXCommand() << '\n';
403         if (!headheight.empty())
404                 os << "\\headheight "
405                    << VSpace(headheight).asLyXCommand() << '\n';
406         if (!headsep.empty())
407                 os << "\\headsep "
408                    << VSpace(headsep).asLyXCommand() << '\n';
409         if (!footskip.empty())
410                 os << "\\footskip "
411                    << VSpace(footskip).asLyXCommand() << '\n';
412         os << "\\secnumdepth " << secnumdepth
413            << "\n\\tocdepth " << tocdepth
414            << "\n\\paragraph_separation "
415            << string_paragraph_separation[paragraph_separation]
416            << "\n\\defskip " << defskip.asLyXCommand()
417            << "\n\\quotes_language "
418            << string_quotes_language[quotes_language] << '\n';
419         switch (quotes_times) {
420                 // An output operator for insetquotes would be nice
421         case InsetQuotes::SingleQ:
422                 os << "\\quotes_times 1\n"; break;
423         case InsetQuotes::DoubleQ:
424                 os << "\\quotes_times 2\n"; break;
425         }
426         os << "\\papercolumns " << columns
427            << "\n\\papersides " << sides
428            << "\n\\paperpagestyle " << pagestyle << '\n';
429         for (int i = 0; i < 4; ++i) {
430                 if (user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
431                         if (user_defined_bullets[i].getFont() != -1) {
432                                 os << "\\bullet " << i
433                                    << "\n\t"
434                                    << user_defined_bullets[i].getFont()
435                                    << "\n\t"
436                                    << user_defined_bullets[i].getCharacter()
437                                    << "\n\t"
438                                    << user_defined_bullets[i].getSize()
439                                    << "\n\\end_bullet\n";
440                         }
441                         else {
442                                 os << "\\bulletLaTeX " << i
443                                    << "\n\t\""
444                                    << user_defined_bullets[i].getText()
445                                    << "\"\n\\end_bullet\n";
446                         }
447                 }
448         }
449
450         os << "\\tracking_changes " << tracking_changes << "\n";
451
452         if (tracking_changes) {
453                 AuthorList::Authors::const_iterator it = authorlist.begin();
454                 AuthorList::Authors::const_iterator end = authorlist.end();
455                 for (; it != end; ++it) {
456                         os << "\\author " << it->second << "\n";
457                 }
458         }
459 }
460
461
462 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
463                               TexRow & texrow) const
464 {
465         os << "\\documentclass";
466
467         LyXTextClass const & tclass = getLyXTextClass();
468
469         ostringstream clsoptions; // the document class options.
470
471         if (tokenPos(tclass.opt_fontsize(),
472                      '|', fontsize) >= 0) {
473                 // only write if existing in list (and not default)
474                 clsoptions << fontsize << "pt,";
475         }
476
477
478         if (!use_geometry &&
479             (paperpackage == PACKAGE_NONE)) {
480                 switch (papersize) {
481                 case PAPER_A4PAPER:
482                         clsoptions << "a4paper,";
483                         break;
484                 case PAPER_USLETTER:
485                         clsoptions << "letterpaper,";
486                         break;
487                 case PAPER_A5PAPER:
488                         clsoptions << "a5paper,";
489                         break;
490                 case PAPER_B5PAPER:
491                         clsoptions << "b5paper,";
492                         break;
493                 case PAPER_EXECUTIVEPAPER:
494                         clsoptions << "executivepaper,";
495                         break;
496                 case PAPER_LEGALPAPER:
497                         clsoptions << "legalpaper,";
498                         break;
499                 }
500         }
501
502         // if needed
503         if (sides != tclass.sides()) {
504                 switch (sides) {
505                 case LyXTextClass::OneSide:
506                         clsoptions << "oneside,";
507                         break;
508                 case LyXTextClass::TwoSides:
509                         clsoptions << "twoside,";
510                         break;
511                 }
512         }
513
514         // if needed
515         if (columns != tclass.columns()) {
516                 if (columns == 2)
517                         clsoptions << "twocolumn,";
518                 else
519                         clsoptions << "onecolumn,";
520         }
521
522         if (!use_geometry
523             && orientation == ORIENTATION_LANDSCAPE)
524                 clsoptions << "landscape,";
525
526         // language should be a parameter to \documentclass
527         use_babel = false;
528         ostringstream language_options;
529         if (language->babel() == "hebrew"
530             && default_language->babel() != "hebrew")
531                 // This seems necessary
532                 features.useLanguage(default_language);
533
534         if (lyxrc.language_use_babel ||
535             language->lang() != lyxrc.default_language ||
536             features.hasLanguages()) {
537                 use_babel = true;
538                 language_options << features.getLanguages();
539                 language_options << language->babel();
540                 if (lyxrc.language_global_options)
541                         clsoptions << language_options.str() << ',';
542         }
543
544         // the user-defined options
545         if (!options.empty()) {
546                 clsoptions << options << ',';
547         }
548
549         string strOptions(STRCONV(clsoptions.str()));
550         if (!strOptions.empty()) {
551                 strOptions = rtrim(strOptions, ",");
552                 os << '[' << strOptions << ']';
553         }
554
555         os << '{' << tclass.latexname() << "}\n";
556         texrow.newline();
557         // end of \documentclass defs
558
559         // font selection must be done before loading fontenc.sty
560         // The ae package is not needed when using OT1 font encoding.
561         if (fonts != "default" &&
562             (fonts != "ae" || lyxrc.fontenc != "default")) {
563                 os << "\\usepackage{" << fonts << "}\n";
564                 texrow.newline();
565                 if (fonts == "ae") {
566                         os << "\\usepackage{aecompl}\n";
567                         texrow.newline();
568                 }
569         }
570         // this one is not per buffer
571         if (lyxrc.fontenc != "default") {
572                 os << "\\usepackage[" << lyxrc.fontenc
573                    << "]{fontenc}\n";
574                 texrow.newline();
575         }
576
577         if (inputenc == "auto") {
578                 string const doc_encoding =
579                         language->encoding()->LatexName();
580
581                 // Create a list with all the input encodings used
582                 // in the document
583                 std::set<string> encodings =
584                         features.getEncodingSet(doc_encoding);
585
586                 os << "\\usepackage[";
587                 std::copy(encodings.begin(), encodings.end(),
588                           std::ostream_iterator<string>(os, ","));
589                 os << doc_encoding << "]{inputenc}\n";
590                 texrow.newline();
591         } else if (inputenc != "default") {
592                 os << "\\usepackage[" << inputenc
593                    << "]{inputenc}\n";
594                 texrow.newline();
595         }
596
597         // At the very beginning the text parameters.
598         if (paperpackage != PACKAGE_NONE) {
599                 switch (paperpackage) {
600                 case PACKAGE_A4:
601                         os << "\\usepackage{a4}\n";
602                         texrow.newline();
603                         break;
604                 case PACKAGE_A4WIDE:
605                         os << "\\usepackage{a4wide}\n";
606                         texrow.newline();
607                         break;
608                 case PACKAGE_WIDEMARGINSA4:
609                         os << "\\usepackage[widemargins]{a4}\n";
610                         texrow.newline();
611                         break;
612                 }
613         }
614         if (use_geometry) {
615                 os << "\\usepackage{geometry}\n";
616                 texrow.newline();
617                 os << "\\geometry{verbose";
618                 if (orientation == ORIENTATION_LANDSCAPE)
619                         os << ",landscape";
620                 switch (papersize2) {
621                 case VM_PAPER_CUSTOM:
622                         if (!paperwidth.empty())
623                                 os << ",paperwidth="
624                                    << paperwidth;
625                         if (!paperheight.empty())
626                                 os << ",paperheight="
627                                    << paperheight;
628                         break;
629                 case VM_PAPER_USLETTER:
630                         os << ",letterpaper";
631                         break;
632                 case VM_PAPER_USLEGAL:
633                         os << ",legalpaper";
634                         break;
635                 case VM_PAPER_USEXECUTIVE:
636                         os << ",executivepaper";
637                         break;
638                 case VM_PAPER_A3:
639                         os << ",a3paper";
640                         break;
641                 case VM_PAPER_A4:
642                         os << ",a4paper";
643                         break;
644                 case VM_PAPER_A5:
645                         os << ",a5paper";
646                         break;
647                 case VM_PAPER_B3:
648                         os << ",b3paper";
649                         break;
650                 case VM_PAPER_B4:
651                         os << ",b4paper";
652                         break;
653                 case VM_PAPER_B5:
654                         os << ",b5paper";
655                         break;
656                 default:
657                                 // default papersize ie VM_PAPER_DEFAULT
658                         switch (lyxrc.default_papersize) {
659                         case PAPER_DEFAULT: // keep compiler happy
660                         case PAPER_USLETTER:
661                                 os << ",letterpaper";
662                                 break;
663                         case PAPER_LEGALPAPER:
664                                 os << ",legalpaper";
665                                 break;
666                         case PAPER_EXECUTIVEPAPER:
667                                 os << ",executivepaper";
668                                 break;
669                         case PAPER_A3PAPER:
670                                 os << ",a3paper";
671                                 break;
672                         case PAPER_A4PAPER:
673                                 os << ",a4paper";
674                                 break;
675                         case PAPER_A5PAPER:
676                                 os << ",a5paper";
677                                 break;
678                         case PAPER_B5PAPER:
679                                 os << ",b5paper";
680                                 break;
681                         }
682                 }
683                 if (!topmargin.empty())
684                         os << ",tmargin=" << topmargin;
685                 if (!bottommargin.empty())
686                         os << ",bmargin=" << bottommargin;
687                 if (!leftmargin.empty())
688                         os << ",lmargin=" << leftmargin;
689                 if (!rightmargin.empty())
690                         os << ",rmargin=" << rightmargin;
691                 if (!headheight.empty())
692                         os << ",headheight=" << headheight;
693                 if (!headsep.empty())
694                         os << ",headsep=" << headsep;
695                 if (!footskip.empty())
696                         os << ",footskip=" << footskip;
697                 os << "}\n";
698                 texrow.newline();
699         }
700
701         if (tokenPos(tclass.opt_pagestyle(),
702                      '|', pagestyle) >= 0) {
703                 if (pagestyle == "fancy") {
704                         os << "\\usepackage{fancyhdr}\n";
705                         texrow.newline();
706                 }
707                 os << "\\pagestyle{" << pagestyle << "}\n";
708                 texrow.newline();
709         }
710
711         if (secnumdepth != tclass.secnumdepth()) {
712                 os << "\\setcounter{secnumdepth}{"
713                    << secnumdepth
714                    << "}\n";
715                 texrow.newline();
716         }
717         if (tocdepth != tclass.tocdepth()) {
718                 os << "\\setcounter{tocdepth}{"
719                    << tocdepth
720                    << "}\n";
721                 texrow.newline();
722         }
723
724         if (paragraph_separation) {
725                 switch (defskip.kind()) {
726                 case VSpace::SMALLSKIP:
727                         os << "\\setlength\\parskip{\\smallskipamount}\n";
728                         break;
729                 case VSpace::MEDSKIP:
730                         os << "\\setlength\\parskip{\\medskipamount}\n";
731                         break;
732                 case VSpace::BIGSKIP:
733                         os << "\\setlength\\parskip{\\bigskipamount}\n";
734                         break;
735                 case VSpace::LENGTH:
736                         os << "\\setlength\\parskip{"
737                            << defskip.length().asLatexString()
738                            << "}\n";
739                         break;
740                 default: // should never happen // Then delete it.
741                         os << "\\setlength\\parskip{\\medskipamount}\n";
742                         break;
743                 }
744                 texrow.newline();
745
746                 os << "\\setlength\\parindent{0pt}\n";
747                 texrow.newline();
748         }
749
750         // Now insert the LyX specific LaTeX commands...
751
752         // The optional packages;
753         string lyxpreamble(features.getPackages());
754
755         // this might be useful...
756         lyxpreamble += "\n\\makeatletter\n";
757
758         // Some macros LyX will need
759         string tmppreamble(features.getMacros());
760
761         if (!tmppreamble.empty()) {
762                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
763                         "LyX specific LaTeX commands.\n"
764                         + tmppreamble + '\n';
765         }
766
767         // the text class specific preamble
768         tmppreamble = features.getTClassPreamble();
769         if (!tmppreamble.empty()) {
770                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
771                         "Textclass specific LaTeX commands.\n"
772                         + tmppreamble + '\n';
773         }
774
775         /* the user-defined preamble */
776         if (!preamble.empty()) {
777                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
778                         "User specified LaTeX commands.\n"
779                         + preamble + '\n';
780         }
781
782         // Itemize bullet settings need to be last in case the user
783         // defines their own bullets that use a package included
784         // in the user-defined preamble -- ARRae
785         // Actually it has to be done much later than that
786         // since some packages like frenchb make modifications
787         // at \begin{document} time -- JMarc
788         string bullets_def;
789         for (int i = 0; i < 4; ++i) {
790                 if (user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
791                         if (bullets_def.empty())
792                                 bullets_def="\\AtBeginDocument{\n";
793                         bullets_def += "  \\renewcommand{\\labelitemi";
794                         switch (i) {
795                                 // `i' is one less than the item to modify
796                         case 0:
797                                 break;
798                         case 1:
799                                 bullets_def += 'i';
800                                 break;
801                         case 2:
802                                 bullets_def += "ii";
803                                 break;
804                         case 3:
805                                 bullets_def += 'v';
806                                 break;
807                         }
808                         bullets_def += "}{" +
809                                 user_defined_bullets[i].getText()
810                                 + "}\n";
811                 }
812         }
813
814         if (!bullets_def.empty())
815                 lyxpreamble += bullets_def + "}\n\n";
816
817         // We try to load babel late, in case it interferes
818         // with other packages.
819         if (use_babel) {
820                 string tmp = lyxrc.language_package;
821                 if (!lyxrc.language_global_options
822                     && tmp == "\\usepackage{babel}")
823                         tmp = string("\\usepackage[") +
824                                 STRCONV(language_options.str()) +
825                                 "]{babel}";
826                 lyxpreamble += tmp + "\n";
827                 lyxpreamble += features.getBabelOptions();
828         }
829
830         lyxpreamble += "\\makeatother\n";
831
832         // dvipost settings come after everything else
833         if (tracking_changes) {
834                 lyxpreamble +=
835                         "\\dvipostlayout\n"
836                         "\\dvipost{osstart color push Red}\n"
837                         "\\dvipost{osend color pop}\n"
838                         "\\dvipost{cbstart color push Blue}\n"
839                         "\\dvipost{cbend color pop} \n";
840         }
841
842         int const nlines =
843                 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
844         for (int j = 0; j != nlines; ++j) {
845                 texrow.newline();
846         }
847
848         os << lyxpreamble;
849         return use_babel;
850 }
851
852 void BufferParams::setPaperStuff()
853 {
854         papersize = PAPER_DEFAULT;
855         char const c1 = paperpackage;
856         if (c1 == PACKAGE_NONE) {
857                 char const c2 = papersize2;
858                 if (c2 == VM_PAPER_USLETTER)
859                         papersize = PAPER_USLETTER;
860                 else if (c2 == VM_PAPER_USLEGAL)
861                         papersize = PAPER_LEGALPAPER;
862                 else if (c2 == VM_PAPER_USEXECUTIVE)
863                         papersize = PAPER_EXECUTIVEPAPER;
864                 else if (c2 == VM_PAPER_A3)
865                         papersize = PAPER_A3PAPER;
866                 else if (c2 == VM_PAPER_A4)
867                         papersize = PAPER_A4PAPER;
868                 else if (c2 == VM_PAPER_A5)
869                         papersize = PAPER_A5PAPER;
870                 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
871                          (c2 == VM_PAPER_B5))
872                         papersize = PAPER_B5PAPER;
873         } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
874                    (c1 == PACKAGE_WIDEMARGINSA4))
875                 papersize = PAPER_A4PAPER;
876 }
877
878
879 void BufferParams::useClassDefaults()
880 {
881         LyXTextClass const & tclass = textclasslist[textclass];
882
883         sides = tclass.sides();
884         columns = tclass.columns();
885         pagestyle = tclass.pagestyle();
886         options = tclass.options();
887         secnumdepth = tclass.secnumdepth();
888         tocdepth = tclass.tocdepth();
889 }
890
891
892 bool BufferParams::hasClassDefaults() const
893 {
894         LyXTextClass const & tclass = textclasslist[textclass];
895
896         return (sides == tclass.sides()
897                 && columns == tclass.columns()
898                 && pagestyle == tclass.pagestyle()
899                 && options == tclass.options()
900                 && secnumdepth == tclass.secnumdepth()
901                 && tocdepth == tclass.tocdepth());
902 }
903
904
905 LyXTextClass const & BufferParams::getLyXTextClass() const
906 {
907         return textclasslist[textclass];
908 }
909
910
911 void BufferParams::readPreamble(LyXLex & lex)
912 {
913         if (lex.getString() != "\\begin_preamble")
914                 lyxerr << "Error (BufferParams::readPreamble):"
915                         "consistency check failed." << endl;
916
917         preamble = lex.getLongString("\\end_preamble");
918 }
919
920
921 void BufferParams::readLanguage(LyXLex & lex)
922 {
923         if (!lex.next()) return;
924
925         string const tmptok = lex.getString();
926
927         // check if tmptok is part of tex_babel in tex-defs.h
928         language = languages.getLanguage(tmptok);
929         if (!language) {
930                 // Language tmptok was not found
931                 language = default_language;
932                 lyxerr << "Warning: Setting language `"
933                        << tmptok << "' to `" << language->lang()
934                        << "'." << endl;
935         }
936 }
937
938
939 void BufferParams::readGraphicsDriver(LyXLex & lex)
940 {
941         if (!lex.next()) return;
942
943         string const tmptok = lex.getString();
944         // check if tmptok is part of tex_graphics in tex_defs.h
945         int n = 0;
946         while (true) {
947                 string const test = tex_graphics[n++];
948
949                 if (test == tmptok) {
950                         graphicsDriver = tmptok;
951                         break;
952                 } else if (test == "last_item") {
953                         lex.printError(
954                                 "Warning: graphics driver `$$Token' not recognized!\n"
955                                 "         Setting graphics driver to `default'.\n");
956                         graphicsDriver = "default";
957                         break;
958                 }
959         }
960 }