/** * Converts an offset in a line into an x co-ordinate. This is a fast version that should only be * used if no changes were made to the text since the last repaint. * * @param line The line * @param offset The offset, from the start of the line */ public int _offsetToX(int line, int offset) { TokenMarker tokenMarker = getTokenMarker(); /* Use painter's cached info for speed */ FontMetrics fm = painter.getFontMetrics(); getLineText(line, lineSegment); int segmentOffset = lineSegment.offset; int x = horizontalOffset; /* If syntax coloring is disabled, do simple translation */ if (tokenMarker == null) { lineSegment.count = offset; return x + Utilities.getTabbedTextWidth(lineSegment, fm, x, painter, 0); } /* If syntax coloring is enabled, we have to do this because * tokens can vary in width */ else { Token tokens; if (painter.currentLineIndex == line && painter.currentLineTokens != null) tokens = painter.currentLineTokens; else { painter.currentLineIndex = line; tokens = painter.currentLineTokens = tokenMarker.markTokens(lineSegment, line); } Toolkit toolkit = painter.getToolkit(); Font defaultFont = painter.getFont(); SyntaxStyle[] styles = painter.getStyles(); for (; ; ) { byte id = tokens.id; if (id == Token.END) { return x; } if (id == Token.NULL) fm = painter.getFontMetrics(); else fm = styles[id].getFontMetrics(defaultFont); int length = tokens.length; if (offset + segmentOffset < lineSegment.offset + length) { lineSegment.count = offset - (lineSegment.offset - segmentOffset); return x + Utilities.getTabbedTextWidth(lineSegment, fm, x, painter, 0); } else { lineSegment.count = length; x += Utilities.getTabbedTextWidth(lineSegment, fm, x, painter, 0); lineSegment.offset += length; } tokens = tokens.next; } } }
/** * Converts an x co-ordinate to an offset within a line. * * @param line The line * @param x The x co-ordinate */ public int xToOffset(int line, int x) { TokenMarker tokenMarker = getTokenMarker(); /* Use painter's cached info for speed */ FontMetrics fm = painter.getFontMetrics(); getLineText(line, lineSegment); char[] segmentArray = lineSegment.array; int segmentOffset = lineSegment.offset; int segmentCount = lineSegment.count; int width = horizontalOffset; if (tokenMarker == null) { for (int i = 0; i < segmentCount; i++) { char c = segmentArray[i + segmentOffset]; int charWidth; if (c == '\t') charWidth = (int) painter.nextTabStop(width, i) - width; else charWidth = fm.charWidth(c); if (painter.isBlockCaretEnabled()) { if (x - charWidth <= width) return i; } else { if (x - charWidth / 2 <= width) return i; } width += charWidth; } return segmentCount; } else { Token tokens; if (painter.currentLineIndex == line && painter.currentLineTokens != null) tokens = painter.currentLineTokens; else { painter.currentLineIndex = line; tokens = painter.currentLineTokens = tokenMarker.markTokens(lineSegment, line); } int offset = 0; Toolkit toolkit = painter.getToolkit(); Font defaultFont = painter.getFont(); SyntaxStyle[] styles = painter.getStyles(); for (; ; ) { byte id = tokens.id; if (id == Token.END) return offset; if (id == Token.NULL) fm = painter.getFontMetrics(); else fm = styles[id].getFontMetrics(defaultFont); int length = tokens.length; for (int i = 0; i < length; i++) { char c = segmentArray[segmentOffset + offset + i]; int charWidth; if (c == '\t') charWidth = (int) painter.nextTabStop(width, offset + i) - width; else charWidth = fm.charWidth(c); if (painter.isBlockCaretEnabled()) { if (x - charWidth <= width) return offset + i; } else { if (x - charWidth / 2 <= width) return offset + i; } width += charWidth; } offset += length; tokens = tokens.next; } } }