1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation "lyxparagraph.h"
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "support/FileInfo.h"
28 #include "support/LAssert.h"
30 #include "LaTeXFeatures.h"
31 #include "insets/insetinclude.h"
32 #include "insets/insetbib.h"
33 #include "insets/insettext.h"
34 #include "support/filetools.h"
35 #include "lyx_gui_misc.h"
37 #include "support/lyxmanip.h"
38 #include "BufferView.h"
45 using std::lower_bound;
46 using std::upper_bound;
49 int tex_code_break_column = 72; // needs non-zero initialization. set later.
50 // this is a bad idea, but how can LyXParagraph find its buffer to get
51 // parameters? (JMarc)
52 extern BufferView * current_view;
53 extern string bibitemWidest(BufferView *);
55 // this is a minibuffer
56 static char minibuffer_char;
57 static LyXFont minibuffer_font;
58 static Inset * minibuffer_inset;
61 // Initialization of the counter for the paragraph id's,
62 // declared in lyxparagraph.h
63 unsigned int LyXParagraph::paragraph_id = 0;
66 LyXParagraph::LyXParagraph()
68 text.reserve(500); // is this number too big?
70 for (int i = 0; i < 10; ++i) setCounter(i , 0);
77 footnoteflag = LyXParagraph::NO_FOOTNOTE;
78 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
80 align = LYX_ALIGN_BLOCK;
83 /* table stuff -- begin*/
85 /* table stuff -- end*/
89 bibkey = 0; // ale970302
94 // This konstruktor inserts the new paragraph in a list.
95 LyXParagraph::LyXParagraph(LyXParagraph * par)
98 par->text.resize(par->text.size());
100 for (int i = 0; i < 10; ++i) setCounter(i, 0);
104 // double linked list begin
107 next->previous = this;
109 previous->next = this;
112 footnoteflag = LyXParagraph::NO_FOOTNOTE;
113 footnotekind = LyXParagraph::FOOTNOTE;
116 /* table stuff -- begin*/
118 /* table stuff -- end*/
121 id_ = paragraph_id++;
123 bibkey = 0; // ale970302
129 void LyXParagraph::writeFile(Buffer const * buf, ostream & os,
130 BufferParams const & params,
131 char footflag, char dth) const
135 footnoteflag != LyXParagraph::NO_FOOTNOTE ||
137 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE
142 // The beginning or the end of a footnote environment?
143 if (footflag != footnoteflag) {
144 footflag = footnoteflag;
146 os << "\n\\begin_float "
147 << string_footnotekinds[footnotekind]
150 os << "\n\\end_float ";
154 // The beginning or end of a deeper (i.e. nested) area?
157 while (depth > dth) {
158 os << "\n\\begin_deeper ";
162 while (depth < dth) {
163 os << "\n\\end_deeper ";
169 // First write the layout
171 << textclasslist.NameOfLayout(params.textclass, layout)
174 // Maybe some vertical spaces.
175 if (added_space_top.kind() != VSpace::NONE)
176 os << "\\added_space_top "
177 << added_space_top.asLyXCommand() << " ";
178 if (added_space_bottom.kind() != VSpace::NONE)
179 os << "\\added_space_bottom "
180 << added_space_bottom.asLyXCommand() << " ";
182 // Maybe the paragraph has special spacing
183 spacing.writeFile(os, true);
185 // The labelwidth string used in lists.
186 if (!labelwidthstring.empty())
187 os << "\\labelwidthstring "
188 << labelwidthstring << '\n';
190 // Lines above or below?
194 os << "\\line_bottom ";
196 // Pagebreaks above or below?
198 os << "\\pagebreak_top ";
199 if (pagebreak_bottom)
200 os << "\\pagebreak_bottom ";
202 // Start of appendix?
203 if (start_of_appendix)
204 os << "\\start_of_appendix ";
211 if (align != LYX_ALIGN_LAYOUT) {
214 case LYX_ALIGN_LEFT: h = 1; break;
215 case LYX_ALIGN_RIGHT: h = 2; break;
216 case LYX_ALIGN_CENTER: h = 3; break;
217 default: h = 0; break;
219 os << "\\align " << string_align[h] << " ";
221 if (pextra_type != PEXTRA_NONE) {
222 os << "\\pextra_type " << pextra_type;
223 if (pextra_type == PEXTRA_MINIPAGE) {
224 os << " \\pextra_alignment "
227 os << " \\pextra_hfill "
229 if (pextra_start_minipage)
230 os << " \\pextra_start_minipage "
231 << pextra_start_minipage;
233 if (!pextra_width.empty()) {
234 os << " \\pextra_width "
235 << VSpace(pextra_width).asLyXCommand();
236 } else if (!pextra_widthp.empty()) {
237 os << " \\pextra_widthp "
244 // Dummy layout. This means that a footnote ended.
245 os << "\n\\end_float ";
246 footflag = LyXParagraph::NO_FOOTNOTE;
250 // It might be a table.
252 os << "\\LyXTable\n";
258 bibkey->Write(buf, os);
260 LyXFont font1(LyXFont::ALL_INHERIT, params.language_info);
263 for (size_type i = 0; i < size(); ++i) {
269 // Write font changes
270 LyXFont font2 = GetFontSettings(params, i);
271 if (font2 != font1) {
272 font2.lyxWriteChanges(font1, os);
277 value_type c = GetChar(i);
281 Inset const * inset = GetInset(i);
283 if (inset->DirectWrite()) {
284 // international char, let it write
285 // code directly so it's shorter in
287 inset->Write(buf, os);
289 os << "\n\\begin_inset ";
290 inset->Write(buf, os);
291 os << "\n\\end_inset \n\n";
297 os << "\n\\newline \n";
301 os << "\n\\hfill \n";
305 os << "\n\\backslash \n";
309 if (i + 1 < size() && GetChar(i + 1) == ' ') {
316 if ((column > 70 && c == ' ')
321 // this check is to amend a bug. LyX sometimes
322 // inserts '\0' this could cause problems.
326 lyxerr << "ERROR (LyXParagraph::writeFile):"
327 " NULL char in structure." << endl;
334 // now write the next paragraph
336 next->writeFile(buf, os, params, footflag, dth);
340 void LyXParagraph::validate(LaTeXFeatures & features) const
342 BufferParams const & params = features.bufferParams();
345 // this will be useful later
346 LyXLayout const & layout =
347 textclasslist.Style(params.textclass,
352 if (line_top || line_bottom)
353 features.lyxline = true;
354 if (!spacing.isDefault())
355 features.setspace = true;
358 features.layout[GetLayout()] = true;
361 Language const * doc_language = params.language_info;
363 for (FontList::const_iterator cit = fontlist.begin();
364 cit != fontlist.end(); ++cit) {
365 if ((*cit).font.noun() == LyXFont::ON) {
366 lyxerr[Debug::LATEX] << "font.noun: "
367 << (*cit).font.noun()
369 features.noun = true;
370 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
371 << (*cit).font.stateText(0)
374 switch ((*cit).font.color()) {
376 case LColor::inherit:
380 features.color = true;
381 lyxerr[Debug::LATEX] << "Color enabled. Font: "
382 << (*cit).font.stateText(0)
386 Language const * language = (*cit).font.language();
387 if (language != doc_language) {
388 features.UsedLanguages.insert(language);
389 lyxerr[Debug::LATEX] << "Found language "
390 << language->lang() << endl;
395 for (InsetList::const_iterator cit = insetlist.begin();
396 cit != insetlist.end(); ++cit) {
398 (*cit).inset->Validate(features);
401 if (table && table->IsLongTable())
402 features.longtable = true;
403 if (pextra_type == PEXTRA_INDENT)
404 features.LyXParagraphIndent = true;
405 if (pextra_type == PEXTRA_FLOATFLT)
406 features.floatflt = true;
408 if (layout.needprotect
409 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
410 features.NeedLyXFootnoteCode = true;
412 if (params.paragraph_separation == BufferParams::PARSEP_INDENT
413 && pextra_type == LyXParagraph::PEXTRA_MINIPAGE)
414 features.NeedLyXMinipageIndent = true;
415 if (table && table->NeedRotating())
416 features.rotating = true;
418 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
419 features.algorithm = true;
424 // First few functions needed for cut and paste and paragraph breaking.
425 void LyXParagraph::CopyIntoMinibuffer(BufferParams const & bparams,
426 LyXParagraph::size_type pos) const
428 minibuffer_char = GetChar(pos);
429 minibuffer_font = GetFontSettings(bparams, pos);
430 minibuffer_inset = 0;
431 if (minibuffer_char == LyXParagraph::META_INSET) {
433 minibuffer_inset = GetInset(pos)->Clone();
435 minibuffer_inset = 0;
436 minibuffer_char = ' ';
437 // This reflects what GetInset() does (ARRae)
443 void LyXParagraph::CutIntoMinibuffer(BufferParams const & bparams,
444 LyXParagraph::size_type pos)
446 minibuffer_char = GetChar(pos);
447 minibuffer_font = GetFontSettings(bparams, pos);
448 minibuffer_inset = 0;
449 if (minibuffer_char == LyXParagraph::META_INSET) {
451 minibuffer_inset = GetInset(pos);
452 // This is a little hack since I want exactly
453 // the inset, not just a clone. Otherwise
454 // the inset would be deleted when calling Erase(pos)
456 InsetTable search_elem(pos, 0);
457 InsetList::iterator it =
458 lower_bound(insetlist.begin(),
460 search_elem, matchIT());
461 if (it != insetlist.end() && (*it).pos == pos)
464 minibuffer_inset = 0;
465 minibuffer_char = ' ';
466 // This reflects what GetInset() does (ARRae)
471 // Erase(pos); now the caller is responsible for that.
475 bool LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
477 if ((minibuffer_char == LyXParagraph::META_INSET) &&
478 !InsertInsetAllowed(minibuffer_inset))
480 if (minibuffer_char == LyXParagraph::META_INSET)
481 InsertInset(pos, minibuffer_inset, minibuffer_font);
483 InsertChar(pos, minibuffer_char, minibuffer_font);
491 void LyXParagraph::Clear()
496 pagebreak_top = false;
497 pagebreak_bottom = false;
499 added_space_top = VSpace(VSpace::NONE);
500 added_space_bottom = VSpace(VSpace::NONE);
501 spacing.set(Spacing::Default);
503 align = LYX_ALIGN_LAYOUT;
507 pextra_type = PEXTRA_NONE;
508 pextra_width.erase();
509 pextra_widthp.erase();
510 pextra_alignment = MINIPAGE_ALIGN_TOP;
511 pextra_hfill = false;
512 pextra_start_minipage = false;
515 labelwidthstring.erase();
519 start_of_appendix = false;
523 // the destructor removes the new paragraph from the list
524 LyXParagraph::~LyXParagraph()
527 previous->next = next;
529 next->previous = previous;
531 for (InsetList::iterator it = insetlist.begin();
532 it != insetlist.end(); ++it) {
536 /* table stuff -- begin*/
538 /* table stuff -- end*/
544 //lyxerr << "LyXParagraph::paragraph_id = "
545 // << LyXParagraph::paragraph_id << endl;
549 void LyXParagraph::Erase(LyXParagraph::size_type pos)
551 // > because last is the next unused position, and you can
552 // use it if you want
555 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
556 NextAfterFootnote()->Erase(pos - text.size() - 1);
559 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
560 "position does not exist." << endl;
563 if (pos < size()) { // last is free for insertation, but should be empty
564 // if it is an inset, delete the inset entry
565 if (text[pos] == LyXParagraph::META_INSET) {
567 InsetTable search_inset(pos, 0);
568 InsetList::iterator it =
569 lower_bound(insetlist.begin(),
571 search_inset, matchIT());
572 if (it != insetlist.end() && (*it).pos == pos) {
577 text.erase(text.begin() + pos);
579 // Erase entries in the tables.
580 FontTable search_font(pos, LyXFont());
582 FontList::iterator it =
583 lower_bound(fontlist.begin(),
585 search_font, matchFT());
586 if (it != fontlist.end() && (*it).pos == pos &&
588 (it != fontlist.begin() && (*(it-1)).pos == pos - 1))) {
589 // If it is a multi-character font
590 // entry, we just make it smaller
591 // (see update below), otherwise we
593 unsigned int i = it - fontlist.begin();
594 fontlist.erase(fontlist.begin() + i);
595 it = fontlist.begin() + i;
596 if (i > 0 && i < fontlist.size() &&
597 fontlist[i-1].font == fontlist[i].font) {
598 fontlist.erase(fontlist.begin() + i-1);
599 it = fontlist.begin() + i-1;
603 // Update all other entries.
604 for (; it != fontlist.end(); ++it)
607 // Update the inset table.
608 InsetTable search_inset(pos, 0);
609 for (InsetList::iterator it =
610 upper_bound(insetlist.begin(),
612 search_inset, matchIT());
613 it != insetlist.end(); ++it)
616 lyxerr << "ERROR (LyXParagraph::Erase): "
617 "can't erase non-existant char." << endl;
622 void LyXParagraph::InsertChar(LyXParagraph::size_type pos,
623 LyXParagraph::value_type c)
625 LyXFont f(LyXFont::ALL_INHERIT);
626 InsertChar(pos, c, f);
630 void LyXParagraph::InsertChar(LyXParagraph::size_type pos,
631 LyXParagraph::value_type c,
632 LyXFont const & font)
634 // > because last is the next unused position, and you can
635 // use it if you want
639 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
640 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
644 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
645 "position does not exist." << endl;
648 text.insert(text.begin() + pos, c);
649 // Update the font table.
650 FontTable search_font(pos, LyXFont());
651 for (FontList::iterator it = lower_bound(fontlist.begin(),
653 search_font, matchFT());
654 it != fontlist.end(); ++it)
657 // Update the inset table.
658 InsetTable search_inset(pos, 0);
659 for (InsetList::iterator it = lower_bound(insetlist.begin(),
661 search_inset, matchIT());
662 it != insetlist.end(); ++it)
669 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
672 LyXFont f(LyXFont::ALL_INHERIT);
673 InsertInset(pos, inset, f);
677 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
678 Inset * inset, LyXFont const & font)
682 // > because last is the next unused position, and you can
683 // use it if you want
687 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
689 ->InsertInset(pos - text.size() - 1,
693 lyxerr << "ERROR (LyXParagraph::InsertInset): "
694 "position does not exist: " << pos << endl;
698 InsertChar(pos, META_INSET, font);
699 Assert(text[pos] == META_INSET);
701 // Add a new entry in the inset table.
702 InsetTable search_inset(pos, 0);
703 InsetList::iterator it = lower_bound(insetlist.begin(),
705 search_inset, matchIT());
706 if (it != insetlist.end() && (*it).pos == pos)
707 lyxerr << "ERROR (LyXParagraph::InsertInset): "
708 "there is an inset in position: " << pos << endl;
710 insetlist.insert(it, InsetTable(pos, inset));
712 inset->setOwner(inset_owner);
716 bool LyXParagraph::InsertInsetAllowed(Inset * inset)
718 lyxerr << "LyXParagraph::InsertInsetAllowed" << endl;
721 return inset_owner->InsertInsetAllowed(inset);
726 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
731 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
732 return NextAfterFootnote()
733 ->GetInset(pos - text.size() - 1);
736 lyxerr << "ERROR (LyXParagraph::GetInset): "
737 "position does not exist: "
743 InsetTable search_inset(pos, 0);
744 InsetList::iterator it = lower_bound(insetlist.begin(),
746 search_inset, matchIT());
747 if (it != insetlist.end() && (*it).pos == pos)
750 lyxerr << "ERROR (LyXParagraph::GetInset): "
751 "Inset does not exist: " << pos << endl;
754 // text[pos] = ' '; // WHY!!! does this set the pos to ' '????
755 // Did this commenting out introduce a bug? So far I have not
756 // see any, please enlighten me. (Lgb)
757 // My guess is that since the inset does not exist, we might
758 // as well replace it with a space to prevent craches. (Asger)
763 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
768 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
769 return NextAfterFootnote()
770 ->GetInset(pos - text.size() - 1);
773 lyxerr << "ERROR (LyXParagraph::GetInset): "
774 "position does not exist: "
780 InsetTable search_inset(pos, 0);
781 InsetList::const_iterator cit = lower_bound(insetlist.begin(),
783 search_inset, matchIT());
784 if (cit != insetlist.end() && (*cit).pos == pos)
787 lyxerr << "ERROR (LyXParagraph::GetInset): "
788 "Inset does not exist: " << pos << endl;
790 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
791 // Did this commenting out introduce a bug? So far I have not
792 // see any, please enlighten me. (Lgb)
793 // My guess is that since the inset does not exist, we might
794 // as well replace it with a space to prevent craches. (Asger)
799 // Gets uninstantiated font setting at position.
800 // Optimized after profiling. (Asger)
801 LyXFont LyXParagraph::GetFontSettings(BufferParams const & bparams,
802 LyXParagraph::size_type pos) const
805 FontTable search_font(pos, LyXFont());
806 FontList::const_iterator cit = lower_bound(fontlist.begin(),
808 search_font, matchFT());
809 if (cit != fontlist.end())
812 // > because last is the next unused position, and you can
813 // use it if you want
814 else if (pos > size()) {
817 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
818 return NextAfterFootnote()
819 ->GetFontSettings(bparams,
820 pos - text.size() - 1);
823 // Why is it an error to ask for the font of a
824 // position that does not exist? Would it be
825 // enough for this to be enabled on debug?
826 // We want strict error checking, but it's ok to only
827 // have it when debugging. (Asger)
828 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
829 "position does not exist. "
830 << pos << " (" << static_cast<int>(pos)
832 } else if (pos > 0) {
833 return GetFontSettings(bparams, pos - 1);
834 } else // pos = size() = 0
835 return LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
837 return LyXFont(LyXFont::ALL_INHERIT);
840 // Gets uninstantiated font setting at position 0
841 LyXFont LyXParagraph::GetFirstFontSettings() const
844 if (!fontlist.empty())
845 return fontlist[0].font;
849 else if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
850 return NextAfterFootnote()->GetFirstFontSettings();
852 return LyXFont(LyXFont::ALL_INHERIT);
856 // Gets the fully instantiated font at a given position in a paragraph
857 // This is basically the same function as LyXText::GetFont() in text2.C.
858 // The difference is that this one is used for generating the LaTeX file,
859 // and thus cosmetic "improvements" are disallowed: This has to deliver
860 // the true picture of the buffer. (Asger)
861 // If position is -1, we get the layout font of the paragraph.
862 // If position is -2, we get the font of the manual label of the paragraph.
863 LyXFont LyXParagraph::getFont(BufferParams const & bparams,
864 LyXParagraph::size_type pos) const
867 LyXLayout const & layout =
868 textclasslist.Style(bparams.textclass,
870 LyXParagraph::size_type main_body = 0;
871 if (layout.labeltype == LABEL_MANUAL)
872 main_body = BeginningOfMainBody();
877 layoutfont = layout.labelfont;
879 layoutfont = layout.font;
880 tmpfont = GetFontSettings(bparams, pos);
881 tmpfont.realize(layoutfont);
883 // process layoutfont for pos == -1 and labelfont for pos < -1
885 tmpfont = layout.font;
887 tmpfont = layout.labelfont;
888 tmpfont.setLanguage(getParLanguage(bparams));
891 // check for environment font information
892 char par_depth = GetDepth();
893 LyXParagraph const * par = this;
894 while (par && par_depth && !tmpfont.resolved()) {
895 par = par->DepthHook(par_depth - 1);
897 tmpfont.realize(textclasslist.
898 Style(bparams.textclass,
899 par->GetLayout()).font);
900 par_depth = par->GetDepth();
904 tmpfont.realize(textclasslist
905 .TextClass(bparams.textclass)
911 /// Returns the height of the highest font in range
913 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
914 LyXParagraph::size_type endpos) const
916 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
917 if (fontlist.empty())
920 FontTable end_search(endpos, LyXFont());
921 FontList::const_iterator end_it = lower_bound(fontlist.begin(),
923 end_search, matchFT());
924 if (end_it != fontlist.end())
927 FontTable start_search(startpos, LyXFont());
928 for (FontList::const_iterator cit =
929 lower_bound(fontlist.begin(),
931 start_search, matchFT());
932 cit != end_it; ++cit) {
933 LyXFont::FONT_SIZE size = (*cit).font.size();
934 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
941 LyXParagraph::value_type
942 LyXParagraph::GetChar(LyXParagraph::size_type pos)
949 // > because last is the next unused position, and you can
950 // use it if you want
951 else if (pos > size()) {
953 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
954 return NextAfterFootnote()
955 ->GetChar(pos - text.size() - 1);
959 lyxerr << "ERROR (LyXParagraph::GetChar): "
960 "position does not exist."
961 << pos << " (" << static_cast<int>(pos)
963 // Assert(false); // This triggers sometimes...
972 // We should have a footnote environment.
973 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
974 // Notice that LyX does request the
975 // last char from time to time. (Asger)
976 //lyxerr << "ERROR (LyXParagraph::GetChar): "
977 // "expected footnote." << endl;
980 switch (next->footnotekind) {
981 case LyXParagraph::FOOTNOTE:
982 return LyXParagraph::META_FOOTNOTE;
983 case LyXParagraph::MARGIN:
984 return LyXParagraph::META_MARGIN;
985 case LyXParagraph::FIG:
986 case LyXParagraph::WIDE_FIG:
987 return LyXParagraph::META_FIG;
988 case LyXParagraph::TAB:
989 case LyXParagraph::WIDE_TAB:
990 return LyXParagraph::META_TAB;
991 case LyXParagraph::ALGORITHM:
992 return LyXParagraph::META_ALGORITHM;
994 return '\0'; // to shut up gcc
997 return '\0'; // to shut up gcc
1002 LyXParagraph::value_type
1003 LyXParagraph::GetChar(LyXParagraph::size_type pos) const
1010 // > because last is the next unused position, and you can
1011 // use it if you want
1012 else if (pos > size()) {
1014 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1015 return NextAfterFootnote()
1016 ->GetChar(pos - text.size() - 1);
1020 lyxerr << "ERROR (LyXParagraph::GetChar const): "
1021 "position does not exist."
1022 << pos << " (" << static_cast<int>(pos)
1030 // We should have a footnote environment.
1031 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1032 // Notice that LyX does request the
1033 // last char from time to time. (Asger)
1034 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1035 // "expected footnote." << endl;
1038 switch (next->footnotekind) {
1039 case LyXParagraph::FOOTNOTE:
1040 return LyXParagraph::META_FOOTNOTE;
1041 case LyXParagraph::MARGIN:
1042 return LyXParagraph::META_MARGIN;
1043 case LyXParagraph::FIG:
1044 case LyXParagraph::WIDE_FIG:
1045 return LyXParagraph::META_FIG;
1046 case LyXParagraph::TAB:
1047 case LyXParagraph::WIDE_TAB:
1048 return LyXParagraph::META_TAB;
1049 case LyXParagraph::ALGORITHM:
1050 return LyXParagraph::META_ALGORITHM;
1052 return '\0'; // to shut up gcc
1055 return '\0'; // to shut up gcc
1061 // return an string of the current word, and the end of the word in lastpos.
1062 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1066 // the current word is defined as starting at the first character
1067 // from the immediate left of lastpospos which meets the definition
1068 // of IsLetter(), continuing to the last character to the right
1069 // of this meeting IsLetter.
1075 // move back until we have a letter
1077 //there's no real reason to have firstpos & lastpos as
1078 //separate variables as this is written, but maybe someon
1079 // will want to return firstpos in the future.
1081 //since someone might have typed a punctuation first
1082 int firstpos = lastpos;
1084 while ((firstpos >= 0) && !IsLetter(firstpos))
1087 // now find the beginning by looking for a nonletter
1089 while ((firstpos>= 0) && IsLetter(firstpos))
1092 // the above is now pointing to the preceeding non-letter
1096 // so copy characters into theword until we get a nonletter
1097 // note that this can easily exceed lastpos, wich means
1098 // that if used in the middle of a word, the whole word
1101 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1108 LyXParagraph::size_type LyXParagraph::Last() const
1111 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1112 return text.size() + NextAfterFootnote()->Last() + 1;
1113 // the 1 is the symbol
1121 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1123 // > because last is the next unused position, and you can
1124 // use it if you want
1128 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1129 return NextAfterFootnote()
1130 ->ParFromPos(pos - text.size() - 1);
1133 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1134 "position does not exist." << endl;
1141 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1143 // > because last is the next unused position, and you can
1144 // use it if you want
1148 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1149 return NextAfterFootnote()
1150 ->PositionInParFromPos(pos - text.size() - 1);
1154 "ERROR (LyXParagraph::PositionInParFromPos): "
1155 "position does not exist." << endl;
1163 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1164 LyXFont const & font)
1166 // > because last is the next unused position, and you can
1167 // use it if you want
1171 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1172 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1176 lyxerr << "ERROR (LyXParagraph::SetFont): "
1177 "position does not exist." << endl;
1182 // First, reduce font against layout/label font
1183 // Update: The SetCharFont() routine in text2.C already
1184 // reduces font, so we don't need to do that here. (Asger)
1185 // No need to simplify this because it will disappear
1186 // in a new kernel. (Asger)
1187 // Next search font table
1189 FontTable search_font(pos, LyXFont());
1190 FontList::iterator it = lower_bound(fontlist.begin(),
1192 search_font, matchFT());
1193 unsigned int i = it - fontlist.begin();
1194 bool notfound = it == fontlist.end();
1196 if (!notfound && fontlist[i].font == font)
1199 bool begin = pos == 0 || notfound ||
1200 (i > 0 && fontlist[i-1].pos == pos - 1);
1201 // Is position pos is a beginning of a font block?
1202 bool end = !notfound && fontlist[i].pos == pos;
1203 // Is position pos is the end of a font block?
1204 if (begin && end) { // A single char block
1205 if (i+1 < fontlist.size() &&
1206 fontlist[i+1].font == font) {
1207 // Merge the singleton block with the next block
1208 fontlist.erase(fontlist.begin() + i);
1209 if (i > 0 && fontlist[i-1].font == font)
1210 fontlist.erase(fontlist.begin() + i-1);
1211 } else if (i > 0 && fontlist[i-1].font == font) {
1212 // Merge the singleton block with the previous block
1213 fontlist[i-1].pos = pos;
1214 fontlist.erase(fontlist.begin() + i);
1216 fontlist[i].font = font;
1218 if (i > 0 && fontlist[i-1].font == font)
1219 fontlist[i-1].pos = pos;
1221 fontlist.insert(fontlist.begin() + i,
1222 FontTable(pos, font));
1224 fontlist[i].pos = pos - 1;
1225 if (!(i+1 < fontlist.size() &&
1226 fontlist[i+1].font == font))
1227 fontlist.insert(fontlist.begin() + i+1,
1228 FontTable(pos, font));
1229 } else { // The general case. The block is splitted into 3 blocks
1230 fontlist.insert(fontlist.begin() + i,
1231 FontTable(pos - 1, fontlist[i].font));
1232 fontlist.insert(fontlist.begin() + i+1, FontTable(pos, font));
1237 // This function is able to hide closed footnotes.
1238 LyXParagraph * LyXParagraph::Next()
1241 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1242 LyXParagraph * tmp = next;
1244 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1246 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1247 return tmp->Next(); /* there can be more than one
1248 footnote in a logical
1251 return next; // This should never happen!
1259 LyXParagraph * LyXParagraph::NextAfterFootnote()
1261 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1262 LyXParagraph * tmp = next;
1263 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1265 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1266 return tmp; /* there can be more than one footnote
1267 in a logical paragraph */
1269 return next; // This should never happen!
1277 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1279 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1280 LyXParagraph * tmp = next;
1281 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1283 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1284 return tmp; /* there can be more than one footnote
1285 in a logical paragraph */
1287 return next; // This should never happen!
1295 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1298 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1300 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1301 tmp = tmp->previous;
1302 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1303 return tmp; /* there can be more than one footnote
1304 in a logical paragraph */
1306 return previous; // This should never happen!
1314 LyXParagraph * LyXParagraph::LastPhysicalPar()
1316 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1319 LyXParagraph * tmp = this;
1321 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1322 tmp = tmp->NextAfterFootnote();
1330 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1332 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1335 LyXParagraph const * tmp = this;
1337 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1338 tmp = tmp->NextAfterFootnote();
1346 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1350 LyXParagraph * tmppar = this;
1354 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1355 tmppar = tmppar->previous;
1366 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1370 LyXParagraph const * tmppar = this;
1374 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1375 tmppar = tmppar->previous;
1385 // This function is able to hide closed footnotes.
1386 LyXParagraph * LyXParagraph::Previous()
1389 LyXParagraph * tmp = previous;
1394 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1395 tmp = tmp->previous;
1397 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1398 tmp = tmp->previous;
1399 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1400 return tmp->next->Previous();
1410 // This function is able to hide closed footnotes.
1411 LyXParagraph const * LyXParagraph::Previous() const
1414 LyXParagraph * tmp = previous;
1418 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1419 tmp = tmp->previous;
1421 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1422 tmp = tmp->previous;
1423 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1424 return tmp->next->Previous();
1434 void LyXParagraph::BreakParagraph(BufferParams const & bparams,
1435 LyXParagraph::size_type pos,
1438 size_type i, j, pos_end, pos_first;
1439 // create a new paragraph
1440 LyXParagraph * par = ParFromPos(pos);
1442 LyXParagraph * firstpar = FirstPhysicalPar();
1444 LyXParagraph * firstpar = this;
1447 LyXParagraph * tmp = new LyXParagraph(par);
1450 tmp->footnoteflag = footnoteflag;
1451 tmp->footnotekind = footnotekind;
1453 // this is an idea for a more userfriendly layout handling, I will
1454 // see what the users say
1456 // layout stays the same with latex-environments
1458 tmp->SetOnlyLayout(bparams, firstpar->layout);
1459 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1462 if (Last() > pos || !Last() || flag == 2) {
1463 tmp->SetOnlyLayout(bparams, firstpar->layout);
1464 tmp->align = firstpar->align;
1465 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1467 tmp->line_bottom = firstpar->line_bottom;
1468 firstpar->line_bottom = false;
1469 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1470 firstpar->pagebreak_bottom = false;
1471 tmp->added_space_bottom = firstpar->added_space_bottom;
1472 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1474 tmp->depth = firstpar->depth;
1475 tmp->noindent = firstpar->noindent;
1477 // copy everything behind the break-position
1478 // to the new paragraph
1480 while (ParFromPos(pos_first) != par)
1483 pos_end = pos_first + par->text.size() - 1;
1485 for (i = j = pos; i <= pos_end; ++i) {
1486 par->CutIntoMinibuffer(bparams, i - pos_first);
1487 if (tmp->InsertFromMinibuffer(j - pos))
1490 tmp->text.resize(tmp->text.size());
1491 for (i = pos_end; i >= pos; --i)
1492 par->Erase(i - pos_first);
1494 par->text.resize(par->text.size());
1497 // just an idea of me
1499 tmp->line_top = firstpar->line_top;
1500 tmp->pagebreak_top = firstpar->pagebreak_top;
1501 tmp->added_space_top = firstpar->added_space_top;
1502 tmp->bibkey = firstpar->bibkey;
1504 // layout stays the same with latex-environments
1506 firstpar->SetOnlyLayout(bparams, tmp->layout);
1507 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1508 firstpar->depth = tmp->depth;
1514 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1517 par = par->FirstPhysicalPar();
1518 footnoteflag = par->footnoteflag;
1519 footnotekind = par->footnotekind;
1521 layout = par->layout;
1522 align = par-> align;
1523 SetLabelWidthString(par->labelwidthstring);
1525 line_bottom = par->line_bottom;
1526 pagebreak_bottom = par->pagebreak_bottom;
1527 added_space_bottom = par->added_space_bottom;
1529 line_top = par->line_top;
1530 pagebreak_top = par->pagebreak_top;
1531 added_space_top = par->added_space_top;
1533 spacing = par->spacing;
1535 pextra_type = par->pextra_type;
1536 pextra_width = par->pextra_width;
1537 pextra_widthp = par->pextra_widthp;
1538 pextra_alignment = par->pextra_alignment;
1539 pextra_hfill = par->pextra_hfill;
1540 pextra_start_minipage = par->pextra_start_minipage;
1542 noindent = par->noindent;
1548 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1550 LyXParagraph * tmppar = this;
1553 && tmppar->previous->footnoteflag ==
1554 LyXParagraph::CLOSED_FOOTNOTE)
1555 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1556 tmppar = tmppar->previous;
1559 return this; // This should never happen!
1566 int LyXParagraph::StripLeadingSpaces(LyXTextClassList::size_type tclass)
1568 if (textclasslist.Style(tclass, GetLayout()).free_spacing)
1578 && (IsNewline(0) || IsLineSeparator(0))){
1587 LyXParagraph * LyXParagraph::Clone() const
1589 // create a new paragraph
1590 LyXParagraph * result = new LyXParagraph;
1592 result->MakeSameLayout(this);
1594 // this is because of the dummy layout of the paragraphs that
1596 result->layout = layout;
1599 /* table stuff -- begin*/
1601 result->table = table->Clone();
1604 /* table stuff -- end*/
1606 result->inset_owner = inset_owner;
1609 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1612 // copy everything behind the break-position to the new paragraph
1614 result->text = text;
1615 result->fontlist = fontlist;
1616 result->insetlist = insetlist;
1617 for (InsetList::iterator it = result->insetlist.begin();
1618 it != result->insetlist.end(); ++it)
1619 (*it).inset = (*it).inset->Clone();
1624 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1627 par = par->FirstPhysicalPar();
1632 par->footnoteflag == footnoteflag &&
1633 par->footnotekind == footnotekind &&
1635 par->layout == layout &&
1637 par->align == align &&
1639 par->line_bottom == line_bottom &&
1640 par->pagebreak_bottom == pagebreak_bottom &&
1641 par->added_space_bottom == added_space_bottom &&
1643 par->line_top == line_top &&
1644 par->pagebreak_top == pagebreak_top &&
1645 par->added_space_top == added_space_top &&
1647 par->spacing == spacing &&
1649 par->pextra_type == pextra_type &&
1650 par->pextra_width == pextra_width &&
1651 par->pextra_widthp == pextra_widthp &&
1652 par->pextra_alignment == pextra_alignment &&
1653 par->pextra_hfill == pextra_hfill &&
1654 par->pextra_start_minipage == pextra_start_minipage &&
1656 par->table == table && // what means: NO TABLE AT ALL
1659 par->noindent == noindent &&
1660 par->depth == depth);
1664 void LyXParagraph::BreakParagraphConservative(BufferParams const & bparams,
1665 LyXParagraph::size_type pos)
1667 // create a new paragraph
1668 LyXParagraph * par = ParFromPos(pos);
1670 LyXParagraph * tmp = new LyXParagraph(par);
1672 tmp->MakeSameLayout(par);
1674 // When can pos < Last()?
1675 // I guess pos == Last() is possible.
1677 // copy everything behind the break-position to the new
1679 size_type pos_first = 0;
1680 while (ParFromPos(pos_first) != par)
1682 size_type pos_end = pos_first + par->text.size() - 1;
1685 for (i = j = pos; i <= pos_end; ++i) {
1686 par->CutIntoMinibuffer(bparams, i - pos_first);
1687 if (tmp->InsertFromMinibuffer(j - pos))
1690 tmp->text.resize(tmp->text.size());
1691 for (size_type i = pos_end; i >= pos; --i)
1692 par->Erase(i - pos_first);
1694 par->text.resize(par->text.size());
1699 // Be carefull, this does not make any check at all.
1700 void LyXParagraph::PasteParagraph(BufferParams const & bparams)
1702 // copy the next paragraph to this one
1703 LyXParagraph * the_next = Next();
1705 LyXParagraph * firstpar = FirstPhysicalPar();
1707 LyXParagraph * firstpar = this;
1710 // first the DTP-stuff
1711 firstpar->line_bottom = the_next->line_bottom;
1712 firstpar->added_space_bottom = the_next->added_space_bottom;
1713 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1715 size_type pos_end = the_next->text.size() - 1;
1716 size_type pos_insert = Last();
1718 // ok, now copy the paragraph
1720 for (i = j = 0; i <= pos_end; ++i) {
1721 the_next->CutIntoMinibuffer(bparams, i);
1722 if (InsertFromMinibuffer(pos_insert + j))
1726 // delete the next paragraph
1727 LyXParagraph * ppar = the_next->previous;
1728 LyXParagraph * npar = the_next->next;
1735 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1737 LyXParagraph * par = ParFromPos(pos);
1739 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1740 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1746 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1748 LyXParagraph * par = ParFromPos(pos);
1750 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1751 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1758 int LyXParagraph::GetEndLabel(BufferParams const & bparams) const
1760 LyXParagraph const * par = this;
1761 int par_depth = GetDepth();
1763 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1765 textclasslist.Style(bparams.textclass,
1766 layout).endlabeltype;
1767 if (endlabeltype != END_LABEL_NO_LABEL) {
1768 LyXParagraph const * last = this;
1770 if( footnoteflag == NO_FOOTNOTE)
1771 last = LastPhysicalPar();
1772 else if (next->footnoteflag == NO_FOOTNOTE)
1773 return endlabeltype;
1778 if (!last || !last->next)
1779 return endlabeltype;
1781 int next_depth = last->next->GetDepth();
1782 if (par_depth > next_depth ||
1783 (par_depth == next_depth && layout != last->next->GetLayout() ))
1784 return endlabeltype;
1789 par = par->DepthHook(par_depth - 1);
1791 par_depth = par->GetDepth();
1793 return END_LABEL_NO_LABEL;
1797 LyXTextClass::size_type LyXParagraph::GetLayout() const
1800 return FirstPhysicalPar()->layout;
1807 char LyXParagraph::GetDepth() const
1810 return FirstPhysicalPar()->depth;
1817 char LyXParagraph::GetAlign() const
1820 return FirstPhysicalPar()->align;
1827 string const & LyXParagraph::GetLabelstring() const
1830 return FirstPhysicalPar()->labelstring;
1837 int LyXParagraph::GetFirstCounter(int i) const
1840 return FirstPhysicalPar()->counter_[i];
1847 // the next two functions are for the manual labels
1848 string LyXParagraph::GetLabelWidthString() const
1851 if (!FirstPhysicalPar()->labelwidthstring.empty())
1852 return FirstPhysicalPar()->labelwidthstring;
1854 if (!labelwidthstring.empty())
1855 return labelwidthstring;
1858 return _("Senseless with this layout!");
1862 void LyXParagraph::SetLabelWidthString(string const & s)
1865 LyXParagraph * par = FirstPhysicalPar();
1867 par->labelwidthstring = s;
1869 labelwidthstring = s;
1874 void LyXParagraph::SetOnlyLayout(BufferParams const & bparams,
1875 LyXTextClass::size_type new_layout)
1878 LyXParagraph * par = FirstPhysicalPar();
1880 LyXParagraph * par = this;
1882 LyXParagraph * ppar = 0;
1883 LyXParagraph * npar = 0;
1885 par->layout = new_layout;
1887 /* table stuff -- begin*/
1890 /* table stuff -- end*/
1892 if (par->pextra_type == PEXTRA_NONE) {
1893 if (par->Previous()) {
1895 ppar = par->Previous()->FirstPhysicalPar();
1897 ppar = par->Previous();
1901 && (ppar->depth > par->depth))
1903 ppar = ppar->Previous()->FirstPhysicalPar();
1905 ppar = ppar->Previous();
1910 npar = par->Next()->NextAfterFootnote();
1916 && (npar->depth > par->depth))
1918 npar = npar->Next()->NextAfterFootnote();
1920 npar = npar->Next();
1923 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1925 p1 = ppar->pextra_width,
1926 p2 = ppar->pextra_widthp;
1927 ppar->SetPExtraType(bparams, ppar->pextra_type,
1928 p1.c_str(), p2.c_str());
1930 if ((par->pextra_type == PEXTRA_NONE) &&
1931 npar && (npar->pextra_type != PEXTRA_NONE)) {
1933 p1 = npar->pextra_width,
1934 p2 = npar->pextra_widthp;
1935 npar->SetPExtraType(bparams, npar->pextra_type,
1936 p1.c_str(), p2.c_str());
1942 void LyXParagraph::SetLayout(BufferParams const & bparams,
1943 LyXTextClass::size_type new_layout)
1947 * par = FirstPhysicalPar(),
1954 par->layout = new_layout;
1955 par->labelwidthstring.erase();
1956 par->align = LYX_ALIGN_LAYOUT;
1957 par->added_space_top = VSpace(VSpace::NONE);
1958 par->added_space_bottom = VSpace(VSpace::NONE);
1959 par->spacing.set(Spacing::Default);
1962 /* table stuff -- begin*/
1965 /* table stuff -- end*/
1967 if (par->pextra_type == PEXTRA_NONE) {
1968 if (par->Previous()) {
1970 ppar = par->Previous()->FirstPhysicalPar();
1972 ppar = par->Previous();
1976 && (ppar->depth > par->depth))
1978 ppar = ppar->Previous()->FirstPhysicalPar();
1980 ppar = ppar->Previous();
1985 npar = par->Next()->NextAfterFootnote();
1991 && (npar->depth > par->depth))
1993 npar = npar->Next()->NextAfterFootnote();
1995 npar = npar->Next();
1998 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2000 p1 = ppar->pextra_width,
2001 p2 = ppar->pextra_widthp;
2002 ppar->SetPExtraType(bparams, ppar->pextra_type,
2003 p1.c_str(), p2.c_str());
2005 if ((par->pextra_type == PEXTRA_NONE) &&
2006 npar && (npar->pextra_type != PEXTRA_NONE)) {
2008 p1 = npar->pextra_width,
2009 p2 = npar->pextra_widthp;
2010 npar->SetPExtraType(bparams, npar->pextra_type,
2011 p1.c_str(), p2.c_str());
2017 // if the layout of a paragraph contains a manual label, the beginning of the
2018 // main body is the beginning of the second word. This is what the par-
2019 // function returns. If the layout does not contain a label, the main
2020 // body always starts with position 0. This differentiation is necessary,
2021 // because there cannot be a newline or a blank <= the beginning of the
2022 // main body in TeX.
2024 int LyXParagraph::BeginningOfMainBody() const
2027 if (FirstPhysicalPar() != this)
2030 // Unroll the first two cycles of the loop
2031 // and remember the previous character to
2032 // remove unnecessary GetChar() calls
2035 && GetChar(i) != LyXParagraph::META_NEWLINE
2038 char previous_char = 0, temp = 0;
2040 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2041 // Yes, this ^ is supposed to be "= " not "=="
2044 && previous_char != ' '
2045 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2047 previous_char = temp;
2053 if (i == 0 && i == size() &&
2054 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
2055 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2056 ++i; /* the cursor should not jump
2057 * to the main body if there
2064 LyXParagraph * LyXParagraph::DepthHook(int deth)
2066 LyXParagraph * newpar = this;
2072 newpar = newpar->FirstPhysicalPar()->Previous();
2074 newpar = newpar->Previous();
2076 } while (newpar && newpar->GetDepth() > deth
2078 && newpar->footnoteflag == footnoteflag
2083 if (Previous() || GetDepth())
2084 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2089 return newpar->FirstPhysicalPar();
2096 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
2098 LyXParagraph const * newpar = this;
2104 newpar = newpar->FirstPhysicalPar()->Previous();
2106 newpar = newpar->Previous();
2108 } while (newpar && newpar->GetDepth() > deth
2110 && newpar->footnoteflag == footnoteflag
2115 if (Previous() || GetDepth())
2116 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2121 return newpar->FirstPhysicalPar();
2128 int LyXParagraph::AutoDeleteInsets()
2131 InsetList::size_type index = 0;
2132 while (index < insetlist.size()) {
2133 if (insetlist[index].inset && insetlist[index].inset->AutoDelete()) {
2134 Erase(insetlist[index].pos);
2135 // Erase() calls to insetlist.erase(&insetlist[index])
2136 // so index shouldn't be increased.
2145 LyXParagraph::inset_iterator
2146 LyXParagraph::InsetIterator(LyXParagraph::size_type pos)
2148 InsetTable search_inset(pos, 0);
2149 InsetList::iterator it = lower_bound(insetlist.begin(),
2151 search_inset, matchIT());
2152 return inset_iterator(it);
2156 // returns -1 if inset not found
2157 int LyXParagraph::GetPositionOfInset(Inset * inset) const
2160 // We could use lower_bound here too, we just need to add
2161 // the approp. operator() to matchIT (and change the name
2162 // of that struct). Code would then be:
2163 // InsetList::const_iterator cit = lower_bound(insetlist.begin(),
2165 // inset, matchIT());
2166 // if ((*cit).inset == inset) {
2167 // return (*cit).pos;
2169 for (InsetList::const_iterator cit = insetlist.begin();
2170 cit != insetlist.end(); ++cit) {
2171 if ((*cit).inset == inset) {
2176 // Think about footnotes.
2177 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2178 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2180 NextAfterFootnote()->GetPositionOfInset(inset);
2182 return text.size() + 1 + further;
2189 LyXParagraph * LyXParagraph::TeXOnePar(Buffer const * buf,
2190 BufferParams const & bparams,
2191 ostream & os, TexRow & texrow,
2196 TexRow & foot_texrow,
2201 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2202 LyXLayout const & style =
2203 textclasslist.Style(bparams.textclass,
2206 bool further_blank_line = false;
2209 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2212 if (start_of_appendix) {
2213 os << "\\appendix\n";
2217 if (!spacing.isDefault()
2218 && (!Previous() || !Previous()->HasSameLayout(this))) {
2219 os << spacing.writeEnvirBegin() << "\n";
2223 if (tex_code_break_column && style.isCommand()){
2228 if (pagebreak_top) {
2230 further_blank_line = true;
2232 if (added_space_top.kind() != VSpace::NONE) {
2233 os << added_space_top.asLatexCommand(bparams);
2234 further_blank_line = true;
2238 os << "\\lyxline{\\" << getFont(bparams, 0).latexSize() << '}'
2239 << "\\vspace{-1\\parskip}";
2240 further_blank_line = true;
2243 if (further_blank_line){
2248 Language const * language = getParLanguage(bparams);
2249 Language const * doc_language = bparams.language_info;
2250 Language const * previous_language = previous
2251 ? previous->getParLanguage(bparams) : doc_language;
2252 if (language != doc_language && language != previous_language) {
2253 os << subst(lyxrc.language_command_begin, "$$lang",
2259 if (bparams.inputenc == "auto" &&
2260 language->encoding() != previous_language->encoding()) {
2261 os << "\\inputencoding{"
2262 << language->encoding()->LatexName()
2267 switch (style.latextype) {
2270 << style.latexname()
2271 << style.latexparam();
2273 case LATEX_ITEM_ENVIRONMENT:
2275 bibkey->Latex(buf, os, false, false);
2279 case LATEX_LIST_ENVIRONMENT:
2286 bool need_par = SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2288 LyXParagraph * par = next;
2290 // Spit out footnotes
2291 if (lyxrc.rtl_support) {
2292 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2293 && next->footnoteflag != footnoteflag) {
2294 LyXParagraph * p = 0;
2295 bool is_rtl = (size() > 0)
2296 ? GetFontSettings(bparams,
2297 size()-1).isRightToLeft()
2298 : language->RightToLeft();
2299 if ( (p = NextAfterFootnote()) != 0 &&
2301 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2302 is_rtl = getParLanguage(bparams)->RightToLeft();
2303 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2304 && par->footnoteflag != footnoteflag) {
2305 par = par->TeXFootnote(buf, bparams,
2307 foot_texrow, foot_count,
2309 par->SimpleTeXOnePar(buf, bparams,
2310 os, texrow, moving_arg);
2311 is_rtl = (par->size() > 0)
2312 ? par->GetFontSettings(bparams,
2313 par->size()-1).isRightToLeft()
2314 : language->RightToLeft();
2316 par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2317 (p = par->NextAfterFootnote()) != 0 &&
2319 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2320 is_rtl = language->RightToLeft();
2325 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2326 && par->footnoteflag != footnoteflag) {
2327 par = par->TeXFootnote(buf, bparams,
2329 foot, foot_texrow, foot_count,
2331 par->SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2337 // Make sure that \\par is done with the font of the last
2338 // character if this has another size as the default.
2339 // This is necessary because LaTeX (and LyX on the screen)
2340 // calculates the space between the baselines according
2341 // to this font. (Matthias)
2342 LyXFont font = getFont(bparams, Last() - 1);
2344 if (style.resfont.size() != font.size()) {
2350 } else if (textclasslist.Style(bparams.textclass,
2351 GetLayout()).isCommand()) {
2352 if (style.resfont.size() != font.size()) {
2358 } else if (style.resfont.size() != font.size()){
2359 os << "{\\" << font.latexSize() << " \\par}";
2362 if (language != doc_language &&
2365 || (footnoteflag != NO_FOOTNOTE && par->footnoteflag != footnoteflag)
2367 || par->getParLanguage(bparams) != language)) {
2369 << subst(lyxrc.language_command_end, "$$lang",
2370 doc_language->lang());
2373 switch (style.latextype) {
2374 case LATEX_ITEM_ENVIRONMENT:
2375 case LATEX_LIST_ENVIRONMENT:
2376 if (par && (depth < par->depth)) {
2381 case LATEX_ENVIRONMENT:
2382 // if its the last paragraph of the current environment
2383 // skip it otherwise fall through
2385 && (par->layout != layout
2386 || par->depth != depth
2387 || par->pextra_type != pextra_type))
2390 // we don't need it for the last paragraph!!!
2394 footnoteflag != LyXParagraph::NO_FOOTNOTE
2395 && footnotekind != LyXParagraph::FOOTNOTE
2396 && footnotekind != LyXParagraph::MARGIN &&
2401 // don't insert this if we would be adding it
2402 // before or after a table in a float. This
2403 // little trick is needed in order to allow
2404 // use of tables in \subfigures or \subtables.
2410 further_blank_line = false;
2412 os << "\\lyxline{\\" << getFont(bparams, Last() - 1).latexSize() << '}';
2413 further_blank_line = true;
2416 if (added_space_bottom.kind() != VSpace::NONE) {
2417 os << added_space_bottom.asLatexCommand(bparams);
2418 further_blank_line = true;
2421 if (pagebreak_bottom) {
2423 further_blank_line = true;
2426 if (further_blank_line){
2431 if (!spacing.isDefault()
2432 && (!par || !par->HasSameLayout(this))) {
2433 os << spacing.writeEnvirEnd() << "\n";
2437 // we don't need it for the last paragraph!!!
2440 && !(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2441 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)
2448 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2453 // This one spits out the text of the paragraph
2454 bool LyXParagraph::SimpleTeXOnePar(Buffer const * buf,
2455 BufferParams const & bparams,
2456 ostream & os, TexRow & texrow,
2459 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2463 return SimpleTeXOneTablePar(buf, bparams, os, texrow);
2466 bool return_value = false;
2468 LyXLayout const & style =
2469 textclasslist.Style(bparams.textclass,
2471 LyXFont basefont, last_font;
2473 // Maybe we have to create a optional argument.
2474 size_type main_body;
2475 if (style.labeltype != LABEL_MANUAL)
2478 main_body = BeginningOfMainBody();
2480 if (main_body > 0) {
2482 basefont = getFont(bparams, -2); // Get label font
2484 basefont = getFont(bparams, -1); // Get layout font
2495 if (style.isCommand()) {
2498 } else if (align != LYX_ALIGN_LAYOUT) {
2501 return_value = true;
2505 moving_arg |= style.needprotect;
2507 // Which font is currently active?
2508 LyXFont running_font(basefont);
2509 // Do we have an open font change?
2510 bool open_font = false;
2512 texrow.start(this, 0);
2514 for (size_type i = 0; i < size(); ++i) {
2516 // First char in paragraph or after label?
2522 if (main_body > 0) {
2524 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2527 basefont = getFont(bparams, -1); // Now use the layout font
2528 running_font = basefont;
2532 if (style.isCommand()) {
2535 } else if (align != LYX_ALIGN_LAYOUT) {
2538 return_value = true;
2542 os << "\\noindent ";
2546 case LYX_ALIGN_NONE:
2547 case LYX_ALIGN_BLOCK:
2548 case LYX_ALIGN_LAYOUT:
2549 case LYX_ALIGN_SPECIAL:
2551 case LYX_ALIGN_LEFT:
2552 if (getParLanguage(bparams)->lang() != "hebrew") {
2553 os << "\\raggedright ";
2556 os << "\\raggedleft ";
2560 case LYX_ALIGN_RIGHT:
2561 if (getParLanguage(bparams)->lang() != "hebrew") {
2562 os << "\\raggedleft ";
2565 os << "\\raggedright ";
2569 case LYX_ALIGN_CENTER:
2570 os << "\\centering ";
2576 value_type c = GetChar(i);
2578 // Fully instantiated font
2579 LyXFont font = getFont(bparams, i);
2580 LyXParagraph * p = 0;
2584 previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2585 (p = PreviousBeforeFootnote()) != 0)
2589 last_font = p->getFont(bparams, p->size() - 1);
2591 last_font = running_font;
2593 // Spaces at end of font change are simulated to be
2594 // outside font change, i.e. we write "\textXX{text} "
2595 // rather than "\textXX{text }". (Asger)
2596 if (open_font && c == ' ' && i <= size() - 2
2597 && !getFont(bparams, i + 1).equalExceptLatex(running_font)
2598 && !getFont(bparams, i + 1).equalExceptLatex(font)) {
2599 font = getFont(bparams, i + 1);
2601 // We end font definition before blanks
2602 if (!font.equalExceptLatex(running_font) && open_font) {
2603 column += running_font.latexWriteEndChanges(os,
2605 (i == main_body-1) ? basefont : font);
2606 running_font = basefont;
2610 // Blanks are printed before start of fontswitch
2612 // Do not print the separation of the optional argument
2613 if (i != main_body - 1) {
2614 SimpleTeXBlanks(os, texrow, i,
2615 column, font, style);
2619 // Do we need to change font?
2620 if (!font.equalExceptLatex(running_font)
2621 && i != main_body-1) {
2622 column += font.latexWriteStartChanges(os, basefont,
2624 running_font = font;
2628 if (c == LyXParagraph::META_NEWLINE) {
2629 // newlines are handled differently here than
2630 // the default in SimpleTeXSpecialChars().
2631 if (!style.newline_allowed
2632 || font.latex() == LyXFont::ON) {
2636 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2639 basefont = getFont(bparams, -1);
2640 running_font = basefont;
2641 if (font.family() ==
2642 LyXFont::TYPEWRITER_FAMILY) {
2650 texrow.start(this, i + 1);
2653 SimpleTeXSpecialChars(buf, bparams,
2654 os, texrow, moving_arg,
2655 font, running_font, basefont,
2656 open_font, style, i, column, c);
2660 // If we have an open font definition, we have to close it
2662 LyXParagraph * p = 0;
2665 && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2666 && (p = NextAfterFootnote()) != 0
2671 running_font.latexWriteEndChanges(os, basefont,
2672 p->getFont(bparams, 0));
2674 running_font.latexWriteEndChanges(os, basefont, basefont);
2677 // Needed if there is an optional argument but no contents.
2678 if (main_body > 0 && main_body == size()) {
2680 return_value = false;
2683 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2684 return return_value;
2688 // This one spits out the text of a table paragraph
2689 bool LyXParagraph::SimpleTeXOneTablePar(Buffer const * buf,
2690 BufferParams const & bparams,
2691 ostream & os, TexRow & texrow)
2693 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2695 bool return_value = false;
2697 LyXLayout const & style =
2698 textclasslist.Style(bparams.textclass, GetLayout());
2702 if (!IsDummy()) { // it is dummy if it is in a float!!!
2704 if (style.isCommand()) {
2707 } else if (align != LYX_ALIGN_LAYOUT) {
2710 return_value = true;
2713 os << "\\noindent ";
2717 case LYX_ALIGN_NONE:
2718 case LYX_ALIGN_BLOCK:
2719 case LYX_ALIGN_LAYOUT:
2720 case LYX_ALIGN_SPECIAL: break;
2721 case LYX_ALIGN_LEFT:
2722 os << "\\raggedright ";
2725 case LYX_ALIGN_RIGHT:
2726 os << "\\raggedleft ";
2729 case LYX_ALIGN_CENTER:
2730 os << "\\centering ";
2738 LyXFont basefont = getFont(bparams, -1); // Get layout font
2739 // Which font is currently active?
2740 LyXFont running_font = basefont;
2742 // Do we have an open font change?
2743 bool open_font = false;
2744 int current_cell_number = -1;
2745 int tmp = table->TexEndOfCell(os, current_cell_number);
2746 for (; tmp > 0 ; --tmp)
2749 texrow.start(this, 0);
2751 bool is_rtl = getParLanguage(bparams)->RightToLeft();
2752 bool first_in_cell = true;
2754 for (size_type i = 0; i < size(); ++i) {
2755 value_type c = GetChar(i);
2756 if (table->IsContRow(current_cell_number + 1)) {
2757 if (c == LyXParagraph::META_NEWLINE)
2758 ++current_cell_number;
2763 if (first_in_cell && is_rtl) {
2766 first_in_cell = false;
2769 // Fully instantiated font
2770 LyXFont font = getFont(bparams, i);
2771 last_font = running_font;
2773 // Spaces at end of font change are simulated to be
2774 // outside font change.
2775 // i.e. we write "\textXX{text} " rather than
2776 // "\textXX{text }". (Asger)
2777 if (open_font && c == ' ' && i <= size() - 2
2778 && getFont(bparams, i + 1) != running_font
2779 && getFont(bparams, i + 1) != font) {
2780 font = getFont(bparams, i + 1);
2783 // We end font definition before blanks
2784 if (font != running_font && open_font) {
2785 column += running_font.latexWriteEndChanges(os,
2788 running_font = basefont;
2791 // Blanks are printed before start of fontswitch
2793 SimpleTeXBlanks(os, texrow, i, column, font, style);
2795 // Do we need to change font?
2796 if (font != running_font) {
2797 column += font.latexWriteStartChanges(os, basefont,
2799 running_font = font;
2802 // Do we need to turn on LaTeX mode?
2803 if (font.latex() != running_font.latex()) {
2804 if (font.latex() == LyXFont::ON
2805 && style.needprotect) {
2810 if (c == LyXParagraph::META_NEWLINE) {
2811 // special case for inside a table
2812 // different from default case in
2813 // SimpleTeXSpecialChars()
2815 column += running_font
2816 .latexWriteEndChanges(os, basefont,
2820 basefont = getFont(bparams, -1);
2821 running_font = basefont;
2822 ++current_cell_number;
2823 if (table->CellHasContRow(current_cell_number) >= 0) {
2824 TeXContTableRows(buf, bparams, os, i + 1,
2825 current_cell_number,
2828 if (is_rtl && !first_in_cell) {
2830 first_in_cell = true;
2833 // if this cell follow only ContRows till end don't
2834 // put the EndOfCell because it is put after the
2836 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2837 --current_cell_number;
2840 int tmp = table->TexEndOfCell(os,
2841 current_cell_number);
2844 } else if (tmp < 0) {
2850 texrow.start(this, i + 1);
2852 SimpleTeXSpecialChars(buf, bparams,
2854 font, running_font, basefont,
2855 open_font, style, i, column, c);
2859 // If we have an open font definition, we have to close it
2861 running_font.latexWriteEndChanges(os, basefont, basefont);
2863 ++current_cell_number;
2864 if (is_rtl && !first_in_cell)
2866 tmp = table->TexEndOfCell(os, current_cell_number);
2867 for (; tmp > 0; --tmp)
2869 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2870 return return_value;
2874 // This one spits out the text off ContRows in tables
2875 bool LyXParagraph::TeXContTableRows(Buffer const * buf,
2876 BufferParams const & bparams,
2878 LyXParagraph::size_type i,
2879 int current_cell_number,
2880 int & column, TexRow & texrow)
2882 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2886 bool return_value = false;
2887 LyXLayout const & style =
2888 textclasslist.Style(bparams.textclass,
2890 LyXFont basefont = getFont(bparams, -1); // Get layout font
2892 // Which font is currently active?
2893 LyXFont running_font = basefont;
2894 // Do we have an open font change?
2895 bool open_font = false;
2897 size_type lastpos = i;
2898 int cell = table->CellHasContRow(current_cell_number);
2899 ++current_cell_number;
2902 // first find the right position
2904 for (; (i < size()) && (current_cell_number < cell); ++i) {
2906 if (c == LyXParagraph::META_NEWLINE)
2907 ++current_cell_number;
2911 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2915 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2920 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2924 // Fully instantiated font
2925 LyXFont font = getFont(bparams, i);
2926 last_font = running_font;
2928 // Spaces at end of font change are simulated to
2929 // be outside font change. i.e. we write
2930 // "\textXX{text} " rather than "\textXX{text }".
2932 if (open_font && c == ' ' && i <= size() - 2
2933 && getFont(bparams, i + 1) != running_font
2934 && getFont(bparams, i + 1) != font) {
2935 font = getFont(bparams, i + 1);
2938 // We end font definition before blanks
2939 if (font != running_font && open_font) {
2940 column += running_font.latexWriteEndChanges(os, basefont, font);
2941 running_font = basefont;
2944 // Blanks are printed before start of fontswitch
2946 SimpleTeXBlanks(os, texrow, i,
2947 column, font, style);
2949 // Do we need to change font?
2950 if (font != running_font) {
2952 font.latexWriteStartChanges(os,
2955 running_font = font;
2958 // Do we need to turn on LaTeX mode?
2959 if (font.latex() != running_font.latex()) {
2960 if (font.latex() == LyXFont::ON
2961 && style.needprotect) {
2966 SimpleTeXSpecialChars(buf, bparams,
2967 os, texrow, false, font,
2968 running_font, basefont,
2969 open_font, style, i, column, c);
2971 // If we have an open font definition, we have to close it
2973 running_font.latexWriteEndChanges(os, basefont,
2977 basefont = getFont(bparams, -1);
2978 running_font = basefont;
2979 cell = table->CellHasContRow(current_cell_number);
2981 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2982 return return_value;
2986 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2988 bool retval = false;
2990 case LyXParagraph::META_HFILL:
2991 sgml_string.erase();
2993 case LyXParagraph::META_NEWLINE:
2997 sgml_string = "&";
3000 sgml_string = "<";
3003 sgml_string = ">";
3006 sgml_string = "$";
3009 sgml_string = "#";
3012 sgml_string = "%";
3015 sgml_string = "[";
3018 sgml_string = "]";
3021 sgml_string = "{";
3024 sgml_string = "}";
3027 sgml_string = "˜";
3030 sgml_string = """;
3033 sgml_string = "\";
3039 case '\0': // Ignore :-)
3040 sgml_string.erase();
3050 void LyXParagraph::SimpleDocBookOneTablePar(Buffer const * buffer,
3051 ostream & os, string & extra,
3052 int & desc_on, int depth)
3054 BufferParams const & bparams = buffer->params;
3056 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3058 LyXFont font1, font2;
3061 size_type main_body;
3062 bool emph_flag = false;
3064 LyXLayout const & style =
3065 textclasslist.Style(bparams.textclass,
3068 if (style.labeltype != LABEL_MANUAL)
3071 main_body = BeginningOfMainBody();
3073 // Gets paragraph main font.
3075 font1 = style.labelfont;
3079 int char_line_count = depth;
3080 os << newlineAndDepth(depth);
3082 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3083 os << "<INFORMALTABLE>"
3084 << newlineAndDepth(++depth);
3087 os << "<INFORMALTABLE>"
3088 << newlineAndDepth(++depth);
3090 int current_cell_number = -1;
3091 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3093 // Parsing main loop.
3094 for (size_type i = 0; i < size(); ++i) {
3096 if (table->IsContRow(current_cell_number+1)) {
3097 if (c == LyXParagraph::META_NEWLINE)
3098 ++current_cell_number;
3103 // Fully instantiated font
3104 font2 = getFont(bparams, i);
3106 // Handle <emphasis> tag.
3107 if (font1.emph() != font2.emph() && i) {
3108 if (font2.emph() == LyXFont::ON) {
3111 } else if (emph_flag) {
3112 os << "</emphasis>";
3116 if (c == LyXParagraph::META_NEWLINE) {
3117 // We have only to control for emphasis open here!
3119 os << "</emphasis>";
3122 font1 = font2 = getFont(bparams, -1);
3123 ++current_cell_number;
3124 if (table->CellHasContRow(current_cell_number) >= 0) {
3125 DocBookContTableRows(buffer,
3126 os, extra, desc_on, i + 1,
3127 current_cell_number,
3130 // if this cell follow only ContRows till end don't
3131 // put the EndOfCell because it is put after the
3133 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3134 --current_cell_number;
3137 tmp = table->DocBookEndOfCell(os,
3138 current_cell_number,
3143 } else if (c == LyXParagraph::META_INSET) {
3144 inset = GetInset(i);
3146 std::ostringstream ost;
3147 inset->DocBook(buffer, ost);
3148 string tmp_out = ost.str().c_str();
3151 inset->DocBook(buffer, ost);
3153 char * ctmp = ost.str();
3154 string tmp_out(ctmp);
3158 // This code needs some explanation:
3159 // Two insets are treated specially
3160 // label if it is the first element in a
3161 // command paragraph
3163 // graphics inside tables or figure floats
3165 // title (the equivalente in latex for this
3167 // and title should come first
3170 if(desc_on != 3 || i != 0) {
3171 if(tmp_out[0] == '@') {
3173 extra += frontStrip(tmp_out,
3176 os << frontStrip(tmp_out,
3181 } else if (font2.latex() == LyXFont::ON) {
3182 // "TeX"-Mode on == > SGML-Mode on.
3188 if (linuxDocConvertChar(c, sgml_string)
3189 && !style.free_spacing) {
3190 // in freespacing mode, spaces are
3191 // non-breaking characters
3196 << "</term><listitem><para>";
3208 // Needed if there is an optional argument but no contents.
3209 if (main_body > 0 && main_body == size()) {
3214 os << "</emphasis>";
3217 ++current_cell_number;
3218 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3219 // Resets description flag correctly.
3222 // <term> not closed...
3227 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3229 os << "</INFORMALTABLE>";
3231 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3236 void LyXParagraph::DocBookContTableRows(Buffer const * buffer,
3237 ostream & os, string & extra,
3239 LyXParagraph::size_type i,
3240 int current_cell_number, int &column)
3245 BufferParams const & bparams = buffer->params;
3247 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3252 //string emph = "emphasis";
3253 bool emph_flag = false;
3254 int char_line_count = 0;
3256 LyXLayout const & style =
3257 textclasslist.Style(bparams.textclass,
3260 size_type main_body;
3261 if (style.labeltype != LABEL_MANUAL)
3264 main_body = BeginningOfMainBody();
3266 // Gets paragraph main font.
3269 font1 = style.labelfont;
3273 size_type lastpos = i;
3274 int cell = table->CellHasContRow(current_cell_number);
3275 ++current_cell_number;
3277 // first find the right position
3279 for (; i < size() && current_cell_number < cell; ++i) {
3281 if (c == LyXParagraph::META_NEWLINE)
3282 ++current_cell_number;
3286 // I don't know how to handle this so I comment it
3287 // for the moment (Jug)
3288 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3289 // file += " \\\\\n";
3292 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3297 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3301 // Fully instantiated font
3302 font2 = getFont(bparams, i);
3304 // Handle <emphasis> tag.
3305 if (font1.emph() != font2.emph() && i) {
3306 if (font2.emph() == LyXFont::ON) {
3309 } else if (emph_flag) {
3310 os << "</emphasis>";
3314 if (c == LyXParagraph::META_INSET) {
3315 inset = GetInset(i);
3317 std::ostringstream ost;
3318 inset->DocBook(buffer, ost);
3319 string tmp_out = ost.str().c_str();
3322 inset->DocBook(buffer, ost);
3324 char * ctmp = ost.str();
3325 string tmp_out(ctmp);
3329 // This code needs some explanation:
3330 // Two insets are treated specially
3331 // label if it is the first element in a
3332 // command paragraph
3334 // graphics inside tables or figure floats
3335 // can't go on title (the equivalente in
3336 // latex for this case is caption and title
3337 // should come first
3340 if(desc_on != 3 || i != 0) {
3341 if(tmp_out[0] == '@') {
3343 extra += frontStrip(tmp_out, '@');
3345 os << frontStrip(tmp_out, '@');
3349 } else if (font2.latex() == LyXFont::ON) {
3350 // "TeX"-Mode on == > SGML-Mode on.
3356 if (linuxDocConvertChar(c, sgml_string)
3357 && !style.free_spacing) {
3358 // in freespacing mode, spaces are
3359 // non-breaking characters
3364 << "</term><listitem><para>";
3374 // we have only to control for emphasis open here!
3376 os << "</emphasis>";
3379 font1 = font2 = getFont(bparams, -1);
3380 cell = table->CellHasContRow(current_cell_number);
3382 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3386 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3387 LyXParagraph::size_type const i,
3388 int & column, LyXFont const & font,
3389 LyXLayout const & style)
3391 if (column > tex_code_break_column
3393 && GetChar(i - 1) != ' '
3395 // In LaTeX mode, we don't want to
3396 // break lines since some commands
3398 && ! (font.latex() == LyXFont::ON)
3399 // same in FreeSpacing mode
3400 && !style.free_spacing
3401 // In typewriter mode, we want to avoid
3402 // ! . ? : at the end of a line
3403 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3404 && (GetChar(i-1) == '.'
3405 || GetChar(i-1) == '?'
3406 || GetChar(i-1) == ':'
3407 || GetChar(i-1) == '!'))) {
3408 if (tex_code_break_column == 0) {
3409 // in batchmode we need LaTeX to still
3410 // see it as a space not as an extra '\n'
3416 texrow.start(this, i + 1);
3418 } else if (font.latex() == LyXFont::OFF) {
3419 if (style.free_spacing) {
3428 void LyXParagraph::SimpleTeXSpecialChars(Buffer const * buf,
3429 BufferParams const & bparams,
3430 ostream & os, TexRow & texrow,
3433 LyXFont & running_font,
3436 LyXLayout const & style,
3437 LyXParagraph::size_type & i,
3439 LyXParagraph::value_type const c)
3441 // Two major modes: LaTeX or plain
3442 // Handle here those cases common to both modes
3443 // and then split to handle the two modes separately.
3445 case LyXParagraph::META_INSET: {
3446 Inset * inset = GetInset(i);
3449 int len = os.tellp();
3450 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3451 || inset->LyxCode() == Inset::MATH_CODE
3452 || inset->LyxCode() == Inset::URL_CODE)
3453 && running_font.isRightToLeft()) {
3458 int tmp = inset->Latex(buf, os, moving_arg,
3459 style.free_spacing);
3467 column += os.tellp() - len;
3476 case LyXParagraph::META_NEWLINE:
3478 column += running_font.latexWriteEndChanges(os,
3483 basefont = getFont(bparams, -1);
3484 running_font = basefont;
3487 case LyXParagraph::META_HFILL:
3493 // And now for the special cases within each mode
3494 // Are we in LaTeX mode?
3495 if (font.latex() == LyXFont::ON) {
3496 // at present we only have one option
3497 // but I'll leave it as a switch statement
3498 // so its simpler to extend. (ARRae)
3501 // make sure that we will not print
3502 // error generating chars to the tex
3503 // file. This test would not be needed
3504 // if it were done in the buffer
3512 // Plain mode (i.e. not LaTeX)
3515 os << "\\textbackslash{}";
3519 case '°': case '±': case '²': case '³':
3520 case '×': case '÷': case '¹': case 'ª':
3521 case 'º': case '¬': case 'µ':
3522 if (bparams.inputenc == "latin1" ||
3523 (bparams.inputenc == "auto" &&
3524 font.language()->encoding()->LatexName()
3526 os << "\\ensuremath{"
3535 case '|': case '<': case '>':
3536 // In T1 encoding, these characters exist
3537 if (lyxrc.fontenc == "T1") {
3539 //... but we should avoid ligatures
3540 if ((c == '>' || c == '<')
3542 && GetChar(i + 1) == c) {
3543 //os << "\\textcompwordmark{}";
3544 // Jean-Marc, have a look at
3545 // this. IÂ think this works
3553 // Typewriter font also has them
3554 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3558 // Otherwise, we use what LaTeX
3562 os << "\\textless{}";
3566 os << "\\textgreater{}";
3570 os << "\\textbar{}";
3576 case '-': // "--" in Typewriter mode -> "-{}-"
3578 && GetChar(i + 1) == '-'
3579 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3588 os << "\\char`\\\"{}";
3593 if (bparams.inputenc == "default") {
3602 case '%': case '#': case '{':
3609 os << "\\textasciitilde{}";
3614 os << "\\textasciicircum{}";
3618 case '*': case '[': case ']':
3619 // avoid being mistaken for optional arguments
3620 os << '{' << c << '}';
3625 // Blanks are printed before font switching.
3626 // Sure? I am not! (try nice-latex)
3627 // I am sure it's correct. LyX might be smarter
3628 // in the future, but for now, nothing wrong is
3633 /* idea for labels --- begin*/
3637 && font.family() != LyXFont::TYPEWRITER_FAMILY
3638 && GetChar(i + 1) == 'y'
3639 && GetChar(i + 2) == 'X') {
3647 && font.family() != LyXFont::TYPEWRITER_FAMILY
3648 && GetChar(i + 1) == 'e'
3649 && GetChar(i + 2) == 'X') {
3654 // Check for "LaTeX2e"
3657 && font.family() != LyXFont::TYPEWRITER_FAMILY
3658 && GetChar(i + 1) == 'a'
3659 && GetChar(i + 2) == 'T'
3660 && GetChar(i + 3) == 'e'
3661 && GetChar(i + 4) == 'X'
3662 && GetChar(i + 5) == '2'
3663 && GetChar(i + 6) == 'e') {
3668 // Check for "LaTeX"
3671 && font.family() != LyXFont::TYPEWRITER_FAMILY
3672 && GetChar(i + 1) == 'a'
3673 && GetChar(i + 2) == 'T'
3674 && GetChar(i + 3) == 'e'
3675 && GetChar(i + 4) == 'X') {
3679 /* idea for labels --- end*/
3680 } else if (c != '\0') {
3690 LyXParagraph * LyXParagraph::TeXDeeper(Buffer const * buf,
3691 BufferParams const & bparams,
3692 ostream & os, TexRow & texrow,
3694 TexRow & foot_texrow,
3697 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3698 LyXParagraph * par = this;
3701 (par->depth == depth)
3703 && (par->footnoteflag == footnoteflag)
3708 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3710 if (textclasslist.Style(bparams.textclass,
3711 par->layout).isEnvironment()
3712 || par->pextra_type != PEXTRA_NONE) {
3713 par = par->TeXEnvironment(buf, bparams,
3718 par = par->TeXOnePar(buf, bparams,
3728 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3734 LyXParagraph * LyXParagraph::TeXEnvironment(Buffer const * buf,
3735 BufferParams const & bparams,
3736 ostream & os, TexRow & texrow,
3738 TexRow & foot_texrow,
3741 bool eindent_open = false;
3742 bool foot_this_level = false;
3743 // flags when footnotetext should be appended to file.
3744 static bool minipage_open = false;
3745 static int minipage_open_depth = 0;
3746 char par_sep = bparams.paragraph_separation;
3748 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3751 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3754 LyXLayout const & style =
3755 textclasslist.Style(bparams.textclass,
3758 if (pextra_type == PEXTRA_INDENT) {
3759 if (!pextra_width.empty()) {
3760 os << "\\begin{LyXParagraphIndent}{"
3761 << pextra_width << "}\n";
3763 //float ib = atof(pextra_widthp.c_str())/100;
3764 // string can't handle floats at present (971109)
3765 // so I'll do a conversion by hand knowing that
3766 // the limits are 0.0 to 1.0. ARRae.
3767 os << "\\begin{LyXParagraphIndent}{";
3768 switch (pextra_widthp.length()) {
3780 os << "\\columnwidth}\n";
3783 eindent_open = true;
3785 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3786 if (pextra_hfill && Previous() &&
3787 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3788 os << "\\hfill{}\n";
3791 if (par_sep == BufferParams::PARSEP_INDENT) {
3792 os << "{\\setlength\\parindent{0pt}\n";
3795 os << "\\begin{minipage}";
3796 switch(pextra_alignment) {
3797 case MINIPAGE_ALIGN_TOP:
3800 case MINIPAGE_ALIGN_MIDDLE:
3803 case MINIPAGE_ALIGN_BOTTOM:
3807 if (!pextra_width.empty()) {
3808 os << '{' << pextra_width << "}\n";
3810 //float ib = atof(par->pextra_width.c_str())/100;
3811 // string can't handle floats at present
3812 // so I'll do a conversion by hand knowing that
3813 // the limits are 0.0 to 1.0. ARRae.
3815 switch (pextra_widthp.length()) {
3827 os << "\\columnwidth}\n";
3830 if (par_sep == BufferParams::PARSEP_INDENT) {
3831 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3834 minipage_open = true;
3835 minipage_open_depth = depth;
3838 #ifdef WITH_WARNINGS
3839 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3840 //I disabled it because it breaks when lists span on several
3843 if (style.isEnvironment()){
3844 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3845 #ifdef FANCY_FOOTNOTE_CODE
3846 if (foot_count < 0) {
3847 // flag that footnote[mark][text] should be
3848 // used for any footnotes from now on
3850 foot_this_level = true;
3853 os << "\\begin{" << style.latexname() << "}{"
3854 << labelwidthstring << "}\n";
3855 } else if (style.labeltype == LABEL_BIBLIO) {
3857 os << "\\begin{" << style.latexname() << "}{"
3858 << bibitemWidest(current_view)
3860 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3861 #ifdef FANCY_FOOTNOTE_CODE
3862 if (foot_count < 0) {
3863 // flag that footnote[mark][text] should be
3864 // used for any footnotes from now on
3866 foot_this_level = true;
3869 os << "\\begin{" << style.latexname() << '}'
3870 << style.latexparam() << '\n';
3872 os << "\\begin{" << style.latexname() << '}'
3873 << style.latexparam() << '\n';
3876 LyXParagraph * par = this;
3878 par = par->TeXOnePar(buf, bparams,
3882 foot, foot_texrow, foot_count
3886 if (minipage_open && par && !style.isEnvironment() &&
3887 (par->pextra_type == PEXTRA_MINIPAGE) &&
3888 par->pextra_start_minipage) {
3889 os << "\\end{minipage}\n";
3891 if (par_sep == BufferParams::PARSEP_INDENT) {
3895 minipage_open = false;
3897 if (par && par->depth > depth) {
3898 if (textclasslist.Style(bparams.textclass,
3899 par->layout).isParagraph()
3902 // How to handle this? (Lgb)
3903 //&& !suffixIs(os, "\n\n")
3905 // There should be at least one '\n' already
3906 // but we need there to be two for Standard
3907 // paragraphs that are depth-increment'ed to be
3908 // output correctly. However, tables can
3909 // also be paragraphs so don't adjust them.
3912 // Will it ever harm to have one '\n' too
3913 // many? i.e. that we sometimes will have
3914 // three in a row. (Lgb)
3918 par = par->TeXDeeper(buf, bparams, os, texrow,
3919 foot, foot_texrow, foot_count);
3921 if (par && par->layout == layout && par->depth == depth &&
3922 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3923 if (par->pextra_hfill && par->Previous() &&
3924 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3925 os << "\\hfill{}\n";
3928 if (par_sep == BufferParams::PARSEP_INDENT) {
3929 os << "{\\setlength\\parindent{0pt}\n";
3932 os << "\\begin{minipage}";
3933 switch(par->pextra_alignment) {
3934 case MINIPAGE_ALIGN_TOP:
3937 case MINIPAGE_ALIGN_MIDDLE:
3940 case MINIPAGE_ALIGN_BOTTOM:
3944 if (!par->pextra_width.empty()) {
3945 os << '{' << par->pextra_width << "}\n";
3947 //float ib = atof(par->pextra_widthp.c_str())/100;
3948 // string can't handle floats at present
3949 // so I'll do a conversion by hand knowing that
3950 // the limits are 0.0 to 1.0. ARRae.
3952 switch (par->pextra_widthp.length()) {
3957 os << "0." << par->pextra_widthp;
3960 os << "0.0" << par->pextra_widthp;
3962 os << "\\columnwidth}\n";
3965 if (par_sep == BufferParams::PARSEP_INDENT) {
3966 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3969 minipage_open = true;
3970 minipage_open_depth = par->depth;
3973 && par->layout == layout
3974 && par->depth == depth
3975 && par->pextra_type == pextra_type
3977 && par->footnoteflag == footnoteflag
3981 if (style.isEnvironment()) {
3982 os << "\\end{" << style.latexname() << '}';
3983 // maybe this should go after the minipage closes?
3984 if (foot_this_level) {
3985 if (foot_count >= 1) {
3986 if (foot_count > 1) {
3987 os << "\\addtocounter{footnote}{-"
3992 texrow += foot_texrow;
3994 foot_texrow.reset();
3999 if (minipage_open && (minipage_open_depth == depth) &&
4000 (!par || par->pextra_start_minipage ||
4001 par->pextra_type != PEXTRA_MINIPAGE)) {
4002 os << "\\end{minipage}\n";
4004 if (par_sep == BufferParams::PARSEP_INDENT) {
4008 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4009 os << "\\medskip\n\n";
4013 minipage_open = false;
4016 os << "\\end{LyXParagraphIndent}\n";
4019 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
4020 && par->pextra_hfill)) {
4024 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4025 return par; // ale970302
4030 LyXParagraph * LyXParagraph::TeXFootnote(Buffer const * buf,
4031 BufferParams const & bparams,
4032 ostream & os, TexRow & texrow,
4033 ostream & foot, TexRow & foot_texrow,
4037 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
4038 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
4039 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4040 "No footnote!" << endl;
4042 LyXParagraph * par = this;
4043 LyXLayout const & style =
4044 textclasslist.Style(bparams.textclass,
4045 previous->GetLayout());
4047 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
4048 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4049 "Float other than footnote in command"
4050 " with moving argument is illegal" << endl;
4053 if (footnotekind != LyXParagraph::FOOTNOTE
4054 && footnotekind != LyXParagraph::MARGIN
4057 // How to solve this?
4058 //&& !suffixIs(file, '\n')
4060 // we need to ensure that real floats like tables and figures
4061 // have their \begin{} on a new line otherwise we can get
4062 // incorrect results when using the endfloat.sty package
4063 // especially if two floats follow one another. ARRae 981022
4064 // NOTE: if the file is length 0 it must have just been
4065 // written out so we assume it ended with a '\n'
4067 // As far as I can see there is never any harm in writing
4068 // a '\n' too much. Please tell me if I am wrong. (Lgb)
4073 bool moving_arg = false;
4074 bool need_closing = false;
4075 bool is_rtl = isRightToLeftPar(bparams);
4077 if (is_rtl != parent_is_rtl) {
4082 need_closing = true;
4085 //BufferParams * params = ¤t_view->buffer()->params;
4086 bool footer_in_body = true;
4087 switch (footnotekind) {
4088 case LyXParagraph::FOOTNOTE:
4089 if (style.intitle) {
4090 os << "\\thanks{\n";
4091 footer_in_body = false;
4094 if (foot_count == -1) {
4095 // we're at depth 0 so we can use:
4096 os << "\\footnote{%\n";
4097 footer_in_body = false;
4099 os << "\\footnotemark{}%\n";
4101 // we only need this when there are
4102 // multiple footnotes
4103 os << "\\stepcounter{footnote}";
4105 os << "\\footnotetext{%\n";
4106 foot_texrow.start(this, 0);
4107 foot_texrow.newline();
4112 case LyXParagraph::MARGIN:
4113 os << "\\marginpar{\n";
4115 case LyXParagraph::FIG:
4116 if (pextra_type == PEXTRA_FLOATFLT
4117 && (!pextra_width.empty()
4118 || !pextra_widthp.empty())) {
4119 if (!pextra_width.empty())
4120 os << "\\begin{floatingfigure}{"
4121 << pextra_width << "}\n";
4123 os << "\\begin{floatingfigure}{"
4124 << atoi(pextra_widthp.c_str())/100.0
4125 << "\\textwidth}\n";
4127 os << "\\begin{figure}";
4128 if (!bparams.float_placement.empty()) {
4129 os << '[' << bparams.float_placement << "]\n";
4135 case LyXParagraph::TAB:
4136 os << "\\begin{table}";
4137 if (!bparams.float_placement.empty()) {
4138 os << '[' << bparams.float_placement << "]\n";
4143 case LyXParagraph::WIDE_FIG:
4144 os << "\\begin{figure*}";
4145 if (!bparams.float_placement.empty()) {
4146 os << '[' << bparams.float_placement << "]\n";
4151 case LyXParagraph::WIDE_TAB:
4152 os << "\\begin{table*}";
4153 if (!bparams.float_placement.empty()) {
4154 os << '[' << bparams.float_placement << "]\n";
4159 case LyXParagraph::ALGORITHM:
4160 os << "\\begin{algorithm}\n";
4165 if (footnotekind != LyXParagraph::FOOTNOTE
4166 || !footer_in_body) {
4167 // Process text for all floats except footnotes in body
4169 LyXLayout const & style =
4171 .Style(bparams.textclass, par->layout);
4173 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4175 if (style.isEnvironment()
4176 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4177 // Allows the use of minipages within float
4178 // environments. Shouldn't be circular because
4179 // we don't support footnotes inside
4180 // floats (yet). ARRae
4181 par = par->TeXEnvironment(buf, bparams, os,
4186 par = par->TeXOnePar(buf, bparams,
4187 os, texrow, moving_arg,
4192 if (par && !par->IsDummy() && par->depth > depth) {
4193 par = par->TeXDeeper(buf, bparams, os, texrow,
4197 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4199 // process footnotes > depth 0 or in environments separately
4200 // NOTE: Currently don't support footnotes within footnotes
4201 // even though that is possible using the \footnotemark
4203 std::ostringstream dummy;
4207 TexRow dummy_texrow;
4208 int dummy_count = 0;
4210 LyXLayout const & style =
4212 .Style(bparams.textclass, par->layout);
4214 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4216 if (style.isEnvironment()
4217 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4218 // Allows the use of minipages within float
4219 // environments. Shouldn't be circular because
4220 // we don't support footnotes inside
4221 // floats (yet). ARRae
4222 par = par->TeXEnvironment(buf, bparams,
4224 dummy, dummy_texrow,
4227 par = par->TeXOnePar(buf, bparams,
4230 dummy, dummy_texrow,
4234 if (par && !par->IsDummy() && par->depth > depth) {
4235 par = par->TeXDeeper(buf, bparams,
4237 dummy, dummy_texrow,
4241 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4243 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4244 "Footnote in a Footnote -- not supported"
4247 #ifndef HAVE_OSTREAM
4248 delete [] dummy.str();
4252 switch (footnotekind) {
4253 case LyXParagraph::FOOTNOTE:
4254 if (footer_in_body) {
4255 // This helps tell which of the multiple
4256 // footnotetexts an error was in.
4258 foot_texrow.newline();
4263 case LyXParagraph::MARGIN:
4266 case LyXParagraph::FIG:
4267 if (pextra_type == PEXTRA_FLOATFLT
4268 && (!pextra_width.empty()
4269 || !pextra_widthp.empty()))
4270 os << "\\end{floatingfigure}";
4272 os << "\\end{figure}";
4274 case LyXParagraph::TAB:
4275 os << "\\end{table}";
4277 case LyXParagraph::WIDE_FIG:
4278 os << "\\end{figure*}";
4280 case LyXParagraph::WIDE_TAB:
4281 os << "\\end{table*}";
4283 case LyXParagraph::ALGORITHM:
4284 os << "\\end{algorithm}";
4291 if (footnotekind != LyXParagraph::FOOTNOTE
4292 && footnotekind != LyXParagraph::MARGIN) {
4293 // we need to ensure that real floats like tables and figures
4294 // have their \end{} on a line of their own otherwise we can
4295 // get incorrect results when using the endfloat.sty package.
4300 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4305 bool LyXParagraph::IsDummy() const
4307 return (footnoteflag == LyXParagraph::NO_FOOTNOTE && previous
4308 && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4312 void LyXParagraph::SetPExtraType(BufferParams const & bparams,
4313 int type, char const * width,
4314 char const * widthp)
4317 pextra_width = width;
4318 pextra_widthp = widthp;
4320 if (textclasslist.Style(bparams.textclass,
4321 layout).isEnvironment()) {
4326 while (par && (par->layout == layout)
4327 && (par->depth == depth)) {
4329 par = par->Previous();
4332 par = par->FirstPhysicalPar();
4334 while (par && par->depth > depth) {
4335 par = par->Previous();
4338 par = par->FirstPhysicalPar();
4343 while (par && (par->layout == layout)
4344 && (par->depth == depth)) {
4345 par->pextra_type = type;
4346 par->pextra_width = width;
4347 par->pextra_widthp = widthp;
4349 par = par->NextAfterFootnote();
4353 if (par && (par->depth > depth))
4354 par->SetPExtraType(bparams,
4355 type, width, widthp);
4357 while (par && ((par->depth > depth) || par->IsDummy()))
4358 par = par->NextAfterFootnote();
4360 while (par && ((par->depth > depth)))
4368 void LyXParagraph::UnsetPExtraType(BufferParams const & bparams)
4370 if (pextra_type == PEXTRA_NONE)
4373 pextra_type = PEXTRA_NONE;
4374 pextra_width.erase();
4375 pextra_widthp.erase();
4377 if (textclasslist.Style(bparams.textclass,
4378 layout).isEnvironment()) {
4383 while (par && (par->layout == layout)
4384 && (par->depth == depth)) {
4386 par = par->Previous();
4389 par = par->FirstPhysicalPar();
4391 while (par && par->depth > depth) {
4392 par = par->Previous();
4395 par = par->FirstPhysicalPar();
4400 while (par && (par->layout == layout)
4401 && (par->depth == depth)) {
4402 par->pextra_type = PEXTRA_NONE;
4403 par->pextra_width.erase();
4404 par->pextra_widthp.erase();
4406 par = par->NextAfterFootnote();
4410 if (par && (par->depth > depth))
4411 par->UnsetPExtraType(bparams);
4413 while (par && ((par->depth > depth) || par->IsDummy()))
4414 par = par->NextAfterFootnote();
4416 while (par && ((par->depth > depth)))
4424 bool LyXParagraph::IsHfill(size_type pos) const
4426 return IsHfillChar(GetChar(pos));
4430 bool LyXParagraph::IsInset(size_type pos) const
4432 return IsInsetChar(GetChar(pos));
4437 bool LyXParagraph::IsFloat(size_type pos) const
4439 return IsFloatChar(GetChar(pos));
4444 bool LyXParagraph::IsNewline(size_type pos) const
4446 return pos >= 0 && IsNewlineChar(GetChar(pos));
4450 bool LyXParagraph::IsSeparator(size_type pos) const
4452 return IsSeparatorChar(GetChar(pos));
4456 bool LyXParagraph::IsLineSeparator(size_type pos) const
4458 return IsLineSeparatorChar(GetChar(pos));
4462 bool LyXParagraph::IsKomma(size_type pos) const
4464 return IsKommaChar(GetChar(pos));
4468 /// Used by the spellchecker
4469 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4471 value_type c = GetChar(pos);
4472 if (IsLetterChar(c))
4474 // '\0' is not a letter, allthough every string contains "" (below)
4477 // We want to pass the ' and escape chars to ispell
4478 string extra = lyxrc.isp_esc_chars + '\'';
4482 return contains(extra, ch);
4486 bool LyXParagraph::IsWord(size_type pos ) const
4488 return IsWordChar(GetChar(pos)) ;
4493 LyXParagraph::getParLanguage(BufferParams const & bparams) const
4497 return FirstPhysicalPar()->getParLanguage(bparams);
4504 return GetFirstFontSettings().language();
4507 for (size_type pos = 0; pos < size(); ++pos)
4509 return GetFontSettings(bparams, pos).language();
4510 return GetFirstFontSettings().language();
4514 return previous->getParLanguage(bparams);
4516 return bparams.language_info;
4520 bool LyXParagraph::isRightToLeftPar(BufferParams const & bparams) const
4522 return lyxrc.rtl_support && !table
4523 && getParLanguage(bparams)->RightToLeft();
4527 void LyXParagraph::ChangeLanguage(BufferParams const & bparams,
4528 Language const * from, Language const * to)
4530 for(size_type i = 0; i < size(); ++i) {
4531 LyXFont font = GetFontSettings(bparams, i);
4532 if (font.language() == from) {
4533 font.setLanguage(to);
4540 bool LyXParagraph::isMultiLingual(BufferParams const & bparams)
4542 Language const * doc_language = bparams.language_info;
4543 for (FontList::const_iterator cit = fontlist.begin();
4544 cit != fontlist.end(); ++cit)
4545 if ((*cit).font.language() != doc_language)
4551 // Convert the paragraph to a string.
4552 // Used for building the table of contents
4553 string LyXParagraph::String(Buffer const * buffer, bool label)
4555 BufferParams const & bparams = buffer->params;
4558 if (label && !IsDummy() && !labelstring.empty())
4560 if (label && !labelstring.empty())
4562 s += labelstring + ' ';
4563 string::size_type len = s.size();
4565 for (LyXParagraph::size_type i = 0; i < size(); ++i) {
4566 value_type c = GetChar(i);
4569 else if (c == META_INSET &&
4570 GetInset(i)->LyxCode() == Inset::MATH_CODE) {
4572 std::ostringstream ost;
4573 GetInset(i)->Ascii(buffer, ost);
4576 GetInset(i)->Ascii(buffer, ost);
4579 s += subst(ost.str(),'\n',' ');
4584 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
4585 && footnoteflag == LyXParagraph::NO_FOOTNOTE)
4586 s += NextAfterFootnote()->String(buffer, false);
4590 if (isRightToLeftPar(bparams))
4591 reverse(s.begin() + len,s.end());
4599 string LyXParagraph::String(Buffer const * buffer,
4600 LyXParagraph::size_type beg,
4601 LyXParagraph::size_type end)
4608 for (LyXParagraph::size_type i = 0; i < beg; ++i)
4610 if (cell >= table->NumberOfCellsInRow(actcell))
4619 if (beg == 0 && !IsDummy() && !labelstring.empty())
4621 if (beg == 0 && !labelstring.empty())
4623 s += labelstring + ' ';
4625 for (LyXParagraph::size_type i = beg; i < end; ++i) {
4626 value_type c = GetChar(i);
4629 else if (c == META_INSET) {
4631 std::ostringstream ost;
4632 GetInset(i)->Ascii(buffer, ost);
4635 GetInset(i)->Ascii(buffer, ost);
4639 } else if (table && IsNewlineChar(c)) {
4640 if (cell >= table->NumberOfCellsInRow(actcell)) {
4655 void LyXParagraph::SetInsetOwner(Inset *i)
4658 for (InsetList::const_iterator cit = insetlist.begin();
4659 cit != insetlist.end(); ++cit) {
4661 (*cit).inset->setOwner(i);
4666 void LyXParagraph::deleteInsetsLyXText(BufferView * bv)
4669 for (InsetList::const_iterator cit = insetlist.begin();
4670 cit != insetlist.end(); ++cit) {
4672 if ((*cit).inset->IsTextInset()) {
4673 static_cast<UpdatableInset *>
4674 ((*cit).inset)->deleteLyXText(bv);
4681 void LyXParagraph::resizeInsetsLyXText(BufferView * bv)
4684 for (InsetList::const_iterator cit = insetlist.begin();
4685 cit != insetlist.end(); ++cit) {
4687 if ((*cit).inset->IsTextInset()) {
4688 static_cast<UpdatableInset *>
4689 ((*cit).inset)->resizeLyXText(bv);