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);
333 string layoutname = lex.GetString();
334 pair<bool, LyXTextClass::LayoutList::size_type> pp
335 = textclasslist.NumberOfLayout(params.textclass,
338 par->layout = pp.second;
339 } else { // layout not found
340 // use default layout "Standard" (0)
343 // Test whether the layout is obsolete.
344 LyXLayout const & layout = textclasslist.Style(params.textclass,
346 if (!layout.obsoleted_by().empty())
348 textclasslist.NumberOfLayout(params.textclass,
349 layout.obsoleted_by()).second;
350 par->footnoteflag = footnoteflag;
351 par->footnotekind = footnotekind;
353 font = LyXFont(LyXFont::ALL_INHERIT);
354 } else if (token == "\\end_float") {
358 par = new LyXParagraph(par);
359 footnotekind = LyXParagraph::FOOTNOTE;
360 footnoteflag = LyXParagraph::NO_FOOTNOTE;
363 par->layout = LYX_DUMMY_LAYOUT;
364 font = LyXFont(LyXFont::ALL_INHERIT);
365 } else if (token == "\\begin_float") {
366 tmpret = lex.FindToken(string_footnotekinds);
367 if (tmpret == -1) tmpret++;
368 if (tmpret != LYX_LAYOUT_DEFAULT)
369 footnotekind = (LyXParagraph::footnote_kind)tmpret; // bad
370 if (footnotekind == LyXParagraph::FOOTNOTE
371 || footnotekind == LyXParagraph::MARGIN)
372 footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
374 footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
375 } else if (token == "\\begin_deeper") {
377 } else if (token == "\\end_deeper") {
379 lex.printError("\\end_deeper: "
380 "depth is already null");
384 } else if (token == "\\begin_preamble") {
385 params.readPreamble(lex);
386 } else if (token == "\\textclass") {
388 pair<bool, LyXTextClassList::ClassList::size_type> pp =
389 textclasslist.NumberOfClass(lex.GetString());
391 params.textclass = pp.second;
393 lex.printError("Unknown textclass `$$Token'");
394 params.textclass = 0;
396 if (!textclasslist.Load(params.textclass)) {
397 // if the textclass wasn't loaded properly
398 // we need to either substitute another
399 // or stop loading the file.
400 // I can substitute but I don't see how I can
401 // stop loading... ideas?? ARRae980418
402 WriteAlert(_("Textclass Loading Error!"),
403 string(_("Can't load textclass ")) +
404 textclasslist.NameOfClass(params.textclass),
405 _("-- substituting default"));
406 params.textclass = 0;
408 } else if (token == "\\options") {
410 params.options = lex.GetString();
411 } else if (token == "\\language") {
412 params.readLanguage(lex);
413 } else if (token == "\\fontencoding") {
415 } else if (token == "\\inputencoding") {
417 params.inputenc = lex.GetString();
418 } else if (token == "\\graphics") {
419 params.readGraphicsDriver(lex);
420 } else if (token == "\\fontscheme") {
422 params.fonts = lex.GetString();
423 } else if (token == "\\noindent") {
424 par->noindent = true;
425 } else if (token == "\\fill_top") {
426 par->added_space_top = VSpace(VSpace::VFILL);
427 } else if (token == "\\fill_bottom") {
428 par->added_space_bottom = VSpace(VSpace::VFILL);
429 } else if (token == "\\line_top") {
430 par->line_top = true;
431 } else if (token == "\\line_bottom") {
432 par->line_bottom = true;
433 } else if (token == "\\pagebreak_top") {
434 par->pagebreak_top = true;
435 } else if (token == "\\pagebreak_bottom") {
436 par->pagebreak_bottom = true;
437 } else if (token == "\\start_of_appendix") {
438 par->start_of_appendix = true;
439 } else if (token == "\\paragraph_separation") {
440 tmpret = lex.FindToken(string_paragraph_separation);
441 if (tmpret == -1) tmpret++;
442 if (tmpret != LYX_LAYOUT_DEFAULT)
443 params.paragraph_separation = tmpret;
444 } else if (token == "\\defskip") {
446 params.defskip = VSpace(lex.GetString());
447 } else if (token == "\\no_isolatin1") {
449 } else if (token == "\\no_babel") {
451 } else if (token == "\\no_epsfig") {
453 } else if (token == "\\epsfig") { // obsolete
454 // Indeed it is obsolete, but we HAVE to be backwards
455 // compatible until 0.14, because otherwise all figures
456 // in existing documents are irretrivably lost. (Asger)
457 params.readGraphicsDriver(lex);
458 } else if (token == "\\quotes_language") {
459 tmpret = lex.FindToken(string_quotes_language);
460 if (tmpret == -1) tmpret++;
461 if (tmpret != LYX_LAYOUT_DEFAULT) {
462 InsetQuotes::quote_language tmpl =
463 InsetQuotes::EnglishQ;
466 tmpl = InsetQuotes::EnglishQ;
469 tmpl = InsetQuotes::SwedishQ;
472 tmpl = InsetQuotes::GermanQ;
475 tmpl = InsetQuotes::PolishQ;
478 tmpl = InsetQuotes::FrenchQ;
481 tmpl = InsetQuotes::DanishQ;
484 params.quotes_language = tmpl;
486 } else if (token == "\\quotes_times") {
488 switch(lex.GetInteger()) {
490 params.quotes_times = InsetQuotes::SingleQ;
493 params.quotes_times = InsetQuotes::DoubleQ;
496 } else if (token == "\\papersize") {
498 tmpret = lex.FindToken(string_papersize);
500 tmpret = lex.FindToken(string_oldpapersize);
504 params.papersize2 = tmpret;
505 } else if (token == "\\paperpackage") {
506 tmpret = lex.FindToken(string_paperpackages);
509 params.paperpackage = PACKAGE_NONE;
511 params.paperpackage = tmpret;
512 } else if (token == "\\use_geometry") {
514 params.use_geometry = lex.GetInteger();
515 } else if (token == "\\use_amsmath") {
517 params.use_amsmath = lex.GetInteger();
518 } else if (token == "\\paperorientation") {
519 tmpret = lex.FindToken(string_orientation);
520 if (tmpret == -1) tmpret++;
521 if (tmpret != LYX_LAYOUT_DEFAULT)
522 params.orientation = tmpret;
523 } else if (token == "\\paperwidth") {
525 params.paperwidth = lex.GetString();
526 } else if (token == "\\paperheight") {
528 params.paperheight = lex.GetString();
529 } else if (token == "\\leftmargin") {
531 params.leftmargin = lex.GetString();
532 } else if (token == "\\topmargin") {
534 params.topmargin = lex.GetString();
535 } else if (token == "\\rightmargin") {
537 params.rightmargin = lex.GetString();
538 } else if (token == "\\bottommargin") {
540 params.bottommargin = lex.GetString();
541 } else if (token == "\\headheight") {
543 params.headheight = lex.GetString();
544 } else if (token == "\\headsep") {
546 params.headsep = lex.GetString();
547 } else if (token == "\\footskip") {
549 params.footskip = lex.GetString();
550 } else if (token == "\\paperfontsize") {
552 params.fontsize = strip(lex.GetString());
553 } else if (token == "\\papercolumns") {
555 params.columns = lex.GetInteger();
556 } else if (token == "\\papersides") {
558 switch(lex.GetInteger()) {
560 case 1: params.sides = LyXTextClass::OneSide; break;
561 case 2: params.sides = LyXTextClass::TwoSides; break;
563 } else if (token == "\\paperpagestyle") {
565 params.pagestyle = strip(lex.GetString());
566 } else if (token == "\\bullet") {
568 int index = lex.GetInteger();
570 int temp_int = lex.GetInteger();
571 params.user_defined_bullets[index].setFont(temp_int);
572 params.temp_bullets[index].setFont(temp_int);
574 temp_int = lex.GetInteger();
575 params.user_defined_bullets[index].setCharacter(temp_int);
576 params.temp_bullets[index].setCharacter(temp_int);
578 temp_int = lex.GetInteger();
579 params.user_defined_bullets[index].setSize(temp_int);
580 params.temp_bullets[index].setSize(temp_int);
582 string temp_str = lex.GetString();
583 if (temp_str != "\\end_bullet") {
584 // this element isn't really necessary for
585 // parsing but is easier for humans
586 // to understand bullets. Put it back and
587 // set a debug message?
588 lex.printError("\\end_bullet expected, got" + temp_str);
589 //how can I put it back?
591 } else if (token == "\\bulletLaTeX") {
593 int index = lex.GetInteger();
595 string temp_str = lex.GetString(), sum_str;
596 while (temp_str != "\\end_bullet") {
597 // this loop structure is needed when user
598 // enters an empty string since the first
599 // thing returned will be the \\end_bullet
601 // if the LaTeX entry has spaces. Each element
602 // therefore needs to be read in turn
605 temp_str = lex.GetString();
607 params.user_defined_bullets[index].setText(sum_str);
608 params.temp_bullets[index].setText(sum_str);
609 } else if (token == "\\secnumdepth") {
611 params.secnumdepth = lex.GetInteger();
612 } else if (token == "\\tocdepth") {
614 params.tocdepth = lex.GetInteger();
615 } else if (token == "\\baselinestretch") { // now obsolete
616 lex.nextToken(); // should not be used directly
618 // Will probably keep a kind of support just for
620 params.spacing.set(Spacing::Other, lex.GetFloat());
621 } else if (token == "\\spacing") {
623 string tmp = strip(lex.GetString());
624 if (tmp == "single") {
625 params.spacing.set(Spacing::Single);
626 } else if (tmp == "onehalf") {
627 params.spacing.set(Spacing::Onehalf);
628 } else if (tmp == "double") {
629 params.spacing.set(Spacing::Double);
630 } else if (tmp == "other") {
632 params.spacing.set(Spacing::Other,
635 lex.printError("Unknown spacing token: '$$Token'");
637 } else if (token == "\\float_placement") {
639 params.float_placement = lex.GetString();
640 } else if (token == "\\cursor") {
641 // this is obsolete, so we just skip it.
643 } else if (token == "\\family") {
645 font.setLyXFamily(lex.GetString());
646 } else if (token == "\\series") {
648 font.setLyXSeries(lex.GetString());
649 } else if (token == "\\shape") {
651 font.setLyXShape(lex.GetString());
652 } else if (token == "\\size") {
654 font.setLyXSize(lex.GetString());
655 } else if (token == "\\latex") {
657 string tok = lex.GetString();
658 // This is dirty, but gone with LyX3. (Asger)
659 if (tok == "no_latex")
660 font.setLatex(LyXFont::OFF);
661 else if (tok == "latex")
662 font.setLatex(LyXFont::ON);
663 else if (tok == "default")
664 font.setLatex(LyXFont::INHERIT);
666 lex.printError("Unknown LaTeX font flag "
668 } else if (token == "\\emph") {
670 font.setEmph(font.setLyXMisc(lex.GetString()));
671 } else if (token == "\\bar") {
673 string tok = lex.GetString();
674 // This is dirty, but gone with LyX3. (Asger)
676 font.setUnderbar(LyXFont::ON);
677 else if (tok == "no")
678 font.setUnderbar(LyXFont::OFF);
679 else if (tok == "default")
680 font.setUnderbar(LyXFont::INHERIT);
682 lex.printError("Unknown bar font flag "
684 } else if (token == "\\noun") {
686 font.setNoun(font.setLyXMisc(lex.GetString()));
687 } else if (token == "\\color") {
689 font.setLyXColor(lex.GetString());
690 } else if (token == "\\align") {
691 tmpret = lex.FindToken(string_align);
692 if (tmpret == -1) tmpret++;
693 if (tmpret != LYX_LAYOUT_DEFAULT) {
695 for (; tmpret>0; tmpret--)
696 tmpret2 = tmpret2 * 2;
697 par->align = LyXAlignment(tmpret2);
699 } else if (token == "\\added_space_top"){
701 par->added_space_top = lex.GetString();
702 } else if (token == "\\added_space_bottom") {
704 par->added_space_bottom = lex.GetString();
705 } else if (token == "\\pextra_type") {
707 par->pextra_type = lex.GetInteger();
708 } else if (token == "\\pextra_width") {
710 par->pextra_width = lex.GetString();
711 } else if (token == "\\pextra_widthp") {
713 par->pextra_widthp = lex.GetString();
714 } else if (token == "\\pextra_alignment") {
716 par->pextra_alignment = lex.GetInteger();
717 } else if (token == "\\pextra_hfill") {
719 par->pextra_hfill = lex.GetInteger();
720 } else if (token == "\\pextra_start_minipage") {
722 par->pextra_start_minipage = lex.GetInteger();
723 } else if (token == "\\labelwidthstring") {
725 par->labelwidthstring = lex.GetString();
726 /* do not delete this token, it is still needed! */
727 } else if (token == "\\end_inset") {
728 /* simple ignore this. The insets do not have
730 // but insets should read it, it is a part of
731 //the inset isn't it? Lgb.
732 } else if (token == "\\begin_inset") {
734 tmptok = lex.GetString();
735 /* test the different insets */
736 if (tmptok == "Quotes") {
737 inset = new InsetQuotes;
739 par->InsertChar(pos, LYX_META_INSET);
740 par->InsertInset(pos, inset);
741 par->SetFont(pos, font);
743 } else if (tmptok == "Latex") {
744 // This one is on its way out
746 tmptok = strip(lex.GetString());
747 //lyxerr <<string(tmptok[0]));
748 if (tmptok[0] == '\\') {
749 // then this latex is a
751 InsetCommand *tmpinset =
753 tmpinset->scanCommand(tmptok);
756 // This should not use InsetLaTexDel
757 // it should rather insert text into
758 // the paragraph and mark it as tex.
759 inset = new InsetLatex(tmptok);
761 par->InsertChar(pos, LYX_META_INSET);
762 par->InsertInset(pos, inset);
763 par->SetFont(pos, font);
765 } else if (tmptok == "LatexDel") {
766 // This one is on its way out...
768 tmptok = strip(lex.GetString());
769 //lyxerr <<string(tmptok[0]));
770 if (tmptok == "\\tableofcontents") {
771 inset = new InsetTOC(this);
772 } else if (tmptok == "\\listoffigures") {
773 inset = new InsetLOF(this);
774 } else if (tmptok == "\\listoftables") {
775 inset = new InsetLOT(this);
776 } else if (tmptok == "\\listofalgorithms") {
777 inset = new InsetLOA(this);
778 } else if (contains(tmptok, "\\ref{")
779 || contains(tmptok, "\\pageref{")) {
780 inset = new InsetRef(tmptok, this);
781 } else if (contains(tmptok, "\\url{")
782 || contains(tmptok, "\\htmlurl{")) {
783 string cont,opt,tmptmptok,cmdname;
785 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
790 tmptmptok=lex.GetString();
791 if(tmptmptok[0] == '\\') {
792 if( tmptmptok == "\\backslash")
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" ) {
822 if(contains(tmptok, "\\url{"))
823 cmdname = string("url");
825 cmdname = string("htmlurl");
828 inset = new InsetUrl(cmdname,cont,opt);
829 } else if (tmptok[0] == '\\') {
830 // then this latex del is a
832 InsetCommand *tmpinset =
834 tmpinset->scanCommand(tmptok);
837 par->InsertChar(pos, LYX_META_INSET);
838 par->InsertInset(pos, inset);
839 par->SetFont(pos, font);
841 } else if (tmptok == "\\i") {
842 inset = new InsetLatexAccent;
844 par->InsertChar(pos, LYX_META_INSET);
845 par->InsertInset(pos, inset);
846 par->SetFont(pos, font);
848 } else if (tmptok == "FormulaMacro") {
849 inset = new InsetFormulaMacro;
851 par->InsertChar(pos, LYX_META_INSET);
852 par->InsertInset(pos, inset);
853 par->SetFont(pos, font);
855 } else if (tmptok == "Formula") {
856 inset = new InsetFormula;
858 par->InsertChar(pos, LYX_META_INSET);
859 par->InsertInset(pos, inset);
860 par->SetFont(pos, font);
862 } else if (tmptok == "Figure") {
863 inset = new InsetFig(100,100, this);
865 par->InsertChar(pos, LYX_META_INSET);
866 par->InsertInset(pos, inset);
867 par->SetFont(pos, font);
869 } else if (tmptok == "Label") {
870 // Kept for compability. Remove in 0.13.
872 string tmp = "\\label{";
873 tmp += lex.GetString();
875 inset = new InsetLabel(tmp);
876 par->InsertChar(pos, LYX_META_INSET);
877 par->InsertInset(pos, inset);
878 par->SetFont(pos, font);
881 } else if (tmptok == "Info") {
882 inset = new InsetInfo;
884 par->InsertChar(pos, LYX_META_INSET);
885 par->InsertInset(pos, inset);
886 par->SetFont(pos, font);
888 } else if (tmptok == "Include") {
889 inset = new InsetInclude(string(), this);
891 par->InsertChar(pos, LYX_META_INSET);
892 par->InsertInset(pos, inset);
893 par->SetFont(pos, font);
895 } else if (tmptok == "LatexCommand") {
898 if (inscmd.getCmdName()=="cite") {
899 inset = new InsetCitation(inscmd.getContents(), inscmd.getOptions());
900 } else if (inscmd.getCmdName()=="bibitem") {
901 lex.printError("Wrong place for bibitem");
902 inset = inscmd.Clone();
903 } else if (inscmd.getCmdName()=="BibTeX") {
904 inset = new InsetBibtex(inscmd.getContents(), inscmd.getOptions(), this);
905 } else if (inscmd.getCmdName()=="index") {
906 inset = new InsetIndex(inscmd.getContents());
907 } else if (inscmd.getCmdName()=="include") {
908 inset = new InsetInclude(inscmd.getContents(), this);
909 } else if (inscmd.getCmdName()=="label") {
910 inset = new InsetLabel(inscmd.getCommand());
911 } else if (inscmd.getCmdName()=="url"
912 || inscmd.getCmdName()=="htmlurl") {
913 inset = new InsetUrl(inscmd.getCommand());
914 } else if (inscmd.getCmdName() == "ref"
915 || inscmd.getCmdName() == "pageref") {
916 if (!inscmd.getOptions().empty() || !inscmd.getContents().empty()) {
917 inset = new InsetRef(inscmd, this);
919 /* This condition comes from a temporary solution
920 to the latexdel ref inset that was transformed to an empty ref
921 inset plus the body surronded by latexdel insets */
923 string cont,opt,tmptmptok,cmdname;
925 while(lex.IsOK() && lex.GetString() != "\\end_inset" ) {
930 tmptmptok=lex.GetString();
931 if(tmptmptok[0] == '\\') {
932 if( tmptmptok == "\\backslash")
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" ) {
965 cmdname = "\\" + inscmd.getCmdName();
966 cmdname += "[" + cont + "]";
967 cmdname += "{" + opt + "}";
968 inset = new InsetRef(cmdname,this);
970 } else if (inscmd.getCmdName()=="tableofcontents") {
971 inset = new InsetTOC(this);
972 } else if (inscmd.getCmdName()=="listoffigures") {
973 inset = new InsetLOF(this);
974 } else if (inscmd.getCmdName()=="listofalgorithms") {
975 inset = new InsetLOA(this);
976 } else if (inscmd.getCmdName()=="listoftables") {
977 inset = new InsetLOT(this);
978 } else if (inscmd.getCmdName()=="printindex") {
979 inset = new InsetPrintIndex(this);
980 } else if (inscmd.getCmdName()=="lyxparent") {
981 inset = new InsetParent(inscmd.getContents(),this);
983 // The following three are only for compatibility
984 if (inscmd.getCmdName()=="-") {
985 inset = new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
986 } else if (inscmd.getCmdName()=="@.") {
987 inset = new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
988 } else if (inscmd.getCmdName()=="ldots") {
989 inset = new InsetSpecialChar(InsetSpecialChar::LDOTS);
991 inset = inscmd.Clone();
994 par->InsertChar(pos, LYX_META_INSET);
995 par->InsertInset(pos, inset);
996 par->SetFont(pos, font);
1000 } else if (token == "\\InsetQuotes") {
1001 inset = new InsetQuotes;
1003 par->InsertChar(pos, LYX_META_INSET);
1004 par->InsertInset(pos, inset);
1005 par->SetFont(pos, font);
1007 } else if (token == "\\InsetLatex") {
1008 inset = new InsetLatex;
1010 par->InsertChar(pos, LYX_META_INSET);
1011 par->InsertInset(pos, inset);
1012 par->SetFont(pos, font);
1014 } else if (token == "\\InsetLatexDel") {
1015 lex.printError(_("Warning: Ignoring Old Inset"));
1016 } else if (token == "\\InsetFormula") {
1017 inset = new InsetFormula;
1019 par->InsertChar(pos, LYX_META_INSET);
1020 par->InsertInset(pos, inset);
1021 par->SetFont(pos, font);
1023 } else if (token == "\\SpecialChar") {
1024 inset = new InsetSpecialChar;
1026 par->InsertChar(pos, LYX_META_INSET);
1027 par->InsertInset(pos, inset);
1028 par->SetFont(pos, font);
1030 } else if (token == "\\Figure") {
1031 inset = new InsetFig(100,100, this);
1033 par->InsertChar(pos, LYX_META_INSET);
1034 par->InsertInset(pos, inset);
1035 par->SetFont(pos, font);
1037 } else if (token == "\\newline") {
1038 par->InsertChar(pos, LYX_META_NEWLINE);
1039 par->SetFont(pos, font);
1041 } else if (token == "\\LyXTable") {
1042 par->table = new LyXTable(lex);
1043 } else if (token == "\\hfill") {
1044 par->InsertChar(pos, LYX_META_HFILL);
1045 par->SetFont(pos, font);
1047 } else if (token == "\\protected_separator") {
1048 par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
1049 par->SetFont(pos, font);
1051 } else if (token == "\\bibitem") { // ale970302
1053 par->bibkey = new InsetBibKey;
1054 par->bibkey->Read(lex);
1055 }else if (token == "\\backslash") {
1056 par->InsertChar(pos, '\\');
1057 par->SetFont(pos, font);
1059 }else if (token == "\\the_end") {
1060 the_end_read = true;
1062 // This should be insurance for the future: (Asger)
1063 lex.printError("Unknown token `$$Token'. "
1064 "Inserting as text.");
1065 int n = token.length();
1066 for (int i=0; i < n; i++) {
1067 par->InsertChar(pos, token[i]);
1068 par->SetFont(pos, font);
1077 paragraph = return_par;
1079 return the_end_read;
1083 bool Buffer::readFile(LyXLex & lex, LyXParagraph * par)
1089 token = lex.GetString();
1090 if (token == "\\lyxformat") { // the first token _must_ be...
1092 format = lex.GetFloat();
1094 if (LYX_FORMAT - format > 0.05) {
1095 printf(_("Warning: need lyxformat %.2f but found %.2f\n"),
1096 LYX_FORMAT, format);
1098 if (format - LYX_FORMAT > 0.05) {
1099 printf(_("ERROR: need lyxformat %.2f but found %.2f\n"),
1100 LYX_FORMAT, format);
1102 bool the_end = readLyXformat2(lex, par);
1103 // Formats >= 2.13 support "\the_end" marker
1106 // Formats >= 2.14 changed papersize stuff
1107 if (format < 2.14) {
1113 WriteAlert(_("Warning!"),
1114 _("Reading of document is not complete"),
1115 _("Maybe the document is truncated"));
1116 // We simulate a safe reading anyways to allow
1117 // users to take the chance... (Asger)
1121 WriteAlert(_("ERROR!"),
1122 _("Old LyX file format found. "
1123 "Use LyX 0.10.x to read this!"));
1127 } else { // "\\lyxformat" not found
1128 WriteAlert(_("ERROR!"), _("Not a LyX file!"));
1131 WriteAlert(_("ERROR!"), _("Unable to read file!"));
1136 // Returns false if unsuccesful
1137 bool Buffer::writeFile(string const & filename, bool flag)
1139 // if flag is false writeFile will not create any GUI
1140 // warnings, only cerr.
1141 // Needed for autosave in background or panic save (Matthias 120496)
1143 if (read_only && (filename == this->filename)) {
1144 // Here we should come with a question if we should
1145 // perform the write anyway.
1147 lyxerr << _("Error! Document is read-only: ")
1148 << filename << endl;
1150 WriteAlert(_("Error! Document is read-only: "), filename);
1154 FileInfo finfo(filename);
1155 if (finfo.exist() && !finfo.writable()) {
1156 // Here we should come with a question if we should
1157 // try to do the save anyway. (i.e. do a chmod first)
1159 lyxerr << _("Error! Cannot write file: ")
1160 << filename << endl;
1162 WriteFSAlert(_("Error! Cannot write file: "), filename);
1166 FilePtr file(filename, FilePtr::truncate);
1169 lyxerr << _("Error! Cannot write file: ")
1170 << filename << endl;
1172 WriteFSAlert(_("Error! Cannot write file: "), filename);
1175 // The top of the file should not be written by params.
1176 // collect some very important information
1177 string userName(getUserName()) ;
1179 // write out a comment in the top of the file
1181 "#This file was created by <%s> %s",
1182 userName.c_str(),(char*)date());
1184 "#LyX 1.0 (C) 1995-1999 Matthias Ettrich"
1185 " and the LyX Team\n");
1187 // at the very beginning the used lyx format
1188 fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
1190 // now write out the buffer parameters.
1191 params.writeFile(file);
1193 char footnoteflag = 0;
1196 // this will write out all the paragraphs
1197 // using recursive descent.
1198 paragraph->writeFile(file, params, footnoteflag, depth);
1200 // Write marker that shows file is complete
1201 fprintf(file, "\n\\the_end\n");
1204 lyxerr << _("Error! Could not close file properly: ")
1205 << filename << endl;
1207 WriteFSAlert(_("Error! Could not close file properly: "),
1215 void Buffer::writeFileAscii(string const & filename, int linelen)
1217 FilePtr file(filename, FilePtr::write);
1221 LyXParagraph * par = paragraph;
1232 LyXParagraph::size_type i;
1251 ref_printed = false;
1255 WriteFSAlert(_("Error: Cannot write file:"), filename);
1258 fname1=TmpFileName();
1262 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE ||
1264 par->previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
1266 /* begins a footnote environment ? */
1267 if (footnoteflag != par->footnoteflag) {
1268 footnoteflag = par->footnoteflag;
1270 j=strlen(string_footnotekinds[par->footnotekind])+4;
1271 if (currlinelen+j > linelen)
1273 fprintf(file, "([%s] ",
1274 string_footnotekinds[par->footnotekind]);
1279 /* begins or ends a deeper area ?*/
1280 if (depth != par->depth) {
1281 if (par->depth > depth) {
1282 while (par->depth > depth) {
1287 while (par->depth < depth) {
1293 /* First write the layout */
1294 tmp = textclasslist.NameOfLayout(params.textclass,par->layout);
1295 if (tmp == "Itemize") {
1297 ltype_depth = depth+1;
1298 } else if (tmp =="Enumerate") {
1300 ltype_depth = depth+1;
1301 } else if (strstr(tmp.c_str(),"ection")) {
1303 ltype_depth = depth+1;
1304 } else if (strstr(tmp.c_str(),"aragraph")) {
1306 ltype_depth = depth+1;
1307 } else if (tmp == "Description") {
1309 ltype_depth = depth+1;
1310 } else if (tmp == "Abstract") {
1313 } else if (tmp == "Bibliography") {
1321 /* maybe some vertical spaces */
1323 /* the labelwidthstring used in lists */
1327 /* some pagebreaks? */
1331 /* what about the alignment */
1334 /* dummy layout, that means a footnote ended */
1335 footnoteflag = LyXParagraph::NO_FOOTNOTE;
1336 fprintf(file, ") ");
1340 /* It might be a table */
1342 if (!lyxrc->ascii_roff_command.empty() &&
1343 lyxrc->ascii_roff_command != "none") {
1344 RoffAsciiTable(file,par);
1350 cells = par->table->columns;
1351 clen = new int [cells];
1352 memset(clen,0,sizeof(int)*cells);
1354 for (i = 0, j = 0, h = 1; i < par->size(); ++i, ++h) {
1356 for (i = 0, j = 0, h=1; i < par->last; i++, h++) {
1358 c = par->GetChar(i);
1359 if (c == LYX_META_INSET) {
1360 if ((inset = par->GetInset(i))) {
1364 WriteFSAlert(_("Error: Cannot open temporary file:"), fname1);
1367 inset->Latex(fp,-1);
1369 remove(fname1.c_str());
1371 } else if (c == LYX_META_NEWLINE) {
1375 j = (++j) % par->table->NumberOfCellsInRow(actcell);
1383 font1 = LyXFont(LyXFont::ALL_INHERIT);
1386 for (i = 0, actpos = 1; i < par->size(); ++i, ++actpos) {
1388 for (i = 0,actpos=1; i < par->last; i++, actpos++) {
1390 if (!i && !footnoteflag && !noparbreak){
1391 fprintf(file, "\n\n");
1392 for(j=0; j<depth; j++)
1394 currlinelen = depth*2;
1396 case 0: /* Standart */
1397 case 4: /* (Sub)Paragraph */
1398 case 5: /* Description */
1400 case 6: /* Abstract */
1401 fprintf(file, "Abstract\n\n");
1403 case 7: /* Bibliography */
1405 fprintf(file, "References\n\n");
1410 fprintf(file,"%s ",par->labelstring.c_str());
1413 if (ltype_depth > depth) {
1414 for(j=ltype_depth-1; j>depth; j--)
1416 currlinelen += (ltype_depth-depth)*2;
1419 for(j=0;j<cells;j++) {
1421 for(h=0; h<(clen[j]+1); h++)
1424 fprintf(file,"+\n");
1425 for(j=0; j<depth; j++)
1427 currlinelen = depth*2;
1428 if (ltype_depth > depth) {
1429 for(j=ltype_depth; j>depth; j--)
1431 currlinelen += (ltype_depth-depth)*2;
1436 font2 = par->GetFontSettings(i);
1437 if (font1.latex() != font2.latex()) {
1438 if (font2.latex() == LyXFont::OFF)
1446 c = par->GetChar(i);
1450 case LYX_META_INSET:
1451 if ((inset = par->GetInset(i))) {
1453 inset->Latex(file,-1);
1454 currlinelen += (ftell(file) - fpos);
1455 actpos += (ftell(file) - fpos) - 1;
1458 case LYX_META_NEWLINE:
1460 if (par->table->NumberOfCellsInRow(actcell) <= cell) {
1461 for(j=actpos;j<clen[cell-1];j++)
1463 fprintf(file," |\n");
1464 for(j=0; j<depth; j++)
1466 currlinelen = depth*2;
1467 if (ltype_depth > depth) {
1468 for(j=ltype_depth; j>depth; j--)
1470 currlinelen += (ltype_depth-depth)*2;
1472 for(j=0;j<cells;j++) {
1474 for(h=0; h<(clen[j]+1); h++)
1477 fprintf(file,"+\n");
1478 for(j=0; j<depth; j++)
1480 currlinelen = depth*2;
1481 if (ltype_depth > depth) {
1482 for(j=ltype_depth; j>depth; j--)
1484 currlinelen += (ltype_depth-depth)*2;
1489 for(j=actpos; j<clen[cell-1]; j++)
1491 fprintf(file, " | ");
1495 currlinelen = actpos = 0;
1497 fprintf(file, "\n");
1498 for(j=0; j<depth; j++)
1500 currlinelen = depth*2;
1501 if (ltype_depth > depth) {
1502 for(j=ltype_depth; j>depth; j--)
1504 currlinelen += (ltype_depth-depth)*2;
1508 case LYX_META_HFILL:
1509 fprintf(file, "\t");
1511 case LYX_META_PROTECTED_SEPARATOR:
1515 fprintf(file, "\\");
1519 if (currlinelen > linelen - 10
1520 && c == ' ' && i + 2 < par->size()) {
1522 if (currlinelen > (linelen-10) \
1523 && c==' ' && (i+2 < par->last)) {
1525 fprintf(file, "\n");
1526 for(j = 0; j < depth; ++j)
1528 currlinelen = depth * 2;
1529 if (ltype_depth > depth) {
1530 for(j = ltype_depth;
1533 currlinelen += (ltype_depth-depth)*2;
1535 } else if (c != '\0')
1536 fprintf(file, "%c", c);
1538 lyxerr.debug() << "writeAsciiFile: NULL char in structure." << endl;
1544 for(j=actpos;j<clen[cell-1];j++)
1546 fprintf(file," |\n");
1547 for(j=0; j<depth; j++)
1549 currlinelen = depth*2;
1550 if (ltype_depth > depth) {
1551 for(j=ltype_depth; j>depth; j--)
1553 currlinelen += (ltype_depth-depth)*2;
1555 for(j=0;j<cells;j++) {
1557 for(h=0; h<(clen[j]+1); h++)
1560 fprintf(file,"+\n");
1566 fprintf(file, "\n");
1570 void Buffer::makeLaTeXFile(string const & filename,
1571 string const & original_path,
1572 bool nice, bool only_body)
1574 lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
1575 params.textclass = GetCurrentTextClass();
1576 niceFile = nice; // this will be used by Insetincludes.
1578 tex_code_break_column = lyxrc->ascii_linelen;
1580 LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
1582 FilePtr file(filename, FilePtr::write);
1584 WriteFSAlert(_("Error: Cannot write file:"),filename);
1588 // validate the buffer.
1589 lyxerr[Debug::LATEX] << " Validating buffer..." << endl;
1590 LaTeXFeatures features(tclass.numLayouts());
1592 lyxerr[Debug::LATEX] << " Buffer validation done." << endl;
1595 // The starting paragraph of the coming rows is the
1596 // first paragraph of the document. (Asger)
1597 texrow.start(paragraph, 0);
1599 string userName(getUserName());
1602 if (!only_body && nice) {
1603 LFile += "%% This LaTeX-file was created by <";
1604 LFile += userName + "> " + (char*)date();
1605 LFile += "%% LyX 1.0 (C) 1995-1999 by Matthias Ettrich and the LyX Team\n";
1606 LFile += "\n%% Do not edit this file unless you know what you are doing.\n";
1612 lyxerr.debug() << "lyx header finished" << endl;
1613 // There are a few differences between nice LaTeX and usual files:
1614 // usual is \batchmode, uses \listfiles and has a
1615 // special input@path to allow the including of figures
1616 // with either \input or \includegraphics (what figinsets do).
1617 // batchmode is not set if there is a tex_code_break_column.
1618 // In this case somebody is interested in the generated LaTeX,
1619 // so this is OK. input@path is set when the actual parameter
1620 // original_path is set. This is done for usual tex-file, but not
1621 // for nice-latex-file. (Matthias 250696)
1624 // code for usual, NOT nice-latex-file
1625 LFile += "\\batchmode\n"; // changed
1626 // from \nonstopmode
1628 // We don't need listfiles anymore
1629 //LFile += "\\listfiles\n";
1632 if (!original_path.empty()) {
1633 LFile += "\\makeatletter\n";
1635 LFile += "\\def\\input@path{{" + original_path
1638 LFile += "\\makeatother\n";
1642 LFile += "\\documentclass";
1644 string options; // the document class options.
1646 if (tokenPos(tclass.opt_fontsize(), '|',params.fontsize) >= 0) {
1647 // only write if existing in list (and not default)
1648 options += params.fontsize;
1653 if (!params.use_geometry &&
1654 (params.paperpackage == PACKAGE_NONE)) {
1655 switch (params.papersize) {
1657 options += "a4paper,";
1659 case PAPER_USLETTER:
1660 options += "letterpaper,";
1663 options += "a5paper,";
1666 options += "b5paper,";
1668 case PAPER_EXECUTIVEPAPER:
1669 options += "executivepaper,";
1671 case PAPER_LEGALPAPER:
1672 options += "legalpaper,";
1678 if (params.sides != tclass.sides()) {
1679 if (params.sides == 2)
1680 options += "twoside,";
1682 options += "oneside,";
1686 if (params.columns != tclass.columns()) {
1687 if (params.columns == 2)
1688 options += "twocolumn,";
1690 options += "onecolumn,";
1693 if (!params.use_geometry && params.orientation == ORIENTATION_LANDSCAPE)
1694 options += "landscape,";
1696 // language should be a parameter to \documentclass
1697 if (params.language != "default") {
1698 options += params.language + ',';
1701 // the user-defined options
1702 if (!params.options.empty()) {
1703 options += params.options + ',';
1706 if (!options.empty()){
1707 options = strip(options, ',');
1714 LFile += textclasslist.LatexnameOfClass(params.textclass);
1717 // end of \documentclass defs
1719 // font selection must be done before loading fontenc.sty
1720 if (params.fonts != "default") {
1721 LFile += "\\usepackage{" + params.fonts + "}\n";
1724 // this one is not per buffer
1725 if (lyxrc->fontenc != "default") {
1726 LFile += "\\usepackage[" + lyxrc->fontenc
1730 if (params.inputenc != "default") {
1731 LFile += "\\usepackage[" + params.inputenc
1736 /* at the very beginning the text parameters */
1737 if (params.paperpackage != PACKAGE_NONE) {
1738 switch (params.paperpackage) {
1740 LFile += "\\usepackage{a4}\n";
1743 case PACKAGE_A4WIDE:
1744 LFile += "\\usepackage{a4wide}\n";
1747 case PACKAGE_WIDEMARGINSA4:
1748 LFile += "\\usepackage[widemargins]{a4}\n";
1753 if (params.use_geometry) {
1754 LFile += "\\usepackage{geometry}\n";
1756 LFile += "\\geometry{verbose";
1757 if (params.orientation == ORIENTATION_LANDSCAPE)
1758 LFile += ",landscape";
1759 switch (params.papersize2) {
1760 case VM_PAPER_CUSTOM:
1761 if (!params.paperwidth.empty())
1762 LFile += ",paperwidth="
1763 + params.paperwidth;
1764 if (!params.paperheight.empty())
1765 LFile += ",paperheight="
1766 + params.paperheight;
1768 case VM_PAPER_USLETTER:
1769 LFile += ",letterpaper";
1771 case VM_PAPER_USLEGAL:
1772 LFile += ",legalpaper";
1774 case VM_PAPER_USEXECUTIVE:
1775 LFile += ",executivepaper";
1778 LFile += ",a3paper";
1781 LFile += ",a4paper";
1784 LFile += ",a5paper";
1787 LFile += ",b3paper";
1790 LFile += ",b4paper";
1793 LFile += ",b5paper";
1796 // default papersize ie VM_PAPER_DEFAULT
1797 switch (lyxrc->default_papersize) {
1798 case PAPER_DEFAULT: // keep compiler happy
1799 case PAPER_USLETTER:
1800 LFile += ",letterpaper";
1802 case PAPER_LEGALPAPER:
1803 LFile += ",legalpaper";
1805 case PAPER_EXECUTIVEPAPER:
1806 LFile += ",executivepaper";
1809 LFile += ",a3paper";
1812 LFile += ",a4paper";
1815 LFile += ",a5paper";
1818 LFile += ",b5paper";
1822 if (!params.topmargin.empty())
1823 LFile += ",tmargin=" + params.topmargin;
1824 if (!params.bottommargin.empty())
1825 LFile += ",bmargin=" + params.bottommargin;
1826 if (!params.leftmargin.empty())
1827 LFile += ",lmargin=" + params.leftmargin;
1828 if (!params.rightmargin.empty())
1829 LFile += ",rmargin=" + params.rightmargin;
1830 if (!params.headheight.empty())
1831 LFile += ",headheight=" + params.headheight;
1832 if (!params.headsep.empty())
1833 LFile += ",headsep=" + params.headsep;
1834 if (!params.footskip.empty())
1835 LFile += ",footskip=" + params.footskip;
1839 if (params.use_amsmath
1840 && !prefixIs(textclasslist.LatexnameOfClass(params.textclass), "ams")) {
1841 LFile += "\\usepackage{amsmath}\n";
1844 if (tokenPos(tclass.opt_pagestyle(), '|',params.pagestyle) >= 0) {
1845 if (params.pagestyle == "fancy") {
1846 LFile += "\\usepackage{fancyhdr}\n";
1849 LFile += "\\pagestyle{" + params.pagestyle + "}\n";
1853 // We try to load babel late, in case it interferes
1854 // with other packages.
1855 if (params.language != "default") {
1856 LFile += "\\usepackage{babel}\n";
1860 if (params.secnumdepth != tclass.secnumdepth()) {
1861 LFile += "\\setcounter{secnumdepth}{";
1862 LFile += tostr(params.secnumdepth);
1866 if (params.tocdepth != tclass.tocdepth()) {
1867 LFile += "\\setcounter{tocdepth}{";
1868 LFile += tostr(params.tocdepth);
1873 if (params.paragraph_separation) {
1874 switch (params.defskip.kind()) {
1875 case VSpace::SMALLSKIP:
1876 LFile += "\\setlength\\parskip{\\smallskipamount}\n";
1878 case VSpace::MEDSKIP:
1879 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1881 case VSpace::BIGSKIP:
1882 LFile += "\\setlength\\parskip{\\bigskipamount}\n";
1884 case VSpace::LENGTH:
1885 LFile += "\\setlength\\parskip{"
1886 + params.defskip.length().asLatexString()
1889 default: // should never happen // Then delete it.
1890 LFile += "\\setlength\\parskip{\\medskipamount}\n";
1895 LFile += "\\setlength\\parindent{0pt}\n";
1899 // Write out what we've generated so far...and reset LFile
1900 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
1903 // Now insert the LyX specific LaTeX commands...
1904 string preamble, tmppreamble;
1906 // The optional packages;
1907 preamble = features.getPackages(params);
1909 // this might be useful...
1910 preamble += "\n\\makeatletter\n\n";
1912 // Some macros LyX will need
1913 tmppreamble = features.getMacros(params);
1915 if (!tmppreamble.empty()) {
1916 preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1917 "LyX specific LaTeX commands.\n"
1918 + tmppreamble + '\n';
1921 // the text class specific preamble
1922 tmppreamble = features.getTClassPreamble(params);
1923 if (!tmppreamble.empty()) {
1924 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1925 "Textclass specific LaTeX commands.\n"
1926 + tmppreamble + '\n';
1929 /* the user-defined preamble */
1930 if (!params.preamble.empty()) {
1931 preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1932 "User specified LaTeX commands.\n"
1933 + params.preamble + '\n';
1936 preamble += "\\makeatother\n\n";
1938 // Itemize bullet settings need to be last in case the user
1939 // defines their own bullets that use a package included
1940 // in the user-defined preamble -- ARRae
1941 for (int i = 0; i < 4; ++i) {
1942 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
1943 preamble += "\\renewcommand\\labelitemi";
1945 // `i' is one less than the item to modify
1958 preamble += "[0]{" + params.user_defined_bullets[i].getText() + "}\n";
1962 for (int j = countChar(preamble, '\n'); j-- ;) {
1966 // A bit faster than printing a char at a time I think.
1967 fwrite(preamble.c_str(), sizeof(char),
1968 preamble.length(), file);
1971 LFile += "\\begin{document}\n\n";
1975 lyxerr.debug() << "preamble finished, now the body." << endl;
1977 bool was_title = false;
1978 bool already_title = false;
1984 LyXParagraph * par = paragraph;
1990 lyxerr[Debug::LATEX] << "Error in MakeLateXFile."
1992 LyXLayout const & layout = textclasslist.Style(params.textclass,
1995 if (layout.intitle) {
1996 if (already_title) {
1997 lyxerr <<"Error in MakeLatexFile: You"
1998 " should not mix title layouts"
1999 " with normal ones." << endl;
2002 } else if (was_title && !already_title) {
2003 LFile += "\\maketitle\n";
2005 already_title = true;
2008 // We are at depth 0 so we can just use
2009 // ordinary \footnote{} generation
2010 // flag this with ftcount
2012 if (layout.isEnvironment()
2013 || par->pextra_type != PEXTRA_NONE) {
2014 par = par->TeXEnvironment(LFile, texrow,
2015 ftnote, ft_texrow, ftcount);
2017 par = par->TeXOnePar(LFile, texrow,
2018 ftnote, ft_texrow, ftcount);
2021 // Write out what we've generated...and reset LFile
2024 LFile += "\\addtocounter{footnote}{-";
2025 LFile += tostr(ftcount - 1);
2029 texrow += ft_texrow;
2034 if (loop_count == 2) {
2035 // fwrite()ing every second time through the loop
2036 // gains a few extra % of speed; going higher than
2037 // 2 will slow things down again. I'll look at
2038 // LFile.length() in a future revision. ARRae
2039 fwrite(LFile.c_str(), sizeof(char),
2040 LFile.length(), file);
2046 // It might be that we only have a title in this document
2047 if (was_title && !already_title) {
2048 LFile += "\\maketitle\n";
2053 LFile += "\\end{document}\n";
2056 lyxerr[Debug::LATEX] << "makeLaTeXFile...done" << endl;
2058 lyxerr[Debug::LATEX] << "LaTeXFile for inclusion made."
2062 // Just to be sure. (Asger)
2065 // Write out what we've generated...and reset LFile
2066 fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
2069 // tex_code_break_column's value is used to decide
2070 // if we are in batchmode or not (within mathed_write()
2071 // in math_write.C) so we must set it to a non-zero
2072 // value when we leave otherwise we save incorrect .lyx files.
2073 tex_code_break_column = lyxrc->ascii_linelen;
2076 WriteFSAlert(_("Error! Could not close file properly:"), filename);
2078 lyxerr.debug() << "Finished making latex file." << endl;
2082 bool Buffer::isLatex()
2084 return textclasslist.TextClass(params.textclass).outputType() == LATEX;
2088 bool Buffer::isLinuxDoc()
2090 return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC;
2094 bool Buffer::isLiterate()
2096 return textclasslist.TextClass(params.textclass).outputType() == LITERATE;
2100 bool Buffer::isDocBook()
2102 return textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2106 bool Buffer::isSGML()
2108 return textclasslist.TextClass(params.textclass).outputType() == LINUXDOC ||
2109 textclasslist.TextClass(params.textclass).outputType() == DOCBOOK;
2113 void Buffer::sgmlOpenTag(FILE * file, int depth, string const & latexname) const
2115 static char *space[] = {" "," "," "," "," "," "," ",
2118 fprintf(file, "%s<%s>\n", space[depth], latexname.c_str());
2122 void Buffer::sgmlCloseTag(FILE * file, int depth, string const & latexname) const
2124 static char *space[] = {" "," "," "," "," "," "," ",
2127 fprintf(file, "%s</%s>\n", space[depth], latexname.c_str());
2131 void Buffer::makeLinuxDocFile(string const & filename, int column)
2133 LyXParagraph * par = paragraph;
2135 string top_element=textclasslist.LatexnameOfClass(params.textclass);
2136 string environment_stack[10];
2139 int depth = 0; /* paragraph depth */
2141 FilePtr file(filename, FilePtr::write);
2142 tex_code_break_column = column;
2145 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2152 if (params.preamble.empty()) {
2153 fprintf(file, "<!doctype linuxdoc system>\n\n");
2156 fprintf(file, "<!doctype linuxdoc system \n [ %s \n]>\n\n",
2157 params.preamble.c_str() );
2160 string userName(getUserName());
2161 fprintf(file, "<!-- LinuxDoc file was created by LyX 1.0 (C) 1995-1999 ");
2162 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2164 if(params.options.empty())
2165 sgmlOpenTag(file,0,top_element);
2167 string top = top_element;
2169 top += params.options;
2170 sgmlOpenTag(file,0,top);
2174 int desc_on=0; /* description mode*/
2175 LyXLayout const & style=textclasslist.Style(GetCurrentTextClass(), par->layout);
2176 par->AutoDeleteInsets();
2178 /* treat <toc> as a special case for compatibility with old code */
2179 if (par->GetChar(0) == LYX_META_INSET) {
2180 Inset *inset = par->GetInset(0);
2181 char lyx_code = inset->LyxCode();
2182 if (lyx_code ==Inset::TOC_CODE){
2184 sgmlOpenTag(file, depth, temp);
2187 linuxDocHandleFootnote(file, par, depth);
2192 /* environment tag closing */
2193 for( ;depth > par->depth; depth--) {
2194 sgmlCloseTag(file,depth,environment_stack[depth]);
2195 environment_stack[depth].clear();
2198 /* write opening SGML tags */
2199 switch(style.latextype) {
2200 case LATEX_PARAGRAPH:
2201 if(depth == par->depth
2202 && !environment_stack[depth].empty()) {
2203 sgmlCloseTag(file,depth,environment_stack[depth]);
2204 environment_stack[depth].clear();
2208 fprintf(file,"</p>");
2210 sgmlOpenTag(file,depth,style.latexname());
2215 LinuxDocError(par, 0, _("Error : Wrong depth for LatexType Command.\n"));
2217 if (!environment_stack[depth].empty()){
2218 sgmlCloseTag(file,depth,environment_stack[depth]);
2219 fprintf(file, "</p>");
2222 environment_stack[depth].clear();
2223 sgmlOpenTag(file,depth, style.latexname());
2226 case LATEX_ENVIRONMENT:
2227 case LATEX_ITEM_ENVIRONMENT:
2228 if(depth == par->depth
2229 && environment_stack[depth] != style.latexname()
2230 && !environment_stack[depth].empty()) {
2232 sgmlCloseTag(file,depth,environment_stack[depth]);
2233 environment_stack[depth].clear();
2235 if (depth < par->depth) {
2237 environment_stack[depth].clear();
2239 if (environment_stack[depth] != style.latexname()) {
2242 sgmlOpenTag(file,depth,temp);
2244 environment_stack[depth] = style.latexname();
2245 sgmlOpenTag(file,depth,environment_stack[depth]);
2247 if(style.latextype == LATEX_ENVIRONMENT) break;
2249 desc_on =(style.labeltype == LABEL_MANUAL);
2256 sgmlOpenTag(file,depth+1,item_name);
2259 sgmlOpenTag(file, depth, style.latexname());
2264 SimpleLinuxDocOnePar(file, par, desc_on, depth);
2267 linuxDocHandleFootnote(file,par,depth);
2269 while(par && par->IsDummy());
2272 /* write closing SGML tags */
2273 switch(style.latextype) {
2275 case LATEX_ENVIRONMENT:
2276 case LATEX_ITEM_ENVIRONMENT:
2279 sgmlCloseTag(file, depth, style.latexname());
2287 /* Close open tags */
2288 for(;depth>0;depth--)
2289 sgmlCloseTag(file,depth,environment_stack[depth]);
2291 if(!environment_stack[depth].empty())
2292 sgmlCloseTag(file,depth,environment_stack[depth]);
2294 fprintf(file, "\n\n");
2295 sgmlCloseTag(file,0,top_element);
2298 WriteFSAlert(_("Error! Could not close file properly:"),
2304 void Buffer::linuxDocHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2306 string tag="footnote";
2308 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2309 sgmlOpenTag(file,depth+1,tag);
2310 SimpleLinuxDocOnePar(file, par, 0,depth+1);
2311 sgmlCloseTag(file,depth+1,tag);
2316 void Buffer::DocBookHandleCaption(FILE *file, string &inner_tag,
2317 int const depth, int desc_on,
2320 LyXParagraph *tpar = par;
2321 string tmp_par, extra_par;
2322 while (tpar && (tpar->footnoteflag != LyXParagraph::NO_FOOTNOTE) &&
2323 (tpar->layout != textclasslist.NumberOfLayout(params.textclass,"Caption").second))
2326 tpar->layout==textclasslist.NumberOfLayout(params.textclass,"Caption").second) {
2327 sgmlOpenTag(file,depth+1,inner_tag);
2328 SimpleDocBookOnePar(tmp_par,extra_par,tpar,desc_on,depth+2);
2329 tmp_par = strip(tmp_par);
2330 tmp_par = frontStrip(tmp_par);
2331 fprintf(file,"%s",tmp_par.c_str());
2332 sgmlCloseTag(file,depth+1,inner_tag);
2333 if(!extra_par.empty())
2334 fprintf(file,"%s",extra_par.c_str());
2338 void Buffer::DocBookHandleFootnote(FILE *file,LyXParagraph* &par, int const depth)
2340 string tag,inner_tag;
2341 string tmp_par,extra_par;
2342 bool inner_span = false;
2345 // This is not how I like to see enums. They should not be anonymous
2346 // and variables of its type should not be declared right after the
2347 // last brace. (Lgb)
2354 } last=NO_ONE, present=FOOTNOTE_LIKE;
2356 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2359 if(!tmp_par.empty()) {
2360 fprintf(file,"%s",tmp_par.c_str());
2362 sgmlCloseTag(file,depth+1,inner_tag);
2363 sgmlOpenTag(file,depth+1,inner_tag);
2369 fprintf(file,"%s",tmp_par.c_str());
2370 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2371 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2372 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2375 switch (par->footnotekind) {
2376 case LyXParagraph::FOOTNOTE:
2377 case LyXParagraph::ALGORITHM:
2380 present=FOOTNOTE_LIKE;
2383 case LyXParagraph::MARGIN:
2386 present=MARGIN_LIKE;
2389 case LyXParagraph::FIG:
2390 case LyXParagraph::WIDE_FIG:
2396 case LyXParagraph::TAB:
2397 case LyXParagraph::WIDE_TAB:
2404 sgmlOpenTag(file,depth,tag);
2405 if ((present == TAB_LIKE) || (present == FIG_LIKE)) {
2406 DocBookHandleCaption(file, inner_tag, depth,
2410 sgmlOpenTag(file,depth+1,inner_tag);
2413 // ignore all caption here, we processed them above!!!
2414 if (par->layout != textclasslist.NumberOfLayout(params.textclass,
2415 "Caption").second) {
2416 SimpleDocBookOnePar(tmp_par,extra_par,par,
2419 tmp_par = frontStrip(strip(tmp_par));
2424 fprintf(file,"%s",tmp_par.c_str());
2425 if(!inner_tag.empty()) sgmlCloseTag(file,depth+1,inner_tag);
2426 if(!extra_par.empty()) fprintf(file,"%s",extra_par.c_str());
2427 if(!tag.empty()) sgmlCloseTag(file,depth,tag);
2432 /* push a tag in a style stack */
2433 void Buffer::push_tag(FILE *file, char const *tag,
2434 int& pos, char stack[5][3])
2438 /* pop all previous tags */
2439 for (j=pos; j>=0; j--)
2440 fprintf(file, "</%s>", stack[j]);
2443 sprintf(stack[++pos], "%s", tag);
2446 for (j=0; j<=pos; j++)
2447 fprintf(file, "<%s>", stack[j]);
2451 // pop a tag from a style stack
2452 void Buffer::pop_tag(FILE *file, char const * tag,
2453 int& pos, char stack[5][3])
2457 // pop all tags till specified one
2458 for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
2459 fprintf(file, "</%s>", stack[j]);
2462 fprintf(file, "</%s>", tag);
2464 // push all tags, but the specified one
2465 for (j=j+1; j<=pos; j++) {
2466 fprintf(file, "<%s>", stack[j]);
2467 strcpy(stack[j-1], stack[j]);
2473 /* handle internal paragraph parsing -- layout already processed */
2475 // checks, if newcol chars should be put into this line
2476 // writes newline, if necessary.
2478 void linux_doc_line_break(FILE *file, unsigned int &colcount, const unsigned int newcol)
2481 if (colcount > lyxrc->ascii_linelen) {
2482 fprintf(file, "\n");
2483 colcount = newcol; // assume write after this call
2488 void Buffer::SimpleLinuxDocOnePar(FILE *file, LyXParagraph *par, int desc_on, int const depth)
2490 LyXFont font1,font2;
2494 LyXParagraph::size_type main_body;
2499 LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
2501 char family_type = 0; // family font flag
2502 bool is_bold = false; // series font flag
2503 char shape_type = 0; // shape font flag
2504 bool is_em = false; // emphasis (italic) font flag
2506 int stack_num = -1; // style stack position
2507 char stack[5][3]; // style stack
2508 unsigned int char_line_count = 5; // Heuristic choice ;-)
2510 if (style.labeltype != LABEL_MANUAL)
2513 main_body = par->BeginningOfMainBody();
2515 /* gets paragraph main font */
2517 font1 = style.labelfont;
2522 /* parsing main loop */
2524 for (LyXParagraph::size_type i = 0;
2525 i < par->size(); ++i) {
2527 for (int i = 0; i < par->last; i++) {
2530 /* handle quote tag */
2531 if (i == main_body && !par->IsDummy()) {
2536 font2 = par->getFont(i);
2538 if (font1.family() != font2.family()) {
2539 switch(family_type) {
2541 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2542 push_tag(file, "tt", stack_num, stack);
2545 else if (font2.family() == LyXFont::SANS_FAMILY) {
2546 push_tag(file, "sf", stack_num, stack);
2551 pop_tag(file, "tt", stack_num, stack);
2552 if (font2.family() == LyXFont::SANS_FAMILY) {
2553 push_tag(file, "sf", stack_num, stack);
2561 pop_tag(file, "sf", stack_num, stack);
2562 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
2563 push_tag(file, "tt", stack_num, stack);
2572 /* handle bold face */
2573 if (font1.series() != font2.series()) {
2574 if (font2.series() == LyXFont::BOLD_SERIES) {
2575 push_tag(file, "bf", stack_num, stack);
2579 pop_tag(file, "bf", stack_num, stack);
2584 /* handle italic and slanted fonts */
2585 if (font1.shape() != font2.shape()) {
2586 switch(shape_type) {
2588 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2589 push_tag(file, "it", stack_num, stack);
2592 else if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2593 push_tag(file, "sl", stack_num, stack);
2598 pop_tag(file, "it", stack_num, stack);
2599 if (font2.shape() == LyXFont::SLANTED_SHAPE) {
2600 push_tag(file, "sl", stack_num, stack);
2608 pop_tag(file, "sl", stack_num, stack);
2609 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
2610 push_tag(file, "it", stack_num, stack);
2618 /* handle <em> tag */
2619 if (font1.emph() != font2.emph()) {
2620 if (font2.emph() == LyXFont::ON) {
2621 push_tag(file, "em", stack_num, stack);
2624 pop_tag(file, "em", stack_num, stack);
2629 c = par->GetChar(i);
2631 if (font2.latex() == LyXFont::ON) {
2632 // "TeX"-Mode on ==> SGML-Mode on.
2634 fprintf(file, "%c", c); // see LaTeX-Generation...
2636 } else if (c == LYX_META_INSET) {
2637 inset = par->GetInset(i);
2639 inset->Linuxdoc(tmp_out);
2640 fprintf(file,"%s",tmp_out.c_str());
2644 if (par->linuxDocConvertChar(c, sgml_string)
2645 && !style.free_spacing) { // in freespacing
2647 // non-breaking characters
2651 linux_doc_line_break(file, char_line_count, 6);
2652 fprintf(file, "</tag>");
2656 linux_doc_line_break(file, char_line_count, 1);
2657 fprintf(file, "%c", c);
2661 fprintf(file, "%s", sgml_string.c_str());
2662 char_line_count += sgml_string.length();
2668 /* needed if there is an optional argument but no contents */
2670 if (main_body > 0 && main_body == par->size()) {
2674 if (main_body > 0 && main_body == par->last) {
2678 /* pop all defined Styles */
2679 for (j = stack_num; j >= 0; j--) {
2680 linux_doc_line_break(file,
2682 3+strlen(stack[j]));
2683 fprintf(file, "</%s>", stack[j]);
2686 /* resets description flag correctly */
2689 /* <tag> not closed... */
2690 linux_doc_line_break(file, char_line_count, 6);
2691 fprintf(file, "</tag>");
2694 /* fprintf(file, "</p>");*/
2700 /* print an error message */
2701 void Buffer::LinuxDocError(LyXParagraph * par, int pos,
2702 char const * message)
2704 InsetError * new_inset;
2706 /* insert an error marker in text */
2707 new_inset = new InsetError(message);
2708 par->InsertChar(pos, LYX_META_INSET);
2709 par->InsertInset(pos, new_inset);
2712 // This constant defines the maximum number of
2713 // environment layouts that can be nesteded.
2714 // The same applies for command layouts.
2715 // These values should be more than enough.
2716 // José Matos (1999/07/22)
2718 enum { MAX_NEST_LEVEL = 25};
2720 void Buffer::makeDocBookFile(string const & filename, int column)
2722 LyXParagraph * par = paragraph;
2724 string top_element=textclasslist.LatexnameOfClass(params.textclass);
2725 string environment_stack[MAX_NEST_LEVEL];
2726 string environment_inner[MAX_NEST_LEVEL];
2727 string command_stack[MAX_NEST_LEVEL];
2728 bool command_flag=false;
2729 int command_depth=0,command_base=0,cmd_depth=0;
2731 string item_name,command_name;
2732 string c_depth,c_params,tmps;
2734 int depth=0; /* paragraph depth */
2736 FilePtr file(filename, FilePtr::write);
2737 tex_code_break_column = column;
2740 WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
2748 "<!doctype %s public \"-//OASIS//DTD DocBook V3.1//EN\"",
2749 top_element.c_str());
2751 if (params.preamble.empty())
2752 fprintf(file, ">\n\n");
2754 fprintf(file, "\n [ %s \n]>\n\n",params.preamble.c_str() );
2756 string userName(getUserName());
2758 "<!-- DocBook file was created by LyX 1.0 (C) 1995-1999\n");
2759 fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
2761 if(params.options.empty())
2762 sgmlOpenTag(file,0,top_element);
2764 string top = top_element;
2766 top += params.options;
2767 sgmlOpenTag(file,0,top);
2771 int desc_on=0; /* description mode*/
2772 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2774 par->AutoDeleteInsets();
2776 /* environment tag closing */
2777 for( ;depth > par->depth; depth--) {
2778 if(environment_inner[depth] != "!-- --") {
2779 item_name="listitem";
2780 sgmlCloseTag(file,command_depth+depth,
2782 if( environment_inner[depth] == "varlistentry")
2783 sgmlCloseTag(file,depth+command_depth,
2784 environment_inner[depth]);
2786 sgmlCloseTag(file,depth+command_depth,
2787 environment_stack[depth]);
2788 environment_stack[depth].clear();
2789 environment_inner[depth].clear();
2792 if(depth == par->depth
2793 && environment_stack[depth] != style.latexname()
2794 && !environment_stack[depth].empty()) {
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]);
2804 sgmlCloseTag(file,depth+command_depth,
2805 environment_stack[depth]);
2807 environment_stack[depth].clear();
2808 environment_inner[depth].clear();
2811 // Write opening SGML tags.
2812 switch(style.latextype) {
2813 case LATEX_PARAGRAPH:
2814 if(style.latexname() != "dummy")
2815 sgmlOpenTag(file, depth+command_depth,
2821 LinuxDocError(par, 0,
2822 _("Error : Wrong depth for "
2823 "LatexType Command.\n"));
2825 command_name = style.latexname();
2827 tmps = style.latexparam();
2828 c_params = split(tmps, c_depth,'|');
2830 cmd_depth=atoi(c_depth.c_str());
2833 if(cmd_depth<command_base) {
2834 for(int j = command_depth;
2835 j >= command_base; j--)
2836 if(!command_stack[j].empty())
2837 sgmlCloseTag(file,j,command_stack[j]);
2838 command_depth=command_base=cmd_depth;
2840 else if(cmd_depth<=command_depth) {
2841 for(int j= command_depth;
2842 j >= cmd_depth; j--)
2844 if(!command_stack[j].empty())
2845 sgmlCloseTag(file,j,command_stack[j]);
2846 command_depth=cmd_depth;
2849 command_depth=cmd_depth;
2852 command_depth = command_base = cmd_depth;
2853 command_flag = true;
2855 command_stack[command_depth]=command_name;
2857 // treat label as a special case for
2858 // more WYSIWYM handling.
2859 if (par->GetChar(0) == LYX_META_INSET) {
2860 Inset *inset = par->GetInset(0);
2861 char lyx_code = inset->LyxCode();
2862 if (lyx_code ==Inset::LABEL_CODE){
2863 command_name+= " id=\"";
2864 command_name+=((InsetCommand *) inset)->getContents();
2870 sgmlOpenTag(file,depth+command_depth, command_name);
2872 sgmlOpenTag(file,depth+1+command_depth,item_name);
2875 case LATEX_ENVIRONMENT:
2876 case LATEX_ITEM_ENVIRONMENT:
2877 if (depth < par->depth) {
2879 environment_stack[depth].clear();
2882 if (environment_stack[depth] != style.latexname()) {
2883 environment_stack[depth]= style.latexname();
2884 environment_inner[depth]= "!-- --";
2885 sgmlOpenTag(file, depth + command_depth,
2886 environment_stack[depth]);
2888 if(environment_inner[depth] != "!-- --") {
2889 item_name="listitem";
2891 command_depth + depth,
2893 if (environment_inner[depth] == "varlistentry")
2895 depth+command_depth,
2896 environment_inner[depth]);
2900 if(style.latextype == LATEX_ENVIRONMENT) {
2901 if(!style.latexparam().empty())
2902 sgmlOpenTag(file, depth+command_depth,
2903 style.latexparam());
2907 desc_on =(style.labeltype == LABEL_MANUAL);
2910 environment_inner[depth]="varlistentry";
2912 environment_inner[depth]="listitem";
2914 sgmlOpenTag(file,depth+1+command_depth,
2915 environment_inner[depth]);
2919 sgmlOpenTag(file,depth+1+command_depth,
2924 sgmlOpenTag(file,depth+1+command_depth,
2929 sgmlOpenTag(file, depth + command_depth,
2935 string tmp_par,extra_par;
2937 SimpleDocBookOnePar(tmp_par,extra_par, par, desc_on,
2938 depth+1+command_depth);
2939 fprintf(file,"%s",tmp_par.c_str());
2942 DocBookHandleFootnote(file,par, depth+1+command_depth);
2944 while(par && par->IsDummy());
2947 /* write closing SGML tags */
2948 switch(style.latextype) {
2951 sgmlCloseTag(file, depth + command_depth, end_tag);
2953 case LATEX_ENVIRONMENT:
2954 if(!style.latexparam().empty())
2955 sgmlCloseTag(file, depth + command_depth,
2956 style.latexparam());
2958 case LATEX_ITEM_ENVIRONMENT:
2959 if(desc_on==1) break;
2961 sgmlCloseTag(file,depth+1+command_depth,end_tag);
2963 case LATEX_PARAGRAPH:
2964 if(style.latexname() != "dummy")
2965 sgmlCloseTag(file, depth + command_depth,
2969 sgmlCloseTag(file,depth+command_depth,
2976 for(;depth>=0;depth--) {
2977 if(!environment_stack[depth].empty()) {
2978 if(environment_inner[depth] != "!-- --") {
2979 item_name="listitem";
2980 sgmlCloseTag(file,command_depth+depth,
2982 if( environment_inner[depth] == "varlistentry")
2983 sgmlCloseTag(file,depth+command_depth,
2984 environment_inner[depth]);
2987 sgmlCloseTag(file,depth+command_depth,
2988 environment_stack[depth]);
2992 for(int j=command_depth;j>=command_base;j--)
2993 if(!command_stack[j].empty())
2994 sgmlCloseTag(file,j,command_stack[j]);
2996 fprintf(file, "\n\n");
2997 sgmlCloseTag(file,0,top_element);
3000 WriteFSAlert(_("Error! Could not close file properly:"),
3006 void Buffer::SimpleDocBookOnePar(string & file, string & extra,
3007 LyXParagraph * par, int & desc_on,
3011 par->SimpleDocBookOneTablePar(file, extra, desc_on, depth);
3014 LyXFont font1,font2;
3018 LyXParagraph::size_type main_body;
3023 string emph="emphasis";
3024 bool emph_flag=false;
3025 int char_line_count=0;
3027 LyXLayout const & style = textclasslist.Style(params.textclass, par->GetLayout());
3029 if (style.labeltype != LABEL_MANUAL)
3032 main_body = par->BeginningOfMainBody();
3034 /* gets paragraph main font */
3036 font1 = style.labelfont;
3040 char_line_count = depth;
3041 if(!style.free_spacing)
3042 for (j=0;j< depth;j++)
3045 /* parsing main loop */
3047 for (LyXParagraph::size_type i = 0;
3048 i < par->size(); ++i) {
3050 for (int i = 0; i < par->last; i++) {
3052 font2 = par->getFont(i);
3054 /* handle <emphasis> tag */
3055 if (font1.emph() != font2.emph() && i) {
3056 if (font2.emph() == LyXFont::ON) {
3057 file += "<emphasis>";
3060 file += "</emphasis>";
3065 c = par->GetChar(i);
3067 if (c == LYX_META_INSET) {
3068 inset = par->GetInset(i);
3070 inset->DocBook(tmp_out);
3072 // This code needs some explanation:
3073 // Two insets are treated specially
3074 // label if it is the first element in a command paragraph
3076 // graphics inside tables or figure floats can't go on
3077 // title (the equivalente in latex for this case is caption
3078 // and title should come first
3081 if(desc_on!=3 || i!=0) {
3082 if(tmp_out[0]=='@') {
3084 extra += frontStrip(tmp_out, '@');
3086 file += frontStrip(tmp_out, '@');
3091 } else if (font2.latex() == LyXFont::ON) {
3092 // "TeX"-Mode on ==> SGML-Mode on.
3099 if (par->linuxDocConvertChar(c, sgml_string)
3100 && !style.free_spacing) { // in freespacing
3102 // non-breaking characters
3107 file += "</term><listitem><para>";
3115 file += sgml_string;
3121 /* needed if there is an optional argument but no contents */
3123 if (main_body > 0 && main_body == par->size()) {
3127 if (main_body > 0 && main_body == par->last) {
3132 file += "</emphasis>";
3135 /* resets description flag correctly */
3138 /* <term> not closed... */
3146 bool Buffer::removeAutoInsets()
3148 LyXParagraph *par = paragraph;
3150 LyXCursor cursor = text->cursor;
3151 LyXCursor tmpcursor = cursor;
3152 cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
3153 cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
3157 if (par->AutoDeleteInsets()){
3159 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
3160 /* this is possible now, since SetCursor takes
3161 care about footnotes */
3162 text->SetCursorIntern(par, 0);
3163 text->RedoParagraphs(text->cursor, text->cursor.par->Next());
3164 text->FullRebreak();
3169 /* avoid forbidden cursor positions caused by error removing */
3170 if (cursor.pos > cursor.par->Last())
3171 cursor.pos = cursor.par->Last();
3172 text->SetCursorIntern(cursor.par, cursor.pos);
3178 int Buffer::runLaTeX()
3180 if (!text) return 0;
3184 // get LaTeX-Filename
3185 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3187 string path = OnlyPath(filename);
3189 string org_path = path;
3190 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3194 Path p(path); // path to LaTeX file
3195 users->getOwner()->getMiniBuffer()->Set(_("Running LaTeX..."));
3197 // Remove all error insets
3198 bool a = removeAutoInsets();
3200 // Always generate the LaTeX file
3201 makeLaTeXFile(name, org_path, false);
3204 // do the LaTex run(s)
3206 LaTeX latex(lyxrc->latex_command, name, filepath);
3207 int res = latex.run(terr,users->getOwner()->getMiniBuffer()); // running latex
3209 // check return value from latex.run().
3210 if ((res & LaTeX::NO_LOGFILE)) {
3211 WriteAlert(_("LaTeX did not work!"),
3212 _("Missing log file:"), name);
3213 } else if ((res & LaTeX::ERRORS)) {
3214 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3215 // Insert all errors as errors boxes
3218 // Dvi should also be kept dirty if the latex run
3219 // ends up with errors. However it should be possible
3220 // to view a dirty dvi too.
3222 //no errors or any other things to think about so:
3223 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3227 // if we removed error insets before we ran LaTeX or if we inserted
3228 // error insets after we ran LaTeX this must be run:
3229 if (a || (res & LaTeX::ERRORS)){
3232 users->updateScrollbar();
3236 return latex.getNumErrors();
3240 int Buffer::runLiterate()
3242 if (!text) return 0;
3246 // get LaTeX-Filename
3247 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3248 // get Literate-Filename
3249 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3251 string path = OnlyPath(filename);
3253 string org_path = path;
3254 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3258 Path p(path); // path to Literate file
3259 users->getOwner()->getMiniBuffer()->Set(_("Running Literate..."));
3261 // Remove all error insets
3262 bool a = removeAutoInsets();
3264 // generate the Literate file if necessary
3265 if (!isDviClean() || a) {
3266 makeLaTeXFile(lit_name, org_path, false);
3270 Literate literate(lyxrc->latex_command, name, filepath,
3272 lyxrc->literate_command, lyxrc->literate_error_filter,
3273 lyxrc->build_command, lyxrc->build_error_filter);
3275 int res = literate.weave(terr, users->getOwner()->getMiniBuffer());
3277 // check return value from literate.weave().
3278 if ((res & Literate::NO_LOGFILE)) {
3279 WriteAlert(_("Literate command did not work!"),
3280 _("Missing log file:"), name);
3281 } else if ((res & Literate::ERRORS)) {
3282 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3283 // Insert all errors as errors boxes
3286 // Dvi should also be kept dirty if the latex run
3287 // ends up with errors. However it should be possible
3288 // to view a dirty dvi too.
3290 //no errors or any other things to think about so:
3291 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3295 // if we removed error insets before we ran LaTeX or if we inserted
3296 // error insets after we ran LaTeX this must be run:
3297 if (a || (res & Literate::ERRORS)){
3300 users->updateScrollbar();
3304 return literate.getNumErrors();
3308 int Buffer::buildProgram()
3310 if (!text) return 0;
3314 // get LaTeX-Filename
3315 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3316 // get Literate-Filename
3317 string lit_name = SpaceLess(ChangeExtension (filename, lyxrc->literate_extension, true));
3319 string path = OnlyPath(filename);
3321 string org_path = path;
3322 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3326 Path p(path); // path to Literate file
3327 users->getOwner()->getMiniBuffer()->Set(_("Building Program..."));
3329 // Remove all error insets
3330 bool a = removeAutoInsets();
3332 // generate the LaTeX file if necessary
3333 if (!isNwClean() || a) {
3334 makeLaTeXFile(lit_name, org_path, false);
3338 Literate literate(lyxrc->latex_command, name, filepath,
3340 lyxrc->literate_command, lyxrc->literate_error_filter,
3341 lyxrc->build_command, lyxrc->build_error_filter);
3343 int res = literate.build(terr, users->getOwner()->getMiniBuffer());
3345 // check return value from literate.build().
3346 if ((res & Literate::NO_LOGFILE)) {
3347 WriteAlert(_("Build did not work!"),
3348 _("Missing log file:"), name);
3349 } else if ((res & Literate::ERRORS)) {
3350 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3351 // Insert all errors as errors boxes
3354 // Literate files should also be kept dirty if the literate
3355 // command run ends up with errors.
3357 //no errors or any other things to think about so:
3358 users->getOwner()->getMiniBuffer()->Set(_("Done"));
3362 // if we removed error insets before we ran Literate/Build or if we inserted
3363 // error insets after we ran Literate/Build this must be run:
3364 if (a || (res & Literate::ERRORS)){
3367 users->updateScrollbar();
3371 return literate.getNumErrors();
3375 // This should be enabled when the Chktex class is implemented. (Asger)
3376 // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
3377 // Other flags: -wall -v0 -x
3378 int Buffer::runChktex()
3380 if (!text) return 0;
3384 // get LaTeX-Filename
3385 string name = SpaceLess(ChangeExtension (filename, ".tex", true));
3386 string path = OnlyPath(filename);
3388 string org_path = path;
3389 if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
3393 Path p(path); // path to LaTeX file
3394 users->getOwner()->getMiniBuffer()->Set(_("Running chktex..."));
3396 // Remove all error insets
3397 bool a = removeAutoInsets();
3399 // Generate the LaTeX file if neccessary
3400 if (!isDviClean() || a) {
3401 makeLaTeXFile(name, org_path, false);
3406 Chktex chktex(lyxrc->chktex_command, name, filepath);
3407 int res = chktex.run(terr); // run chktex
3410 WriteAlert(_("chktex did not work!"),
3411 _("Could not run with file:"), name);
3412 } else if (res > 0) {
3413 // Insert all errors as errors boxes
3417 // if we removed error insets before we ran chktex or if we inserted
3418 // error insets after we ran chktex, this must be run:
3422 users->updateScrollbar();
3430 extern void AllFloats(char, char);
3433 void Buffer::insertErrors(TeXErrors & terr)
3435 // Save the cursor position
3436 LyXCursor cursor = text->cursor;
3438 // This is drastic, but it's the only fix, I could find. (Asger)
3442 for (TeXErrors::Errors::const_iterator cit = terr.begin();
3445 string desctext((*cit).error_desc);
3446 string errortext((*cit).error_text);
3447 string msgtxt = desctext + '\n' + errortext;
3448 int errorrow = (*cit).error_in_line;
3450 // Insert error string for row number
3454 texrow.getIdFromRow(errorrow, tmpid, tmppos);
3456 LyXParagraph* texrowpar;
3459 texrowpar = text->FirstParagraph();
3462 texrowpar = text->GetParFromID(tmpid);
3468 InsetError *new_inset = new InsetError(msgtxt);
3470 text->SetCursorIntern(texrowpar, tmppos);
3471 text->InsertInset(new_inset);
3472 text->FullRebreak();
3474 // Restore the cursor position
3475 text->SetCursorIntern(cursor.par, cursor.pos);
3479 void Buffer::setCursorFromRow (int row)
3484 texrow.getIdFromRow(row, tmpid, tmppos);
3486 LyXParagraph* texrowpar;
3489 texrowpar = text->FirstParagraph();
3492 texrowpar = text->GetParFromID(tmpid);
3494 text->SetCursor(texrowpar, tmppos);
3498 void Buffer::RoffAsciiTable(FILE * file, LyXParagraph * par)
3501 font1 = LyXFont(LyXFont::ALL_INHERIT),
3505 LyXParagraph::size_type i;
3517 string fname1 = TmpFileName(string(),"RAT1");
3518 string fname2 = TmpFileName(string(),"RAT2");
3519 if (!(fp=fopen(fname1.c_str(),"w"))) {
3520 WriteAlert(_("LYX_ERROR:"),
3521 _("Cannot open temporary file:"), fname1);
3524 par->table->RoffEndOfCell(fp, -1);
3526 for (i = 0; i < par->size(); ++i) {
3528 for (i = 0; i < par->last; ++i) {
3530 c = par->GetChar(i);
3531 if (par->table->IsContRow(cell)) {
3532 if (c == LYX_META_NEWLINE)
3536 font2 = par->GetFontSettings(i);
3537 if (font1.latex() != font2.latex()) {
3538 if (font2.latex() != LyXFont::OFF)
3542 case LYX_META_INSET:
3543 if ((inset = par->GetInset(i))) {
3544 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3545 WriteAlert(_("LYX_ERROR:"),
3546 _("Cannot open temporary file:"), fname2);
3548 remove(fname1.c_str());
3551 inset->Latex(fp2,-1);
3564 case LYX_META_NEWLINE:
3565 if (par->table->CellHasContRow(cell)>=0)
3566 par->RoffContTableRows(fp, i+1,cell);
3567 par->table->RoffEndOfCell(fp, cell);
3570 case LYX_META_HFILL:
3572 case LYX_META_PROTECTED_SEPARATOR:
3575 fprintf(fp, "\\\\");
3579 fprintf(fp, "%c", c);
3582 << "RoffAsciiTable:"
3583 " NULL char in structure." << endl;
3587 par->table->RoffEndOfCell(fp, cell);
3589 string cmd = lyxrc->ascii_roff_command + " >" + fname2;
3590 cmd = subst(cmd, "$$FName", fname1);
3591 Systemcalls one(Systemcalls::System, cmd);
3592 if (!(lyxerr.debugging(Debug::ROFF))) {
3593 remove(fname1.c_str());
3595 if (!(fp=fopen(fname2.c_str(),"r"))) {
3596 WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
3599 // now output the produced file
3600 fprintf(file, "\n\n");
3603 WriteAlert(_("Error!"),
3604 _("Error executing *roff command on table"));
3605 // overread leading blank lines
3606 while(!feof(fp) && (c == '\n'))
3609 for(j=0; j<par->depth; j++)
3611 while(!feof(fp) && (c != '\n')) {
3616 // overread trailing blank lines
3617 while(!feof(fp) && (c == '\n'))
3621 remove(fname2.c_str());
3625 /// changed Heinrich Bauer, 23/03/98
3626 bool Buffer::isDviClean()
3628 if (lyxrc->use_tempdir)
3629 return dvi_clean_tmpd;
3631 return dvi_clean_orgd;
3635 /// changed Heinrich Bauer, 23/03/98
3636 void Buffer::markDviClean()
3638 if (lyxrc->use_tempdir)
3639 dvi_clean_tmpd = true;
3641 dvi_clean_orgd = true;
3645 /// changed Heinrich Bauer, 23/03/98
3646 void Buffer::markDviDirty()
3648 if (lyxrc->use_tempdir)
3649 dvi_clean_tmpd = false;
3651 dvi_clean_orgd = false;
3655 void Buffer::update(signed char f)
3659 users->getOwner()->updateLayoutChoice();
3661 if (!text->selection && f > -3)
3662 text->sel_cursor = text->cursor;
3665 text->FullRebreak();
3668 if (f != 3 && f != -3) {
3670 users->updateScrollbar();
3673 if (f==1 || f==-1) {
3676 users->getOwner()->getMiniBuffer()->setTimer(4);
3684 void Buffer::validate(LaTeXFeatures & features)
3686 LyXParagraph * par = paragraph;
3687 LyXTextClass const & tclass =
3688 textclasslist.TextClass(params.textclass);
3690 // AMS Style is at document level
3692 features.amsstyle = (params.use_amsmath ||
3693 tclass.provides(LyXTextClass::amsmath));
3696 // We don't use "lyxerr.debug" because of speed. (Asger)
3697 if (lyxerr.debugging(Debug::LATEX))
3698 lyxerr << "Paragraph: " << par << endl;
3700 // Now just follow the list of paragraphs and run
3701 // validate on each of them.
3702 par->validate(features);
3704 // and then the next paragraph
3708 // the bullet shapes are buffer level not paragraph level
3709 // so they are tested here
3710 for (int i = 0; i < 4; ++i) {
3711 if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
3712 int font = params.user_defined_bullets[i].getFont();
3715 .user_defined_bullets[i]
3722 features.latexsym = true;
3726 features.amssymb = true;
3728 else if ((font >= 2 && font <=5)) {
3729 features.pifont = true;
3734 if (lyxerr.debugging(Debug::LATEX)) {
3735 features.showStruct(params);
3740 void Buffer::setPaperStuff()
3742 params.papersize = PAPER_DEFAULT;
3743 char c1 = params.paperpackage;
3744 if (c1 == PACKAGE_NONE) {
3745 char c2 = params.papersize2;
3746 if (c2 == VM_PAPER_USLETTER)
3747 params.papersize = PAPER_USLETTER;
3748 else if (c2 == VM_PAPER_USLEGAL)
3749 params.papersize = PAPER_LEGALPAPER;
3750 else if (c2 == VM_PAPER_USEXECUTIVE)
3751 params.papersize = PAPER_EXECUTIVEPAPER;
3752 else if (c2 == VM_PAPER_A3)
3753 params.papersize = PAPER_A3PAPER;
3754 else if (c2 == VM_PAPER_A4)
3755 params.papersize = PAPER_A4PAPER;
3756 else if (c2 == VM_PAPER_A5)
3757 params.papersize = PAPER_A5PAPER;
3758 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
3759 (c2 == VM_PAPER_B5))
3760 params.papersize = PAPER_B5PAPER;
3761 } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
3762 (c1 == PACKAGE_WIDEMARGINSA4))
3763 params.papersize = PAPER_A4PAPER;
3767 void Buffer::setOldPaperStuff()
3769 char c = params.papersize = params.papersize2;
3770 params.papersize2 = VM_PAPER_DEFAULT;
3771 params.paperpackage = PACKAGE_NONE;
3772 if (c == OLD_PAPER_A4PAPER)
3773 params.papersize2 = VM_PAPER_A4;
3774 else if (c == OLD_PAPER_A4)
3775 params.paperpackage = PACKAGE_A4;
3776 else if (c == OLD_PAPER_A4WIDE)
3777 params.paperpackage = PACKAGE_A4WIDE;
3778 else if (c == OLD_PAPER_WIDEMARGINSA4)
3779 params.paperpackage = PACKAGE_WIDEMARGINSA4;
3780 else if (c == OLD_PAPER_USLETTER)
3781 params.papersize2 = VM_PAPER_USLETTER;
3782 else if (c == OLD_PAPER_A5PAPER)
3783 params.papersize2 = VM_PAPER_A5;
3784 else if (c == OLD_PAPER_B5PAPER)
3785 params.papersize2 = VM_PAPER_B5;
3786 else if (c == OLD_PAPER_EXECUTIVEPAPER)
3787 params.papersize2 = VM_PAPER_USEXECUTIVE;
3788 else if (c == OLD_PAPER_LEGALPAPER)
3789 params.papersize2 = VM_PAPER_USLEGAL;
3794 void Buffer::insertInset(Inset * inset, string const & lout,
3797 // check for table/list in tables
3798 if (no_table && text->cursor.par->table){
3799 WriteAlert(_("Impossible Operation!"),
3800 _("Cannot insert table/list in table."),
3804 // not quite sure if we want this...
3805 text->SetCursorParUndo();
3809 if (!lout.empty()) {
3811 text->BreakParagraph();
3814 if (text->cursor.par->Last()) {
3817 text->BreakParagraph();
3821 int lay = textclasslist.NumberOfLayout(params.textclass,
3823 if (lay == -1) // layout not found
3824 // use default layout "Standard" (0)
3827 text->SetLayout(lay);
3829 text->SetParagraph(0, 0,
3831 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3837 text->current_font.setLatex(LyXFont::OFF);
3840 text->InsertInset(inset);
3843 text->UnFreezeUndo();
3847 // Open and lock an updatable inset
3848 void Buffer::open_new_inset(UpdatableInset * new_inset)
3852 insertInset(new_inset);
3855 new_inset->Edit(0,0);
3859 /* This function should be in Buffer because it's a buffer's property (ale) */
3860 string Buffer::getIncludeonlyList(char delim)
3863 LyXParagraph * par = paragraph;
3865 LyXParagraph::size_type pos;
3872 while ((inset = par->ReturnNextInsetPointer(pos))){
3873 if (inset->LyxCode()==Inset::INCLUDE_CODE) {
3874 InsetInclude * insetinc =
3875 static_cast<InsetInclude*>(inset);
3876 if (insetinc->isInclude()
3877 && insetinc->isNoLoad()) {
3880 lst += ChangeExtension(insetinc->getContents(), string(), true);
3887 lyxerr.debug() << "Includeonly(" << lst << ')' << endl;
3892 /* This is also a buffer property (ale) */
3893 string Buffer::getReferenceList(char delim)
3895 /// if this is a child document and the parent is already loaded
3896 /// Use the parent's list instead [ale990407]
3897 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3898 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3900 return tmp->getReferenceList(delim);
3903 LyXParagraph *par = paragraph;
3905 LyXParagraph::size_type pos;
3913 while ((inset = par->ReturnNextInsetPointer(pos))){
3914 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
3917 lst += inset->getLabel(i);
3923 lyxerr.debug() << "References(" << lst << ")" << endl;
3928 /* This is also a buffer property (ale) */
3929 string Buffer::getBibkeyList(char delim)
3931 /// if this is a child document and the parent is already loaded
3932 /// Use the parent's list instead [ale990412]
3933 if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
3934 Buffer *tmp = bufferlist.getBuffer(params.parentname);
3936 return tmp->getBibkeyList(delim);
3940 LyXParagraph * par = paragraph;
3943 if (!bibkeys.empty())
3945 bibkeys += par->bibkey->getContents();
3950 // Might be either using bibtex or a child has bibliography
3951 if (bibkeys.empty()) {
3956 LyXParagraph::size_type pos = -1;
3961 // Search for Bibtex or Include inset
3962 while ((inset = par->ReturnNextInsetPointer(pos))) {
3963 if (inset-> LyxCode()==Inset::BIBTEX_CODE) {
3964 if (!bibkeys.empty())
3966 bibkeys += ((InsetBibtex*)inset)->getKeys();
3967 } else if (inset-> LyxCode()==Inset::INCLUDE_CODE) {
3968 string bk = ((InsetInclude*)inset)->getKeys();
3970 if (!bibkeys.empty())
3981 lyxerr.debug() << "Bibkeys(" << bibkeys << ")" << endl;
3986 /* This is also a buffer property (ale) */
3987 // Not so sure about that. a goto Label function can not be buffer local, just
3988 // think how this will work in a multiwindo/buffer environment, all the
3989 // cursors in all the views showing this buffer will move. (Lgb)
3990 // OK, then no cursor action should be allowed in buffer. (ale)
3991 bool Buffer::gotoLabel(string const & label)
3994 LyXParagraph * par = paragraph;
3996 LyXParagraph::size_type pos;
4003 while ((inset = par->ReturnNextInsetPointer(pos))){
4004 for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
4005 if (label==inset->getLabel(i)) {
4007 text->SetCursor(par, pos);
4008 text->sel_cursor = text->cursor;
4021 bool Buffer::isDepClean(string const & name) const
4023 DEPCLEAN * item = dep_clean;
4024 while (item && item->master != name)
4026 if (!item) return true;
4031 void Buffer::markDepClean(string const & name)
4034 dep_clean = new DEPCLEAN;
4035 dep_clean->clean = true;
4036 dep_clean->master = name;
4037 dep_clean->next = 0;
4039 DEPCLEAN* item = dep_clean;
4040 while (item && item->master != name)
4045 item = new DEPCLEAN;
4047 item->master = name;