X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fparagraph.C;h=c0c53c3e524220eed2aefacf3aef80680facef39;hb=35204f8f33d7400a5fefeffea533fb4cb4097211;hp=6af0a4205e97dcb3d6a393f16b57614f6ee445ec;hpb=d27e1b9dd76867adc7149d32730d1d93ea58eae4;p=lyx.git diff --git a/src/paragraph.C b/src/paragraph.C index 6af0a4205e..c0c53c3e52 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -44,8 +44,8 @@ #include "support/lstrings.h" #include "support/textutils.h" #include "support/convert.h" +#include "support/unicode.h" -#include #include #include @@ -53,9 +53,10 @@ #include #include -using lyx::pos_type; -using lyx::support::subst; +namespace lyx { + +using support::subst; using std::distance; using std::endl; @@ -152,13 +153,12 @@ void Paragraph::write(Buffer const & buf, ostream & os, LyXFont font1(LyXFont::ALL_INHERIT, bparams.language); Change running_change = Change(Change::UNCHANGED); - lyx::time_type const curtime(lyx::current_time()); int column = 0; for (pos_type i = 0; i <= size(); ++i) { - Change change = pimpl_->lookupChangeFull(i); - Changes::lyxMarkChange(os, column, curtime, running_change, change); + Change change = pimpl_->lookupChange(i); + Changes::lyxMarkChange(os, column, running_change, change); running_change = change; if (i == size()) @@ -212,9 +212,11 @@ void Paragraph::write(Buffer const & buf, ostream & os, } // this check is to amend a bug. LyX sometimes // inserts '\0' this could cause problems. - if (c != '\0') - os << c; - else + if (c != '\0') { + std::vector tmp = ucs4_to_utf8(c); + tmp.push_back('\0'); + os << &tmp[0]; + } else lyxerr << "ERROR (Paragraph::writeFile):" " NULL char in structure." << endl; ++column; @@ -232,55 +234,60 @@ void Paragraph::validate(LaTeXFeatures & features) const } -void Paragraph::eraseIntern(lyx::pos_type pos) +bool Paragraph::eraseChar(pos_type pos, bool trackChanges) { - pimpl_->eraseIntern(pos); + return pimpl_->eraseChar(pos, trackChanges); } -bool Paragraph::erase(pos_type pos) +int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges) { - return pimpl_->erase(pos); + return pimpl_->eraseChars(start, end, trackChanges); } -int Paragraph::erase(pos_type start, pos_type end) +void Paragraph::insert(pos_type start, docstring const & str, + LyXFont const & font, Change const & change) { - return pimpl_->erase(start, end); + for (size_t i = 0, n = str.size(); i != n ; ++i) + insertChar(start + i, str[i], font, change); } -void Paragraph::insert(pos_type start, string const & str, - LyXFont const & font) +void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, + bool trackChanges) { - for (size_t i = 0, n = str.size(); i != n ; ++i) - insertChar(start + i, str[i], font); + pimpl_->insertChar(pos, c, Change(trackChanges ? + Change::INSERTED : Change::UNCHANGED)); } void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, - Change change) + LyXFont const & font, bool trackChanges) { - pimpl_->insertChar(pos, c, change); + pimpl_->insertChar(pos, c, Change(trackChanges ? + Change::INSERTED : Change::UNCHANGED)); + setFont(pos, font); } void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, - LyXFont const & font, Change change) + LyXFont const & font, Change const & change) { pimpl_->insertChar(pos, c, change); setFont(pos, font); } -void Paragraph::insertInset(pos_type pos, InsetBase * inset, Change change) +void Paragraph::insertInset(pos_type pos, InsetBase * inset, + Change const & change) { pimpl_->insertInset(pos, inset, change); } void Paragraph::insertInset(pos_type pos, InsetBase * inset, - LyXFont const & font, Change change) + LyXFont const & font, Change const & change) { pimpl_->insertInset(pos, inset, change); setFont(pos, font); @@ -318,10 +325,10 @@ LyXFont const Paragraph::getFontSettings(BufferParams const & bparams, } -FontSpan Paragraph::fontSpan(lyx::pos_type pos) const +FontSpan Paragraph::fontSpan(pos_type pos) const { BOOST_ASSERT(pos <= size()); - lyx::pos_type start = 0; + pos_type start = 0; Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin(); Pimpl::FontList::const_iterator end = pimpl_->fontlist.end(); @@ -378,7 +385,7 @@ LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos, LyXFont font = getFontSettings(bparams, pos); font.realize(layoutfont); font.realize(outerfont); - font.realize(bparams.getLyXTextClass().defaultfont()); + font.realize(bparams.getFont()); return font; } @@ -390,7 +397,7 @@ LyXFont const Paragraph::getLabelFont LyXFont tmpfont = layout()->labelfont; tmpfont.setLanguage(getParLanguage(bparams)); tmpfont.realize(outerfont); - tmpfont.realize(bparams.getLyXTextClass().defaultfont()); + tmpfont.realize(bparams.getFont()); return tmpfont; } @@ -401,7 +408,7 @@ LyXFont const Paragraph::getLayoutFont LyXFont tmpfont = layout()->font; tmpfont.setLanguage(getParLanguage(bparams)); tmpfont.realize(outerfont); - tmpfont.realize(bparams.getLyXTextClass().defaultfont()); + tmpfont.realize(bparams.getFont()); return tmpfont; } @@ -560,8 +567,8 @@ int Paragraph::stripLeadingSpaces() int i = 0; while (!empty() && (isNewline(0) || isLineSeparator(0)) - && (lookupChange(0) != Change::DELETED)) { - erase(0); + && !isDeleted(0)) { + eraseChar(0, false); // no change tracking here ++i; } @@ -575,13 +582,13 @@ bool Paragraph::hasSameLayout(Paragraph const & par) const } -Paragraph::depth_type Paragraph::getDepth() const +depth_type Paragraph::getDepth() const { return params().depth(); } -Paragraph::depth_type Paragraph::getMaxDepthAfter() const +depth_type Paragraph::getMaxDepthAfter() const { if (layout()->isEnvironment()) return params().depth() + 1; @@ -596,14 +603,14 @@ char Paragraph::getAlign() const } -string const & Paragraph::getLabelstring() const +docstring const & Paragraph::getLabelstring() const { return params().labelString(); } // the next two functions are for the manual labels -string const Paragraph::getLabelWidthString() const +docstring const Paragraph::getLabelWidthString() const { if (!params().labelWidthString().empty()) return params().labelWidthString(); @@ -612,7 +619,7 @@ string const Paragraph::getLabelWidthString() const } -void Paragraph::setLabelWidthString(string const & s) +void Paragraph::setLabelWidthString(docstring const & s) { params().labelWidthString(s); } @@ -621,7 +628,7 @@ void Paragraph::setLabelWidthString(string const & s) void Paragraph::applyLayout(LyXLayout_ptr const & new_layout) { layout(new_layout); - params().labelWidthString(string()); + params().labelWidthString(docstring()); params().align(LYX_ALIGN_LAYOUT); params().spacing(Spacing(Spacing::Default)); } @@ -647,8 +654,8 @@ void Paragraph::setBeginOfBody() pos_type end = size(); if (i < end && !isNewline(i)) { ++i; - char previous_char = 0; - char temp = 0; + char_type previous_char = 0; + char_type temp = 0; if (i < end) { previous_char = text_[i]; if (!isNewline(i)) { @@ -737,7 +744,7 @@ string const corrected_env(string const & suffix, string const & env, // This could go to ParagraphParameters if we want to int Paragraph::startTeXParParams(BufferParams const & bparams, - ostream & os, bool moving_arg) const + odocstream & os, bool moving_arg) const { int column = 0; @@ -774,7 +781,7 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, output = corrected_env("\\begin", "flushleft", ownerCode()); else output = corrected_env("\\begin", "flushright", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } case LYX_ALIGN_RIGHT: { @@ -783,13 +790,13 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, output = corrected_env("\\begin", "flushright", ownerCode()); else output = corrected_env("\\begin", "flushleft", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } case LYX_ALIGN_CENTER: { string output; output = corrected_env("\\begin", "center", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } @@ -801,7 +808,7 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, // This could go to ParagraphParameters if we want to int Paragraph::endTeXParParams(BufferParams const & bparams, - ostream & os, bool moving_arg) const + odocstream & os, bool moving_arg) const { int column = 0; @@ -833,7 +840,7 @@ int Paragraph::endTeXParParams(BufferParams const & bparams, output = corrected_env("\\par\\end", "flushleft", ownerCode()); else output = corrected_env("\\par\\end", "flushright", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } case LYX_ALIGN_RIGHT: { @@ -842,13 +849,13 @@ int Paragraph::endTeXParParams(BufferParams const & bparams, output = corrected_env("\\par\\end", "flushright", ownerCode()); else output = corrected_env("\\par\\end", "flushleft", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } case LYX_ALIGN_CENTER: { string output; output = corrected_env("\\par\\end", "center", ownerCode()); - os << output; + os << from_ascii(output); column += output.size(); break; } @@ -862,7 +869,7 @@ int Paragraph::endTeXParParams(BufferParams const & bparams, bool Paragraph::simpleTeXOnePar(Buffer const & buf, BufferParams const & bparams, LyXFont const & outerfont, - ostream & os, TexRow & texrow, + odocstream & os, TexRow & texrow, OutputParams const & runparams) const { lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl; @@ -890,7 +897,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, // output change tracking marks only if desired, // if dvipost is installed, // and with dvi/ps (other formats don't work) - bool const output = bparams.output_changes + bool const output = bparams.outputChanges && runparams.flavor == OutputParams::LATEX && features.isAvailable("dvipost"); @@ -913,7 +920,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, // Do we have an open font change? bool open_font = false; - Change::Type running_change = Change::UNCHANGED; + Change::Type runningChangeType = Change::UNCHANGED; texrow.start(id(), 0); @@ -1001,15 +1008,15 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, open_font = true; } - Change::Type change = pimpl_->lookupChange(i); + Change::Type changeType = pimpl_->lookupChange(i).type; - column += Changes::latexMarkChange(os, running_change, - change, output); - running_change = change; + column += Changes::latexMarkChange(os, runningChangeType, + changeType, output); + runningChangeType = changeType; // do not output text which is marked deleted // if change tracking output is not desired - if (output || running_change != Change::DELETED) { + if (output || runningChangeType != Change::DELETED) { OutputParams rp = runparams; rp.free_spacing = style->free_spacing; rp.local_font = &font; @@ -1018,13 +1025,13 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, os, texrow, rp, font, running_font, basefont, outerfont, open_font, - running_change, + runningChangeType, *style, i, column, c); } } column += Changes::latexMarkChange(os, - running_change, Change::UNCHANGED, output); + runningChangeType, Change::UNCHANGED, output); // If we have an open font definition, we have to close it if (open_font) { @@ -1118,201 +1125,6 @@ void reset(PAR_TAG & p1, PAR_TAG const & p2) } // anon -// Handle internal paragraph parsing -- layout already processed. -void Paragraph::simpleLinuxDocOnePar(Buffer const & buf, - ostream & os, - LyXFont const & outerfont, - OutputParams const & runparams, - lyx::depth_type /*depth*/) const -{ - LyXLayout_ptr const & style = layout(); - - string::size_type char_line_count = 5; // Heuristic choice ;-) - - // gets paragraph main font - LyXFont font_old; - bool desc_on; - if (style->labeltype == LABEL_MANUAL) { - font_old = style->labelfont; - desc_on = true; - } else { - font_old = style->font; - desc_on = false; - } - - LyXFont::FONT_FAMILY family_type = LyXFont::ROMAN_FAMILY; - LyXFont::FONT_SERIES series_type = LyXFont::MEDIUM_SERIES; - LyXFont::FONT_SHAPE shape_type = LyXFont::UP_SHAPE; - bool is_em = false; - - stack tag_state; - // parsing main loop - for (pos_type i = 0; i < size(); ++i) { - - PAR_TAG tag_close = PAR_NONE; - list < PAR_TAG > tag_open; - - LyXFont const font = getFont(buf.params(), i, outerfont); - - if (font_old.family() != font.family()) { - switch (family_type) { - case LyXFont::SANS_FAMILY: - tag_close |= SF; - break; - case LyXFont::TYPEWRITER_FAMILY: - tag_close |= TT; - break; - default: - break; - } - - family_type = font.family(); - - switch (family_type) { - case LyXFont::SANS_FAMILY: - tag_open.push_back(SF); - break; - case LyXFont::TYPEWRITER_FAMILY: - tag_open.push_back(TT); - break; - default: - break; - } - } - - if (font_old.series() != font.series()) { - switch (series_type) { - case LyXFont::BOLD_SERIES: - tag_close |= BF; - break; - default: - break; - } - - series_type = font.series(); - - switch (series_type) { - case LyXFont::BOLD_SERIES: - tag_open.push_back(BF); - break; - default: - break; - } - - } - - if (font_old.shape() != font.shape()) { - switch (shape_type) { - case LyXFont::ITALIC_SHAPE: - tag_close |= IT; - break; - case LyXFont::SLANTED_SHAPE: - tag_close |= SL; - break; - default: - break; - } - - shape_type = font.shape(); - - switch (shape_type) { - case LyXFont::ITALIC_SHAPE: - tag_open.push_back(IT); - break; - case LyXFont::SLANTED_SHAPE: - tag_open.push_back(SL); - break; - default: - break; - } - } - // handle tag - if (font_old.emph() != font.emph()) { - if (font.emph() == LyXFont::ON) { - tag_open.push_back(EM); - is_em = true; - } - else if (is_em) { - tag_close |= EM; - is_em = false; - } - } - - list < PAR_TAG > temp; - while (!tag_state.empty() && tag_close) { - PAR_TAG k = tag_state.top(); - tag_state.pop(); - os << "'; - if (tag_close & k) - reset(tag_close,k); - else - temp.push_back(k); - } - - for(list< PAR_TAG >::const_iterator j = temp.begin(); - j != temp.end(); ++j) { - tag_state.push(*j); - os << '<' << tag_name(*j) << '>'; - } - - for(list< PAR_TAG >::const_iterator j = tag_open.begin(); - j != tag_open.end(); ++j) { - tag_state.push(*j); - os << '<' << tag_name(*j) << '>'; - } - - value_type c = getChar(i); - - - if (c == Paragraph::META_INSET) { - getInset(i)->linuxdoc(buf, os, runparams); - font_old = font; - continue; - } - - if (style->latexparam() == "CDATA") { - // "TeX"-Mode on == > SGML-Mode on. - if (c != '\0') - os << c; - ++char_line_count; - } else { - bool ws; - string str; - boost::tie(ws, str) = sgml::escapeChar(c); - if (ws && !isFreeSpacing()) { - // in freespacing mode, spaces are - // non-breaking characters - if (desc_on) { // if char is ' ' then... - ++char_line_count; - sgmlLineBreak(os, char_line_count, 6); - os << ""; - desc_on = false; - } else { - sgmlLineBreak(os, char_line_count, 1); - os << c; - } - } else { - os << str; - char_line_count += str.length(); - } - } - font_old = font; - } - - while (!tag_state.empty()) { - os << "'; - tag_state.pop(); - } - - // resets description flag correctly - if (desc_on) { - // not closed... - sgmlLineBreak(os, char_line_count, 6); - os << ""; - } -} - - bool Paragraph::emptyTag() const { for (pos_type i = 0; i < size(); ++i) { @@ -1345,7 +1157,7 @@ string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) cons InsetBase::Code lyx_code = inset->lyxCode(); if (lyx_code == InsetBase::LABEL_CODE) { string const id = static_cast(inset)->getContents(); - return "id=\"" + sgml::cleanID(buf, runparams, id) + "\""; + return "id='" + to_utf8(sgml::cleanID(buf, runparams, from_utf8(id))) + "'"; } } @@ -1354,7 +1166,7 @@ string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) cons } -pos_type Paragraph::getFirstWord(Buffer const & buf, ostream & os, OutputParams const & runparams) const +pos_type Paragraph::getFirstWord(Buffer const & buf, odocstream & os, OutputParams const & runparams) const { pos_type i; for (i = 0; i < size(); ++i) { @@ -1365,12 +1177,8 @@ pos_type Paragraph::getFirstWord(Buffer const & buf, ostream & os, OutputParams value_type c = getChar(i); if (c == ' ') break; - bool ws; - string str; - boost::tie(ws, str) = sgml::escapeChar(c); - - os << str; - } + os << sgml::escapeChar(c); + } } return i; } @@ -1394,7 +1202,7 @@ bool Paragraph::onlyText(Buffer const & buf, LyXFont const & outerfont, pos_type void Paragraph::simpleDocBookOnePar(Buffer const & buf, - ostream & os, + odocstream & os, OutputParams const & runparams, LyXFont const & outerfont, pos_type initial) const @@ -1428,14 +1236,11 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, inset->docbook(buf, os, runparams); } else { value_type c = getChar(i); - bool ws; - string str; - boost::tie(ws, str) = sgml::escapeChar(c); if (style->pass_thru) - os << c; + os.put(c); else - os << str; + os << sgml::escapeChar(c); } font_old = font; } @@ -1502,7 +1307,8 @@ bool Paragraph::isRightToLeftPar(BufferParams const & bparams) const void Paragraph::changeLanguage(BufferParams const & bparams, Language const * from, Language const * to) { - for (pos_type i = 0; i < size(); ++i) { + // change language including dummy font change at the end + for (pos_type i = 0; i <= size(); ++i) { LyXFont font = getFontSettings(bparams, i); if (font.language() == from) { font.setLanguage(to); @@ -1529,14 +1335,14 @@ bool Paragraph::isMultiLingual(BufferParams const & bparams) const // Convert the paragraph to a string. // Used for building the table of contents -string const Paragraph::asString(Buffer const & buffer, bool label) const +docstring const Paragraph::asString(Buffer const & buffer, bool label) const { OutputParams runparams; return asString(buffer, runparams, label); } -string const Paragraph::asString(Buffer const & buffer, +docstring const Paragraph::asString(Buffer const & buffer, OutputParams const & runparams, bool label) const { @@ -1560,13 +1366,13 @@ string const Paragraph::asString(Buffer const & buffer, return s; #else // This should really be done by the caller and not here. - string ret = asString(buffer, runparams, 0, size(), label); + docstring ret = asString(buffer, runparams, 0, size(), label); return subst(ret, '\n', ' '); #endif } -string const Paragraph::asString(Buffer const & buffer, +docstring const Paragraph::asString(Buffer const & buffer, pos_type beg, pos_type end, bool label) const { @@ -1575,11 +1381,11 @@ string const Paragraph::asString(Buffer const & buffer, } -string const Paragraph::asString(Buffer const & buffer, +docstring const Paragraph::asString(Buffer const & buffer, OutputParams const & runparams, pos_type beg, pos_type end, bool label) const { - ostringstream os; + lyx::odocstringstream os; if (beg == 0 && label && !params().labelString().empty()) os << params().labelString() << ' '; @@ -1587,7 +1393,7 @@ string const Paragraph::asString(Buffer const & buffer, for (pos_type i = beg; i < end; ++i) { value_type const c = getUChar(buffer.params(), i); if (isPrintable(c)) - os << c; + os.put(c); else if (c == META_INSET) getInset(i)->textString(buffer, os, runparams); } @@ -1602,83 +1408,40 @@ void Paragraph::setInsetOwner(InsetBase * inset) } -void Paragraph::setContentsFromPar(Paragraph const & par) -{ - pimpl_->setContentsFromPar(par); -} - - -void Paragraph::trackChanges(Change::Type type) -{ - pimpl_->trackChanges(type); -} - - -void Paragraph::untrackChanges() -{ - pimpl_->untrackChanges(); -} - - -void Paragraph::cleanChanges(ChangeTracking ct) -{ - pimpl_->cleanChanges(ct); -} - - -Change::Type Paragraph::lookupChange(lyx::pos_type pos) const +Change const Paragraph::lookupChange(pos_type pos) const { BOOST_ASSERT(pos <= size()); return pimpl_->lookupChange(pos); } -Change const Paragraph::lookupChangeFull(lyx::pos_type pos) const -{ - BOOST_ASSERT(pos <= size()); - return pimpl_->lookupChangeFull(pos); -} - - bool Paragraph::isChanged(pos_type start, pos_type end) const { return pimpl_->isChanged(start, end); } -bool Paragraph::isChangeEdited(pos_type start, pos_type end) const -{ - return pimpl_->isChangeEdited(start, end); -} - - -void Paragraph::setChange(lyx::pos_type pos, Change::Type type) +void Paragraph::setChange(Change const & change) { - pimpl_->setChange(pos, type); + pimpl_->setChange(change); } -void Paragraph::setChangeFull(lyx::pos_type pos, Change change) +void Paragraph::setChange(pos_type pos, Change const & change) { - pimpl_->setChangeFull(pos, change); + pimpl_->setChange(pos, change); } -void Paragraph::markErased(bool erased) +void Paragraph::acceptChanges(pos_type start, pos_type end) { - pimpl_->markErased(erased); + return pimpl_->acceptChanges(start, end); } -void Paragraph::acceptChange(pos_type start, pos_type end) +void Paragraph::rejectChanges(pos_type start, pos_type end) { - return pimpl_->acceptChange(start, end); -} - - -void Paragraph::rejectChange(pos_type start, pos_type end) -{ - return pimpl_->rejectChange(start, end); + return pimpl_->rejectChanges(start, end); } @@ -1719,12 +1482,6 @@ void Paragraph::clearContents() } -void Paragraph::setChar(pos_type pos, value_type c) -{ - text_[pos] = c; -} - - ParagraphParameters & Paragraph::params() { return pimpl_->params; @@ -1808,10 +1565,11 @@ size_t Paragraph::pos2row(pos_type pos) const } -unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const +char_type Paragraph::transformChar(char_type c, pos_type pos) const { if (!Encodings::is_arabic(c)) if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && isDigit(c)) + // FIXME UNICODE What does this do? return c + (0xb0 - '0'); else return c; @@ -1851,3 +1609,38 @@ void Paragraph::dump() const rows_[i].dump(); } } + + +bool Paragraph::hfillExpansion(Row const & row, pos_type pos) const +{ + if (!isHfill(pos)) + return false; + + // at the end of a row it does not count + // unless another hfill exists on the line + if (pos >= row.endpos()) { + for (pos_type i = row.pos(); i < pos && !isHfill(i); ++i) + return false; + } + + // at the beginning of a row it does not count, if it is not + // the first row of a paragaph + if (row.pos() == 0) + return true; + + // in some labels it does not count + if (layout()->margintype != MARGIN_MANUAL && pos < beginOfBody()) + return false; + + // if there is anything between the first char of the row and + // the specified position that is not a newline and not a hfill, + // the hfill will count, otherwise not + pos_type i = row.pos(); + while (i < pos && (isNewline(i) || isHfill(i))) + ++i; + + return i != pos; +} + + +} // namespace lyx