diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Editor.cxx | 111 | ||||
-rw-r--r-- | src/PositionCache.cxx | 44 | ||||
-rw-r--r-- | src/PositionCache.h | 3 |
3 files changed, 80 insertions, 78 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 0f0eed80b..7802061f2 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -477,36 +477,17 @@ Point Editor::LocationFromPosition(SelectionPosition pos) { RefreshStyleData(); if (pos.Position() == INVALID_POSITION) return pt; - int line = pdoc->LineFromPosition(pos.Position()); - int lineVisible = cs.DisplayFromDoc(line); + const int line = pdoc->LineFromPosition(pos.Position()); + const int lineVisible = cs.DisplayFromDoc(line); //Platform::DebugPrintf("line=%d\n", line); AutoSurface surface(this); AutoLineLayout ll(llc, RetrieveLineLayout(line)); if (surface && ll) { - // -1 because of adding in for visible lines in following loop. - pt.y = (lineVisible - topLine - 1) * vs.lineHeight; - pt.x = 0; - unsigned int posLineStart = pdoc->LineStart(line); + const int posLineStart = pdoc->LineStart(line); LayoutLine(line, surface, vs, ll, wrapWidth); - int posInLine = pos.Position() - posLineStart; - // In case of very long line put x at arbitrary large position - if (posInLine > ll->maxLineLength) { - pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)]; - } - - for (int subLine = 0; subLine < ll->lines; subLine++) { - if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { - pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)]; - if (ll->wrapIndent != 0) { - int lineStart = ll->LineStart(subLine); - if (lineStart != 0) // Wrapped - pt.x += ll->wrapIndent; - } - } - if (posInLine >= ll->LineStart(subLine)) { - pt.y += vs.lineHeight; - } - } + const int posInLine = pos.Position() - posLineStart; + pt = ll->PointFromPosition(posInLine, vs.lineHeight); + pt.y += (lineVisible - topLine) * vs.lineHeight; pt.x += vs.textStart - xOffset; } pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; @@ -558,58 +539,44 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, int visibleLine = floor(pt.y / vs.lineHeight); if (!canReturnInvalid && (visibleLine < 0)) visibleLine = 0; - int lineDoc = cs.DocFromDisplay(visibleLine); + const int lineDoc = cs.DocFromDisplay(visibleLine); if (canReturnInvalid && (lineDoc < 0)) return SelectionPosition(INVALID_POSITION); if (lineDoc >= pdoc->LinesTotal()) return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length()); - unsigned int posLineStart = pdoc->LineStart(lineDoc); - SelectionPosition retVal(canReturnInvalid ? INVALID_POSITION : static_cast<int>(posLineStart)); + const int posLineStart = pdoc->LineStart(lineDoc); AutoSurface surface(this); AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); if (surface && ll) { LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - int lineStartSet = cs.DisplayFromDoc(lineDoc); - int subLine = visibleLine - lineStartSet; + const int lineStartSet = cs.DisplayFromDoc(lineDoc); + const int subLine = visibleLine - lineStartSet; if (subLine < ll->lines) { - int lineStart = ll->LineStart(subLine); - int lineEnd = ll->LineLastVisible(subLine); - XYPOSITION subLineStart = ll->positions[lineStart]; - - if (ll->wrapIndent != 0) { - if (lineStart != 0) // Wrapped - pt.x -= ll->wrapIndent; - } - int i = ll->FindBefore(pt.x + subLineStart, lineStart, lineEnd); - while (i < lineEnd) { - if (charPosition) { - if ((pt.x + subLineStart) < (ll->positions[i + 1])) { - return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1)); - } - } else { - if ((pt.x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) { - return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1)); - } - } - i++; + const Range rangeSubLine = ll->SubLineRange(subLine); + const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; + if (subLine > 0) // Wrapped + pt.x -= ll->wrapIndent; + const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); + if (positionInLine < rangeSubLine.end) { + return SelectionPosition(pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); } if (virtualSpace) { const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / + const int spaceOffset = (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth; - return SelectionPosition(lineEnd + posLineStart, spaceOffset); + return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); } else if (canReturnInvalid) { - if (pt.x < (ll->positions[lineEnd] - subLineStart)) { - return SelectionPosition(pdoc->MovePositionOutsideChar(lineEnd + posLineStart, 1)); + if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { + return SelectionPosition(pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); } } else { - return SelectionPosition(lineEnd + posLineStart); + return SelectionPosition(rangeSubLine.end + posLineStart); } } if (!canReturnInvalid) return SelectionPosition(ll->numCharsInLine + posLineStart); } - return retVal; + return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); } int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) { @@ -619,6 +586,7 @@ int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosit /** * Find the document position corresponding to an x coordinate on a particular document line. * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. + * This method is used for rectangular selections and does not work on wrapped lines. */ SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) { RefreshStyleData(); @@ -627,33 +595,20 @@ SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) { //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); AutoSurface surface(this); AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); - int retVal = 0; if (surface && ll) { - unsigned int posLineStart = pdoc->LineStart(lineDoc); + const int posLineStart = pdoc->LineStart(lineDoc); LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - int subLine = 0; - int lineStart = ll->LineStart(subLine); - int lineEnd = ll->LineLastVisible(subLine); - XYPOSITION subLineStart = ll->positions[lineStart]; - XYPOSITION newX = x; - - if (ll->wrapIndent != 0) { - if (lineStart != 0) // Wrapped - newX -= ll->wrapIndent; - } - int i = ll->FindBefore(newX + subLineStart, lineStart, lineEnd); - while (i < lineEnd) { - if ((newX + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) { - retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1); - return SelectionPosition(retVal); - } - i++; + const Range rangeSubLine = ll->SubLineRange(0); + const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; + const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); + if (positionInLine < rangeSubLine.end) { + return SelectionPosition(pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); } const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - int spaceOffset = (newX + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth; - return SelectionPosition(lineEnd + posLineStart, spaceOffset); + const int spaceOffset = (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth; + return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); } - return SelectionPosition(retVal); + return SelectionPosition(0); } int Editor::PositionFromLineX(int lineDoc, int x) { diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index db64b1160..90a3f02f0 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -132,6 +132,10 @@ int LineLayout::LineLastVisible(int line) const { } } +Range LineLayout::SubLineRange(int subLine) const { + return Range(LineStart(subLine), LineLastVisible(subLine)); +} + bool LineLayout::InLine(int offset, int line) const { return ((offset >= LineStart(line)) && (offset < LineStart(line + 1))) || ((offset == numCharsInLine) && (line == (lines-1))); @@ -205,6 +209,46 @@ int LineLayout::FindBefore(XYPOSITION x, int lower, int upper) const { return lower; } + +int LineLayout::FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const { + int pos = FindBefore(x, range.start, range.end); + while (pos < range.end) { + if (charPosition) { + if (x < (positions[pos + 1])) { + return pos; + } + } else { + if (x < ((positions[pos] + positions[pos + 1]) / 2)) { + return pos; + } + } + pos++; + } + return range.end; +} + +Point LineLayout::PointFromPosition(int posInLine, int lineHeight) const { + Point pt; + // In case of very long line put x at arbitrary large position + if (posInLine > maxLineLength) { + pt.x = positions[maxLineLength] - positions[LineStart(lines)]; + } + + for (int subLine = 0; subLine < lines; subLine++) { + const Range rangeSubLine = SubLineRange(subLine); + if (posInLine >= rangeSubLine.start) { + pt.y = subLine*lineHeight; + if (posInLine <= rangeSubLine.end) { + pt.x = positions[posInLine] - positions[rangeSubLine.start]; + if (rangeSubLine.start != 0) // Wrapped lines may be indented + pt.x += wrapIndent; + break; + } + } + } + return pt; +} + int LineLayout::EndLineStyle() const { return styles[numCharsBeforeEOL > 0 ? numCharsBeforeEOL-1 : 0]; } diff --git a/src/PositionCache.h b/src/PositionCache.h index 2b4223769..871bb6e46 100644 --- a/src/PositionCache.h +++ b/src/PositionCache.h @@ -60,12 +60,15 @@ public: void Invalidate(validLevel validity_); int LineStart(int line) const; int LineLastVisible(int line) const; + Range SubLineRange(int line) const; bool InLine(int offset, int line) const; void SetLineStart(int line, int start); void SetBracesHighlight(Range rangeLine, Position braces[], char bracesMatchStyle, int xHighlight, bool ignoreStyle); void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle); int FindBefore(XYPOSITION x, int lower, int upper) const; + int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const; + Point PointFromPosition(int posInLine, int lineHeight) const; int EndLineStyle() const; }; |