diff --git a/src/TexRow.cpp b/src/TexRow.cpp index fe2f694e27..4bec66e05a 100644 --- a/src/TexRow.cpp +++ b/src/TexRow.cpp @@ -38,9 +38,15 @@ bool TexRow::RowEntryList::addEntry(RowEntry const & entry) else text_entry_ = size(); } + forceAddEntry(entry); + return true; +} + + +void TexRow::RowEntryList::forceAddEntry(RowEntry const & entry) +{ if (size() == 0 || !(operator[](size() - 1) == entry)) push_back(RowEntry(entry)); - return true; } @@ -60,6 +66,14 @@ TexRow::RowEntry TexRow::RowEntryList::entry() const } +void TexRow::RowEntryList::append(RowEntryList const & row) +{ + if (text_entry_ >= size()) + text_entry_ = row.text_entry_ + size(); + insert(end(), row.begin(), row.end()); +} + + TexRow::TextEntry const TexRow::text_none = { -1, 0 }; TexRow::RowEntry const TexRow::row_none = { false, TexRow::text_none }; @@ -130,9 +144,17 @@ bool TexRow::start(int id, int pos) } -bool TexRow::startMath(uid_type id, idx_type cell) +void TexRow::forceStart(int id, int pos) { - return start(mathEntry(id,cell)); + if (!enabled_) + return; + return current_row_.forceAddEntry(textEntry(id,pos)); +} + + +void TexRow::startMath(uid_type id, idx_type cell) +{ + start(mathEntry(id,cell)); } @@ -161,6 +183,24 @@ void TexRow::finalize() } +void TexRow::append(TexRow const & texrow) +{ + if (!enabled_ || !texrow.enabled_) + return; + RowList::const_iterator it = texrow.rowlist_.begin(); + RowList::const_iterator const end = texrow.rowlist_.end(); + if (it == end) { + current_row_.append(texrow.current_row_); + } else { + current_row_.append(*it++); + rowlist_.push_back(current_row_); + rowlist_.insert(rowlist_.end(), it, end); + current_row_ = texrow.current_row_; + } +} + + + bool TexRow::getIdFromRow(int row, int & id, int & pos) const { TextEntry t = text_none; @@ -267,8 +307,8 @@ public: { return row_it_ == row_end_; } - - + + bool operator==(RowListIterator const & a) const { return row_it_ == a.row_it_ && ((atEnd() && a.atEnd()) || it_ == a.it_); @@ -353,7 +393,7 @@ std::pair TexRow::rowFromDocIterator(DocIterator const & dit) const end_offset = 1; break; case -1: { - // ...or it is the row preceding the first that matches pos+1 + // ...or it is the row preceding the first that matches pos+1 if (!end_is_next) { end_is_next = true; if (it.row() != best_end_entry.row()) @@ -406,8 +446,13 @@ std::pair TexRow::rowFromCursor(Cursor const & cur) const std::pair beg_rows = rowFromDocIterator(beg); if (cur.selection()) { DocIterator end = cur.selectionEnd(); - if (!cur.selIsMultiCell()) - end.top().backwardPos(); + if (!cur.selIsMultiCell() + // backwardPos asserts without the following test, IMO it's not my + // duty to check this. + && (end.top().pit() != 0 + || end.top().idx() != 0 + || end.top().pos() != 0)) + end.top().backwardPos(); std::pair end_rows = rowFromDocIterator(end); return std::make_pair(std::min(beg_rows.first, end_rows.first), std::max(beg_rows.second, end_rows.second)); @@ -460,7 +505,7 @@ LyXErr & operator<<(LyXErr & l, TexRow & texrow) for (int i = 0; i < texrow.rows(); i++) { int id,pos; if (texrow.getIdFromRow(i+1,id,pos) && id>0) - l << i+1 << ":" << id << ":" << pos << "\n"; + l << i+1 << ":" << id << ":" << pos << "\n"; } } return l; diff --git a/src/TexRow.h b/src/TexRow.h index 7468386be4..c072ec18ab 100644 --- a/src/TexRow.h +++ b/src/TexRow.h @@ -12,6 +12,19 @@ * Full author contact details are available in file CREDITS. */ +/* Note about debugging options: + * + * When compiled in devel mode and run with the option -dbg latex, two ways + * of debugging TexRow are available: + * + * 1. The source view panel prepends the full TexRow information to the LaTeX + * output. + * + * 2. Clicking on any line in the source view moves the buffer to the location + * recognised by TexRow. + * + */ + #ifndef TEXROW_H #define TEXROW_H @@ -53,11 +66,11 @@ public: }; }; - // For each row we store a list of one TextEntry and several - // MathEntries. (The order is important.) We only want one text entry + // For each row we store a list of one special TextEntry and several + // RowEntries. (The order is important.) We only want one text entry // because we do not want to store every position in the lyx file. On the - // other hand we want to record all math cells positions for enough - // precision. Usually the count of math cells is easier to handle. + // other hand we want to record all math and table cells positions for + // enough precision. Usually the count of cells is easier to handle. class RowEntryList : public std::vector { public: RowEntryList() : std::vector(), text_entry_(-1) {} @@ -65,12 +78,19 @@ public: // returns true if the row entry will appear in the row entry list bool addEntry(RowEntry const &); + // the row entry will appear in the row entry list, but it never counts + // as a proper text entry. + void forceAddEntry(RowEntry const &); + // returns the TextEntry or TexRow::text_none if none TextEntry getTextEntry() const; // returns the first entry, or TexRow::row_none if none RowEntry entry() const; + // appends a row + void append(RowEntryList const &); + private: size_t text_entry_; }; @@ -79,7 +99,7 @@ public: static bool isNone(RowEntry const &); static const TextEntry text_none; static const RowEntry row_none; - + /// Returns true if TextEntry is devoid of information static bool isNone(TextEntry const &); @@ -118,9 +138,16 @@ public: /// returns true if this entry will appear on the current row bool start(int id, int pos); - /// Defines a cell and position for the current line - /// returns true if this entry will appear on the current row - bool startMath(uid_type id, idx_type cell); + /// Defines a cell and position for the current line. Always appear in the + /// current row. + void startMath(uid_type id, idx_type cell); + + /// Defines the paragraph for the current cell-like inset. Always appears + /// in the current row like a math cell, but is detached from the normal + /// text flow. Note: since the cell idx is not recorded it does not work as + /// well as for math grids; if we were to do that properly we would need to + /// access the id of the parent Tabular inset from the CursorSlice. + void forceStart(int id, int pos); /// Insert node when line is completed void newline(); @@ -155,6 +182,10 @@ public: /// Returns the number of rows contained int rows() const { return rowlist_.size(); } + /// appends texrow. the final line of this is merged with the first line of + /// texrow. + void append(TexRow const & texrow); + /// for debugging purpose void prepend(docstring_list &) const; diff --git a/src/insets/InsetCaption.cpp b/src/insets/InsetCaption.cpp index 93abfe47ee..21b834aac5 100644 --- a/src/insets/InsetCaption.cpp +++ b/src/insets/InsetCaption.cpp @@ -329,6 +329,8 @@ void InsetCaption::getArgument(otexstream & os, rp.par_end = paragraphs().size(); // Output the contents of the inset + if (!paragraphs().empty()) + os.texrow().forceStart(paragraphs()[0].id(), 0); latexParagraphs(buffer(), text(), os, rp); runparams.encoding = rp.encoding; diff --git a/src/insets/InsetFloat.cpp b/src/insets/InsetFloat.cpp index 1cda8d9cba..cfd4002677 100644 --- a/src/insets/InsetFloat.cpp +++ b/src/insets/InsetFloat.cpp @@ -327,12 +327,11 @@ void InsetFloat::latex(otexstream & os, OutputParams const & runparams_in) const OutputParams rp = runparams_in; rp.moving_arg = true; - docstring const caption = getCaption(rp); - if (!caption.empty()) { - os << caption; - } + getCaption(os, rp); os << '{'; // The main argument is the contents of the float. This is not a moving argument. + if (!paragraphs().empty()) + os.texrow().forceStart(paragraphs()[0].id(), 0); rp.moving_arg = false; rp.inFloat = OutputParams::SUBFLOAT; InsetText::latex(os, rp); @@ -493,29 +492,38 @@ bool InsetFloat::allowsCaptionVariation(std::string const & newtype) const docstring InsetFloat::getCaption(OutputParams const & runparams) const +{ + TexRow texrow(false); + odocstringstream ods; + otexstream os(ods, texrow); + getCaption(os, runparams); + return ods.str(); +} + + +void InsetFloat::getCaption(otexstream & os, + OutputParams const & runparams) const { if (paragraphs().empty()) - return docstring(); + return; InsetCaption const * ins = getCaptionInset(); if (ins == 0) - return docstring(); + return; + ins->getArgs(os, runparams); + + os << '['; TexRow texrow; odocstringstream ods; - otexstream os(ods, texrow); - ins->getArgs(os, runparams); - ods << '['; - odocstringstream odss; - otexstream oss(odss, texrow); + otexstream oss(ods, texrow); ins->getArgument(oss, runparams); - docstring arg = odss.str(); + docstring arg = ods.str(); // Protect ']' if (arg.find(']') != docstring::npos) arg = '{' + arg + '}'; - ods << arg; - ods << ']'; - return ods.str(); + os.append(arg, texrow); + os << ']'; } diff --git a/src/insets/InsetFloat.h b/src/insets/InsetFloat.h index c58be580b1..9c202678fc 100644 --- a/src/insets/InsetFloat.h +++ b/src/insets/InsetFloat.h @@ -109,6 +109,8 @@ private: /// docstring getCaption(OutputParams const &) const; /// + void getCaption(otexstream & os, OutputParams const & runparams) const; + InsetFloatParams params_; }; diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index d92acf2e0f..e827bfd27e 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -2572,6 +2572,9 @@ void Tabular::TeXRow(otexstream & os, row_type row, shared_ptr inset = cellInset(cell); Paragraph const & par = inset->paragraphs().front(); + + os.texrow().forceStart(par.id(), 0); + bool rtl = par.isRTL(buffer().params()) && !par.empty() && getPWidth(cell).zero() diff --git a/src/texstream.cpp b/src/texstream.cpp index 84fb060552..3268dca7b2 100644 --- a/src/texstream.cpp +++ b/src/texstream.cpp @@ -29,6 +29,14 @@ using lyx::support::split; namespace lyx { + +void otexrowstream::append(docstring const & str, TexRow const & texrow) +{ + os_ << str; + texrow_.append(texrow); +} + + void otexrowstream::put(char_type const & c) { os_.put(c); @@ -36,6 +44,7 @@ void otexrowstream::put(char_type const & c) texrow_.newline(); } + void otexstream::put(char_type const & c) { if (protectspace_) { diff --git a/src/texstream.h b/src/texstream.h index 4fff211146..c81bbf9a84 100644 --- a/src/texstream.h +++ b/src/texstream.h @@ -33,6 +33,8 @@ public: TexRow & texrow() { return texrow_; } /// void put(char_type const & c); + /// + void append(docstring const &, TexRow const &); private: /// odocstream & os_;