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 void LyXParagraph::readSimpleWholeFile(istream & is)
1903 InsertChar(text.size(), c);
1908 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1909 ostream & foot, TexRow & foot_texrow,
1912 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1913 LyXParagraph * par = next;
1914 LyXLayout const & style =
1915 textclasslist.Style(current_view->buffer()->params.textclass,
1918 bool further_blank_line = false;
1920 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1922 if (start_of_appendix) {
1923 os << "\\appendix\n";
1927 if (tex_code_break_column && style.isCommand()){
1932 if (pagebreak_top) {
1934 further_blank_line = true;
1936 if (added_space_top.kind() != VSpace::NONE) {
1937 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1938 further_blank_line = true;
1942 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1943 << "\\vspace{-1\\parskip}";
1944 further_blank_line = true;
1947 if (further_blank_line){
1952 LyXDirection direction = getParDirection();
1953 LyXDirection global_direction =
1954 current_view->buffer()->params.getDocumentDirection();
1955 if (direction != global_direction) {
1956 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1957 os << lyxrc.language_command_ltr << '\n';
1959 os << lyxrc.language_command_rtl << '\n';
1964 switch (style.latextype) {
1967 << style.latexname()
1968 << style.latexparam();
1970 case LATEX_ITEM_ENVIRONMENT:
1972 bibkey->Latex(os, false, false);
1976 case LATEX_LIST_ENVIRONMENT:
1983 bool need_par = SimpleTeXOnePar(os, texrow);
1985 // Spit out footnotes
1986 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1987 && par->footnoteflag != footnoteflag) {
1988 par = par->TeXFootnote(os, texrow,
1989 foot, foot_texrow, foot_count,
1991 par->SimpleTeXOnePar(os, texrow);
1995 // Make sure that \\par is done with the font of the last
1996 // character if this has another size as the default.
1997 // This is necessary because LaTeX (and LyX on the screen)
1998 // calculates the space between the baselines according
1999 // to this font. (Matthias)
2000 LyXFont font = getFont(Last() - 1);
2002 if (style.resfont.size() != font.size()) {
2008 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2009 GetLayout()).isCommand()){
2010 if (style.resfont.size() != font.size()) {
2016 } else if (style.resfont.size() != font.size()){
2017 os << "{\\" << font.latexSize() << " \\par}";
2020 if (direction != global_direction)
2021 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2022 os << '\n' << lyxrc.language_command_rtl;
2024 os << '\n' << lyxrc.language_command_ltr;
2026 switch (style.latextype) {
2027 case LATEX_ITEM_ENVIRONMENT:
2028 case LATEX_LIST_ENVIRONMENT:
2029 if (par && (depth < par->depth)) {
2034 case LATEX_ENVIRONMENT:
2035 // if its the last paragraph of the current environment
2036 // skip it otherwise fall through
2038 && (par->layout != layout
2039 || par->depth != depth
2040 || par->pextra_type != pextra_type))
2043 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2044 && footnotekind != LyXParagraph::FOOTNOTE
2045 && footnotekind != LyXParagraph::MARGIN
2049 // don't insert this if we would be adding it
2050 // before or after a table in a float. This
2051 // little trick is needed in order to allow
2052 // use of tables in \subfigures or \subtables.
2058 further_blank_line = false;
2060 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2061 further_blank_line = true;
2064 if (added_space_bottom.kind() != VSpace::NONE) {
2065 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2066 further_blank_line = true;
2069 if (pagebreak_bottom) {
2071 further_blank_line = true;
2074 if (further_blank_line){
2079 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2080 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2085 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2090 // This one spits out the text of the paragraph
2091 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2093 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2096 return SimpleTeXOneTablePar(os, texrow);
2098 bool return_value = false;
2100 LyXLayout const & style =
2101 textclasslist.Style(current_view->buffer()->params.textclass,
2103 LyXFont basefont, last_font;
2105 // Maybe we have to create a optional argument.
2106 size_type main_body;
2107 if (style.labeltype != LABEL_MANUAL)
2110 main_body = BeginningOfMainBody();
2112 if (main_body > 0) {
2114 basefont = getFont(-2); // Get label font
2116 basefont = getFont(-1); // Get layout font
2124 if (style.isCommand()) {
2127 } else if (align != LYX_ALIGN_LAYOUT) {
2130 return_value = true;
2134 // Which font is currently active?
2135 LyXFont running_font(basefont);
2136 // Do we have an open font change?
2137 bool open_font = false;
2139 texrow.start(this, 0);
2141 for (size_type i = 0; i < size(); ++i) {
2143 // First char in paragraph or after label?
2144 if (i == main_body && !IsDummy()) {
2145 if (main_body > 0) {
2147 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2150 basefont = getFont(-1); // Now use the layout font
2151 running_font = basefont;
2155 if (style.isCommand()) {
2158 } else if (align != LYX_ALIGN_LAYOUT) {
2161 return_value = true;
2165 os << "\\noindent ";
2169 case LYX_ALIGN_NONE:
2170 case LYX_ALIGN_BLOCK:
2171 case LYX_ALIGN_LAYOUT:
2172 case LYX_ALIGN_SPECIAL: break;
2173 case LYX_ALIGN_LEFT:
2174 os << "\\raggedright ";
2177 case LYX_ALIGN_RIGHT:
2178 os << "\\raggedleft ";
2181 case LYX_ALIGN_CENTER:
2182 os << "\\centering ";
2190 // Fully instantiated font
2191 LyXFont font = getFont(i);
2192 last_font = running_font;
2194 // Spaces at end of font change are simulated to be
2195 // outside font change, i.e. we write "\textXX{text} "
2196 // rather than "\textXX{text }". (Asger)
2197 if (open_font && c == ' ' && i <= size() - 2
2198 && !getFont(i+1).equalExceptLatex(running_font)
2199 && !getFont(i+1).equalExceptLatex(font)) {
2200 font = getFont(i + 1);
2202 // We end font definition before blanks
2203 if (!font.equalExceptLatex(running_font) && open_font) {
2204 column += running_font.latexWriteEndChanges(os,
2206 (i == main_body-1) ? basefont : font);
2207 running_font = basefont;
2211 // Blanks are printed before start of fontswitch
2213 // Do not print the separation of the optional argument
2214 if (i != main_body - 1) {
2215 SimpleTeXBlanks(os, texrow, i,
2216 column, font, style);
2220 // Do we need to change font?
2221 if (!font.equalExceptLatex(running_font)
2222 && i != main_body-1) {
2223 column += font.latexWriteStartChanges(os, basefont,
2225 running_font = font;
2229 if (c == LyXParagraph::META_NEWLINE) {
2230 // newlines are handled differently here than
2231 // the default in SimpleTeXSpecialChars().
2232 if (!style.newline_allowed
2233 || font.latex() == LyXFont::ON) {
2237 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2240 basefont = getFont(-1);
2241 running_font = basefont;
2242 if (font.family() ==
2243 LyXFont::TYPEWRITER_FAMILY) {
2249 texrow.start(this, i + 1);
2252 SimpleTeXSpecialChars(os, texrow,
2253 font, running_font, basefont,
2254 open_font, style, i, column, c);
2258 // If we have an open font definition, we have to close it
2260 running_font.latexWriteEndChanges(os, basefont, basefont);
2263 // Needed if there is an optional argument but no contents.
2264 if (main_body > 0 && main_body == size()) {
2266 return_value = false;
2269 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2270 return return_value;
2274 // This one spits out the text of a table paragraph
2275 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2277 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2279 bool return_value = false;
2281 LyXLayout const & style =
2282 textclasslist.Style(current_view->buffer()->params.textclass,
2286 if (!IsDummy()) { // it is dummy if it is in a float!!!
2287 if (style.isCommand()) {
2290 } else if (align != LYX_ALIGN_LAYOUT) {
2293 return_value = true;
2296 os << "\\noindent ";
2300 case LYX_ALIGN_NONE:
2301 case LYX_ALIGN_BLOCK:
2302 case LYX_ALIGN_LAYOUT:
2303 case LYX_ALIGN_SPECIAL: break;
2304 case LYX_ALIGN_LEFT:
2305 os << "\\raggedright ";
2308 case LYX_ALIGN_RIGHT:
2309 os << "\\raggedleft ";
2312 case LYX_ALIGN_CENTER:
2313 os << "\\centering ";
2319 LyXFont basefont = getFont(-1); // Get layout font
2320 // Which font is currently active?
2321 LyXFont running_font = basefont;
2323 // Do we have an open font change?
2324 bool open_font = false;
2325 int current_cell_number = -1;
2326 int tmp = table->TexEndOfCell(os, current_cell_number);
2327 for (; tmp > 0 ; --tmp)
2330 texrow.start(this, 0);
2332 for (size_type i = 0; i < size(); ++i) {
2333 char c = GetChar(i);
2334 if (table->IsContRow(current_cell_number + 1)) {
2335 if (c == LyXParagraph::META_NEWLINE)
2336 ++current_cell_number;
2341 // Fully instantiated font
2342 LyXFont font = getFont(i);
2343 last_font = running_font;
2345 // Spaces at end of font change are simulated to be
2346 // outside font change.
2347 // i.e. we write "\textXX{text} " rather than
2348 // "\textXX{text }". (Asger)
2349 if (open_font && c == ' ' && i <= size() - 2
2350 && getFont(i + 1) != running_font
2351 && getFont(i + 1) != font) {
2352 font = getFont(i + 1);
2355 // We end font definition before blanks
2356 if (font != running_font && open_font) {
2357 column += running_font.latexWriteEndChanges(os,
2360 running_font = basefont;
2363 // Blanks are printed before start of fontswitch
2365 SimpleTeXBlanks(os, texrow, i, column, font, style);
2367 // Do we need to change font?
2368 if (font != running_font) {
2369 column += font.latexWriteStartChanges(os, basefont,
2371 running_font = font;
2374 // Do we need to turn on LaTeX mode?
2375 if (font.latex() != running_font.latex()) {
2376 if (font.latex() == LyXFont::ON
2377 && style.needprotect) {
2382 if (c == LyXParagraph::META_NEWLINE) {
2383 // special case for inside a table
2384 // different from default case in
2385 // SimpleTeXSpecialChars()
2387 column += running_font
2388 .latexWriteEndChanges(os, basefont,
2392 basefont = getFont(-1);
2393 running_font = basefont;
2394 ++current_cell_number;
2395 if (table->CellHasContRow(current_cell_number) >= 0) {
2396 TeXContTableRows(os, i + 1,
2397 current_cell_number,
2400 // if this cell follow only ContRows till end don't
2401 // put the EndOfCell because it is put after the
2403 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2404 --current_cell_number;
2407 int tmp = table->TexEndOfCell(os,
2408 current_cell_number);
2411 } else if (tmp < 0) {
2417 texrow.start(this, i + 1);
2419 SimpleTeXSpecialChars(os, texrow,
2420 font, running_font, basefont,
2421 open_font, style, i, column, c);
2425 // If we have an open font definition, we have to close it
2427 running_font.latexWriteEndChanges(os, basefont, basefont);
2429 ++current_cell_number;
2430 tmp = table->TexEndOfCell(os, current_cell_number);
2431 for (; tmp > 0; --tmp)
2433 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2434 return return_value;
2438 // This one spits out the text off ContRows in tables
2439 bool LyXParagraph::TeXContTableRows(ostream & os,
2440 LyXParagraph::size_type i,
2441 int current_cell_number,
2442 int & column, TexRow & texrow)
2444 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2450 bool return_value = false;
2451 LyXLayout const & style =
2452 textclasslist.Style(current_view->buffer()->params.textclass,
2454 LyXFont basefont = getFont(-1); // Get layout font
2456 // Which font is currently active?
2457 LyXFont running_font = basefont;
2458 // Do we have an open font change?
2459 bool open_font = false;
2461 size_type lastpos = i;
2462 int cell = table->CellHasContRow(current_cell_number);
2463 ++current_cell_number;
2465 // first find the right position
2467 for (; (i < size()) && (current_cell_number<cell); ++i) {
2469 if (c == LyXParagraph::META_NEWLINE)
2470 ++current_cell_number;
2474 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2478 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2483 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2487 // Fully instantiated font
2488 LyXFont font = getFont(i);
2489 last_font = running_font;
2491 // Spaces at end of font change are simulated to
2492 // be outside font change. i.e. we write
2493 // "\textXX{text} " rather than "\textXX{text }".
2495 if (open_font && c == ' ' && i <= size() - 2
2496 && getFont(i + 1) != running_font
2497 && getFont(i + 1) != font) {
2498 font = getFont(i + 1);
2501 // We end font definition before blanks
2502 if (font != running_font && open_font) {
2503 column += running_font.latexWriteEndChanges(os, basefont, font);
2504 running_font = basefont;
2507 // Blanks are printed before start of fontswitch
2509 SimpleTeXBlanks(os, texrow, i,
2510 column, font, style);
2512 // Do we need to change font?
2513 if (font != running_font) {
2515 font.latexWriteStartChanges(os,
2518 running_font = font;
2521 // Do we need to turn on LaTeX mode?
2522 if (font.latex() != running_font.latex()) {
2523 if (font.latex() == LyXFont::ON
2524 && style.needprotect) {
2529 SimpleTeXSpecialChars(os, texrow, font,
2530 running_font, basefont,
2531 open_font, style, i, column, c);
2533 // If we have an open font definition, we have to close it
2535 running_font.latexWriteEndChanges(os, basefont,
2539 basefont = getFont(-1);
2540 running_font = basefont;
2541 cell = table->CellHasContRow(current_cell_number);
2543 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2544 return return_value;
2548 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2550 bool retval = false;
2552 case LyXParagraph::META_HFILL:
2553 sgml_string.clear();
2556 case LyXParagraph::META_PROTECTED_SEPARATOR:
2560 case LyXParagraph::META_NEWLINE:
2564 sgml_string = "&";
2567 sgml_string = "<";
2570 sgml_string = ">";
2573 sgml_string = "$";
2576 sgml_string = "#";
2579 sgml_string = "%";
2582 sgml_string = "[";
2585 sgml_string = "]";
2588 sgml_string = "{";
2591 sgml_string = "}";
2594 sgml_string = "˜";
2597 sgml_string = """;
2600 sgml_string = "\";
2606 case '\0': // Ignore :-)
2607 sgml_string.clear();
2617 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2618 int & desc_on, int depth)
2621 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2623 LyXFont font1, font2;
2626 size_type main_body;
2627 bool emph_flag = false;
2629 LyXLayout const & style =
2630 textclasslist.Style(current_view->buffer()->params.textclass,
2633 if (style.labeltype != LABEL_MANUAL)
2636 main_body = BeginningOfMainBody();
2638 // Gets paragraph main font.
2640 font1 = style.labelfont;
2644 int char_line_count = depth;
2645 os << newlineAndDepth(depth);
2646 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2647 os << "<INFORMALTABLE>"
2648 << newlineAndDepth(++depth);
2650 int current_cell_number = -1;
2651 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2653 // Parsing main loop.
2654 for (size_type i = 0; i < size(); ++i) {
2656 if (table->IsContRow(current_cell_number+1)) {
2657 if (c == LyXParagraph::META_NEWLINE)
2658 ++current_cell_number;
2663 // Fully instantiated font
2666 // Handle <emphasis> tag.
2667 if (font1.emph() != font2.emph() && i) {
2668 if (font2.emph() == LyXFont::ON) {
2671 } else if (emph_flag) {
2672 os << "</emphasis>";
2676 if (c == LyXParagraph::META_NEWLINE) {
2677 // We have only to control for emphasis open here!
2679 os << "</emphasis>";
2682 font1 = font2 = getFont(-1);
2683 ++current_cell_number;
2684 if (table->CellHasContRow(current_cell_number) >= 0) {
2685 DocBookContTableRows(os, extra, desc_on, i + 1,
2686 current_cell_number,
2689 // if this cell follow only ContRows till end don't
2690 // put the EndOfCell because it is put after the
2692 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2693 --current_cell_number;
2696 tmp = table->DocBookEndOfCell(os,
2697 current_cell_number,
2702 } else if (c == LyXParagraph::META_INSET) {
2703 inset = GetInset(i);
2706 inset->DocBook(ost);
2707 string tmp_out = ost.str().c_str();
2710 inset->DocBook(ost);
2712 char * ctmp = ost.str();
2713 string tmp_out(ctmp);
2717 // This code needs some explanation:
2718 // Two insets are treated specially
2719 // label if it is the first element in a
2720 // command paragraph
2722 // graphics inside tables or figure floats
2724 // title (the equivalente in latex for this
2726 // and title should come first
2729 if(desc_on != 3 || i != 0) {
2730 if(tmp_out[0] == '@') {
2732 extra += frontStrip(tmp_out,
2735 os << frontStrip(tmp_out,
2740 } else if (font2.latex() == LyXFont::ON) {
2741 // "TeX"-Mode on == > SGML-Mode on.
2747 if (linuxDocConvertChar(c, sgml_string)
2748 && !style.free_spacing) {
2749 // in freespacing mode, spaces are
2750 // non-breaking characters
2755 << "</term><listitem><para>";
2767 // Needed if there is an optional argument but no contents.
2768 if (main_body > 0 && main_body == size()) {
2773 os << "</emphasis>";
2776 ++current_cell_number;
2777 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2778 // Resets description flag correctly.
2781 // <term> not closed...
2785 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2786 os << "</INFORMALTABLE>";
2788 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2793 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
2795 LyXParagraph::size_type i,
2796 int current_cell_number, int &column)
2801 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2806 //string emph = "emphasis";
2807 bool emph_flag = false;
2808 int char_line_count = 0;
2810 LyXLayout const & style =
2811 textclasslist.Style(current_view->buffer()->params.textclass,
2814 size_type main_body;
2815 if (style.labeltype != LABEL_MANUAL)
2818 main_body = BeginningOfMainBody();
2820 // Gets paragraph main font.
2823 font1 = style.labelfont;
2827 size_type lastpos = i;
2828 int cell = table->CellHasContRow(current_cell_number);
2829 ++current_cell_number;
2831 // first find the right position
2833 for (; i < size() && current_cell_number < cell; ++i) {
2835 if (c == LyXParagraph::META_NEWLINE)
2836 ++current_cell_number;
2840 // I don't know how to handle this so I comment it
2841 // for the moment (Jug)
2842 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2843 // file += " \\\\\n";
2846 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2851 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2855 // Fully instantiated font
2858 // Handle <emphasis> tag.
2859 if (font1.emph() != font2.emph() && i) {
2860 if (font2.emph() == LyXFont::ON) {
2863 } else if (emph_flag) {
2864 os << "</emphasis>";
2868 if (c == LyXParagraph::META_INSET) {
2869 inset = GetInset(i);
2872 inset->DocBook(ost);
2873 string tmp_out = ost.str().c_str();
2876 inset->DocBook(ost);
2878 char * ctmp = ost.str();
2879 string tmp_out(ctmp);
2883 // This code needs some explanation:
2884 // Two insets are treated specially
2885 // label if it is the first element in a
2886 // command paragraph
2888 // graphics inside tables or figure floats
2889 // can't go on title (the equivalente in
2890 // latex for this case is caption and title
2891 // should come first
2894 if(desc_on != 3 || i != 0) {
2895 if(tmp_out[0] == '@') {
2897 extra += frontStrip(tmp_out, '@');
2899 os << frontStrip(tmp_out, '@');
2903 } else if (font2.latex() == LyXFont::ON) {
2904 // "TeX"-Mode on == > SGML-Mode on.
2910 if (linuxDocConvertChar(c, sgml_string)
2911 && !style.free_spacing) {
2912 // in freespacing mode, spaces are
2913 // non-breaking characters
2918 << "</term><listitem><para>";
2928 // we have only to control for emphasis open here!
2930 os << "</emphasis>";
2933 font1 = font2 = getFont(-1);
2934 cell = table->CellHasContRow(current_cell_number);
2936 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2940 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
2941 LyXParagraph::size_type const i,
2942 int & column, LyXFont const & font,
2943 LyXLayout const & style)
2945 if (column > tex_code_break_column
2947 && GetChar(i - 1) != ' '
2949 // In LaTeX mode, we don't want to
2950 // break lines since some commands
2952 && ! (font.latex() == LyXFont::ON)
2953 // same in FreeSpacing mode
2954 && !style.free_spacing
2955 // In typewriter mode, we want to avoid
2956 // ! . ? : at the end of a line
2957 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2958 && (GetChar(i-1) == '.'
2959 || GetChar(i-1) == '?'
2960 || GetChar(i-1) == ':'
2961 || GetChar(i-1) == '!'))) {
2962 if (tex_code_break_column == 0) {
2963 // in batchmode we need LaTeX to still
2964 // see it as a space not as an extra '\n'
2970 texrow.start(this, i + 1);
2972 } else if (font.latex() == LyXFont::OFF) {
2973 if (style.free_spacing) {
2982 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
2984 LyXFont & running_font,
2987 LyXLayout const & style,
2988 LyXParagraph::size_type & i,
2989 int & column, char const c)
2991 // Two major modes: LaTeX or plain
2992 // Handle here those cases common to both modes
2993 // and then split to handle the two modes separately.
2995 case LyXParagraph::META_INSET: {
2996 Inset * inset = GetInset(i);
2999 int len = os.tellp();
3000 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3001 || inset->LyxCode() == Inset::MATH_CODE
3002 || inset->LyxCode() == Inset::URL_CODE)
3003 && running_font.getFontDirection()
3004 == LYX_DIR_RIGHT_TO_LEFT) {
3009 int tmp = inset->Latex(os, style.isCommand(),
3010 style.free_spacing);
3018 column += os.tellp() - len;
3027 case LyXParagraph::META_NEWLINE:
3029 column += running_font.latexWriteEndChanges(os,
3034 basefont = getFont(-1);
3035 running_font = basefont;
3038 case LyXParagraph::META_HFILL:
3044 // And now for the special cases within each mode
3045 // Are we in LaTeX mode?
3046 if (font.latex() == LyXFont::ON) {
3047 // at present we only have one option
3048 // but I'll leave it as a switch statement
3049 // so its simpler to extend. (ARRae)
3052 case LyXParagraph::META_PROTECTED_SEPARATOR:
3057 // make sure that we will not print
3058 // error generating chars to the tex
3059 // file. This test would not be needed
3060 // if it were done in the buffer
3068 // Plain mode (i.e. not LaTeX)
3071 case LyXParagraph::META_PROTECTED_SEPARATOR:
3076 os << "\\textbackslash{}";
3080 case '°': case '±': case '²': case '³':
3081 case '×': case '÷': case '¹': case 'ª':
3082 case 'º': case '¬': case 'µ':
3083 if (current_view->buffer()->params.inputenc == "latin1") {
3084 os << "\\ensuremath{"
3093 case '|': case '<': case '>':
3094 // In T1 encoding, these characters exist
3095 if (lyxrc.fontenc == "T1") {
3097 //... but we should avoid ligatures
3098 if ((c == '>' || c == '<')
3100 && GetChar(i + 1) == c){
3101 os << "\\textcompwordmark{}";
3106 // Typewriter font also has them
3107 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3111 // Otherwise, we use what LaTeX
3115 os << "\\textless{}";
3119 os << "\\textgreater{}";
3123 os << "\\textbar{}";
3129 case '-': // "--" in Typewriter mode -> "-{}-"
3131 && GetChar(i + 1) == '-'
3132 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3141 os << "\\char`\\\"{}";
3146 if (current_view->buffer()->params.inputenc == "default") {
3155 case '%': case '#': case '{':
3162 os << "\\textasciitilde{}";
3167 os << "\\textasciicircum{}";
3171 case '*': case '[': case ']':
3172 // avoid being mistaken for optional arguments
3173 os << '{' << c << '}';
3178 // Blanks are printed before font switching.
3179 // Sure? I am not! (try nice-latex)
3180 // I am sure it's correct. LyX might be smarter
3181 // in the future, but for now, nothing wrong is
3186 /* idea for labels --- begin*/
3190 && font.family() != LyXFont::TYPEWRITER_FAMILY
3191 && GetChar(i + 1) == 'y'
3192 && GetChar(i + 2) == 'X') {
3200 && font.family() != LyXFont::TYPEWRITER_FAMILY
3201 && GetChar(i + 1) == 'e'
3202 && GetChar(i + 2) == 'X') {
3207 // Check for "LaTeX2e"
3210 && font.family() != LyXFont::TYPEWRITER_FAMILY
3211 && GetChar(i + 1) == 'a'
3212 && GetChar(i + 2) == 'T'
3213 && GetChar(i + 3) == 'e'
3214 && GetChar(i + 4) == 'X'
3215 && GetChar(i + 5) == '2'
3216 && GetChar(i + 6) == 'e') {
3221 // Check for "LaTeX"
3224 && font.family() != LyXFont::TYPEWRITER_FAMILY
3225 && GetChar(i + 1) == 'a'
3226 && GetChar(i + 2) == 'T'
3227 && GetChar(i + 3) == 'e'
3228 && GetChar(i + 4) == 'X') {
3232 /* idea for labels --- end*/
3233 } else if (c != '\0') {
3244 bool LyXParagraph::RoffContTableRows(ostream & os,
3245 LyXParagraph::size_type i,
3251 LyXFont font1(LyXFont::ALL_INHERIT);
3256 string fname2 = TmpFileName(string(), "RAT2");
3258 int cell = table->CellHasContRow(actcell);
3261 // first find the right position
3263 for (; i < size() && actcell < cell; ++i) {
3265 if (c == LyXParagraph::META_NEWLINE)
3270 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3273 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3275 font2 = GetFontSettings(i);
3276 if (font1.latex() != font2.latex()) {
3277 if (font2.latex() != LyXFont::OFF)
3282 case LyXParagraph::META_INSET:
3283 if ((inset = GetInset(i))) {
3286 stringstream ss(ios::in | ios::out);
3287 inset->Latex(ss, -1);
3299 inset->Latex(ss, -1);
3312 fstream fs(fname2.c_str(),
3315 WriteAlert(_("LYX_ERROR:"),
3316 _("Cannot open temporary file:"),
3320 inset->Latex(fs, -1);
3334 case LyXParagraph::META_NEWLINE:
3336 case LyXParagraph::META_HFILL:
3339 case LyXParagraph::META_PROTECTED_SEPARATOR:
3349 lyxerr.debug() << "RoffAsciiTable: "
3350 "NULL char in structure."
3355 cell = table->CellHasContRow(actcell);
3362 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3363 ostream & foot, TexRow & foot_texrow,
3366 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3367 LyXParagraph * par = this;
3369 while (par && par->depth == depth) {
3371 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3372 if (textclasslist.Style(current_view->buffer()->params.textclass,
3373 par->layout).isEnvironment()
3374 || par->pextra_type != PEXTRA_NONE) {
3375 par = par->TeXEnvironment(os, texrow,
3379 par = par->TeXOnePar(os, texrow,
3384 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3390 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3392 TexRow & foot_texrow,
3395 bool eindent_open = false;
3396 bool foot_this_level = false;
3397 // flags when footnotetext should be appended to file.
3398 static bool minipage_open = false;
3399 static int minipage_open_depth = 0;
3400 char par_sep = current_view->buffer()->params.paragraph_separation;
3402 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3404 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3406 LyXLayout const & style =
3407 textclasslist.Style(current_view->buffer()->params.textclass,
3410 if (pextra_type == PEXTRA_INDENT) {
3411 if (!pextra_width.empty()) {
3412 os << "\\begin{LyXParagraphIndent}{"
3413 << pextra_width << "}\n";
3415 //float ib = atof(pextra_widthp.c_str())/100;
3416 // string can't handle floats at present (971109)
3417 // so I'll do a conversion by hand knowing that
3418 // the limits are 0.0 to 1.0. ARRae.
3419 os << "\\begin{LyXParagraphIndent}{";
3420 switch (pextra_widthp.length()) {
3432 os << "\\columnwidth}\n";
3435 eindent_open = true;
3437 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3438 if (pextra_hfill && Previous() &&
3439 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3440 os << "\\hfill{}\n";
3443 if (par_sep == BufferParams::PARSEP_INDENT) {
3444 os << "{\\setlength\\parindent{0pt}\n";
3447 os << "\\begin{minipage}";
3448 switch(pextra_alignment) {
3449 case MINIPAGE_ALIGN_TOP:
3452 case MINIPAGE_ALIGN_MIDDLE:
3455 case MINIPAGE_ALIGN_BOTTOM:
3459 if (!pextra_width.empty()) {
3460 os << '{' << pextra_width << "}\n";
3462 //float ib = atof(par->pextra_width.c_str())/100;
3463 // string can't handle floats at present
3464 // so I'll do a conversion by hand knowing that
3465 // the limits are 0.0 to 1.0. ARRae.
3467 switch (pextra_widthp.length()) {
3479 os << "\\columnwidth}\n";
3482 if (par_sep == BufferParams::PARSEP_INDENT) {
3483 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3486 minipage_open = true;
3487 minipage_open_depth = depth;
3490 #ifdef WITH_WARNINGS
3491 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3492 //I disabled it because it breaks when lists span on several
3495 if (style.isEnvironment()){
3496 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3497 #ifdef FANCY_FOOTNOTE_CODE
3498 if (foot_count < 0) {
3499 // flag that footnote[mark][text] should be
3500 // used for any footnotes from now on
3502 foot_this_level = true;
3505 os << "\\begin{" << style.latexname() << "}{"
3506 << labelwidthstring << "}\n";
3507 } else if (style.labeltype == LABEL_BIBLIO) {
3509 os << "\\begin{" << style.latexname() << "}{"
3510 << bibitemWidthest(current_view->painter())
3512 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3513 #ifdef FANCY_FOOTNOTE_CODE
3514 if (foot_count < 0) {
3515 // flag that footnote[mark][text] should be
3516 // used for any footnotes from now on
3518 foot_this_level = true;
3521 os << "\\begin{" << style.latexname() << '}'
3522 << style.latexparam() << '\n';
3524 os << "\\begin{" << style.latexname() << '}'
3525 << style.latexparam() << '\n';
3528 LyXParagraph * par = this;
3530 par = par->TeXOnePar(os, texrow,
3531 foot, foot_texrow, foot_count);
3533 if (minipage_open && par && !style.isEnvironment() &&
3534 (par->pextra_type == PEXTRA_MINIPAGE) &&
3535 par->pextra_start_minipage) {
3536 os << "\\end{minipage}\n";
3538 if (par_sep == BufferParams::PARSEP_INDENT) {
3542 minipage_open = false;
3544 if (par && par->depth > depth) {
3545 if (textclasslist.Style(current_view->buffer()->params.textclass,
3546 par->layout).isParagraph()
3549 // How to handle this? (Lgb)
3550 //&& !suffixIs(os, "\n\n")
3552 // There should be at least one '\n' already
3553 // but we need there to be two for Standard
3554 // paragraphs that are depth-increment'ed to be
3555 // output correctly. However, tables can
3556 // also be paragraphs so don't adjust them.
3559 // Will it ever harm to have one '\n' too
3560 // many? i.e. that we sometimes will have
3561 // three in a row. (Lgb)
3565 par = par->TeXDeeper(os, texrow,
3566 foot, foot_texrow, foot_count);
3568 if (par && par->layout == layout && par->depth == depth &&
3569 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3570 if (par->pextra_hfill && par->Previous() &&
3571 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3572 os << "\\hfill{}\n";
3575 if (par_sep == BufferParams::PARSEP_INDENT) {
3576 os << "{\\setlength\\parindent{0pt}\n";
3579 os << "\\begin{minipage}";
3580 switch(par->pextra_alignment) {
3581 case MINIPAGE_ALIGN_TOP:
3584 case MINIPAGE_ALIGN_MIDDLE:
3587 case MINIPAGE_ALIGN_BOTTOM:
3591 if (!par->pextra_width.empty()) {
3592 os << '{' << par->pextra_width << "}\n";
3594 //float ib = atof(par->pextra_widthp.c_str())/100;
3595 // string can't handle floats at present
3596 // so I'll do a conversion by hand knowing that
3597 // the limits are 0.0 to 1.0. ARRae.
3599 switch (par->pextra_widthp.length()) {
3604 os << "0." << par->pextra_widthp;
3607 os << "0.0" << par->pextra_widthp;
3609 os << "\\columnwidth}\n";
3612 if (par_sep == BufferParams::PARSEP_INDENT) {
3613 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3616 minipage_open = true;
3617 minipage_open_depth = par->depth;
3620 && par->layout == layout
3621 && par->depth == depth
3622 && par->pextra_type == pextra_type);
3624 if (style.isEnvironment()) {
3625 os << "\\end{" << style.latexname() << '}';
3626 // maybe this should go after the minipage closes?
3627 if (foot_this_level) {
3628 if (foot_count >= 1) {
3629 if (foot_count > 1) {
3630 os << "\\addtocounter{footnote}{-"
3635 texrow += foot_texrow;
3637 foot_texrow.reset();
3642 if (minipage_open && (minipage_open_depth == depth) &&
3643 (!par || par->pextra_start_minipage ||
3644 par->pextra_type != PEXTRA_MINIPAGE)) {
3645 os << "\\end{minipage}\n";
3647 if (par_sep == BufferParams::PARSEP_INDENT) {
3651 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3652 os << "\\medskip\n\n";
3656 minipage_open = false;
3659 os << "\\end{LyXParagraphIndent}\n";
3662 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3663 && par->pextra_hfill)) {
3667 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3668 return par; // ale970302
3672 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3673 ostream & foot, TexRow & foot_texrow,
3675 LyXDirection par_direction)
3677 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3678 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3679 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3680 "No footnote!" << endl;
3682 LyXParagraph * par = this;
3683 LyXLayout const & style =
3684 textclasslist.Style(current_view->buffer()->params.textclass,
3685 previous->GetLayout());
3687 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3688 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3689 "Float other than footnote in command"
3690 " with moving argument is illegal" << endl;
3693 if (footnotekind != LyXParagraph::FOOTNOTE
3694 && footnotekind != LyXParagraph::MARGIN
3697 // How to solve this?
3698 //&& !suffixIs(file, '\n')
3700 // we need to ensure that real floats like tables and figures
3701 // have their \begin{} on a new line otherwise we can get
3702 // incorrect results when using the endfloat.sty package
3703 // especially if two floats follow one another. ARRae 981022
3704 // NOTE: if the file is length 0 it must have just been
3705 // written out so we assume it ended with a '\n'
3707 // As far as I can see there is never any harm in writing
3708 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3713 BufferParams * params = ¤t_view->buffer()->params;
3714 bool footer_in_body = true;
3715 switch (footnotekind) {
3716 case LyXParagraph::FOOTNOTE:
3717 if (style.intitle) {
3718 os << "\\thanks{\n";
3719 footer_in_body = false;
3721 if (foot_count == -1) {
3722 // we're at depth 0 so we can use:
3723 os << "\\footnote{%\n";
3724 footer_in_body = false;
3726 os << "\\footnotemark{}%\n";
3728 // we only need this when there are
3729 // multiple footnotes
3730 os << "\\stepcounter{footnote}";
3732 os << "\\footnotetext{%\n";
3733 foot_texrow.start(this, 0);
3734 foot_texrow.newline();
3739 case LyXParagraph::MARGIN:
3740 os << "\\marginpar{\n";
3742 case LyXParagraph::FIG:
3743 if (pextra_type == PEXTRA_FLOATFLT
3744 && (!pextra_width.empty()
3745 || !pextra_widthp.empty())) {
3746 if (!pextra_width.empty())
3747 os << "\\begin{floatingfigure}{"
3748 << pextra_width << "}\n";
3750 os << "\\begin{floatingfigure}{"
3751 << atoi(pextra_widthp.c_str())/100.0
3752 << "\\textwidth}\n";
3754 os << "\\begin{figure}";
3755 if (!params->float_placement.empty()) {
3756 os << '[' << params->float_placement << "]\n";
3762 case LyXParagraph::TAB:
3763 os << "\\begin{table}";
3764 if (!params->float_placement.empty()) {
3765 os << '[' << params->float_placement << "]\n";
3770 case LyXParagraph::WIDE_FIG:
3771 os << "\\begin{figure*}";
3772 if (!params->float_placement.empty()) {
3773 os << '[' << params->float_placement << "]\n";
3778 case LyXParagraph::WIDE_TAB:
3779 os << "\\begin{table*}";
3780 if (!params->float_placement.empty()) {
3781 os << '[' << params->float_placement << "]\n";
3786 case LyXParagraph::ALGORITHM:
3787 os << "\\begin{algorithm}\n";
3793 LyXDirection direction = getParDirection();
3794 if (direction != par_direction) {
3795 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3796 os << lyxrc.language_command_ltr << '\n';
3798 os << lyxrc.language_command_rtl << '\n';
3802 if (footnotekind != LyXParagraph::FOOTNOTE
3803 || !footer_in_body) {
3804 // Process text for all floats except footnotes in body
3806 LyXLayout const & style =
3808 .Style(current_view->buffer()->params
3812 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3814 if (style.isEnvironment()
3815 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3816 // Allows the use of minipages within float
3817 // environments. Shouldn't be circular because
3818 // we don't support footnotes inside
3819 // floats (yet). ARRae
3820 par = par->TeXEnvironment(os, texrow,
3824 par = par->TeXOnePar(os, texrow,
3829 if (par && !par->IsDummy() && par->depth > depth) {
3830 par = par->TeXDeeper(os, texrow,
3834 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3836 // process footnotes > depth 0 or in environments separately
3837 // NOTE: Currently don't support footnotes within footnotes
3838 // even though that is possible using the \footnotemark
3840 ostringstream dummy;
3844 TexRow dummy_texrow;
3845 int dummy_count = 0;
3847 LyXLayout const & style =
3849 .Style(current_view->buffer()->params
3853 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3855 if (style.isEnvironment()
3856 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3857 // Allows the use of minipages within float
3858 // environments. Shouldn't be circular because
3859 // we don't support footnotes inside
3860 // floats (yet). ARRae
3861 par = par->TeXEnvironment(foot, foot_texrow,
3862 dummy, dummy_texrow,
3865 par = par->TeXOnePar(foot, foot_texrow,
3866 dummy, dummy_texrow,
3870 if (par && !par->IsDummy() && par->depth > depth) {
3871 par = par->TeXDeeper(foot, foot_texrow,
3872 dummy, dummy_texrow,
3876 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3878 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3879 "Footnote in a Footnote -- not supported"
3882 #ifndef HAVE_OSTREAM
3883 delete [] dummy.str();
3887 switch (footnotekind) {
3888 case LyXParagraph::FOOTNOTE:
3889 if (footer_in_body) {
3890 // This helps tell which of the multiple
3891 // footnotetexts an error was in.
3893 foot_texrow.newline();
3898 case LyXParagraph::MARGIN:
3901 case LyXParagraph::FIG:
3902 if (pextra_type == PEXTRA_FLOATFLT
3903 && (!pextra_width.empty()
3904 || !pextra_widthp.empty()))
3905 os << "\\end{floatingfigure}";
3907 os << "\\end{figure}";
3909 case LyXParagraph::TAB:
3910 os << "\\end{table}";
3912 case LyXParagraph::WIDE_FIG:
3913 os << "\\end{figure*}";
3915 case LyXParagraph::WIDE_TAB:
3916 os << "\\end{table*}";
3918 case LyXParagraph::ALGORITHM:
3919 os << "\\end{algorithm}";
3923 if (footnotekind != LyXParagraph::FOOTNOTE
3924 && footnotekind != LyXParagraph::MARGIN) {
3925 // we need to ensure that real floats like tables and figures
3926 // have their \end{} on a line of their own otherwise we can
3927 // get incorrect results when using the endfloat.sty package.
3932 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
3937 void LyXParagraph::SetPExtraType(int type, char const * width,
3938 char const * widthp)
3941 pextra_width = width;
3942 pextra_widthp = widthp;
3944 if (textclasslist.Style(current_view->buffer()->params.textclass,
3945 layout).isEnvironment()) {
3950 while (par && (par->layout == layout)
3951 && (par->depth == depth)) {
3953 par = par->Previous();
3955 par = par->FirstPhysicalPar();
3956 while (par && par->depth > depth) {
3957 par = par->Previous();
3959 par = par->FirstPhysicalPar();
3963 while (par && (par->layout == layout)
3964 && (par->depth == depth)) {
3965 par->pextra_type = type;
3966 par->pextra_width = width;
3967 par->pextra_widthp = widthp;
3968 par = par->NextAfterFootnote();
3969 if (par && (par->depth > depth))
3970 par->SetPExtraType(type, width, widthp);
3971 while (par && ((par->depth > depth) || par->IsDummy()))
3972 par = par->NextAfterFootnote();
3978 void LyXParagraph::UnsetPExtraType()
3980 if (pextra_type == PEXTRA_NONE)
3983 pextra_type = PEXTRA_NONE;
3984 pextra_width.clear();
3985 pextra_widthp.clear();
3987 if (textclasslist.Style(current_view->buffer()->params.textclass,
3988 layout).isEnvironment()) {
3993 while (par && (par->layout == layout)
3994 && (par->depth == depth)) {
3996 par = par->Previous();
3998 par = par->FirstPhysicalPar();
3999 while (par && par->depth > depth) {
4000 par = par->Previous();
4002 par = par->FirstPhysicalPar();
4006 while (par && (par->layout == layout)
4007 && (par->depth == depth)) {
4008 par->pextra_type = PEXTRA_NONE;
4009 par->pextra_width.clear();
4010 par->pextra_widthp.clear();
4011 par = par->NextAfterFootnote();
4012 if (par && (par->depth > depth))
4013 par->UnsetPExtraType();
4014 while (par && ((par->depth > depth) || par->IsDummy()))
4015 par = par->NextAfterFootnote();
4021 bool LyXParagraph::IsHfill(size_type pos) const
4023 return IsHfillChar(GetChar(pos));
4027 bool LyXParagraph::IsInset(size_type pos) const
4029 return IsInsetChar(GetChar(pos));
4033 bool LyXParagraph::IsFloat(size_type pos) const
4035 return IsFloatChar(GetChar(pos));
4039 bool LyXParagraph::IsNewline(size_type pos) const
4043 tmp = IsNewlineChar(GetChar(pos));
4048 bool LyXParagraph::IsSeparator(size_type pos) const
4050 return IsSeparatorChar(GetChar(pos));
4054 bool LyXParagraph::IsLineSeparator(size_type pos) const
4056 return IsLineSeparatorChar(GetChar(pos));
4060 bool LyXParagraph::IsKomma(size_type pos) const
4062 return IsKommaChar(GetChar(pos));
4066 /// Used by the spellchecker
4067 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4069 unsigned char c = GetChar(pos);
4070 if (IsLetterChar(c))
4072 // '\0' is not a letter, allthough every string contains "" (below)
4075 // We want to pass the ' and escape chars to ispell
4076 string extra = lyxrc.isp_esc_chars + '\'';
4080 return contains(extra, ch);
4084 bool LyXParagraph::IsWord(size_type pos ) const
4086 return IsWordChar(GetChar(pos)) ;
4090 LyXDirection LyXParagraph::getParDirection() const
4092 if (!lyxrc.rtl_support || table)
4093 return LYX_DIR_LEFT_TO_RIGHT;
4096 return (getFont(0).direction() == LyXFont::RTL_DIR)
4097 ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
4099 return current_view->buffer()->params.getDocumentDirection();
4104 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4106 if (!lyxrc.rtl_support)
4107 return LYX_DIR_LEFT_TO_RIGHT;
4109 LyXDirection direction = getFont(pos).getFontDirection();
4110 if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4111 && !IsLineSeparator(pos + 1)
4112 && !(table && IsNewline(pos + 1))
4113 && (getFont(pos - 1).getFontDirection() != direction
4114 || getFont(pos + 1).getFontDirection() != direction))
4115 return getParDirection();