String (String text, List<? extends CaretState> states) { if (states.isEmpty()) return text; record Point(int x, int y) { static Point from(LogicalPosition pos) { return new Point(pos.column, pos.line); } } Map<Point, String> tags = new HashMap<>(); for (int i = 0; i < states.size(); i++) { CaretState state = states.get(i); LogicalPosition caretPosition = state.getCaretPosition(); if (caretPosition != null) { tags.merge(Point.from(caretPosition), "\0c" + i + "\0", String::concat); } LogicalPosition selectionStart = state.getSelectionStart(); if (selectionStart != null) { tags.merge(Point.from(selectionStart), "\0s" + i + "\0", String::concat); } LogicalPosition selectionEnd = state.getSelectionEnd(); if (selectionEnd != null) { tags.merge(Point.from(selectionEnd), "\0e" + i + "\0", String::concat); } } StringBuilder builder = new StringBuilder(text.length() + tags.values().stream().mapToInt(String::length).sum()); int x = 0; int y = 0; for (int i = 0; i < text.length(); i++) { builder.append(tags.getOrDefault(new Point(x, y), "")); char c = text.charAt(i); if (c == '\n') { y++; x = 0; } else { x++; } builder.append(c); } return builder.toString(); }