void MacroData::expand(vector<MathData> const & args, MathData & to) const { updateData(); // Hack. Any inset with a cell would do. static InsetMathSqrt inset(0); inset.setBuffer(const_cast<Buffer &>(*buffer_)); // FIXME UNICODE asArray(display_.empty() ? definition_ : display_, inset.cell(0)); //lyxerr << "MathData::expand: args: " << args << endl; //lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl; for (DocIterator it = doc_iterator_begin(buffer_, &inset); it; it.forwardChar()) { if (!it.nextInset()) continue; if (it.nextInset()->lyxCode() != MATH_MACROARG_CODE) continue; //it.cell().erase(it.pos()); //it.cell().insert(it.pos(), it.nextInset()->asInsetMath() size_t n = static_cast<MathMacroArgument*>(it.nextInset())->number(); if (n <= args.size()) { it.cell().erase(it.pos()); it.cell().insert(it.pos(), args[n - 1]); } } //lyxerr << "MathData::expand: res: " << inset.cell(0) << endl; to = inset.cell(0); }
bool Row::isMarginSelected(bool left_margin, DocIterator const & beg, DocIterator const & end) const { pos_type const sel_pos = left_margin ? sel_beg : sel_end; pos_type const margin_pos = left_margin ? pos_ : end_; // Is the chosen margin selected ? if (sel_pos == margin_pos) { if (beg.pos() == end.pos()) // This is a special case in which the space between after // pos i-1 and before pos i is selected, i.e. the margins // (see DocIterator::boundary_). return beg.boundary() && !end.boundary(); else if (end.pos() == margin_pos) // If the selection ends around the margin, it is only // drawn if the cursor is after the margin. return !end.boundary(); else if (beg.pos() == margin_pos) // If the selection begins around the margin, it is // only drawn if the cursor is before the margin. return beg.boundary(); else return true; } return false; }
void Row::setSelectionAndMargins(DocIterator const & beg, DocIterator const & end) const { setSelection(beg.pos(), end.pos()); if (selection()) { end_margin_sel = isMarginSelected(false, beg, end); begin_margin_sel = isMarginSelected(true, beg, end); } }
static bool equal(DocIterator & o, DocIterator & n) { // Explicitly check for this, so we won't call // Paragraph::getChar for the last pos. bool const o_lastpos = o.pos() == o.lastpos(); bool const n_lastpos = n.pos() == n.lastpos(); if (o_lastpos || n_lastpos) return o_lastpos && n_lastpos; Paragraph const & old_par = o.text()->getPar(o.pit()); Paragraph const & new_par = n.text()->getPar(n.pit()); char_type const c_o = old_par.getChar(o.pos()); char_type const c_n = new_par.getChar(n.pos()); if (c_o != c_n) return false; if (old_par.isInset(o.pos())) { Inset const * i_o = old_par.getInset(o.pos()); Inset const * i_n = new_par.getInset(n.pos()); if (i_o && i_n) return equal(i_o, i_n); } Font fo = old_par.getFontSettings(o.buffer()->params(), o.pos()); Font fn = new_par.getFontSettings(n.buffer()->params(), n.pos()); return fo == fn; }
void InsetText::iterateForToc(DocIterator const & cdit, bool output_active) const { DocIterator dit = cdit; Toc & toc = buffer().tocBackend().toc("tableofcontents"); BufferParams const & bufparams = buffer_->params(); int const min_toclevel = bufparams.documentClass().min_toclevel(); // we really should have done this before we got here, but it // can't hurt too much to do it again bool const doing_output = output_active && producesOutput(); // For each paragraph, traverse its insets and let them add // their toc items ParagraphList const & pars = paragraphs(); pit_type pend = paragraphs().size(); for (pit_type pit = 0; pit != pend; ++pit) { Paragraph const & par = pars[pit]; dit.pit() = pit; // if we find an optarg, we'll save it for use later. InsetText const * arginset = 0; InsetList::const_iterator it = par.insetList().begin(); InsetList::const_iterator end = par.insetList().end(); for (; it != end; ++it) { Inset & inset = *it->inset; dit.pos() = it->pos; //lyxerr << (void*)&inset << " code: " << inset.lyxCode() << std::endl; inset.addToToc(dit, doing_output); if (inset.lyxCode() == ARG_CODE) arginset = inset.asInsetText(); } // now the toc entry for the paragraph int const toclevel = text().getTocLevel(pit); if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) { // insert this into the table of contents docstring tocstring; int const length = doing_output ? INT_MAX : TOC_ENTRY_LENGTH; if (arginset) { tocstring = par.labelString(); if (!tocstring.empty()) tocstring += ' '; arginset->text().forToc(tocstring, length); } else par.forToc(tocstring, length); dit.pos() = 0; toc.push_back(TocItem(dit, toclevel - min_toclevel, tocstring, doing_output, tocstring)); } // And now the list of changes. par.addChangesToToc(dit, buffer(), doing_output); } }
void GuiSpellchecker::check() { LYXERR(Debug::GUI, "Check the spelling of a word"); DocIterator from = bufferview()->cursor(); DocIterator to; WordLangTuple word_lang; docstring_list suggestions; int progress; try { progress = buffer().spellCheck(from, to, word_lang, suggestions); } catch (ExceptionMessage const & message) { if (message.type_ == WarningException) { Alert::warning(message.title_, message.details_); close(); return; } throw message; } LYXERR(Debug::GUI, "Found word \"" << word_lang.word() << "\""); d->count_ += progress; d->progress_ += progress; // end of document if (from == doc_iterator_end(&buffer())) { showSummary(); return; } if (!isVisible()) show(); d->word_ = word_lang; int const progress_bar = d->total_ ? int(100.0 * float(d->progress_)/d->total_) : 100; LYXERR(Debug::GUI, "Updating spell progress."); // set progress bar d->ui.spellcheckPR->setValue(progress_bar); // set suggestions updateSuggestions(suggestions); // set language int const pos = d->ui.languageCO->findData(toqstr(word_lang.lang()->lang())); if (pos != -1) d->ui.languageCO->setCurrentIndex(pos); // FIXME: if we used a lfun like in find/replace, dispatch would do // that for us int const size = to.pos() - from.pos(); BufferView * bv = const_cast<BufferView *>(bufferview()); bv->putSelectionAt(from, size, false); }
void InsetText::addToToc(DocIterator const & cdit) const { DocIterator dit = cdit; dit.push_back(CursorSlice(const_cast<InsetText &>(*this))); Toc & toc = buffer().tocBackend().toc("tableofcontents"); BufferParams const & bufparams = buffer_->params(); int const min_toclevel = bufparams.documentClass().min_toclevel(); // For each paragraph, traverse its insets and let them add // their toc items ParagraphList const & pars = paragraphs(); pit_type pend = paragraphs().size(); for (pit_type pit = 0; pit != pend; ++pit) { Paragraph const & par = pars[pit]; dit.pit() = pit; // if we find an optarg, we'll save it for use later. InsetText const * arginset = 0; InsetList::const_iterator it = par.insetList().begin(); InsetList::const_iterator end = par.insetList().end(); for (; it != end; ++it) { Inset & inset = *it->inset; dit.pos() = it->pos; //lyxerr << (void*)&inset << " code: " << inset.lyxCode() << std::endl; inset.addToToc(dit); if (inset.lyxCode() == ARG_CODE) arginset = inset.asInsetText(); } // now the toc entry for the paragraph int const toclevel = par.layout().toclevel; if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) { // insert this into the table of contents docstring tocstring; if (arginset) { tocstring = par.labelString(); if (!tocstring.empty()) tocstring += ' '; arginset->text().forToc(tocstring, TOC_ENTRY_LENGTH); } else par.forToc(tocstring, TOC_ENTRY_LENGTH); dit.pos() = 0; toc.push_back(TocItem(dit, toclevel - min_toclevel, tocstring, tocstring)); } // And now the list of changes. par.addChangesToToc(dit, buffer()); } }
void RowPainter::paintMisspelledMark(Row::Element const & e) const { if (e.font.fontInfo().nospellcheck() == FONT_ON) return; // if changed the misspelled marker gets placed slightly lower than normal // to avoid drawing at the same vertical offset FontMetrics const & fm = theFontMetrics(e.font); int const thickness = max(fm.lineWidth(), 2); int const y = yo_ + pi_.base.solidLineOffset() + pi_.base.solidLineThickness() + (e.change.changed() ? pi_.base.solidLineThickness() + 1 : 0) + 1 + thickness / 2; //FIXME: this could be computed only once, it is probably not costly. // check for cursor position // don't draw misspelled marker for words at cursor position // we don't want to disturb the process of text editing DocIterator const nw = pi_.base.bv->cursor().newWord(); pos_type cpos = -1; if (!nw.empty() && par_.id() == nw.paragraph().id()) { cpos = nw.pos(); if (cpos > 0 && cpos == par_.size() && !par_.isWordSeparator(cpos-1)) --cpos; else if (cpos > 0 && par_.isWordSeparator(cpos)) --cpos; } pos_type pos = e.pos; while (pos < e.pos + pos_type(e.str.length())) { if (!par_.isMisspelled(pos)) { ++pos; continue; } FontSpan const & range = par_.getSpellRange(pos); // Skip element which are being edited if (range.contains(cpos)) { // the range includes the last element pos = range.last + 1; continue; } int x1 = fm.pos2x(e.str, range.first - e.pos, e.isRTL(), e.extra); int x2 = fm.pos2x(e.str, min(range.last - e.pos + 1, pos_type(e.str.length())), e.isRTL(), e.extra); if (x1 > x2) swap(x1, x2); pi_.pain.line(int(x_ + x1), y, int(x_ + x2), y, Color_error, Painter::line_onoffdash, thickness); pos = range.last + 1; } }
void SpellcheckerWidget::Private::setSelection( DocIterator const & from, DocIterator const & to) const { BufferView * bv = gv_->documentBufferView(); DocIterator end = to; if (from.pit() != end.pit()) { // there are multiple paragraphs in selection Cursor & bvcur = bv->cursor(); bvcur.setCursor(from); bvcur.clearSelection(); bvcur.setSelection(true); bvcur.setCursor(end); bvcur.setSelection(true); } else { // FIXME LFUN // If we used a LFUN, dispatch would do all of this for us int const size = end.pos() - from.pos(); bv->putSelectionAt(from, size, false); } bv->processUpdateFlags(Update::Force | Update::FitCursor); }
bool GuiErrorList::goTo(int item) { if (&buffer() != buf_) { if (!theBufferList().isLoaded(buf_)) return false; FuncRequest fr(LFUN_BUFFER_SWITCH, buf_->absFileName()); dispatch(fr); } ErrorItem const & err = errorList()[item]; if (err.par_id == -1) return false; if (from_master_) // FIXME: implement return false; DocIterator dit = buf_->getParFromID(err.par_id); if (dit == doc_iterator_end(buf_)) { // FIXME: Happens when loading a read-only doc with // unknown layout. Should this be the case? LYXERR0("par id " << err.par_id << " not found"); return false; } // Now make the selection. // if pos_end is 0, this means it is end-of-paragraph pos_type const s = dit.paragraph().size(); pos_type const end = err.pos_end ? min(err.pos_end, s) : s; pos_type const start = min(err.pos_start, end); pos_type const range = end - start; dit.pos() = start; BufferView * bv = const_cast<BufferView *>(bufferview()); // FIXME: If we used an LFUN, we would not need this line: bv->putSelectionAt(dit, range, false); bv->processUpdateFlags(Update::Force | Update::FitCursor); return true; }
void InsetText::iterateForToc(DocIterator const & cdit, bool output_active, UpdateType utype, TocBackend & backend) const { DocIterator dit = cdit; // This also ensures that any document has a table of contents shared_ptr<Toc> toc = backend.toc("tableofcontents"); BufferParams const & bufparams = buffer_->params(); int const min_toclevel = bufparams.documentClass().min_toclevel(); // we really should have done this before we got here, but it // can't hurt too much to do it again bool const doing_output = output_active && producesOutput(); // For each paragraph, // * Add a toc item for the paragraph if it is AddToToc--merging adjacent // paragraphs as needed. // * Traverse its insets and let them add their toc items // * Compute the main table of contents (this is hardcoded) // * Add the list of changes ParagraphList const & pars = paragraphs(); pit_type pend = paragraphs().size(); // Record pairs {start,end} of where a toc item was opened for a paragraph // and where it must be closed stack<pair<pit_type, pit_type>> addtotoc_stack; for (pit_type pit = 0; pit != pend; ++pit) { Paragraph const & par = pars[pit]; dit.pit() = pit; dit.pos() = 0; // Custom AddToToc in paragraph layouts (i.e. theorems) if (par.layout().addToToc() && text().isFirstInSequence(pit)) { pit_type end = openAddToTocForParagraph(pit, dit, output_active, backend); addtotoc_stack.push({pit, end}); } // If we find an InsetArgument that is supposed to provide the TOC caption, // we'll save it for use later. InsetArgument const * arginset = nullptr; for (auto const & table : par.insetList()) { dit.pos() = table.pos; table.inset->addToToc(dit, doing_output, utype, backend); if (InsetArgument const * x = table.inset->asInsetArgument()) if (x->isTocCaption()) arginset = x; } // End custom AddToToc in paragraph layouts while (!addtotoc_stack.empty() && addtotoc_stack.top().second == pit) { // execute the closing function closeAddToTocForParagraph(addtotoc_stack.top().first, addtotoc_stack.top().second, backend); addtotoc_stack.pop(); } // now the toc entry for the paragraph in the main table of contents int const toclevel = text().getTocLevel(pit); if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) { // insert this into the table of contents docstring tocstring; int const length = (doing_output && utype == OutputUpdate) ? INT_MAX : TOC_ENTRY_LENGTH; if (arginset) { tocstring = par.labelString(); if (!tocstring.empty()) tocstring += ' '; arginset->text().forOutliner(tocstring, length); } else par.forOutliner(tocstring, length); dit.pos() = 0; toc->push_back(TocItem(dit, toclevel - min_toclevel, tocstring, doing_output)); } // And now the list of changes. par.addChangesToToc(dit, buffer(), doing_output, backend); } }