]> git.lyx.org Git - lyx.git/blob - src/layout.C
Two small bugfixes for tabulars and cursor setting
[lyx.git] / src / layout.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-1999 The LyX Team.
8  *
9  * ======================================================*/
10
11 /* Change log:
12  * 
13  *  14/11/1995,   Pascal AndrĂ© <andre@via.ecp.fr>
14  *  Modified for external style definition. 
15  * 
16  *  15/11/1995,   Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
17  *  Modified to use binary search and a small pseudo lexical analyzer.
18  *  
19  *  29/03/1996,  Dirk Niggeman
20  *  Created classes LyXTextClass & LyXLayout.
21  * 
22  *  30/03/1996,  asierra
23  *  Created class LyxLex and improved the lexical analyzer. 
24  */
25
26 #include <config.h>
27
28 #ifdef __GNUG__
29 #pragma implementation
30 #endif
31
32 #include "definitions.h"
33 #include <cstdlib>
34 #include "layout.h"
35 #include "lyxlex.h"
36 #include "support/filetools.h"
37 #include "lyx_gui_misc.h"
38 #include "debug.h"
39 #include "gettext.h"
40
41 /* Global variable: textclass table */
42 LyXTextClassList lyxstyle;
43
44 // Reads the style files
45 void LyXSetStyle()
46 {
47         lyxerr.debug() << "LyXSetStyle: parsing configuration..." << endl;
48         
49         if (!lyxstyle.Read()) {
50                 lyxerr << "LyXSetStyle: an error occured during parsing.\n"
51                        << "             Exiting." << endl;
52                 exit(1);
53         }
54
55         lyxerr.debug() << "LyXSetStyle: configuration parsed." << endl;
56 }
57
58
59 //  The order of the LayoutTags enum is no more important. [asierra300396]
60 /* tags indexes */
61 enum _LayoutTags {
62         LT_ALIGN, LT_ALIGNPOSSIBLE, 
63         LT_BLOCK, LT_MARGIN,
64         LT_BOTTOMSEP, LT_CENTER, LT_CENTERED_TOP_ENVIRONMENT, LT_COLUMNS,
65         LT_COPYSTYLE, LT_OBSOLETEDBY,
66         LT_COMMAND, LT_COUNTER_CHAPTER, LT_COUNTER_ENUMI, LT_COUNTER_ENUMII,
67         LT_COUNTER_ENUMIII, LT_COUNTER_ENUMIV, LT_COUNTER_PARAGRAPH,
68         LT_COUNTER_SECTION, LT_COUNTER_SUBPARAGRAPH, LT_COUNTER_SUBSECTION,
69         LT_COUNTER_SUBSUBSECTION, LT_DEFAULTFONT, LT_DYNAMIC, LT_EMPTY,
70         LT_END, LT_ENVIRONMENT, LT_ENVIRONMENT_DEFAULT, 
71         LT_FANCYHDR, LT_FILL_BOTTOM, LT_FILL_TOP, LT_FIRST_COUNTER,
72         LT_FIRST_DYNAMIC, LT_FONT, LT_FREE_SPACING, LT_HEADINGS, LT_INPUT,
73         LT_ITEM_ENVIRONMENT, LT_ITEMSEP, LT_KEEPEMPTY,
74         LT_LABEL_BOTTOMSEP, LT_LABELFONT, LT_TEXTFONT,
75         LT_LABELINDENT, LT_LABELSEP, LT_LABELSTRING,
76         LT_LABELSTRING_APPENDIX, LT_LABELTYPE,
77         LT_LATEXNAME, LT_LATEXPARAM, LT_LATEXTYPE, LT_LAYOUT, LT_LEFT,
78         LT_LEFTMARGIN,
79         LT_LIST_ENVIRONMENT , LT_MANUAL, LT_MAXCOUNTER, 
80         LT_NEED_PROTECT, LT_NEWLINE,
81         LT_NEXTNOINDENT, LT_NO_LABEL, LT_NOSTYLE,
82         LT_PAGESTYLE, LT_PARAGRAPH,
83         LT_PARINDENT, LT_PARSEP, LT_PARSKIP, LT_PLAIN, LT_PREAMBLE, 
84         LT_PROVIDESAMSMATH, LT_PROVIDESMAKEIDX, LT_PROVIDESURL, LT_RIGHT,
85         LT_RIGHT_ADDRESS_BOX, LT_RIGHTMARGIN, LT_SENSITIVE, LT_SIDES,
86         LT_SPACING, LT_SPACING_SINGLE, LT_SPACING_ONEHALF,
87         LT_SPACING_DOUBLE, LT_OTHER,  LT_CLASSOPTIONS, LT_FONTSIZE,
88         LT_STATIC, LT_STYLE, LT_TOP_ENVIRONMENT, LT_TOPSEP, LT_BIBLIO,
89         LT_INTITLE, LT_SECNUMDEPTH, LT_TOCDEPTH,
90         LT_OUTPUTTYPE, LT_OTLATEX, LT_OTLINUXDOC, LT_OTDOCBOOK, LT_OTLITERATE
91 };
92
93
94 // This table is sorted alphabetically [asierra 30March96]
95 static keyword_item layoutTags[] = {
96         { "align",                      LT_ALIGN },
97         { "alignpossible",              LT_ALIGNPOSSIBLE },
98         { "bibliography",               LT_BIBLIO },
99         { "block",                      LT_BLOCK },
100         { "bottomsep",                  LT_BOTTOMSEP },
101         { "center",                     LT_CENTER },
102         { "centered_top_environment",   LT_CENTERED_TOP_ENVIRONMENT },
103         { "classoptions",               LT_CLASSOPTIONS },
104         { "columns",                    LT_COLUMNS },
105         { "command",                    LT_COMMAND },
106         { "copystyle",                  LT_COPYSTYLE },
107         { "counter_chapter",            LT_COUNTER_CHAPTER },
108         { "counter_enumi",              LT_COUNTER_ENUMI },
109         { "counter_enumii",             LT_COUNTER_ENUMII },
110         { "counter_enumiii",            LT_COUNTER_ENUMIII },
111         { "counter_enumiv",             LT_COUNTER_ENUMIV },
112         { "counter_paragraph",          LT_COUNTER_PARAGRAPH },
113         { "counter_section",            LT_COUNTER_SECTION },
114         { "counter_subparagraph",       LT_COUNTER_SUBPARAGRAPH },
115         { "counter_subsection",         LT_COUNTER_SUBSECTION },
116         { "counter_subsubsection",      LT_COUNTER_SUBSUBSECTION },
117         { "defaultfont",                LT_DEFAULTFONT },
118         { "docbook",                    LT_OTDOCBOOK },
119         { "double",                     LT_SPACING_DOUBLE },
120         { "dynamic",                    LT_DYNAMIC },
121         { "empty",                      LT_EMPTY },
122         { "end",                        LT_END },
123         { "environment",                LT_ENVIRONMENT },
124         { "environment_default",        LT_ENVIRONMENT_DEFAULT },
125         { "fancyhdr",                   LT_FANCYHDR },
126         { "fill_bottom",                LT_FILL_BOTTOM },
127         { "fill_top",                   LT_FILL_TOP },
128         { "first_counter",              LT_FIRST_COUNTER },
129         { "first_dynamic",              LT_FIRST_DYNAMIC },
130         { "font",                       LT_FONT },
131         { "fontsize",                   LT_FONTSIZE },
132         { "freespacing",                LT_FREE_SPACING },
133         { "headings",                   LT_HEADINGS },
134         { "input",                      LT_INPUT },
135         { "intitle",                    LT_INTITLE },
136         { "item_environment",           LT_ITEM_ENVIRONMENT },
137         { "itemsep",                    LT_ITEMSEP },
138         { "keepempty",                  LT_KEEPEMPTY },
139         { "labelbottomsep",             LT_LABEL_BOTTOMSEP },
140         { "labelfont",                  LT_LABELFONT },
141         { "labelindent",                LT_LABELINDENT },
142         { "labelsep",                   LT_LABELSEP },
143         { "labelstring",                LT_LABELSTRING },
144         { "labelstringappendix",                LT_LABELSTRING_APPENDIX },
145         { "labeltype",                  LT_LABELTYPE },
146         { "latex",                      LT_OTLATEX },
147         { "latexname",                  LT_LATEXNAME },
148         { "latexparam",                 LT_LATEXPARAM },    //arrae970411
149         { "latextype",                  LT_LATEXTYPE },
150         { "layout",                     LT_LAYOUT },
151         { "left",                       LT_LEFT },
152         { "leftmargin",                 LT_LEFTMARGIN },
153         { "linuxdoc",                   LT_OTLINUXDOC },
154         { "list_environment",           LT_LIST_ENVIRONMENT },
155         { "literate",                   LT_OTLITERATE },
156         { "manual",                     LT_MANUAL },
157         { "margin",                     LT_MARGIN },
158         { "maxcounter",                 LT_MAXCOUNTER },
159         { "needprotect",                LT_NEED_PROTECT },
160         { "newline",                    LT_NEWLINE },
161         { "nextnoindent",               LT_NEXTNOINDENT },
162         { "no_label",                   LT_NO_LABEL },
163         { "nostyle",                    LT_NOSTYLE },
164         { "obsoletedby",                LT_OBSOLETEDBY },
165         { "onehalf",                    LT_SPACING_ONEHALF },
166         { "other",                      LT_OTHER },
167         { "outputtype",                 LT_OUTPUTTYPE },
168         { "pagestyle",                  LT_PAGESTYLE },
169         { "paragraph",                  LT_PARAGRAPH },
170         { "parindent",                  LT_PARINDENT },
171         { "parsep",                     LT_PARSEP },
172         { "parskip",                    LT_PARSKIP },
173         { "plain",                      LT_PLAIN },
174         { "preamble",                   LT_PREAMBLE },
175         { "providesamsmath",            LT_PROVIDESAMSMATH },
176         { "providesmakeidx",            LT_PROVIDESMAKEIDX },
177         { "providesurl",                LT_PROVIDESURL },
178         { "right",                      LT_RIGHT },
179         { "right_address_box",          LT_RIGHT_ADDRESS_BOX },
180         { "rightmargin",                LT_RIGHTMARGIN },
181         { "secnumdepth",                LT_SECNUMDEPTH },
182         { "sensitive",                  LT_SENSITIVE },
183         { "sides",                      LT_SIDES },
184         { "single",                     LT_SPACING_SINGLE },
185         { "spacing",                    LT_SPACING },
186         { "static",                     LT_STATIC },
187         { "style",                      LT_STYLE },
188         { "textfont",                   LT_TEXTFONT },
189         { "tocdepth",                   LT_TOCDEPTH },
190         { "top_environment",            LT_TOP_ENVIRONMENT },
191         { "topsep",                     LT_TOPSEP }
192 };
193
194
195 /* ******************************************************************* */
196
197 // Constructor for layout
198 LyXLayout::LyXLayout ()
199 {
200         margintype = MARGIN_STATIC;
201         latextype = LATEX_PARAGRAPH;
202         intitle = false;
203         needprotect = false;
204         keepempty = false;
205         font = LyXFont(LyXFont::ALL_INHERIT);
206         labelfont = LyXFont(LyXFont::ALL_INHERIT);
207         resfont = LyXFont(LyXFont::ALL_SANE);
208         reslabelfont = LyXFont(LyXFont::ALL_SANE);
209         nextnoindent = false;
210         parskip = 0.0;
211         itemsep = 0;
212         topsep = 0.0;
213         bottomsep = 0.0;
214         labelbottomsep = 0.0;
215         parsep = 0;
216         align = LYX_ALIGN_BLOCK;
217         alignpossible = LYX_ALIGN_BLOCK;
218         labeltype = LABEL_NO_LABEL;
219         // Should or should not. That is the question.
220         // spacing.set(Spacing::OneHalf);
221         fill_top = false;
222         fill_bottom = false;
223         newline_allowed = true;
224         free_spacing = false;
225 }
226
227
228 LyXLayout::~LyXLayout ()
229 {
230 }
231
232
233 void LyXLayout::Copy (LyXLayout const &l)
234 {
235         name = l.name;
236         obsoleted_by = l.obsoleted_by;
237         margintype = l.margintype;
238         latextype = l.latextype;
239         intitle = l.intitle;
240         needprotect = l.needprotect;
241         keepempty = l.keepempty;
242         latexname = l.latexname;
243         latexparam = l.latexparam;   //arrae970411
244         preamble = l.preamble;
245         font = l.font;
246         labelfont = l.labelfont;
247         resfont = l.resfont;
248         reslabelfont = l.reslabelfont;
249         nextnoindent = l.nextnoindent;
250         leftmargin = l.leftmargin;
251         rightmargin = l.rightmargin;
252         labelsep = l.labelsep;
253         labelindent = l.labelindent;
254         parindent = l.parindent;
255         parskip = l.parskip;
256         itemsep = l.itemsep;
257         topsep = l.topsep;
258         bottomsep = l.bottomsep;
259         labelbottomsep = l.labelbottomsep;
260         parsep = l.parsep;
261         align = l.align;
262         alignpossible = l.alignpossible;
263         labeltype = l.labeltype;
264         spacing = l.spacing;
265         labelstring = l.labelstring;
266         labelstring_appendix = l.labelstring_appendix;
267         fill_top = l.fill_top;
268         fill_bottom = l.fill_bottom;
269         newline_allowed = l.newline_allowed;
270         free_spacing = l.free_spacing;
271 }
272
273
274 /* Reads a layout definition from file */
275 bool LyXLayout::Read (LyXLex & lexrc, LyXLayoutList * list)
276 {
277         bool error = false;
278         bool finished = false;
279         
280         /* parse style section */
281         while (!finished && lexrc.IsOK() && !error) {
282                 switch(lexrc.lex()) {
283
284                 case -2:
285                         break;
286
287                 case -1:                /* parse error */
288                         lexrc.printError("Unknown tag `$$Token'");
289                         error = true;
290                         break;
291
292                 case LT_END:            /* end of structure */
293                         finished = true;
294                         break;
295
296                 case LT_COPYSTYLE:     // initialize with a known style
297                         if (lexrc.next()) {
298                                 LyXLayout * layout = list->GetLayout(lexrc.GetString());
299                                 if (layout) {
300                                         string tmpname = name;
301                                         Copy(*layout);
302                                         name = tmpname;
303                                 } else {
304                                         lexrc.printError("Cannot copy unknown "
305                                                  "style `$$Token'");
306                                 }
307                         }
308                         break;
309
310                 case LT_OBSOLETEDBY:     // replace with a known style
311                         if (lexrc.next()) {
312                                 LyXLayout * layout = list->GetLayout(lexrc.GetString());
313                                 if (layout) {
314                                         string tmpname = name;
315                                         Copy(*layout);
316                                         name = tmpname;
317                                         if (obsoleted_by.empty())
318                                                 obsoleted_by = lexrc.GetString();
319                                 } else {
320                                         lexrc.printError("Cannot replace with" 
321                                                          " unknown style "
322                                                          "`$$Token'");
323                                 }
324                         }
325                         break;
326
327                 case LT_MARGIN:         /* margin style definition */
328                        
329                         switch(lexrc.lex()) {
330                         case LT_STATIC:
331                                 margintype = MARGIN_STATIC;
332                                 break;
333                         case LT_MANUAL:
334                                 margintype = MARGIN_MANUAL;
335                                 break;
336                         case LT_DYNAMIC:
337                                 margintype = MARGIN_DYNAMIC;
338                                 break;
339                         case LT_FIRST_DYNAMIC:
340                                 margintype = MARGIN_FIRST_DYNAMIC;
341                                 break;
342                         case LT_RIGHT_ADDRESS_BOX:
343                                 margintype = MARGIN_RIGHT_ADDRESS_BOX;
344                                 break;
345                         default:
346                                 lexrc.printError("Unknown margin type `$$Token'");
347                                 break;
348                         }
349                         break;
350
351                 case LT_LATEXTYPE:      /* latex style definition */
352                         switch (lexrc.lex()) {
353                         case LT_PARAGRAPH:
354                                 latextype=LATEX_PARAGRAPH;
355                                 break;
356                         case LT_COMMAND:
357                                 latextype=LATEX_COMMAND;
358                                 break;
359                         case LT_ENVIRONMENT:
360                                 latextype=LATEX_ENVIRONMENT;
361                                 break;
362                         case LT_ITEM_ENVIRONMENT:
363                                 latextype=LATEX_ITEM_ENVIRONMENT;
364                                 break;
365                         case LT_LIST_ENVIRONMENT:
366                                 latextype=LATEX_LIST_ENVIRONMENT;
367                                 break;
368                         default:
369                                 lexrc.printError("Unknown latextype `$$Token'");
370                                 break;
371                         }
372                         break;
373
374                 case LT_INTITLE:
375                         intitle = lexrc.next() && lexrc.GetInteger();
376                         break;
377                         
378                 case LT_NEED_PROTECT:
379                         needprotect = lexrc.next() && lexrc.GetInteger();
380                         break;
381                         
382                 case LT_KEEPEMPTY:
383                         keepempty = lexrc.next() && lexrc.GetInteger();
384                         break;
385
386                 case LT_FONT:
387                         font.lyxRead(lexrc);
388                         labelfont=font;
389                         break;
390
391                 case LT_TEXTFONT:
392                         font.lyxRead(lexrc);
393                         break;
394
395                 case LT_LABELFONT:
396                         labelfont.lyxRead(lexrc);
397                         break;
398
399                 case LT_NEXTNOINDENT:   /* indent next paragraph ? */
400                         if (lexrc.next() && lexrc.GetInteger())
401                                 nextnoindent = true;
402                         else
403                                 nextnoindent = false;
404                         break;
405
406                 case LT_LATEXNAME:      /* latex name */
407                         if (lexrc.next())
408                                 latexname = lexrc.GetString();
409                         break;
410                         
411                 //arrae970411
412                 case LT_LATEXPARAM:     /* latex parameter */
413                         if (lexrc.next())
414                                 latexparam = lexrc.GetString();
415                         break;
416
417                 case LT_PREAMBLE:
418                         preamble = lexrc.getLongString("EndPreamble");
419                         break;
420
421                 case LT_LABELTYPE:      /* label type */
422                         switch (lexrc.lex()) {
423                         case LT_NO_LABEL:
424                                 labeltype = LABEL_NO_LABEL;
425                                 break;
426                         case LT_MANUAL:
427                                 labeltype = LABEL_MANUAL;
428                                 break;
429                         case LT_TOP_ENVIRONMENT:
430                                 labeltype = LABEL_TOP_ENVIRONMENT;
431                                 break;
432                         case LT_CENTERED_TOP_ENVIRONMENT:
433                                 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
434                                 break;
435                         case LT_STATIC:
436                                 labeltype = LABEL_STATIC;
437                                 break;
438                         case LT_SENSITIVE:
439                                 labeltype = LABEL_SENSITIVE;
440                                 break;
441                         case LT_COUNTER_CHAPTER:
442                                 labeltype = LABEL_COUNTER_CHAPTER;
443                                 break;
444                         case LT_COUNTER_SECTION:
445                                 labeltype = LABEL_COUNTER_SECTION;
446                                 break;
447                         case LT_COUNTER_SUBSECTION:
448                                 labeltype = LABEL_COUNTER_SUBSECTION;
449                                 break;
450                         case LT_COUNTER_SUBSUBSECTION:
451                                 labeltype = LABEL_COUNTER_SUBSUBSECTION;
452                                 break;
453                         case LT_COUNTER_PARAGRAPH:
454                                 labeltype = LABEL_COUNTER_PARAGRAPH;
455                                 break;
456                         case LT_COUNTER_SUBPARAGRAPH:
457                                 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
458                                 break;
459                         case LT_COUNTER_ENUMI:
460                                 labeltype = LABEL_COUNTER_ENUMI;
461                                 break;
462                         case LT_COUNTER_ENUMII:
463                                 labeltype = LABEL_COUNTER_ENUMII;
464                                 break;
465                         case LT_COUNTER_ENUMIII:
466                                 labeltype = LABEL_COUNTER_ENUMIII;
467                                 break;
468                         case LT_COUNTER_ENUMIV:
469                                 labeltype = LABEL_COUNTER_ENUMIV;
470                                 break;
471                         case LT_BIBLIO:
472                                 labeltype = LABEL_BIBLIO;
473                                 break;
474                         default:
475                                 lexrc.printError("Unknown labeltype `$$Token'");
476                         }
477                         break;
478
479                 case LT_LEFTMARGIN:     /* left margin type */
480                         if (lexrc.next())
481                                 leftmargin = lexrc.GetString();
482                         break;                  
483
484                 case LT_RIGHTMARGIN:    /* right margin type */
485                         if (lexrc.next())
486                                 rightmargin = lexrc.GetString();
487                         break;
488
489                 case LT_LABELINDENT:    /* label indenting flag */
490                         if (lexrc.next())
491                                 labelindent = lexrc.GetString();
492                         break;
493
494                 case LT_PARINDENT:      /* paragraph indent. flag */
495                         if (lexrc.next())
496                                 parindent = lexrc.GetString();
497                         break;
498
499                 case LT_PARSKIP:        /* paragraph skip size */
500                         if (lexrc.next())
501                                 parskip = lexrc.GetFloat();
502                         break;
503
504                 case LT_ITEMSEP:        /* item separation size */
505                         if (lexrc.next())
506                                 itemsep = lexrc.GetFloat();
507                         break;
508
509                 case LT_TOPSEP:         /* top separation size */
510                         if (lexrc.next())
511                                 topsep = lexrc.GetFloat();
512                         break;
513
514                 case LT_BOTTOMSEP:      /* bottom separation size */
515                         if (lexrc.next())
516                                 bottomsep = lexrc.GetFloat();
517                         break;
518
519                 case LT_LABEL_BOTTOMSEP:/* label bottom separation size */
520                         if (lexrc.next())
521                                 labelbottomsep = lexrc.GetFloat();
522                         break;
523
524                 case LT_LABELSEP:       /* label separator */
525                         if (lexrc.next()) {
526                                 labelsep = lexrc.GetString();
527                                 subst(labelsep, 'x', ' ');
528                         }
529                         break;
530
531                 case LT_PARSEP:         /* par. separation size */
532                         if (lexrc.next())
533                                 parsep = lexrc.GetFloat();
534                         break;
535
536                 case LT_FILL_TOP:       /* fill top flag */
537                         if (lexrc.next())
538                                 fill_top = lexrc.GetInteger();
539                         break;
540
541                 case LT_FILL_BOTTOM:    /* fill bottom flag */
542                         if (lexrc.next())
543                                 fill_bottom = lexrc.GetInteger();
544                         break;
545
546                 case LT_NEWLINE:        /* newlines allowed ? */
547                         if (lexrc.next())
548                                 newline_allowed = lexrc.GetInteger();
549                         break;
550
551                 case LT_ALIGN:          /* paragraph align */
552                         switch (lexrc.lex()) {
553                         case LT_BLOCK:
554                                 align = LYX_ALIGN_BLOCK;
555                                 break;
556                         case LT_LEFT:
557                                 align = LYX_ALIGN_LEFT;
558                                 break;
559                         case LT_RIGHT:
560                                 align = LYX_ALIGN_RIGHT;
561                                 break;
562                         case LT_CENTER:
563                                 align = LYX_ALIGN_CENTER;
564                                 break;
565                         case LT_LAYOUT:
566                                 align = LYX_ALIGN_LAYOUT;
567                                 break;
568                         default:
569                                 lexrc.printError("Unknown alignment `$$Token'");
570                         }
571                         break;
572
573                 case LT_ALIGNPOSSIBLE:  /* paragraph allowed align */
574                 {       alignpossible = 0;
575                       
576                 int lineno = lexrc.GetLineNo();
577                 do {
578                         switch (lexrc.lex()) {
579                         case LT_BLOCK:
580                                 alignpossible |= LYX_ALIGN_BLOCK;
581                                 break;
582                         case LT_LEFT:
583                                 alignpossible |= LYX_ALIGN_LEFT;
584                                 break;
585                         case LT_RIGHT:
586                                 alignpossible |= LYX_ALIGN_RIGHT;
587                                 break;
588                         case LT_CENTER:
589                                 alignpossible |= LYX_ALIGN_CENTER;
590                                 break;
591                         case LT_LAYOUT:
592                                 alignpossible |= LYX_ALIGN_LAYOUT;
593                                 break;
594                         default:
595                                 lexrc.printError("Unknown alignment `$$Token'");
596
597                         }
598                 } while (lineno==lexrc.GetLineNo());
599                 break;
600                 }
601
602                 case LT_LABELSTRING:    /* label string definition */
603                         if (lexrc.next())
604                                 labelstring = lexrc.GetString();
605                         break;
606
607                 case LT_LABELSTRING_APPENDIX:   /* label string appendix definition */
608                         if (lexrc.next())
609                                 labelstring_appendix = lexrc.GetString();
610                         break;
611
612                 case LT_FREE_SPACING:   /* Allow for free spacing. */
613                         if (lexrc.next())
614                                 free_spacing = lexrc.GetInteger();
615                         break;
616
617                 case LT_SPACING: // setspace.sty
618                         switch(lexrc.lex()) {
619                         case LT_SPACING_SINGLE:
620                                 spacing.set(Spacing::Single);
621                                 //spacing_value = 1.0;
622                                 break;
623                         case LT_SPACING_ONEHALF:
624                                 spacing.set(Spacing::Onehalf);
625                                 //spacing_value = 1.25;
626                                 break;
627                         case LT_SPACING_DOUBLE:
628                                 spacing.set(Spacing::Double);
629                                 //spacing_value = 1.667;
630                                 break;
631                         case LT_OTHER:
632                                 lexrc.next();
633                                 spacing.set(Spacing::Other, lexrc.GetFloat());
634                                 break;
635                         default:
636                                 lexrc.printError("Unknown spacing `$$Token'");
637                         }
638                         break;
639                 default:                /* context error */
640                         lexrc.printError("Tag `$$Token' is not "
641                                          "allowed in layout");
642                         error = true;
643                         break;
644                 }
645         }
646
647         return error;
648 }
649
650 /* ******************************************************************* */
651
652 LyXLayoutList::LyXLayoutList()
653 {
654         l = 0;
655         eol = 0;
656         num_layouts = 0;
657 }
658
659
660 LyXLayoutList::~LyXLayoutList()
661 {
662         //don't do anything. the layouts will be extracted by ToAr.
663         //destruction is done by Clean in emergencies
664 }
665
666
667 int LyXLayoutList::GetNum ()
668 {
669         return num_layouts;
670 }
671
672
673 void LyXLayoutList::Add (LyXLayout *lay)
674 {
675         LyXLayoutL * tmp = new LyXLayoutL;
676         tmp->layout = lay;
677         tmp->next = 0;
678         if (!eol) l = tmp; 
679         else eol->next = tmp;
680         eol = tmp;
681         num_layouts++;
682 }
683
684
685 bool LyXLayoutList::Delete (string const &name)
686 {
687         LyXLayoutL * layoutl = l;
688         while(layoutl) {
689                 if (layoutl->layout && layoutl->layout->name == name) {
690                         delete layoutl->layout;
691                         layoutl->layout = 0; // not sure it is necessary
692                         num_layouts--;
693                         return true;
694                 }
695                 layoutl = layoutl->next;
696         }
697         return false;
698 }
699
700
701 LyXLayout * LyXLayoutList::GetLayout (string const &name)
702 {
703         LyXLayoutL * layoutl = l;
704         while(layoutl) {
705                 if (layoutl->layout && layoutl->layout->name == name) 
706                         return layoutl->layout;
707                 layoutl = layoutl->next;
708         }
709         return 0;
710 }
711
712
713 LyXLayout * LyXLayoutList::ToAr ()
714 {
715         LyXLayoutL * lp, * op;
716         int idx = 0;
717         LyXLayout* ar = new LyXLayout [num_layouts];
718         lp = l;
719         while (lp) {
720                 if (lp->layout) {
721                         ar[idx].Copy (*lp->layout);
722                         idx++;
723                         delete lp->layout;
724                 }
725                 op = lp;
726                 lp = lp->next;
727                 delete op;
728         }
729         return ar;
730 }
731
732
733 //wipe up any dead layouts
734 void LyXLayoutList::Clean ()
735 {
736         LyXLayoutL * lp, * op;
737         lp = l;
738         while (lp) {
739                 delete lp->layout;
740                 op = lp;
741                 lp = lp->next;
742                 delete op;
743         }
744 }
745
746 /* ******************************************************************* */
747
748 LyXTextClass::LyXTextClass(string const &fn, string const &cln,
749                            string const &desc)
750 {
751         name = fn;
752         latexname = cln;
753         description = desc;
754         output_type = LATEX;
755         style = 0;
756         columns = 1;
757         sides = 1;
758         secnumdepth = 3;
759         tocdepth = 3;
760         pagestyle = "default";
761         maxcounter = LABEL_COUNTER_CHAPTER;
762         defaultfont = LyXFont(LyXFont::ALL_SANE);
763         number_of_defined_layouts = 0;
764         opt_fontsize = "10|11|12";
765         opt_pagestyle = "empty|plain|headings|fancy";
766         provides_amsmath = false;
767         provides_makeidx = false;
768         provides_url = false;
769         loaded = false;
770 }
771
772
773 // This is not a proper copy.
774 // It just references the style rather than copying it!
775 void LyXTextClass::Copy (LyXTextClass const &l)
776 {
777         name = l.name;
778         latexname = l.latexname;
779         description = l.description;
780         output_type = l.output_type;
781         preamble = l.preamble;
782         options = l.options;
783         if (style) delete style;
784         style = l.style; //just aliases NO COPY
785         number_of_defined_layouts = l.number_of_defined_layouts;
786         columns = l.columns;
787         sides = l.sides;
788         secnumdepth = l.secnumdepth;
789         tocdepth = l.tocdepth;
790         pagestyle = l.pagestyle;
791         maxcounter = l.maxcounter;
792         defaultfont = l.defaultfont;
793         opt_fontsize = l.opt_fontsize;
794         opt_pagestyle = l.opt_pagestyle;
795         provides_amsmath = l.provides_amsmath;
796         provides_makeidx = l.provides_makeidx;
797         provides_url = l.provides_url;
798         loaded = l.loaded;
799
800         leftmargin = l.leftmargin;
801         rightmargin = l.rightmargin;
802           
803 }
804
805
806 LyXTextClass::~LyXTextClass()
807 {
808         //we can't delete the style here because otherwise 
809         //our list classes wouldn't work
810 }
811
812
813 /* Reads a textclass structure from file */
814 int LyXTextClass::Read (string const &filename, LyXLayoutList *list)
815 {
816         if (!list)
817                 lyxerr[Debug::TCLASS] << "Reading textclass "
818                                       << MakeDisplayPath(filename)
819                                       << endl;
820         else 
821                 lyxerr[Debug::TCLASS] << "Reading input file "
822                                       << MakeDisplayPath(filename) << endl;
823
824         LyXLex lexrc(layoutTags, sizeof(layoutTags)/sizeof(keyword_item));
825         bool error = false;
826
827         lexrc.setFile(filename);
828         if (!lexrc.IsOK()) return -2; 
829
830         LyXLayoutList * l;
831         LyXLayout * tmpl;
832
833         if (list) 
834                 l = list;
835         else 
836                 l = new LyXLayoutList;
837
838         /* parsing */
839         while (lexrc.IsOK() && !error) {
840                 switch(lexrc.lex()) {
841                 case -2:
842                         break;
843
844                 case -1:                                 
845                         lexrc.printError("Unknown tag `$$Token'");
846                         error = true;
847                         break;
848
849                 case LT_OUTPUTTYPE:   // output type definition
850                         switch(lexrc.lex()) {
851                         case LT_OTLATEX:
852                                 output_type=LATEX;
853                                 break;
854                         case LT_OTLINUXDOC:
855                                 output_type=LINUXDOC;
856                                 break;
857                         case LT_OTDOCBOOK:
858                                 output_type=DOCBOOK;
859                                 break;
860                         case LT_OTLITERATE:
861                                 output_type=LITERATE;
862                                 break;
863                         default:
864                                 lexrc.printError("Unknown output type `$$Token'");
865                                 break;
866                         }
867                         break;
868                         
869                 case LT_INPUT: // Include file
870                         if (lexrc.next()) {
871                                 string tmp = LibFileSearch("layouts",
872                                                             lexrc.GetString(), 
873                                                             "layout");
874                                 
875                                 if (Read(tmp, l)) {
876                                         lexrc.printError("Error reading input"
877                                                          "file: "+tmp);
878                                         error = true;
879                                 }
880                         }
881                         break;
882
883                 case LT_STYLE:
884                         if (lexrc.next()) {
885                                 string name = lexrc.GetString();
886                                 bool is_new = false;
887
888                                 subst(name, '_',' ');
889                                 tmpl = l->GetLayout(name);
890                                 if (!tmpl) {
891                                         is_new = true;
892                                         tmpl = new LyXLayout;
893                                         tmpl->name = name;
894                                 }
895
896                                 lyxerr[Debug::TCLASS] << "  Reading style "
897                                                       << tmpl->name
898                                                       << endl;
899
900                                 if (!tmpl->Read(lexrc, l)) {
901                                         // Resolve fonts
902                                         tmpl->resfont = tmpl->font;
903                                         tmpl->resfont.realize(defaultfont);
904                                         tmpl->reslabelfont = tmpl->labelfont;
905                                         tmpl->reslabelfont.realize(defaultfont);
906                                         if (is_new) {
907                                                 l->Add (tmpl);
908                                                 // NB! we don't delete because 
909                                                 // we just pass it in.... 
910                                         }
911                                 } else {
912                                         lexrc.printError(
913                                                        "Error parsing style `"
914                                                        +tmpl->name+'\'');
915                                         error = true;
916                                         if (is_new) {
917                                                 delete tmpl;  
918                                                 //we delete dead ones here
919                                         }
920                                 }
921                         }
922                         else {
923                                 lexrc.printError("No name given for style: `$$Token'.");
924                                 error = true;
925                         }
926                         break;
927
928                 case LT_NOSTYLE:
929                         if (lexrc.next()) {
930                                 string style = lexrc.GetString();
931                                 if (!l->Delete(subst(style, '_', ' ')))
932                                         lexrc.printError("Cannot delete style `$$Token'");
933                         }
934                         break;
935
936                 case LT_COLUMNS:
937                         if (lexrc.next())
938                                 columns = lexrc.GetInteger();
939                         break;
940                         
941                 case LT_SIDES:
942                         if (lexrc.next())
943                                 sides = lexrc.GetInteger();
944                         break;
945                         
946                 case LT_PAGESTYLE:
947                         lexrc.next();
948                         pagestyle = strip(lexrc.GetString());
949                         break;
950                         
951                 case LT_DEFAULTFONT:
952                         defaultfont.lyxRead(lexrc);
953                         if (!defaultfont.resolved()) {
954                                 lexrc.printError("Warning: defaultfont should "
955                                                  "be fully instantiated!");
956                                 defaultfont.realize(LyXFont::ALL_SANE);
957                         }
958                         break;
959
960                 case LT_MAXCOUNTER:
961                         switch (lexrc.lex()) {
962                         case LT_COUNTER_CHAPTER:
963                                 maxcounter = LABEL_COUNTER_CHAPTER;
964                                 break;
965                         case LT_COUNTER_SECTION:
966                                 maxcounter = LABEL_COUNTER_SECTION;
967                                 break;
968                         case LT_COUNTER_SUBSECTION:
969                                 maxcounter = LABEL_COUNTER_SUBSECTION;
970                                 break;
971                         case LT_COUNTER_SUBSUBSECTION:
972                                 maxcounter = LABEL_COUNTER_SUBSUBSECTION;
973                                 break;
974                         case LT_COUNTER_PARAGRAPH:
975                                 maxcounter = LABEL_COUNTER_PARAGRAPH;
976                                 break;
977                         case LT_COUNTER_SUBPARAGRAPH:
978                                 maxcounter = LABEL_COUNTER_SUBPARAGRAPH;
979                                 break;
980                         case LT_COUNTER_ENUMI:
981                                 maxcounter = LABEL_COUNTER_ENUMI;
982                                 break;
983                         case LT_COUNTER_ENUMII:
984                                 maxcounter = LABEL_COUNTER_ENUMII;
985                                 break;
986                         case LT_COUNTER_ENUMIII:
987                                 maxcounter = LABEL_COUNTER_ENUMIII;
988                                 break;
989                         case LT_COUNTER_ENUMIV:
990                                 maxcounter = LABEL_COUNTER_ENUMIV;
991                                 break;
992                         }
993                         break;
994
995                 case LT_SECNUMDEPTH:
996                         lexrc.next();
997                         secnumdepth = lexrc.GetInteger();
998                         break;
999
1000                 case LT_TOCDEPTH:
1001                         lexrc.next();
1002                         tocdepth = lexrc.GetInteger();
1003                         break;
1004
1005          // First step to support options 
1006                 case LT_CLASSOPTIONS:
1007                 {
1008                         bool getout = true;
1009                         while (getout && lexrc.IsOK()) { 
1010                                 switch (lexrc.lex()) {
1011                                 case LT_FONTSIZE:
1012                                         lexrc.next();
1013                                         opt_fontsize = strip(lexrc.GetString());
1014                                         break;
1015                                 case LT_PAGESTYLE:
1016                                         lexrc.next();
1017                                         opt_pagestyle = strip(lexrc.GetString()); 
1018                                         break;
1019                                 case LT_OTHER:
1020                                         lexrc.next();
1021                                         options = lexrc.GetString();
1022                                         break;
1023                                 case LT_END: getout = false; break;
1024                                 default:
1025                                         lexrc.printError("Out of context tag `$$Token'");
1026                                         break;
1027                                 }
1028                         }
1029                         break;
1030                 }
1031
1032                 case LT_PREAMBLE:
1033                         preamble = lexrc.getLongString("EndPreamble");
1034                         break;
1035
1036                 case LT_PROVIDESAMSMATH:
1037                         if (lexrc.next())
1038                                 provides_amsmath = lexrc.GetInteger();
1039                         break;
1040
1041                 case LT_PROVIDESMAKEIDX:
1042                         if (lexrc.next())
1043                                 provides_makeidx = lexrc.GetInteger();
1044                         break;
1045
1046                 case LT_PROVIDESURL:
1047                         if (lexrc.next())
1048                                 provides_url = lexrc.GetInteger();
1049                         break;
1050
1051                 case LT_LEFTMARGIN:     /* left margin type */
1052                         if (lexrc.next())
1053                                 leftmargin = lexrc.GetString();
1054                         break;                  
1055
1056                 case LT_RIGHTMARGIN:    /* right margin type */
1057                         if (lexrc.next())
1058                                 rightmargin = lexrc.GetString();
1059                         break;
1060
1061                 default:
1062                         lexrc.printError("Out of context tag `$$Token'");
1063                         break;
1064                 }
1065         }       
1066
1067         if (!list) { // we are at top level here.
1068                 if (error) {
1069                         number_of_defined_layouts = 0;
1070                         l->Clean(); //wipe any we may have found
1071                         delete l;
1072                 }
1073                 else {
1074                         style = l->ToAr();
1075                         number_of_defined_layouts = l->GetNum();
1076                         delete l;
1077                 }
1078                 lyxerr[Debug::TCLASS] << "Finished reading textclass " 
1079                                       << MakeDisplayPath(filename)
1080                                       << endl;
1081         }
1082         else
1083                 lyxerr[Debug::TCLASS] << "Finished reading input file " 
1084                                       << MakeDisplayPath(filename)
1085                                       << endl;
1086
1087         return error;
1088 }
1089
1090
1091 // Load textclass info if not loaded yet
1092 void LyXTextClass::load()
1093 {
1094         if (loaded)
1095                 return;
1096
1097         // Read style-file
1098         string real_file = LibFileSearch("layouts", name, "layout");
1099
1100         if (Read(real_file)) {
1101                 lyxerr << "Error reading `"
1102                        << MakeDisplayPath(real_file)
1103                        << "'\n(Check `" << name
1104                        << "')\nCheck your installation and "
1105                         "try Options/Reconfigure..." << endl;
1106         }
1107         loaded = true;
1108 }
1109
1110 /* ******************************************************************* */
1111
1112 LyXTextClassList::LyXTextClassList()
1113 {
1114         l = 0;
1115         ar = 0;
1116         num_textclass = 0;
1117 }
1118
1119
1120 LyXTextClassList::~LyXTextClassList()
1121 {
1122         // The textclass list is in ar.
1123         if (ar) {
1124                 delete [] ar;
1125         }
1126 }
1127
1128
1129 // Gets textclass number from name
1130 signed char LyXTextClassList::NumberOfClass(string const &textclass) 
1131 {
1132         int i = 0;
1133    
1134         while (i < num_textclass && textclass != ar[i].name)
1135                 i++;
1136    
1137         if (i >= num_textclass)
1138                 i = -1;
1139
1140         return i;
1141 }
1142
1143
1144 // Gets layout structure from style number and textclass number
1145 LyXLayout *LyXTextClassList::Style(char textclass, char layout) 
1146 {
1147         ar[textclass].load();
1148
1149         if (layout < ar[textclass].number_of_defined_layouts)
1150                 return &ar[textclass].style[layout];
1151         else {
1152                 return &ar[textclass].style[0];
1153         };
1154 }
1155
1156
1157 // Gets layout number from name and textclass number
1158 char LyXTextClassList::NumberOfLayout(char textclass, string const &name) 
1159 {
1160         ar[textclass].load();
1161
1162         int i = 0;
1163         while (i < ar[textclass].number_of_defined_layouts 
1164                && name != ar[textclass].style[i].name)
1165                 i++;
1166
1167         if (i >= ar[textclass].number_of_defined_layouts) {
1168                 if (name == "dummy")
1169                         i = LYX_DUMMY_LAYOUT;
1170                 else
1171                         // so that we can detect if the layout doesn't exist.
1172                         i = -1; // not found
1173         } 
1174         return i;
1175 }
1176
1177
1178 // Gets a layout (style) name from layout number and textclass number
1179 string LyXTextClassList::NameOfLayout(char textclass, char layout) 
1180 {
1181         ar[textclass].load();
1182
1183         if (layout < ar[textclass].number_of_defined_layouts)
1184                 return ar[textclass].style[layout].name;
1185         else if (layout == LYX_DUMMY_LAYOUT)
1186                 return "dummy";
1187         else
1188                 return "@@end@@";
1189 }
1190
1191
1192 // Gets a textclass name from number
1193 string LyXTextClassList::NameOfClass(char number) 
1194 {
1195         if (num_textclass == 0) { 
1196                 if (number == 0) return "dummy";
1197                 else return "@@end@@";
1198         }
1199         if (number < num_textclass)
1200                 return ar[number].name;
1201         else
1202                 return "@@end@@";
1203 }
1204
1205 // Gets a textclass latexname from number
1206 string LyXTextClassList::LatexnameOfClass(char number) 
1207 {
1208         ar[number].load();
1209
1210         if (num_textclass == 0) { 
1211                 if (number == 0) return "dummy";
1212                 else return "@@end@@";
1213         }
1214         if (number < num_textclass)
1215                 return ar[number].latexname;
1216         else
1217                 return "@@end@@";
1218 }
1219
1220 // Gets a textclass description from number
1221 string LyXTextClassList::DescOfClass(char number) 
1222 {
1223         if (num_textclass == 0) { 
1224                 if (number == 0) return "dummy";
1225                 else return "@@end@@";
1226         }
1227         if (number < num_textclass)
1228                 return ar[number].description;
1229         else
1230                 return "@@end@@";
1231 }
1232
1233
1234 // Gets a textclass structure from number
1235 LyXTextClass * LyXTextClassList::TextClass(char textclass) 
1236 {
1237         ar[textclass].load();
1238         if (textclass < num_textclass)
1239                 return &ar[textclass];
1240         else
1241                 return &ar[0];
1242 }
1243
1244
1245 void LyXTextClassList::Add (LyXTextClass *t)
1246 {
1247         LyXTextClassL ** h = &l;
1248         string const desc = t->description;
1249         while (*h && compare_no_case((*h)->textclass->description, desc) < 0)
1250                 h = &((*h)->next);
1251         LyXTextClassL * tmp = new LyXTextClassL;
1252         tmp->textclass = t;
1253         tmp->next = *h;
1254         *h = tmp;
1255         num_textclass++;
1256 }
1257
1258
1259 void LyXTextClassList::ToAr ()
1260 {
1261         LyXTextClassL * lp, *op;
1262         int idx = 0;
1263         ar = new LyXTextClass [num_textclass];
1264         lp = l;
1265         while (lp) {
1266                 ar[idx].Copy (*lp->textclass);
1267                 idx++;
1268                 delete lp->textclass; // note we don't delete layouts
1269                                       // here at all 
1270                 op = lp;
1271                 lp = lp->next;
1272                 delete op;
1273         }
1274 }
1275
1276
1277 // Reads LyX textclass definitions according to textclass config file
1278 bool LyXTextClassList::Read ()
1279 {
1280         LyXLex lex(0, 0);
1281         string real_file = LibFileSearch("", "textclass.lst");
1282         lyxerr[Debug::TCLASS] << "Reading textclasses from "
1283                               << real_file << endl;
1284
1285         if (real_file.empty()) {
1286                 lyxerr << "LyXTextClassList::Read: unable to find "
1287                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1288                        << "'. Exiting." << endl;
1289
1290                 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1291                            _("Check that the file \"textclass.lst\""),
1292                            _("is installed correctly. Sorry, has to exit :-("));
1293                 return false;
1294                 // This causes LyX to end... Not a desirable behaviour. Lgb
1295                 // What do you propose? That the user gets a file dialog
1296                 // and is allowed to hunt for the file? (Asger)
1297         }
1298
1299         lex.setFile(real_file);
1300         
1301         if (!lex.IsOK()) {
1302                 lyxerr << "LyXTextClassList::Read: unable to open "
1303                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1304                        << "\'\nCheck your installation. LyX can't continue."
1305                        << endl;
1306                 return false;
1307         }
1308         bool finished = false;
1309         string fname, clname, desc;
1310         LyXTextClass * tmpl;
1311
1312         // Parse config-file
1313         while (lex.IsOK() && !finished) {
1314                 switch (lex.lex()) {
1315                 case LyXLex::LEX_FEOF:
1316                         finished = true;
1317                         break;
1318                 default:
1319                         fname = lex.GetString();
1320                         lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1321                         if (lex.next()) {
1322                                 clname = lex.GetString();
1323                                 lyxerr[Debug::TCLASS]
1324                                         << "Clname: " << clname << endl;
1325                                 if (lex.next()) {
1326                                               desc = lex.GetString();
1327                                               lyxerr[Debug::TCLASS]
1328                                                       << "Desc: " << desc << endl;
1329                                               // This code is run when we have
1330                                               // fname, clname and desc
1331                                               tmpl =new LyXTextClass(fname,
1332                                                                      clname,
1333                                                                      desc);
1334                                               Add (tmpl);
1335                                               if (lyxerr.
1336                                                   debugging(Debug::TCLASS)) {
1337                                                     tmpl->load();
1338                                               }
1339                                 }
1340                         }
1341                 }
1342         }
1343         
1344         if (num_textclass == 0) {
1345                 lyxerr << "LyXTextClassList::Read: no textclass found!" << endl;
1346                 WriteAlert(_("LyX wasn't able to find any layout description!"),
1347                            _("Check the contents of  the file \"textclass.lst\""),
1348                            _("Sorry, has to exit :-("));
1349                 return false;
1350         }
1351         else { 
1352                 ToAr();
1353                 return true;
1354         }
1355 }
1356
1357 // Load textclass
1358 /* Returns false if this fails */
1359 bool LyXTextClassList::Load (char const number)
1360 {
1361         bool result = 1;
1362         
1363         if (number < num_textclass) {
1364                 ar[number].load();
1365                 if (!ar[number].number_of_defined_layouts) {
1366                         result = 0;
1367                 }
1368         } else {
1369                 result = 0;
1370         }
1371         return result;
1372 }