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 "insets/insettext.h"
33 #include "support/filetools.h"
34 #include "lyx_gui_misc.h"
36 #include "support/lyxmanip.h"
37 #include "BufferView.h"
43 using std::lower_bound;
44 using std::upper_bound;
47 int tex_code_break_column = 72; // needs non-zero initialization. set later.
48 // this is a bad idea, but how can LyXParagraph find its buffer to get
49 // parameters? (JMarc)
50 extern BufferView * current_view;
51 extern string bibitemWidest(Painter &);
53 // this is a minibuffer
54 static char minibuffer_char;
55 static LyXFont minibuffer_font;
56 static Inset * minibuffer_inset;
59 // Initialization of the counter for the paragraph id's,
60 // declared in lyxparagraph.h
61 unsigned int LyXParagraph::paragraph_id = 0;
64 LyXParagraph::LyXParagraph()
66 text.reserve(500); // is this number too big?
68 for (int i = 0; i < 10; ++i) setCounter(i , 0);
74 footnoteflag = LyXParagraph::NO_FOOTNOTE;
75 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
77 align = LYX_ALIGN_BLOCK;
80 /* table stuff -- begin*/
82 /* table stuff -- end*/
86 bibkey = 0; // ale970302
91 // This konstruktor inserts the new paragraph in a list.
92 LyXParagraph::LyXParagraph(LyXParagraph * par)
95 par->text.resize(par->text.size());
97 for (int i = 0; i < 10; ++i) setCounter(i, 0);
101 // double linked list begin
104 next->previous = this;
106 previous->next = this;
108 footnoteflag = LyXParagraph::NO_FOOTNOTE;
109 footnotekind = LyXParagraph::FOOTNOTE;
112 /* table stuff -- begin*/
114 /* table stuff -- end*/
117 id_ = paragraph_id++;
119 bibkey = 0; // ale970302
125 void LyXParagraph::writeFile(Buffer const * buf, ostream & os,
126 BufferParams const & params,
127 char footflag, char dth) const
129 LyXFont font1, font2;
134 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
136 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
138 // The beginning or the end of a footnote environment?
139 if (footflag != footnoteflag) {
140 footflag = footnoteflag;
142 os << "\n\\begin_float "
143 << string_footnotekinds[footnotekind]
146 os << "\n\\end_float ";
150 // The beginning or end of a deeper (i.e. nested) area?
153 while (depth > dth) {
154 os << "\n\\begin_deeper ";
158 while (depth < dth) {
159 os << "\n\\end_deeper ";
165 // First write the layout
167 << textclasslist.NameOfLayout(params.textclass, layout)
170 // Maybe some vertical spaces.
171 if (added_space_top.kind() != VSpace::NONE)
172 os << "\\added_space_top "
173 << added_space_top.asLyXCommand() << " ";
174 if (added_space_bottom.kind() != VSpace::NONE)
175 os << "\\added_space_bottom "
176 << added_space_bottom.asLyXCommand() << " ";
178 // Maybe the paragraph has special spacing
179 spacing.writeFile(os, true);
181 // The labelwidth string used in lists.
182 if (!labelwidthstring.empty())
183 os << "\\labelwidthstring "
184 << labelwidthstring << '\n';
186 // Lines above or below?
190 os << "\\line_bottom ";
192 // Pagebreaks above or below?
194 os << "\\pagebreak_top ";
195 if (pagebreak_bottom)
196 os << "\\pagebreak_bottom ";
198 // Start of appendix?
199 if (start_of_appendix)
200 os << "\\start_of_appendix ";
207 if (align != LYX_ALIGN_LAYOUT) {
209 case LYX_ALIGN_LEFT: h = 1; break;
210 case LYX_ALIGN_RIGHT: h = 2; break;
211 case LYX_ALIGN_CENTER: h = 3; break;
212 default: h = 0; break;
214 os << "\\align " << string_align[h] << " ";
216 if (pextra_type != PEXTRA_NONE) {
217 os << "\\pextra_type " << pextra_type;
218 if (pextra_type == PEXTRA_MINIPAGE) {
219 os << " \\pextra_alignment "
222 os << " \\pextra_hfill "
224 if (pextra_start_minipage)
225 os << " \\pextra_start_minipage "
226 << pextra_start_minipage;
228 if (!pextra_width.empty()) {
229 os << " \\pextra_width "
230 << VSpace(pextra_width).asLyXCommand();
231 } else if (!pextra_widthp.empty()) {
232 os << " \\pextra_widthp "
238 // Dummy layout. This means that a footnote ended.
239 os << "\n\\end_float ";
240 footflag = LyXParagraph::NO_FOOTNOTE;
243 // It might be a table.
245 os << "\\LyXTable\n";
251 bibkey->Write(buf, os);
253 font1 = LyXFont(LyXFont::ALL_INHERIT,params.language_info);
256 for (size_type i = 0; i < size(); ++i) {
262 // Write font changes
263 font2 = GetFontSettings(params, i);
264 if (font2 != font1) {
265 font2.lyxWriteChanges(font1, os);
274 Inset const * inset = GetInset(i);
276 if (inset->DirectWrite()) {
277 // international char, let it write
278 // code directly so it's shorter in
280 inset->Write(buf, os);
282 os << "\n\\begin_inset ";
283 inset->Write(buf, os);
284 os << "\n\\end_inset \n\n";
290 os << "\n\\newline \n";
294 os << "\n\\hfill \n";
298 os << "\n\\backslash \n";
302 if (i + 1 < size() && GetChar(i + 1) == ' ') {
309 if ((column > 70 && c == ' ')
314 // this check is to amend a bug. LyX sometimes
315 // inserts '\0' this could cause problems.
319 lyxerr << "ERROR (LyXParagraph::writeFile):"
320 " NULL char in structure." << endl;
326 // now write the next paragraph
328 next->writeFile(buf, os, params, footflag, dth);
332 void LyXParagraph::validate(LaTeXFeatures & features) const
334 BufferParams const & params = features.bufferParams();
336 // this will be useful later
337 LyXLayout const & layout =
338 textclasslist.Style(params.textclass,
342 if (line_top || line_bottom)
343 features.lyxline = true;
344 if (!spacing.isDefault())
345 features.setspace = true;
348 features.layout[GetLayout()] = true;
351 Language const * doc_language = params.language_info;
353 for (FontList::const_iterator cit = fontlist.begin();
354 cit != fontlist.end(); ++cit) {
355 if ((*cit).font.noun() == LyXFont::ON) {
356 lyxerr[Debug::LATEX] << "font.noun: "
357 << (*cit).font.noun()
359 features.noun = true;
360 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
361 << (*cit).font.stateText(0)
364 switch ((*cit).font.color()) {
366 case LColor::inherit:
370 features.color = true;
371 lyxerr[Debug::LATEX] << "Color enabled. Font: "
372 << (*cit).font.stateText(0)
376 Language const * language = (*cit).font.language();
377 if (language != doc_language) {
378 features.UsedLanguages.insert(language);
379 lyxerr[Debug::LATEX] << "Found language "
380 << language->lang() << endl;
385 for (InsetList::const_iterator cit = insetlist.begin();
386 cit != insetlist.end(); ++cit) {
388 (*cit).inset->Validate(features);
391 if (table && table->IsLongTable())
392 features.longtable = true;
393 if (pextra_type == PEXTRA_INDENT)
394 features.LyXParagraphIndent = true;
395 if (pextra_type == PEXTRA_FLOATFLT)
396 features.floatflt = true;
397 if (layout.needprotect
398 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
399 features.NeedLyXFootnoteCode = true;
400 if (params.paragraph_separation == BufferParams::PARSEP_INDENT
401 && pextra_type == LyXParagraph::PEXTRA_MINIPAGE)
402 features.NeedLyXMinipageIndent = true;
403 if (table && table->NeedRotating())
404 features.rotating = true;
405 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
406 features.algorithm = true;
410 // First few functions needed for cut and paste and paragraph breaking.
411 void LyXParagraph::CopyIntoMinibuffer(BufferParams const & bparams,
412 LyXParagraph::size_type pos) const
414 minibuffer_char = GetChar(pos);
415 minibuffer_font = GetFontSettings(bparams, pos);
416 minibuffer_inset = 0;
417 if (minibuffer_char == LyXParagraph::META_INSET) {
419 minibuffer_inset = GetInset(pos)->Clone();
421 minibuffer_inset = 0;
422 minibuffer_char = ' ';
423 // This reflects what GetInset() does (ARRae)
429 void LyXParagraph::CutIntoMinibuffer(BufferParams const & bparams,
430 LyXParagraph::size_type pos)
432 minibuffer_char = GetChar(pos);
433 minibuffer_font = GetFontSettings(bparams, pos);
434 minibuffer_inset = 0;
435 if (minibuffer_char == LyXParagraph::META_INSET) {
437 minibuffer_inset = GetInset(pos);
438 // This is a little hack since I want exactly
439 // the inset, not just a clone. Otherwise
440 // the inset would be deleted when calling Erase(pos)
442 InsetList::iterator it = lower_bound(insetlist.begin(),
445 if (it != insetlist.end() && (*it).pos == pos)
448 minibuffer_inset = 0;
449 minibuffer_char = ' ';
450 // This reflects what GetInset() does (ARRae)
455 // Erase(pos); now the caller is responsible for that.
459 bool LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
461 if ((minibuffer_char == LyXParagraph::META_INSET) &&
462 !InsertInsetAllowed(minibuffer_inset))
464 InsertChar(pos, minibuffer_char);
465 SetFont(pos, minibuffer_font);
466 if (minibuffer_char == LyXParagraph::META_INSET)
467 InsertInset(pos, minibuffer_inset);
475 void LyXParagraph::Clear()
480 pagebreak_top = false;
481 pagebreak_bottom = false;
483 added_space_top = VSpace(VSpace::NONE);
484 added_space_bottom = VSpace(VSpace::NONE);
485 spacing.set(Spacing::Default);
487 align = LYX_ALIGN_LAYOUT;
491 pextra_type = PEXTRA_NONE;
492 pextra_width.erase();
493 pextra_widthp.erase();
494 pextra_alignment = MINIPAGE_ALIGN_TOP;
495 pextra_hfill = false;
496 pextra_start_minipage = false;
499 labelwidthstring.erase();
503 start_of_appendix = false;
507 // the destructor removes the new paragraph from the list
508 LyXParagraph::~LyXParagraph()
511 previous->next = next;
513 next->previous = previous;
515 for (InsetList::iterator it = insetlist.begin();
516 it != insetlist.end(); ++it) {
520 /* table stuff -- begin*/
522 /* table stuff -- end*/
528 //lyxerr << "LyXParagraph::paragraph_id = "
529 // << LyXParagraph::paragraph_id << endl;
533 void LyXParagraph::Erase(LyXParagraph::size_type pos)
535 // > because last is the next unused position, and you can
536 // use it if you want
538 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
539 NextAfterFootnote()->Erase(pos - text.size() - 1);
541 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
542 "position does not exist." << endl;
545 if (pos < size()) { // last is free for insertation, but should be empty
546 // if it is an inset, delete the inset entry
547 if (text[pos] == LyXParagraph::META_INSET) {
549 InsetList::iterator it = lower_bound(insetlist.begin(),
552 if (it != insetlist.end() && (*it).pos == pos) {
557 text.erase(text.begin() + pos);
559 // Erase entries in the tables.
560 FontList::iterator it = lower_bound(fontlist.begin(),
563 if (it != fontlist.end() && (*it).pos == pos &&
565 (it != fontlist.begin() && (*(it-1)).pos == pos - 1))) {
566 // If it is a multi-character font
567 // entry, we just make it smaller
568 // (see update below), otherwise we
570 unsigned int i = it - fontlist.begin();
571 fontlist.erase(fontlist.begin() + i);
572 it = fontlist.begin() + i;
573 if (i > 0 && i < fontlist.size() &&
574 fontlist[i-1].font == fontlist[i].font) {
575 fontlist.erase(fontlist.begin() + i-1);
576 it = fontlist.begin() + i-1;
580 // Update all other entries.
581 for (; it != fontlist.end(); ++it)
584 // Update the inset table.
585 for (InsetList::iterator it = upper_bound(insetlist.begin(),
588 it != insetlist.end(); ++it)
591 lyxerr << "ERROR (LyXParagraph::Erase): "
592 "can't erase non-existant char." << endl;
597 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
599 // > because last is the next unused position, and you can
600 // use it if you want
603 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
604 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
607 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
608 "position does not exist." << endl;
611 text.insert(text.begin() + pos, c);
612 // Update the font table.
613 for (FontList::iterator it = lower_bound(fontlist.begin(),
616 it != fontlist.end(); ++it)
619 // Update the inset table.
620 for (InsetList::iterator it = lower_bound(insetlist.begin(),
623 it != insetlist.end(); ++it)
628 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
631 // > because last is the next unused position, and you can
632 // use it if you want
635 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
637 ->InsertInset(pos - text.size() - 1, inset);
639 lyxerr << "ERROR (LyXParagraph::InsertInset): "
640 "position does not exist: " << pos << endl;
643 if (text[pos] != LyXParagraph::META_INSET) {
644 lyxerr << "ERROR (LyXParagraph::InsertInset): "
645 "there is no LyXParagraph::META_INSET" << endl;
650 // Add a new entry in the inset table.
651 InsetList::iterator it = lower_bound(insetlist.begin(),
654 if (it != insetlist.end() && (*it).pos == pos)
655 lyxerr << "ERROR (LyXParagraph::InsertInset): "
656 "there is an inset in position: " << pos << endl;
658 insetlist.insert(it, InsetTable(pos,inset));
660 inset->setOwner(inset_owner);
665 bool LyXParagraph::InsertInsetAllowed(Inset * inset)
668 return inset_owner->InsertInsetAllowed(inset);
673 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
677 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
678 return NextAfterFootnote()
679 ->GetInset(pos - text.size() - 1);
681 lyxerr << "ERROR (LyXParagraph::GetInset): "
682 "position does not exist: "
688 InsetList::iterator it = lower_bound(insetlist.begin(),
691 if (it != insetlist.end() && (*it).pos == pos)
694 lyxerr << "ERROR (LyXParagraph::GetInset): "
695 "Inset does not exist: " << pos << endl;
696 // text[pos] = ' '; // WHY!!! does this set the pos to ' '????
697 // Did this commenting out introduce a bug? So far I have not
698 // see any, please enlighten me. (Lgb)
699 // My guess is that since the inset does not exist, we might
700 // as well replace it with a space to prevent craches. (Asger)
705 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
709 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
710 return NextAfterFootnote()
711 ->GetInset(pos - text.size() - 1);
713 lyxerr << "ERROR (LyXParagraph::GetInset): "
714 "position does not exist: "
720 InsetList::const_iterator cit = lower_bound(insetlist.begin(),
723 if (cit != insetlist.end() && (*cit).pos == pos)
726 lyxerr << "ERROR (LyXParagraph::GetInset): "
727 "Inset does not exist: " << pos << endl;
728 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
729 // Did this commenting out introduce a bug? So far I have not
730 // see any, please enlighten me. (Lgb)
731 // My guess is that since the inset does not exist, we might
732 // as well replace it with a space to prevent craches. (Asger)
737 // Gets uninstantiated font setting at position.
738 // Optimized after profiling. (Asger)
739 LyXFont LyXParagraph::GetFontSettings(BufferParams const & bparams,
740 LyXParagraph::size_type pos) const
743 FontList::const_iterator cit = lower_bound(fontlist.begin(),
746 if (cit != fontlist.end())
749 // > because last is the next unused position, and you can
750 // use it if you want
751 else if (pos > size()) {
753 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
754 return NextAfterFootnote()
755 ->GetFontSettings(bparams,
756 pos - text.size() - 1);
758 // Why is it an error to ask for the font of a
759 // position that does not exist? Would it be
760 // enough for this to be enabled on debug?
761 // We want strict error checking, but it's ok to only
762 // have it when debugging. (Asger)
763 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
764 "position does not exist. "
765 << pos << " (" << static_cast<int>(pos)
768 } else if (pos > 0) {
769 return GetFontSettings(bparams, pos - 1);
770 } else // pos = size() = 0
771 return LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
773 return LyXFont(LyXFont::ALL_INHERIT);
776 // Gets uninstantiated font setting at position 0
777 LyXFont LyXParagraph::GetFirstFontSettings() const
780 if (!fontlist.empty())
781 return fontlist[0].font;
782 } else if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
783 return NextAfterFootnote()->GetFirstFontSettings();
784 return LyXFont(LyXFont::ALL_INHERIT);
788 // Gets the fully instantiated font at a given position in a paragraph
789 // This is basically the same function as LyXText::GetFont() in text2.C.
790 // The difference is that this one is used for generating the LaTeX file,
791 // and thus cosmetic "improvements" are disallowed: This has to deliver
792 // the true picture of the buffer. (Asger)
793 // If position is -1, we get the layout font of the paragraph.
794 // If position is -2, we get the font of the manual label of the paragraph.
795 LyXFont LyXParagraph::getFont(BufferParams const & bparams,
796 LyXParagraph::size_type pos) const
799 LyXLayout const & layout =
800 textclasslist.Style(bparams.textclass,
802 LyXParagraph::size_type main_body = 0;
803 if (layout.labeltype == LABEL_MANUAL)
804 main_body = BeginningOfMainBody();
809 layoutfont = layout.labelfont;
811 layoutfont = layout.font;
812 tmpfont = GetFontSettings(bparams, pos);
813 tmpfont.realize(layoutfont);
815 // process layoutfont for pos == -1 and labelfont for pos < -1
817 tmpfont = layout.font;
819 tmpfont = layout.labelfont;
820 tmpfont.setLanguage(getParLanguage(bparams));
823 // check for environment font information
824 char par_depth = GetDepth();
825 LyXParagraph const * par = this;
826 while (par && par_depth && !tmpfont.resolved()) {
827 par = par->DepthHook(par_depth - 1);
829 tmpfont.realize(textclasslist.
830 Style(bparams.textclass,
831 par->GetLayout()).font);
832 par_depth = par->GetDepth();
836 tmpfont.realize(textclasslist
837 .TextClass(bparams.textclass)
843 /// Returns the height of the highest font in range
845 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
846 LyXParagraph::size_type endpos) const
848 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
849 if (fontlist.empty())
852 FontList::const_iterator end_it = lower_bound(fontlist.begin(),
855 if (end_it != fontlist.end())
858 for (FontList::const_iterator cit = lower_bound(fontlist.begin(),
860 startpos, matchFT());
861 cit != end_it; ++cit) {
862 LyXFont::FONT_SIZE size = (*cit).font.size();
863 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
870 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
877 // > because last is the next unused position, and you can
878 // use it if you want
879 else if (pos > size()) {
880 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
881 return NextAfterFootnote()
882 ->GetChar(pos - text.size() - 1);
884 lyxerr << "ERROR (LyXParagraph::GetChar): "
885 "position does not exist."
886 << pos << " (" << static_cast<int>(pos)
888 // Assert(false); // This triggers sometimes...
893 // We should have a footnote environment.
894 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
895 // Notice that LyX does request the
896 // last char from time to time. (Asger)
897 //lyxerr << "ERROR (LyXParagraph::GetChar): "
898 // "expected footnote." << endl;
901 switch (next->footnotekind) {
902 case LyXParagraph::FOOTNOTE:
903 return LyXParagraph::META_FOOTNOTE;
904 case LyXParagraph::MARGIN:
905 return LyXParagraph::META_MARGIN;
906 case LyXParagraph::FIG:
907 case LyXParagraph::WIDE_FIG:
908 return LyXParagraph::META_FIG;
909 case LyXParagraph::TAB:
910 case LyXParagraph::WIDE_TAB:
911 return LyXParagraph::META_TAB;
912 case LyXParagraph::ALGORITHM:
913 return LyXParagraph::META_ALGORITHM;
915 return '\0'; // to shut up gcc
920 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
927 // > because last is the next unused position, and you can
928 // use it if you want
929 else if (pos > size()) {
930 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
931 return NextAfterFootnote()
932 ->GetChar(pos - text.size() - 1);
934 lyxerr << "ERROR (LyXParagraph::GetChar const): "
935 "position does not exist."
936 << pos << " (" << static_cast<int>(pos)
942 // We should have a footnote environment.
943 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
944 // Notice that LyX does request the
945 // last char from time to time. (Asger)
946 //lyxerr << "ERROR (LyXParagraph::GetChar): "
947 // "expected footnote." << endl;
950 switch (next->footnotekind) {
951 case LyXParagraph::FOOTNOTE:
952 return LyXParagraph::META_FOOTNOTE;
953 case LyXParagraph::MARGIN:
954 return LyXParagraph::META_MARGIN;
955 case LyXParagraph::FIG:
956 case LyXParagraph::WIDE_FIG:
957 return LyXParagraph::META_FIG;
958 case LyXParagraph::TAB:
959 case LyXParagraph::WIDE_TAB:
960 return LyXParagraph::META_TAB;
961 case LyXParagraph::ALGORITHM:
962 return LyXParagraph::META_ALGORITHM;
964 return '\0'; // to shut up gcc
969 // return an string of the current word, and the end of the word in lastpos.
970 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
974 // the current word is defined as starting at the first character
975 // from the immediate left of lastpospos which meets the definition
976 // of IsLetter(), continuing to the last character to the right
977 // of this meeting IsLetter.
983 // move back until we have a letter
985 //there's no real reason to have firstpos & lastpos as
986 //separate variables as this is written, but maybe someon
987 // will want to return firstpos in the future.
989 //since someone might have typed a punctuation first
990 int firstpos = lastpos;
992 while ((firstpos >= 0) && !IsLetter(firstpos))
995 // now find the beginning by looking for a nonletter
997 while ((firstpos>= 0) && IsLetter(firstpos))
1000 // the above is now pointing to the preceeding non-letter
1004 // so copy characters into theword until we get a nonletter
1005 // note that this can easily exceed lastpos, wich means
1006 // that if used in the middle of a word, the whole word
1009 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1016 LyXParagraph::size_type LyXParagraph::Last() const
1018 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1019 return text.size() + NextAfterFootnote()->Last() + 1;
1020 // the 1 is the symbol
1027 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1029 // > because last is the next unused position, and you can
1030 // use it if you want
1033 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1034 return NextAfterFootnote()
1035 ->ParFromPos(pos - text.size() - 1);
1037 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1038 "position does not exist." << endl;
1045 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1047 // > because last is the next unused position, and you can
1048 // use it if you want
1051 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1052 return NextAfterFootnote()
1053 ->PositionInParFromPos(pos - text.size() - 1);
1056 "ERROR (LyXParagraph::PositionInParFromPos): "
1057 "position does not exist." << endl;
1065 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1066 LyXFont const & font)
1068 // > because last is the next unused position, and you can
1069 // use it if you want
1072 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1073 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1076 lyxerr << "ERROR (LyXParagraph::SetFont): "
1077 "position does not exist." << endl;
1082 // First, reduce font against layout/label font
1083 // Update: The SetCharFont() routine in text2.C already
1084 // reduces font, so we don't need to do that here. (Asger)
1085 // No need to simplify this because it will disappear
1086 // in a new kernel. (Asger)
1087 // Next search font table
1089 FontList::iterator it = lower_bound(fontlist.begin(),
1092 unsigned int i = it - fontlist.begin();
1093 bool notfound = it == fontlist.end();
1095 if (!notfound && fontlist[i].font == font)
1098 bool begin = pos == 0 || notfound ||
1099 (i > 0 && fontlist[i-1].pos == pos - 1);
1100 // Is position pos is a beginning of a font block?
1101 bool end = !notfound && fontlist[i].pos == pos;
1102 // Is position pos is the end of a font block?
1103 if (begin && end) { // A single char block
1104 if (i+1 < fontlist.size() &&
1105 fontlist[i+1].font == font) {
1106 // Merge the singleton block with the next block
1107 fontlist.erase(fontlist.begin() + i);
1108 if (i > 0 && fontlist[i-1].font == font)
1109 fontlist.erase(fontlist.begin() + i-1);
1110 } else if (i > 0 && fontlist[i-1].font == font) {
1111 // Merge the singleton block with the previous block
1112 fontlist[i-1].pos = pos;
1113 fontlist.erase(fontlist.begin() + i);
1115 fontlist[i].font = font;
1117 if (i > 0 && fontlist[i-1].font == font)
1118 fontlist[i-1].pos = pos;
1120 fontlist.insert(fontlist.begin() + i,
1121 FontTable(pos, font));
1123 fontlist[i].pos = pos - 1;
1124 if (!(i+1 < fontlist.size() &&
1125 fontlist[i+1].font == font))
1126 fontlist.insert(fontlist.begin() + i+1,
1127 FontTable(pos, font));
1128 } else { // The general case. The block is splitted into 3 blocks
1129 fontlist.insert(fontlist.begin() + i,
1130 FontTable(pos - 1, fontlist[i].font));
1131 fontlist.insert(fontlist.begin() + i+1, FontTable(pos, font));
1136 // This function is able to hide closed footnotes.
1137 LyXParagraph * LyXParagraph::Next()
1139 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1140 LyXParagraph * tmp = next;
1142 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1144 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1145 return tmp->Next(); /* there can be more than one
1146 footnote in a logical
1149 return next; // This should never happen!
1155 LyXParagraph * LyXParagraph::NextAfterFootnote()
1157 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1158 LyXParagraph * tmp = next;
1159 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1161 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1162 return tmp; /* there can be more than one footnote
1163 in a logical paragraph */
1165 return next; // This should never happen!
1171 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1173 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1174 LyXParagraph * tmp = next;
1175 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1177 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1178 return tmp; /* there can be more than one footnote
1179 in a logical paragraph */
1181 return next; // This should never happen!
1187 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1190 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1192 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1193 tmp = tmp->previous;
1194 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1195 return tmp; /* there can be more than one footnote
1196 in a logical paragraph */
1198 return previous; // This should never happen!
1204 LyXParagraph * LyXParagraph::LastPhysicalPar()
1206 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1209 LyXParagraph * tmp = this;
1211 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1212 tmp = tmp->NextAfterFootnote();
1217 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1219 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1222 LyXParagraph const * tmp = this;
1224 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1225 tmp = tmp->NextAfterFootnote();
1230 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1234 LyXParagraph * tmppar = this;
1238 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1239 tmppar = tmppar->previous;
1248 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1252 LyXParagraph const * tmppar = this;
1256 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1257 tmppar = tmppar->previous;
1266 // This function is able to hide closed footnotes.
1267 LyXParagraph * LyXParagraph::Previous()
1269 LyXParagraph * tmp = previous;
1274 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1275 tmp = tmp->previous;
1277 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1278 tmp = tmp->previous;
1279 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1280 return tmp->next->Previous();
1289 // This function is able to hide closed footnotes.
1290 LyXParagraph const * LyXParagraph::Previous() const
1292 LyXParagraph * tmp = previous;
1297 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1298 tmp = tmp->previous;
1300 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1301 tmp = tmp->previous;
1302 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1303 return tmp->next->Previous();
1312 void LyXParagraph::BreakParagraph(BufferParams const & bparams,
1313 LyXParagraph::size_type pos,
1316 size_type i, j, pos_end, pos_first;
1317 // create a new paragraph
1318 LyXParagraph * par = ParFromPos(pos);
1319 LyXParagraph * firstpar = FirstPhysicalPar();
1321 LyXParagraph * tmp = new LyXParagraph(par);
1323 tmp->footnoteflag = footnoteflag;
1324 tmp->footnotekind = footnotekind;
1326 // this is an idea for a more userfriendly layout handling, I will
1327 // see what the users say
1329 // layout stays the same with latex-environments
1331 tmp->SetOnlyLayout(bparams, firstpar->layout);
1332 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1335 if (Last() > pos || !Last() || flag == 2) {
1336 tmp->SetOnlyLayout(bparams, firstpar->layout);
1337 tmp->align = firstpar->align;
1338 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1340 tmp->line_bottom = firstpar->line_bottom;
1341 firstpar->line_bottom = false;
1342 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1343 firstpar->pagebreak_bottom = false;
1344 tmp->added_space_bottom = firstpar->added_space_bottom;
1345 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1347 tmp->depth = firstpar->depth;
1348 tmp->noindent = firstpar->noindent;
1350 // copy everything behind the break-position
1351 // to the new paragraph
1353 while (ParFromPos(pos_first) != par)
1356 pos_end = pos_first + par->text.size() - 1;
1358 for (i = j = pos; i <= pos_end; ++i) {
1359 par->CutIntoMinibuffer(bparams, i - pos_first);
1360 if (tmp->InsertFromMinibuffer(j - pos))
1363 tmp->text.resize(tmp->text.size());
1364 for (i = pos_end; i >= pos; --i)
1365 par->Erase(i - pos_first);
1367 par->text.resize(par->text.size());
1370 // just an idea of me
1372 tmp->line_top = firstpar->line_top;
1373 tmp->pagebreak_top = firstpar->pagebreak_top;
1374 tmp->added_space_top = firstpar->added_space_top;
1375 tmp->bibkey = firstpar->bibkey;
1377 // layout stays the same with latex-environments
1379 firstpar->SetOnlyLayout(bparams, tmp->layout);
1380 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1381 firstpar->depth = tmp->depth;
1387 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1389 par = par->FirstPhysicalPar();
1390 footnoteflag = par->footnoteflag;
1391 footnotekind = par->footnotekind;
1393 layout = par->layout;
1394 align = par-> align;
1395 SetLabelWidthString(par->labelwidthstring);
1397 line_bottom = par->line_bottom;
1398 pagebreak_bottom = par->pagebreak_bottom;
1399 added_space_bottom = par->added_space_bottom;
1401 line_top = par->line_top;
1402 pagebreak_top = par->pagebreak_top;
1403 added_space_top = par->added_space_top;
1405 spacing = par->spacing;
1407 pextra_type = par->pextra_type;
1408 pextra_width = par->pextra_width;
1409 pextra_widthp = par->pextra_widthp;
1410 pextra_alignment = par->pextra_alignment;
1411 pextra_hfill = par->pextra_hfill;
1412 pextra_start_minipage = par->pextra_start_minipage;
1414 noindent = par->noindent;
1419 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1421 LyXParagraph * tmppar = this;
1424 && tmppar->previous->footnoteflag ==
1425 LyXParagraph::CLOSED_FOOTNOTE)
1426 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1427 tmppar = tmppar->previous;
1430 return this; // This should never happen!
1435 int LyXParagraph::StripLeadingSpaces(LyXTextClassList::size_type tclass)
1437 if (textclasslist.Style(tclass, GetLayout()).free_spacing)
1441 if (!IsDummy() && !table){
1443 && (IsNewline(0) || IsLineSeparator(0))){
1452 LyXParagraph * LyXParagraph::Clone() const
1454 // create a new paragraph
1455 LyXParagraph * result = new LyXParagraph;
1457 result->MakeSameLayout(this);
1459 // this is because of the dummy layout of the paragraphs that
1461 result->layout = layout;
1464 /* table stuff -- begin*/
1466 result->table = table->Clone();
1469 /* table stuff -- end*/
1471 result->inset_owner = inset_owner;
1474 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1477 // copy everything behind the break-position to the new paragraph
1479 result->text = text;
1480 result->fontlist = fontlist;
1481 result->insetlist = insetlist;
1482 for (InsetList::iterator it = result->insetlist.begin();
1483 it != result->insetlist.end(); ++it)
1484 (*it).inset = (*it).inset->Clone();
1489 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1491 par = par->FirstPhysicalPar();
1494 par->footnoteflag == footnoteflag &&
1495 par->footnotekind == footnotekind &&
1497 par->layout == layout &&
1499 par->align == align &&
1501 par->line_bottom == line_bottom &&
1502 par->pagebreak_bottom == pagebreak_bottom &&
1503 par->added_space_bottom == added_space_bottom &&
1505 par->line_top == line_top &&
1506 par->pagebreak_top == pagebreak_top &&
1507 par->added_space_top == added_space_top &&
1509 par->spacing == spacing &&
1511 par->pextra_type == pextra_type &&
1512 par->pextra_width == pextra_width &&
1513 par->pextra_widthp == pextra_widthp &&
1514 par->pextra_alignment == pextra_alignment &&
1515 par->pextra_hfill == pextra_hfill &&
1516 par->pextra_start_minipage == pextra_start_minipage &&
1518 par->table == table && // what means: NO TABLE AT ALL
1521 par->noindent == noindent &&
1522 par->depth == depth);
1526 void LyXParagraph::BreakParagraphConservative(BufferParams const & bparams,
1527 LyXParagraph::size_type pos)
1529 // create a new paragraph
1530 LyXParagraph * par = ParFromPos(pos);
1532 LyXParagraph * tmp = new LyXParagraph(par);
1534 tmp->MakeSameLayout(par);
1536 // When can pos < Last()?
1537 // I guess pos == Last() is possible.
1539 // copy everything behind the break-position to the new
1541 size_type pos_first = 0;
1542 while (ParFromPos(pos_first) != par)
1544 size_type pos_end = pos_first + par->text.size() - 1;
1547 for (i = j = pos; i <= pos_end; ++i) {
1548 par->CutIntoMinibuffer(bparams, i - pos_first);
1549 if (tmp->InsertFromMinibuffer(j - pos))
1552 tmp->text.resize(tmp->text.size());
1553 for (size_type i = pos_end; i >= pos; --i)
1554 par->Erase(i - pos_first);
1556 par->text.resize(par->text.size());
1561 // Be carefull, this does not make any check at all.
1562 void LyXParagraph::PasteParagraph(BufferParams const & bparams)
1564 // copy the next paragraph to this one
1565 LyXParagraph * the_next = Next();
1567 LyXParagraph * firstpar = FirstPhysicalPar();
1569 // first the DTP-stuff
1570 firstpar->line_bottom = the_next->line_bottom;
1571 firstpar->added_space_bottom = the_next->added_space_bottom;
1572 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1574 size_type pos_end = the_next->text.size() - 1;
1575 size_type pos_insert = Last();
1577 // ok, now copy the paragraph
1579 for (i = j = 0; i <= pos_end; ++i) {
1580 the_next->CutIntoMinibuffer(bparams, i);
1581 if (InsertFromMinibuffer(pos_insert + j))
1585 // delete the next paragraph
1586 LyXParagraph *ppar = the_next->previous;
1587 LyXParagraph *npar = the_next->next;
1593 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1595 LyXParagraph * par = ParFromPos(pos);
1597 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1598 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1604 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1606 LyXParagraph * par = ParFromPos(pos);
1608 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1609 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1614 int LyXParagraph::GetEndLabel(BufferParams const & bparams) const
1616 LyXParagraph const * par = this;
1617 int par_depth = GetDepth();
1619 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1621 textclasslist.Style(bparams.textclass,
1622 layout).endlabeltype;
1623 if (endlabeltype != END_LABEL_NO_LABEL) {
1624 LyXParagraph const * last = this;
1625 if( footnoteflag == NO_FOOTNOTE)
1626 last = LastPhysicalPar();
1627 else if (next->footnoteflag == NO_FOOTNOTE)
1628 return endlabeltype;
1630 if (!last || !last->next)
1631 return endlabeltype;
1633 int next_depth = last->next->GetDepth();
1634 if (par_depth > next_depth ||
1635 (par_depth == next_depth && layout != last->next->GetLayout() ))
1636 return endlabeltype;
1641 par = par->DepthHook(par_depth - 1);
1643 par_depth = par->GetDepth();
1645 return END_LABEL_NO_LABEL;
1649 LyXTextClass::size_type LyXParagraph::GetLayout() const
1651 return FirstPhysicalPar()->layout;
1655 char LyXParagraph::GetDepth() const
1657 return FirstPhysicalPar()->depth;
1661 char LyXParagraph::GetAlign() const
1663 return FirstPhysicalPar()->align;
1667 string LyXParagraph::GetLabelstring() const
1669 return FirstPhysicalPar()->labelstring;
1673 int LyXParagraph::GetFirstCounter(int i) const
1675 return FirstPhysicalPar()->counter_[i];
1679 // the next two functions are for the manual labels
1680 string LyXParagraph::GetLabelWidthString() const
1682 if (!FirstPhysicalPar()->labelwidthstring.empty())
1683 return FirstPhysicalPar()->labelwidthstring;
1685 return _("Senseless with this layout!");
1689 void LyXParagraph::SetLabelWidthString(string const & s)
1691 LyXParagraph * par = FirstPhysicalPar();
1693 par->labelwidthstring = s;
1697 void LyXParagraph::SetOnlyLayout(BufferParams const & bparams,
1698 LyXTextClass::size_type new_layout)
1700 LyXParagraph * par = FirstPhysicalPar();
1701 LyXParagraph * ppar = 0;
1702 LyXParagraph * npar = 0;
1704 par->layout = new_layout;
1706 /* table stuff -- begin*/
1709 /* table stuff -- end*/
1711 if (par->pextra_type == PEXTRA_NONE) {
1712 if (par->Previous()) {
1713 ppar = par->Previous()->FirstPhysicalPar();
1716 && (ppar->depth > par->depth))
1717 ppar = ppar->Previous()->FirstPhysicalPar();
1720 npar = par->Next()->NextAfterFootnote();
1723 && (npar->depth > par->depth))
1724 npar = npar->Next()->NextAfterFootnote();
1726 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1728 p1 = ppar->pextra_width,
1729 p2 = ppar->pextra_widthp;
1730 ppar->SetPExtraType(bparams, ppar->pextra_type,
1731 p1.c_str(), p2.c_str());
1733 if ((par->pextra_type == PEXTRA_NONE) &&
1734 npar && (npar->pextra_type != PEXTRA_NONE)) {
1736 p1 = npar->pextra_width,
1737 p2 = npar->pextra_widthp;
1738 npar->SetPExtraType(bparams, npar->pextra_type,
1739 p1.c_str(), p2.c_str());
1745 void LyXParagraph::SetLayout(BufferParams const & bparams,
1746 LyXTextClass::size_type new_layout)
1749 * par = FirstPhysicalPar(),
1753 par->layout = new_layout;
1754 par->labelwidthstring.erase();
1755 par->align = LYX_ALIGN_LAYOUT;
1756 par->added_space_top = VSpace(VSpace::NONE);
1757 par->added_space_bottom = VSpace(VSpace::NONE);
1758 par->spacing.set(Spacing::Default);
1761 /* table stuff -- begin*/
1764 /* table stuff -- end*/
1766 if (par->pextra_type == PEXTRA_NONE) {
1767 if (par->Previous()) {
1768 ppar = par->Previous()->FirstPhysicalPar();
1771 && (ppar->depth > par->depth))
1772 ppar = ppar->Previous()->FirstPhysicalPar();
1775 npar = par->Next()->NextAfterFootnote();
1778 && (npar->depth > par->depth))
1779 npar = npar->Next()->NextAfterFootnote();
1781 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1783 p1 = ppar->pextra_width,
1784 p2 = ppar->pextra_widthp;
1785 ppar->SetPExtraType(bparams, ppar->pextra_type,
1786 p1.c_str(), p2.c_str());
1788 if ((par->pextra_type == PEXTRA_NONE) &&
1789 npar && (npar->pextra_type != PEXTRA_NONE)) {
1791 p1 = npar->pextra_width,
1792 p2 = npar->pextra_widthp;
1793 npar->SetPExtraType(bparams, npar->pextra_type,
1794 p1.c_str(), p2.c_str());
1800 // if the layout of a paragraph contains a manual label, the beginning of the
1801 // main body is the beginning of the second word. This is what the par-
1802 // function returns. If the layout does not contain a label, the main
1803 // body always starts with position 0. This differentiation is necessary,
1804 // because there cannot be a newline or a blank <= the beginning of the
1805 // main body in TeX.
1807 int LyXParagraph::BeginningOfMainBody() const
1809 if (FirstPhysicalPar() != this)
1812 // Unroll the first two cycles of the loop
1813 // and remember the previous character to
1814 // remove unnecessary GetChar() calls
1817 && GetChar(i) != LyXParagraph::META_NEWLINE
1820 char previous_char = 0, temp = 0;
1822 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1823 // Yes, this ^ is supposed to be "= " not "=="
1826 && previous_char != ' '
1827 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1829 previous_char = temp;
1834 if (i == 0 && i == size() &&
1835 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1836 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1837 ++i; /* the cursor should not jump
1838 * to the main body if there
1844 LyXParagraph * LyXParagraph::DepthHook(int deth)
1846 LyXParagraph * newpar = this;
1851 newpar = newpar->FirstPhysicalPar()->Previous();
1852 } while (newpar && newpar->GetDepth() > deth
1853 && newpar->footnoteflag == footnoteflag);
1856 if (Previous() || GetDepth())
1857 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1861 return newpar->FirstPhysicalPar();
1865 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1867 LyXParagraph const * newpar = this;
1872 newpar = newpar->FirstPhysicalPar()->Previous();
1873 } while (newpar && newpar->GetDepth() > deth
1874 && newpar->footnoteflag == footnoteflag);
1877 if (Previous() || GetDepth())
1878 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1882 return newpar->FirstPhysicalPar();
1886 int LyXParagraph::AutoDeleteInsets()
1889 InsetList::size_type index = 0;
1890 while (index < insetlist.size()) {
1891 if (insetlist[index].inset && insetlist[index].inset->AutoDelete()) {
1892 Erase(insetlist[index].pos);
1893 // Erase() calls to insetlist.erase(&insetlist[index])
1894 // so index shouldn't be increased.
1903 LyXParagraph::inset_iterator LyXParagraph::InsetIterator(LyXParagraph::size_type pos)
1905 InsetList::iterator it = lower_bound(insetlist.begin(),
1908 return inset_iterator(it);
1912 // returns -1 if inset not found
1913 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1916 // We could use lower_bound here too, we just need to add
1917 // the approp. operator() to matchIT (and change the name
1918 // of that struct). Code would then be:
1919 // InsetList::const_iterator cit = lower_bound(insetlist.begin(),
1921 // inset, matchIT());
1922 // if ((*cit).inset == inset) {
1923 // return (*cit).pos;
1925 for (InsetList::const_iterator cit = insetlist.begin();
1926 cit != insetlist.end(); ++cit) {
1927 if ((*cit).inset == inset) {
1931 // Think about footnotes.
1932 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1933 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1935 NextAfterFootnote()->GetPositionOfInset(inset);
1937 return text.size() + 1 + further;
1943 LyXParagraph * LyXParagraph::TeXOnePar(Buffer const * buf,
1944 BufferParams const & bparams,
1945 ostream & os, TexRow & texrow,
1948 TexRow & foot_texrow,
1951 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1952 LyXLayout const & style =
1953 textclasslist.Style(bparams.textclass,
1956 bool further_blank_line = false;
1958 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1960 if (start_of_appendix) {
1961 os << "\\appendix\n";
1965 if (!spacing.isDefault()
1966 && (!Previous() || !Previous()->HasSameLayout(this))) {
1967 os << spacing.writeEnvirBegin() << "\n";
1971 if (tex_code_break_column && style.isCommand()){
1976 if (pagebreak_top) {
1978 further_blank_line = true;
1980 if (added_space_top.kind() != VSpace::NONE) {
1981 os << added_space_top.asLatexCommand(bparams);
1982 further_blank_line = true;
1986 os << "\\lyxline{\\" << getFont(bparams, 0).latexSize() << '}'
1987 << "\\vspace{-1\\parskip}";
1988 further_blank_line = true;
1991 if (further_blank_line){
1996 Language const * language = getParLanguage(bparams);
1997 Language const * doc_language = bparams.language_info;
1998 if (language != doc_language &&
1999 (!previous || previous->getParLanguage(bparams) != language)) {
2000 os << subst(lyxrc.language_command_begin, "$$lang",
2006 switch (style.latextype) {
2009 << style.latexname()
2010 << style.latexparam();
2012 case LATEX_ITEM_ENVIRONMENT:
2014 bibkey->Latex(buf, os, false, false);
2018 case LATEX_LIST_ENVIRONMENT:
2025 bool need_par = SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2027 // Spit out footnotes
2028 LyXParagraph * par = next;
2029 if (lyxrc.rtl_support) {
2030 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2031 && next->footnoteflag != footnoteflag) {
2032 LyXParagraph * p = 0;
2033 bool is_rtl = (size() > 0)
2034 ? GetFontSettings(bparams,
2035 size()-1).isRightToLeft()
2036 : language->RightToLeft();
2037 if ( (p = NextAfterFootnote()) != 0 &&
2039 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2040 is_rtl = getParLanguage(bparams)->RightToLeft();
2041 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2042 && par->footnoteflag != footnoteflag) {
2043 par = par->TeXFootnote(buf, bparams,
2045 foot_texrow, foot_count,
2047 par->SimpleTeXOnePar(buf, bparams,
2048 os, texrow, moving_arg);
2049 is_rtl = (par->size() > 0)
2050 ? par->GetFontSettings(bparams,
2051 par->size()-1).isRightToLeft()
2052 : language->RightToLeft();
2054 par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2055 (p = par->NextAfterFootnote()) != 0 &&
2057 p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2058 is_rtl = language->RightToLeft();
2063 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2064 && par->footnoteflag != footnoteflag) {
2065 par = par->TeXFootnote(buf, bparams,
2067 foot, foot_texrow, foot_count,
2069 par->SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2074 // Make sure that \\par is done with the font of the last
2075 // character if this has another size as the default.
2076 // This is necessary because LaTeX (and LyX on the screen)
2077 // calculates the space between the baselines according
2078 // to this font. (Matthias)
2079 LyXFont font = getFont(bparams, Last() - 1);
2081 if (style.resfont.size() != font.size()) {
2087 } else if (textclasslist.Style(bparams.textclass,
2088 GetLayout()).isCommand()) {
2089 if (style.resfont.size() != font.size()) {
2095 } else if (style.resfont.size() != font.size()){
2096 os << "{\\" << font.latexSize() << " \\par}";
2099 if (language != doc_language &&
2101 || (footnoteflag != NO_FOOTNOTE && par->footnoteflag != footnoteflag)
2102 || par->getParLanguage(bparams) != language)) {
2104 << subst(lyxrc.language_command_end, "$$lang",
2105 doc_language->lang());
2108 switch (style.latextype) {
2109 case LATEX_ITEM_ENVIRONMENT:
2110 case LATEX_LIST_ENVIRONMENT:
2111 if (par && (depth < par->depth)) {
2116 case LATEX_ENVIRONMENT:
2117 // if its the last paragraph of the current environment
2118 // skip it otherwise fall through
2120 && (par->layout != layout
2121 || par->depth != depth
2122 || par->pextra_type != pextra_type))
2125 // we don't need it for the last paragraph!!!
2126 if (next && !(footnoteflag != LyXParagraph::NO_FOOTNOTE
2127 && footnotekind != LyXParagraph::FOOTNOTE
2128 && footnotekind != LyXParagraph::MARGIN
2132 // don't insert this if we would be adding it
2133 // before or after a table in a float. This
2134 // little trick is needed in order to allow
2135 // use of tables in \subfigures or \subtables.
2141 further_blank_line = false;
2143 os << "\\lyxline{\\" << getFont(bparams, Last() - 1).latexSize() << '}';
2144 further_blank_line = true;
2147 if (added_space_bottom.kind() != VSpace::NONE) {
2148 os << added_space_bottom.asLatexCommand(bparams);
2149 further_blank_line = true;
2152 if (pagebreak_bottom) {
2154 further_blank_line = true;
2157 if (further_blank_line){
2162 if (!spacing.isDefault()
2163 && (!par || !par->HasSameLayout(this))) {
2164 os << spacing.writeEnvirEnd() << "\n";
2168 // we don't need it for the last paragraph!!!
2169 if (next && !(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2170 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2175 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2180 // This one spits out the text of the paragraph
2181 bool LyXParagraph::SimpleTeXOnePar(Buffer const * buf,
2182 BufferParams const & bparams,
2183 ostream & os, TexRow & texrow,
2186 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2190 return SimpleTeXOneTablePar(buf, bparams, os, texrow);
2193 bool return_value = false;
2195 LyXLayout const & style =
2196 textclasslist.Style(bparams.textclass,
2198 LyXFont basefont, last_font;
2200 // Maybe we have to create a optional argument.
2201 size_type main_body;
2202 if (style.labeltype != LABEL_MANUAL)
2205 main_body = BeginningOfMainBody();
2207 if (main_body > 0) {
2209 basefont = getFont(bparams, -2); // Get label font
2211 basefont = getFont(bparams, -1); // Get layout font
2219 if (style.isCommand()) {
2222 } else if (align != LYX_ALIGN_LAYOUT) {
2225 return_value = true;
2229 moving_arg |= style.needprotect;
2231 // Which font is currently active?
2232 LyXFont running_font(basefont);
2233 // Do we have an open font change?
2234 bool open_font = false;
2236 texrow.start(this, 0);
2238 for (size_type i = 0; i < size(); ++i) {
2240 // First char in paragraph or after label?
2241 if (i == main_body && !IsDummy()) {
2242 if (main_body > 0) {
2244 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2247 basefont = getFont(bparams, -1); // Now use the layout font
2248 running_font = basefont;
2252 if (style.isCommand()) {
2255 } else if (align != LYX_ALIGN_LAYOUT) {
2258 return_value = true;
2262 os << "\\noindent ";
2266 case LYX_ALIGN_NONE:
2267 case LYX_ALIGN_BLOCK:
2268 case LYX_ALIGN_LAYOUT:
2269 case LYX_ALIGN_SPECIAL:
2271 case LYX_ALIGN_LEFT:
2272 if (getParLanguage(bparams)->lang() != "hebrew") {
2273 os << "\\raggedright ";
2276 os << "\\raggedleft ";
2280 case LYX_ALIGN_RIGHT:
2281 if (getParLanguage(bparams)->lang() != "hebrew") {
2282 os << "\\raggedleft ";
2285 os << "\\raggedright ";
2289 case LYX_ALIGN_CENTER:
2290 os << "\\centering ";
2298 // Fully instantiated font
2299 LyXFont font = getFont(bparams, i);
2300 LyXParagraph * p = 0;
2301 if (i == 0 && previous &&
2302 previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2303 (p = PreviousBeforeFootnote()) != 0)
2304 last_font = p->getFont(bparams, p->size()-1);
2306 last_font = running_font;
2308 // Spaces at end of font change are simulated to be
2309 // outside font change, i.e. we write "\textXX{text} "
2310 // rather than "\textXX{text }". (Asger)
2311 if (open_font && c == ' ' && i <= size() - 2
2312 && !getFont(bparams, i + 1).equalExceptLatex(running_font)
2313 && !getFont(bparams, i + 1).equalExceptLatex(font)) {
2314 font = getFont(bparams, i + 1);
2316 // We end font definition before blanks
2317 if (!font.equalExceptLatex(running_font) && open_font) {
2318 column += running_font.latexWriteEndChanges(os,
2320 (i == main_body-1) ? basefont : font);
2321 running_font = basefont;
2325 // Blanks are printed before start of fontswitch
2327 // Do not print the separation of the optional argument
2328 if (i != main_body - 1) {
2329 SimpleTeXBlanks(os, texrow, i,
2330 column, font, style);
2334 // Do we need to change font?
2335 if (!font.equalExceptLatex(running_font)
2336 && i != main_body-1) {
2337 column += font.latexWriteStartChanges(os, basefont,
2339 running_font = font;
2343 if (c == LyXParagraph::META_NEWLINE) {
2344 // newlines are handled differently here than
2345 // the default in SimpleTeXSpecialChars().
2346 if (!style.newline_allowed
2347 || font.latex() == LyXFont::ON) {
2351 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2354 basefont = getFont(bparams, -1);
2355 running_font = basefont;
2356 if (font.family() ==
2357 LyXFont::TYPEWRITER_FAMILY) {
2365 texrow.start(this, i + 1);
2368 SimpleTeXSpecialChars(buf, bparams,
2369 os, texrow, moving_arg,
2370 font, running_font, basefont,
2371 open_font, style, i, column, c);
2375 // If we have an open font definition, we have to close it
2377 LyXParagraph * p = 0;
2378 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2379 && (p = NextAfterFootnote()) != 0)
2380 running_font.latexWriteEndChanges(os, basefont,
2381 p->getFont(bparams, 0));
2383 running_font.latexWriteEndChanges(os, basefont, basefont);
2386 // Needed if there is an optional argument but no contents.
2387 if (main_body > 0 && main_body == size()) {
2389 return_value = false;
2392 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2393 return return_value;
2397 // This one spits out the text of a table paragraph
2398 bool LyXParagraph::SimpleTeXOneTablePar(Buffer const * buf,
2399 BufferParams const & bparams,
2400 ostream & os, TexRow & texrow)
2402 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2404 bool return_value = false;
2406 LyXLayout const & style =
2407 textclasslist.Style(bparams.textclass, GetLayout());
2410 if (!IsDummy()) { // it is dummy if it is in a float!!!
2411 if (style.isCommand()) {
2414 } else if (align != LYX_ALIGN_LAYOUT) {
2417 return_value = true;
2420 os << "\\noindent ";
2424 case LYX_ALIGN_NONE:
2425 case LYX_ALIGN_BLOCK:
2426 case LYX_ALIGN_LAYOUT:
2427 case LYX_ALIGN_SPECIAL: break;
2428 case LYX_ALIGN_LEFT:
2429 os << "\\raggedright ";
2432 case LYX_ALIGN_RIGHT:
2433 os << "\\raggedleft ";
2436 case LYX_ALIGN_CENTER:
2437 os << "\\centering ";
2443 LyXFont basefont = getFont(bparams, -1); // Get layout font
2444 // Which font is currently active?
2445 LyXFont running_font = basefont;
2447 // Do we have an open font change?
2448 bool open_font = false;
2449 int current_cell_number = -1;
2450 int tmp = table->TexEndOfCell(os, current_cell_number);
2451 for (; tmp > 0 ; --tmp)
2454 texrow.start(this, 0);
2456 bool is_rtl = getParLanguage(bparams)->RightToLeft();
2457 bool first_in_cell = true;
2459 for (size_type i = 0; i < size(); ++i) {
2460 char c = GetChar(i);
2461 if (table->IsContRow(current_cell_number + 1)) {
2462 if (c == LyXParagraph::META_NEWLINE)
2463 ++current_cell_number;
2468 if (first_in_cell && is_rtl) {
2471 first_in_cell = false;
2474 // Fully instantiated font
2475 LyXFont font = getFont(bparams, i);
2476 last_font = running_font;
2478 // Spaces at end of font change are simulated to be
2479 // outside font change.
2480 // i.e. we write "\textXX{text} " rather than
2481 // "\textXX{text }". (Asger)
2482 if (open_font && c == ' ' && i <= size() - 2
2483 && getFont(bparams, i + 1) != running_font
2484 && getFont(bparams, i + 1) != font) {
2485 font = getFont(bparams, i + 1);
2488 // We end font definition before blanks
2489 if (font != running_font && open_font) {
2490 column += running_font.latexWriteEndChanges(os,
2493 running_font = basefont;
2496 // Blanks are printed before start of fontswitch
2498 SimpleTeXBlanks(os, texrow, i, column, font, style);
2500 // Do we need to change font?
2501 if (font != running_font) {
2502 column += font.latexWriteStartChanges(os, basefont,
2504 running_font = font;
2507 // Do we need to turn on LaTeX mode?
2508 if (font.latex() != running_font.latex()) {
2509 if (font.latex() == LyXFont::ON
2510 && style.needprotect) {
2515 if (c == LyXParagraph::META_NEWLINE) {
2516 // special case for inside a table
2517 // different from default case in
2518 // SimpleTeXSpecialChars()
2520 column += running_font
2521 .latexWriteEndChanges(os, basefont,
2525 basefont = getFont(bparams, -1);
2526 running_font = basefont;
2527 ++current_cell_number;
2528 if (table->CellHasContRow(current_cell_number) >= 0) {
2529 TeXContTableRows(buf, bparams, os, i + 1,
2530 current_cell_number,
2533 if (is_rtl && !first_in_cell) {
2535 first_in_cell = true;
2538 // if this cell follow only ContRows till end don't
2539 // put the EndOfCell because it is put after the
2541 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2542 --current_cell_number;
2545 int tmp = table->TexEndOfCell(os,
2546 current_cell_number);
2549 } else if (tmp < 0) {
2555 texrow.start(this, i + 1);
2557 SimpleTeXSpecialChars(buf, bparams,
2559 font, running_font, basefont,
2560 open_font, style, i, column, c);
2564 // If we have an open font definition, we have to close it
2566 running_font.latexWriteEndChanges(os, basefont, basefont);
2568 ++current_cell_number;
2569 if (is_rtl && !first_in_cell)
2571 tmp = table->TexEndOfCell(os, current_cell_number);
2572 for (; tmp > 0; --tmp)
2574 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2575 return return_value;
2579 // This one spits out the text off ContRows in tables
2580 bool LyXParagraph::TeXContTableRows(Buffer const * buf,
2581 BufferParams const & bparams,
2583 LyXParagraph::size_type i,
2584 int current_cell_number,
2585 int & column, TexRow & texrow)
2587 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2591 bool return_value = false;
2592 LyXLayout const & style =
2593 textclasslist.Style(bparams.textclass,
2595 LyXFont basefont = getFont(bparams, -1); // Get layout font
2597 // Which font is currently active?
2598 LyXFont running_font = basefont;
2599 // Do we have an open font change?
2600 bool open_font = false;
2602 size_type lastpos = i;
2603 int cell = table->CellHasContRow(current_cell_number);
2604 ++current_cell_number;
2607 // first find the right position
2609 for (; (i < size()) && (current_cell_number<cell); ++i) {
2611 if (c == LyXParagraph::META_NEWLINE)
2612 ++current_cell_number;
2616 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2620 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2625 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2629 // Fully instantiated font
2630 LyXFont font = getFont(bparams, i);
2631 last_font = running_font;
2633 // Spaces at end of font change are simulated to
2634 // be outside font change. i.e. we write
2635 // "\textXX{text} " rather than "\textXX{text }".
2637 if (open_font && c == ' ' && i <= size() - 2
2638 && getFont(bparams, i + 1) != running_font
2639 && getFont(bparams, i + 1) != font) {
2640 font = getFont(bparams, i + 1);
2643 // We end font definition before blanks
2644 if (font != running_font && open_font) {
2645 column += running_font.latexWriteEndChanges(os, basefont, font);
2646 running_font = basefont;
2649 // Blanks are printed before start of fontswitch
2651 SimpleTeXBlanks(os, texrow, i,
2652 column, font, style);
2654 // Do we need to change font?
2655 if (font != running_font) {
2657 font.latexWriteStartChanges(os,
2660 running_font = font;
2663 // Do we need to turn on LaTeX mode?
2664 if (font.latex() != running_font.latex()) {
2665 if (font.latex() == LyXFont::ON
2666 && style.needprotect) {
2671 SimpleTeXSpecialChars(buf, bparams,
2672 os, texrow, false, font,
2673 running_font, basefont,
2674 open_font, style, i, column, c);
2676 // If we have an open font definition, we have to close it
2678 running_font.latexWriteEndChanges(os, basefont,
2682 basefont = getFont(bparams, -1);
2683 running_font = basefont;
2684 cell = table->CellHasContRow(current_cell_number);
2686 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2687 return return_value;
2691 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2693 bool retval = false;
2695 case LyXParagraph::META_HFILL:
2696 sgml_string.erase();
2698 case LyXParagraph::META_NEWLINE:
2702 sgml_string = "&";
2705 sgml_string = "<";
2708 sgml_string = ">";
2711 sgml_string = "$";
2714 sgml_string = "#";
2717 sgml_string = "%";
2720 sgml_string = "[";
2723 sgml_string = "]";
2726 sgml_string = "{";
2729 sgml_string = "}";
2732 sgml_string = "˜";
2735 sgml_string = """;
2738 sgml_string = "\";
2744 case '\0': // Ignore :-)
2745 sgml_string.erase();
2755 void LyXParagraph::SimpleDocBookOneTablePar(Buffer const * buffer,
2756 ostream & os, string & extra,
2757 int & desc_on, int depth)
2759 BufferParams const & bparams = buffer->params;
2761 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2763 LyXFont font1, font2;
2766 size_type main_body;
2767 bool emph_flag = false;
2769 LyXLayout const & style =
2770 textclasslist.Style(bparams.textclass,
2773 if (style.labeltype != LABEL_MANUAL)
2776 main_body = BeginningOfMainBody();
2778 // Gets paragraph main font.
2780 font1 = style.labelfont;
2784 int char_line_count = depth;
2785 os << newlineAndDepth(depth);
2786 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2787 os << "<INFORMALTABLE>"
2788 << newlineAndDepth(++depth);
2790 int current_cell_number = -1;
2791 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2793 // Parsing main loop.
2794 for (size_type i = 0; i < size(); ++i) {
2796 if (table->IsContRow(current_cell_number+1)) {
2797 if (c == LyXParagraph::META_NEWLINE)
2798 ++current_cell_number;
2803 // Fully instantiated font
2804 font2 = getFont(bparams, i);
2806 // Handle <emphasis> tag.
2807 if (font1.emph() != font2.emph() && i) {
2808 if (font2.emph() == LyXFont::ON) {
2811 } else if (emph_flag) {
2812 os << "</emphasis>";
2816 if (c == LyXParagraph::META_NEWLINE) {
2817 // We have only to control for emphasis open here!
2819 os << "</emphasis>";
2822 font1 = font2 = getFont(bparams, -1);
2823 ++current_cell_number;
2824 if (table->CellHasContRow(current_cell_number) >= 0) {
2825 DocBookContTableRows(buffer,
2826 os, extra, desc_on, i + 1,
2827 current_cell_number,
2830 // if this cell follow only ContRows till end don't
2831 // put the EndOfCell because it is put after the
2833 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2834 --current_cell_number;
2837 tmp = table->DocBookEndOfCell(os,
2838 current_cell_number,
2843 } else if (c == LyXParagraph::META_INSET) {
2844 inset = GetInset(i);
2846 std::ostringstream ost;
2847 inset->DocBook(buffer, ost);
2848 string tmp_out = ost.str().c_str();
2851 inset->DocBook(buffer, ost);
2853 char * ctmp = ost.str();
2854 string tmp_out(ctmp);
2858 // This code needs some explanation:
2859 // Two insets are treated specially
2860 // label if it is the first element in a
2861 // command paragraph
2863 // graphics inside tables or figure floats
2865 // title (the equivalente in latex for this
2867 // and title should come first
2870 if(desc_on != 3 || i != 0) {
2871 if(tmp_out[0] == '@') {
2873 extra += frontStrip(tmp_out,
2876 os << frontStrip(tmp_out,
2881 } else if (font2.latex() == LyXFont::ON) {
2882 // "TeX"-Mode on == > SGML-Mode on.
2888 if (linuxDocConvertChar(c, sgml_string)
2889 && !style.free_spacing) {
2890 // in freespacing mode, spaces are
2891 // non-breaking characters
2896 << "</term><listitem><para>";
2908 // Needed if there is an optional argument but no contents.
2909 if (main_body > 0 && main_body == size()) {
2914 os << "</emphasis>";
2917 ++current_cell_number;
2918 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2919 // Resets description flag correctly.
2922 // <term> not closed...
2926 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2927 os << "</INFORMALTABLE>";
2929 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2934 void LyXParagraph::DocBookContTableRows(Buffer const * buffer,
2935 ostream & os, string & extra,
2937 LyXParagraph::size_type i,
2938 int current_cell_number, int &column)
2943 BufferParams const & bparams = buffer->params;
2945 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2950 //string emph = "emphasis";
2951 bool emph_flag = false;
2952 int char_line_count = 0;
2954 LyXLayout const & style =
2955 textclasslist.Style(bparams.textclass,
2958 size_type main_body;
2959 if (style.labeltype != LABEL_MANUAL)
2962 main_body = BeginningOfMainBody();
2964 // Gets paragraph main font.
2967 font1 = style.labelfont;
2971 size_type lastpos = i;
2972 int cell = table->CellHasContRow(current_cell_number);
2973 ++current_cell_number;
2975 // first find the right position
2977 for (; i < size() && current_cell_number < cell; ++i) {
2979 if (c == LyXParagraph::META_NEWLINE)
2980 ++current_cell_number;
2984 // I don't know how to handle this so I comment it
2985 // for the moment (Jug)
2986 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2987 // file += " \\\\\n";
2990 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2995 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2999 // Fully instantiated font
3000 font2 = getFont(bparams, i);
3002 // Handle <emphasis> tag.
3003 if (font1.emph() != font2.emph() && i) {
3004 if (font2.emph() == LyXFont::ON) {
3007 } else if (emph_flag) {
3008 os << "</emphasis>";
3012 if (c == LyXParagraph::META_INSET) {
3013 inset = GetInset(i);
3015 std::ostringstream ost;
3016 inset->DocBook(buffer, ost);
3017 string tmp_out = ost.str().c_str();
3020 inset->DocBook(buffer, ost);
3022 char * ctmp = ost.str();
3023 string tmp_out(ctmp);
3027 // This code needs some explanation:
3028 // Two insets are treated specially
3029 // label if it is the first element in a
3030 // command paragraph
3032 // graphics inside tables or figure floats
3033 // can't go on title (the equivalente in
3034 // latex for this case is caption and title
3035 // should come first
3038 if(desc_on != 3 || i != 0) {
3039 if(tmp_out[0] == '@') {
3041 extra += frontStrip(tmp_out, '@');
3043 os << frontStrip(tmp_out, '@');
3047 } else if (font2.latex() == LyXFont::ON) {
3048 // "TeX"-Mode on == > SGML-Mode on.
3054 if (linuxDocConvertChar(c, sgml_string)
3055 && !style.free_spacing) {
3056 // in freespacing mode, spaces are
3057 // non-breaking characters
3062 << "</term><listitem><para>";
3072 // we have only to control for emphasis open here!
3074 os << "</emphasis>";
3077 font1 = font2 = getFont(bparams, -1);
3078 cell = table->CellHasContRow(current_cell_number);
3080 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3084 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3085 LyXParagraph::size_type const i,
3086 int & column, LyXFont const & font,
3087 LyXLayout const & style)
3089 if (column > tex_code_break_column
3091 && GetChar(i - 1) != ' '
3093 // In LaTeX mode, we don't want to
3094 // break lines since some commands
3096 && ! (font.latex() == LyXFont::ON)
3097 // same in FreeSpacing mode
3098 && !style.free_spacing
3099 // In typewriter mode, we want to avoid
3100 // ! . ? : at the end of a line
3101 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3102 && (GetChar(i-1) == '.'
3103 || GetChar(i-1) == '?'
3104 || GetChar(i-1) == ':'
3105 || GetChar(i-1) == '!'))) {
3106 if (tex_code_break_column == 0) {
3107 // in batchmode we need LaTeX to still
3108 // see it as a space not as an extra '\n'
3114 texrow.start(this, i + 1);
3116 } else if (font.latex() == LyXFont::OFF) {
3117 if (style.free_spacing) {
3126 void LyXParagraph::SimpleTeXSpecialChars(Buffer const * buf,
3127 BufferParams const & bparams,
3128 ostream & os, TexRow & texrow,
3131 LyXFont & running_font,
3134 LyXLayout const & style,
3135 LyXParagraph::size_type & i,
3136 int & column, char const c)
3138 // Two major modes: LaTeX or plain
3139 // Handle here those cases common to both modes
3140 // and then split to handle the two modes separately.
3142 case LyXParagraph::META_INSET: {
3143 Inset * inset = GetInset(i);
3146 int len = os.tellp();
3147 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3148 || inset->LyxCode() == Inset::MATH_CODE
3149 || inset->LyxCode() == Inset::URL_CODE)
3150 && running_font.isRightToLeft()) {
3155 int tmp = inset->Latex(buf, os, moving_arg,
3156 style.free_spacing);
3164 column += os.tellp() - len;
3173 case LyXParagraph::META_NEWLINE:
3175 column += running_font.latexWriteEndChanges(os,
3180 basefont = getFont(bparams, -1);
3181 running_font = basefont;
3184 case LyXParagraph::META_HFILL:
3190 // And now for the special cases within each mode
3191 // Are we in LaTeX mode?
3192 if (font.latex() == LyXFont::ON) {
3193 // at present we only have one option
3194 // but I'll leave it as a switch statement
3195 // so its simpler to extend. (ARRae)
3198 // make sure that we will not print
3199 // error generating chars to the tex
3200 // file. This test would not be needed
3201 // if it were done in the buffer
3209 // Plain mode (i.e. not LaTeX)
3212 os << "\\textbackslash{}";
3216 case '°': case '±': case '²': case '³':
3217 case '×': case '÷': case '¹': case 'ª':
3218 case 'º': case '¬': case 'µ':
3219 if (bparams.inputenc == "latin1") {
3220 os << "\\ensuremath{"
3229 case '|': case '<': case '>':
3230 // In T1 encoding, these characters exist
3231 if (lyxrc.fontenc == "T1") {
3233 //... but we should avoid ligatures
3234 if ((c == '>' || c == '<')
3236 && GetChar(i + 1) == c){
3237 os << "\\textcompwordmark{}";
3242 // Typewriter font also has them
3243 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3247 // Otherwise, we use what LaTeX
3251 os << "\\textless{}";
3255 os << "\\textgreater{}";
3259 os << "\\textbar{}";
3265 case '-': // "--" in Typewriter mode -> "-{}-"
3267 && GetChar(i + 1) == '-'
3268 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3277 os << "\\char`\\\"{}";
3282 if (bparams.inputenc == "default") {
3291 case '%': case '#': case '{':
3298 os << "\\textasciitilde{}";
3303 os << "\\textasciicircum{}";
3307 case '*': case '[': case ']':
3308 // avoid being mistaken for optional arguments
3309 os << '{' << c << '}';
3314 // Blanks are printed before font switching.
3315 // Sure? I am not! (try nice-latex)
3316 // I am sure it's correct. LyX might be smarter
3317 // in the future, but for now, nothing wrong is
3322 /* idea for labels --- begin*/
3326 && font.family() != LyXFont::TYPEWRITER_FAMILY
3327 && GetChar(i + 1) == 'y'
3328 && GetChar(i + 2) == 'X') {
3336 && font.family() != LyXFont::TYPEWRITER_FAMILY
3337 && GetChar(i + 1) == 'e'
3338 && GetChar(i + 2) == 'X') {
3343 // Check for "LaTeX2e"
3346 && font.family() != LyXFont::TYPEWRITER_FAMILY
3347 && GetChar(i + 1) == 'a'
3348 && GetChar(i + 2) == 'T'
3349 && GetChar(i + 3) == 'e'
3350 && GetChar(i + 4) == 'X'
3351 && GetChar(i + 5) == '2'
3352 && GetChar(i + 6) == 'e') {
3357 // Check for "LaTeX"
3360 && font.family() != LyXFont::TYPEWRITER_FAMILY
3361 && GetChar(i + 1) == 'a'
3362 && GetChar(i + 2) == 'T'
3363 && GetChar(i + 3) == 'e'
3364 && GetChar(i + 4) == 'X') {
3368 /* idea for labels --- end*/
3369 } else if (c != '\0') {
3380 bool LyXParagraph::RoffContTableRows(ostream & os,
3381 LyXParagraph::size_type i,
3387 LyXFont font1(LyXFont::ALL_INHERIT);
3392 string fname2 = TmpFileName(string(), "RAT2");
3394 int cell = table->CellHasContRow(actcell);
3397 // first find the right position
3399 for (; i < size() && actcell < cell; ++i) {
3401 if (c == LyXParagraph::META_NEWLINE)
3406 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3409 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3411 font2 = GetFontSettings(i);
3412 if (font1.latex() != font2.latex()) {
3413 if (font2.latex() != LyXFont::OFF)
3418 case LyXParagraph::META_INSET:
3419 if ((inset = GetInset(i))) {
3421 stringstream ss(ios::in | ios::out);
3422 inset->Ascii(buffer, ss);
3434 inset->Ascii(buffer, ss);
3448 case LyXParagraph::META_NEWLINE:
3450 case LyXParagraph::META_HFILL:
3459 lyxerr.debug() << "RoffAsciiTable: "
3460 "NULL char in structure."
3465 cell = table->CellHasContRow(actcell);
3472 LyXParagraph * LyXParagraph::TeXDeeper(Buffer const * buf,
3473 BufferParams const & bparams,
3474 ostream & os, TexRow & texrow,
3476 TexRow & foot_texrow,
3479 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3480 LyXParagraph * par = this;
3483 (par->depth == depth) &&
3484 (par->footnoteflag == footnoteflag)) {
3486 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3487 if (textclasslist.Style(bparams.textclass,
3488 par->layout).isEnvironment()
3489 || par->pextra_type != PEXTRA_NONE) {
3490 par = par->TeXEnvironment(buf, bparams,
3495 par = par->TeXOnePar(buf, bparams,
3501 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3507 LyXParagraph * LyXParagraph::TeXEnvironment(Buffer const * buf,
3508 BufferParams const & bparams,
3509 ostream & os, TexRow & texrow,
3511 TexRow & foot_texrow,
3514 bool eindent_open = false;
3515 bool foot_this_level = false;
3516 // flags when footnotetext should be appended to file.
3517 static bool minipage_open = false;
3518 static int minipage_open_depth = 0;
3519 char par_sep = bparams.paragraph_separation;
3521 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3523 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3525 LyXLayout const & style =
3526 textclasslist.Style(bparams.textclass,
3529 if (pextra_type == PEXTRA_INDENT) {
3530 if (!pextra_width.empty()) {
3531 os << "\\begin{LyXParagraphIndent}{"
3532 << pextra_width << "}\n";
3534 //float ib = atof(pextra_widthp.c_str())/100;
3535 // string can't handle floats at present (971109)
3536 // so I'll do a conversion by hand knowing that
3537 // the limits are 0.0 to 1.0. ARRae.
3538 os << "\\begin{LyXParagraphIndent}{";
3539 switch (pextra_widthp.length()) {
3551 os << "\\columnwidth}\n";
3554 eindent_open = true;
3556 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3557 if (pextra_hfill && Previous() &&
3558 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3559 os << "\\hfill{}\n";
3562 if (par_sep == BufferParams::PARSEP_INDENT) {
3563 os << "{\\setlength\\parindent{0pt}\n";
3566 os << "\\begin{minipage}";
3567 switch(pextra_alignment) {
3568 case MINIPAGE_ALIGN_TOP:
3571 case MINIPAGE_ALIGN_MIDDLE:
3574 case MINIPAGE_ALIGN_BOTTOM:
3578 if (!pextra_width.empty()) {
3579 os << '{' << pextra_width << "}\n";
3581 //float ib = atof(par->pextra_width.c_str())/100;
3582 // string can't handle floats at present
3583 // so I'll do a conversion by hand knowing that
3584 // the limits are 0.0 to 1.0. ARRae.
3586 switch (pextra_widthp.length()) {
3598 os << "\\columnwidth}\n";
3601 if (par_sep == BufferParams::PARSEP_INDENT) {
3602 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3605 minipage_open = true;
3606 minipage_open_depth = depth;
3609 #ifdef WITH_WARNINGS
3610 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3611 //I disabled it because it breaks when lists span on several
3614 if (style.isEnvironment()){
3615 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3616 #ifdef FANCY_FOOTNOTE_CODE
3617 if (foot_count < 0) {
3618 // flag that footnote[mark][text] should be
3619 // used for any footnotes from now on
3621 foot_this_level = true;
3624 os << "\\begin{" << style.latexname() << "}{"
3625 << labelwidthstring << "}\n";
3626 } else if (style.labeltype == LABEL_BIBLIO) {
3628 os << "\\begin{" << style.latexname() << "}{"
3629 << bibitemWidest(current_view->painter())
3631 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3632 #ifdef FANCY_FOOTNOTE_CODE
3633 if (foot_count < 0) {
3634 // flag that footnote[mark][text] should be
3635 // used for any footnotes from now on
3637 foot_this_level = true;
3640 os << "\\begin{" << style.latexname() << '}'
3641 << style.latexparam() << '\n';
3643 os << "\\begin{" << style.latexname() << '}'
3644 << style.latexparam() << '\n';
3647 LyXParagraph * par = this;
3649 par = par->TeXOnePar(buf, bparams,
3651 foot, foot_texrow, foot_count);
3653 if (minipage_open && par && !style.isEnvironment() &&
3654 (par->pextra_type == PEXTRA_MINIPAGE) &&
3655 par->pextra_start_minipage) {
3656 os << "\\end{minipage}\n";
3658 if (par_sep == BufferParams::PARSEP_INDENT) {
3662 minipage_open = false;
3664 if (par && par->depth > depth) {
3665 if (textclasslist.Style(bparams.textclass,
3666 par->layout).isParagraph()
3669 // How to handle this? (Lgb)
3670 //&& !suffixIs(os, "\n\n")
3672 // There should be at least one '\n' already
3673 // but we need there to be two for Standard
3674 // paragraphs that are depth-increment'ed to be
3675 // output correctly. However, tables can
3676 // also be paragraphs so don't adjust them.
3679 // Will it ever harm to have one '\n' too
3680 // many? i.e. that we sometimes will have
3681 // three in a row. (Lgb)
3685 par = par->TeXDeeper(buf, bparams, os, texrow,
3686 foot, foot_texrow, foot_count);
3688 if (par && par->layout == layout && par->depth == depth &&
3689 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3690 if (par->pextra_hfill && par->Previous() &&
3691 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3692 os << "\\hfill{}\n";
3695 if (par_sep == BufferParams::PARSEP_INDENT) {
3696 os << "{\\setlength\\parindent{0pt}\n";
3699 os << "\\begin{minipage}";
3700 switch(par->pextra_alignment) {
3701 case MINIPAGE_ALIGN_TOP:
3704 case MINIPAGE_ALIGN_MIDDLE:
3707 case MINIPAGE_ALIGN_BOTTOM:
3711 if (!par->pextra_width.empty()) {
3712 os << '{' << par->pextra_width << "}\n";
3714 //float ib = atof(par->pextra_widthp.c_str())/100;
3715 // string can't handle floats at present
3716 // so I'll do a conversion by hand knowing that
3717 // the limits are 0.0 to 1.0. ARRae.
3719 switch (par->pextra_widthp.length()) {
3724 os << "0." << par->pextra_widthp;
3727 os << "0.0" << par->pextra_widthp;
3729 os << "\\columnwidth}\n";
3732 if (par_sep == BufferParams::PARSEP_INDENT) {
3733 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3736 minipage_open = true;
3737 minipage_open_depth = par->depth;
3740 && par->layout == layout
3741 && par->depth == depth
3742 && par->pextra_type == pextra_type
3743 && par->footnoteflag == footnoteflag);
3745 if (style.isEnvironment()) {
3746 os << "\\end{" << style.latexname() << '}';
3747 // maybe this should go after the minipage closes?
3748 if (foot_this_level) {
3749 if (foot_count >= 1) {
3750 if (foot_count > 1) {
3751 os << "\\addtocounter{footnote}{-"
3756 texrow += foot_texrow;
3758 foot_texrow.reset();
3763 if (minipage_open && (minipage_open_depth == depth) &&
3764 (!par || par->pextra_start_minipage ||
3765 par->pextra_type != PEXTRA_MINIPAGE)) {
3766 os << "\\end{minipage}\n";
3768 if (par_sep == BufferParams::PARSEP_INDENT) {
3772 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3773 os << "\\medskip\n\n";
3777 minipage_open = false;
3780 os << "\\end{LyXParagraphIndent}\n";
3783 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3784 && par->pextra_hfill)) {
3788 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3789 return par; // ale970302
3793 LyXParagraph * LyXParagraph::TeXFootnote(Buffer const * buf,
3794 BufferParams const & bparams,
3795 ostream & os, TexRow & texrow,
3796 ostream & foot, TexRow & foot_texrow,
3800 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3801 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3802 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3803 "No footnote!" << endl;
3805 LyXParagraph * par = this;
3806 LyXLayout const & style =
3807 textclasslist.Style(bparams.textclass,
3808 previous->GetLayout());
3810 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3811 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3812 "Float other than footnote in command"
3813 " with moving argument is illegal" << endl;
3816 if (footnotekind != LyXParagraph::FOOTNOTE
3817 && footnotekind != LyXParagraph::MARGIN
3820 // How to solve this?
3821 //&& !suffixIs(file, '\n')
3823 // we need to ensure that real floats like tables and figures
3824 // have their \begin{} on a new line otherwise we can get
3825 // incorrect results when using the endfloat.sty package
3826 // especially if two floats follow one another. ARRae 981022
3827 // NOTE: if the file is length 0 it must have just been
3828 // written out so we assume it ended with a '\n'
3830 // As far as I can see there is never any harm in writing
3831 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3836 bool moving_arg = false;
3837 bool need_closing = false;
3838 bool is_rtl = isRightToLeftPar(bparams);
3840 if (is_rtl != parent_is_rtl) {
3845 need_closing = true;
3848 //BufferParams * params = ¤t_view->buffer()->params;
3849 bool footer_in_body = true;
3850 switch (footnotekind) {
3851 case LyXParagraph::FOOTNOTE:
3852 if (style.intitle) {
3853 os << "\\thanks{\n";
3854 footer_in_body = false;
3857 if (foot_count == -1) {
3858 // we're at depth 0 so we can use:
3859 os << "\\footnote{%\n";
3860 footer_in_body = false;
3862 os << "\\footnotemark{}%\n";
3864 // we only need this when there are
3865 // multiple footnotes
3866 os << "\\stepcounter{footnote}";
3868 os << "\\footnotetext{%\n";
3869 foot_texrow.start(this, 0);
3870 foot_texrow.newline();
3875 case LyXParagraph::MARGIN:
3876 os << "\\marginpar{\n";
3878 case LyXParagraph::FIG:
3879 if (pextra_type == PEXTRA_FLOATFLT
3880 && (!pextra_width.empty()
3881 || !pextra_widthp.empty())) {
3882 if (!pextra_width.empty())
3883 os << "\\begin{floatingfigure}{"
3884 << pextra_width << "}\n";
3886 os << "\\begin{floatingfigure}{"
3887 << atoi(pextra_widthp.c_str())/100.0
3888 << "\\textwidth}\n";
3890 os << "\\begin{figure}";
3891 if (!bparams.float_placement.empty()) {
3892 os << '[' << bparams.float_placement << "]\n";
3898 case LyXParagraph::TAB:
3899 os << "\\begin{table}";
3900 if (!bparams.float_placement.empty()) {
3901 os << '[' << bparams.float_placement << "]\n";
3906 case LyXParagraph::WIDE_FIG:
3907 os << "\\begin{figure*}";
3908 if (!bparams.float_placement.empty()) {
3909 os << '[' << bparams.float_placement << "]\n";
3914 case LyXParagraph::WIDE_TAB:
3915 os << "\\begin{table*}";
3916 if (!bparams.float_placement.empty()) {
3917 os << '[' << bparams.float_placement << "]\n";
3922 case LyXParagraph::ALGORITHM:
3923 os << "\\begin{algorithm}\n";
3928 if (footnotekind != LyXParagraph::FOOTNOTE
3929 || !footer_in_body) {
3930 // Process text for all floats except footnotes in body
3932 LyXLayout const & style =
3934 .Style(bparams.textclass, par->layout);
3936 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3938 if (style.isEnvironment()
3939 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3940 // Allows the use of minipages within float
3941 // environments. Shouldn't be circular because
3942 // we don't support footnotes inside
3943 // floats (yet). ARRae
3944 par = par->TeXEnvironment(buf, bparams, os,
3949 par = par->TeXOnePar(buf, bparams,
3950 os, texrow, moving_arg,
3955 if (par && !par->IsDummy() && par->depth > depth) {
3956 par = par->TeXDeeper(buf, bparams, os, texrow,
3960 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3962 // process footnotes > depth 0 or in environments separately
3963 // NOTE: Currently don't support footnotes within footnotes
3964 // even though that is possible using the \footnotemark
3966 std::ostringstream dummy;
3970 TexRow dummy_texrow;
3971 int dummy_count = 0;
3973 LyXLayout const & style =
3975 .Style(bparams.textclass, par->layout);
3977 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3979 if (style.isEnvironment()
3980 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3981 // Allows the use of minipages within float
3982 // environments. Shouldn't be circular because
3983 // we don't support footnotes inside
3984 // floats (yet). ARRae
3985 par = par->TeXEnvironment(buf, bparams,
3987 dummy, dummy_texrow,
3990 par = par->TeXOnePar(buf, bparams,
3993 dummy, dummy_texrow,
3997 if (par && !par->IsDummy() && par->depth > depth) {
3998 par = par->TeXDeeper(buf, bparams,
4000 dummy, dummy_texrow,
4004 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4006 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4007 "Footnote in a Footnote -- not supported"
4010 #ifndef HAVE_OSTREAM
4011 delete [] dummy.str();
4015 switch (footnotekind) {
4016 case LyXParagraph::FOOTNOTE:
4017 if (footer_in_body) {
4018 // This helps tell which of the multiple
4019 // footnotetexts an error was in.
4021 foot_texrow.newline();
4026 case LyXParagraph::MARGIN:
4029 case LyXParagraph::FIG:
4030 if (pextra_type == PEXTRA_FLOATFLT
4031 && (!pextra_width.empty()
4032 || !pextra_widthp.empty()))
4033 os << "\\end{floatingfigure}";
4035 os << "\\end{figure}";
4037 case LyXParagraph::TAB:
4038 os << "\\end{table}";
4040 case LyXParagraph::WIDE_FIG:
4041 os << "\\end{figure*}";
4043 case LyXParagraph::WIDE_TAB:
4044 os << "\\end{table*}";
4046 case LyXParagraph::ALGORITHM:
4047 os << "\\end{algorithm}";
4054 if (footnotekind != LyXParagraph::FOOTNOTE
4055 && footnotekind != LyXParagraph::MARGIN) {
4056 // we need to ensure that real floats like tables and figures
4057 // have their \end{} on a line of their own otherwise we can
4058 // get incorrect results when using the endfloat.sty package.
4063 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4068 bool LyXParagraph::IsDummy() const
4070 return (footnoteflag == LyXParagraph::NO_FOOTNOTE && previous
4071 && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4075 void LyXParagraph::SetPExtraType(BufferParams const & bparams,
4076 int type, char const * width,
4077 char const * widthp)
4080 pextra_width = width;
4081 pextra_widthp = widthp;
4083 if (textclasslist.Style(bparams.textclass,
4084 layout).isEnvironment()) {
4089 while (par && (par->layout == layout)
4090 && (par->depth == depth)) {
4092 par = par->Previous();
4094 par = par->FirstPhysicalPar();
4095 while (par && par->depth > depth) {
4096 par = par->Previous();
4098 par = par->FirstPhysicalPar();
4102 while (par && (par->layout == layout)
4103 && (par->depth == depth)) {
4104 par->pextra_type = type;
4105 par->pextra_width = width;
4106 par->pextra_widthp = widthp;
4107 par = par->NextAfterFootnote();
4108 if (par && (par->depth > depth))
4109 par->SetPExtraType(bparams,
4110 type, width, widthp);
4111 while (par && ((par->depth > depth) || par->IsDummy()))
4112 par = par->NextAfterFootnote();
4118 void LyXParagraph::UnsetPExtraType(BufferParams const & bparams)
4120 if (pextra_type == PEXTRA_NONE)
4123 pextra_type = PEXTRA_NONE;
4124 pextra_width.erase();
4125 pextra_widthp.erase();
4127 if (textclasslist.Style(bparams.textclass,
4128 layout).isEnvironment()) {
4133 while (par && (par->layout == layout)
4134 && (par->depth == depth)) {
4136 par = par->Previous();
4138 par = par->FirstPhysicalPar();
4139 while (par && par->depth > depth) {
4140 par = par->Previous();
4142 par = par->FirstPhysicalPar();
4146 while (par && (par->layout == layout)
4147 && (par->depth == depth)) {
4148 par->pextra_type = PEXTRA_NONE;
4149 par->pextra_width.erase();
4150 par->pextra_widthp.erase();
4151 par = par->NextAfterFootnote();
4152 if (par && (par->depth > depth))
4153 par->UnsetPExtraType(bparams);
4154 while (par && ((par->depth > depth) || par->IsDummy()))
4155 par = par->NextAfterFootnote();
4161 bool LyXParagraph::IsHfill(size_type pos) const
4163 return IsHfillChar(GetChar(pos));
4167 bool LyXParagraph::IsInset(size_type pos) const
4169 return IsInsetChar(GetChar(pos));
4173 bool LyXParagraph::IsFloat(size_type pos) const
4175 return IsFloatChar(GetChar(pos));
4179 bool LyXParagraph::IsNewline(size_type pos) const
4181 return pos >= 0 && IsNewlineChar(GetChar(pos));
4185 bool LyXParagraph::IsSeparator(size_type pos) const
4187 return IsSeparatorChar(GetChar(pos));
4191 bool LyXParagraph::IsLineSeparator(size_type pos) const
4193 return IsLineSeparatorChar(GetChar(pos));
4197 bool LyXParagraph::IsKomma(size_type pos) const
4199 return IsKommaChar(GetChar(pos));
4203 /// Used by the spellchecker
4204 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4206 unsigned char c = GetChar(pos);
4207 if (IsLetterChar(c))
4209 // '\0' is not a letter, allthough every string contains "" (below)
4212 // We want to pass the ' and escape chars to ispell
4213 string extra = lyxrc.isp_esc_chars + '\'';
4217 return contains(extra, ch);
4221 bool LyXParagraph::IsWord(size_type pos ) const
4223 return IsWordChar(GetChar(pos)) ;
4228 LyXParagraph::getParLanguage(BufferParams const & bparams) const
4231 return FirstPhysicalPar()->getParLanguage(bparams);
4232 else if (size() > 0)
4236 return GetFirstFontSettings().language();
4239 for (size_type pos = 0; pos < size(); ++pos)
4241 return GetFontSettings(bparams, pos).language();
4242 return GetFirstFontSettings().language();
4246 return previous->getParLanguage(bparams);
4248 return bparams.language_info;
4252 bool LyXParagraph::isRightToLeftPar(BufferParams const & bparams) const
4254 return lyxrc.rtl_support && !table
4255 && getParLanguage(bparams)->RightToLeft();
4259 void LyXParagraph::ChangeLanguage(BufferParams const & bparams,
4260 Language const * from, Language const * to)
4262 for(size_type i = 0; i < size(); ++i) {
4263 LyXFont font = GetFontSettings(bparams, i);
4264 if (font.language() == from) {
4265 font.setLanguage(to);
4272 bool LyXParagraph::isMultiLingual(BufferParams const & bparams)
4274 Language const * doc_language =
4275 bparams.language_info;
4276 for(size_type i = 0; i < size(); ++i) {
4277 LyXFont font = GetFontSettings(bparams, i);
4278 if (font.language() != doc_language)
4285 // Convert the paragraph to a string.
4286 // Used for building the table of contents
4287 string LyXParagraph::String(Buffer const * buffer, bool label)
4289 BufferParams const & bparams = buffer->params;
4291 if (label && !IsDummy() && !labelstring.empty())
4292 s += labelstring + ' ';
4293 string::size_type len = s.size();
4295 for (LyXParagraph::size_type i = 0; i < size(); ++i) {
4296 unsigned char c = GetChar(i);
4299 else if (c == META_INSET &&
4300 GetInset(i)->LyxCode() == Inset::MATH_CODE) {
4302 std::ostringstream ost;
4303 GetInset(i)->Ascii(buffer, ost);
4306 GetInset(i)->Ascii(buffer, ost);
4309 s += subst(ost.str(),'\n',' ');
4313 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
4314 && footnoteflag == LyXParagraph::NO_FOOTNOTE)
4315 s += NextAfterFootnote()->String(buffer, false);
4318 if (isRightToLeftPar(bparams))
4319 reverse(s.begin() + len,s.end());
4325 string LyXParagraph::String(Buffer const * buffer,
4326 LyXParagraph::size_type beg,
4327 LyXParagraph::size_type end)
4334 for (LyXParagraph::size_type i = 0; i < beg; ++i)
4336 if (cell >= table->NumberOfCellsInRow(actcell))
4344 if (beg == 0 && !IsDummy() && !labelstring.empty())
4345 s += labelstring + ' ';
4347 for (LyXParagraph::size_type i = beg; i < end; ++i) {
4348 unsigned char c = GetChar(i);
4351 else if (c == META_INSET) {
4353 std::ostringstream ost;
4354 GetInset(i)->Ascii(buffer, ost);
4357 GetInset(i)->Ascii(buffer, ost);
4361 } else if (table && IsNewlineChar(c)) {
4362 if (cell >= table->NumberOfCellsInRow(actcell)) {
4373 //if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
4374 // s += NextAfterFootnote()->String(false);
4380 void LyXParagraph::SetInsetOwner(Inset *i)
4383 for (InsetList::const_iterator cit = insetlist.begin();
4384 cit != insetlist.end(); ++cit) {
4386 (*cit).inset->setOwner(i);
4391 void LyXParagraph::deleteInsetsLyXText(BufferView * bv)
4394 for (InsetList::const_iterator cit = insetlist.begin();
4395 cit != insetlist.end(); ++cit) {
4397 if ((*cit).inset->IsTextInset()) {
4398 static_cast<InsetText *>((*cit).inset)->