]> git.lyx.org Git - features.git/blob - src/buffer.C
more fixes and updates
[features.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         filename = file;
106         filepath = OnlyPath(file);
107         paragraph = 0;
108         text = 0;
109         the_locking_inset = 0;
110         lyx_clean = true;
111         bak_clean = true;
112         dvi_clean_orgd = false;  // Heinrich Bauer, 23/03/98
113         dvi_clean_tmpd = false;  // Heinrich Bauer, 23/03/98
114         dep_clean = 0;
115         read_only = ronly;
116         inset_slept = false;
117         users = 0;
118         lyxvc.setBuffer(this);
119         lyxerr.debug() << "Buffer::Buffer()" << endl;
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() << "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->setBuffer(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->getOwner()->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->getOwner()->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->getOwner()->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,users->getOwner()->getMiniBuffer()); // running latex
3225
3226         // check return value from latex.run().
3227         if ((res & LaTeX::NO_LOGFILE)) {
3228                 WriteAlert(_("LaTeX did not work!"),
3229                            _("Missing log file:"), name);
3230         } else if ((res & LaTeX::ERRORS)) {
3231                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3232                 // Insert all errors as errors boxes
3233                 insertErrors(terr);
3234                 
3235                 // Dvi should also be kept dirty if the latex run
3236                 // ends up with errors. However it should be possible
3237                 // to view a dirty dvi too.
3238         } else {
3239                 //no errors or any other things to think about so:
3240                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3241                 markDviClean();
3242         }
3243
3244         // if we removed error insets before we ran LaTeX or if we inserted
3245         // error insets after we ran LaTeX this must be run:
3246         if (a || (res & LaTeX::ERRORS)){
3247                 users->redraw();
3248                 users->fitCursor();
3249                 users->updateScrollbar();
3250         }
3251         AllowInput();
3252  
3253         return latex.getNumErrors();
3254 }
3255
3256
3257 int Buffer::runLiterate()
3258 {
3259         if (!text) return 0;
3260
3261         ProhibitInput();
3262
3263         // get LaTeX-Filename
3264         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3265         // get Literate-Filename
3266         string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3267
3268         string path = OnlyPath(filename);
3269
3270         string org_path = path;
3271         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3272                 path = tmppath;  
3273         }
3274
3275         Path p(path); // path to Literate file
3276         users->getOwner()->getMiniBuffer()->Set(_("Running Literate..."));   
3277
3278         // Remove all error insets
3279         bool a = removeAutoInsets();
3280
3281         // generate the Literate file if necessary
3282         if (!isDviClean() || a) {
3283                 makeLaTeXFile(lit_name, org_path, false);
3284                 markDviDirty();
3285         }
3286
3287         Literate literate(lyxrc->latex_command, name, filepath, 
3288                           lit_name,
3289                           lyxrc->literate_command, lyxrc->literate_error_filter,
3290                           lyxrc->build_command, lyxrc->build_error_filter);
3291         TeXErrors terr;
3292         int res = literate.weave(terr, users->getOwner()->getMiniBuffer());
3293
3294         // check return value from literate.weave().
3295         if ((res & Literate::NO_LOGFILE)) {
3296                 WriteAlert(_("Literate command did not work!"),
3297                            _("Missing log file:"), name);
3298         } else if ((res & Literate::ERRORS)) {
3299                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3300                 // Insert all errors as errors boxes
3301                 insertErrors(terr);
3302                 
3303                 // Dvi should also be kept dirty if the latex run
3304                 // ends up with errors. However it should be possible
3305                 // to view a dirty dvi too.
3306         } else {
3307                 //no errors or any other things to think about so:
3308                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3309                 markDviClean();
3310         }
3311
3312         // if we removed error insets before we ran LaTeX or if we inserted
3313         // error insets after we ran LaTeX this must be run:
3314         if (a || (res & Literate::ERRORS)){
3315                 users->redraw();
3316                 users->fitCursor();
3317                 users->updateScrollbar();
3318         }
3319         AllowInput();
3320  
3321         return literate.getNumErrors();
3322 }
3323
3324
3325 int Buffer::buildProgram()
3326 {
3327         if (!text) return 0;
3328  
3329         ProhibitInput();
3330  
3331         // get LaTeX-Filename
3332         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3333         // get Literate-Filename
3334         string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3335  
3336         string path = OnlyPath(filename);
3337  
3338         string org_path = path;
3339         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3340                 path = tmppath;  
3341         }
3342  
3343         Path p(path); // path to Literate file
3344         users->getOwner()->getMiniBuffer()->Set(_("Building Program..."));   
3345  
3346         // Remove all error insets
3347         bool a = removeAutoInsets();
3348  
3349         // generate the LaTeX file if necessary
3350         if (!isNwClean() || a) {
3351                 makeLaTeXFile(lit_name, org_path, false);
3352                 markNwDirty();
3353         }
3354  
3355         Literate literate(lyxrc->latex_command, name, filepath, 
3356                           lit_name,
3357                           lyxrc->literate_command, lyxrc->literate_error_filter,
3358                           lyxrc->build_command, lyxrc->build_error_filter);
3359         TeXErrors terr;
3360         int res = literate.build(terr, users->getOwner()->getMiniBuffer());
3361  
3362         // check return value from literate.build().
3363         if ((res & Literate::NO_LOGFILE)) {
3364                 WriteAlert(_("Build did not work!"),
3365                            _("Missing log file:"), name);
3366         } else if ((res & Literate::ERRORS)) {
3367                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3368                 // Insert all errors as errors boxes
3369                 insertErrors(terr);
3370                 
3371                 // Literate files should also be kept dirty if the literate 
3372                 // command run ends up with errors.
3373         } else {
3374                 //no errors or any other things to think about so:
3375                 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3376                 markNwClean();
3377         }
3378  
3379         // if we removed error insets before we ran Literate/Build or if we inserted
3380         // error insets after we ran Literate/Build this must be run:
3381         if (a || (res & Literate::ERRORS)){
3382                 users->redraw();
3383                 users->fitCursor();
3384                 users->updateScrollbar();
3385         }
3386         AllowInput();
3387
3388         return literate.getNumErrors();
3389 }
3390
3391
3392 // This should be enabled when the Chktex class is implemented. (Asger)
3393 // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
3394 // Other flags: -wall -v0 -x
3395 int Buffer::runChktex()
3396 {
3397         if (!text) return 0;
3398
3399         ProhibitInput();
3400
3401         // get LaTeX-Filename
3402         string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3403         string path = OnlyPath(filename);
3404
3405         string org_path = path;
3406         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3407                 path = tmppath;  
3408         }
3409
3410         Path p(path); // path to LaTeX file
3411         users->getOwner()->getMiniBuffer()->Set(_("Running chktex..."));
3412
3413         // Remove all error insets
3414         bool a = removeAutoInsets();
3415
3416         // Generate the LaTeX file if neccessary
3417         if (!isDviClean() || a) {
3418                 makeLaTeXFile(name, org_path, false);
3419                 markDviDirty();
3420         }
3421
3422         TeXErrors terr;
3423         Chktex chktex(lyxrc->chktex_command, name, filepath);
3424         int res = chktex.run(terr); // run chktex
3425
3426         if (res == -1) {
3427                 WriteAlert(_("chktex did not work!"),
3428                            _("Could not run with file:"), name);
3429         } else if (res > 0) {
3430                 // Insert all errors as errors boxes
3431                 insertErrors(terr);
3432         }
3433
3434         // if we removed error insets before we ran chktex or if we inserted
3435         // error insets after we ran chktex, this must be run:
3436         if (a || res){
3437                 users->redraw();
3438                 users->fitCursor();
3439                 users->updateScrollbar();
3440         }
3441         AllowInput();
3442
3443         return res;
3444 }
3445
3446
3447 extern void AllFloats(char, char);
3448
3449
3450 void Buffer::insertErrors(TeXErrors & terr)
3451 {
3452         // Save the cursor position
3453         LyXCursor cursor = text->cursor;
3454
3455         // This is drastic, but it's the only fix, I could find. (Asger)
3456         AllFloats(1,0);
3457         AllFloats(1,1);
3458
3459         for (TeXErrors::Errors::const_iterator cit = terr.begin();
3460              cit != terr.end();
3461              ++cit) {
3462                 string desctext((*cit).error_desc);
3463                 string errortext((*cit).error_text);
3464                 string msgtxt = desctext + '\n' + errortext;
3465                 int errorrow = (*cit).error_in_line;
3466
3467                 // Insert error string for row number
3468                 int tmpid = -1; 
3469                 int tmppos = -1;
3470
3471                 texrow.getIdFromRow(errorrow, tmpid, tmppos);
3472
3473                 LyXParagraph* texrowpar;
3474
3475                 if (tmpid == -1) {
3476                         texrowpar = text->FirstParagraph();
3477                         tmppos = 0;
3478                 } else {
3479                         texrowpar = text->GetParFromID(tmpid);
3480                 }
3481
3482                 if (texrowpar == 0)
3483                         continue;
3484
3485                 InsetError *new_inset = new InsetError(msgtxt);
3486
3487                 text->SetCursorIntern(texrowpar, tmppos);
3488                 text->InsertInset(new_inset);
3489                 text->FullRebreak();
3490         }
3491         // Restore the cursor position
3492         text->SetCursorIntern(cursor.par, cursor.pos);
3493 }
3494
3495
3496 void Buffer::setCursorFromRow (int row)
3497 {
3498         int tmpid = -1; 
3499         int tmppos = -1;
3500
3501         texrow.getIdFromRow(row, tmpid, tmppos);
3502
3503         LyXParagraph* texrowpar;
3504
3505         if (tmpid == -1) {
3506                 texrowpar = text->FirstParagraph();
3507                 tmppos = 0;
3508         } else {
3509                 texrowpar = text->GetParFromID(tmpid);
3510         }
3511         text->SetCursor(texrowpar, tmppos);
3512 }
3513
3514
3515 void Buffer::RoffAsciiTable(FILE * file, LyXParagraph * par)
3516 {
3517         LyXFont
3518                 font1 =  LyXFont(LyXFont::ALL_INHERIT),
3519                 font2;
3520         Inset * inset;
3521 #ifdef NEW_TEXT
3522         LyXParagraph::size_type i;
3523 #else
3524         int i;
3525 #endif
3526         int
3527                 j,
3528                 cell = 0;
3529         char
3530                 c;
3531         FILE
3532                 * fp, * fp2;
3533         
3534         string fname1 = TmpFileName(string(),"RAT1");
3535         string fname2 = TmpFileName(string(),"RAT2");
3536         if (!(fp=fopen(fname1.c_str(),"w"))) {
3537                 WriteAlert(_("LYX_ERROR:"),
3538                            _("Cannot open temporary file:"), fname1);
3539                 return;
3540         }
3541         par->table->RoffEndOfCell(fp, -1);
3542 #ifdef NEW_TEXT
3543         for (i = 0; i < par->size(); ++i) {
3544 #else
3545         for (i = 0; i < par->last; ++i) {
3546 #endif
3547                 c = par->GetChar(i);
3548                 if (par->table->IsContRow(cell)) {
3549                         if (c == LYX_META_NEWLINE)
3550                                 cell++;
3551                         continue;
3552                 }
3553                 font2 = par->GetFontSettings(i);
3554                 if (font1.latex() != font2.latex()) {
3555                         if (font2.latex() != LyXFont::OFF)
3556                                 continue;
3557                 }
3558                 switch (c) {
3559                 case LYX_META_INSET:
3560                         if ((inset = par->GetInset(i))) {
3561                                 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3562                                         WriteAlert(_("LYX_ERROR:"),
3563                                                    _("Cannot open temporary file:"), fname2);
3564                                         fclose(fp);
3565                                         remove(fname1.c_str());
3566                                         return;
3567                                 }
3568                                 inset->Latex(fp2,-1);
3569                                 rewind(fp2);
3570                                 c = fgetc(fp2);
3571                                 while(!feof(fp2)) {
3572                                         if (c == '\\')
3573                                                 fprintf(fp,"\\\\");
3574                                         else
3575                                                 fputc(c,fp);
3576                                         c = fgetc(fp2);
3577                                 }
3578                                 fclose(fp2);
3579                         }
3580                         break;
3581                 case LYX_META_NEWLINE:
3582                         if (par->table->CellHasContRow(cell)>=0)
3583                                 par->RoffContTableRows(fp, i+1,cell);
3584                         par->table->RoffEndOfCell(fp, cell);
3585                         cell++;
3586                         break;
3587                 case LYX_META_HFILL: 
3588                         break;
3589                 case LYX_META_PROTECTED_SEPARATOR:
3590                         break;
3591                 case '\\': 
3592                         fprintf(fp, "\\\\");
3593                         break;
3594                 default:
3595                         if (c != '\0')
3596                                 fprintf(fp, "%c", c);
3597                         else if (c == '\0')
3598                                 lyxerr.debug()
3599                                         << "RoffAsciiTable:"
3600                                         " NULL char in structure." << endl;
3601                         break;
3602                 }
3603         }
3604         par->table->RoffEndOfCell(fp, cell);
3605         fclose(fp);
3606         string cmd = lyxrc->ascii_roff_command + " >" + fname2;
3607         cmd = subst(cmd, "$$FName", fname1);
3608         Systemcalls one(Systemcalls::System, cmd);
3609         if (!(lyxerr.debugging(Debug::ROFF))) {
3610                 remove(fname1.c_str());
3611         }
3612         if (!(fp=fopen(fname2.c_str(),"r"))) {
3613                 WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
3614                 return;
3615         }
3616         // now output the produced file
3617         fprintf(file, "\n\n");
3618         c = fgetc(fp);
3619         if (feof(fp))
3620                 WriteAlert(_("Error!"),
3621                            _("Error executing *roff command on table"));
3622         // overread leading blank lines
3623         while(!feof(fp) && (c == '\n'))
3624                 c = fgetc(fp);
3625         while(!feof(fp)) {
3626                 for(j=0; j<par->depth; j++)
3627                         fprintf(file, "  ");
3628                 while(!feof(fp) && (c != '\n')) {
3629                         fputc(c,file);
3630                         c = fgetc(fp);
3631                 }
3632                 fputc('\n',file);
3633                 // overread trailing blank lines
3634                 while(!feof(fp) && (c == '\n'))
3635                         c = fgetc(fp);
3636         }
3637         fclose(fp);
3638         remove(fname2.c_str());
3639 }
3640
3641         
3642 /// changed Heinrich Bauer, 23/03/98
3643 bool Buffer::isDviClean()
3644 {
3645   if (lyxrc->use_tempdir)
3646     return dvi_clean_tmpd;
3647   else
3648     return dvi_clean_orgd;
3649 }
3650
3651  
3652 /// changed Heinrich Bauer, 23/03/98
3653 void Buffer::markDviClean()
3654 {
3655   if (lyxrc->use_tempdir)
3656     dvi_clean_tmpd = true;
3657   else
3658     dvi_clean_orgd = true;
3659 }
3660
3661
3662 /// changed Heinrich Bauer, 23/03/98
3663 void Buffer::markDviDirty()
3664 {
3665   if (lyxrc->use_tempdir)
3666     dvi_clean_tmpd = false;
3667   else
3668     dvi_clean_orgd = false;
3669 }
3670
3671
3672 void Buffer::update(signed char f)
3673 {
3674         if (!users) return;
3675         
3676         users->getOwner()->updateLayoutChoice();
3677
3678         if (!text->selection && f > -3)
3679                 text->sel_cursor = text->cursor;
3680         
3681         FreeUpdateTimer();
3682         text->FullRebreak();
3683         users->update();
3684
3685         if (f != 3 && f != -3) {
3686                 users->fitCursor();
3687                 users->updateScrollbar();
3688         }
3689
3690         if (f==1 || f==-1) {
3691                 if (isLyxClean()) {
3692                         markDirty();
3693                         users->getOwner()->getMiniBuffer()->setTimer(4);
3694                 } else {
3695                         markDirty();
3696                 }
3697         }
3698 }
3699
3700
3701 void Buffer::validate(LaTeXFeatures & features)
3702 {
3703         LyXParagraph * par = paragraph;
3704         LyXTextClass const & tclass =
3705                 textclasslist.TextClass(params.textclass);
3706     
3707         // AMS Style is at document level
3708     
3709         features.amsstyle = (params.use_amsmath ||
3710                              tclass.provides(LyXTextClass::amsmath));
3711     
3712         while (par) {
3713                 // We don't use "lyxerr.debug" because of speed. (Asger)
3714                 if (lyxerr.debugging(Debug::LATEX))
3715                         lyxerr << "Paragraph: " <<  par << endl;
3716
3717                 // Now just follow the list of paragraphs and run
3718                 // validate on each of them.
3719                 par->validate(features);
3720
3721                 // and then the next paragraph
3722                 par = par->next;
3723         }
3724
3725         // the bullet shapes are buffer level not paragraph level
3726         // so they are tested here
3727         for (int i = 0; i < 4; ++i) {
3728                 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
3729                         int font = params.user_defined_bullets[i].getFont();
3730                         if (font == 0) {
3731                                 int c = params
3732                                         .user_defined_bullets[i]
3733                                         .getCharacter();
3734                                 if (c == 16
3735                                    || c == 17
3736                                    || c == 25
3737                                    || c == 26
3738                                    || c == 31) {
3739                                         features.latexsym = true;
3740                                 }
3741                         }
3742                         if (font == 1) {
3743                                 features.amssymb = true;
3744                         }
3745                         else if ((font >= 2 && font <=5)) {
3746                                 features.pifont = true;
3747                         }
3748                 }
3749         }
3750         
3751         if (lyxerr.debugging(Debug::LATEX)) {
3752                 features.showStruct(params);
3753         }
3754 }
3755
3756
3757 void Buffer::setPaperStuff()
3758 {
3759         params.papersize = PAPER_DEFAULT;
3760         char c1 = params.paperpackage;
3761         if (c1 == PACKAGE_NONE) {
3762                 char c2 = params.papersize2;
3763                 if (c2 == VM_PAPER_USLETTER)
3764                         params.papersize = PAPER_USLETTER;
3765                 else if (c2 == VM_PAPER_USLEGAL)
3766                         params.papersize = PAPER_LEGALPAPER;
3767                 else if (c2 == VM_PAPER_USEXECUTIVE)
3768                         params.papersize = PAPER_EXECUTIVEPAPER;
3769                 else if (c2 == VM_PAPER_A3)
3770                         params.papersize = PAPER_A3PAPER;
3771                 else if (c2 == VM_PAPER_A4)
3772                         params.papersize = PAPER_A4PAPER;
3773                 else if (c2 == VM_PAPER_A5)
3774                         params.papersize = PAPER_A5PAPER;
3775                 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
3776                          (c2 == VM_PAPER_B5))
3777                         params.papersize = PAPER_B5PAPER;
3778         } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
3779                    (c1 == PACKAGE_WIDEMARGINSA4))
3780                 params.papersize = PAPER_A4PAPER;
3781 }
3782
3783
3784 void Buffer::setOldPaperStuff()
3785 {
3786         char c = params.papersize = params.papersize2;
3787         params.papersize2 = VM_PAPER_DEFAULT;
3788         params.paperpackage = PACKAGE_NONE;
3789         if (c == OLD_PAPER_A4PAPER)
3790                 params.papersize2 = VM_PAPER_A4;
3791         else if (c == OLD_PAPER_A4)
3792                 params.paperpackage = PACKAGE_A4;
3793         else if (c == OLD_PAPER_A4WIDE)
3794                 params.paperpackage = PACKAGE_A4WIDE;
3795         else if (c == OLD_PAPER_WIDEMARGINSA4)
3796                 params.paperpackage = PACKAGE_WIDEMARGINSA4;
3797         else if (c == OLD_PAPER_USLETTER)
3798                 params.papersize2 = VM_PAPER_USLETTER;
3799         else if (c == OLD_PAPER_A5PAPER)
3800                 params.papersize2 = VM_PAPER_A5;
3801         else if (c == OLD_PAPER_B5PAPER)
3802                 params.papersize2 = VM_PAPER_B5;
3803         else if (c == OLD_PAPER_EXECUTIVEPAPER)
3804                 params.papersize2 = VM_PAPER_USEXECUTIVE;
3805         else if (c == OLD_PAPER_LEGALPAPER)
3806                 params.papersize2 = VM_PAPER_USLEGAL;
3807         setPaperStuff();
3808 }
3809
3810
3811 void Buffer::insertInset(Inset * inset, string const & lout,
3812                          bool no_table)
3813 {
3814         // check for table/list in tables
3815         if (no_table && text->cursor.par->table){
3816                 WriteAlert(_("Impossible Operation!"),
3817                            _("Cannot insert table/list in table."),
3818                            _("Sorry."));
3819                 return;
3820         }
3821         // not quite sure if we want this...
3822         text->SetCursorParUndo();
3823         text->FreezeUndo();
3824         
3825         BeforeChange();
3826         if (!lout.empty()) {
3827                 update(-2);
3828                 text->BreakParagraph();
3829                 update(-1);
3830                 
3831                 if (text->cursor.par->Last()) {
3832                         text->CursorLeft();
3833                         
3834                         text->BreakParagraph();
3835                         update(-1);
3836                 }
3837
3838                 int lay = textclasslist.NumberOfLayout(params.textclass,
3839                                                        lout).second;
3840                 if (lay == -1) // layout not found
3841                         // use default layout "Standard" (0)
3842                         lay = 0;
3843                 
3844                 text->SetLayout(lay);
3845                 
3846                 text->SetParagraph(0, 0,
3847                                    0, 0,
3848                                    VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3849                                    LYX_ALIGN_LAYOUT, 
3850                                    string(),
3851                                    0);
3852                 update(-1);
3853                 
3854                 text->current_font.setLatex(LyXFont::OFF);
3855         }
3856         
3857         text->InsertInset(inset);
3858         update(-1);
3859
3860         text->UnFreezeUndo();   
3861 }
3862
3863
3864 // Open and lock an updatable inset
3865 void Buffer::open_new_inset(UpdatableInset * new_inset)
3866 {
3867         BeforeChange();
3868         text->FinishUndo();
3869         insertInset(new_inset);
3870         text->CursorLeft();
3871         update(1);
3872         new_inset->Edit(0,0);
3873 }
3874
3875
3876 /* This function should be in Buffer because it's a buffer's property (ale) */
3877 string Buffer::getIncludeonlyList(char delim)
3878 {
3879         string lst;
3880         LyXParagraph * par = paragraph;
3881 #ifdef NEW_TEXT
3882         LyXParagraph::size_type pos;
3883 #else
3884         int pos;
3885 #endif
3886         Inset * inset;
3887         while (par){
3888                 pos = -1;
3889                 while ((inset = par->ReturnNextInsetPointer(pos))){
3890                         if (inset->LyxCode()==Inset::INCLUDE_CODE) {
3891                                 InsetInclude * insetinc =
3892                                         static_cast<InsetInclude*>(inset);
3893                                 if (insetinc->isInclude() 
3894                                     && insetinc->isNoLoad()) {
3895                                         if (!lst.empty())
3896                                                 lst += delim;
3897                                         lst += ChangeExtension(insetinc->getContents(), string(), true);
3898                                 }
3899                         }
3900                         pos++;
3901                 } 
3902                 par = par->next;
3903         }
3904         lyxerr.debug() << "Includeonly(" << lst << ')' << endl;
3905         return lst;
3906 }
3907
3908
3909 /* This is also a buffer property (ale) */ 
3910 string Buffer::getReferenceList(char delim)
3911 {
3912         /// if this is a child document and the parent is already loaded
3913         /// Use the parent's list instead  [ale990407]
3914         if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3915                 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3916                 if (tmp)
3917                   return tmp->getReferenceList(delim);
3918         }
3919
3920         LyXParagraph *par = paragraph;
3921 #ifdef NEW_TEXT
3922         LyXParagraph::size_type pos;
3923 #else
3924         int pos;
3925 #endif
3926         Inset * inset;
3927         string lst;
3928         while (par){
3929                 pos = -1;
3930                 while ((inset = par->ReturnNextInsetPointer(pos))){     
3931                         for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3932                                 if (!lst.empty())
3933                                         lst += delim;
3934                                 lst += inset->getLabel(i);
3935                         }
3936                         pos++;
3937                 } 
3938                 par = par->next;
3939         }
3940         lyxerr.debug() << "References(" <<  lst << ")" << endl;
3941         return lst;
3942 }
3943
3944
3945 /* This is also a buffer property (ale) */ 
3946 string Buffer::getBibkeyList(char delim)
3947 {
3948         /// if this is a child document and the parent is already loaded
3949         /// Use the parent's list instead  [ale990412]
3950         if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3951                 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3952                 if (tmp)
3953                         return tmp->getBibkeyList(delim);
3954         }
3955
3956         string bibkeys;
3957         LyXParagraph * par = paragraph;
3958         while (par) {
3959                 if (par->bibkey) {
3960                         if (!bibkeys.empty())
3961                                 bibkeys += delim;
3962                         bibkeys += par->bibkey->getContents();
3963                 }
3964                 par = par->next;
3965         }
3966
3967         // Might be either using bibtex or a child has bibliography
3968         if (bibkeys.empty()) {
3969                 par = paragraph;
3970                 while (par) {
3971                         Inset * inset;
3972 #ifdef NEW_TEXT
3973                         LyXParagraph::size_type pos = -1;
3974 #else
3975                         int pos = -1;
3976 #endif
3977
3978                         // Search for Bibtex or Include inset
3979                         while ((inset = par->ReturnNextInsetPointer(pos))) {
3980                                 if (inset-> LyxCode()==Inset::BIBTEX_CODE) {
3981                                         if (!bibkeys.empty())
3982                                                 bibkeys += delim;
3983                                         bibkeys += ((InsetBibtex*)inset)->getKeys();
3984                                 } else if (inset-> LyxCode()==Inset::INCLUDE_CODE) {
3985                                         string bk = ((InsetInclude*)inset)->getKeys();
3986                                         if (!bk.empty()) {
3987                                                 if (!bibkeys.empty())
3988                                                         bibkeys += delim;
3989                                                 bibkeys += bk;
3990                                         }
3991                                 }
3992                                 pos++;
3993                         }
3994                         par = par->next;
3995                 }
3996         }
3997  
3998         lyxerr.debug() << "Bibkeys(" << bibkeys << ")" << endl;
3999         return bibkeys;
4000 }
4001
4002
4003 /* This is also a buffer property (ale) */
4004 // Not so sure about that. a goto Label function can not be buffer local, just
4005 // think how this will work in a multiwindo/buffer environment, all the
4006 // cursors in all the views showing this buffer will move. (Lgb)
4007 // OK, then no cursor action should be allowed in buffer. (ale)
4008 bool Buffer::gotoLabel(string const & label)
4009
4010 {
4011         LyXParagraph * par = paragraph;
4012 #ifdef NEW_TEXT
4013         LyXParagraph::size_type pos;
4014 #else
4015         int pos;
4016 #endif
4017         Inset * inset;
4018         while (par) {
4019                 pos = -1;
4020                 while ((inset = par->ReturnNextInsetPointer(pos))){     
4021                         for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
4022                                 if (label==inset->getLabel(i)) {
4023                                         BeforeChange();
4024                                         text->SetCursor(par, pos);
4025                                         text->sel_cursor = text->cursor;
4026                                         update(0);
4027                                         return true;
4028                                 }
4029                         }
4030                         pos++;
4031                 } 
4032                 par = par->next;
4033         }
4034         return false;
4035 }
4036
4037
4038 bool Buffer::isDepClean(string const & name) const
4039 {
4040         DEPCLEAN * item = dep_clean;
4041         while (item && item->master != name)
4042                 item = item->next;
4043         if (!item) return true;
4044         return item->clean;
4045 }
4046
4047
4048 void Buffer::markDepClean(string const & name)
4049 {
4050         if (!dep_clean) {
4051                 dep_clean = new DEPCLEAN;
4052                 dep_clean->clean = true;
4053                 dep_clean->master = name;
4054                 dep_clean->next = 0;
4055         } else {
4056                 DEPCLEAN* item = dep_clean;
4057                 while (item && item->master != name)
4058                         item = item->next;
4059                 if (item) {
4060                         item->clean = true;
4061                 } else {
4062                         item = new DEPCLEAN;
4063                         item->clean = true;
4064                         item->master = name;
4065                         item->next = 0;;
4066                 }
4067         }
4068 }