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 if (blockIt.textDirection() == Qt::RightToLeft) {
316 if (op == QTextCursor::WordLeft)
317 op = QTextCursor::NextWord;
318 else if (op == QTextCursor::WordRight)
319 op = QTextCursor::PreviousWord;
321 if (!visualMovement) {
322 if (op == QTextCursor::Left)
323 op = QTextCursor::NextCharacter;
324 else if (op == QTextCursor::Right)
325 op = QTextCursor::PreviousCharacter;
329 const QTextLayout *layout = blockLayout(blockIt);
330 int relativePos = position - blockIt.position();
332 if (!priv->isInEditBlock())
333 line = layout->lineForTextPosition(relativePos);
335 Q_ASSERT(priv->frameAt(position) == priv->frameAt(adjusted_anchor));
337 int newPosition = position;
339 if (mode == QTextCursor::KeepAnchor && complexSelectionTable() !=
nullptr) {
340 if ((op >= QTextCursor::EndOfLine && op <= QTextCursor::NextWord)
341 || (op >= QTextCursor::Right && op <= QTextCursor::WordRight)) {
342 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
344 QTextTableCell cell_pos = t->cellAt(position);
345 if (cell_pos.column() + cell_pos.columnSpan() != t->columns())
346 op = QTextCursor::NextCell;
350 if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
354 case QTextCursor::NoMove:
357 case QTextCursor::Start:
360 case QTextCursor::StartOfLine: {
361 newPosition = blockIt.position();
363 newPosition += line.textStart();
367 case QTextCursor::StartOfBlock: {
368 newPosition = blockIt.position();
371 case QTextCursor::PreviousBlock: {
372 if (blockIt == priv->blocksBegin())
374 blockIt = blockIt.previous();
376 newPosition = blockIt.position();
379 case QTextCursor::PreviousCharacter:
380 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
381 newPosition = qMin(position, adjusted_anchor);
383 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
385 case QTextCursor::Left:
386 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
387 newPosition = visualMovement ? qMax(position, adjusted_anchor)
388 : qMin(position, adjusted_anchor);
390 newPosition = visualMovement ? priv->leftCursorPosition(position)
391 : priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
393 case QTextCursor::StartOfWord: {
394 if (relativePos == 0)
398 QTextEngine *engine = layout->engine();
399 const QCharAttributes *attributes = engine->attributes();
400 if ((relativePos == blockIt.length() - 1)
401 && (attributes[relativePos - 1].whiteSpace || engine->atWordSeparator(relativePos - 1)))
404 if (relativePos < blockIt.length()-1)
409 case QTextCursor::PreviousWord:
410 case QTextCursor::WordLeft:
411 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipWords);
413 case QTextCursor::Up: {
414 int i = line.lineNumber() - 1;
416 if (blockIt == priv->blocksBegin())
418 int blockPosition = blockIt.position();
419 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
421 QTextTableCell cell = table->cellAt(blockPosition);
422 if (cell.firstPosition() == blockPosition) {
423 int row = cell.row() - 1;
425 blockPosition = table->cellAt(row, cell.column()).lastPosition();
428 blockPosition = table->firstPosition() - 1;
430 blockIt = priv->blocksFind(blockPosition);
432 blockIt = blockIt.previous();
435 blockIt = blockIt.previous();
437 layout = blockLayout(blockIt);
438 i = layout->lineCount()-1;
440 if (layout->lineCount()) {
441 QTextLine line = layout->lineAt(i);
442 newPosition = line.xToCursor(x) + blockIt.position();
444 newPosition = blockIt.position();
450 case QTextCursor::End:
451 newPosition = priv->length() - 1;
453 case QTextCursor::EndOfLine: {
454 if (!line.isValid() || line.textLength() == 0) {
455 if (blockIt.length() >= 1)
457 newPosition = blockIt.position() + blockIt.length() - 1;
460 newPosition = blockIt.position() + line.textStart() + line.textLength();
461 if (newPosition >= priv->length())
462 newPosition = priv->length() - 1;
463 if (line.lineNumber() < layout->lineCount() - 1) {
464 const QString text = blockIt.text();
467 if (text.at(line.textStart() + line.textLength() - 1).isSpace())
472 case QTextCursor::EndOfWord: {
473 QTextEngine *engine = layout->engine();
474 const QCharAttributes *attributes = engine->attributes();
475 const int len = blockIt.length() - 1;
476 if (relativePos >= len)
478 if (engine->atWordSeparator(relativePos)) {
480 while (relativePos < len && engine->atWordSeparator(relativePos))
483 while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
486 newPosition = blockIt.position() + relativePos;
489 case QTextCursor::EndOfBlock:
490 if (blockIt.length() >= 1)
492 newPosition = blockIt.position() + blockIt.length() - 1;
494 case QTextCursor::NextBlock: {
495 blockIt = blockIt.next();
496 if (!blockIt.isValid())
499 newPosition = blockIt.position();
502 case QTextCursor::NextCharacter:
503 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
504 newPosition = qMax(position, adjusted_anchor);
506 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
508 case QTextCursor::Right:
509 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
510 newPosition = visualMovement ? qMin(position, adjusted_anchor)
511 : qMax(position, adjusted_anchor);
513 newPosition = visualMovement ? priv->rightCursorPosition(position)
514 : priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
516 case QTextCursor::NextWord:
517 case QTextCursor::WordRight:
518 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);
521 case QTextCursor::Down: {
522 int i = line.lineNumber() + 1;
524 if (i >= layout->lineCount()) {
525 int blockPosition = blockIt.position() + blockIt.length() - 1;
526 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
528 QTextTableCell cell = table->cellAt(blockPosition);
529 if (cell.lastPosition() == blockPosition) {
530 int row = cell.row() + cell.rowSpan();
531 if (row < table->rows()) {
532 blockPosition = table->cellAt(row, cell.column()).firstPosition();
535 blockPosition = table->lastPosition() + 1;
537 blockIt = priv->blocksFind(blockPosition);
539 blockIt = blockIt.next();
542 blockIt = blockIt.next();
545 if (blockIt == priv->blocksEnd())
547 layout = blockLayout(blockIt);
550 if (layout->lineCount()) {
551 QTextLine line = layout->lineAt(i);
552 newPosition = line.xToCursor(x) + blockIt.position();
554 newPosition = blockIt.position();
559 case QTextCursor::NextCell:
560 case QTextCursor::PreviousCell:
561 case QTextCursor::NextRow:
562 case QTextCursor::PreviousRow: {
563 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
567 QTextTableCell cell = table->cellAt(position);
568 Q_ASSERT(cell.isValid());
569 int column = cell.column();
570 int row = cell.row();
571 const int currentRow = row;
572 if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
574 column += cell.columnSpan();
575 if (column >= table->columns()) {
579 cell = table->cellAt(row, column);
581 }
while (cell.isValid()
582 && ((op == QTextCursor::NextRow && currentRow == cell.row())
583 || cell.row() < row));
585 else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
589 column = table->columns()-1;
592 cell = table->cellAt(row, column);
594 }
while (cell.isValid()
595 && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
596 || cell.row() < row));
599 newPosition = cell.firstPosition();
604 if (mode == QTextCursor::KeepAnchor) {
605 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
606 if (table && ((op >= QTextCursor::PreviousBlock && op <= QTextCursor::WordLeft)
607 || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
608 int oldColumn = table->cellAt(position).column();
610 const QTextTableCell otherCell = table->cellAt(newPosition);
611 if (!otherCell.isValid())
614 int newColumn = otherCell.column();
615 if ((oldColumn > newColumn && op >= QTextCursor::End)
616 || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
621 const bool moved = setPosition(newPosition);
623 if (mode == QTextCursor::MoveAnchor) {
625 adjusted_anchor = position;