1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation "lyxparagraph.h"
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "support/FileInfo.h"
28 #include "support/LAssert.h"
30 #include "LaTeXFeatures.h"
31 #include "insets/insetinclude.h"
32 #include "insets/insetbib.h"
33 #include "support/filetools.h"
34 #include "lyx_gui_misc.h"
36 #include "support/lyxmanip.h"
39 int tex_code_break_column = 72; // needs non-zero initialization. set later.
40 // this is a bad idea, but how can LyXParagraph find its buffer to get
41 // parameters? (JMarc)
42 extern BufferView * current_view;
46 extern string bibitemWidthest(Painter &);
48 // this is a minibuffer
49 static char minibuffer_char;
50 static LyXFont minibuffer_font;
51 static Inset * minibuffer_inset;
54 // Initialization of the counter for the paragraph id's,
55 // declared in lyxparagraph.h
56 unsigned int LyXParagraph::paragraph_id = 0;
59 LyXParagraph::LyXParagraph()
61 text.reserve(500); // is this number too big?
63 for (int i = 0; i < 10; ++i) setCounter(i , 0);
69 footnoteflag = LyXParagraph::NO_FOOTNOTE;
70 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
72 align = LYX_ALIGN_BLOCK;
74 /* table stuff -- begin*/
76 /* table stuff -- end*/
78 bibkey = 0; // ale970302
83 // This konstruktor inserts the new paragraph in a list.
84 LyXParagraph::LyXParagraph(LyXParagraph * par)
87 par->text.resize(par->text.size());
89 for (int i = 0; i < 10; ++i) setCounter(i, 0);
93 // double linked list begin
96 next->previous = this;
98 previous->next = this;
100 footnoteflag = LyXParagraph::NO_FOOTNOTE;
101 footnotekind = LyXParagraph::FOOTNOTE;
103 /* table stuff -- begin*/
105 /* table stuff -- end*/
106 id_ = paragraph_id++;
108 bibkey = 0; // ale970302
114 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
115 char footflag, char dth) const
117 LyXFont font1, font2;
122 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
124 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
126 // The beginning or the end of a footnote environment?
127 if (footflag != footnoteflag) {
128 footflag = footnoteflag;
130 os << "\n\\begin_float "
131 << string_footnotekinds[footnotekind]
134 os << "\n\\end_float ";
138 // The beginning or end of a deeper (i.e. nested) area?
141 while (depth > dth) {
142 os << "\n\\begin_deeper ";
146 while (depth < dth) {
147 os << "\n\\end_deeper ";
153 // First write the layout
155 << textclasslist.NameOfLayout(params.textclass, layout)
158 // Maybe some vertical spaces.
159 if (added_space_top.kind() != VSpace::NONE)
160 os << "\\added_space_top "
161 << added_space_top.asLyXCommand() << " ";
162 if (added_space_bottom.kind() != VSpace::NONE)
163 os << "\\added_space_bottom "
164 << added_space_bottom.asLyXCommand() << " ";
166 // The labelwidth string used in lists.
167 if (!labelwidthstring.empty())
168 os << "\\labelwidthstring "
169 << labelwidthstring << '\n';
171 // Lines above or below?
175 os << "\\line_bottom ";
177 // Pagebreaks above or below?
179 os << "\\pagebreak_top ";
180 if (pagebreak_bottom)
181 os << "\\pagebreak_bottom ";
183 // Start of appendix?
184 if (start_of_appendix)
185 os << "\\start_of_appendix ";
192 if (align != LYX_ALIGN_LAYOUT) {
194 case LYX_ALIGN_LEFT: h = 1; break;
195 case LYX_ALIGN_RIGHT: h = 2; break;
196 case LYX_ALIGN_CENTER: h = 3; break;
197 default: h = 0; break;
199 os << "\\align " << string_align[h] << " ";
201 if (pextra_type != PEXTRA_NONE) {
202 os << "\\pextra_type " << pextra_type;
203 if (pextra_type == PEXTRA_MINIPAGE) {
204 os << " \\pextra_alignment "
207 os << " \\pextra_hfill "
209 if (pextra_start_minipage)
210 os << " \\pextra_start_minipage "
211 << pextra_start_minipage;
213 if (!pextra_width.empty()) {
214 os << " \\pextra_width "
215 << VSpace(pextra_width).asLyXCommand();
216 } else if (!pextra_widthp.empty()) {
217 os << " \\pextra_widthp "
223 // Dummy layout. This means that a footnote ended.
224 os << "\n\\end_float ";
225 footflag = LyXParagraph::NO_FOOTNOTE;
228 // It might be a table.
230 os << "\\LyXTable\n";
238 font1 = LyXFont(LyXFont::ALL_INHERIT);
241 for (size_type i = 0; i < size(); ++i) {
247 // Write font changes
248 font2 = GetFontSettings(i);
249 if (font2 != font1) {
250 font2.lyxWriteChanges(font1, os);
259 Inset const * inset = GetInset(i);
261 if (inset->DirectWrite()) {
262 // international char, let it write
263 // code directly so it's shorter in
267 os << "\n\\begin_inset ";
269 os << "\n\\end_inset \n\n";
275 os << "\n\\newline \n";
279 os << "\n\\hfill \n";
283 case META_PROTECTED_SEPARATOR:
284 os << "\n\\protected_separator \n";
289 os << "\n\\backslash \n";
293 if (i + 1 < size() && GetChar(i + 1) == ' ') {
300 if ((column > 70 && c == ' ')
305 // this check is to amend a bug. LyX sometimes
306 // inserts '\0' this could cause problems.
310 lyxerr << "ERROR (LyXParagraph::writeFile):"
311 " NULL char in structure." << endl;
317 // now write the next paragraph
319 next->writeFile(os, params, footflag, dth);
323 void LyXParagraph::validate(LaTeXFeatures & features) const
325 // this will be useful later
326 LyXLayout const & layout =
327 textclasslist.Style(current_view->buffer()->params.textclass,
331 if (line_top || line_bottom)
332 features.lyxline = true;
335 features.layout[GetLayout()] = true;
338 for (FontList::const_iterator cit = fontlist.begin();
339 cit != fontlist.end(); ++cit) {
340 if ((*cit).font.noun() == LyXFont::ON) {
341 lyxerr[Debug::LATEX] << "font.noun: "
342 << (*cit).font.noun()
344 features.noun = true;
345 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
346 << (*cit).font.stateText()
349 switch ((*cit).font.color()) {
351 case LColor::inherit:
355 features.color = true;
356 lyxerr[Debug::LATEX] << "Color enabled. Font: "
357 << (*cit).font.stateText()
363 for (InsetList::const_iterator cit = insetlist.begin();
364 cit != insetlist.end(); ++cit) {
366 (*cit).inset->Validate(features);
369 if (table && table->IsLongTable())
370 features.longtable = true;
371 if (pextra_type == PEXTRA_INDENT)
372 features.LyXParagraphIndent = true;
373 if (pextra_type == PEXTRA_FLOATFLT)
374 features.floatflt = true;
375 if (layout.needprotect
376 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
377 features.NeedLyXFootnoteCode = true;
378 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
379 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
380 features.NeedLyXMinipageIndent = true;
381 if (table && table->NeedRotating())
382 features.rotating = true;
383 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
384 features.algorithm = true;
388 // First few functions needed for cut and paste and paragraph breaking.
389 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
391 minibuffer_char = GetChar(pos);
392 minibuffer_font = GetFontSettings(pos);
393 minibuffer_inset = 0;
394 if (minibuffer_char == LyXParagraph::META_INSET) {
396 minibuffer_inset = GetInset(pos)->Clone();
398 minibuffer_inset = 0;
399 minibuffer_char = ' ';
400 // This reflects what GetInset() does (ARRae)
406 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
408 minibuffer_char = GetChar(pos);
409 minibuffer_font = GetFontSettings(pos);
410 minibuffer_inset = 0;
411 if (minibuffer_char == LyXParagraph::META_INSET) {
413 minibuffer_inset = GetInset(pos);
414 // This is a little hack since I want exactly
415 // the inset, not just a clone. Otherwise
416 // the inset would be deleted when calling Erase(pos)
418 for (InsetList::iterator it = insetlist.begin();
419 it != insetlist.end(); ++it) {
420 if ((*it).pos == pos) {
427 minibuffer_inset = 0;
428 minibuffer_char = ' ';
429 // This reflects what GetInset() does (ARRae)
434 // Erase(pos); now the caller is responsible for that.
438 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
440 InsertChar(pos, minibuffer_char);
441 SetFont(pos, minibuffer_font);
442 if (minibuffer_char == LyXParagraph::META_INSET)
443 InsertInset(pos, minibuffer_inset);
450 void LyXParagraph::Clear()
455 pagebreak_top = false;
456 pagebreak_bottom = false;
458 added_space_top = VSpace(VSpace::NONE);
459 added_space_bottom = VSpace(VSpace::NONE);
461 align = LYX_ALIGN_LAYOUT;
465 pextra_type = PEXTRA_NONE;
466 pextra_width.clear();
467 pextra_widthp.clear();
468 pextra_alignment = MINIPAGE_ALIGN_TOP;
469 pextra_hfill = false;
470 pextra_start_minipage = false;
473 labelwidthstring.clear();
477 start_of_appendix = false;
481 // the destructor removes the new paragraph from the list
482 LyXParagraph::~LyXParagraph()
485 previous->next = next;
487 next->previous = previous;
489 for (InsetList::iterator it = insetlist.begin();
490 it != insetlist.end(); ++it) {
494 /* table stuff -- begin*/
496 /* table stuff -- end*/
503 void LyXParagraph::Erase(LyXParagraph::size_type pos)
505 // > because last is the next unused position, and you can
506 // use it if you want
508 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
509 NextAfterFootnote()->Erase(pos - text.size() - 1);
511 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
512 "position does not exist." << endl;
515 if (pos < size()) { // last is free for insertation, but should be empty
516 // if it is an inset, delete the inset entry
517 if (text[pos] == LyXParagraph::META_INSET) {
519 for (InsetList::iterator it = insetlist.begin();
520 it != insetlist.end(); ++it) {
521 if ((*it).pos == pos) {
528 text.erase(text.begin() + pos);
529 // Erase entries in the tables.
530 for (FontList::iterator it = fontlist.begin();
531 it != fontlist.end(); ++it) {
532 if (pos >= (*it).pos && pos <= (*it).pos_end) {
533 if ((*it).pos == (*it).pos_end) {
534 // If it is a multi-character font
535 // entry, we just make it smaller
536 // (see update below), otherwise we
543 // Update all other entries.
544 for (FontList::iterator it = fontlist.begin();
545 it != fontlist.end(); ++it) {
548 if ((*it).pos_end >= pos)
552 // Update the inset table.
553 for (InsetList::iterator it = insetlist.begin();
554 it != insetlist.end(); ++it) {
559 lyxerr << "ERROR (LyXParagraph::Erase): "
560 "can't erase non-existant char." << endl;
565 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
567 // > because last is the next unused position, and you can
568 // use it if you want
571 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
572 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
575 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
576 "position does not exist." << endl;
579 text.insert(text.begin() + pos, c);
580 // Update the font table.
581 for (FontList::iterator it = fontlist.begin();
582 it != fontlist.end(); ++it) {
583 if ((*it).pos >= pos)
585 if ((*it).pos_end >= pos)
589 // Update the inset table.
590 for (InsetList::iterator it = insetlist.begin();
591 it != insetlist.end(); ++it) {
592 if ((*it).pos >= pos)
598 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
601 // > because last is the next unused position, and you can
602 // use it if you want
605 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
607 ->InsertInset(pos - text.size() - 1, inset);
609 lyxerr << "ERROR (LyXParagraph::InsertInset): "
610 "position does not exist: " << pos << endl;
613 if (text[pos] != LyXParagraph::META_INSET) {
614 lyxerr << "ERROR (LyXParagraph::InsertInset): "
615 "there is no LyXParagraph::META_INSET" << endl;
620 // Add a new entry in the inset table.
621 InsetList::iterator it =
622 insetlist.insert(insetlist.begin(), InsetTable());
629 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
633 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
634 return NextAfterFootnote()
635 ->GetInset(pos - text.size() - 1);
637 lyxerr << "ERROR (LyXParagraph::GetInset): "
638 "position does not exist: "
644 for (InsetList::iterator it = insetlist.begin();
645 it != insetlist.end(); ++it) {
646 if ((*it).pos == pos) {
650 lyxerr << "ERROR (LyXParagraph::GetInset): "
651 "Inset does not exist: " << pos << endl;
652 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
653 // Did this commenting out introduce a bug? So far I have not
654 // see any, please enlighten me. (Lgb)
655 // My guess is that since the inset does not exist, we might
656 // as well replace it with a space to prevent craches. (Asger)
661 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
665 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
666 return NextAfterFootnote()
667 ->GetInset(pos - text.size() - 1);
669 lyxerr << "ERROR (LyXParagraph::GetInset): "
670 "position does not exist: "
676 for (InsetList::const_iterator cit = insetlist.begin();
677 cit != insetlist.end(); ++cit) {
678 if ((*cit).pos == pos) {
682 lyxerr << "ERROR (LyXParagraph::GetInset): "
683 "Inset does not exist: " << pos << endl;
684 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
685 // Did this commenting out introduce a bug? So far I have not
686 // see any, please enlighten me. (Lgb)
687 // My guess is that since the inset does not exist, we might
688 // as well replace it with a space to prevent craches. (Asger)
693 // Gets uninstantiated font setting at position.
694 // Optimized after profiling. (Asger)
695 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
698 for (FontList::const_iterator cit = fontlist.begin();
699 cit != fontlist.end(); ++cit) {
700 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
704 // > because last is the next unused position, and you can
705 // use it if you want
706 else if (pos > size()) {
708 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
709 return NextAfterFootnote()
710 ->GetFontSettings(pos - text.size() - 1);
712 // Why is it an error to ask for the font of a
713 // position that does not exist? Would it be
714 // enough for this to be enabled on debug?
715 // We want strict error checking, but it's ok to only
716 // have it when debugging. (Asger)
717 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
718 "position does not exist. "
719 << pos << " (" << static_cast<int>(pos)
723 return GetFontSettings(pos - 1);
725 return LyXFont(LyXFont::ALL_INHERIT);
729 // Gets the fully instantiated font at a given position in a paragraph
730 // This is basically the same function as LyXText::GetFont() in text2.C.
731 // The difference is that this one is used for generating the LaTeX file,
732 // and thus cosmetic "improvements" are disallowed: This has to deliver
733 // the true picture of the buffer. (Asger)
734 // If position is -1, we get the layout font of the paragraph.
735 // If position is -2, we get the font of the manual label of the paragraph.
736 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
739 LyXLayout const & layout =
740 textclasslist.Style(current_view->buffer()->params.textclass,
742 LyXParagraph::size_type main_body = 0;
743 if (layout.labeltype == LABEL_MANUAL)
744 main_body = BeginningOfMainBody();
749 layoutfont = layout.labelfont;
751 layoutfont = layout.font;
752 tmpfont = GetFontSettings(pos);
753 tmpfont.realize(layoutfont);
755 // process layoutfont for pos == -1 and labelfont for pos < -1
757 tmpfont = layout.font;
759 tmpfont = layout.labelfont;
760 if (getParDirection() == LYX_DIR_RIGHT_TO_LEFT)
761 tmpfont.setDirection(LyXFont::RTL_DIR);
764 // check for environment font information
765 char par_depth = GetDepth();
766 LyXParagraph const * par = this;
767 while (par && par_depth && !tmpfont.resolved()) {
768 par = par->DepthHook(par_depth - 1);
770 tmpfont.realize(textclasslist.
771 Style(current_view->buffer()->params.textclass,
772 par->GetLayout()).font);
773 par_depth = par->GetDepth();
777 tmpfont.realize(textclasslist
778 .TextClass(current_view->buffer()->params.textclass)
784 /// Returns the height of the highest font in range
786 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
787 LyXParagraph::size_type endpos) const
789 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
790 for (FontList::const_iterator cit = fontlist.begin();
791 cit != fontlist.end(); ++cit) {
792 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
793 LyXFont::FONT_SIZE size = (*cit).font.size();
794 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
802 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
809 // > because last is the next unused position, and you can
810 // use it if you want
811 else if (pos > size()) {
812 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
813 return NextAfterFootnote()
814 ->GetChar(pos - text.size() - 1);
816 lyxerr << "ERROR (LyXParagraph::GetChar): "
817 "position does not exist."
818 << pos << " (" << static_cast<int>(pos)
820 // Assert(false); // This triggers sometimes...
825 // We should have a footnote environment.
826 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
827 // Notice that LyX does request the
828 // last char from time to time. (Asger)
829 //lyxerr << "ERROR (LyXParagraph::GetChar): "
830 // "expected footnote." << endl;
833 switch (next->footnotekind) {
834 case LyXParagraph::FOOTNOTE:
835 return LyXParagraph::META_FOOTNOTE;
836 case LyXParagraph::MARGIN:
837 return LyXParagraph::META_MARGIN;
838 case LyXParagraph::FIG:
839 case LyXParagraph::WIDE_FIG:
840 return LyXParagraph::META_FIG;
841 case LyXParagraph::TAB:
842 case LyXParagraph::WIDE_TAB:
843 return LyXParagraph::META_TAB;
844 case LyXParagraph::ALGORITHM:
845 return LyXParagraph::META_ALGORITHM;
847 return '\0'; // to shut up gcc
852 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
859 // > because last is the next unused position, and you can
860 // use it if you want
861 else if (pos > size()) {
862 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
863 return NextAfterFootnote()
864 ->GetChar(pos - text.size() - 1);
866 lyxerr << "ERROR (LyXParagraph::GetChar const): "
867 "position does not exist."
868 << pos << " (" << static_cast<int>(pos)
874 // We should have a footnote environment.
875 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
876 // Notice that LyX does request the
877 // last char from time to time. (Asger)
878 //lyxerr << "ERROR (LyXParagraph::GetChar): "
879 // "expected footnote." << endl;
882 switch (next->footnotekind) {
883 case LyXParagraph::FOOTNOTE:
884 return LyXParagraph::META_FOOTNOTE;
885 case LyXParagraph::MARGIN:
886 return LyXParagraph::META_MARGIN;
887 case LyXParagraph::FIG:
888 case LyXParagraph::WIDE_FIG:
889 return LyXParagraph::META_FIG;
890 case LyXParagraph::TAB:
891 case LyXParagraph::WIDE_TAB:
892 return LyXParagraph::META_TAB;
893 case LyXParagraph::ALGORITHM:
894 return LyXParagraph::META_ALGORITHM;
896 return '\0'; // to shut up gcc
901 // return an string of the current word, and the end of the word in lastpos.
902 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
906 // the current word is defined as starting at the first character
907 // from the immediate left of lastpospos which meets the definition
908 // of IsLetter(), continuing to the last character to the right
909 // of this meeting IsLetter.
915 // move back until we have a letter
917 //there's no real reason to have firstpos & lastpos as
918 //separate variables as this is written, but maybe someon
919 // will want to return firstpos in the future.
921 //since someone might have typed a punctuation first
922 int firstpos = lastpos;
924 while ((firstpos >= 0) && !IsLetter(firstpos))
927 // now find the beginning by looking for a nonletter
929 while ((firstpos>= 0) && IsLetter(firstpos))
932 // the above is now pointing to the preceeding non-letter
936 // so copy characters into theword until we get a nonletter
937 // note that this can easily exceed lastpos, wich means
938 // that if used in the middle of a word, the whole word
941 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
948 LyXParagraph::size_type LyXParagraph::Last() const
950 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
951 return text.size() + NextAfterFootnote()->Last() + 1;
952 // the 1 is the symbol
959 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
961 // > because last is the next unused position, and you can
962 // use it if you want
965 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
966 return NextAfterFootnote()
967 ->ParFromPos(pos - text.size() - 1);
969 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
970 "position does not exist." << endl;
977 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
979 // > because last is the next unused position, and you can
980 // use it if you want
983 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
984 return NextAfterFootnote()
985 ->PositionInParFromPos(pos - text.size() - 1);
988 "ERROR (LyXParagraph::PositionInParFromPos): "
989 "position does not exist." << endl;
997 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
998 LyXFont const & font)
1000 // > because last is the next unused position, and you can
1001 // use it if you want
1004 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1005 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1008 lyxerr << "ERROR (LyXParagraph::SetFont): "
1009 "position does not exist." << endl;
1013 LyXFont patternfont(LyXFont::ALL_INHERIT);
1015 // First, reduce font against layout/label font
1016 // Update: The SetCharFont() routine in text2.C already
1017 // reduces font, so we don't need to do that here. (Asger)
1018 // No need to simplify this because it will disappear
1019 // in a new kernel. (Asger)
1020 // Next search font table
1021 FontList::iterator tmp = fontlist.begin();
1022 for (; tmp != fontlist.end(); ++tmp) {
1023 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1027 if (tmp == fontlist.end()) { // !found
1028 // if we did not find a font entry, but if the font at hand
1029 // is the same as default, we just forget it
1030 if (font == patternfont) return;
1032 // ok, we did not find a font entry. But maybe there is exactly
1033 // the needed font ientry one position left
1034 FontList::iterator tmp2 = fontlist.begin();
1035 for (; tmp2 != fontlist.end(); ++tmp2) {
1036 if (pos - 1 >= (*tmp2).pos
1037 && pos - 1 <= (*tmp2).pos_end)
1040 if (tmp2 != fontlist.end()) {
1041 // ok there is one, maybe it is exactly
1043 if ((*tmp2).font == font) {
1044 // put the position under the font
1049 // Add a new entry in the
1050 // fontlist for the position
1054 ft.font = font; // or patternfont
1055 // It seems that using font instead of patternfont here
1056 // fixes all the problems. This also surfaces a "bug" in
1058 fontlist.insert(fontlist.begin(), ft);
1059 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1061 // more than one character
1062 if (pos == (*tmp).pos) {
1063 // maybe we should enlarge the left fonttable
1064 FontList::iterator tmp2 = fontlist.begin();
1065 for (; tmp2 != fontlist.end(); ++tmp2) {
1066 if (pos - 1 >= (*tmp2).pos
1067 && pos - 1 <= (*tmp2).pos_end)
1070 // Is there is one, and is it exactly
1072 if (tmp2 != fontlist.end() &&
1073 (*tmp2).font == font) {
1074 // Put the position under the font
1080 // Add a new entry in the
1081 // fontlist for the position
1084 ft.pos_end = (*tmp).pos_end;
1085 ft.font = (*tmp).font;
1086 (*tmp).pos_end = pos;
1088 fontlist.insert(fontlist.begin(), ft);
1089 } else if (pos == (*tmp).pos_end) {
1090 // Add a new entry in the
1091 // fontlist for the position
1093 ft.pos = (*tmp).pos;
1094 ft.pos_end = (*tmp).pos_end - 1;
1095 ft.font = (*tmp).font;
1096 (*tmp).pos = (*tmp).pos_end;
1098 fontlist.insert(fontlist.begin(), ft);
1100 // Add a new entry in the
1101 // fontlist for the position
1103 ft.pos = (*tmp).pos;
1104 ft.pos_end = pos - 1;
1105 ft.font = (*tmp).font;
1109 ft2.pos_end = (*tmp).pos_end;
1110 ft2.font = (*tmp).font;
1113 (*tmp).pos_end = pos;
1116 fontlist.insert(fontlist.begin(), ft);
1117 fontlist.insert(fontlist.begin(), ft2);
1125 // This function is able to hide closed footnotes.
1126 LyXParagraph * LyXParagraph::Next()
1128 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1129 LyXParagraph * tmp = next;
1131 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1133 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1134 return tmp->Next(); /* there can be more than one
1135 footnote in a logical
1138 return next; // This should never happen!
1144 LyXParagraph * LyXParagraph::NextAfterFootnote()
1146 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1147 LyXParagraph * tmp = next;
1148 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1150 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1151 return tmp; /* there can be more than one footnote
1152 in a logical paragraph */
1154 return next; // This should never happen!
1160 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1162 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1163 LyXParagraph * tmp = next;
1164 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1166 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1167 return tmp; /* there can be more than one footnote
1168 in a logical paragraph */
1170 return next; // This should never happen!
1176 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1179 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1181 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1182 tmp = tmp->previous;
1183 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1184 return tmp; /* there can be more than one footnote
1185 in a logical paragraph */
1187 return previous; // This should never happen!
1193 LyXParagraph * LyXParagraph::LastPhysicalPar()
1195 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1198 LyXParagraph * tmp = this;
1200 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1201 tmp = tmp->NextAfterFootnote();
1206 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1208 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1211 LyXParagraph const * tmp = this;
1213 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1214 tmp = tmp->NextAfterFootnote();
1219 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1223 LyXParagraph * tmppar = this;
1227 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1228 tmppar = tmppar->previous;
1237 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1241 LyXParagraph const * tmppar = this;
1245 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1246 tmppar = tmppar->previous;
1255 // This function is able to hide closed footnotes.
1256 LyXParagraph * LyXParagraph::Previous()
1258 LyXParagraph * tmp = previous;
1263 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1264 tmp = tmp->previous;
1266 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1267 tmp = tmp->previous;
1268 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1269 return tmp->next->Previous();
1278 // This function is able to hide closed footnotes.
1279 LyXParagraph const * LyXParagraph::Previous() const
1281 LyXParagraph * tmp = previous;
1286 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1287 tmp = tmp->previous;
1289 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1290 tmp = tmp->previous;
1291 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1292 return tmp->next->Previous();
1301 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1304 size_type i, pos_end, pos_first;
1305 // create a new paragraph
1306 LyXParagraph * par = ParFromPos(pos);
1307 LyXParagraph * firstpar = FirstPhysicalPar();
1309 LyXParagraph * tmp = new LyXParagraph(par);
1311 tmp->footnoteflag = footnoteflag;
1312 tmp->footnotekind = footnotekind;
1314 // this is an idea for a more userfriendly layout handling, I will
1315 // see what the users say
1317 // layout stays the same with latex-environments
1319 tmp->SetOnlyLayout(firstpar->layout);
1320 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1323 if (Last() > pos || !Last() || flag == 2) {
1324 tmp->SetOnlyLayout(firstpar->layout);
1325 tmp->align = firstpar->align;
1326 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1328 tmp->line_bottom = firstpar->line_bottom;
1329 firstpar->line_bottom = false;
1330 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1331 firstpar->pagebreak_bottom = false;
1332 tmp->added_space_bottom = firstpar->added_space_bottom;
1333 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1335 tmp->depth = firstpar->depth;
1336 tmp->noindent = firstpar->noindent;
1338 // copy everything behind the break-position
1339 // to the new paragraph
1341 while (ParFromPos(pos_first) != par)
1344 pos_end = pos_first + par->text.size() - 1;
1345 // The constructor has already reserved 500 elements
1346 //if (pos_end > pos)
1347 // tmp->text.reserve(pos_end - pos);
1349 for (i = pos; i <= pos_end; ++i) {
1350 par->CutIntoMinibuffer(i - pos_first);
1351 tmp->InsertFromMinibuffer(i - pos);
1353 tmp->text.resize(tmp->text.size());
1354 for (i = pos_end; i >= pos; --i)
1355 par->Erase(i - pos_first);
1357 par->text.resize(par->text.size());
1360 // just an idea of me
1362 tmp->line_top = firstpar->line_top;
1363 tmp->pagebreak_top = firstpar->pagebreak_top;
1364 tmp->added_space_top = firstpar->added_space_top;
1365 tmp->bibkey = firstpar->bibkey;
1367 // layout stays the same with latex-environments
1369 firstpar->SetOnlyLayout(tmp->layout);
1370 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1371 firstpar->depth = tmp->depth;
1377 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1379 par = par->FirstPhysicalPar();
1380 footnoteflag = par->footnoteflag;
1381 footnotekind = par->footnotekind;
1383 layout = par->layout;
1384 align = par-> align;
1385 SetLabelWidthString(par->labelwidthstring);
1387 line_bottom = par->line_bottom;
1388 pagebreak_bottom = par->pagebreak_bottom;
1389 added_space_bottom = par->added_space_bottom;
1391 line_top = par->line_top;
1392 pagebreak_top = par->pagebreak_top;
1393 added_space_top = par->added_space_top;
1395 pextra_type = par->pextra_type;
1396 pextra_width = par->pextra_width;
1397 pextra_widthp = par->pextra_widthp;
1398 pextra_alignment = par->pextra_alignment;
1399 pextra_hfill = par->pextra_hfill;
1400 pextra_start_minipage = par->pextra_start_minipage;
1402 noindent = par->noindent;
1407 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1409 LyXParagraph * tmppar = this;
1412 && tmppar->previous->footnoteflag ==
1413 LyXParagraph::CLOSED_FOOTNOTE)
1414 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1415 tmppar = tmppar->previous;
1418 return this; // This should never happen!
1424 LyXParagraph * LyXParagraph::Clone() const
1426 // create a new paragraph
1427 LyXParagraph * result = new LyXParagraph;
1429 result->MakeSameLayout(this);
1431 // this is because of the dummy layout of the paragraphs that
1433 result->layout = layout;
1435 /* table stuff -- begin*/
1437 result->table = table->Clone();
1440 /* table stuff -- end*/
1443 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1446 // copy everything behind the break-position to the new paragraph
1448 for (size_type i = 0; i < size(); ++i) {
1449 CopyIntoMinibuffer(i);
1450 result->InsertFromMinibuffer(i);
1452 result->text.resize(result->text.size());
1457 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1459 par = par->FirstPhysicalPar();
1462 par->footnoteflag == footnoteflag &&
1463 par->footnotekind == footnotekind &&
1465 par->layout == layout &&
1467 par->align == align &&
1469 par->line_bottom == line_bottom &&
1470 par->pagebreak_bottom == pagebreak_bottom &&
1471 par->added_space_bottom == added_space_bottom &&
1473 par->line_top == line_top &&
1474 par->pagebreak_top == pagebreak_top &&
1475 par->added_space_top == added_space_top &&
1477 par->pextra_type == pextra_type &&
1478 par->pextra_width == pextra_width &&
1479 par->pextra_widthp == pextra_widthp &&
1480 par->pextra_alignment == pextra_alignment &&
1481 par->pextra_hfill == pextra_hfill &&
1482 par->pextra_start_minipage == pextra_start_minipage &&
1484 par->table == table && // what means: NO TABLE AT ALL
1486 par->noindent == noindent &&
1487 par->depth == depth);
1491 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1493 // create a new paragraph
1494 LyXParagraph * par = ParFromPos(pos);
1496 LyXParagraph * tmp = new LyXParagraph(par);
1498 tmp->MakeSameLayout(par);
1500 // When can pos < Last()?
1501 // I guess pos == Last() is possible.
1503 // copy everything behind the break-position to the new
1505 size_type pos_first = 0;
1506 while (ParFromPos(pos_first) != par)
1508 size_type pos_end = pos_first + par->text.size() - 1;
1509 // make sure there is enough memory for the now larger
1510 // paragraph. This is not neccessary, because
1511 // InsertFromMinibuffer will enlarge the memory (it uses
1512 // InsertChar of course). But doing it by hand
1513 // is MUCH faster! (only one time, not thousend times!!)
1514 // Not needed since the constructor aleady have
1515 // reserved 500 elements in text.
1516 //if (pos_end > pos)
1517 // tmp->text.reserve(pos_end - pos);
1519 for (size_type i = pos; i <= pos_end; ++i) {
1520 par->CutIntoMinibuffer(i - pos_first);
1521 tmp->InsertFromMinibuffer(i - pos);
1523 tmp->text.resize(tmp->text.size());
1524 for (size_type i = pos_end; i >= pos; --i)
1525 par->Erase(i - pos_first);
1527 par->text.resize(par->text.size());
1532 // Be carefull, this does not make any check at all.
1533 void LyXParagraph::PasteParagraph()
1535 // copy the next paragraph to this one
1536 LyXParagraph * the_next = Next();
1538 LyXParagraph * firstpar = FirstPhysicalPar();
1540 // first the DTP-stuff
1541 firstpar->line_bottom = the_next->line_bottom;
1542 firstpar->added_space_bottom = the_next->added_space_bottom;
1543 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1545 size_type pos_end = the_next->text.size() - 1;
1546 size_type pos_insert = Last();
1548 // ok, now copy the paragraph
1549 for (size_type i = 0; i <= pos_end; ++i) {
1550 the_next->CutIntoMinibuffer(i);
1551 InsertFromMinibuffer(pos_insert + i);
1554 // delete the next paragraph
1559 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1561 LyXParagraph * par = ParFromPos(pos);
1563 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1564 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1570 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1572 LyXParagraph * par = ParFromPos(pos);
1574 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1575 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1580 int LyXParagraph::GetEndLabel() const
1582 LyXParagraph const * par = this;
1583 int par_depth = GetDepth();
1585 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1587 textclasslist.Style(current_view->buffer()->params.textclass,
1588 layout).endlabeltype;
1589 if (endlabeltype != END_LABEL_NO_LABEL) {
1590 LyXParagraph const * last = LastPhysicalPar();
1591 if (!last || !last->next)
1592 return endlabeltype;
1594 int next_depth = last->next->GetDepth();
1595 if (par_depth > next_depth ||
1596 (par_depth == next_depth && layout != last->next->GetLayout() ))
1597 return endlabeltype;
1602 par = par->DepthHook(par_depth - 1);
1604 par_depth = par->GetDepth();
1606 return END_LABEL_NO_LABEL;
1609 LyXTextClass::size_type LyXParagraph::GetLayout() const
1611 return FirstPhysicalPar()->layout;
1615 char LyXParagraph::GetDepth() const
1617 return FirstPhysicalPar()->depth;
1621 char LyXParagraph::GetAlign() const
1623 return FirstPhysicalPar()->align;
1627 string LyXParagraph::GetLabestring() const
1629 return FirstPhysicalPar()->labelstring;
1633 int LyXParagraph::GetFirstCounter(int i) const
1635 return FirstPhysicalPar()->counter_[i];
1639 // the next two functions are for the manual labels
1640 string LyXParagraph::GetLabelWidthString() const
1642 if (!FirstPhysicalPar()->labelwidthstring.empty())
1643 return FirstPhysicalPar()->labelwidthstring;
1645 return _("Senseless with this layout!");
1649 void LyXParagraph::SetLabelWidthString(string const & s)
1651 LyXParagraph * par = FirstPhysicalPar();
1653 par->labelwidthstring = s;
1657 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1659 LyXParagraph * par = FirstPhysicalPar();
1660 LyXParagraph * ppar = 0;
1661 LyXParagraph * npar = 0;
1663 par->layout = new_layout;
1664 /* table stuff -- begin*/
1667 /* table stuff -- end*/
1668 if (par->pextra_type == PEXTRA_NONE) {
1669 if (par->Previous()) {
1670 ppar = par->Previous()->FirstPhysicalPar();
1673 && (ppar->depth > par->depth))
1674 ppar = ppar->Previous()->FirstPhysicalPar();
1677 npar = par->Next()->NextAfterFootnote();
1680 && (npar->depth > par->depth))
1681 npar = npar->Next()->NextAfterFootnote();
1683 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1685 p1 = ppar->pextra_width,
1686 p2 = ppar->pextra_widthp;
1687 ppar->SetPExtraType(ppar->pextra_type,
1688 p1.c_str(), p2.c_str());
1690 if ((par->pextra_type == PEXTRA_NONE) &&
1691 npar && (npar->pextra_type != PEXTRA_NONE)) {
1693 p1 = npar->pextra_width,
1694 p2 = npar->pextra_widthp;
1695 npar->SetPExtraType(npar->pextra_type,
1696 p1.c_str(), p2.c_str());
1702 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1705 * par = FirstPhysicalPar(),
1709 par->layout = new_layout;
1710 par->labelwidthstring.clear();
1711 par->align = LYX_ALIGN_LAYOUT;
1712 par->added_space_top = VSpace(VSpace::NONE);
1713 par->added_space_bottom = VSpace(VSpace::NONE);
1714 /* table stuff -- begin*/
1717 /* table stuff -- end*/
1718 if (par->pextra_type == PEXTRA_NONE) {
1719 if (par->Previous()) {
1720 ppar = par->Previous()->FirstPhysicalPar();
1723 && (ppar->depth > par->depth))
1724 ppar = ppar->Previous()->FirstPhysicalPar();
1727 npar = par->Next()->NextAfterFootnote();
1730 && (npar->depth > par->depth))
1731 npar = npar->Next()->NextAfterFootnote();
1733 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1735 p1 = ppar->pextra_width,
1736 p2 = ppar->pextra_widthp;
1737 ppar->SetPExtraType(ppar->pextra_type,
1738 p1.c_str(), p2.c_str());
1740 if ((par->pextra_type == PEXTRA_NONE) &&
1741 npar && (npar->pextra_type != PEXTRA_NONE)) {
1743 p1 = npar->pextra_width,
1744 p2 = npar->pextra_widthp;
1745 npar->SetPExtraType(npar->pextra_type,
1746 p1.c_str(), p2.c_str());
1752 // if the layout of a paragraph contains a manual label, the beginning of the
1753 // main body is the beginning of the second word. This is what the par-
1754 // function returns. If the layout does not contain a label, the main
1755 // body always starts with position 0. This differentiation is necessary,
1756 // because there cannot be a newline or a blank <= the beginning of the
1757 // main body in TeX.
1759 int LyXParagraph::BeginningOfMainBody() const
1761 if (FirstPhysicalPar() != this)
1764 // Unroll the first two cycles of the loop
1765 // and remember the previous character to
1766 // remove unnecessary GetChar() calls
1769 && GetChar(i) != LyXParagraph::META_NEWLINE
1772 char previous_char = 0, temp = 0;
1774 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1775 // Yes, this ^ is supposed to be "= " not "=="
1778 && previous_char != ' '
1779 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1781 previous_char = temp;
1786 if (i == 0 && i == size() &&
1787 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1788 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1789 ++i; /* the cursor should not jump
1790 * to the main body if there
1796 LyXParagraph * LyXParagraph::DepthHook(int deth)
1798 LyXParagraph * newpar = this;
1803 newpar = newpar->FirstPhysicalPar()->Previous();
1804 } while (newpar && newpar->GetDepth() > deth
1805 && newpar->footnoteflag == footnoteflag);
1808 if (Previous() || GetDepth())
1809 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1813 return newpar->FirstPhysicalPar();
1817 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1819 LyXParagraph const * newpar = this;
1824 newpar = newpar->FirstPhysicalPar()->Previous();
1825 } while (newpar && newpar->GetDepth() > deth
1826 && newpar->footnoteflag == footnoteflag);
1829 if (Previous() || GetDepth())
1830 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1834 return newpar->FirstPhysicalPar();
1838 int LyXParagraph::AutoDeleteInsets()
1840 vector<size_type> tmpvec;
1842 for (InsetList::iterator it = insetlist.begin();
1843 it != insetlist.end(); ++it) {
1844 if ((*it).inset && (*it).inset->AutoDelete()) {
1845 tmpvec.push_back((*it).pos);
1849 for (vector<size_type>::const_iterator cit = tmpvec.begin();
1850 cit != tmpvec.end(); ++cit) {
1857 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1859 InsetList::iterator it2 = insetlist.end();
1860 for (InsetList::iterator it = insetlist.begin();
1861 it != insetlist.end(); ++it) {
1862 if ((*it).pos >= pos) {
1863 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1867 if (it2 != insetlist.end()) {
1869 return (*it2).inset;
1875 // returns -1 if inset not found
1876 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1879 for (InsetList::const_iterator cit = insetlist.begin();
1880 cit != insetlist.end(); ++cit) {
1881 if ((*cit).inset == inset) {
1885 // Think about footnotes.
1886 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1887 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1889 NextAfterFootnote()->GetPositionOfInset(inset);
1891 return text.size() + 1 + further;
1897 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1898 ostream & foot, TexRow & foot_texrow,
1901 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1902 LyXParagraph * par = next;
1903 LyXLayout const & style =
1904 textclasslist.Style(current_view->buffer()->params.textclass,
1907 bool further_blank_line = false;
1909 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1911 if (start_of_appendix) {
1912 os << "\\appendix\n";
1916 if (tex_code_break_column && style.isCommand()){
1921 if (pagebreak_top) {
1923 further_blank_line = true;
1925 if (added_space_top.kind() != VSpace::NONE) {
1926 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1927 further_blank_line = true;
1931 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1932 << "\\vspace{-1\\parskip}";
1933 further_blank_line = true;
1936 if (further_blank_line){
1941 LyXDirection direction = getParDirection();
1942 LyXDirection global_direction =
1943 current_view->buffer()->params.getDocumentDirection();
1944 if (direction != global_direction) {
1945 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1946 os << lyxrc.language_command_ltr << '\n';
1948 os << lyxrc.language_command_rtl << '\n';
1953 switch (style.latextype) {
1956 << style.latexname()
1957 << style.latexparam();
1959 case LATEX_ITEM_ENVIRONMENT:
1961 bibkey->Latex(os, false, false);
1965 case LATEX_LIST_ENVIRONMENT:
1972 bool need_par = SimpleTeXOnePar(os, texrow);
1974 // Spit out footnotes
1975 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1976 && par->footnoteflag != footnoteflag) {
1977 par = par->TeXFootnote(os, texrow,
1978 foot, foot_texrow, foot_count,
1980 par->SimpleTeXOnePar(os, texrow);
1984 // Make sure that \\par is done with the font of the last
1985 // character if this has another size as the default.
1986 // This is necessary because LaTeX (and LyX on the screen)
1987 // calculates the space between the baselines according
1988 // to this font. (Matthias)
1989 LyXFont font = getFont(Last() - 1);
1991 if (style.resfont.size() != font.size()) {
1997 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1998 GetLayout()).isCommand()){
1999 if (style.resfont.size() != font.size()) {
2005 } else if (style.resfont.size() != font.size()){
2006 os << "{\\" << font.latexSize() << " \\par}";
2009 if (direction != global_direction)
2010 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2011 os << '\n' << lyxrc.language_command_rtl;
2013 os << '\n' << lyxrc.language_command_ltr;
2015 switch (style.latextype) {
2016 case LATEX_ITEM_ENVIRONMENT:
2017 case LATEX_LIST_ENVIRONMENT:
2018 if (par && (depth < par->depth)) {
2023 case LATEX_ENVIRONMENT:
2024 // if its the last paragraph of the current environment
2025 // skip it otherwise fall through
2027 && (par->layout != layout
2028 || par->depth != depth
2029 || par->pextra_type != pextra_type))
2032 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2033 && footnotekind != LyXParagraph::FOOTNOTE
2034 && footnotekind != LyXParagraph::MARGIN
2038 // don't insert this if we would be adding it
2039 // before or after a table in a float. This
2040 // little trick is needed in order to allow
2041 // use of tables in \subfigures or \subtables.
2047 further_blank_line = false;
2049 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2050 further_blank_line = true;
2053 if (added_space_bottom.kind() != VSpace::NONE) {
2054 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2055 further_blank_line = true;
2058 if (pagebreak_bottom) {
2060 further_blank_line = true;
2063 if (further_blank_line){
2068 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2069 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2074 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2079 // This one spits out the text of the paragraph
2080 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2082 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2085 return SimpleTeXOneTablePar(os, texrow);
2087 bool return_value = false;
2089 LyXLayout const & style =
2090 textclasslist.Style(current_view->buffer()->params.textclass,
2092 LyXFont basefont, last_font;
2094 // Maybe we have to create a optional argument.
2095 size_type main_body;
2096 if (style.labeltype != LABEL_MANUAL)
2099 main_body = BeginningOfMainBody();
2101 if (main_body > 0) {
2103 basefont = getFont(-2); // Get label font
2105 basefont = getFont(-1); // Get layout font
2113 if (style.isCommand()) {
2116 } else if (align != LYX_ALIGN_LAYOUT) {
2119 return_value = true;
2123 // Which font is currently active?
2124 LyXFont running_font(basefont);
2125 // Do we have an open font change?
2126 bool open_font = false;
2128 texrow.start(this, 0);
2130 for (size_type i = 0; i < size(); ++i) {
2132 // First char in paragraph or after label?
2133 if (i == main_body && !IsDummy()) {
2134 if (main_body > 0) {
2136 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2139 basefont = getFont(-1); // Now use the layout font
2140 running_font = basefont;
2144 if (style.isCommand()) {
2147 } else if (align != LYX_ALIGN_LAYOUT) {
2150 return_value = true;
2154 os << "\\noindent ";
2158 case LYX_ALIGN_NONE:
2159 case LYX_ALIGN_BLOCK:
2160 case LYX_ALIGN_LAYOUT:
2161 case LYX_ALIGN_SPECIAL: break;
2162 case LYX_ALIGN_LEFT:
2163 os << "\\raggedright ";
2166 case LYX_ALIGN_RIGHT:
2167 os << "\\raggedleft ";
2170 case LYX_ALIGN_CENTER:
2171 os << "\\centering ";
2179 // Fully instantiated font
2180 LyXFont font = getFont(i);
2181 last_font = running_font;
2183 // Spaces at end of font change are simulated to be
2184 // outside font change, i.e. we write "\textXX{text} "
2185 // rather than "\textXX{text }". (Asger)
2186 if (open_font && c == ' ' && i <= size() - 2
2187 && !getFont(i+1).equalExceptLatex(running_font)
2188 && !getFont(i+1).equalExceptLatex(font)) {
2189 font = getFont(i + 1);
2191 // We end font definition before blanks
2192 if (!font.equalExceptLatex(running_font) && open_font) {
2193 column += running_font.latexWriteEndChanges(os,
2195 (i == main_body-1) ? basefont : font);
2196 running_font = basefont;
2200 // Blanks are printed before start of fontswitch
2202 // Do not print the separation of the optional argument
2203 if (i != main_body - 1) {
2204 SimpleTeXBlanks(os, texrow, i,
2205 column, font, style);
2209 // Do we need to change font?
2210 if (!font.equalExceptLatex(running_font)
2211 && i != main_body-1) {
2212 column += font.latexWriteStartChanges(os, basefont,
2214 running_font = font;
2218 if (c == LyXParagraph::META_NEWLINE) {
2219 // newlines are handled differently here than
2220 // the default in SimpleTeXSpecialChars().
2221 if (!style.newline_allowed
2222 || font.latex() == LyXFont::ON) {
2226 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2229 basefont = getFont(-1);
2230 running_font = basefont;
2231 if (font.family() ==
2232 LyXFont::TYPEWRITER_FAMILY) {
2238 texrow.start(this, i + 1);
2241 SimpleTeXSpecialChars(os, texrow,
2242 font, running_font, basefont,
2243 open_font, style, i, column, c);
2247 // If we have an open font definition, we have to close it
2249 running_font.latexWriteEndChanges(os, basefont, basefont);
2252 // Needed if there is an optional argument but no contents.
2253 if (main_body > 0 && main_body == size()) {
2255 return_value = false;
2258 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2259 return return_value;
2263 // This one spits out the text of a table paragraph
2264 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2266 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2268 bool return_value = false;
2270 LyXLayout const & style =
2271 textclasslist.Style(current_view->buffer()->params.textclass,
2275 if (!IsDummy()) { // it is dummy if it is in a float!!!
2276 if (style.isCommand()) {
2279 } else if (align != LYX_ALIGN_LAYOUT) {
2282 return_value = true;
2285 os << "\\noindent ";
2289 case LYX_ALIGN_NONE:
2290 case LYX_ALIGN_BLOCK:
2291 case LYX_ALIGN_LAYOUT:
2292 case LYX_ALIGN_SPECIAL: break;
2293 case LYX_ALIGN_LEFT:
2294 os << "\\raggedright ";
2297 case LYX_ALIGN_RIGHT:
2298 os << "\\raggedleft ";
2301 case LYX_ALIGN_CENTER:
2302 os << "\\centering ";
2308 LyXFont basefont = getFont(-1); // Get layout font
2309 // Which font is currently active?
2310 LyXFont running_font = basefont;
2312 // Do we have an open font change?
2313 bool open_font = false;
2314 int current_cell_number = -1;
2315 int tmp = table->TexEndOfCell(os, current_cell_number);
2316 for (; tmp > 0 ; --tmp)
2319 texrow.start(this, 0);
2321 for (size_type i = 0; i < size(); ++i) {
2322 char c = GetChar(i);
2323 if (table->IsContRow(current_cell_number + 1)) {
2324 if (c == LyXParagraph::META_NEWLINE)
2325 ++current_cell_number;
2330 // Fully instantiated font
2331 LyXFont font = getFont(i);
2332 last_font = running_font;
2334 // Spaces at end of font change are simulated to be
2335 // outside font change.
2336 // i.e. we write "\textXX{text} " rather than
2337 // "\textXX{text }". (Asger)
2338 if (open_font && c == ' ' && i <= size() - 2
2339 && getFont(i + 1) != running_font
2340 && getFont(i + 1) != font) {
2341 font = getFont(i + 1);
2344 // We end font definition before blanks
2345 if (font != running_font && open_font) {
2346 column += running_font.latexWriteEndChanges(os,
2349 running_font = basefont;
2352 // Blanks are printed before start of fontswitch
2354 SimpleTeXBlanks(os, texrow, i, column, font, style);
2356 // Do we need to change font?
2357 if (font != running_font) {
2358 column += font.latexWriteStartChanges(os, basefont,
2360 running_font = font;
2363 // Do we need to turn on LaTeX mode?
2364 if (font.latex() != running_font.latex()) {
2365 if (font.latex() == LyXFont::ON
2366 && style.needprotect) {
2371 if (c == LyXParagraph::META_NEWLINE) {
2372 // special case for inside a table
2373 // different from default case in
2374 // SimpleTeXSpecialChars()
2376 column += running_font
2377 .latexWriteEndChanges(os, basefont,
2381 basefont = getFont(-1);
2382 running_font = basefont;
2383 ++current_cell_number;
2384 if (table->CellHasContRow(current_cell_number) >= 0) {
2385 TeXContTableRows(os, i + 1,
2386 current_cell_number,
2389 // if this cell follow only ContRows till end don't
2390 // put the EndOfCell because it is put after the
2392 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2393 --current_cell_number;
2396 int tmp = table->TexEndOfCell(os,
2397 current_cell_number);
2400 } else if (tmp < 0) {
2406 texrow.start(this, i + 1);
2408 SimpleTeXSpecialChars(os, texrow,
2409 font, running_font, basefont,
2410 open_font, style, i, column, c);
2414 // If we have an open font definition, we have to close it
2416 running_font.latexWriteEndChanges(os, basefont, basefont);
2418 ++current_cell_number;
2419 tmp = table->TexEndOfCell(os, current_cell_number);
2420 for (; tmp > 0; --tmp)
2422 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2423 return return_value;
2427 // This one spits out the text off ContRows in tables
2428 bool LyXParagraph::TeXContTableRows(ostream & os,
2429 LyXParagraph::size_type i,
2430 int current_cell_number,
2431 int & column, TexRow & texrow)
2433 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2439 bool return_value = false;
2440 LyXLayout const & style =
2441 textclasslist.Style(current_view->buffer()->params.textclass,
2443 LyXFont basefont = getFont(-1); // Get layout font
2445 // Which font is currently active?
2446 LyXFont running_font = basefont;
2447 // Do we have an open font change?
2448 bool open_font = false;
2450 size_type lastpos = i;
2451 int cell = table->CellHasContRow(current_cell_number);
2452 ++current_cell_number;
2454 // first find the right position
2456 for (; (i < size()) && (current_cell_number<cell); ++i) {
2458 if (c == LyXParagraph::META_NEWLINE)
2459 ++current_cell_number;
2463 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2467 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2472 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2476 // Fully instantiated font
2477 LyXFont font = getFont(i);
2478 last_font = running_font;
2480 // Spaces at end of font change are simulated to
2481 // be outside font change. i.e. we write
2482 // "\textXX{text} " rather than "\textXX{text }".
2484 if (open_font && c == ' ' && i <= size() - 2
2485 && getFont(i + 1) != running_font
2486 && getFont(i + 1) != font) {
2487 font = getFont(i + 1);
2490 // We end font definition before blanks
2491 if (font != running_font && open_font) {
2492 column += running_font.latexWriteEndChanges(os, basefont, font);
2493 running_font = basefont;
2496 // Blanks are printed before start of fontswitch
2498 SimpleTeXBlanks(os, texrow, i,
2499 column, font, style);
2501 // Do we need to change font?
2502 if (font != running_font) {
2504 font.latexWriteStartChanges(os,
2507 running_font = font;
2510 // Do we need to turn on LaTeX mode?
2511 if (font.latex() != running_font.latex()) {
2512 if (font.latex() == LyXFont::ON
2513 && style.needprotect) {
2518 SimpleTeXSpecialChars(os, texrow, font,
2519 running_font, basefont,
2520 open_font, style, i, column, c);
2522 // If we have an open font definition, we have to close it
2524 running_font.latexWriteEndChanges(os, basefont,
2528 basefont = getFont(-1);
2529 running_font = basefont;
2530 cell = table->CellHasContRow(current_cell_number);
2532 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2533 return return_value;
2537 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2539 bool retval = false;
2541 case LyXParagraph::META_HFILL:
2542 sgml_string.clear();
2545 case LyXParagraph::META_PROTECTED_SEPARATOR:
2549 case LyXParagraph::META_NEWLINE:
2553 sgml_string = "&";
2556 sgml_string = "<";
2559 sgml_string = ">";
2562 sgml_string = "$";
2565 sgml_string = "#";
2568 sgml_string = "%";
2571 sgml_string = "[";
2574 sgml_string = "]";
2577 sgml_string = "{";
2580 sgml_string = "}";
2583 sgml_string = "˜";
2586 sgml_string = """;
2589 sgml_string = "\";
2595 case '\0': // Ignore :-)
2596 sgml_string.clear();
2606 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2607 int & desc_on, int depth)
2610 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2612 LyXFont font1, font2;
2615 size_type main_body;
2616 bool emph_flag = false;
2618 LyXLayout const & style =
2619 textclasslist.Style(current_view->buffer()->params.textclass,
2622 if (style.labeltype != LABEL_MANUAL)
2625 main_body = BeginningOfMainBody();
2627 // Gets paragraph main font.
2629 font1 = style.labelfont;
2633 int char_line_count = depth;
2634 os << newlineAndDepth(depth);
2635 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2636 os << "<INFORMALTABLE>"
2637 << newlineAndDepth(++depth);
2639 int current_cell_number = -1;
2640 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2642 // Parsing main loop.
2643 for (size_type i = 0; i < size(); ++i) {
2645 if (table->IsContRow(current_cell_number+1)) {
2646 if (c == LyXParagraph::META_NEWLINE)
2647 ++current_cell_number;
2652 // Fully instantiated font
2655 // Handle <emphasis> tag.
2656 if (font1.emph() != font2.emph() && i) {
2657 if (font2.emph() == LyXFont::ON) {
2660 } else if (emph_flag) {
2661 os << "</emphasis>";
2665 if (c == LyXParagraph::META_NEWLINE) {
2666 // We have only to control for emphasis open here!
2668 os << "</emphasis>";
2671 font1 = font2 = getFont(-1);
2672 ++current_cell_number;
2673 if (table->CellHasContRow(current_cell_number) >= 0) {
2674 DocBookContTableRows(os, extra, desc_on, i + 1,
2675 current_cell_number,
2678 // if this cell follow only ContRows till end don't
2679 // put the EndOfCell because it is put after the
2681 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2682 --current_cell_number;
2685 tmp = table->DocBookEndOfCell(os,
2686 current_cell_number,
2691 } else if (c == LyXParagraph::META_INSET) {
2692 inset = GetInset(i);
2695 inset->DocBook(ost);
2696 string tmp_out = ost.str().c_str();
2699 inset->DocBook(ost);
2701 char * ctmp = ost.str();
2702 string tmp_out(ctmp);
2706 // This code needs some explanation:
2707 // Two insets are treated specially
2708 // label if it is the first element in a
2709 // command paragraph
2711 // graphics inside tables or figure floats
2713 // title (the equivalente in latex for this
2715 // and title should come first
2718 if(desc_on != 3 || i != 0) {
2719 if(tmp_out[0] == '@') {
2721 extra += frontStrip(tmp_out,
2724 os << frontStrip(tmp_out,
2729 } else if (font2.latex() == LyXFont::ON) {
2730 // "TeX"-Mode on == > SGML-Mode on.
2736 if (linuxDocConvertChar(c, sgml_string)
2737 && !style.free_spacing) {
2738 // in freespacing mode, spaces are
2739 // non-breaking characters
2744 << "</term><listitem><para>";
2756 // Needed if there is an optional argument but no contents.
2757 if (main_body > 0 && main_body == size()) {
2762 os << "</emphasis>";
2765 ++current_cell_number;
2766 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2767 // Resets description flag correctly.
2770 // <term> not closed...
2774 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2775 os << "</INFORMALTABLE>";
2777 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2782 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
2784 LyXParagraph::size_type i,
2785 int current_cell_number, int &column)
2790 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2795 //string emph = "emphasis";
2796 bool emph_flag = false;
2797 int char_line_count = 0;
2799 LyXLayout const & style =
2800 textclasslist.Style(current_view->buffer()->params.textclass,
2803 size_type main_body;
2804 if (style.labeltype != LABEL_MANUAL)
2807 main_body = BeginningOfMainBody();
2809 // Gets paragraph main font.
2812 font1 = style.labelfont;
2816 size_type lastpos = i;
2817 int cell = table->CellHasContRow(current_cell_number);
2818 ++current_cell_number;
2820 // first find the right position
2822 for (; i < size() && current_cell_number < cell; ++i) {
2824 if (c == LyXParagraph::META_NEWLINE)
2825 ++current_cell_number;
2829 // I don't know how to handle this so I comment it
2830 // for the moment (Jug)
2831 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2832 // file += " \\\\\n";
2835 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2840 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2844 // Fully instantiated font
2847 // Handle <emphasis> tag.
2848 if (font1.emph() != font2.emph() && i) {
2849 if (font2.emph() == LyXFont::ON) {
2852 } else if (emph_flag) {
2853 os << "</emphasis>";
2857 if (c == LyXParagraph::META_INSET) {
2858 inset = GetInset(i);
2861 inset->DocBook(ost);
2862 string tmp_out = ost.str().c_str();
2865 inset->DocBook(ost);
2867 char * ctmp = ost.str();
2868 string tmp_out(ctmp);
2872 // This code needs some explanation:
2873 // Two insets are treated specially
2874 // label if it is the first element in a
2875 // command paragraph
2877 // graphics inside tables or figure floats
2878 // can't go on title (the equivalente in
2879 // latex for this case is caption and title
2880 // should come first
2883 if(desc_on != 3 || i != 0) {
2884 if(tmp_out[0] == '@') {
2886 extra += frontStrip(tmp_out, '@');
2888 os << frontStrip(tmp_out, '@');
2892 } else if (font2.latex() == LyXFont::ON) {
2893 // "TeX"-Mode on == > SGML-Mode on.
2899 if (linuxDocConvertChar(c, sgml_string)
2900 && !style.free_spacing) {
2901 // in freespacing mode, spaces are
2902 // non-breaking characters
2907 << "</term><listitem><para>";
2917 // we have only to control for emphasis open here!
2919 os << "</emphasis>";
2922 font1 = font2 = getFont(-1);
2923 cell = table->CellHasContRow(current_cell_number);
2925 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2929 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
2930 LyXParagraph::size_type const i,
2931 int & column, LyXFont const & font,
2932 LyXLayout const & style)
2934 if (column > tex_code_break_column
2936 && GetChar(i - 1) != ' '
2938 // In LaTeX mode, we don't want to
2939 // break lines since some commands
2941 && ! (font.latex() == LyXFont::ON)
2942 // same in FreeSpacing mode
2943 && !style.free_spacing
2944 // In typewriter mode, we want to avoid
2945 // ! . ? : at the end of a line
2946 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2947 && (GetChar(i-1) == '.'
2948 || GetChar(i-1) == '?'
2949 || GetChar(i-1) == ':'
2950 || GetChar(i-1) == '!'))) {
2951 if (tex_code_break_column == 0) {
2952 // in batchmode we need LaTeX to still
2953 // see it as a space not as an extra '\n'
2959 texrow.start(this, i + 1);
2961 } else if (font.latex() == LyXFont::OFF) {
2962 if (style.free_spacing) {
2971 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
2973 LyXFont & running_font,
2976 LyXLayout const & style,
2977 LyXParagraph::size_type & i,
2978 int & column, char const c)
2980 // Two major modes: LaTeX or plain
2981 // Handle here those cases common to both modes
2982 // and then split to handle the two modes separately.
2984 case LyXParagraph::META_INSET: {
2985 Inset * inset = GetInset(i);
2988 int len = os.tellp();
2989 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
2990 || inset->LyxCode() == Inset::MATH_CODE
2991 || inset->LyxCode() == Inset::URL_CODE)
2992 && running_font.getFontDirection()
2993 == LYX_DIR_RIGHT_TO_LEFT) {
2998 int tmp = inset->Latex(os, style.isCommand(),
2999 style.free_spacing);
3007 column += os.tellp() - len;
3016 case LyXParagraph::META_NEWLINE:
3018 column += running_font.latexWriteEndChanges(os,
3023 basefont = getFont(-1);
3024 running_font = basefont;
3027 case LyXParagraph::META_HFILL:
3033 // And now for the special cases within each mode
3034 // Are we in LaTeX mode?
3035 if (font.latex() == LyXFont::ON) {
3036 // at present we only have one option
3037 // but I'll leave it as a switch statement
3038 // so its simpler to extend. (ARRae)
3041 case LyXParagraph::META_PROTECTED_SEPARATOR:
3046 // make sure that we will not print
3047 // error generating chars to the tex
3048 // file. This test would not be needed
3049 // if it were done in the buffer
3057 // Plain mode (i.e. not LaTeX)
3060 case LyXParagraph::META_PROTECTED_SEPARATOR:
3065 os << "\\textbackslash{}";
3069 case '°': case '±': case '²': case '³':
3070 case '×': case '÷': case '¹': case 'ª':
3071 case 'º': case '¬': case 'µ':
3072 if (current_view->buffer()->params.inputenc == "latin1") {
3073 os << "\\ensuremath{"
3082 case '|': case '<': case '>':
3083 // In T1 encoding, these characters exist
3084 if (lyxrc.fontenc == "T1") {
3086 //... but we should avoid ligatures
3087 if ((c == '>' || c == '<')
3089 && GetChar(i + 1) == c){
3090 os << "\\textcompwordmark{}";
3095 // Typewriter font also has them
3096 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3100 // Otherwise, we use what LaTeX
3104 os << "\\textless{}";
3108 os << "\\textgreater{}";
3112 os << "\\textbar{}";
3118 case '-': // "--" in Typewriter mode -> "-{}-"
3120 && GetChar(i + 1) == '-'
3121 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3130 os << "\\char`\\\"{}";
3135 if (current_view->buffer()->params.inputenc == "default") {
3144 case '%': case '#': case '{':
3151 os << "\\textasciitilde{}";
3156 os << "\\textasciicircum{}";
3160 case '*': case '[': case ']':
3161 // avoid being mistaken for optional arguments
3162 os << '{' << c << '}';
3167 // Blanks are printed before font switching.
3168 // Sure? I am not! (try nice-latex)
3169 // I am sure it's correct. LyX might be smarter
3170 // in the future, but for now, nothing wrong is
3175 /* idea for labels --- begin*/
3179 && font.family() != LyXFont::TYPEWRITER_FAMILY
3180 && GetChar(i + 1) == 'y'
3181 && GetChar(i + 2) == 'X') {
3189 && font.family() != LyXFont::TYPEWRITER_FAMILY
3190 && GetChar(i + 1) == 'e'
3191 && GetChar(i + 2) == 'X') {
3196 // Check for "LaTeX2e"
3199 && font.family() != LyXFont::TYPEWRITER_FAMILY
3200 && GetChar(i + 1) == 'a'
3201 && GetChar(i + 2) == 'T'
3202 && GetChar(i + 3) == 'e'
3203 && GetChar(i + 4) == 'X'
3204 && GetChar(i + 5) == '2'
3205 && GetChar(i + 6) == 'e') {
3210 // Check for "LaTeX"
3213 && font.family() != LyXFont::TYPEWRITER_FAMILY
3214 && GetChar(i + 1) == 'a'
3215 && GetChar(i + 2) == 'T'
3216 && GetChar(i + 3) == 'e'
3217 && GetChar(i + 4) == 'X') {
3221 /* idea for labels --- end*/
3222 } else if (c != '\0') {
3233 bool LyXParagraph::RoffContTableRows(ostream & os,
3234 LyXParagraph::size_type i,
3240 LyXFont font1(LyXFont::ALL_INHERIT);
3245 string fname2 = TmpFileName(string(), "RAT2");
3247 int cell = table->CellHasContRow(actcell);
3250 // first find the right position
3252 for (; i < size() && actcell < cell; ++i) {
3254 if (c == LyXParagraph::META_NEWLINE)
3259 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3262 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3264 font2 = GetFontSettings(i);
3265 if (font1.latex() != font2.latex()) {
3266 if (font2.latex() != LyXFont::OFF)
3271 case LyXParagraph::META_INSET:
3272 if ((inset = GetInset(i))) {
3275 stringstream ss(ios::in | ios::out);
3276 inset->Latex(ss, -1);
3288 inset->Latex(ss, -1);
3301 fstream fs(fname2.c_str(),
3304 WriteAlert(_("LYX_ERROR:"),
3305 _("Cannot open temporary file:"),
3309 inset->Latex(fs, -1);
3323 case LyXParagraph::META_NEWLINE:
3325 case LyXParagraph::META_HFILL:
3328 case LyXParagraph::META_PROTECTED_SEPARATOR:
3338 lyxerr.debug() << "RoffAsciiTable: "
3339 "NULL char in structure."
3344 cell = table->CellHasContRow(actcell);
3351 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3352 ostream & foot, TexRow & foot_texrow,
3355 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3356 LyXParagraph * par = this;
3358 while (par && par->depth == depth) {
3360 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3361 if (textclasslist.Style(current_view->buffer()->params.textclass,
3362 par->layout).isEnvironment()
3363 || par->pextra_type != PEXTRA_NONE) {
3364 par = par->TeXEnvironment(os, texrow,
3368 par = par->TeXOnePar(os, texrow,
3373 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3379 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3381 TexRow & foot_texrow,
3384 bool eindent_open = false;
3385 bool foot_this_level = false;
3386 // flags when footnotetext should be appended to file.
3387 static bool minipage_open = false;
3388 static int minipage_open_depth = 0;
3389 char par_sep = current_view->buffer()->params.paragraph_separation;
3391 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3393 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3395 LyXLayout const & style =
3396 textclasslist.Style(current_view->buffer()->params.textclass,
3399 if (pextra_type == PEXTRA_INDENT) {
3400 if (!pextra_width.empty()) {
3401 os << "\\begin{LyXParagraphIndent}{"
3402 << pextra_width << "}\n";
3404 //float ib = atof(pextra_widthp.c_str())/100;
3405 // string can't handle floats at present (971109)
3406 // so I'll do a conversion by hand knowing that
3407 // the limits are 0.0 to 1.0. ARRae.
3408 os << "\\begin{LyXParagraphIndent}{";
3409 switch (pextra_widthp.length()) {
3421 os << "\\columnwidth}\n";
3424 eindent_open = true;
3426 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3427 if (pextra_hfill && Previous() &&
3428 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3429 os << "\\hfill{}\n";
3432 if (par_sep == BufferParams::PARSEP_INDENT) {
3433 os << "{\\setlength\\parindent{0pt}\n";
3436 os << "\\begin{minipage}";
3437 switch(pextra_alignment) {
3438 case MINIPAGE_ALIGN_TOP:
3441 case MINIPAGE_ALIGN_MIDDLE:
3444 case MINIPAGE_ALIGN_BOTTOM:
3448 if (!pextra_width.empty()) {
3449 os << '{' << pextra_width << "}\n";
3451 //float ib = atof(par->pextra_width.c_str())/100;
3452 // string can't handle floats at present
3453 // so I'll do a conversion by hand knowing that
3454 // the limits are 0.0 to 1.0. ARRae.
3456 switch (pextra_widthp.length()) {
3468 os << "\\columnwidth}\n";
3471 if (par_sep == BufferParams::PARSEP_INDENT) {
3472 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3475 minipage_open = true;
3476 minipage_open_depth = depth;
3479 #ifdef WITH_WARNINGS
3480 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3481 //I disabled it because it breaks when lists span on several
3484 if (style.isEnvironment()){
3485 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3486 #ifdef FANCY_FOOTNOTE_CODE
3487 if (foot_count < 0) {
3488 // flag that footnote[mark][text] should be
3489 // used for any footnotes from now on
3491 foot_this_level = true;
3494 os << "\\begin{" << style.latexname() << "}{"
3495 << labelwidthstring << "}\n";
3496 } else if (style.labeltype == LABEL_BIBLIO) {
3498 os << "\\begin{" << style.latexname() << "}{"
3499 << bibitemWidthest(current_view->painter())
3501 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3502 #ifdef FANCY_FOOTNOTE_CODE
3503 if (foot_count < 0) {
3504 // flag that footnote[mark][text] should be
3505 // used for any footnotes from now on
3507 foot_this_level = true;
3510 os << "\\begin{" << style.latexname() << '}'
3511 << style.latexparam() << '\n';
3513 os << "\\begin{" << style.latexname() << '}'
3514 << style.latexparam() << '\n';
3517 LyXParagraph * par = this;
3519 par = par->TeXOnePar(os, texrow,
3520 foot, foot_texrow, foot_count);
3522 if (minipage_open && par && !style.isEnvironment() &&
3523 (par->pextra_type == PEXTRA_MINIPAGE) &&
3524 par->pextra_start_minipage) {
3525 os << "\\end{minipage}\n";
3527 if (par_sep == BufferParams::PARSEP_INDENT) {
3531 minipage_open = false;
3533 if (par && par->depth > depth) {
3534 if (textclasslist.Style(current_view->buffer()->params.textclass,
3535 par->layout).isParagraph()
3538 // How to handle this? (Lgb)
3539 //&& !suffixIs(os, "\n\n")
3541 // There should be at least one '\n' already
3542 // but we need there to be two for Standard
3543 // paragraphs that are depth-increment'ed to be
3544 // output correctly. However, tables can
3545 // also be paragraphs so don't adjust them.
3548 // Will it ever harm to have one '\n' too
3549 // many? i.e. that we sometimes will have
3550 // three in a row. (Lgb)
3554 par = par->TeXDeeper(os, texrow,
3555 foot, foot_texrow, foot_count);
3557 if (par && par->layout == layout && par->depth == depth &&
3558 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3559 if (par->pextra_hfill && par->Previous() &&
3560 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3561 os << "\\hfill{}\n";
3564 if (par_sep == BufferParams::PARSEP_INDENT) {
3565 os << "{\\setlength\\parindent{0pt}\n";
3568 os << "\\begin{minipage}";
3569 switch(par->pextra_alignment) {
3570 case MINIPAGE_ALIGN_TOP:
3573 case MINIPAGE_ALIGN_MIDDLE:
3576 case MINIPAGE_ALIGN_BOTTOM:
3580 if (!par->pextra_width.empty()) {
3581 os << '{' << par->pextra_width << "}\n";
3583 //float ib = atof(par->pextra_widthp.c_str())/100;
3584 // string can't handle floats at present
3585 // so I'll do a conversion by hand knowing that
3586 // the limits are 0.0 to 1.0. ARRae.
3588 switch (par->pextra_widthp.length()) {
3593 os << "0." << par->pextra_widthp;
3596 os << "0.0" << par->pextra_widthp;
3598 os << "\\columnwidth}\n";
3601 if (par_sep == BufferParams::PARSEP_INDENT) {
3602 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3605 minipage_open = true;
3606 minipage_open_depth = par->depth;
3609 && par->layout == layout
3610 && par->depth == depth
3611 && par->pextra_type == pextra_type);
3613 if (style.isEnvironment()) {
3614 os << "\\end{" << style.latexname() << '}';
3615 // maybe this should go after the minipage closes?
3616 if (foot_this_level) {
3617 if (foot_count >= 1) {
3618 if (foot_count > 1) {
3619 os << "\\addtocounter{footnote}{-"
3624 texrow += foot_texrow;
3626 foot_texrow.reset();
3631 if (minipage_open && (minipage_open_depth == depth) &&
3632 (!par || par->pextra_start_minipage ||
3633 par->pextra_type != PEXTRA_MINIPAGE)) {
3634 os << "\\end{minipage}\n";
3636 if (par_sep == BufferParams::PARSEP_INDENT) {
3640 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3641 os << "\\medskip\n\n";
3645 minipage_open = false;
3648 os << "\\end{LyXParagraphIndent}\n";
3651 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3652 && par->pextra_hfill)) {
3656 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3657 return par; // ale970302
3661 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3662 ostream & foot, TexRow & foot_texrow,
3664 LyXDirection par_direction)
3666 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3667 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3668 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3669 "No footnote!" << endl;
3671 LyXParagraph * par = this;
3672 LyXLayout const & style =
3673 textclasslist.Style(current_view->buffer()->params.textclass,
3674 previous->GetLayout());
3676 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3677 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3678 "Float other than footnote in command"
3679 " with moving argument is illegal" << endl;
3682 if (footnotekind != LyXParagraph::FOOTNOTE
3683 && footnotekind != LyXParagraph::MARGIN
3686 // How to solve this?
3687 //&& !suffixIs(file, '\n')
3689 // we need to ensure that real floats like tables and figures
3690 // have their \begin{} on a new line otherwise we can get
3691 // incorrect results when using the endfloat.sty package
3692 // especially if two floats follow one another. ARRae 981022
3693 // NOTE: if the file is length 0 it must have just been
3694 // written out so we assume it ended with a '\n'
3696 // As far as I can see there is never any harm in writing
3697 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3702 BufferParams * params = ¤t_view->buffer()->params;
3703 bool footer_in_body = true;
3704 switch (footnotekind) {
3705 case LyXParagraph::FOOTNOTE:
3706 if (style.intitle) {
3707 os << "\\thanks{\n";
3708 footer_in_body = false;
3710 if (foot_count == -1) {
3711 // we're at depth 0 so we can use:
3712 os << "\\footnote{%\n";
3713 footer_in_body = false;
3715 os << "\\footnotemark{}%\n";
3717 // we only need this when there are
3718 // multiple footnotes
3719 os << "\\stepcounter{footnote}";
3721 os << "\\footnotetext{%\n";
3722 foot_texrow.start(this, 0);
3723 foot_texrow.newline();
3728 case LyXParagraph::MARGIN:
3729 os << "\\marginpar{\n";
3731 case LyXParagraph::FIG:
3732 if (pextra_type == PEXTRA_FLOATFLT
3733 && (!pextra_width.empty()
3734 || !pextra_widthp.empty())) {
3735 if (!pextra_width.empty())
3736 os << "\\begin{floatingfigure}{"
3737 << pextra_width << "}\n";
3739 os << "\\begin{floatingfigure}{"
3740 << atoi(pextra_widthp.c_str())/100.0
3741 << "\\textwidth}\n";
3743 os << "\\begin{figure}";
3744 if (!params->float_placement.empty()) {
3745 os << '[' << params->float_placement << "]\n";
3751 case LyXParagraph::TAB:
3752 os << "\\begin{table}";
3753 if (!params->float_placement.empty()) {
3754 os << '[' << params->float_placement << "]\n";
3759 case LyXParagraph::WIDE_FIG:
3760 os << "\\begin{figure*}";
3761 if (!params->float_placement.empty()) {
3762 os << '[' << params->float_placement << "]\n";
3767 case LyXParagraph::WIDE_TAB:
3768 os << "\\begin{table*}";
3769 if (!params->float_placement.empty()) {
3770 os << '[' << params->float_placement << "]\n";
3775 case LyXParagraph::ALGORITHM:
3776 os << "\\begin{algorithm}\n";
3782 LyXDirection direction = getParDirection();
3783 if (direction != par_direction) {
3784 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3785 os << lyxrc.language_command_ltr << '\n';
3787 os << lyxrc.language_command_rtl << '\n';
3791 if (footnotekind != LyXParagraph::FOOTNOTE
3792 || !footer_in_body) {
3793 // Process text for all floats except footnotes in body
3795 LyXLayout const & style =
3797 .Style(current_view->buffer()->params
3801 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3803 if (style.isEnvironment()
3804 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3805 // Allows the use of minipages within float
3806 // environments. Shouldn't be circular because
3807 // we don't support footnotes inside
3808 // floats (yet). ARRae
3809 par = par->TeXEnvironment(os, texrow,
3813 par = par->TeXOnePar(os, texrow,
3818 if (par && !par->IsDummy() && par->depth > depth) {
3819 par = par->TeXDeeper(os, texrow,
3823 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3825 // process footnotes > depth 0 or in environments separately
3826 // NOTE: Currently don't support footnotes within footnotes
3827 // even though that is possible using the \footnotemark
3829 ostringstream dummy;
3833 TexRow dummy_texrow;
3834 int dummy_count = 0;
3836 LyXLayout const & style =
3838 .Style(current_view->buffer()->params
3842 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3844 if (style.isEnvironment()
3845 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3846 // Allows the use of minipages within float
3847 // environments. Shouldn't be circular because
3848 // we don't support footnotes inside
3849 // floats (yet). ARRae
3850 par = par->TeXEnvironment(foot, foot_texrow,
3851 dummy, dummy_texrow,
3854 par = par->TeXOnePar(foot, foot_texrow,
3855 dummy, dummy_texrow,
3859 if (par && !par->IsDummy() && par->depth > depth) {
3860 par = par->TeXDeeper(foot, foot_texrow,
3861 dummy, dummy_texrow,
3865 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3867 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3868 "Footnote in a Footnote -- not supported"
3871 #ifndef HAVE_OSTREAM
3872 delete [] dummy.str();
3876 switch (footnotekind) {
3877 case LyXParagraph::FOOTNOTE:
3878 if (footer_in_body) {
3879 // This helps tell which of the multiple
3880 // footnotetexts an error was in.
3882 foot_texrow.newline();
3887 case LyXParagraph::MARGIN:
3890 case LyXParagraph::FIG:
3891 if (pextra_type == PEXTRA_FLOATFLT
3892 && (!pextra_width.empty()
3893 || !pextra_widthp.empty()))
3894 os << "\\end{floatingfigure}";
3896 os << "\\end{figure}";
3898 case LyXParagraph::TAB:
3899 os << "\\end{table}";
3901 case LyXParagraph::WIDE_FIG:
3902 os << "\\end{figure*}";
3904 case LyXParagraph::WIDE_TAB:
3905 os << "\\end{table*}";
3907 case LyXParagraph::ALGORITHM:
3908 os << "\\end{algorithm}";
3912 if (footnotekind != LyXParagraph::FOOTNOTE
3913 && footnotekind != LyXParagraph::MARGIN) {
3914 // we need to ensure that real floats like tables and figures
3915 // have their \end{} on a line of their own otherwise we can
3916 // get incorrect results when using the endfloat.sty package.
3921 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
3926 void LyXParagraph::SetPExtraType(int type, char const * width,
3927 char const * widthp)
3930 pextra_width = width;
3931 pextra_widthp = widthp;
3933 if (textclasslist.Style(current_view->buffer()->params.textclass,
3934 layout).isEnvironment()) {
3939 while (par && (par->layout == layout)
3940 && (par->depth == depth)) {
3942 par = par->Previous();
3944 par = par->FirstPhysicalPar();
3945 while (par && par->depth > depth) {
3946 par = par->Previous();
3948 par = par->FirstPhysicalPar();
3952 while (par && (par->layout == layout)
3953 && (par->depth == depth)) {
3954 par->pextra_type = type;
3955 par->pextra_width = width;
3956 par->pextra_widthp = widthp;
3957 par = par->NextAfterFootnote();
3958 if (par && (par->depth > depth))
3959 par->SetPExtraType(type, width, widthp);
3960 while (par && ((par->depth > depth) || par->IsDummy()))
3961 par = par->NextAfterFootnote();
3967 void LyXParagraph::UnsetPExtraType()
3969 if (pextra_type == PEXTRA_NONE)
3972 pextra_type = PEXTRA_NONE;
3973 pextra_width.clear();
3974 pextra_widthp.clear();
3976 if (textclasslist.Style(current_view->buffer()->params.textclass,
3977 layout).isEnvironment()) {
3982 while (par && (par->layout == layout)
3983 && (par->depth == depth)) {
3985 par = par->Previous();
3987 par = par->FirstPhysicalPar();
3988 while (par && par->depth > depth) {
3989 par = par->Previous();
3991 par = par->FirstPhysicalPar();
3995 while (par && (par->layout == layout)
3996 && (par->depth == depth)) {
3997 par->pextra_type = PEXTRA_NONE;
3998 par->pextra_width.clear();
3999 par->pextra_widthp.clear();
4000 par = par->NextAfterFootnote();
4001 if (par && (par->depth > depth))
4002 par->UnsetPExtraType();
4003 while (par && ((par->depth > depth) || par->IsDummy()))
4004 par = par->NextAfterFootnote();
4010 bool LyXParagraph::IsHfill(size_type pos) const
4012 return IsHfillChar(GetChar(pos));
4016 bool LyXParagraph::IsInset(size_type pos) const
4018 return IsInsetChar(GetChar(pos));
4022 bool LyXParagraph::IsFloat(size_type pos) const
4024 return IsFloatChar(GetChar(pos));
4028 bool LyXParagraph::IsNewline(size_type pos) const
4032 tmp = IsNewlineChar(GetChar(pos));
4037 bool LyXParagraph::IsSeparator(size_type pos) const
4039 return IsSeparatorChar(GetChar(pos));
4043 bool LyXParagraph::IsLineSeparator(size_type pos) const
4045 return IsLineSeparatorChar(GetChar(pos));
4049 bool LyXParagraph::IsKomma(size_type pos) const
4051 return IsKommaChar(GetChar(pos));
4055 /// Used by the spellchecker
4056 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4058 unsigned char c = GetChar(pos);
4059 if (IsLetterChar(c))
4061 // '\0' is not a letter, allthough every string contains "" (below)
4064 // We want to pass the ' and escape chars to ispell
4065 string extra = lyxrc.isp_esc_chars + '\'';
4069 return contains(extra, ch);
4073 bool LyXParagraph::IsWord(size_type pos ) const
4075 return IsWordChar(GetChar(pos)) ;
4079 LyXDirection LyXParagraph::getParDirection() const
4081 if (!lyxrc.rtl_support || table)
4082 return LYX_DIR_LEFT_TO_RIGHT;
4085 return (getFont(0).direction() == LyXFont::RTL_DIR)
4086 ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
4088 return current_view->buffer()->params.getDocumentDirection();
4093 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4095 if (!lyxrc.rtl_support)
4096 return LYX_DIR_LEFT_TO_RIGHT;
4098 LyXDirection direction = getFont(pos).getFontDirection();
4099 if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4100 && !IsLineSeparator(pos + 1)
4101 && !(table && IsNewline(pos + 1))
4102 && (getFont(pos - 1).getFontDirection() != direction
4103 || getFont(pos + 1).getFontDirection() != direction))
4104 return getParDirection();