]> git.lyx.org Git - lyx.git/blob - src/buffer.C
3b4788e8e70fff443112cff97f08fd7ff9701d26
[lyx.git] / src / buffer.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  *           This file is Copyright 1996-1999
10  *           Lars Gullik Bjønnes
11  *
12  * ======================================================
13  */
14
15 // Change Log:
16 // ===========
17 // 23/03/98   Heinrich Bauer (heinrich.bauer@t-mobil.de)
18 // Spots marked "changed Heinrich Bauer, 23/03/98" modified due to the
19 // following bug: dvi file export did not work after printing (or previewing)
20 // and vice versa as long as the same file was concerned. This happened
21 // every time the LyX-file was left unchanged between the two actions mentioned
22 // above.
23
24 #include <config.h>
25
26 #include <cstdlib>
27 #include <unistd.h>
28
29 #ifdef __GNUG__
30 #pragma implementation "buffer.h"
31 #endif
32
33 #include "definitions.h"
34 #include "buffer.h"
35 #include "bufferlist.h"
36 #include "lyx_main.h"
37 #include "lyx_gui_misc.h"
38 #include "lyxrc.h"
39 #include "lyxlex.h"
40 #include "tex-strings.h"
41 #include "layout.h"
42 #include "lyx_cb.h"
43 #include "minibuffer.h"
44 #include "lyxfont.h"
45 #include "mathed/formulamacro.h"
46 #include "insets/lyxinset.h"
47 #include "insets/inseterror.h"
48 #include "insets/insetlabel.h"
49 #include "insets/insetref.h"
50 #include "insets/inseturl.h"
51 #include "insets/insetinfo.h"
52 #include "insets/insetquotes.h"
53 #include "insets/insetlatex.h"
54 #include "insets/insetlatexaccent.h"
55 #include "insets/insetbib.h" 
56 #include "insets/insetindex.h" 
57 #include "insets/insetinclude.h"
58 #include "insets/insettoc.h"
59 #include "insets/insetlof.h"
60 #include "insets/insetlot.h"
61 #include "insets/insetloa.h"
62 #include "insets/insetparent.h"
63 #include "insets/insetspecialchar.h"
64 #include "insets/figinset.h"
65 #include "support/filetools.h"
66 #include "support/path.h"
67 #include "LaTeX.h"
68 #include "Literate.h"
69 #include "Chktex.h"
70 #include "LyXView.h"
71 #include "debug.h"
72 #include "LaTeXFeatures.h"
73 #include "support/syscall.h"
74 #include "support/lyxlib.h"
75 #include "support/FileInfo.h"
76 #include "lyxtext.h"
77 #include "gettext.h"
78
79 // Uncomment this line to enable a workaround for the weird behaviour
80 // of the cursor between a displayed inset and last character
81 // at the upper line. (Alejandro 20.9.96)
82 // #define BREAK_BEFORE_INSET
83
84 /* Lars, when changing this file sometime in the future to a list,
85  * please check out the figinsets-sideeffects described at the
86  * beginning of figinset.C    Matthias (04.07.1996)
87  */
88
89
90 // all these externs should eventually be removed.
91 extern BufferList bufferlist;
92 extern void SmallUpdate(signed char);
93 extern unsigned char GetCurrentTextClass();
94 extern void BeforeChange();
95
96 static const float LYX_FORMAT = 2.15;
97
98 extern int tex_code_break_column;
99
100 extern void FreeUpdateTimer();
101
102
103 Buffer::Buffer(string const & file, LyXRC *lyxrc, bool ronly)
104 {
105         lyxerr[Debug::INFO] << "Buffer::Buffer()" << endl;
106         filename = file;
107         filepath = OnlyPath(file);
108         paragraph = 0;
109         text = 0;
110         the_locking_inset = 0;
111         lyx_clean = true;
112         bak_clean = true;
113         dvi_clean_orgd = false;  // Heinrich Bauer, 23/03/98
114         dvi_clean_tmpd = false;  // Heinrich Bauer, 23/03/98
115         dep_clean = 0;
116         read_only = ronly;
117         inset_slept = false;
118         users = 0;
119         lyxvc.buffer(this);
120         if (read_only || (lyxrc && lyxrc->use_tempdir)) {
121                 tmppath = CreateBufferTmpDir();
122         } else tmppath.clear();
123 }
124
125
126 Buffer::~Buffer()
127 {
128         lyxerr[Debug::INFO] << "Buffer::~Buffer()" << endl;
129         // here the buffer should take care that it is
130         // saved properly, before it goes into the void.
131
132         // make sure that views using this buffer
133         // forgets it.
134         if (users)
135                 users->buffer(0);
136         
137         if (!tmppath.empty()) {
138                 DestroyBufferTmpDir(tmppath);
139         }
140         
141         LyXParagraph * par = paragraph;
142         LyXParagraph * tmppar;
143         while (par) {
144                 tmppar = par->next;
145                 delete par;
146                 par = tmppar;
147         }
148         paragraph = 0;
149         delete text;
150 }
151
152
153 bool Buffer::saveParamsAsDefaults()
154 {
155         string fname = AddName(AddPath(user_lyxdir, "templates/"),
156                                 "defaults.lyx");
157         Buffer defaults = Buffer(fname);
158         
159         // Use the current buffer's parameters as default
160         defaults.params.Copy(params);
161         // add an empty paragraph. Is this enough?
162         defaults.paragraph = new LyXParagraph;
163
164         return defaults.writeFile(defaults.filename,false);
165 }
166
167
168 /// Update window titles of all users
169 // Should work on a list
170 void Buffer::updateTitles()
171 {
172         if (users) users->owner()->updateWindowTitle();
173 }
174
175
176 /// Reset autosave timer of all users
177 // Should work on a list
178 void Buffer::resetAutosaveTimers()
179 {
180         if (users) users->owner()->resetAutosaveTimer();
181 }
182
183
184 void Buffer::setFileName(string const & newfile)
185 {
186         filename = MakeAbsPath(newfile);
187         filepath = OnlyPath(filename);
188         setReadonly(IsFileWriteable(filename) == 0);
189         updateTitles();
190 }
191
192 void Buffer::InsetUnlock()
193 {
194         if (the_locking_inset) {
195                 if (!inset_slept) the_locking_inset->InsetUnlock();
196                 the_locking_inset = 0;
197                 text->FinishUndo();
198                 inset_slept = false;
199         }
200 }
201
202
203 // Inserts a file into current document
204 bool Buffer::insertLyXFile(string const & filen)
205         //
206         // (c) CHT Software Service GmbH
207         // Uwe C. Schroeder
208         //
209         // Insert a Lyxformat - file into current buffer
210         //
211         // Moved from lyx_cb.C (Lgb)
212 {
213         if (filen.empty()) return false;
214
215         string filename = MakeAbsPath(filen);
216
217         // check if file exist
218         FileInfo fi(filename);
219
220         if (!fi.exist() || !fi.readable()) {
221                 WriteAlert(_("Error!"),
222                            _("Cannot open specified file:"),
223                            MakeDisplayPath(filename,50));
224                 return false;
225         }
226         
227         BeforeChange();
228
229         FilePtr myfile(filename, FilePtr::read);
230         if (!myfile()) {
231                 WriteAlert(_("Error!"),
232                            _("Cannot open specified file:"),
233                            MakeDisplayPath(filename,50));
234                 return false;
235         }
236         LyXLex lex(0, 0);
237         lex.setFile(myfile);
238         int c = fgetc(myfile());
239         ungetc(c, myfile);
240
241         bool res = true;
242
243         if (c == '#') {
244                 lyxerr.debug() << "Will insert file with header" << endl;
245                 res = readFile(lex, text->cursor.par);
246         } else {
247                 lyxerr.debug() << "Will insert file without header" << endl;
248                 res = readLyXformat2(lex, text->cursor.par);
249         }
250         resize();
251         return res;
252 }
253
254
255 //
256 // Uwe C. Schroeder
257 // changed to be public and have one parameter
258 // if par = 0 normal behavior
259 // else insert behavior
260 // Returns false if "\the_end" is not read for formats >= 2.13. (Asger)
261 bool Buffer::readLyXformat2(LyXLex &lex, LyXParagraph * par)
262 {
263         string tmptok;
264         Inset * inset = 0;
265         int pos = 0;
266         int tmpret, tmpret2;
267         char depth = 0; // signed or unsigned?
268         LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
269         LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
270         bool the_end_read = false;
271
272         LyXParagraph *return_par = 0;
273         LyXFont font = LyXFont(LyXFont::ALL_INHERIT);
274
275         // If we are inserting, we cheat and get a token in advance
276         bool has_token = false;
277         string pretoken;
278
279         if(!par) {
280                 par = new LyXParagraph;
281 #ifdef NEW_TEXT
282                 par->text.reserve(500);
283 #endif
284         } else {
285                 text->BreakParagraph();
286                 return_par = text->FirstParagraph();
287                 pos=0;
288                 markDirty();
289                 // We don't want to adopt the parameters from the
290                 // document we insert, so we skip until the text begins:
291                 while (lex.IsOK()) {
292                         lex.nextToken();
293                         pretoken = lex.GetString();
294                         if (pretoken == "\\layout") {
295                                 has_token = true;
296                                 break;
297                         }
298                 }
299         }
300
301         while (lex.IsOK()) {
302                 if (has_token) {
303                         has_token = false;
304                 } else {
305                         lex.nextToken();
306                         pretoken = lex.GetString();
307                 }
308
309                 // Profiling show this should give a lot: (Asger)
310                 string const token = pretoken;
311
312                 if (token.empty())
313                         continue;
314                 else if (token[0] != '\\') {
315                         int n = token.length();
316                         for (int i=0; i < n; i++) {
317                                 par->InsertChar(pos, token[i]);
318                                 par->SetFont(pos, font);
319                                 pos++;
320                         }
321                 } else if (token == "\\i") {
322                         inset = new InsetLatexAccent;
323                         inset->Read(lex);
324                         par->InsertChar(pos, LYX_META_INSET); 
325                         
326                         par->InsertInset(pos, inset);
327                         par->SetFont(pos, font);
328                         pos++;
329                 } else if (token == "\\layout") {
330                         if (!return_par) 
331                                 return_par = par;
332                         else {
333 #ifdef NEW_TEXT
334                                 par->text.resize(par->text.size());
335 #endif
336                                 par = new LyXParagraph(par);
337 #ifdef NEW_TEXT
338                                 par->text.reserve(500);
339 #endif
340                         }
341                         pos = 0;
342                         lex.EatLine();
343                         string layoutname = lex.GetString();
344                         pair<bool, LyXTextClass::LayoutList::size_type> pp
345                                 = textclasslist.NumberOfLayout(params.textclass,
346                                                                 layoutname);
347                         if (pp.first) {
348                                 par->layout = pp.second;
349                         } else { // layout not found
350                                 // use default layout "Standard" (0)
351                                 par->layout = 0;
352                         }
353                         // Test whether the layout is obsolete.
354                         LyXLayout const & layout = textclasslist.Style(params.textclass,
355                                                             par->layout); 
356                         if (!layout.obsoleted_by().empty())
357                                 par->layout = 
358                                         textclasslist.NumberOfLayout(params.textclass, 
359                                                                 layout.obsoleted_by()).second;
360                         par->footnoteflag = footnoteflag;
361                         par->footnotekind = footnotekind;
362                         par->depth = depth;
363                         font = LyXFont(LyXFont::ALL_INHERIT);
364                 } else if (token == "\\end_float") {
365                         if (!return_par) 
366                                 return_par = par;
367                         else {
368 #ifdef NEW_TEXT
369                                 par->text.resize(par->text.size());
370 #endif
371                                 par = new LyXParagraph(par);
372 #ifdef NEW_TEXT
373                                 par->text.reserve(500);
374 #endif
375                         }
376                         footnotekind = LyXParagraph::FOOTNOTE;
377                         footnoteflag = LyXParagraph::NO_FOOTNOTE;
378                         pos = 0;
379                         lex.EatLine();
380                         par->layout = LYX_DUMMY_LAYOUT;
381                         font = LyXFont(LyXFont::ALL_INHERIT);
382                 } else if (token == "\\begin_float") {
383                         tmpret = lex.FindToken(string_footnotekinds);
384                         if (tmpret == -1) tmpret++;
385                         if (tmpret != LYX_LAYOUT_DEFAULT) 
386                                 footnotekind = (LyXParagraph::footnote_kind)tmpret; // bad
387                         if (footnotekind == LyXParagraph::FOOTNOTE
388                             || footnotekind == LyXParagraph::MARGIN)
389                                 footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
390                         else 
391                                 footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
392                 } else if (token == "\\begin_deeper") {
393                         depth++;
394                 } else if (token == "\\end_deeper") {
395                         if (!depth) {
396                                 lex.printError("\\end_deeper: "
397                                                "depth is already null");
398                         }
399                         else
400                                 depth--;
401                 } else if (token == "\\begin_preamble") {
402                         params.readPreamble(lex);
403                 } else if (token == "\\textclass") {
404                         lex.EatLine();
405                         pair<bool, LyXTextClassList::ClassList::size_type> pp =
406                                 textclasslist.NumberOfClass(lex.GetString());
407                         if (pp.first) {
408                                 params.textclass = pp.second;
409                         } else {
410                                 lex.printError("Unknown textclass `$$Token'");
411                                 params.textclass = 0;
412                         }
413                         if (!textclasslist.Load(params.textclass)) {
414                                 // if the textclass wasn't loaded properly
415                                 // we need to either substitute another
416                                 // or stop loading the file.
417                                 // I can substitute but I don't see how I can
418                                 // stop loading... ideas??  ARRae980418
419                                 WriteAlert(_("Textclass Loading Error!"),
420                                            string(_("Can't load textclass ")) +
421                                            textclasslist.NameOfClass(params.textclass),
422                                            _("-- substituting default"));
423                                 params.textclass = 0;
424                         }
425                 } else if (token == "\\options") {
426                         lex.EatLine();
427                         params.options = lex.GetString();
428                 } else if (token == "\\language") {
429                         params.readLanguage(lex);           
430                 } else if (token == "\\fontencoding") {
431                         lex.EatLine();
432                 } else if (token == "\\inputencoding") {
433                         lex.EatLine();
434                         params.inputenc = lex.GetString();
435                 } else if (token == "\\graphics") {
436                         params.readGraphicsDriver(lex);
437                 } else if (token == "\\fontscheme") {
438                         lex.EatLine();
439                         params.fonts = lex.GetString();
440                 } else if (token == "\\noindent") {
441                         par->noindent = true;
442                 } else if (token == "\\fill_top") {
443                         par->added_space_top = VSpace(VSpace::VFILL);
444                 } else if (token == "\\fill_bottom") {
445                         par->added_space_bottom = VSpace(VSpace::VFILL);
446                 } else if (token == "\\line_top") {
447                         par->line_top = true;
448                 } else if (token == "\\line_bottom") {
449                         par->line_bottom = true;
450                 } else if (token == "\\pagebreak_top") {
451                         par->pagebreak_top = true;
452                 } else if (token == "\\pagebreak_bottom") {
453                         par->pagebreak_bottom = true;
454                 } else if (token == "\\start_of_appendix") {
455                         par->start_of_appendix = true;
456                 } else if (token == "\\paragraph_separation") {
457                         tmpret = lex.FindToken(string_paragraph_separation);
458                         if (tmpret == -1) tmpret++;
459                         if (tmpret != LYX_LAYOUT_DEFAULT) 
460                                 params.paragraph_separation = tmpret;
461                 } else if (token == "\\defskip") {
462                         lex.nextToken();
463                         params.defskip = VSpace(lex.GetString());
464                 } else if (token == "\\no_isolatin1") {
465                         lex.nextToken();
466                 } else if (token == "\\no_babel") {
467                         lex.nextToken();
468                 } else if (token == "\\no_epsfig") {
469                         lex.nextToken();
470                 } else if (token == "\\epsfig") { // obsolete
471                         // Indeed it is obsolete, but we HAVE to be backwards
472                         // compatible until 0.14, because otherwise all figures
473                         // in existing documents are irretrivably lost. (Asger)
474                         params.readGraphicsDriver(lex);
475                 } else if (token == "\\quotes_language") {
476                         tmpret = lex.FindToken(string_quotes_language);
477                         if (tmpret == -1) tmpret++;
478                         if (tmpret != LYX_LAYOUT_DEFAULT) {
479                                 InsetQuotes::quote_language tmpl =
480                                         InsetQuotes::EnglishQ;
481                                 switch(tmpret) {
482                                 case 0:
483                                         tmpl = InsetQuotes::EnglishQ;
484                                         break;
485                                 case 1:
486                                         tmpl = InsetQuotes::SwedishQ;
487                                         break;
488                                 case 2:
489                                         tmpl = InsetQuotes::GermanQ;
490                                         break;
491                                 case 3:
492                                         tmpl = InsetQuotes::PolishQ;
493                                         break;
494                                 case 4:
495                                         tmpl = InsetQuotes::FrenchQ;
496                                         break;
497                                 case 5:
498                                         tmpl = InsetQuotes::DanishQ;
499                                         break;  
500                                 }
501                                 params.quotes_language = tmpl;
502                         }
503                 } else if (token == "\\quotes_times") {
504                         lex.nextToken();
505                         switch(lex.GetInteger()) {
506                         case 1: 
507                                 params.quotes_times = InsetQuotes::SingleQ; 
508                                 break;
509                         case 2: 
510                                 params.quotes_times = InsetQuotes::DoubleQ; 
511                                 break;
512                         }
513                 } else if (token == "\\papersize") {
514                         if (format > 2.13)
515                                 tmpret = lex.FindToken(string_papersize);
516                         else
517                                 tmpret = lex.FindToken(string_oldpapersize);
518                         if (tmpret == -1)
519                                 tmpret++;
520                         else
521                                 params.papersize2 = tmpret;
522                 } else if (token == "\\paperpackage") {
523                         tmpret = lex.FindToken(string_paperpackages);
524                         if (tmpret == -1) {
525                                 tmpret++;
526                                 params.paperpackage = PACKAGE_NONE;
527                         } else
528                                 params.paperpackage = tmpret;
529                 } else if (token == "\\use_geometry") {
530                         lex.nextToken();
531                         params.use_geometry = lex.GetInteger();
532                 } else if (token == "\\use_amsmath") {
533                         lex.nextToken();
534                         params.use_amsmath = lex.GetInteger();
535                 } else if (token == "\\paperorientation") {
536                         tmpret = lex.FindToken(string_orientation);
537                         if (tmpret == -1) tmpret++;
538                         if (tmpret != LYX_LAYOUT_DEFAULT) 
539                                 params.orientation = tmpret;
540                 } else if (token == "\\paperwidth") {
541                         lex.next();
542                         params.paperwidth = lex.GetString();
543                 } else if (token == "\\paperheight") {
544                         lex.next();
545                         params.paperheight = lex.GetString();
546                 } else if (token == "\\leftmargin") {
547                         lex.next();
548                         params.leftmargin = lex.GetString();
549                 } else if (token == "\\topmargin") {
550                         lex.next();
551                         params.topmargin = lex.GetString();
552                 } else if (token == "\\rightmargin") {
553                         lex.next();
554                         params.rightmargin = lex.GetString();
555                 } else if (token == "\\bottommargin") {
556                         lex.next();
557                         params.bottommargin = lex.GetString();
558                 } else if (token == "\\headheight") {
559                         lex.next();
560                         params.headheight = lex.GetString();
561                 } else if (token == "\\headsep") {
562                         lex.next();
563                         params.headsep = lex.GetString();
564                 } else if (token == "\\footskip") {
565                         lex.next();
566                         params.footskip = lex.GetString();
567                 } else if (token == "\\paperfontsize") {
568                         lex.nextToken();
569                         params.fontsize = strip(lex.GetString());
570                 } else if (token == "\\papercolumns") {
571                         lex.nextToken();
572                         params.columns = lex.GetInteger();
573                 } else if (token == "\\papersides") {
574                         lex.nextToken();
575                         switch(lex.GetInteger()) {
576                         default:
577                         case 1: params.sides = LyXTextClass::OneSide; break;
578                         case 2: params.sides = LyXTextClass::TwoSides; break;
579                         }
580                 } else if (token == "\\paperpagestyle") {
581                         lex.nextToken();
582                         params.pagestyle = strip(lex.GetString());
583                 } else if (token == "\\bullet") {
584                         lex.nextToken();
585                         int index = lex.GetInteger();
586                         lex.nextToken();
587                         int temp_int = lex.GetInteger();
588                         params.user_defined_bullets[index].setFont(temp_int);
589                         params.temp_bullets[index].setFont(temp_int);
590                         lex.nextToken();
591                         temp_int = lex.GetInteger();
592                         params.user_defined_bullets[index].setCharacter(temp_int);
593                         params.temp_bullets[index].setCharacter(temp_int);
594                         lex.nextToken();
595                         temp_int = lex.GetInteger();
596                         params.user_defined_bullets[index].setSize(temp_int);
597                         params.temp_bullets[index].setSize(temp_int);
598                         lex.nextToken();
599                         string temp_str = lex.GetString();
600                         if (temp_str != "\\end_bullet") {
601                                 // this element isn't really necessary for
602                                 // parsing but is easier for humans
603                                 // to understand bullets. Put it back and
604                                 // set a debug message?
605                                 lex.printError("\\end_bullet expected, got" + temp_str);
606                                 //how can I put it back?
607                         }
608                 } else if (token == "\\bulletLaTeX") {
609                         lex.nextToken();
610                         int index = lex.GetInteger();
611                         lex.next();
612                         string temp_str = lex.GetString(), sum_str;
613                         while (temp_str != "\\end_bullet") {
614                                 // this loop structure is needed when user
615                                 // enters an empty string since the first
616                                 // thing returned will be the \\end_bullet
617                                 // OR
618                                 // if the LaTeX entry has spaces. Each element
619                                 // therefore needs to be read in turn
620                                 sum_str += temp_str;
621                                 lex.next();
622                                 temp_str = lex.GetString();
623                         }
624                         params.user_defined_bullets[index].setText(sum_str);
625                         params.temp_bullets[index].setText(sum_str);
626                 } else if (token == "\\secnumdepth") {
627                         lex.nextToken();
628                         params.secnumdepth = lex.GetInteger();
629                 } else if (token == "\\tocdepth") {
630                         lex.nextToken();
631                         params.tocdepth = lex.GetInteger();
632                 } else if (token == "\\baselinestretch") { // now obsolete
633                         lex.nextToken(); // should not be used directly
634                         // anymore.
635                         // Will probably keep a kind of support just for
636                         // compability.
637                         params.spacing.set(Spacing::Other, lex.GetFloat());
638                 } else if (token == "\\spacing") {
639                         lex.next();
640                         string tmp = strip(lex.GetString());
641                         if (tmp == "single") {
642                                 params.spacing.set(Spacing::Single);
643                         } else if (tmp == "onehalf") {
644                                 params.spacing.set(Spacing::Onehalf);
645                         } else if (tmp == "double") {
646                                 params.spacing.set(Spacing::Double);
647                         } else if (tmp == "other") {
648                                 lex.next();
649                                 params.spacing.set(Spacing::Other,
650                                                    lex.GetFloat());
651                         } else {
652                                 lex.printError("Unknown spacing token: '$$Token'");
653                         }
654                 } else if (token == "\\float_placement") {
655                         lex.nextToken();
656                         params.float_placement = lex.GetString();
657                 } else if (token == "\\cursor") {
658                         // this is obsolete, so we just skip it.
659                         lex.nextToken();
660                 } else if (token == "\\family") { 
661                         lex.next();
662                         font.setLyXFamily(lex.GetString());
663                 } else if (token == "\\series") {
664                         lex.next();
665                         font.setLyXSeries(lex.GetString());
666                 } else if (token == "\\shape") {
667                         lex.next();
668                         font.setLyXShape(lex.GetString());
669                 } else if (token == "\\size") {
670                         lex.next();
671                         font.setLyXSize(lex.GetString());
672                 } else if (token == "\\latex") {
673                         lex.next();
674                         string tok = lex.GetString();
675                         // This is dirty, but gone with LyX3. (Asger)
676                         if (tok == "no_latex")
677                                 font.setLatex(LyXFont::OFF);
678                         else if (tok == "latex")
679                                 font.setLatex(LyXFont::ON);
680                         else if (tok == "default")
681                                 font.setLatex(LyXFont::INHERIT);
682                         else
683                                 lex.printError("Unknown LaTeX font flag "
684                                                "`$$Token'");
685                 } else if (token == "\\emph") {
686                         lex.next();
687                         font.setEmph(font.setLyXMisc(lex.GetString()));
688                 } else if (token == "\\bar") {
689                         lex.next();
690                         string tok = lex.GetString();
691                         // This is dirty, but gone with LyX3. (Asger)
692                         if (tok == "under")
693                                 font.setUnderbar(LyXFont::ON);
694                         else if (tok == "no")
695                                 font.setUnderbar(LyXFont::OFF);
696                         else if (tok == "default")
697                                 font.setUnderbar(LyXFont::INHERIT);
698                         else
699                                 lex.printError("Unknown bar font flag "
700                                                "`$$Token'");
701                 } else if (token == "\\noun") {
702                         lex.next();
703                         font.setNoun(font.setLyXMisc(lex.GetString()));
704                 } else if (token == "\\color") {
705                         lex.next();
706                         font.setLyXColor(lex.GetString());
707                 } else if (token == "\\align") {
708                         tmpret = lex.FindToken(string_align);
709                         if (tmpret == -1) tmpret++;
710                         if (tmpret != LYX_LAYOUT_DEFAULT) {
711                                 tmpret2 = 1;
712                                 for (; tmpret>0; tmpret--)
713                                         tmpret2 = tmpret2 * 2;
714                                 par->align = LyXAlignment(tmpret2);
715                         }
716                 } else if (token == "\\added_space_top"){
717                         lex.nextToken();
718                         par->added_space_top = lex.GetString();
719                 } else if (token == "\\added_space_bottom") {
720                         lex.nextToken();
721                         par->added_space_bottom = lex.GetString();
722                 } else if (token == "\\pextra_type") {
723                         lex.nextToken();
724                         par->pextra_type = lex.GetInteger();
725                 } else if (token == "\\pextra_width") {
726                         lex.nextToken();
727                         par->pextra_width = lex.GetString();
728                 } else if (token == "\\pextra_widthp") {
729                         lex.nextToken();
730                         par->pextra_widthp = lex.GetString();
731                 } else if (token == "\\pextra_alignment") {
732                         lex.nextToken();
733                         par->pextra_alignment = lex.GetInteger();
734                 } else if (token == "\\pextra_hfill") {
735                         lex.nextToken();
736                         par->pextra_hfill = lex.GetInteger();
737                 } else if (token == "\\pextra_start_minipage") {
738                         lex.nextToken();
739                         par->pextra_start_minipage = lex.GetInteger();
740                 } else if (token == "\\labelwidthstring") {
741                         lex.EatLine();
742                         par->labelwidthstring = lex.GetString();
743                         /* do not delete this token, it is still needed! */ 
744                 } else if (token == "\\end_inset") {
745                         /* simple ignore this. The insets do not have
746                          *  to read this */
747                         // but insets should read it, it is a part of
748                         //the inset isn't it? Lgb.
749                 } else if (token == "\\begin_inset") {
750                         lex.next();
751                         tmptok = lex.GetString();
752                         /* test the different insets */ 
753                         if (tmptok == "Quotes") {
754                                 inset = new InsetQuotes;
755                                 inset->Read(lex);
756                                 par->InsertChar(pos, LYX_META_INSET); 
757                                 par->InsertInset(pos, inset);
758                                 par->SetFont(pos, font);
759                                 pos++;
760                         } else if (tmptok == "Latex") {
761                                 // This one is on its way out
762                                 lex.EatLine();
763                                 tmptok = strip(lex.GetString());
764                                 //lyxerr <<string(tmptok[0]));
765                                 if (tmptok[0] == '\\') {
766                                         // then this latex is a
767                                         // latex command
768                                         InsetCommand *tmpinset =
769                                                 new InsetCommand();
770                                         tmpinset->scanCommand(tmptok);
771                                         inset = tmpinset;
772                                 } else {
773                                         // This should not use InsetLaTexDel
774                                         // it should rather insert text into
775                                         // the paragraph and mark it as tex.
776                                         inset = new InsetLatex(tmptok);
777                                 }
778                                 par->InsertChar(pos, LYX_META_INSET); 
779                                 par->InsertInset(pos, inset);
780                                 par->SetFont(pos, font);
781                                 pos++;
782                         } else if (tmptok == "LatexDel") {
783                                 // This one is on its way out...
784                                 lex.EatLine();
785                                 tmptok = strip(lex.GetString());
786                                 //lyxerr <<string(tmptok[0]));
787                                 if (tmptok == "\\tableofcontents") {
788                                         inset = new InsetTOC(this);
789                                 } else if (tmptok == "\\listoffigures") {
790                                         inset = new InsetLOF(this);
791                                 } else if (tmptok == "\\listoftables") {
792                                         inset = new InsetLOT(this);
793                                 } else if (tmptok == "\\listofalgorithms") {
794                                         inset = new InsetLOA(this);
795                                 } else if (contains(tmptok, "\\ref{")
796                                            || contains(tmptok, "\\pageref{")) {
797                                         inset = new InsetRef(tmptok, this);
798                                 } else if (contains(tmptok, "\\url{")
799                                            || contains(tmptok, "\\htmlurl{")) {
800                                         string cont,opt,tmptmptok,cmdname;
801                                         lex.next();
802                                         while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
803                                                 lex.next();
804                                         }
805                                         lex.next();
806                                         while(lex.IsOK()) {
807                                                 tmptmptok=lex.GetString();
808                                                 if(tmptmptok[0] == '\\') {
809                                                         if( tmptmptok == "\\backslash")
810                                                                 opt += '\\';
811                                                         else
812                                                                 break;
813                                                 }
814                                                 else
815                                                         opt += tmptmptok;
816                                                 opt += ' ';
817                                                 lex.next();
818                                         }
819                                         while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
820                                                 lex.next();
821                                         }
822                                         lex.next();
823                                         while(lex.IsOK()) {
824                                                 tmptmptok=lex.GetString();
825                                                 if(tmptmptok[0] == '\\') {
826                                                         if( tmptmptok == "\\backslash")
827                                                                 cont += '\\';
828                                                         else
829                                                                 break;
830                                                 }
831                                                 else
832                                                         cont += tmptmptok;
833                                                 cont += ' ';
834                                                 lex.next();
835                                         }
836                                         while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
837                                                 lex.next();
838                                         }
839                                         if(contains(tmptok, "\\url{"))
840                                                 cmdname = string("url");
841                                         else
842                                                 cmdname = string("htmlurl");
843                                         cont = strip(cont);
844                                         opt = strip(opt);
845                                         inset = new InsetUrl(cmdname,cont,opt);
846                                 } else if (tmptok[0] == '\\') {
847                                         // then this latex del is a
848                                         // latex command
849                                         InsetCommand *tmpinset =
850                                                 new InsetCommand();
851                                         tmpinset->scanCommand(tmptok);
852                                         inset = tmpinset;
853                                 } 
854                                 par->InsertChar(pos, LYX_META_INSET); 
855                                 par->InsertInset(pos, inset);
856                                 par->SetFont(pos, font);
857                                 pos++;
858                         } else if (tmptok == "\\i") {
859                                 inset = new InsetLatexAccent;
860                                 inset->Read(lex);
861                                 par->InsertChar(pos, LYX_META_INSET); 
862                                 par->InsertInset(pos, inset);
863                                 par->SetFont(pos, font);
864                                 pos++;
865                         } else if (tmptok == "FormulaMacro") {
866                                 inset = new InsetFormulaMacro;
867                                 inset->Read(lex);
868                                 par->InsertChar(pos, LYX_META_INSET); 
869                                 par->InsertInset(pos, inset);
870                                 par->SetFont(pos, font);
871                                 pos++;
872                         } else if (tmptok == "Formula") {
873                                 inset = new InsetFormula;
874                                 inset->Read(lex);
875                                 par->InsertChar(pos, LYX_META_INSET); 
876                                 par->InsertInset(pos, inset);
877                                 par->SetFont(pos, font);
878                                 pos++;
879                         } else if (tmptok == "Figure") {
880                                 inset = new InsetFig(100,100, this);
881                                 inset->Read(lex);
882                                 par->InsertChar(pos, LYX_META_INSET); 
883                                 par->InsertInset(pos, inset);
884                                 par->SetFont(pos, font);
885                                 pos++;
886                         } else if (tmptok == "Label") {
887                                 // Kept for compability. Remove in 0.13.
888                                 if (lex.EatLine()) {
889                                         string tmp = "\\label{";
890                                         tmp += lex.GetString();
891                                         tmp += '}';
892                                         inset = new InsetLabel(tmp);
893                                         par->InsertChar(pos, LYX_META_INSET); 
894                                         par->InsertInset(pos, inset);
895                                         par->SetFont(pos, font);
896                                         pos++;
897                                 }
898                         } else if (tmptok == "Info") {
899                                 inset = new InsetInfo;
900                                 inset->Read(lex);
901                                 par->InsertChar(pos, LYX_META_INSET); 
902                                 par->InsertInset(pos, inset);
903                                 par->SetFont(pos, font);
904                                 pos++;
905                         } else if (tmptok == "Include") {
906                                 inset = new InsetInclude(string(), this);
907                                 inset->Read(lex);
908                                 par->InsertChar(pos, LYX_META_INSET); 
909                                 par->InsertInset(pos, inset);
910                                 par->SetFont(pos, font);
911                                 pos++;
912                         } else if (tmptok == "LatexCommand") {
913                                 InsetCommand inscmd;
914                                 inscmd.Read(lex);
915                                 if (inscmd.getCmdName()=="cite") {
916                                         inset = new InsetCitation(inscmd.getContents(), inscmd.getOptions());
917                                 } else if (inscmd.getCmdName()=="bibitem") {
918                                         lex.printError("Wrong place for bibitem");
919                                         inset = inscmd.Clone();
920                                 } else if (inscmd.getCmdName()=="BibTeX") {
921                                         inset = new InsetBibtex(inscmd.getContents(), inscmd.getOptions(), this);
922                                 } else if (inscmd.getCmdName()=="index") {
923                                         inset = new InsetIndex(inscmd.getContents());
924                                 } else if (inscmd.getCmdName()=="include") {
925                                         inset = new InsetInclude(inscmd.getContents(), this);
926                                 } else if (inscmd.getCmdName()=="label") {
927                                         inset = new InsetLabel(inscmd.getCommand());
928                                 } else if (inscmd.getCmdName()=="url"
929                                            || inscmd.getCmdName()=="htmlurl") {
930                                         inset = new InsetUrl(inscmd.getCommand());
931                                 } else if (inscmd.getCmdName() == "ref"
932                                            || inscmd.getCmdName() == "pageref") {
933                                         if (!inscmd.getOptions().empty() || !inscmd.getContents().empty()) {
934                                                 inset = new InsetRef(inscmd, this);
935                                         }
936                                         /* This condition comes from a temporary solution
937                                            to the latexdel ref inset that was transformed to an empty ref
938                                            inset plus the body surronded by latexdel insets */
939                                         else {
940                                                 string cont,opt,tmptmptok,cmdname;
941                                                 lex.next();
942                                                 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
943                                                         lex.next();
944                                                 }
945                                                 lex.next();
946                                                 while(lex.IsOK()) {
947                                                         tmptmptok=lex.GetString();
948                                                         if(tmptmptok[0] == '\\') {
949                                                                 if( tmptmptok == "\\backslash")
950                                                                         opt += '\\';
951                                                                 else
952                                                                         break;
953                                                         }
954                                                         else
955                                                                 opt += tmptmptok;
956                                                         opt += ' ';
957                                                         lex.next();
958                                                 }
959                                                 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
960                                                         lex.next();
961                                                 }
962                                                 lex.next();
963                                                 while(lex.IsOK()) {
964                                                         tmptmptok=lex.GetString();
965                                                         if(tmptmptok[0] == '\\') {
966                                                                 if( tmptmptok == "\\backslash")
967                                                                         cont += '\\';
968                                                                 else
969                                                                         break;
970                                                         }
971                                                         else
972                                                                 cont += tmptmptok;
973                                                         cont += ' ';
974                                                         lex.next();
975                                                 }
976                                                 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
977                                                         lex.next();
978                                                 }
979
980                                                 cont = strip(cont);
981                                                 opt = strip(opt);
982                                                 cmdname =  "\\" + inscmd.getCmdName();
983                                                 cmdname += "["  + cont  + "]";
984                                                 cmdname += "{"  + opt + "}";
985                                                 inset = new InsetRef(cmdname,this);
986                                         }
987                                 } else if (inscmd.getCmdName()=="tableofcontents") {
988                                         inset = new InsetTOC(this);
989                                 } else if (inscmd.getCmdName()=="listoffigures") {
990                                         inset = new InsetLOF(this);
991                                 } else if (inscmd.getCmdName()=="listofalgorithms") {
992                                         inset = new InsetLOA(this);
993                                 } else if (inscmd.getCmdName()=="listoftables") {
994                                         inset = new InsetLOT(this);
995                                 } else if (inscmd.getCmdName()=="printindex") {
996                                         inset = new InsetPrintIndex(this);
997                                 } else if (inscmd.getCmdName()=="lyxparent") {
998                                         inset = new InsetParent(inscmd.getContents(),this);
999                                 } else 
1000                                         // The following three are only for compatibility
1001                                         if (inscmd.getCmdName()=="-") {
1002                                                 inset = new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
1003                                         } else if (inscmd.getCmdName()=="@.") {
1004                                                 inset = new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
1005                                         } else if (inscmd.getCmdName()=="ldots") {
1006                                                 inset = new InsetSpecialChar(InsetSpecialChar::LDOTS);
1007                                         } else
1008                                                 inset = inscmd.Clone();
1009                                
1010                                 if (inset) {
1011                                         par->InsertChar(pos, LYX_META_INSET);
1012                                         par->InsertInset(pos, inset);
1013                                         par->SetFont(pos, font);
1014                                         pos++;
1015                                 }
1016                         }
1017                 } else if (token == "\\InsetQuotes") {
1018                         inset = new InsetQuotes;
1019                         inset->Read(lex);
1020                         par->InsertChar(pos, LYX_META_INSET); 
1021                         par->InsertInset(pos, inset);
1022                         par->SetFont(pos, font);
1023                         pos++;
1024                 } else if (token == "\\InsetLatex") {
1025                         inset = new InsetLatex;
1026                         inset->Read(lex);
1027                         par->InsertChar(pos, LYX_META_INSET); 
1028                         par->InsertInset(pos, inset);
1029                         par->SetFont(pos, font);
1030                         pos++;
1031                 } else if (token == "\\InsetLatexDel") {
1032                         lex.printError(_("Warning: Ignoring Old Inset"));
1033                 } else if (token == "\\InsetFormula") {
1034                         inset = new InsetFormula;
1035                         inset->Read(lex);
1036                         par->InsertChar(pos, LYX_META_INSET); 
1037                         par->InsertInset(pos, inset);
1038                         par->SetFont(pos, font);
1039                         pos++;
1040                 } else if (token == "\\SpecialChar") {
1041                         inset = new InsetSpecialChar;
1042                         inset->Read(lex);
1043                         par->InsertChar(pos, LYX_META_INSET); 
1044                         par->InsertInset(pos, inset);
1045                         par->SetFont(pos, font);
1046                         pos++;
1047                 } else if (token == "\\Figure") {
1048                         inset = new InsetFig(100,100, this);
1049                         inset->Read(lex);
1050                         par->InsertChar(pos, LYX_META_INSET); 
1051                         par->InsertInset(pos, inset);
1052                         par->SetFont(pos, font);
1053                         pos++;
1054                 } else if (token == "\\newline") {
1055                         par->InsertChar(pos, LYX_META_NEWLINE);
1056                         par->SetFont(pos, font);
1057                         pos++;
1058                 } else if (token == "\\LyXTable") {
1059                         par->table = new LyXTable(lex);
1060                 } else if (token == "\\hfill") {
1061                         par->InsertChar(pos, LYX_META_HFILL);
1062                         par->SetFont(pos, font);
1063                         pos++;
1064                 } else if (token == "\\protected_separator") {
1065                         par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
1066                         par->SetFont(pos, font);
1067                         pos++;
1068                 } else if (token == "\\bibitem") {  // ale970302
1069                         if (!par->bibkey)
1070                                 par->bibkey = new InsetBibKey;
1071                         par->bibkey->Read(lex);                 
1072                 }else if (token == "\\backslash") {
1073                         par->InsertChar(pos, '\\');
1074                         par->SetFont(pos, font);
1075                         pos++;
1076                 }else if (token == "\\the_end") {
1077                         the_end_read = true;
1078                 } else {
1079                         // This should be insurance for the future: (Asger)
1080                         lex.printError("Unknown token `$$Token'. "
1081                                        "Inserting as text.");
1082                         int n = token.length();
1083                         for (int i=0; i < n; i++) {
1084                                 par->InsertChar(pos, token[i]);
1085                                 par->SetFont(pos, font);
1086                                 pos++;
1087                         }
1088                 }
1089         }
1090    
1091         if (!return_par)
1092                 return_par = par;
1093
1094         paragraph = return_par;
1095         
1096         return the_end_read;
1097 }
1098
1099
1100 bool Buffer::readFile(LyXLex & lex, LyXParagraph * par)
1101 {
1102         string token;
1103
1104         if (lex.IsOK()) {
1105                 lex.next();
1106                 token = lex.GetString();
1107                 if (token == "\\lyxformat") { // the first token _must_ be...
1108                         lex.next();
1109                         format = lex.GetFloat();
1110                         if (format > 1) {
1111                                 if (LYX_FORMAT - format > 0.05) {
1112                                         printf(_("Warning: need lyxformat %.2f but found %.2f\n"),
1113                                                LYX_FORMAT, format);
1114                                 }
1115                                 if (format - LYX_FORMAT > 0.05) {
1116                                         printf(_("ERROR: need lyxformat %.2f but found %.2f\n"),
1117                                                LYX_FORMAT, format);
1118                                 }
1119                                 bool the_end = readLyXformat2(lex, par);
1120                                 // Formats >= 2.13 support "\the_end" marker
1121                                 if (format < 2.13)
1122                                         the_end = true;
1123                                 // Formats >= 2.14 changed papersize stuff
1124                                 if (format < 2.14) {
1125                                         setOldPaperStuff();
1126                                 } else {
1127                                         setPaperStuff();
1128                                 }
1129                                 if (!the_end)
1130                                         WriteAlert(_("Warning!"),
1131                                                    _("Reading of document is not complete"),
1132                                                    _("Maybe the document is truncated"));
1133                                 // We simulate a safe reading anyways to allow
1134                                 // users to take the chance... (Asger)
1135                                 return true;
1136                         } // format < 1
1137                         else {
1138                                 WriteAlert(_("ERROR!"),
1139                                            _("Old LyX file format found. "
1140                                              "Use LyX 0.10.x to read this!"));
1141                                 return false;
1142                         }
1143
1144                 } else { // "\\lyxformat" not found
1145                         WriteAlert(_("ERROR!"), _("Not a LyX file!"));
1146                 }
1147         } else
1148                 WriteAlert(_("ERROR!"), _("Unable to read file!"));
1149         return false;
1150 }
1151                     
1152
1153 // Returns false if unsuccesful
1154 bool Buffer::writeFile(string const & filename, bool flag)
1155 {
1156         // if flag is false writeFile will not create any GUI
1157         // warnings, only cerr.
1158         // Needed for autosave in background or panic save (Matthias 120496)
1159
1160         if (read_only && (filename == this->filename)) {
1161                 // Here we should come with a question if we should
1162                 // perform the write anyway.
1163                 if (flag)
1164                         lyxerr << _("Error! Document is read-only: ")
1165                                << filename << endl;
1166                 else
1167                         WriteAlert(_("Error! Document is read-only: "), filename);
1168                 return false;
1169         }
1170
1171         FileInfo finfo(filename);
1172         if (finfo.exist() && !finfo.writable()) {
1173                 // Here we should come with a question if we should
1174                 // try to do the save anyway. (i.e. do a chmod first)
1175                 if (flag)
1176                         lyxerr << _("Error! Cannot write file: ")
1177                                << filename << endl;
1178                 else
1179                         WriteFSAlert(_("Error! Cannot write file: "), filename);
1180                 return false;
1181         }
1182
1183         FilePtr file(filename, FilePtr::truncate);
1184         if (!file()) {
1185                 if (flag)
1186                         lyxerr << _("Error! Cannot write file: ")
1187                                << filename << endl;
1188                 else
1189                         WriteFSAlert(_("Error! Cannot write file: "), filename);
1190                 return false;
1191         }
1192         // The top of the file should not be written by params.
1193         // collect some very important information
1194         string userName(getUserName()) ;
1195
1196         // write out a comment in the top of the file
1197         fprintf(file,
1198                 "#This file was created by <%s> %s",
1199                 userName.c_str(),(char*)date());
1200         fprintf(file,
1201                 "#LyX 1.0 (C) 1995-1999 Matthias Ettrich"
1202                 " and the LyX Team\n");
1203         
1204         // at the very beginning the used lyx format
1205         fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
1206
1207         // now write out the buffer parameters.
1208         params.writeFile(file);
1209
1210         char footnoteflag = 0;
1211         char depth = 0;
1212
1213         // this will write out all the paragraphs
1214         // using recursive descent.
1215         paragraph->writeFile(file, params, footnoteflag, depth);
1216
1217         // Write marker that shows file is complete
1218         fprintf(file, "\n\\the_end\n");
1219         if (file.close()) {
1220                 if (flag)
1221                         lyxerr << _("Error! Could not close file properly: ")
1222                                << filename << endl;
1223                 else
1224                         WriteFSAlert(_("Error! Could not close file properly: "),
1225                                      filename);
1226                 return false;
1227         }
1228         return true;
1229 }
1230
1231
1232 void Buffer::writeFileAscii(string const & filename, int linelen) 
1233 {
1234         FilePtr file(filename, FilePtr::write);
1235         LyXFont
1236                 font1, font2;
1237         Inset * inset;
1238         LyXParagraph * par = paragraph;
1239         char
1240                 c,
1241                 footnoteflag = 0,
1242                 depth = 0;
1243
1244         string
1245                 fname1,
1246                 tmp;
1247
1248 #ifdef NEW_TEXT
1249         LyXParagraph::size_type i;
1250 #else
1251         int i;
1252 #endif
1253         int
1254                 j,h,
1255                 ltype=0,
1256                 ltype_depth=0,
1257                 noparbreak=0,
1258                 islatex=0,
1259                 *clen=0,
1260                 actcell=0,
1261                 actpos=0,
1262                 cell=0,
1263                 cells=0,
1264                 currlinelen=0;
1265         long
1266                 fpos=0;
1267         bool
1268                 ref_printed = false;
1269    
1270    
1271         if (!file()) {
1272                 WriteFSAlert(_("Error: Cannot write file:"), filename);
1273                 return;
1274         }
1275         fname1=TmpFileName();
1276         while (par) {
1277                 noparbreak = 0;
1278                 islatex = 0;
1279                 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE ||
1280                     !par->previous ||
1281                     par->previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
1282          
1283                         /* begins a footnote environment ? */ 
1284                         if (footnoteflag != par->footnoteflag) {
1285                                 footnoteflag = par->footnoteflag;
1286                                 if (footnoteflag) {
1287                                         j=strlen(string_footnotekinds[par->footnotekind])+4;
1288                                         if (currlinelen+j > linelen)
1289                                                 fprintf(file,"\n");
1290                                         fprintf(file, "([%s] ", 
1291                                                 string_footnotekinds[par->footnotekind]);
1292                                         currlinelen += j;
1293                                 }
1294                         }
1295          
1296                         /* begins or ends a deeper area ?*/ 
1297                         if (depth != par->depth) {
1298                                 if (par->depth > depth) {
1299                                         while (par->depth > depth) {
1300                                                 depth++;
1301                                         }
1302                                 }
1303                                 else {
1304                                         while (par->depth < depth) {
1305                                                 depth--;
1306                                         }
1307                                 }
1308                         }
1309          
1310                         /* First write the layout */
1311                         tmp = textclasslist.NameOfLayout(params.textclass,par->layout);
1312                         if (tmp == "Itemize") {
1313                                 ltype = 1;
1314                                 ltype_depth = depth+1;
1315                         } else if (tmp =="Enumerate") {
1316                                 ltype = 2;
1317                                 ltype_depth = depth+1;
1318                         } else if (strstr(tmp.c_str(),"ection")) {
1319                                 ltype = 3;
1320                                 ltype_depth = depth+1;
1321                         } else if (strstr(tmp.c_str(),"aragraph")) {
1322                                 ltype = 4;
1323                                 ltype_depth = depth+1;
1324                         } else if (tmp == "Description") {
1325                                 ltype = 5;
1326                                 ltype_depth = depth+1;
1327                         } else if (tmp == "Abstract") {
1328                                 ltype = 6;
1329                                 ltype_depth = 0;
1330                         } else if (tmp == "Bibliography") {
1331                                 ltype = 7;
1332                                 ltype_depth = 0;
1333                         } else {
1334                                 ltype = 0;
1335                                 ltype_depth = 0;
1336                         }
1337          
1338                         /* maybe some vertical spaces */ 
1339
1340                         /* the labelwidthstring used in lists */ 
1341          
1342                         /* some lines? */ 
1343          
1344                         /* some pagebreaks? */ 
1345          
1346                         /* noindent ? */ 
1347          
1348                         /* what about the alignment */ 
1349                 }
1350                 else {
1351                         /* dummy layout, that means a footnote ended */ 
1352                         footnoteflag = LyXParagraph::NO_FOOTNOTE;
1353                         fprintf(file, ") ");
1354                         noparbreak = 1;
1355                 }
1356       
1357                 /* It might be a table */ 
1358                 if (par->table){
1359                         if (!lyxrc->ascii_roff_command.empty() &&
1360                             lyxrc->ascii_roff_command != "none") {
1361                                 RoffAsciiTable(file,par);
1362                                 par = par->next;
1363                                 continue;
1364                         }
1365                         cell = 1;
1366                         actcell = 0;
1367                         cells = par->table->columns;
1368                         clen = new int [cells];
1369                         memset(clen,0,sizeof(int)*cells);
1370 #ifdef NEW_TEXT
1371                         for (i = 0, j = 0, h = 1; i < par->size(); ++i, ++h) {
1372 #else
1373                         for (i = 0, j = 0, h=1; i < par->last; i++, h++) {
1374 #endif
1375                                 c = par->GetChar(i);
1376                                 if (c == LYX_META_INSET) {
1377                                         if ((inset = par->GetInset(i))) {
1378                                                 FilePtr fp(fname1,
1379                                                            FilePtr::write);
1380                                                 if (!fp()) {
1381                                                         WriteFSAlert(_("Error: Cannot open temporary file:"), fname1);
1382                                                         return;
1383                                                 }
1384                                                 inset->Latex(fp,-1);
1385                                                 h += ftell(fp) - 1;
1386                                                 remove(fname1.c_str());
1387                                         }
1388                                 } else if (c == LYX_META_NEWLINE) {
1389                                         if (clen[j] < h)
1390                                                 clen[j] = h;
1391                                         h = 0;
1392                                         j = (++j) % par->table->NumberOfCellsInRow(actcell);
1393                                         actcell++;
1394                                 }
1395                         }
1396                         if (clen[j] < h)
1397                                 clen[j] = h;
1398                 }
1399       
1400                 font1 = LyXFont(LyXFont::ALL_INHERIT);
1401                 actcell=0;
1402 #ifdef NEW_TEXT
1403                 for (i = 0, actpos = 1; i < par->size(); ++i, ++actpos) {
1404 #else
1405                 for (i = 0,actpos=1; i < par->last; i++, actpos++) {
1406 #endif
1407                         if (!i && !footnoteflag && !noparbreak){
1408                                 fprintf(file, "\n\n");
1409                                 for(j=0; j<depth; j++)
1410                                         fprintf(file, "  ");
1411                                 currlinelen = depth*2;
1412                                 switch(ltype) {
1413                                 case 0: /* Standart */
1414                                 case 4: /* (Sub)Paragraph */
1415                                 case 5: /* Description */
1416                                         break;
1417                                 case 6: /* Abstract */
1418                                         fprintf(file, "Abstract\n\n");
1419                                         break;
1420                                 case 7: /* Bibliography */
1421                                         if (!ref_printed) {
1422                                                 fprintf(file, "References\n\n");
1423                                                 ref_printed = true;
1424                                         }
1425                                         break;
1426                                 default:
1427                                         fprintf(file,"%s ",par->labelstring.c_str());
1428                                         break;
1429                                 }
1430                                 if (ltype_depth > depth) {
1431                                         for(j=ltype_depth-1; j>depth; j--)
1432                                                 fprintf(file, "  ");
1433                                         currlinelen += (ltype_depth-depth)*2;
1434                                 }
1435                                 if (par->table) {
1436                                         for(j=0;j<cells;j++) {
1437                                                 fputc('+',file);
1438                                                 for(h=0; h<(clen[j]+1); h++)
1439                                                         fputc('-',file);
1440                                         }
1441                                         fprintf(file,"+\n");
1442                                         for(j=0; j<depth; j++)
1443                                                 fprintf(file, "  ");
1444                                         currlinelen = depth*2;
1445                                         if (ltype_depth > depth) {
1446                                                 for(j=ltype_depth; j>depth; j--)
1447                                                         fprintf(file, "  ");
1448                                                 currlinelen += (ltype_depth-depth)*2;
1449                                         }
1450                                         fprintf(file,"| ");
1451                                 }
1452                         }
1453                         font2 = par->GetFontSettings(i);
1454                         if (font1.latex() != font2.latex()) {
1455                                 if (font2.latex() == LyXFont::OFF)
1456                                         islatex = 0;
1457                                 else
1458                                         islatex = 1;
1459                         }
1460                         else {
1461                                 islatex = 0;
1462                         }
1463                         c = par->GetChar(i);
1464                         if (islatex)
1465                                 continue;
1466                         switch (c) {
1467                         case LYX_META_INSET:
1468                                 if ((inset = par->GetInset(i))) {
1469                                         fpos = ftell(file);
1470                                         inset->Latex(file,-1);
1471                                         currlinelen += (ftell(file) - fpos);
1472                                         actpos += (ftell(file) - fpos) - 1;
1473                                 }
1474                                 break;
1475                         case LYX_META_NEWLINE:
1476                                 if (par->table) {
1477                                         if (par->table->NumberOfCellsInRow(actcell) <= cell) {
1478                                                 for(j=actpos;j<clen[cell-1];j++)
1479                                                         fputc(' ',file);
1480                                                 fprintf(file," |\n");
1481                                                 for(j=0; j<depth; j++)
1482                                                         fprintf(file, "  ");
1483                                                 currlinelen = depth*2;
1484                                                 if (ltype_depth > depth) {
1485                                                         for(j=ltype_depth; j>depth; j--)
1486                                                                 fprintf(file, "  ");
1487                                                         currlinelen += (ltype_depth-depth)*2;
1488                                                 }
1489                                                 for(j=0;j<cells;j++) {
1490                                                         fputc('+',file);
1491                                                         for(h=0; h<(clen[j]+1); h++)
1492                                                                 fputc('-',file);
1493                                                 }
1494                                                 fprintf(file,"+\n");
1495                                                 for(j=0; j<depth; j++)
1496                                                         fprintf(file, "  ");
1497                                                 currlinelen = depth*2;
1498                                                 if (ltype_depth > depth) {
1499                                                         for(j=ltype_depth; j>depth; j--)
1500                                                                 fprintf(file, "  ");
1501                                                         currlinelen += (ltype_depth-depth)*2;
1502                                                 }
1503                                                 fprintf(file,"| ");
1504                                                 cell = 1;
1505                                         } else {
1506                                                 for(j=actpos; j<clen[cell-1]; j++)
1507                                                         fputc(' ',file);
1508                                                 fprintf(file, " | ");
1509                                                 cell++;
1510                                         }
1511                                         actcell++;
1512                                         currlinelen = actpos = 0;
1513                                 } else {
1514                                         fprintf(file, "\n");
1515                                         for(j=0; j<depth; j++)
1516                                                 fprintf(file, "  ");
1517                                         currlinelen = depth*2;
1518                                         if (ltype_depth > depth) {
1519                                                 for(j=ltype_depth; j>depth; j--)
1520                                                         fprintf(file, "  ");
1521                                                 currlinelen += (ltype_depth-depth)*2;
1522                                         }
1523                                 }
1524                                 break;
1525                         case LYX_META_HFILL: 
1526                                 fprintf(file, "\t");
1527                                 break;
1528                         case LYX_META_PROTECTED_SEPARATOR:
1529                                 fprintf(file, " ");
1530                                 break;
1531                         case '\\': 
1532                                 fprintf(file, "\\");
1533                                 break;
1534                         default:
1535 #ifdef NEW_TEXT
1536                                 if (currlinelen > linelen - 10
1537                                     && c == ' ' && i + 2 < par->size()) {
1538 #else
1539                                 if (currlinelen > (linelen-10) \
1540                                     && c==' ' && (i+2 < par->last)) {
1541 #endif
1542                                         fprintf(file, "\n");
1543                                         for(j = 0; j < depth; ++j)
1544                                                 fprintf(file, "  ");
1545                                         currlinelen = depth * 2;
1546                                         if (ltype_depth > depth) {
1547                                                 for(j = ltype_depth;
1548                                                     j > depth; --j)
1549                                                         fprintf(file, "  ");
1550                                                 currlinelen += (ltype_depth-depth)*2;
1551                                         }
1552                                 } else if (c != '\0')
1553                                         fprintf(file, "%c", c);
1554                                 else if (c == '\0')
1555                                         lyxerr.debug() << "writeAsciiFile: NULL char in structure." << endl;
1556                                 currlinelen++;
1557                                 break;
1558                         }
1559                 }
1560                 if (par->table) {
1561                         for(j=actpos;j<clen[cell-1];j++)
1562                                 fputc(' ',file);
1563                         fprintf(file," |\n");
1564                         for(j=0; j<depth; j++)
1565                                 fprintf(file, "  ");
1566                         currlinelen = depth*2;
1567                         if (ltype_depth > depth) {
1568                                 for(j=ltype_depth; j>depth; j--)
1569                                         fprintf(file, "  ");
1570                                 currlinelen += (ltype_depth-depth)*2;
1571                         }
1572                         for(j=0;j<cells;j++) {
1573                                 fputc('+',file);
1574                                 for(h=0; h<(clen[j]+1); h++)
1575                                         fputc('-',file);
1576                         }
1577                         fprintf(file,"+\n");
1578                         delete [] clen;    
1579                 }      
1580                 par = par->next;
1581         }
1582    
1583         fprintf(file, "\n");
1584 }
1585
1586
1587 void Buffer::makeLaTeXFile(string const & filename, 
1588                            string const & original_path,
1589                            bool nice, bool only_body)
1590 {
1591         lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
1592         params.textclass = GetCurrentTextClass();
1593         niceFile = nice; // this will be used by Insetincludes.
1594
1595         tex_code_break_column = lyxrc->ascii_linelen;
1596
1597         LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
1598   
1599         FilePtr file(filename, FilePtr::write);
1600         if (!file()) {
1601                 WriteFSAlert(_("Error: Cannot write file:"),filename);
1602                 return;
1603         }
1604
1605         // validate the buffer.
1606         lyxerr[Debug::LATEX] << "  Validating buffer..." << endl;
1607         LaTeXFeatures features(tclass.numLayouts());
1608         validate(features);
1609         lyxerr[Debug::LATEX] << "  Buffer validation done." << endl;
1610         
1611         texrow.reset();
1612         // The starting paragraph of the coming rows is the 
1613         // first paragraph of the document. (Asger)
1614         texrow.start(paragraph, 0);
1615
1616         string userName(getUserName());
1617         string LFile;
1618         
1619         if (!only_body && nice) {
1620                 LFile += "%% This LaTeX-file was created by <";
1621                 LFile += userName + "> " + (char*)date();
1622                 LFile += "%% LyX 1.0 (C) 1995-1999 by Matthias Ettrich and the LyX Team\n";
1623                 LFile += "\n%% Do not edit this file unless you know what you are doing.\n";
1624                 texrow.newline();
1625                 texrow.newline();
1626                 texrow.newline();
1627                 texrow.newline();
1628         }
1629         lyxerr.debug() << "lyx header finished" << endl;
1630         // There are a few differences between nice LaTeX and usual files:
1631         // usual is \batchmode, uses \listfiles and has a 
1632         // special input@path to allow the including of figures
1633         // with either \input or \includegraphics (what figinsets do).
1634         // batchmode is not set if there is a tex_code_break_column.
1635         // In this case somebody is interested in the generated LaTeX,
1636         // so this is OK. input@path is set when the actual parameter
1637         // original_path is set. This is done for usual tex-file, but not
1638         // for nice-latex-file. (Matthias 250696)
1639         if (!only_body) {
1640                 if (!nice){
1641                         // code for usual, NOT nice-latex-file
1642                         LFile += "\\batchmode\n"; // changed
1643                         // from \nonstopmode
1644                         texrow.newline();
1645                         // We don't need listfiles anymore
1646                         //LFile += "\\listfiles\n";
1647                         //texrow.newline();
1648                 }
1649                 if (!original_path.empty()) {
1650                         LFile += "\\makeatletter\n";
1651                         texrow.newline();
1652                         LFile += "\\def\\input@path{{" + original_path
1653                                  + "/}}\n";
1654                         texrow.newline();
1655                         LFile += "\\makeatother\n";
1656                         texrow.newline();
1657                 }
1658                 
1659                 LFile += "\\documentclass";
1660                 
1661                 string options; // the document class options.
1662                 
1663                 if (tokenPos(tclass.opt_fontsize(), '|',params.fontsize) >= 0) {
1664                         // only write if existing in list (and not default)
1665                         options += params.fontsize;
1666                         options += "pt,";
1667                 }
1668                 
1669                 
1670                 if (!params.use_geometry &&
1671                     (params.paperpackage == PACKAGE_NONE)) {
1672                         switch (params.papersize) {
1673                         case PAPER_A4PAPER:
1674                                 options += "a4paper,";
1675                                 break;
1676                         case PAPER_USLETTER:
1677                                 options += "letterpaper,";
1678                                 break;
1679                         case PAPER_A5PAPER:
1680                                 options += "a5paper,";
1681                                 break;
1682                         case PAPER_B5PAPER:
1683                                 options += "b5paper,";
1684                                 break;
1685                         case PAPER_EXECUTIVEPAPER:
1686                                 options += "executivepaper,";
1687                                 break;
1688                         case PAPER_LEGALPAPER:
1689                                 options += "legalpaper,";
1690                                 break;
1691                         }
1692                 }
1693
1694                 // if needed
1695                 if (params.sides != tclass.sides()) {
1696                         if (params.sides == 2)
1697                                 options += "twoside,";
1698                         else
1699                                 options += "oneside,";
1700                 }
1701
1702                 // if needed
1703                 if (params.columns != tclass.columns()) {
1704                         if (params.columns == 2)
1705                                 options += "twocolumn,";
1706                         else
1707                                 options += "onecolumn,";
1708                 }
1709
1710                 if (!params.use_geometry && params.orientation == ORIENTATION_LANDSCAPE)
1711                         options += "landscape,";
1712                 
1713                 // language should be a parameter to \documentclass
1714                 if (params.language != "default") {
1715                         options += params.language + ',';
1716                 }
1717                 
1718                 // the user-defined options
1719                 if (!params.options.empty()) {
1720                         options += params.options + ',';
1721                 }
1722                 
1723                 if (!options.empty()){
1724                         options = strip(options, ',');
1725                         LFile += '[';
1726                         LFile += options;
1727                         LFile += ']';
1728                 }
1729                 
1730                 LFile += '{';
1731                 LFile += textclasslist.LatexnameOfClass(params.textclass);
1732                 LFile += "}\n";
1733                 texrow.newline();
1734                 // end of \documentclass defs
1735                 
1736                 // font selection must be done before loading fontenc.sty
1737                 if (params.fonts != "default") {
1738                         LFile += "\\usepackage{" + params.fonts + "}\n";
1739                         texrow.newline();
1740                 }
1741                 // this one is not per buffer
1742                 if (lyxrc->fontenc != "default") {
1743                         LFile += "\\usepackage[" + lyxrc->fontenc
1744                                  + "]{fontenc}\n";
1745                         texrow.newline();
1746                 }
1747                 if (params.inputenc != "default") {
1748                         LFile += "\\usepackage[" + params.inputenc
1749                                  + "]{inputenc}\n";
1750                         texrow.newline();
1751                 }
1752                 
1753                 /* at the very beginning the text parameters */
1754                 if (params.paperpackage != PACKAGE_NONE) {
1755                         switch (params.paperpackage) {
1756                         case PACKAGE_A4:
1757                                 LFile += "\\usepackage{a4}\n";
1758                                 texrow.newline();
1759                                 break;
1760                         case PACKAGE_A4WIDE:
1761                                 LFile += "\\usepackage{a4wide}\n";
1762                                 texrow.newline();
1763                                 break;
1764                         case PACKAGE_WIDEMARGINSA4:
1765                                 LFile += "\\usepackage[widemargins]{a4}\n";
1766                                 texrow.newline();
1767                                 break;
1768                         }
1769                 }
1770                 if (params.use_geometry) {
1771                         LFile += "\\usepackage{geometry}\n";
1772                         texrow.newline();
1773                         LFile += "\\geometry{verbose";
1774                         if (params.orientation == ORIENTATION_LANDSCAPE)
1775                                 LFile += ",landscape";
1776                         switch (params.papersize2) {
1777                         case VM_PAPER_CUSTOM:
1778                                 if (!params.paperwidth.empty())
1779                                         LFile += ",paperwidth="
1780                                                  + params.paperwidth;
1781                                 if (!params.paperheight.empty())
1782                                         LFile += ",paperheight="
1783                                                  + params.paperheight;
1784                                 break;
1785                         case VM_PAPER_USLETTER:
1786                                 LFile += ",letterpaper";
1787                                 break;
1788                         case VM_PAPER_USLEGAL:
1789                                 LFile += ",legalpaper";
1790                                 break;
1791                         case VM_PAPER_USEXECUTIVE:
1792                                 LFile += ",executivepaper";
1793                                 break;
1794                         case VM_PAPER_A3:
1795                                 LFile += ",a3paper";
1796                                 break;
1797                         case VM_PAPER_A4:
1798                                 LFile += ",a4paper";
1799                                 break;
1800                         case VM_PAPER_A5:
1801                                 LFile += ",a5paper";
1802                                 break;
1803                         case VM_PAPER_B3:
1804                                 LFile += ",b3paper";
1805                                 break;
1806                         case VM_PAPER_B4:
1807                                 LFile += ",b4paper";
1808                                 break;
1809                         case VM_PAPER_B5:
1810                                 LFile += ",b5paper";
1811                                 break;
1812                         default:
1813                                 // default papersize ie VM_PAPER_DEFAULT
1814                                 switch (lyxrc->default_papersize) {
1815                                 case PAPER_DEFAULT: // keep compiler happy
1816                                 case PAPER_USLETTER:
1817                                         LFile += ",letterpaper";
1818                                         break;
1819                                 case PAPER_LEGALPAPER:
1820                                         LFile += ",legalpaper";
1821                                         break;
1822                                 case PAPER_EXECUTIVEPAPER:
1823                                         LFile += ",executivepaper";
1824                                         break;
1825                                 case PAPER_A3PAPER:
1826                                         LFile += ",a3paper";
1827                                         break;
1828                                 case PAPER_A4PAPER:
1829                                         LFile += ",a4paper";
1830                                         break;
1831                                 case PAPER_A5PAPER:
1832                                         LFile += ",a5paper";
1833                                         break;
1834                                 case PAPER_B5PAPER:
1835                                         LFile += ",b5paper";
1836                                         break;
1837                                 }
1838                         }
1839                         if (!params.topmargin.empty())
1840                                 LFile += ",tmargin=" + params.topmargin;
1841                         if (!params.bottommargin.empty())
1842                                 LFile += ",bmargin=" + params.bottommargin;
1843                         if (!params.leftmargin.empty())
1844                                 LFile += ",lmargin=" + params.leftmargin;
1845                         if (!params.rightmargin.empty())
1846                                 LFile += ",rmargin=" + params.rightmargin;
1847                         if (!params.headheight.empty())
1848                                 LFile += ",headheight=" + params.headheight;
1849                         if (!params.headsep.empty())
1850                                 LFile += ",headsep=" + params.headsep;
1851                         if (!params.footskip.empty())
1852                                 LFile += ",footskip=" + params.footskip;
1853                         LFile += "}\n";
1854                         texrow.newline();
1855                 }
1856                 if (params.use_amsmath
1857                     && !prefixIs(textclasslist.LatexnameOfClass(params.textclass), "ams")) {
1858                         LFile += "\\usepackage{amsmath}\n";
1859                 }
1860
1861                 if (tokenPos(tclass.opt_pagestyle(), '|',params.pagestyle) >= 0) {
1862                         if (params.pagestyle == "fancy") {
1863                                 LFile += "\\usepackage{fancyhdr}\n";
1864                                 texrow.newline();
1865                         }
1866                         LFile += "\\pagestyle{" + params.pagestyle + "}\n";
1867                         texrow.newline();
1868                 }
1869
1870                 // We try to load babel late, in case it interferes
1871                 // with other packages.
1872                 if (params.language != "default") {
1873                         LFile += "\\usepackage{babel}\n";
1874                         texrow.newline();
1875                 }
1876
1877                 if (params.secnumdepth != tclass.secnumdepth()) {
1878                         LFile += "\\setcounter{secnumdepth}{";
1879                         LFile += tostr(params.secnumdepth);
1880                         LFile += "}\n";
1881                         texrow.newline();
1882                 }
1883                 if (params.tocdepth != tclass.tocdepth()) {
1884                         LFile += "\\setcounter{tocdepth}{";
1885                         LFile += tostr(params.tocdepth);
1886                         LFile += "}\n";
1887                         texrow.newline();
1888                 }
1889                 
1890                 if (params.paragraph_separation) {
1891                         switch (params.defskip.kind()) {
1892                         case VSpace::SMALLSKIP: 
1893                                 LFile += "\\setlength\\parskip{\\smallskipamount}\n";
1894                                 break;
1895                         case VSpace::MEDSKIP:
1896                                 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1897                                 break;
1898                         case VSpace::BIGSKIP:
1899                                 LFile += "\\setlength\\parskip{\\bigskipamount}\n";
1900                                 break;
1901                         case VSpace::LENGTH:
1902                                 LFile += "\\setlength\\parskip{"
1903                                          + params.defskip.length().asLatexString()
1904                                          + "}\n";
1905                                 break;
1906                         default: // should never happen // Then delete it.
1907                                 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1908                                 break;
1909                         }
1910                         texrow.newline();
1911                         
1912                         LFile += "\\setlength\\parindent{0pt}\n";
1913                         texrow.newline();
1914                 }
1915
1916                 // Write out what we've generated so far...and reset LFile
1917                 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
1918                 LFile.clear(); 
1919
1920                 // Now insert the LyX specific LaTeX commands...
1921                 string preamble, tmppreamble;
1922
1923                 // The optional packages;
1924                 preamble = features.getPackages(params);
1925
1926                 // this might be useful...
1927                 preamble += "\n\\makeatletter\n\n";
1928
1929                 // Some macros LyX will need
1930                 tmppreamble = features.getMacros(params);
1931
1932                 if (!tmppreamble.empty()) {
1933                         preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1934                                 "LyX specific LaTeX commands.\n"
1935                                 + tmppreamble + '\n';
1936                 }
1937
1938                 // the text class specific preamble 
1939                 tmppreamble = features.getTClassPreamble(params);
1940                 if (!tmppreamble.empty()) {
1941                         preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1942                                 "Textclass specific LaTeX commands.\n"
1943                                 + tmppreamble + '\n';
1944                 }
1945
1946                 /* the user-defined preamble */
1947                 if (!params.preamble.empty()) {
1948                         preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1949                                 "User specified LaTeX commands.\n"
1950                                 + params.preamble + '\n';
1951                 }
1952
1953                 preamble += "\\makeatother\n\n";
1954
1955                 // Itemize bullet settings need to be last in case the user
1956                 // defines their own bullets that use a package included
1957                 // in the user-defined preamble -- ARRae
1958                 for (int i = 0; i < 4; ++i) {
1959                         if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
1960                                 preamble += "\\renewcommand\\labelitemi";
1961                                 switch (i) {
1962                                         // `i' is one less than the item to modify
1963                                 case 0:
1964                                         break;
1965                                 case 1:
1966                                         preamble += 'i';
1967                                         break;
1968                                 case 2:
1969                                         preamble += "ii";
1970                                         break;
1971                                 case 3:
1972                                         preamble += 'v';
1973                                         break;
1974                                 }
1975                                 preamble += "[0]{" + params.user_defined_bullets[i].getText() + "}\n";
1976                         }
1977                 }
1978
1979                 for (int j = countChar(preamble, '\n'); j-- ;) {
1980                         texrow.newline();
1981                 }
1982
1983                 // A bit faster than printing a char at a time I think.
1984                 fwrite(preamble.c_str(), sizeof(char),
1985                        preamble.length(), file);
1986
1987                 // make the body.
1988                 LFile += "\\begin{document}\n\n";
1989                 texrow.newline();
1990                 texrow.newline();
1991         } // only_body
1992         lyxerr.debug() << "preamble finished, now the body." << endl;
1993         
1994         bool was_title = false;
1995         bool already_title = false;
1996         string ftnote;
1997         TexRow ft_texrow;
1998         int ftcount = 0;
1999         int loop_count = 0;
2000
2001         LyXParagraph * par = paragraph;
2002
2003         // if only_body
2004         while (par) {
2005                 ++loop_count;
2006                 if (par->IsDummy())
2007                         lyxerr[Debug::LATEX] << "Error in MakeLateXFile."
2008                                              << endl;
2009                 LyXLayout const & layout = textclasslist.Style(params.textclass,
2010                                                     par->layout);
2011             
2012                 if (layout.intitle) {
2013                         if (already_title) {
2014                                 lyxerr <<"Error in MakeLatexFile: You"
2015                                         " should not mix title layouts"
2016                                         " with normal ones." << endl;
2017                         } else
2018                                 was_title = true;
2019                 } else if (was_title && !already_title) {
2020                         LFile += "\\maketitle\n";
2021                         texrow.newline();
2022                         already_title = true;
2023                         was_title = false;                  
2024                 }
2025                 // We are at depth 0 so we can just use
2026                 // ordinary \footnote{} generation
2027                 // flag this with ftcount
2028                 ftcount = -1;
2029                 if (layout.isEnvironment()
2030                     || par->pextra_type != PEXTRA_NONE) {
2031                         par = par->TeXEnvironment(LFile, texrow,
2032                                                   ftnote, ft_texrow, ftcount);
2033                 } else {
2034                         par = par->TeXOnePar(LFile, texrow,
2035                                              ftnote, ft_texrow, ftcount);
2036                 }
2037
2038                 // Write out what we've generated...and reset LFile
2039                 if (ftcount >= 1) {
2040                         if (ftcount > 1) {
2041                                 LFile += "\\addtocounter{footnote}{-";
2042                                 LFile += tostr(ftcount - 1);
2043                                 LFile += '}';
2044                         }
2045                         LFile += ftnote;
2046                         texrow += ft_texrow;
2047                         ftnote.clear();
2048                         ft_texrow.reset();
2049                         ftcount = 0;
2050                 }
2051                 if (loop_count == 2) {
2052                         // fwrite()ing every second time through the loop
2053                         // gains a few extra % of speed; going higher than
2054                         // 2 will slow things down again.  I'll look at
2055                         // LFile.length() in a future revision.  ARRae
2056                         fwrite(LFile.c_str(), sizeof(char),
2057                                LFile.length(), file);
2058                         LFile.clear();
2059                         loop_count = 0;
2060                 }
2061         }
2062
2063         // It might be that we only have a title in this document
2064         if (was_title && !already_title) {
2065                 LFile += "\\maketitle\n";
2066                 texrow.newline();
2067         }
2068
2069         if (!only_body) {
2070                 LFile += "\\end{document}\n";
2071                 texrow.newline();
2072         
2073                 lyxerr[Debug::LATEX] << "makeLaTeXFile...done" << endl;
2074         } else {
2075                 lyxerr[Debug::LATEX] << "LaTeXFile for inclusion made."
2076                                      << endl;
2077         }
2078
2079         // Just to be sure. (Asger)
2080         texrow.newline();
2081
2082         // Write out what we've generated...and reset LFile
2083         fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
2084         LFile.clear();
2085
2086         // tex_code_break_column's value is used to decide
2087         // if we are in batchmode or not (within mathed_write()
2088         // in math_write.C) so we must set it to a non-zero
2089         // value when we leave otherwise we save incorrect .lyx files.
2090         tex_code_break_column = lyxrc->ascii_linelen;
2091
2092         if (file.close()) {
2093                 WriteFSAlert(_("Error! Could not close file properly:"), filename);
2094         }
2095         lyxerr.debug() << "Finished making latex file." << endl;
2096 }
2097
2098
2099 bool Buffer::isLatex()
2100 {
2101         return textclasslist.TextClass(params.textclass).outputType() == LATEX;
2102 }
2103
2104
2105 bool Buffer::isLinuxDoc()
2106 {
2107         return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC;
2108 }
2109
2110
2111 bool Buffer::isLiterate()
2112 {
2113         return textclasslist.TextClass(params.textclass).outputType() == LITERATE;
2114 }
2115
2116
2117 bool Buffer::isDocBook()
2118 {
2119         return textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2120 }
2121
2122
2123 bool Buffer::isSGML()
2124 {
2125         return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC ||
2126                textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2127 }
2128
2129
2130 void Buffer::sgmlOpenTag(FILE * file, int depth, string const & latexname) const
2131 {
2132         static char *space[] = {" ","  ","   ","    ","     ","      ","       ",
2133                          "        ","         ","          ","          "};
2134
2135         fprintf(file, "%s<%s>\n", space[depth], latexname.c_str());
2136 }
2137
2138
2139 void Buffer::sgmlCloseTag(FILE * file, int depth, string const & latexname) const
2140 {
2141         static char *space[] = {" ","  ","   ","    ","     ","      ","       ",
2142                          "        ","         ","          ","          "};
2143
2144         fprintf(file, "%s</%s>\n", space[depth], latexname.c_str());
2145 }
2146
2147
2148 void Buffer::makeLinuxDocFile(string const & filename, int column)
2149 {
2150         LyXParagraph * par = paragraph;
2151
2152         string top_element=textclasslist.LatexnameOfClass(params.textclass);
2153         string environment_stack[10];
2154         string item_name;
2155
2156         int depth = 0;              /* paragraph depth */
2157
2158         FilePtr file(filename, FilePtr::write);
2159         tex_code_break_column = column; 
2160
2161         if (!file()) {
2162                 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2163                 return;
2164         }
2165    
2166         //ResetTexRow();
2167         texrow.reset();
2168    
2169         if (params.preamble.empty()) {
2170                 fprintf(file, "<!doctype linuxdoc system>\n\n");
2171         }
2172         else {
2173                 fprintf(file, "<!doctype linuxdoc system \n [ %s \n]>\n\n", 
2174                         params.preamble.c_str() );
2175         }
2176
2177         string userName(getUserName());
2178         fprintf(file, "<!-- LinuxDoc file was created by LyX 1.0 (C) 1995-1999 ");
2179         fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2180
2181         if(params.options.empty())
2182                 sgmlOpenTag(file,0,top_element);
2183         else {
2184                 string top = top_element;
2185                 top += " ";
2186                 top += params.options;
2187                 sgmlOpenTag(file,0,top);
2188         }
2189
2190         while (par) {
2191                 int desc_on=0;            /* description mode*/
2192                 LyXLayout const & style=textclasslist.Style(GetCurrentTextClass(), par->layout);
2193                 par->AutoDeleteInsets();
2194
2195                 /* treat <toc> as a special case for compatibility with old code */
2196                 if (par->GetChar(0) == LYX_META_INSET) {
2197                         Inset *inset = par->GetInset(0);
2198                         char  lyx_code = inset->LyxCode();
2199                         if (lyx_code ==Inset::TOC_CODE){
2200                                 string temp= "toc";
2201                                 sgmlOpenTag(file, depth, temp);
2202
2203                                 par = par->next;
2204                                 linuxDocHandleFootnote(file, par, depth);
2205                                 continue;
2206                         }
2207                 }
2208
2209                 /* environment tag closing */
2210                 for( ;depth > par->depth; depth--) {
2211                         sgmlCloseTag(file,depth,environment_stack[depth]);
2212                         environment_stack[depth].clear();
2213                 }
2214
2215                 /* write opening SGML tags */
2216                 switch(style.latextype) {
2217                 case LATEX_PARAGRAPH:
2218                         if(depth == par->depth 
2219                            && !environment_stack[depth].empty()) {
2220                                 sgmlCloseTag(file,depth,environment_stack[depth]);
2221                                 environment_stack[depth].clear();
2222                                 if(depth) 
2223                                         depth--;
2224                                 else
2225                                         fprintf(file,"</p>");
2226                         }
2227                         sgmlOpenTag(file,depth,style.latexname());
2228                         break;
2229
2230                 case LATEX_COMMAND:
2231                         if (depth!=0)
2232                                 LinuxDocError(par, 0, _("Error : Wrong depth for LatexType Command.\n"));
2233
2234                         if (!environment_stack[depth].empty()){
2235                                 sgmlCloseTag(file,depth,environment_stack[depth]);
2236                                 fprintf(file, "</p>");
2237                         }
2238
2239                         environment_stack[depth].clear();
2240                         sgmlOpenTag(file,depth, style.latexname());
2241                         break;
2242
2243                 case LATEX_ENVIRONMENT:
2244                 case LATEX_ITEM_ENVIRONMENT:
2245                         if(depth == par->depth 
2246                            && environment_stack[depth] != style.latexname()
2247                            && !environment_stack[depth].empty()) {
2248
2249                                 sgmlCloseTag(file,depth,environment_stack[depth]);
2250                                 environment_stack[depth].clear();
2251                         }
2252                         if (depth < par->depth) {
2253                                depth = par->depth;
2254                                environment_stack[depth].clear();
2255                         }
2256                         if (environment_stack[depth] != style.latexname()) {
2257                                 if(depth==0) {
2258                                         string temp="p";
2259                                         sgmlOpenTag(file,depth,temp);
2260                                 }
2261                                 environment_stack[depth] = style.latexname();
2262                                 sgmlOpenTag(file,depth,environment_stack[depth]);
2263                         }
2264                         if(style.latextype == LATEX_ENVIRONMENT) break;
2265
2266                         desc_on =(style.labeltype == LABEL_MANUAL);
2267
2268                         if(desc_on)
2269                                 item_name="tag";
2270                         else
2271                                 item_name="item";
2272
2273                         sgmlOpenTag(file,depth+1,item_name);
2274                         break;
2275                 default:
2276                         sgmlOpenTag(file, depth, style.latexname());
2277                         break;
2278                 }
2279
2280                 do {
2281                         SimpleLinuxDocOnePar(file, par, desc_on, depth);
2282
2283                         par = par->next;
2284                         linuxDocHandleFootnote(file,par,depth);
2285                 }
2286                 while(par && par->IsDummy());
2287
2288                 fprintf(file,"\n");
2289                 /* write closing SGML tags */
2290                 switch(style.latextype) {
2291                 case LATEX_COMMAND:
2292                 case LATEX_ENVIRONMENT:
2293                 case LATEX_ITEM_ENVIRONMENT:
2294                         break;
2295                 default:
2296                         sgmlCloseTag(file, depth, style.latexname());
2297                         break;
2298                 }
2299
2300
2301         }
2302    
2303         
2304         /* Close open tags */
2305         for(;depth>0;depth--)
2306                 sgmlCloseTag(file,depth,environment_stack[depth]);
2307
2308         if(!environment_stack[depth].empty())
2309                 sgmlCloseTag(file,depth,environment_stack[depth]);
2310
2311         fprintf(file, "\n\n");
2312         sgmlCloseTag(file,0,top_element);
2313
2314         if (file.close()) {
2315                 WriteFSAlert(_("Error! Could not close file properly:"),
2316                              filename);
2317         }
2318 }
2319
2320
2321 void Buffer::linuxDocHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2322 {
2323         string tag="footnote";
2324
2325         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2326                 sgmlOpenTag(file,depth+1,tag);
2327                 SimpleLinuxDocOnePar(file, par, 0,depth+1);
2328                 sgmlCloseTag(file,depth+1,tag);
2329                 par = par->next;
2330         }
2331 }
2332
2333 void Buffer::DocBookHandleCaption(FILE *file, string &inner_tag,
2334                                   int const depth, int desc_on,
2335                                   LyXParagraph* &par)
2336 {
2337         LyXParagraph *tpar = par;
2338         string tmp_par, extra_par;
2339         while (tpar && (tpar->footnoteflag != LyXParagraph::NO_FOOTNOTE) &&
2340                (tpar->layout != textclasslist.NumberOfLayout(params.textclass,"Caption").second))
2341                 tpar = tpar->next;
2342         if (tpar &&
2343             tpar->layout==textclasslist.NumberOfLayout(params.textclass,"Caption").second) {
2344                 sgmlOpenTag(file,depth+1,inner_tag);
2345             SimpleDocBookOnePar(tmp_par,extra_par,tpar,desc_on,depth+2);
2346                tmp_par = strip(tmp_par);
2347                tmp_par = frontStrip(tmp_par);
2348                fprintf(file,"%s",tmp_par.c_str());
2349                sgmlCloseTag(file,depth+1,inner_tag);
2350                if(!extra_par.empty())
2351                        fprintf(file,"%s",extra_par.c_str());
2352        }
2353 }
2354
2355 void Buffer::DocBookHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2356 {
2357         string tag,inner_tag;
2358         string tmp_par,extra_par;
2359         bool inner_span = false;
2360         int desc_on=4;
2361
2362         // This is not how I like to see enums. They should not be anonymous
2363         // and variables of its type should not be declared right after the
2364         // last brace. (Lgb)
2365         enum {
2366                 NO_ONE,
2367                 FOOTNOTE_LIKE,
2368                 MARGIN_LIKE,
2369                 FIG_LIKE,
2370                 TAB_LIKE
2371         } last=NO_ONE, present=FOOTNOTE_LIKE;
2372
2373         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2374                 if(last==present) {
2375                         if(inner_span) {
2376                                 if(!tmp_par.empty()) {
2377                                         fprintf(file,"%s",tmp_par.c_str());
2378                                         tmp_par.clear();
2379                                         sgmlCloseTag(file,depth+1,inner_tag);
2380                                         sgmlOpenTag(file,depth+1,inner_tag);
2381                                 }
2382                         }
2383                         else
2384                                 fprintf(file,"\n");
2385                 } else {
2386                         fprintf(file,"%s",tmp_par.c_str());
2387                         if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2388                         if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2389                         if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2390                         extra_par.clear();
2391
2392                         switch (par->footnotekind) {
2393                         case LyXParagraph::FOOTNOTE:
2394                         case LyXParagraph::ALGORITHM:
2395                                 tag="footnote";
2396                                 inner_tag="para";
2397                                 present=FOOTNOTE_LIKE;
2398                                 inner_span=true;
2399                                 break;
2400                         case LyXParagraph::MARGIN:
2401                                 tag="sidebar";
2402                                 inner_tag="para";
2403                                 present=MARGIN_LIKE;
2404                                 inner_span=true;
2405                                 break;
2406                         case LyXParagraph::FIG:
2407                         case LyXParagraph::WIDE_FIG:
2408                                 tag="figure";
2409                                 inner_tag="title";
2410                                 present=FIG_LIKE;
2411                                 inner_span=false;
2412                                 break;
2413                         case LyXParagraph::TAB:
2414                         case LyXParagraph::WIDE_TAB:
2415                                 tag="table";
2416                                 inner_tag="title";
2417                                 present=TAB_LIKE;
2418                                 inner_span=false;
2419                                 break;
2420                         }
2421                         sgmlOpenTag(file,depth,tag);
2422                         if ((present == TAB_LIKE) || (present == FIG_LIKE)) {
2423                                 DocBookHandleCaption(file, inner_tag, depth,
2424                                                      desc_on, par);
2425                                 inner_tag.clear();
2426                         } else {
2427                                 sgmlOpenTag(file,depth+1,inner_tag);
2428                         }
2429                 }
2430                 // ignore all caption here, we processed them above!!!
2431                 if (par->layout != textclasslist.NumberOfLayout(params.textclass,
2432                                                            "Caption").second) {
2433                         SimpleDocBookOnePar(tmp_par,extra_par,par,
2434                                             desc_on,depth+2);
2435                 }
2436                 tmp_par = frontStrip(strip(tmp_par));
2437
2438                 last=present;
2439                 par = par->next;
2440         }
2441         fprintf(file,"%s",tmp_par.c_str());
2442         if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2443         if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2444         if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2445
2446 }
2447
2448
2449 /* push a tag in a style stack */
2450 void Buffer::push_tag(FILE *file, char const *tag,
2451                       int& pos, char stack[5][3])
2452 {
2453         int j;
2454
2455         /* pop all previous tags */
2456         for (j=pos; j>=0; j--)
2457                 fprintf(file, "</%s>", stack[j]); 
2458
2459         /* add new tag */
2460         sprintf(stack[++pos], "%s", tag);
2461
2462         /* push all tags */
2463         for (j=0; j<=pos; j++)
2464                 fprintf(file, "<%s>", stack[j]);
2465 }
2466
2467
2468 // pop a tag from a style stack
2469 void Buffer::pop_tag(FILE *file, char const * tag,
2470                      int& pos, char stack[5][3])
2471 {
2472         int j;
2473
2474         // pop all tags till specified one
2475         for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
2476                 fprintf(file, "</%s>", stack[j]);
2477
2478         // closes the tag
2479         fprintf(file, "</%s>", tag);
2480
2481         // push all tags, but the specified one
2482         for (j=j+1; j<=pos; j++) {
2483                 fprintf(file, "<%s>", stack[j]);
2484                 strcpy(stack[j-1], stack[j]);
2485         }
2486         pos --;
2487 }
2488
2489
2490 /* handle internal paragraph parsing -- layout already processed */
2491
2492 // checks, if newcol chars should be put into this line
2493 // writes newline, if necessary.
2494 static
2495 void linux_doc_line_break(FILE *file, unsigned int &colcount, const unsigned int newcol)
2496 {
2497         colcount += newcol;
2498         if (colcount > lyxrc->ascii_linelen) {
2499                 fprintf(file, "\n");
2500                 colcount = newcol; // assume write after this call
2501         }
2502 }
2503
2504
2505 void Buffer::SimpleLinuxDocOnePar(FILE *file, LyXParagraph *par, int desc_on, int const depth)
2506 {
2507         LyXFont font1,font2;
2508         char c;
2509         Inset * inset;
2510 #ifdef NEW_TEXT
2511         LyXParagraph::size_type main_body;
2512         int j;
2513 #else
2514         int main_body, j;
2515 #endif
2516         LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
2517
2518         char family_type = 0;               // family font flag 
2519         bool is_bold     = false;           // series font flag 
2520         char shape_type  = 0;               // shape font flag 
2521         bool is_em = false;                 // emphasis (italic) font flag 
2522
2523         int stack_num = -1;          // style stack position 
2524         char stack[5][3];            // style stack 
2525         unsigned int char_line_count = 5;     // Heuristic choice ;-) 
2526
2527         if (style.labeltype != LABEL_MANUAL)
2528                 main_body = 0;
2529         else
2530                 main_body = par->BeginningOfMainBody();
2531
2532         /* gets paragraph main font */
2533         if (main_body > 0)
2534                 font1 = style.labelfont;
2535         else
2536                 font1 = style.font;
2537
2538   
2539         /* parsing main loop */
2540 #ifdef NEW_TEXT
2541         for (LyXParagraph::size_type i = 0;
2542              i < par->size(); ++i) {
2543 #else
2544         for (int i = 0; i < par->last; i++) {
2545 #endif
2546
2547                 /* handle quote tag */
2548                 if (i == main_body && !par->IsDummy()) {
2549                         if (main_body > 0)
2550                                 font1 = style.font;
2551                 }
2552
2553                 font2 = par->getFont(i);
2554
2555                 if (font1.family() != font2.family()) {
2556                         switch(family_type) {
2557                         case 0:
2558                                 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2559                                         push_tag(file, "tt", stack_num, stack);
2560                                         family_type=1;
2561                                 }
2562                                 else if (font2.family() == LyXFont::SANS_FAMILY) {
2563                                         push_tag(file, "sf", stack_num, stack);
2564                                         family_type=2;
2565                                 }
2566                                 break;
2567                         case 1:
2568                                 pop_tag(file, "tt", stack_num, stack);
2569                                 if (font2.family() == LyXFont::SANS_FAMILY) {
2570                                         push_tag(file, "sf", stack_num, stack);
2571                                         family_type=2;
2572                                 }
2573                                 else {
2574                                         family_type=0;
2575                                 }
2576                                 break;
2577                         case 2:
2578                                 pop_tag(file, "sf", stack_num, stack);
2579                                 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2580                                         push_tag(file, "tt", stack_num, stack);
2581                                         family_type=1;
2582                                 }
2583                                 else {
2584                                         family_type=0;
2585                                 }
2586                         }
2587                 }
2588
2589                 /* handle bold face */
2590                 if (font1.series() != font2.series()) {
2591                         if (font2.series() == LyXFont::BOLD_SERIES) {
2592                                 push_tag(file, "bf", stack_num, stack);
2593                                 is_bold = true;
2594                         }
2595                         else if (is_bold) {
2596                                 pop_tag(file, "bf", stack_num, stack);
2597                                 is_bold = false;
2598                         }
2599                 }
2600
2601                 /* handle italic and slanted fonts */
2602                 if (font1.shape() != font2.shape()) {
2603                         switch(shape_type) {
2604                         case 0:
2605                                 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2606                                         push_tag(file, "it", stack_num, stack);
2607                                         shape_type=1;
2608                                 }
2609                                 else if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2610                                         push_tag(file, "sl", stack_num, stack);
2611                                         shape_type=2;
2612                                 }
2613                                 break;
2614                         case 1:
2615                                 pop_tag(file, "it", stack_num, stack);
2616                                 if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2617                                         push_tag(file, "sl", stack_num, stack);
2618                                         shape_type=2;
2619                                 }
2620                                 else {
2621                                         shape_type=0;
2622                                 }
2623                                 break;
2624                         case 2:
2625                                 pop_tag(file, "sl", stack_num, stack);
2626                                 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2627                                         push_tag(file, "it", stack_num, stack);
2628                                         shape_type=1;
2629                                 }
2630                                 else {
2631                                         shape_type=0;
2632                                 }
2633                         }
2634                 }
2635                 /* handle <em> tag */
2636                 if (font1.emph() != font2.emph()) {
2637                         if (font2.emph() == LyXFont::ON) {
2638                                 push_tag(file, "em", stack_num, stack);
2639                                 is_em = true;
2640                         } else if (is_em) {
2641                                 pop_tag(file, "em", stack_num, stack);
2642                                 is_em = false;
2643                         }
2644                 }
2645
2646                 c = par->GetChar(i);
2647       
2648                 if (font2.latex() == LyXFont::ON) {
2649                         // "TeX"-Mode on ==> SGML-Mode on.
2650                         if (c!='\0')
2651                                 fprintf(file, "%c", c); // see LaTeX-Generation...
2652                         char_line_count++;
2653                 } else if (c == LYX_META_INSET) {
2654                         inset = par->GetInset(i);
2655                         string tmp_out;
2656                         inset->Linuxdoc(tmp_out);
2657                         fprintf(file,"%s",tmp_out.c_str());
2658                 }
2659                 else {
2660                         string sgml_string;
2661                         if (par->linuxDocConvertChar(c, sgml_string)
2662                             && !style.free_spacing) { // in freespacing
2663                                                      // mode, spaces are
2664                                                      // non-breaking characters
2665                                 // char is ' '
2666                                 if (desc_on == 1) {
2667                                         char_line_count++;
2668                                         linux_doc_line_break(file, char_line_count, 6);
2669                                         fprintf(file, "</tag>");
2670                                         desc_on = 2;
2671                                 }
2672                                 else  {
2673                                         linux_doc_line_break(file, char_line_count, 1);
2674                                         fprintf(file, "%c", c);
2675                                 }
2676                         }
2677                         else {
2678                                 fprintf(file, "%s", sgml_string.c_str());
2679                                 char_line_count += sgml_string.length();
2680                         }
2681                 }
2682                 font1 = font2;
2683         }
2684
2685         /* needed if there is an optional argument but no contents */
2686 #ifdef NEW_TEXT
2687         if (main_body > 0 && main_body == par->size()) {
2688                 font1 = style.font;
2689         }
2690 #else
2691         if (main_body > 0 && main_body == par->last) {
2692                 font1 = style.font;
2693         }
2694 #endif
2695         /* pop all defined Styles */
2696         for (j = stack_num; j >= 0; j--) {
2697                 linux_doc_line_break(file, 
2698                                      char_line_count, 
2699                                      3+strlen(stack[j]));
2700                 fprintf(file, "</%s>", stack[j]);
2701         }
2702
2703         /* resets description flag correctly */
2704         switch(desc_on){
2705         case 1:
2706                 /* <tag> not closed... */
2707                 linux_doc_line_break(file, char_line_count, 6);
2708                 fprintf(file, "</tag>");
2709                 break;
2710         case 2:
2711                 /* fprintf(file, "</p>");*/
2712                 break;
2713         }
2714 }
2715
2716
2717 /* print an error message */
2718 void Buffer::LinuxDocError(LyXParagraph * par, int pos,
2719                            char const * message) 
2720 {
2721         InsetError * new_inset;
2722
2723         /* insert an error marker in text */
2724         new_inset = new InsetError(message);
2725         par->InsertChar(pos, LYX_META_INSET);
2726         par->InsertInset(pos, new_inset);
2727 }
2728
2729 // This constant defines the maximum number of 
2730 // environment layouts that can be nesteded.
2731 // The same applies for command layouts.
2732 // These values should be more than enough.
2733 //           José Matos (1999/07/22)
2734
2735 enum { MAX_NEST_LEVEL = 25};
2736
2737 void Buffer::makeDocBookFile(string const & filename, int column)
2738 {
2739         LyXParagraph * par = paragraph;
2740
2741         string top_element=textclasslist.LatexnameOfClass(params.textclass);
2742         string environment_stack[MAX_NEST_LEVEL];
2743         string environment_inner[MAX_NEST_LEVEL];
2744         string command_stack[MAX_NEST_LEVEL];
2745         bool command_flag=false;
2746         int command_depth=0,command_base=0,cmd_depth=0;
2747
2748         string item_name,command_name;
2749         string c_depth,c_params,tmps;
2750
2751         int depth=0;              /* paragraph depth */
2752
2753         FilePtr file(filename, FilePtr::write);
2754         tex_code_break_column = column; 
2755
2756         if (!file()) {
2757                 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2758                 return;
2759         }
2760    
2761         //ResetTexRow();
2762         texrow.reset();
2763
2764         fprintf(file,
2765                 "<!doctype %s public \"-//OASIS//DTD DocBook V3.1//EN\"",
2766                 top_element.c_str());
2767
2768         if (params.preamble.empty())
2769                 fprintf(file, ">\n\n");
2770         else
2771                 fprintf(file, "\n [ %s \n]>\n\n",params.preamble.c_str() );
2772
2773         string userName(getUserName());
2774         fprintf(file,
2775                 "<!-- DocBook file was created by LyX 1.0 (C) 1995-1999\n");
2776         fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2777
2778         if(params.options.empty())
2779                 sgmlOpenTag(file,0,top_element);
2780         else {
2781                 string top = top_element;
2782                 top += " ";
2783                 top += params.options;
2784                 sgmlOpenTag(file,0,top);
2785         }
2786
2787         while (par) {
2788                 int desc_on=0;            /* description mode*/
2789                 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2790                                                    par->layout);
2791                 par->AutoDeleteInsets();
2792
2793                 /* environment tag closing */
2794                 for( ;depth > par->depth; depth--) {
2795                         if(environment_inner[depth] != "!-- --") {
2796                                 item_name="listitem";
2797                                 sgmlCloseTag(file,command_depth+depth,
2798                                              item_name);
2799                                 if( environment_inner[depth] == "varlistentry")
2800                                         sgmlCloseTag(file,depth+command_depth,
2801                                                      environment_inner[depth]);
2802                         }
2803                         sgmlCloseTag(file,depth+command_depth,
2804                                      environment_stack[depth]);
2805                         environment_stack[depth].clear();
2806                         environment_inner[depth].clear();
2807                 }
2808
2809                 if(depth == par->depth
2810                    && environment_stack[depth] != style.latexname()
2811                    && !environment_stack[depth].empty()) {
2812                         if(environment_inner[depth] != "!-- --") {
2813                                 item_name="listitem";
2814                                 sgmlCloseTag(file,command_depth+depth,
2815                                              item_name);
2816                                 if( environment_inner[depth] == "varlistentry")
2817                                         sgmlCloseTag(file,depth+command_depth,
2818                                                      environment_inner[depth]);
2819                         }
2820                         
2821                         sgmlCloseTag(file,depth+command_depth,
2822                                      environment_stack[depth]);
2823                         
2824                         environment_stack[depth].clear();
2825                         environment_inner[depth].clear();
2826                 }
2827
2828                 // Write opening SGML tags.
2829                 switch(style.latextype) {
2830                 case LATEX_PARAGRAPH:
2831                         if(style.latexname() != "dummy")
2832                                sgmlOpenTag(file, depth+command_depth,
2833                                            style.latexname());
2834                         break;
2835
2836                 case LATEX_COMMAND:
2837                         if (depth!=0)
2838                                 LinuxDocError(par, 0,
2839                                               _("Error : Wrong depth for "
2840                                                 "LatexType Command.\n"));
2841                         
2842                         command_name = style.latexname();
2843                         
2844                         tmps = style.latexparam();
2845                         c_params = split(tmps, c_depth,'|');
2846                         
2847                         cmd_depth=atoi(c_depth.c_str());
2848                         
2849                         if(command_flag) {
2850                                 if(cmd_depth<command_base) {
2851                                         for(int j = command_depth;
2852                                             j >= command_base; j--)
2853                                                 if(!command_stack[j].empty())
2854                                                         sgmlCloseTag(file,j,command_stack[j]);
2855                                         command_depth=command_base=cmd_depth;
2856                                 }
2857                                 else if(cmd_depth<=command_depth) {
2858                                         for(int j= command_depth;
2859                                             j >= cmd_depth; j--)
2860
2861                                                 if(!command_stack[j].empty())
2862                                                         sgmlCloseTag(file,j,command_stack[j]);
2863                                         command_depth=cmd_depth;
2864                                 }
2865                                 else
2866                                         command_depth=cmd_depth;
2867                         }
2868                         else {
2869                                 command_depth = command_base = cmd_depth;
2870                                 command_flag = true;
2871                         }
2872                         command_stack[command_depth]=command_name;
2873
2874                         // treat label as a special case for
2875                         // more WYSIWYM handling.
2876                         if (par->GetChar(0) == LYX_META_INSET) {
2877                                 Inset *inset = par->GetInset(0);
2878                                 char  lyx_code = inset->LyxCode();
2879                                 if (lyx_code ==Inset::LABEL_CODE){
2880                                         command_name+= " id=\"";
2881                                         command_name+=((InsetCommand *) inset)->getContents();
2882                                         command_name+="\"";
2883                                         desc_on=3;
2884                                 }
2885                         }
2886
2887                         sgmlOpenTag(file,depth+command_depth, command_name);
2888                         item_name="title";
2889                         sgmlOpenTag(file,depth+1+command_depth,item_name);
2890                         break;
2891
2892                 case LATEX_ENVIRONMENT:
2893                 case LATEX_ITEM_ENVIRONMENT:
2894                         if (depth < par->depth) {
2895                                 depth = par->depth;
2896                                 environment_stack[depth].clear();
2897                         }
2898
2899                         if (environment_stack[depth] != style.latexname()) {
2900                                 environment_stack[depth]= style.latexname();
2901                                 environment_inner[depth]= "!-- --";
2902                                 sgmlOpenTag(file, depth + command_depth,
2903                                             environment_stack[depth]);
2904                         } else {
2905                                 if(environment_inner[depth] != "!-- --") {
2906                                         item_name="listitem";
2907                                         sgmlCloseTag(file,
2908                                                      command_depth + depth,
2909                                                      item_name);
2910                                         if (environment_inner[depth] == "varlistentry")
2911                                                 sgmlCloseTag(file,
2912                                                              depth+command_depth,
2913                                                              environment_inner[depth]);
2914                                 }
2915                         }
2916                         
2917                         if(style.latextype == LATEX_ENVIRONMENT) {
2918                                 if(!style.latexparam().empty())
2919                                         sgmlOpenTag(file, depth+command_depth,
2920                                                     style.latexparam());
2921                                 break;
2922                         }
2923
2924                         desc_on =(style.labeltype == LABEL_MANUAL);
2925
2926                         if(desc_on)
2927                                 environment_inner[depth]="varlistentry";
2928                         else
2929                                 environment_inner[depth]="listitem";
2930
2931                         sgmlOpenTag(file,depth+1+command_depth,
2932                                     environment_inner[depth]);
2933
2934                         if(desc_on) {
2935                                 item_name="term";
2936                                 sgmlOpenTag(file,depth+1+command_depth,
2937                                             item_name);
2938                         }
2939                         else {
2940                                 item_name="para";
2941                                 sgmlOpenTag(file,depth+1+command_depth,
2942                                             item_name);
2943                         }
2944                         break;
2945                 default:
2946                         sgmlOpenTag(file, depth + command_depth,
2947                                     style.latexname());
2948                         break;
2949                 }
2950
2951                 do {
2952                         string tmp_par,extra_par;
2953
2954                         SimpleDocBookOnePar(tmp_par,extra_par, par, desc_on,
2955                                             depth+1+command_depth);
2956                         fprintf(file,"%s",tmp_par.c_str());
2957
2958                         par = par->next;
2959                         DocBookHandleFootnote(file,par, depth+1+command_depth);
2960                 }
2961                 while(par && par->IsDummy());
2962
2963                 string end_tag;
2964                 /* write closing SGML tags */
2965                 switch(style.latextype) {
2966                 case LATEX_COMMAND:
2967                         end_tag = "title";
2968                         sgmlCloseTag(file, depth + command_depth, end_tag);
2969                         break;
2970                 case LATEX_ENVIRONMENT:
2971                         if(!style.latexparam().empty())
2972                                 sgmlCloseTag(file, depth + command_depth,
2973                                              style.latexparam());
2974                         break;
2975                 case LATEX_ITEM_ENVIRONMENT:
2976                         if(desc_on==1) break;
2977                         end_tag="para";
2978                         sgmlCloseTag(file,depth+1+command_depth,end_tag);
2979                         break;
2980                 case LATEX_PARAGRAPH:
2981                         if(style.latexname() != "dummy")
2982                                 sgmlCloseTag(file, depth + command_depth,
2983                                              style.latexname());
2984                         break;
2985                 default:
2986                         sgmlCloseTag(file,depth+command_depth,
2987                                      style.latexname());
2988                         break;
2989                 }
2990         }
2991
2992         // Close open tags
2993         for(;depth>=0;depth--) {
2994                 if(!environment_stack[depth].empty()) {
2995                         if(environment_inner[depth] != "!-- --") {
2996                                 item_name="listitem";
2997                                 sgmlCloseTag(file,command_depth+depth,
2998                                              item_name);
2999                                if( environment_inner[depth] == "varlistentry")
3000                                        sgmlCloseTag(file,depth+command_depth,
3001                                                     environment_inner[depth]);
3002                         }
3003                         
3004                         sgmlCloseTag(file,depth+command_depth,
3005                                      environment_stack[depth]);
3006                 }
3007         }
3008         
3009         for(int j=command_depth;j>=command_base;j--)
3010                 if(!command_stack[j].empty())
3011                         sgmlCloseTag(file,j,command_stack[j]);
3012
3013         fprintf(file, "\n\n");
3014         sgmlCloseTag(file,0,top_element);
3015
3016         if (file.close()) {
3017                 WriteFSAlert(_("Error! Could not close file properly:"),
3018                              filename);
3019         }
3020 }
3021
3022
3023 void Buffer::SimpleDocBookOnePar(string & file, string & extra,
3024                                  LyXParagraph * par, int & desc_on,
3025                                  int const depth) 
3026 {
3027         if (par->table) {
3028                 par->SimpleDocBookOneTablePar(file, extra, desc_on, depth);
3029                 return;
3030         }
3031         LyXFont font1,font2;
3032         char c;
3033         Inset *inset;
3034 #ifdef NEW_TEXT
3035         LyXParagraph::size_type main_body;
3036         int j;
3037 #else
3038         int main_body, j;
3039 #endif
3040         string emph="emphasis";
3041         bool emph_flag=false;
3042         int char_line_count=0;
3043
3044         LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
3045
3046         if (style.labeltype != LABEL_MANUAL)
3047                 main_body = 0;
3048         else
3049                 main_body = par->BeginningOfMainBody();
3050
3051         /* gets paragraph main font */
3052         if (main_body > 0)
3053                 font1 = style.labelfont;
3054         else
3055                 font1 = style.font;
3056
3057         char_line_count = depth;
3058         if(!style.free_spacing)
3059                 for (j=0;j< depth;j++)
3060                         file += ' ';
3061
3062         /* parsing main loop */
3063 #ifdef NEW_TEXT
3064         for (LyXParagraph::size_type i = 0;
3065              i < par->size(); ++i) {
3066 #else
3067         for (int i = 0; i < par->last; i++) {
3068 #endif
3069                 font2 = par->getFont(i);
3070
3071                 /* handle <emphasis> tag */
3072                 if (font1.emph() != font2.emph() && i) {
3073                         if (font2.emph() == LyXFont::ON) {
3074                                 file += "<emphasis>";
3075                                 emph_flag=true;
3076                         }else {
3077                                 file += "</emphasis>";
3078                                 emph_flag=false;
3079                         }
3080                 }
3081       
3082                 c = par->GetChar(i);
3083
3084                 if (c == LYX_META_INSET) {
3085                         inset = par->GetInset(i);
3086                         string tmp_out;
3087                         inset->DocBook(tmp_out);
3088                         //
3089                         // This code needs some explanation:
3090                         // Two insets are treated specially
3091                         //   label if it is the first element in a command paragraph
3092                         //         desc_on==3
3093                         //   graphics inside tables or figure floats can't go on
3094                         //   title (the equivalente in latex for this case is caption
3095                         //   and title should come first
3096                         //         desc_on==4
3097                         //
3098                         if(desc_on!=3 || i!=0) {
3099                                 if(tmp_out[0]=='@') {
3100                                         if(desc_on==4)
3101                                                 extra += frontStrip(tmp_out, '@');
3102                                         else
3103                                                 file += frontStrip(tmp_out, '@');
3104                                 }
3105                                 else
3106                                         file += tmp_out;
3107                         }
3108                 } else if (font2.latex() == LyXFont::ON) {
3109                         // "TeX"-Mode on ==> SGML-Mode on.
3110                         if (c!='\0')
3111                                 file += c;
3112                         char_line_count++;
3113                 }
3114                 else {
3115                         string sgml_string;
3116                         if (par->linuxDocConvertChar(c, sgml_string)
3117                             && !style.free_spacing) { // in freespacing
3118                                                      // mode, spaces are
3119                                                      // non-breaking characters
3120                                 // char is ' '
3121                                 if (desc_on == 1) {
3122                                         char_line_count++;
3123                                         file += '\n';
3124                                         file += "</term><listitem><para>";
3125                                         desc_on = 2;
3126                                 }
3127                                 else  {
3128                                         file += c;
3129                                 }
3130                         }
3131                         else {
3132                                 file += sgml_string;
3133                         }
3134                 }
3135                 font1 = font2;
3136         }
3137
3138         /* needed if there is an optional argument but no contents */
3139 #ifdef NEW_TEXT
3140         if (main_body > 0 && main_body == par->size()) {
3141                 font1 = style.font;
3142         }
3143 #else
3144         if (main_body > 0 && main_body == par->last) {
3145                 font1 = style.font;
3146         }
3147 #endif
3148         if (emph_flag) {
3149                 file += "</emphasis>";
3150         }
3151         
3152         /* resets description flag correctly */
3153         switch(desc_on){
3154         case 1:
3155                 /* <term> not closed... */
3156                 file += "</term>";
3157                 break;
3158         }
3159         file += '\n';
3160 }
3161
3162
3163 bool Buffer::removeAutoInsets()
3164 {
3165         LyXParagraph *par = paragraph;
3166
3167         LyXCursor cursor = text->cursor;
3168         LyXCursor tmpcursor = cursor;
3169         cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
3170         cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
3171
3172         bool a = false;
3173         while (par) {
3174                 if (par->AutoDeleteInsets()){
3175                         a = true;
3176                         if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
3177                                 /* this is possible now, since SetCursor takes
3178                                    care about footnotes */
3179                                 text->SetCursorIntern(par, 0);
3180                                 text->RedoParagraphs(text->cursor, text->cursor.par->Next());
3181                                 text->FullRebreak();
3182                         }
3183                 }
3184                 par = par->next;
3185         }
3186         /* avoid forbidden cursor positions caused by error removing */ 
3187         if (cursor.pos > cursor.par->Last())
3188                 cursor.pos = cursor.par->Last();
3189         text->SetCursorIntern(cursor.par, cursor.pos);
3190
3191         return a;
3192 }
3193
3194
3195 int Buffer::runLaTeX()
3196 {
3197         if (!text) return 0;
3198
3199         ProhibitInput();
3200
3201         // get LaTeX-Filename
3202         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3203
3204         string path = OnlyPath(filename);
3205
3206         string org_path = path;
3207         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3208                 path = tmppath;  
3209         }
3210
3211         Path p(path); // path to LaTeX file
3212         users->owner()->getMiniBuffer()->Set(_("Running LaTeX..."));   
3213
3214         // Remove all error insets
3215         bool a = removeAutoInsets();
3216
3217         // Always generate the LaTeX file
3218         makeLaTeXFile(name, org_path, false);
3219         markDviDirty();
3220
3221         // do the LaTex run(s)
3222         TeXErrors terr;
3223         LaTeX latex(lyxrc->latex_command, name, filepath);
3224         int res = latex.run(terr,
3225                             users->owner()->getMiniBuffer()); // running latex
3226
3227         // check return value from latex.run().
3228         if ((res & LaTeX::NO_LOGFILE)) {
3229                 WriteAlert(_("LaTeX did not work!"),
3230                            _("Missing log file:"), name);
3231         } else if ((res & LaTeX::ERRORS)) {
3232                 users->owner()->getMiniBuffer()->Set(_("Done"));
3233                 // Insert all errors as errors boxes
3234                 insertErrors(terr);
3235                 
3236                 // Dvi should also be kept dirty if the latex run
3237                 // ends up with errors. However it should be possible
3238                 // to view a dirty dvi too.
3239         } else {
3240                 //no errors or any other things to think about so:
3241                 users->owner()->getMiniBuffer()->Set(_("Done"));
3242                 markDviClean();
3243         }
3244
3245         // if we removed error insets before we ran LaTeX or if we inserted
3246         // error insets after we ran LaTeX this must be run:
3247         if (a || (res & LaTeX::ERRORS)){
3248                 users->redraw();
3249                 users->fitCursor();
3250                 users->updateScrollbar();
3251         }
3252         AllowInput();
3253  
3254         return latex.getNumErrors();
3255 }
3256
3257
3258 int Buffer::runLiterate()
3259 {
3260         if (!text) return 0;
3261
3262         ProhibitInput();
3263
3264         // get LaTeX-Filename
3265         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3266         // get Literate-Filename
3267         string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3268
3269         string path = OnlyPath(filename);
3270
3271         string org_path = path;
3272         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3273                 path = tmppath;  
3274         }
3275
3276         Path p(path); // path to Literate file
3277         users->owner()->getMiniBuffer()->Set(_("Running Literate..."));   
3278
3279         // Remove all error insets
3280         bool a = removeAutoInsets();
3281
3282         // generate the Literate file if necessary
3283         if (!isDviClean() || a) {
3284                 makeLaTeXFile(lit_name, org_path, false);
3285                 markDviDirty();
3286         }
3287
3288         Literate literate(lyxrc->latex_command, name, filepath, 
3289                           lit_name,
3290                           lyxrc->literate_command, lyxrc->literate_error_filter,
3291                           lyxrc->build_command, lyxrc->build_error_filter);
3292         TeXErrors terr;
3293         int res = literate.weave(terr, users->owner()->getMiniBuffer());
3294
3295         // check return value from literate.weave().
3296         if ((res & Literate::NO_LOGFILE)) {
3297                 WriteAlert(_("Literate command did not work!"),
3298                            _("Missing log file:"), name);
3299         } else if ((res & Literate::ERRORS)) {
3300                 users->owner()->getMiniBuffer()->Set(_("Done"));
3301                 // Insert all errors as errors boxes
3302                 insertErrors(terr);
3303                 
3304                 // Dvi should also be kept dirty if the latex run
3305                 // ends up with errors. However it should be possible
3306                 // to view a dirty dvi too.
3307         } else {
3308                 //no errors or any other things to think about so:
3309                 users->owner()->getMiniBuffer()->Set(_("Done"));
3310                 markDviClean();
3311         }
3312
3313         // if we removed error insets before we ran LaTeX or if we inserted
3314         // error insets after we ran LaTeX this must be run:
3315         if (a || (res & Literate::ERRORS)){
3316                 users->redraw();
3317                 users->fitCursor();
3318                 users->updateScrollbar();
3319         }
3320         AllowInput();
3321  
3322         return literate.getNumErrors();
3323 }
3324
3325
3326 int Buffer::buildProgram()
3327 {
3328         if (!text) return 0;
3329  
3330         ProhibitInput();
3331  
3332         // get LaTeX-Filename
3333         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3334         // get Literate-Filename
3335         string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3336  
3337         string path = OnlyPath(filename);
3338  
3339         string org_path = path;
3340         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3341                 path = tmppath;  
3342         }
3343  
3344         Path p(path); // path to Literate file
3345         users->owner()->getMiniBuffer()->Set(_("Building Program..."));   
3346  
3347         // Remove all error insets
3348         bool a = removeAutoInsets();
3349  
3350         // generate the LaTeX file if necessary
3351         if (!isNwClean() || a) {
3352                 makeLaTeXFile(lit_name, org_path, false);
3353                 markNwDirty();
3354         }
3355  
3356         Literate literate(lyxrc->latex_command, name, filepath, 
3357                           lit_name,
3358                           lyxrc->literate_command, lyxrc->literate_error_filter,
3359                           lyxrc->build_command, lyxrc->build_error_filter);
3360         TeXErrors terr;
3361         int res = literate.build(terr, users->owner()->getMiniBuffer());
3362  
3363         // check return value from literate.build().
3364         if ((res & Literate::NO_LOGFILE)) {
3365                 WriteAlert(_("Build did not work!"),
3366                            _("Missing log file:"), name);
3367         } else if ((res & Literate::ERRORS)) {
3368                 users->owner()->getMiniBuffer()->Set(_("Done"));
3369                 // Insert all errors as errors boxes
3370                 insertErrors(terr);
3371                 
3372                 // Literate files should also be kept dirty if the literate 
3373                 // command run ends up with errors.
3374         } else {
3375                 //no errors or any other things to think about so:
3376                 users->owner()->getMiniBuffer()->Set(_("Done"));
3377                 markNwClean();
3378         }
3379  
3380         // if we removed error insets before we ran Literate/Build or if we inserted
3381         // error insets after we ran Literate/Build this must be run:
3382         if (a || (res & Literate::ERRORS)){
3383                 users->redraw();
3384                 users->fitCursor();
3385                 users->updateScrollbar();
3386         }
3387         AllowInput();
3388
3389         return literate.getNumErrors();
3390 }
3391
3392
3393 // This should be enabled when the Chktex class is implemented. (Asger)
3394 // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
3395 // Other flags: -wall -v0 -x
3396 int Buffer::runChktex()
3397 {
3398         if (!text) return 0;
3399
3400         ProhibitInput();
3401
3402         // get LaTeX-Filename
3403         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3404         string path = OnlyPath(filename);
3405
3406         string org_path = path;
3407         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3408                 path = tmppath;  
3409         }
3410
3411         Path p(path); // path to LaTeX file
3412         users->owner()->getMiniBuffer()->Set(_("Running chktex..."));
3413
3414         // Remove all error insets
3415         bool a = removeAutoInsets();
3416
3417         // Generate the LaTeX file if neccessary
3418         if (!isDviClean() || a) {
3419                 makeLaTeXFile(name, org_path, false);
3420                 markDviDirty();
3421         }
3422
3423         TeXErrors terr;
3424         Chktex chktex(lyxrc->chktex_command, name, filepath);
3425         int res = chktex.run(terr); // run chktex
3426
3427         if (res == -1) {
3428                 WriteAlert(_("chktex did not work!"),
3429                            _("Could not run with file:"), name);
3430         } else if (res > 0) {
3431                 // Insert all errors as errors boxes
3432                 insertErrors(terr);
3433         }
3434
3435         // if we removed error insets before we ran chktex or if we inserted
3436         // error insets after we ran chktex, this must be run:
3437         if (a || res){
3438                 users->redraw();
3439                 users->fitCursor();
3440                 users->updateScrollbar();
3441         }
3442         AllowInput();
3443
3444         return res;
3445 }
3446
3447
3448 extern void AllFloats(char, char);
3449
3450
3451 void Buffer::insertErrors(TeXErrors & terr)
3452 {
3453         // Save the cursor position
3454         LyXCursor cursor = text->cursor;
3455
3456         // This is drastic, but it's the only fix, I could find. (Asger)
3457         AllFloats(1,0);
3458         AllFloats(1,1);
3459
3460         for (TeXErrors::Errors::const_iterator cit = terr.begin();
3461              cit != terr.end();
3462              ++cit) {
3463                 string desctext((*cit).error_desc);
3464                 string errortext((*cit).error_text);
3465                 string msgtxt = desctext + '\n' + errortext;
3466                 int errorrow = (*cit).error_in_line;
3467
3468                 // Insert error string for row number
3469                 int tmpid = -1; 
3470                 int tmppos = -1;
3471
3472                 texrow.getIdFromRow(errorrow, tmpid, tmppos);
3473
3474                 LyXParagraph* texrowpar;
3475
3476                 if (tmpid == -1) {
3477                         texrowpar = text->FirstParagraph();
3478                         tmppos = 0;
3479                 } else {
3480                         texrowpar = text->GetParFromID(tmpid);
3481                 }
3482
3483                 if (texrowpar == 0)
3484                         continue;
3485
3486                 InsetError *new_inset = new InsetError(msgtxt);
3487
3488                 text->SetCursorIntern(texrowpar, tmppos);
3489                 text->InsertInset(new_inset);
3490                 text->FullRebreak();
3491         }
3492         // Restore the cursor position
3493         text->SetCursorIntern(cursor.par, cursor.pos);
3494 }
3495
3496
3497 void Buffer::setCursorFromRow (int row)
3498 {
3499         int tmpid = -1; 
3500         int tmppos = -1;
3501
3502         texrow.getIdFromRow(row, tmpid, tmppos);
3503
3504         LyXParagraph* texrowpar;
3505
3506         if (tmpid == -1) {
3507                 texrowpar = text->FirstParagraph();
3508                 tmppos = 0;
3509         } else {
3510                 texrowpar = text->GetParFromID(tmpid);
3511         }
3512         text->SetCursor(texrowpar, tmppos);
3513 }
3514
3515
3516 void Buffer::RoffAsciiTable(FILE * file, LyXParagraph * par)
3517 {
3518         LyXFont
3519                 font1 =  LyXFont(LyXFont::ALL_INHERIT),
3520                 font2;
3521         Inset * inset;
3522 #ifdef NEW_TEXT
3523         LyXParagraph::size_type i;
3524 #else
3525         int i;
3526 #endif
3527         int
3528                 j,
3529                 cell = 0;
3530         char
3531                 c;
3532         FILE
3533                 * fp, * fp2;
3534         
3535         string fname1 = TmpFileName(string(),"RAT1");
3536         string fname2 = TmpFileName(string(),"RAT2");
3537         if (!(fp=fopen(fname1.c_str(),"w"))) {
3538                 WriteAlert(_("LYX_ERROR:"),
3539                            _("Cannot open temporary file:"), fname1);
3540                 return;
3541         }
3542         par->table->RoffEndOfCell(fp, -1);
3543 #ifdef NEW_TEXT
3544         for (i = 0; i < par->size(); ++i) {
3545 #else
3546         for (i = 0; i < par->last; ++i) {
3547 #endif
3548                 c = par->GetChar(i);
3549                 if (par->table->IsContRow(cell)) {
3550                         if (c == LYX_META_NEWLINE)
3551                                 cell++;
3552                         continue;
3553                 }
3554                 font2 = par->GetFontSettings(i);
3555                 if (font1.latex() != font2.latex()) {
3556                         if (font2.latex() != LyXFont::OFF)
3557                                 continue;
3558                 }
3559                 switch (c) {
3560                 case LYX_META_INSET:
3561                         if ((inset = par->GetInset(i))) {
3562                                 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3563                                         WriteAlert(_("LYX_ERROR:"),
3564                                                    _("Cannot open temporary file:"), fname2);
3565                                         fclose(fp);
3566                                         remove(fname1.c_str());
3567                                         return;
3568                                 }
3569                                 inset->Latex(fp2,-1);
3570                                 rewind(fp2);
3571                                 c = fgetc(fp2);
3572                                 while(!feof(fp2)) {
3573                                         if (c == '\\')
3574                                                 fprintf(fp,"\\\\");
3575                                         else
3576                                                 fputc(c,fp);
3577                                         c = fgetc(fp2);
3578                                 }
3579                                 fclose(fp2);
3580                         }
3581                         break;
3582                 case LYX_META_NEWLINE:
3583                         if (par->table->CellHasContRow(cell)>=0)
3584                                 par->RoffContTableRows(fp, i+1,cell);
3585                         par->table->RoffEndOfCell(fp, cell);
3586                         cell++;
3587                         break;
3588                 case LYX_META_HFILL: 
3589                         break;
3590                 case LYX_META_PROTECTED_SEPARATOR:
3591                         break;
3592                 case '\\': 
3593                         fprintf(fp, "\\\\");
3594                         break;
3595                 default:
3596                         if (c != '\0')
3597                                 fprintf(fp, "%c", c);
3598                         else if (c == '\0')
3599                                 lyxerr.debug()
3600                                         << "RoffAsciiTable:"
3601                                         " NULL char in structure." << endl;
3602                         break;
3603                 }
3604         }
3605         par->table->RoffEndOfCell(fp, cell);
3606         fclose(fp);
3607         string cmd = lyxrc->ascii_roff_command + " >" + fname2;
3608         cmd = subst(cmd, "$$FName", fname1);
3609         Systemcalls one(Systemcalls::System, cmd);
3610         if (!(lyxerr.debugging(Debug::ROFF))) {
3611                 remove(fname1.c_str());
3612         }
3613         if (!(fp=fopen(fname2.c_str(),"r"))) {
3614                 WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
3615                 return;
3616         }
3617         // now output the produced file
3618         fprintf(file, "\n\n");
3619         c = fgetc(fp);
3620         if (feof(fp))
3621                 WriteAlert(_("Error!"),
3622                            _("Error executing *roff command on table"));
3623         // overread leading blank lines
3624         while(!feof(fp) && (c == '\n'))
3625                 c = fgetc(fp);
3626         while(!feof(fp)) {
3627                 for(j=0; j<par->depth; j++)
3628                         fprintf(file, "  ");
3629                 while(!feof(fp) && (c != '\n')) {
3630                         fputc(c,file);
3631                         c = fgetc(fp);
3632                 }
3633                 fputc('\n',file);
3634                 // overread trailing blank lines
3635                 while(!feof(fp) && (c == '\n'))
3636                         c = fgetc(fp);
3637         }
3638         fclose(fp);
3639         remove(fname2.c_str());
3640 }
3641
3642         
3643 /// changed Heinrich Bauer, 23/03/98
3644 bool Buffer::isDviClean()
3645 {
3646   if (lyxrc->use_tempdir)
3647     return dvi_clean_tmpd;
3648   else
3649     return dvi_clean_orgd;
3650 }
3651
3652  
3653 /// changed Heinrich Bauer, 23/03/98
3654 void Buffer::markDviClean()
3655 {
3656   if (lyxrc->use_tempdir)
3657     dvi_clean_tmpd = true;
3658   else
3659     dvi_clean_orgd = true;
3660 }
3661
3662
3663 /// changed Heinrich Bauer, 23/03/98
3664 void Buffer::markDviDirty()
3665 {
3666   if (lyxrc->use_tempdir)
3667     dvi_clean_tmpd = false;
3668   else
3669     dvi_clean_orgd = false;
3670 }
3671
3672
3673 void Buffer::update(signed char f)
3674 {
3675         if (!users) return;
3676         
3677         users->owner()->updateLayoutChoice();
3678
3679         if (!text->selection && f > -3)
3680                 text->sel_cursor = text->cursor;
3681         
3682         FreeUpdateTimer();
3683         text->FullRebreak();
3684         users->update();
3685
3686         if (f != 3 && f != -3) {
3687                 users->fitCursor();
3688                 users->updateScrollbar();
3689         }
3690
3691         if (f==1 || f==-1) {
3692                 if (isLyxClean()) {
3693                         markDirty();
3694                         users->owner()->getMiniBuffer()->setTimer(4);
3695                 } else {
3696                         markDirty();
3697                 }
3698         }
3699 }
3700
3701
3702 void Buffer::validate(LaTeXFeatures & features)
3703 {
3704         LyXParagraph * par = paragraph;
3705         LyXTextClass const & tclass =
3706                 textclasslist.TextClass(params.textclass);
3707     
3708         // AMS Style is at document level
3709     
3710         features.amsstyle = (params.use_amsmath ||
3711                              tclass.provides(LyXTextClass::amsmath));
3712     
3713         while (par) {
3714                 // We don't use "lyxerr.debug" because of speed. (Asger)
3715                 if (lyxerr.debugging(Debug::LATEX))
3716                         lyxerr << "Paragraph: " <<  par << endl;
3717
3718                 // Now just follow the list of paragraphs and run
3719                 // validate on each of them.
3720                 par->validate(features);
3721
3722                 // and then the next paragraph
3723                 par = par->next;
3724         }
3725
3726         // the bullet shapes are buffer level not paragraph level
3727         // so they are tested here
3728         for (int i = 0; i < 4; ++i) {
3729                 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
3730                         int font = params.user_defined_bullets[i].getFont();
3731                         if (font == 0) {
3732                                 int c = params
3733                                         .user_defined_bullets[i]
3734                                         .getCharacter();
3735                                 if (c == 16
3736                                    || c == 17
3737                                    || c == 25
3738                                    || c == 26
3739                                    || c == 31) {
3740                                         features.latexsym = true;
3741                                 }
3742                         }
3743                         if (font == 1) {
3744                                 features.amssymb = true;
3745                         }
3746                         else if ((font >= 2 && font <=5)) {
3747                                 features.pifont = true;
3748                         }
3749                 }
3750         }
3751         
3752         if (lyxerr.debugging(Debug::LATEX)) {
3753                 features.showStruct(params);
3754         }
3755 }
3756
3757
3758 void Buffer::setPaperStuff()
3759 {
3760         params.papersize = PAPER_DEFAULT;
3761         char c1 = params.paperpackage;
3762         if (c1 == PACKAGE_NONE) {
3763                 char c2 = params.papersize2;
3764                 if (c2 == VM_PAPER_USLETTER)
3765                         params.papersize = PAPER_USLETTER;
3766                 else if (c2 == VM_PAPER_USLEGAL)
3767                         params.papersize = PAPER_LEGALPAPER;
3768                 else if (c2 == VM_PAPER_USEXECUTIVE)
3769                         params.papersize = PAPER_EXECUTIVEPAPER;
3770                 else if (c2 == VM_PAPER_A3)
3771                         params.papersize = PAPER_A3PAPER;
3772                 else if (c2 == VM_PAPER_A4)
3773                         params.papersize = PAPER_A4PAPER;
3774                 else if (c2 == VM_PAPER_A5)
3775                         params.papersize = PAPER_A5PAPER;
3776                 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
3777                          (c2 == VM_PAPER_B5))
3778                         params.papersize = PAPER_B5PAPER;
3779         } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
3780                    (c1 == PACKAGE_WIDEMARGINSA4))
3781                 params.papersize = PAPER_A4PAPER;
3782 }
3783
3784
3785 void Buffer::setOldPaperStuff()
3786 {
3787         char c = params.papersize = params.papersize2;
3788         params.papersize2 = VM_PAPER_DEFAULT;
3789         params.paperpackage = PACKAGE_NONE;
3790         if (c == OLD_PAPER_A4PAPER)
3791                 params.papersize2 = VM_PAPER_A4;
3792         else if (c == OLD_PAPER_A4)
3793                 params.paperpackage = PACKAGE_A4;
3794         else if (c == OLD_PAPER_A4WIDE)
3795                 params.paperpackage = PACKAGE_A4WIDE;
3796         else if (c == OLD_PAPER_WIDEMARGINSA4)
3797                 params.paperpackage = PACKAGE_WIDEMARGINSA4;
3798         else if (c == OLD_PAPER_USLETTER)
3799                 params.papersize2 = VM_PAPER_USLETTER;
3800         else if (c == OLD_PAPER_A5PAPER)
3801                 params.papersize2 = VM_PAPER_A5;
3802         else if (c == OLD_PAPER_B5PAPER)
3803                 params.papersize2 = VM_PAPER_B5;
3804         else if (c == OLD_PAPER_EXECUTIVEPAPER)
3805                 params.papersize2 = VM_PAPER_USEXECUTIVE;
3806         else if (c == OLD_PAPER_LEGALPAPER)
3807                 params.papersize2 = VM_PAPER_USLEGAL;
3808         setPaperStuff();
3809 }
3810
3811
3812 void Buffer::insertInset(Inset * inset, string const & lout,
3813                          bool no_table)
3814 {
3815         // check for table/list in tables
3816         if (no_table && text->cursor.par->table){
3817                 WriteAlert(_("Impossible Operation!"),
3818                            _("Cannot insert table/list in table."),
3819                            _("Sorry."));
3820                 return;
3821         }
3822         // not quite sure if we want this...
3823         text->SetCursorParUndo();
3824         text->FreezeUndo();
3825         
3826         BeforeChange();
3827         if (!lout.empty()) {
3828                 update(-2);
3829                 text->BreakParagraph();
3830                 update(-1);
3831                 
3832                 if (text->cursor.par->Last()) {
3833                         text->CursorLeft();
3834                         
3835                         text->BreakParagraph();
3836                         update(-1);
3837                 }
3838
3839                 int lay = textclasslist.NumberOfLayout(params.textclass,
3840                                                        lout).second;
3841                 if (lay == -1) // layout not found
3842                         // use default layout "Standard" (0)
3843                         lay = 0;
3844                 
3845                 text->SetLayout(lay);
3846                 
3847                 text->SetParagraph(0, 0,
3848                                    0, 0,
3849                                    VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3850                                    LYX_ALIGN_LAYOUT, 
3851                                    string(),
3852                                    0);
3853                 update(-1);
3854                 
3855                 text->current_font.setLatex(LyXFont::OFF);
3856         }
3857         
3858         text->InsertInset(inset);
3859         update(-1);
3860
3861         text->UnFreezeUndo();   
3862 }
3863
3864
3865 // Open and lock an updatable inset
3866 void Buffer::open_new_inset(UpdatableInset * new_inset)
3867 {
3868         BeforeChange();
3869         text->FinishUndo();
3870         insertInset(new_inset);
3871         text->CursorLeft();
3872         update(1);
3873         new_inset->Edit(0,0);
3874 }
3875
3876
3877 /* This function should be in Buffer because it's a buffer's property (ale) */
3878 string Buffer::getIncludeonlyList(char delim)
3879 {
3880         string lst;
3881         LyXParagraph * par = paragraph;
3882 #ifdef NEW_TEXT
3883         LyXParagraph::size_type pos;
3884 #else
3885         int pos;
3886 #endif
3887         Inset * inset;
3888         while (par){
3889                 pos = -1;
3890                 while ((inset = par->ReturnNextInsetPointer(pos))){
3891                         if (inset->LyxCode()==Inset::INCLUDE_CODE) {
3892                                 InsetInclude * insetinc =
3893                                         static_cast<InsetInclude*>(inset);
3894                                 if (insetinc->isInclude() 
3895                                     && insetinc->isNoLoad()) {
3896                                         if (!lst.empty())
3897                                                 lst += delim;
3898                                         lst += ChangeExtension(insetinc->getContents(), string(), true);
3899                                 }
3900                         }
3901                         pos++;
3902                 } 
3903                 par = par->next;
3904         }
3905         lyxerr.debug() << "Includeonly(" << lst << ')' << endl;
3906         return lst;
3907 }
3908
3909
3910 /* This is also a buffer property (ale) */ 
3911 string Buffer::getReferenceList(char delim)
3912 {
3913         /// if this is a child document and the parent is already loaded
3914         /// Use the parent's list instead  [ale990407]
3915         if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3916                 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3917                 if (tmp)
3918                   return tmp->getReferenceList(delim);
3919         }
3920
3921         LyXParagraph *par = paragraph;
3922 #ifdef NEW_TEXT
3923         LyXParagraph::size_type pos;
3924 #else
3925         int pos;
3926 #endif
3927         Inset * inset;
3928         string lst;
3929         while (par){
3930                 pos = -1;
3931                 while ((inset = par->ReturnNextInsetPointer(pos))){     
3932                         for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3933                                 if (!lst.empty())
3934                                         lst += delim;
3935                                 lst += inset->getLabel(i);
3936                         }
3937                         pos++;
3938                 } 
3939                 par = par->next;
3940         }
3941         lyxerr.debug() << "References(" <<  lst << ")" << endl;
3942         return lst;
3943 }
3944
3945
3946 /* This is also a buffer property (ale) */ 
3947 string Buffer::getBibkeyList(char delim)
3948 {
3949         /// if this is a child document and the parent is already loaded
3950         /// Use the parent's list instead  [ale990412]
3951         if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3952                 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3953                 if (tmp)
3954                         return tmp->getBibkeyList(delim);
3955         }
3956
3957         string bibkeys;
3958         LyXParagraph * par = paragraph;
3959         while (par) {
3960                 if (par->bibkey) {
3961                         if (!bibkeys.empty())
3962                                 bibkeys += delim;
3963                         bibkeys += par->bibkey->getContents();
3964                 }
3965                 par = par->next;
3966         }
3967
3968         // Might be either using bibtex or a child has bibliography
3969         if (bibkeys.empty()) {
3970                 par = paragraph;
3971                 while (par) {
3972                         Inset * inset;
3973 #ifdef NEW_TEXT
3974                         LyXParagraph::size_type pos = -1;
3975 #else
3976                         int pos = -1;
3977 #endif
3978
3979                         // Search for Bibtex or Include inset
3980                         while ((inset = par->ReturnNextInsetPointer(pos))) {
3981                                 if (inset-> LyxCode()==Inset::BIBTEX_CODE) {
3982                                         if (!bibkeys.empty())
3983                                                 bibkeys += delim;
3984                                         bibkeys += ((InsetBibtex*)inset)->getKeys();
3985                                 } else if (inset-> LyxCode()==Inset::INCLUDE_CODE) {
3986                                         string bk = ((InsetInclude*)inset)->getKeys();
3987                                         if (!bk.empty()) {
3988                                                 if (!bibkeys.empty())
3989                                                         bibkeys += delim;
3990                                                 bibkeys += bk;
3991                                         }
3992                                 }
3993                                 pos++;
3994                         }
3995                         par = par->next;
3996                 }
3997         }
3998  
3999         lyxerr.debug() << "Bibkeys(" << bibkeys << ")" << endl;
4000         return bibkeys;
4001 }
4002
4003
4004 /* This is also a buffer property (ale) */
4005 // Not so sure about that. a goto Label function can not be buffer local, just
4006 // think how this will work in a multiwindo/buffer environment, all the
4007 // cursors in all the views showing this buffer will move. (Lgb)
4008 // OK, then no cursor action should be allowed in buffer. (ale)
4009 bool Buffer::gotoLabel(string const & label)
4010
4011 {
4012         LyXParagraph * par = paragraph;
4013 #ifdef NEW_TEXT
4014         LyXParagraph::size_type pos;
4015 #else
4016         int pos;
4017 #endif
4018         Inset * inset;
4019         while (par) {
4020                 pos = -1;
4021                 while ((inset = par->ReturnNextInsetPointer(pos))){     
4022                         for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
4023                                 if (label==inset->getLabel(i)) {
4024                                         BeforeChange();
4025                                         text->SetCursor(par, pos);
4026                                         text->sel_cursor = text->cursor;
4027                                         update(0);
4028                                         return true;
4029                                 }
4030                         }
4031                         pos++;
4032                 } 
4033                 par = par->next;
4034         }
4035         return false;
4036 }
4037
4038
4039 bool Buffer::isDepClean(string const & name) const
4040 {
4041         DEPCLEAN * item = dep_clean;
4042         while (item && item->master != name)
4043                 item = item->next;
4044         if (!item) return true;
4045         return item->clean;
4046 }
4047
4048
4049 void Buffer::markDepClean(string const & name)
4050 {
4051         if (!dep_clean) {
4052                 dep_clean = new DEPCLEAN;
4053                 dep_clean->clean = true;
4054                 dep_clean->master = name;
4055                 dep_clean->next = 0;
4056         } else {
4057                 DEPCLEAN* item = dep_clean;
4058                 while (item && item->master != name)
4059                         item = item->next;
4060                 if (item) {
4061                         item->clean = true;
4062                 } else {
4063                         item = new DEPCLEAN;
4064                         item->clean = true;
4065                         item->master = name;
4066                         item->next = 0;;
4067                 }
4068         }
4069 }