VisualPosition (Point p) { int line = yPositionToVisibleLineNumber(p.y); int x = 0; int offset = logicalPositionToOffset(visualToLogicalPosition(new VisualPosition(line, 0))); int textLength = myDocument.getTextLength(); if (offset >= textLength) return new VisualPosition(line, 0); int column = 0; int prevX = 0; CharSequence text = myDocument.getCharsNoThreadCheck(); char c = ' '; IterationState state = new IterationState(this, offset, false); int fontType = state.getMergedAttributes().getFontType(); int spaceSize = getSpaceWidth(fontType); outer: while (true) { if (offset >= textLength) break; if (offset >= state.getEndOffset()) { state.advance(); fontType = state.getMergedAttributes().getFontType(); } FoldRegion region = state.getCurrentFold(); if (region != null) { char[] placeholder = region.getPlaceholderText().toCharArray(); for (int j = 0; j < placeholder.length; j++) { c = placeholder[j]; x += charWidth(fontType, c); if (x >= p.x) break outer; column++; } offset = region.getEndOffset(); } else { prevX = x; c = text.charAt(offset); if (c == '\n') { break; } if (c == '\t') { x = nextTabStop(x); } else { x += charWidth(fontType, c); } if (x >= p.x) break; if (c == '\t') { column += (x - prevX) / spaceSize; } else { column++; } offset++; } } int charWidth = charWidth(fontType, c); if (x >= p.x && c == '\t') { if (mySettings.isCaretInsideTabs()) { column += (p.x - prevX) / spaceSize; if ((p.x - prevX) % spaceSize > spaceSize / 2) column++; } else { if ((x - p.x) * 2 < x - prevX) { column += (x - prevX) / spaceSize; } } } else { if (x >= p.x) { if ((x - p.x) * 2 < charWidth) column++; } else { column += (p.x - x) / getSpaceWidth(fontType); } } return new VisualPosition(line, column); }