private int wrapPositionForTabbedTextWithOptimization( @NotNull CharSequence text, int tabSize, int startLineOffset, int endLineOffset, int targetRangeEndOffset) { int width = 0; int symbolWidth; int result = Integer.MAX_VALUE; boolean wrapLine = false; for (int i = startLineOffset; i < Math.min(endLineOffset, targetRangeEndOffset); i++) { char c = text.charAt(i); switch (c) { case '\t': symbolWidth = tabSize - (width % tabSize); break; default: symbolWidth = 1; } if (width + symbolWidth + FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS >= mySettings.RIGHT_MARGIN && (Math.min(endLineOffset, targetRangeEndOffset) - i) >= FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS) { // Remember preferred position. result = i - 1; } if (width + symbolWidth >= mySettings.RIGHT_MARGIN) { wrapLine = true; break; } width += symbolWidth; } return wrapLine ? result : -1; }
private int wrapPositionForTabbedTextWithoutOptimization( @NotNull Editor editor, @NotNull CharSequence text, int spaceSize, int startLineOffset, int endLineOffset, int targetRangeEndOffset) { int width = 0; int x = 0; int newX; int symbolWidth; int result = Integer.MAX_VALUE; boolean wrapLine = false; for (int i = startLineOffset; i < Math.min(endLineOffset, targetRangeEndOffset); i++) { char c = text.charAt(i); switch (c) { case '\t': newX = EditorUtil.nextTabStop(x, editor); int diffInPixels = newX - x; symbolWidth = diffInPixels / spaceSize; if (diffInPixels % spaceSize > 0) { symbolWidth++; } break; default: newX = x + EditorUtil.charWidth(c, Font.PLAIN, editor); symbolWidth = 1; } if (width + symbolWidth + FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS >= mySettings.RIGHT_MARGIN && (Math.min(endLineOffset, targetRangeEndOffset) - i) >= FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS) { result = i - 1; } if (width + symbolWidth >= mySettings.RIGHT_MARGIN) { wrapLine = true; break; } x = newX; width += symbolWidth; } return wrapLine ? result : -1; }
/** * Checks if it's worth to try to wrap target line (it's long enough) and tries to calculate * preferred wrap position. * * @param editor target editor * @param text text contained at the given editor * @param tabSize tab space to use (number of visual columns occupied by a tab) * @param spaceSize space width in pixels * @param startLineOffset start offset of the text line to process * @param endLineOffset end offset of the text line to process * @param targetRangeEndOffset target text region's end offset * @return negative value if no wrapping should be performed for the target line; preferred wrap * position otherwise */ private int calculatePreferredWrapPosition( @NotNull Editor editor, @NotNull CharSequence text, int tabSize, int spaceSize, int startLineOffset, int endLineOffset, int targetRangeEndOffset) { boolean hasTabs = false; boolean canOptimize = true; boolean hasNonSpaceSymbols = false; loop: for (int i = startLineOffset; i < Math.min(endLineOffset, targetRangeEndOffset); i++) { char c = text.charAt(i); switch (c) { case '\t': { hasTabs = true; if (hasNonSpaceSymbols) { canOptimize = false; break loop; } } case ' ': break; default: hasNonSpaceSymbols = true; } } if (!hasTabs) { return wrapPositionForTextWithoutTabs(startLineOffset, endLineOffset, targetRangeEndOffset); } else if (canOptimize) { return wrapPositionForTabbedTextWithOptimization( text, tabSize, startLineOffset, endLineOffset, targetRangeEndOffset); } else { return wrapPositionForTabbedTextWithoutOptimization( editor, text, spaceSize, startLineOffset, endLineOffset, targetRangeEndOffset); } }