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