/**
* Background character for unfilled-in text.
*/
- protected char backgroundChar = GraphicsChars.HATCH;
+ protected int backgroundChar = GraphicsChars.HATCH;
/**
* Field text.
if (keypress.equals(kbLeft)) {
if (position > 0) {
- if (position < text.length()) {
- screenPosition -= StringUtils.width(text.charAt(position));
+ if (position < codePointLength(text)) {
+ screenPosition -= StringUtils.width(text.codePointBefore(position));
+ position -= Character.charCount(text.codePointBefore(position));
} else {
screenPosition--;
+ position--;
}
- position--;
}
if (fixed == false) {
if ((screenPosition == windowStart) && (windowStart > 0)) {
- windowStart -= StringUtils.width(text.charAt(
+ windowStart -= StringUtils.width(text.codePointAt(
screenToTextPosition(windowStart)));
}
}
}
if (keypress.equals(kbRight)) {
- if (position < text.length()) {
- screenPosition += StringUtils.width(text.charAt(position));
- position++;
+ if (position < codePointLength(text)) {
+ screenPosition += StringUtils.width(text.codePointAt(position));
+ position += Character.charCount(text.codePointAt(position));
if (fixed == true) {
if (screenPosition == getWidth()) {
screenPosition--;
- position--;
+ position -= Character.charCount(text.codePointAt(position));
}
} else {
if ((screenPosition - windowStart) >= getWidth()) {
- windowStart += StringUtils.width(text.charAt(
+ windowStart += StringUtils.width(text.codePointAt(
screenToTextPosition(windowStart)));
}
}
}
if (keypress.equals(kbDel)) {
- if ((text.length() > 0) && (position < text.length())) {
+ if ((codePointLength(text) > 0) && (position < codePointLength(text))) {
text = text.substring(0, position)
+ text.substring(position + 1);
screenPosition = StringUtils.width(text.substring(0, position));
if (keypress.equals(kbBackspace) || keypress.equals(kbBackspaceDel)) {
if (position > 0) {
- position--;
+ position -= Character.charCount(text.codePointBefore(position));
text = text.substring(0, position)
+ text.substring(position + 1);
screenPosition = StringUtils.width(text.substring(0, position));
if ((screenPosition >= windowStart)
&& (windowStart > 0)
) {
- windowStart -= StringUtils.width(text.charAt(
+ windowStart -= StringUtils.width(text.codePointAt(
screenToTextPosition(windowStart)));
}
}
&& !keypress.getKey().isCtrl()
) {
// Plain old keystroke, process it
- if ((position == text.length())
+ if ((position == codePointLength(text))
&& (StringUtils.width(text) < getWidth())) {
// Append case
appendChar(keypress.getKey().getChar());
- } else if ((position < text.length())
+ } else if ((position < codePointLength(text))
&& (StringUtils.width(text) < getWidth())) {
// Overwrite or insert a character
if (insertMode == false) {
// Replace character
text = text.substring(0, position)
- + keypress.getKey().getChar()
+ + codePointString(keypress.getKey().getChar())
+ text.substring(position + 1);
- screenPosition += StringUtils.width(text.charAt(position));
- position++;
+ screenPosition += StringUtils.width(text.codePointAt(position));
+ position += Character.charCount(keypress.getKey().getChar());
} else {
// Insert character
insertChar(keypress.getKey().getChar());
}
- } else if ((position < text.length())
+ } else if ((position < codePointLength(text))
&& (StringUtils.width(text) >= getWidth())) {
// Multiple cases here
} else if ((fixed == true) && (insertMode == false)) {
// Overwrite the last character, maybe move position
text = text.substring(0, position)
- + keypress.getKey().getChar()
+ + codePointString(keypress.getKey().getChar())
+ text.substring(position + 1);
if (screenPosition < getWidth() - 1) {
- screenPosition += StringUtils.width(text.charAt(position));
- position++;
+ screenPosition += StringUtils.width(text.codePointAt(position));
+ position += Character.charCount(keypress.getKey().getChar());
}
} else if ((fixed == false) && (insertMode == false)) {
// Overwrite the last character, definitely move position
text = text.substring(0, position)
- + keypress.getKey().getChar()
+ + codePointString(keypress.getKey().getChar())
+ text.substring(position + 1);
- screenPosition += StringUtils.width(text.charAt(position));
- position++;
+ screenPosition += StringUtils.width(text.codePointAt(position));
+ position += Character.charCount(keypress.getKey().getChar());
} else {
- if (position == text.length()) {
+ if (position == codePointLength(text)) {
// Append this character
appendChar(keypress.getKey().getChar());
} else {
// TField -----------------------------------------------------------------
// ------------------------------------------------------------------------
+ /**
+ * Convert a char (codepoint) to a string.
+ *
+ * @param ch the char
+ * @return the string
+ */
+ private String codePointString(final int ch) {
+ StringBuilder sb = new StringBuilder(1);
+ sb.append(Character.toChars(ch));
+ return sb.toString();
+ }
+
+ /**
+ * Get the number of codepoints in a string.
+ *
+ * @param str the string
+ * @return the number of codepoints
+ */
+ private int codePointLength(final String str) {
+ return str.codePointCount(0, str.length());
+ }
+
/**
* Get field background character.
*
* @return background character
*/
- public final char getBackgroundChar() {
+ public final int getBackgroundChar() {
return backgroundChar;
}
*
* @param backgroundChar the background character
*/
- public void setBackgroundChar(final char backgroundChar) {
+ public void setBackgroundChar(final int backgroundChar) {
this.backgroundChar = backgroundChar;
}
}
int n = 0;
- for (int i = 0; i < text.length(); i++) {
- n += StringUtils.width(text.charAt(i));
+ for (int i = 0; i < codePointLength(text); i++) {
+ n += StringUtils.width(text.codePointAt(i));
if (n >= screenPosition) {
return i + 1;
}
}
// screenPosition exceeds the available text length.
throw new IndexOutOfBoundsException("screenPosition " + screenPosition +
- " exceeds available text length " + text.length());
+ " exceeds available text length " + codePointLength(text));
}
/**
/**
* Append char to the end of the field.
*
- * @param ch = char to append
+ * @param ch char to append
*/
- protected void appendChar(final char ch) {
+ protected void appendChar(final int ch) {
// Append the LAST character
- text += ch;
- position++;
+ text += codePointString(ch);
+ position += Character.charCount(ch);
screenPosition += StringUtils.width(ch);
- assert (position == text.length());
+ assert (position == codePointLength(text));
if (fixed) {
if (screenPosition >= getWidth()) {
- position--;
+ position -= Character.charCount(ch);
screenPosition -= StringUtils.width(ch);
}
} else {
*
* @param ch char to append
*/
- protected void insertChar(final char ch) {
- text = text.substring(0, position) + ch + text.substring(position);
- position++;
+ protected void insertChar(final int ch) {
+ text = text.substring(0, position) + codePointString(ch)
+ + text.substring(position);
+ position += Character.charCount(ch);
screenPosition += StringUtils.width(ch);
if ((screenPosition - windowStart) == getWidth()) {
assert (!fixed);
* adjust the window start to show as much of the field as possible.
*/
public void end() {
- position = text.length();
+ position = codePointLength(text);
screenPosition = StringUtils.width(text);
if (fixed == true) {
if (screenPosition >= getWidth()) {
- position = text.length() - 1;
+ position = codePointLength(text) - 1;
screenPosition = StringUtils.width(text) - 1;
}
} else {
* the available text
*/
public void setPosition(final int position) {
- if ((position < 0) || (position >= text.length())) {
+ if ((position < 0) || (position >= codePointLength(text))) {
throw new IndexOutOfBoundsException("Max length is " +
- StringUtils.width(text) + ", requested position " + position);
+ codePointLength(text) + ", requested position " + position);
}
this.position = position;
normalizeWindowStart();