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