alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Picrosystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.io.Reader;
import java.io.Writer;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.Action;
import javax.swing.JEditorPane;
import javax.swing.SwingConstants;
import javax.swing.text.Document;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.BadLocationException;
import javax.swing.text.ViewFactory;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import java.io.CharArrayWriter;
import java.util.Vector;
import javax.swing.text.Position;
import org.openide.ErrorManager;

/**
* Editor kit implementation for base document
*
* @author Miloslav Metelka
* @version 1.00
*/

public class BaseKit extends DefaultEditorKit {

    /** split the current line at cursor position */
    public static final String splitLineAction = "split-line"; // NOI18N

    /** Cycle through annotations on the current line */
    public static final String annotationsCyclingAction = "annotations-cycling"; // NOI18N
    
    /** Collapse a fold. Depends on the current caret position. */
    public static final String collapseFoldAction = "collapse-fold"; //NOI18N
    
    /** Expand a fold. Depends on the current caret position. */
    public static final String expandFoldAction = "expand-fold"; //NOI18N
    
    /** Collapse all existing folds in the document. */
    public static final String collapseAllFoldsAction = "collapse-all-folds"; //NOI18N
    
    /** Expand all existing folds in the document. */
    public static final String expandAllFoldsAction = "expand-all-folds"; //NOI18N
    
    /** Move one page up and make or extend selection */
    public static final String selectionPageUpAction = "selection-page-up"; // NOI18N

    /** Move one page down and make or extend selection */
    public static final String selectionPageDownAction = "selection-page-down"; // NOI18N

    /** Remove indentation */
    public static final String removeTabAction = "remove-tab"; // NOI18N

    /** Remove selected block or do nothing - useful for popup menu */
    public static final String removeSelectionAction = "remove-selection"; // NOI18N

    /** Toggle bookmark on the current line */
    public static final String toggleBookmarkAction = "bookmark-toggle"; // NOI18N

    /** Goto the next bookmark */
    public static final String gotoNextBookmarkAction = "bookmark-next"; // NOI18N

    /** Expand the abbreviation */
    public static final String abbrevExpandAction = "abbrev-expand"; // NOI18N

    /** Reset the abbreviation accounting string */
    public static final String abbrevResetAction = "abbrev-reset"; // NOI18N

    /** Remove to the begining of the word */
    public static final String removeWordAction = "remove-word"; // NOI18N

    /** Remove to the begining of the line */
    public static final String removeLineBeginAction = "remove-line-begin"; // NOI18N

    /** Remove line */
    public static final String removeLineAction = "remove-line"; // NOI18N

    /** Toggle the typing mode to overwrite mode or back to insert mode */
    public static final String toggleTypingModeAction = "toggle-typing-mode"; // NOI18N

    /** Change the selected text or current character to uppercase */
    public static final String toUpperCaseAction = "to-upper-case"; // NOI18N

    /** Change the selected text or current character to lowercase */
    public static final String toLowerCaseAction = "to-lower-case"; // NOI18N

    /** Switch the case of the selected text or current character */
    public static final String switchCaseAction = "switch-case"; // NOI18N

    /** Find next occurence action */
    public static final String findNextAction = "find-next"; // NOI18N

    /** Find previous occurence action */
    public static final String findPreviousAction = "find-previous"; // NOI18N

    /** Toggle highlight search action */
    public static final String toggleHighlightSearchAction = "toggle-highlight-search"; // NOI18N

    /** Find current word */
    public static final String findSelectionAction = "find-selection"; // NOI18N

    /** Undo action */
    public static final String undoAction = "undo"; // NOI18N

    /** Redo action */
    public static final String redoAction = "redo"; // NOI18N

    /** Word match next */
    public static final String wordMatchNextAction = "word-match-next"; // NOI18N

    /** Word match prev */
    public static final String wordMatchPrevAction = "word-match-prev"; // NOI18N

    /** Shift line right action */
    public static final String shiftLineRightAction = "shift-line-right"; // NOI18N

    /** Shift line left action */
    public static final String shiftLineLeftAction = "shift-line-left"; // NOI18N

    /** Action that scrolls the window so that caret is at the center of the window */
    public static final String adjustWindowCenterAction = "adjust-window-center"; // NOI18N

    /** Action that scrolls the window so that caret is at the top of the window */
    public static final String adjustWindowTopAction = "adjust-window-top"; // NOI18N

    /** Action that scrolls the window so that caret is at the bottom of the window */
    public static final String adjustWindowBottomAction = "adjust-window-bottom"; // NOI18N

    /** Action that moves the caret so that caret is at the center of the window */
    public static final String adjustCaretCenterAction = "adjust-caret-center"; // NOI18N

    /** Action that moves the caret so that caret is at the top of the window */
    public static final String adjustCaretTopAction = "adjust-caret-top"; // NOI18N

    /** Action that moves the caret so that caret is at the bottom of the window */
    public static final String adjustCaretBottomAction = "adjust-caret-bottom"; // NOI18N

    /** Format part of the document text using Indent */
    public static final String formatAction = "format"; // NOI18N

    /** First non-white character on the line */
    public static final String firstNonWhiteAction = "first-non-white"; // NOI18N

    /** Last non-white character on the line */
    public static final String lastNonWhiteAction = "last-non-white"; // NOI18N

    /** First non-white character on the line */
    public static final String selectionFirstNonWhiteAction = "selection-first-non-white"; // NOI18N

    /** Last non-white character on the line */
    public static final String selectionLastNonWhiteAction = "selection-last-non-white"; // NOI18N

    /** Select the nearest identifier around caret */
    public static final String selectIdentifierAction = "select-identifier"; // NOI18N

    /** Select the next parameter (after the comma) in the given context */
    public static final String selectNextParameterAction = "select-next-parameter"; // NOI18N

    /** Go to the previous position stored in the jump-list */
    public static final String jumpListNextAction = "jump-list-next"; // NOI18N

    /** Go to the next position stored in the jump-list */
    public static final String jumpListPrevAction = "jump-list-prev"; // NOI18N

    /** Go to the last position in the previous component stored in the jump-list */
    public static final String jumpListNextComponentAction = "jump-list-next-component"; // NOI18N

    /** Go to the next position in the previous component stored in the jump-list */
    public static final String jumpListPrevComponentAction = "jump-list-prev-component"; // NOI18N

    /** Scroll window one line up */
    public static final String scrollUpAction = "scroll-up"; // NOI18N

    /** Scroll window one line down */
    public static final String scrollDownAction = "scroll-down"; // NOI18N

    /** Prefix of all macro-based actions */
    public static final String macroActionPrefix = "macro-"; // NOI18N
    
    /** Start recording of macro. Only one macro recording can be active at the time */
    public static final String startMacroRecordingAction = "start-macro-recording"; //NOI18N
    
