mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-13 06:50:39 -08:00
* java/org/gnu/emacs/EmacsCursor.java (EmacsCursor): * java/org/gnu/emacs/EmacsGC.java (EmacsGC): * java/org/gnu/emacs/EmacsHandleObject.java (EmacsHandleObject): Remove HANDLE argument to constructor. * java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): * java/org/gnu/emacs/EmacsInputConnection.java (EmacsInputConnection) <windowHandle>: Change type to long. * java/org/gnu/emacs/EmacsNative.java (EmacsNative) (sendConfigureNotify, sendKeyPress, sendKeyRelease, sendFocusIn) (sendFocusOut, sendWindowAction, sendEnterNotify) (sendLeaveNotify, sendMotionNotify, sendButtonPress) (sendButtonRelease, sendTouchDown, sendTouchUp, sendTouchMove) (sendWheel, sendIconified, sendDeiconified, sendContextMenu) (sendExpose, sendDndDrag, sendDndUri, sendDndText) (beginBatchEdit, commitCompletion, endBatchEdit, commitText) (deleteSurroundingText, finishComposingText, replaceText) (getSelectedText, getTextAfterCursor, getTextBeforeCursor) (setComposingText, setComposingRegion, setSelection) (performEditorAction, performContextMenuAction, getExtractedText) (requestSelectionUpdate, requestCursorUpdates, clearInputFlags) (getSurroundingText, takeSnapshot, getSelection): Accept handles as longs, rather than shorts. All callers changed. * java/org/gnu/emacs/EmacsService.java (queryTree): Return handles as longs rather than shorts. (viewGetSelection): Take long WINDOW, not short. * src/android.c (struct android_emacs_handle): New structure. (handle_class): New variable. (android_init_emacs_service, android_init_emacs_pixmap) (android_init_emacs_gc_class, android_init_emacs_cursor): Adjust to match signature changes in constructors. (android_init_emacs_handle): New function. (initEmacs): Initialize the handle class, its fields and metods. (sendConfigureNotify, sendKeyPress, sendKeyRelease, sendFocusIn) (sendFocusOut, sendWindowAction, sendEnterNotify) (sendLeaveNotify, sendMotionNotify, sendButtonPress) (sendButtonRelease, sendTouchDown, sendTouchUp, sendTouchMove) (sendWheel, sendIconified, sendDeiconified, sendContextMenu) (sendExpose, sendDndDrag, sendDndUri, sendDndText): Update for changes to handle type. (android_alloc_id, android_resolve_handle) (android_resolve_handle2): Remove functions; replace the second with a macro that accepts one fewer argument. All callers changed. (android_destroy_handle): Cease indexing the handle list for the handle object. (android_globalize_reference): New function. (android_create_window, android_create_gc, android_create_pixmap) (android_create_font_cursor): Call android_globalize_reference to convert global references into handles. (android_free_cursor, android_destroy_window): Cease verifying the handle type. (android_copy_area): Check destination object type rather than handle entry. (android_query_tree): Adjust for changes to return types. (likely): Define __builtin_expect variant unconditionally. * src/android.h (android_resolve_handle): New macro. * src/androidgui.h (android_handle): Define to intptr_t. * src/androidterm.c (deleteSurroundingText, finishComposingText) (performEditorAction, performContextMenuAction, getExtractedText) (getSelectedText, requestSelectionUpdate, requestCursorUpdates) (clearInputFlags, getSurroundingText) (android_get_surrounding_text_internal): Accept handles as longs, not jshorts.
713 lines
17 KiB
Java
713 lines
17 KiB
Java
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||
|
||
Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||
|
||
This file is part of GNU Emacs.
|
||
|
||
GNU Emacs is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or (at
|
||
your option) any later version.
|
||
|
||
GNU Emacs is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||
|
||
package org.gnu.emacs;
|
||
|
||
import android.os.Build;
|
||
import android.os.Bundle;
|
||
import android.os.Handler;
|
||
|
||
import android.view.KeyEvent;
|
||
|
||
import android.view.inputmethod.CompletionInfo;
|
||
import android.view.inputmethod.CorrectionInfo;
|
||
import android.view.inputmethod.ExtractedText;
|
||
import android.view.inputmethod.ExtractedTextRequest;
|
||
import android.view.inputmethod.InputConnection;
|
||
import android.view.inputmethod.InputContentInfo;
|
||
import android.view.inputmethod.SurroundingText;
|
||
import android.view.inputmethod.TextAttribute;
|
||
import android.view.inputmethod.TextSnapshot;
|
||
|
||
import android.util.Log;
|
||
|
||
/* Android input methods, take number six. See textconv.c for more
|
||
details; this is more-or-less a thin wrapper around that file. */
|
||
|
||
public final class EmacsInputConnection implements InputConnection
|
||
{
|
||
private static final String TAG = "EmacsInputConnection";
|
||
|
||
/* View associated with this input connection. */
|
||
private EmacsView view;
|
||
|
||
/* The handle ID associated with that view's window. */
|
||
private long windowHandle;
|
||
|
||
/* Number of batch edits currently underway. Used to avoid
|
||
synchronizing with the Emacs thread after each
|
||
`endBatchEdit'. */
|
||
private int batchEditCount;
|
||
|
||
/* Whether or not to synchronize and call `updateIC' with the
|
||
selection position after committing text.
|
||
|
||
This helps with on screen keyboard programs found in some vendor
|
||
versions of Android, which rely on immediate updates to the point
|
||
position after text is committed in order to place the cursor
|
||
within that text. */
|
||
|
||
private static boolean syncAfterCommit;
|
||
|
||
/* Whether or not to return empty text with the offset set to zero
|
||
if a request arrives that has no flags set and has requested no
|
||
characters at all.
|
||
|
||
This is necessary with on screen keyboard programs found in some
|
||
vendor versions of Android which don't rely on the documented
|
||
meaning of `ExtractedText.startOffset', and instead take the
|
||
selection offset inside at face value. */
|
||
|
||
private static boolean extractAbsoluteOffsets;
|
||
|
||
static
|
||
{
|
||
if (Build.MANUFACTURER.equalsIgnoreCase ("Huawei")
|
||
|| Build.MANUFACTURER.equalsIgnoreCase ("Honor"))
|
||
extractAbsoluteOffsets = syncAfterCommit = true;
|
||
|
||
/* The Samsung and Vivo keyboards take `selectionStart' at face
|
||
value if some text is returned, and also searches for words
|
||
solely within that text. However, when no text is returned, it
|
||
falls back to getTextAfterCursor and getTextBeforeCursor. */
|
||
if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung")
|
||
|| Build.MANUFACTURER.equalsIgnoreCase ("Vivo"))
|
||
extractAbsoluteOffsets = true;
|
||
};
|
||
|
||
|
||
public
|
||
EmacsInputConnection (EmacsView view)
|
||
{
|
||
this.view = view;
|
||
this.windowHandle = view.window.handle;
|
||
}
|
||
|
||
|
||
/* The functions below are called by input methods whenever they
|
||
need to perform an edit. */
|
||
|
||
@Override
|
||
public boolean
|
||
beginBatchEdit ()
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "beginBatchEdit");
|
||
|
||
EmacsNative.beginBatchEdit (windowHandle);
|
||
|
||
/* Keep a record of the number of outstanding batch edits here as
|
||
well. */
|
||
batchEditCount++;
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
endBatchEdit ()
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "endBatchEdit");
|
||
|
||
EmacsNative.endBatchEdit (windowHandle);
|
||
|
||
/* Subtract one from the UI thread record of the number of batch
|
||
edits currently under way. */
|
||
|
||
if (batchEditCount > 0)
|
||
batchEditCount -= 1;
|
||
|
||
return batchEditCount > 0;
|
||
}
|
||
|
||
public boolean
|
||
commitCompletion (CompletionInfo info)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "commitCompletion: " + info);
|
||
|
||
EmacsNative.commitCompletion (windowHandle,
|
||
info.getText ().toString (),
|
||
info.getPosition ());
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
commitCorrection (CorrectionInfo info)
|
||
{
|
||
/* The input method calls this function not to commit text, but to
|
||
indicate that a subsequent edit will consist of a correction.
|
||
Emacs has no use for this information.
|
||
|
||
Of course this completely contradicts the provided
|
||
documentation, but this is how Android actually behaves. */
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
commitText (CharSequence text, int newCursorPosition)
|
||
{
|
||
int[] selection;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "commitText: " + text + " " + newCursorPosition);
|
||
|
||
EmacsNative.commitText (windowHandle, text.toString (),
|
||
newCursorPosition);
|
||
|
||
if (syncAfterCommit)
|
||
{
|
||
/* Synchronize with the Emacs thread, obtain the new
|
||
selection, and report it immediately. */
|
||
|
||
selection = EmacsNative.getSelection (windowHandle);
|
||
|
||
if (EmacsService.DEBUG_IC && selection != null)
|
||
Log.d (TAG, "commitText: new selection is " + selection[0]
|
||
+ ", by " + selection[1]);
|
||
|
||
if (selection != null)
|
||
/* N.B. that the composing region is removed after text is
|
||
committed. */
|
||
view.imManager.updateSelection (view, selection[0],
|
||
selection[1], -1, -1);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
commitText (CharSequence text, int newCursorPosition,
|
||
TextAttribute textAttribute)
|
||
{
|
||
return commitText (text, newCursorPosition);
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
deleteSurroundingText (int leftLength, int rightLength)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, ("deleteSurroundingText: "
|
||
+ leftLength + " " + rightLength));
|
||
|
||
EmacsNative.deleteSurroundingText (windowHandle, leftLength,
|
||
rightLength);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
deleteSurroundingTextInCodePoints (int leftLength, int rightLength)
|
||
{
|
||
/* Emacs returns characters which cannot be represented in a Java
|
||
`char' as NULL characters, so code points always reflect
|
||
characters themselves. */
|
||
return deleteSurroundingText (leftLength, rightLength);
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
finishComposingText ()
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "finishComposingText");
|
||
|
||
EmacsNative.finishComposingText (windowHandle);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public String
|
||
getSelectedText (int flags)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getSelectedText: " + flags);
|
||
|
||
return EmacsNative.getSelectedText (windowHandle, flags);
|
||
}
|
||
|
||
@Override
|
||
public String
|
||
getTextAfterCursor (int length, int flags)
|
||
{
|
||
String string;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getTextAfterCursor: " + length + " " + flags);
|
||
|
||
string = EmacsNative.getTextAfterCursor (windowHandle, length,
|
||
flags);
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, " --> " + string);
|
||
|
||
return string;
|
||
}
|
||
|
||
@Override
|
||
public String
|
||
getTextBeforeCursor (int length, int flags)
|
||
{
|
||
String string;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getTextBeforeCursor: " + length + " " + flags);
|
||
|
||
string = EmacsNative.getTextBeforeCursor (windowHandle, length,
|
||
flags);
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, " --> " + string);
|
||
|
||
return string;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setComposingText (CharSequence text, int newCursorPosition)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, ("setComposingText: "
|
||
+ text + " ## " + newCursorPosition));
|
||
|
||
EmacsNative.setComposingText (windowHandle, text.toString (),
|
||
newCursorPosition);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setComposingText (CharSequence text, int newCursorPosition,
|
||
TextAttribute textAttribute)
|
||
{
|
||
return setComposingText (text, newCursorPosition);
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setComposingRegion (int start, int end)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "setComposingRegion: " + start + " " + end);
|
||
|
||
EmacsNative.setComposingRegion (windowHandle, start, end);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setComposingRegion (int start, int end, TextAttribute textAttribute)
|
||
{
|
||
return setComposingRegion (start, end);
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
performEditorAction (int editorAction)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "performEditorAction: " + editorAction);
|
||
|
||
EmacsNative.performEditorAction (windowHandle, editorAction);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
performContextMenuAction (int contextMenuAction)
|
||
{
|
||
int action;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "performContextMenuAction: " + contextMenuAction);
|
||
|
||
/* Translate the action in Java code. That way, a great deal of
|
||
JNI boilerplate can be avoided. */
|
||
|
||
switch (contextMenuAction)
|
||
{
|
||
case android.R.id.selectAll:
|
||
action = 0;
|
||
break;
|
||
|
||
case android.R.id.startSelectingText:
|
||
action = 1;
|
||
break;
|
||
|
||
case android.R.id.stopSelectingText:
|
||
action = 2;
|
||
break;
|
||
|
||
case android.R.id.cut:
|
||
action = 3;
|
||
break;
|
||
|
||
case android.R.id.copy:
|
||
action = 4;
|
||
break;
|
||
|
||
case android.R.id.paste:
|
||
action = 5;
|
||
break;
|
||
|
||
default:
|
||
return true;
|
||
}
|
||
|
||
EmacsNative.performContextMenuAction (windowHandle, action);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public ExtractedText
|
||
getExtractedText (ExtractedTextRequest request, int flags)
|
||
{
|
||
ExtractedText text;
|
||
int[] selection;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getExtractedText: " + request.hintMaxChars + ", "
|
||
+ request.hintMaxLines + " " + flags);
|
||
|
||
/* If a request arrives with hintMaxChars, hintMaxLines and flags
|
||
set to 0, and the system is known to be buggy, return an empty
|
||
extracted text object with the absolute selection positions. */
|
||
|
||
if (extractAbsoluteOffsets
|
||
&& request.hintMaxChars == 0
|
||
&& request.hintMaxLines == 0
|
||
&& flags == 0)
|
||
{
|
||
/* Obtain the selection. */
|
||
selection = EmacsNative.getSelection (windowHandle);
|
||
if (selection == null)
|
||
return null;
|
||
|
||
/* Create the workaround extracted text. */
|
||
text = new ExtractedText ();
|
||
text.partialStartOffset = -1;
|
||
text.partialEndOffset = -1;
|
||
text.text = "";
|
||
text.selectionStart = selection[0];
|
||
text.selectionEnd = selection[1];
|
||
}
|
||
else
|
||
text = EmacsNative.getExtractedText (windowHandle, request,
|
||
flags);
|
||
|
||
if (text == null)
|
||
{
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getExtractedText: text is NULL");
|
||
|
||
return null;
|
||
}
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "getExtractedText: " + text.text + " @"
|
||
+ text.startOffset + ":" + text.selectionStart
|
||
+ ", " + text.selectionEnd);
|
||
|
||
return text;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setSelection (int start, int end)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "setSelection: " + start + " " + end);
|
||
|
||
EmacsNative.setSelection (windowHandle, start, end);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
/* ACTION_MULTIPLE is apparently obsolete. */
|
||
@SuppressWarnings ("deprecation")
|
||
public boolean
|
||
sendKeyEvent (KeyEvent key)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "sendKeyEvent: " + key);
|
||
|
||
/* Use the standard API if possible. */
|
||
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||
view.imManager.dispatchKeyEventFromInputMethod (view, key);
|
||
else
|
||
{
|
||
/* Fall back to dispatching the event manually if not. */
|
||
|
||
switch (key.getAction ())
|
||
{
|
||
case KeyEvent.ACTION_DOWN:
|
||
view.onKeyDown (key.getKeyCode (), key);
|
||
break;
|
||
|
||
case KeyEvent.ACTION_UP:
|
||
view.onKeyUp (key.getKeyCode (), key);
|
||
break;
|
||
|
||
case KeyEvent.ACTION_MULTIPLE:
|
||
view.onKeyMultiple (key.getKeyCode (),
|
||
key.getRepeatCount (),
|
||
key);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
requestCursorUpdates (int cursorUpdateMode)
|
||
{
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return false;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, "requestCursorUpdates: " + cursorUpdateMode);
|
||
|
||
EmacsNative.requestCursorUpdates (windowHandle, cursorUpdateMode);
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
requestCursorUpdates (int cursorUpdateMode, int filter)
|
||
{
|
||
if (filter != 0)
|
||
return false;
|
||
|
||
return requestCursorUpdates (cursorUpdateMode);
|
||
}
|
||
|
||
@Override
|
||
public SurroundingText
|
||
getSurroundingText (int beforeLength, int afterLength,
|
||
int flags)
|
||
{
|
||
SurroundingText text;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, ("getSurroundingText: " + beforeLength + ", "
|
||
+ afterLength));
|
||
|
||
text = EmacsNative.getSurroundingText (windowHandle, beforeLength,
|
||
afterLength, flags);
|
||
|
||
if (EmacsService.DEBUG_IC && text != null)
|
||
Log.d (TAG, ("getSurroundingText: "
|
||
+ text.getSelectionStart ()
|
||
+ ","
|
||
+ text.getSelectionEnd ()
|
||
+ "+"
|
||
+ text.getOffset ()
|
||
+ ": "
|
||
+ text.getText ()));
|
||
|
||
return text;
|
||
}
|
||
|
||
@Override
|
||
public TextSnapshot
|
||
takeSnapshot ()
|
||
{
|
||
TextSnapshot snapshot;
|
||
|
||
/* Return if the input connection is out of date. */
|
||
if (view.icSerial < view.icGeneration)
|
||
return null;
|
||
|
||
snapshot = EmacsNative.takeSnapshot (windowHandle);
|
||
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, ("takeSnapshot: "
|
||
+ snapshot.getSurroundingText ().getText ()
|
||
+ " @ " + snapshot.getCompositionEnd ()
|
||
+ ", " + snapshot.getCompositionStart ()));
|
||
|
||
return snapshot;
|
||
}
|
||
|
||
@Override
|
||
public void
|
||
closeConnection ()
|
||
{
|
||
batchEditCount = 0;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
replaceText (int start, int end, CharSequence text,
|
||
int newCursorPosition, TextAttribute attributes)
|
||
{
|
||
if (EmacsService.DEBUG_IC)
|
||
Log.d (TAG, ("replaceText: " + text + ":: " + start + ","
|
||
+ end + "," + newCursorPosition));
|
||
|
||
EmacsNative.replaceText (windowHandle, start, end,
|
||
text.toString (), newCursorPosition,
|
||
attributes);
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
public void
|
||
reset ()
|
||
{
|
||
batchEditCount = 0;
|
||
}
|
||
|
||
|
||
/* Override functions which are not implemented. */
|
||
|
||
@Override
|
||
public Handler
|
||
getHandler ()
|
||
{
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
commitContent (InputContentInfo inputContentInfo, int flags,
|
||
Bundle opts)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
setImeConsumesInput (boolean imeConsumesInput)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
clearMetaKeyStates (int states)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
reportFullscreenMode (boolean enabled)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
performSpellCheck ()
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public boolean
|
||
performPrivateCommand (String action, Bundle data)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public int
|
||
getCursorCapsMode (int reqModes)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|