( s: SelectionState, screen: Screen, col: number, row: number, )
| 387 | * noSelect cell or out of bounds, so dragging into gutters still extends. |
| 388 | */ |
| 389 | export function extendSelection( |
| 390 | s: SelectionState, |
| 391 | screen: Screen, |
| 392 | col: number, |
| 393 | row: number, |
| 394 | ): void { |
| 395 | if (!s.isDragging || !s.anchorSpan) return |
| 396 | const span = s.anchorSpan |
| 397 | let mLo: Point |
| 398 | let mHi: Point |
| 399 | if (span.kind === 'word') { |
| 400 | const b = wordBoundsAt(screen, col, row) |
| 401 | mLo = { col: b ? b.lo : col, row } |
| 402 | mHi = { col: b ? b.hi : col, row } |
| 403 | } else { |
| 404 | const r = clamp(row, 0, screen.height - 1) |
| 405 | mLo = { col: 0, row: r } |
| 406 | mHi = { col: screen.width - 1, row: r } |
| 407 | } |
| 408 | if (comparePoints(mHi, span.lo) < 0) { |
| 409 | // Mouse target ends before anchor span: extend backward. |
| 410 | s.anchor = span.hi |
| 411 | s.focus = mLo |
| 412 | } else if (comparePoints(mLo, span.hi) > 0) { |
| 413 | // Mouse target starts after anchor span: extend forward. |
| 414 | s.anchor = span.lo |
| 415 | s.focus = mHi |
| 416 | } else { |
| 417 | // Mouse overlaps the anchor span: just select the anchor span. |
| 418 | s.anchor = span.lo |
| 419 | s.focus = span.hi |
| 420 | } |
| 421 | } |
| 422 | |
| 423 | /** Semantic keyboard focus moves. See moveSelectionFocus in ink.tsx for |
| 424 | * how screen bounds + row-wrap are applied. */ |
no test coverage detected