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"
20 #include "lyxparagraph.h"
21 #include "support/textutils.h"
24 #include "tex-strings.h"
25 #include "bufferparams.h"
26 #include "support/FileInfo.h"
27 #include "support/LAssert.h"
29 #include "LaTeXFeatures.h"
30 #include "insets/insetinclude.h"
31 #include "insets/insetbib.h"
32 #include "support/filetools.h"
33 #include "lyx_gui_misc.h"
35 #include "support/lyxmanip.h"
41 using std::lower_bound;
42 using std::upper_bound;
45 int tex_code_break_column = 72; // needs non-zero initialization. set later.
46 // this is a bad idea, but how can LyXParagraph find its buffer to get
47 // parameters? (JMarc)
48 extern BufferView * current_view;
49 extern string bibitemWidest(Painter &);
51 // this is a minibuffer
52 static char minibuffer_char;
53 static LyXFont minibuffer_font;
54 static Inset * minibuffer_inset;
57 // Initialization of the counter for the paragraph id's,
58 // declared in lyxparagraph.h
59 unsigned int LyXParagraph::paragraph_id = 0;
62 LyXParagraph::LyXParagraph()
64 text.reserve(500); // is this number too big?
66 for (int i = 0; i < 10; ++i) setCounter(i , 0);
72 footnoteflag = LyXParagraph::NO_FOOTNOTE;
73 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
75 align = LYX_ALIGN_BLOCK;
78 /* table stuff -- begin*/
80 /* table stuff -- end*/
84 bibkey = 0; // ale970302
89 // This konstruktor inserts the new paragraph in a list.
90 LyXParagraph::LyXParagraph(LyXParagraph * par)
93 par->text.resize(par->text.size());
95 for (int i = 0; i < 10; ++i) setCounter(i, 0);
99 // double linked list begin
102 next->previous = this;
104 previous->next = this;
106 footnoteflag = LyXParagraph::NO_FOOTNOTE;
107 footnotekind = LyXParagraph::FOOTNOTE;
110 /* table stuff -- begin*/
112 /* table stuff -- end*/
115 id_ = paragraph_id++;
117 bibkey = 0; // ale970302
123 void LyXParagraph::writeFile(Buffer const * buf, ostream & os,
124 BufferParams const & params,
125 char footflag, char dth) const
127 LyXFont font1, font2;
132 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
134 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
136 // The beginning or the end of a footnote environment?
137 if (footflag != footnoteflag) {
138 footflag = footnoteflag;
140 os << "\n\\begin_float "
141 << string_footnotekinds[footnotekind]
144 os << "\n\\end_float ";
148 // The beginning or end of a deeper (i.e. nested) area?
151 while (depth > dth) {
152 os << "\n\\begin_deeper ";
156 while (depth < dth) {
157 os << "\n\\end_deeper ";
163 // First write the layout
165 << textclasslist.NameOfLayout(params.textclass, layout)
168 // Maybe some vertical spaces.
169 if (added_space_top.kind() != VSpace::NONE)
170 os << "\\added_space_top "
171 << added_space_top.asLyXCommand() << " ";
172 if (added_space_bottom.kind() != VSpace::NONE)
173 os << "\\added_space_bottom "
174 << added_space_bottom.asLyXCommand() << " ";
176 // Maybe the paragraph has special spacing
177 spacing.writeFile(os, true);
179 // The labelwidth string used in lists.
180 if (!labelwidthstring.empty())
181 os << "\\labelwidthstring "
182 << labelwidthstring << '\n';
184 // Lines above or below?
188 os << "\\line_bottom ";
190 // Pagebreaks above or below?
192 os << "\\pagebreak_top ";
193 if (pagebreak_bottom)
194 os << "\\pagebreak_bottom ";
196 // Start of appendix?
197 if (start_of_appendix)
198 os << "\\start_of_appendix ";
205 if (align != LYX_ALIGN_LAYOUT) {
207 case LYX_ALIGN_LEFT: h = 1; break;
208 case LYX_ALIGN_RIGHT: h = 2; break;
209 case LYX_ALIGN_CENTER: h = 3; break;
210 default: h = 0; break;
212 os << "\\align " << string_align[h] << " ";
214 if (pextra_type != PEXTRA_NONE) {
215 os << "\\pextra_type " << pextra_type;
216 if (pextra_type == PEXTRA_MINIPAGE) {
217 os << " \\pextra_alignment "
220 os << " \\pextra_hfill "
222 if (pextra_start_minipage)
223 os << " \\pextra_start_minipage "
224 << pextra_start_minipage;
226 if (!pextra_width.empty()) {
227 os << " \\pextra_width "
228 << VSpace(pextra_width).asLyXCommand();
229 } else if (!pextra_widthp.empty()) {
230 os << " \\pextra_widthp "
236 // Dummy layout. This means that a footnote ended.
237 os << "\n\\end_float ";
238 footflag = LyXParagraph::NO_FOOTNOTE;
241 // It might be a table.
243 os << "\\LyXTable\n";
249 bibkey->Write(buf, os);
251 font1 = LyXFont(LyXFont::ALL_INHERIT,params.language_info);
254 for (size_type i = 0; i < size(); ++i) {
260 // Write font changes
261 font2 = GetFontSettings(params, i);
262 if (font2 != font1) {
263 font2.lyxWriteChanges(font1, os);
272 Inset const * inset = GetInset(i);
274 if (inset->DirectWrite()) {
275 // international char, let it write
276 // code directly so it's shorter in
278 inset->Write(buf, os);
280 os << "\n\\begin_inset ";
281 inset->Write(buf, os);
282 os << "\n\\end_inset \n\n";
288 os << "\n\\newline \n";
292 os << "\n\\hfill \n";
296 os << "\n\\backslash \n";
300 if (i + 1 < size() && GetChar(i + 1) == ' ') {
307 if ((column > 70 && c == ' ')
312 // this check is to amend a bug. LyX sometimes
313 // inserts '\0' this could cause problems.
317 lyxerr << "ERROR (LyXParagraph::writeFile):"
318 " NULL char in structure." << endl;
324 // now write the next paragraph
326 next->writeFile(buf, os, params, footflag, dth);
330 void LyXParagraph::validate(LaTeXFeatures & features) const
332 BufferParams const & params = features.bufferParams();
334 // this will be useful later
335 LyXLayout const & layout =
336 textclasslist.Style(params.textclass,
340 if (line_top || line_bottom)
341 features.lyxline = true;
342 if (!spacing.isDefault())
343 features.setspace = true;
346 features.layout[GetLayout()] = true;
349 Language const * doc_language = params.language_info;
351 for (FontList::const_iterator cit = fontlist.begin();
352 cit != fontlist.end(); ++cit) {
353 if ((*cit).font.noun() == LyXFont::ON) {
354 lyxerr[Debug::LATEX] << "font.noun: "
355 << (*cit).font.noun()
357 features.noun = true;
358 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
359 << (*cit).font.stateText(0)
362 switch ((*cit).font.color()) {
364 case LColor::inherit:
368 features.color = true;
369 lyxerr[Debug::LATEX] << "Color enabled. Font: "
370 << (*cit).font.stateText(0)
374 Language const * language = (*cit).font.language();
375 if (language != doc_language) {
376 features.UsedLanguages.insert(language);
377 lyxerr[Debug::LATEX] << "Found language "
378 << language->lang() << endl;
383 for (InsetList::const_iterator cit = insetlist.begin();
384 cit != insetlist.end(); ++cit) {
386 (*cit).inset->Validate(features);
389 if (table && table->IsLongTable())
390 features.longtable = true;
391 if (pextra_type == PEXTRA_INDENT)
392 features.LyXParagraphIndent = true;
393 if (pextra_type == PEXTRA_FLOATFLT)
394 features.floatflt = true;
395 if (layout.needprotect
396 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
397 features.NeedLyXFootnoteCode = true;
398 if (params.paragraph_separation == BufferParams::PARSEP_INDENT
399 && pextra_type == LyXParagraph::PEXTRA_MINIPAGE)
400 features.NeedLyXMinipageIndent = true;
401 if (table && table->NeedRotating())
402 features.rotating = true;
403 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
404 features.algorithm = true;
408 // First few functions needed for cut and paste and paragraph breaking.
409 void LyXParagraph::CopyIntoMinibuffer(BufferParams const & bparams,
410 LyXParagraph::size_type pos) const
412 minibuffer_char = GetChar(pos);
413 minibuffer_font = GetFontSettings(bparams, pos);
414 minibuffer_inset = 0;
415 if (minibuffer_char == LyXParagraph::META_INSET) {
417 minibuffer_inset = GetInset(pos)->Clone();
419 minibuffer_inset = 0;
420 minibuffer_char = ' ';
421 // This reflects what GetInset() does (ARRae)
427 void LyXParagraph::CutIntoMinibuffer(BufferParams const & bparams,
428 LyXParagraph::size_type pos)
430 minibuffer_char = GetChar(pos);
431 minibuffer_font = GetFontSettings(bparams, pos);
432 minibuffer_inset = 0;
433 if (minibuffer_char == LyXParagraph::META_INSET) {
435 minibuffer_inset = GetInset(pos);
436 // This is a little hack since I want exactly
437 // the inset, not just a clone. Otherwise
438 // the inset would be deleted when calling Erase(pos)
440 InsetList::iterator it = lower_bound(insetlist.begin(),
443 if (it != insetlist.end() && (*it).pos == pos)
446 minibuffer_inset = 0;
447 minibuffer_char = ' ';
448 // This reflects what GetInset() does (ARRae)
453 // Erase(pos); now the caller is responsible for that.
457 bool LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
459 if ((minibuffer_char == LyXParagraph::META_INSET) &&
460 !InsertInsetAllowed(minibuffer_inset))
462 InsertChar(pos, minibuffer_char);
463 SetFont(pos, minibuffer_font);
464 if (minibuffer_char == LyXParagraph::META_INSET)
465 InsertInset(pos, minibuffer_inset);
473 void LyXParagraph::Clear()
478 pagebreak_top = false;
479 pagebreak_bottom = false;
481 added_space_top = VSpace(VSpace::NONE);
482 added_space_bottom = VSpace(VSpace::NONE);
483 spacing.set(Spacing::Default);
485 align = LYX_ALIGN_LAYOUT;
489 pextra_type = PEXTRA_NONE;
490 pextra_width.erase();
491 pextra_widthp.erase();
492 pextra_alignment = MINIPAGE_ALIGN_TOP;
493 pextra_hfill = false;
494 pextra_start_minipage = false;
497 labelwidthstring.erase();
501 start_of_appendix = false;
505 // the destructor removes the new paragraph from the list
506 LyXParagraph::~LyXParagraph()
509 previous->next = next;
511 next->previous = previous;
513 for (InsetList::iterator it = insetlist.begin();
514 it != insetlist.end(); ++it) {
518 /* table stuff -- begin*/
520 /* table stuff -- end*/
526 //lyxerr << "LyXParagraph::paragraph_id = "
527 // << LyXParagraph::paragraph_id << endl;
531 void LyXParagraph::Erase(LyXParagraph::size_type pos)
533 // > because last is the next unused position, and you can
534 // use it if you want
536 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
537 NextAfterFootnote()->Erase(pos - text.size() - 1);
539 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
540 "position does not exist." << endl;
543 if (pos < size()) { // last is free for insertation, but should be empty
544 // if it is an inset, delete the inset entry
545 if (text[pos] == LyXParagraph::META_INSET) {
547 InsetList::iterator it = lower_bound(insetlist.begin(),
550 if (it != insetlist.end() && (*it).pos == pos) {
555 text.erase(text.begin() + pos);
557 // Erase entries in the tables.
558 FontList::iterator it = lower_bound(fontlist.begin(),
561 if (it != fontlist.end() && (*it).pos == pos &&
563 (it != fontlist.begin() && (*(it-1)).pos == pos - 1))) {
564 // If it is a multi-character font
565 // entry, we just make it smaller
566 // (see update below), otherwise we
568 unsigned int i = it - fontlist.begin();
569 fontlist.erase(fontlist.begin() + i);
570 it = fontlist.begin() + i;
571 if (i > 0 && i < fontlist.size() &&
572 fontlist[i-1].font == fontlist[i].font) {
573 fontlist.erase(fontlist.begin() + i-1);
574 it = fontlist.begin() + i-1;
578 // Update all other entries.
579 for (; it != fontlist.end(); ++it)
582 // Update the inset table.
583 for (InsetList::iterator it = upper_bound(insetlist.begin(),
586 it != insetlist.end(); ++it)
589 lyxerr << "ERROR (LyXParagraph::Erase): "
590 "can't erase non-existant char." << endl;
595 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
597 // > because last is the next unused position, and you can
598 // use it if you want
601 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
602 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
605 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
606 "position does not exist." << endl;
609 text.insert(text.begin() + pos, c);
610 // Update the font table.
611 for (FontList::iterator it = lower_bound(fontlist.begin(),
614 it != fontlist.end(); ++it)
617 // Update the inset table.
618 for (InsetList::iterator it = lower_bound(insetlist.begin(),
621 it != insetlist.end(); ++it)
626 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
629 // > because last is the next unused position, and you can
630 // use it if you want
633 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
635 ->InsertInset(pos - text.size() - 1, inset);
637 lyxerr << "ERROR (LyXParagraph::InsertInset): "
638 "position does not exist: " << pos << endl;
641 if (text[pos] != LyXParagraph::META_INSET) {
642 lyxerr << "ERROR (LyXParagraph::InsertInset): "
643 "there is no LyXParagraph::META_INSET" << endl;
648 // Add a new entry in the inset table.
649 InsetList::iterator it = lower_bound(insetlist.begin(),
652 if (it != insetlist.end() && (*it).pos == pos)
653 lyxerr << "ERROR (LyXParagraph::InsertInset): "
654 "there is an inset in position: " << pos << endl;
656 insetlist.insert(it, InsetTable(pos,inset));
658 inset->setOwner(inset_owner);
663 bool LyXParagraph::InsertInsetAllowed(Inset * inset)
666 return inset_owner->InsertInsetAllowed(inset);
671 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
675 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
676 return NextAfterFootnote()
677 ->GetInset(pos - text.size() - 1);
679 lyxerr << "ERROR (LyXParagraph::GetInset): "
680 "position does not exist: "
686 InsetList::iterator it = lower_bound(insetlist.begin(),
689 if (it != insetlist.end() && (*it).pos == pos)
692 lyxerr << "ERROR (LyXParagraph::GetInset): "
693 "Inset does not exist: " << pos << endl;
694 // text[pos] = ' '; // WHY!!! does this set the pos to ' '????
695 // Did this commenting out introduce a bug? So far I have not
696 // see any, please enlighten me. (Lgb)
697 // My guess is that since the inset does not exist, we might
698 // as well replace it with a space to prevent craches. (Asger)
703 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
707 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
708 return NextAfterFootnote()
709 ->GetInset(pos - text.size() - 1);
711 lyxerr << "ERROR (LyXParagraph::GetInset): "
712 "position does not exist: "
718 InsetList::const_iterator cit = lower_bound(insetlist.begin(),
721 if (cit != insetlist.end() && (*cit).pos == pos)
724 lyxerr << "ERROR (LyXParagraph::GetInset): "
725 "Inset does not exist: " << pos << endl;
726 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
727 // Did this commenting out introduce a bug? So far I have not
728 // see any, please enlighten me. (Lgb)
729 // My guess is that since the inset does not exist, we might
730 // as well replace it with a space to prevent craches. (Asger)
735 // Gets uninstantiated font setting at position.
736 // Optimized after profiling. (Asger)
737 LyXFont LyXParagraph::GetFontSettings(BufferParams const & bparams,
738 LyXParagraph::size_type pos) const
741 FontList::const_iterator cit = lower_bound(fontlist.begin(),
744 if (cit != fontlist.end())
747 // > because last is the next unused position, and you can
748 // use it if you want
749 else if (pos > size()) {
751 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
752 return NextAfterFootnote()
753 ->GetFontSettings(bparams,
754 pos - text.size() - 1);
756 // Why is it an error to ask for the font of a
757 // position that does not exist? Would it be
758 // enough for this to be enabled on debug?
759 // We want strict error checking, but it's ok to only
760 // have it when debugging. (Asger)
761 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
762 "position does not exist. "
763 << pos << " (" << static_cast<int>(pos)
766 } else if (pos > 0) {
767 return GetFontSettings(bparams, pos - 1);
768 } else // pos = size() = 0
769 return LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
771 return LyXFont(LyXFont::ALL_INHERIT);
774 // Gets uninstantiated font setting at position 0
775 LyXFont LyXParagraph::GetFirstFontSettings() const
778 if (!fontlist.empty())
779 return fontlist[0].font;
780 } else if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
781 return NextAfterFootnote()->GetFirstFontSettings();
782 return LyXFont(LyXFont::ALL_INHERIT);
786 // Gets the fully instantiated font at a given position in a paragraph
787 // This is basically the same function as LyXText::GetFont() in text2.C.
788 // The difference is that this one is used for generating the LaTeX file,
789 // and thus cosmetic "improvements" are disallowed: This has to deliver
790 // the true picture of the buffer. (Asger)
791 // If position is -1, we get the layout font of the paragraph.
792 // If position is -2, we get the font of the manual label of the paragraph.
793 LyXFont LyXParagraph::getFont(BufferParams const & bparams,
794 LyXParagraph::size_type pos) const
797 LyXLayout const & layout =
798 textclasslist.Style(bparams.textclass,
800 LyXParagraph::size_type main_body = 0;
801 if (layout.labeltype == LABEL_MANUAL)
802 main_body = BeginningOfMainBody();
807 layoutfont = layout.labelfont;
809 layoutfont = layout.font;
810 tmpfont = GetFontSettings(bparams, pos);
811 tmpfont.realize(layoutfont);
813 // process layoutfont for pos == -1 and labelfont for pos < -1
815 tmpfont = layout.font;
817 tmpfont = layout.labelfont;
818 tmpfont.setLanguage(getParLanguage(bparams));
821 // check for environment font information
822 char par_depth = GetDepth();
823 LyXParagraph const * par = this;
824 while (par && par_depth && !tmpfont.resolved()) {
825 par = par->DepthHook(par_depth - 1);
827 tmpfont.realize(textclasslist.
828 Style(bparams.textclass,
829 par->GetLayout()).font);
830 par_depth = par->GetDepth();
834 tmpfont.realize(textclasslist
835 .TextClass(bparams.textclass)
841 /// Returns the height of the highest font in range
843 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
844 LyXParagraph::size_type endpos) const
846 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
847 if (fontlist.empty())
850 FontList::const_iterator end_it = lower_bound(fontlist.begin(),
853 if (end_it != fontlist.end())
856 for (FontList::const_iterator cit = lower_bound(fontlist.begin(),
858 startpos, matchFT());
859 cit != end_it; ++cit) {
860 LyXFont::FONT_SIZE size = (*cit).font.size();
861 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
868 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
875 // > because last is the next unused position, and you can
876 // use it if you want
877 else if (pos > size()) {
878 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
879 return NextAfterFootnote()
880 ->GetChar(pos - text.size() - 1);
882 lyxerr << "ERROR (LyXParagraph::GetChar): "
883 "position does not exist."
884 << pos << " (" << static_cast<int>(pos)
886 // Assert(false); // This triggers sometimes...
891 // We should have a footnote environment.
892 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
893 // Notice that LyX does request the
894 // last char from time to time. (Asger)
895 //lyxerr << "ERROR (LyXParagraph::GetChar): "
896 // "expected footnote." << endl;
899 switch (next->footnotekind) {
900 case LyXParagraph::FOOTNOTE:
901 return LyXParagraph::META_FOOTNOTE;
902 case LyXParagraph::MARGIN:
903 return LyXParagraph::META_MARGIN;
904 case LyXParagraph::FIG:
905 case LyXParagraph::WIDE_FIG:
906 return LyXParagraph::META_FIG;
907 case LyXParagraph::TAB:
908 case LyXParagraph::WIDE_TAB:
909 return LyXParagraph::META_TAB;
910 case LyXParagraph::ALGORITHM:
911 return LyXParagraph::META_ALGORITHM;
913 return '\0'; // to shut up gcc
918 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
925 // > because last is the next unused position, and you can
926 // use it if you want
927 else if (pos > size()) {
928 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
929 return NextAfterFootnote()
930 ->GetChar(pos - text.size() - 1);
932 lyxerr << "ERROR (LyXParagraph::GetChar const): "
933 "position does not exist."
934 << pos << " (" << static_cast<int>(pos)
940 // We should have a footnote environment.
941 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
942 // Notice that LyX does request the
943 // last char from time to time. (Asger)
944 //lyxerr << "ERROR (LyXParagraph::GetChar): "
945 // "expected footnote." << endl;
948 switch (next->footnotekind) {
949 case LyXParagraph::FOOTNOTE:
950 return LyXParagraph::META_FOOTNOTE;
951 case LyXParagraph::MARGIN:
952 return LyXParagraph::META_MARGIN;
953 case LyXParagraph::FIG:
954 case LyXParagraph::WIDE_FIG:
955 return LyXParagraph::META_FIG;
956 case LyXParagraph::TAB:
957 case LyXParagraph::WIDE_TAB:
958 return LyXParagraph::META_TAB;
959 case LyXParagraph::ALGORITHM:
960 return LyXParagraph::META_ALGORITHM;
962 return '\0'; // to shut up gcc
967 // return an string of the current word, and the end of the word in lastpos.
968 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
972 // the current word is defined as starting at the first character
973 // from the immediate left of lastpospos which meets the definition
974 // of IsLetter(), continuing to the last character to the right
975 // of this meeting IsLetter.
981 // move back until we have a letter
983 //there's no real reason to have firstpos & lastpos as
984 //separate variables as this is written, but maybe someon
985 // will want to return firstpos in the future.
987 //since someone might have typed a punctuation first
988 int firstpos = lastpos;
990 while ((firstpos >= 0) && !IsLetter(firstpos))
993 // now find the beginning by looking for a nonletter
995 while ((firstpos>= 0) && IsLetter(firstpos))
998 // the above is now pointing to the preceeding non-letter
1002 // so copy characters into theword until we get a nonletter
1003 // note that this can easily exceed lastpos, wich means
1004 // that if used in the middle of a word, the whole word
1007 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1014 LyXParagraph::size_type LyXParagraph::Last() const
1016 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1017 return text.size() + NextAfterFootnote()->Last() + 1;
1018 // the 1 is the symbol
1025 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1027 // > because last is the next unused position, and you can
1028 // use it if you want
1031 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1032 return NextAfterFootnote()
1033 ->ParFromPos(pos - text.size() - 1);
1035 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1036 "position does not exist." << endl;
1043 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1045 // > because last is the next unused position, and you can
1046 // use it if you want
1049 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1050 return NextAfterFootnote()
1051 ->PositionInParFromPos(pos - text.size() - 1);
1054 "ERROR (LyXParagraph::PositionInParFromPos): "
1055 "position does not exist." << endl;
1063 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1064 LyXFont const & font)
1066 // > because last is the next unused position, and you can
1067 // use it if you want
1070 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1071 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1074 lyxerr << "ERROR (LyXParagraph::SetFont): "
1075 "position does not exist." << endl;
1080 // First, reduce font against layout/label font
1081 // Update: The SetCharFont() routine in text2.C already
1082 // reduces font, so we don't need to do that here. (Asger)
1083 // No need to simplify this because it will disappear
1084 // in a new kernel. (Asger)
1085 // Next search font table
1087 FontList::iterator it = lower_bound(fontlist.begin(),
1090 unsigned int i = it - fontlist.begin();
1091 bool notfound = it == fontlist.end();
1093 if (!notfound && fontlist[i].font == font)
1096 bool begin = pos == 0 || notfound ||
1097 (i > 0 && fontlist[i-1].pos == pos - 1);
1098 // Is position pos is a beginning of a font block?
1099 bool end = !notfound && fontlist[i].pos == pos;
1100 // Is position pos is the end of a font block?
1101 if (begin && end) { // A single char block
1102 if (i+1 < fontlist.size() &&
1103 fontlist[i+1].font == font) {
1104 // Merge the singleton block with the next block
1105 fontlist.erase(fontlist.begin() + i);
1106 if (i > 0 && fontlist[i-1].font == font)
1107 fontlist.erase(fontlist.begin() + i-1);
1108 } else if (i > 0 && fontlist[i-1].font == font) {
1109 // Merge the singleton block with the previous block
1110 fontlist[i-1].pos = pos;
1111 fontlist.erase(fontlist.begin() + i);
1113 fontlist[i].font = font;
1115 if (i > 0 && fontlist[i-1].font == font)
1116 fontlist[i-1].pos = pos;
1118 fontlist.insert(fontlist.begin() + i,
1119 FontTable(pos, font));
1121 fontlist[i].pos = pos - 1;
1122 if (!(i+1 < fontlist.size() &&
1123 fontlist[i+1].font == font))
1124 fontlist.insert(fontlist.begin() + i+1,
1125 FontTable(pos, font));
1126 } else { // The general case. The block is splitted into 3 blocks
1127 fontlist.insert(fontlist.begin() + i,
1128 FontTable(pos - 1, fontlist[i].font));
1129 fontlist.insert(fontlist.begin() + i+1, FontTable(pos, font));
1134 // This function is able to hide closed footnotes.
1135 LyXParagraph * LyXParagraph::Next()
1137 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1138 LyXParagraph * tmp = next;
1140 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1142 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1143 return tmp->Next(); /* there can be more than one
1144 footnote in a logical
1147 return next; // This should never happen!
1153 LyXParagraph * LyXParagraph::NextAfterFootnote()
1155 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1156 LyXParagraph * tmp = next;
1157 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1159 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1160 return tmp; /* there can be more than one footnote
1161 in a logical paragraph */
1163 return next; // This should never happen!
1169 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1171 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1172 LyXParagraph * tmp = next;
1173 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1175 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1176 return tmp; /* there can be more than one footnote
1177 in a logical paragraph */
1179 return next; // This should never happen!
1185 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1188 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1190 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1191 tmp = tmp->previous;
1192 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1193 return tmp; /* there can be more than one footnote
1194 in a logical paragraph */
1196 return previous; // This should never happen!
1202 LyXParagraph * LyXParagraph::LastPhysicalPar()
1204 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1207 LyXParagraph * tmp = this;
1209 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1210 tmp = tmp->NextAfterFootnote();
1215 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1217 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1220 LyXParagraph const * tmp = this;
1222 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1223 tmp = tmp->NextAfterFootnote();
1228 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1232 LyXParagraph * tmppar = this;
1236 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1237 tmppar = tmppar->previous;
1246 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1250 LyXParagraph const * tmppar = this;
1254 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1255 tmppar = tmppar->previous;
1264 // This function is able to hide closed footnotes.
1265 LyXParagraph * LyXParagraph::Previous()
1267 LyXParagraph * tmp = previous;
1272 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1273 tmp = tmp->previous;
1275 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1276 tmp = tmp->previous;
1277 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1278 return tmp->next->Previous();
1287 // This function is able to hide closed footnotes.
1288 LyXParagraph const * LyXParagraph::Previous() const
1290 LyXParagraph * tmp = previous;
1295 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1296 tmp = tmp->previous;
1298 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1299 tmp = tmp->previous;
1300 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1301 return tmp->next->Previous();
1310 void LyXParagraph::BreakParagraph(BufferParams const & bparams,
1311 LyXParagraph::size_type pos,
1314 size_type i, j, pos_end, pos_first;
1315 // create a new paragraph
1316 LyXParagraph * par = ParFromPos(pos);
1317 LyXParagraph * firstpar = FirstPhysicalPar();
1319 LyXParagraph * tmp = new LyXParagraph(par);
1321 tmp->footnoteflag = footnoteflag;
1322 tmp->footnotekind = footnotekind;
1324 // this is an idea for a more userfriendly layout handling, I will
1325 // see what the users say
1327 // layout stays the same with latex-environments
1329 tmp->SetOnlyLayout(bparams, firstpar->layout);
1330 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1333 if (Last() > pos || !Last() || flag == 2) {
1334 tmp->SetOnlyLayout(bparams, firstpar->layout);
1335 tmp->align = firstpar->align;
1336 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1338 tmp->line_bottom = firstpar->line_bottom;
1339 firstpar->line_bottom = false;
1340 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1341 firstpar->pagebreak_bottom = false;
1342 tmp->added_space_bottom = firstpar->added_space_bottom;
1343 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1345 tmp->depth = firstpar->depth;
1346 tmp->noindent = firstpar->noindent;
1348 // copy everything behind the break-position
1349 // to the new paragraph
1351 while (ParFromPos(pos_first) != par)
1354 pos_end = pos_first + par->text.size() - 1;
1356 for (i = j = pos; i <= pos_end; ++i) {
1357 par->CutIntoMinibuffer(bparams, i - pos_first);
1358 if (tmp->InsertFromMinibuffer(j - pos))
1361 tmp->text.resize(tmp->text.size());
1362 for (i = pos_end; i >= pos; --i)
1363 par->Erase(i - pos_first);
1365 par->text.resize(par->text.size());
1368 // just an idea of me
1370 tmp->line_top = firstpar->line_top;
1371 tmp->pagebreak_top = firstpar->pagebreak_top;
1372 tmp->added_space_top = firstpar->added_space_top;
1373 tmp->bibkey = firstpar->bibkey;
1375 // layout stays the same with latex-environments
1377 firstpar->SetOnlyLayout(bparams, tmp->layout);
1378 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1379 firstpar->depth = tmp->depth;
1385 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1387 par = par->FirstPhysicalPar();
1388 footnoteflag = par->footnoteflag;
1389 footnotekind = par->footnotekind;
1391 layout = par->layout;
1392 align = par-> align;
1393 SetLabelWidthString(par->labelwidthstring);
1395 line_bottom = par->line_bottom;
1396 pagebreak_bottom = par->pagebreak_bottom;
1397 added_space_bottom = par->added_space_bottom;
1399 line_top = par->line_top;
1400 pagebreak_top = par->pagebreak_top;
1401 added_space_top = par->added_space_top;
1403 spacing = par->spacing;
1405 pextra_type = par->pextra_type;
1406 pextra_width = par->pextra_width;
1407 pextra_widthp = par->pextra_widthp;
1408 pextra_alignment = par->pextra_alignment;
1409 pextra_hfill = par->pextra_hfill;
1410 pextra_start_minipage = par->pextra_start_minipage;
1412 noindent = par->noindent;
1417 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1419 LyXParagraph * tmppar = this;
1422 && tmppar->previous->footnoteflag ==
1423 LyXParagraph::CLOSED_FOOTNOTE)
1424 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1425 tmppar = tmppar->previous;
1428 return this; // This should never happen!
1433 int LyXParagraph::StripLeadingSpaces(LyXTextClassList::size_type tclass)
1435 if (textclasslist.Style(tclass, GetLayout()).free_spacing)
1439 if (!IsDummy() && !table){
1441 && (IsNewline(0) || IsLineSeparator(0))){
1450 LyXParagraph * LyXParagraph::Clone() const
1452 // create a new paragraph
1453 LyXParagraph * result = new LyXParagraph;
1455 result->MakeSameLayout(this);
1457 // this is because of the dummy layout of the paragraphs that
1459 result->layout = layout;
1462 /* table stuff -- begin*/
1464 result->table = table->Clone();
1467 /* table stuff -- end*/
1469 result->inset_owner = inset_owner;
1472 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1475 // copy everything behind the break-position to the new paragraph
1477 result->text = text;
1478 result->fontlist = fontlist;
1479 result->insetlist = insetlist;
1480 for (InsetList::iterator it = result->insetlist.begin();
1481 it != result->insetlist.end(); ++it)
1482 (*it).inset = (*it).inset->Clone();
1487 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1489 par = par->FirstPhysicalPar();
1492 par->footnoteflag == footnoteflag &&
1493 par->footnotekind == footnotekind &&
1495 par->layout == layout &&
1497 par->align == align &&
1499 par->line_bottom == line_bottom &&
1500 par->pagebreak_bottom == pagebreak_bottom &&
1501 par->added_space_bottom == added_space_bottom &&
1503 par->line_top == line_top &&
1504 par->pagebreak_top == pagebreak_top &&
1505 par->added_space_top == added_space_top &&
1507 par->spacing == spacing &&
1509 par->pextra_type == pextra_type &&
1510 par->pextra_width == pextra_width &&
1511 par->pextra_widthp == pextra_widthp &&
1512 par->pextra_alignment == pextra_alignment &&
1513 par->pextra_hfill == pextra_hfill &&
1514 par->pextra_start_minipage == pextra_start_minipage &&
1516 par->table == table && // what means: NO TABLE AT ALL
1519 par->noindent == noindent &&
1520 par->depth == depth);
1524 void LyXParagraph::BreakParagraphConservative(BufferParams const & bparams,
1525 LyXParagraph::size_type pos)
1527 // create a new paragraph
1528 LyXParagraph * par = ParFromPos(pos);
1530 LyXParagraph * tmp = new LyXParagraph(par);
1532 tmp->MakeSameLayout(par);
1534 // When can pos < Last()?
1535 // I guess pos == Last() is possible.
1537 // copy everything behind the break-position to the new
1539 size_type pos_first = 0;
1540 while (ParFromPos(pos_first) != par)
1542 size_type pos_end = pos_first + par->text.size() - 1;
1545 for (i = j = pos; i <= pos_end; ++i) {
1546 par->CutIntoMinibuffer(bparams, i - pos_first);
1547 if (tmp->InsertFromMinibuffer(j - pos))
1550 tmp->text.resize(tmp->text.size());
1551 for (size_type i = pos_end; i >= pos; --i)
1552 par->Erase(i - pos_first);
1554 par->text.resize(par->text.size());
1559 // Be carefull, this does not make any check at all.
1560 void LyXParagraph::PasteParagraph(BufferParams const & bparams)
1562 // copy the next paragraph to this one
1563 LyXParagraph * the_next = Next();
1565 LyXParagraph * firstpar = FirstPhysicalPar();
1567 // first the DTP-stuff
1568 firstpar->line_bottom = the_next->line_bottom;
1569 firstpar->added_space_bottom = the_next->added_space_bottom;
1570 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1572 size_type pos_end = the_next->text.size() - 1;
1573 size_type pos_insert = Last();
1575 // ok, now copy the paragraph
1577 for (i = j = 0; i <= pos_end; ++i) {
1578 the_next->CutIntoMinibuffer(bparams, i);
1579 if (InsertFromMinibuffer(pos_insert + j))
1583 // delete the next paragraph
1584 LyXParagraph *ppar = the_next->previous;
1585 LyXParagraph *npar = the_next->next;
1591 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1593 LyXParagraph * par = ParFromPos(pos);
1595 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1596 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1602 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1604 LyXParagraph * par = ParFromPos(pos);
1606 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1607 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1612 int LyXParagraph::GetEndLabel(BufferParams const & bparams) const
1614 LyXParagraph const * par = this;
1615 int par_depth = GetDepth();
1617 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1619 textclasslist.Style(bparams.textclass,
1620 layout).endlabeltype;
1621 if (endlabeltype != END_LABEL_NO_LABEL) {
1622 LyXParagraph const * last = this;
1623 if( footnoteflag == NO_FOOTNOTE)
1624 last = LastPhysicalPar();
1625 else if (next->footnoteflag == NO_FOOTNOTE)
1626 return endlabeltype;
1628 if (!last || !last->next)
1629 return endlabeltype;
1631 int next_depth = last->next->GetDepth();
1632 if (par_depth > next_depth ||
1633 (par_depth == next_depth && layout != last->next->GetLayout() ))
1634 return endlabeltype;
1639 par = par->DepthHook(par_depth - 1);
1641 par_depth = par->GetDepth();
1643 return END_LABEL_NO_LABEL;
1647 LyXTextClass::size_type LyXParagraph::GetLayout() const
1649 return FirstPhysicalPar()->layout;
1653 char LyXParagraph::GetDepth() const
1655 return FirstPhysicalPar()->depth;
1659 char LyXParagraph::GetAlign() const
1661 return FirstPhysicalPar()->align;
1665 string LyXParagraph::GetLabelstring() const
1667 return FirstPhysicalPar()->labelstring;
1671 int LyXParagraph::GetFirstCounter(int i) const
1673 return FirstPhysicalPar()->counter_[i];
1677 // the next two functions are for the manual labels
1678 string LyXParagraph::GetLabelWidthString() const
1680 if (!FirstPhysicalPar()->labelwidthstring.empty())
1681 return FirstPhysicalPar()->labelwidthstring;
1683 return _("Senseless with this layout!");
1687 void LyXParagraph::SetLabelWidthString(string const & s)
1689 LyXParagraph * par = FirstPhysicalPar();
1691 par->labelwidthstring = s;
1695 void LyXParagraph::SetOnlyLayout(BufferParams const & bparams,
1696 LyXTextClass::size_type new_layout)
1698 LyXParagraph * par = FirstPhysicalPar();
1699 LyXParagraph * ppar = 0;
1700 LyXParagraph * npar = 0;
1702 par->layout = new_layout;
1704 /* table stuff -- begin*/
1707 /* table stuff -- end*/
1709 if (par->pextra_type == PEXTRA_NONE) {
1710 if (par->Previous()) {
1711 ppar = par->Previous()->FirstPhysicalPar();
1714 && (ppar->depth > par->depth))
1715 ppar = ppar->Previous()->FirstPhysicalPar();
1718 npar = par->Next()->NextAfterFootnote();
1721 && (npar->depth > par->depth))
1722 npar = npar->Next()->NextAfterFootnote();
1724 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1726 p1 = ppar->pextra_width,
1727 p2 = ppar->pextra_widthp;
1728 ppar->SetPExtraType(bparams, ppar->pextra_type,
1729 p1.c_str(), p2.c_str());
1731 if ((par->pextra_type == PEXTRA_NONE) &&
1732 npar && (npar->pextra_type != PEXTRA_NONE)) {
1734 p1 = npar->pextra_width,
1735 p2 = npar->pextra_widthp;
1736 npar->SetPExtraType(bparams, npar->pextra_type,
1737 p1.c_str(), p2.c_str());
1743 void LyXParagraph::SetLayout(BufferParams const & bparams,
1744 LyXTextClass::size_type new_layout)
1747 * par = FirstPhysicalPar(),
1751 par->layout = new_layout;
1752 par->labelwidthstring.erase();
1753 par->align = LYX_ALIGN_LAYOUT;
1754 par->added_space_top = VSpace(VSpace::NONE);
1755 par->added_space_bottom = VSpace(VSpace::NONE);
1756 par->spacing.set(Spacing::Default);
1759 /* table stuff -- begin*/
1762 /* table stuff -- end*/
1764 if (par->pextra_type == PEXTRA_NONE) {
1765 if (par->Previous()) {
1766 ppar = par->Previous()->FirstPhysicalPar();
1769 && (ppar->depth > par->depth))
1770 ppar = ppar->Previous()->FirstPhysicalPar();
1773 npar = par->Next()->NextAfterFootnote();
1776 && (npar->depth > par->depth))
1777 npar = npar->Next()->NextAfterFootnote();
1779 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1781 p1 = ppar->pextra_width,
1782 p2 = ppar->pextra_widthp;
1783 ppar->SetPExtraType(bparams, ppar->pextra_type,
1784 p1.c_str(), p2.c_str());
1786 if ((par->pextra_type == PEXTRA_NONE) &&
1787 npar && (npar->pextra_type != PEXTRA_NONE)) {
1789 p1 = npar->pextra_width,
1790 p2 = npar->pextra_widthp;
1791 npar->SetPExtraType(bparams, npar->pextra_type,
1792 p1.c_str(), p2.c_str());
1798 // if the layout of a paragraph contains a manual label, the beginning of the
1799 // main body is the beginning of the second word. This is what the par-
1800 // function returns. If the layout does not contain a label, the main
1801 // body always starts with position 0. This differentiation is necessary,
1802 // because there cannot be a newline or a blank <= the beginning of the
1803 // main body in TeX.
1805 int LyXParagraph::BeginningOfMainBody() const
1807 if (FirstPhysicalPar() != this)
1810 // Unroll the first two cycles of the loop
1811 // and remember the previous character to
1812 // remove unnecessary GetChar() calls
1815 && GetChar(i) != LyXParagraph::META_NEWLINE
1818 char previous_char = 0, temp = 0;
1820 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1821 // Yes, this ^ is supposed to be "= " not "=="
1824 && previous_char != ' '
1825 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1827 previous_char = temp;
1832 if (i == 0 && i == size() &&
1833 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1834 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1835 ++i; /* the cursor should not jump
1836 * to the main body if there
1842 LyXParagraph * LyXParagraph::DepthHook(int deth)
1844 LyXParagraph * newpar = this;
1849 newpar = newpar->FirstPhysicalPar()->Previous();
1850 } while (newpar && newpar->GetDepth() > deth
1851 && newpar->footnoteflag == footnoteflag);
1854 if (Previous() || GetDepth())
1855 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1859 return newpar->FirstPhysicalPar();
1863 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1865 LyXParagraph const * newpar = this;
1870 newpar = newpar->FirstPhysicalPar()->Previous();
1871 } while (newpar && newpar->GetDepth() > deth
1872 && newpar->footnoteflag == footnoteflag);
1875 if (Previous() || GetDepth())
1876 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1880 return newpar->FirstPhysicalPar();
1884 int LyXParagraph::AutoDeleteInsets()
1887 InsetList::size_type index = 0;
1888 while (index < insetlist.size()) {
1889 if (insetlist[index].inset && insetlist[index].inset->AutoDelete()) {
1890 Erase(insetlist[index].pos);
1891 // Erase() calls to insetlist.erase(&insetlist[index])
1892 // so index shouldn't be increased.
1901 LyXParagraph::inset_iterator LyXParagraph::InsetIterator(LyXParagraph::size_type pos)
1903 InsetList::iterator it = lower_bound(insetlist.begin(),
1906 return inset_iterator(it);
1910 // returns -1 if inset not found
1911 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1914 // We could use lower_bound here too, we just need to add
1915 // the approp. operator() to matchIT (and change the name
1916 // of that struct). Code would then be:
1917 // InsetList::const_iterator cit = lower_bound(insetlist.begin(),
1919 // inset, matchIT());
1920 // if ((*cit).inset == inset) {
1921 // return (*cit).pos;
1923 for (InsetList::const_iterator cit = insetlist.begin();
1924 cit != insetlist.end(); ++cit) {
1925 if ((*cit).inset == inset) {
1929 // Think about footnotes.
1930 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1931 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1933 NextAfterFootnote()->GetPositionOfInset(inset);
1935 return text.size() + 1 + further;
1941 LyXParagraph * LyXParagraph::TeXOnePar(Buffer const * buf,
1942 BufferParams const & bparams,
1943 ostream & os, TexRow & texrow,
1946 TexRow & foot_texrow,
1949 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1950 LyXLayout const & style =
1951 textclasslist.Style(bparams.textclass,
1954 bool further_blank_line = false;
1956 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1958 if (start_of_appendix) {
1959 os << "\\appendix\n";
1963 if (!spacing.isDefault()
1964 && (!Previous() || !Previous()->HasSameLayout(this))) {
1965 os << spacing.writeEnvirBegin() << "\n";
1969 if (tex_code_break_column && style.isCommand()){
1974 if (pagebreak_top) {
1976 further_blank_line = true;
1978 if (added_space_top.kind() != VSpace::NONE) {
1979 os << added_space_top.asLatexCommand(bparams);
1980 further_blank_line = true;
1984 os << "\\lyxline{\\" << getFont(bparams, 0).latexSize() << '}'
1985 << "\\vspace{-1\\parskip}";
1986 further_blank_line = true;
1989 if (further_blank_line){
1994 Language const * language = getParLanguage(bparams);
1995 Language const * doc_language = bparams.language_info;
1996 if (language != doc_language &&
1997 (!previous || previous->getParLanguage(bparams) != language)) {
1998 os << subst(lyxrc.language_command_begin, "$$lang",
2004 switch (style.latextype) {
2007 << style.latexname()
2008 << style.latexparam();
2010 case LATEX_ITEM_ENVIRONMENT:
2012 bibkey->Latex(buf, os, false, false);
2016 case LATEX_LIST_ENVIRONMENT:
2023 bool need_par = SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2025 // Spit out footnotes
2026 LyXParagraph * par = next;
2027 if (lyxrc.rtl_support) {
2028 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2029 && next->footnoteflag != footnoteflag) {
2030 LyXParagraph * p = 0;
2031 bool is_rtl = (size() > 0)
2032 ? GetFontSettings(bparams,
2033 size()-1).isRightToLeft()
2034 : language->RightToLeft();
2035 if ( (p = NextAfterFootnote()) != 0 &&
2037 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2038 is_rtl = getParLanguage(bparams)->RightToLeft();
2039 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2040 && par->footnoteflag != footnoteflag) {
2041 par = par->TeXFootnote(buf, bparams,
2043 foot_texrow, foot_count,
2045 par->SimpleTeXOnePar(buf, bparams,
2046 os, texrow, moving_arg);
2047 is_rtl = (par->size() > 0)
2048 ? par->GetFontSettings(bparams,
2049 par->size()-1).isRightToLeft()
2050 : language->RightToLeft();
2052 par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2053 (p = par->NextAfterFootnote()) != 0 &&
2055 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2056 is_rtl = language->RightToLeft();
2061 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2062 && par->footnoteflag != footnoteflag) {
2063 par = par->TeXFootnote(buf, bparams,
2065 foot, foot_texrow, foot_count,
2067 par->SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2072 // Make sure that \\par is done with the font of the last
2073 // character if this has another size as the default.
2074 // This is necessary because LaTeX (and LyX on the screen)
2075 // calculates the space between the baselines according
2076 // to this font. (Matthias)
2077 LyXFont font = getFont(bparams, Last() - 1);
2079 if (style.resfont.size() != font.size()) {
2085 } else if (textclasslist.Style(bparams.textclass,
2086 GetLayout()).isCommand()) {
2087 if (style.resfont.size() != font.size()) {
2093 } else if (style.resfont.size() != font.size()){
2094 os << "{\\" << font.latexSize() << " \\par}";
2097 if (language != doc_language &&
2099 || (footnoteflag != NO_FOOTNOTE && par->footnoteflag != footnoteflag)
2100 || par->getParLanguage(bparams) != language)) {
2102 << subst(lyxrc.language_command_end, "$$lang",
2103 doc_language->lang());
2106 switch (style.latextype) {
2107 case LATEX_ITEM_ENVIRONMENT:
2108 case LATEX_LIST_ENVIRONMENT:
2109 if (par && (depth < par->depth)) {
2114 case LATEX_ENVIRONMENT:
2115 // if its the last paragraph of the current environment
2116 // skip it otherwise fall through
2118 && (par->layout != layout
2119 || par->depth != depth
2120 || par->pextra_type != pextra_type))
2123 // we don't need it for the last paragraph!!!
2124 if (next && !(footnoteflag != LyXParagraph::NO_FOOTNOTE
2125 && footnotekind != LyXParagraph::FOOTNOTE
2126 && footnotekind != LyXParagraph::MARGIN
2130 // don't insert this if we would be adding it
2131 // before or after a table in a float. This
2132 // little trick is needed in order to allow
2133 // use of tables in \subfigures or \subtables.
2139 further_blank_line = false;
2141 os << "\\lyxline{\\" << getFont(bparams, Last() - 1).latexSize() << '}';
2142 further_blank_line = true;
2145 if (added_space_bottom.kind() != VSpace::NONE) {
2146 os << added_space_bottom.asLatexCommand(bparams);
2147 further_blank_line = true;
2150 if (pagebreak_bottom) {
2152 further_blank_line = true;
2155 if (further_blank_line){
2160 if (!spacing.isDefault()
2161 && (!par || !par->HasSameLayout(this))) {
2162 os << spacing.writeEnvirEnd() << "\n";
2166 // we don't need it for the last paragraph!!!
2167 if (next && !(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2168 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2173 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2178 // This one spits out the text of the paragraph
2179 bool LyXParagraph::SimpleTeXOnePar(Buffer const * buf,
2180 BufferParams const & bparams,
2181 ostream & os, TexRow & texrow,
2184 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2188 return SimpleTeXOneTablePar(buf, bparams, os, texrow);
2191 bool return_value = false;
2193 LyXLayout const & style =
2194 textclasslist.Style(bparams.textclass,
2196 LyXFont basefont, last_font;
2198 // Maybe we have to create a optional argument.
2199 size_type main_body;
2200 if (style.labeltype != LABEL_MANUAL)
2203 main_body = BeginningOfMainBody();
2205 if (main_body > 0) {
2207 basefont = getFont(bparams, -2); // Get label font
2209 basefont = getFont(bparams, -1); // Get layout font
2217 if (style.isCommand()) {
2220 } else if (align != LYX_ALIGN_LAYOUT) {
2223 return_value = true;
2227 moving_arg |= style.needprotect;
2229 // Which font is currently active?
2230 LyXFont running_font(basefont);
2231 // Do we have an open font change?
2232 bool open_font = false;
2234 texrow.start(this, 0);
2236 for (size_type i = 0; i < size(); ++i) {
2238 // First char in paragraph or after label?
2239 if (i == main_body && !IsDummy()) {
2240 if (main_body > 0) {
2242 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2245 basefont = getFont(bparams, -1); // Now use the layout font
2246 running_font = basefont;
2250 if (style.isCommand()) {
2253 } else if (align != LYX_ALIGN_LAYOUT) {
2256 return_value = true;
2260 os << "\\noindent ";
2264 case LYX_ALIGN_NONE:
2265 case LYX_ALIGN_BLOCK:
2266 case LYX_ALIGN_LAYOUT:
2267 case LYX_ALIGN_SPECIAL:
2269 case LYX_ALIGN_LEFT:
2270 if (getParLanguage(bparams)->lang() != "hebrew") {
2271 os << "\\raggedright ";
2274 os << "\\raggedleft ";
2278 case LYX_ALIGN_RIGHT:
2279 if (getParLanguage(bparams)->lang() != "hebrew") {
2280 os << "\\raggedleft ";
2283 os << "\\raggedright ";
2287 case LYX_ALIGN_CENTER:
2288 os << "\\centering ";
2296 // Fully instantiated font
2297 LyXFont font = getFont(bparams, i);
2298 LyXParagraph * p = 0;
2299 if (i == 0 && previous &&
2300 previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2301 (p = PreviousBeforeFootnote()) != 0)
2302 last_font = p->getFont(bparams, p->size()-1);
2304 last_font = running_font;
2306 // Spaces at end of font change are simulated to be
2307 // outside font change, i.e. we write "\textXX{text} "
2308 // rather than "\textXX{text }". (Asger)
2309 if (open_font && c == ' ' && i <= size() - 2
2310 && !getFont(bparams, i + 1).equalExceptLatex(running_font)
2311 && !getFont(bparams, i + 1).equalExceptLatex(font)) {
2312 font = getFont(bparams, i + 1);
2314 // We end font definition before blanks
2315 if (!font.equalExceptLatex(running_font) && open_font) {
2316 column += running_font.latexWriteEndChanges(os,
2318 (i == main_body-1) ? basefont : font);
2319 running_font = basefont;
2323 // Blanks are printed before start of fontswitch
2325 // Do not print the separation of the optional argument
2326 if (i != main_body - 1) {
2327 SimpleTeXBlanks(os, texrow, i,
2328 column, font, style);
2332 // Do we need to change font?
2333 if (!font.equalExceptLatex(running_font)
2334 && i != main_body-1) {
2335 column += font.latexWriteStartChanges(os, basefont,
2337 running_font = font;
2341 if (c == LyXParagraph::META_NEWLINE) {
2342 // newlines are handled differently here than
2343 // the default in SimpleTeXSpecialChars().
2344 if (!style.newline_allowed
2345 || font.latex() == LyXFont::ON) {
2349 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2352 basefont = getFont(bparams, -1);
2353 running_font = basefont;
2354 if (font.family() ==
2355 LyXFont::TYPEWRITER_FAMILY) {
2363 texrow.start(this, i + 1);
2366 SimpleTeXSpecialChars(buf, bparams,
2367 os, texrow, moving_arg,
2368 font, running_font, basefont,
2369 open_font, style, i, column, c);
2373 // If we have an open font definition, we have to close it
2375 LyXParagraph * p = 0;
2376 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2377 && (p = NextAfterFootnote()) != 0)
2378 running_font.latexWriteEndChanges(os, basefont,
2379 p->getFont(bparams, 0));
2381 running_font.latexWriteEndChanges(os, basefont, basefont);
2384 // Needed if there is an optional argument but no contents.
2385 if (main_body > 0 && main_body == size()) {
2387 return_value = false;
2390 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2391 return return_value;
2395 // This one spits out the text of a table paragraph
2396 bool LyXParagraph::SimpleTeXOneTablePar(Buffer const * buf,
2397 BufferParams const & bparams,
2398 ostream & os, TexRow & texrow)
2400 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2402 bool return_value = false;
2404 LyXLayout const & style =
2405 textclasslist.Style(bparams.textclass, GetLayout());
2408 if (!IsDummy()) { // it is dummy if it is in a float!!!
2409 if (style.isCommand()) {
2412 } else if (align != LYX_ALIGN_LAYOUT) {
2415 return_value = true;
2418 os << "\\noindent ";
2422 case LYX_ALIGN_NONE:
2423 case LYX_ALIGN_BLOCK:
2424 case LYX_ALIGN_LAYOUT:
2425 case LYX_ALIGN_SPECIAL: break;
2426 case LYX_ALIGN_LEFT:
2427 os << "\\raggedright ";
2430 case LYX_ALIGN_RIGHT:
2431 os << "\\raggedleft ";
2434 case LYX_ALIGN_CENTER:
2435 os << "\\centering ";
2441 LyXFont basefont = getFont(bparams, -1); // Get layout font
2442 // Which font is currently active?
2443 LyXFont running_font = basefont;
2445 // Do we have an open font change?
2446 bool open_font = false;
2447 int current_cell_number = -1;
2448 int tmp = table->TexEndOfCell(os, current_cell_number);
2449 for (; tmp > 0 ; --tmp)
2452 texrow.start(this, 0);
2454 bool is_rtl = getParLanguage(bparams)->RightToLeft();
2455 bool first_in_cell = true;
2457 for (size_type i = 0; i < size(); ++i) {
2458 char c = GetChar(i);
2459 if (table->IsContRow(current_cell_number + 1)) {
2460 if (c == LyXParagraph::META_NEWLINE)
2461 ++current_cell_number;
2466 if (first_in_cell && is_rtl) {
2469 first_in_cell = false;
2472 // Fully instantiated font
2473 LyXFont font = getFont(bparams, i);
2474 last_font = running_font;
2476 // Spaces at end of font change are simulated to be
2477 // outside font change.
2478 // i.e. we write "\textXX{text} " rather than
2479 // "\textXX{text }". (Asger)
2480 if (open_font && c == ' ' && i <= size() - 2
2481 && getFont(bparams, i + 1) != running_font
2482 && getFont(bparams, i + 1) != font) {
2483 font = getFont(bparams, i + 1);
2486 // We end font definition before blanks
2487 if (font != running_font && open_font) {
2488 column += running_font.latexWriteEndChanges(os,
2491 running_font = basefont;
2494 // Blanks are printed before start of fontswitch
2496 SimpleTeXBlanks(os, texrow, i, column, font, style);
2498 // Do we need to change font?
2499 if (font != running_font) {
2500 column += font.latexWriteStartChanges(os, basefont,
2502 running_font = font;
2505 // Do we need to turn on LaTeX mode?
2506 if (font.latex() != running_font.latex()) {
2507 if (font.latex() == LyXFont::ON
2508 && style.needprotect) {
2513 if (c == LyXParagraph::META_NEWLINE) {
2514 // special case for inside a table
2515 // different from default case in
2516 // SimpleTeXSpecialChars()
2518 column += running_font
2519 .latexWriteEndChanges(os, basefont,
2523 basefont = getFont(bparams, -1);
2524 running_font = basefont;
2525 ++current_cell_number;
2526 if (table->CellHasContRow(current_cell_number) >= 0) {
2527 TeXContTableRows(buf, bparams, os, i + 1,
2528 current_cell_number,
2531 if (is_rtl && !first_in_cell) {
2533 first_in_cell = true;
2536 // if this cell follow only ContRows till end don't
2537 // put the EndOfCell because it is put after the
2539 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2540 --current_cell_number;
2543 int tmp = table->TexEndOfCell(os,
2544 current_cell_number);
2547 } else if (tmp < 0) {
2553 texrow.start(this, i + 1);
2555 SimpleTeXSpecialChars(buf, bparams,
2557 font, running_font, basefont,
2558 open_font, style, i, column, c);
2562 // If we have an open font definition, we have to close it
2564 running_font.latexWriteEndChanges(os, basefont, basefont);
2566 ++current_cell_number;
2567 if (is_rtl && !first_in_cell)
2569 tmp = table->TexEndOfCell(os, current_cell_number);
2570 for (; tmp > 0; --tmp)
2572 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2573 return return_value;
2577 // This one spits out the text off ContRows in tables
2578 bool LyXParagraph::TeXContTableRows(Buffer const * buf,
2579 BufferParams const & bparams,
2581 LyXParagraph::size_type i,
2582 int current_cell_number,
2583 int & column, TexRow & texrow)
2585 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2589 bool return_value = false;
2590 LyXLayout const & style =
2591 textclasslist.Style(bparams.textclass,
2593 LyXFont basefont = getFont(bparams, -1); // Get layout font
2595 // Which font is currently active?
2596 LyXFont running_font = basefont;
2597 // Do we have an open font change?
2598 bool open_font = false;
2600 size_type lastpos = i;
2601 int cell = table->CellHasContRow(current_cell_number);
2602 ++current_cell_number;
2605 // first find the right position
2607 for (; (i < size()) && (current_cell_number<cell); ++i) {
2609 if (c == LyXParagraph::META_NEWLINE)
2610 ++current_cell_number;
2614 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2618 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2623 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2627 // Fully instantiated font
2628 LyXFont font = getFont(bparams, i);
2629 last_font = running_font;
2631 // Spaces at end of font change are simulated to
2632 // be outside font change. i.e. we write
2633 // "\textXX{text} " rather than "\textXX{text }".
2635 if (open_font && c == ' ' && i <= size() - 2
2636 && getFont(bparams, i + 1) != running_font
2637 && getFont(bparams, i + 1) != font) {
2638 font = getFont(bparams, i + 1);
2641 // We end font definition before blanks
2642 if (font != running_font && open_font) {
2643 column += running_font.latexWriteEndChanges(os, basefont, font);
2644 running_font = basefont;
2647 // Blanks are printed before start of fontswitch
2649 SimpleTeXBlanks(os, texrow, i,
2650 column, font, style);
2652 // Do we need to change font?
2653 if (font != running_font) {
2655 font.latexWriteStartChanges(os,
2658 running_font = font;
2661 // Do we need to turn on LaTeX mode?
2662 if (font.latex() != running_font.latex()) {
2663 if (font.latex() == LyXFont::ON
2664 && style.needprotect) {
2669 SimpleTeXSpecialChars(buf, bparams,
2670 os, texrow, false, font,
2671 running_font, basefont,
2672 open_font, style, i, column, c);
2674 // If we have an open font definition, we have to close it
2676 running_font.latexWriteEndChanges(os, basefont,
2680 basefont = getFont(bparams, -1);
2681 running_font = basefont;
2682 cell = table->CellHasContRow(current_cell_number);
2684 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2685 return return_value;
2689 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2691 bool retval = false;
2693 case LyXParagraph::META_HFILL:
2694 sgml_string.erase();
2696 case LyXParagraph::META_NEWLINE:
2700 sgml_string = "&";
2703 sgml_string = "<";
2706 sgml_string = ">";
2709 sgml_string = "$";
2712 sgml_string = "#";
2715 sgml_string = "%";
2718 sgml_string = "[";
2721 sgml_string = "]";
2724 sgml_string = "{";
2727 sgml_string = "}";
2730 sgml_string = "˜";
2733 sgml_string = """;
2736 sgml_string = "\";
2742 case '\0': // Ignore :-)
2743 sgml_string.erase();
2753 void LyXParagraph::SimpleDocBookOneTablePar(Buffer const * buffer,
2754 ostream & os, string & extra,
2755 int & desc_on, int depth)
2757 BufferParams const & bparams = buffer->params;
2759 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2761 LyXFont font1, font2;
2764 size_type main_body;
2765 bool emph_flag = false;
2767 LyXLayout const & style =
2768 textclasslist.Style(bparams.textclass,
2771 if (style.labeltype != LABEL_MANUAL)
2774 main_body = BeginningOfMainBody();
2776 // Gets paragraph main font.
2778 font1 = style.labelfont;
2782 int char_line_count = depth;
2783 os << newlineAndDepth(depth);
2784 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2785 os << "<INFORMALTABLE>"
2786 << newlineAndDepth(++depth);
2788 int current_cell_number = -1;
2789 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2791 // Parsing main loop.
2792 for (size_type i = 0; i < size(); ++i) {
2794 if (table->IsContRow(current_cell_number+1)) {
2795 if (c == LyXParagraph::META_NEWLINE)
2796 ++current_cell_number;
2801 // Fully instantiated font
2802 font2 = getFont(bparams, i);
2804 // Handle <emphasis> tag.
2805 if (font1.emph() != font2.emph() && i) {
2806 if (font2.emph() == LyXFont::ON) {
2809 } else if (emph_flag) {
2810 os << "</emphasis>";
2814 if (c == LyXParagraph::META_NEWLINE) {
2815 // We have only to control for emphasis open here!
2817 os << "</emphasis>";
2820 font1 = font2 = getFont(bparams, -1);
2821 ++current_cell_number;
2822 if (table->CellHasContRow(current_cell_number) >= 0) {
2823 DocBookContTableRows(buffer,
2824 os, extra, desc_on, i + 1,
2825 current_cell_number,
2828 // if this cell follow only ContRows till end don't
2829 // put the EndOfCell because it is put after the
2831 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2832 --current_cell_number;
2835 tmp = table->DocBookEndOfCell(os,
2836 current_cell_number,
2841 } else if (c == LyXParagraph::META_INSET) {
2842 inset = GetInset(i);
2844 std::ostringstream ost;
2845 inset->DocBook(buffer, ost);
2846 string tmp_out = ost.str().c_str();
2849 inset->DocBook(buffer, ost);
2851 char * ctmp = ost.str();
2852 string tmp_out(ctmp);
2856 // This code needs some explanation:
2857 // Two insets are treated specially
2858 // label if it is the first element in a
2859 // command paragraph
2861 // graphics inside tables or figure floats
2863 // title (the equivalente in latex for this
2865 // and title should come first
2868 if(desc_on != 3 || i != 0) {
2869 if(tmp_out[0] == '@') {
2871 extra += frontStrip(tmp_out,
2874 os << frontStrip(tmp_out,
2879 } else if (font2.latex() == LyXFont::ON) {
2880 // "TeX"-Mode on == > SGML-Mode on.
2886 if (linuxDocConvertChar(c, sgml_string)
2887 && !style.free_spacing) {
2888 // in freespacing mode, spaces are
2889 // non-breaking characters
2894 << "</term><listitem><para>";
2906 // Needed if there is an optional argument but no contents.
2907 if (main_body > 0 && main_body == size()) {
2912 os << "</emphasis>";
2915 ++current_cell_number;
2916 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2917 // Resets description flag correctly.
2920 // <term> not closed...
2924 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2925 os << "</INFORMALTABLE>";
2927 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2932 void LyXParagraph::DocBookContTableRows(Buffer const * buffer,
2933 ostream & os, string & extra,
2935 LyXParagraph::size_type i,
2936 int current_cell_number, int &column)
2941 BufferParams const & bparams = buffer->params;
2943 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2948 //string emph = "emphasis";
2949 bool emph_flag = false;
2950 int char_line_count = 0;
2952 LyXLayout const & style =
2953 textclasslist.Style(bparams.textclass,
2956 size_type main_body;
2957 if (style.labeltype != LABEL_MANUAL)
2960 main_body = BeginningOfMainBody();
2962 // Gets paragraph main font.
2965 font1 = style.labelfont;
2969 size_type lastpos = i;
2970 int cell = table->CellHasContRow(current_cell_number);
2971 ++current_cell_number;
2973 // first find the right position
2975 for (; i < size() && current_cell_number < cell; ++i) {
2977 if (c == LyXParagraph::META_NEWLINE)
2978 ++current_cell_number;
2982 // I don't know how to handle this so I comment it
2983 // for the moment (Jug)
2984 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2985 // file += " \\\\\n";
2988 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2993 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2997 // Fully instantiated font
2998 font2 = getFont(bparams, i);
3000 // Handle <emphasis> tag.
3001 if (font1.emph() != font2.emph() && i) {
3002 if (font2.emph() == LyXFont::ON) {
3005 } else if (emph_flag) {
3006 os << "</emphasis>";
3010 if (c == LyXParagraph::META_INSET) {
3011 inset = GetInset(i);
3013 std::ostringstream ost;
3014 inset->DocBook(buffer, ost);
3015 string tmp_out = ost.str().c_str();
3018 inset->DocBook(buffer, ost);
3020 char * ctmp = ost.str();
3021 string tmp_out(ctmp);
3025 // This code needs some explanation:
3026 // Two insets are treated specially
3027 // label if it is the first element in a
3028 // command paragraph
3030 // graphics inside tables or figure floats
3031 // can't go on title (the equivalente in
3032 // latex for this case is caption and title
3033 // should come first
3036 if(desc_on != 3 || i != 0) {
3037 if(tmp_out[0] == '@') {
3039 extra += frontStrip(tmp_out, '@');
3041 os << frontStrip(tmp_out, '@');
3045 } else if (font2.latex() == LyXFont::ON) {
3046 // "TeX"-Mode on == > SGML-Mode on.
3052 if (linuxDocConvertChar(c, sgml_string)
3053 && !style.free_spacing) {
3054 // in freespacing mode, spaces are
3055 // non-breaking characters
3060 << "</term><listitem><para>";
3070 // we have only to control for emphasis open here!
3072 os << "</emphasis>";
3075 font1 = font2 = getFont(bparams, -1);
3076 cell = table->CellHasContRow(current_cell_number);
3078 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3082 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3083 LyXParagraph::size_type const i,
3084 int & column, LyXFont const & font,
3085 LyXLayout const & style)
3087 if (column > tex_code_break_column
3089 && GetChar(i - 1) != ' '
3091 // In LaTeX mode, we don't want to
3092 // break lines since some commands
3094 && ! (font.latex() == LyXFont::ON)
3095 // same in FreeSpacing mode
3096 && !style.free_spacing
3097 // In typewriter mode, we want to avoid
3098 // ! . ? : at the end of a line
3099 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3100 && (GetChar(i-1) == '.'
3101 || GetChar(i-1) == '?'
3102 || GetChar(i-1) == ':'
3103 || GetChar(i-1) == '!'))) {
3104 if (tex_code_break_column == 0) {
3105 // in batchmode we need LaTeX to still
3106 // see it as a space not as an extra '\n'
3112 texrow.start(this, i + 1);
3114 } else if (font.latex() == LyXFont::OFF) {
3115 if (style.free_spacing) {
3124 void LyXParagraph::SimpleTeXSpecialChars(Buffer const * buf,
3125 BufferParams const & bparams,
3126 ostream & os, TexRow & texrow,
3129 LyXFont & running_font,
3132 LyXLayout const & style,
3133 LyXParagraph::size_type & i,
3134 int & column, char const c)
3136 // Two major modes: LaTeX or plain
3137 // Handle here those cases common to both modes
3138 // and then split to handle the two modes separately.
3140 case LyXParagraph::META_INSET: {
3141 Inset * inset = GetInset(i);
3144 int len = os.tellp();
3145 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3146 || inset->LyxCode() == Inset::MATH_CODE
3147 || inset->LyxCode() == Inset::URL_CODE)
3148 && running_font.isRightToLeft()) {
3153 int tmp = inset->Latex(buf, os, moving_arg,
3154 style.free_spacing);
3162 column += os.tellp() - len;
3171 case LyXParagraph::META_NEWLINE:
3173 column += running_font.latexWriteEndChanges(os,
3178 basefont = getFont(bparams, -1);
3179 running_font = basefont;
3182 case LyXParagraph::META_HFILL:
3188 // And now for the special cases within each mode
3189 // Are we in LaTeX mode?
3190 if (font.latex() == LyXFont::ON) {
3191 // at present we only have one option
3192 // but I'll leave it as a switch statement
3193 // so its simpler to extend. (ARRae)
3196 // make sure that we will not print
3197 // error generating chars to the tex
3198 // file. This test would not be needed
3199 // if it were done in the buffer
3207 // Plain mode (i.e. not LaTeX)
3210 os << "\\textbackslash{}";
3214 case '°': case '±': case '²': case '³':
3215 case '×': case '÷': case '¹': case 'ª':
3216 case 'º': case '¬': case 'µ':
3217 if (bparams.inputenc == "latin1") {
3218 os << "\\ensuremath{"
3227 case '|': case '<': case '>':
3228 // In T1 encoding, these characters exist
3229 if (lyxrc.fontenc == "T1") {
3231 //... but we should avoid ligatures
3232 if ((c == '>' || c == '<')
3234 && GetChar(i + 1) == c){
3235 os << "\\textcompwordmark{}";
3240 // Typewriter font also has them
3241 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3245 // Otherwise, we use what LaTeX
3249 os << "\\textless{}";
3253 os << "\\textgreater{}";
3257 os << "\\textbar{}";
3263 case '-': // "--" in Typewriter mode -> "-{}-"
3265 && GetChar(i + 1) == '-'
3266 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3275 os << "\\char`\\\"{}";
3280 if (bparams.inputenc == "default") {
3289 case '%': case '#': case '{':
3296 os << "\\textasciitilde{}";
3301 os << "\\textasciicircum{}";
3305 case '*': case '[': case ']':
3306 // avoid being mistaken for optional arguments
3307 os << '{' << c << '}';
3312 // Blanks are printed before font switching.
3313 // Sure? I am not! (try nice-latex)
3314 // I am sure it's correct. LyX might be smarter
3315 // in the future, but for now, nothing wrong is
3320 /* idea for labels --- begin*/
3324 && font.family() != LyXFont::TYPEWRITER_FAMILY
3325 && GetChar(i + 1) == 'y'
3326 && GetChar(i + 2) == 'X') {
3334 && font.family() != LyXFont::TYPEWRITER_FAMILY
3335 && GetChar(i + 1) == 'e'
3336 && GetChar(i + 2) == 'X') {
3341 // Check for "LaTeX2e"
3344 && font.family() != LyXFont::TYPEWRITER_FAMILY
3345 && GetChar(i + 1) == 'a'
3346 && GetChar(i + 2) == 'T'
3347 && GetChar(i + 3) == 'e'
3348 && GetChar(i + 4) == 'X'
3349 && GetChar(i + 5) == '2'
3350 && GetChar(i + 6) == 'e') {
3355 // Check for "LaTeX"
3358 && font.family() != LyXFont::TYPEWRITER_FAMILY
3359 && GetChar(i + 1) == 'a'
3360 && GetChar(i + 2) == 'T'
3361 && GetChar(i + 3) == 'e'
3362 && GetChar(i + 4) == 'X') {
3366 /* idea for labels --- end*/
3367 } else if (c != '\0') {
3378 bool LyXParagraph::RoffContTableRows(ostream & os,
3379 LyXParagraph::size_type i,
3385 LyXFont font1(LyXFont::ALL_INHERIT);
3390 string fname2 = TmpFileName(string(), "RAT2");
3392 int cell = table->CellHasContRow(actcell);
3395 // first find the right position
3397 for (; i < size() && actcell < cell; ++i) {
3399 if (c == LyXParagraph::META_NEWLINE)
3404 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3407 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3409 font2 = GetFontSettings(i);
3410 if (font1.latex() != font2.latex()) {
3411 if (font2.latex() != LyXFont::OFF)
3416 case LyXParagraph::META_INSET:
3417 if ((inset = GetInset(i))) {
3419 stringstream ss(ios::in | ios::out);
3420 inset->Ascii(buffer, ss);
3432 inset->Ascii(buffer, ss);
3446 case LyXParagraph::META_NEWLINE:
3448 case LyXParagraph::META_HFILL:
3457 lyxerr.debug() << "RoffAsciiTable: "
3458 "NULL char in structure."
3463 cell = table->CellHasContRow(actcell);
3470 LyXParagraph * LyXParagraph::TeXDeeper(Buffer const * buf,
3471 BufferParams const & bparams,
3472 ostream & os, TexRow & texrow,
3474 TexRow & foot_texrow,
3477 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3478 LyXParagraph * par = this;
3481 (par->depth == depth) &&
3482 (par->footnoteflag == footnoteflag)) {
3484 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3485 if (textclasslist.Style(bparams.textclass,
3486 par->layout).isEnvironment()
3487 || par->pextra_type != PEXTRA_NONE) {
3488 par = par->TeXEnvironment(buf, bparams,
3493 par = par->TeXOnePar(buf, bparams,
3499 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3505 LyXParagraph * LyXParagraph::TeXEnvironment(Buffer const * buf,
3506 BufferParams const & bparams,
3507 ostream & os, TexRow & texrow,
3509 TexRow & foot_texrow,
3512 bool eindent_open = false;
3513 bool foot_this_level = false;
3514 // flags when footnotetext should be appended to file.
3515 static bool minipage_open = false;
3516 static int minipage_open_depth = 0;
3517 char par_sep = bparams.paragraph_separation;
3519 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3521 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3523 LyXLayout const & style =
3524 textclasslist.Style(bparams.textclass,
3527 if (pextra_type == PEXTRA_INDENT) {
3528 if (!pextra_width.empty()) {
3529 os << "\\begin{LyXParagraphIndent}{"
3530 << pextra_width << "}\n";
3532 //float ib = atof(pextra_widthp.c_str())/100;
3533 // string can't handle floats at present (971109)
3534 // so I'll do a conversion by hand knowing that
3535 // the limits are 0.0 to 1.0. ARRae.
3536 os << "\\begin{LyXParagraphIndent}{";
3537 switch (pextra_widthp.length()) {
3549 os << "\\columnwidth}\n";
3552 eindent_open = true;
3554 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3555 if (pextra_hfill && Previous() &&
3556 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3557 os << "\\hfill{}\n";
3560 if (par_sep == BufferParams::PARSEP_INDENT) {
3561 os << "{\\setlength\\parindent{0pt}\n";
3564 os << "\\begin{minipage}";
3565 switch(pextra_alignment) {
3566 case MINIPAGE_ALIGN_TOP:
3569 case MINIPAGE_ALIGN_MIDDLE:
3572 case MINIPAGE_ALIGN_BOTTOM:
3576 if (!pextra_width.empty()) {
3577 os << '{' << pextra_width << "}\n";
3579 //float ib = atof(par->pextra_width.c_str())/100;
3580 // string can't handle floats at present
3581 // so I'll do a conversion by hand knowing that
3582 // the limits are 0.0 to 1.0. ARRae.
3584 switch (pextra_widthp.length()) {
3596 os << "\\columnwidth}\n";
3599 if (par_sep == BufferParams::PARSEP_INDENT) {
3600 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3603 minipage_open = true;
3604 minipage_open_depth = depth;
3607 #ifdef WITH_WARNINGS
3608 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3609 //I disabled it because it breaks when lists span on several
3612 if (style.isEnvironment()){
3613 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3614 #ifdef FANCY_FOOTNOTE_CODE
3615 if (foot_count < 0) {
3616 // flag that footnote[mark][text] should be
3617 // used for any footnotes from now on
3619 foot_this_level = true;
3622 os << "\\begin{" << style.latexname() << "}{"
3623 << labelwidthstring << "}\n";
3624 } else if (style.labeltype == LABEL_BIBLIO) {
3626 os << "\\begin{" << style.latexname() << "}{"
3627 << bibitemWidest(current_view->painter())
3629 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3630 #ifdef FANCY_FOOTNOTE_CODE
3631 if (foot_count < 0) {
3632 // flag that footnote[mark][text] should be
3633 // used for any footnotes from now on
3635 foot_this_level = true;
3638 os << "\\begin{" << style.latexname() << '}'
3639 << style.latexparam() << '\n';
3641 os << "\\begin{" << style.latexname() << '}'
3642 << style.latexparam() << '\n';
3645 LyXParagraph * par = this;
3647 par = par->TeXOnePar(buf, bparams,
3649 foot, foot_texrow, foot_count);
3651 if (minipage_open && par && !style.isEnvironment() &&
3652 (par->pextra_type == PEXTRA_MINIPAGE) &&
3653 par->pextra_start_minipage) {
3654 os << "\\end{minipage}\n";
3656 if (par_sep == BufferParams::PARSEP_INDENT) {
3660 minipage_open = false;
3662 if (par && par->depth > depth) {
3663 if (textclasslist.Style(bparams.textclass,
3664 par->layout).isParagraph()
3667 // How to handle this? (Lgb)
3668 //&& !suffixIs(os, "\n\n")
3670 // There should be at least one '\n' already
3671 // but we need there to be two for Standard
3672 // paragraphs that are depth-increment'ed to be
3673 // output correctly. However, tables can
3674 // also be paragraphs so don't adjust them.
3677 // Will it ever harm to have one '\n' too
3678 // many? i.e. that we sometimes will have
3679 // three in a row. (Lgb)
3683 par = par->TeXDeeper(buf, bparams, os, texrow,
3684 foot, foot_texrow, foot_count);
3686 if (par && par->layout == layout && par->depth == depth &&
3687 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3688 if (par->pextra_hfill && par->Previous() &&
3689 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3690 os << "\\hfill{}\n";
3693 if (par_sep == BufferParams::PARSEP_INDENT) {
3694 os << "{\\setlength\\parindent{0pt}\n";
3697 os << "\\begin{minipage}";
3698 switch(par->pextra_alignment) {
3699 case MINIPAGE_ALIGN_TOP:
3702 case MINIPAGE_ALIGN_MIDDLE:
3705 case MINIPAGE_ALIGN_BOTTOM:
3709 if (!par->pextra_width.empty()) {
3710 os << '{' << par->pextra_width << "}\n";
3712 //float ib = atof(par->pextra_widthp.c_str())/100;
3713 // string can't handle floats at present
3714 // so I'll do a conversion by hand knowing that
3715 // the limits are 0.0 to 1.0. ARRae.
3717 switch (par->pextra_widthp.length()) {
3722 os << "0." << par->pextra_widthp;
3725 os << "0.0" << par->pextra_widthp;
3727 os << "\\columnwidth}\n";
3730 if (par_sep == BufferParams::PARSEP_INDENT) {
3731 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3734 minipage_open = true;
3735 minipage_open_depth = par->depth;
3738 && par->layout == layout
3739 && par->depth == depth
3740 && par->pextra_type == pextra_type
3741 && par->footnoteflag == footnoteflag);
3743 if (style.isEnvironment()) {
3744 os << "\\end{" << style.latexname() << '}';
3745 // maybe this should go after the minipage closes?
3746 if (foot_this_level) {
3747 if (foot_count >= 1) {
3748 if (foot_count > 1) {
3749 os << "\\addtocounter{footnote}{-"
3754 texrow += foot_texrow;
3756 foot_texrow.reset();
3761 if (minipage_open && (minipage_open_depth == depth) &&
3762 (!par || par->pextra_start_minipage ||
3763 par->pextra_type != PEXTRA_MINIPAGE)) {
3764 os << "\\end{minipage}\n";
3766 if (par_sep == BufferParams::PARSEP_INDENT) {
3770 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3771 os << "\\medskip\n\n";
3775 minipage_open = false;
3778 os << "\\end{LyXParagraphIndent}\n";
3781 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3782 && par->pextra_hfill)) {
3786 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3787 return par; // ale970302
3791 LyXParagraph * LyXParagraph::TeXFootnote(Buffer const * buf,
3792 BufferParams const & bparams,
3793 ostream & os, TexRow & texrow,
3794 ostream & foot, TexRow & foot_texrow,
3798 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3799 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3800 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3801 "No footnote!" << endl;
3803 LyXParagraph * par = this;
3804 LyXLayout const & style =
3805 textclasslist.Style(bparams.textclass,
3806 previous->GetLayout());
3808 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3809 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3810 "Float other than footnote in command"
3811 " with moving argument is illegal" << endl;
3814 if (footnotekind != LyXParagraph::FOOTNOTE
3815 && footnotekind != LyXParagraph::MARGIN
3818 // How to solve this?
3819 //&& !suffixIs(file, '\n')
3821 // we need to ensure that real floats like tables and figures
3822 // have their \begin{} on a new line otherwise we can get
3823 // incorrect results when using the endfloat.sty package
3824 // especially if two floats follow one another. ARRae 981022
3825 // NOTE: if the file is length 0 it must have just been
3826 // written out so we assume it ended with a '\n'
3828 // As far as I can see there is never any harm in writing
3829 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3834 bool moving_arg = false;
3835 bool need_closing = false;
3836 bool is_rtl = isRightToLeftPar(bparams);
3838 if (is_rtl != parent_is_rtl) {
3843 need_closing = true;
3846 //BufferParams * params = ¤t_view->buffer()->params;
3847 bool footer_in_body = true;
3848 switch (footnotekind) {
3849 case LyXParagraph::FOOTNOTE:
3850 if (style.intitle) {
3851 os << "\\thanks{\n";
3852 footer_in_body = false;
3855 if (foot_count == -1) {
3856 // we're at depth 0 so we can use:
3857 os << "\\footnote{%\n";
3858 footer_in_body = false;
3860 os << "\\footnotemark{}%\n";
3862 // we only need this when there are
3863 // multiple footnotes
3864 os << "\\stepcounter{footnote}";
3866 os << "\\footnotetext{%\n";
3867 foot_texrow.start(this, 0);
3868 foot_texrow.newline();
3873 case LyXParagraph::MARGIN:
3874 os << "\\marginpar{\n";
3876 case LyXParagraph::FIG:
3877 if (pextra_type == PEXTRA_FLOATFLT
3878 && (!pextra_width.empty()
3879 || !pextra_widthp.empty())) {
3880 if (!pextra_width.empty())
3881 os << "\\begin{floatingfigure}{"
3882 << pextra_width << "}\n";
3884 os << "\\begin{floatingfigure}{"
3885 << atoi(pextra_widthp.c_str())/100.0
3886 << "\\textwidth}\n";
3888 os << "\\begin{figure}";
3889 if (!bparams.float_placement.empty()) {
3890 os << '[' << bparams.float_placement << "]\n";
3896 case LyXParagraph::TAB:
3897 os << "\\begin{table}";
3898 if (!bparams.float_placement.empty()) {
3899 os << '[' << bparams.float_placement << "]\n";
3904 case LyXParagraph::WIDE_FIG:
3905 os << "\\begin{figure*}";
3906 if (!bparams.float_placement.empty()) {
3907 os << '[' << bparams.float_placement << "]\n";
3912 case LyXParagraph::WIDE_TAB:
3913 os << "\\begin{table*}";
3914 if (!bparams.float_placement.empty()) {
3915 os << '[' << bparams.float_placement << "]\n";
3920 case LyXParagraph::ALGORITHM:
3921 os << "\\begin{algorithm}\n";
3926 if (footnotekind != LyXParagraph::FOOTNOTE
3927 || !footer_in_body) {
3928 // Process text for all floats except footnotes in body
3930 LyXLayout const & style =
3932 .Style(bparams.textclass, par->layout);
3934 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3936 if (style.isEnvironment()
3937 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3938 // Allows the use of minipages within float
3939 // environments. Shouldn't be circular because
3940 // we don't support footnotes inside
3941 // floats (yet). ARRae
3942 par = par->TeXEnvironment(buf, bparams, os,
3947 par = par->TeXOnePar(buf, bparams,
3948 os, texrow, moving_arg,
3953 if (par && !par->IsDummy() && par->depth > depth) {
3954 par = par->TeXDeeper(buf, bparams, os, texrow,
3958 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3960 // process footnotes > depth 0 or in environments separately
3961 // NOTE: Currently don't support footnotes within footnotes
3962 // even though that is possible using the \footnotemark
3964 std::ostringstream dummy;
3968 TexRow dummy_texrow;
3969 int dummy_count = 0;
3971 LyXLayout const & style =
3973 .Style(bparams.textclass, par->layout);
3975 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3977 if (style.isEnvironment()
3978 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3979 // Allows the use of minipages within float
3980 // environments. Shouldn't be circular because
3981 // we don't support footnotes inside
3982 // floats (yet). ARRae
3983 par = par->TeXEnvironment(buf, bparams,
3985 dummy, dummy_texrow,
3988 par = par->TeXOnePar(buf, bparams,
3991 dummy, dummy_texrow,
3995 if (par && !par->IsDummy() && par->depth > depth) {
3996 par = par->TeXDeeper(buf, bparams,
3998 dummy, dummy_texrow,
4002 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4004 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4005 "Footnote in a Footnote -- not supported"
4008 #ifndef HAVE_OSTREAM
4009 delete [] dummy.str();
4013 switch (footnotekind) {
4014 case LyXParagraph::FOOTNOTE:
4015 if (footer_in_body) {
4016 // This helps tell which of the multiple
4017 // footnotetexts an error was in.
4019 foot_texrow.newline();
4024 case LyXParagraph::MARGIN:
4027 case LyXParagraph::FIG:
4028 if (pextra_type == PEXTRA_FLOATFLT
4029 && (!pextra_width.empty()
4030 || !pextra_widthp.empty()))
4031 os << "\\end{floatingfigure}";
4033 os << "\\end{figure}";
4035 case LyXParagraph::TAB:
4036 os << "\\end{table}";
4038 case LyXParagraph::WIDE_FIG:
4039 os << "\\end{figure*}";
4041 case LyXParagraph::WIDE_TAB:
4042 os << "\\end{table*}";
4044 case LyXParagraph::ALGORITHM:
4045 os << "\\end{algorithm}";
4052 if (footnotekind != LyXParagraph::FOOTNOTE
4053 && footnotekind != LyXParagraph::MARGIN) {
4054 // we need to ensure that real floats like tables and figures
4055 // have their \end{} on a line of their own otherwise we can
4056 // get incorrect results when using the endfloat.sty package.
4061 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4066 bool LyXParagraph::IsDummy() const
4068 return (footnoteflag == LyXParagraph::NO_FOOTNOTE && previous
4069 && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4073 void LyXParagraph::SetPExtraType(BufferParams const & bparams,
4074 int type, char const * width,
4075 char const * widthp)
4078 pextra_width = width;
4079 pextra_widthp = widthp;
4081 if (textclasslist.Style(bparams.textclass,
4082 layout).isEnvironment()) {
4087 while (par && (par->layout == layout)
4088 && (par->depth == depth)) {
4090 par = par->Previous();
4092 par = par->FirstPhysicalPar();
4093 while (par && par->depth > depth) {
4094 par = par->Previous();
4096 par = par->FirstPhysicalPar();
4100 while (par && (par->layout == layout)
4101 && (par->depth == depth)) {
4102 par->pextra_type = type;
4103 par->pextra_width = width;
4104 par->pextra_widthp = widthp;
4105 par = par->NextAfterFootnote();
4106 if (par && (par->depth > depth))
4107 par->SetPExtraType(bparams,
4108 type, width, widthp);
4109 while (par && ((par->depth > depth) || par->IsDummy()))
4110 par = par->NextAfterFootnote();
4116 void LyXParagraph::UnsetPExtraType(BufferParams const & bparams)
4118 if (pextra_type == PEXTRA_NONE)
4121 pextra_type = PEXTRA_NONE;
4122 pextra_width.erase();
4123 pextra_widthp.erase();
4125 if (textclasslist.Style(bparams.textclass,
4126 layout).isEnvironment()) {
4131 while (par && (par->layout == layout)
4132 && (par->depth == depth)) {
4134 par = par->Previous();
4136 par = par->FirstPhysicalPar();
4137 while (par && par->depth > depth) {
4138 par = par->Previous();
4140 par = par->FirstPhysicalPar();
4144 while (par && (par->layout == layout)
4145 && (par->depth == depth)) {
4146 par->pextra_type = PEXTRA_NONE;
4147 par->pextra_width.erase();
4148 par->pextra_widthp.erase();
4149 par = par->NextAfterFootnote();
4150 if (par && (par->depth > depth))
4151 par->UnsetPExtraType(bparams);
4152 while (par && ((par->depth > depth) || par->IsDummy()))
4153 par = par->NextAfterFootnote();
4159 bool LyXParagraph::IsHfill(size_type pos) const
4161 return IsHfillChar(GetChar(pos));
4165 bool LyXParagraph::IsInset(size_type pos) const
4167 return IsInsetChar(GetChar(pos));
4171 bool LyXParagraph::IsFloat(size_type pos) const
4173 return IsFloatChar(GetChar(pos));
4177 bool LyXParagraph::IsNewline(size_type pos) const
4179 return pos >= 0 && IsNewlineChar(GetChar(pos));
4183 bool LyXParagraph::IsSeparator(size_type pos) const
4185 return IsSeparatorChar(GetChar(pos));
4189 bool LyXParagraph::IsLineSeparator(size_type pos) const
4191 return IsLineSeparatorChar(GetChar(pos));
4195 bool LyXParagraph::IsKomma(size_type pos) const
4197 return IsKommaChar(GetChar(pos));
4201 /// Used by the spellchecker
4202 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4204 unsigned char c = GetChar(pos);
4205 if (IsLetterChar(c))
4207 // '\0' is not a letter, allthough every string contains "" (below)
4210 // We want to pass the ' and escape chars to ispell
4211 string extra = lyxrc.isp_esc_chars + '\'';
4215 return contains(extra, ch);
4219 bool LyXParagraph::IsWord(size_type pos ) const
4221 return IsWordChar(GetChar(pos)) ;
4226 LyXParagraph::getParLanguage(BufferParams const & bparams) const
4229 return FirstPhysicalPar()->getParLanguage(bparams);
4230 else if (size() > 0)
4234 return GetFirstFontSettings().language();
4237 for (size_type pos = 0; pos < size(); ++pos)
4239 return GetFontSettings(bparams, pos).language();
4240 return GetFirstFontSettings().language();
4244 return previous->getParLanguage(bparams);
4246 return bparams.language_info;
4250 bool LyXParagraph::isRightToLeftPar(BufferParams const & bparams) const
4252 return lyxrc.rtl_support && !table
4253 && getParLanguage(bparams)->RightToLeft();
4257 void LyXParagraph::ChangeLanguage(BufferParams const & bparams,
4258 Language const * from, Language const * to)
4260 for(size_type i = 0; i < size(); ++i) {
4261 LyXFont font = GetFontSettings(bparams, i);
4262 if (font.language() == from) {
4263 font.setLanguage(to);
4270 bool LyXParagraph::isMultiLingual(BufferParams const & bparams)
4272 Language const * doc_language =
4273 bparams.language_info;
4274 for(size_type i = 0; i < size(); ++i) {
4275 LyXFont font = GetFontSettings(bparams, i);
4276 if (font.language() != doc_language)
4283 // Convert the paragraph to a string.
4284 // Used for building the table of contents
4285 string LyXParagraph::String(Buffer const * buffer, bool label)
4287 BufferParams const & bparams = buffer->params;
4289 if (label && !IsDummy() && !labelstring.empty())
4290 s += labelstring + ' ';
4291 string::size_type len = s.size();
4293 for (LyXParagraph::size_type i = 0; i < size(); ++i) {
4294 unsigned char c = GetChar(i);
4297 else if (c == META_INSET &&
4298 GetInset(i)->LyxCode() == Inset::MATH_CODE) {
4300 std::ostringstream ost;
4301 GetInset(i)->Ascii(buffer, ost);
4304 GetInset(i)->Ascii(buffer, ost);
4307 s += subst(ost.str(),'\n',' ');
4311 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
4312 && footnoteflag == LyXParagraph::NO_FOOTNOTE)
4313 s += NextAfterFootnote()->String(buffer, false);
4316 if (isRightToLeftPar(bparams))
4317 reverse(s.begin() + len,s.end());
4323 string LyXParagraph::String(Buffer const * buffer,
4324 LyXParagraph::size_type beg,
4325 LyXParagraph::size_type end)
4332 for (LyXParagraph::size_type i = 0; i < beg; ++i)
4334 if (cell >= table->NumberOfCellsInRow(actcell))
4342 if (beg == 0 && !IsDummy() && !labelstring.empty())
4343 s += labelstring + ' ';
4345 for (LyXParagraph::size_type i = beg; i < end; ++i) {
4346 unsigned char c = GetChar(i);
4349 else if (c == META_INSET) {
4351 std::ostringstream ost;
4352 GetInset(i)->Ascii(buffer, ost);
4355 GetInset(i)->Ascii(buffer, ost);
4359 } else if (table && IsNewlineChar(c)) {
4360 if (cell >= table->NumberOfCellsInRow(actcell)) {
4371 //if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
4372 // s += NextAfterFootnote()->String(false);