178void QTextCursorPrivate::adjustCursor(QTextCursor::MoveOperation m)
180 adjusted_anchor = anchor;
181 if (position == anchor)
184 QTextFrame *f_position = priv->frameAt(position);
185 QTextFrame *f_anchor = priv->frameAt(adjusted_anchor);
187 if (f_position != f_anchor) {
189 QList<QTextFrame *> positionChain;
190 QList<QTextFrame *> anchorChain;
191 QTextFrame *f = f_position;
193 positionChain.prepend(f);
194 f = f->parentFrame();
198 anchorChain.prepend(f);
199 f = f->parentFrame();
201 Q_ASSERT(positionChain.at(0) == anchorChain.at(0));
203 int l = qMin(positionChain.size(), anchorChain.size());
205 if (positionChain.at(i) != anchorChain.at(i))
209 if (m <= QTextCursor::WordLeft) {
210 if (i < positionChain.size())
211 position = positionChain.at(i)->firstPosition() - 1;
213 if (i < positionChain.size())
214 position = positionChain.at(i)->lastPosition() + 1;
216 if (position < adjusted_anchor) {
217 if (i < anchorChain.size())
218 adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;
220 if (i < anchorChain.size())
221 adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;
224 f_position = positionChain.at(i-1);
228 QTextTable *table = qobject_cast<QTextTable *>(f_position);
232 QTextTableCell c_position = table->cellAt(position);
233 QTextTableCell c_anchor = table->cellAt(adjusted_anchor);
234 if (c_position != c_anchor) {
235 position = c_position.firstPosition();
236 if (position < adjusted_anchor)
237 adjusted_anchor = c_anchor.lastPosition();
239 adjusted_anchor = c_anchor.firstPosition();
241 currentCharFormat = -1;
244void QTextCursorPrivate::aboutToRemoveCell(
int from,
int to)
246 Q_ASSERT(from <= to);
247 if (position == anchor)
250 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
253 QTextTableCell removedCellFrom = t->cellAt(from);
254 QTextTableCell removedCellEnd = t->cellAt(to);
255 if (! removedCellFrom.isValid() || !removedCellEnd.isValid())
258 int curFrom = position;
259 int curTo = adjusted_anchor;
261 qSwap(curFrom, curTo);
263 QTextTableCell cellStart = t->cellAt(curFrom);
264 QTextTableCell cellEnd = t->cellAt(curTo);
266 if (cellStart.row() >= removedCellFrom.row() && cellEnd.row() <= removedCellEnd.row()
267 && cellStart.column() >= removedCellFrom.column()
268 && cellEnd.column() <= removedCellEnd.column()) {
271 if (removedCellFrom.row() == 0 && removedCellEnd.row() == t->rows()-1)
272 cell = t->cellAt(cellStart.row(), removedCellEnd.column()+1);
273 else if (removedCellFrom.column() == 0 && removedCellEnd.column() == t->columns()-1)
274 cell = t->cellAt(removedCellEnd.row() + 1, cellStart.column());
278 newPosition = cell.firstPosition();
280 newPosition = t->lastPosition()+1;
282 setPosition(newPosition);
283 anchor = newPosition;
284 adjusted_anchor = newPosition;
287 else if (cellStart.row() >= removedCellFrom.row() && cellStart.row() <= removedCellEnd.row()
288 && cellEnd.row() > removedCellEnd.row()) {
289 int newPosition = t->cellAt(removedCellEnd.row() + 1, cellStart.column()).firstPosition();
290 if (position < anchor)
291 position = newPosition;
293 anchor = adjusted_anchor = newPosition;
295 else if (cellStart.column() >= removedCellFrom.column() && cellStart.column() <= removedCellEnd.column()
296 && cellEnd.column() > removedCellEnd.column()) {
297 int newPosition = t->cellAt(cellStart.row(), removedCellEnd.column()+1).firstPosition();
298 if (position < anchor)
299 position = newPosition;
301 anchor = adjusted_anchor = newPosition;
305bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
307 currentCharFormat = -1;
309 QTextBlock blockIt = block();
310 bool visualMovement = priv->defaultCursorMoveStyle == Qt::VisualMoveStyle;
312 if (!blockIt.isValid())
315 const QTextLayout *layout = blockLayout(blockIt);
317 Qt::LayoutDirection blockDirection = layout->textOption().textDirection();
318 if (blockDirection == Qt::LayoutDirectionAuto)
319 blockDirection = blockIt.textDirection();
321 if (blockDirection == Qt::RightToLeft) {
322 if (op == QTextCursor::WordLeft)
323 op = QTextCursor::NextWord;
324 else if (op == QTextCursor::WordRight)
325 op = QTextCursor::PreviousWord;
327 if (!visualMovement) {
328 if (op == QTextCursor::Left)
329 op = QTextCursor::NextCharacter;
330 else if (op == QTextCursor::Right)
331 op = QTextCursor::PreviousCharacter;
335 int relativePos = position - blockIt.position();
337 if (!priv->isInEditBlock())
338 line = layout->lineForTextPosition(relativePos);
340 Q_ASSERT(priv->frameAt(position) == priv->frameAt(adjusted_anchor));
342 int newPosition = position;
344 if (mode == QTextCursor::KeepAnchor && complexSelectionTable() !=
nullptr) {
345 if ((op >= QTextCursor::EndOfLine && op <= QTextCursor::NextWord)
346 || (op >= QTextCursor::Right && op <= QTextCursor::WordRight)) {
347 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
349 QTextTableCell cell_pos = t->cellAt(position);
350 if (cell_pos.column() + cell_pos.columnSpan() != t->columns())
351 op = QTextCursor::NextCell;
355 if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
359 case QTextCursor::NoMove:
362 case QTextCursor::Start:
365 case QTextCursor::StartOfLine: {
366 newPosition = blockIt.position();
368 newPosition += line.textStart();
372 case QTextCursor::StartOfBlock: {
373 newPosition = blockIt.position();
376 case QTextCursor::PreviousBlock: {
377 if (blockIt == priv->blocksBegin())
379 blockIt = blockIt.previous();
381 newPosition = blockIt.position();
384 case QTextCursor::PreviousCharacter:
385 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
386 newPosition = qMin(position, adjusted_anchor);
388 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
390 case QTextCursor::Left:
391 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
392 newPosition = visualMovement ? qMax(position, adjusted_anchor)
393 : qMin(position, adjusted_anchor);
395 newPosition = visualMovement ? priv->leftCursorPosition(position)
396 : priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
398 case QTextCursor::StartOfWord: {
399 if (relativePos == 0)
403 QTextEngine *engine = layout->engine();
404 const QCharAttributes *attributes = engine->attributes();
405 if ((relativePos == blockIt.length() - 1)
406 && (attributes[relativePos - 1].whiteSpace || engine->atWordSeparator(relativePos - 1)))
409 if (relativePos < blockIt.length()-1)
414 case QTextCursor::PreviousWord:
415 case QTextCursor::WordLeft:
416 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipWords);
418 case QTextCursor::Up: {
419 int i = line.lineNumber() - 1;
421 if (blockIt == priv->blocksBegin())
423 int blockPosition = blockIt.position();
424 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
426 QTextTableCell cell = table->cellAt(blockPosition);
427 if (cell.firstPosition() == blockPosition) {
428 int row = cell.row() - 1;
430 blockPosition = table->cellAt(row, cell.column()).lastPosition();
433 blockPosition = table->firstPosition() - 1;
435 blockIt = priv->blocksFind(blockPosition);
437 blockIt = blockIt.previous();
440 blockIt = blockIt.previous();
442 layout = blockLayout(blockIt);
443 i = layout->lineCount()-1;
445 if (layout->lineCount()) {
446 QTextLine line = layout->lineAt(i);
447 newPosition = line.xToCursor(x) + blockIt.position();
449 newPosition = blockIt.position();
455 case QTextCursor::End:
456 newPosition = priv->length() - 1;
458 case QTextCursor::EndOfLine: {
459 if (!line.isValid() || line.textLength() == 0) {
460 if (blockIt.length() >= 1)
462 newPosition = blockIt.position() + blockIt.length() - 1;
465 newPosition = blockIt.position() + line.textStart() + line.textLength();
466 if (newPosition >= priv->length())
467 newPosition = priv->length() - 1;
468 if (line.lineNumber() < layout->lineCount() - 1) {
469 const QString text = blockIt.text();
472 if (text.at(line.textStart() + line.textLength() - 1).isSpace())
477 case QTextCursor::EndOfWord: {
478 QTextEngine *engine = layout->engine();
479 const QCharAttributes *attributes = engine->attributes();
480 const int len = blockIt.length() - 1;
481 if (relativePos >= len)
483 if (engine->atWordSeparator(relativePos)) {
485 while (relativePos < len && engine->atWordSeparator(relativePos))
488 while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
491 newPosition = blockIt.position() + relativePos;
494 case QTextCursor::EndOfBlock:
495 if (blockIt.length() >= 1)
497 newPosition = blockIt.position() + blockIt.length() - 1;
499 case QTextCursor::NextBlock: {
500 blockIt = blockIt.next();
501 if (!blockIt.isValid())
504 newPosition = blockIt.position();
507 case QTextCursor::NextCharacter:
508 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
509 newPosition = qMax(position, adjusted_anchor);
511 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
513 case QTextCursor::Right:
514 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
515 newPosition = visualMovement ? qMin(position, adjusted_anchor)
516 : qMax(position, adjusted_anchor);
518 newPosition = visualMovement ? priv->rightCursorPosition(position)
519 : priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
521 case QTextCursor::NextWord:
522 case QTextCursor::WordRight:
523 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);
526 case QTextCursor::Down: {
527 int i = line.lineNumber() + 1;
529 if (i >= layout->lineCount()) {
530 int blockPosition = blockIt.position() + blockIt.length() - 1;
531 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
533 QTextTableCell cell = table->cellAt(blockPosition);
534 if (cell.lastPosition() == blockPosition) {
535 int row = cell.row() + cell.rowSpan();
536 if (row < table->rows()) {
537 blockPosition = table->cellAt(row, cell.column()).firstPosition();
540 blockPosition = table->lastPosition() + 1;
542 blockIt = priv->blocksFind(blockPosition);
544 blockIt = blockIt.next();
547 blockIt = blockIt.next();
550 if (blockIt == priv->blocksEnd())
552 layout = blockLayout(blockIt);
555 if (layout->lineCount()) {
556 QTextLine line = layout->lineAt(i);
557 newPosition = line.xToCursor(x) + blockIt.position();
559 newPosition = blockIt.position();
564 case QTextCursor::NextCell:
565 case QTextCursor::PreviousCell:
566 case QTextCursor::NextRow:
567 case QTextCursor::PreviousRow: {
568 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
572 QTextTableCell cell = table->cellAt(position);
573 Q_ASSERT(cell.isValid());
574 int column = cell.column();
575 int row = cell.row();
576 const int currentRow = row;
577 if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
579 column += cell.columnSpan();
580 if (column >= table->columns()) {
584 cell = table->cellAt(row, column);
586 }
while (cell.isValid()
587 && ((op == QTextCursor::NextRow && currentRow == cell.row())
588 || cell.row() < row));
590 else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
594 column = table->columns()-1;
597 cell = table->cellAt(row, column);
599 }
while (cell.isValid()
600 && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
601 || cell.row() < row));
604 newPosition = cell.firstPosition();
609 if (mode == QTextCursor::KeepAnchor) {
610 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
611 if (table && ((op >= QTextCursor::PreviousBlock && op <= QTextCursor::WordLeft)
612 || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
613 int oldColumn = table->cellAt(position).column();
615 const QTextTableCell otherCell = table->cellAt(newPosition);
616 if (!otherCell.isValid())
619 int newColumn = otherCell.column();
620 if ((oldColumn > newColumn && op >= QTextCursor::End)
621 || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
626 const bool moved = setPosition(newPosition);
628 if (mode == QTextCursor::MoveAnchor) {
630 adjusted_anchor = position;