    /** Stop the active recording */
    public static final String stopMacroRecordingAction = "stop-macro-recording"; //NOI18N

    /** Name of the action moving caret to the first column on the line */
    public static final String lineFirstColumnAction = "caret-line-first-column"; // NOI18N

    /** Insert the current Date and Time  */
    public static final String insertDateTimeAction = "insert-date-time"; // NOI18N
    
    /** Name of the action moving caret to the first 
     * column on the line and extending the selection
     */
    public static final String selectionLineFirstColumnAction = "selection-line-first-column"; // NOI18N

    /** Name of the action for generating of Glyph Gutter popup menu*/
    public static final String generateGutterPopupAction = "generate-gutter-popup"; // NOI18N

    /** Toggle visibility of line numbers*/
    public static final String toggleLineNumbersAction = "toggle-line-numbers"; // NOI18N

    /** Paste and reformat code */
    public static final String pasteFormatedAction = "paste-formated"; // NOI18N

    /** Starts a new line in code */
    public static final String startNewLineAction = "start-new-line"; // NOI18N    
    
    private static final int KIT_CNT_PREALLOC = 57;

    static final long serialVersionUID = -8570495408376659348L;

    /** [kit-class, kit-instance] pairs are stored here */
    static Map kits = new HashMap(KIT_CNT_PREALLOC);

    /** [kit-class, keymap] pairs */
    static Map kitKeymaps = new HashMap(KIT_CNT_PREALLOC);

    /** [kit, action[]] pairs */
    static Map kitActions = new HashMap(KIT_CNT_PREALLOC);

    /** [kit, action-map] pairs */
    static Map kitActionMaps = new HashMap(KIT_CNT_PREALLOC);
    
    private CopyAction copyActionDef = new CopyAction();
    private CutAction cutActionDef = new CutAction();
    private PasteAction pasteActionDef = new PasteAction(false);
    
    static SettingsChangeListener settingsListener = new SettingsChangeListener() {
        public void settingsChange(SettingsChangeEvent evt) {
            String settingName = (evt != null) ? evt.getSettingName() : null;

            boolean clearActions = (settingName == null
                    || SettingsNames.CUSTOM_ACTION_LIST.equals(settingName)
                    || SettingsNames.MACRO_MAP.equals(settingName));

            if (clearActions || SettingsNames.KEY_BINDING_LIST.equals(settingName)) {
                kitKeymaps.clear();
            }

            if (clearActions) {
                kitActions.clear();
                kitActionMaps.clear();
            } else { // only refresh action settings
                Iterator i = kitActions.entrySet().iterator();
                while (i.hasNext()) {
                    Map.Entry me = (Map.Entry)i.next();
                    updateActionSettings((Action[])me.getValue(), evt, (Class)me.getKey());
                }
            }
        }
    };

    static {
        Settings.addSettingsChangeListener(settingsListener);
    }

    private static void updateActionSettings(Action[] actions,
            SettingsChangeEvent evt, Class kitClass) {
        for (int i = 0; i < actions.length; i++) {
            if (actions[i] instanceof BaseAction) {
                ((BaseAction)actions[i]).settingsChange(evt, kitClass);
            }
        }
    }

    public static BaseKit getKit(Class kitClass) {
        synchronized (Settings.class){
            if (kitClass == null) {
                kitClass = BaseKit.class;
            }
            BaseKit kit = (BaseKit)kits.get(kitClass);
            if (kit == null) {
                try {
                    kit = (BaseKit)kitClass.newInstance();
                } catch (IllegalAccessException e) {
                    Utilities.annotateLoggable(e);
                } catch (InstantiationException e) {
                    Utilities.annotateLoggable(e);
                }
                kits.put(kitClass, kit);
            }
            return kit;
        }
    }

    public BaseKit() {
        // possibly register
        synchronized (Settings.class) {
            if (kits.get(this.getClass()) == null) {
                kits.put(this.getClass(), this); // register itself
            }
        }
    }

    /** Clone this editor kit */
    public Object clone() {
        return this; // no need to create another instance
    }

    /** Fetches a factory that is suitable for producing
     * views of any models that are produced by this
     * kit.  The default is to have the UI produce the
     * factory, so this method has no implementation.
     *
     * @return the view factory
     */
    public ViewFactory getViewFactory() {
        return null;
    }

    /** Create caret to navigate through document */
    public Caret createCaret() {
        return new BaseCaret();
    }

    /** Create empty document */
    public Document createDefaultDocument() {
        return new BaseDocument(this.getClass(), true);
    }

    /** Create new instance of syntax coloring scanner
    * @param doc document to operate on. It can be null in the cases the syntax
    *   creation is not related to the particular document
    */
    public Syntax createSyntax(Document doc) {
        return new Syntax();
    }

    /** Create the syntax used for formatting */
    public Syntax createFormatSyntax(Document doc) {
        return createSyntax(doc);
    }

