+ public void addChar(final int ch) {
+ if (screenPosition < getDisplayLength() - 1) {
+ rawText.insert(position, Character.toChars(ch));
+ } else {
+ rawText.append(Character.toChars(ch));
+ }
+ position += Character.charCount(ch);
+ screenPosition += StringUtils.width(ch);
+ scanLine();
+ }
+
+ /**
+ * Replace a character at the cursor.
+ *
+ * @param ch the character to replace
+ */
+ public void replaceChar(final int ch) {
+ if (screenPosition < getDisplayLength() - 1) {
+ // Replace character
+ String oldText = rawText.toString();
+ rawText = new StringBuilder(oldText.substring(0, position));
+ rawText.append(Character.toChars(ch));
+ rawText.append(oldText.substring(position + 1));
+ screenPosition += StringUtils.width(rawText.codePointAt(position));
+ position += Character.charCount(ch);
+ } else {
+ rawText.append(Character.toChars(ch));
+ position += Character.charCount(ch);
+ screenPosition += StringUtils.width(ch);
+ }
+ scanLine();
+ }
+
+ /**
+ * Determine string position from screen position.
+ *
+ * @param screenPosition the position on screen
+ * @return the equivalent position in text
+ */
+ private int screenToTextPosition(final int screenPosition) {
+ if (screenPosition == 0) {
+ return 0;
+ }
+
+ int n = 0;
+ for (int i = 0; i < rawText.length(); i++) {
+ n += StringUtils.width(rawText.codePointAt(i));
+ if (n >= screenPosition) {
+ return i + 1;
+ }
+ }
+ // screenPosition exceeds the available text length.
+ throw new IndexOutOfBoundsException("screenPosition " + screenPosition +
+ " exceeds available text length " + rawText.length());
+ }
+
+ /**
+ * Trim trailing whitespace from line, repositioning cursor if needed.
+ */
+ public void trimRight() {
+ if (rawText.length() == 0) {
+ return;
+ }
+ if (!Character.isWhitespace(rawText.charAt(rawText.length() - 1))) {
+ return;
+ }
+ while ((rawText.length() > 0)
+ && Character.isWhitespace(rawText.charAt(rawText.length() - 1))
+ ) {
+ rawText.deleteCharAt(rawText.length() - 1);
+ }
+ if (position >= rawText.length()) {
+ end();
+ }
+ scanLine();
+ }
+
+ /**
+ * Handle the tab character.
+ *
+ * @param tabSize the tab stop size
+ */
+ public void tab(final int tabSize) {
+ if (tabSize > 0) {
+ do {
+ addChar(' ');
+ } while ((screenPosition % tabSize) != 0);
+ }
+ }
+
+ /**
+ * Handle the backtab (shift-tab) character.
+ *
+ * @param tabSize the tab stop size
+ */
+ public void backTab(final int tabSize) {
+ if ((tabSize > 0) && (screenPosition > 0)
+ && (rawText.charAt(position - 1) == ' ')
+ ) {
+ do {
+ backspace(tabSize, false);
+ } while (((screenPosition % tabSize) != 0)
+ && (screenPosition > 0)
+ && (rawText.charAt(position - 1) == ' '));
+ }