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 extern BufferView * current_view;
73 Paragraph::Paragraph()
74 : pimpl_(new Paragraph::Pimpl(this))
89 Paragraph::Paragraph(Paragraph const & lp, bool same_ids)
90 : pimpl_(new Paragraph::Pimpl(*lp.pimpl_, this, same_ids))
101 // this is because of the dummy layout of the paragraphs that
103 layout_ = lp.layout();
105 // copy everything behind the break-position to the new paragraph
106 insetlist = lp.insetlist;
107 InsetList::iterator it = insetlist.begin();
108 InsetList::iterator end = insetlist.end();
109 for (; it != end; ++it) {
110 it.setInset(it.getInset()->clone(*current_view->buffer(),
112 // tell the new inset who is the boss now
113 it.getInset()->parOwner(this);
118 // the destructor removes the new paragraph from the list
119 Paragraph::~Paragraph()
123 previous_->next_ = next_;
125 next_->previous_ = previous_;
130 //lyxerr << "Paragraph::paragraph_id = "
131 // << Paragraph::paragraph_id << endl;
135 void Paragraph::write(Buffer const * buf, ostream & os,
136 BufferParams const & bparams,
137 depth_type & dth) const
139 // The beginning or end of a deeper (i.e. nested) area?
140 if (dth != params().depth()) {
141 if (params().depth() > dth) {
142 while (params().depth() > dth) {
143 os << "\n\\begin_deeper ";
147 while (params().depth() < dth) {
148 os << "\n\\end_deeper ";
154 // First write the layout
155 os << "\n\\layout " << layout()->name() << '\n';
159 LyXFont font1(LyXFont::ALL_INHERIT, bparams.language);
161 Change running_change = Change(Change::UNCHANGED);
162 lyx::time_type const curtime(lyx::current_time());
165 for (pos_type i = 0; i < size(); ++i) {
171 Change change = pimpl_->lookupChangeFull(i);
172 Changes::lyxMarkChange(os, column, curtime, running_change, change);
173 running_change = change;
175 // Write font changes
176 LyXFont font2 = getFontSettings(bparams, i);
177 if (font2 != font1) {
178 font2.lyxWriteChanges(font1, os);
183 value_type const c = getChar(i);
187 Inset const * inset = getInset(i);
189 if (inset->directWrite()) {
190 // international char, let it write
191 // code directly so it's shorter in
193 inset->write(buf, os);
195 os << "\n\\begin_inset ";
196 inset->write(buf, os);
197 os << "\n\\end_inset \n\n";
203 os << "\n\\backslash \n";
207 if (i + 1 < size() && getChar(i + 1) == ' ') {
214 if ((column > 70 && c == ' ')
219 // this check is to amend a bug. LyX sometimes
220 // inserts '\0' this could cause problems.
224 lyxerr << "ERROR (Paragraph::writeFile):"
225 " NULL char in structure." << endl;
231 // to make reading work properly
233 running_change = pimpl_->lookupChange(0);
234 Changes::lyxMarkChange(os, column, curtime,
235 Change(Change::UNCHANGED), running_change);
237 Changes::lyxMarkChange(os, column, curtime,
238 running_change, Change(Change::UNCHANGED));
242 void Paragraph::validate(LaTeXFeatures & features) const
244 pimpl_->validate(features, *layout());
248 // First few functions needed for cut and paste and paragraph breaking.
249 void Paragraph::copyIntoMinibuffer(Buffer const & buffer, pos_type pos) const
251 BufferParams bparams = buffer.params;
253 minibuffer_char = getChar(pos);
254 minibuffer_font = getFontSettings(bparams, pos);
255 minibuffer_inset = 0;
256 if (minibuffer_char == Paragraph::META_INSET) {
258 minibuffer_inset = getInset(pos)->clone(buffer);
260 minibuffer_inset = 0;
261 minibuffer_char = ' ';
262 // This reflects what GetInset() does (ARRae)
268 void Paragraph::cutIntoMinibuffer(BufferParams const & bparams, pos_type pos)
270 minibuffer_char = getChar(pos);
271 minibuffer_font = getFontSettings(bparams, pos);
272 minibuffer_inset = 0;
273 if (minibuffer_char == Paragraph::META_INSET) {
275 // the inset is not in a paragraph anymore
276 minibuffer_inset = insetlist.release(pos);
277 minibuffer_inset->parOwner(0);
279 minibuffer_inset = 0;
280 minibuffer_char = ' ';
281 // This reflects what GetInset() does (ARRae)
286 // Erase(pos); now the caller is responsible for that.
290 bool Paragraph::insertFromMinibuffer(pos_type pos)
292 if (minibuffer_char == Paragraph::META_INSET) {
293 if (!insetAllowed(minibuffer_inset->lyxCode())) {
296 insertInset(pos, minibuffer_inset, minibuffer_font);
298 LyXFont f = minibuffer_font;
299 if (!checkInsertChar(f)) {
302 insertChar(pos, minibuffer_char, f);
310 void Paragraph::eraseIntern(lyx::pos_type pos)
312 pimpl_->eraseIntern(pos);
316 bool Paragraph::erase(pos_type pos)
318 return pimpl_->erase(pos);
322 int Paragraph::erase(pos_type start, pos_type end)
324 return pimpl_->erase(start, end);
328 bool Paragraph::checkInsertChar(LyXFont & font)
330 if (pimpl_->inset_owner)
331 return pimpl_->inset_owner->checkInsertChar(font);
336 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c)
338 LyXFont const f(LyXFont::ALL_INHERIT);
339 insertChar(pos, c, f);
343 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c,
344 LyXFont const & font, Change change)
346 pimpl_->insertChar(pos, c, font, change);
350 void Paragraph::insertInset(pos_type pos, Inset * inset)
352 LyXFont const f(LyXFont::ALL_INHERIT);
353 insertInset(pos, inset, f);
357 void Paragraph::insertInset(pos_type pos, Inset * inset, LyXFont const & font, Change change)
359 pimpl_->insertInset(pos, inset, font, change);
363 bool Paragraph::insetAllowed(Inset::Code code)
365 //lyxerr << "Paragraph::InsertInsetAllowed" << endl;
366 if (pimpl_->inset_owner)
367 return pimpl_->inset_owner->insetAllowed(code);
372 Inset * Paragraph::getInset(pos_type pos)
374 lyx::Assert(pos < size());
375 return insetlist.get(pos);
379 Inset const * Paragraph::getInset(pos_type pos) const
381 lyx::Assert(pos < size());
382 return insetlist.get(pos);
386 // Gets uninstantiated font setting at position.
387 LyXFont const Paragraph::getFontSettings(BufferParams const & bparams,
390 lyx::Assert(pos <= size());
392 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
393 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
394 for (; cit != end; ++cit) {
395 if (cit->pos() >= pos)
401 retfont = cit->font();
402 else if (pos == size() && !empty())
403 retfont = getFontSettings(bparams, pos - 1);
405 retfont = LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
411 // Gets uninstantiated font setting at position 0
412 LyXFont const Paragraph::getFirstFontSettings() const
414 if (!empty() && !pimpl_->fontlist.empty())
415 return pimpl_->fontlist[0].font();
417 return LyXFont(LyXFont::ALL_INHERIT);
421 // Gets the fully instantiated font at a given position in a paragraph
422 // This is basically the same function as LyXText::GetFont() in text2.C.
423 // The difference is that this one is used for generating the LaTeX file,
424 // and thus cosmetic "improvements" are disallowed: This has to deliver
425 // the true picture of the buffer. (Asger)
426 LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
427 LyXFont const & outerfont) const
429 lyx::Assert(pos >= 0);
431 LyXLayout_ptr const & lout = layout();
433 pos_type const body_pos = beginningOfBody();
437 layoutfont = lout->labelfont;
439 layoutfont = lout->font;
441 LyXFont tmpfont = getFontSettings(bparams, pos);
442 tmpfont.realize(layoutfont);
443 tmpfont.realize(outerfont);
445 return realizeFont(tmpfont, bparams);
449 LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
450 LyXFont const & outerfont) const
452 LyXLayout_ptr const & lout = layout();
454 LyXFont tmpfont = lout->labelfont;
455 tmpfont.setLanguage(getParLanguage(bparams));
456 tmpfont.realize(outerfont);
458 return realizeFont(tmpfont, bparams);
462 LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
463 LyXFont const & outerfont) const
465 LyXLayout_ptr const & lout = layout();
467 LyXFont tmpfont = lout->font;
468 tmpfont.setLanguage(getParLanguage(bparams));
469 tmpfont.realize(outerfont);
471 return realizeFont(tmpfont, bparams);
475 /// Returns the height of the highest font in range
477 Paragraph::highestFontInRange(pos_type startpos, pos_type endpos,
478 LyXFont::FONT_SIZE const def_size) const
480 if (pimpl_->fontlist.empty())
483 Pimpl::FontList::const_iterator end_it = pimpl_->fontlist.begin();
484 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
485 for (; end_it != end; ++end_it) {
486 if (end_it->pos() >= endpos)
493 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
494 for (; cit != end; ++cit) {
495 if (cit->pos() >= startpos)
499 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
500 for (; cit != end_it; ++cit) {
501 LyXFont::FONT_SIZE size = cit->font().size();
502 if (size == LyXFont::INHERIT_SIZE)
504 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
511 Paragraph::value_type
512 Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
514 value_type c = getChar(pos);
515 if (!lyxrc.rtl_support)
545 if (uc != c && getFontSettings(bparams, pos).isRightToLeft())
552 void Paragraph::setFont(pos_type pos, LyXFont const & font)
554 lyx::Assert(pos <= size());
556 // First, reduce font against layout/label font
557 // Update: The SetCharFont() routine in text2.C already
558 // reduces font, so we don't need to do that here. (Asger)
559 // No need to simplify this because it will disappear
560 // in a new kernel. (Asger)
561 // Next search font table
563 Pimpl::FontList::iterator beg = pimpl_->fontlist.begin();
564 Pimpl::FontList::iterator it = beg;
565 Pimpl::FontList::iterator endit = pimpl_->fontlist.end();
566 for (; it != endit; ++it) {
567 if (it->pos() >= pos)
570 unsigned int i = std::distance(beg, it);
571 bool notfound = (it == endit);
573 if (!notfound && pimpl_->fontlist[i].font() == font)
576 bool begin = pos == 0 || notfound ||
577 (i > 0 && pimpl_->fontlist[i - 1].pos() == pos - 1);
578 // Is position pos is a beginning of a font block?
579 bool end = !notfound && pimpl_->fontlist[i].pos() == pos;
580 // Is position pos is the end of a font block?
581 if (begin && end) { // A single char block
582 if (i + 1 < pimpl_->fontlist.size() &&
583 pimpl_->fontlist[i + 1].font() == font) {
584 // Merge the singleton block with the next block
585 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
586 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
587 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i - 1);
588 } else if (i > 0 && pimpl_->fontlist[i - 1].font() == font) {
589 // Merge the singleton block with the previous block
590 pimpl_->fontlist[i - 1].pos(pos);
591 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
593 pimpl_->fontlist[i].font(font);
595 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
596 pimpl_->fontlist[i - 1].pos(pos);
598 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
599 Pimpl::FontTable(pos, font));
601 pimpl_->fontlist[i].pos(pos - 1);
602 if (!(i + 1 < pimpl_->fontlist.size() &&
603 pimpl_->fontlist[i + 1].font() == font))
604 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
605 Pimpl::FontTable(pos, font));
606 } else { // The general case. The block is splitted into 3 blocks
607 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
608 Pimpl::FontTable(pos - 1, pimpl_->fontlist[i].font()));
609 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
610 Pimpl::FontTable(pos, font));
616 void Paragraph::next(Paragraph * p)
622 // This function is able to hide closed footnotes.
623 Paragraph * Paragraph::next()
629 Paragraph const * Paragraph::next() const
635 void Paragraph::previous(Paragraph * p)
641 // This function is able to hide closed footnotes.
642 Paragraph * Paragraph::previous()
648 // This function is able to hide closed footnotes.
649 Paragraph const * Paragraph::previous() const
656 void Paragraph::makeSameLayout(Paragraph const & par)
658 layout(par.layout());
660 params() = par.params();
664 int Paragraph::stripLeadingSpaces()
666 if (layout()->free_spacing || isFreeSpacing())
670 while (!empty() && (isNewline(0) || isLineSeparator(0))) {
671 pimpl_->eraseIntern(0);
679 bool Paragraph::hasSameLayout(Paragraph const & par) const
682 par.layout() == layout() &&
683 params().sameLayout(par.params());
687 Paragraph::depth_type Paragraph::getDepth() const
689 return params().depth();
693 Paragraph::depth_type Paragraph::getMaxDepthAfter() const
695 if (layout()->isEnvironment())
696 return params().depth() + 1;
698 return params().depth();
702 char Paragraph::getAlign() const
704 return params().align();
708 string const & Paragraph::getLabelstring() const
710 return params().labelString();
714 // the next two functions are for the manual labels
715 string const Paragraph::getLabelWidthString() const
717 if (!params().labelWidthString().empty())
718 return params().labelWidthString();
720 return _("Senseless with this layout!");
724 void Paragraph::setLabelWidthString(string const & s)
726 params().labelWidthString(s);
730 void Paragraph::applyLayout(LyXLayout_ptr const & new_layout)
733 params().labelWidthString(string());
734 params().align(LYX_ALIGN_LAYOUT);
735 params().spaceTop(VSpace(VSpace::NONE));
736 params().spaceBottom(VSpace(VSpace::NONE));
737 params().spacing(Spacing(Spacing::Default));
741 int Paragraph::beginningOfBody() const
743 if (layout()->labeltype != LABEL_MANUAL)
746 // Unroll the first two cycles of the loop
747 // and remember the previous character to
748 // remove unnecessary GetChar() calls
750 if (i < size() && !isNewline(i)) {
752 char previous_char = 0;
755 previous_char = getChar(i);
758 while (i < size() && previous_char != ' ') {
764 previous_char = temp;
774 // returns -1 if inset not found
775 int Paragraph::getPositionOfInset(Inset const * inset) const
778 InsetList::iterator it = insetlist.begin();
779 InsetList::iterator end = insetlist.end();
780 for (; it != end; ++it)
781 if (it.getInset() == inset)
787 InsetBibitem * Paragraph::bibitem()
789 InsetList::iterator it = insetlist.begin();
790 if (it != insetlist.end() && it.getInset()->lyxCode() == Inset::BIBTEX_CODE)
791 return static_cast<InsetBibitem *>(it.getInset());
797 // This could go to ParagraphParameters if we want to
798 int Paragraph::startTeXParParams(BufferParams const & bparams,
799 ostream & os, bool moving_arg) const
803 if (params().noindent()) {
808 switch (params().align()) {
810 case LYX_ALIGN_BLOCK:
811 case LYX_ALIGN_LAYOUT:
812 case LYX_ALIGN_SPECIAL:
815 case LYX_ALIGN_RIGHT:
816 case LYX_ALIGN_CENTER:
824 switch (params().align()) {
826 case LYX_ALIGN_BLOCK:
827 case LYX_ALIGN_LAYOUT:
828 case LYX_ALIGN_SPECIAL:
831 if (getParLanguage(bparams)->babel() != "hebrew") {
832 os << "\\begin{flushleft}";
835 os << "\\begin{flushright}";
839 case LYX_ALIGN_RIGHT:
840 if (getParLanguage(bparams)->babel() != "hebrew") {
841 os << "\\begin{flushright}";
844 os << "\\begin{flushleft}";
848 case LYX_ALIGN_CENTER:
849 os << "\\begin{center}";
858 // This could go to ParagraphParameters if we want to
859 int Paragraph::endTeXParParams(BufferParams const & bparams,
860 ostream & os, bool moving_arg) const
864 switch (params().align()) {
866 case LYX_ALIGN_BLOCK:
867 case LYX_ALIGN_LAYOUT:
868 case LYX_ALIGN_SPECIAL:
871 case LYX_ALIGN_RIGHT:
872 case LYX_ALIGN_CENTER:
880 switch (params().align()) {
882 case LYX_ALIGN_BLOCK:
883 case LYX_ALIGN_LAYOUT:
884 case LYX_ALIGN_SPECIAL:
887 if (getParLanguage(bparams)->babel() != "hebrew") {
888 os << "\\end{flushleft}";
891 os << "\\end{flushright}";
895 case LYX_ALIGN_RIGHT:
896 if (getParLanguage(bparams)->babel() != "hebrew") {
897 os << "\\end{flushright}";
900 os << "\\end{flushleft}";
904 case LYX_ALIGN_CENTER:
905 os << "\\end{center}";
913 // This one spits out the text of the paragraph
914 bool Paragraph::simpleTeXOnePar(Buffer const * buf,
915 BufferParams const & bparams,
916 LyXFont const & outerfont,
917 ostream & os, TexRow & texrow,
918 LatexRunParams const & runparams)
920 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
922 bool return_value = false;
926 // well we have to check if we are in an inset with unlimited
927 // lenght (all in one row) if that is true then we don't allow
928 // any special options in the paragraph and also we don't allow
929 // any environment other then "Standard" to be valid!
931 (inInset() && inInset()->forceDefaultParagraphs(inInset()));
934 style = bparams.getLyXTextClass().defaultLayout();
941 // Maybe we have to create a optional argument.
944 // FIXME: can we actually skip this check and just call
945 // beginningOfBody() ??
946 if (style->labeltype != LABEL_MANUAL) {
949 body_pos = beginningOfBody();
952 unsigned int column = 0;
957 basefont = getLabelFont(bparams, outerfont);
959 basefont = getLayoutFont(bparams, outerfont);
962 bool moving_arg = runparams.moving_arg;
963 moving_arg |= style->needprotect;
965 // Which font is currently active?
966 LyXFont running_font(basefont);
967 // Do we have an open font change?
968 bool open_font = false;
970 Change::Type running_change = Change::UNCHANGED;
972 texrow.start(id(), 0);
974 // if the paragraph is empty, the loop will not be entered at all
976 if (style->isCommand()) {
981 column += startTeXParParams(bparams, os, moving_arg);
985 for (pos_type i = 0; i < size(); ++i) {
987 // First char in paragraph or after label?
991 column += running_font.latexWriteEndChanges(os, basefont, basefont);
994 basefont = getLayoutFont(bparams, outerfont);
995 running_font = basefont;
999 if (style->isCommand()) {
1005 column += startTeXParParams(bparams, os,
1009 value_type c = getChar(i);
1011 // Fully instantiated font
1012 LyXFont font = getFont(bparams, i, outerfont);
1014 LyXFont const last_font = running_font;
1016 // Spaces at end of font change are simulated to be
1017 // outside font change, i.e. we write "\textXX{text} "
1018 // rather than "\textXX{text }". (Asger)
1019 if (open_font && c == ' ' && i <= size() - 2) {
1020 LyXFont const & next_font = getFont(bparams, i + 1, outerfont);
1021 if (next_font != running_font
1022 && next_font != font) {
1027 // We end font definition before blanks
1029 (font != running_font ||
1030 font.language() != running_font.language()))
1032 column += running_font.latexWriteEndChanges(os,
1034 (i == body_pos-1) ? basefont : font);
1035 running_font = basefont;
1039 // Blanks are printed before start of fontswitch
1041 // Do not print the separation of the optional argument
1042 if (i != body_pos - 1) {
1043 pimpl_->simpleTeXBlanks(os, texrow, i,
1044 column, font, *style);
1048 // Do we need to change font?
1049 if ((font != running_font ||
1050 font.language() != running_font.language()) &&
1053 column += font.latexWriteStartChanges(os, basefont,
1055 running_font = font;
1059 Change::Type change = pimpl_->lookupChange(i);
1061 column += Changes::latexMarkChange(os, running_change, change);
1062 running_change = change;
1064 LatexRunParams rp = runparams;
1065 rp.moving_arg = moving_arg;
1066 rp.free_spacing = style->free_spacing;
1067 pimpl_->simpleTeXSpecialChars(buf, bparams,
1068 os, texrow, runparams,
1070 basefont, outerfont, open_font,
1072 *style, i, column, c);
1075 column += Changes::latexMarkChange(os,
1076 running_change, Change::UNCHANGED);
1078 // If we have an open font definition, we have to close it
1080 #ifdef FIXED_LANGUAGE_END_DETECTION
1083 .latexWriteEndChanges(os, basefont,
1084 next_->getFont(bparams,
1087 running_font.latexWriteEndChanges(os, basefont,
1091 #ifdef WITH_WARNINGS
1092 //#warning For now we ALWAYS have to close the foreign font settings if they are
1093 //#warning there as we start another \selectlanguage with the next paragraph if
1094 //#warning we are in need of this. This should be fixed sometime (Jug)
1096 running_font.latexWriteEndChanges(os, basefont, basefont);
1100 // Needed if there is an optional argument but no contents.
1101 if (body_pos > 0 && body_pos == size()) {
1103 return_value = false;
1107 column += endTeXParParams(bparams, os, moving_arg);
1110 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
1111 return return_value;
1117 bool Paragraph::isHfill(pos_type pos) const
1119 return IsInsetChar(getChar(pos))
1120 && getInset(pos)->lyxCode() == Inset::HFILL_CODE;
1124 bool Paragraph::isInset(pos_type pos) const
1126 return IsInsetChar(getChar(pos));
1130 bool Paragraph::isNewline(pos_type pos) const
1132 return IsInsetChar(getChar(pos))
1133 && getInset(pos)->lyxCode() == Inset::NEWLINE_CODE;
1137 bool Paragraph::isSeparator(pos_type pos) const
1139 return IsSeparatorChar(getChar(pos));
1143 bool Paragraph::isLineSeparator(pos_type pos) const
1145 value_type const c = getChar(pos);
1146 return IsLineSeparatorChar(c)
1147 || (IsInsetChar(c) && getInset(pos) &&
1148 getInset(pos)->isLineSeparator());
1152 bool Paragraph::isKomma(pos_type pos) const
1154 return IsKommaChar(getChar(pos));
1158 /// Used by the spellchecker
1159 bool Paragraph::isLetter(pos_type pos) const
1161 value_type const c = getChar(pos);
1162 if (IsLetterChar(c))
1165 return getInset(pos)->isLetter();
1166 // We want to pass the ' and escape chars to ispell
1167 string const extra = lyxrc.isp_esc_chars + '\'';
1168 return contains(extra, c);
1172 bool Paragraph::isWord(pos_type pos) const
1174 return IsWordChar(getChar(pos)) ;
1179 Paragraph::getParLanguage(BufferParams const & bparams) const
1182 return getFirstFontSettings().language();
1183 #warning FIXME we should check the prev par as well (Lgb)
1185 } else if (previous_) {
1186 return previous_->getParLanguage(bparams);
1189 return bparams.language;
1193 bool Paragraph::isRightToLeftPar(BufferParams const & bparams) const
1195 return lyxrc.rtl_support
1196 && getParLanguage(bparams)->RightToLeft()
1197 && !(inInset() && inInset()->owner() &&
1198 inInset()->owner()->lyxCode() == Inset::ERT_CODE);
1202 void Paragraph::changeLanguage(BufferParams const & bparams,
1203 Language const * from, Language const * to)
1205 for (pos_type i = 0; i < size(); ++i) {
1206 LyXFont font = getFontSettings(bparams, i);
1207 if (font.language() == from) {
1208 font.setLanguage(to);
1215 bool Paragraph::isMultiLingual(BufferParams const & bparams)
1217 Language const * doc_language = bparams.language;
1218 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
1219 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
1221 for (; cit != end; ++cit)
1222 if (cit->font().language() != ignore_language &&
1223 cit->font().language() != latex_language &&
1224 cit->font().language() != doc_language)
1230 // Convert the paragraph to a string.
1231 // Used for building the table of contents
1232 string const Paragraph::asString(Buffer const * buffer, bool label) const
1235 if (label && !params().labelString().empty())
1236 s += params().labelString() + ' ';
1238 for (pos_type i = 0; i < size(); ++i) {
1239 value_type c = getChar(i);
1242 else if (c == META_INSET &&
1243 getInset(i)->lyxCode() == Inset::MATH_CODE) {
1245 getInset(i)->ascii(buffer, ost);
1246 s += subst(STRCONV(ost.str()),'\n',' ');
1254 string const Paragraph::asString(Buffer const * buffer,
1255 pos_type beg, pos_type end, bool label) const
1259 if (beg == 0 && label && !params().labelString().empty())
1260 os << params().labelString() << ' ';
1262 for (pos_type i = beg; i < end; ++i) {
1263 value_type const c = getUChar(buffer->params, i);
1266 else if (c == META_INSET)
1267 getInset(i)->ascii(buffer, os);
1270 return STRCONV(os.str());
1274 void Paragraph::setInsetOwner(Inset * i)
1276 pimpl_->inset_owner = i;
1277 InsetList::iterator it = insetlist.begin();
1278 InsetList::iterator end = insetlist.end();
1279 for (; it != end; ++it)
1281 it.getInset()->setOwner(i);
1285 void Paragraph::deleteInsetsLyXText(BufferView * bv)
1288 insetlist.deleteInsetsLyXText(bv);
1292 void Paragraph::resizeInsetsLyXText(BufferView * bv)
1295 insetlist.resizeInsetsLyXText(bv);
1299 void Paragraph::setContentsFromPar(Paragraph const & par)
1301 pimpl_->setContentsFromPar(par);
1305 void Paragraph::trackChanges(Change::Type type)
1307 pimpl_->trackChanges(type);
1311 void Paragraph::untrackChanges()
1313 pimpl_->untrackChanges();
1317 void Paragraph::cleanChanges()
1319 pimpl_->cleanChanges();
1323 Change::Type Paragraph::lookupChange(lyx::pos_type pos) const
1325 lyx::Assert(!size() || pos < size());
1326 return pimpl_->lookupChange(pos);
1330 Change const Paragraph::lookupChangeFull(lyx::pos_type pos) const
1332 lyx::Assert(!size() || pos < size());
1333 return pimpl_->lookupChangeFull(pos);
1337 bool Paragraph::isChanged(pos_type start, pos_type end) const
1339 return pimpl_->isChanged(start, end);
1343 bool Paragraph::isChangeEdited(pos_type start, pos_type end) const
1345 return pimpl_->isChangeEdited(start, end);
1349 void Paragraph::setChange(lyx::pos_type pos, Change::Type type)
1351 pimpl_->setChange(pos, type);
1356 void Paragraph::markErased()
1358 pimpl_->markErased();
1362 void Paragraph::acceptChange(pos_type start, pos_type end)
1364 return pimpl_->acceptChange(start, end);
1368 void Paragraph::rejectChange(pos_type start, pos_type end)
1370 return pimpl_->rejectChange(start, end);
1374 lyx::pos_type Paragraph::size() const
1376 return pimpl_->size();
1380 bool Paragraph::empty() const
1382 return pimpl_->empty();
1386 Paragraph::value_type Paragraph::getChar(pos_type pos) const
1388 return pimpl_->getChar(pos);
1392 int Paragraph::id() const
1398 LyXLayout_ptr const & Paragraph::layout() const
1400 Inset * inset = inInset();
1401 if (inset && inset->lyxCode() == Inset::ENVIRONMENT_CODE)
1402 return static_cast<InsetEnvironment*>(inset)->layout();
1407 void Paragraph::layout(LyXLayout_ptr const & new_layout)
1409 layout_ = new_layout;
1413 Inset * Paragraph::inInset() const
1415 return pimpl_->inset_owner;
1419 void Paragraph::clearContents()
1424 void Paragraph::setChar(pos_type pos, value_type c)
1426 pimpl_->setChar(pos, c);
1430 ParagraphParameters & Paragraph::params()
1432 return pimpl_->params;
1436 ParagraphParameters const & Paragraph::params() const
1438 return pimpl_->params;
1442 bool Paragraph::isFreeSpacing() const
1444 // for now we just need this, later should we need this in some
1445 // other way we can always add a function to Inset::() too.
1446 if (pimpl_->inset_owner && pimpl_->inset_owner->owner())
1447 return (pimpl_->inset_owner->owner()->lyxCode() == Inset::ERT_CODE);