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 par->text.reserve(500);
285 text->BreakParagraph();
286 return_par = text->FirstParagraph();
289 // We don't want to adopt the parameters from the
290 // document we insert, so we skip until the text begins:
293 pretoken = lex.GetString();
294 if (pretoken == "\\layout") {
306 pretoken = lex.GetString();
309 // Profiling show this should give a lot: (Asger)
310 string const token = pretoken;
314 else if (token[0] != '\\') {
315 int n = token.length();
316 for (int i=0; i < n; i++) {
317 par->InsertChar(pos, token[i]);
318 par->SetFont(pos, font);
321 } else if (token == "\\i") {
322 inset = new InsetLatexAccent;
324 par->InsertChar(pos, LYX_META_INSET);
326 par->InsertInset(pos, inset);
327 par->SetFont(pos, font);
329 } else if (token == "\\layout") {
334 par->text.resize(par->text.size());
336 par = new LyXParagraph(par);
338 par->text.reserve(500);
343 string layoutname = lex.GetString();
344 pair<bool, LyXTextClass::LayoutList::size_type> pp
345 = textclasslist.NumberOfLayout(params.textclass,
348 par->layout = pp.second;
349 } else { // layout not found
350 // use default layout "Standard" (0)
353 // Test whether the layout is obsolete.
354 LyXLayout const & layout = textclasslist.Style(params.textclass,
356 if (!layout.obsoleted_by().empty())
358 textclasslist.NumberOfLayout(params.textclass,
359 layout.obsoleted_by()).second;
360 par->footnoteflag = footnoteflag;
361 par->footnotekind = footnotekind;
363 font = LyXFont(LyXFont::ALL_INHERIT);
364 } else if (token == "\\end_float") {
369 par->text.resize(par->text.size());
371 par = new LyXParagraph(par);
373 par->text.reserve(500);
376 footnotekind = LyXParagraph::FOOTNOTE;
377 footnoteflag = LyXParagraph::NO_FOOTNOTE;
380 par->layout = LYX_DUMMY_LAYOUT;
381 font = LyXFont(LyXFont::ALL_INHERIT);
382 } else if (token == "\\begin_float") {
383 tmpret = lex.FindToken(string_footnotekinds);
384 if (tmpret == -1) tmpret++;
385 if (tmpret != LYX_LAYOUT_DEFAULT)
386 footnotekind = (LyXParagraph::footnote_kind)tmpret; // bad
387 if (footnotekind == LyXParagraph::FOOTNOTE
388 || footnotekind == LyXParagraph::MARGIN)
389 footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
391 footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
392 } else if (token == "\\begin_deeper") {
394 } else if (token == "\\end_deeper") {
396 lex.printError("\\end_deeper: "
397 "depth is already null");
401 } else if (token == "\\begin_preamble") {
402 params.readPreamble(lex);
403 } else if (token == "\\textclass") {
405 pair<bool, LyXTextClassList::ClassList::size_type> pp =
406 textclasslist.NumberOfClass(lex.GetString());
408 params.textclass = pp.second;
410 lex.printError("Unknown textclass `$$Token'");
411 params.textclass = 0;
413 if (!textclasslist.Load(params.textclass)) {
414 // if the textclass wasn't loaded properly
415 // we need to either substitute another
416 // or stop loading the file.
417 // I can substitute but I don't see how I can
418 // stop loading... ideas?? ARRae980418
419 WriteAlert(_("Textclass Loading Error!"),
420 string(_("Can't load textclass ")) +
421 textclasslist.NameOfClass(params.textclass),
422 _("-- substituting default"));
423 params.textclass = 0;
425 } else if (token == "\\options") {
427 params.options = lex.GetString();
428 } else if (token == "\\language") {
429 params.readLanguage(lex);
430 } else if (token == "\\fontencoding") {
432 } else if (token == "\\inputencoding") {
434 params.inputenc = lex.GetString();
435 } else if (token == "\\graphics") {
436 params.readGraphicsDriver(lex);
437 } else if (token == "\\fontscheme") {
439 params.fonts = lex.GetString();
440 } else if (token == "\\noindent") {
441 par->noindent = true;
442 } else if (token == "\\fill_top") {
443 par->added_space_top = VSpace(VSpace::VFILL);
444 } else if (token == "\\fill_bottom") {
445 par->added_space_bottom = VSpace(VSpace::VFILL);
446 } else if (token == "\\line_top") {
447 par->line_top = true;
448 } else if (token == "\\line_bottom") {
449 par->line_bottom = true;
450 } else if (token == "\\pagebreak_top") {
451 par->pagebreak_top = true;
452 } else if (token == "\\pagebreak_bottom") {
453 par->pagebreak_bottom = true;
454 } else if (token == "\\start_of_appendix") {
455 par->start_of_appendix = true;
456 } else if (token == "\\paragraph_separation") {
457 tmpret = lex.FindToken(string_paragraph_separation);
458 if (tmpret == -1) tmpret++;
459 if (tmpret != LYX_LAYOUT_DEFAULT)
460 params.paragraph_separation = tmpret;
461 } else if (token == "\\defskip") {
463 params.defskip = VSpace(lex.GetString());
464 } else if (token == "\\no_isolatin1") {
466 } else if (token == "\\no_babel") {
468 } else if (token == "\\no_epsfig") {
470 } else if (token == "\\epsfig") { // obsolete
471 // Indeed it is obsolete, but we HAVE to be backwards
472 // compatible until 0.14, because otherwise all figures
473 // in existing documents are irretrivably lost. (Asger)
474 params.readGraphicsDriver(lex);
475 } else if (token == "\\quotes_language") {
476 tmpret = lex.FindToken(string_quotes_language);
477 if (tmpret == -1) tmpret++;
478 if (tmpret != LYX_LAYOUT_DEFAULT) {
479 InsetQuotes::quote_language tmpl =
480 InsetQuotes::EnglishQ;
483 tmpl = InsetQuotes::EnglishQ;
486 tmpl = InsetQuotes::SwedishQ;
489 tmpl = InsetQuotes::GermanQ;
492 tmpl = InsetQuotes::PolishQ;
495 tmpl = InsetQuotes::FrenchQ;
498 tmpl = InsetQuotes::DanishQ;
501 params.quotes_language = tmpl;
503 } else if (token == "\\quotes_times") {
505 switch(lex.GetInteger()) {
507 params.quotes_times = InsetQuotes::SingleQ;
510 params.quotes_times = InsetQuotes::DoubleQ;
513 } else if (token == "\\papersize") {
515 tmpret = lex.FindToken(string_papersize);
517 tmpret = lex.FindToken(string_oldpapersize);
521 params.papersize2 = tmpret;
522 } else if (token == "\\paperpackage") {
523 tmpret = lex.FindToken(string_paperpackages);
526 params.paperpackage = PACKAGE_NONE;
528 params.paperpackage = tmpret;
529 } else if (token == "\\use_geometry") {
531 params.use_geometry = lex.GetInteger();
532 } else if (token == "\\use_amsmath") {
534 params.use_amsmath = lex.GetInteger();
535 } else if (token == "\\paperorientation") {
536 tmpret = lex.FindToken(string_orientation);
537 if (tmpret == -1) tmpret++;
538 if (tmpret != LYX_LAYOUT_DEFAULT)
539 params.orientation = tmpret;
540 } else if (token == "\\paperwidth") {
542 params.paperwidth = lex.GetString();
543 } else if (token == "\\paperheight") {
545 params.paperheight = lex.GetString();
546 } else if (token == "\\leftmargin") {
548 params.leftmargin = lex.GetString();
549 } else if (token == "\\topmargin") {
551 params.topmargin = lex.GetString();
552 } else if (token == "\\rightmargin") {
554 params.rightmargin = lex.GetString();
555 } else if (token == "\\bottommargin") {
557 params.bottommargin = lex.GetString();
558 } else if (token == "\\headheight") {
560 params.headheight = lex.GetString();
561 } else if (token == "\\headsep") {
563 params.headsep = lex.GetString();
564 } else if (token == "\\footskip") {
566 params.footskip = lex.GetString();
567 } else if (token == "\\paperfontsize") {
569 params.fontsize = strip(lex.GetString());
570 } else if (token == "\\papercolumns") {
572 params.columns = lex.GetInteger();
573 } else if (token == "\\papersides") {
575 switch(lex.GetInteger()) {
577 case 1: params.sides = LyXTextClass::OneSide; break;
578 case 2: params.sides = LyXTextClass::TwoSides; break;
580 } else if (token == "\\paperpagestyle") {
582 params.pagestyle = strip(lex.GetString());
583 } else if (token == "\\bullet") {
585 int index = lex.GetInteger();
587 int temp_int = lex.GetInteger();
588 params.user_defined_bullets[index].setFont(temp_int);
589 params.temp_bullets[index].setFont(temp_int);
591 temp_int = lex.GetInteger();
592 params.user_defined_bullets[index].setCharacter(temp_int);
593 params.temp_bullets[index].setCharacter(temp_int);
595 temp_int = lex.GetInteger();
596 params.user_defined_bullets[index].setSize(temp_int);
597 params.temp_bullets[index].setSize(temp_int);
599 string temp_str = lex.GetString();
600 if (temp_str != "\\end_bullet") {
601 // this element isn't really necessary for
602 // parsing but is easier for humans
603 // to understand bullets. Put it back and
604 // set a debug message?
605 lex.printError("\\end_bullet expected, got" + temp_str);
606 //how can I put it back?
608 } else if (token == "\\bulletLaTeX") {
610 int index = lex.GetInteger();
612 string temp_str = lex.GetString(), sum_str;
613 while (temp_str != "\\end_bullet") {
614 // this loop structure is needed when user
615 // enters an empty string since the first
616 // thing returned will be the \\end_bullet
618 // if the LaTeX entry has spaces. Each element
619 // therefore needs to be read in turn
622 temp_str = lex.GetString();
624 params.user_defined_bullets[index].setText(sum_str);
625 params.temp_bullets[index].setText(sum_str);
626 } else if (token == "\\secnumdepth") {
628 params.secnumdepth = lex.GetInteger();
629 } else if (token == "\\tocdepth") {
631 params.tocdepth = lex.GetInteger();
632 } else if (token == "\\baselinestretch") { // now obsolete
633 lex.nextToken(); // should not be used directly
635 // Will probably keep a kind of support just for
637 params.spacing.set(Spacing::Other, lex.GetFloat());
638 } else if (token == "\\spacing") {
640 string tmp = strip(lex.GetString());
641 if (tmp == "single") {
642 params.spacing.set(Spacing::Single);
643 } else if (tmp == "onehalf") {
644 params.spacing.set(Spacing::Onehalf);
645 } else if (tmp == "double") {
646 params.spacing.set(Spacing::Double);
647 } else if (tmp == "other") {
649 params.spacing.set(Spacing::Other,
652 lex.printError("Unknown spacing token: '$$Token'");
654 } else if (token == "\\float_placement") {
656 params.float_placement = lex.GetString();
657 } else if (token == "\\cursor") {
658 // this is obsolete, so we just skip it.
660 } else if (token == "\\family") {
662 font.setLyXFamily(lex.GetString());
663 } else if (token == "\\series") {
665 font.setLyXSeries(lex.GetString());
666 } else if (token == "\\shape") {
668 font.setLyXShape(lex.GetString());
669 } else if (token == "\\size") {
671 font.setLyXSize(lex.GetString());
672 } else if (token == "\\latex") {
674 string tok = lex.GetString();
675 // This is dirty, but gone with LyX3. (Asger)
676 if (tok == "no_latex")
677 font.setLatex(LyXFont::OFF);
678 else if (tok == "latex")
679 font.setLatex(LyXFont::ON);
680 else if (tok == "default")
681 font.setLatex(LyXFont::INHERIT);
683 lex.printError("Unknown LaTeX font flag "
685 } else if (token == "\\emph") {
687 font.setEmph(font.setLyXMisc(lex.GetString()));
688 } else if (token == "\\bar") {
690 string tok = lex.GetString();
691 // This is dirty, but gone with LyX3. (Asger)
693 font.setUnderbar(LyXFont::ON);
694 else if (tok == "no")
695 font.setUnderbar(LyXFont::OFF);
696 else if (tok == "default")
697 font.setUnderbar(LyXFont::INHERIT);
699 lex.printError("Unknown bar font flag "
701 } else if (token == "\\noun") {
703 font.setNoun(font.setLyXMisc(lex.GetString()));
704 } else if (token == "\\color") {
706 font.setLyXColor(lex.GetString());
707 } else if (token == "\\align") {
708 tmpret = lex.FindToken(string_align);
709 if (tmpret == -1) tmpret++;
710 if (tmpret != LYX_LAYOUT_DEFAULT) {
712 for (; tmpret>0; tmpret--)
713 tmpret2 = tmpret2 * 2;
714 par->align = LyXAlignment(tmpret2);
716 } else if (token == "\\added_space_top"){
718 par->added_space_top = lex.GetString();
719 } else if (token == "\\added_space_bottom") {
721 par->added_space_bottom = lex.GetString();
722 } else if (token == "\\pextra_type") {
724 par->pextra_type = lex.GetInteger();
725 } else if (token == "\\pextra_width") {
727 par->pextra_width = lex.GetString();
728 } else if (token == "\\pextra_widthp") {
730 par->pextra_widthp = lex.GetString();
731 } else if (token == "\\pextra_alignment") {
733 par->pextra_alignment = lex.GetInteger();
734 } else if (token == "\\pextra_hfill") {
736 par->pextra_hfill = lex.GetInteger();
737 } else if (token == "\\pextra_start_minipage") {
739 par->pextra_start_minipage = lex.GetInteger();
740 } else if (token == "\\labelwidthstring") {
742 par->labelwidthstring = lex.GetString();
743 /* do not delete this token, it is still needed! */
744 } else if (token == "\\end_inset") {
745 /* simple ignore this. The insets do not have
747 // but insets should read it, it is a part of
748 //the inset isn't it? Lgb.
749 } else if (token == "\\begin_inset") {
751 tmptok = lex.GetString();
752 /* test the different insets */
753 if (tmptok == "Quotes") {
754 inset = new InsetQuotes;
756 par->InsertChar(pos, LYX_META_INSET);
757 par->InsertInset(pos, inset);
758 par->SetFont(pos, font);
760 } else if (tmptok == "Latex") {
761 // This one is on its way out
763 tmptok = strip(lex.GetString());
764 //lyxerr <<string(tmptok[0]));
765 if (tmptok[0] == '\\') {
766 // then this latex is a
768 InsetCommand *tmpinset =
770 tmpinset->scanCommand(tmptok);
773 // This should not use InsetLaTexDel
774 // it should rather insert text into
775 // the paragraph and mark it as tex.
776 inset = new InsetLatex(tmptok);
778 par->InsertChar(pos, LYX_META_INSET);
779 par->InsertInset(pos, inset);
780 par->SetFont(pos, font);
782 } else if (tmptok == "LatexDel") {
783 // This one is on its way out...
785 tmptok = strip(lex.GetString());
786 //lyxerr <<string(tmptok[0]));
787 if (tmptok == "\\tableofcontents") {
788 inset = new InsetTOC(this);
789 } else if (tmptok == "\\listoffigures") {
790 inset = new InsetLOF(this);
791 } else if (tmptok == "\\listoftables") {
792 inset = new InsetLOT(this);
793 } else if (tmptok == "\\listofalgorithms") {
794 inset = new InsetLOA(this);
795 } else if (contains(tmptok, "\\ref{")
796 || contains(tmptok, "\\pageref{")) {
797 inset = new InsetRef(tmptok, this);
798 } else if (contains(tmptok, "\\url{")
799 || contains(tmptok, "\\htmlurl{")) {
800 string cont,opt,tmptmptok,cmdname;
802 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
807 tmptmptok=lex.GetString();
808 if(tmptmptok[0] == '\\') {
809 if( tmptmptok == "\\backslash")
819 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
824 tmptmptok=lex.GetString();
825 if(tmptmptok[0] == '\\') {
826 if( tmptmptok == "\\backslash")
836 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
839 if(contains(tmptok, "\\url{"))
840 cmdname = string("url");
842 cmdname = string("htmlurl");
845 inset = new InsetUrl(cmdname,cont,opt);
846 } else if (tmptok[0] == '\\') {
847 // then this latex del is a
849 InsetCommand *tmpinset =
851 tmpinset->scanCommand(tmptok);
854 par->InsertChar(pos, LYX_META_INSET);
855 par->InsertInset(pos, inset);
856 par->SetFont(pos, font);
858 } else if (tmptok == "\\i") {
859 inset = new InsetLatexAccent;
861 par->InsertChar(pos, LYX_META_INSET);
862 par->InsertInset(pos, inset);
863 par->SetFont(pos, font);
865 } else if (tmptok == "FormulaMacro") {
866 inset = new InsetFormulaMacro;
868 par->InsertChar(pos, LYX_META_INSET);
869 par->InsertInset(pos, inset);
870 par->SetFont(pos, font);
872 } else if (tmptok == "Formula") {
873 inset = new InsetFormula;
875 par->InsertChar(pos, LYX_META_INSET);
876 par->InsertInset(pos, inset);
877 par->SetFont(pos, font);
879 } else if (tmptok == "Figure") {
880 inset = new InsetFig(100,100, this);
882 par->InsertChar(pos, LYX_META_INSET);
883 par->InsertInset(pos, inset);
884 par->SetFont(pos, font);
886 } else if (tmptok == "Label") {
887 // Kept for compability. Remove in 0.13.
889 string tmp = "\\label{";
890 tmp += lex.GetString();
892 inset = new InsetLabel(tmp);
893 par->InsertChar(pos, LYX_META_INSET);
894 par->InsertInset(pos, inset);
895 par->SetFont(pos, font);
898 } else if (tmptok == "Info") {
899 inset = new InsetInfo;
901 par->InsertChar(pos, LYX_META_INSET);
902 par->InsertInset(pos, inset);
903 par->SetFont(pos, font);
905 } else if (tmptok == "Include") {
906 inset = new InsetInclude(string(), this);
908 par->InsertChar(pos, LYX_META_INSET);
909 par->InsertInset(pos, inset);
910 par->SetFont(pos, font);
912 } else if (tmptok == "LatexCommand") {
915 if (inscmd.getCmdName()=="cite") {
916 inset = new InsetCitation(inscmd.getContents(), inscmd.getOptions());
917 } else if (inscmd.getCmdName()=="bibitem") {
918 lex.printError("Wrong place for bibitem");
919 inset = inscmd.Clone();
920 } else if (inscmd.getCmdName()=="BibTeX") {
921 inset = new InsetBibtex(inscmd.getContents(), inscmd.getOptions(), this);
922 } else if (inscmd.getCmdName()=="index") {
923 inset = new InsetIndex(inscmd.getContents());
924 } else if (inscmd.getCmdName()=="include") {
925 inset = new InsetInclude(inscmd.getContents(), this);
926 } else if (inscmd.getCmdName()=="label") {
927 inset = new InsetLabel(inscmd.getCommand());
928 } else if (inscmd.getCmdName()=="url"
929 || inscmd.getCmdName()=="htmlurl") {
930 inset = new InsetUrl(inscmd.getCommand());
931 } else if (inscmd.getCmdName() == "ref"
932 || inscmd.getCmdName() == "pageref") {
933 if (!inscmd.getOptions().empty() || !inscmd.getContents().empty()) {
934 inset = new InsetRef(inscmd, this);
936 /* This condition comes from a temporary solution
937 to the latexdel ref inset that was transformed to an empty ref
938 inset plus the body surronded by latexdel insets */
940 string cont,opt,tmptmptok,cmdname;
942 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
947 tmptmptok=lex.GetString();
948 if(tmptmptok[0] == '\\') {
949 if( tmptmptok == "\\backslash")
959 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
964 tmptmptok=lex.GetString();
965 if(tmptmptok[0] == '\\') {
966 if( tmptmptok == "\\backslash")
976 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
982 cmdname = "\\" + inscmd.getCmdName();
983 cmdname += "[" + cont + "]";
984 cmdname += "{" + opt + "}";
985 inset = new InsetRef(cmdname,this);
987 } else if (inscmd.getCmdName()=="tableofcontents") {
988 inset = new InsetTOC(this);
989 } else if (inscmd.getCmdName()=="listoffigures") {
990 inset = new InsetLOF(this);
991 } else if (inscmd.getCmdName()=="listofalgorithms") {
992 inset = new InsetLOA(this);
993 } else if (inscmd.getCmdName()=="listoftables") {
994 inset = new InsetLOT(this);
995 } else if (inscmd.getCmdName()=="printindex") {
996 inset = new InsetPrintIndex(this);
997 } else if (inscmd.getCmdName()=="lyxparent") {
998 inset = new InsetParent(inscmd.getContents(),this);
1000 // The following three are only for compatibility
1001 if (inscmd.getCmdName()=="-") {
1002 inset = new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
1003 } else if (inscmd.getCmdName()=="@.") {
1004 inset = new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
1005 } else if (inscmd.getCmdName()=="ldots") {
1006 inset = new InsetSpecialChar(InsetSpecialChar::LDOTS);
1008 inset = inscmd.Clone();
1011 par->InsertChar(pos, LYX_META_INSET);
1012 par->InsertInset(pos, inset);
1013 par->SetFont(pos, font);
1017 } else if (token == "\\InsetQuotes") {
1018 inset = new InsetQuotes;
1020 par->InsertChar(pos, LYX_META_INSET);
1021 par->InsertInset(pos, inset);
1022 par->SetFont(pos, font);
1024 } else if (token == "\\InsetLatex") {
1025 inset = new InsetLatex;
1027 par->InsertChar(pos, LYX_META_INSET);
1028 par->InsertInset(pos, inset);
1029 par->SetFont(pos, font);
1031 } else if (token == "\\InsetLatexDel") {
1032 lex.printError(_("Warning: Ignoring Old Inset"));
1033 } else if (token == "\\InsetFormula") {
1034 inset = new InsetFormula;
1036 par->InsertChar(pos, LYX_META_INSET);
1037 par->InsertInset(pos, inset);
1038 par->SetFont(pos, font);
1040 } else if (token == "\\SpecialChar") {
1041 inset = new InsetSpecialChar;
1043 par->InsertChar(pos, LYX_META_INSET);
1044 par->InsertInset(pos, inset);
1045 par->SetFont(pos, font);
1047 } else if (token == "\\Figure") {
1048 inset = new InsetFig(100,100, this);
1050 par->InsertChar(pos, LYX_META_INSET);
1051 par->InsertInset(pos, inset);
1052 par->SetFont(pos, font);
1054 } else if (token == "\\newline") {
1055 par->InsertChar(pos, LYX_META_NEWLINE);
1056 par->SetFont(pos, font);
1058 } else if (token == "\\LyXTable") {
1059 par->table = new LyXTable(lex);
1060 } else if (token == "\\hfill") {
1061 par->InsertChar(pos, LYX_META_HFILL);
1062 par->SetFont(pos, font);
1064 } else if (token == "\\protected_separator") {
1065 par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
1066 par->SetFont(pos, font);
1068 } else if (token == "\\bibitem") { // ale970302
1070 par->bibkey = new InsetBibKey;
1071 par->bibkey->Read(lex);
1072 }else if (token == "\\backslash") {
1073 par->InsertChar(pos, '\\');
1074 par->SetFont(pos, font);
1076 }else if (token == "\\the_end") {
1077 the_end_read = true;
1079 // This should be insurance for the future: (Asger)
1080 lex.printError("Unknown token `$$Token'. "
1081 "Inserting as text.");
1082 int n = token.length();
1083 for (int i=0; i < n; i++) {
1084 par->InsertChar(pos, token[i]);
1085 par->SetFont(pos, font);
1094 paragraph = return_par;
1096 return the_end_read;
1100 bool Buffer::readFile(LyXLex & lex, LyXParagraph * par)
1106 token = lex.GetString();
1107 if (token == "\\lyxformat") { // the first token _must_ be...
1109 format = lex.GetFloat();
1111 if (LYX_FORMAT - format > 0.05) {
1112 printf(_("Warning: need lyxformat %.2f but found %.2f\n"),
1113 LYX_FORMAT, format);
1115 if (format - LYX_FORMAT > 0.05) {
1116 printf(_("ERROR: need lyxformat %.2f but found %.2f\n"),
1117 LYX_FORMAT, format);
1119 bool the_end = readLyXformat2(lex, par);
1120 // Formats >= 2.13 support "\the_end" marker
1123 // Formats >= 2.14 changed papersize stuff
1124 if (format < 2.14) {
1130 WriteAlert(_("Warning!"),
1131 _("Reading of document is not complete"),
1132 _("Maybe the document is truncated"));
1133 // We simulate a safe reading anyways to allow
1134 // users to take the chance... (Asger)
1138 WriteAlert(_("ERROR!"),
1139 _("Old LyX file format found. "
1140 "Use LyX 0.10.x to read this!"));
1144 } else { // "\\lyxformat" not found
1145 WriteAlert(_("ERROR!"), _("Not a LyX file!"));
1148 WriteAlert(_("ERROR!"), _("Unable to read file!"));
1153 // Returns false if unsuccesful
1154 bool Buffer::writeFile(string const & filename, bool flag)
1156 // if flag is false writeFile will not create any GUI
1157 // warnings, only cerr.
1158 // Needed for autosave in background or panic save (Matthias 120496)
1160 if (read_only && (filename == this->filename)) {
1161 // Here we should come with a question if we should
1162 // perform the write anyway.
1164 lyxerr << _("Error! Document is read-only: ")
1165 << filename << endl;
1167 WriteAlert(_("Error! Document is read-only: "), filename);
1171 FileInfo finfo(filename);
1172 if (finfo.exist() && !finfo.writable()) {
1173 // Here we should come with a question if we should
1174 // try to do the save anyway. (i.e. do a chmod first)
1176 lyxerr << _("Error! Cannot write file: ")
1177 << filename << endl;
1179 WriteFSAlert(_("Error! Cannot write file: "), filename);
1183 FilePtr file(filename, FilePtr::truncate);
1186 lyxerr << _("Error! Cannot write file: ")
1187 << filename << endl;
1189 WriteFSAlert(_("Error! Cannot write file: "), filename);
1192 // The top of the file should not be written by params.
1193 // collect some very important information
1194 string userName(getUserName()) ;
1196 // write out a comment in the top of the file
1198 "#This file was created by <%s> %s",
1199 userName.c_str(),(char*)date());
1201 "#LyX 1.0 (C) 1995-1999 Matthias Ettrich"
1202 " and the LyX Team\n");
1204 // at the very beginning the used lyx format
1205 fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
1207 // now write out the buffer parameters.
1208 params.writeFile(file);
1210 char footnoteflag = 0;
1213 // this will write out all the paragraphs
1214 // using recursive descent.
1215 paragraph->writeFile(file, params, footnoteflag, depth);
1217 // Write marker that shows file is complete
1218 fprintf(file, "\n\\the_end\n");
1221 lyxerr << _("Error! Could not close file properly: ")
1222 << filename << endl;
1224 WriteFSAlert(_("Error! Could not close file properly: "),
1232 void Buffer::writeFileAscii(string const & filename, int linelen)
1234 FilePtr file(filename, FilePtr::write);
1238 LyXParagraph * par = paragraph;
1249 LyXParagraph::size_type i;
1268 ref_printed = false;
1272 WriteFSAlert(_("Error: Cannot write file:"), filename);
1275 fname1=TmpFileName();
1279 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE ||
1281 par->previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
1283 /* begins a footnote environment ? */
1284 if (footnoteflag != par->footnoteflag) {
1285 footnoteflag = par->footnoteflag;
1287 j=strlen(string_footnotekinds[par->footnotekind])+4;
1288 if (currlinelen+j > linelen)
1290 fprintf(file, "([%s] ",
1291 string_footnotekinds[par->footnotekind]);
1296 /* begins or ends a deeper area ?*/
1297 if (depth != par->depth) {
1298 if (par->depth > depth) {
1299 while (par->depth > depth) {
1304 while (par->depth < depth) {
1310 /* First write the layout */
1311 tmp = textclasslist.NameOfLayout(params.textclass,par->layout);
1312 if (tmp == "Itemize") {
1314 ltype_depth = depth+1;
1315 } else if (tmp =="Enumerate") {
1317 ltype_depth = depth+1;
1318 } else if (strstr(tmp.c_str(),"ection")) {
1320 ltype_depth = depth+1;
1321 } else if (strstr(tmp.c_str(),"aragraph")) {
1323 ltype_depth = depth+1;
1324 } else if (tmp == "Description") {
1326 ltype_depth = depth+1;
1327 } else if (tmp == "Abstract") {
1330 } else if (tmp == "Bibliography") {
1338 /* maybe some vertical spaces */
1340 /* the labelwidthstring used in lists */
1344 /* some pagebreaks? */
1348 /* what about the alignment */
1351 /* dummy layout, that means a footnote ended */
1352 footnoteflag = LyXParagraph::NO_FOOTNOTE;
1353 fprintf(file, ") ");
1357 /* It might be a table */
1359 if (!lyxrc->ascii_roff_command.empty() &&
1360 lyxrc->ascii_roff_command != "none") {
1361 RoffAsciiTable(file,par);
1367 cells = par->table->columns;
1368 clen = new int [cells];
1369 memset(clen,0,sizeof(int)*cells);
1371 for (i = 0, j = 0, h = 1; i < par->size(); ++i, ++h) {
1373 for (i = 0, j = 0, h=1; i < par->last; i++, h++) {
1375 c = par->GetChar(i);
1376 if (c == LYX_META_INSET) {
1377 if ((inset = par->GetInset(i))) {
1381 WriteFSAlert(_("Error: Cannot open temporary file:"), fname1);
1384 inset->Latex(fp,-1);
1386 remove(fname1.c_str());
1388 } else if (c == LYX_META_NEWLINE) {
1392 j = (++j) % par->table->NumberOfCellsInRow(actcell);
1400 font1 = LyXFont(LyXFont::ALL_INHERIT);
1403 for (i = 0, actpos = 1; i < par->size(); ++i, ++actpos) {
1405 for (i = 0,actpos=1; i < par->last; i++, actpos++) {
1407 if (!i && !footnoteflag && !noparbreak){
1408 fprintf(file, "\n\n");
1409 for(j=0; j<depth; j++)
1411 currlinelen = depth*2;
1413 case 0: /* Standart */
1414 case 4: /* (Sub)Paragraph */
1415 case 5: /* Description */
1417 case 6: /* Abstract */
1418 fprintf(file, "Abstract\n\n");
1420 case 7: /* Bibliography */
1422 fprintf(file, "References\n\n");
1427 fprintf(file,"%s ",par->labelstring.c_str());
1430 if (ltype_depth > depth) {
1431 for(j=ltype_depth-1; j>depth; j--)
1433 currlinelen += (ltype_depth-depth)*2;
1436 for(j=0;j<cells;j++) {
1438 for(h=0; h<(clen[j]+1); h++)
1441 fprintf(file,"+\n");
1442 for(j=0; j<depth; j++)
1444 currlinelen = depth*2;
1445 if (ltype_depth > depth) {
1446 for(j=ltype_depth; j>depth; j--)
1448 currlinelen += (ltype_depth-depth)*2;
1453 font2 = par->GetFontSettings(i);
1454 if (font1.latex() != font2.latex()) {
1455 if (font2.latex() == LyXFont::OFF)
1463 c = par->GetChar(i);
1467 case LYX_META_INSET:
1468 if ((inset = par->GetInset(i))) {
1470 inset->Latex(file,-1);
1471 currlinelen += (ftell(file) - fpos);
1472 actpos += (ftell(file) - fpos) - 1;
1475 case LYX_META_NEWLINE:
1477 if (par->table->NumberOfCellsInRow(actcell) <= cell) {
1478 for(j=actpos;j<clen[cell-1];j++)
1480 fprintf(file," |\n");
1481 for(j=0; j<depth; j++)
1483 currlinelen = depth*2;
1484 if (ltype_depth > depth) {
1485 for(j=ltype_depth; j>depth; j--)
1487 currlinelen += (ltype_depth-depth)*2;
1489 for(j=0;j<cells;j++) {
1491 for(h=0; h<(clen[j]+1); h++)
1494 fprintf(file,"+\n");
1495 for(j=0; j<depth; j++)
1497 currlinelen = depth*2;
1498 if (ltype_depth > depth) {
1499 for(j=ltype_depth; j>depth; j--)
1501 currlinelen += (ltype_depth-depth)*2;
1506 for(j=actpos; j<clen[cell-1]; j++)
1508 fprintf(file, " | ");
1512 currlinelen = actpos = 0;
1514 fprintf(file, "\n");
1515 for(j=0; j<depth; j++)
1517 currlinelen = depth*2;
1518 if (ltype_depth > depth) {
1519 for(j=ltype_depth; j>depth; j--)
1521 currlinelen += (ltype_depth-depth)*2;
1525 case LYX_META_HFILL:
1526 fprintf(file, "\t");
1528 case LYX_META_PROTECTED_SEPARATOR:
1532 fprintf(file, "\\");
1536 if (currlinelen > linelen - 10
1537 && c == ' ' && i + 2 < par->size()) {
1539 if (currlinelen > (linelen-10) \
1540 && c==' ' && (i+2 < par->last)) {
1542 fprintf(file, "\n");
1543 for(j = 0; j < depth; ++j)
1545 currlinelen = depth * 2;
1546 if (ltype_depth > depth) {
1547 for(j = ltype_depth;
1550 currlinelen += (ltype_depth-depth)*2;
1552 } else if (c != '\0')
1553 fprintf(file, "%c", c);
1555 lyxerr.debug() << "writeAsciiFile: NULL char in structure." << endl;
1561 for(j=actpos;j<clen[cell-1];j++)
1563 fprintf(file," |\n");
1564 for(j=0; j<depth; j++)
1566 currlinelen = depth*2;
1567 if (ltype_depth > depth) {
1568 for(j=ltype_depth; j>depth; j--)
1570 currlinelen += (ltype_depth-depth)*2;
1572 for(j=0;j<cells;j++) {
1574 for(h=0; h<(clen[j]+1); h++)
1577 fprintf(file,"+\n");
1583 fprintf(file, "\n");
1587 void Buffer::makeLaTeXFile(string const & filename,
1588 string const & original_path,
1589 bool nice, bool only_body)
1591 lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
1592 params.textclass = GetCurrentTextClass();
1593 niceFile = nice; // this will be used by Insetincludes.
1595 tex_code_break_column = lyxrc->ascii_linelen;
1597 LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
1599 FilePtr file(filename, FilePtr::write);
1601 WriteFSAlert(_("Error: Cannot write file:"),filename);
1605 // validate the buffer.
1606 lyxerr[Debug::LATEX] << " Validating buffer..." << endl;
1607 LaTeXFeatures features(tclass.numLayouts());
1609 lyxerr[Debug::LATEX] << " Buffer validation done." << endl;
1612 // The starting paragraph of the coming rows is the
1613 // first paragraph of the document. (Asger)
1614 texrow.start(paragraph, 0);
1616 string userName(getUserName());
1619 if (!only_body && nice) {
1620 LFile += "%% This LaTeX-file was created by <";
1621 LFile += userName + "> " + (char*)date();
1622 LFile += "%% LyX 1.0 (C) 1995-1999 by Matthias Ettrich and the LyX Team\n";
1623 LFile += "\n%% Do not edit this file unless you know what you are doing.\n";
1629 lyxerr.debug() << "lyx header finished" << endl;
1630 // There are a few differences between nice LaTeX and usual files:
1631 // usual is \batchmode, uses \listfiles and has a
1632 // special input@path to allow the including of figures
1633 // with either \input or \includegraphics (what figinsets do).
1634 // batchmode is not set if there is a tex_code_break_column.
1635 // In this case somebody is interested in the generated LaTeX,
1636 // so this is OK. input@path is set when the actual parameter
1637 // original_path is set. This is done for usual tex-file, but not
1638 // for nice-latex-file. (Matthias 250696)
1641 // code for usual, NOT nice-latex-file
1642 LFile += "\\batchmode\n"; // changed
1643 // from \nonstopmode
1645 // We don't need listfiles anymore
1646 //LFile += "\\listfiles\n";
1649 if (!original_path.empty()) {
1650 LFile += "\\makeatletter\n";
1652 LFile += "\\def\\input@path{{" + original_path
1655 LFile += "\\makeatother\n";
1659 LFile += "\\documentclass";
1661 string options; // the document class options.
1663 if (tokenPos(tclass.opt_fontsize(), '|',params.fontsize) >= 0) {
1664 // only write if existing in list (and not default)
1665 options += params.fontsize;
1670 if (!params.use_geometry &&
1671 (params.paperpackage == PACKAGE_NONE)) {
1672 switch (params.papersize) {
1674 options += "a4paper,";
1676 case PAPER_USLETTER:
1677 options += "letterpaper,";
1680 options += "a5paper,";
1683 options += "b5paper,";
1685 case PAPER_EXECUTIVEPAPER:
1686 options += "executivepaper,";
1688 case PAPER_LEGALPAPER:
1689 options += "legalpaper,";
1695 if (params.sides != tclass.sides()) {
1696 if (params.sides == 2)
1697 options += "twoside,";
1699 options += "oneside,";
1703 if (params.columns != tclass.columns()) {
1704 if (params.columns == 2)
1705 options += "twocolumn,";
1707 options += "onecolumn,";
1710 if (!params.use_geometry && params.orientation == ORIENTATION_LANDSCAPE)
1711 options += "landscape,";
1713 // language should be a parameter to \documentclass
1714 if (params.language != "default") {
1715 options += params.language + ',';
1718 // the user-defined options
1719 if (!params.options.empty()) {
1720 options += params.options + ',';
1723 if (!options.empty()){
1724 options = strip(options, ',');
1731 LFile += textclasslist.LatexnameOfClass(params.textclass);
1734 // end of \documentclass defs
1736 // font selection must be done before loading fontenc.sty
1737 if (params.fonts != "default") {
1738 LFile += "\\usepackage{" + params.fonts + "}\n";
1741 // this one is not per buffer
1742 if (lyxrc->fontenc != "default") {
1743 LFile += "\\usepackage[" + lyxrc->fontenc
1747 if (params.inputenc != "default") {
1748 LFile += "\\usepackage[" + params.inputenc
1753 /* at the very beginning the text parameters */
1754 if (params.paperpackage != PACKAGE_NONE) {
1755 switch (params.paperpackage) {
1757 LFile += "\\usepackage{a4}\n";
1760 case PACKAGE_A4WIDE:
1761 LFile += "\\usepackage{a4wide}\n";
1764 case PACKAGE_WIDEMARGINSA4:
1765 LFile += "\\usepackage[widemargins]{a4}\n";
1770 if (params.use_geometry) {
1771 LFile += "\\usepackage{geometry}\n";
1773 LFile += "\\geometry{verbose";
1774 if (params.orientation == ORIENTATION_LANDSCAPE)
1775 LFile += ",landscape";
1776 switch (params.papersize2) {
1777 case VM_PAPER_CUSTOM:
1778 if (!params.paperwidth.empty())
1779 LFile += ",paperwidth="
1780 + params.paperwidth;
1781 if (!params.paperheight.empty())
1782 LFile += ",paperheight="
1783 + params.paperheight;
1785 case VM_PAPER_USLETTER:
1786 LFile += ",letterpaper";
1788 case VM_PAPER_USLEGAL:
1789 LFile += ",legalpaper";
1791 case VM_PAPER_USEXECUTIVE:
1792 LFile += ",executivepaper";
1795 LFile += ",a3paper";
1798 LFile += ",a4paper";
1801 LFile += ",a5paper";
1804 LFile += ",b3paper";
1807 LFile += ",b4paper";
1810 LFile += ",b5paper";
1813 // default papersize ie VM_PAPER_DEFAULT
1814 switch (lyxrc->default_papersize) {
1815 case PAPER_DEFAULT: // keep compiler happy
1816 case PAPER_USLETTER:
1817 LFile += ",letterpaper";
1819 case PAPER_LEGALPAPER:
1820 LFile += ",legalpaper";
1822 case PAPER_EXECUTIVEPAPER:
1823 LFile += ",executivepaper";
1826 LFile += ",a3paper";
1829 LFile += ",a4paper";
1832 LFile += ",a5paper";
1835 LFile += ",b5paper";
1839 if (!params.topmargin.empty())
1840 LFile += ",tmargin=" + params.topmargin;
1841 if (!params.bottommargin.empty())
1842 LFile += ",bmargin=" + params.bottommargin;
1843 if (!params.leftmargin.empty())
1844 LFile += ",lmargin=" + params.leftmargin;
1845 if (!params.rightmargin.empty())
1846 LFile += ",rmargin=" + params.rightmargin;
1847 if (!params.headheight.empty())
1848 LFile += ",headheight=" + params.headheight;
1849 if (!params.headsep.empty())
1850 LFile += ",headsep=" + params.headsep;
1851 if (!params.footskip.empty())
1852 LFile += ",footskip=" + params.footskip;
1856 if (params.use_amsmath
1857 && !prefixIs(textclasslist.LatexnameOfClass(params.textclass), "ams")) {
1858 LFile += "\\usepackage{amsmath}\n";
1861 if (tokenPos(tclass.opt_pagestyle(), '|',params.pagestyle) >= 0) {
1862 if (params.pagestyle == "fancy") {
1863 LFile += "\\usepackage{fancyhdr}\n";
1866 LFile += "\\pagestyle{" + params.pagestyle + "}\n";
1870 // We try to load babel late, in case it interferes
1871 // with other packages.
1872 if (params.language != "default") {
1873 LFile += "\\usepackage{babel}\n";
1877 if (params.secnumdepth != tclass.secnumdepth()) {
1878 LFile += "\\setcounter{secnumdepth}{";
1879 LFile += tostr(params.secnumdepth);
1883 if (params.tocdepth != tclass.tocdepth()) {
1884 LFile += "\\setcounter{tocdepth}{";
1885 LFile += tostr(params.tocdepth);
1890 if (params.paragraph_separation) {
1891 switch (params.defskip.kind()) {
1892 case VSpace::SMALLSKIP:
1893 LFile += "\\setlength\\parskip{\\smallskipamount}\n";
1895 case VSpace::MEDSKIP:
1896 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1898 case VSpace::BIGSKIP:
1899 LFile += "\\setlength\\parskip{\\bigskipamount}\n";
1901 case VSpace::LENGTH:
1902 LFile += "\\setlength\\parskip{"
1903 + params.defskip.length().asLatexString()
1906 default: // should never happen // Then delete it.
1907 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1912 LFile += "\\setlength\\parindent{0pt}\n";
1916 // Write out what we've generated so far...and reset LFile
1917 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
1920 // Now insert the LyX specific LaTeX commands...
1921 string preamble, tmppreamble;
1923 // The optional packages;
1924 preamble = features.getPackages(params);
1926 // this might be useful...
1927 preamble += "\n\\makeatletter\n\n";
1929 // Some macros LyX will need
1930 tmppreamble = features.getMacros(params);
1932 if (!tmppreamble.empty()) {
1933 preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1934 "LyX specific LaTeX commands.\n"
1935 + tmppreamble + '\n';
1938 // the text class specific preamble
1939 tmppreamble = features.getTClassPreamble(params);
1940 if (!tmppreamble.empty()) {
1941 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1942 "Textclass specific LaTeX commands.\n"
1943 + tmppreamble + '\n';
1946 /* the user-defined preamble */
1947 if (!params.preamble.empty()) {
1948 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1949 "User specified LaTeX commands.\n"
1950 + params.preamble + '\n';
1953 preamble += "\\makeatother\n\n";
1955 // Itemize bullet settings need to be last in case the user
1956 // defines their own bullets that use a package included
1957 // in the user-defined preamble -- ARRae
1958 for (int i = 0; i < 4; ++i) {
1959 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
1960 preamble += "\\renewcommand\\labelitemi";
1962 // `i' is one less than the item to modify
1975 preamble += "[0]{" + params.user_defined_bullets[i].getText() + "}\n";
1979 for (int j = countChar(preamble, '\n'); j-- ;) {
1983 // A bit faster than printing a char at a time I think.
1984 fwrite(preamble.c_str(), sizeof(char),
1985 preamble.length(), file);
1988 LFile += "\\begin{document}\n\n";
1992 lyxerr.debug() << "preamble finished, now the body." << endl;
1994 bool was_title = false;
1995 bool already_title = false;
2001 LyXParagraph * par = paragraph;
2007 lyxerr[Debug::LATEX] << "Error in MakeLateXFile."
2009 LyXLayout const & layout = textclasslist.Style(params.textclass,
2012 if (layout.intitle) {
2013 if (already_title) {
2014 lyxerr <<"Error in MakeLatexFile: You"
2015 " should not mix title layouts"
2016 " with normal ones." << endl;
2019 } else if (was_title && !already_title) {
2020 LFile += "\\maketitle\n";
2022 already_title = true;
2025 // We are at depth 0 so we can just use
2026 // ordinary \footnote{} generation
2027 // flag this with ftcount
2029 if (layout.isEnvironment()
2030 || par->pextra_type != PEXTRA_NONE) {
2031 par = par->TeXEnvironment(LFile, texrow,
2032 ftnote, ft_texrow, ftcount);
2034 par = par->TeXOnePar(LFile, texrow,
2035 ftnote, ft_texrow, ftcount);
2038 // Write out what we've generated...and reset LFile
2041 LFile += "\\addtocounter{footnote}{-";
2042 LFile += tostr(ftcount - 1);
2046 texrow += ft_texrow;
2051 if (loop_count == 2) {
2052 // fwrite()ing every second time through the loop
2053 // gains a few extra % of speed; going higher than
2054 // 2 will slow things down again. I'll look at
2055 // LFile.length() in a future revision. ARRae
2056 fwrite(LFile.c_str(), sizeof(char),
2057 LFile.length(), file);
2063 // It might be that we only have a title in this document
2064 if (was_title && !already_title) {
2065 LFile += "\\maketitle\n";
2070 LFile += "\\end{document}\n";
2073 lyxerr[Debug::LATEX] << "makeLaTeXFile...done" << endl;
2075 lyxerr[Debug::LATEX] << "LaTeXFile for inclusion made."
2079 // Just to be sure. (Asger)
2082 // Write out what we've generated...and reset LFile
2083 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
2086 // tex_code_break_column's value is used to decide
2087 // if we are in batchmode or not (within mathed_write()
2088 // in math_write.C) so we must set it to a non-zero
2089 // value when we leave otherwise we save incorrect .lyx files.
2090 tex_code_break_column = lyxrc->ascii_linelen;
2093 WriteFSAlert(_("Error! Could not close file properly:"), filename);
2095 lyxerr.debug() << "Finished making latex file." << endl;
2099 bool Buffer::isLatex()
2101 return textclasslist.TextClass(params.textclass).outputType() == LATEX;
2105 bool Buffer::isLinuxDoc()
2107 return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC;
2111 bool Buffer::isLiterate()
2113 return textclasslist.TextClass(params.textclass).outputType() == LITERATE;
2117 bool Buffer::isDocBook()
2119 return textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2123 bool Buffer::isSGML()
2125 return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC ||
2126 textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2130 void Buffer::sgmlOpenTag(FILE * file, int depth, string const & latexname) const
2132 static char *space[] = {" "," "," "," "," "," "," ",
2135 fprintf(file, "%s<%s>\n", space[depth], latexname.c_str());
2139 void Buffer::sgmlCloseTag(FILE * file, int depth, string const & latexname) const
2141 static char *space[] = {" "," "," "," "," "," "," ",
2144 fprintf(file, "%s</%s>\n", space[depth], latexname.c_str());
2148 void Buffer::makeLinuxDocFile(string const & filename, int column)
2150 LyXParagraph * par = paragraph;
2152 string top_element=textclasslist.LatexnameOfClass(params.textclass);
2153 string environment_stack[10];
2156 int depth = 0; /* paragraph depth */
2158 FilePtr file(filename, FilePtr::write);
2159 tex_code_break_column = column;
2162 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2169 if (params.preamble.empty()) {
2170 fprintf(file, "<!doctype linuxdoc system>\n\n");
2173 fprintf(file, "<!doctype linuxdoc system \n [ %s \n]>\n\n",
2174 params.preamble.c_str() );
2177 string userName(getUserName());
2178 fprintf(file, "<!-- LinuxDoc file was created by LyX 1.0 (C) 1995-1999 ");
2179 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2181 if(params.options.empty())
2182 sgmlOpenTag(file,0,top_element);
2184 string top = top_element;
2186 top += params.options;
2187 sgmlOpenTag(file,0,top);
2191 int desc_on=0; /* description mode*/
2192 LyXLayout const & style=textclasslist.Style(GetCurrentTextClass(), par->layout);
2193 par->AutoDeleteInsets();
2195 /* treat <toc> as a special case for compatibility with old code */
2196 if (par->GetChar(0) == LYX_META_INSET) {
2197 Inset *inset = par->GetInset(0);
2198 char lyx_code = inset->LyxCode();
2199 if (lyx_code ==Inset::TOC_CODE){
2201 sgmlOpenTag(file, depth, temp);
2204 linuxDocHandleFootnote(file, par, depth);
2209 /* environment tag closing */
2210 for( ;depth > par->depth; depth--) {
2211 sgmlCloseTag(file,depth,environment_stack[depth]);
2212 environment_stack[depth].clear();
2215 /* write opening SGML tags */
2216 switch(style.latextype) {
2217 case LATEX_PARAGRAPH:
2218 if(depth == par->depth
2219 && !environment_stack[depth].empty()) {
2220 sgmlCloseTag(file,depth,environment_stack[depth]);
2221 environment_stack[depth].clear();
2225 fprintf(file,"</p>");
2227 sgmlOpenTag(file,depth,style.latexname());
2232 LinuxDocError(par, 0, _("Error : Wrong depth for LatexType Command.\n"));
2234 if (!environment_stack[depth].empty()){
2235 sgmlCloseTag(file,depth,environment_stack[depth]);
2236 fprintf(file, "</p>");
2239 environment_stack[depth].clear();
2240 sgmlOpenTag(file,depth, style.latexname());
2243 case LATEX_ENVIRONMENT:
2244 case LATEX_ITEM_ENVIRONMENT:
2245 if(depth == par->depth
2246 && environment_stack[depth] != style.latexname()
2247 && !environment_stack[depth].empty()) {
2249 sgmlCloseTag(file,depth,environment_stack[depth]);
2250 environment_stack[depth].clear();
2252 if (depth < par->depth) {
2254 environment_stack[depth].clear();
2256 if (environment_stack[depth] != style.latexname()) {
2259 sgmlOpenTag(file,depth,temp);
2261 environment_stack[depth] = style.latexname();
2262 sgmlOpenTag(file,depth,environment_stack[depth]);
2264 if(style.latextype == LATEX_ENVIRONMENT) break;
2266 desc_on =(style.labeltype == LABEL_MANUAL);
2273 sgmlOpenTag(file,depth+1,item_name);
2276 sgmlOpenTag(file, depth, style.latexname());
2281 SimpleLinuxDocOnePar(file, par, desc_on, depth);
2284 linuxDocHandleFootnote(file,par,depth);
2286 while(par && par->IsDummy());
2289 /* write closing SGML tags */
2290 switch(style.latextype) {
2292 case LATEX_ENVIRONMENT:
2293 case LATEX_ITEM_ENVIRONMENT:
2296 sgmlCloseTag(file, depth, style.latexname());
2304 /* Close open tags */
2305 for(;depth>0;depth--)
2306 sgmlCloseTag(file,depth,environment_stack[depth]);
2308 if(!environment_stack[depth].empty())
2309 sgmlCloseTag(file,depth,environment_stack[depth]);
2311 fprintf(file, "\n\n");
2312 sgmlCloseTag(file,0,top_element);
2315 WriteFSAlert(_("Error! Could not close file properly:"),
2321 void Buffer::linuxDocHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2323 string tag="footnote";
2325 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2326 sgmlOpenTag(file,depth+1,tag);
2327 SimpleLinuxDocOnePar(file, par, 0,depth+1);
2328 sgmlCloseTag(file,depth+1,tag);
2333 void Buffer::DocBookHandleCaption(FILE *file, string &inner_tag,
2334 int const depth, int desc_on,
2337 LyXParagraph *tpar = par;
2338 string tmp_par, extra_par;
2339 while (tpar && (tpar->footnoteflag != LyXParagraph::NO_FOOTNOTE) &&
2340 (tpar->layout != textclasslist.NumberOfLayout(params.textclass,"Caption").second))
2343 tpar->layout==textclasslist.NumberOfLayout(params.textclass,"Caption").second) {
2344 sgmlOpenTag(file,depth+1,inner_tag);
2345 SimpleDocBookOnePar(tmp_par,extra_par,tpar,desc_on,depth+2);
2346 tmp_par = strip(tmp_par);
2347 tmp_par = frontStrip(tmp_par);
2348 fprintf(file,"%s",tmp_par.c_str());
2349 sgmlCloseTag(file,depth+1,inner_tag);
2350 if(!extra_par.empty())
2351 fprintf(file,"%s",extra_par.c_str());
2355 void Buffer::DocBookHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2357 string tag,inner_tag;
2358 string tmp_par,extra_par;
2359 bool inner_span = false;
2362 // This is not how I like to see enums. They should not be anonymous
2363 // and variables of its type should not be declared right after the
2364 // last brace. (Lgb)
2371 } last=NO_ONE, present=FOOTNOTE_LIKE;
2373 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2376 if(!tmp_par.empty()) {
2377 fprintf(file,"%s",tmp_par.c_str());
2379 sgmlCloseTag(file,depth+1,inner_tag);
2380 sgmlOpenTag(file,depth+1,inner_tag);
2386 fprintf(file,"%s",tmp_par.c_str());
2387 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2388 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2389 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2392 switch (par->footnotekind) {
2393 case LyXParagraph::FOOTNOTE:
2394 case LyXParagraph::ALGORITHM:
2397 present=FOOTNOTE_LIKE;
2400 case LyXParagraph::MARGIN:
2403 present=MARGIN_LIKE;
2406 case LyXParagraph::FIG:
2407 case LyXParagraph::WIDE_FIG:
2413 case LyXParagraph::TAB:
2414 case LyXParagraph::WIDE_TAB:
2421 sgmlOpenTag(file,depth,tag);
2422 if ((present == TAB_LIKE) || (present == FIG_LIKE)) {
2423 DocBookHandleCaption(file, inner_tag, depth,
2427 sgmlOpenTag(file,depth+1,inner_tag);
2430 // ignore all caption here, we processed them above!!!
2431 if (par->layout != textclasslist.NumberOfLayout(params.textclass,
2432 "Caption").second) {
2433 SimpleDocBookOnePar(tmp_par,extra_par,par,
2436 tmp_par = frontStrip(strip(tmp_par));
2441 fprintf(file,"%s",tmp_par.c_str());
2442 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2443 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2444 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2449 /* push a tag in a style stack */
2450 void Buffer::push_tag(FILE *file, char const *tag,
2451 int& pos, char stack[5][3])
2455 /* pop all previous tags */
2456 for (j=pos; j>=0; j--)
2457 fprintf(file, "</%s>", stack[j]);
2460 sprintf(stack[++pos], "%s", tag);
2463 for (j=0; j<=pos; j++)
2464 fprintf(file, "<%s>", stack[j]);
2468 // pop a tag from a style stack
2469 void Buffer::pop_tag(FILE *file, char const * tag,
2470 int& pos, char stack[5][3])
2474 // pop all tags till specified one
2475 for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
2476 fprintf(file, "</%s>", stack[j]);
2479 fprintf(file, "</%s>", tag);
2481 // push all tags, but the specified one
2482 for (j=j+1; j<=pos; j++) {
2483 fprintf(file, "<%s>", stack[j]);
2484 strcpy(stack[j-1], stack[j]);
2490 /* handle internal paragraph parsing -- layout already processed */
2492 // checks, if newcol chars should be put into this line
2493 // writes newline, if necessary.
2495 void linux_doc_line_break(FILE *file, unsigned int &colcount, const unsigned int newcol)
2498 if (colcount > lyxrc->ascii_linelen) {
2499 fprintf(file, "\n");
2500 colcount = newcol; // assume write after this call
2505 void Buffer::SimpleLinuxDocOnePar(FILE *file, LyXParagraph *par, int desc_on, int const depth)
2507 LyXFont font1,font2;
2511 LyXParagraph::size_type main_body;
2516 LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
2518 char family_type = 0; // family font flag
2519 bool is_bold = false; // series font flag
2520 char shape_type = 0; // shape font flag
2521 bool is_em = false; // emphasis (italic) font flag
2523 int stack_num = -1; // style stack position
2524 char stack[5][3]; // style stack
2525 unsigned int char_line_count = 5; // Heuristic choice ;-)
2527 if (style.labeltype != LABEL_MANUAL)
2530 main_body = par->BeginningOfMainBody();
2532 /* gets paragraph main font */
2534 font1 = style.labelfont;
2539 /* parsing main loop */
2541 for (LyXParagraph::size_type i = 0;
2542 i < par->size(); ++i) {
2544 for (int i = 0; i < par->last; i++) {
2547 /* handle quote tag */
2548 if (i == main_body && !par->IsDummy()) {
2553 font2 = par->getFont(i);
2555 if (font1.family() != font2.family()) {
2556 switch(family_type) {
2558 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2559 push_tag(file, "tt", stack_num, stack);
2562 else if (font2.family() == LyXFont::SANS_FAMILY) {
2563 push_tag(file, "sf", stack_num, stack);
2568 pop_tag(file, "tt", stack_num, stack);
2569 if (font2.family() == LyXFont::SANS_FAMILY) {
2570 push_tag(file, "sf", stack_num, stack);
2578 pop_tag(file, "sf", stack_num, stack);
2579 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2580 push_tag(file, "tt", stack_num, stack);
2589 /* handle bold face */
2590 if (font1.series() != font2.series()) {
2591 if (font2.series() == LyXFont::BOLD_SERIES) {
2592 push_tag(file, "bf", stack_num, stack);
2596 pop_tag(file, "bf", stack_num, stack);
2601 /* handle italic and slanted fonts */
2602 if (font1.shape() != font2.shape()) {
2603 switch(shape_type) {
2605 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2606 push_tag(file, "it", stack_num, stack);
2609 else if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2610 push_tag(file, "sl", stack_num, stack);
2615 pop_tag(file, "it", stack_num, stack);
2616 if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2617 push_tag(file, "sl", stack_num, stack);
2625 pop_tag(file, "sl", stack_num, stack);
2626 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2627 push_tag(file, "it", stack_num, stack);
2635 /* handle <em> tag */
2636 if (font1.emph() != font2.emph()) {
2637 if (font2.emph() == LyXFont::ON) {
2638 push_tag(file, "em", stack_num, stack);
2641 pop_tag(file, "em", stack_num, stack);
2646 c = par->GetChar(i);
2648 if (font2.latex() == LyXFont::ON) {
2649 // "TeX"-Mode on ==> SGML-Mode on.
2651 fprintf(file, "%c", c); // see LaTeX-Generation...
2653 } else if (c == LYX_META_INSET) {
2654 inset = par->GetInset(i);
2656 inset->Linuxdoc(tmp_out);
2657 fprintf(file,"%s",tmp_out.c_str());
2661 if (par->linuxDocConvertChar(c, sgml_string)
2662 && !style.free_spacing) { // in freespacing
2664 // non-breaking characters
2668 linux_doc_line_break(file, char_line_count, 6);
2669 fprintf(file, "</tag>");
2673 linux_doc_line_break(file, char_line_count, 1);
2674 fprintf(file, "%c", c);
2678 fprintf(file, "%s", sgml_string.c_str());
2679 char_line_count += sgml_string.length();
2685 /* needed if there is an optional argument but no contents */
2687 if (main_body > 0 && main_body == par->size()) {
2691 if (main_body > 0 && main_body == par->last) {
2695 /* pop all defined Styles */
2696 for (j = stack_num; j >= 0; j--) {
2697 linux_doc_line_break(file,
2699 3+strlen(stack[j]));
2700 fprintf(file, "</%s>", stack[j]);
2703 /* resets description flag correctly */
2706 /* <tag> not closed... */
2707 linux_doc_line_break(file, char_line_count, 6);
2708 fprintf(file, "</tag>");
2711 /* fprintf(file, "</p>");*/
2717 /* print an error message */
2718 void Buffer::LinuxDocError(LyXParagraph * par, int pos,
2719 char const * message)
2721 InsetError * new_inset;
2723 /* insert an error marker in text */
2724 new_inset = new InsetError(message);
2725 par->InsertChar(pos, LYX_META_INSET);
2726 par->InsertInset(pos, new_inset);
2729 // This constant defines the maximum number of
2730 // environment layouts that can be nesteded.
2731 // The same applies for command layouts.
2732 // These values should be more than enough.
2733 // José Matos (1999/07/22)
2735 enum { MAX_NEST_LEVEL = 25};
2737 void Buffer::makeDocBookFile(string const & filename, int column)
2739 LyXParagraph * par = paragraph;
2741 string top_element=textclasslist.LatexnameOfClass(params.textclass);
2742 string environment_stack[MAX_NEST_LEVEL];
2743 string environment_inner[MAX_NEST_LEVEL];
2744 string command_stack[MAX_NEST_LEVEL];
2745 bool command_flag=false;
2746 int command_depth=0,command_base=0,cmd_depth=0;
2748 string item_name,command_name;
2749 string c_depth,c_params,tmps;
2751 int depth=0; /* paragraph depth */
2753 FilePtr file(filename, FilePtr::write);
2754 tex_code_break_column = column;
2757 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2765 "<!doctype %s public \"-//OASIS//DTD DocBook V3.1//EN\"",
2766 top_element.c_str());
2768 if (params.preamble.empty())
2769 fprintf(file, ">\n\n");
2771 fprintf(file, "\n [ %s \n]>\n\n",params.preamble.c_str() );
2773 string userName(getUserName());
2775 "<!-- DocBook file was created by LyX 1.0 (C) 1995-1999\n");
2776 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2778 if(params.options.empty())
2779 sgmlOpenTag(file,0,top_element);
2781 string top = top_element;
2783 top += params.options;
2784 sgmlOpenTag(file,0,top);
2788 int desc_on=0; /* description mode*/
2789 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2791 par->AutoDeleteInsets();
2793 /* environment tag closing */
2794 for( ;depth > par->depth; depth--) {
2795 if(environment_inner[depth] != "!-- --") {
2796 item_name="listitem";
2797 sgmlCloseTag(file,command_depth+depth,
2799 if( environment_inner[depth] == "varlistentry")
2800 sgmlCloseTag(file,depth+command_depth,
2801 environment_inner[depth]);
2803 sgmlCloseTag(file,depth+command_depth,
2804 environment_stack[depth]);
2805 environment_stack[depth].clear();
2806 environment_inner[depth].clear();
2809 if(depth == par->depth
2810 && environment_stack[depth] != style.latexname()
2811 && !environment_stack[depth].empty()) {
2812 if(environment_inner[depth] != "!-- --") {
2813 item_name="listitem";
2814 sgmlCloseTag(file,command_depth+depth,
2816 if( environment_inner[depth] == "varlistentry")
2817 sgmlCloseTag(file,depth+command_depth,
2818 environment_inner[depth]);
2821 sgmlCloseTag(file,depth+command_depth,
2822 environment_stack[depth]);
2824 environment_stack[depth].clear();
2825 environment_inner[depth].clear();
2828 // Write opening SGML tags.
2829 switch(style.latextype) {
2830 case LATEX_PARAGRAPH:
2831 if(style.latexname() != "dummy")
2832 sgmlOpenTag(file, depth+command_depth,
2838 LinuxDocError(par, 0,
2839 _("Error : Wrong depth for "
2840 "LatexType Command.\n"));
2842 command_name = style.latexname();
2844 tmps = style.latexparam();
2845 c_params = split(tmps, c_depth,'|');
2847 cmd_depth=atoi(c_depth.c_str());
2850 if(cmd_depth<command_base) {
2851 for(int j = command_depth;
2852 j >= command_base; j--)
2853 if(!command_stack[j].empty())
2854 sgmlCloseTag(file,j,command_stack[j]);
2855 command_depth=command_base=cmd_depth;
2857 else if(cmd_depth<=command_depth) {
2858 for(int j= command_depth;
2859 j >= cmd_depth; j--)
2861 if(!command_stack[j].empty())
2862 sgmlCloseTag(file,j,command_stack[j]);
2863 command_depth=cmd_depth;
2866 command_depth=cmd_depth;
2869 command_depth = command_base = cmd_depth;
2870 command_flag = true;
2872 command_stack[command_depth]=command_name;
2874 // treat label as a special case for
2875 // more WYSIWYM handling.
2876 if (par->GetChar(0) == LYX_META_INSET) {
2877 Inset *inset = par->GetInset(0);
2878 char lyx_code = inset->LyxCode();
2879 if (lyx_code ==Inset::LABEL_CODE){
2880 command_name+= " id=\"";
2881 command_name+=((InsetCommand *) inset)->getContents();
2887 sgmlOpenTag(file,depth+command_depth, command_name);
2889 sgmlOpenTag(file,depth+1+command_depth,item_name);
2892 case LATEX_ENVIRONMENT:
2893 case LATEX_ITEM_ENVIRONMENT:
2894 if (depth < par->depth) {
2896 environment_stack[depth].clear();
2899 if (environment_stack[depth] != style.latexname()) {
2900 environment_stack[depth]= style.latexname();
2901 environment_inner[depth]= "!-- --";
2902 sgmlOpenTag(file, depth + command_depth,
2903 environment_stack[depth]);
2905 if(environment_inner[depth] != "!-- --") {
2906 item_name="listitem";
2908 command_depth + depth,
2910 if (environment_inner[depth] == "varlistentry")
2912 depth+command_depth,
2913 environment_inner[depth]);
2917 if(style.latextype == LATEX_ENVIRONMENT) {
2918 if(!style.latexparam().empty())
2919 sgmlOpenTag(file, depth+command_depth,
2920 style.latexparam());
2924 desc_on =(style.labeltype == LABEL_MANUAL);
2927 environment_inner[depth]="varlistentry";
2929 environment_inner[depth]="listitem";
2931 sgmlOpenTag(file,depth+1+command_depth,
2932 environment_inner[depth]);
2936 sgmlOpenTag(file,depth+1+command_depth,
2941 sgmlOpenTag(file,depth+1+command_depth,
2946 sgmlOpenTag(file, depth + command_depth,
2952 string tmp_par,extra_par;
2954 SimpleDocBookOnePar(tmp_par,extra_par, par, desc_on,
2955 depth+1+command_depth);
2956 fprintf(file,"%s",tmp_par.c_str());
2959 DocBookHandleFootnote(file,par, depth+1+command_depth);
2961 while(par && par->IsDummy());
2964 /* write closing SGML tags */
2965 switch(style.latextype) {
2968 sgmlCloseTag(file, depth + command_depth, end_tag);
2970 case LATEX_ENVIRONMENT:
2971 if(!style.latexparam().empty())
2972 sgmlCloseTag(file, depth + command_depth,
2973 style.latexparam());
2975 case LATEX_ITEM_ENVIRONMENT:
2976 if(desc_on==1) break;
2978 sgmlCloseTag(file,depth+1+command_depth,end_tag);
2980 case LATEX_PARAGRAPH:
2981 if(style.latexname() != "dummy")
2982 sgmlCloseTag(file, depth + command_depth,
2986 sgmlCloseTag(file,depth+command_depth,
2993 for(;depth>=0;depth--) {
2994 if(!environment_stack[depth].empty()) {
2995 if(environment_inner[depth] != "!-- --") {
2996 item_name="listitem";
2997 sgmlCloseTag(file,command_depth+depth,
2999 if( environment_inner[depth] == "varlistentry")
3000 sgmlCloseTag(file,depth+command_depth,
3001 environment_inner[depth]);
3004 sgmlCloseTag(file,depth+command_depth,
3005 environment_stack[depth]);
3009 for(int j=command_depth;j>=command_base;j--)
3010 if(!command_stack[j].empty())
3011 sgmlCloseTag(file,j,command_stack[j]);
3013 fprintf(file, "\n\n");
3014 sgmlCloseTag(file,0,top_element);
3017 WriteFSAlert(_("Error! Could not close file properly:"),
3023 void Buffer::SimpleDocBookOnePar(string & file, string & extra,
3024 LyXParagraph * par, int & desc_on,
3028 par->SimpleDocBookOneTablePar(file, extra, desc_on, depth);
3031 LyXFont font1,font2;
3035 LyXParagraph::size_type main_body;
3040 string emph="emphasis";
3041 bool emph_flag=false;
3042 int char_line_count=0;
3044 LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
3046 if (style.labeltype != LABEL_MANUAL)
3049 main_body = par->BeginningOfMainBody();
3051 /* gets paragraph main font */
3053 font1 = style.labelfont;
3057 char_line_count = depth;
3058 if(!style.free_spacing)
3059 for (j=0;j< depth;j++)
3062 /* parsing main loop */
3064 for (LyXParagraph::size_type i = 0;
3065 i < par->size(); ++i) {
3067 for (int i = 0; i < par->last; i++) {
3069 font2 = par->getFont(i);
3071 /* handle <emphasis> tag */
3072 if (font1.emph() != font2.emph() && i) {
3073 if (font2.emph() == LyXFont::ON) {
3074 file += "<emphasis>";
3077 file += "</emphasis>";
3082 c = par->GetChar(i);
3084 if (c == LYX_META_INSET) {
3085 inset = par->GetInset(i);
3087 inset->DocBook(tmp_out);
3089 // This code needs some explanation:
3090 // Two insets are treated specially
3091 // label if it is the first element in a command paragraph
3093 // graphics inside tables or figure floats can't go on
3094 // title (the equivalente in latex for this case is caption
3095 // and title should come first
3098 if(desc_on!=3 || i!=0) {
3099 if(tmp_out[0]=='@') {
3101 extra += frontStrip(tmp_out, '@');
3103 file += frontStrip(tmp_out, '@');
3108 } else if (font2.latex() == LyXFont::ON) {
3109 // "TeX"-Mode on ==> SGML-Mode on.
3116 if (par->linuxDocConvertChar(c, sgml_string)
3117 && !style.free_spacing) { // in freespacing
3119 // non-breaking characters
3124 file += "</term><listitem><para>";
3132 file += sgml_string;
3138 /* needed if there is an optional argument but no contents */
3140 if (main_body > 0 && main_body == par->size()) {
3144 if (main_body > 0 && main_body == par->last) {
3149 file += "</emphasis>";
3152 /* resets description flag correctly */
3155 /* <term> not closed... */
3163 bool Buffer::removeAutoInsets()
3165 LyXParagraph *par = paragraph;
3167 LyXCursor cursor = text->cursor;
3168 LyXCursor tmpcursor = cursor;
3169 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
3170 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
3174 if (par->AutoDeleteInsets()){
3176 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
3177 /* this is possible now, since SetCursor takes
3178 care about footnotes */
3179 text->SetCursorIntern(par, 0);
3180 text->RedoParagraphs(text->cursor, text->cursor.par->Next());
3181 text->FullRebreak();
3186 /* avoid forbidden cursor positions caused by error removing */
3187 if (cursor.pos > cursor.par->Last())
3188 cursor.pos = cursor.par->Last();
3189 text->SetCursorIntern(cursor.par, cursor.pos);
3195 int Buffer::runLaTeX()
3197 if (!text) return 0;
3201 // get LaTeX-Filename
3202 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3204 string path = OnlyPath(filename);
3206 string org_path = path;
3207 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3211 Path p(path); // path to LaTeX file
3212 users->getOwner()->getMiniBuffer()->Set(_("Running LaTeX..."));
3214 // Remove all error insets
3215 bool a = removeAutoInsets();
3217 // Always generate the LaTeX file
3218 makeLaTeXFile(name, org_path, false);
3221 // do the LaTex run(s)
3223 LaTeX latex(lyxrc->latex_command, name, filepath);
3224 int res = latex.run(terr,users->getOwner()->getMiniBuffer()); // running latex
3226 // check return value from latex.run().
3227 if ((res & LaTeX::NO_LOGFILE)) {
3228 WriteAlert(_("LaTeX did not work!"),
3229 _("Missing log file:"), name);
3230 } else if ((res & LaTeX::ERRORS)) {
3231 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3232 // Insert all errors as errors boxes
3235 // Dvi should also be kept dirty if the latex run
3236 // ends up with errors. However it should be possible
3237 // to view a dirty dvi too.
3239 //no errors or any other things to think about so:
3240 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3244 // if we removed error insets before we ran LaTeX or if we inserted
3245 // error insets after we ran LaTeX this must be run:
3246 if (a || (res & LaTeX::ERRORS)){
3249 users->updateScrollbar();
3253 return latex.getNumErrors();
3257 int Buffer::runLiterate()
3259 if (!text) return 0;
3263 // get LaTeX-Filename
3264 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3265 // get Literate-Filename
3266 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3268 string path = OnlyPath(filename);
3270 string org_path = path;
3271 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3275 Path p(path); // path to Literate file
3276 users->getOwner()->getMiniBuffer()->Set(_("Running Literate..."));
3278 // Remove all error insets
3279 bool a = removeAutoInsets();
3281 // generate the Literate file if necessary
3282 if (!isDviClean() || a) {
3283 makeLaTeXFile(lit_name, org_path, false);
3287 Literate literate(lyxrc->latex_command, name, filepath,
3289 lyxrc->literate_command, lyxrc->literate_error_filter,
3290 lyxrc->build_command, lyxrc->build_error_filter);
3292 int res = literate.weave(terr, users->getOwner()->getMiniBuffer());
3294 // check return value from literate.weave().
3295 if ((res & Literate::NO_LOGFILE)) {
3296 WriteAlert(_("Literate command did not work!"),
3297 _("Missing log file:"), name);
3298 } else if ((res & Literate::ERRORS)) {
3299 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3300 // Insert all errors as errors boxes
3303 // Dvi should also be kept dirty if the latex run
3304 // ends up with errors. However it should be possible
3305 // to view a dirty dvi too.
3307 //no errors or any other things to think about so:
3308 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3312 // if we removed error insets before we ran LaTeX or if we inserted
3313 // error insets after we ran LaTeX this must be run:
3314 if (a || (res & Literate::ERRORS)){
3317 users->updateScrollbar();
3321 return literate.getNumErrors();
3325 int Buffer::buildProgram()
3327 if (!text) return 0;
3331 // get LaTeX-Filename
3332 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3333 // get Literate-Filename
3334 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3336 string path = OnlyPath(filename);
3338 string org_path = path;
3339 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3343 Path p(path); // path to Literate file
3344 users->getOwner()->getMiniBuffer()->Set(_("Building Program..."));
3346 // Remove all error insets
3347 bool a = removeAutoInsets();
3349 // generate the LaTeX file if necessary
3350 if (!isNwClean() || a) {
3351 makeLaTeXFile(lit_name, org_path, false);
3355 Literate literate(lyxrc->latex_command, name, filepath,
3357 lyxrc->literate_command, lyxrc->literate_error_filter,
3358 lyxrc->build_command, lyxrc->build_error_filter);
3360 int res = literate.build(terr, users->getOwner()->getMiniBuffer());
3362 // check return value from literate.build().
3363 if ((res & Literate::NO_LOGFILE)) {
3364 WriteAlert(_("Build did not work!"),
3365 _("Missing log file:"), name);
3366 } else if ((res & Literate::ERRORS)) {
3367 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3368 // Insert all errors as errors boxes
3371 // Literate files should also be kept dirty if the literate
3372 // command run ends up with errors.
3374 //no errors or any other things to think about so:
3375 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3379 // if we removed error insets before we ran Literate/Build or if we inserted
3380 // error insets after we ran Literate/Build this must be run:
3381 if (a || (res & Literate::ERRORS)){
3384 users->updateScrollbar();
3388 return literate.getNumErrors();
3392 // This should be enabled when the Chktex class is implemented. (Asger)
3393 // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
3394 // Other flags: -wall -v0 -x
3395 int Buffer::runChktex()
3397 if (!text) return 0;
3401 // get LaTeX-Filename
3402 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3403 string path = OnlyPath(filename);
3405 string org_path = path;
3406 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3410 Path p(path); // path to LaTeX file
3411 users->getOwner()->getMiniBuffer()->Set(_("Running chktex..."));
3413 // Remove all error insets
3414 bool a = removeAutoInsets();
3416 // Generate the LaTeX file if neccessary
3417 if (!isDviClean() || a) {
3418 makeLaTeXFile(name, org_path, false);
3423 Chktex chktex(lyxrc->chktex_command, name, filepath);
3424 int res = chktex.run(terr); // run chktex
3427 WriteAlert(_("chktex did not work!"),
3428 _("Could not run with file:"), name);
3429 } else if (res > 0) {
3430 // Insert all errors as errors boxes
3434 // if we removed error insets before we ran chktex or if we inserted
3435 // error insets after we ran chktex, this must be run:
3439 users->updateScrollbar();
3447 extern void AllFloats(char, char);
3450 void Buffer::insertErrors(TeXErrors & terr)
3452 // Save the cursor position
3453 LyXCursor cursor = text->cursor;
3455 // This is drastic, but it's the only fix, I could find. (Asger)
3459 for (TeXErrors::Errors::const_iterator cit = terr.begin();
3462 string desctext((*cit).error_desc);
3463 string errortext((*cit).error_text);
3464 string msgtxt = desctext + '\n' + errortext;
3465 int errorrow = (*cit).error_in_line;
3467 // Insert error string for row number
3471 texrow.getIdFromRow(errorrow, tmpid, tmppos);
3473 LyXParagraph* texrowpar;
3476 texrowpar = text->FirstParagraph();
3479 texrowpar = text->GetParFromID(tmpid);
3485 InsetError *new_inset = new InsetError(msgtxt);
3487 text->SetCursorIntern(texrowpar, tmppos);
3488 text->InsertInset(new_inset);
3489 text->FullRebreak();
3491 // Restore the cursor position
3492 text->SetCursorIntern(cursor.par, cursor.pos);
3496 void Buffer::setCursorFromRow (int row)
3501 texrow.getIdFromRow(row, tmpid, tmppos);
3503 LyXParagraph* texrowpar;
3506 texrowpar = text->FirstParagraph();
3509 texrowpar = text->GetParFromID(tmpid);
3511 text->SetCursor(texrowpar, tmppos);
3515 void Buffer::RoffAsciiTable(FILE * file, LyXParagraph * par)
3518 font1 = LyXFont(LyXFont::ALL_INHERIT),
3522 LyXParagraph::size_type i;
3534 string fname1 = TmpFileName(string(),"RAT1");
3535 string fname2 = TmpFileName(string(),"RAT2");
3536 if (!(fp=fopen(fname1.c_str(),"w"))) {
3537 WriteAlert(_("LYX_ERROR:"),
3538 _("Cannot open temporary file:"), fname1);
3541 par->table->RoffEndOfCell(fp, -1);
3543 for (i = 0; i < par->size(); ++i) {
3545 for (i = 0; i < par->last; ++i) {
3547 c = par->GetChar(i);
3548 if (par->table->IsContRow(cell)) {
3549 if (c == LYX_META_NEWLINE)
3553 font2 = par->GetFontSettings(i);
3554 if (font1.latex() != font2.latex()) {
3555 if (font2.latex() != LyXFont::OFF)
3559 case LYX_META_INSET:
3560 if ((inset = par->GetInset(i))) {
3561 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3562 WriteAlert(_("LYX_ERROR:"),
3563 _("Cannot open temporary file:"), fname2);
3565 remove(fname1.c_str());
3568 inset->Latex(fp2,-1);
3581 case LYX_META_NEWLINE:
3582 if (par->table->CellHasContRow(cell)>=0)
3583 par->RoffContTableRows(fp, i+1,cell);
3584 par->table->RoffEndOfCell(fp, cell);
3587 case LYX_META_HFILL:
3589 case LYX_META_PROTECTED_SEPARATOR:
3592 fprintf(fp, "\\\\");
3596 fprintf(fp, "%c", c);
3599 << "RoffAsciiTable:"
3600 " NULL char in structure." << endl;
3604 par->table->RoffEndOfCell(fp, cell);
3606 string cmd = lyxrc->ascii_roff_command + " >" + fname2;
3607 cmd = subst(cmd, "$$FName", fname1);
3608 Systemcalls one(Systemcalls::System, cmd);
3609 if (!(lyxerr.debugging(Debug::ROFF))) {
3610 remove(fname1.c_str());
3612 if (!(fp=fopen(fname2.c_str(),"r"))) {
3613 WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
3616 // now output the produced file
3617 fprintf(file, "\n\n");
3620 WriteAlert(_("Error!"),
3621 _("Error executing *roff command on table"));
3622 // overread leading blank lines
3623 while(!feof(fp) && (c == '\n'))
3626 for(j=0; j<par->depth; j++)
3628 while(!feof(fp) && (c != '\n')) {
3633 // overread trailing blank lines
3634 while(!feof(fp) && (c == '\n'))
3638 remove(fname2.c_str());
3642 /// changed Heinrich Bauer, 23/03/98
3643 bool Buffer::isDviClean()
3645 if (lyxrc->use_tempdir)
3646 return dvi_clean_tmpd;
3648 return dvi_clean_orgd;
3652 /// changed Heinrich Bauer, 23/03/98
3653 void Buffer::markDviClean()
3655 if (lyxrc->use_tempdir)
3656 dvi_clean_tmpd = true;
3658 dvi_clean_orgd = true;
3662 /// changed Heinrich Bauer, 23/03/98
3663 void Buffer::markDviDirty()
3665 if (lyxrc->use_tempdir)
3666 dvi_clean_tmpd = false;
3668 dvi_clean_orgd = false;
3672 void Buffer::update(signed char f)
3676 users->getOwner()->updateLayoutChoice();
3678 if (!text->selection && f > -3)
3679 text->sel_cursor = text->cursor;
3682 text->FullRebreak();
3685 if (f != 3 && f != -3) {
3687 users->updateScrollbar();
3690 if (f==1 || f==-1) {
3693 users->getOwner()->getMiniBuffer()->setTimer(4);
3701 void Buffer::validate(LaTeXFeatures & features)
3703 LyXParagraph * par = paragraph;
3704 LyXTextClass const & tclass =
3705 textclasslist.TextClass(params.textclass);
3707 // AMS Style is at document level
3709 features.amsstyle = (params.use_amsmath ||
3710 tclass.provides(LyXTextClass::amsmath));
3713 // We don't use "lyxerr.debug" because of speed. (Asger)
3714 if (lyxerr.debugging(Debug::LATEX))
3715 lyxerr << "Paragraph: " << par << endl;
3717 // Now just follow the list of paragraphs and run
3718 // validate on each of them.
3719 par->validate(features);
3721 // and then the next paragraph
3725 // the bullet shapes are buffer level not paragraph level
3726 // so they are tested here
3727 for (int i = 0; i < 4; ++i) {
3728 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
3729 int font = params.user_defined_bullets[i].getFont();
3732 .user_defined_bullets[i]
3739 features.latexsym = true;
3743 features.amssymb = true;
3745 else if ((font >= 2 && font <=5)) {
3746 features.pifont = true;
3751 if (lyxerr.debugging(Debug::LATEX)) {
3752 features.showStruct(params);
3757 void Buffer::setPaperStuff()
3759 params.papersize = PAPER_DEFAULT;
3760 char c1 = params.paperpackage;
3761 if (c1 == PACKAGE_NONE) {
3762 char c2 = params.papersize2;
3763 if (c2 == VM_PAPER_USLETTER)
3764 params.papersize = PAPER_USLETTER;
3765 else if (c2 == VM_PAPER_USLEGAL)
3766 params.papersize = PAPER_LEGALPAPER;
3767 else if (c2 == VM_PAPER_USEXECUTIVE)
3768 params.papersize = PAPER_EXECUTIVEPAPER;
3769 else if (c2 == VM_PAPER_A3)
3770 params.papersize = PAPER_A3PAPER;
3771 else if (c2 == VM_PAPER_A4)
3772 params.papersize = PAPER_A4PAPER;
3773 else if (c2 == VM_PAPER_A5)
3774 params.papersize = PAPER_A5PAPER;
3775 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
3776 (c2 == VM_PAPER_B5))
3777 params.papersize = PAPER_B5PAPER;
3778 } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
3779 (c1 == PACKAGE_WIDEMARGINSA4))
3780 params.papersize = PAPER_A4PAPER;
3784 void Buffer::setOldPaperStuff()
3786 char c = params.papersize = params.papersize2;
3787 params.papersize2 = VM_PAPER_DEFAULT;
3788 params.paperpackage = PACKAGE_NONE;
3789 if (c == OLD_PAPER_A4PAPER)
3790 params.papersize2 = VM_PAPER_A4;
3791 else if (c == OLD_PAPER_A4)
3792 params.paperpackage = PACKAGE_A4;
3793 else if (c == OLD_PAPER_A4WIDE)
3794 params.paperpackage = PACKAGE_A4WIDE;
3795 else if (c == OLD_PAPER_WIDEMARGINSA4)
3796 params.paperpackage = PACKAGE_WIDEMARGINSA4;
3797 else if (c == OLD_PAPER_USLETTER)
3798 params.papersize2 = VM_PAPER_USLETTER;
3799 else if (c == OLD_PAPER_A5PAPER)
3800 params.papersize2 = VM_PAPER_A5;
3801 else if (c == OLD_PAPER_B5PAPER)
3802 params.papersize2 = VM_PAPER_B5;
3803 else if (c == OLD_PAPER_EXECUTIVEPAPER)
3804 params.papersize2 = VM_PAPER_USEXECUTIVE;
3805 else if (c == OLD_PAPER_LEGALPAPER)
3806 params.papersize2 = VM_PAPER_USLEGAL;
3811 void Buffer::insertInset(Inset * inset, string const & lout,
3814 // check for table/list in tables
3815 if (no_table && text->cursor.par->table){
3816 WriteAlert(_("Impossible Operation!"),
3817 _("Cannot insert table/list in table."),
3821 // not quite sure if we want this...
3822 text->SetCursorParUndo();
3826 if (!lout.empty()) {
3828 text->BreakParagraph();
3831 if (text->cursor.par->Last()) {
3834 text->BreakParagraph();
3838 int lay = textclasslist.NumberOfLayout(params.textclass,
3840 if (lay == -1) // layout not found
3841 // use default layout "Standard" (0)
3844 text->SetLayout(lay);
3846 text->SetParagraph(0, 0,
3848 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3854 text->current_font.setLatex(LyXFont::OFF);
3857 text->InsertInset(inset);
3860 text->UnFreezeUndo();
3864 // Open and lock an updatable inset
3865 void Buffer::open_new_inset(UpdatableInset * new_inset)
3869 insertInset(new_inset);
3872 new_inset->Edit(0,0);
3876 /* This function should be in Buffer because it's a buffer's property (ale) */
3877 string Buffer::getIncludeonlyList(char delim)
3880 LyXParagraph * par = paragraph;
3882 LyXParagraph::size_type pos;
3889 while ((inset = par->ReturnNextInsetPointer(pos))){
3890 if (inset->LyxCode()==Inset::INCLUDE_CODE) {
3891 InsetInclude * insetinc =
3892 static_cast<InsetInclude*>(inset);
3893 if (insetinc->isInclude()
3894 && insetinc->isNoLoad()) {
3897 lst += ChangeExtension(insetinc->getContents(), string(), true);
3904 lyxerr.debug() << "Includeonly(" << lst << ')' << endl;
3909 /* This is also a buffer property (ale) */
3910 string Buffer::getReferenceList(char delim)
3912 /// if this is a child document and the parent is already loaded
3913 /// Use the parent's list instead [ale990407]
3914 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3915 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3917 return tmp->getReferenceList(delim);
3920 LyXParagraph *par = paragraph;
3922 LyXParagraph::size_type pos;
3930 while ((inset = par->ReturnNextInsetPointer(pos))){
3931 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3934 lst += inset->getLabel(i);
3940 lyxerr.debug() << "References(" << lst << ")" << endl;
3945 /* This is also a buffer property (ale) */
3946 string Buffer::getBibkeyList(char delim)
3948 /// if this is a child document and the parent is already loaded
3949 /// Use the parent's list instead [ale990412]
3950 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3951 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3953 return tmp->getBibkeyList(delim);
3957 LyXParagraph * par = paragraph;
3960 if (!bibkeys.empty())
3962 bibkeys += par->bibkey->getContents();
3967 // Might be either using bibtex or a child has bibliography
3968 if (bibkeys.empty()) {
3973 LyXParagraph::size_type pos = -1;
3978 // Search for Bibtex or Include inset
3979 while ((inset = par->ReturnNextInsetPointer(pos))) {
3980 if (inset-> LyxCode()==Inset::BIBTEX_CODE) {
3981 if (!bibkeys.empty())
3983 bibkeys += ((InsetBibtex*)inset)->getKeys();
3984 } else if (inset-> LyxCode()==Inset::INCLUDE_CODE) {
3985 string bk = ((InsetInclude*)inset)->getKeys();
3987 if (!bibkeys.empty())
3998 lyxerr.debug() << "Bibkeys(" << bibkeys << ")" << endl;
4003 /* This is also a buffer property (ale) */
4004 // Not so sure about that. a goto Label function can not be buffer local, just
4005 // think how this will work in a multiwindo/buffer environment, all the
4006 // cursors in all the views showing this buffer will move. (Lgb)
4007 // OK, then no cursor action should be allowed in buffer. (ale)
4008 bool Buffer::gotoLabel(string const & label)
4011 LyXParagraph * par = paragraph;
4013 LyXParagraph::size_type pos;
4020 while ((inset = par->ReturnNextInsetPointer(pos))){
4021 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
4022 if (label==inset->getLabel(i)) {
4024 text->SetCursor(par, pos);
4025 text->sel_cursor = text->cursor;
4038 bool Buffer::isDepClean(string const & name) const
4040 DEPCLEAN * item = dep_clean;
4041 while (item && item->master != name)
4043 if (!item) return true;
4048 void Buffer::markDepClean(string const & name)
4051 dep_clean = new DEPCLEAN;
4052 dep_clean->clean = true;
4053 dep_clean->master = name;
4054 dep_clean->next = 0;
4056 DEPCLEAN* item = dep_clean;
4057 while (item && item->master != name)
4062 item = new DEPCLEAN;
4064 item->master = name;