1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2001 The LyX Team.
9 * ====================================================== */
13 #include "paragraph.h"
14 #include "paragraph_pimpl.h"
17 #include "bufferparams.h"
18 #include "BufferView.h"
24 #include "latexrunparams.h"
27 #include "paragraph_funcs.h"
28 #include "ParameterStruct.h"
33 #include "insets/insetbibitem.h"
34 #include "insets/insetoptarg.h"
35 #include "insets/insetenv.h"
37 #include "support/filetools.h"
38 #include "support/lstrings.h"
39 #include "support/lyxmanip.h"
40 #include "support/FileInfo.h"
41 #include "support/LAssert.h"
42 #include "support/textutils.h"
53 using std::lower_bound;
54 using std::upper_bound;
59 // this is a minibuffer
64 LyXFont minibuffer_font;
65 Inset * minibuffer_inset;
70 Paragraph::Paragraph()
71 : pimpl_(new Paragraph::Pimpl(this))
79 Paragraph::Paragraph(Paragraph const & lp)
80 : pimpl_(new Paragraph::Pimpl(*lp.pimpl_, this))
84 // this is because of the dummy layout of the paragraphs that
86 layout_ = lp.layout();
89 // copy everything behind the break-position to the new paragraph
90 insetlist = lp.insetlist;
91 InsetList::iterator it = insetlist.begin();
92 InsetList::iterator end = insetlist.end();
93 for (; it != end; ++it) {
94 it->inset = it->inset->clone(**buffer_);
95 // tell the new inset who is the boss now
96 it->inset->parOwner(this);
101 // the destructor removes the new paragraph from the list
102 Paragraph::~Paragraph()
106 //lyxerr << "Paragraph::paragraph_id = "
107 // << Paragraph::paragraph_id << endl;
111 void Paragraph::write(Buffer const * buf, ostream & os,
112 BufferParams const & bparams,
113 depth_type & dth) const
115 // The beginning or end of a deeper (i.e. nested) area?
116 if (dth != params().depth()) {
117 if (params().depth() > dth) {
118 while (params().depth() > dth) {
119 os << "\n\\begin_deeper ";
123 while (params().depth() < dth) {
124 os << "\n\\end_deeper ";
130 // First write the layout
131 os << "\n\\layout " << layout()->name() << '\n';
135 LyXFont font1(LyXFont::ALL_INHERIT, bparams.language);
137 Change running_change = Change(Change::UNCHANGED);
138 lyx::time_type const curtime(lyx::current_time());
141 for (pos_type i = 0; i < size(); ++i) {
147 Change change = pimpl_->lookupChangeFull(i);
148 Changes::lyxMarkChange(os, column, curtime, running_change, change);
149 running_change = change;
151 // Write font changes
152 LyXFont font2 = getFontSettings(bparams, i);
153 if (font2 != font1) {
154 font2.lyxWriteChanges(font1, os);
159 value_type const c = getChar(i);
163 Inset const * inset = getInset(i);
165 if (inset->directWrite()) {
166 // international char, let it write
167 // code directly so it's shorter in
169 inset->write(buf, os);
171 os << "\n\\begin_inset ";
172 inset->write(buf, os);
173 os << "\n\\end_inset \n\n";
179 os << "\n\\backslash \n";
183 if (i + 1 < size() && getChar(i + 1) == ' ') {
190 if ((column > 70 && c == ' ')
195 // this check is to amend a bug. LyX sometimes
196 // inserts '\0' this could cause problems.
200 lyxerr << "ERROR (Paragraph::writeFile):"
201 " NULL char in structure." << endl;
207 // to make reading work properly
209 running_change = pimpl_->lookupChange(0);
210 Changes::lyxMarkChange(os, column, curtime,
211 Change(Change::UNCHANGED), running_change);
213 Changes::lyxMarkChange(os, column, curtime,
214 running_change, Change(Change::UNCHANGED));
218 void Paragraph::validate(LaTeXFeatures & features) const
220 pimpl_->validate(features, *layout());
224 // First few functions needed for cut and paste and paragraph breaking.
225 void Paragraph::copyIntoMinibuffer(Buffer const & buffer, pos_type pos) const
227 BufferParams bparams = buffer.params;
229 minibuffer_char = getChar(pos);
230 minibuffer_font = getFontSettings(bparams, pos);
231 minibuffer_inset = 0;
232 if (minibuffer_char == Paragraph::META_INSET) {
234 minibuffer_inset = getInset(pos)->clone(buffer);
236 minibuffer_inset = 0;
237 minibuffer_char = ' ';
238 // This reflects what GetInset() does (ARRae)
244 void Paragraph::cutIntoMinibuffer(BufferParams const & bparams, pos_type pos)
246 minibuffer_char = getChar(pos);
247 minibuffer_font = getFontSettings(bparams, pos);
248 minibuffer_inset = 0;
249 if (minibuffer_char == Paragraph::META_INSET) {
251 // the inset is not in a paragraph anymore
252 minibuffer_inset = insetlist.release(pos);
253 minibuffer_inset->parOwner(0);
255 minibuffer_inset = 0;
256 minibuffer_char = ' ';
257 // This reflects what GetInset() does (ARRae)
262 // Erase(pos); now the caller is responsible for that.
266 bool Paragraph::insertFromMinibuffer(pos_type pos)
268 if (minibuffer_char == Paragraph::META_INSET) {
269 if (!insetAllowed(minibuffer_inset->lyxCode())) {
272 insertInset(pos, minibuffer_inset, minibuffer_font);
274 LyXFont f = minibuffer_font;
275 if (!checkInsertChar(f)) {
278 insertChar(pos, minibuffer_char, f);
286 void Paragraph::eraseIntern(lyx::pos_type pos)
288 pimpl_->eraseIntern(pos);
292 bool Paragraph::erase(pos_type pos)
294 return pimpl_->erase(pos);
298 int Paragraph::erase(pos_type start, pos_type end)
300 return pimpl_->erase(start, end);
304 bool Paragraph::checkInsertChar(LyXFont & font)
306 if (pimpl_->inset_owner)
307 return pimpl_->inset_owner->checkInsertChar(font);
312 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c)
314 LyXFont const f(LyXFont::ALL_INHERIT);
315 insertChar(pos, c, f);
319 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c,
320 LyXFont const & font, Change change)
322 pimpl_->insertChar(pos, c, font, change);
326 void Paragraph::insertInset(pos_type pos, Inset * inset)
328 LyXFont const f(LyXFont::ALL_INHERIT);
329 insertInset(pos, inset, f);
333 void Paragraph::insertInset(pos_type pos, Inset * inset, LyXFont const & font, Change change)
335 pimpl_->insertInset(pos, inset, font, change);
339 bool Paragraph::insetAllowed(Inset::Code code)
341 //lyxerr << "Paragraph::InsertInsetAllowed" << endl;
342 if (pimpl_->inset_owner)
343 return pimpl_->inset_owner->insetAllowed(code);
348 Inset * Paragraph::getInset(pos_type pos)
350 lyx::Assert(pos < size());
351 return insetlist.get(pos);
355 Inset const * Paragraph::getInset(pos_type pos) const
357 lyx::Assert(pos < size());
358 return insetlist.get(pos);
362 // Gets uninstantiated font setting at position.
363 LyXFont const Paragraph::getFontSettings(BufferParams const & bparams,
366 lyx::Assert(pos <= size());
368 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
369 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
370 for (; cit != end; ++cit) {
371 if (cit->pos() >= pos)
377 retfont = cit->font();
378 else if (pos == size() && !empty())
379 retfont = getFontSettings(bparams, pos - 1);
381 retfont = LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
387 // Gets uninstantiated font setting at position 0
388 LyXFont const Paragraph::getFirstFontSettings() const
390 if (!empty() && !pimpl_->fontlist.empty())
391 return pimpl_->fontlist[0].font();
393 return LyXFont(LyXFont::ALL_INHERIT);
397 // Gets the fully instantiated font at a given position in a paragraph
398 // This is basically the same function as LyXText::GetFont() in text2.C.
399 // The difference is that this one is used for generating the LaTeX file,
400 // and thus cosmetic "improvements" are disallowed: This has to deliver
401 // the true picture of the buffer. (Asger)
402 LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
403 LyXFont const & outerfont) const
405 lyx::Assert(pos >= 0);
407 LyXLayout_ptr const & lout = layout();
409 pos_type const body_pos = beginningOfBody();
413 layoutfont = lout->labelfont;
415 layoutfont = lout->font;
417 LyXFont tmpfont = getFontSettings(bparams, pos);
418 tmpfont.realize(layoutfont);
419 tmpfont.realize(outerfont);
421 return realizeFont(tmpfont, bparams);
425 LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
426 LyXFont const & outerfont) const
428 LyXLayout_ptr const & lout = layout();
430 LyXFont tmpfont = lout->labelfont;
431 tmpfont.setLanguage(getParLanguage(bparams));
432 tmpfont.realize(outerfont);
434 return realizeFont(tmpfont, bparams);
438 LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
439 LyXFont const & outerfont) const
441 LyXLayout_ptr const & lout = layout();
443 LyXFont tmpfont = lout->font;
444 tmpfont.setLanguage(getParLanguage(bparams));
445 tmpfont.realize(outerfont);
447 return realizeFont(tmpfont, bparams);
451 /// Returns the height of the highest font in range
453 Paragraph::highestFontInRange(pos_type startpos, pos_type endpos,
454 LyXFont::FONT_SIZE const def_size) const
456 if (pimpl_->fontlist.empty())
459 Pimpl::FontList::const_iterator end_it = pimpl_->fontlist.begin();
460 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
461 for (; end_it != end; ++end_it) {
462 if (end_it->pos() >= endpos)
469 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
470 for (; cit != end; ++cit) {
471 if (cit->pos() >= startpos)
475 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
476 for (; cit != end_it; ++cit) {
477 LyXFont::FONT_SIZE size = cit->font().size();
478 if (size == LyXFont::INHERIT_SIZE)
480 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
487 Paragraph::value_type
488 Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
490 value_type c = getChar(pos);
491 if (!lyxrc.rtl_support)
521 if (uc != c && getFontSettings(bparams, pos).isRightToLeft())
528 void Paragraph::setFont(pos_type pos, LyXFont const & font)
530 lyx::Assert(pos <= size());
532 // First, reduce font against layout/label font
533 // Update: The SetCharFont() routine in text2.C already
534 // reduces font, so we don't need to do that here. (Asger)
535 // No need to simplify this because it will disappear
536 // in a new kernel. (Asger)
537 // Next search font table
539 Pimpl::FontList::iterator beg = pimpl_->fontlist.begin();
540 Pimpl::FontList::iterator it = beg;
541 Pimpl::FontList::iterator endit = pimpl_->fontlist.end();
542 for (; it != endit; ++it) {
543 if (it->pos() >= pos)
546 unsigned int i = std::distance(beg, it);
547 bool notfound = (it == endit);
549 if (!notfound && pimpl_->fontlist[i].font() == font)
552 bool begin = pos == 0 || notfound ||
553 (i > 0 && pimpl_->fontlist[i - 1].pos() == pos - 1);
554 // Is position pos is a beginning of a font block?
555 bool end = !notfound && pimpl_->fontlist[i].pos() == pos;
556 // Is position pos is the end of a font block?
557 if (begin && end) { // A single char block
558 if (i + 1 < pimpl_->fontlist.size() &&
559 pimpl_->fontlist[i + 1].font() == font) {
560 // Merge the singleton block with the next block
561 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
562 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
563 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i - 1);
564 } else if (i > 0 && pimpl_->fontlist[i - 1].font() == font) {
565 // Merge the singleton block with the previous block
566 pimpl_->fontlist[i - 1].pos(pos);
567 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
569 pimpl_->fontlist[i].font(font);
571 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
572 pimpl_->fontlist[i - 1].pos(pos);
574 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
575 Pimpl::FontTable(pos, font));
577 pimpl_->fontlist[i].pos(pos - 1);
578 if (!(i + 1 < pimpl_->fontlist.size() &&
579 pimpl_->fontlist[i + 1].font() == font))
580 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
581 Pimpl::FontTable(pos, font));
582 } else { // The general case. The block is splitted into 3 blocks
583 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
584 Pimpl::FontTable(pos - 1, pimpl_->fontlist[i].font()));
585 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
586 Pimpl::FontTable(pos, font));
591 void Paragraph::makeSameLayout(Paragraph const & par)
593 layout(par.layout());
595 params() = par.params();
599 int Paragraph::stripLeadingSpaces()
601 if (layout()->free_spacing || isFreeSpacing())
605 while (!empty() && (isNewline(0) || isLineSeparator(0))) {
606 pimpl_->eraseIntern(0);
614 bool Paragraph::hasSameLayout(Paragraph const & par) const
617 par.layout() == layout() &&
618 params().sameLayout(par.params());
622 Paragraph::depth_type Paragraph::getDepth() const
624 return params().depth();
628 Paragraph::depth_type Paragraph::getMaxDepthAfter() const
630 if (layout()->isEnvironment())
631 return params().depth() + 1;
633 return params().depth();
637 char Paragraph::getAlign() const
639 return params().align();
643 string const & Paragraph::getLabelstring() const
645 return params().labelString();
649 // the next two functions are for the manual labels
650 string const Paragraph::getLabelWidthString() const
652 if (!params().labelWidthString().empty())
653 return params().labelWidthString();
655 return _("Senseless with this layout!");
659 void Paragraph::setLabelWidthString(string const & s)
661 params().labelWidthString(s);
665 void Paragraph::applyLayout(LyXLayout_ptr const & new_layout)
668 params().labelWidthString(string());
669 params().align(LYX_ALIGN_LAYOUT);
670 params().spaceTop(VSpace(VSpace::NONE));
671 params().spaceBottom(VSpace(VSpace::NONE));
672 params().spacing(Spacing(Spacing::Default));
676 int Paragraph::beginningOfBody() const
678 if (layout()->labeltype != LABEL_MANUAL)
681 // Unroll the first two cycles of the loop
682 // and remember the previous character to
683 // remove unnecessary GetChar() calls
685 if (i < size() && !isNewline(i)) {
687 char previous_char = 0;
690 previous_char = getChar(i);
693 while (i < size() && previous_char != ' ') {
699 previous_char = temp;
709 // returns -1 if inset not found
710 int Paragraph::getPositionOfInset(Inset const * inset) const
713 InsetList::const_iterator it = insetlist.begin();
714 InsetList::const_iterator end = insetlist.end();
715 for (; it != end; ++it)
716 if (it->inset == inset)
722 InsetBibitem * Paragraph::bibitem() const
724 InsetList::const_iterator it = insetlist.begin();
725 if (it != insetlist.end() && it->inset->lyxCode() == Inset::BIBTEX_CODE)
726 return static_cast<InsetBibitem *>(it->inset);
732 // This could go to ParagraphParameters if we want to
733 int Paragraph::startTeXParParams(BufferParams const & bparams,
734 ostream & os, bool moving_arg) const
738 if (params().noindent()) {
743 switch (params().align()) {
745 case LYX_ALIGN_BLOCK:
746 case LYX_ALIGN_LAYOUT:
747 case LYX_ALIGN_SPECIAL:
750 case LYX_ALIGN_RIGHT:
751 case LYX_ALIGN_CENTER:
759 switch (params().align()) {
761 case LYX_ALIGN_BLOCK:
762 case LYX_ALIGN_LAYOUT:
763 case LYX_ALIGN_SPECIAL:
766 if (getParLanguage(bparams)->babel() != "hebrew") {
767 os << "\\begin{flushleft}";
770 os << "\\begin{flushright}";
774 case LYX_ALIGN_RIGHT:
775 if (getParLanguage(bparams)->babel() != "hebrew") {
776 os << "\\begin{flushright}";
779 os << "\\begin{flushleft}";
783 case LYX_ALIGN_CENTER:
784 os << "\\begin{center}";
793 // This could go to ParagraphParameters if we want to
794 int Paragraph::endTeXParParams(BufferParams const & bparams,
795 ostream & os, bool moving_arg) const
799 switch (params().align()) {
801 case LYX_ALIGN_BLOCK:
802 case LYX_ALIGN_LAYOUT:
803 case LYX_ALIGN_SPECIAL:
806 case LYX_ALIGN_RIGHT:
807 case LYX_ALIGN_CENTER:
815 switch (params().align()) {
817 case LYX_ALIGN_BLOCK:
818 case LYX_ALIGN_LAYOUT:
819 case LYX_ALIGN_SPECIAL:
822 if (getParLanguage(bparams)->babel() != "hebrew") {
823 os << "\\end{flushleft}";
826 os << "\\end{flushright}";
830 case LYX_ALIGN_RIGHT:
831 if (getParLanguage(bparams)->babel() != "hebrew") {
832 os << "\\end{flushright}";
835 os << "\\end{flushleft}";
839 case LYX_ALIGN_CENTER:
840 os << "\\end{center}";
848 // This one spits out the text of the paragraph
849 bool Paragraph::simpleTeXOnePar(Buffer const * buf,
850 BufferParams const & bparams,
851 LyXFont const & outerfont,
852 ostream & os, TexRow & texrow,
853 LatexRunParams const & runparams)
855 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
857 bool return_value = false;
861 // well we have to check if we are in an inset with unlimited
862 // lenght (all in one row) if that is true then we don't allow
863 // any special options in the paragraph and also we don't allow
864 // any environment other then "Standard" to be valid!
866 (inInset() && inInset()->forceDefaultParagraphs(inInset()));
869 style = bparams.getLyXTextClass().defaultLayout();
876 // Maybe we have to create a optional argument.
879 // FIXME: can we actually skip this check and just call
880 // beginningOfBody() ??
881 if (style->labeltype != LABEL_MANUAL) {
884 body_pos = beginningOfBody();
887 unsigned int column = 0;
892 basefont = getLabelFont(bparams, outerfont);
894 basefont = getLayoutFont(bparams, outerfont);
897 bool moving_arg = runparams.moving_arg;
898 moving_arg |= style->needprotect;
900 // Which font is currently active?
901 LyXFont running_font(basefont);
902 // Do we have an open font change?
903 bool open_font = false;
905 Change::Type running_change = Change::UNCHANGED;
907 texrow.start(id(), 0);
909 // if the paragraph is empty, the loop will not be entered at all
911 if (style->isCommand()) {
916 column += startTeXParParams(bparams, os, moving_arg);
920 for (pos_type i = 0; i < size(); ++i) {
922 // First char in paragraph or after label?
926 column += running_font.latexWriteEndChanges(os, basefont, basefont);
929 basefont = getLayoutFont(bparams, outerfont);
930 running_font = basefont;
934 if (style->isCommand()) {
940 column += startTeXParParams(bparams, os,
944 value_type c = getChar(i);
946 // Fully instantiated font
947 LyXFont font = getFont(bparams, i, outerfont);
949 LyXFont const last_font = running_font;
951 // Spaces at end of font change are simulated to be
952 // outside font change, i.e. we write "\textXX{text} "
953 // rather than "\textXX{text }". (Asger)
954 if (open_font && c == ' ' && i <= size() - 2) {
955 LyXFont const & next_font = getFont(bparams, i + 1, outerfont);
956 if (next_font != running_font
957 && next_font != font) {
962 // We end font definition before blanks
964 (font != running_font ||
965 font.language() != running_font.language()))
967 column += running_font.latexWriteEndChanges(os,
969 (i == body_pos-1) ? basefont : font);
970 running_font = basefont;
974 // Blanks are printed before start of fontswitch
976 // Do not print the separation of the optional argument
977 if (i != body_pos - 1) {
978 pimpl_->simpleTeXBlanks(os, texrow, i,
979 column, font, *style);
983 // Do we need to change font?
984 if ((font != running_font ||
985 font.language() != running_font.language()) &&
988 column += font.latexWriteStartChanges(os, basefont,
994 Change::Type change = pimpl_->lookupChange(i);
996 column += Changes::latexMarkChange(os, running_change, change);
997 running_change = change;
999 LatexRunParams rp = runparams;
1000 rp.moving_arg = moving_arg;
1001 rp.free_spacing = style->free_spacing;
1002 pimpl_->simpleTeXSpecialChars(buf, bparams,
1003 os, texrow, runparams,
1005 basefont, outerfont, open_font,
1007 *style, i, column, c);
1010 column += Changes::latexMarkChange(os,
1011 running_change, Change::UNCHANGED);
1013 // If we have an open font definition, we have to close it
1015 #ifdef FIXED_LANGUAGE_END_DETECTION
1018 .latexWriteEndChanges(os, basefont,
1019 next_->getFont(bparams,
1022 running_font.latexWriteEndChanges(os, basefont,
1026 #ifdef WITH_WARNINGS
1027 //#warning For now we ALWAYS have to close the foreign font settings if they are
1028 //#warning there as we start another \selectlanguage with the next paragraph if
1029 //#warning we are in need of this. This should be fixed sometime (Jug)
1031 running_font.latexWriteEndChanges(os, basefont, basefont);
1035 // Needed if there is an optional argument but no contents.
1036 if (body_pos > 0 && body_pos == size()) {
1038 return_value = false;
1042 column += endTeXParParams(bparams, os, moving_arg);
1045 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
1046 return return_value;
1052 bool Paragraph::isHfill(pos_type pos) const
1054 return IsInsetChar(getChar(pos))
1055 && getInset(pos)->lyxCode() == Inset::HFILL_CODE;
1059 bool Paragraph::isInset(pos_type pos) const
1061 return IsInsetChar(getChar(pos));
1065 bool Paragraph::isNewline(pos_type pos) const
1067 return IsInsetChar(getChar(pos))
1068 && getInset(pos)->lyxCode() == Inset::NEWLINE_CODE;
1072 bool Paragraph::isSeparator(pos_type pos) const
1074 return IsSeparatorChar(getChar(pos));
1078 bool Paragraph::isLineSeparator(pos_type pos) const
1080 value_type const c = getChar(pos);
1081 return IsLineSeparatorChar(c)
1082 || (IsInsetChar(c) && getInset(pos) &&
1083 getInset(pos)->isLineSeparator());
1087 bool Paragraph::isKomma(pos_type pos) const
1089 return IsKommaChar(getChar(pos));
1093 /// Used by the spellchecker
1094 bool Paragraph::isLetter(pos_type pos) const
1096 value_type const c = getChar(pos);
1097 if (IsLetterChar(c))
1100 return getInset(pos)->isLetter();
1101 // We want to pass the ' and escape chars to ispell
1102 string const extra = lyxrc.isp_esc_chars + '\'';
1103 return contains(extra, c);
1107 bool Paragraph::isWord(pos_type pos) const
1109 return IsWordChar(getChar(pos)) ;
1114 Paragraph::getParLanguage(BufferParams const & bparams) const
1117 return getFirstFontSettings().language();
1118 #warning FIXME we should check the prev par as well (Lgb)
1120 } else if (previous_) {
1121 return previous_->getParLanguage(bparams);
1124 return bparams.language;
1128 bool Paragraph::isRightToLeftPar(BufferParams const & bparams) const
1130 return lyxrc.rtl_support
1131 && getParLanguage(bparams)->RightToLeft()
1132 && !(inInset() && inInset()->owner() &&
1133 inInset()->owner()->lyxCode() == Inset::ERT_CODE);
1137 void Paragraph::changeLanguage(BufferParams const & bparams,
1138 Language const * from, Language const * to)
1140 for (pos_type i = 0; i < size(); ++i) {
1141 LyXFont font = getFontSettings(bparams, i);
1142 if (font.language() == from) {
1143 font.setLanguage(to);
1150 bool Paragraph::isMultiLingual(BufferParams const & bparams)
1152 Language const * doc_language = bparams.language;
1153 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
1154 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
1156 for (; cit != end; ++cit)
1157 if (cit->font().language() != ignore_language &&
1158 cit->font().language() != latex_language &&
1159 cit->font().language() != doc_language)
1165 // Convert the paragraph to a string.
1166 // Used for building the table of contents
1167 string const Paragraph::asString(Buffer const * buffer, bool label) const
1170 if (label && !params().labelString().empty())
1171 s += params().labelString() + ' ';
1173 for (pos_type i = 0; i < size(); ++i) {
1174 value_type c = getChar(i);
1177 else if (c == META_INSET &&
1178 getInset(i)->lyxCode() == Inset::MATH_CODE) {
1180 getInset(i)->ascii(buffer, ost);
1181 s += subst(STRCONV(ost.str()),'\n',' ');
1189 string const Paragraph::asString(Buffer const * buffer,
1190 pos_type beg, pos_type end, bool label) const
1194 if (beg == 0 && label && !params().labelString().empty())
1195 os << params().labelString() << ' ';
1197 for (pos_type i = beg; i < end; ++i) {
1198 value_type const c = getUChar(buffer->params, i);
1201 else if (c == META_INSET)
1202 getInset(i)->ascii(buffer, os);
1205 return STRCONV(os.str());
1209 void Paragraph::setInsetOwner(Inset * i)
1211 pimpl_->inset_owner = i;
1212 InsetList::iterator it = insetlist.begin();
1213 InsetList::iterator end = insetlist.end();
1214 for (; it != end; ++it)
1216 it->inset->setOwner(i);
1220 void Paragraph::deleteInsetsLyXText(BufferView * bv)
1223 insetlist.deleteInsetsLyXText(bv);
1227 void Paragraph::resizeInsetsLyXText(BufferView * bv)
1230 insetlist.resizeInsetsLyXText(bv);
1234 void Paragraph::setContentsFromPar(Paragraph const & par)
1236 pimpl_->setContentsFromPar(par);
1240 void Paragraph::trackChanges(Change::Type type)
1242 pimpl_->trackChanges(type);
1246 void Paragraph::untrackChanges()
1248 pimpl_->untrackChanges();
1252 void Paragraph::cleanChanges()
1254 pimpl_->cleanChanges();
1258 Change::Type Paragraph::lookupChange(lyx::pos_type pos) const
1260 lyx::Assert(!size() || pos < size());
1261 return pimpl_->lookupChange(pos);
1265 Change const Paragraph::lookupChangeFull(lyx::pos_type pos) const
1267 lyx::Assert(!size() || pos < size());
1268 return pimpl_->lookupChangeFull(pos);
1272 bool Paragraph::isChanged(pos_type start, pos_type end) const
1274 return pimpl_->isChanged(start, end);
1278 bool Paragraph::isChangeEdited(pos_type start, pos_type end) const
1280 return pimpl_->isChangeEdited(start, end);
1284 void Paragraph::setChange(lyx::pos_type pos, Change::Type type)
1286 pimpl_->setChange(pos, type);
1291 void Paragraph::markErased()
1293 pimpl_->markErased();
1297 void Paragraph::acceptChange(pos_type start, pos_type end)
1299 return pimpl_->acceptChange(start, end);
1303 void Paragraph::rejectChange(pos_type start, pos_type end)
1305 return pimpl_->rejectChange(start, end);
1309 lyx::pos_type Paragraph::size() const
1311 return pimpl_->size();
1315 bool Paragraph::empty() const
1317 return pimpl_->empty();
1321 Paragraph::value_type Paragraph::getChar(pos_type pos) const
1323 return pimpl_->getChar(pos);
1327 int Paragraph::id() const
1333 void Paragraph::id(int i)
1339 LyXLayout_ptr const & Paragraph::layout() const
1341 Inset * inset = inInset();
1342 if (inset && inset->lyxCode() == Inset::ENVIRONMENT_CODE)
1343 return static_cast<InsetEnvironment*>(inset)->layout();
1348 void Paragraph::layout(LyXLayout_ptr const & new_layout)
1350 layout_ = new_layout;
1354 Inset * Paragraph::inInset() const
1356 return pimpl_->inset_owner;
1360 void Paragraph::clearContents()
1365 void Paragraph::setChar(pos_type pos, value_type c)
1367 pimpl_->setChar(pos, c);
1371 ParagraphParameters & Paragraph::params()
1373 return pimpl_->params;
1377 ParagraphParameters const & Paragraph::params() const
1379 return pimpl_->params;
1383 bool Paragraph::isFreeSpacing() const
1385 // for now we just need this, later should we need this in some
1386 // other way we can always add a function to Inset::() too.
1387 if (pimpl_->inset_owner && pimpl_->inset_owner->owner())
1388 return (pimpl_->inset_owner->owner()->lyxCode() == Inset::ERT_CODE);
1393 bool operator==(Paragraph const & lhs, Paragraph const & rhs)
1395 #warning FIXME this implementatoin must be completely wrong...
1396 return &lhs == &rhs;