1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1999 The LyX Team.
9 * This file is Copyright 1996-1999
12 * ======================================================
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
30 #pragma implementation "buffer.h"
33 #include "definitions.h"
35 #include "bufferlist.h"
37 #include "lyx_gui_misc.h"
40 #include "tex-strings.h"
43 #include "minibuffer.h"
45 #include "mathed/formulamacro.h"
46 #include "insets/lyxinset.h"
47 #include "insets/inseterror.h"
48 #include "insets/insetlabel.h"
49 #include "insets/insetref.h"
50 #include "insets/inseturl.h"
51 #include "insets/insetinfo.h"
52 #include "insets/insetquotes.h"
53 #include "insets/insetlatex.h"
54 #include "insets/insetlatexaccent.h"
55 #include "insets/insetbib.h"
56 #include "insets/insetindex.h"
57 #include "insets/insetinclude.h"
58 #include "insets/insettoc.h"
59 #include "insets/insetlof.h"
60 #include "insets/insetlot.h"
61 #include "insets/insetloa.h"
62 #include "insets/insetparent.h"
63 #include "insets/insetspecialchar.h"
64 #include "insets/figinset.h"
65 #include "support/filetools.h"
66 #include "support/path.h"
72 #include "LaTeXFeatures.h"
73 #include "support/syscall.h"
74 #include "support/lyxlib.h"
75 #include "support/FileInfo.h"
79 // Uncomment this line to enable a workaround for the weird behaviour
80 // of the cursor between a displayed inset and last character
81 // at the upper line. (Alejandro 20.9.96)
82 // #define BREAK_BEFORE_INSET
84 /* Lars, when changing this file sometime in the future to a list,
85 * please check out the figinsets-sideeffects described at the
86 * beginning of figinset.C Matthias (04.07.1996)
90 // all these externs should eventually be removed.
91 extern BufferList bufferlist;
92 extern void SmallUpdate(signed char);
93 extern unsigned char GetCurrentTextClass();
94 extern void BeforeChange();
96 static const float LYX_FORMAT = 2.15;
98 extern int tex_code_break_column;
100 extern void FreeUpdateTimer();
103 Buffer::Buffer(string const & file, LyXRC *lyxrc, bool ronly)
106 filepath = OnlyPath(file);
109 the_locking_inset = 0;
112 dvi_clean_orgd = false; // Heinrich Bauer, 23/03/98
113 dvi_clean_tmpd = false; // Heinrich Bauer, 23/03/98
118 lyxvc.setBuffer(this);
119 lyxerr.debug() << "Buffer::Buffer()" << endl;
120 if (read_only || (lyxrc && lyxrc->use_tempdir)) {
121 tmppath = CreateBufferTmpDir();
122 } else tmppath.clear();
128 lyxerr.debug() << "Buffer::~Buffer()" << endl;
129 // here the buffer should take care that it is
130 // saved properly, before it goes into the void.
132 // make sure that views using this buffer
137 if (!tmppath.empty()) {
138 DestroyBufferTmpDir(tmppath);
141 LyXParagraph *par = paragraph;
142 LyXParagraph *tmppar;
153 bool Buffer::saveParamsAsDefaults()
155 string fname = AddName(AddPath(user_lyxdir, "templates/"),
157 Buffer defaults = Buffer(fname);
159 // Use the current buffer's parameters as default
160 defaults.params.Copy(params);
161 // add an empty paragraph. Is this enough?
162 defaults.paragraph = new LyXParagraph();
164 return defaults.writeFile(defaults.filename,false);
168 /// Update window titles of all users
169 // Should work on a list
170 void Buffer::updateTitles()
172 if (users) users->getOwner()->updateWindowTitle();
176 /// Reset autosave timer of all users
177 // Should work on a list
178 void Buffer::resetAutosaveTimers()
180 if (users) users->getOwner()->resetAutosaveTimer();
184 void Buffer::setFileName(string const & newfile)
186 filename = MakeAbsPath(newfile);
187 filepath = OnlyPath(filename);
188 setReadonly(IsFileWriteable(filename) == 0);
192 void Buffer::InsetUnlock()
194 if (the_locking_inset) {
195 if (!inset_slept) the_locking_inset->InsetUnlock();
196 the_locking_inset = 0;
203 // Inserts a file into current document
204 bool Buffer::insertLyXFile(string const & filen)
206 // (c) CHT Software Service GmbH
209 // Insert a Lyxformat - file into current buffer
211 // Moved from lyx_cb.C (Lgb)
213 if (filen.empty()) return false;
215 string filename = MakeAbsPath(filen);
217 // check if file exist
218 FileInfo fi(filename);
220 if (!fi.exist() || !fi.readable()) {
221 WriteAlert(_("Error!"),
222 _("Cannot open specified file:"),
223 MakeDisplayPath(filename,50));
229 FilePtr myfile(filename, FilePtr::read);
231 WriteAlert(_("Error!"),
232 _("Cannot open specified file:"),
233 MakeDisplayPath(filename,50));
238 int c = fgetc(myfile());
244 lyxerr.debug() << "Will insert file with header" << endl;
245 res = readFile(lex, text->cursor.par);
247 lyxerr.debug() << "Will insert file without header" << endl;
248 res = readLyXformat2(lex, text->cursor.par);
257 // changed to be public and have one parameter
258 // if par = 0 normal behavior
259 // else insert behavior
260 // Returns false if "\the_end" is not read for formats >= 2.13. (Asger)
261 bool Buffer::readLyXformat2(LyXLex &lex, LyXParagraph *par)
267 char depth = 0; // signed or unsigned?
268 LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
269 LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
270 bool the_end_read = false;
272 LyXParagraph *return_par = 0;
273 LyXFont font = LyXFont(LyXFont::ALL_INHERIT);
275 // If we are inserting, we cheat and get a token in advance
276 bool has_token = false;
280 par = new LyXParagraph();
282 text->BreakParagraph();
283 return_par = text->FirstParagraph();
286 // We don't want to adopt the parameters from the
287 // document we insert, so we skip until the text begins:
290 pretoken = lex.GetString();
291 if (pretoken == "\\layout") {
303 pretoken = lex.GetString();
306 // Profiling show this should give a lot: (Asger)
307 string const token = pretoken;
311 else if (token[0] != '\\') {
312 int n = token.length();
313 for (int i=0; i < n; i++) {
314 par->InsertChar(pos, token[i]);
315 par->SetFont(pos, font);
318 } else if (token == "\\i") {
319 inset = new InsetLatexAccent;
321 par->InsertChar(pos, LYX_META_INSET);
323 par->InsertInset(pos, inset);
324 par->SetFont(pos, font);
326 } else if (token == "\\layout") {
330 par = new LyXParagraph(par);
334 lyxstyle.NumberOfLayout(params.textclass,
336 if (par->layout == -1) // layout not found
337 // use default layout "Standard" (0)
339 // Test whether the layout is obsolete.
340 LyXLayout* layout = lyxstyle.Style(params.textclass,
342 if (!layout->obsoleted_by.empty())
344 lyxstyle.NumberOfLayout(params.textclass,
345 layout->obsoleted_by);
346 par->footnoteflag = footnoteflag;
347 par->footnotekind = footnotekind;
349 font = LyXFont(LyXFont::ALL_INHERIT);
350 } else if (token == "\\end_float") {
354 par = new LyXParagraph(par);
355 footnotekind = LyXParagraph::FOOTNOTE;
356 footnoteflag = LyXParagraph::NO_FOOTNOTE;
359 par->layout = LYX_DUMMY_LAYOUT;
360 font = LyXFont(LyXFont::ALL_INHERIT);
361 } else if (token == "\\begin_float") {
362 tmpret = lex.FindToken(string_footnotekinds);
363 if (tmpret == -1) tmpret++;
364 if (tmpret != LYX_LAYOUT_DEFAULT)
365 footnotekind = (LyXParagraph::footnote_kind)tmpret; // bad
366 if (footnotekind == LyXParagraph::FOOTNOTE
367 || footnotekind == LyXParagraph::MARGIN)
368 footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
370 footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
371 } else if (token == "\\begin_deeper") {
373 } else if (token == "\\end_deeper") {
375 lex.printError("\\end_deeper: "
376 "depth is already null");
380 } else if (token == "\\begin_preamble") {
381 params.readPreamble(lex);
382 } else if (token == "\\textclass") {
384 params.textclass = lyxstyle.NumberOfClass(lex.GetString());
385 if (params.textclass == -1) {
386 lex.printError("Unknown textclass `$$Token'");
387 params.textclass = 0;
389 if (!lyxstyle.Load(params.textclass)) {
390 // if the textclass wasn't loaded properly
391 // we need to either substitute another
392 // or stop loading the file.
393 // I can substitute but I don't see how I can
394 // stop loading... ideas?? ARRae980418
395 WriteAlert(_("Textclass Loading Error!"),
396 string(_("Can't load textclass ")) +
397 lyxstyle.NameOfClass(params.textclass),
398 _("-- substituting default"));
399 params.textclass = 0;
401 } else if (token == "\\options") {
403 params.options = lex.GetString();
404 } else if (token == "\\language") {
405 params.readLanguage(lex);
406 } else if (token == "\\fontencoding") {
408 } else if (token == "\\inputencoding") {
410 params.inputenc = lex.GetString();
411 } else if (token == "\\graphics") {
412 params.readGraphicsDriver(lex);
413 } else if (token == "\\fontscheme") {
415 params.fonts = lex.GetString();
416 } else if (token == "\\noindent") {
417 par->noindent = true;
418 } else if (token == "\\fill_top") {
419 par->added_space_top = VSpace(VSpace::VFILL);
420 } else if (token == "\\fill_bottom") {
421 par->added_space_bottom = VSpace(VSpace::VFILL);
422 } else if (token == "\\line_top") {
423 par->line_top = true;
424 } else if (token == "\\line_bottom") {
425 par->line_bottom = true;
426 } else if (token == "\\pagebreak_top") {
427 par->pagebreak_top = true;
428 } else if (token == "\\pagebreak_bottom") {
429 par->pagebreak_bottom = true;
430 } else if (token == "\\start_of_appendix") {
431 par->start_of_appendix = true;
432 } else if (token == "\\paragraph_separation") {
433 tmpret = lex.FindToken(string_paragraph_separation);
434 if (tmpret == -1) tmpret++;
435 if (tmpret != LYX_LAYOUT_DEFAULT)
436 params.paragraph_separation = tmpret;
437 } else if (token == "\\defskip") {
439 params.defskip = VSpace(lex.GetString());
440 } else if (token == "\\no_isolatin1") {
442 } else if (token == "\\no_babel") {
444 } else if (token == "\\no_epsfig") {
446 } else if (token == "\\epsfig") { // obsolete
447 // Indeed it is obsolete, but we HAVE to be backwards
448 // compatible until 0.14, because otherwise all figures
449 // in existing documents are irretrivably lost. (Asger)
450 params.readGraphicsDriver(lex);
451 } else if (token == "\\quotes_language") {
452 tmpret = lex.FindToken(string_quotes_language);
453 if (tmpret == -1) tmpret++;
454 if (tmpret != LYX_LAYOUT_DEFAULT) {
455 InsetQuotes::quote_language tmpl =
456 InsetQuotes::EnglishQ;
459 tmpl = InsetQuotes::EnglishQ;
462 tmpl = InsetQuotes::SwedishQ;
465 tmpl = InsetQuotes::GermanQ;
468 tmpl = InsetQuotes::PolishQ;
471 tmpl = InsetQuotes::FrenchQ;
474 tmpl = InsetQuotes::DanishQ;
477 params.quotes_language = tmpl;
479 } else if (token == "\\quotes_times") {
481 switch(lex.GetInteger()) {
483 params.quotes_times = InsetQuotes::SingleQ;
486 params.quotes_times = InsetQuotes::DoubleQ;
489 } else if (token == "\\papersize") {
491 tmpret = lex.FindToken(string_papersize);
493 tmpret = lex.FindToken(string_oldpapersize);
497 params.papersize2 = tmpret;
498 } else if (token == "\\paperpackage") {
499 tmpret = lex.FindToken(string_paperpackages);
502 params.paperpackage = PACKAGE_NONE;
504 params.paperpackage = tmpret;
505 } else if (token == "\\use_geometry") {
507 params.use_geometry = lex.GetInteger();
508 } else if (token == "\\use_amsmath") {
510 params.use_amsmath = lex.GetInteger();
511 } else if (token == "\\paperorientation") {
512 tmpret = lex.FindToken(string_orientation);
513 if (tmpret == -1) tmpret++;
514 if (tmpret != LYX_LAYOUT_DEFAULT)
515 params.orientation = tmpret;
516 } else if (token == "\\paperwidth") {
518 params.paperwidth = lex.GetString();
519 } else if (token == "\\paperheight") {
521 params.paperheight = lex.GetString();
522 } else if (token == "\\leftmargin") {
524 params.leftmargin = lex.GetString();
525 } else if (token == "\\topmargin") {
527 params.topmargin = lex.GetString();
528 } else if (token == "\\rightmargin") {
530 params.rightmargin = lex.GetString();
531 } else if (token == "\\bottommargin") {
533 params.bottommargin = lex.GetString();
534 } else if (token == "\\headheight") {
536 params.headheight = lex.GetString();
537 } else if (token == "\\headsep") {
539 params.headsep = lex.GetString();
540 } else if (token == "\\footskip") {
542 params.footskip = lex.GetString();
543 } else if (token == "\\paperfontsize") {
545 params.fontsize = strip(lex.GetString());
546 } else if (token == "\\papercolumns") {
548 params.columns = lex.GetInteger();
549 } else if (token == "\\papersides") {
551 params.sides = lex.GetInteger();
552 } else if (token == "\\paperpagestyle") {
554 params.pagestyle = strip(lex.GetString());
555 } else if (token == "\\bullet") {
557 int index = lex.GetInteger();
559 int temp_int = lex.GetInteger();
560 params.user_defined_bullets[index].setFont(temp_int);
561 params.temp_bullets[index].setFont(temp_int);
563 temp_int = lex.GetInteger();
564 params.user_defined_bullets[index].setCharacter(temp_int);
565 params.temp_bullets[index].setCharacter(temp_int);
567 temp_int = lex.GetInteger();
568 params.user_defined_bullets[index].setSize(temp_int);
569 params.temp_bullets[index].setSize(temp_int);
571 string temp_str = lex.GetString();
572 if (temp_str != "\\end_bullet") {
573 // this element isn't really necessary for
574 // parsing but is easier for humans
575 // to understand bullets. Put it back and
576 // set a debug message?
577 lex.printError("\\end_bullet expected, got" + temp_str);
578 //how can I put it back?
580 } else if (token == "\\bulletLaTeX") {
582 int index = lex.GetInteger();
584 string temp_str = lex.GetString(), sum_str;
585 while (temp_str != "\\end_bullet") {
586 // this loop structure is needed when user
587 // enters an empty string since the first
588 // thing returned will be the \\end_bullet
590 // if the LaTeX entry has spaces. Each element
591 // therefore needs to be read in turn
594 temp_str = lex.GetString();
596 params.user_defined_bullets[index].setText(sum_str);
597 params.temp_bullets[index].setText(sum_str);
598 } else if (token == "\\secnumdepth") {
600 params.secnumdepth = lex.GetInteger();
601 } else if (token == "\\tocdepth") {
603 params.tocdepth = lex.GetInteger();
604 } else if (token == "\\baselinestretch") { // now obsolete
605 lex.nextToken(); // should not be used directly
607 // Will probably keep a kind of support just for
609 params.spacing.set(Spacing::Other, lex.GetFloat());
610 } else if (token == "\\spacing") {
612 string tmp = strip(lex.GetString());
613 if (tmp == "single") {
614 params.spacing.set(Spacing::Single);
615 } else if (tmp == "onehalf") {
616 params.spacing.set(Spacing::Onehalf);
617 } else if (tmp == "double") {
618 params.spacing.set(Spacing::Double);
619 } else if (tmp == "other") {
621 params.spacing.set(Spacing::Other,
624 lex.printError("Unknown spacing token: '$$Token'");
626 } else if (token == "\\float_placement") {
628 params.float_placement = lex.GetString();
629 } else if (token == "\\cursor") {
630 // this is obsolete, so we just skip it.
632 } else if (token == "\\family") {
634 font.setLyXFamily(lex.GetString());
635 } else if (token == "\\series") {
637 font.setLyXSeries(lex.GetString());
638 } else if (token == "\\shape") {
640 font.setLyXShape(lex.GetString());
641 } else if (token == "\\size") {
643 font.setLyXSize(lex.GetString());
644 } else if (token == "\\latex") {
646 string tok = lex.GetString();
647 // This is dirty, but gone with LyX3. (Asger)
648 if (tok == "no_latex")
649 font.setLatex(LyXFont::OFF);
650 else if (tok == "latex")
651 font.setLatex(LyXFont::ON);
652 else if (tok == "default")
653 font.setLatex(LyXFont::INHERIT);
655 lex.printError("Unknown LaTeX font flag "
657 } else if (token == "\\emph") {
659 font.setEmph(font.setLyXMisc(lex.GetString()));
660 } else if (token == "\\bar") {
662 string tok = lex.GetString();
663 // This is dirty, but gone with LyX3. (Asger)
665 font.setUnderbar(LyXFont::ON);
666 else if (tok == "no")
667 font.setUnderbar(LyXFont::OFF);
668 else if (tok == "default")
669 font.setUnderbar(LyXFont::INHERIT);
671 lex.printError("Unknown bar font flag "
673 } else if (token == "\\noun") {
675 font.setNoun(font.setLyXMisc(lex.GetString()));
676 } else if (token == "\\color") {
678 font.setLyXColor(lex.GetString());
679 } else if (token == "\\align") {
680 tmpret = lex.FindToken(string_align);
681 if (tmpret == -1) tmpret++;
682 if (tmpret != LYX_LAYOUT_DEFAULT) {
684 for (; tmpret>0; tmpret--)
685 tmpret2 = tmpret2 * 2;
686 par->align = tmpret2;
688 } else if (token == "\\added_space_top"){
690 par->added_space_top = lex.GetString();
691 } else if (token == "\\added_space_bottom") {
693 par->added_space_bottom = lex.GetString();
694 } else if (token == "\\pextra_type") {
696 par->pextra_type = lex.GetInteger();
697 } else if (token == "\\pextra_width") {
699 par->pextra_width = lex.GetString();
700 } else if (token == "\\pextra_widthp") {
702 par->pextra_widthp = lex.GetString();
703 } else if (token == "\\pextra_alignment") {
705 par->pextra_alignment = lex.GetInteger();
706 } else if (token == "\\pextra_hfill") {
708 par->pextra_hfill = lex.GetInteger();
709 } else if (token == "\\pextra_start_minipage") {
711 par->pextra_start_minipage = lex.GetInteger();
712 } else if (token == "\\labelwidthstring") {
714 par->labelwidthstring = lex.GetString();
715 /* do not delete this token, it is still needed! */
716 } else if (token == "\\end_inset") {
717 /* simple ignore this. The insets do not have
719 // but insets should read it, it is a part of
720 //the inset isn't it? Lgb.
721 } else if (token == "\\begin_inset") {
723 tmptok = lex.GetString();
724 /* test the different insets */
725 if (tmptok == "Quotes") {
726 inset = new InsetQuotes;
728 par->InsertChar(pos, LYX_META_INSET);
729 par->InsertInset(pos, inset);
730 par->SetFont(pos, font);
732 } else if (tmptok == "Latex") {
733 // This one is on its way out
735 tmptok = strip(lex.GetString());
736 //lyxerr <<string(tmptok[0]));
737 if (tmptok[0] == '\\') {
738 // then this latex is a
740 InsetCommand *tmpinset =
742 tmpinset->scanCommand(tmptok);
745 // This should not use InsetLaTexDel
746 // it should rather insert text into
747 // the paragraph and mark it as tex.
748 inset = new InsetLatex(tmptok);
750 par->InsertChar(pos, LYX_META_INSET);
751 par->InsertInset(pos, inset);
752 par->SetFont(pos, font);
754 } else if (tmptok == "LatexDel") {
755 // This one is on its way out...
757 tmptok = strip(lex.GetString());
758 //lyxerr <<string(tmptok[0]));
759 if (tmptok == "\\tableofcontents") {
760 inset = new InsetTOC(this);
761 } else if (tmptok == "\\listoffigures") {
762 inset = new InsetLOF(this);
763 } else if (tmptok == "\\listoftables") {
764 inset = new InsetLOT(this);
765 } else if (tmptok == "\\listofalgorithms") {
766 inset = new InsetLOA(this);
767 } else if (contains(tmptok, "\\ref{")
768 || contains(tmptok, "\\pageref{")) {
769 inset = new InsetRef(tmptok, this);
770 } else if (contains(tmptok, "\\url{")
771 || contains(tmptok, "\\htmlurl{")) {
772 string cont,opt,tmptmptok,cmdname;
774 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
779 tmptmptok=lex.GetString();
780 if(tmptmptok[0] == '\\') {
781 if( tmptmptok == "\\backslash")
791 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
796 tmptmptok=lex.GetString();
797 if(tmptmptok[0] == '\\') {
798 if( tmptmptok == "\\backslash")
808 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
811 if(contains(tmptok, "\\url{"))
812 cmdname = string("url");
814 cmdname = string("htmlurl");
817 inset = new InsetUrl(cmdname,cont,opt);
818 } else if (tmptok[0] == '\\') {
819 // then this latex del is a
821 InsetCommand *tmpinset =
823 tmpinset->scanCommand(tmptok);
826 par->InsertChar(pos, LYX_META_INSET);
827 par->InsertInset(pos, inset);
828 par->SetFont(pos, font);
830 } else if (tmptok == "\\i") {
831 inset = new InsetLatexAccent;
833 par->InsertChar(pos, LYX_META_INSET);
834 par->InsertInset(pos, inset);
835 par->SetFont(pos, font);
837 } else if (tmptok == "FormulaMacro") {
838 inset = new InsetFormulaMacro;
840 par->InsertChar(pos, LYX_META_INSET);
841 par->InsertInset(pos, inset);
842 par->SetFont(pos, font);
844 } else if (tmptok == "Formula") {
845 inset = new InsetFormula;
847 par->InsertChar(pos, LYX_META_INSET);
848 par->InsertInset(pos, inset);
849 par->SetFont(pos, font);
851 } else if (tmptok == "Figure") {
852 inset = new InsetFig(100,100, this);
854 par->InsertChar(pos, LYX_META_INSET);
855 par->InsertInset(pos, inset);
856 par->SetFont(pos, font);
858 } else if (tmptok == "Label") {
859 // Kept for compability. Remove in 0.13.
863 tmp += lex.GetString();
865 inset = new InsetLabel(tmp);
866 par->InsertChar(pos, LYX_META_INSET);
867 par->InsertInset(pos, inset);
868 par->SetFont(pos, font);
871 } else if (tmptok == "Info") {
872 inset = new InsetInfo;
874 par->InsertChar(pos, LYX_META_INSET);
875 par->InsertInset(pos, inset);
876 par->SetFont(pos, font);
878 } else if (tmptok == "Include") {
879 inset = new InsetInclude(string(), this);
881 par->InsertChar(pos, LYX_META_INSET);
882 par->InsertInset(pos, inset);
883 par->SetFont(pos, font);
885 } else if (tmptok == "LatexCommand") {
888 if (inscmd.getCmdName()=="cite") {
889 inset = new InsetCitation(inscmd.getContents(), inscmd.getOptions());
890 } else if (inscmd.getCmdName()=="bibitem") {
891 lex.printError("Wrong place for bibitem");
892 inset = inscmd.Clone();
893 } else if (inscmd.getCmdName()=="BibTeX") {
894 inset = new InsetBibtex(inscmd.getContents(), inscmd.getOptions(), this);
895 } else if (inscmd.getCmdName()=="index") {
896 inset = new InsetIndex(inscmd.getContents());
897 } else if (inscmd.getCmdName()=="include") {
898 inset = new InsetInclude(inscmd.getContents(), this);
899 } else if (inscmd.getCmdName()=="label") {
900 inset = new InsetLabel(inscmd.getCommand());
901 } else if (inscmd.getCmdName()=="url"
902 || inscmd.getCmdName()=="htmlurl") {
903 inset = new InsetUrl(inscmd.getCommand());
904 } else if (inscmd.getCmdName() == "ref"
905 || inscmd.getCmdName() == "pageref") {
906 if (!inscmd.getOptions().empty() || !inscmd.getContents().empty()) {
907 inset = new InsetRef(inscmd, this);
909 /* This condition comes from a temporary solution
910 to the latexdel ref inset that was transformed to an empty ref
911 inset plus the body surronded by latexdel insets */
913 string cont,opt,tmptmptok,cmdname;
915 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
920 tmptmptok=lex.GetString();
921 if(tmptmptok[0] == '\\') {
922 if( tmptmptok == "\\backslash")
932 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
937 tmptmptok=lex.GetString();
938 if(tmptmptok[0] == '\\') {
939 if( tmptmptok == "\\backslash")
949 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
955 cmdname = "\\" + inscmd.getCmdName();
956 cmdname += "[" + cont + "]";
957 cmdname += "{" + opt + "}";
958 inset = new InsetRef(cmdname,this);
960 } else if (inscmd.getCmdName()=="tableofcontents") {
961 inset = new InsetTOC(this);
962 } else if (inscmd.getCmdName()=="listoffigures") {
963 inset = new InsetLOF(this);
964 } else if (inscmd.getCmdName()=="listofalgorithms") {
965 inset = new InsetLOA(this);
966 } else if (inscmd.getCmdName()=="listoftables") {
967 inset = new InsetLOT(this);
968 } else if (inscmd.getCmdName()=="printindex") {
969 inset = new InsetPrintIndex(this);
970 } else if (inscmd.getCmdName()=="lyxparent") {
971 inset = new InsetParent(inscmd.getContents(),this);
973 // The following three are only for compatibility
974 if (inscmd.getCmdName()=="-") {
975 inset = new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
976 } else if (inscmd.getCmdName()=="@.") {
977 inset = new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
978 } else if (inscmd.getCmdName()=="ldots") {
979 inset = new InsetSpecialChar(InsetSpecialChar::LDOTS);
981 inset = inscmd.Clone();
984 par->InsertChar(pos, LYX_META_INSET);
985 par->InsertInset(pos, inset);
986 par->SetFont(pos, font);
990 } else if (token == "\\InsetQuotes") {
991 inset = new InsetQuotes;
993 par->InsertChar(pos, LYX_META_INSET);
994 par->InsertInset(pos, inset);
995 par->SetFont(pos, font);
997 } else if (token == "\\InsetLatex") {
998 inset = new InsetLatex;
1000 par->InsertChar(pos, LYX_META_INSET);
1001 par->InsertInset(pos, inset);
1002 par->SetFont(pos, font);
1004 } else if (token == "\\InsetLatexDel") {
1005 lex.printError(_("Warning: Ignoring Old Inset"));
1006 } else if (token == "\\InsetFormula") {
1007 inset = new InsetFormula;
1009 par->InsertChar(pos, LYX_META_INSET);
1010 par->InsertInset(pos, inset);
1011 par->SetFont(pos, font);
1013 } else if (token == "\\SpecialChar") {
1014 inset = new InsetSpecialChar;
1016 par->InsertChar(pos, LYX_META_INSET);
1017 par->InsertInset(pos, inset);
1018 par->SetFont(pos, font);
1020 } else if (token == "\\Figure") {
1021 inset = new InsetFig(100,100, this);
1023 par->InsertChar(pos, LYX_META_INSET);
1024 par->InsertInset(pos, inset);
1025 par->SetFont(pos, font);
1027 } else if (token == "\\newline") {
1028 par->InsertChar(pos, LYX_META_NEWLINE);
1029 par->SetFont(pos, font);
1031 } else if (token == "\\LyXTable") {
1032 par->table = new LyXTable(lex);
1033 } else if (token == "\\hfill") {
1034 par->InsertChar(pos, LYX_META_HFILL);
1035 par->SetFont(pos, font);
1037 } else if (token == "\\protected_separator") {
1038 par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
1039 par->SetFont(pos, font);
1041 } else if (token == "\\bibitem") { // ale970302
1043 par->bibkey = new InsetBibKey;
1044 par->bibkey->Read(lex);
1045 }else if (token == "\\backslash") {
1046 par->InsertChar(pos, '\\');
1047 par->SetFont(pos, font);
1049 }else if (token == "\\the_end") {
1050 the_end_read = true;
1052 // This should be insurance for the future: (Asger)
1053 lex.printError("Unknown token `$$Token'. "
1054 "Inserting as text.");
1055 int n = token.length();
1056 for (int i=0; i < n; i++) {
1057 par->InsertChar(pos, token[i]);
1058 par->SetFont(pos, font);
1067 paragraph = return_par;
1069 return the_end_read;
1073 bool Buffer::readFile(LyXLex &lex, LyXParagraph *par)
1079 token = lex.GetString();
1080 if (token == "\\lyxformat") { // the first token _must_ be...
1082 format = lex.GetFloat();
1084 if (LYX_FORMAT - format > 0.05) {
1085 printf(_("Warning: need lyxformat %.2f but found %.2f\n"),
1086 LYX_FORMAT, format);
1088 if (format - LYX_FORMAT > 0.05) {
1089 printf(_("ERROR: need lyxformat %.2f but found %.2f\n"),
1090 LYX_FORMAT, format);
1092 bool the_end = readLyXformat2(lex, par);
1093 // Formats >= 2.13 support "\the_end" marker
1096 // Formats >= 2.14 changed papersize stuff
1097 if (format < 2.14) {
1103 WriteAlert(_("Warning!"),
1104 _("Reading of document is not complete"),
1105 _("Maybe the document is truncated"));
1106 // We simulate a safe reading anyways to allow
1107 // users to take the chance... (Asger)
1111 WriteAlert(_("ERROR!"),
1112 _("Old LyX file format found. "
1113 "Use LyX 0.10.x to read this!"));
1117 } else { // "\\lyxformat" not found
1118 WriteAlert(_("ERROR!"), _("Not a LyX file!"));
1121 WriteAlert(_("ERROR!"), _("Unable to read file!"));
1126 // Returns false if unsuccesful
1127 bool Buffer::writeFile(string const & filename, bool flag)
1129 // if flag is false writeFile will not create any GUI
1130 // warnings, only cerr.
1131 // Needed for autosave in background or panic save (Matthias 120496)
1133 if (read_only && (filename == this->filename)) {
1134 // Here we should come with a question if we should
1135 // perform the write anyway.
1137 lyxerr << _("Error! Document is read-only: ")
1138 << filename << endl;
1140 WriteAlert(_("Error! Document is read-only: "), filename);
1144 FileInfo finfo(filename);
1145 if (finfo.exist() && !finfo.writable()) {
1146 // Here we should come with a question if we should
1147 // try to do the save anyway. (i.e. do a chmod first)
1149 lyxerr << _("Error! Cannot write file: ")
1150 << filename << endl;
1152 WriteFSAlert(_("Error! Cannot write file: "), filename);
1156 FilePtr file(filename, FilePtr::truncate);
1159 lyxerr << _("Error! Cannot write file: ")
1160 << filename << endl;
1162 WriteFSAlert(_("Error! Cannot write file: "), filename);
1165 // The top of the file should not be written by params.
1166 // collect some very important information
1167 string userName(getUserName()) ;
1169 // write out a comment in the top of the file
1171 "#This file was created by <%s> %s",
1172 userName.c_str(),(char*)date());
1174 "#LyX 1.0 (C) 1995-1999 Matthias Ettrich"
1175 " and the LyX Team\n");
1177 // at the very beginning the used lyx format
1178 fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
1180 // now write out the buffer parameters.
1181 params.writeFile(file);
1183 char footnoteflag = 0;
1186 // this will write out all the paragraphs
1187 // using recursive descent.
1188 paragraph->writeFile(file, params, footnoteflag, depth);
1190 // Write marker that shows file is complete
1191 fprintf(file, "\n\\the_end\n");
1194 lyxerr << _("Error! Could not close file properly: ")
1195 << filename << endl;
1197 WriteFSAlert(_("Error! Could not close file properly: "),
1205 void Buffer::writeFileAscii(string const & filename, int linelen)
1207 FilePtr file(filename, FilePtr::write);
1238 ref_printed = false;
1242 WriteFSAlert(_("Error: Cannot write file:"), filename);
1245 fname1=TmpFileName();
1249 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE ||
1251 par->previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
1253 /* begins a footnote environment ? */
1254 if (footnoteflag != par->footnoteflag) {
1255 footnoteflag = par->footnoteflag;
1257 j=strlen(string_footnotekinds[par->footnotekind])+4;
1258 if (currlinelen+j > linelen)
1260 fprintf(file, "([%s] ",
1261 string_footnotekinds[par->footnotekind]);
1266 /* begins or ends a deeper area ?*/
1267 if (depth != par->depth) {
1268 if (par->depth > depth) {
1269 while (par->depth > depth) {
1274 while (par->depth < depth) {
1280 /* First write the layout */
1281 tmp = lyxstyle.NameOfLayout(params.textclass,par->layout);
1282 if (tmp == "Itemize") {
1284 ltype_depth = depth+1;
1285 } else if (tmp =="Enumerate") {
1287 ltype_depth = depth+1;
1288 } else if (strstr(tmp.c_str(),"ection")) {
1290 ltype_depth = depth+1;
1291 } else if (strstr(tmp.c_str(),"aragraph")) {
1293 ltype_depth = depth+1;
1294 } else if (tmp == "Description") {
1296 ltype_depth = depth+1;
1297 } else if (tmp == "Abstract") {
1300 } else if (tmp == "Bibliography") {
1308 /* maybe some vertical spaces */
1310 /* the labelwidthstring used in lists */
1314 /* some pagebreaks? */
1318 /* what about the alignment */
1321 /* dummy layout, that means a footnote ended */
1322 footnoteflag = LyXParagraph::NO_FOOTNOTE;
1323 fprintf(file, ") ");
1327 /* It might be a table */
1329 if (!lyxrc->ascii_roff_command.empty() &&
1330 lyxrc->ascii_roff_command != "none") {
1331 RoffAsciiTable(file,par);
1337 cells = par->table->columns;
1338 clen = new int [cells];
1339 memset(clen,0,sizeof(int)*cells);
1340 for (i = 0, j = 0, h=1; i < par->last; i++, h++) {
1341 c = par->GetChar(i);
1342 if (c == LYX_META_INSET) {
1343 if ((inset = par->GetInset(i))) {
1347 WriteFSAlert(_("Error: Cannot open temporary file:"), fname1);
1350 inset->Latex(fp,-1);
1352 remove(fname1.c_str());
1354 } else if (c == LYX_META_NEWLINE) {
1358 j = (++j) % par->table->NumberOfCellsInRow(actcell);
1366 font1 = LyXFont(LyXFont::ALL_INHERIT);
1368 for (i = 0,actpos=1; i < par->last; i++, actpos++) {
1369 if (!i && !footnoteflag && !noparbreak){
1370 fprintf(file, "\n\n");
1371 for(j=0; j<depth; j++)
1373 currlinelen = depth*2;
1375 case 0: /* Standart */
1376 case 4: /* (Sub)Paragraph */
1377 case 5: /* Description */
1379 case 6: /* Abstract */
1380 fprintf(file, "Abstract\n\n");
1382 case 7: /* Bibliography */
1384 fprintf(file, "References\n\n");
1389 fprintf(file,"%s ",par->labelstring.c_str());
1392 if (ltype_depth > depth) {
1393 for(j=ltype_depth-1; j>depth; j--)
1395 currlinelen += (ltype_depth-depth)*2;
1398 for(j=0;j<cells;j++) {
1400 for(h=0; h<(clen[j]+1); h++)
1403 fprintf(file,"+\n");
1404 for(j=0; j<depth; j++)
1406 currlinelen = depth*2;
1407 if (ltype_depth > depth) {
1408 for(j=ltype_depth; j>depth; j--)
1410 currlinelen += (ltype_depth-depth)*2;
1415 font2 = par->GetFontSettings(i);
1416 if (font1.latex() != font2.latex()) {
1417 if (font2.latex() == LyXFont::OFF)
1425 c = par->GetChar(i);
1429 case LYX_META_INSET:
1430 if ((inset = par->GetInset(i))) {
1432 inset->Latex(file,-1);
1433 currlinelen += (ftell(file) - fpos);
1434 actpos += (ftell(file) - fpos) - 1;
1437 case LYX_META_NEWLINE:
1439 if (par->table->NumberOfCellsInRow(actcell) <= cell) {
1440 for(j=actpos;j<clen[cell-1];j++)
1442 fprintf(file," |\n");
1443 for(j=0; j<depth; j++)
1445 currlinelen = depth*2;
1446 if (ltype_depth > depth) {
1447 for(j=ltype_depth; j>depth; j--)
1449 currlinelen += (ltype_depth-depth)*2;
1451 for(j=0;j<cells;j++) {
1453 for(h=0; h<(clen[j]+1); h++)
1456 fprintf(file,"+\n");
1457 for(j=0; j<depth; j++)
1459 currlinelen = depth*2;
1460 if (ltype_depth > depth) {
1461 for(j=ltype_depth; j>depth; j--)
1463 currlinelen += (ltype_depth-depth)*2;
1468 for(j=actpos; j<clen[cell-1]; j++)
1470 fprintf(file, " | ");
1474 currlinelen = actpos = 0;
1476 fprintf(file, "\n");
1477 for(j=0; j<depth; j++)
1479 currlinelen = depth*2;
1480 if (ltype_depth > depth) {
1481 for(j=ltype_depth; j>depth; j--)
1483 currlinelen += (ltype_depth-depth)*2;
1487 case LYX_META_HFILL:
1488 fprintf(file, "\t");
1490 case LYX_META_PROTECTED_SEPARATOR:
1494 fprintf(file, "\\");
1497 if (currlinelen > (linelen-10) \
1498 && c==' ' && (i+2 < par->last)) {
1499 fprintf(file, "\n");
1500 for(j=0; j<depth; j++)
1502 currlinelen = depth*2;
1503 if (ltype_depth > depth) {
1504 for(j=ltype_depth; j>depth; j--)
1506 currlinelen += (ltype_depth-depth)*2;
1508 } else if (c != '\0')
1509 fprintf(file, "%c", c);
1511 lyxerr.debug() << "writeAsciiFile: NULL char in structure." << endl;
1517 for(j=actpos;j<clen[cell-1];j++)
1519 fprintf(file," |\n");
1520 for(j=0; j<depth; j++)
1522 currlinelen = depth*2;
1523 if (ltype_depth > depth) {
1524 for(j=ltype_depth; j>depth; j--)
1526 currlinelen += (ltype_depth-depth)*2;
1528 for(j=0;j<cells;j++) {
1530 for(h=0; h<(clen[j]+1); h++)
1533 fprintf(file,"+\n");
1539 fprintf(file, "\n");
1543 void Buffer::makeLaTeXFile(string const & filename,
1544 string const & original_path,
1545 bool nice, bool only_body)
1547 lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
1548 params.textclass = GetCurrentTextClass();
1549 niceFile = nice; // this will be used by Insetincludes.
1551 tex_code_break_column = lyxrc->ascii_linelen;
1553 LyXTextClass *tclass = lyxstyle.TextClass(params.textclass);
1555 FilePtr file(filename, FilePtr::write);
1557 WriteFSAlert(_("Error: Cannot write file:"),filename);
1561 // validate the buffer.
1562 lyxerr[Debug::LATEX] << " Validating buffer..." << endl;
1563 LaTeXFeatures features(tclass->number_of_defined_layouts);
1565 lyxerr[Debug::LATEX] << " Buffer validation done." << endl;
1568 // The starting paragraph of the coming rows is the
1569 // first paragraph of the document. (Asger)
1570 texrow.start(paragraph, 0);
1572 string userName(getUserName());
1575 if (!only_body && nice) {
1576 LFile += "%% This LaTeX-file was created by <";
1577 LFile += userName + "> " + (char*)date();
1578 LFile += "%% LyX 1.0 (C) 1995-1999 by Matthias Ettrich and the LyX Team\n";
1579 LFile += "\n%% Do not edit this file unless you know what you are doing.\n";
1585 lyxerr.debug() << "lyx header finished" << endl;
1586 // There are a few differences between nice LaTeX and usual files:
1587 // usual is \batchmode, uses \listfiles and has a
1588 // special input@path to allow the including of figures
1589 // with either \input or \includegraphics (what figinsets do).
1590 // batchmode is not set if there is a tex_code_break_column.
1591 // In this case somebody is interested in the generated LaTeX,
1592 // so this is OK. input@path is set when the actual parameter
1593 // original_path is set. This is done for usual tex-file, but not
1594 // for nice-latex-file. (Matthias 250696)
1597 // code for usual, NOT nice-latex-file
1598 LFile += "\\batchmode\n"; // changed
1599 // from \nonstopmode
1601 // We don't need listfiles anymore
1602 //LFile += "\\listfiles\n";
1605 if (!original_path.empty()) {
1606 LFile += "\\makeatletter\n";
1608 LFile += "\\def\\input@path{{" + original_path
1611 LFile += "\\makeatother\n";
1615 LFile += "\\documentclass";
1617 string options; // the document class options.
1619 if (tokenPos(tclass->opt_fontsize, '|',params.fontsize) >= 0) {
1620 // only write if existing in list (and not default)
1621 options += params.fontsize;
1626 if (!params.use_geometry &&
1627 (params.paperpackage == PACKAGE_NONE)) {
1628 switch (params.papersize) {
1630 options += "a4paper,";
1632 case PAPER_USLETTER:
1633 options += "letterpaper,";
1636 options += "a5paper,";
1639 options += "b5paper,";
1641 case PAPER_EXECUTIVEPAPER:
1642 options += "executivepaper,";
1644 case PAPER_LEGALPAPER:
1645 options += "legalpaper,";
1651 if (params.sides != tclass->sides) {
1652 if (params.sides == 2)
1653 options += "twoside,";
1655 options += "oneside,";
1659 if (params.columns != tclass->columns) {
1660 if (params.columns == 2)
1661 options += "twocolumn,";
1663 options += "onecolumn,";
1666 if (!params.use_geometry && params.orientation == ORIENTATION_LANDSCAPE)
1667 options += "landscape,";
1669 // language should be a parameter to \documentclass
1670 if (params.language != "default") {
1671 options += params.language + ',';
1674 // the user-defined options
1675 if (!params.options.empty()) {
1676 options += params.options + ',';
1679 if (!options.empty()){
1680 options = strip(options, ',');
1687 LFile += lyxstyle.LatexnameOfClass(params.textclass);
1690 // end of \documentclass defs
1692 // font selection must be done before loading fontenc.sty
1693 if (params.fonts != "default") {
1694 LFile += "\\usepackage{" + params.fonts + "}\n";
1697 // this one is not per buffer
1698 if (lyxrc->fontenc != "default") {
1699 LFile += "\\usepackage[" + lyxrc->fontenc
1703 if (params.inputenc != "default") {
1704 LFile += "\\usepackage[" + params.inputenc
1709 /* at the very beginning the text parameters */
1710 if (params.paperpackage != PACKAGE_NONE) {
1711 switch (params.paperpackage) {
1713 LFile += "\\usepackage{a4}\n";
1716 case PACKAGE_A4WIDE:
1717 LFile += "\\usepackage{a4wide}\n";
1720 case PACKAGE_WIDEMARGINSA4:
1721 LFile += "\\usepackage[widemargins]{a4}\n";
1726 if (params.use_geometry) {
1727 LFile += "\\usepackage{geometry}\n";
1729 LFile += "\\geometry{verbose";
1730 if (params.orientation == ORIENTATION_LANDSCAPE)
1731 LFile += ",landscape";
1732 switch (params.papersize2) {
1733 case VM_PAPER_CUSTOM:
1734 if (!params.paperwidth.empty())
1735 LFile += ",paperwidth="
1736 + params.paperwidth;
1737 if (!params.paperheight.empty())
1738 LFile += ",paperheight="
1739 + params.paperheight;
1741 case VM_PAPER_USLETTER:
1742 LFile += ",letterpaper";
1744 case VM_PAPER_USLEGAL:
1745 LFile += ",legalpaper";
1747 case VM_PAPER_USEXECUTIVE:
1748 LFile += ",executivepaper";
1751 LFile += ",a3paper";
1754 LFile += ",a4paper";
1757 LFile += ",a5paper";
1760 LFile += ",b3paper";
1763 LFile += ",b4paper";
1766 LFile += ",b5paper";
1769 // default papersize ie VM_PAPER_DEFAULT
1770 switch (lyxrc->default_papersize) {
1771 case PAPER_DEFAULT: // keep compiler happy
1772 case PAPER_USLETTER:
1773 LFile += ",letterpaper";
1775 case PAPER_LEGALPAPER:
1776 LFile += ",legalpaper";
1778 case PAPER_EXECUTIVEPAPER:
1779 LFile += ",executivepaper";
1782 LFile += ",a3paper";
1785 LFile += ",a4paper";
1788 LFile += ",a5paper";
1791 LFile += ",b5paper";
1795 if (!params.topmargin.empty())
1796 LFile += ",tmargin=" + params.topmargin;
1797 if (!params.bottommargin.empty())
1798 LFile += ",bmargin=" + params.bottommargin;
1799 if (!params.leftmargin.empty())
1800 LFile += ",lmargin=" + params.leftmargin;
1801 if (!params.rightmargin.empty())
1802 LFile += ",rmargin=" + params.rightmargin;
1803 if (!params.headheight.empty())
1804 LFile += ",headheight=" + params.headheight;
1805 if (!params.headsep.empty())
1806 LFile += ",headsep=" + params.headsep;
1807 if (!params.footskip.empty())
1808 LFile += ",footskip=" + params.footskip;
1812 if (params.use_amsmath
1813 && !prefixIs(lyxstyle.LatexnameOfClass(params.textclass), "ams")) {
1814 LFile += "\\usepackage{amsmath}\n";
1817 if (tokenPos(tclass->opt_pagestyle, '|',params.pagestyle) >= 0) {
1818 if (params.pagestyle == "fancy") {
1819 LFile += "\\usepackage{fancyhdr}\n";
1822 LFile += "\\pagestyle{" + params.pagestyle + "}\n";
1826 // We try to load babel late, in case it interferes
1827 // with other packages.
1828 if (params.language != "default") {
1829 LFile += "\\usepackage{babel}\n";
1833 if (params.secnumdepth != tclass->secnumdepth) {
1834 LFile += "\\setcounter{secnumdepth}{";
1835 LFile += tostr(params.secnumdepth);
1839 if (params.tocdepth != tclass->tocdepth) {
1840 LFile += "\\setcounter{tocdepth}{";
1841 LFile += tostr(params.tocdepth);
1846 if (params.paragraph_separation) {
1847 switch (params.defskip.kind()) {
1848 case VSpace::SMALLSKIP:
1849 LFile += "\\setlength\\parskip{\\smallskipamount}\n";
1851 case VSpace::MEDSKIP:
1852 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1854 case VSpace::BIGSKIP:
1855 LFile += "\\setlength\\parskip{\\bigskipamount}\n";
1857 case VSpace::LENGTH:
1858 LFile += "\\setlength\\parskip{"
1859 + params.defskip.length().asLatexString()
1862 default: // should never happen // Then delete it.
1863 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1868 LFile += "\\setlength\\parindent{0pt}\n";
1872 // Write out what we've generated so far...and reset LFile
1873 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
1876 // Now insert the LyX specific LaTeX commands...
1877 string preamble, tmppreamble;
1879 // The optional packages;
1880 preamble = features.getPackages(params);
1882 // this might be useful...
1883 preamble += "\n\\makeatletter\n\n";
1885 // Some macros LyX will need
1886 tmppreamble = features.getMacros(params);
1888 if (!tmppreamble.empty()) {
1889 preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1890 "LyX specific LaTeX commands.\n"
1891 + tmppreamble + '\n';
1894 // the text class specific preamble
1895 tmppreamble = features.getTClassPreamble(params);
1896 if (!tmppreamble.empty()) {
1897 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1898 "Textclass specific LaTeX commands.\n"
1899 + tmppreamble + '\n';
1902 /* the user-defined preamble */
1903 if (!params.preamble.empty()) {
1904 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1905 "User specified LaTeX commands.\n"
1906 + params.preamble + '\n';
1909 preamble += "\\makeatother\n\n";
1911 // Itemize bullet settings need to be last in case the user
1912 // defines their own bullets that use a package included
1913 // in the user-defined preamble -- ARRae
1914 for (int i = 0; i < 4; ++i) {
1915 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
1916 preamble += "\\renewcommand\\labelitemi";
1918 // `i' is one less than the item to modify
1931 preamble += "[0]{" + params.user_defined_bullets[i].getText() + "}\n";
1935 for (int j = countChar(preamble, '\n'); j-- ;) {
1939 // A bit faster than printing a char at a time I think.
1940 fwrite(preamble.c_str(), sizeof(char),
1941 preamble.length(), file);
1944 LFile += "\\begin{document}\n\n";
1948 lyxerr.debug() << "preamble finished, now the body." << endl;
1950 bool was_title = false;
1951 bool already_title = false;
1957 LyXParagraph *par = paragraph;
1963 lyxerr[Debug::LATEX] << "Error in MakeLateXFile."
1965 LyXLayout * layout = lyxstyle.Style(params.textclass,
1968 if (layout->intitle) {
1969 if (already_title) {
1970 lyxerr <<"Error in MakeLatexFile: You"
1971 " should not mix title layouts"
1972 " with normal ones." << endl;
1975 } else if (was_title && !already_title) {
1976 LFile += "\\maketitle\n";
1978 already_title = true;
1981 // We are at depth 0 so we can just use
1982 // ordinary \footnote{} generation
1983 // flag this with ftcount
1985 if (layout->isEnvironment()
1986 || par->pextra_type != PEXTRA_NONE) {
1987 par = par->TeXEnvironment(LFile, texrow,
1988 ftnote, ft_texrow, ftcount);
1990 par = par->TeXOnePar(LFile, texrow,
1991 ftnote, ft_texrow, ftcount);
1994 // Write out what we've generated...and reset LFile
1997 LFile += "\\addtocounter{footnote}{-";
1998 LFile += tostr(ftcount - 1);
2002 texrow += ft_texrow;
2007 if (loop_count == 2) {
2008 // fwrite()ing every second time through the loop
2009 // gains a few extra % of speed; going higher than
2010 // 2 will slow things down again. I'll look at
2011 // LFile.length() in a future revision. ARRae
2012 fwrite(LFile.c_str(), sizeof(char),
2013 LFile.length(), file);
2019 // It might be that we only have a title in this document
2020 if (was_title && !already_title) {
2021 LFile += "\\maketitle\n";
2026 LFile += "\\end{document}\n";
2029 lyxerr[Debug::LATEX] << "makeLaTeXFile...done" << endl;
2031 lyxerr[Debug::LATEX] << "LaTeXFile for inclusion made."
2035 // Just to be sure. (Asger)
2038 // Write out what we've generated...and reset LFile
2039 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
2042 // tex_code_break_column's value is used to decide
2043 // if we are in batchmode or not (within mathed_write()
2044 // in math_write.C) so we must set it to a non-zero
2045 // value when we leave otherwise we save incorrect .lyx files.
2046 tex_code_break_column = lyxrc->ascii_linelen;
2049 WriteFSAlert(_("Error! Could not close file properly:"), filename);
2051 lyxerr.debug() << "Finished making latex file." << endl;
2055 bool Buffer::isLatex()
2057 return lyxstyle.TextClass(params.textclass)->output_type == LATEX;
2061 bool Buffer::isLinuxDoc()
2063 return lyxstyle.TextClass(params.textclass)->output_type == LINUXDOC;
2067 bool Buffer::isLiterate()
2069 return lyxstyle.TextClass(params.textclass)->output_type == LITERATE;
2073 bool Buffer::isDocBook()
2075 return lyxstyle.TextClass(params.textclass)->output_type == DOCBOOK;
2079 bool Buffer::isSGML()
2081 return lyxstyle.TextClass(params.textclass)->output_type == LINUXDOC ||
2082 lyxstyle.TextClass(params.textclass)->output_type == DOCBOOK;
2086 void Buffer::sgmlOpenTag(FILE * file,int depth,string & latexname)
2088 static char *space[] = {" "," "," "," "," "," "," ",
2091 fprintf(file,"%s<%s>\n",space[depth],latexname.c_str());
2095 void Buffer::sgmlCloseTag(FILE * file,int depth,string & latexname)
2097 static char *space[] = {" "," "," "," "," "," "," ",
2100 fprintf(file,"%s</%s>\n",space[depth],latexname.c_str());
2104 void Buffer::makeLinuxDocFile(string const & filename, int column)
2106 LyXParagraph *par = paragraph;
2108 string top_element=lyxstyle.LatexnameOfClass(params.textclass);
2109 string environment_stack[10];
2112 int depth=0; /* paragraph depth */
2114 FilePtr file(filename, FilePtr::write);
2115 tex_code_break_column = column;
2118 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2125 if (params.preamble.empty()) {
2126 fprintf(file, "<!doctype linuxdoc system>\n\n");
2129 fprintf(file, "<!doctype linuxdoc system \n [ %s \n]>\n\n",
2130 params.preamble.c_str() );
2133 string userName(getUserName());
2134 fprintf(file, "<!-- LinuxDoc file was created by LyX 1.0 (C) 1995-1999 ");
2135 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2137 if(params.options.empty())
2138 sgmlOpenTag(file,0,top_element);
2140 string top = top_element;
2142 top += params.options;
2143 sgmlOpenTag(file,0,top);
2147 int desc_on=0; /* description mode*/
2148 LyXLayout *style=lyxstyle.Style(GetCurrentTextClass(), par->layout);
2149 par->AutoDeleteInsets();
2151 /* treat <toc> as a special case for compatibility with old code */
2152 if (par->GetChar(0) == LYX_META_INSET) {
2153 Inset *inset = par->GetInset(0);
2154 char lyx_code = inset->LyxCode();
2155 if (lyx_code ==Inset::TOC_CODE){
2157 sgmlOpenTag(file, depth, temp);
2160 linuxDocHandleFootnote(file, par, depth);
2165 /* environment tag closing */
2166 for( ;depth > par->depth; depth--) {
2167 sgmlCloseTag(file,depth,environment_stack[depth]);
2168 environment_stack[depth].clear();
2171 /* write opening SGML tags */
2172 switch(style->latextype) {
2173 case LATEX_PARAGRAPH:
2174 if(depth == par->depth
2175 && !environment_stack[depth].empty()) {
2176 sgmlCloseTag(file,depth,environment_stack[depth]);
2177 environment_stack[depth].clear();
2181 fprintf(file,"</p>");
2183 sgmlOpenTag(file,depth,style->latexname);
2188 LinuxDocError(par, 0, _("Error : Wrong depth for LatexType Command.\n"));
2190 if (!environment_stack[depth].empty()){
2191 sgmlCloseTag(file,depth,environment_stack[depth]);
2192 fprintf(file, "</p>");
2195 environment_stack[depth].clear();
2196 sgmlOpenTag(file,depth, style->latexname);
2199 case LATEX_ENVIRONMENT:
2200 case LATEX_ITEM_ENVIRONMENT:
2201 if(depth == par->depth
2202 && environment_stack[depth]!=style->latexname
2203 && !environment_stack[depth].empty()) {
2205 sgmlCloseTag(file,depth,environment_stack[depth]);
2206 environment_stack[depth].clear();
2208 if (depth < par->depth) {
2210 environment_stack[depth].clear();
2212 if (environment_stack[depth] != style->latexname) {
2215 sgmlOpenTag(file,depth,temp);
2217 environment_stack[depth]= style->latexname;
2218 sgmlOpenTag(file,depth,environment_stack[depth]);
2220 if(style->latextype == LATEX_ENVIRONMENT) break;
2222 desc_on =(style->labeltype == LABEL_MANUAL);
2229 sgmlOpenTag(file,depth+1,item_name);
2232 sgmlOpenTag(file,depth,style->latexname);
2237 SimpleLinuxDocOnePar(file, par, desc_on, depth);
2240 linuxDocHandleFootnote(file,par,depth);
2242 while(par && par->IsDummy());
2245 /* write closing SGML tags */
2246 switch(style->latextype) {
2248 case LATEX_ENVIRONMENT:
2249 case LATEX_ITEM_ENVIRONMENT:
2252 sgmlCloseTag(file,depth,style->latexname);
2260 /* Close open tags */
2261 for(;depth>0;depth--)
2262 sgmlCloseTag(file,depth,environment_stack[depth]);
2264 if(!environment_stack[depth].empty())
2265 sgmlCloseTag(file,depth,environment_stack[depth]);
2267 fprintf(file, "\n\n");
2268 sgmlCloseTag(file,0,top_element);
2271 WriteFSAlert(_("Error! Could not close file properly:"),
2277 void Buffer::linuxDocHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2279 string tag="footnote";
2281 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2282 sgmlOpenTag(file,depth+1,tag);
2283 SimpleLinuxDocOnePar(file, par, 0,depth+1);
2284 sgmlCloseTag(file,depth+1,tag);
2289 void Buffer::DocBookHandleCaption(FILE *file, string &inner_tag,
2290 int const depth, int desc_on,
2293 LyXParagraph *tpar = par;
2294 string tmp_par, extra_par;
2295 while (tpar && (tpar->footnoteflag != LyXParagraph::NO_FOOTNOTE) &&
2296 (tpar->layout != lyxstyle.NumberOfLayout(params.textclass,"Caption")))
2299 tpar->layout==lyxstyle.NumberOfLayout(params.textclass,"Caption")) {
2300 sgmlOpenTag(file,depth+1,inner_tag);
2301 SimpleDocBookOnePar(tmp_par,extra_par,tpar,desc_on,depth+2);
2302 tmp_par = strip(tmp_par);
2303 tmp_par = frontStrip(tmp_par);
2304 fprintf(file,"%s",tmp_par.c_str());
2305 sgmlCloseTag(file,depth+1,inner_tag);
2306 if(!extra_par.empty())
2307 fprintf(file,"%s",extra_par.c_str());
2311 void Buffer::DocBookHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2313 string tag,inner_tag;
2314 string tmp_par,extra_par;
2315 bool inner_span = false;
2318 // This is not how I like to see enums. They should not be anonymous
2319 // and variables of its type should not be declared right after the
2320 // last brace. (Lgb)
2327 } last=NO_ONE, present=FOOTNOTE_LIKE;
2329 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2332 if(!tmp_par.empty()) {
2333 fprintf(file,"%s",tmp_par.c_str());
2335 sgmlCloseTag(file,depth+1,inner_tag);
2336 sgmlOpenTag(file,depth+1,inner_tag);
2342 fprintf(file,"%s",tmp_par.c_str());
2343 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2344 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2345 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2348 switch (par->footnotekind) {
2349 case LyXParagraph::FOOTNOTE:
2350 case LyXParagraph::ALGORITHM:
2353 present=FOOTNOTE_LIKE;
2356 case LyXParagraph::MARGIN:
2359 present=MARGIN_LIKE;
2362 case LyXParagraph::FIG:
2363 case LyXParagraph::WIDE_FIG:
2369 case LyXParagraph::TAB:
2370 case LyXParagraph::WIDE_TAB:
2377 sgmlOpenTag(file,depth,tag);
2378 if ((present == TAB_LIKE) || (present == FIG_LIKE)) {
2379 DocBookHandleCaption(file, inner_tag, depth,
2383 sgmlOpenTag(file,depth+1,inner_tag);
2386 // ignore all caption here, we processed them above!!!
2387 if (par->layout != lyxstyle.NumberOfLayout(params.textclass,
2389 SimpleDocBookOnePar(tmp_par,extra_par,par,
2392 tmp_par = frontStrip(strip(tmp_par));
2397 fprintf(file,"%s",tmp_par.c_str());
2398 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2399 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2400 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2405 /* push a tag in a style stack */
2406 void Buffer::push_tag(FILE *file, char const *tag,
2407 int& pos, char stack[5][3])
2411 /* pop all previous tags */
2412 for (j=pos; j>=0; j--)
2413 fprintf(file, "</%s>", stack[j]);
2416 sprintf(stack[++pos], "%s", tag);
2419 for (j=0; j<=pos; j++)
2420 fprintf(file, "<%s>", stack[j]);
2424 // pop a tag from a style stack
2425 void Buffer::pop_tag(FILE *file, char const * tag,
2426 int& pos, char stack[5][3])
2430 // pop all tags till specified one
2431 for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
2432 fprintf(file, "</%s>", stack[j]);
2435 fprintf(file, "</%s>", tag);
2437 // push all tags, but the specified one
2438 for (j=j+1; j<=pos; j++) {
2439 fprintf(file, "<%s>", stack[j]);
2440 strcpy(stack[j-1], stack[j]);
2446 /* handle internal paragraph parsing -- layout already processed */
2448 // checks, if newcol chars should be put into this line
2449 // writes newline, if necessary.
2451 void linux_doc_line_break(FILE *file, unsigned int &colcount, const unsigned int newcol)
2454 if (colcount > lyxrc->ascii_linelen) {
2455 fprintf(file, "\n");
2456 colcount = newcol; // assume write after this call
2461 void Buffer::SimpleLinuxDocOnePar(FILE *file, LyXParagraph *par, int desc_on, int const depth)
2463 LyXFont font1,font2;
2467 LyXLayout * style = lyxstyle.Style(params.textclass, par->GetLayout());
2469 char family_type = 0; // family font flag
2470 bool is_bold = false; // series font flag
2471 char shape_type = 0; // shape font flag
2472 bool is_em = false; // emphasis (italic) font flag
2474 int stack_num = -1; // style stack position
2475 char stack[5][3]; // style stack
2476 unsigned int char_line_count = 5; // Heuristic choice ;-)
2478 if (style->labeltype != LABEL_MANUAL)
2481 main_body = par->BeginningOfMainBody();
2483 /* gets paragraph main font */
2485 font1 = style->labelfont;
2487 font1 = style->font;
2490 /* parsing main loop */
2491 for (int i = 0; i < par->last; i++) {
2493 /* handle quote tag */
2494 if (i == main_body && !par->IsDummy()) {
2496 font1 = style->font;
2499 font2 = par->getFont(i);
2501 if (font1.family() != font2.family()) {
2502 switch(family_type) {
2504 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2505 push_tag(file, "tt", stack_num, stack);
2508 else if (font2.family() == LyXFont::SANS_FAMILY) {
2509 push_tag(file, "sf", stack_num, stack);
2514 pop_tag(file, "tt", stack_num, stack);
2515 if (font2.family() == LyXFont::SANS_FAMILY) {
2516 push_tag(file, "sf", stack_num, stack);
2524 pop_tag(file, "sf", stack_num, stack);
2525 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2526 push_tag(file, "tt", stack_num, stack);
2535 /* handle bold face */
2536 if (font1.series() != font2.series()) {
2537 if (font2.series() == LyXFont::BOLD_SERIES) {
2538 push_tag(file, "bf", stack_num, stack);
2542 pop_tag(file, "bf", stack_num, stack);
2547 /* handle italic and slanted fonts */
2548 if (font1.shape() != font2.shape()) {
2549 switch(shape_type) {
2551 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2552 push_tag(file, "it", stack_num, stack);
2555 else if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2556 push_tag(file, "sl", stack_num, stack);
2561 pop_tag(file, "it", stack_num, stack);
2562 if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2563 push_tag(file, "sl", stack_num, stack);
2571 pop_tag(file, "sl", stack_num, stack);
2572 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2573 push_tag(file, "it", stack_num, stack);
2581 /* handle <em> tag */
2582 if (font1.emph() != font2.emph()) {
2583 if (font2.emph() == LyXFont::ON) {
2584 push_tag(file, "em", stack_num, stack);
2587 pop_tag(file, "em", stack_num, stack);
2592 c = par->GetChar(i);
2594 if (font2.latex() == LyXFont::ON) {
2595 // "TeX"-Mode on ==> SGML-Mode on.
2597 fprintf(file, "%c", c); // see LaTeX-Generation...
2599 } else if (c == LYX_META_INSET) {
2600 inset = par->GetInset(i);
2602 inset->Linuxdoc(tmp_out);
2603 fprintf(file,"%s",tmp_out.c_str());
2607 if (par->linuxDocConvertChar(c, sgml_string)
2608 && !style->free_spacing) { // in freespacing
2610 // non-breaking characters
2614 linux_doc_line_break(file, char_line_count, 6);
2615 fprintf(file, "</tag>");
2619 linux_doc_line_break(file, char_line_count, 1);
2620 fprintf(file, "%c", c);
2624 fprintf(file, "%s", sgml_string.c_str());
2625 char_line_count += sgml_string.length();
2631 /* needed if there is an optional argument but no contents */
2632 if (main_body > 0 && main_body == par->last) {
2633 font1 = style->font;
2636 /* pop all defined Styles */
2637 for (j=stack_num; j>=0; j--) {
2638 linux_doc_line_break(file,
2640 3+strlen(stack[j]));
2641 fprintf(file, "</%s>", stack[j]);
2644 /* resets description flag correctly */
2647 /* <tag> not closed... */
2648 linux_doc_line_break(file, char_line_count, 6);
2649 fprintf(file, "</tag>");
2652 /* fprintf(file, "</p>");*/
2658 /* print an error message */
2659 void Buffer::LinuxDocError(LyXParagraph *par, int pos,
2660 char const *message)
2662 InsetError *new_inset;
2664 /* insert an error marker in text */
2665 new_inset = new InsetError(message);
2666 par->InsertChar(pos, LYX_META_INSET);
2667 par->InsertInset(pos, new_inset);
2670 // This constant defines the maximum number of
2671 // environment layouts that can be nesteded.
2672 // The same applies for command layouts.
2673 // These values should be more than enough.
2674 // José Matos (1999/07/22)
2676 enum { MAX_NEST_LEVEL = 25};
2678 void Buffer::makeDocBookFile(string const & filename, int column)
2680 LyXParagraph *par = paragraph;
2682 string top_element=lyxstyle.LatexnameOfClass(params.textclass);
2683 string environment_stack[MAX_NEST_LEVEL];
2684 string environment_inner[MAX_NEST_LEVEL];
2685 string command_stack[MAX_NEST_LEVEL];
2686 bool command_flag=false;
2687 int command_depth=0,command_base=0,cmd_depth=0;
2689 string item_name,command_name;
2690 string c_depth,c_params,tmps;
2692 int depth=0; /* paragraph depth */
2694 FilePtr file(filename, FilePtr::write);
2695 tex_code_break_column = column;
2698 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2705 fprintf(file, "<!doctype %s public \"-//OASIS//DTD DocBook V3.1//EN\"",top_element.c_str());
2707 if (params.preamble.empty())
2708 fprintf(file, ">\n\n");
2710 fprintf(file, "\n [ %s \n]>\n\n",params.preamble.c_str() );
2712 string userName(getUserName());
2714 "<!-- DocBook file was created by LyX 1.0 (C) 1995-1999\n");
2715 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2717 if(params.options.empty())
2718 sgmlOpenTag(file,0,top_element);
2720 string top = top_element;
2722 top += params.options;
2723 sgmlOpenTag(file,0,top);
2727 int desc_on=0; /* description mode*/
2728 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(),
2730 par->AutoDeleteInsets();
2732 /* environment tag closing */
2733 for( ;depth > par->depth; depth--) {
2734 if(environment_inner[depth] != "!-- --") {
2735 item_name="listitem";
2736 sgmlCloseTag(file,command_depth+depth,
2738 if( environment_inner[depth] == "varlistentry")
2739 sgmlCloseTag(file,depth+command_depth,
2740 environment_inner[depth]);
2742 sgmlCloseTag(file,depth+command_depth,
2743 environment_stack[depth]);
2744 environment_stack[depth].clear();
2745 environment_inner[depth].clear();
2748 if(depth == par->depth
2749 && environment_stack[depth]!=style->latexname
2750 && !environment_stack[depth].empty()) {
2751 if(environment_inner[depth] != "!-- --") {
2752 item_name="listitem";
2753 sgmlCloseTag(file,command_depth+depth,
2755 if( environment_inner[depth] == "varlistentry")
2756 sgmlCloseTag(file,depth+command_depth,
2757 environment_inner[depth]);
2760 sgmlCloseTag(file,depth+command_depth,
2761 environment_stack[depth]);
2763 environment_stack[depth].clear();
2764 environment_inner[depth].clear();
2767 // Write opening SGML tags.
2768 switch(style->latextype) {
2769 case LATEX_PARAGRAPH:
2770 if(style->latexname != "dummy")
2771 sgmlOpenTag(file, depth+command_depth,
2777 LinuxDocError(par, 0,
2778 _("Error : Wrong depth for "
2779 "LatexType Command.\n"));
2781 command_name=style->latexname;
2783 tmps=style->latexparam;
2784 c_params= split(tmps, c_depth,'|');
2786 cmd_depth=atoi(c_depth.c_str());
2789 if(cmd_depth<command_base) {
2790 for(int j = command_depth;
2791 j >= command_base; j--)
2792 if(!command_stack[j].empty())
2793 sgmlCloseTag(file,j,command_stack[j]);
2794 command_depth=command_base=cmd_depth;
2796 else if(cmd_depth<=command_depth) {
2797 for(int j= command_depth;
2798 j >= cmd_depth; j--)
2800 if(!command_stack[j].empty())
2801 sgmlCloseTag(file,j,command_stack[j]);
2802 command_depth=cmd_depth;
2805 command_depth=cmd_depth;
2808 command_depth = command_base = cmd_depth;
2809 command_flag = true;
2811 command_stack[command_depth]=command_name;
2813 // treat label as a special case for
2814 // more WYSIWYM handling.
2815 if (par->GetChar(0) == LYX_META_INSET) {
2816 Inset *inset = par->GetInset(0);
2817 char lyx_code = inset->LyxCode();
2818 if (lyx_code ==Inset::LABEL_CODE){
2819 command_name+= " id=\"";
2820 command_name+=((InsetCommand *) inset)->getContents();
2826 sgmlOpenTag(file,depth+command_depth, command_name);
2828 sgmlOpenTag(file,depth+1+command_depth,item_name);
2831 case LATEX_ENVIRONMENT:
2832 case LATEX_ITEM_ENVIRONMENT:
2833 if (depth < par->depth) {
2835 environment_stack[depth].clear();
2838 if (environment_stack[depth] != style->latexname) {
2839 environment_stack[depth]= style->latexname;
2840 environment_inner[depth]= "!-- --";
2841 sgmlOpenTag(file, depth + command_depth,
2842 environment_stack[depth]);
2844 if(environment_inner[depth] != "!-- --") {
2845 item_name="listitem";
2847 command_depth + depth,
2849 if (environment_inner[depth] == "varlistentry")
2851 depth+command_depth,
2852 environment_inner[depth]);
2856 if(style->latextype == LATEX_ENVIRONMENT) {
2857 if(!style->latexparam.empty())
2858 sgmlOpenTag(file, depth+command_depth,
2863 desc_on =(style->labeltype == LABEL_MANUAL);
2866 environment_inner[depth]="varlistentry";
2868 environment_inner[depth]="listitem";
2870 sgmlOpenTag(file,depth+1+command_depth,
2871 environment_inner[depth]);
2875 sgmlOpenTag(file,depth+1+command_depth,
2880 sgmlOpenTag(file,depth+1+command_depth,
2885 sgmlOpenTag(file,depth+command_depth,style->latexname);
2890 string tmp_par,extra_par;
2892 SimpleDocBookOnePar(tmp_par,extra_par, par, desc_on,
2893 depth+1+command_depth);
2894 fprintf(file,"%s",tmp_par.c_str());
2897 DocBookHandleFootnote(file,par, depth+1+command_depth);
2899 while(par && par->IsDummy());
2902 /* write closing SGML tags */
2903 switch(style->latextype) {
2906 sgmlCloseTag(file,depth+command_depth,end_tag);
2908 case LATEX_ENVIRONMENT:
2909 if(!style->latexparam.empty())
2910 sgmlCloseTag(file,depth+command_depth,
2913 case LATEX_ITEM_ENVIRONMENT:
2914 if(desc_on==1) break;
2916 sgmlCloseTag(file,depth+1+command_depth,end_tag);
2918 case LATEX_PARAGRAPH:
2919 if( style->latexname != "dummy")
2920 sgmlCloseTag(file,depth+command_depth,
2924 sgmlCloseTag(file,depth+command_depth,
2931 for(;depth>=0;depth--) {
2932 if(!environment_stack[depth].empty()) {
2933 if(environment_inner[depth] != "!-- --") {
2934 item_name="listitem";
2935 sgmlCloseTag(file,command_depth+depth,
2937 if( environment_inner[depth] == "varlistentry")
2938 sgmlCloseTag(file,depth+command_depth,
2939 environment_inner[depth]);
2942 sgmlCloseTag(file,depth+command_depth,
2943 environment_stack[depth]);
2947 for(int j=command_depth;j>=command_base;j--)
2948 if(!command_stack[j].empty())
2949 sgmlCloseTag(file,j,command_stack[j]);
2951 fprintf(file, "\n\n");
2952 sgmlCloseTag(file,0,top_element);
2955 WriteFSAlert(_("Error! Could not close file properly:"),
2961 void Buffer::SimpleDocBookOnePar(string & file, string & extra,
2962 LyXParagraph * par, int & desc_on,
2966 par->SimpleDocBookOneTablePar(file, extra, desc_on, depth);
2969 LyXFont font1,font2;
2973 string emph="emphasis";
2974 bool emph_flag=false;
2975 int char_line_count=0;
2977 LyXLayout * style = lyxstyle.Style(params.textclass, par->GetLayout());
2979 if (style->labeltype != LABEL_MANUAL)
2982 main_body = par->BeginningOfMainBody();
2984 /* gets paragraph main font */
2986 font1 = style->labelfont;
2988 font1 = style->font;
2990 char_line_count = depth;
2991 if(!style->free_spacing)
2992 for (j=0;j< depth;j++)
2995 /* parsing main loop */
2996 for (int i = 0; i < par->last; i++) {
2998 font2 = par->getFont(i);
3000 /* handle <emphasis> tag */
3001 if (font1.emph() != font2.emph() && i) {
3002 if (font2.emph() == LyXFont::ON) {
3003 file += "<emphasis>";
3006 file += "</emphasis>";
3011 c = par->GetChar(i);
3013 if (c == LYX_META_INSET) {
3014 inset = par->GetInset(i);
3016 inset->DocBook(tmp_out);
3018 // This code needs some explanation:
3019 // Two insets are treated specially
3020 // label if it is the first element in a command paragraph
3022 // graphics inside tables or figure floats can't go on
3023 // title (the equivalente in latex for this case is caption
3024 // and title should come first
3027 if(desc_on!=3 || i!=0) {
3028 if(tmp_out[0]=='@') {
3030 extra += frontStrip(tmp_out, '@');
3032 file += frontStrip(tmp_out, '@');
3037 } else if (font2.latex() == LyXFont::ON) {
3038 // "TeX"-Mode on ==> SGML-Mode on.
3045 if (par->linuxDocConvertChar(c, sgml_string)
3046 && !style->free_spacing) { // in freespacing
3048 // non-breaking characters
3053 file += "</term><listitem><para>";
3061 file += sgml_string;
3067 /* needed if there is an optional argument but no contents */
3068 if (main_body > 0 && main_body == par->last) {
3069 font1 = style->font;
3073 file += "</emphasis>";
3076 /* resets description flag correctly */
3079 /* <term> not closed... */
3087 bool Buffer::removeAutoInsets()
3089 LyXParagraph *par = paragraph;
3091 LyXCursor cursor = text->cursor;
3092 LyXCursor tmpcursor = cursor;
3093 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
3094 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
3098 if (par->AutoDeleteInsets()){
3100 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
3101 /* this is possible now, since SetCursor takes
3102 care about footnotes */
3103 text->SetCursorIntern(par, 0);
3104 text->RedoParagraphs(text->cursor, text->cursor.par->Next());
3105 text->FullRebreak();
3110 /* avoid forbidden cursor positions caused by error removing */
3111 if (cursor.pos > cursor.par->Last())
3112 cursor.pos = cursor.par->Last();
3113 text->SetCursorIntern(cursor.par, cursor.pos);
3119 int Buffer::runLaTeX()
3121 if (!text) return 0;
3125 // get LaTeX-Filename
3126 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3128 string path = OnlyPath(filename);
3130 string org_path = path;
3131 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3135 Path p(path); // path to LaTeX file
3136 users->getOwner()->getMiniBuffer()->Set(_("Running LaTeX..."));
3138 // Remove all error insets
3139 bool a = removeAutoInsets();
3141 // generate the LaTeX file if necessary
3142 //if (!isDviClean() || a) {
3143 // makeLaTeXFile(name, org_path, false);
3147 // Always generate the LaTeX file
3148 makeLaTeXFile(name, org_path, false);
3151 // do the LaTex run(s)
3153 LaTeX latex(lyxrc->latex_command, name, filepath);
3154 int res = latex.run(terr,users->getOwner()->getMiniBuffer()); // running latex
3156 // check return value from latex.run().
3157 if ((res & LaTeX::NO_LOGFILE)) {
3158 WriteAlert(_("LaTeX did not work!"),
3159 _("Missing log file:"), name);
3160 } else if ((res & LaTeX::ERRORS)) {
3161 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3162 // Insert all errors as errors boxes
3165 // Dvi should also be kept dirty if the latex run
3166 // ends up with errors. However it should be possible
3167 // to view a dirty dvi too.
3169 //no errors or any other things to think about so:
3170 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3174 // if we removed error insets before we ran LaTeX or if we inserted
3175 // error insets after we ran LaTeX this must be run:
3176 if (a || (res & LaTeX::ERRORS)){
3179 users->updateScrollbar();
3183 return latex.getNumErrors();
3187 int Buffer::runLiterate()
3189 if (!text) return 0;
3193 // get LaTeX-Filename
3194 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3195 // get Literate-Filename
3196 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3198 string path = OnlyPath(filename);
3200 string org_path = path;
3201 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3205 Path p(path); // path to Literate file
3206 users->getOwner()->getMiniBuffer()->Set(_("Running Literate..."));
3208 // Remove all error insets
3209 bool a = removeAutoInsets();
3211 // generate the Literate file if necessary
3212 if (!isDviClean() || a) {
3213 makeLaTeXFile(lit_name, org_path, false);
3218 Literate literate(lyxrc->latex_command, name, filepath,
3220 lyxrc->literate_command, lyxrc->literate_error_filter,
3221 lyxrc->build_command, lyxrc->build_error_filter);
3222 int res = literate.weave(terr,users->getOwner()->getMiniBuffer());
3224 // check return value from literate.weave().
3225 if ((res & Literate::NO_LOGFILE)) {
3226 WriteAlert(_("Literate command did not work!"),
3227 _("Missing log file:"), name);
3228 } else if ((res & Literate::ERRORS)) {
3229 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3230 // Insert all errors as errors boxes
3233 // Dvi should also be kept dirty if the latex run
3234 // ends up with errors. However it should be possible
3235 // to view a dirty dvi too.
3237 //no errors or any other things to think about so:
3238 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3242 // if we removed error insets before we ran LaTeX or if we inserted
3243 // error insets after we ran LaTeX this must be run:
3244 if (a || (res & Literate::ERRORS)){
3247 users->updateScrollbar();
3251 return literate.getNumErrors();
3255 int Buffer::buildProgram()
3257 if (!text) return 0;
3261 // get LaTeX-Filename
3262 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3263 // get Literate-Filename
3264 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3266 string path = OnlyPath(filename);
3268 string org_path = path;
3269 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3273 Path p(path); // path to Literate file
3274 users->getOwner()->getMiniBuffer()->Set(_("Building Program..."));
3276 // Remove all error insets
3277 bool a = removeAutoInsets();
3279 // generate the LaTeX file if necessary
3280 if (!isNwClean() || a) {
3281 makeLaTeXFile(lit_name, org_path, false);
3286 Literate literate(lyxrc->latex_command, name, filepath,
3288 lyxrc->literate_command, lyxrc->literate_error_filter,
3289 lyxrc->build_command, lyxrc->build_error_filter);
3290 int res = literate.build(terr,users->getOwner()->getMiniBuffer());
3292 // check return value from literate.build().
3293 if ((res & Literate::NO_LOGFILE)) {
3294 WriteAlert(_("Build did not work!"),
3295 _("Missing log file:"), name);
3296 } else if ((res & Literate::ERRORS)) {
3297 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3298 // Insert all errors as errors boxes
3301 // Literate files should also be kept dirty if the literate
3302 // command run ends up with errors.
3304 //no errors or any other things to think about so:
3305 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3309 // if we removed error insets before we ran Literate/Build or if we inserted
3310 // error insets after we ran Literate/Build this must be run:
3311 if (a || (res & Literate::ERRORS)){
3314 users->updateScrollbar();
3318 return literate.getNumErrors();
3322 // This should be enabled when the Chktex class is implemented. (Asger)
3323 // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
3324 // Other flags: -wall -v0 -x
3325 int Buffer::runChktex()
3327 if (!text) return 0;
3331 // get LaTeX-Filename
3332 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3333 string path = OnlyPath(filename);
3335 string org_path = path;
3336 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3340 Path p(path); // path to LaTeX file
3341 users->getOwner()->getMiniBuffer()->Set(_("Running chktex..."));
3343 // Remove all error insets
3344 bool a = removeAutoInsets();
3346 // Generate the LaTeX file if neccessary
3347 if (!isDviClean() || a) {
3348 makeLaTeXFile(name, org_path, false);
3353 Chktex chktex(lyxrc->chktex_command, name, filepath);
3354 int res = chktex.run(terr); // run chktex
3357 WriteAlert(_("chktex did not work!"),
3358 _("Could not run with file:"), name);
3359 } else if (res > 0) {
3360 // Insert all errors as errors boxes
3364 // if we removed error insets before we ran chktex or if we inserted
3365 // error insets after we ran chktex, this must be run:
3369 users->updateScrollbar();
3377 extern void AllFloats(char, char);
3380 void Buffer::insertErrors(TeXErrors &terr)
3382 // Save the cursor position
3383 LyXCursor cursor = text->cursor;
3385 // Now traverse all the errors and insert them
3386 bool firsterror = true;
3389 // This is drastic, but it's the only fix, I could find. (Asger)
3398 more = terr.getFirstError(&errorrow, &errortext);
3401 more = terr.getNextError(&errorrow, &errortext);
3407 // Insert error string for row number
3411 texrow.getIdFromRow(errorrow, tmpid, tmppos);
3413 LyXParagraph* texrowpar;
3416 texrowpar = text->FirstParagraph();
3419 texrowpar = text->GetParFromID(tmpid);
3425 InsetError *new_inset = new InsetError(errortext);
3427 text->SetCursorIntern(texrowpar, tmppos);
3428 text->InsertInset(new_inset);
3429 text->FullRebreak();
3431 // Restore the cursor position
3432 text->SetCursorIntern(cursor.par, cursor.pos);
3436 void Buffer::setCursorFromRow (int row)
3441 texrow.getIdFromRow(row, tmpid, tmppos);
3443 LyXParagraph* texrowpar;
3446 texrowpar = text->FirstParagraph();
3449 texrowpar = text->GetParFromID(tmpid);
3451 text->SetCursor(texrowpar, tmppos);
3455 void Buffer::RoffAsciiTable(FILE *file, LyXParagraph *par)
3458 font1 = LyXFont(LyXFont::ALL_INHERIT),
3473 fname1 = TmpFileName(string(),"RAT1");
3474 fname2 = TmpFileName(string(),"RAT2");
3475 if (!(fp=fopen(fname1.c_str(),"w"))) {
3476 WriteAlert(_("LYX_ERROR:"),
3477 _("Cannot open temporary file:"), fname1);
3480 par->table->RoffEndOfCell(fp, -1);
3481 for (i = 0; i < par->last; i++) {
3482 c = par->GetChar(i);
3483 if (par->table->IsContRow(cell)) {
3484 if (c == LYX_META_NEWLINE)
3488 font2 = par->GetFontSettings(i);
3489 if (font1.latex() != font2.latex()) {
3490 if (font2.latex() != LyXFont::OFF)
3494 case LYX_META_INSET:
3495 if ((inset = par->GetInset(i))) {
3496 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3497 WriteAlert(_("LYX_ERROR:"),
3498 _("Cannot open temporary file:"), fname2);
3500 remove(fname1.c_str());
3503 inset->Latex(fp2,-1);
3516 case LYX_META_NEWLINE:
3517 if (par->table->CellHasContRow(cell)>=0)
3518 par->RoffContTableRows(fp, i+1,cell);
3519 par->table->RoffEndOfCell(fp, cell);
3522 case LYX_META_HFILL:
3524 case LYX_META_PROTECTED_SEPARATOR:
3527 fprintf(fp, "\\\\");
3531 fprintf(fp, "%c", c);
3534 << "RoffAsciiTable:"
3535 " NULL char in structure." << endl;
3539 par->table->RoffEndOfCell(fp, cell);
3541 string cmd = lyxrc->ascii_roff_command + " >" + fname2;
3542 subst(cmd, "$$FName",fname1);
3543 Systemcalls one(Systemcalls::System, cmd);
3544 if (!(lyxerr.debugging(Debug::ROFF))) {
3545 remove(fname1.c_str());
3547 if (!(fp=fopen(fname2.c_str(),"r"))) {
3548 WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
3551 // now output the produced file
3552 fprintf(file, "\n\n");
3555 WriteAlert(_("Error!"),
3556 _("Error executing *roff command on table"));
3557 // overread leading blank lines
3558 while(!feof(fp) && (c == '\n'))
3561 for(j=0; j<par->depth; j++)
3563 while(!feof(fp) && (c != '\n')) {
3568 // overread trailing blank lines
3569 while(!feof(fp) && (c == '\n'))
3573 remove(fname2.c_str());
3576 /// changed Heinrich Bauer, 23/03/98
3577 bool Buffer::isDviClean()
3579 if (lyxrc->use_tempdir)
3580 return dvi_clean_tmpd;
3582 return dvi_clean_orgd;
3585 /// changed Heinrich Bauer, 23/03/98
3586 void Buffer::markDviClean()
3588 if (lyxrc->use_tempdir)
3589 dvi_clean_tmpd = true;
3591 dvi_clean_orgd = true;
3594 /// changed Heinrich Bauer, 23/03/98
3595 void Buffer::markDviDirty()
3597 if (lyxrc->use_tempdir)
3598 dvi_clean_tmpd = false;
3600 dvi_clean_orgd = false;
3603 void Buffer::update(signed char f)
3607 users->getOwner()->updateLayoutChoice();
3609 if (!text->selection && f > -3)
3610 text->sel_cursor = text->cursor;
3613 text->FullRebreak();
3616 if (f != 3 && f != -3) {
3618 users->updateScrollbar();
3621 if (f==1 || f==-1) {
3624 users->getOwner()->getMiniBuffer()->setTimer(4);
3632 void Buffer::validate(LaTeXFeatures &features)
3634 LyXParagraph *par = paragraph;
3635 LyXTextClass *tclass = lyxstyle.TextClass(params.textclass);
3637 // AMS Style is at document level
3639 features.amsstyle = (params.use_amsmath ||
3640 tclass->provides_amsmath);
3643 // We don't use "lyxerr.debug" because of speed. (Asger)
3644 if (lyxerr.debugging(Debug::LATEX))
3645 lyxerr << "Paragraph: " << par << endl;
3647 // Now just follow the list of paragraphs and run
3648 // validate on each of them.
3649 par->validate(features);
3651 // and then the next paragraph
3655 // the bullet shapes are buffer level not paragraph level
3656 // so they are tested here
3657 for (int i = 0; i < 4; ++i) {
3658 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
3659 int font = params.user_defined_bullets[i].getFont();
3661 int c = params.user_defined_bullets[i].getCharacter();
3667 features.latexsym = true;
3671 features.amssymb = true;
3673 else if ((font >= 2 && font <=5)) {
3674 features.pifont = true;
3679 if (lyxerr.debugging(Debug::LATEX)) {
3680 features.showStruct(params);
3685 void Buffer::setPaperStuff()
3689 params.papersize = PAPER_DEFAULT;
3690 c1 = params.paperpackage;
3691 if (c1 == PACKAGE_NONE) {
3692 c2 = params.papersize2;
3693 if (c2 == VM_PAPER_USLETTER)
3694 params.papersize = PAPER_USLETTER;
3695 else if (c2 == VM_PAPER_USLEGAL)
3696 params.papersize = PAPER_LEGALPAPER;
3697 else if (c2 == VM_PAPER_USEXECUTIVE)
3698 params.papersize = PAPER_EXECUTIVEPAPER;
3699 else if (c2 == VM_PAPER_A3)
3700 params.papersize = PAPER_A3PAPER;
3701 else if (c2 == VM_PAPER_A4)
3702 params.papersize = PAPER_A4PAPER;
3703 else if (c2 == VM_PAPER_A5)
3704 params.papersize = PAPER_A5PAPER;
3705 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
3706 (c2 == VM_PAPER_B5))
3707 params.papersize = PAPER_B5PAPER;
3708 } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
3709 (c1 == PACKAGE_WIDEMARGINSA4))
3710 params.papersize = PAPER_A4PAPER;
3714 void Buffer::setOldPaperStuff()
3718 c = params.papersize = params.papersize2;
3719 params.papersize2 = VM_PAPER_DEFAULT;
3720 params.paperpackage = PACKAGE_NONE;
3721 if (c == OLD_PAPER_A4PAPER)
3722 params.papersize2 = VM_PAPER_A4;
3723 else if (c == OLD_PAPER_A4)
3724 params.paperpackage = PACKAGE_A4;
3725 else if (c == OLD_PAPER_A4WIDE)
3726 params.paperpackage = PACKAGE_A4WIDE;
3727 else if (c == OLD_PAPER_WIDEMARGINSA4)
3728 params.paperpackage = PACKAGE_WIDEMARGINSA4;
3729 else if (c == OLD_PAPER_USLETTER)
3730 params.papersize2 = VM_PAPER_USLETTER;
3731 else if (c == OLD_PAPER_A5PAPER)
3732 params.papersize2 = VM_PAPER_A5;
3733 else if (c == OLD_PAPER_B5PAPER)
3734 params.papersize2 = VM_PAPER_B5;
3735 else if (c == OLD_PAPER_EXECUTIVEPAPER)
3736 params.papersize2 = VM_PAPER_USEXECUTIVE;
3737 else if (c == OLD_PAPER_LEGALPAPER)
3738 params.papersize2 = VM_PAPER_USLEGAL;
3743 void Buffer::insertInset(Inset *inset, string const &lout,
3746 // check for table/list in tables
3747 if (no_table && text->cursor.par->table){
3748 WriteAlert(_("Impossible Operation!"),
3749 _("Cannot insert table/list in table."),
3753 // not quite sure if we want this...
3754 text->SetCursorParUndo();
3758 if (!lout.empty()) {
3760 text->BreakParagraph();
3763 if (text->cursor.par->Last()) {
3766 text->BreakParagraph();
3770 int lay = lyxstyle.NumberOfLayout(params.textclass, lout);
3771 if (lay == -1) // layout not found
3772 // use default layout "Standard" (0)
3775 text->SetLayout(lay);
3777 text->SetParagraph(0, 0,
3779 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3785 text->current_font.setLatex(LyXFont::OFF);
3788 text->InsertInset(inset);
3791 // Commenting these two lines fixes the problem with new display inset
3792 // inside a paragraph, not sure why. (ale 971117)
3793 // if (inset->Display())
3794 // text->CursorRight();
3796 text->UnFreezeUndo();
3800 // Open and lock an updatable inset
3801 void Buffer::open_new_inset(UpdatableInset* new_inset)
3805 insertInset(new_inset);
3808 new_inset->Edit(0,0);
3812 /* This function should be in Buffer because it's a buffer's property (ale) */
3813 string Buffer::getIncludeonlyList(char delim)
3816 LyXParagraph *par = paragraph;
3821 while ((inset = par->ReturnNextInsetPointer(pos))){
3822 if (inset->LyxCode()==Inset::INCLUDE_CODE) {
3823 InsetInclude *insetinc = (InsetInclude*)inset;
3824 if (insetinc->isInclude()
3825 && insetinc->isNoLoad()) {
3828 list += ChangeExtension(insetinc->getContents(), string(), true);
3835 lyxerr.debug() << "Includeonly(" << list << ')' << endl;
3840 /* This is also a buffer property (ale) */
3841 string Buffer::getReferenceList(char delim)
3843 /// if this is a child document and the parent is already loaded
3844 /// Use the parent's list instead [ale990407]
3845 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3846 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3848 return tmp->getReferenceList(delim);
3851 LyXParagraph *par = paragraph;
3857 while ((inset = par->ReturnNextInsetPointer(pos))){
3858 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3861 list += inset->getLabel(i);
3867 lyxerr.debug() << "References(" << list << ")" << endl;
3872 /* This is also a buffer property (ale) */
3873 string Buffer::getBibkeyList(char delim)
3875 /// if this is a child document and the parent is already loaded
3876 /// Use the parent's list instead [ale990412]
3877 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3878 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3880 return tmp->getBibkeyList(delim);
3884 LyXParagraph *par = paragraph;
3887 if (!bibkeys.empty())
3889 bibkeys += par->bibkey->getContents();
3894 // Might be either using bibtex or a child has bibliography
3895 if (bibkeys.empty()) {
3901 // Search for Bibtex or Include inset
3902 while ((inset = par->ReturnNextInsetPointer(pos))) {
3903 if (inset-> LyxCode()==Inset::BIBTEX_CODE) {
3904 if (!bibkeys.empty())
3906 bibkeys += ((InsetBibtex*)inset)->getKeys();
3907 } else if (inset-> LyxCode()==Inset::INCLUDE_CODE) {
3908 string bk = ((InsetInclude*)inset)->getKeys();
3910 if (!bibkeys.empty())
3921 lyxerr.debug() << "Bibkeys(" << bibkeys << ")" << endl;
3926 /* This is also a buffer property (ale) */
3927 // Not so sure about that. a goto Label function can not be buffer local, just
3928 // think how this will work in a multiwindo/buffer environment, all the
3929 // cursors in all the views showing this buffer will move. (Lgb)
3930 // OK, then no cursor action should be allowed in buffer. (ale)
3931 bool Buffer::gotoLabel(const string &label)
3934 LyXParagraph *par = paragraph;
3940 while ((inset = par->ReturnNextInsetPointer(pos))){
3941 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3942 if (label==inset->getLabel(i)) {
3944 text->SetCursor(par, pos);
3945 text->sel_cursor = text->cursor;
3958 bool Buffer::isDepClean(string const & name) const
3960 DEPCLEAN* item = dep_clean;
3961 while (item && item->master != name)
3963 if (!item) return true;
3968 void Buffer::markDepClean(string const & name)
3971 dep_clean = new DEPCLEAN;
3972 dep_clean->clean = true;
3973 dep_clean->master = name;
3974 dep_clean->next = 0;
3976 DEPCLEAN* item = dep_clean;
3977 while (item && item->master != name)
3982 item = new DEPCLEAN;
3984 item->master = name;
3988 //return false; // why use that in a void method??