private void press(Editable content, Object what) { int state = content.getSpanFlags(what); if (state == PRESSED) ; // repeat before use else if (state == RELEASED) content.setSpan(what, 0, 0, LOCKED); else if (state == USED) ; // repeat after use else if (state == LOCKED) content.removeSpan(what); else content.setSpan(what, 0, 0, PRESSED); }
public void setErrorLine(int errorLine) { Editable e = getEditableText(); for (ErrorLineSpan span : e.getSpans(0, e.length(), ErrorLineSpan.class)) e.removeSpan(span); final int start = getLayout().getLineStart(errorLine); final int end = getLayout().getLineEnd(errorLine); e.setSpan(new ErrorLineSpan(errorLine), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }
private void release(Editable content, Object what) { int current = content.getSpanFlags(what); if (current == USED) content.removeSpan(what); else if (current == PRESSED) content.setSpan(what, 0, 0, RELEASED); }
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) { int selStart, selEnd; int pref = 0; if (view != null) { pref = TextKeyListener.getInstance().getPrefs(view.getContext()); } { int a = Selection.getSelectionStart(content); int b = Selection.getSelectionEnd(content); selStart = Math.min(a, b); selEnd = Math.max(a, b); } int activeStart = content.getSpanStart(TextKeyListener.ACTIVE); int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE); // now for the multitap cases... // Try to increment the character we were working on before // if we have one and it's still the same key. int rec = (content.getSpanFlags(TextKeyListener.ACTIVE) & Spannable.SPAN_USER) >>> Spannable.SPAN_USER_SHIFT; if (activeStart == selStart && activeEnd == selEnd && selEnd - selStart == 1 && rec >= 0 && rec < sRecs.size()) { if (keyCode == KeyEvent.KEYCODE_STAR) { char current = content.charAt(selStart); if (Character.isLowerCase(current)) { content.replace(selStart, selEnd, String.valueOf(current).toUpperCase()); removeTimeouts(content); new Timeout(content); // for its side effects return true; } if (Character.isUpperCase(current)) { content.replace(selStart, selEnd, String.valueOf(current).toLowerCase()); removeTimeouts(content); new Timeout(content); // for its side effects return true; } } if (sRecs.indexOfKey(keyCode) == rec) { String val = sRecs.valueAt(rec); char ch = content.charAt(selStart); int ix = val.indexOf(ch); if (ix >= 0) { ix = (ix + 1) % (val.length()); content.replace(selStart, selEnd, val, ix, ix + 1); removeTimeouts(content); new Timeout(content); // for its side effects return true; } } // Is this key one we know about at all? If so, acknowledge // that the selection is our fault but the key has changed // or the text no longer matches, so move the selection over // so that it inserts instead of replaces. rec = sRecs.indexOfKey(keyCode); if (rec >= 0) { Selection.setSelection(content, selEnd, selEnd); selStart = selEnd; } } else { rec = sRecs.indexOfKey(keyCode); } if (rec >= 0) { // We have a valid key. Replace the selection or insertion point // with the first character for that key, and remember what // record it came from for next time. String val = sRecs.valueAt(rec); int off = 0; if ((pref & TextKeyListener.AUTO_CAP) != 0 && TextKeyListener.shouldCap(mCapitalize, content, selStart)) { for (int i = 0; i < val.length(); i++) { if (Character.isUpperCase(val.charAt(i))) { off = i; break; } } } if (selStart != selEnd) { Selection.setSelection(content, selEnd); } content.setSpan(OLD_SEL_START, selStart, selStart, Spannable.SPAN_MARK_MARK); content.replace(selStart, selEnd, val, off, off + 1); int oldStart = content.getSpanStart(OLD_SEL_START); selEnd = Selection.getSelectionEnd(content); if (selEnd != oldStart) { Selection.setSelection(content, oldStart, selEnd); content.setSpan( TextKeyListener.LAST_TYPED, oldStart, selEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); content.setSpan( TextKeyListener.ACTIVE, oldStart, selEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | (rec << Spannable.SPAN_USER_SHIFT)); } removeTimeouts(content); new Timeout(content); // for its side effects // Set up the callback so we can remove the timeout if the // cursor moves. if (content.getSpanStart(this) < 0) { KeyListener[] methods = content.getSpans(0, content.length(), KeyListener.class); for (Object method : methods) { content.removeSpan(method); } content.setSpan(this, 0, content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } return true; } return super.onKeyDown(view, content, keyCode, event); }
private void highlight(int offsetCharStart, int offsetCharEnd) { Editable e = getEditableText(); CharSequence textToHighlight = e.subSequence(offsetCharStart, offsetCharEnd); { // numbers Matcher m = numbers.matcher(textToHighlight); while (m.find()) e.setSpan( new ForegroundColorSpan(COLOR_NUMBER), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } { // keywords Matcher m = keywords.matcher(textToHighlight); while (m.find()) e.setSpan( new ForegroundColorSpan(COLOR_KEYWORD), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } { // builtins Matcher m = builtins.matcher(textToHighlight); while (m.find()) e.setSpan( new ForegroundColorSpan(COLOR_BUILTIN), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } { // symbols Matcher m = symbols.matcher(textToHighlight); while (m.find()) e.setSpan( new ForegroundColorSpan(COLOR_SYMBOL), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } { // macros Matcher m = macros.matcher(textToHighlight); while (m.find()) { e.setSpan( new ForegroundColorSpan(COLOR_MACROS), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } { // comments Matcher m = comments.matcher(textToHighlight); while (m.find()) { e.setSpan( new ForegroundColorSpan(COLOR_COMMENT), offsetCharStart + m.start(), offsetCharStart + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } }