/*
* Copyright (C) 2007 Quadduc <quadduc@gmail.com>
* Copyright (C) 2008 Clam <clamisgood@gmail.com>
* Copyright (C) 2008 IsmAvatar <IsmAvatar@gmail.com>
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* InputHandler.java - Manages key bindings and executes actions
* Copyright (C) 1999 Slava Pestov
*
* You may use and modify this package for any purpose. Redistribution is
* permitted, in both source and binary form, provided that this notice
* remains intact in all source distributions of this package.
*/
package org.lateralgm.jedit;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.JPopupMenu;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/**
* An input handler converts the user's key strokes into concrete actions.
* It also takes care of macro recording and action repetition.<p>
*
* This class provides all the necessary support code for an input
* handler, but doesn't actually do any key binding logic. It is up
* to the implementations of this class to do so.
*
* @author Slava Pestov
*/
public abstract class InputHandler extends KeyAdapter
{
public static final String KEEP_INDENT_PROPERTY = "InputHandler.keepIndent";
public static final String TAB_TO_INDENT_PROPERTY = "InputHandler.tabToIndent";
public static final String CONVERT_TABS_PROPERTY = "InputHandler.convertTabs";
public static final ActionListener BACKSPACE = new Backspace();
public static final ActionListener BACKSPACE_WORD = new BackspaceWord();
public static final ActionListener DELETE = new Delete();
public static final ActionListener DELETE_WORD = new DeleteWord();
public static final ActionListener END = new End(false);
public static final ActionListener DOCUMENT_END = new DocumentEnd(false);
public static final ActionListener SELECT_END = new End(true);
public static final ActionListener SELECT_DOC_END = new DocumentEnd(true);
public static final ActionListener SELECT_ALL = new SelectAll();
public static final ActionListener INSERT_BREAK = new InsertBreak();
public static final ActionListener INSERT_TAB = new InsertTab();
public static final ActionListener HOME = new Home(false);
public static final ActionListener DOCUMENT_HOME = new DocumentHome(false);
public static final ActionListener SELECT_HOME = new Home(true);
public static final ActionListener SELECT_DOC_HOME = new DocumentHome(true);
public static final ActionListener NEXT_CHAR = new NextChar(false);
public static final ActionListener NEXT_LINE = new NextLine(false);
public static final ActionListener NEXT_PAGE = new NextPage(false);
public static final ActionListener NEXT_WORD = new NextWord(false);
public static final ActionListener SELECT_NEXT_CHAR = new NextChar(true);
public static final ActionListener SELECT_NEXT_LINE = new NextLine(true);
public static final ActionListener SELECT_NEXT_PAGE = new NextPage(true);
public static final ActionListener SELECT_NEXT_WORD = new NextWord(true);
public static final ActionListener OVERWRITE = new Overwrite();
public static final ActionListener PREV_CHAR = new PrevChar(false);
public static final ActionListener PREV_LINE = new PrevLine(false);
public static final ActionListener PREV_PAGE = new PrevPage(false);
public static final ActionListener PREV_WORD = new PrevWord(false);
public static final ActionListener SELECT_PREV_CHAR = new PrevChar(true);
public static final ActionListener SELECT_PREV_LINE = new PrevLine(true);
public static final ActionListener SELECT_PREV_PAGE = new PrevPage(true);
public static final ActionListener SELECT_PREV_WORD = new PrevWord(true);
public static final ActionListener REPEAT = new Repeat();
public static final ActionListener TOGGLE_RECT = new ToggleRect();
public static final ActionListener CUT = new Cut();
public static final ActionListener COPY = new Copy();
public static final ActionListener PASTE = new Paste();
// Default action
public static final ActionListener INSERT_CHAR = new InsertChar();
private static Hashtable<String,ActionListener> actions;
static
{
actions = new Hashtable<String,ActionListener>();
actions.put("backspace",BACKSPACE);
actions.put("backspace-word",BACKSPACE_WORD);
actions.put("delete",DELETE);
actions.put("delete-word",DELETE_WORD);
actions.put("select-all",SELECT_ALL);
actions.put("end",END);
actions.put("select-end",SELECT_END);
actions.put("document-end",DOCUMENT_END);
actions.put("select-doc-end",SELECT_DOC_END);
actions.put("insert-break",INSERT_BREAK);
actions.put("insert-tab",INSERT_TAB);
actions.put("home",HOME);
actions.put("select-home",SELECT_HOME);
actions.put("document-home",DOCUMENT_HOME);
actions.put("select-doc-home",SELECT_DOC_HOME);
actions.put("next-char",NEXT_CHAR);
actions.put("next-line",NEXT_LINE);
actions.put("next-page",NEXT_PAGE);
actions.put("next-word",NEXT_WORD);
actions.put("select-next-char",SELECT_NEXT_CHAR);
actions.put("select-next-line",SELECT_NEXT_LINE);
actions.put("select-next-page",SELECT_NEXT_PAGE);
actions.put("select-next-word",SELECT_NEXT_WORD);
actions.put("overwrite",OVERWRITE);
actions.put("prev-char",PREV_CHAR);
actions.put("prev-line",PREV_LINE);
actions.put("prev-page",PREV_PAGE);
actions.put("prev-word",PREV_WORD);
actions.put("select-prev-char",SELECT_PREV_CHAR);
actions.put("select-prev-line",SELECT_PREV_LINE);
actions.put("select-prev-page",SELECT_PREV_PAGE);
actions.put("select-prev-word",SELECT_PREV_WORD);
actions.put("repeat",REPEAT);
actions.put("toggle-rect",TOGGLE_RECT);
actions.put("insert-char",INSERT_CHAR);
//
actions.put("cut",CUT);
actions.put("copy",COPY);
actions.put("paste",PASTE);
}
/**
* Returns a named text area action.
* @param name The action name
*/
public static ActionListener getAction(String name)
{
return actions.get(name);
}
/**
* Returns the name of the specified text area action.
* @param listener The action
*/
public static String getOperationName(ActionListener listener)
{
Enumeration<String> en = getActions();
while (en.hasMoreElements())
{
String name = en.nextElement();
ActionListener l = getAction(name);
if (l == listener) return name;
}
return null;
}
/** Returns an enumeration of all available actions. */
public static Enumeration<String> getActions()
{
return actions.keys();
}
/**
* Adds the default key bindings to this input handler.
* This should not be called in the constructor of this
* input handler, because applications might load the
* key bindings from a file, etc.
*/
public abstract void addDefaultKeyBindings();
/**
* Adds a key binding to this input handler.
* @param keyBinding The key binding (the format of this is
* input-handler specific)
* @param action The action
*/
public abstract void addKeyBinding(String keyBinding, ActionListener action);
/**
* Removes a key binding from this input handler.
* @param keyBinding The key binding
*/
public abstract void removeKeyBinding(String keyBinding);
/** Removes all key bindings from this input handler. */
public abstract void removeAllKeyBindings();
/**
* Grabs the next key typed event and invokes the specified
* action with the key as a the action command.
* @param action The action
*/
public void grabNextKeyStroke(ActionListener listener)
{
grabAction = listener;
}
/**
* Returns if repeating is enabled. When repeating is enabled,
* actions will be executed multiple times. This is usually
* invoked with a special key stroke in the input handler.
*/
public boolean isRepeatEnabled()
{
return repeat;
}
/**
* Enables repeating. When repeating is enabled, actions will be
* executed multiple times. Once repeating is enabled, the input
* handler should read a number from the keyboard.
*/
public void setRepeatEnabled(boolean repeat)
{
this.repeat = repeat;
}
/** Returns the number of times the next action will be repeated. */
public int getRepeatCount()
{
return (repeat ? Math.max(1,repeatCount) : 1);
}
/**
* Sets the number of times the next action will be repeated.
* @param repeatCount The repeat count
*/
public void setRepeatCount(int repeatCount)
{
this.repeatCount = repeatCount;
}
/**
* Returns the macro recorder. If this is non-null, all executed
* actions should be forwarded to the recorder.
*/
public InputHandler.MacroRecorder getMacroRecorder()
{
return recorder;
}
/**
* Sets the macro recorder. If this is non-null, all executed
* actions should be forwarded to the recorder.
* @param recorder The macro recorder
*/
public void setMacroRecorder(InputHandler.MacroRecorder recorder)
{
this.recorder = recorder;
}
/**
* Executes the specified action, repeating and recording it as
* necessary.
* @param listener The action listener
* @param source The event source
* @param actionCommand The action command
*/
public void executeAction(ActionListener listener, Object source, String actionCommand)
{
// create event
ActionEvent evt = new ActionEvent(source,ActionEvent.ACTION_PERFORMED,actionCommand);
// don't do anything if the action is a wrapper
// (like EditAction.Wrapper)
if (listener instanceof Wrapper)
{
listener.actionPerformed(evt);
return;
}
// remember old values, in case action changes them
boolean r = repeat;
int rc = getRepeatCount();
// execute the action
if (listener instanceof InputHandler.NonRepeatable)
listener.actionPerformed(evt);
else
{
for (int i = 0; i < Math.max(1,repeatCount); i++)
listener.actionPerformed(evt);
}
// do recording. Notice that we do no recording whatsoever
// for actions that grab keys
if (grabAction == null)
{
if (recorder != null)
{
if (!(listener instanceof InputHandler.NonRecordable))
{
if (rc != 1) recorder.actionPerformed(REPEAT,String.valueOf(rc));
recorder.actionPerformed(listener,actionCommand);
}
}
// If repeat was true originally, clear it
// Otherwise it might have been set by the action, etc
if (r)
{
repeat = false;
repeatCount = 0;
}
}
}
/**
* Returns the text area that fired the specified event.
* @param evt The event
*/
public static JEditTextArea getTextArea(EventObject evt)
{
if (evt != null)
{
Object o = evt.getSource();
if (o instanceof Component)
{
// find the parent text area
Component c = (Component) o;
for (;;)
{
if (c instanceof JEditTextArea)
return (JEditTextArea) c;
else if (c == null) break;
if (c instanceof JPopupMenu)
c = ((JPopupMenu) c).getInvoker();
else
c = c.getParent();
}
}
}
// this shouldn't happen
System.err.println("BUG: getTextArea() returning null");
return null;
}
// protected members
/**
* If a key is being grabbed, this method should be called with
* the appropriate key event. It executes the grab action with
* the typed character as the parameter.
*/
protected void handleGrabAction(KeyEvent evt)
{
// Clear it *before* it is executed so that executeAction()
// resets the repeat count
ActionListener ga = grabAction;
grabAction = null;
executeAction(ga,evt.getSource(),String.valueOf(evt.getKeyChar()));
}
// protected members
protected ActionListener grabAction;
protected boolean repeat;
protected int repeatCount;
protected InputHandler.MacroRecorder recorder;
/**
* If an action implements this interface, it should not be repeated.
* Instead, it will handle the repetition itself.
*/
public interface NonRepeatable
{
}
/**
* If an action implements this interface, it should not be recorded
* by the macro recorder. Instead, it will do its own recording.
*/
public interface NonRecordable
{
}
/**
* For use by EditAction.Wrapper only.
* @since jEdit 2.2final
*/
public interface Wrapper
{
}
/**
* Macro recorder.
*/
public interface MacroRecorder
{
void actionPerformed(ActionListener listener, String actionCommand);
}
public static class Backspace implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (!textArea.editable)
{
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionEnd())
{
textArea.setSelectedText("");
}
else
{
int caret = textArea.getCaretPosition();
if (caret == 0)
{
textArea.getToolkit().beep();
return;
}
try
{
textArea.getDocument().remove(caret - 1,1);
}
catch (BadLocationException bl)
{
bl.printStackTrace();
}
}
}
}
public static class BackspaceWord implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionEnd())
{
textArea.setSelectedText("");
}
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
int caret = start - lineStart;
String lineText = textArea.getLineText(textArea.getCaretLine());
if (caret == 0)
{
if (lineStart == 0)
{
textArea.getToolkit().beep();
return;
}
caret--;
}
else
{
String noWordSep = (String) textArea.getDocument().getProperty("noWordSep");
caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
}
try
{
textArea.getDocument().remove(caret + lineStart,start - (caret + lineStart));
}
catch (BadLocationException bl)
{
bl.printStackTrace();
}
}
}
public static class Delete implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (!textArea.editable)
{
textArea.getToolkit().beep();
return;
}
if (textArea.getSelectionStart() != textArea.getSelectionEnd())
{
textArea.setSelectedText("");
}
else
{
int caret = textArea.getCaretPosition();
if (caret == textArea.getDocumentLength())
{
textArea.getToolkit().beep();
return;
}
try
{
textArea.getDocument().remove(caret,1);
}
catch (BadLocationException bl)
{
bl.printStackTrace();
}
}
}
}
public static class DeleteWord implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
if (start != textArea.getSelectionEnd())
{
textArea.setSelectedText("");
}
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
int caret = start - lineStart;
String lineText = textArea.getLineText(textArea.getCaretLine());
if (caret == lineText.length())
{
if (lineStart + caret == textArea.getDocumentLength())
{
textArea.getToolkit().beep();
return;
}
caret++;
}
else
{
String noWordSep = (String) textArea.getDocument().getProperty("noWordSep");
caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
}
try
{
textArea.getDocument().remove(start,(caret + lineStart) - start);
}
catch (BadLocationException bl)
{
bl.printStackTrace();
}
}
}
public static class SelectAll implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea eta = getTextArea(evt);
eta.select(0,eta.getDocumentLength());
}
}
public static class End implements ActionListener
{
private boolean select;
public End(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int lastOfLine = textArea.getLineEndOffset(textArea.getCaretLine()) - 1;
if (select)
textArea.select(textArea.getMarkPosition(),lastOfLine);
else
textArea.setCaretPosition(lastOfLine);
}
}
public static class DocumentEnd implements ActionListener
{
private boolean select;
public DocumentEnd(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (select)
textArea.select(textArea.getMarkPosition(),textArea.getDocumentLength());
else
textArea.setCaretPosition(textArea.getDocumentLength());
}
}
public static class Home implements ActionListener
{
private boolean select;
public Home(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int firstOfLine = textArea.getLineStartOffset(textArea.getCaretLine());
char[] line = textArea.getLineText(textArea.getCaretLine()).toCharArray();
int i;
for (i = 0; i < line.length; i++)
if (!Character.isWhitespace(line[i])) break;
i += firstOfLine;
if (caret != i)
caret = i;
else
caret = firstOfLine;
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class DocumentHome implements ActionListener
{
private boolean select;
public DocumentHome(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (select)
textArea.select(textArea.getMarkPosition(),0);
else
textArea.setCaretPosition(0);
}
}
public static class InsertBreak implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (!textArea.editable)
{
textArea.getToolkit().beep();
return;
}
if (Boolean.TRUE.equals(textArea.getClientProperty(KEEP_INDENT_PROPERTY))
&& textArea.getSelectedText() == null)
{
int caretLine = textArea.getCaretLine();
int caretPos = textArea.getCaretPosition() - textArea.getLineStartOffset(caretLine);
String indent = textArea.getLineText(caretLine).split("\\S",2)[0];
if (indent.length() > caretPos) indent = indent.substring(0,caretPos);
textArea.setSelectedText("\n" + indent);
}
else
textArea.setSelectedText("\n");
}
}
public static class InsertTab implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
if (!textArea.editable)
{
textArea.getToolkit().beep();
return;
}
if (Boolean.TRUE.equals(textArea.getClientProperty(TAB_TO_INDENT_PROPERTY)))
{
int caretLine = textArea.getCaretLine();
int caretLineStartOffset = textArea.getLineStartOffset(caretLine);
int caretPos = textArea.getCaretPosition() - caretLineStartOffset;
if (textArea.getSelectionEnd() != textArea.getSelectionStart())
insertTab(textArea);
else if (caretLine > 0)
{
String i1 = textArea.getLineText(caretLine - 1).split("\\S",2)[0];
String i2 = textArea.getLineText(caretLine).split("\\S",2)[0];
int i1w = textArea.offsetToX(caretLine - 1,i1.length());
int i2w = textArea.offsetToX(caretLine,i2.length());
int cx = textArea.offsetToX(caretLine,caretPos);
if (caretPos <= i2.length() && cx < i1w)
{
String s = i1w > i2w ? i1 : i2;
textArea.setSelectionStart(caretLineStartOffset);
textArea.setSelectionEnd(caretLineStartOffset + i2.length());
textArea.setSelectedText(s);
}
else
insertTab(textArea);
}
else
insertTab(textArea);
}
else
insertTab(textArea);
}
private void insertTab(JEditTextArea textArea)
{
if (Boolean.TRUE.equals(textArea.getClientProperty(CONVERT_TABS_PROPERTY)))
{
String key = PlainDocument.tabSizeAttribute;
int tabSize = ((Integer) textArea.getDocument().getProperty(key)).intValue();
String tab = "";
for (int i = 0; i < tabSize; i++)
tab += " ";
int p = textArea.getCaretPosition() - textArea.getLineStartOffset(textArea.getCaretLine());
textArea.setSelectedText(tab.substring(p % tab.length()));
}
else
textArea.setSelectedText("\t");
}
}
public static class NextChar implements ActionListener
{
private boolean select;
public NextChar(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if (caret == textArea.getDocumentLength())
{
textArea.getToolkit().beep();
return;
}
if (select)
textArea.select(textArea.getMarkPosition(),caret + 1);
else
textArea.setCaretPosition(caret + 1);
}
}
public static class NextLine implements ActionListener
{
private boolean select;
public NextLine(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
if (line == textArea.getLineCount() - 1)
{
textArea.getToolkit().beep();
return;
}
if (textArea.magicCaret == -1)
{
textArea.magicCaret = textArea.offsetToX(line,caret - textArea.getLineStartOffset(line));
}
caret = textArea.getLineStartOffset(line + 1)
+ textArea.xToOffset(line + 1,textArea.magicCaret);
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class NextPage implements ActionListener
{
private boolean select;
public NextPage(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int lineCount = textArea.getLineCount();
int firstLine = textArea.getFirstLine();
int visibleLines = textArea.getVisibleLines();
int line = textArea.getCaretLine();
firstLine += visibleLines;
if (firstLine + visibleLines >= lineCount - 1) firstLine = lineCount - visibleLines;
textArea.setFirstLine(firstLine);
int l = Math.min(textArea.getLineCount() - 1,line + visibleLines);
int caret = textArea.getLineStartOffset(l);
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class NextWord implements ActionListener
{
private boolean select;
public NextWord(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
caret -= lineStart;
String lineText = textArea.getLineText(textArea.getCaretLine());
if (caret == lineText.length())
{
if (lineStart + caret == textArea.getDocumentLength())
{
textArea.getToolkit().beep();
return;
}
caret++;
}
else
{
String noWordSep = (String) textArea.getDocument().getProperty("noWordSep");
caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
}
if (select)
textArea.select(textArea.getMarkPosition(),lineStart + caret);
else
textArea.setCaretPosition(lineStart + caret);
}
}
public static class Overwrite implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.setOverwriteEnabled(!textArea.isOverwriteEnabled());
}
}
public static class PrevChar implements ActionListener
{
private boolean select;
public PrevChar(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if (caret == 0)
{
textArea.getToolkit().beep();
return;
}
if (select)
textArea.select(textArea.getMarkPosition(),caret - 1);
else
textArea.setCaretPosition(caret - 1);
}
}
public static class PrevLine implements ActionListener
{
private boolean select;
public PrevLine(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
if (line == 0)
{
textArea.getToolkit().beep();
return;
}
if (textArea.magicCaret == -1)
{
textArea.magicCaret = textArea.offsetToX(line,caret - textArea.getLineStartOffset(line));
}
caret = textArea.getLineStartOffset(line - 1)
+ textArea.xToOffset(line - 1,textArea.magicCaret);
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class PrevPage implements ActionListener
{
private boolean select;
public PrevPage(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int firstLine = textArea.getFirstLine();
int visibleLines = textArea.getVisibleLines();
int line = textArea.getCaretLine();
if (firstLine < visibleLines) firstLine = visibleLines;
textArea.setFirstLine(firstLine - visibleLines);
int caret = textArea.getLineStartOffset(Math.max(0,line - visibleLines));
if (select)
textArea.select(textArea.getMarkPosition(),caret);
else
textArea.setCaretPosition(caret);
}
}
public static class PrevWord implements ActionListener
{
private boolean select;
public PrevWord(boolean select)
{
this.select = select;
}
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
int line = textArea.getCaretLine();
int lineStart = textArea.getLineStartOffset(line);
caret -= lineStart;
String lineText = textArea.getLineText(textArea.getCaretLine());
if (caret == 0)
{
if (lineStart == 0)
{
textArea.getToolkit().beep();
return;
}
caret--;
}
else
{
String noWordSep = (String) textArea.getDocument().getProperty("noWordSep");
caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
}
if (select)
textArea.select(textArea.getMarkPosition(),lineStart + caret);
else
textArea.setCaretPosition(lineStart + caret);
}
}
public static class Repeat implements ActionListener,InputHandler.NonRecordable
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.inputHandler.setRepeatEnabled(true);
String actionCommand = evt.getActionCommand();
if (actionCommand != null)
{
textArea.inputHandler.setRepeatCount(Integer.parseInt(actionCommand));
}
}
}
public static class ToggleRect implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.setSelectionRectangular(!textArea.isSelectionRectangular());
}
}
public static class InsertChar implements ActionListener,InputHandler.NonRepeatable
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
String str = evt.getActionCommand();
int repeatCount = textArea.inputHandler.getRepeatCount();
if (textArea.editable)
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < repeatCount; i++)
buf.append(str);
textArea.overwriteSetSelectedText(buf.toString());
}
else
{
textArea.getToolkit().beep();
}
}
}
public static class Cut implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.cut();
}
}
public static class Copy implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.copy();
}
}
public static class Paste implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
JEditTextArea textArea = getTextArea(evt);
textArea.paste();
}
}
}