177void QTextCursorPrivate::adjustCursor(QTextCursor::MoveOperation m)
179 adjusted_anchor = anchor;
180 if (position == anchor)
183 QTextFrame *f_position = priv->frameAt(position);
184 QTextFrame *f_anchor = priv->frameAt(adjusted_anchor);
186 if (f_position != f_anchor) {
188 QList<QTextFrame *> positionChain;
189 QList<QTextFrame *> anchorChain;
190 QTextFrame *f = f_position;
192 positionChain.prepend(f);
193 f = f->parentFrame();
197 anchorChain.prepend(f);
198 f = f->parentFrame();
200 Q_ASSERT(positionChain.at(0) == anchorChain.at(0));
202 int l = qMin(positionChain.size(), anchorChain.size());
204 if (positionChain.at(i) != anchorChain.at(i))
208 if (m <= QTextCursor::WordLeft) {
209 if (i < positionChain.size())
210 position = positionChain.at(i)->firstPosition() - 1;
212 if (i < positionChain.size())
213 position = positionChain.at(i)->lastPosition() + 1;
215 if (position < adjusted_anchor) {
216 if (i < anchorChain.size())
217 adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;
219 if (i < anchorChain.size())
220 adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;
223 f_position = positionChain.at(i-1);
227 QTextTable *table = qobject_cast<QTextTable *>(f_position);
231 QTextTableCell c_position = table->cellAt(position);
232 QTextTableCell c_anchor = table->cellAt(adjusted_anchor);
233 if (c_position != c_anchor) {
234 position = c_position.firstPosition();
235 if (position < adjusted_anchor)
236 adjusted_anchor = c_anchor.lastPosition();
238 adjusted_anchor = c_anchor.firstPosition();
240 currentCharFormat = -1;
243void QTextCursorPrivate::aboutToRemoveCell(
int from,
int to)
245 Q_ASSERT(from <= to);
246 if (position == anchor)
249 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
252 QTextTableCell removedCellFrom = t->cellAt(from);
253 QTextTableCell removedCellEnd = t->cellAt(to);
254 if (! removedCellFrom.isValid() || !removedCellEnd.isValid())
257 int curFrom = position;
258 int curTo = adjusted_anchor;
260 qSwap(curFrom, curTo);
262 QTextTableCell cellStart = t->cellAt(curFrom);
263 QTextTableCell cellEnd = t->cellAt(curTo);
265 if (cellStart.row() >= removedCellFrom.row() && cellEnd.row() <= removedCellEnd.row()
266 && cellStart.column() >= removedCellFrom.column()
267 && cellEnd.column() <= removedCellEnd.column()) {
270 if (removedCellFrom.row() == 0 && removedCellEnd.row() == t->rows()-1)
271 cell = t->cellAt(cellStart.row(), removedCellEnd.column()+1);
272 else if (removedCellFrom.column() == 0 && removedCellEnd.column() == t->columns()-1)
273 cell = t->cellAt(removedCellEnd.row() + 1, cellStart.column());
277 newPosition = cell.firstPosition();
279 newPosition = t->lastPosition()+1;
281 setPosition(newPosition);
282 anchor = newPosition;
283 adjusted_anchor = newPosition;
286 else if (cellStart.row() >= removedCellFrom.row() && cellStart.row() <= removedCellEnd.row()
287 && cellEnd.row() > removedCellEnd.row()) {
288 int newPosition = t->cellAt(removedCellEnd.row() + 1, cellStart.column()).firstPosition();
289 if (position < anchor)
290 position = newPosition;
292 anchor = adjusted_anchor = newPosition;
294 else if (cellStart.column() >= removedCellFrom.column() && cellStart.column() <= removedCellEnd.column()
295 && cellEnd.column() > removedCellEnd.column()) {
296 int newPosition = t->cellAt(cellStart.row(), removedCellEnd.column()+1).firstPosition();
297 if (position < anchor)
298 position = newPosition;
300 anchor = adjusted_anchor = newPosition;
304bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
306 currentCharFormat = -1;
308 QTextBlock blockIt = block();
309 bool visualMovement = priv->defaultCursorMoveStyle == Qt::VisualMoveStyle;
311 if (!blockIt.isValid())
314 if (blockIt.textDirection() == Qt::RightToLeft) {
315 if (op == QTextCursor::WordLeft)
316 op = QTextCursor::NextWord;
317 else if (op == QTextCursor::WordRight)
318 op = QTextCursor::PreviousWord;
320 if (!visualMovement) {
321 if (op == QTextCursor::Left)
322 op = QTextCursor::NextCharacter;
323 else if (op == QTextCursor::Right)
324 op = QTextCursor::PreviousCharacter;
328 const QTextLayout *layout = blockLayout(blockIt);
329 int relativePos = position - blockIt.position();
331 if (!priv->isInEditBlock())
332 line = layout->lineForTextPosition(relativePos);
334 Q_ASSERT(priv->frameAt(position) == priv->frameAt(adjusted_anchor));
336 int newPosition = position;
338 if (mode == QTextCursor::KeepAnchor && complexSelectionTable() !=
nullptr) {
339 if ((op >= QTextCursor::EndOfLine && op <= QTextCursor::NextWord)
340 || (op >= QTextCursor::Right && op <= QTextCursor::WordRight)) {
341 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
343 QTextTableCell cell_pos = t->cellAt(position);
344 if (cell_pos.column() + cell_pos.columnSpan() != t->columns())
345 op = QTextCursor::NextCell;
349 if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
353 case QTextCursor::NoMove:
356 case QTextCursor::Start:
359 case QTextCursor::StartOfLine: {
360 newPosition = blockIt.position();
362 newPosition += line.textStart();
366 case QTextCursor::StartOfBlock: {
367 newPosition = blockIt.position();
370 case QTextCursor::PreviousBlock: {
371 if (blockIt == priv->blocksBegin())
373 blockIt = blockIt.previous();
375 newPosition = blockIt.position();
378 case QTextCursor::PreviousCharacter:
379 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
380 newPosition = qMin(position, adjusted_anchor);
382 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
384 case QTextCursor::Left:
385 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
386 newPosition = visualMovement ? qMax(position, adjusted_anchor)
387 : qMin(position, adjusted_anchor);
389 newPosition = visualMovement ? priv->leftCursorPosition(position)
390 : priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
392 case QTextCursor::StartOfWord: {
393 if (relativePos == 0)
397 QTextEngine *engine = layout->engine();
398 const QCharAttributes *attributes = engine->attributes();
399 if ((relativePos == blockIt.length() - 1)
400 && (attributes[relativePos - 1].whiteSpace || engine->atWordSeparator(relativePos - 1)))
403 if (relativePos < blockIt.length()-1)
408 case QTextCursor::PreviousWord:
409 case QTextCursor::WordLeft:
410 newPosition = priv->previousCursorPosition(position, QTextLayout::SkipWords);
412 case QTextCursor::Up: {
413 int i = line.lineNumber() - 1;
415 if (blockIt == priv->blocksBegin())
417 int blockPosition = blockIt.position();
418 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
420 QTextTableCell cell = table->cellAt(blockPosition);
421 if (cell.firstPosition() == blockPosition) {
422 int row = cell.row() - 1;
424 blockPosition = table->cellAt(row, cell.column()).lastPosition();
427 blockPosition = table->firstPosition() - 1;
429 blockIt = priv->blocksFind(blockPosition);
431 blockIt = blockIt.previous();
434 blockIt = blockIt.previous();
436 layout = blockLayout(blockIt);
437 i = layout->lineCount()-1;
439 if (layout->lineCount()) {
440 QTextLine line = layout->lineAt(i);
441 newPosition = line.xToCursor(x) + blockIt.position();
443 newPosition = blockIt.position();
449 case QTextCursor::End:
450 newPosition = priv->length() - 1;
452 case QTextCursor::EndOfLine: {
453 if (!line.isValid() || line.textLength() == 0) {
454 if (blockIt.length() >= 1)
456 newPosition = blockIt.position() + blockIt.length() - 1;
459 newPosition = blockIt.position() + line.textStart() + line.textLength();
460 if (newPosition >= priv->length())
461 newPosition = priv->length() - 1;
462 if (line.lineNumber() < layout->lineCount() - 1) {
463 const QString text = blockIt.text();
466 if (text.at(line.textStart() + line.textLength() - 1).isSpace())
471 case QTextCursor::EndOfWord: {
472 QTextEngine *engine = layout->engine();
473 const QCharAttributes *attributes = engine->attributes();
474 const int len = blockIt.length() - 1;
475 if (relativePos >= len)
477 if (engine->atWordSeparator(relativePos)) {
479 while (relativePos < len && engine->atWordSeparator(relativePos))
482 while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
485 newPosition = blockIt.position() + relativePos;
488 case QTextCursor::EndOfBlock:
489 if (blockIt.length() >= 1)
491 newPosition = blockIt.position() + blockIt.length() - 1;
493 case QTextCursor::NextBlock: {
494 blockIt = blockIt.next();
495 if (!blockIt.isValid())
498 newPosition = blockIt.position();
501 case QTextCursor::NextCharacter:
502 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
503 newPosition = qMax(position, adjusted_anchor);
505 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
507 case QTextCursor::Right:
508 if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
509 newPosition = visualMovement ? qMin(position, adjusted_anchor)
510 : qMax(position, adjusted_anchor);
512 newPosition = visualMovement ? priv->rightCursorPosition(position)
513 : priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
515 case QTextCursor::NextWord:
516 case QTextCursor::WordRight:
517 newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);
520 case QTextCursor::Down: {
521 int i = line.lineNumber() + 1;
523 if (i >= layout->lineCount()) {
524 int blockPosition = blockIt.position() + blockIt.length() - 1;
525 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
527 QTextTableCell cell = table->cellAt(blockPosition);
528 if (cell.lastPosition() == blockPosition) {
529 int row = cell.row() + cell.rowSpan();
530 if (row < table->rows()) {
531 blockPosition = table->cellAt(row, cell.column()).firstPosition();
534 blockPosition = table->lastPosition() + 1;
536 blockIt = priv->blocksFind(blockPosition);
538 blockIt = blockIt.next();
541 blockIt = blockIt.next();
544 if (blockIt == priv->blocksEnd())
546 layout = blockLayout(blockIt);
549 if (layout->lineCount()) {
550 QTextLine line = layout->lineAt(i);
551 newPosition = line.xToCursor(x) + blockIt.position();
553 newPosition = blockIt.position();
558 case QTextCursor::NextCell:
559 case QTextCursor::PreviousCell:
560 case QTextCursor::NextRow:
561 case QTextCursor::PreviousRow: {
562 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
566 QTextTableCell cell = table->cellAt(position);
567 Q_ASSERT(cell.isValid());
568 int column = cell.column();
569 int row = cell.row();
570 const int currentRow = row;
571 if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
573 column += cell.columnSpan();
574 if (column >= table->columns()) {
578 cell = table->cellAt(row, column);
580 }
while (cell.isValid()
581 && ((op == QTextCursor::NextRow && currentRow == cell.row())
582 || cell.row() < row));
584 else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
588 column = table->columns()-1;
591 cell = table->cellAt(row, column);
593 }
while (cell.isValid()
594 && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
595 || cell.row() < row));
598 newPosition = cell.firstPosition();
603 if (mode == QTextCursor::KeepAnchor) {
604 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
605 if (table && ((op >= QTextCursor::PreviousBlock && op <= QTextCursor::WordLeft)
606 || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
607 int oldColumn = table->cellAt(position).column();
609 const QTextTableCell otherCell = table->cellAt(newPosition);
610 if (!otherCell.isValid())
613 int newColumn = otherCell.column();
614 if ((oldColumn > newColumn && op >= QTextCursor::End)
615 || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
620 const bool moved = setPosition(newPosition);
622 if (mode == QTextCursor::MoveAnchor) {
624 adjusted_anchor = position;