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"
19 #include "bufferparams.h"
22 #include "BufferView.h"
24 #include "ParameterStruct.h"
27 #include "paragraph_funcs.h"
29 #include "insets/insetbibitem.h"
30 #include "insets/insetoptarg.h"
32 #include "support/filetools.h"
33 #include "support/lstrings.h"
34 #include "support/lyxmanip.h"
35 #include "support/FileInfo.h"
36 #include "support/LAssert.h"
37 #include "support/textutils.h"
48 using std::lower_bound;
49 using std::upper_bound;
54 // this is a minibuffer
59 LyXFont minibuffer_font;
60 Inset * minibuffer_inset;
65 extern BufferView * current_view;
68 Paragraph::Paragraph()
69 : pimpl_(new Paragraph::Pimpl(this))
82 // This constructor inserts the new paragraph in a list.
83 // It is placed after par.
84 Paragraph::Paragraph(Paragraph * par)
85 : pimpl_(new Paragraph::Pimpl(this))
90 // double linked list begin
93 next_->previous_ = this;
95 previous_->next_ = this;
103 Paragraph::Paragraph(Paragraph const & lp, bool same_ids)
104 : pimpl_(new Paragraph::Pimpl(*lp.pimpl_, this, same_ids))
112 // this is because of the dummy layout of the paragraphs that
114 layout_ = lp.layout();
116 // copy everything behind the break-position to the new paragraph
117 insetlist = lp.insetlist;
118 InsetList::iterator it = insetlist.begin();
119 InsetList::iterator end = insetlist.end();
120 for (; it != end; ++it) {
121 it.setInset(it.getInset()->clone(*current_view->buffer(),
123 // tell the new inset who is the boss now
124 it.getInset()->parOwner(this);
129 // the destructor removes the new paragraph from the list
130 Paragraph::~Paragraph()
134 previous_->next_ = next_;
136 next_->previous_ = previous_;
141 //lyxerr << "Paragraph::paragraph_id = "
142 // << Paragraph::paragraph_id << endl;
146 void Paragraph::write(Buffer const * buf, ostream & os,
147 BufferParams const & bparams,
148 depth_type & dth) const
150 // The beginning or end of a deeper (i.e. nested) area?
151 if (dth != params().depth()) {
152 if (params().depth() > dth) {
153 while (params().depth() > dth) {
154 os << "\n\\begin_deeper ";
158 while (params().depth() < dth) {
159 os << "\n\\end_deeper ";
165 // First write the layout
166 os << "\n\\layout " << layout()->name() << '\n';
170 LyXFont font1(LyXFont::ALL_INHERIT, bparams.language);
172 Change running_change = Change(Change::UNCHANGED);
173 lyx::time_type const curtime(lyx::current_time());
176 for (pos_type i = 0; i < size(); ++i) {
182 Change change = pimpl_->lookupChangeFull(i);
183 Changes::lyxMarkChange(os, column, curtime, running_change, change);
184 running_change = change;
186 // Write font changes
187 LyXFont font2 = getFontSettings(bparams, i);
188 if (font2 != font1) {
189 font2.lyxWriteChanges(font1, os);
194 value_type const c = getChar(i);
198 Inset const * inset = getInset(i);
200 if (inset->directWrite()) {
201 // international char, let it write
202 // code directly so it's shorter in
204 inset->write(buf, os);
206 os << "\n\\begin_inset ";
207 inset->write(buf, os);
208 os << "\n\\end_inset \n\n";
214 os << "\n\\backslash \n";
218 if (i + 1 < size() && getChar(i + 1) == ' ') {
225 if ((column > 70 && c == ' ')
230 // this check is to amend a bug. LyX sometimes
231 // inserts '\0' this could cause problems.
235 lyxerr << "ERROR (Paragraph::writeFile):"
236 " NULL char in structure." << endl;
242 // to make reading work properly
244 running_change = pimpl_->lookupChange(0);
245 Changes::lyxMarkChange(os, column, curtime,
246 Change(Change::UNCHANGED), running_change);
248 Changes::lyxMarkChange(os, column, curtime,
249 running_change, Change(Change::UNCHANGED));
253 void Paragraph::validate(LaTeXFeatures & features) const
255 pimpl_->validate(features, *layout());
259 // First few functions needed for cut and paste and paragraph breaking.
260 void Paragraph::copyIntoMinibuffer(Buffer const & buffer, pos_type pos) const
262 BufferParams bparams = buffer.params;
264 minibuffer_char = getChar(pos);
265 minibuffer_font = getFontSettings(bparams, pos);
266 minibuffer_inset = 0;
267 if (minibuffer_char == Paragraph::META_INSET) {
269 minibuffer_inset = getInset(pos)->clone(buffer);
271 minibuffer_inset = 0;
272 minibuffer_char = ' ';
273 // This reflects what GetInset() does (ARRae)
279 void Paragraph::cutIntoMinibuffer(BufferParams const & bparams, pos_type pos)
281 minibuffer_char = getChar(pos);
282 minibuffer_font = getFontSettings(bparams, pos);
283 minibuffer_inset = 0;
284 if (minibuffer_char == Paragraph::META_INSET) {
286 // the inset is not in a paragraph anymore
287 minibuffer_inset = insetlist.release(pos);
288 minibuffer_inset->parOwner(0);
290 minibuffer_inset = 0;
291 minibuffer_char = ' ';
292 // This reflects what GetInset() does (ARRae)
297 // Erase(pos); now the caller is responsible for that.
301 bool Paragraph::insertFromMinibuffer(pos_type pos)
303 if (minibuffer_char == Paragraph::META_INSET) {
304 if (!insetAllowed(minibuffer_inset->lyxCode())) {
307 insertInset(pos, minibuffer_inset, minibuffer_font);
309 LyXFont f = minibuffer_font;
310 if (!checkInsertChar(f)) {
313 insertChar(pos, minibuffer_char, f);
321 void Paragraph::eraseIntern(lyx::pos_type pos)
323 pimpl_->eraseIntern(pos);
327 bool Paragraph::erase(pos_type pos)
329 return pimpl_->erase(pos);
333 int Paragraph::erase(pos_type start, pos_type end)
335 return pimpl_->erase(start, end);
339 bool Paragraph::checkInsertChar(LyXFont & font)
341 if (pimpl_->inset_owner)
342 return pimpl_->inset_owner->checkInsertChar(font);
347 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c)
349 LyXFont const f(LyXFont::ALL_INHERIT);
350 insertChar(pos, c, f);
354 void Paragraph::insertChar(pos_type pos, Paragraph::value_type c,
355 LyXFont const & font, Change change)
357 pimpl_->insertChar(pos, c, font, change);
361 void Paragraph::insertInset(pos_type pos, Inset * inset)
363 LyXFont const f(LyXFont::ALL_INHERIT);
364 insertInset(pos, inset, f);
368 void Paragraph::insertInset(pos_type pos, Inset * inset, LyXFont const & font, Change change)
370 pimpl_->insertInset(pos, inset, font, change);
374 bool Paragraph::insetAllowed(Inset::Code code)
376 //lyxerr << "Paragraph::InsertInsetAllowed" << endl;
377 if (pimpl_->inset_owner)
378 return pimpl_->inset_owner->insetAllowed(code);
383 Inset * Paragraph::getInset(pos_type pos)
385 lyx::Assert(pos < size());
386 return insetlist.get(pos);
390 Inset const * Paragraph::getInset(pos_type pos) const
392 lyx::Assert(pos < size());
393 return insetlist.get(pos);
397 // Gets uninstantiated font setting at position.
398 LyXFont const Paragraph::getFontSettings(BufferParams const & bparams,
401 lyx::Assert(pos <= size());
403 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
404 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
405 for (; cit != end; ++cit) {
406 if (cit->pos() >= pos)
412 retfont = cit->font();
413 else if (pos == size() && !empty())
414 retfont = getFontSettings(bparams, pos - 1);
416 retfont = LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
422 // Gets uninstantiated font setting at position 0
423 LyXFont const Paragraph::getFirstFontSettings() const
425 if (!empty() && !pimpl_->fontlist.empty())
426 return pimpl_->fontlist[0].font();
428 return LyXFont(LyXFont::ALL_INHERIT);
432 // Gets the fully instantiated font at a given position in a paragraph
433 // This is basically the same function as LyXText::GetFont() in text2.C.
434 // The difference is that this one is used for generating the LaTeX file,
435 // and thus cosmetic "improvements" are disallowed: This has to deliver
436 // the true picture of the buffer. (Asger)
437 LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
438 LyXFont const & outerfont) const
440 lyx::Assert(pos >= 0);
442 LyXLayout_ptr const & lout = layout();
444 pos_type const body_pos = beginningOfBody();
448 layoutfont = lout->labelfont;
450 layoutfont = lout->font;
452 LyXFont tmpfont = getFontSettings(bparams, pos);
453 tmpfont.realize(layoutfont);
454 tmpfont.realize(outerfont);
456 return realizeFont(tmpfont, bparams);
460 LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
461 LyXFont const & outerfont) const
463 LyXLayout_ptr const & lout = layout();
465 LyXFont tmpfont = lout->labelfont;
466 tmpfont.setLanguage(getParLanguage(bparams));
467 tmpfont.realize(outerfont);
469 return realizeFont(tmpfont, bparams);
473 LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
474 LyXFont const & outerfont) const
476 LyXLayout_ptr const & lout = layout();
478 LyXFont tmpfont = lout->font;
479 tmpfont.setLanguage(getParLanguage(bparams));
480 tmpfont.realize(outerfont);
482 return realizeFont(tmpfont, bparams);
486 /// Returns the height of the highest font in range
488 Paragraph::highestFontInRange(pos_type startpos, pos_type endpos,
489 LyXFont::FONT_SIZE const def_size) const
491 if (pimpl_->fontlist.empty())
494 Pimpl::FontList::const_iterator end_it = pimpl_->fontlist.begin();
495 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
496 for (; end_it != end; ++end_it) {
497 if (end_it->pos() >= endpos)
504 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
505 for (; cit != end; ++cit) {
506 if (cit->pos() >= startpos)
510 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
511 for (; cit != end_it; ++cit) {
512 LyXFont::FONT_SIZE size = cit->font().size();
513 if (size == LyXFont::INHERIT_SIZE)
515 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
522 Paragraph::value_type
523 Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
525 value_type c = getChar(pos);
526 if (!lyxrc.rtl_support)
556 if (uc != c && getFontSettings(bparams, pos).isRightToLeft())
563 void Paragraph::setFont(pos_type pos, LyXFont const & font)
565 lyx::Assert(pos <= size());
567 // First, reduce font against layout/label font
568 // Update: The SetCharFont() routine in text2.C already
569 // reduces font, so we don't need to do that here. (Asger)
570 // No need to simplify this because it will disappear
571 // in a new kernel. (Asger)
572 // Next search font table
574 Pimpl::FontList::iterator beg = pimpl_->fontlist.begin();
575 Pimpl::FontList::iterator it = beg;
576 Pimpl::FontList::iterator endit = pimpl_->fontlist.end();
577 for (; it != endit; ++it) {
578 if (it->pos() >= pos)
581 unsigned int i = std::distance(beg, it);
582 bool notfound = (it == endit);
584 if (!notfound && pimpl_->fontlist[i].font() == font)
587 bool begin = pos == 0 || notfound ||
588 (i > 0 && pimpl_->fontlist[i - 1].pos() == pos - 1);
589 // Is position pos is a beginning of a font block?
590 bool end = !notfound && pimpl_->fontlist[i].pos() == pos;
591 // Is position pos is the end of a font block?
592 if (begin && end) { // A single char block
593 if (i + 1 < pimpl_->fontlist.size() &&
594 pimpl_->fontlist[i + 1].font() == font) {
595 // Merge the singleton block with the next block
596 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
597 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
598 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i - 1);
599 } else if (i > 0 && pimpl_->fontlist[i - 1].font() == font) {
600 // Merge the singleton block with the previous block
601 pimpl_->fontlist[i - 1].pos(pos);
602 pimpl_->fontlist.erase(pimpl_->fontlist.begin() + i);
604 pimpl_->fontlist[i].font(font);
606 if (i > 0 && pimpl_->fontlist[i - 1].font() == font)
607 pimpl_->fontlist[i - 1].pos(pos);
609 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
610 Pimpl::FontTable(pos, font));
612 pimpl_->fontlist[i].pos(pos - 1);
613 if (!(i + 1 < pimpl_->fontlist.size() &&
614 pimpl_->fontlist[i + 1].font() == font))
615 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
616 Pimpl::FontTable(pos, font));
617 } else { // The general case. The block is splitted into 3 blocks
618 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i,
619 Pimpl::FontTable(pos - 1, pimpl_->fontlist[i].font()));
620 pimpl_->fontlist.insert(pimpl_->fontlist.begin() + i + 1,
621 Pimpl::FontTable(pos, font));
627 void Paragraph::next(Paragraph * p)
633 // This function is able to hide closed footnotes.
634 Paragraph * Paragraph::next()
640 Paragraph const * Paragraph::next() const
646 void Paragraph::previous(Paragraph * p)
652 // This function is able to hide closed footnotes.
653 Paragraph * Paragraph::previous()
659 // This function is able to hide closed footnotes.
660 Paragraph const * Paragraph::previous() const
667 void Paragraph::makeSameLayout(Paragraph const & par)
669 layout(par.layout());
671 params() = par.params();
675 int Paragraph::stripLeadingSpaces()
677 if (layout()->free_spacing || isFreeSpacing())
681 while (!empty() && (isNewline(0) || isLineSeparator(0))) {
682 pimpl_->eraseIntern(0);
690 bool Paragraph::hasSameLayout(Paragraph const & par) const
693 par.layout() == layout() &&
694 params().sameLayout(par.params());
698 Paragraph::depth_type Paragraph::getDepth() const
700 return params().depth();
704 Paragraph::depth_type Paragraph::getMaxDepthAfter() const
706 if (layout()->isEnvironment())
707 return params().depth() + 1;
709 return params().depth();
713 char Paragraph::getAlign() const
715 return params().align();
719 string const & Paragraph::getLabelstring() const
721 return params().labelString();
725 // the next two functions are for the manual labels
726 string const Paragraph::getLabelWidthString() const
728 if (!params().labelWidthString().empty())
729 return params().labelWidthString();
731 return _("Senseless with this layout!");
735 void Paragraph::setLabelWidthString(string const & s)
737 params().labelWidthString(s);
741 void Paragraph::applyLayout(LyXLayout_ptr const & new_layout)
744 params().labelWidthString(string());
745 params().align(LYX_ALIGN_LAYOUT);
746 params().spaceTop(VSpace(VSpace::NONE));
747 params().spaceBottom(VSpace(VSpace::NONE));
748 params().spacing(Spacing(Spacing::Default));
752 int Paragraph::beginningOfBody() const
754 if (layout()->labeltype != LABEL_MANUAL)
757 // Unroll the first two cycles of the loop
758 // and remember the previous character to
759 // remove unnecessary GetChar() calls
761 if (i < size() && !isNewline(i)) {
763 char previous_char = 0;
766 previous_char = getChar(i);
769 while (i < size() && previous_char != ' ') {
775 previous_char = temp;
785 // returns -1 if inset not found
786 int Paragraph::getPositionOfInset(Inset const * inset) const
789 InsetList::iterator it = insetlist.begin();
790 InsetList::iterator end = insetlist.end();
791 for (; it != end; ++it)
792 if (it.getInset() == inset)
798 InsetBibitem * Paragraph::bibitem()
800 InsetList::iterator it = insetlist.begin();
801 if (it != insetlist.end() && it.getInset()->lyxCode() == Inset::BIBTEX_CODE)
802 return static_cast<InsetBibitem *>(it.getInset());
808 // This could go to ParagraphParameters if we want to
809 int Paragraph::startTeXParParams(BufferParams const & bparams,
810 ostream & os, bool moving_arg) const
814 if (params().noindent()) {
819 switch (params().align()) {
821 case LYX_ALIGN_BLOCK:
822 case LYX_ALIGN_LAYOUT:
823 case LYX_ALIGN_SPECIAL:
826 case LYX_ALIGN_RIGHT:
827 case LYX_ALIGN_CENTER:
835 switch (params().align()) {
837 case LYX_ALIGN_BLOCK:
838 case LYX_ALIGN_LAYOUT:
839 case LYX_ALIGN_SPECIAL:
842 if (getParLanguage(bparams)->babel() != "hebrew") {
843 os << "\\begin{flushleft}";
846 os << "\\begin{flushright}";
850 case LYX_ALIGN_RIGHT:
851 if (getParLanguage(bparams)->babel() != "hebrew") {
852 os << "\\begin{flushright}";
855 os << "\\begin{flushleft}";
859 case LYX_ALIGN_CENTER:
860 os << "\\begin{center}";
869 // This could go to ParagraphParameters if we want to
870 int Paragraph::endTeXParParams(BufferParams const & bparams,
871 ostream & os, bool moving_arg) const
875 switch (params().align()) {
877 case LYX_ALIGN_BLOCK:
878 case LYX_ALIGN_LAYOUT:
879 case LYX_ALIGN_SPECIAL:
882 case LYX_ALIGN_RIGHT:
883 case LYX_ALIGN_CENTER:
891 switch (params().align()) {
893 case LYX_ALIGN_BLOCK:
894 case LYX_ALIGN_LAYOUT:
895 case LYX_ALIGN_SPECIAL:
898 if (getParLanguage(bparams)->babel() != "hebrew") {
899 os << "\\end{flushleft}";
902 os << "\\end{flushright}";
906 case LYX_ALIGN_RIGHT:
907 if (getParLanguage(bparams)->babel() != "hebrew") {
908 os << "\\end{flushright}";
911 os << "\\end{flushleft}";
915 case LYX_ALIGN_CENTER:
916 os << "\\end{center}";
924 // This one spits out the text of the paragraph
925 bool Paragraph::simpleTeXOnePar(Buffer const * buf,
926 BufferParams const & bparams,
927 LyXFont const & outerfont,
928 ostream & os, TexRow & texrow,
931 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
933 bool return_value = false;
937 // well we have to check if we are in an inset with unlimited
938 // lenght (all in one row) if that is true then we don't allow
939 // any special options in the paragraph and also we don't allow
940 // any environment other then "Standard" to be valid!
942 (inInset() && inInset()->forceDefaultParagraphs(inInset()));
945 style = bparams.getLyXTextClass().defaultLayout();
952 // Maybe we have to create a optional argument.
955 // FIXME: can we actually skip this check and just call
956 // beginningOfBody() ??
957 if (style->labeltype != LABEL_MANUAL) {
960 body_pos = beginningOfBody();
963 unsigned int column = 0;
968 basefont = getLabelFont(bparams, outerfont);
970 basefont = getLayoutFont(bparams, outerfont);
973 moving_arg |= style->needprotect;
975 // Which font is currently active?
976 LyXFont running_font(basefont);
977 // Do we have an open font change?
978 bool open_font = false;
980 Change::Type running_change = Change::UNCHANGED;
982 texrow.start(id(), 0);
984 // if the paragraph is empty, the loop will not be entered at all
986 if (style->isCommand()) {
991 column += startTeXParParams(bparams, os, moving_arg);
995 for (pos_type i = 0; i < size(); ++i) {
997 // First char in paragraph or after label?
1001 column += running_font.latexWriteEndChanges(os, basefont, basefont);
1004 basefont = getLayoutFont(bparams, outerfont);
1005 running_font = basefont;
1009 if (style->isCommand()) {
1015 column += startTeXParParams(bparams, os,
1019 value_type c = getChar(i);
1021 // Fully instantiated font
1022 LyXFont font = getFont(bparams, i, outerfont);
1024 LyXFont const last_font = running_font;
1026 // Spaces at end of font change are simulated to be
1027 // outside font change, i.e. we write "\textXX{text} "
1028 // rather than "\textXX{text }". (Asger)
1029 if (open_font && c == ' ' && i <= size() - 2) {
1030 LyXFont const & next_font = getFont(bparams, i + 1, outerfont);
1031 if (next_font != running_font
1032 && next_font != font) {
1037 // We end font definition before blanks
1039 (font != running_font ||
1040 font.language() != running_font.language()))
1042 column += running_font.latexWriteEndChanges(os,
1044 (i == body_pos-1) ? basefont : font);
1045 running_font = basefont;
1049 // Blanks are printed before start of fontswitch
1051 // Do not print the separation of the optional argument
1052 if (i != body_pos - 1) {
1053 pimpl_->simpleTeXBlanks(os, texrow, i,
1054 column, font, *style);
1058 // Do we need to change font?
1059 if ((font != running_font ||
1060 font.language() != running_font.language()) &&
1063 column += font.latexWriteStartChanges(os, basefont,
1065 running_font = font;
1069 Change::Type change = pimpl_->lookupChange(i);
1071 column += Changes::latexMarkChange(os, running_change, change);
1072 running_change = change;
1074 pimpl_->simpleTeXSpecialChars(buf, bparams,
1075 os, texrow, moving_arg,
1077 basefont, outerfont, open_font,
1079 *style, i, column, c);
1082 column += Changes::latexMarkChange(os,
1083 running_change, Change::UNCHANGED);
1085 // If we have an open font definition, we have to close it
1087 #ifdef FIXED_LANGUAGE_END_DETECTION
1090 .latexWriteEndChanges(os, basefont,
1091 next_->getFont(bparams,
1094 running_font.latexWriteEndChanges(os, basefont,
1098 #ifdef WITH_WARNINGS
1099 //#warning For now we ALWAYS have to close the foreign font settings if they are
1100 //#warning there as we start another \selectlanguage with the next paragraph if
1101 //#warning we are in need of this. This should be fixed sometime (Jug)
1103 running_font.latexWriteEndChanges(os, basefont, basefont);
1107 // Needed if there is an optional argument but no contents.
1108 if (body_pos > 0 && body_pos == size()) {
1110 return_value = false;
1114 column += endTeXParParams(bparams, os, moving_arg);
1117 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
1118 return return_value;
1124 bool Paragraph::isHfill(pos_type pos) const
1126 return IsInsetChar(getChar(pos))
1127 && getInset(pos)->lyxCode() == Inset::HFILL_CODE;
1131 bool Paragraph::isInset(pos_type pos) const
1133 return IsInsetChar(getChar(pos));
1137 bool Paragraph::isNewline(pos_type pos) const
1139 return IsInsetChar(getChar(pos))
1140 && getInset(pos)->lyxCode() == Inset::NEWLINE_CODE;
1144 bool Paragraph::isSeparator(pos_type pos) const
1146 return IsSeparatorChar(getChar(pos));
1150 bool Paragraph::isLineSeparator(pos_type pos) const
1152 value_type const c = getChar(pos);
1153 return IsLineSeparatorChar(c)
1154 || (IsInsetChar(c) && getInset(pos) &&
1155 getInset(pos)->isLineSeparator());
1159 bool Paragraph::isKomma(pos_type pos) const
1161 return IsKommaChar(getChar(pos));
1165 /// Used by the spellchecker
1166 bool Paragraph::isLetter(pos_type pos) const
1168 value_type const c = getChar(pos);
1169 if (IsLetterChar(c))
1172 return getInset(pos)->isLetter();
1173 // We want to pass the ' and escape chars to ispell
1174 string const extra = lyxrc.isp_esc_chars + '\'';
1175 return contains(extra, c);
1179 bool Paragraph::isWord(pos_type pos) const
1181 return IsWordChar(getChar(pos)) ;
1186 Paragraph::getParLanguage(BufferParams const & bparams) const
1189 return getFirstFontSettings().language();
1190 #warning FIXME we should check the prev par as well (Lgb)
1192 } else if (previous_) {
1193 return previous_->getParLanguage(bparams);
1196 return bparams.language;
1200 bool Paragraph::isRightToLeftPar(BufferParams const & bparams) const
1202 return lyxrc.rtl_support
1203 && getParLanguage(bparams)->RightToLeft()
1204 && !(inInset() && inInset()->owner() &&
1205 inInset()->owner()->lyxCode() == Inset::ERT_CODE);
1209 void Paragraph::changeLanguage(BufferParams const & bparams,
1210 Language const * from, Language const * to)
1212 for (pos_type i = 0; i < size(); ++i) {
1213 LyXFont font = getFontSettings(bparams, i);
1214 if (font.language() == from) {
1215 font.setLanguage(to);
1222 bool Paragraph::isMultiLingual(BufferParams const & bparams)
1224 Language const * doc_language = bparams.language;
1225 Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
1226 Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
1228 for (; cit != end; ++cit)
1229 if (cit->font().language() != ignore_language &&
1230 cit->font().language() != latex_language &&
1231 cit->font().language() != doc_language)
1237 // Convert the paragraph to a string.
1238 // Used for building the table of contents
1239 string const Paragraph::asString(Buffer const * buffer, bool label) const
1242 if (label && !params().labelString().empty())
1243 s += params().labelString() + ' ';
1245 for (pos_type i = 0; i < size(); ++i) {
1246 value_type c = getChar(i);
1249 else if (c == META_INSET &&
1250 getInset(i)->lyxCode() == Inset::MATH_CODE) {
1252 getInset(i)->ascii(buffer, ost);
1253 s += subst(STRCONV(ost.str()),'\n',' ');
1261 string const Paragraph::asString(Buffer const * buffer,
1262 pos_type beg, pos_type end, bool label) const
1266 if (beg == 0 && label && !params().labelString().empty())
1267 os << params().labelString() << ' ';
1269 for (pos_type i = beg; i < end; ++i) {
1270 value_type const c = getUChar(buffer->params, i);
1273 else if (c == META_INSET)
1274 getInset(i)->ascii(buffer, os);
1277 return STRCONV(os.str());
1281 void Paragraph::setInsetOwner(Inset * i)
1283 pimpl_->inset_owner = i;
1284 InsetList::iterator it = insetlist.begin();
1285 InsetList::iterator end = insetlist.end();
1286 for (; it != end; ++it)
1288 it.getInset()->setOwner(i);
1292 void Paragraph::deleteInsetsLyXText(BufferView * bv)
1295 insetlist.deleteInsetsLyXText(bv);
1299 void Paragraph::resizeInsetsLyXText(BufferView * bv)
1302 insetlist.resizeInsetsLyXText(bv);
1306 void Paragraph::setContentsFromPar(Paragraph const & par)
1308 pimpl_->setContentsFromPar(par);
1312 void Paragraph::trackChanges(Change::Type type)
1314 pimpl_->trackChanges(type);
1318 void Paragraph::untrackChanges()
1320 pimpl_->untrackChanges();
1324 void Paragraph::cleanChanges()
1326 pimpl_->cleanChanges();
1330 Change::Type Paragraph::lookupChange(lyx::pos_type pos) const
1332 lyx::Assert(!size() || pos < size());
1333 return pimpl_->lookupChange(pos);
1337 Change const Paragraph::lookupChangeFull(lyx::pos_type pos) const
1339 lyx::Assert(!size() || pos < size());
1340 return pimpl_->lookupChangeFull(pos);
1344 bool Paragraph::isChanged(pos_type start, pos_type end) const
1346 return pimpl_->isChanged(start, end);
1350 bool Paragraph::isChangeEdited(pos_type start, pos_type end) const
1352 return pimpl_->isChangeEdited(start, end);
1356 void Paragraph::setChange(lyx::pos_type pos, Change::Type type)
1358 pimpl_->setChange(pos, type);
1363 void Paragraph::markErased()
1365 pimpl_->markErased();
1369 void Paragraph::acceptChange(pos_type start, pos_type end)
1371 return pimpl_->acceptChange(start, end);
1375 void Paragraph::rejectChange(pos_type start, pos_type end)
1377 return pimpl_->rejectChange(start, end);
1381 lyx::pos_type Paragraph::size() const
1383 return pimpl_->size();
1387 bool Paragraph::empty() const
1389 return pimpl_->empty();
1393 Paragraph::value_type Paragraph::getChar(pos_type pos) const
1395 return pimpl_->getChar(pos);
1399 int Paragraph::id() const
1405 LyXLayout_ptr const & Paragraph::layout() const
1411 void Paragraph::layout(LyXLayout_ptr const & new_layout)
1413 layout_ = new_layout;
1417 Inset * Paragraph::inInset() const
1419 return pimpl_->inset_owner;
1423 void Paragraph::clearContents()
1428 void Paragraph::setChar(pos_type pos, value_type c)
1430 pimpl_->setChar(pos, c);
1434 ParagraphParameters & Paragraph::params()
1436 return pimpl_->params;
1440 ParagraphParameters const & Paragraph::params() const
1442 return pimpl_->params;
1446 bool Paragraph::isFreeSpacing() const
1448 // for now we just need this, later should we need this in some
1449 // other way we can always add a function to Inset::() too.
1450 if (pimpl_->inset_owner && pimpl_->inset_owner->owner())
1451 return (pimpl_->inset_owner->owner()->lyxCode() == Inset::ERT_CODE);