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