void Text::setCharFont(Buffer const & buffer, pit_type pit,
pos_type pos, Font const & fnt)
{
+ BOOST_ASSERT(!pars_[pit].isInset(pos) ||
+ !pars_[pit].getInset(pos)->noFontChange());
+
Font font = fnt;
Layout_ptr const & layout = pars_[pit].layout();
}
+void Text::setInsetFont(Buffer const & buffer, pit_type pit,
+ pos_type pos, Font const & font, bool toggleall)
+{
+ BOOST_ASSERT(pars_[pit].isInset(pos) &&
+ pars_[pit].getInset(pos)->noFontChange());
+
+ Inset * const inset = pars_[pit].getInset(pos);
+ DocIterator dit = doc_iterator_begin(*inset);
+ // start of the last cell
+ DocIterator end = dit;
+ end.idx() = end.lastidx();
+
+ while (true) {
+ Text * text = dit.text();
+ Inset * cell = dit.realInset();
+ if (text && cell) {
+ DocIterator cellbegin = doc_iterator_begin(*cell);
+ // last position of the cell
+ DocIterator cellend = cellbegin;
+ cellend.pit() = cellend.lastpit();
+ cellend.pos() = cellend.lastpos();
+ text->setFont(buffer, cellbegin, cellend, font, toggleall);
+ }
+ if (dit == end)
+ break;
+ dit.forwardIdx();
+ }
+}
+
+
// return past-the-last paragraph influenced by a layout change on pit
pit_type Text::undoSpan(pit_type pit)
{
}
-// set font over selection
void Text::setFont(Cursor & cur, Font const & font, bool toggleall)
{
BOOST_ASSERT(this == cur.text());
- // if there is no selection just set the current_font
- if (!cur.selection()) {
- // Determine basis font
- Font layoutfont;
- pit_type pit = cur.pit();
- if (cur.pos() < pars_[pit].beginOfBody())
- layoutfont = getLabelFont(cur.buffer(), pars_[pit]);
- else
- layoutfont = getLayoutFont(cur.buffer(), pit);
+ // Set the current_font
+ // Determine basis font
+ Font layoutfont;
+ pit_type pit = cur.pit();
+ if (cur.pos() < pars_[pit].beginOfBody())
+ layoutfont = getLabelFont(cur.buffer(), pars_[pit]);
+ else
+ layoutfont = getLayoutFont(cur.buffer(), pit);
- // Update current font
- real_current_font.update(font,
- cur.buffer().params().language,
- toggleall);
+ // Update current font
+ real_current_font.update(font,
+ cur.buffer().params().language,
+ toggleall);
- // Reduce to implicit settings
- current_font = real_current_font;
- current_font.reduce(layoutfont);
- // And resolve it completely
- real_current_font.realize(layoutfont);
+ // Reduce to implicit settings
+ current_font = real_current_font;
+ current_font.reduce(layoutfont);
+ // And resolve it completely
+ real_current_font.realize(layoutfont);
+ // if there is no selection that's all we need to do
+ if (!cur.selection())
return;
- }
// Ok, we have a selection.
recordUndoSelection(cur);
- DocIterator dit = cur.selectionBegin();
- DocIterator ditend = cur.selectionEnd();
+ setFont(cur.buffer(), cur.selectionBegin(), cur.selectionEnd(), font,
+ toggleall);
+}
- BufferParams const & params = cur.buffer().params();
+void Text::setFont(Buffer const & buffer, DocIterator const & begin,
+ DocIterator const & end, Font const & font,
+ bool toggleall)
+{
// Don't use forwardChar here as ditend might have
// pos() == lastpos() and forwardChar would miss it.
// Can't use forwardPos either as this descends into
// nested insets.
- for (; dit != ditend; dit.forwardPosNoDescend()) {
+ Language const * language = buffer.params().language;
+ for (DocIterator dit = begin; dit != end; dit.forwardPosNoDescend()) {
if (dit.pos() != dit.lastpos()) {
- Font f = getFont(cur.buffer(), dit.paragraph(), dit.pos());
- f.update(font, params.language, toggleall);
- setCharFont(cur.buffer(), dit.pit(), dit.pos(), f);
+ pit_type const pit = dit.pit();
+ pos_type const pos = dit.pos();
+ if (pars_[pit].isInset(pos) &&
+ pars_[pit].getInset(pos)->noFontChange())
+ // We need to propagate the font change to all
+ // text cells of the inset (bug 1973).
+ // FIXME: This should change, see documentation
+ // of noFontChange in insetbase.h
+ setInsetFont(buffer, pit, pos, font, toggleall);
+ else {
+ Font f = getFont(buffer, dit.paragraph(), pos);
+ f.update(font, language, toggleall);
+ setCharFont(buffer, pit, pos, f);
+ }
}
}
}
pos_type pos = cur.pos();
Paragraph & par = cur.paragraph();
- if (cur.boundary() && pos > 0)
+ if (cur.boundary() && pos > 0 && pos < cur.lastpos()) {
--pos;
+ // We may have just moved to the previous row ---
+ // we're going to be needing its bidi tables!
+ bidi.computeTables(par, cur.buffer(), cur.textRow());
+ }
if (pos > 0) {
if (pos == cur.lastpos())
return false;
if (cur.pos() == cur.lastpos())
return false;
- Inset * inset = cur.nextInset();
+ Inset * inset = front ? cur.nextInset() : cur.prevInset();
if (!isHighlyEditableInset(inset))
return false;
+ /*
+ * Apparently, when entering an inset we are expected to be positioned
+ * *before* it in the containing paragraph, regardless of the direction
+ * from which we are entering. Otherwise, cursor placement goes awry,
+ * and when we exit from the beginning, we'll be placed *after* the
+ * inset.
+ */
+ if (!front)
+ --cur.pos();
inset->edit(cur, front);
return true;
}
// Tell BufferView to test for FitCursor in any case!
cur.updateFlags(Update::FitCursor);
- if (!cur.boundary() && cur.pos() > 0 &&
- cur.textRow().pos() == cur.pos() &&
- !cur.paragraph().isLineSeparator(cur.pos()-1) &&
- !cur.paragraph().isNewline(cur.pos()-1)) {
- return setCursor(cur, cur.pit(), cur.pos(), true, true);
- }
- if (cur.pos() != 0) {
- bool updateNeeded = setCursor(cur, cur.pit(), cur.pos() - 1, true, false);
+ if (cur.pos() > 0) {
+ if (cur.boundary())
+ return setCursor(cur, cur.pit(), cur.pos(), true, false);
+
+ bool updateNeeded = false;
+ // If checkAndActivateInset returns true, that means that
+ // the cursor was placed inside it, so we're done
if (!checkAndActivateInset(cur, false)) {
- /** FIXME: What's this cause purpose???
- bool boundary = cur.boundary();
- if (false && !boundary &&
- bidi.isBoundary(cur.buffer(), cur.paragraph(), cur.pos() + 1))
- updateNeeded |=
- setCursor(cur, cur.pit(), cur.pos() + 1, true, true);
- */
+ if (!cur.boundary() &&
+ cur.textRow().pos() == cur.pos()
+ // FIXME: the following two conditions are copied
+ // from cursorRight; however, isLineSeparator()
+ // is definitely wrong here, isNewline I'm not sure
+ // about. I'm leaving them as comments for now,
+ // until we understand why they should or shouldn't
+ // be here.
+ /*&&
+ !cur.paragraph().isLineSeparator(cur.pos()-1) &&
+ !cur.paragraph().isNewline(cur.pos() - 1)*/) {
+ updateNeeded |= setCursor(cur, cur.pit(), cur.pos(),
+ true, true);
+ }
+ updateNeeded |= setCursor(cur, cur.pit(),cur.pos() - 1,
+ true, false);
}
return updateNeeded;
}
- if (cur.pit() != 0) {
+ if (cur.pit() > 0) {
// Steps into the paragraph above
return setCursor(cur, cur.pit() - 1, getPar(cur.pit() - 1).size());
}
true, false);
bool updateNeeded = false;
+ // If checkAndActivateInset returns true, that means that
+ // the cursor was placed inside it, so we're done
if (!checkAndActivateInset(cur, true)) {
if (cur.textRow().endpos() == cur.pos() + 1 &&
cur.textRow().endpos() != cur.lastpos() &&
cur.boundary(true);
}
updateNeeded |= setCursor(cur, cur.pit(), cur.pos() + 1, true, cur.boundary());
- if (false && bidi.isBoundary(cur.buffer(), cur.paragraph(),
- cur.pos()))
- updateNeeded |= setCursor(cur, cur.pit(), cur.pos(), true, true);
}
return updateNeeded;
}