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"
42 int tex_code_break_column = 72; // needs non-zero initialization. set later.
43 // this is a bad idea, but how can LyXParagraph find its buffer to get
44 // parameters? (JMarc)
45 extern BufferView * current_view;
49 extern string bibitemWidthest(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;
77 /* table stuff -- begin*/
79 /* table stuff -- end*/
81 bibkey = 0; // ale970302
86 // This konstruktor inserts the new paragraph in a list.
87 LyXParagraph::LyXParagraph(LyXParagraph * par)
90 par->text.resize(par->text.size());
92 for (int i = 0; i < 10; ++i) setCounter(i, 0);
96 // double linked list begin
99 next->previous = this;
101 previous->next = this;
103 footnoteflag = LyXParagraph::NO_FOOTNOTE;
104 footnotekind = LyXParagraph::FOOTNOTE;
106 /* table stuff -- begin*/
108 /* table stuff -- end*/
109 id_ = paragraph_id++;
111 bibkey = 0; // ale970302
117 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
118 char footflag, char dth) const
120 LyXFont font1, font2;
125 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
127 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
129 // The beginning or the end of a footnote environment?
130 if (footflag != footnoteflag) {
131 footflag = footnoteflag;
133 os << "\n\\begin_float "
134 << string_footnotekinds[footnotekind]
137 os << "\n\\end_float ";
141 // The beginning or end of a deeper (i.e. nested) area?
144 while (depth > dth) {
145 os << "\n\\begin_deeper ";
149 while (depth < dth) {
150 os << "\n\\end_deeper ";
156 // First write the layout
158 << textclasslist.NameOfLayout(params.textclass, layout)
161 // Maybe some vertical spaces.
162 if (added_space_top.kind() != VSpace::NONE)
163 os << "\\added_space_top "
164 << added_space_top.asLyXCommand() << " ";
165 if (added_space_bottom.kind() != VSpace::NONE)
166 os << "\\added_space_bottom "
167 << added_space_bottom.asLyXCommand() << " ";
169 // The labelwidth string used in lists.
170 if (!labelwidthstring.empty())
171 os << "\\labelwidthstring "
172 << labelwidthstring << '\n';
174 // Lines above or below?
178 os << "\\line_bottom ";
180 // Pagebreaks above or below?
182 os << "\\pagebreak_top ";
183 if (pagebreak_bottom)
184 os << "\\pagebreak_bottom ";
186 // Start of appendix?
187 if (start_of_appendix)
188 os << "\\start_of_appendix ";
195 if (align != LYX_ALIGN_LAYOUT) {
197 case LYX_ALIGN_LEFT: h = 1; break;
198 case LYX_ALIGN_RIGHT: h = 2; break;
199 case LYX_ALIGN_CENTER: h = 3; break;
200 default: h = 0; break;
202 os << "\\align " << string_align[h] << " ";
204 if (pextra_type != PEXTRA_NONE) {
205 os << "\\pextra_type " << pextra_type;
206 if (pextra_type == PEXTRA_MINIPAGE) {
207 os << " \\pextra_alignment "
210 os << " \\pextra_hfill "
212 if (pextra_start_minipage)
213 os << " \\pextra_start_minipage "
214 << pextra_start_minipage;
216 if (!pextra_width.empty()) {
217 os << " \\pextra_width "
218 << VSpace(pextra_width).asLyXCommand();
219 } else if (!pextra_widthp.empty()) {
220 os << " \\pextra_widthp "
226 // Dummy layout. This means that a footnote ended.
227 os << "\n\\end_float ";
228 footflag = LyXParagraph::NO_FOOTNOTE;
231 // It might be a table.
233 os << "\\LyXTable\n";
241 font1 = LyXFont(LyXFont::ALL_INHERIT,params.language_info);
244 for (size_type i = 0; i < size(); ++i) {
250 // Write font changes
251 font2 = GetFontSettings(i);
252 if (font2 != font1) {
253 font2.lyxWriteChanges(font1, os);
262 Inset const * inset = GetInset(i);
264 if (inset->DirectWrite()) {
265 // international char, let it write
266 // code directly so it's shorter in
270 os << "\n\\begin_inset ";
272 os << "\n\\end_inset \n\n";
278 os << "\n\\newline \n";
282 os << "\n\\hfill \n";
286 case META_PROTECTED_SEPARATOR:
287 os << "\n\\protected_separator \n";
292 os << "\n\\backslash \n";
296 if (i + 1 < size() && GetChar(i + 1) == ' ') {
303 if ((column > 70 && c == ' ')
308 // this check is to amend a bug. LyX sometimes
309 // inserts '\0' this could cause problems.
313 lyxerr << "ERROR (LyXParagraph::writeFile):"
314 " NULL char in structure." << endl;
320 // now write the next paragraph
322 next->writeFile(os, params, footflag, dth);
326 void LyXParagraph::validate(LaTeXFeatures & features) const
328 // this will be useful later
329 LyXLayout const & layout =
330 textclasslist.Style(current_view->buffer()->params.textclass,
334 if (line_top || line_bottom)
335 features.lyxline = true;
338 features.layout[GetLayout()] = true;
341 Language const * doc_language = current_view->buffer()->params.language_info;
342 for (FontList::const_iterator cit = fontlist.begin();
343 cit != fontlist.end(); ++cit) {
344 if ((*cit).font.noun() == LyXFont::ON) {
345 lyxerr[Debug::LATEX] << "font.noun: "
346 << (*cit).font.noun()
348 features.noun = true;
349 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
350 << (*cit).font.stateText()
353 switch ((*cit).font.color()) {
355 case LColor::inherit:
359 features.color = true;
360 lyxerr[Debug::LATEX] << "Color enabled. Font: "
361 << (*cit).font.stateText()
364 Language const * language = (*cit).font.language();
365 if (language != doc_language && language != default_language) {
366 features.UsedLanguages.insert(language);
367 lyxerr[Debug::LATEX] << "Found language "
368 << language->lang << endl;
373 for (InsetList::const_iterator cit = insetlist.begin();
374 cit != insetlist.end(); ++cit) {
376 (*cit).inset->Validate(features);
379 if (table && table->IsLongTable())
380 features.longtable = true;
381 if (pextra_type == PEXTRA_INDENT)
382 features.LyXParagraphIndent = true;
383 if (pextra_type == PEXTRA_FLOATFLT)
384 features.floatflt = true;
385 if (layout.needprotect
386 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
387 features.NeedLyXFootnoteCode = true;
388 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
389 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
390 features.NeedLyXMinipageIndent = true;
391 if (table && table->NeedRotating())
392 features.rotating = true;
393 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
394 features.algorithm = true;
398 // First few functions needed for cut and paste and paragraph breaking.
399 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
401 minibuffer_char = GetChar(pos);
402 minibuffer_font = GetFontSettings(pos);
403 minibuffer_inset = 0;
404 if (minibuffer_char == LyXParagraph::META_INSET) {
406 minibuffer_inset = GetInset(pos)->Clone();
408 minibuffer_inset = 0;
409 minibuffer_char = ' ';
410 // This reflects what GetInset() does (ARRae)
416 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
418 minibuffer_char = GetChar(pos);
419 minibuffer_font = GetFontSettings(pos);
420 minibuffer_inset = 0;
421 if (minibuffer_char == LyXParagraph::META_INSET) {
423 minibuffer_inset = GetInset(pos);
424 // This is a little hack since I want exactly
425 // the inset, not just a clone. Otherwise
426 // the inset would be deleted when calling Erase(pos)
428 InsetList::iterator it = lower_bound(insetlist.begin(),
431 if (it != insetlist.end() && (*it).pos == pos)
434 minibuffer_inset = 0;
435 minibuffer_char = ' ';
436 // This reflects what GetInset() does (ARRae)
441 // Erase(pos); now the caller is responsible for that.
445 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
447 InsertChar(pos, minibuffer_char);
448 SetFont(pos, minibuffer_font);
449 if (minibuffer_char == LyXParagraph::META_INSET)
450 InsertInset(pos, minibuffer_inset);
457 void LyXParagraph::Clear()
462 pagebreak_top = false;
463 pagebreak_bottom = false;
465 added_space_top = VSpace(VSpace::NONE);
466 added_space_bottom = VSpace(VSpace::NONE);
468 align = LYX_ALIGN_LAYOUT;
472 pextra_type = PEXTRA_NONE;
473 pextra_width.clear();
474 pextra_widthp.clear();
475 pextra_alignment = MINIPAGE_ALIGN_TOP;
476 pextra_hfill = false;
477 pextra_start_minipage = false;
480 labelwidthstring.clear();
484 start_of_appendix = false;
488 // the destructor removes the new paragraph from the list
489 LyXParagraph::~LyXParagraph()
492 previous->next = next;
494 next->previous = previous;
496 for (InsetList::iterator it = insetlist.begin();
497 it != insetlist.end(); ++it) {
501 /* table stuff -- begin*/
503 /* table stuff -- end*/
510 void LyXParagraph::Erase(LyXParagraph::size_type pos)
512 // > because last is the next unused position, and you can
513 // use it if you want
515 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
516 NextAfterFootnote()->Erase(pos - text.size() - 1);
518 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
519 "position does not exist." << endl;
522 if (pos < size()) { // last is free for insertation, but should be empty
523 // if it is an inset, delete the inset entry
524 if (text[pos] == LyXParagraph::META_INSET) {
526 InsetList::iterator it = lower_bound(insetlist.begin(),
529 if (it != insetlist.end() && (*it).pos == pos) {
534 text.erase(text.begin() + pos);
535 // Erase entries in the tables.
536 for (FontList::iterator it = fontlist.begin();
537 it != fontlist.end(); ++it) {
538 if (pos >= (*it).pos && pos <= (*it).pos_end) {
539 if ((*it).pos == (*it).pos_end) {
540 // If it is a multi-character font
541 // entry, we just make it smaller
542 // (see update below), otherwise we
549 // Update all other entries.
550 for (FontList::iterator it = fontlist.begin();
551 it != fontlist.end(); ++it) {
554 if ((*it).pos_end >= pos)
558 // Update the inset table.
559 for (InsetList::iterator it = upper_bound(insetlist.begin(),
562 it != insetlist.end(); ++it)
565 lyxerr << "ERROR (LyXParagraph::Erase): "
566 "can't erase non-existant char." << endl;
571 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
573 // > because last is the next unused position, and you can
574 // use it if you want
577 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
578 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
581 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
582 "position does not exist." << endl;
585 text.insert(text.begin() + pos, c);
586 // Update the font table.
587 for (FontList::iterator it = fontlist.begin();
588 it != fontlist.end(); ++it) {
589 if ((*it).pos >= pos)
591 if ((*it).pos_end >= pos)
595 // Update the inset table.
596 for (InsetList::iterator it = lower_bound(insetlist.begin(),
599 it != insetlist.end(); ++it)
604 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
607 // > because last is the next unused position, and you can
608 // use it if you want
611 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
613 ->InsertInset(pos - text.size() - 1, inset);
615 lyxerr << "ERROR (LyXParagraph::InsertInset): "
616 "position does not exist: " << pos << endl;
619 if (text[pos] != LyXParagraph::META_INSET) {
620 lyxerr << "ERROR (LyXParagraph::InsertInset): "
621 "there is no LyXParagraph::META_INSET" << endl;
626 // Add a new entry in the inset table.
627 InsetList::iterator it = lower_bound(insetlist.begin(),
630 if (it != insetlist.end() && (*it).pos == pos)
631 lyxerr << "ERROR (LyXParagraph::InsertInset): "
632 "there is an inset in position: " << pos << endl;
634 insetlist.insert(it,InsetTable(pos,inset));
639 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
643 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
644 return NextAfterFootnote()
645 ->GetInset(pos - text.size() - 1);
647 lyxerr << "ERROR (LyXParagraph::GetInset): "
648 "position does not exist: "
654 InsetList::iterator it = lower_bound(insetlist.begin(),
657 if (it != insetlist.end() && (*it).pos == pos)
660 lyxerr << "ERROR (LyXParagraph::GetInset): "
661 "Inset does not exist: " << pos << endl;
662 // text[pos] = ' '; // WHY!!! does this set the pos to ' '????
663 // Did this commenting out introduce a bug? So far I have not
664 // see any, please enlighten me. (Lgb)
665 // My guess is that since the inset does not exist, we might
666 // as well replace it with a space to prevent craches. (Asger)
671 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
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::const_iterator cit = lower_bound(insetlist.begin(),
689 if (cit != insetlist.end() && (*cit).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 // Gets uninstantiated font setting at position.
704 // Optimized after profiling. (Asger)
705 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
708 #ifdef SORTED_FONT_LIST
709 for (FontList::const_iterator cit = fontlist.begin();
710 cit != fontlist.end() && pos <= (*cit).pos_end; ++cit)
711 if (pos >= (*cit).pos)
714 for (FontList::const_iterator cit = fontlist.begin();
715 cit != fontlist.end(); ++cit)
716 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
720 // > because last is the next unused position, and you can
721 // use it if you want
722 else if (pos > size()) {
724 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
725 return NextAfterFootnote()
726 ->GetFontSettings(pos - text.size() - 1);
728 // Why is it an error to ask for the font of a
729 // position that does not exist? Would it be
730 // enough for this to be enabled on debug?
731 // We want strict error checking, but it's ok to only
732 // have it when debugging. (Asger)
733 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
734 "position does not exist. "
735 << pos << " (" << static_cast<int>(pos)
738 } else if (pos > 0) {
739 return GetFontSettings(pos - 1);
740 } else // pos = size() = 0
741 return LyXFont(LyXFont::ALL_INHERIT,getParLanguage());
743 return LyXFont(LyXFont::ALL_INHERIT);
746 // Gets uninstantiated font setting at position 0
747 LyXFont LyXParagraph::GetFirstFontSettings() const
750 #ifdef SORTED_FONT_LIST
751 if (!fontlist.empty() && fontlist.front().pos == 0)
752 return fontlist.front().font;
754 for (FontList::const_iterator cit = fontlist.begin();
755 cit != fontlist.end(); ++cit)
756 if (0 >= (*cit).pos && 0 <= (*cit).pos_end)
759 } else if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
760 return NextAfterFootnote()->GetFirstFontSettings();
761 return LyXFont(LyXFont::ALL_INHERIT);
764 // Gets the fully instantiated font at a given position in a paragraph
765 // This is basically the same function as LyXText::GetFont() in text2.C.
766 // The difference is that this one is used for generating the LaTeX file,
767 // and thus cosmetic "improvements" are disallowed: This has to deliver
768 // the true picture of the buffer. (Asger)
769 // If position is -1, we get the layout font of the paragraph.
770 // If position is -2, we get the font of the manual label of the paragraph.
771 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
774 LyXLayout const & layout =
775 textclasslist.Style(current_view->buffer()->params.textclass,
777 LyXParagraph::size_type main_body = 0;
778 if (layout.labeltype == LABEL_MANUAL)
779 main_body = BeginningOfMainBody();
784 layoutfont = layout.labelfont;
786 layoutfont = layout.font;
787 tmpfont = GetFontSettings(pos);
788 tmpfont.realize(layoutfont);
790 // process layoutfont for pos == -1 and labelfont for pos < -1
792 tmpfont = layout.font;
794 tmpfont = layout.labelfont;
795 tmpfont.setLanguage(getParLanguage());
798 // check for environment font information
799 char par_depth = GetDepth();
800 LyXParagraph const * par = this;
801 while (par && par_depth && !tmpfont.resolved()) {
802 par = par->DepthHook(par_depth - 1);
804 tmpfont.realize(textclasslist.
805 Style(current_view->buffer()->params.textclass,
806 par->GetLayout()).font);
807 par_depth = par->GetDepth();
811 tmpfont.realize(textclasslist
812 .TextClass(current_view->buffer()->params.textclass)
818 /// Returns the height of the highest font in range
820 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
821 LyXParagraph::size_type endpos) const
823 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
824 for (FontList::const_iterator cit = fontlist.begin();
825 cit != fontlist.end(); ++cit) {
826 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
827 LyXFont::FONT_SIZE size = (*cit).font.size();
828 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
836 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
843 // > because last is the next unused position, and you can
844 // use it if you want
845 else if (pos > size()) {
846 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
847 return NextAfterFootnote()
848 ->GetChar(pos - text.size() - 1);
850 lyxerr << "ERROR (LyXParagraph::GetChar): "
851 "position does not exist."
852 << pos << " (" << static_cast<int>(pos)
854 // Assert(false); // This triggers sometimes...
859 // We should have a footnote environment.
860 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
861 // Notice that LyX does request the
862 // last char from time to time. (Asger)
863 //lyxerr << "ERROR (LyXParagraph::GetChar): "
864 // "expected footnote." << endl;
867 switch (next->footnotekind) {
868 case LyXParagraph::FOOTNOTE:
869 return LyXParagraph::META_FOOTNOTE;
870 case LyXParagraph::MARGIN:
871 return LyXParagraph::META_MARGIN;
872 case LyXParagraph::FIG:
873 case LyXParagraph::WIDE_FIG:
874 return LyXParagraph::META_FIG;
875 case LyXParagraph::TAB:
876 case LyXParagraph::WIDE_TAB:
877 return LyXParagraph::META_TAB;
878 case LyXParagraph::ALGORITHM:
879 return LyXParagraph::META_ALGORITHM;
881 return '\0'; // to shut up gcc
886 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
893 // > because last is the next unused position, and you can
894 // use it if you want
895 else if (pos > size()) {
896 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
897 return NextAfterFootnote()
898 ->GetChar(pos - text.size() - 1);
900 lyxerr << "ERROR (LyXParagraph::GetChar const): "
901 "position does not exist."
902 << pos << " (" << static_cast<int>(pos)
908 // We should have a footnote environment.
909 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
910 // Notice that LyX does request the
911 // last char from time to time. (Asger)
912 //lyxerr << "ERROR (LyXParagraph::GetChar): "
913 // "expected footnote." << endl;
916 switch (next->footnotekind) {
917 case LyXParagraph::FOOTNOTE:
918 return LyXParagraph::META_FOOTNOTE;
919 case LyXParagraph::MARGIN:
920 return LyXParagraph::META_MARGIN;
921 case LyXParagraph::FIG:
922 case LyXParagraph::WIDE_FIG:
923 return LyXParagraph::META_FIG;
924 case LyXParagraph::TAB:
925 case LyXParagraph::WIDE_TAB:
926 return LyXParagraph::META_TAB;
927 case LyXParagraph::ALGORITHM:
928 return LyXParagraph::META_ALGORITHM;
930 return '\0'; // to shut up gcc
935 // return an string of the current word, and the end of the word in lastpos.
936 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
940 // the current word is defined as starting at the first character
941 // from the immediate left of lastpospos which meets the definition
942 // of IsLetter(), continuing to the last character to the right
943 // of this meeting IsLetter.
949 // move back until we have a letter
951 //there's no real reason to have firstpos & lastpos as
952 //separate variables as this is written, but maybe someon
953 // will want to return firstpos in the future.
955 //since someone might have typed a punctuation first
956 int firstpos = lastpos;
958 while ((firstpos >= 0) && !IsLetter(firstpos))
961 // now find the beginning by looking for a nonletter
963 while ((firstpos>= 0) && IsLetter(firstpos))
966 // the above is now pointing to the preceeding non-letter
970 // so copy characters into theword until we get a nonletter
971 // note that this can easily exceed lastpos, wich means
972 // that if used in the middle of a word, the whole word
975 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
982 LyXParagraph::size_type LyXParagraph::Last() const
984 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
985 return text.size() + NextAfterFootnote()->Last() + 1;
986 // the 1 is the symbol
993 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
995 // > because last is the next unused position, and you can
996 // use it if you want
999 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1000 return NextAfterFootnote()
1001 ->ParFromPos(pos - text.size() - 1);
1003 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1004 "position does not exist." << endl;
1011 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1013 // > because last is the next unused position, and you can
1014 // use it if you want
1017 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1018 return NextAfterFootnote()
1019 ->PositionInParFromPos(pos - text.size() - 1);
1022 "ERROR (LyXParagraph::PositionInParFromPos): "
1023 "position does not exist." << endl;
1031 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1032 LyXFont const & font)
1034 // > because last is the next unused position, and you can
1035 // use it if you want
1038 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1039 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1042 lyxerr << "ERROR (LyXParagraph::SetFont): "
1043 "position does not exist." << endl;
1047 LyXFont patternfont(LyXFont::ALL_INHERIT);
1049 // First, reduce font against layout/label font
1050 // Update: The SetCharFont() routine in text2.C already
1051 // reduces font, so we don't need to do that here. (Asger)
1052 // No need to simplify this because it will disappear
1053 // in a new kernel. (Asger)
1054 // Next search font table
1055 FontList::iterator tmp = fontlist.begin();
1056 for (; tmp != fontlist.end(); ++tmp) {
1057 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1061 if (tmp == fontlist.end()) { // !found
1062 // if we did not find a font entry, but if the font at hand
1063 // is the same as default, we just forget it
1064 if (font == patternfont) return;
1066 // ok, we did not find a font entry. But maybe there is exactly
1067 // the needed font ientry one position left
1068 FontList::iterator tmp2 = fontlist.begin();
1069 for (; tmp2 != fontlist.end(); ++tmp2) {
1070 if (pos - 1 >= (*tmp2).pos
1071 && pos - 1 <= (*tmp2).pos_end)
1074 if (tmp2 != fontlist.end()) {
1075 // ok there is one, maybe it is exactly
1077 if ((*tmp2).font == font) {
1078 // put the position under the font
1083 // Add a new entry in the
1084 // fontlist for the position
1088 ft.font = font; // or patternfont
1089 // It seems that using font instead of patternfont here
1090 // fixes all the problems. This also surfaces a "bug" in
1092 fontlist.insert(fontlist.begin(), ft);
1093 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1095 // more than one character
1096 if (pos == (*tmp).pos) {
1097 // maybe we should enlarge the left fonttable
1098 FontList::iterator tmp2 = fontlist.begin();
1099 for (; tmp2 != fontlist.end(); ++tmp2) {
1100 if (pos - 1 >= (*tmp2).pos
1101 && pos - 1 <= (*tmp2).pos_end)
1104 // Is there is one, and is it exactly
1106 if (tmp2 != fontlist.end() &&
1107 (*tmp2).font == font) {
1108 // Put the position under the font
1114 // Add a new entry in the
1115 // fontlist for the position
1118 ft.pos_end = (*tmp).pos_end;
1119 ft.font = (*tmp).font;
1120 (*tmp).pos_end = pos;
1122 fontlist.insert(fontlist.begin(), ft);
1123 } else if (pos == (*tmp).pos_end) {
1124 // Add a new entry in the
1125 // fontlist for the position
1127 ft.pos = (*tmp).pos;
1128 ft.pos_end = (*tmp).pos_end - 1;
1129 ft.font = (*tmp).font;
1130 (*tmp).pos = (*tmp).pos_end;
1132 fontlist.insert(fontlist.begin(), ft);
1134 // Add a new entry in the
1135 // fontlist for the position
1137 ft.pos = (*tmp).pos;
1138 ft.pos_end = pos - 1;
1139 ft.font = (*tmp).font;
1143 ft2.pos_end = (*tmp).pos_end;
1144 ft2.font = (*tmp).font;
1147 (*tmp).pos_end = pos;
1150 fontlist.insert(fontlist.begin(), ft);
1151 fontlist.insert(fontlist.begin(), ft2);
1159 // This function is able to hide closed footnotes.
1160 LyXParagraph * LyXParagraph::Next()
1162 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1163 LyXParagraph * tmp = next;
1165 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1167 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1168 return tmp->Next(); /* there can be more than one
1169 footnote in a logical
1172 return next; // This should never happen!
1178 LyXParagraph * LyXParagraph::NextAfterFootnote()
1180 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1181 LyXParagraph * tmp = next;
1182 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1184 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1185 return tmp; /* there can be more than one footnote
1186 in a logical paragraph */
1188 return next; // This should never happen!
1194 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1196 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1197 LyXParagraph * tmp = next;
1198 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1200 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1201 return tmp; /* there can be more than one footnote
1202 in a logical paragraph */
1204 return next; // This should never happen!
1210 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1213 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1215 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1216 tmp = tmp->previous;
1217 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1218 return tmp; /* there can be more than one footnote
1219 in a logical paragraph */
1221 return previous; // This should never happen!
1227 LyXParagraph * LyXParagraph::LastPhysicalPar()
1229 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1232 LyXParagraph * tmp = this;
1234 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1235 tmp = tmp->NextAfterFootnote();
1240 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1242 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1245 LyXParagraph const * tmp = this;
1247 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1248 tmp = tmp->NextAfterFootnote();
1253 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1257 LyXParagraph * tmppar = this;
1261 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1262 tmppar = tmppar->previous;
1271 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1275 LyXParagraph const * tmppar = this;
1279 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1280 tmppar = tmppar->previous;
1289 // This function is able to hide closed footnotes.
1290 LyXParagraph * LyXParagraph::Previous()
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 // This function is able to hide closed footnotes.
1313 LyXParagraph const * LyXParagraph::Previous() const
1315 LyXParagraph * tmp = previous;
1320 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1321 tmp = tmp->previous;
1323 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1324 tmp = tmp->previous;
1325 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1326 return tmp->next->Previous();
1335 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1338 size_type i, pos_end, pos_first;
1339 // create a new paragraph
1340 LyXParagraph * par = ParFromPos(pos);
1341 LyXParagraph * firstpar = FirstPhysicalPar();
1343 LyXParagraph * tmp = new LyXParagraph(par);
1345 tmp->footnoteflag = footnoteflag;
1346 tmp->footnotekind = footnotekind;
1348 // this is an idea for a more userfriendly layout handling, I will
1349 // see what the users say
1351 // layout stays the same with latex-environments
1353 tmp->SetOnlyLayout(firstpar->layout);
1354 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1357 if (Last() > pos || !Last() || flag == 2) {
1358 tmp->SetOnlyLayout(firstpar->layout);
1359 tmp->align = firstpar->align;
1360 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1362 tmp->line_bottom = firstpar->line_bottom;
1363 firstpar->line_bottom = false;
1364 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1365 firstpar->pagebreak_bottom = false;
1366 tmp->added_space_bottom = firstpar->added_space_bottom;
1367 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1369 tmp->depth = firstpar->depth;
1370 tmp->noindent = firstpar->noindent;
1372 // copy everything behind the break-position
1373 // to the new paragraph
1375 while (ParFromPos(pos_first) != par)
1378 pos_end = pos_first + par->text.size() - 1;
1379 // The constructor has already reserved 500 elements
1380 //if (pos_end > pos)
1381 // tmp->text.reserve(pos_end - pos);
1383 for (i = pos; i <= pos_end; ++i) {
1384 par->CutIntoMinibuffer(i - pos_first);
1385 tmp->InsertFromMinibuffer(i - pos);
1387 tmp->text.resize(tmp->text.size());
1388 for (i = pos_end; i >= pos; --i)
1389 par->Erase(i - pos_first);
1391 par->text.resize(par->text.size());
1394 // just an idea of me
1396 tmp->line_top = firstpar->line_top;
1397 tmp->pagebreak_top = firstpar->pagebreak_top;
1398 tmp->added_space_top = firstpar->added_space_top;
1399 tmp->bibkey = firstpar->bibkey;
1401 // layout stays the same with latex-environments
1403 firstpar->SetOnlyLayout(tmp->layout);
1404 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1405 firstpar->depth = tmp->depth;
1411 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1413 par = par->FirstPhysicalPar();
1414 footnoteflag = par->footnoteflag;
1415 footnotekind = par->footnotekind;
1417 layout = par->layout;
1418 align = par-> align;
1419 SetLabelWidthString(par->labelwidthstring);
1421 line_bottom = par->line_bottom;
1422 pagebreak_bottom = par->pagebreak_bottom;
1423 added_space_bottom = par->added_space_bottom;
1425 line_top = par->line_top;
1426 pagebreak_top = par->pagebreak_top;
1427 added_space_top = par->added_space_top;
1429 pextra_type = par->pextra_type;
1430 pextra_width = par->pextra_width;
1431 pextra_widthp = par->pextra_widthp;
1432 pextra_alignment = par->pextra_alignment;
1433 pextra_hfill = par->pextra_hfill;
1434 pextra_start_minipage = par->pextra_start_minipage;
1436 noindent = par->noindent;
1441 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1443 LyXParagraph * tmppar = this;
1446 && tmppar->previous->footnoteflag ==
1447 LyXParagraph::CLOSED_FOOTNOTE)
1448 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1449 tmppar = tmppar->previous;
1452 return this; // This should never happen!
1458 LyXParagraph * LyXParagraph::Clone() const
1460 // create a new paragraph
1461 LyXParagraph * result = new LyXParagraph;
1463 result->MakeSameLayout(this);
1465 // this is because of the dummy layout of the paragraphs that
1467 result->layout = layout;
1469 /* table stuff -- begin*/
1471 result->table = table->Clone();
1474 /* table stuff -- end*/
1477 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1480 // copy everything behind the break-position to the new paragraph
1482 result->text = text;
1483 result->fontlist = fontlist;
1484 result->insetlist = insetlist;
1485 for (InsetList::iterator it = result->insetlist.begin();
1486 it != result->insetlist.end(); ++it)
1487 (*it).inset = (*it).inset->Clone();
1492 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1494 par = par->FirstPhysicalPar();
1497 par->footnoteflag == footnoteflag &&
1498 par->footnotekind == footnotekind &&
1500 par->layout == layout &&
1502 par->align == align &&
1504 par->line_bottom == line_bottom &&
1505 par->pagebreak_bottom == pagebreak_bottom &&
1506 par->added_space_bottom == added_space_bottom &&
1508 par->line_top == line_top &&
1509 par->pagebreak_top == pagebreak_top &&
1510 par->added_space_top == added_space_top &&
1512 par->pextra_type == pextra_type &&
1513 par->pextra_width == pextra_width &&
1514 par->pextra_widthp == pextra_widthp &&
1515 par->pextra_alignment == pextra_alignment &&
1516 par->pextra_hfill == pextra_hfill &&
1517 par->pextra_start_minipage == pextra_start_minipage &&
1519 par->table == table && // what means: NO TABLE AT ALL
1521 par->noindent == noindent &&
1522 par->depth == depth);
1526 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1528 // create a new paragraph
1529 LyXParagraph * par = ParFromPos(pos);
1531 LyXParagraph * tmp = new LyXParagraph(par);
1533 tmp->MakeSameLayout(par);
1535 // When can pos < Last()?
1536 // I guess pos == Last() is possible.
1538 // copy everything behind the break-position to the new
1540 size_type pos_first = 0;
1541 while (ParFromPos(pos_first) != par)
1543 size_type pos_end = pos_first + par->text.size() - 1;
1544 // make sure there is enough memory for the now larger
1545 // paragraph. This is not neccessary, because
1546 // InsertFromMinibuffer will enlarge the memory (it uses
1547 // InsertChar of course). But doing it by hand
1548 // is MUCH faster! (only one time, not thousend times!!)
1549 // Not needed since the constructor aleady have
1550 // reserved 500 elements in text.
1551 //if (pos_end > pos)
1552 // tmp->text.reserve(pos_end - pos);
1554 for (size_type i = pos; i <= pos_end; ++i) {
1555 par->CutIntoMinibuffer(i - pos_first);
1556 tmp->InsertFromMinibuffer(i - pos);
1558 tmp->text.resize(tmp->text.size());
1559 for (size_type i = pos_end; i >= pos; --i)
1560 par->Erase(i - pos_first);
1562 par->text.resize(par->text.size());
1567 // Be carefull, this does not make any check at all.
1568 void LyXParagraph::PasteParagraph()
1570 // copy the next paragraph to this one
1571 LyXParagraph * the_next = Next();
1573 LyXParagraph * firstpar = FirstPhysicalPar();
1575 // first the DTP-stuff
1576 firstpar->line_bottom = the_next->line_bottom;
1577 firstpar->added_space_bottom = the_next->added_space_bottom;
1578 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1580 size_type pos_end = the_next->text.size() - 1;
1581 size_type pos_insert = Last();
1583 // ok, now copy the paragraph
1584 for (size_type i = 0; i <= pos_end; ++i) {
1585 the_next->CutIntoMinibuffer(i);
1586 InsertFromMinibuffer(pos_insert + i);
1589 // delete the next paragraph
1594 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1596 LyXParagraph * par = ParFromPos(pos);
1598 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1599 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1605 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1607 LyXParagraph * par = ParFromPos(pos);
1609 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1610 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1615 int LyXParagraph::GetEndLabel() const
1617 LyXParagraph const * par = this;
1618 int par_depth = GetDepth();
1620 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1622 textclasslist.Style(current_view->buffer()->params.textclass,
1623 layout).endlabeltype;
1624 if (endlabeltype != END_LABEL_NO_LABEL) {
1625 LyXParagraph const * last = this;
1626 if( footnoteflag == NO_FOOTNOTE)
1627 last = LastPhysicalPar();
1628 else if (next->footnoteflag == NO_FOOTNOTE)
1629 return endlabeltype;
1631 if (!last || !last->next)
1632 return endlabeltype;
1634 int next_depth = last->next->GetDepth();
1635 if (par_depth > next_depth ||
1636 (par_depth == next_depth && layout != last->next->GetLayout() ))
1637 return endlabeltype;
1642 par = par->DepthHook(par_depth - 1);
1644 par_depth = par->GetDepth();
1646 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(LyXTextClass::size_type new_layout)
1699 LyXParagraph * par = FirstPhysicalPar();
1700 LyXParagraph * ppar = 0;
1701 LyXParagraph * npar = 0;
1703 par->layout = new_layout;
1704 /* table stuff -- begin*/
1707 /* table stuff -- end*/
1708 if (par->pextra_type == PEXTRA_NONE) {
1709 if (par->Previous()) {
1710 ppar = par->Previous()->FirstPhysicalPar();
1713 && (ppar->depth > par->depth))
1714 ppar = ppar->Previous()->FirstPhysicalPar();
1717 npar = par->Next()->NextAfterFootnote();
1720 && (npar->depth > par->depth))
1721 npar = npar->Next()->NextAfterFootnote();
1723 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1725 p1 = ppar->pextra_width,
1726 p2 = ppar->pextra_widthp;
1727 ppar->SetPExtraType(ppar->pextra_type,
1728 p1.c_str(), p2.c_str());
1730 if ((par->pextra_type == PEXTRA_NONE) &&
1731 npar && (npar->pextra_type != PEXTRA_NONE)) {
1733 p1 = npar->pextra_width,
1734 p2 = npar->pextra_widthp;
1735 npar->SetPExtraType(npar->pextra_type,
1736 p1.c_str(), p2.c_str());
1742 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1745 * par = FirstPhysicalPar(),
1749 par->layout = new_layout;
1750 par->labelwidthstring.clear();
1751 par->align = LYX_ALIGN_LAYOUT;
1752 par->added_space_top = VSpace(VSpace::NONE);
1753 par->added_space_bottom = VSpace(VSpace::NONE);
1754 /* table stuff -- begin*/
1757 /* table stuff -- end*/
1758 if (par->pextra_type == PEXTRA_NONE) {
1759 if (par->Previous()) {
1760 ppar = par->Previous()->FirstPhysicalPar();
1763 && (ppar->depth > par->depth))
1764 ppar = ppar->Previous()->FirstPhysicalPar();
1767 npar = par->Next()->NextAfterFootnote();
1770 && (npar->depth > par->depth))
1771 npar = npar->Next()->NextAfterFootnote();
1773 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1775 p1 = ppar->pextra_width,
1776 p2 = ppar->pextra_widthp;
1777 ppar->SetPExtraType(ppar->pextra_type,
1778 p1.c_str(), p2.c_str());
1780 if ((par->pextra_type == PEXTRA_NONE) &&
1781 npar && (npar->pextra_type != PEXTRA_NONE)) {
1783 p1 = npar->pextra_width,
1784 p2 = npar->pextra_widthp;
1785 npar->SetPExtraType(npar->pextra_type,
1786 p1.c_str(), p2.c_str());
1792 // if the layout of a paragraph contains a manual label, the beginning of the
1793 // main body is the beginning of the second word. This is what the par-
1794 // function returns. If the layout does not contain a label, the main
1795 // body always starts with position 0. This differentiation is necessary,
1796 // because there cannot be a newline or a blank <= the beginning of the
1797 // main body in TeX.
1799 int LyXParagraph::BeginningOfMainBody() const
1801 if (FirstPhysicalPar() != this)
1804 // Unroll the first two cycles of the loop
1805 // and remember the previous character to
1806 // remove unnecessary GetChar() calls
1809 && GetChar(i) != LyXParagraph::META_NEWLINE
1812 char previous_char = 0, temp = 0;
1814 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1815 // Yes, this ^ is supposed to be "= " not "=="
1818 && previous_char != ' '
1819 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1821 previous_char = temp;
1826 if (i == 0 && i == size() &&
1827 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1828 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1829 ++i; /* the cursor should not jump
1830 * to the main body if there
1836 LyXParagraph * LyXParagraph::DepthHook(int deth)
1838 LyXParagraph * newpar = this;
1843 newpar = newpar->FirstPhysicalPar()->Previous();
1844 } while (newpar && newpar->GetDepth() > deth
1845 && newpar->footnoteflag == footnoteflag);
1848 if (Previous() || GetDepth())
1849 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1853 return newpar->FirstPhysicalPar();
1857 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1859 LyXParagraph const * newpar = this;
1864 newpar = newpar->FirstPhysicalPar()->Previous();
1865 } while (newpar && newpar->GetDepth() > deth
1866 && newpar->footnoteflag == footnoteflag);
1869 if (Previous() || GetDepth())
1870 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1874 return newpar->FirstPhysicalPar();
1878 int LyXParagraph::AutoDeleteInsets()
1882 while (i < insetlist.size()) {
1883 if (insetlist[i].inset && insetlist[i].inset->AutoDelete()) {
1884 Erase(insetlist[i].pos);
1885 // Erase() calls to insetlist.erase(&insetlist[i])
1886 // so i shouldn't be increased.
1895 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1897 InsetList::iterator it = lower_bound(insetlist.begin(),
1899 InsetTable(pos, 0));
1900 if (it != insetlist.end()) {
1908 // returns -1 if inset not found
1909 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1912 for (InsetList::const_iterator cit = insetlist.begin();
1913 cit != insetlist.end(); ++cit) {
1914 if ((*cit).inset == inset) {
1918 // Think about footnotes.
1919 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1920 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1922 NextAfterFootnote()->GetPositionOfInset(inset);
1924 return text.size() + 1 + further;
1930 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1932 TexRow & foot_texrow,
1935 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1936 LyXLayout const & style =
1937 textclasslist.Style(current_view->buffer()->params.textclass,
1940 bool further_blank_line = false;
1942 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1944 if (start_of_appendix) {
1945 os << "\\appendix\n";
1949 if (tex_code_break_column && style.isCommand()){
1954 if (pagebreak_top) {
1956 further_blank_line = true;
1958 if (added_space_top.kind() != VSpace::NONE) {
1959 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1960 further_blank_line = true;
1964 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1965 << "\\vspace{-1\\parskip}";
1966 further_blank_line = true;
1969 if (further_blank_line){
1974 Language const * language = getParLanguage();
1975 Language const * doc_language = current_view->buffer()->params.language_info;
1976 if (language != doc_language) {
1977 os << subst(lyxrc.language_command_begin, "$$lang",
1983 switch (style.latextype) {
1986 << style.latexname()
1987 << style.latexparam();
1989 case LATEX_ITEM_ENVIRONMENT:
1991 bibkey->Latex(os, false, false);
1995 case LATEX_LIST_ENVIRONMENT:
2002 bool need_par = SimpleTeXOnePar(os, texrow);
2004 // Spit out footnotes
2005 LyXParagraph * par = next;
2006 if (lyxrc.rtl_support) {
2007 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2008 && next->footnoteflag != footnoteflag) {
2009 LyXParagraph * p = 0;
2010 bool is_rtl = GetFontSettings(size()-1).isRightToLeft();
2011 if ( (p = NextAfterFootnote()) != 0 &&
2012 p->GetFontSettings(0).isRightToLeft() != is_rtl)
2013 is_rtl = GetFontSettings(0).isRightToLeft();
2015 par->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2016 par->footnoteflag != footnoteflag) {
2017 LyXDirection dir = (is_rtl)
2018 ? LYX_DIR_RIGHT_TO_LEFT
2019 : LYX_DIR_LEFT_TO_RIGHT;
2020 par = par->TeXFootnote(os, texrow, foot,
2021 foot_texrow, foot_count,
2023 par->SimpleTeXOnePar(os, texrow);
2024 is_rtl = par->GetFontSettings(par->size()-1).isRightToLeft();
2026 par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2027 (p = par->NextAfterFootnote()) != 0 &&
2028 p->GetFontSettings(0).isRightToLeft() != is_rtl)
2029 is_rtl = GetFontSettings(0).isRightToLeft();
2034 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2035 && par->footnoteflag != footnoteflag) {
2036 par = par->TeXFootnote(os, texrow,
2037 foot, foot_texrow, foot_count,
2038 LYX_DIR_LEFT_TO_RIGHT);
2039 par->SimpleTeXOnePar(os, texrow);
2044 // Make sure that \\par is done with the font of the last
2045 // character if this has another size as the default.
2046 // This is necessary because LaTeX (and LyX on the screen)
2047 // calculates the space between the baselines according
2048 // to this font. (Matthias)
2049 LyXFont font = getFont(Last() - 1);
2051 if (style.resfont.size() != font.size()) {
2057 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2058 GetLayout()).isCommand()){
2059 if (style.resfont.size() != font.size()) {
2065 } else if (style.resfont.size() != font.size()){
2066 os << "{\\" << font.latexSize() << " \\par}";
2069 if (language != doc_language) {
2071 << subst(lyxrc.language_command_end, "$$lang",
2072 doc_language->lang);
2075 switch (style.latextype) {
2076 case LATEX_ITEM_ENVIRONMENT:
2077 case LATEX_LIST_ENVIRONMENT:
2078 if (par && (depth < par->depth)) {
2083 case LATEX_ENVIRONMENT:
2084 // if its the last paragraph of the current environment
2085 // skip it otherwise fall through
2087 && (par->layout != layout
2088 || par->depth != depth
2089 || par->pextra_type != pextra_type))
2092 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2093 && footnotekind != LyXParagraph::FOOTNOTE
2094 && footnotekind != LyXParagraph::MARGIN
2098 // don't insert this if we would be adding it
2099 // before or after a table in a float. This
2100 // little trick is needed in order to allow
2101 // use of tables in \subfigures or \subtables.
2107 further_blank_line = false;
2109 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2110 further_blank_line = true;
2113 if (added_space_bottom.kind() != VSpace::NONE) {
2114 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2115 further_blank_line = true;
2118 if (pagebreak_bottom) {
2120 further_blank_line = true;
2123 if (further_blank_line){
2128 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2129 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2134 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2139 // This one spits out the text of the paragraph
2140 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2142 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2145 return SimpleTeXOneTablePar(os, texrow);
2147 bool return_value = false;
2149 LyXLayout const & style =
2150 textclasslist.Style(current_view->buffer()->params.textclass,
2152 LyXFont basefont, last_font;
2154 // Maybe we have to create a optional argument.
2155 size_type main_body;
2156 if (style.labeltype != LABEL_MANUAL)
2159 main_body = BeginningOfMainBody();
2161 if (main_body > 0) {
2163 basefont = getFont(-2); // Get label font
2165 basefont = getFont(-1); // Get layout font
2173 if (style.isCommand()) {
2176 } else if (align != LYX_ALIGN_LAYOUT) {
2179 return_value = true;
2183 // Which font is currently active?
2184 LyXFont running_font(basefont);
2185 // Do we have an open font change?
2186 bool open_font = false;
2188 texrow.start(this, 0);
2190 for (size_type i = 0; i < size(); ++i) {
2192 // First char in paragraph or after label?
2193 if (i == main_body && !IsDummy()) {
2194 if (main_body > 0) {
2196 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2199 basefont = getFont(-1); // Now use the layout font
2200 running_font = basefont;
2204 if (style.isCommand()) {
2207 } else if (align != LYX_ALIGN_LAYOUT) {
2210 return_value = true;
2214 os << "\\noindent ";
2218 case LYX_ALIGN_NONE:
2219 case LYX_ALIGN_BLOCK:
2220 case LYX_ALIGN_LAYOUT:
2221 case LYX_ALIGN_SPECIAL:
2223 case LYX_ALIGN_LEFT:
2224 if (getParLanguage()->lang != "hebrew") {
2225 os << "\\raggedright ";
2228 os << "\\raggedleft ";
2232 case LYX_ALIGN_RIGHT:
2233 if (getParLanguage()->lang != "hebrew") {
2234 os << "\\raggedleft ";
2237 os << "\\raggedright ";
2241 case LYX_ALIGN_CENTER:
2242 os << "\\centering ";
2250 // Fully instantiated font
2251 LyXFont font = getFont(i);
2252 LyXParagraph * p = 0;
2253 if (i == 0 && previous &&
2254 previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2255 (p = PreviousBeforeFootnote()) != 0)
2256 last_font = p->getFont(p->size()-1);
2258 last_font = running_font;
2260 // Spaces at end of font change are simulated to be
2261 // outside font change, i.e. we write "\textXX{text} "
2262 // rather than "\textXX{text }". (Asger)
2263 if (open_font && c == ' ' && i <= size() - 2
2264 && !getFont(i+1).equalExceptLatex(running_font)
2265 && !getFont(i+1).equalExceptLatex(font)) {
2266 font = getFont(i + 1);
2268 // We end font definition before blanks
2269 if (!font.equalExceptLatex(running_font) && open_font) {
2270 column += running_font.latexWriteEndChanges(os,
2272 (i == main_body-1) ? basefont : font);
2273 running_font = basefont;
2277 // Blanks are printed before start of fontswitch
2279 // Do not print the separation of the optional argument
2280 if (i != main_body - 1) {
2281 SimpleTeXBlanks(os, texrow, i,
2282 column, font, style);
2286 // Do we need to change font?
2287 if (!font.equalExceptLatex(running_font)
2288 && i != main_body-1) {
2289 column += font.latexWriteStartChanges(os, basefont,
2291 running_font = font;
2295 if (c == LyXParagraph::META_NEWLINE) {
2296 // newlines are handled differently here than
2297 // the default in SimpleTeXSpecialChars().
2298 if (!style.newline_allowed
2299 || font.latex() == LyXFont::ON) {
2303 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2306 basefont = getFont(-1);
2307 running_font = basefont;
2308 if (font.family() ==
2309 LyXFont::TYPEWRITER_FAMILY) {
2315 texrow.start(this, i + 1);
2318 SimpleTeXSpecialChars(os, texrow,
2319 font, running_font, basefont,
2320 open_font, style, i, column, c);
2324 // If we have an open font definition, we have to close it
2326 LyXParagraph * p = 0;
2327 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2328 && (p = NextAfterFootnote()) != 0)
2329 running_font.latexWriteEndChanges(os, basefont,
2332 running_font.latexWriteEndChanges(os, basefont, basefont);
2335 // Needed if there is an optional argument but no contents.
2336 if (main_body > 0 && main_body == size()) {
2338 return_value = false;
2341 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2342 return return_value;
2346 // This one spits out the text of a table paragraph
2347 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2349 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2351 bool return_value = false;
2353 LyXLayout const & style =
2354 textclasslist.Style(current_view->buffer()->params.textclass,
2358 if (!IsDummy()) { // it is dummy if it is in a float!!!
2359 if (style.isCommand()) {
2362 } else if (align != LYX_ALIGN_LAYOUT) {
2365 return_value = true;
2368 os << "\\noindent ";
2372 case LYX_ALIGN_NONE:
2373 case LYX_ALIGN_BLOCK:
2374 case LYX_ALIGN_LAYOUT:
2375 case LYX_ALIGN_SPECIAL: break;
2376 case LYX_ALIGN_LEFT:
2377 os << "\\raggedright ";
2380 case LYX_ALIGN_RIGHT:
2381 os << "\\raggedleft ";
2384 case LYX_ALIGN_CENTER:
2385 os << "\\centering ";
2391 LyXFont basefont = getFont(-1); // Get layout font
2392 // Which font is currently active?
2393 LyXFont running_font = basefont;
2395 // Do we have an open font change?
2396 bool open_font = false;
2397 int current_cell_number = -1;
2398 int tmp = table->TexEndOfCell(os, current_cell_number);
2399 for (; tmp > 0 ; --tmp)
2402 texrow.start(this, 0);
2404 for (size_type i = 0; i < size(); ++i) {
2405 char c = GetChar(i);
2406 if (table->IsContRow(current_cell_number + 1)) {
2407 if (c == LyXParagraph::META_NEWLINE)
2408 ++current_cell_number;
2413 // Fully instantiated font
2414 LyXFont font = getFont(i);
2415 last_font = running_font;
2417 // Spaces at end of font change are simulated to be
2418 // outside font change.
2419 // i.e. we write "\textXX{text} " rather than
2420 // "\textXX{text }". (Asger)
2421 if (open_font && c == ' ' && i <= size() - 2
2422 && getFont(i + 1) != running_font
2423 && getFont(i + 1) != font) {
2424 font = getFont(i + 1);
2427 // We end font definition before blanks
2428 if (font != running_font && open_font) {
2429 column += running_font.latexWriteEndChanges(os,
2432 running_font = basefont;
2435 // Blanks are printed before start of fontswitch
2437 SimpleTeXBlanks(os, texrow, i, column, font, style);
2439 // Do we need to change font?
2440 if (font != running_font) {
2441 column += font.latexWriteStartChanges(os, basefont,
2443 running_font = font;
2446 // Do we need to turn on LaTeX mode?
2447 if (font.latex() != running_font.latex()) {
2448 if (font.latex() == LyXFont::ON
2449 && style.needprotect) {
2454 if (c == LyXParagraph::META_NEWLINE) {
2455 // special case for inside a table
2456 // different from default case in
2457 // SimpleTeXSpecialChars()
2459 column += running_font
2460 .latexWriteEndChanges(os, basefont,
2464 basefont = getFont(-1);
2465 running_font = basefont;
2466 ++current_cell_number;
2467 if (table->CellHasContRow(current_cell_number) >= 0) {
2468 TeXContTableRows(os, i + 1,
2469 current_cell_number,
2472 // if this cell follow only ContRows till end don't
2473 // put the EndOfCell because it is put after the
2475 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2476 --current_cell_number;
2479 int tmp = table->TexEndOfCell(os,
2480 current_cell_number);
2483 } else if (tmp < 0) {
2489 texrow.start(this, i + 1);
2491 SimpleTeXSpecialChars(os, texrow,
2492 font, running_font, basefont,
2493 open_font, style, i, column, c);
2497 // If we have an open font definition, we have to close it
2499 running_font.latexWriteEndChanges(os, basefont, basefont);
2501 ++current_cell_number;
2502 tmp = table->TexEndOfCell(os, current_cell_number);
2503 for (; tmp > 0; --tmp)
2505 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2506 return return_value;
2510 // This one spits out the text off ContRows in tables
2511 bool LyXParagraph::TeXContTableRows(ostream & os,
2512 LyXParagraph::size_type i,
2513 int current_cell_number,
2514 int & column, TexRow & texrow)
2516 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2522 bool return_value = false;
2523 LyXLayout const & style =
2524 textclasslist.Style(current_view->buffer()->params.textclass,
2526 LyXFont basefont = getFont(-1); // Get layout font
2528 // Which font is currently active?
2529 LyXFont running_font = basefont;
2530 // Do we have an open font change?
2531 bool open_font = false;
2533 size_type lastpos = i;
2534 int cell = table->CellHasContRow(current_cell_number);
2535 ++current_cell_number;
2537 // first find the right position
2539 for (; (i < size()) && (current_cell_number<cell); ++i) {
2541 if (c == LyXParagraph::META_NEWLINE)
2542 ++current_cell_number;
2546 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2550 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2555 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2559 // Fully instantiated font
2560 LyXFont font = getFont(i);
2561 last_font = running_font;
2563 // Spaces at end of font change are simulated to
2564 // be outside font change. i.e. we write
2565 // "\textXX{text} " rather than "\textXX{text }".
2567 if (open_font && c == ' ' && i <= size() - 2
2568 && getFont(i + 1) != running_font
2569 && getFont(i + 1) != font) {
2570 font = getFont(i + 1);
2573 // We end font definition before blanks
2574 if (font != running_font && open_font) {
2575 column += running_font.latexWriteEndChanges(os, basefont, font);
2576 running_font = basefont;
2579 // Blanks are printed before start of fontswitch
2581 SimpleTeXBlanks(os, texrow, i,
2582 column, font, style);
2584 // Do we need to change font?
2585 if (font != running_font) {
2587 font.latexWriteStartChanges(os,
2590 running_font = font;
2593 // Do we need to turn on LaTeX mode?
2594 if (font.latex() != running_font.latex()) {
2595 if (font.latex() == LyXFont::ON
2596 && style.needprotect) {
2601 SimpleTeXSpecialChars(os, texrow, font,
2602 running_font, basefont,
2603 open_font, style, i, column, c);
2605 // If we have an open font definition, we have to close it
2607 running_font.latexWriteEndChanges(os, basefont,
2611 basefont = getFont(-1);
2612 running_font = basefont;
2613 cell = table->CellHasContRow(current_cell_number);
2615 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2616 return return_value;
2620 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2622 bool retval = false;
2624 case LyXParagraph::META_HFILL:
2625 sgml_string.clear();
2628 case LyXParagraph::META_PROTECTED_SEPARATOR:
2632 case LyXParagraph::META_NEWLINE:
2636 sgml_string = "&";
2639 sgml_string = "<";
2642 sgml_string = ">";
2645 sgml_string = "$";
2648 sgml_string = "#";
2651 sgml_string = "%";
2654 sgml_string = "[";
2657 sgml_string = "]";
2660 sgml_string = "{";
2663 sgml_string = "}";
2666 sgml_string = "˜";
2669 sgml_string = """;
2672 sgml_string = "\";
2678 case '\0': // Ignore :-)
2679 sgml_string.clear();
2689 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2690 int & desc_on, int depth)
2693 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2695 LyXFont font1, font2;
2698 size_type main_body;
2699 bool emph_flag = false;
2701 LyXLayout const & style =
2702 textclasslist.Style(current_view->buffer()->params.textclass,
2705 if (style.labeltype != LABEL_MANUAL)
2708 main_body = BeginningOfMainBody();
2710 // Gets paragraph main font.
2712 font1 = style.labelfont;
2716 int char_line_count = depth;
2717 os << newlineAndDepth(depth);
2718 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2719 os << "<INFORMALTABLE>"
2720 << newlineAndDepth(++depth);
2722 int current_cell_number = -1;
2723 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2725 // Parsing main loop.
2726 for (size_type i = 0; i < size(); ++i) {
2728 if (table->IsContRow(current_cell_number+1)) {
2729 if (c == LyXParagraph::META_NEWLINE)
2730 ++current_cell_number;
2735 // Fully instantiated font
2738 // Handle <emphasis> tag.
2739 if (font1.emph() != font2.emph() && i) {
2740 if (font2.emph() == LyXFont::ON) {
2743 } else if (emph_flag) {
2744 os << "</emphasis>";
2748 if (c == LyXParagraph::META_NEWLINE) {
2749 // We have only to control for emphasis open here!
2751 os << "</emphasis>";
2754 font1 = font2 = getFont(-1);
2755 ++current_cell_number;
2756 if (table->CellHasContRow(current_cell_number) >= 0) {
2757 DocBookContTableRows(os, extra, desc_on, i + 1,
2758 current_cell_number,
2761 // if this cell follow only ContRows till end don't
2762 // put the EndOfCell because it is put after the
2764 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2765 --current_cell_number;
2768 tmp = table->DocBookEndOfCell(os,
2769 current_cell_number,
2774 } else if (c == LyXParagraph::META_INSET) {
2775 inset = GetInset(i);
2777 std::ostringstream ost;
2778 inset->DocBook(ost);
2779 string tmp_out = ost.str().c_str();
2782 inset->DocBook(ost);
2784 char * ctmp = ost.str();
2785 string tmp_out(ctmp);
2789 // This code needs some explanation:
2790 // Two insets are treated specially
2791 // label if it is the first element in a
2792 // command paragraph
2794 // graphics inside tables or figure floats
2796 // title (the equivalente in latex for this
2798 // and title should come first
2801 if(desc_on != 3 || i != 0) {
2802 if(tmp_out[0] == '@') {
2804 extra += frontStrip(tmp_out,
2807 os << frontStrip(tmp_out,
2812 } else if (font2.latex() == LyXFont::ON) {
2813 // "TeX"-Mode on == > SGML-Mode on.
2819 if (linuxDocConvertChar(c, sgml_string)
2820 && !style.free_spacing) {
2821 // in freespacing mode, spaces are
2822 // non-breaking characters
2827 << "</term><listitem><para>";
2839 // Needed if there is an optional argument but no contents.
2840 if (main_body > 0 && main_body == size()) {
2845 os << "</emphasis>";
2848 ++current_cell_number;
2849 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2850 // Resets description flag correctly.
2853 // <term> not closed...
2857 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2858 os << "</INFORMALTABLE>";
2860 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2865 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
2867 LyXParagraph::size_type i,
2868 int current_cell_number, int &column)
2873 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2878 //string emph = "emphasis";
2879 bool emph_flag = false;
2880 int char_line_count = 0;
2882 LyXLayout const & style =
2883 textclasslist.Style(current_view->buffer()->params.textclass,
2886 size_type main_body;
2887 if (style.labeltype != LABEL_MANUAL)
2890 main_body = BeginningOfMainBody();
2892 // Gets paragraph main font.
2895 font1 = style.labelfont;
2899 size_type lastpos = i;
2900 int cell = table->CellHasContRow(current_cell_number);
2901 ++current_cell_number;
2903 // first find the right position
2905 for (; i < size() && current_cell_number < cell; ++i) {
2907 if (c == LyXParagraph::META_NEWLINE)
2908 ++current_cell_number;
2912 // I don't know how to handle this so I comment it
2913 // for the moment (Jug)
2914 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2915 // file += " \\\\\n";
2918 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2923 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2927 // Fully instantiated font
2930 // Handle <emphasis> tag.
2931 if (font1.emph() != font2.emph() && i) {
2932 if (font2.emph() == LyXFont::ON) {
2935 } else if (emph_flag) {
2936 os << "</emphasis>";
2940 if (c == LyXParagraph::META_INSET) {
2941 inset = GetInset(i);
2943 std::ostringstream ost;
2944 inset->DocBook(ost);
2945 string tmp_out = ost.str().c_str();
2948 inset->DocBook(ost);
2950 char * ctmp = ost.str();
2951 string tmp_out(ctmp);
2955 // This code needs some explanation:
2956 // Two insets are treated specially
2957 // label if it is the first element in a
2958 // command paragraph
2960 // graphics inside tables or figure floats
2961 // can't go on title (the equivalente in
2962 // latex for this case is caption and title
2963 // should come first
2966 if(desc_on != 3 || i != 0) {
2967 if(tmp_out[0] == '@') {
2969 extra += frontStrip(tmp_out, '@');
2971 os << frontStrip(tmp_out, '@');
2975 } else if (font2.latex() == LyXFont::ON) {
2976 // "TeX"-Mode on == > SGML-Mode on.
2982 if (linuxDocConvertChar(c, sgml_string)
2983 && !style.free_spacing) {
2984 // in freespacing mode, spaces are
2985 // non-breaking characters
2990 << "</term><listitem><para>";
3000 // we have only to control for emphasis open here!
3002 os << "</emphasis>";
3005 font1 = font2 = getFont(-1);
3006 cell = table->CellHasContRow(current_cell_number);
3008 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3012 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3013 LyXParagraph::size_type const i,
3014 int & column, LyXFont const & font,
3015 LyXLayout const & style)
3017 if (column > tex_code_break_column
3019 && GetChar(i - 1) != ' '
3021 // In LaTeX mode, we don't want to
3022 // break lines since some commands
3024 && ! (font.latex() == LyXFont::ON)
3025 // same in FreeSpacing mode
3026 && !style.free_spacing
3027 // In typewriter mode, we want to avoid
3028 // ! . ? : at the end of a line
3029 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3030 && (GetChar(i-1) == '.'
3031 || GetChar(i-1) == '?'
3032 || GetChar(i-1) == ':'
3033 || GetChar(i-1) == '!'))) {
3034 if (tex_code_break_column == 0) {
3035 // in batchmode we need LaTeX to still
3036 // see it as a space not as an extra '\n'
3042 texrow.start(this, i + 1);
3044 } else if (font.latex() == LyXFont::OFF) {
3045 if (style.free_spacing) {
3054 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
3056 LyXFont & running_font,
3059 LyXLayout const & style,
3060 LyXParagraph::size_type & i,
3061 int & column, char const c)
3063 // Two major modes: LaTeX or plain
3064 // Handle here those cases common to both modes
3065 // and then split to handle the two modes separately.
3067 case LyXParagraph::META_INSET: {
3068 Inset * inset = GetInset(i);
3071 int len = os.tellp();
3072 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3073 || inset->LyxCode() == Inset::MATH_CODE
3074 || inset->LyxCode() == Inset::URL_CODE)
3075 && running_font.isRightToLeft()) {
3078 } else if (inset->LyxCode() == Inset::NUMBER_CODE
3079 && running_font.isRightToLeft()) {
3084 int tmp = inset->Latex(os, style.isCommand(),
3085 style.free_spacing);
3088 if (inset->LyxCode() == Inset::NUMBER_CODE)
3096 column += os.tellp() - len;
3105 case LyXParagraph::META_NEWLINE:
3107 column += running_font.latexWriteEndChanges(os,
3112 basefont = getFont(-1);
3113 running_font = basefont;
3116 case LyXParagraph::META_HFILL:
3122 // And now for the special cases within each mode
3123 // Are we in LaTeX mode?
3124 if (font.latex() == LyXFont::ON) {
3125 // at present we only have one option
3126 // but I'll leave it as a switch statement
3127 // so its simpler to extend. (ARRae)
3130 case LyXParagraph::META_PROTECTED_SEPARATOR:
3135 // make sure that we will not print
3136 // error generating chars to the tex
3137 // file. This test would not be needed
3138 // if it were done in the buffer
3146 // Plain mode (i.e. not LaTeX)
3149 case LyXParagraph::META_PROTECTED_SEPARATOR:
3154 os << "\\textbackslash{}";
3158 case '°': case '±': case '²': case '³':
3159 case '×': case '÷': case '¹': case 'ª':
3160 case 'º': case '¬': case 'µ':
3161 if (current_view->buffer()->params.inputenc == "latin1") {
3162 os << "\\ensuremath{"
3171 case '|': case '<': case '>':
3172 // In T1 encoding, these characters exist
3173 if (lyxrc.fontenc == "T1") {
3175 //... but we should avoid ligatures
3176 if ((c == '>' || c == '<')
3178 && GetChar(i + 1) == c){
3179 os << "\\textcompwordmark{}";
3184 // Typewriter font also has them
3185 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3189 // Otherwise, we use what LaTeX
3193 os << "\\textless{}";
3197 os << "\\textgreater{}";
3201 os << "\\textbar{}";
3207 case '-': // "--" in Typewriter mode -> "-{}-"
3209 && GetChar(i + 1) == '-'
3210 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3219 os << "\\char`\\\"{}";
3224 if (current_view->buffer()->params.inputenc == "default") {
3233 case '%': case '#': case '{':
3240 os << "\\textasciitilde{}";
3245 os << "\\textasciicircum{}";
3249 case '*': case '[': case ']':
3250 // avoid being mistaken for optional arguments
3251 os << '{' << c << '}';
3256 // Blanks are printed before font switching.
3257 // Sure? I am not! (try nice-latex)
3258 // I am sure it's correct. LyX might be smarter
3259 // in the future, but for now, nothing wrong is
3264 /* idea for labels --- begin*/
3268 && font.family() != LyXFont::TYPEWRITER_FAMILY
3269 && GetChar(i + 1) == 'y'
3270 && GetChar(i + 2) == 'X') {
3278 && font.family() != LyXFont::TYPEWRITER_FAMILY
3279 && GetChar(i + 1) == 'e'
3280 && GetChar(i + 2) == 'X') {
3285 // Check for "LaTeX2e"
3288 && font.family() != LyXFont::TYPEWRITER_FAMILY
3289 && GetChar(i + 1) == 'a'
3290 && GetChar(i + 2) == 'T'
3291 && GetChar(i + 3) == 'e'
3292 && GetChar(i + 4) == 'X'
3293 && GetChar(i + 5) == '2'
3294 && GetChar(i + 6) == 'e') {
3299 // Check for "LaTeX"
3302 && font.family() != LyXFont::TYPEWRITER_FAMILY
3303 && GetChar(i + 1) == 'a'
3304 && GetChar(i + 2) == 'T'
3305 && GetChar(i + 3) == 'e'
3306 && GetChar(i + 4) == 'X') {
3310 /* idea for labels --- end*/
3311 } else if (c != '\0') {
3322 bool LyXParagraph::RoffContTableRows(ostream & os,
3323 LyXParagraph::size_type i,
3329 LyXFont font1(LyXFont::ALL_INHERIT);
3334 string fname2 = TmpFileName(string(), "RAT2");
3336 int cell = table->CellHasContRow(actcell);
3339 // first find the right position
3341 for (; i < size() && actcell < cell; ++i) {
3343 if (c == LyXParagraph::META_NEWLINE)
3348 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3351 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3353 font2 = GetFontSettings(i);
3354 if (font1.latex() != font2.latex()) {
3355 if (font2.latex() != LyXFont::OFF)
3360 case LyXParagraph::META_INSET:
3361 if ((inset = GetInset(i))) {
3364 stringstream ss(ios::in | ios::out);
3365 inset->Latex(ss, -1);
3377 inset->Latex(ss, -1);
3390 fstream fs(fname2.c_str(),
3393 WriteAlert(_("LYX_ERROR:"),
3394 _("Cannot open temporary file:"),
3398 inset->Latex(fs, -1);
3412 case LyXParagraph::META_NEWLINE:
3414 case LyXParagraph::META_HFILL:
3417 case LyXParagraph::META_PROTECTED_SEPARATOR:
3427 lyxerr.debug() << "RoffAsciiTable: "
3428 "NULL char in structure."
3433 cell = table->CellHasContRow(actcell);
3440 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3442 TexRow & foot_texrow,
3445 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3446 LyXParagraph * par = this;
3448 while (par && par->depth == depth) {
3450 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3451 if (textclasslist.Style(current_view->buffer()->params.textclass,
3452 par->layout).isEnvironment()
3453 || par->pextra_type != PEXTRA_NONE) {
3454 par = par->TeXEnvironment(os, texrow,
3458 par = par->TeXOnePar(os, texrow,
3463 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3469 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3471 TexRow & foot_texrow,
3474 bool eindent_open = false;
3475 bool foot_this_level = false;
3476 // flags when footnotetext should be appended to file.
3477 static bool minipage_open = false;
3478 static int minipage_open_depth = 0;
3479 char par_sep = current_view->buffer()->params.paragraph_separation;
3481 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3483 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3485 LyXLayout const & style =
3486 textclasslist.Style(current_view->buffer()->params.textclass,
3489 if (pextra_type == PEXTRA_INDENT) {
3490 if (!pextra_width.empty()) {
3491 os << "\\begin{LyXParagraphIndent}{"
3492 << pextra_width << "}\n";
3494 //float ib = atof(pextra_widthp.c_str())/100;
3495 // string can't handle floats at present (971109)
3496 // so I'll do a conversion by hand knowing that
3497 // the limits are 0.0 to 1.0. ARRae.
3498 os << "\\begin{LyXParagraphIndent}{";
3499 switch (pextra_widthp.length()) {
3511 os << "\\columnwidth}\n";
3514 eindent_open = true;
3516 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3517 if (pextra_hfill && Previous() &&
3518 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3519 os << "\\hfill{}\n";
3522 if (par_sep == BufferParams::PARSEP_INDENT) {
3523 os << "{\\setlength\\parindent{0pt}\n";
3526 os << "\\begin{minipage}";
3527 switch(pextra_alignment) {
3528 case MINIPAGE_ALIGN_TOP:
3531 case MINIPAGE_ALIGN_MIDDLE:
3534 case MINIPAGE_ALIGN_BOTTOM:
3538 if (!pextra_width.empty()) {
3539 os << '{' << pextra_width << "}\n";
3541 //float ib = atof(par->pextra_width.c_str())/100;
3542 // string can't handle floats at present
3543 // so I'll do a conversion by hand knowing that
3544 // the limits are 0.0 to 1.0. ARRae.
3546 switch (pextra_widthp.length()) {
3558 os << "\\columnwidth}\n";
3561 if (par_sep == BufferParams::PARSEP_INDENT) {
3562 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3565 minipage_open = true;
3566 minipage_open_depth = depth;
3569 #ifdef WITH_WARNINGS
3570 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3571 //I disabled it because it breaks when lists span on several
3574 if (style.isEnvironment()){
3575 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3576 #ifdef FANCY_FOOTNOTE_CODE
3577 if (foot_count < 0) {
3578 // flag that footnote[mark][text] should be
3579 // used for any footnotes from now on
3581 foot_this_level = true;
3584 os << "\\begin{" << style.latexname() << "}{"
3585 << labelwidthstring << "}\n";
3586 } else if (style.labeltype == LABEL_BIBLIO) {
3588 os << "\\begin{" << style.latexname() << "}{"
3589 << bibitemWidthest(current_view->painter())
3591 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3592 #ifdef FANCY_FOOTNOTE_CODE
3593 if (foot_count < 0) {
3594 // flag that footnote[mark][text] should be
3595 // used for any footnotes from now on
3597 foot_this_level = true;
3600 os << "\\begin{" << style.latexname() << '}'
3601 << style.latexparam() << '\n';
3603 os << "\\begin{" << style.latexname() << '}'
3604 << style.latexparam() << '\n';
3607 LyXParagraph * par = this;
3609 par = par->TeXOnePar(os, texrow,
3610 foot, foot_texrow, foot_count);
3612 if (minipage_open && par && !style.isEnvironment() &&
3613 (par->pextra_type == PEXTRA_MINIPAGE) &&
3614 par->pextra_start_minipage) {
3615 os << "\\end{minipage}\n";
3617 if (par_sep == BufferParams::PARSEP_INDENT) {
3621 minipage_open = false;
3623 if (par && par->depth > depth) {
3624 if (textclasslist.Style(current_view->buffer()->params.textclass,
3625 par->layout).isParagraph()
3628 // How to handle this? (Lgb)
3629 //&& !suffixIs(os, "\n\n")
3631 // There should be at least one '\n' already
3632 // but we need there to be two for Standard
3633 // paragraphs that are depth-increment'ed to be
3634 // output correctly. However, tables can
3635 // also be paragraphs so don't adjust them.
3638 // Will it ever harm to have one '\n' too
3639 // many? i.e. that we sometimes will have
3640 // three in a row. (Lgb)
3644 par = par->TeXDeeper(os, texrow,
3645 foot, foot_texrow, foot_count);
3647 if (par && par->layout == layout && par->depth == depth &&
3648 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3649 if (par->pextra_hfill && par->Previous() &&
3650 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3651 os << "\\hfill{}\n";
3654 if (par_sep == BufferParams::PARSEP_INDENT) {
3655 os << "{\\setlength\\parindent{0pt}\n";
3658 os << "\\begin{minipage}";
3659 switch(par->pextra_alignment) {
3660 case MINIPAGE_ALIGN_TOP:
3663 case MINIPAGE_ALIGN_MIDDLE:
3666 case MINIPAGE_ALIGN_BOTTOM:
3670 if (!par->pextra_width.empty()) {
3671 os << '{' << par->pextra_width << "}\n";
3673 //float ib = atof(par->pextra_widthp.c_str())/100;
3674 // string can't handle floats at present
3675 // so I'll do a conversion by hand knowing that
3676 // the limits are 0.0 to 1.0. ARRae.
3678 switch (par->pextra_widthp.length()) {
3683 os << "0." << par->pextra_widthp;
3686 os << "0.0" << par->pextra_widthp;
3688 os << "\\columnwidth}\n";
3691 if (par_sep == BufferParams::PARSEP_INDENT) {
3692 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3695 minipage_open = true;
3696 minipage_open_depth = par->depth;
3699 && par->layout == layout
3700 && par->depth == depth
3701 && par->pextra_type == pextra_type);
3703 if (style.isEnvironment()) {
3704 os << "\\end{" << style.latexname() << '}';
3705 // maybe this should go after the minipage closes?
3706 if (foot_this_level) {
3707 if (foot_count >= 1) {
3708 if (foot_count > 1) {
3709 os << "\\addtocounter{footnote}{-"
3714 texrow += foot_texrow;
3716 foot_texrow.reset();
3721 if (minipage_open && (minipage_open_depth == depth) &&
3722 (!par || par->pextra_start_minipage ||
3723 par->pextra_type != PEXTRA_MINIPAGE)) {
3724 os << "\\end{minipage}\n";
3726 if (par_sep == BufferParams::PARSEP_INDENT) {
3730 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3731 os << "\\medskip\n\n";
3735 minipage_open = false;
3738 os << "\\end{LyXParagraphIndent}\n";
3741 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3742 && par->pextra_hfill)) {
3746 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3747 return par; // ale970302
3751 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3752 ostream & foot, TexRow & foot_texrow,
3754 LyXDirection parent_direction)
3756 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3757 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3758 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3759 "No footnote!" << endl;
3761 LyXParagraph * par = this;
3762 LyXLayout const & style =
3763 textclasslist.Style(current_view->buffer()->params.textclass,
3764 previous->GetLayout());
3766 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3767 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3768 "Float other than footnote in command"
3769 " with moving argument is illegal" << endl;
3772 if (footnotekind != LyXParagraph::FOOTNOTE
3773 && footnotekind != LyXParagraph::MARGIN
3776 // How to solve this?
3777 //&& !suffixIs(file, '\n')
3779 // we need to ensure that real floats like tables and figures
3780 // have their \begin{} on a new line otherwise we can get
3781 // incorrect results when using the endfloat.sty package
3782 // especially if two floats follow one another. ARRae 981022
3783 // NOTE: if the file is length 0 it must have just been
3784 // written out so we assume it ended with a '\n'
3786 // As far as I can see there is never any harm in writing
3787 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3792 bool need_closing = false;
3793 LyXDirection direction = getParDirection();
3794 if (direction != parent_direction) {
3795 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3799 need_closing = true;
3802 BufferParams * params = ¤t_view->buffer()->params;
3803 bool footer_in_body = true;
3804 switch (footnotekind) {
3805 case LyXParagraph::FOOTNOTE:
3806 if (style.intitle) {
3807 os << "\\thanks{\n";
3808 footer_in_body = false;
3810 if (foot_count == -1) {
3811 // we're at depth 0 so we can use:
3812 os << "\\footnote{%\n";
3813 footer_in_body = false;
3815 os << "\\footnotemark{}%\n";
3817 // we only need this when there are
3818 // multiple footnotes
3819 os << "\\stepcounter{footnote}";
3821 os << "\\footnotetext{%\n";
3822 foot_texrow.start(this, 0);
3823 foot_texrow.newline();
3828 case LyXParagraph::MARGIN:
3829 os << "\\marginpar{\n";
3831 case LyXParagraph::FIG:
3832 if (pextra_type == PEXTRA_FLOATFLT
3833 && (!pextra_width.empty()
3834 || !pextra_widthp.empty())) {
3835 if (!pextra_width.empty())
3836 os << "\\begin{floatingfigure}{"
3837 << pextra_width << "}\n";
3839 os << "\\begin{floatingfigure}{"
3840 << atoi(pextra_widthp.c_str())/100.0
3841 << "\\textwidth}\n";
3843 os << "\\begin{figure}";
3844 if (!params->float_placement.empty()) {
3845 os << '[' << params->float_placement << "]\n";
3851 case LyXParagraph::TAB:
3852 os << "\\begin{table}";
3853 if (!params->float_placement.empty()) {
3854 os << '[' << params->float_placement << "]\n";
3859 case LyXParagraph::WIDE_FIG:
3860 os << "\\begin{figure*}";
3861 if (!params->float_placement.empty()) {
3862 os << '[' << params->float_placement << "]\n";
3867 case LyXParagraph::WIDE_TAB:
3868 os << "\\begin{table*}";
3869 if (!params->float_placement.empty()) {
3870 os << '[' << params->float_placement << "]\n";
3875 case LyXParagraph::ALGORITHM:
3876 os << "\\begin{algorithm}\n";
3881 if (footnotekind != LyXParagraph::FOOTNOTE
3882 || !footer_in_body) {
3883 // Process text for all floats except footnotes in body
3885 LyXLayout const & style =
3887 .Style(current_view->buffer()->params
3891 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3893 if (style.isEnvironment()
3894 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3895 // Allows the use of minipages within float
3896 // environments. Shouldn't be circular because
3897 // we don't support footnotes inside
3898 // floats (yet). ARRae
3899 par = par->TeXEnvironment(os, texrow,
3903 par = par->TeXOnePar(os, texrow,
3908 if (par && !par->IsDummy() && par->depth > depth) {
3909 par = par->TeXDeeper(os, texrow,
3913 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3915 // process footnotes > depth 0 or in environments separately
3916 // NOTE: Currently don't support footnotes within footnotes
3917 // even though that is possible using the \footnotemark
3919 std::ostringstream dummy;
3923 TexRow dummy_texrow;
3924 int dummy_count = 0;
3926 LyXLayout const & style =
3928 .Style(current_view->buffer()->params
3932 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3934 if (style.isEnvironment()
3935 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3936 // Allows the use of minipages within float
3937 // environments. Shouldn't be circular because
3938 // we don't support footnotes inside
3939 // floats (yet). ARRae
3940 par = par->TeXEnvironment(foot, foot_texrow,
3941 dummy, dummy_texrow,
3944 par = par->TeXOnePar(foot, foot_texrow,
3945 dummy, dummy_texrow,
3949 if (par && !par->IsDummy() && par->depth > depth) {
3950 par = par->TeXDeeper(foot, foot_texrow,
3951 dummy, dummy_texrow,
3955 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3957 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3958 "Footnote in a Footnote -- not supported"
3961 #ifndef HAVE_OSTREAM
3962 delete [] dummy.str();
3966 switch (footnotekind) {
3967 case LyXParagraph::FOOTNOTE:
3968 if (footer_in_body) {
3969 // This helps tell which of the multiple
3970 // footnotetexts an error was in.
3972 foot_texrow.newline();
3977 case LyXParagraph::MARGIN:
3980 case LyXParagraph::FIG:
3981 if (pextra_type == PEXTRA_FLOATFLT
3982 && (!pextra_width.empty()
3983 || !pextra_widthp.empty()))
3984 os << "\\end{floatingfigure}";
3986 os << "\\end{figure}";
3988 case LyXParagraph::TAB:
3989 os << "\\end{table}";
3991 case LyXParagraph::WIDE_FIG:
3992 os << "\\end{figure*}";
3994 case LyXParagraph::WIDE_TAB:
3995 os << "\\end{table*}";
3997 case LyXParagraph::ALGORITHM:
3998 os << "\\end{algorithm}";
4005 if (footnotekind != LyXParagraph::FOOTNOTE
4006 && footnotekind != LyXParagraph::MARGIN) {
4007 // we need to ensure that real floats like tables and figures
4008 // have their \end{} on a line of their own otherwise we can
4009 // get incorrect results when using the endfloat.sty package.
4014 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4019 bool LyXParagraph::IsDummy() const
4021 return (footnoteflag == LyXParagraph::NO_FOOTNOTE && previous
4022 && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4026 void LyXParagraph::SetPExtraType(int type, char const * width,
4027 char const * widthp)
4030 pextra_width = width;
4031 pextra_widthp = widthp;
4033 if (textclasslist.Style(current_view->buffer()->params.textclass,
4034 layout).isEnvironment()) {
4039 while (par && (par->layout == layout)
4040 && (par->depth == depth)) {
4042 par = par->Previous();
4044 par = par->FirstPhysicalPar();
4045 while (par && par->depth > depth) {
4046 par = par->Previous();
4048 par = par->FirstPhysicalPar();
4052 while (par && (par->layout == layout)
4053 && (par->depth == depth)) {
4054 par->pextra_type = type;
4055 par->pextra_width = width;
4056 par->pextra_widthp = widthp;
4057 par = par->NextAfterFootnote();
4058 if (par && (par->depth > depth))
4059 par->SetPExtraType(type, width, widthp);
4060 while (par && ((par->depth > depth) || par->IsDummy()))
4061 par = par->NextAfterFootnote();
4067 void LyXParagraph::UnsetPExtraType()
4069 if (pextra_type == PEXTRA_NONE)
4072 pextra_type = PEXTRA_NONE;
4073 pextra_width.clear();
4074 pextra_widthp.clear();
4076 if (textclasslist.Style(current_view->buffer()->params.textclass,
4077 layout).isEnvironment()) {
4082 while (par && (par->layout == layout)
4083 && (par->depth == depth)) {
4085 par = par->Previous();
4087 par = par->FirstPhysicalPar();
4088 while (par && par->depth > depth) {
4089 par = par->Previous();
4091 par = par->FirstPhysicalPar();
4095 while (par && (par->layout == layout)
4096 && (par->depth == depth)) {
4097 par->pextra_type = PEXTRA_NONE;
4098 par->pextra_width.clear();
4099 par->pextra_widthp.clear();
4100 par = par->NextAfterFootnote();
4101 if (par && (par->depth > depth))
4102 par->UnsetPExtraType();
4103 while (par && ((par->depth > depth) || par->IsDummy()))
4104 par = par->NextAfterFootnote();
4110 bool LyXParagraph::IsHfill(size_type pos) const
4112 return IsHfillChar(GetChar(pos));
4116 bool LyXParagraph::IsInset(size_type pos) const
4118 return IsInsetChar(GetChar(pos));
4122 bool LyXParagraph::IsFloat(size_type pos) const
4124 return IsFloatChar(GetChar(pos));
4128 bool LyXParagraph::IsNewline(size_type pos) const
4130 return pos >= 0 && IsNewlineChar(GetChar(pos));
4134 bool LyXParagraph::IsSeparator(size_type pos) const
4136 return IsSeparatorChar(GetChar(pos));
4140 bool LyXParagraph::IsLineSeparator(size_type pos) const
4142 return IsLineSeparatorChar(GetChar(pos));
4146 bool LyXParagraph::IsKomma(size_type pos) const
4148 return IsKommaChar(GetChar(pos));
4152 /// Used by the spellchecker
4153 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4155 unsigned char c = GetChar(pos);
4156 if (IsLetterChar(c))
4158 // '\0' is not a letter, allthough every string contains "" (below)
4161 // We want to pass the ' and escape chars to ispell
4162 string extra = lyxrc.isp_esc_chars + '\'';
4166 return contains(extra, ch);
4170 bool LyXParagraph::IsWord(size_type pos ) const
4172 return IsWordChar(GetChar(pos)) ;
4175 Language const * LyXParagraph::getParLanguage() const
4177 if (!table && size() > 0)
4178 return FirstPhysicalPar()->GetFirstFontSettings().language();
4180 return previous->getParLanguage();
4182 return current_view->buffer()->params.language_info;
4185 Language const * LyXParagraph::getLetterLanguage(size_type pos) const
4187 return GetFontSettings(pos).language();
4190 LyXDirection LyXParagraph::getParDirection() const
4192 if (!lyxrc.rtl_support || table)
4193 return LYX_DIR_LEFT_TO_RIGHT;
4194 else if (getParLanguage()->RightToLeft)
4195 return LYX_DIR_RIGHT_TO_LEFT;
4197 return LYX_DIR_LEFT_TO_RIGHT;
4201 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4203 if (!lyxrc.rtl_support)
4204 return LYX_DIR_LEFT_TO_RIGHT;
4205 else if (table && IsNewline(pos))
4206 return LYX_DIR_LEFT_TO_RIGHT;
4208 bool is_rtl = GetFontSettings(pos).isVisibleRightToLeft();
4209 if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4210 && !IsLineSeparator(pos + 1)
4211 && !(table && IsNewline(pos + 1))
4212 && ( GetFontSettings(pos - 1).isVisibleRightToLeft() != is_rtl
4213 || GetFontSettings(pos + 1).isVisibleRightToLeft() != is_rtl))
4214 return getParDirection();
4216 return (is_rtl) ? LYX_DIR_RIGHT_TO_LEFT
4217 : LYX_DIR_LEFT_TO_RIGHT;