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"
22 #include "lyxparagraph.h"
23 #include "support/textutils.h"
26 #include "tex-strings.h"
27 #include "bufferparams.h"
28 #include "support/FileInfo.h"
29 #include "support/LAssert.h"
31 #include "LaTeXFeatures.h"
32 #include "insets/insetinclude.h"
33 #include "insets/insetbib.h"
34 #include "support/filetools.h"
35 #include "lyx_gui_misc.h"
37 #include "support/lyxmanip.h"
40 int tex_code_break_column = 72; // needs non-zero initialization. set later.
41 // this is a bad idea, but how can LyXParagraph find its buffer to get
42 // parameters? (JMarc)
43 extern BufferView * current_view;
47 extern string bibitemWidthest(Painter &);
49 // this is a minibuffer
50 static char minibuffer_char;
51 static LyXFont minibuffer_font;
52 static Inset * minibuffer_inset;
55 // Initialization of the counter for the paragraph id's,
56 // declared in lyxparagraph.h
57 unsigned int LyXParagraph::paragraph_id = 0;
60 LyXParagraph::LyXParagraph()
62 text.reserve(500); // is this number too big?
64 for (int i = 0; i < 10; ++i) setCounter(i , 0);
70 footnoteflag = LyXParagraph::NO_FOOTNOTE;
71 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
73 align = LYX_ALIGN_BLOCK;
75 /* table stuff -- begin*/
77 /* table stuff -- end*/
79 bibkey = 0; // ale970302
84 // This konstruktor inserts the new paragraph in a list.
85 LyXParagraph::LyXParagraph(LyXParagraph * par)
88 par->text.resize(par->text.size());
90 for (int i = 0; i < 10; ++i) setCounter(i, 0);
94 // double linked list begin
97 next->previous = this;
99 previous->next = this;
101 footnoteflag = LyXParagraph::NO_FOOTNOTE;
102 footnotekind = LyXParagraph::FOOTNOTE;
104 /* table stuff -- begin*/
106 /* table stuff -- end*/
107 id_ = paragraph_id++;
109 bibkey = 0; // ale970302
115 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
116 char footflag, char dth) const
118 LyXFont font1, font2;
123 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
125 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
127 // The beginning or the end of a footnote environment?
128 if (footflag != footnoteflag) {
129 footflag = footnoteflag;
131 os << "\n\\begin_float "
132 << string_footnotekinds[footnotekind]
135 os << "\n\\end_float ";
139 // The beginning or end of a deeper (i.e. nested) area?
142 while (depth > dth) {
143 os << "\n\\begin_deeper ";
147 while (depth < dth) {
148 os << "\n\\end_deeper ";
154 // First write the layout
156 << textclasslist.NameOfLayout(params.textclass, layout)
159 // Maybe some vertical spaces.
160 if (added_space_top.kind() != VSpace::NONE)
161 os << "\\added_space_top "
162 << added_space_top.asLyXCommand() << " ";
163 if (added_space_bottom.kind() != VSpace::NONE)
164 os << "\\added_space_bottom "
165 << added_space_bottom.asLyXCommand() << " ";
167 // The labelwidth string used in lists.
168 if (!labelwidthstring.empty())
169 os << "\\labelwidthstring "
170 << labelwidthstring << '\n';
172 // Lines above or below?
176 os << "\\line_bottom ";
178 // Pagebreaks above or below?
180 os << "\\pagebreak_top ";
181 if (pagebreak_bottom)
182 os << "\\pagebreak_bottom ";
184 // Start of appendix?
185 if (start_of_appendix)
186 os << "\\start_of_appendix ";
193 if (align != LYX_ALIGN_LAYOUT) {
195 case LYX_ALIGN_LEFT: h = 1; break;
196 case LYX_ALIGN_RIGHT: h = 2; break;
197 case LYX_ALIGN_CENTER: h = 3; break;
198 default: h = 0; break;
200 os << "\\align " << string_align[h] << " ";
202 if (pextra_type != PEXTRA_NONE) {
203 os << "\\pextra_type " << pextra_type;
204 if (pextra_type == PEXTRA_MINIPAGE) {
205 os << " \\pextra_alignment "
208 os << " \\pextra_hfill "
210 if (pextra_start_minipage)
211 os << " \\pextra_start_minipage "
212 << pextra_start_minipage;
214 if (!pextra_width.empty()) {
215 os << " \\pextra_width "
216 << VSpace(pextra_width).asLyXCommand();
217 } else if (!pextra_widthp.empty()) {
218 os << " \\pextra_widthp "
224 // Dummy layout. This means that a footnote ended.
225 os << "\n\\end_float ";
226 footflag = LyXParagraph::NO_FOOTNOTE;
229 // It might be a table.
231 os << "\\LyXTable\n";
239 font1 = LyXFont(LyXFont::ALL_INHERIT,params.language_info);
242 for (size_type i = 0; i < size(); ++i) {
248 // Write font changes
249 font2 = GetFontSettings(i);
250 if (font2 != font1) {
251 font2.lyxWriteChanges(font1, os);
260 Inset const * inset = GetInset(i);
262 if (inset->DirectWrite()) {
263 // international char, let it write
264 // code directly so it's shorter in
268 os << "\n\\begin_inset ";
270 os << "\n\\end_inset \n\n";
276 os << "\n\\newline \n";
280 os << "\n\\hfill \n";
284 case META_PROTECTED_SEPARATOR:
285 os << "\n\\protected_separator \n";
290 os << "\n\\backslash \n";
294 if (i + 1 < size() && GetChar(i + 1) == ' ') {
301 if ((column > 70 && c == ' ')
306 // this check is to amend a bug. LyX sometimes
307 // inserts '\0' this could cause problems.
311 lyxerr << "ERROR (LyXParagraph::writeFile):"
312 " NULL char in structure." << endl;
318 // now write the next paragraph
320 next->writeFile(os, params, footflag, dth);
324 void LyXParagraph::validate(LaTeXFeatures & features) const
326 // this will be useful later
327 LyXLayout const & layout =
328 textclasslist.Style(current_view->buffer()->params.textclass,
332 if (line_top || line_bottom)
333 features.lyxline = true;
336 features.layout[GetLayout()] = true;
339 Language const * doc_language = current_view->buffer()->params.language_info;
340 for (FontList::const_iterator cit = fontlist.begin();
341 cit != fontlist.end(); ++cit) {
342 if ((*cit).font.noun() == LyXFont::ON) {
343 lyxerr[Debug::LATEX] << "font.noun: "
344 << (*cit).font.noun()
346 features.noun = true;
347 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
348 << (*cit).font.stateText()
351 switch ((*cit).font.color()) {
353 case LColor::inherit:
357 features.color = true;
358 lyxerr[Debug::LATEX] << "Color enabled. Font: "
359 << (*cit).font.stateText()
362 Language const * language = (*cit).font.language();
363 if (language != doc_language && language != default_language) {
364 features.UsedLanguages.insert(language);
365 lyxerr[Debug::LATEX] << "Found language "
366 << language->lang << endl;
371 for (InsetList::const_iterator cit = insetlist.begin();
372 cit != insetlist.end(); ++cit) {
374 (*cit).inset->Validate(features);
377 if (table && table->IsLongTable())
378 features.longtable = true;
379 if (pextra_type == PEXTRA_INDENT)
380 features.LyXParagraphIndent = true;
381 if (pextra_type == PEXTRA_FLOATFLT)
382 features.floatflt = true;
383 if (layout.needprotect
384 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
385 features.NeedLyXFootnoteCode = true;
386 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
387 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
388 features.NeedLyXMinipageIndent = true;
389 if (table && table->NeedRotating())
390 features.rotating = true;
391 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
392 features.algorithm = true;
396 // First few functions needed for cut and paste and paragraph breaking.
397 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
399 minibuffer_char = GetChar(pos);
400 minibuffer_font = GetFontSettings(pos);
401 minibuffer_inset = 0;
402 if (minibuffer_char == LyXParagraph::META_INSET) {
404 minibuffer_inset = GetInset(pos)->Clone();
406 minibuffer_inset = 0;
407 minibuffer_char = ' ';
408 // This reflects what GetInset() does (ARRae)
414 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
416 minibuffer_char = GetChar(pos);
417 minibuffer_font = GetFontSettings(pos);
418 minibuffer_inset = 0;
419 if (minibuffer_char == LyXParagraph::META_INSET) {
421 minibuffer_inset = GetInset(pos);
422 // This is a little hack since I want exactly
423 // the inset, not just a clone. Otherwise
424 // the inset would be deleted when calling Erase(pos)
426 for (InsetList::iterator it = insetlist.begin();
427 it != insetlist.end(); ++it) {
428 if ((*it).pos == pos) {
435 minibuffer_inset = 0;
436 minibuffer_char = ' ';
437 // This reflects what GetInset() does (ARRae)
442 // Erase(pos); now the caller is responsible for that.
446 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
448 InsertChar(pos, minibuffer_char);
449 SetFont(pos, minibuffer_font);
450 if (minibuffer_char == LyXParagraph::META_INSET)
451 InsertInset(pos, minibuffer_inset);
458 void LyXParagraph::Clear()
463 pagebreak_top = false;
464 pagebreak_bottom = false;
466 added_space_top = VSpace(VSpace::NONE);
467 added_space_bottom = VSpace(VSpace::NONE);
469 align = LYX_ALIGN_LAYOUT;
473 pextra_type = PEXTRA_NONE;
474 pextra_width.clear();
475 pextra_widthp.clear();
476 pextra_alignment = MINIPAGE_ALIGN_TOP;
477 pextra_hfill = false;
478 pextra_start_minipage = false;
481 labelwidthstring.clear();
485 start_of_appendix = false;
489 // the destructor removes the new paragraph from the list
490 LyXParagraph::~LyXParagraph()
493 previous->next = next;
495 next->previous = previous;
497 for (InsetList::iterator it = insetlist.begin();
498 it != insetlist.end(); ++it) {
502 /* table stuff -- begin*/
504 /* table stuff -- end*/
511 void LyXParagraph::Erase(LyXParagraph::size_type pos)
513 // > because last is the next unused position, and you can
514 // use it if you want
516 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
517 NextAfterFootnote()->Erase(pos - text.size() - 1);
519 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
520 "position does not exist." << endl;
523 if (pos < size()) { // last is free for insertation, but should be empty
524 // if it is an inset, delete the inset entry
525 if (text[pos] == LyXParagraph::META_INSET) {
527 for (InsetList::iterator it = insetlist.begin();
528 it != insetlist.end(); ++it) {
529 if ((*it).pos == pos) {
536 text.erase(text.begin() + pos);
537 // Erase entries in the tables.
538 for (FontList::iterator it = fontlist.begin();
539 it != fontlist.end(); ++it) {
540 if (pos >= (*it).pos && pos <= (*it).pos_end) {
541 if ((*it).pos == (*it).pos_end) {
542 // If it is a multi-character font
543 // entry, we just make it smaller
544 // (see update below), otherwise we
551 // Update all other entries.
552 for (FontList::iterator it = fontlist.begin();
553 it != fontlist.end(); ++it) {
556 if ((*it).pos_end >= pos)
560 // Update the inset table.
561 for (InsetList::iterator it = insetlist.begin();
562 it != insetlist.end(); ++it) {
567 lyxerr << "ERROR (LyXParagraph::Erase): "
568 "can't erase non-existant char." << endl;
573 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
575 // > because last is the next unused position, and you can
576 // use it if you want
579 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
580 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
583 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
584 "position does not exist." << endl;
587 text.insert(text.begin() + pos, c);
588 // Update the font table.
589 for (FontList::iterator it = fontlist.begin();
590 it != fontlist.end(); ++it) {
591 if ((*it).pos >= pos)
593 if ((*it).pos_end >= pos)
597 // Update the inset table.
598 for (InsetList::iterator it = insetlist.begin();
599 it != insetlist.end(); ++it) {
600 if ((*it).pos >= pos)
606 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
609 // > because last is the next unused position, and you can
610 // use it if you want
613 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
615 ->InsertInset(pos - text.size() - 1, inset);
617 lyxerr << "ERROR (LyXParagraph::InsertInset): "
618 "position does not exist: " << pos << endl;
621 if (text[pos] != LyXParagraph::META_INSET) {
622 lyxerr << "ERROR (LyXParagraph::InsertInset): "
623 "there is no LyXParagraph::META_INSET" << endl;
628 // Add a new entry in the inset table.
629 InsetList::iterator it =
630 insetlist.insert(insetlist.begin(), InsetTable());
637 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
641 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
642 return NextAfterFootnote()
643 ->GetInset(pos - text.size() - 1);
645 lyxerr << "ERROR (LyXParagraph::GetInset): "
646 "position does not exist: "
652 for (InsetList::iterator it = insetlist.begin();
653 it != insetlist.end(); ++it) {
654 if ((*it).pos == pos) {
658 lyxerr << "ERROR (LyXParagraph::GetInset): "
659 "Inset does not exist: " << pos << endl;
660 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
661 // Did this commenting out introduce a bug? So far I have not
662 // see any, please enlighten me. (Lgb)
663 // My guess is that since the inset does not exist, we might
664 // as well replace it with a space to prevent craches. (Asger)
669 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
673 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
674 return NextAfterFootnote()
675 ->GetInset(pos - text.size() - 1);
677 lyxerr << "ERROR (LyXParagraph::GetInset): "
678 "position does not exist: "
684 for (InsetList::const_iterator cit = insetlist.begin();
685 cit != insetlist.end(); ++cit) {
686 if ((*cit).pos == pos) {
690 lyxerr << "ERROR (LyXParagraph::GetInset): "
691 "Inset does not exist: " << pos << endl;
692 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
693 // Did this commenting out introduce a bug? So far I have not
694 // see any, please enlighten me. (Lgb)
695 // My guess is that since the inset does not exist, we might
696 // as well replace it with a space to prevent craches. (Asger)
701 // Gets uninstantiated font setting at position.
702 // Optimized after profiling. (Asger)
703 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
706 #ifdef SORTED_FONT_LIST
707 for (FontList::const_iterator cit = fontlist.begin();
708 cit != fontlist.end() && pos <= (*cit).pos_end; ++cit)
709 if (pos >= (*cit).pos)
712 for (FontList::const_iterator cit = fontlist.begin();
713 cit != fontlist.end(); ++cit)
714 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
718 // > because last is the next unused position, and you can
719 // use it if you want
720 else if (pos > size()) {
722 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
723 return NextAfterFootnote()
724 ->GetFontSettings(pos - text.size() - 1);
726 // Why is it an error to ask for the font of a
727 // position that does not exist? Would it be
728 // enough for this to be enabled on debug?
729 // We want strict error checking, but it's ok to only
730 // have it when debugging. (Asger)
731 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
732 "position does not exist. "
733 << pos << " (" << static_cast<int>(pos)
736 } else if (pos > 0) {
737 return GetFontSettings(pos - 1);
738 } else // pos = size() = 0
739 return LyXFont(LyXFont::ALL_INHERIT,getParLanguage());
741 return LyXFont(LyXFont::ALL_INHERIT);
744 // Gets uninstantiated font setting at position 0
745 LyXFont LyXParagraph::GetFirstFontSettings() const
748 #ifdef SORTED_FONT_LIST
749 if (!fontlist.empty() && fontlist.front().pos == 0)
750 return fontlist.front().font;
752 for (FontList::const_iterator cit = fontlist.begin();
753 cit != fontlist.end(); ++cit)
754 if (0 >= (*cit).pos && 0 <= (*cit).pos_end)
758 return LyXFont(LyXFont::ALL_INHERIT);
761 // Gets the fully instantiated font at a given position in a paragraph
762 // This is basically the same function as LyXText::GetFont() in text2.C.
763 // The difference is that this one is used for generating the LaTeX file,
764 // and thus cosmetic "improvements" are disallowed: This has to deliver
765 // the true picture of the buffer. (Asger)
766 // If position is -1, we get the layout font of the paragraph.
767 // If position is -2, we get the font of the manual label of the paragraph.
768 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
771 LyXLayout const & layout =
772 textclasslist.Style(current_view->buffer()->params.textclass,
774 LyXParagraph::size_type main_body = 0;
775 if (layout.labeltype == LABEL_MANUAL)
776 main_body = BeginningOfMainBody();
781 layoutfont = layout.labelfont;
783 layoutfont = layout.font;
784 tmpfont = GetFontSettings(pos);
785 tmpfont.realize(layoutfont);
787 // process layoutfont for pos == -1 and labelfont for pos < -1
789 tmpfont = layout.font;
791 tmpfont = layout.labelfont;
792 tmpfont.setLanguage(getParLanguage());
795 // check for environment font information
796 char par_depth = GetDepth();
797 LyXParagraph const * par = this;
798 while (par && par_depth && !tmpfont.resolved()) {
799 par = par->DepthHook(par_depth - 1);
801 tmpfont.realize(textclasslist.
802 Style(current_view->buffer()->params.textclass,
803 par->GetLayout()).font);
804 par_depth = par->GetDepth();
808 tmpfont.realize(textclasslist
809 .TextClass(current_view->buffer()->params.textclass)
815 /// Returns the height of the highest font in range
817 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
818 LyXParagraph::size_type endpos) const
820 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
821 for (FontList::const_iterator cit = fontlist.begin();
822 cit != fontlist.end(); ++cit) {
823 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
824 LyXFont::FONT_SIZE size = (*cit).font.size();
825 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
833 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
840 // > because last is the next unused position, and you can
841 // use it if you want
842 else if (pos > size()) {
843 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
844 return NextAfterFootnote()
845 ->GetChar(pos - text.size() - 1);
847 lyxerr << "ERROR (LyXParagraph::GetChar): "
848 "position does not exist."
849 << pos << " (" << static_cast<int>(pos)
851 // Assert(false); // This triggers sometimes...
856 // We should have a footnote environment.
857 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
858 // Notice that LyX does request the
859 // last char from time to time. (Asger)
860 //lyxerr << "ERROR (LyXParagraph::GetChar): "
861 // "expected footnote." << endl;
864 switch (next->footnotekind) {
865 case LyXParagraph::FOOTNOTE:
866 return LyXParagraph::META_FOOTNOTE;
867 case LyXParagraph::MARGIN:
868 return LyXParagraph::META_MARGIN;
869 case LyXParagraph::FIG:
870 case LyXParagraph::WIDE_FIG:
871 return LyXParagraph::META_FIG;
872 case LyXParagraph::TAB:
873 case LyXParagraph::WIDE_TAB:
874 return LyXParagraph::META_TAB;
875 case LyXParagraph::ALGORITHM:
876 return LyXParagraph::META_ALGORITHM;
878 return '\0'; // to shut up gcc
883 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
890 // > because last is the next unused position, and you can
891 // use it if you want
892 else if (pos > size()) {
893 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
894 return NextAfterFootnote()
895 ->GetChar(pos - text.size() - 1);
897 lyxerr << "ERROR (LyXParagraph::GetChar const): "
898 "position does not exist."
899 << pos << " (" << static_cast<int>(pos)
905 // We should have a footnote environment.
906 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
907 // Notice that LyX does request the
908 // last char from time to time. (Asger)
909 //lyxerr << "ERROR (LyXParagraph::GetChar): "
910 // "expected footnote." << endl;
913 switch (next->footnotekind) {
914 case LyXParagraph::FOOTNOTE:
915 return LyXParagraph::META_FOOTNOTE;
916 case LyXParagraph::MARGIN:
917 return LyXParagraph::META_MARGIN;
918 case LyXParagraph::FIG:
919 case LyXParagraph::WIDE_FIG:
920 return LyXParagraph::META_FIG;
921 case LyXParagraph::TAB:
922 case LyXParagraph::WIDE_TAB:
923 return LyXParagraph::META_TAB;
924 case LyXParagraph::ALGORITHM:
925 return LyXParagraph::META_ALGORITHM;
927 return '\0'; // to shut up gcc
932 // return an string of the current word, and the end of the word in lastpos.
933 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
937 // the current word is defined as starting at the first character
938 // from the immediate left of lastpospos which meets the definition
939 // of IsLetter(), continuing to the last character to the right
940 // of this meeting IsLetter.
946 // move back until we have a letter
948 //there's no real reason to have firstpos & lastpos as
949 //separate variables as this is written, but maybe someon
950 // will want to return firstpos in the future.
952 //since someone might have typed a punctuation first
953 int firstpos = lastpos;
955 while ((firstpos >= 0) && !IsLetter(firstpos))
958 // now find the beginning by looking for a nonletter
960 while ((firstpos>= 0) && IsLetter(firstpos))
963 // the above is now pointing to the preceeding non-letter
967 // so copy characters into theword until we get a nonletter
968 // note that this can easily exceed lastpos, wich means
969 // that if used in the middle of a word, the whole word
972 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
979 LyXParagraph::size_type LyXParagraph::Last() const
981 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
982 return text.size() + NextAfterFootnote()->Last() + 1;
983 // the 1 is the symbol
990 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
992 // > because last is the next unused position, and you can
993 // use it if you want
996 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
997 return NextAfterFootnote()
998 ->ParFromPos(pos - text.size() - 1);
1000 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1001 "position does not exist." << endl;
1008 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1010 // > because last is the next unused position, and you can
1011 // use it if you want
1014 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1015 return NextAfterFootnote()
1016 ->PositionInParFromPos(pos - text.size() - 1);
1019 "ERROR (LyXParagraph::PositionInParFromPos): "
1020 "position does not exist." << endl;
1028 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1029 LyXFont const & font)
1031 // > because last is the next unused position, and you can
1032 // use it if you want
1035 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1036 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1039 lyxerr << "ERROR (LyXParagraph::SetFont): "
1040 "position does not exist." << endl;
1044 LyXFont patternfont(LyXFont::ALL_INHERIT);
1046 // First, reduce font against layout/label font
1047 // Update: The SetCharFont() routine in text2.C already
1048 // reduces font, so we don't need to do that here. (Asger)
1049 // No need to simplify this because it will disappear
1050 // in a new kernel. (Asger)
1051 // Next search font table
1052 FontList::iterator tmp = fontlist.begin();
1053 for (; tmp != fontlist.end(); ++tmp) {
1054 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1058 if (tmp == fontlist.end()) { // !found
1059 // if we did not find a font entry, but if the font at hand
1060 // is the same as default, we just forget it
1061 if (font == patternfont) return;
1063 // ok, we did not find a font entry. But maybe there is exactly
1064 // the needed font ientry one position left
1065 FontList::iterator tmp2 = fontlist.begin();
1066 for (; tmp2 != fontlist.end(); ++tmp2) {
1067 if (pos - 1 >= (*tmp2).pos
1068 && pos - 1 <= (*tmp2).pos_end)
1071 if (tmp2 != fontlist.end()) {
1072 // ok there is one, maybe it is exactly
1074 if ((*tmp2).font == font) {
1075 // put the position under the font
1080 // Add a new entry in the
1081 // fontlist for the position
1085 ft.font = font; // or patternfont
1086 // It seems that using font instead of patternfont here
1087 // fixes all the problems. This also surfaces a "bug" in
1089 fontlist.insert(fontlist.begin(), ft);
1090 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1092 // more than one character
1093 if (pos == (*tmp).pos) {
1094 // maybe we should enlarge the left fonttable
1095 FontList::iterator tmp2 = fontlist.begin();
1096 for (; tmp2 != fontlist.end(); ++tmp2) {
1097 if (pos - 1 >= (*tmp2).pos
1098 && pos - 1 <= (*tmp2).pos_end)
1101 // Is there is one, and is it exactly
1103 if (tmp2 != fontlist.end() &&
1104 (*tmp2).font == font) {
1105 // Put the position under the font
1111 // Add a new entry in the
1112 // fontlist for the position
1115 ft.pos_end = (*tmp).pos_end;
1116 ft.font = (*tmp).font;
1117 (*tmp).pos_end = pos;
1119 fontlist.insert(fontlist.begin(), ft);
1120 } else if (pos == (*tmp).pos_end) {
1121 // Add a new entry in the
1122 // fontlist for the position
1124 ft.pos = (*tmp).pos;
1125 ft.pos_end = (*tmp).pos_end - 1;
1126 ft.font = (*tmp).font;
1127 (*tmp).pos = (*tmp).pos_end;
1129 fontlist.insert(fontlist.begin(), ft);
1131 // Add a new entry in the
1132 // fontlist for the position
1134 ft.pos = (*tmp).pos;
1135 ft.pos_end = pos - 1;
1136 ft.font = (*tmp).font;
1140 ft2.pos_end = (*tmp).pos_end;
1141 ft2.font = (*tmp).font;
1144 (*tmp).pos_end = pos;
1147 fontlist.insert(fontlist.begin(), ft);
1148 fontlist.insert(fontlist.begin(), ft2);
1156 // This function is able to hide closed footnotes.
1157 LyXParagraph * LyXParagraph::Next()
1159 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1160 LyXParagraph * tmp = next;
1162 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1164 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1165 return tmp->Next(); /* there can be more than one
1166 footnote in a logical
1169 return next; // This should never happen!
1175 LyXParagraph * LyXParagraph::NextAfterFootnote()
1177 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1178 LyXParagraph * tmp = next;
1179 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1181 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1182 return tmp; /* there can be more than one footnote
1183 in a logical paragraph */
1185 return next; // This should never happen!
1191 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1193 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1194 LyXParagraph * tmp = next;
1195 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1197 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1198 return tmp; /* there can be more than one footnote
1199 in a logical paragraph */
1201 return next; // This should never happen!
1207 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1210 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1212 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1213 tmp = tmp->previous;
1214 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1215 return tmp; /* there can be more than one footnote
1216 in a logical paragraph */
1218 return previous; // This should never happen!
1224 LyXParagraph * LyXParagraph::LastPhysicalPar()
1226 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1229 LyXParagraph * tmp = this;
1231 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1232 tmp = tmp->NextAfterFootnote();
1237 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1239 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1242 LyXParagraph const * tmp = this;
1244 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1245 tmp = tmp->NextAfterFootnote();
1250 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1254 LyXParagraph * tmppar = this;
1258 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1259 tmppar = tmppar->previous;
1268 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1272 LyXParagraph const * tmppar = this;
1276 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1277 tmppar = tmppar->previous;
1286 // This function is able to hide closed footnotes.
1287 LyXParagraph * LyXParagraph::Previous()
1289 LyXParagraph * tmp = previous;
1294 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1295 tmp = tmp->previous;
1297 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1298 tmp = tmp->previous;
1299 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1300 return tmp->next->Previous();
1309 // This function is able to hide closed footnotes.
1310 LyXParagraph const * LyXParagraph::Previous() const
1312 LyXParagraph * tmp = previous;
1317 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1318 tmp = tmp->previous;
1320 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1321 tmp = tmp->previous;
1322 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1323 return tmp->next->Previous();
1332 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1335 size_type i, pos_end, pos_first;
1336 // create a new paragraph
1337 LyXParagraph * par = ParFromPos(pos);
1338 LyXParagraph * firstpar = FirstPhysicalPar();
1340 LyXParagraph * tmp = new LyXParagraph(par);
1342 tmp->footnoteflag = footnoteflag;
1343 tmp->footnotekind = footnotekind;
1345 // this is an idea for a more userfriendly layout handling, I will
1346 // see what the users say
1348 // layout stays the same with latex-environments
1350 tmp->SetOnlyLayout(firstpar->layout);
1351 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1354 if (Last() > pos || !Last() || flag == 2) {
1355 tmp->SetOnlyLayout(firstpar->layout);
1356 tmp->align = firstpar->align;
1357 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1359 tmp->line_bottom = firstpar->line_bottom;
1360 firstpar->line_bottom = false;
1361 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1362 firstpar->pagebreak_bottom = false;
1363 tmp->added_space_bottom = firstpar->added_space_bottom;
1364 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1366 tmp->depth = firstpar->depth;
1367 tmp->noindent = firstpar->noindent;
1369 // copy everything behind the break-position
1370 // to the new paragraph
1372 while (ParFromPos(pos_first) != par)
1375 pos_end = pos_first + par->text.size() - 1;
1376 // The constructor has already reserved 500 elements
1377 //if (pos_end > pos)
1378 // tmp->text.reserve(pos_end - pos);
1380 for (i = pos; i <= pos_end; ++i) {
1381 par->CutIntoMinibuffer(i - pos_first);
1382 tmp->InsertFromMinibuffer(i - pos);
1384 tmp->text.resize(tmp->text.size());
1385 for (i = pos_end; i >= pos; --i)
1386 par->Erase(i - pos_first);
1388 par->text.resize(par->text.size());
1391 // just an idea of me
1393 tmp->line_top = firstpar->line_top;
1394 tmp->pagebreak_top = firstpar->pagebreak_top;
1395 tmp->added_space_top = firstpar->added_space_top;
1396 tmp->bibkey = firstpar->bibkey;
1398 // layout stays the same with latex-environments
1400 firstpar->SetOnlyLayout(tmp->layout);
1401 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1402 firstpar->depth = tmp->depth;
1408 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1410 par = par->FirstPhysicalPar();
1411 footnoteflag = par->footnoteflag;
1412 footnotekind = par->footnotekind;
1414 layout = par->layout;
1415 align = par-> align;
1416 SetLabelWidthString(par->labelwidthstring);
1418 line_bottom = par->line_bottom;
1419 pagebreak_bottom = par->pagebreak_bottom;
1420 added_space_bottom = par->added_space_bottom;
1422 line_top = par->line_top;
1423 pagebreak_top = par->pagebreak_top;
1424 added_space_top = par->added_space_top;
1426 pextra_type = par->pextra_type;
1427 pextra_width = par->pextra_width;
1428 pextra_widthp = par->pextra_widthp;
1429 pextra_alignment = par->pextra_alignment;
1430 pextra_hfill = par->pextra_hfill;
1431 pextra_start_minipage = par->pextra_start_minipage;
1433 noindent = par->noindent;
1438 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1440 LyXParagraph * tmppar = this;
1443 && tmppar->previous->footnoteflag ==
1444 LyXParagraph::CLOSED_FOOTNOTE)
1445 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1446 tmppar = tmppar->previous;
1449 return this; // This should never happen!
1455 LyXParagraph * LyXParagraph::Clone() const
1457 // create a new paragraph
1458 LyXParagraph * result = new LyXParagraph;
1460 result->MakeSameLayout(this);
1462 // this is because of the dummy layout of the paragraphs that
1464 result->layout = layout;
1466 /* table stuff -- begin*/
1468 result->table = table->Clone();
1471 /* table stuff -- end*/
1474 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1477 // copy everything behind the break-position to the new paragraph
1479 for (size_type i = 0; i < size(); ++i) {
1480 CopyIntoMinibuffer(i);
1481 result->InsertFromMinibuffer(i);
1483 result->text.resize(result->text.size());
1488 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1490 par = par->FirstPhysicalPar();
1493 par->footnoteflag == footnoteflag &&
1494 par->footnotekind == footnotekind &&
1496 par->layout == layout &&
1498 par->align == align &&
1500 par->line_bottom == line_bottom &&
1501 par->pagebreak_bottom == pagebreak_bottom &&
1502 par->added_space_bottom == added_space_bottom &&
1504 par->line_top == line_top &&
1505 par->pagebreak_top == pagebreak_top &&
1506 par->added_space_top == added_space_top &&
1508 par->pextra_type == pextra_type &&
1509 par->pextra_width == pextra_width &&
1510 par->pextra_widthp == pextra_widthp &&
1511 par->pextra_alignment == pextra_alignment &&
1512 par->pextra_hfill == pextra_hfill &&
1513 par->pextra_start_minipage == pextra_start_minipage &&
1515 par->table == table && // what means: NO TABLE AT ALL
1517 par->noindent == noindent &&
1518 par->depth == depth);
1522 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1524 // create a new paragraph
1525 LyXParagraph * par = ParFromPos(pos);
1527 LyXParagraph * tmp = new LyXParagraph(par);
1529 tmp->MakeSameLayout(par);
1531 // When can pos < Last()?
1532 // I guess pos == Last() is possible.
1534 // copy everything behind the break-position to the new
1536 size_type pos_first = 0;
1537 while (ParFromPos(pos_first) != par)
1539 size_type pos_end = pos_first + par->text.size() - 1;
1540 // make sure there is enough memory for the now larger
1541 // paragraph. This is not neccessary, because
1542 // InsertFromMinibuffer will enlarge the memory (it uses
1543 // InsertChar of course). But doing it by hand
1544 // is MUCH faster! (only one time, not thousend times!!)
1545 // Not needed since the constructor aleady have
1546 // reserved 500 elements in text.
1547 //if (pos_end > pos)
1548 // tmp->text.reserve(pos_end - pos);
1550 for (size_type i = pos; i <= pos_end; ++i) {
1551 par->CutIntoMinibuffer(i - pos_first);
1552 tmp->InsertFromMinibuffer(i - pos);
1554 tmp->text.resize(tmp->text.size());
1555 for (size_type i = pos_end; i >= pos; --i)
1556 par->Erase(i - pos_first);
1558 par->text.resize(par->text.size());
1563 // Be carefull, this does not make any check at all.
1564 void LyXParagraph::PasteParagraph()
1566 // copy the next paragraph to this one
1567 LyXParagraph * the_next = Next();
1569 LyXParagraph * firstpar = FirstPhysicalPar();
1571 // first the DTP-stuff
1572 firstpar->line_bottom = the_next->line_bottom;
1573 firstpar->added_space_bottom = the_next->added_space_bottom;
1574 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1576 size_type pos_end = the_next->text.size() - 1;
1577 size_type pos_insert = Last();
1579 // ok, now copy the paragraph
1580 for (size_type i = 0; i <= pos_end; ++i) {
1581 the_next->CutIntoMinibuffer(i);
1582 InsertFromMinibuffer(pos_insert + i);
1585 // delete the next paragraph
1590 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1592 LyXParagraph * par = ParFromPos(pos);
1594 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1595 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1601 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1603 LyXParagraph * par = ParFromPos(pos);
1605 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1606 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1611 int LyXParagraph::GetEndLabel() const
1613 LyXParagraph const * par = this;
1614 int par_depth = GetDepth();
1616 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1618 textclasslist.Style(current_view->buffer()->params.textclass,
1619 layout).endlabeltype;
1620 if (endlabeltype != END_LABEL_NO_LABEL) {
1621 LyXParagraph const * last = this;
1622 if( footnoteflag == NO_FOOTNOTE)
1623 last = LastPhysicalPar();
1624 else if (next->footnoteflag == NO_FOOTNOTE)
1625 return endlabeltype;
1627 if (!last || !last->next)
1628 return endlabeltype;
1630 int next_depth = last->next->GetDepth();
1631 if (par_depth > next_depth ||
1632 (par_depth == next_depth && layout != last->next->GetLayout() ))
1633 return endlabeltype;
1638 par = par->DepthHook(par_depth - 1);
1640 par_depth = par->GetDepth();
1642 return END_LABEL_NO_LABEL;
1645 LyXTextClass::size_type LyXParagraph::GetLayout() const
1647 return FirstPhysicalPar()->layout;
1651 char LyXParagraph::GetDepth() const
1653 return FirstPhysicalPar()->depth;
1657 char LyXParagraph::GetAlign() const
1659 return FirstPhysicalPar()->align;
1663 string LyXParagraph::GetLabestring() const
1665 return FirstPhysicalPar()->labelstring;
1669 int LyXParagraph::GetFirstCounter(int i) const
1671 return FirstPhysicalPar()->counter_[i];
1675 // the next two functions are for the manual labels
1676 string LyXParagraph::GetLabelWidthString() const
1678 if (!FirstPhysicalPar()->labelwidthstring.empty())
1679 return FirstPhysicalPar()->labelwidthstring;
1681 return _("Senseless with this layout!");
1685 void LyXParagraph::SetLabelWidthString(string const & s)
1687 LyXParagraph * par = FirstPhysicalPar();
1689 par->labelwidthstring = s;
1693 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1695 LyXParagraph * par = FirstPhysicalPar();
1696 LyXParagraph * ppar = 0;
1697 LyXParagraph * npar = 0;
1699 par->layout = new_layout;
1700 /* table stuff -- begin*/
1703 /* table stuff -- end*/
1704 if (par->pextra_type == PEXTRA_NONE) {
1705 if (par->Previous()) {
1706 ppar = par->Previous()->FirstPhysicalPar();
1709 && (ppar->depth > par->depth))
1710 ppar = ppar->Previous()->FirstPhysicalPar();
1713 npar = par->Next()->NextAfterFootnote();
1716 && (npar->depth > par->depth))
1717 npar = npar->Next()->NextAfterFootnote();
1719 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1721 p1 = ppar->pextra_width,
1722 p2 = ppar->pextra_widthp;
1723 ppar->SetPExtraType(ppar->pextra_type,
1724 p1.c_str(), p2.c_str());
1726 if ((par->pextra_type == PEXTRA_NONE) &&
1727 npar && (npar->pextra_type != PEXTRA_NONE)) {
1729 p1 = npar->pextra_width,
1730 p2 = npar->pextra_widthp;
1731 npar->SetPExtraType(npar->pextra_type,
1732 p1.c_str(), p2.c_str());
1738 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1741 * par = FirstPhysicalPar(),
1745 par->layout = new_layout;
1746 par->labelwidthstring.clear();
1747 par->align = LYX_ALIGN_LAYOUT;
1748 par->added_space_top = VSpace(VSpace::NONE);
1749 par->added_space_bottom = VSpace(VSpace::NONE);
1750 /* table stuff -- begin*/
1753 /* table stuff -- end*/
1754 if (par->pextra_type == PEXTRA_NONE) {
1755 if (par->Previous()) {
1756 ppar = par->Previous()->FirstPhysicalPar();
1759 && (ppar->depth > par->depth))
1760 ppar = ppar->Previous()->FirstPhysicalPar();
1763 npar = par->Next()->NextAfterFootnote();
1766 && (npar->depth > par->depth))
1767 npar = npar->Next()->NextAfterFootnote();
1769 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1771 p1 = ppar->pextra_width,
1772 p2 = ppar->pextra_widthp;
1773 ppar->SetPExtraType(ppar->pextra_type,
1774 p1.c_str(), p2.c_str());
1776 if ((par->pextra_type == PEXTRA_NONE) &&
1777 npar && (npar->pextra_type != PEXTRA_NONE)) {
1779 p1 = npar->pextra_width,
1780 p2 = npar->pextra_widthp;
1781 npar->SetPExtraType(npar->pextra_type,
1782 p1.c_str(), p2.c_str());
1788 // if the layout of a paragraph contains a manual label, the beginning of the
1789 // main body is the beginning of the second word. This is what the par-
1790 // function returns. If the layout does not contain a label, the main
1791 // body always starts with position 0. This differentiation is necessary,
1792 // because there cannot be a newline or a blank <= the beginning of the
1793 // main body in TeX.
1795 int LyXParagraph::BeginningOfMainBody() const
1797 if (FirstPhysicalPar() != this)
1800 // Unroll the first two cycles of the loop
1801 // and remember the previous character to
1802 // remove unnecessary GetChar() calls
1805 && GetChar(i) != LyXParagraph::META_NEWLINE
1808 char previous_char = 0, temp = 0;
1810 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1811 // Yes, this ^ is supposed to be "= " not "=="
1814 && previous_char != ' '
1815 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1817 previous_char = temp;
1822 if (i == 0 && i == size() &&
1823 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1824 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1825 ++i; /* the cursor should not jump
1826 * to the main body if there
1832 LyXParagraph * LyXParagraph::DepthHook(int deth)
1834 LyXParagraph * newpar = this;
1839 newpar = newpar->FirstPhysicalPar()->Previous();
1840 } while (newpar && newpar->GetDepth() > deth
1841 && newpar->footnoteflag == footnoteflag);
1844 if (Previous() || GetDepth())
1845 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1849 return newpar->FirstPhysicalPar();
1853 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1855 LyXParagraph const * newpar = this;
1860 newpar = newpar->FirstPhysicalPar()->Previous();
1861 } while (newpar && newpar->GetDepth() > deth
1862 && newpar->footnoteflag == footnoteflag);
1865 if (Previous() || GetDepth())
1866 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1870 return newpar->FirstPhysicalPar();
1874 int LyXParagraph::AutoDeleteInsets()
1876 vector<size_type> tmpvec;
1878 for (InsetList::iterator it = insetlist.begin();
1879 it != insetlist.end(); ++it) {
1880 if ((*it).inset && (*it).inset->AutoDelete()) {
1881 tmpvec.push_back((*it).pos);
1885 for (vector<size_type>::const_iterator cit = tmpvec.begin();
1886 cit != tmpvec.end(); ++cit) {
1893 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1895 InsetList::iterator it2 = insetlist.end();
1896 for (InsetList::iterator it = insetlist.begin();
1897 it != insetlist.end(); ++it) {
1898 if ((*it).pos >= pos) {
1899 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1903 if (it2 != insetlist.end()) {
1905 return (*it2).inset;
1911 // returns -1 if inset not found
1912 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1915 for (InsetList::const_iterator cit = insetlist.begin();
1916 cit != insetlist.end(); ++cit) {
1917 if ((*cit).inset == inset) {
1921 // Think about footnotes.
1922 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1923 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1925 NextAfterFootnote()->GetPositionOfInset(inset);
1927 return text.size() + 1 + further;
1933 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1934 ostream & foot, TexRow & foot_texrow,
1937 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1938 LyXLayout const & style =
1939 textclasslist.Style(current_view->buffer()->params.textclass,
1942 bool further_blank_line = false;
1944 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1946 if (start_of_appendix) {
1947 os << "\\appendix\n";
1951 if (tex_code_break_column && style.isCommand()){
1956 if (pagebreak_top) {
1958 further_blank_line = true;
1960 if (added_space_top.kind() != VSpace::NONE) {
1961 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1962 further_blank_line = true;
1966 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1967 << "\\vspace{-1\\parskip}";
1968 further_blank_line = true;
1971 if (further_blank_line){
1976 Language const * language = getParLanguage();
1977 Language const * doc_language = current_view->buffer()->params.language_info;
1978 if (language != doc_language) {
1979 os << subst(lyxrc.language_command_begin, "$$lang",
1985 switch (style.latextype) {
1988 << style.latexname()
1989 << style.latexparam();
1991 case LATEX_ITEM_ENVIRONMENT:
1993 bibkey->Latex(os, false, false);
1997 case LATEX_LIST_ENVIRONMENT:
2004 bool need_par = SimpleTeXOnePar(os, texrow);
2006 // Spit out footnotes
2007 LyXParagraph * par = next;
2008 if (lyxrc.rtl_support) {
2009 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2010 && next->footnoteflag != footnoteflag) {
2011 LyXParagraph * p = 0;
2012 bool is_rtl = GetFontSettings(size()-1).isRightToLeft();
2013 if ( (p = NextAfterFootnote()) != 0 &&
2014 p->GetFontSettings(0).isRightToLeft() != is_rtl)
2015 is_rtl = GetFontSettings(0).isRightToLeft();
2017 par->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2018 par->footnoteflag != footnoteflag) {
2019 LyXDirection dir = (is_rtl)
2020 ? LYX_DIR_RIGHT_TO_LEFT
2021 : LYX_DIR_LEFT_TO_RIGHT;
2022 par = par->TeXFootnote(os, texrow, foot,
2023 foot_texrow, foot_count,
2025 par->SimpleTeXOnePar(os, texrow);
2026 is_rtl = par->GetFontSettings(par->size()-1).isRightToLeft();
2028 par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2029 (p = par->NextAfterFootnote()) != 0 &&
2030 p->GetFontSettings(0).isRightToLeft() != is_rtl)
2031 is_rtl = GetFontSettings(0).isRightToLeft();
2036 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2037 && par->footnoteflag != footnoteflag) {
2038 par = par->TeXFootnote(os, texrow,
2039 foot, foot_texrow, foot_count,
2040 LYX_DIR_LEFT_TO_RIGHT);
2041 par->SimpleTeXOnePar(os, texrow);
2046 // Make sure that \\par is done with the font of the last
2047 // character if this has another size as the default.
2048 // This is necessary because LaTeX (and LyX on the screen)
2049 // calculates the space between the baselines according
2050 // to this font. (Matthias)
2051 LyXFont font = getFont(Last() - 1);
2053 if (style.resfont.size() != font.size()) {
2059 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2060 GetLayout()).isCommand()){
2061 if (style.resfont.size() != font.size()) {
2067 } else if (style.resfont.size() != font.size()){
2068 os << "{\\" << font.latexSize() << " \\par}";
2071 if (language != doc_language) {
2073 << subst(lyxrc.language_command_end, "$$lang",
2074 doc_language->lang);
2077 switch (style.latextype) {
2078 case LATEX_ITEM_ENVIRONMENT:
2079 case LATEX_LIST_ENVIRONMENT:
2080 if (par && (depth < par->depth)) {
2085 case LATEX_ENVIRONMENT:
2086 // if its the last paragraph of the current environment
2087 // skip it otherwise fall through
2089 && (par->layout != layout
2090 || par->depth != depth
2091 || par->pextra_type != pextra_type))
2094 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2095 && footnotekind != LyXParagraph::FOOTNOTE
2096 && footnotekind != LyXParagraph::MARGIN
2100 // don't insert this if we would be adding it
2101 // before or after a table in a float. This
2102 // little trick is needed in order to allow
2103 // use of tables in \subfigures or \subtables.
2109 further_blank_line = false;
2111 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2112 further_blank_line = true;
2115 if (added_space_bottom.kind() != VSpace::NONE) {
2116 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2117 further_blank_line = true;
2120 if (pagebreak_bottom) {
2122 further_blank_line = true;
2125 if (further_blank_line){
2130 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2131 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2136 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2141 // This one spits out the text of the paragraph
2142 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2144 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2147 return SimpleTeXOneTablePar(os, texrow);
2149 bool return_value = false;
2151 LyXLayout const & style =
2152 textclasslist.Style(current_view->buffer()->params.textclass,
2154 LyXFont basefont, last_font;
2156 // Maybe we have to create a optional argument.
2157 size_type main_body;
2158 if (style.labeltype != LABEL_MANUAL)
2161 main_body = BeginningOfMainBody();
2163 if (main_body > 0) {
2165 basefont = getFont(-2); // Get label font
2167 basefont = getFont(-1); // Get layout font
2175 if (style.isCommand()) {
2178 } else if (align != LYX_ALIGN_LAYOUT) {
2181 return_value = true;
2185 // Which font is currently active?
2186 LyXFont running_font(basefont);
2187 // Do we have an open font change?
2188 bool open_font = false;
2190 texrow.start(this, 0);
2192 for (size_type i = 0; i < size(); ++i) {
2194 // First char in paragraph or after label?
2195 if (i == main_body && !IsDummy()) {
2196 if (main_body > 0) {
2198 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2201 basefont = getFont(-1); // Now use the layout font
2202 running_font = basefont;
2206 if (style.isCommand()) {
2209 } else if (align != LYX_ALIGN_LAYOUT) {
2212 return_value = true;
2216 os << "\\noindent ";
2220 case LYX_ALIGN_NONE:
2221 case LYX_ALIGN_BLOCK:
2222 case LYX_ALIGN_LAYOUT:
2223 case LYX_ALIGN_SPECIAL:
2225 case LYX_ALIGN_LEFT:
2226 if (getParLanguage()->lang != "hebrew") {
2227 os << "\\raggedright ";
2230 os << "\\raggedleft ";
2234 case LYX_ALIGN_RIGHT:
2235 if (getParLanguage()->lang != "hebrew") {
2236 os << "\\raggedleft ";
2239 os << "\\raggedright ";
2243 case LYX_ALIGN_CENTER:
2244 os << "\\centering ";
2252 // Fully instantiated font
2253 LyXFont font = getFont(i);
2254 LyXParagraph * p = 0;
2255 if (i == 0 && previous &&
2256 previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2257 (p = PreviousBeforeFootnote()) != 0)
2258 last_font = p->getFont(p->size()-1);
2260 last_font = running_font;
2262 // Spaces at end of font change are simulated to be
2263 // outside font change, i.e. we write "\textXX{text} "
2264 // rather than "\textXX{text }". (Asger)
2265 if (open_font && c == ' ' && i <= size() - 2
2266 && !getFont(i+1).equalExceptLatex(running_font)
2267 && !getFont(i+1).equalExceptLatex(font)) {
2268 font = getFont(i + 1);
2270 // We end font definition before blanks
2271 if (!font.equalExceptLatex(running_font) && open_font) {
2272 column += running_font.latexWriteEndChanges(os,
2274 (i == main_body-1) ? basefont : font);
2275 running_font = basefont;
2279 // Blanks are printed before start of fontswitch
2281 // Do not print the separation of the optional argument
2282 if (i != main_body - 1) {
2283 SimpleTeXBlanks(os, texrow, i,
2284 column, font, style);
2288 // Do we need to change font?
2289 if (!font.equalExceptLatex(running_font)
2290 && i != main_body-1) {
2291 column += font.latexWriteStartChanges(os, basefont,
2293 running_font = font;
2297 if (c == LyXParagraph::META_NEWLINE) {
2298 // newlines are handled differently here than
2299 // the default in SimpleTeXSpecialChars().
2300 if (!style.newline_allowed
2301 || font.latex() == LyXFont::ON) {
2305 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2308 basefont = getFont(-1);
2309 running_font = basefont;
2310 if (font.family() ==
2311 LyXFont::TYPEWRITER_FAMILY) {
2317 texrow.start(this, i + 1);
2320 SimpleTeXSpecialChars(os, texrow,
2321 font, running_font, basefont,
2322 open_font, style, i, column, c);
2326 // If we have an open font definition, we have to close it
2328 LyXParagraph * p = 0;
2329 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2330 && (p = NextAfterFootnote()) != 0)
2331 running_font.latexWriteEndChanges(os, basefont,
2334 running_font.latexWriteEndChanges(os, basefont, basefont);
2337 // Needed if there is an optional argument but no contents.
2338 if (main_body > 0 && main_body == size()) {
2340 return_value = false;
2343 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2344 return return_value;
2348 // This one spits out the text of a table paragraph
2349 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2351 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2353 bool return_value = false;
2355 LyXLayout const & style =
2356 textclasslist.Style(current_view->buffer()->params.textclass,
2360 if (!IsDummy()) { // it is dummy if it is in a float!!!
2361 if (style.isCommand()) {
2364 } else if (align != LYX_ALIGN_LAYOUT) {
2367 return_value = true;
2370 os << "\\noindent ";
2374 case LYX_ALIGN_NONE:
2375 case LYX_ALIGN_BLOCK:
2376 case LYX_ALIGN_LAYOUT:
2377 case LYX_ALIGN_SPECIAL: break;
2378 case LYX_ALIGN_LEFT:
2379 os << "\\raggedright ";
2382 case LYX_ALIGN_RIGHT:
2383 os << "\\raggedleft ";
2386 case LYX_ALIGN_CENTER:
2387 os << "\\centering ";
2393 LyXFont basefont = getFont(-1); // Get layout font
2394 // Which font is currently active?
2395 LyXFont running_font = basefont;
2397 // Do we have an open font change?
2398 bool open_font = false;
2399 int current_cell_number = -1;
2400 int tmp = table->TexEndOfCell(os, current_cell_number);
2401 for (; tmp > 0 ; --tmp)
2404 texrow.start(this, 0);
2406 for (size_type i = 0; i < size(); ++i) {
2407 char c = GetChar(i);
2408 if (table->IsContRow(current_cell_number + 1)) {
2409 if (c == LyXParagraph::META_NEWLINE)
2410 ++current_cell_number;
2415 // Fully instantiated font
2416 LyXFont font = getFont(i);
2417 last_font = running_font;
2419 // Spaces at end of font change are simulated to be
2420 // outside font change.
2421 // i.e. we write "\textXX{text} " rather than
2422 // "\textXX{text }". (Asger)
2423 if (open_font && c == ' ' && i <= size() - 2
2424 && getFont(i + 1) != running_font
2425 && getFont(i + 1) != font) {
2426 font = getFont(i + 1);
2429 // We end font definition before blanks
2430 if (font != running_font && open_font) {
2431 column += running_font.latexWriteEndChanges(os,
2434 running_font = basefont;
2437 // Blanks are printed before start of fontswitch
2439 SimpleTeXBlanks(os, texrow, i, column, font, style);
2441 // Do we need to change font?
2442 if (font != running_font) {
2443 column += font.latexWriteStartChanges(os, basefont,
2445 running_font = font;
2448 // Do we need to turn on LaTeX mode?
2449 if (font.latex() != running_font.latex()) {
2450 if (font.latex() == LyXFont::ON
2451 && style.needprotect) {
2456 if (c == LyXParagraph::META_NEWLINE) {
2457 // special case for inside a table
2458 // different from default case in
2459 // SimpleTeXSpecialChars()
2461 column += running_font
2462 .latexWriteEndChanges(os, basefont,
2466 basefont = getFont(-1);
2467 running_font = basefont;
2468 ++current_cell_number;
2469 if (table->CellHasContRow(current_cell_number) >= 0) {
2470 TeXContTableRows(os, i + 1,
2471 current_cell_number,
2474 // if this cell follow only ContRows till end don't
2475 // put the EndOfCell because it is put after the
2477 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2478 --current_cell_number;
2481 int tmp = table->TexEndOfCell(os,
2482 current_cell_number);
2485 } else if (tmp < 0) {
2491 texrow.start(this, i + 1);
2493 SimpleTeXSpecialChars(os, texrow,
2494 font, running_font, basefont,
2495 open_font, style, i, column, c);
2499 // If we have an open font definition, we have to close it
2501 running_font.latexWriteEndChanges(os, basefont, basefont);
2503 ++current_cell_number;
2504 tmp = table->TexEndOfCell(os, current_cell_number);
2505 for (; tmp > 0; --tmp)
2507 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2508 return return_value;
2512 // This one spits out the text off ContRows in tables
2513 bool LyXParagraph::TeXContTableRows(ostream & os,
2514 LyXParagraph::size_type i,
2515 int current_cell_number,
2516 int & column, TexRow & texrow)
2518 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2524 bool return_value = false;
2525 LyXLayout const & style =
2526 textclasslist.Style(current_view->buffer()->params.textclass,
2528 LyXFont basefont = getFont(-1); // Get layout font
2530 // Which font is currently active?
2531 LyXFont running_font = basefont;
2532 // Do we have an open font change?
2533 bool open_font = false;
2535 size_type lastpos = i;
2536 int cell = table->CellHasContRow(current_cell_number);
2537 ++current_cell_number;
2539 // first find the right position
2541 for (; (i < size()) && (current_cell_number<cell); ++i) {
2543 if (c == LyXParagraph::META_NEWLINE)
2544 ++current_cell_number;
2548 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2552 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2557 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2561 // Fully instantiated font
2562 LyXFont font = getFont(i);
2563 last_font = running_font;
2565 // Spaces at end of font change are simulated to
2566 // be outside font change. i.e. we write
2567 // "\textXX{text} " rather than "\textXX{text }".
2569 if (open_font && c == ' ' && i <= size() - 2
2570 && getFont(i + 1) != running_font
2571 && getFont(i + 1) != font) {
2572 font = getFont(i + 1);
2575 // We end font definition before blanks
2576 if (font != running_font && open_font) {
2577 column += running_font.latexWriteEndChanges(os, basefont, font);
2578 running_font = basefont;
2581 // Blanks are printed before start of fontswitch
2583 SimpleTeXBlanks(os, texrow, i,
2584 column, font, style);
2586 // Do we need to change font?
2587 if (font != running_font) {
2589 font.latexWriteStartChanges(os,
2592 running_font = font;
2595 // Do we need to turn on LaTeX mode?
2596 if (font.latex() != running_font.latex()) {
2597 if (font.latex() == LyXFont::ON
2598 && style.needprotect) {
2603 SimpleTeXSpecialChars(os, texrow, font,
2604 running_font, basefont,
2605 open_font, style, i, column, c);
2607 // If we have an open font definition, we have to close it
2609 running_font.latexWriteEndChanges(os, basefont,
2613 basefont = getFont(-1);
2614 running_font = basefont;
2615 cell = table->CellHasContRow(current_cell_number);
2617 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2618 return return_value;
2622 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2624 bool retval = false;
2626 case LyXParagraph::META_HFILL:
2627 sgml_string.clear();
2630 case LyXParagraph::META_PROTECTED_SEPARATOR:
2634 case LyXParagraph::META_NEWLINE:
2638 sgml_string = "&";
2641 sgml_string = "<";
2644 sgml_string = ">";
2647 sgml_string = "$";
2650 sgml_string = "#";
2653 sgml_string = "%";
2656 sgml_string = "[";
2659 sgml_string = "]";
2662 sgml_string = "{";
2665 sgml_string = "}";
2668 sgml_string = "˜";
2671 sgml_string = """;
2674 sgml_string = "\";
2680 case '\0': // Ignore :-)
2681 sgml_string.clear();
2691 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2692 int & desc_on, int depth)
2695 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2697 LyXFont font1, font2;
2700 size_type main_body;
2701 bool emph_flag = false;
2703 LyXLayout const & style =
2704 textclasslist.Style(current_view->buffer()->params.textclass,
2707 if (style.labeltype != LABEL_MANUAL)
2710 main_body = BeginningOfMainBody();
2712 // Gets paragraph main font.
2714 font1 = style.labelfont;
2718 int char_line_count = depth;
2719 os << newlineAndDepth(depth);
2720 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2721 os << "<INFORMALTABLE>"
2722 << newlineAndDepth(++depth);
2724 int current_cell_number = -1;
2725 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2727 // Parsing main loop.
2728 for (size_type i = 0; i < size(); ++i) {
2730 if (table->IsContRow(current_cell_number+1)) {
2731 if (c == LyXParagraph::META_NEWLINE)
2732 ++current_cell_number;
2737 // Fully instantiated font
2740 // Handle <emphasis> tag.
2741 if (font1.emph() != font2.emph() && i) {
2742 if (font2.emph() == LyXFont::ON) {
2745 } else if (emph_flag) {
2746 os << "</emphasis>";
2750 if (c == LyXParagraph::META_NEWLINE) {
2751 // We have only to control for emphasis open here!
2753 os << "</emphasis>";
2756 font1 = font2 = getFont(-1);
2757 ++current_cell_number;
2758 if (table->CellHasContRow(current_cell_number) >= 0) {
2759 DocBookContTableRows(os, extra, desc_on, i + 1,
2760 current_cell_number,
2763 // if this cell follow only ContRows till end don't
2764 // put the EndOfCell because it is put after the
2766 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2767 --current_cell_number;
2770 tmp = table->DocBookEndOfCell(os,
2771 current_cell_number,
2776 } else if (c == LyXParagraph::META_INSET) {
2777 inset = GetInset(i);
2780 inset->DocBook(ost);
2781 string tmp_out = ost.str().c_str();
2784 inset->DocBook(ost);
2786 char * ctmp = ost.str();
2787 string tmp_out(ctmp);
2791 // This code needs some explanation:
2792 // Two insets are treated specially
2793 // label if it is the first element in a
2794 // command paragraph
2796 // graphics inside tables or figure floats
2798 // title (the equivalente in latex for this
2800 // and title should come first
2803 if(desc_on != 3 || i != 0) {
2804 if(tmp_out[0] == '@') {
2806 extra += frontStrip(tmp_out,
2809 os << frontStrip(tmp_out,
2814 } else if (font2.latex() == LyXFont::ON) {
2815 // "TeX"-Mode on == > SGML-Mode on.
2821 if (linuxDocConvertChar(c, sgml_string)
2822 && !style.free_spacing) {
2823 // in freespacing mode, spaces are
2824 // non-breaking characters
2829 << "</term><listitem><para>";
2841 // Needed if there is an optional argument but no contents.
2842 if (main_body > 0 && main_body == size()) {
2847 os << "</emphasis>";
2850 ++current_cell_number;
2851 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2852 // Resets description flag correctly.
2855 // <term> not closed...
2859 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2860 os << "</INFORMALTABLE>";
2862 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2867 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
2869 LyXParagraph::size_type i,
2870 int current_cell_number, int &column)
2875 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2880 //string emph = "emphasis";
2881 bool emph_flag = false;
2882 int char_line_count = 0;
2884 LyXLayout const & style =
2885 textclasslist.Style(current_view->buffer()->params.textclass,
2888 size_type main_body;
2889 if (style.labeltype != LABEL_MANUAL)
2892 main_body = BeginningOfMainBody();
2894 // Gets paragraph main font.
2897 font1 = style.labelfont;
2901 size_type lastpos = i;
2902 int cell = table->CellHasContRow(current_cell_number);
2903 ++current_cell_number;
2905 // first find the right position
2907 for (; i < size() && current_cell_number < cell; ++i) {
2909 if (c == LyXParagraph::META_NEWLINE)
2910 ++current_cell_number;
2914 // I don't know how to handle this so I comment it
2915 // for the moment (Jug)
2916 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2917 // file += " \\\\\n";
2920 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2925 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2929 // Fully instantiated font
2932 // Handle <emphasis> tag.
2933 if (font1.emph() != font2.emph() && i) {
2934 if (font2.emph() == LyXFont::ON) {
2937 } else if (emph_flag) {
2938 os << "</emphasis>";
2942 if (c == LyXParagraph::META_INSET) {
2943 inset = GetInset(i);
2946 inset->DocBook(ost);
2947 string tmp_out = ost.str().c_str();
2950 inset->DocBook(ost);
2952 char * ctmp = ost.str();
2953 string tmp_out(ctmp);
2957 // This code needs some explanation:
2958 // Two insets are treated specially
2959 // label if it is the first element in a
2960 // command paragraph
2962 // graphics inside tables or figure floats
2963 // can't go on title (the equivalente in
2964 // latex for this case is caption and title
2965 // should come first
2968 if(desc_on != 3 || i != 0) {
2969 if(tmp_out[0] == '@') {
2971 extra += frontStrip(tmp_out, '@');
2973 os << frontStrip(tmp_out, '@');
2977 } else if (font2.latex() == LyXFont::ON) {
2978 // "TeX"-Mode on == > SGML-Mode on.
2984 if (linuxDocConvertChar(c, sgml_string)
2985 && !style.free_spacing) {
2986 // in freespacing mode, spaces are
2987 // non-breaking characters
2992 << "</term><listitem><para>";
3002 // we have only to control for emphasis open here!
3004 os << "</emphasis>";
3007 font1 = font2 = getFont(-1);
3008 cell = table->CellHasContRow(current_cell_number);
3010 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3014 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3015 LyXParagraph::size_type const i,
3016 int & column, LyXFont const & font,
3017 LyXLayout const & style)
3019 if (column > tex_code_break_column
3021 && GetChar(i - 1) != ' '
3023 // In LaTeX mode, we don't want to
3024 // break lines since some commands
3026 && ! (font.latex() == LyXFont::ON)
3027 // same in FreeSpacing mode
3028 && !style.free_spacing
3029 // In typewriter mode, we want to avoid
3030 // ! . ? : at the end of a line
3031 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3032 && (GetChar(i-1) == '.'
3033 || GetChar(i-1) == '?'
3034 || GetChar(i-1) == ':'
3035 || GetChar(i-1) == '!'))) {
3036 if (tex_code_break_column == 0) {
3037 // in batchmode we need LaTeX to still
3038 // see it as a space not as an extra '\n'
3044 texrow.start(this, i + 1);
3046 } else if (font.latex() == LyXFont::OFF) {
3047 if (style.free_spacing) {
3056 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
3058 LyXFont & running_font,
3061 LyXLayout const & style,
3062 LyXParagraph::size_type & i,
3063 int & column, char const c)
3065 // Two major modes: LaTeX or plain
3066 // Handle here those cases common to both modes
3067 // and then split to handle the two modes separately.
3069 case LyXParagraph::META_INSET: {
3070 Inset * inset = GetInset(i);
3073 int len = os.tellp();
3074 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3075 || inset->LyxCode() == Inset::MATH_CODE
3076 || inset->LyxCode() == Inset::URL_CODE)
3077 && running_font.isRightToLeft()) {
3082 int tmp = inset->Latex(os, style.isCommand(),
3083 style.free_spacing);
3091 column += os.tellp() - len;
3100 case LyXParagraph::META_NEWLINE:
3102 column += running_font.latexWriteEndChanges(os,
3107 basefont = getFont(-1);
3108 running_font = basefont;
3111 case LyXParagraph::META_HFILL:
3117 // And now for the special cases within each mode
3118 // Are we in LaTeX mode?
3119 if (font.latex() == LyXFont::ON) {
3120 // at present we only have one option
3121 // but I'll leave it as a switch statement
3122 // so its simpler to extend. (ARRae)
3125 case LyXParagraph::META_PROTECTED_SEPARATOR:
3130 // make sure that we will not print
3131 // error generating chars to the tex
3132 // file. This test would not be needed
3133 // if it were done in the buffer
3141 // Plain mode (i.e. not LaTeX)
3144 case LyXParagraph::META_PROTECTED_SEPARATOR:
3149 os << "\\textbackslash{}";
3153 case '°': case '±': case '²': case '³':
3154 case '×': case '÷': case '¹': case 'ª':
3155 case 'º': case '¬': case 'µ':
3156 if (current_view->buffer()->params.inputenc == "latin1") {
3157 os << "\\ensuremath{"
3166 case '|': case '<': case '>':
3167 // In T1 encoding, these characters exist
3168 if (lyxrc.fontenc == "T1") {
3170 //... but we should avoid ligatures
3171 if ((c == '>' || c == '<')
3173 && GetChar(i + 1) == c){
3174 os << "\\textcompwordmark{}";
3179 // Typewriter font also has them
3180 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3184 // Otherwise, we use what LaTeX
3188 os << "\\textless{}";
3192 os << "\\textgreater{}";
3196 os << "\\textbar{}";
3202 case '-': // "--" in Typewriter mode -> "-{}-"
3204 && GetChar(i + 1) == '-'
3205 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3214 os << "\\char`\\\"{}";
3219 if (current_view->buffer()->params.inputenc == "default") {
3228 case '%': case '#': case '{':
3235 os << "\\textasciitilde{}";
3240 os << "\\textasciicircum{}";
3244 case '*': case '[': case ']':
3245 // avoid being mistaken for optional arguments
3246 os << '{' << c << '}';
3251 // Blanks are printed before font switching.
3252 // Sure? I am not! (try nice-latex)
3253 // I am sure it's correct. LyX might be smarter
3254 // in the future, but for now, nothing wrong is
3259 /* idea for labels --- begin*/
3263 && font.family() != LyXFont::TYPEWRITER_FAMILY
3264 && GetChar(i + 1) == 'y'
3265 && GetChar(i + 2) == 'X') {
3273 && font.family() != LyXFont::TYPEWRITER_FAMILY
3274 && GetChar(i + 1) == 'e'
3275 && GetChar(i + 2) == 'X') {
3280 // Check for "LaTeX2e"
3283 && font.family() != LyXFont::TYPEWRITER_FAMILY
3284 && GetChar(i + 1) == 'a'
3285 && GetChar(i + 2) == 'T'
3286 && GetChar(i + 3) == 'e'
3287 && GetChar(i + 4) == 'X'
3288 && GetChar(i + 5) == '2'
3289 && GetChar(i + 6) == 'e') {
3294 // Check for "LaTeX"
3297 && font.family() != LyXFont::TYPEWRITER_FAMILY
3298 && GetChar(i + 1) == 'a'
3299 && GetChar(i + 2) == 'T'
3300 && GetChar(i + 3) == 'e'
3301 && GetChar(i + 4) == 'X') {
3305 /* idea for labels --- end*/
3306 } else if (c != '\0') {
3317 bool LyXParagraph::RoffContTableRows(ostream & os,
3318 LyXParagraph::size_type i,
3324 LyXFont font1(LyXFont::ALL_INHERIT);
3329 string fname2 = TmpFileName(string(), "RAT2");
3331 int cell = table->CellHasContRow(actcell);
3334 // first find the right position
3336 for (; i < size() && actcell < cell; ++i) {
3338 if (c == LyXParagraph::META_NEWLINE)
3343 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3346 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3348 font2 = GetFontSettings(i);
3349 if (font1.latex() != font2.latex()) {
3350 if (font2.latex() != LyXFont::OFF)
3355 case LyXParagraph::META_INSET:
3356 if ((inset = GetInset(i))) {
3359 stringstream ss(ios::in | ios::out);
3360 inset->Latex(ss, -1);
3372 inset->Latex(ss, -1);
3385 fstream fs(fname2.c_str(),
3388 WriteAlert(_("LYX_ERROR:"),
3389 _("Cannot open temporary file:"),
3393 inset->Latex(fs, -1);
3407 case LyXParagraph::META_NEWLINE:
3409 case LyXParagraph::META_HFILL:
3412 case LyXParagraph::META_PROTECTED_SEPARATOR:
3422 lyxerr.debug() << "RoffAsciiTable: "
3423 "NULL char in structure."
3428 cell = table->CellHasContRow(actcell);
3435 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3436 ostream & foot, TexRow & foot_texrow,
3439 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3440 LyXParagraph * par = this;
3442 while (par && par->depth == depth) {
3444 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3445 if (textclasslist.Style(current_view->buffer()->params.textclass,
3446 par->layout).isEnvironment()
3447 || par->pextra_type != PEXTRA_NONE) {
3448 par = par->TeXEnvironment(os, texrow,
3452 par = par->TeXOnePar(os, texrow,
3457 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3463 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3465 TexRow & foot_texrow,
3468 bool eindent_open = false;
3469 bool foot_this_level = false;
3470 // flags when footnotetext should be appended to file.
3471 static bool minipage_open = false;
3472 static int minipage_open_depth = 0;
3473 char par_sep = current_view->buffer()->params.paragraph_separation;
3475 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3477 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3479 LyXLayout const & style =
3480 textclasslist.Style(current_view->buffer()->params.textclass,
3483 if (pextra_type == PEXTRA_INDENT) {
3484 if (!pextra_width.empty()) {
3485 os << "\\begin{LyXParagraphIndent}{"
3486 << pextra_width << "}\n";
3488 //float ib = atof(pextra_widthp.c_str())/100;
3489 // string can't handle floats at present (971109)
3490 // so I'll do a conversion by hand knowing that
3491 // the limits are 0.0 to 1.0. ARRae.
3492 os << "\\begin{LyXParagraphIndent}{";
3493 switch (pextra_widthp.length()) {
3505 os << "\\columnwidth}\n";
3508 eindent_open = true;
3510 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3511 if (pextra_hfill && Previous() &&
3512 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3513 os << "\\hfill{}\n";
3516 if (par_sep == BufferParams::PARSEP_INDENT) {
3517 os << "{\\setlength\\parindent{0pt}\n";
3520 os << "\\begin{minipage}";
3521 switch(pextra_alignment) {
3522 case MINIPAGE_ALIGN_TOP:
3525 case MINIPAGE_ALIGN_MIDDLE:
3528 case MINIPAGE_ALIGN_BOTTOM:
3532 if (!pextra_width.empty()) {
3533 os << '{' << pextra_width << "}\n";
3535 //float ib = atof(par->pextra_width.c_str())/100;
3536 // string can't handle floats at present
3537 // so I'll do a conversion by hand knowing that
3538 // the limits are 0.0 to 1.0. ARRae.
3540 switch (pextra_widthp.length()) {
3552 os << "\\columnwidth}\n";
3555 if (par_sep == BufferParams::PARSEP_INDENT) {
3556 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3559 minipage_open = true;
3560 minipage_open_depth = depth;
3563 #ifdef WITH_WARNINGS
3564 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3565 //I disabled it because it breaks when lists span on several
3568 if (style.isEnvironment()){
3569 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3570 #ifdef FANCY_FOOTNOTE_CODE
3571 if (foot_count < 0) {
3572 // flag that footnote[mark][text] should be
3573 // used for any footnotes from now on
3575 foot_this_level = true;
3578 os << "\\begin{" << style.latexname() << "}{"
3579 << labelwidthstring << "}\n";
3580 } else if (style.labeltype == LABEL_BIBLIO) {
3582 os << "\\begin{" << style.latexname() << "}{"
3583 << bibitemWidthest(current_view->painter())
3585 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3586 #ifdef FANCY_FOOTNOTE_CODE
3587 if (foot_count < 0) {
3588 // flag that footnote[mark][text] should be
3589 // used for any footnotes from now on
3591 foot_this_level = true;
3594 os << "\\begin{" << style.latexname() << '}'
3595 << style.latexparam() << '\n';
3597 os << "\\begin{" << style.latexname() << '}'
3598 << style.latexparam() << '\n';
3601 LyXParagraph * par = this;
3603 par = par->TeXOnePar(os, texrow,
3604 foot, foot_texrow, foot_count);
3606 if (minipage_open && par && !style.isEnvironment() &&
3607 (par->pextra_type == PEXTRA_MINIPAGE) &&
3608 par->pextra_start_minipage) {
3609 os << "\\end{minipage}\n";
3611 if (par_sep == BufferParams::PARSEP_INDENT) {
3615 minipage_open = false;
3617 if (par && par->depth > depth) {
3618 if (textclasslist.Style(current_view->buffer()->params.textclass,
3619 par->layout).isParagraph()
3622 // How to handle this? (Lgb)
3623 //&& !suffixIs(os, "\n\n")
3625 // There should be at least one '\n' already
3626 // but we need there to be two for Standard
3627 // paragraphs that are depth-increment'ed to be
3628 // output correctly. However, tables can
3629 // also be paragraphs so don't adjust them.
3632 // Will it ever harm to have one '\n' too
3633 // many? i.e. that we sometimes will have
3634 // three in a row. (Lgb)
3638 par = par->TeXDeeper(os, texrow,
3639 foot, foot_texrow, foot_count);
3641 if (par && par->layout == layout && par->depth == depth &&
3642 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3643 if (par->pextra_hfill && par->Previous() &&
3644 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3645 os << "\\hfill{}\n";
3648 if (par_sep == BufferParams::PARSEP_INDENT) {
3649 os << "{\\setlength\\parindent{0pt}\n";
3652 os << "\\begin{minipage}";
3653 switch(par->pextra_alignment) {
3654 case MINIPAGE_ALIGN_TOP:
3657 case MINIPAGE_ALIGN_MIDDLE:
3660 case MINIPAGE_ALIGN_BOTTOM:
3664 if (!par->pextra_width.empty()) {
3665 os << '{' << par->pextra_width << "}\n";
3667 //float ib = atof(par->pextra_widthp.c_str())/100;
3668 // string can't handle floats at present
3669 // so I'll do a conversion by hand knowing that
3670 // the limits are 0.0 to 1.0. ARRae.
3672 switch (par->pextra_widthp.length()) {
3677 os << "0." << par->pextra_widthp;
3680 os << "0.0" << par->pextra_widthp;
3682 os << "\\columnwidth}\n";
3685 if (par_sep == BufferParams::PARSEP_INDENT) {
3686 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3689 minipage_open = true;
3690 minipage_open_depth = par->depth;
3693 && par->layout == layout
3694 && par->depth == depth
3695 && par->pextra_type == pextra_type);
3697 if (style.isEnvironment()) {
3698 os << "\\end{" << style.latexname() << '}';
3699 // maybe this should go after the minipage closes?
3700 if (foot_this_level) {
3701 if (foot_count >= 1) {
3702 if (foot_count > 1) {
3703 os << "\\addtocounter{footnote}{-"
3708 texrow += foot_texrow;
3710 foot_texrow.reset();
3715 if (minipage_open && (minipage_open_depth == depth) &&
3716 (!par || par->pextra_start_minipage ||
3717 par->pextra_type != PEXTRA_MINIPAGE)) {
3718 os << "\\end{minipage}\n";
3720 if (par_sep == BufferParams::PARSEP_INDENT) {
3724 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3725 os << "\\medskip\n\n";
3729 minipage_open = false;
3732 os << "\\end{LyXParagraphIndent}\n";
3735 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3736 && par->pextra_hfill)) {
3740 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3741 return par; // ale970302
3745 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3746 ostream & foot, TexRow & foot_texrow,
3748 LyXDirection parent_direction)
3750 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3751 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3752 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3753 "No footnote!" << endl;
3755 LyXParagraph * par = this;
3756 LyXLayout const & style =
3757 textclasslist.Style(current_view->buffer()->params.textclass,
3758 previous->GetLayout());
3760 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3761 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3762 "Float other than footnote in command"
3763 " with moving argument is illegal" << endl;
3766 if (footnotekind != LyXParagraph::FOOTNOTE
3767 && footnotekind != LyXParagraph::MARGIN
3770 // How to solve this?
3771 //&& !suffixIs(file, '\n')
3773 // we need to ensure that real floats like tables and figures
3774 // have their \begin{} on a new line otherwise we can get
3775 // incorrect results when using the endfloat.sty package
3776 // especially if two floats follow one another. ARRae 981022
3777 // NOTE: if the file is length 0 it must have just been
3778 // written out so we assume it ended with a '\n'
3780 // As far as I can see there is never any harm in writing
3781 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3786 bool need_closing = false;
3787 LyXDirection direction = getParDirection();
3788 if (direction != parent_direction) {
3789 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3793 need_closing = true;
3796 BufferParams * params = ¤t_view->buffer()->params;
3797 bool footer_in_body = true;
3798 switch (footnotekind) {
3799 case LyXParagraph::FOOTNOTE:
3800 if (style.intitle) {
3801 os << "\\thanks{\n";
3802 footer_in_body = false;
3804 if (foot_count == -1) {
3805 // we're at depth 0 so we can use:
3806 os << "\\footnote{%\n";
3807 footer_in_body = false;
3809 os << "\\footnotemark{}%\n";
3811 // we only need this when there are
3812 // multiple footnotes
3813 os << "\\stepcounter{footnote}";
3815 os << "\\footnotetext{%\n";
3816 foot_texrow.start(this, 0);
3817 foot_texrow.newline();
3822 case LyXParagraph::MARGIN:
3823 os << "\\marginpar{\n";
3825 case LyXParagraph::FIG:
3826 if (pextra_type == PEXTRA_FLOATFLT
3827 && (!pextra_width.empty()
3828 || !pextra_widthp.empty())) {
3829 if (!pextra_width.empty())
3830 os << "\\begin{floatingfigure}{"
3831 << pextra_width << "}\n";
3833 os << "\\begin{floatingfigure}{"
3834 << atoi(pextra_widthp.c_str())/100.0
3835 << "\\textwidth}\n";
3837 os << "\\begin{figure}";
3838 if (!params->float_placement.empty()) {
3839 os << '[' << params->float_placement << "]\n";
3845 case LyXParagraph::TAB:
3846 os << "\\begin{table}";
3847 if (!params->float_placement.empty()) {
3848 os << '[' << params->float_placement << "]\n";
3853 case LyXParagraph::WIDE_FIG:
3854 os << "\\begin{figure*}";
3855 if (!params->float_placement.empty()) {
3856 os << '[' << params->float_placement << "]\n";
3861 case LyXParagraph::WIDE_TAB:
3862 os << "\\begin{table*}";
3863 if (!params->float_placement.empty()) {
3864 os << '[' << params->float_placement << "]\n";
3869 case LyXParagraph::ALGORITHM:
3870 os << "\\begin{algorithm}\n";
3875 if (footnotekind != LyXParagraph::FOOTNOTE
3876 || !footer_in_body) {
3877 // Process text for all floats except footnotes in body
3879 LyXLayout const & style =
3881 .Style(current_view->buffer()->params
3885 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3887 if (style.isEnvironment()
3888 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3889 // Allows the use of minipages within float
3890 // environments. Shouldn't be circular because
3891 // we don't support footnotes inside
3892 // floats (yet). ARRae
3893 par = par->TeXEnvironment(os, texrow,
3897 par = par->TeXOnePar(os, texrow,
3902 if (par && !par->IsDummy() && par->depth > depth) {
3903 par = par->TeXDeeper(os, texrow,
3907 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3909 // process footnotes > depth 0 or in environments separately
3910 // NOTE: Currently don't support footnotes within footnotes
3911 // even though that is possible using the \footnotemark
3913 ostringstream dummy;
3917 TexRow dummy_texrow;
3918 int dummy_count = 0;
3920 LyXLayout const & style =
3922 .Style(current_view->buffer()->params
3926 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3928 if (style.isEnvironment()
3929 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3930 // Allows the use of minipages within float
3931 // environments. Shouldn't be circular because
3932 // we don't support footnotes inside
3933 // floats (yet). ARRae
3934 par = par->TeXEnvironment(foot, foot_texrow,
3935 dummy, dummy_texrow,
3938 par = par->TeXOnePar(foot, foot_texrow,
3939 dummy, dummy_texrow,
3943 if (par && !par->IsDummy() && par->depth > depth) {
3944 par = par->TeXDeeper(foot, foot_texrow,
3945 dummy, dummy_texrow,
3949 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3951 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3952 "Footnote in a Footnote -- not supported"
3955 #ifndef HAVE_OSTREAM
3956 delete [] dummy.str();
3960 switch (footnotekind) {
3961 case LyXParagraph::FOOTNOTE:
3962 if (footer_in_body) {
3963 // This helps tell which of the multiple
3964 // footnotetexts an error was in.
3966 foot_texrow.newline();
3971 case LyXParagraph::MARGIN:
3974 case LyXParagraph::FIG:
3975 if (pextra_type == PEXTRA_FLOATFLT
3976 && (!pextra_width.empty()
3977 || !pextra_widthp.empty()))
3978 os << "\\end{floatingfigure}";
3980 os << "\\end{figure}";
3982 case LyXParagraph::TAB:
3983 os << "\\end{table}";
3985 case LyXParagraph::WIDE_FIG:
3986 os << "\\end{figure*}";
3988 case LyXParagraph::WIDE_TAB:
3989 os << "\\end{table*}";
3991 case LyXParagraph::ALGORITHM:
3992 os << "\\end{algorithm}";
3999 if (footnotekind != LyXParagraph::FOOTNOTE
4000 && footnotekind != LyXParagraph::MARGIN) {
4001 // we need to ensure that real floats like tables and figures
4002 // have their \end{} on a line of their own otherwise we can
4003 // get incorrect results when using the endfloat.sty package.
4008 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4013 void LyXParagraph::SetPExtraType(int type, char const * width,
4014 char const * widthp)
4017 pextra_width = width;
4018 pextra_widthp = widthp;
4020 if (textclasslist.Style(current_view->buffer()->params.textclass,
4021 layout).isEnvironment()) {
4026 while (par && (par->layout == layout)
4027 && (par->depth == depth)) {
4029 par = par->Previous();
4031 par = par->FirstPhysicalPar();
4032 while (par && par->depth > depth) {
4033 par = par->Previous();
4035 par = par->FirstPhysicalPar();
4039 while (par && (par->layout == layout)
4040 && (par->depth == depth)) {
4041 par->pextra_type = type;
4042 par->pextra_width = width;
4043 par->pextra_widthp = widthp;
4044 par = par->NextAfterFootnote();
4045 if (par && (par->depth > depth))
4046 par->SetPExtraType(type, width, widthp);
4047 while (par && ((par->depth > depth) || par->IsDummy()))
4048 par = par->NextAfterFootnote();
4054 void LyXParagraph::UnsetPExtraType()
4056 if (pextra_type == PEXTRA_NONE)
4059 pextra_type = PEXTRA_NONE;
4060 pextra_width.clear();
4061 pextra_widthp.clear();
4063 if (textclasslist.Style(current_view->buffer()->params.textclass,
4064 layout).isEnvironment()) {
4069 while (par && (par->layout == layout)
4070 && (par->depth == depth)) {
4072 par = par->Previous();
4074 par = par->FirstPhysicalPar();
4075 while (par && par->depth > depth) {
4076 par = par->Previous();
4078 par = par->FirstPhysicalPar();
4082 while (par && (par->layout == layout)
4083 && (par->depth == depth)) {
4084 par->pextra_type = PEXTRA_NONE;
4085 par->pextra_width.clear();
4086 par->pextra_widthp.clear();
4087 par = par->NextAfterFootnote();
4088 if (par && (par->depth > depth))
4089 par->UnsetPExtraType();
4090 while (par && ((par->depth > depth) || par->IsDummy()))
4091 par = par->NextAfterFootnote();
4097 bool LyXParagraph::IsHfill(size_type pos) const
4099 return IsHfillChar(GetChar(pos));
4103 bool LyXParagraph::IsInset(size_type pos) const
4105 return IsInsetChar(GetChar(pos));
4109 bool LyXParagraph::IsFloat(size_type pos) const
4111 return IsFloatChar(GetChar(pos));
4115 bool LyXParagraph::IsNewline(size_type pos) const
4117 return pos >= 0 && IsNewlineChar(GetChar(pos));
4121 bool LyXParagraph::IsSeparator(size_type pos) const
4123 return IsSeparatorChar(GetChar(pos));
4127 bool LyXParagraph::IsLineSeparator(size_type pos) const
4129 return IsLineSeparatorChar(GetChar(pos));
4133 bool LyXParagraph::IsKomma(size_type pos) const
4135 return IsKommaChar(GetChar(pos));
4139 /// Used by the spellchecker
4140 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4142 unsigned char c = GetChar(pos);
4143 if (IsLetterChar(c))
4145 // '\0' is not a letter, allthough every string contains "" (below)
4148 // We want to pass the ' and escape chars to ispell
4149 string extra = lyxrc.isp_esc_chars + '\'';
4153 return contains(extra, ch);
4157 bool LyXParagraph::IsWord(size_type pos ) const
4159 return IsWordChar(GetChar(pos)) ;
4162 Language const * LyXParagraph::getParLanguage() const
4164 if (!table && size() > 0)
4165 return FirstPhysicalPar()->GetFirstFontSettings().language();
4167 return previous->getParLanguage();
4169 return current_view->buffer()->params.language_info;
4172 Language const * LyXParagraph::getLetterLanguage(size_type pos) const
4174 return GetFontSettings(pos).language();
4177 LyXDirection LyXParagraph::getParDirection() const
4179 if (!lyxrc.rtl_support || table)
4180 return LYX_DIR_LEFT_TO_RIGHT;
4181 else if (getParLanguage()->RightToLeft)
4182 return LYX_DIR_RIGHT_TO_LEFT;
4184 return LYX_DIR_LEFT_TO_RIGHT;
4188 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4190 if (!lyxrc.rtl_support)
4191 return LYX_DIR_LEFT_TO_RIGHT;
4192 else if (table && IsNewline(pos))
4193 return LYX_DIR_LEFT_TO_RIGHT;
4195 bool is_rtl = GetFontSettings(pos).isVisibleRightToLeft();
4196 if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4197 && !IsLineSeparator(pos + 1)
4198 && !(table && IsNewline(pos + 1))
4199 && ( GetFontSettings(pos - 1).isVisibleRightToLeft() != is_rtl
4200 || GetFontSettings(pos + 1).isVisibleRightToLeft() != is_rtl))
4201 return getParDirection();
4203 return (is_rtl) ? LYX_DIR_RIGHT_TO_LEFT
4204 : LYX_DIR_LEFT_TO_RIGHT;