    /** Create syntax support */
    public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
        return new SyntaxSupport(doc);
    }

    /** Create the formatter appropriate for this kit */
    public Formatter createFormatter() {
        return new Formatter(this.getClass());
    }

    /** Create text UI */
    protected BaseTextUI createTextUI() {
        return new BaseTextUI();
    }

    /** Create extended UI */
    protected EditorUI createEditorUI() {
        return new EditorUI();
    }

    /**
     * Create extended UI for printing a document.
     * @deprecated this method is no longer being called by {@link EditorUI}.
     *  {@link #createPrintEditorUI(BaseDocument, boolean, boolean)} is being
     *  called instead.
     */
    protected EditorUI createPrintEditorUI(BaseDocument doc) {
        return new EditorUI(doc);
    }
    
    /**
     * Create extended UI for printing a document.
     *
     * @param doc document for which the extended UI is being created.
     * @param usePrintColoringMap use printing coloring settings instead
     *  of the regular ones.
     * @param lineNumberEnabled if set to false the line numbers will not be printed.
     *  If set to true the visibility of line numbers depends on the settings
     *  for the line number visibility.
     */
    protected EditorUI createPrintEditorUI(BaseDocument doc,
    boolean usePrintColoringMap, boolean lineNumberEnabled) {
        
        return new EditorUI(doc, usePrintColoringMap, lineNumberEnabled);
    }

    public MultiKeymap getKeymap() {
        synchronized (Settings.class) {
            MultiKeymap km = (MultiKeymap)kitKeymaps.get(this.getClass());
            if (km == null) { // keymap not yet constructed
                // construct new keymap
                km = new MultiKeymap("Keymap for " + this.getClass()); // NOI18N
                // retrieve key bindings for this kit and super kits
                Settings.KitAndValue kv[] = Settings.getValueHierarchy(
                                                this.getClass(), SettingsNames.KEY_BINDING_LIST);
                // go through all levels and collect key bindings
                for (int i = kv.length - 1; i >= 0; i--) {
                    List keyList = (List)kv[i].value;
                    JTextComponent.KeyBinding[] keys = new JTextComponent.KeyBinding[keyList.size()];
                    keyList.toArray(keys);
                    km.load(keys, getActionMap());
                }

                kitKeymaps.put(this.getClass(), km);
            }
            return km;
        }
    }

    /** Inserts content from the given stream. */
    public void read(Reader in, Document doc, int pos)
    throws IOException, BadLocationException {
        if (doc instanceof BaseDocument) {
            ((BaseDocument)doc).read(in, pos); // delegate it to document
        } else {
            super.read(in, doc, pos);
        }
    }

    /** Writes content from a document to the given stream */
    public void write(Writer out, Document doc, int pos, int len)
    throws IOException, BadLocationException {
        if (doc instanceof BaseDocument) {
            ((BaseDocument)doc).write(out, pos, len);
        } else {
            super.write(out, doc, pos, len);
        }
    }

    /** Creates map with [name, action] pairs from the given
    * array of actions.
    */
    public static Map actionsToMap(Action[] actions) {
        Map map = new HashMap();
        for (int i = 0; i < actions.length; i++) {
            Action a = actions[i];
            String name = (String)a.getValue(Action.NAME);
            map.put(((name != null) ? name : ""), a); // NOI18N
        }
        return map;
    }

    /** Converts map with [name, action] back
    * to array of actions.
    */
    public static Action[] mapToActions(Map map) {
        Action[] actions = new Action[map.size()];
        int i = 0;
        for (Iterator iter = map.values().iterator() ; iter.hasNext() ;) {
            actions[i++] = (Action)iter.next();
        }
        return actions;
    }

    /** Called after the kit is installed into JEditorPane */
    public void install(JEditorPane c) {
        BaseTextUI ui = createTextUI();
        c.setUI(ui);

        String propName = "netbeans.editor.noinputmethods"; // NOI18N
        Object noInputMethods = System.getProperty(propName);
        boolean enableIM;
        if (noInputMethods != null) {
            enableIM = !Boolean.getBoolean(propName);
        } else {
            enableIM = SettingsUtil.getBoolean(this.getClass(),
                                               SettingsNames.INPUT_METHODS_ENABLED, true);
        }

        c.enableInputMethods(enableIM);
        executeInstallActions(c);
    }

    protected void executeInstallActions(JEditorPane c) {
        Settings.KitAndValue[] kv = Settings.getValueHierarchy(this.getClass(),
                                    SettingsNames.KIT_INSTALL_ACTION_NAME_LIST);
        for (int i = kv.length - 1; i >= 0; i--) {
            List actList = (List)kv[i].value;
            actList = translateActionNameList(actList); // translate names to actions
            if (actList != null) {
                for (Iterator iter = actList.iterator(); iter.hasNext();) {
                    Action a = (Action)iter.next();
                    a.actionPerformed(new ActionEvent(c, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
                }
            }
        }
    }

    public void deinstall(JEditorPane c) {
        executeDeinstallActions(c);
        c.updateUI();
        
        // #41209: reset ancestor override flag if previously set
        if (c.getClientProperty("ancestorOverride") != null) { // NOI18N
            c.putClientProperty("ancestorOverride", Boolean.FALSE); // NOI18N
        }
    }

    protected void executeDeinstallActions(JEditorPane c) {
        Settings.KitAndValue[] kv = Settings.getValueHierarchy(this.getClass(),
                                    SettingsNames.KIT_DEINSTALL_ACTION_NAME_LIST);
        for (int i = kv.length - 1; i >= 0; i--) {
            List actList = (List)kv[i].value;
            actList = translateActionNameList(actList); // translate names to actions
            if (actList != null) {
                for (Iterator iter = actList.iterator(); iter.hasNext();) {
                    Action a = (Action)iter.next();
                    a.actionPerformed(new ActionEvent(c, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
                }
            }
        }
    }

    /** Initialize document by adding the draw-layers for example. */
    protected void initDocument(BaseDocument doc) {
    }

    /** Create actions that this kit supports. To use the actions of the parent kit
    * it's better instead of using super.createActions() to use
    * getKit(super.getClass()).getActions() because it can reuse existing
    * parent actions.
    */
    protected Action[] createActions() {
        return new Action[] {
                   new DefaultKeyTypedAction(),
                   new InsertContentAction(),
                   new InsertBreakAction(),
		   new SplitLineAction(),
                   new InsertTabAction(),
                   new DeleteCharAction(deletePrevCharAction, false),
                   new DeleteCharAction(deleteNextCharAction, true),
                   new ReadOnlyAction(),
                   new WritableAction(),
                   cutActionDef,
                   copyActionDef,
                   pasteActionDef,
                   new PasteAction(true),
                   new BeepAction(),
                   new UpAction(upAction, false),
                   new UpAction(selectionUpAction, true),
                   new PageUpAction(pageUpAction, false),
                   new PageUpAction(selectionPageUpAction, true),
                   new DownAction(downAction, false),
                   new DownAction(selectionDownAction, true),
                   new PageDownAction(selectionPageDownAction, true),
                   new PageDownAction(pageDownAction, false),
                   new ForwardAction(forwardAction, false),
                   new ForwardAction(selectionForwardAction, true),
                   new BackwardAction(backwardAction, false),
                   new BackwardAction(selectionBackwardAction, true),
                   new BeginLineAction(lineFirstColumnAction, false, true),
                   new BeginLineAction(selectionLineFirstColumnAction, true, true),
                   new BeginLineAction(beginLineAction, false),
                   new BeginLineAction(selectionBeginLineAction, true),
                   new EndLineAction(endLineAction, false),
                   new EndLineAction(selectionEndLineAction, true),
                   new BeginAction(beginAction, false),
                   new BeginAction(selectionBeginAction, true),
                   new EndAction(endAction, false),
                   new EndAction(selectionEndAction, true),
                   new NextWordAction(nextWordAction, false),
                   new NextWordAction(selectionNextWordAction, true),
                   new PreviousWordAction(previousWordAction, false),
                   new PreviousWordAction(selectionPreviousWordAction, true),
                   new BeginWordAction(beginWordAction, false),
                   new BeginWordAction(selectionBeginWordAction, true),
                   new EndWordAction(endWordAction, false),
                   new EndWordAction(selectionEndWordAction, true),
                   new SelectWordAction(),
                   new SelectLineAction(),
                   new SelectAllAction(),
                   new ActionFactory.RemoveTabAction(),
                   new ActionFactory.RemoveWordAction(),
                   new ActionFactory.RemoveLineBeginAction(),
                   new ActionFactory.RemoveLineAction(),
                   new ActionFactory.RemoveSelectionAction(),
                   new ActionFactory.ToggleTypingModeAction(),
                   new ActionFactory.ToggleBookmarkAction(),
                   new ActionFactory.GotoNextBookmarkAction(gotoNextBookmarkAction, false),
                   new ActionFactory.AbbrevExpandAction(),
                   new ActionFactory.AbbrevResetAction(),
                   new ActionFactory.ChangeCaseAction(toUpperCaseAction, Utilities.CASE_UPPER),
                   new ActionFactory.ChangeCaseAction(toLowerCaseAction, Utilities.CASE_LOWER),
                   new ActionFactory.ChangeCaseAction(switchCaseAction, Utilities.CASE_SWITCH),
                   new ActionFactory.FindNextAction(),
                   new ActionFactory.FindPreviousAction(),
                   new ActionFactory.FindSelectionAction(),
                   new ActionFactory.ToggleHighlightSearchAction(),
                   new ActionFactory.UndoAction(),
                   new ActionFactory.RedoAction(),
                   new ActionFactory.WordMatchAction(wordMatchNextAction, true),
                   new ActionFactory.WordMatchAction(wordMatchPrevAction, false),
                   new ActionFactory.ShiftLineAction(shiftLineLeftAction, false),
                   new ActionFactory.ShiftLineAction(shiftLineRightAction, true),
                   new ActionFactory.AdjustWindowAction(adjustWindowTopAction, 0),
                   new ActionFactory.AdjustWindowAction(adjustWindowCenterAction, 50),
                   new ActionFactory.AdjustWindowAction(adjustWindowBottomAction, 100),
                   new ActionFactory.AdjustCaretAction(adjustCaretTopAction, 0),
                   new ActionFactory.AdjustCaretAction(adjustCaretCenterAction, 50),
                   new ActionFactory.AdjustCaretAction(adjustCaretBottomAction, 100),
                   new ActionFactory.FormatAction(),
                   new ActionFactory.FirstNonWhiteAction(firstNonWhiteAction, false),
                   new ActionFactory.FirstNonWhiteAction(selectionFirstNonWhiteAction, true),
                   new ActionFactory.LastNonWhiteAction(lastNonWhiteAction, false),
                   new ActionFactory.LastNonWhiteAction(selectionLastNonWhiteAction, true),
                   new ActionFactory.SelectIdentifierAction(),
                   new ActionFactory.SelectNextParameterAction(),
                   new ActionFactory.JumpListPrevAction(),
                   new ActionFactory.JumpListNextAction(),
                   new ActionFactory.JumpListPrevComponentAction(),
                   new ActionFactory.JumpListNextComponentAction(),
                   new ActionFactory.ScrollUpAction(),
                   new ActionFactory.ScrollDownAction(),
                   new ActionFactory.StartMacroRecordingAction(),
                   new ActionFactory.StopMacroRecordingAction(),
                   new ActionFactory.InsertDateTimeAction(),
                   new ActionFactory.GenerateGutterPopupAction(),
                   new ActionFactory.ToggleLineNumbersAction(),
                   new ActionFactory.AnnotationsCyclingAction(),
                   new ActionFactory.CollapseFold(),
                   new ActionFactory.ExpandFold(),
                   new ActionFactory.CollapseAllFolds(),
                   new ActionFactory.ExpandAllFolds(),
                   new ActionFactory.DumpViewHierarchyAction(),
                   new ActionFactory.StartNewLine()
                   // Self test actions
                   //      new EditorDebug.SelfTestAction(),
                   //      new EditorDebug.DumpPlanesAction(),
                   //      new EditorDebug.DumpSyntaxMarksAction()
               };
    }

    protected Action[] getCustomActions() {
        Settings.KitAndValue kv[] = Settings.getValueHierarchy(
                                          this.getClass(), SettingsNames.CUSTOM_ACTION_LIST);
        if (kv.length == 0) {
            return null;
        }
        if (kv.length == 1) {
            List l = (List)kv[0].value;
            return (Action[])l.toArray(new Action[l.size()]);
        }
        // more than one list of actions
        List l = new ArrayList();
        for (int i = kv.length - 1; i >= 0; i--) { // from BaseKit down
            l.addAll((List)kv[i].value);
        }
        return (Action[])l.toArray(new Action[l.size()]);
    }
    
    protected Action[] getMacroActions() {
        Class kitClass = this.getClass();
        Map macroMap = (Map)Settings.getValue( kitClass, SettingsNames.MACRO_MAP);
        if( macroMap == null ) return null;
        List actions = new ArrayList();
        for( Iterator it = macroMap.keySet().iterator(); it.hasNext(); ) {
            String macroName = (String)it.next();
            actions.add( new ActionFactory.RunMacroAction( macroName ) );
        }
        return (Action[])actions.toArray( new Action[ actions.size() ] );
    }                               

    /** Get actions associated with this kit. createActions() is called
    * to get basic list and then customActions are added.
    */
    public final Action[] getActions() {
        synchronized (Settings.class) { // possibly long running code follows
            Class thisClass = this.getClass();
            Action[] actions = (Action[])kitActions.get(thisClass);
            if (actions == null) {
                // create map of actions
                Action[] createdActions = createActions();
                updateActionSettings(createdActions, null, thisClass);
                Map actionMap = actionsToMap(createdActions);
                // add custom actions
                Action[] customActions = getCustomActions();
                if (customActions != null) {
                    updateActionSettings(customActions, null, thisClass);
                    actionMap.putAll(actionsToMap(customActions));
                }
                Action[] macroActions = getMacroActions();
                if (macroActions != null) {
                    updateActionSettings(macroActions, null, thisClass);
                    actionMap.putAll(actionsToMap(macroActions));
                }

                // store for later use
                kitActionMaps.put(thisClass, actionMap);
                // create action array and store for later use
                actions = mapToActions(actionMap);
                kitActions.put(thisClass, actions);

                // At this moment the actions are constructed completely
                // The actions will be updated now if necessary
                updateActions();
            }
            return actions;
        }
    }

    Map getActionMap() {
        Map actionMap = (Map)kitActionMaps.get(this.getClass());
        if (actionMap == null) {
            getActions(); // init action map
            actionMap = (Map)kitActionMaps.get(this.getClass());

            // Fix of #27418
            if (actionMap == null) {
                actionMap = Collections.EMPTY_MAP;
            }
        }
        return actionMap;
    }

    /** Update the actions right after their creation was finished.
     * The getActions() and getActionByName()
     * can be used safely in this method.
     * The implementation must call super.updateActions() so that
     * the updating in parent is performed too.
     */
    protected void updateActions() {
    }

    /** Get action from its name. */
    public Action getActionByName(String name) {
        return (name != null) ? (Action)getActionMap().get(name) : null;
    }

    public List translateActionNameList(List actionNameList) {
        List ret = new ArrayList();
        if (actionNameList != null) {
            Iterator i = actionNameList.iterator();
            while (i.hasNext()) {
                Action a = getActionByName((String)i.next());
                if (a != null) {
                    ret.add(a);
                }
            }
        }
        return ret;
    }



    /** Default typed action */
    public static class DefaultKeyTypedAction extends BaseAction {

        static final long serialVersionUID =3069164318144463899L;

        public DefaultKeyTypedAction() {
            super(defaultKeyTypedAction, MAGIC_POSITION_RESET | SAVE_POSITION
                | CLEAR_STATUS_TEXT);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if ((target != null) && (evt != null)) {

                // Check whether the modifiers are OK
                int mod = evt.getModifiers();
                boolean ctrl = ((mod & ActionEvent.CTRL_MASK) != 0);
                boolean alt = ((mod & ActionEvent.ALT_MASK) != 0);
                if ((alt && !ctrl) || (ctrl && !alt)) {
                    return;
                }
                
                // Check whether the target is enabled and editable
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                Caret caret = target.getCaret();
                BaseDocument doc = (BaseDocument)target.getDocument();
                EditorUI editorUI = Utilities.getEditorUI(target);
                // determine if typed char is valid
                String cmd = evt.getActionCommand();
                if ((cmd != null) && (cmd.length() == 1)) {
                    //          Utilities.clearStatusText(target);

                    char ch = cmd.charAt(0);
                    if ((ch >= 0x20) && (ch != 0x7F)) { // valid character
                        editorUI.getWordMatch().clear(); // reset word matching

                        try {
                            boolean doInsert = editorUI.getAbbrev().checkAndExpand(ch, evt);
                            if (doInsert) {
                                if (caret.isSelectionVisible()) { // valid selection
                                    target.replaceSelection(cmd);
                                } else { // no selection
                                    int dotPos = caret.getDot();
                                    Boolean overwriteMode = (Boolean)editorUI.getProperty(
                                                                EditorUI.OVERWRITE_MODE_PROPERTY);
                                    if (overwriteMode != null && overwriteMode.booleanValue()
                                            && dotPos < doc.getLength() && doc.getChars(dotPos, 1)[0] != '\n'
                                       ) { // overwrite current char
                                        doc.atomicLock();
                                        try {
					  insertString(doc, dotPos, caret, cmd, true); 
                                        } finally {
					  doc.atomicUnlock();
                                        }
                                    } else { // insert mode
				      insertString(doc, dotPos, caret, cmd, false);
                                    }
                                }
                            }
                        } catch (BadLocationException e) {
                            target.getToolkit().beep();
                        }
                    }

                    checkIndent(target, cmd);
                }

            }
        }

      /** 
       * Hook to insert the given string at the given position into
       * the given document in insert-mode, no selection, writeable
       * document. Designed to be overridden by subclasses that want
       * to intercept inserted characters.
       */
      protected void insertString(BaseDocument doc,  
				  int dotPos, 
				  Caret caret,
				  String str, 
				  boolean overwrite) 
	throws BadLocationException 
      {
	if (overwrite) doc.remove(dotPos, 1);
	doc.insertString(dotPos, str, null);
      }



        /** Check whether there was any important character typed
        * so that the line should be possibly reformatted.
        */
        protected void checkIndent(JTextComponent target, String typedText) {
        }

    }

    public static class InsertBreakAction extends BaseAction {

        static final long serialVersionUID =7966576342334158659L;

        public InsertBreakAction() {
            super(insertBreakAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

		target.replaceSelection("");
                
		Caret caret = target.getCaret();
		BaseDocument doc = (BaseDocument)target.getDocument();
	
                doc.atomicLock();
                try{
                    Object cookie = beforeBreak(target, doc, caret);

                    int dotPos = caret.getDot();
                    int newDotPos = doc.getFormatter().indentNewLine(doc, dotPos);
                    caret.setDot(newDotPos);

                    afterBreak(target, doc, caret, cookie);
                } finally {
                    doc.atomicUnlock();
                }
            }
        }

      /**
       * Hook called before any changes to the document. The value
       * returned is passed intact to the other hook.
       */
      protected Object beforeBreak(JTextComponent target, BaseDocument doc, Caret caret) { 
	return null;
      }

      /**
       * Hook called after the enter was inserted and cursor
       * repositioned. *data* is the object returned previously by
       * *beforeBreak* hook. By default null.
       */
      protected void afterBreak(JTextComponent target, BaseDocument doc, Caret caret, Object data) {
      }
    }

    public static class SplitLineAction extends BaseAction {

        static final long serialVersionUID =7966576342334158659L;

        public SplitLineAction() {
	  super(splitLineAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                BaseDocument doc = (BaseDocument)target.getDocument();
                Caret caret = target.getCaret();
                int dotPos = caret.getDot();
		
		doc.atomicLock();
                try{
                    target.replaceSelection("");
                    int newDotPos = dotPos; 		  // dot stays where it was
                    doc.getFormatter().indentNewLine(doc, dotPos);   // newline
                    caret.setDot(newDotPos);
                } finally {
                    doc.atomicUnlock();
                }
            }
        }

    }


    public static class InsertTabAction extends BaseAction {

        static final long serialVersionUID =-3379768531715989243L;

        public InsertTabAction() {
            super(insertTabAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                Caret caret = target.getCaret();
                BaseDocument doc = (BaseDocument)target.getDocument();
                if (caret.isSelectionVisible()) { // block selected
                    try {
                        doc.getFormatter().changeBlockIndent(doc,
                                target.getSelectionStart(), target.getSelectionEnd(), +1);
                    } catch (GuardedException e) {
                        target.getToolkit().beep();
                    } catch (BadLocationException e) {
                        e.printStackTrace();
                    }
                } else { // no selected text
                    int dotPos = caret.getDot();
                    int caretCol;
                    // find caret column
                    try {
                        caretCol = doc.getVisColFromPos(dotPos);
                    } catch (BadLocationException e) {
                        Utilities.annotateLoggable(e);
                        caretCol = 0;
                    }

                    try {
                        // find indent of the first previous non-white row
                        int upperCol = Utilities.getRowIndent(doc, dotPos, false);
                        if (upperCol == -1) { // no prev line with  indent
                            upperCol = 0;
                        }
                        // is there any char on this line before cursor?
                        int indent = Utilities.getRowIndent(doc, dotPos);
                        // test whether we should indent
                        if (indent == -1) {
                            if (upperCol > caretCol) { // upper indent is greater
                                indent = upperCol;
                            } else { // simulate insert tab by changing indent
                                indent = Utilities.getNextTabColumn(doc, dotPos);
                            }

                            // Fix of #32240 - #1 of 2
                            int rowStart = Utilities.getRowStart(doc, dotPos);

                            doc.getFormatter().changeRowIndent(doc, dotPos, indent);

                            // Fix of #32240 - #2 of 2
                            int newDotPos = doc.getOffsetFromVisCol(indent, rowStart);
                            if (newDotPos >= 0) {
                                caret.setDot(newDotPos);
                            }
                            
                        } else { // already chars on the line
                            doc.getFormatter().insertTabString(doc, dotPos);

                        }
                    } catch (BadLocationException e) {
                        // use the same pos
                    }
                }
            }

        }

    }

    /** Compound action that encapsulates several actions */
    public static class CompoundAction extends BaseAction {

        Action[] actions;

        static final long serialVersionUID =1649688300969753758L;

        public CompoundAction(String nm, Action actions[]) {
            this(nm, 0, actions);
        }

        public CompoundAction(String nm, int resetMask, Action actions[]) {
            super(nm, resetMask);
            this.actions = actions;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                for (int i = 0; i < actions.length; i++) {
                    Action a = actions[i];
                    if (a instanceof BaseAction) {
                        ((BaseAction)a).actionPerformed(evt, target);
                    } else {
                        a.actionPerformed(evt);
                    }
                }
            }
        }
    }

    /** Compound action that gets and executes its actions
    * depending on the kit of the component.
    * The other advantage is that it doesn't create additional
    * instances of compound actions.
    */
    public static class KitCompoundAction extends BaseAction {

        private String[] actionNames;

        static final long serialVersionUID =8415246475764264835L;

        public KitCompoundAction(String nm, String actionNames[]) {
            this(nm, 0, actionNames);
        }

        public KitCompoundAction(String nm, int resetMask, String actionNames[]) {
            super(nm, resetMask);
            this.actionNames = actionNames;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                BaseKit kit = Utilities.getKit(target);
                if (kit != null) {
                    for (int i = 0; i < actionNames.length; i++) {
                        Action a = kit.getActionByName(actionNames[i]);
                        if (a != null) {
                            if (a instanceof BaseAction) {
                                ((BaseAction)a).actionPerformed(evt, target);
                            } else {
                                a.actionPerformed(evt);
                            }
                        }
                    }
                }
            }
        }
    }

    public static class InsertContentAction extends BaseAction {

        static final long serialVersionUID =5647751370952797218L;

        public InsertContentAction() {
            super(insertContentAction, MAGIC_POSITION_RESET | ABBREV_RESET
                  | WORD_MATCH_RESET);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if ((target != null) && (evt != null)) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                String content = evt.getActionCommand();
                if (content != null) {
                    target.replaceSelection(content);
                } else {
                    target.getToolkit().beep();
                }
            }
        }
    }

    /** Insert text specified in constructor */
    public static class InsertStringAction extends BaseAction {

        String text;

        static final long serialVersionUID =-2755852016584693328L;

        public InsertStringAction(String nm, String text) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
            this.text = text;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                target.replaceSelection(text);
            }
        }
    }

    /** Remove previous or next character */
    public static class DeleteCharAction extends BaseAction {

        protected boolean nextChar;

        static final long serialVersionUID =-4321971925753148556L;

        public DeleteCharAction(String nm, boolean nextChar) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
            this.nextChar = nextChar;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

		BaseDocument doc = (BaseDocument)target.getDocument();
		Caret caret = target.getCaret();
		int dot = caret.getDot();
		int mark = caret.getMark();

                try {
                    if (dot != mark) { // remove selection
                        doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
                    } else {
                        if (nextChar) { // remove next char
                            doc.remove(dot, 1);
                        } else { // remove previous char
                            doc.atomicLock();
                            try {
                                char ch = doc.getChars(dot-1, 1)[0];
                                doc.remove(dot - 1, 1);
                                charBackspaced(doc, dot-1, caret, ch);
                            } finally {
                                doc.atomicUnlock();
                            }
                        }
                    }
                } catch (BadLocationException e) {
                    target.getToolkit().beep();
		}

            }
        }

      protected void charBackspaced(BaseDocument doc, int dotPos, Caret caret, char ch) 
	throws BadLocationException
      {
      }
    }

    public static class ReadOnlyAction extends BaseAction {

        static final long serialVersionUID =9204335480208463193L;

        public ReadOnlyAction() {
            super(readOnlyAction);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                target.setEditable(false);
            }
        }
    }

    public static class WritableAction extends BaseAction {

        static final long serialVersionUID =-5982547952800937954L;

        public WritableAction() {
            super(writableAction);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                target.setEditable(true);
            }
        }
    }

    public static class CutAction extends BaseAction {

        static final long serialVersionUID =6377157040901778853L;

        public CutAction() {
            super(cutAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
            setEnabled(false);
            putValue ("helpID", CutAction.class.getName ()); // NOI18N
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                target.cut();
            }
        }
    }

    public static class CopyAction extends BaseAction {

        static final long serialVersionUID =-5119779005431986964L;

        public CopyAction() {
            super(copyAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
            setEnabled(false);
            putValue ("helpID", CopyAction.class.getName ()); // NOI18N
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                target.copy();
            }
        }
    }

    public static class PasteAction extends BaseAction {

        static final long serialVersionUID =5839791453996432149L;
        private boolean formated;

        public PasteAction(boolean formated) {
            super(formated ? pasteFormatedAction : pasteAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
            putValue ("helpID", PasteAction.class.getName ()); // NOI18N
            this.formated = formated;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }
                
                
                BaseDocument doc = Utilities.getDocument(target);
                if (doc==null) return;
                
                doc.atomicLock();
                try{
                    if (formated) {
                        Caret caret = target.getCaret();
                        int prevPos = target.getSelectionStart();
                        target.paste();
                        int postPos = caret.getDot();
                        indentBlock(doc, prevPos, postPos);
                    } else {
                        target.paste();
                    }
                }catch(Exception e){
                    target.getToolkit().beep();
		    //		    ErrorManager.getDefault().notify(e);
                } finally {
                    doc.atomicUnlock();
                }
            }
        }

      public static void indentBlock(BaseDocument doc, int startOffset, int endOffset)
	throws BadLocationException
      {
	char [] text = doc.getChars(startOffset, endOffset-startOffset);
	String [] lines = toLines(new String(text));

	doc.remove(startOffset, endOffset - startOffset);
	//	System.out.println("Lines:\n"); // NOI18N
	//	for (int j = 0 ; j < lines.length; j++) System.out.println(lines[j] + "<"); // NOI18N

	int offset = startOffset;
	// handle the full lines
	for (int i = 0; i < lines.length - 1; i++) {
	  String indent = getIndentString(doc, offset, lines[i]);
	  String fragment = indent + lines[i].trim() + '\n';
	  //	  System.out.println(fragment + "|"); // NOI18N
	  doc.insertString(offset, fragment, null);
	  offset += fragment.length();
	}

	// the rest just paste without indenting
	doc.insertString(offset, lines[lines.length-1], null);

      }

      /** Break string to lines */
      private static String [] toLines(String str) {
	Vector v = new Vector();
	int p=0 , p0=0;
	for (; p < str.length() ; p++) {
	  if (str.charAt(p) == '\n') {
	    v.add(str.substring(p0, p+1));
	    p0 = p+1;
	  }
	}
	if (p0 < str.length()) v.add(str.substring(p0, str.length())); else v.add("");

	return (String [])v.toArray(new String [0]);
      }

      private static String getIndentString(BaseDocument doc, int startOffset, String str) {
	try {
	  Formatter f = doc.getFormatter();
	  CharArrayWriter cw = new CharArrayWriter();
	  Writer w = f.createWriter(doc, startOffset, cw);
	  w.write(str, 0, str.length());
	  w.close();
	  String out = new String(cw.toCharArray());
	  int i = 0;
	  for (; i < out.length(); i++) {
	    if (out.charAt(i) != ' ' && out.charAt(i) != '\t') break;
	  }
	  //	  System.out.println(out+"|"); // NOI18N
	  //	  System.out.println(out.substring(0,i)+"^"); // NOI18N

	  return out.substring(0, i);
	} catch (java.io.IOException e) {
	  return "";
	}
      }
    }



    public static class BeepAction extends BaseAction {

        static final long serialVersionUID =-4474054576633223968L;

        public BeepAction() {
            super(beepAction);
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                target.getToolkit().beep();
            }
        }
    }


    public static class UpAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =4621760742646981563L;

        public UpAction(String nm, boolean select) {
            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
            | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                try {
                    Caret caret = target.getCaret();
                    int dot = caret.getDot();
                    Point p = caret.getMagicCaretPosition();
                    if (p == null) {
                        Rectangle r = target.modelToView(dot);
                        if (r!=null){
                            p = new Point(r.x, r.y);
                            caret.setMagicCaretPosition(p);
                        }else{
                            return; // model to view failed
                        }
                    }
                    try {
                        dot = Utilities.getPositionAbove(target, dot, p.x);
                        if (select) {
                            caret.moveDot(dot);
                        } else {
                            if (caret instanceof BaseCaret) {
                                BaseCaret bCaret = (BaseCaret)caret;
                                bCaret.setDot(dot, bCaret, EditorUI.SCROLL_MOVE, false);
                                
                            } else {
                                caret.setDot(dot);
                            }
                        }
                    } catch (BadLocationException e) {
                        // the position stays the same
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class DownAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =-5635702355125266822L;

        public DownAction(String nm, boolean select) {
            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
            | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                try {
                    Caret caret = target.getCaret();
                    int dot = caret.getDot();
                    Point p = caret.getMagicCaretPosition();
                    if (p == null) {
                        Rectangle r = target.modelToView(dot);
                        if (r!=null){
                            p = new Point(r.x, r.y);
                            caret.setMagicCaretPosition(p);
                        }else{
                            return; // model to view failed
                        }
                    }
                    try {
                        dot = Utilities.getPositionBelow(target, dot, p.x);
                        if (select) {
                            caret.moveDot(dot);
                        } else {
                            if (caret instanceof BaseCaret) {
                                BaseCaret bCaret = (BaseCaret)caret;
                                bCaret.setDot(dot, bCaret, EditorUI.SCROLL_MOVE, false);
                                
                            } else {
                                caret.setDot(dot);
                            }
                        }
                    } catch (BadLocationException e) {
                        // position stays the same
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    /** Go one page up */
    public static class PageUpAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =-3107382148581661079L;

        public PageUpAction(String nm, boolean select) {
            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
            | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                try {
                    Caret caret = target.getCaret();
                    BaseDocument doc = (BaseDocument)target.getDocument();
                    int dot = caret.getDot();
                    Rectangle tgtRect = ((BaseTextUI)target.getUI()).modelToView(target, dot);
                    Point p = caret.getMagicCaretPosition();
                    if (p == null && tgtRect !=null) {
                        p = new Point((int)tgtRect.x, (int)tgtRect.y);
                        caret.setMagicCaretPosition(p);
                    } else {
                        p.y = (int)tgtRect.y;
                    }
                    EditorUI editorUI = ((BaseTextUI)target.getUI()).getEditorUI();
                    Rectangle bounds = editorUI.getExtentBounds();
                    int trHeight = Math.max(tgtRect.height, 1); // prevent division by zero
                    int baseY = (bounds.y + trHeight - 1) / trHeight * trHeight;
                    int lines = (int)(bounds.height / trHeight);
                    int baseHeight =  lines * trHeight;
                    tgtRect.y = Math.max(baseY - baseHeight, 0);
                    tgtRect.height = bounds.height;
                    p.y = (int)Math.max(p.y - baseHeight, 0);
                    int newDot = target.viewToModel(p);
                    editorUI.scrollRectToVisible(tgtRect, EditorUI.SCROLL_DEFAULT);
                    if (select) {
                        caret.moveDot(newDot);
                    } else {
                        caret.setDot(newDot);
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class ForwardAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =8007293230193334414L;

        public ForwardAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
            | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int pos;
                    if (!select && caret.isSelectionVisible())
                    {
                        pos = target.getSelectionEnd(); 
                        if (pos != caret.getDot())
                            pos--;
                    }
                    else
                        pos = caret.getDot();
                    int dot = target.getUI().getNextVisualPositionFrom(target,
                              pos, Position.Bias.Forward, SwingConstants.EAST, null);
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        caret.setDot(dot);
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    /** Go one page down */
    public static class PageDownAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =8942534850985048862L;

        public PageDownAction(String nm, boolean select) {
            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
            | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                try {
                    Caret caret = target.getCaret();
                    BaseDocument doc = (BaseDocument)target.getDocument();
                    int dot = caret.getDot();
                    Rectangle tgtRect = ((BaseTextUI)target.getUI()).modelToView(target, dot);
                    Point p = caret.getMagicCaretPosition();
                    
                    if (p == null && tgtRect!=null) {
                        p = new Point(tgtRect.x, tgtRect.y);
                        caret.setMagicCaretPosition(p);
                    } else {
                        p.y = tgtRect.y;
                    }
                    EditorUI editorUI = ((BaseTextUI)target.getUI()).getEditorUI();
                    Rectangle bounds = editorUI.getExtentBounds();
                    int trHeight = Math.max(tgtRect.height, 1); // prevent division by zero
                    int baseY = bounds.y / trHeight * trHeight;
                    int lines = bounds.height / trHeight;
                    int baseHeight =  lines * trHeight;
                    tgtRect.y = Math.max(baseY + baseHeight, 0);
                    tgtRect.height = bounds.height;
                    p.y = Math.max(p.y + baseHeight, 0);
                    int newDot = target.viewToModel(p);
                    editorUI.scrollRectToVisible(tgtRect, EditorUI.SCROLL_DEFAULT);
                    if (select) {
                        caret.moveDot(newDot);
                    } else {
                        if (caret instanceof BaseCaret) {
                            BaseCaret bCaret = (BaseCaret)caret;
                            bCaret.setDot(newDot, bCaret, EditorUI.SCROLL_MOVE);

                        } else {
                            caret.setDot(newDot);
                        }
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class BackwardAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =-3048379822817847356L;

        public BackwardAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int pos;
                    if (!select && caret.isSelectionVisible())
                    {
                        pos = target.getSelectionStart(); 
                        if (pos != caret.getDot())
                            pos++;
                    }
                    else
                        pos = caret.getDot();
                    int dot = target.getUI().getNextVisualPositionFrom(target,
                              pos, Position.Bias.Backward, SwingConstants.WEST, null);
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        if (caret instanceof BaseCaret) {
                            BaseCaret bCaret = (BaseCaret)caret;
                            bCaret.setDot(dot, bCaret, EditorUI.SCROLL_MOVE, false);

                        } else {
                            caret.setDot(dot);
                        }
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class BeginLineAction extends BaseAction {

        protected boolean select;

        /** Whether the action should go to the begining of
         * the text on the line or to the first column on the line*/
        boolean homeKeyColumnOne;

        static final long serialVersionUID =3269462923524077779L;

        public BeginLineAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
            homeKeyColumnOne = false;
        }

        public BeginLineAction(String nm, boolean select, boolean columnOne) {
            this(nm, select);
            homeKeyColumnOne = columnOne;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                BaseDocument doc = (BaseDocument)target.getDocument();
                try {
                    int dot = caret.getDot();
                    int lineStartPos = javax.swing.text.Utilities.getRowStart(target, dot);
                    if (homeKeyColumnOne) { // to first column
                        dot = lineStartPos;
                    } else { // either to line start or text start
                        int textStartPos = Utilities.getRowFirstNonWhite(doc, lineStartPos);
                        if (textStartPos < 0) { // no text on the line
                            textStartPos = javax.swing.text.Utilities.getRowEnd(target, lineStartPos);
                        }
                        if (dot == lineStartPos) { // go to the text start pos
                            dot = textStartPos;
                        } else if (dot <= textStartPos) {
                            dot = lineStartPos;
                        } else {
                            dot = textStartPos;
                        }
                    }
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        caret.setDot(dot);
                    }
                } catch (BadLocationException e) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class EndLineAction extends BaseAction {

        protected boolean select;

        static final long serialVersionUID =5216077634055190170L;

        public EndLineAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int dot = javax.swing.text.Utilities.getRowEnd(target, caret.getDot());
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        caret.setDot(dot);
                    }
                    // now move the magic caret position far to the right
                    Rectangle r = target.modelToView(dot);
                    if (r!=null){
                        Point p = new Point(Short.MAX_VALUE - 1, r.y);
                        caret.setMagicCaretPosition(p);
                    }
                } catch (BadLocationException e) {
                    e.printStackTrace();
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class BeginAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =3463563396210234361L;

        public BeginAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                int dot = 0; // begin of document
                if (select) {
                    caret.moveDot(dot);
                } else {
                    caret.setDot(dot);
                }
            }
        }
    }

    public static class EndAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =8547506353130203657L;

        public EndAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                int dot = target.getDocument().getLength(); // end of document
                if (select) {
                    caret.moveDot(dot);
                } else {
                    caret.setDot(dot);
                }
            }
        }
    }

    public static class NextWordAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =-5909906947175434032L;

        public NextWordAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int dotPos = caret.getDot();
                    dotPos = Utilities.getNextWord(target, dotPos);
                    if (caret instanceof BaseCaret){
                        BaseCaret bCaret = (BaseCaret) caret;
                        if (select) {
                            bCaret.moveDot(dotPos);
                        } else {
                            bCaret.setDot(dotPos, false);
                        }
                    }else {
                        if (select) {
                            caret.moveDot(dotPos);
                        } else {
                            caret.setDot(dotPos);
                        }
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class PreviousWordAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =-5465143382669785799L;

        public PreviousWordAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int dot = Utilities.getPreviousWord(target, caret.getDot());
                    if (caret instanceof BaseCaret){
                        BaseCaret bCaret = (BaseCaret) caret;
                        if (select) {
                            bCaret.moveDot(dot);
                        } else {
                            bCaret.setDot(dot, false);
                        }
                    }else {
                        if (select) {
                            caret.moveDot(dot);
                        } else {
                            caret.setDot(dot);
                        }
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class BeginWordAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =3991338381212491110L;

        public BeginWordAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int dot = Utilities.getWordStart(target, caret.getDot());
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        caret.setDot(dot);
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    public static class EndWordAction extends BaseAction {

        boolean select;

        static final long serialVersionUID =3812523676620144633L;

        public EndWordAction(String nm, boolean select) {
            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
            this.select = select;
        }

        public void actionPerformed(ActionEvent evt, JTextComponent target) {
            if (target != null) {
                Caret caret = target.getCaret();
                try {
                    int dot = Utilities.getWordEnd(target, caret.getDot());
                    if (select) {
                        caret.moveDot(dot);
                    } else {
                        caret.setDot(dot);
                    }
                } catch (BadLocationException ex) {
                    target.getToolkit().beep();
                }
            }
        }
    }

    /** Select word around caret */
    public static class SelectWordAction extends KitCompoundAction {

        static final long serialVersionUID =7678848538073016357L;

        public SelectWordAction() {
            super(selectWordAction,
                  new String[] {
                      beginWordAction,
                      selectionEndWordAction
                  }
                 );
        }

    }

    /** Select line around caret */
    public static class SelectLineAction extends KitCompoundAction {

        static final long serialVersionUID =-7407681863035740281L;

        public SelectLineAction() {
            super(selectLineAction,
                  new String[] {
                      lineFirstColumnAction,
                      selectionEndLineAction
                      //selectionForwardAction //#41371
                  }
                 );
        }

    }

    /** Select text of whole document */
    public static class SelectAllAction extends KitCompoundAction {

        static final long serialVersionUID =-3502499718130556524L;

        public SelectAllAction() {
            super(selectAllAction,
                  new String[] {
                      beginAction,
                      selectionEndAction
                  }
                 );
        }

    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.