Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Netbeans/ide/editor.lib/src/org/netbeans/editor/   (Apache JAVA IDE Version 28©)  Datei vom 3.10.2025 mit Größe 218 kB image not shown  

Quelle  BaseKit.java   Sprache: JAVA

 
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package org.netbeans.editor;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
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 java.util.prefs.PreferenceChangeEvent;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JEditorPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.text.Document;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.ViewFactory;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.TextUI;
import javax.swing.text.AbstractDocument;

import static javax.swing.text.DefaultEditorKit.selectionBackwardAction;
import static javax.swing.text.DefaultEditorKit.selectionBeginLineAction;
import static javax.swing.text.DefaultEditorKit.selectionDownAction;
import static javax.swing.text.DefaultEditorKit.selectionEndLineAction;
import static javax.swing.text.DefaultEditorKit.selectionForwardAction;
import static javax.swing.text.DefaultEditorKit.selectionUpAction;

import javax.swing.text.EditorKit;
import javax.swing.text.Position;
import javax.swing.text.View;
import org.netbeans.api.editor.caret.CaretInfo;
import org.netbeans.api.editor.EditorActionRegistration;
import org.netbeans.api.editor.EditorActionRegistrations;
import org.netbeans.api.editor.EditorUtilities;
import org.netbeans.api.editor.caret.EditorCaret;
import org.netbeans.api.editor.mimelookup.MimeLookup;
import org.netbeans.api.editor.mimelookup.MimePath;
import org.netbeans.api.editor.settings.KeyBindingSettings;
import org.netbeans.api.editor.settings.SimpleValueNames;
import org.netbeans.lib.editor.util.CharSequenceUtilities;
import org.netbeans.lib.editor.util.ListenerList;
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
import org.netbeans.modules.editor.indent.api.Indent;
import org.netbeans.modules.editor.indent.api.IndentUtils;
import org.netbeans.modules.editor.indent.api.Reformat;
import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
import org.netbeans.modules.editor.lib2.EditorPreferencesDefaults;
import org.netbeans.modules.editor.lib2.EditorPreferencesKeys;
import org.netbeans.modules.editor.lib.KitsTracker;
import org.netbeans.api.editor.NavigationHistory;
import org.netbeans.api.editor.caret.CaretMoveContext;
import org.netbeans.api.editor.caret.MoveCaretsOrigin;
import org.netbeans.spi.editor.caret.CaretMoveHandler;
import org.netbeans.lib.editor.util.swing.PositionRegion;
import org.netbeans.modules.editor.lib.SettingsConversions;
import org.netbeans.modules.editor.lib2.RectangularSelectionCaretAccessor;
import org.netbeans.modules.editor.lib2.RectangularSelectionUtils;
import org.netbeans.modules.editor.lib2.actions.KeyBindingsUpdater;
import org.netbeans.modules.editor.lib2.typinghooks.DeletedTextInterceptorsManager;
import org.netbeans.modules.editor.lib2.typinghooks.TypedBreakInterceptorsManager;
import org.netbeans.modules.editor.lib2.typinghooks.TypedTextInterceptorsManager;
import org.netbeans.spi.editor.typinghooks.CamelCaseInterceptor;
import org.openide.awt.StatusDisplayer;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;

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


public class BaseKit extends DefaultEditorKit {

    /**
     * Flag indicating that the JTextComponent.paste() is in progress.
     * Checked in BaseDocument.read() to ignore clearing of the regions
     * for trailing-whitespace-removal.
     */

    static ThreadLocal<Boolean> IN_PASTE = new ThreadLocal<Boolean>();

    // -J-Dorg.netbeans.editor.BaseKit.level=FINEST
    private static final Logger LOG = Logger.getLogger(BaseKit.class.getName());
    
    /** 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

    /** 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 characters to the begining of the word or 
     *  the previous word if caret is not directly at word */

    public static final String removePreviousWordAction = "remove-word-previous"// NOI18N

    /** Remove characters to the end of the word or 
     *  the next word if caret is not directly at word */

    public static final String removeNextWordAction = "remove-word-next"// 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
    
    public static final String moveSelectionElseLineUpAction = "move-selection-else-line-up"// NOI18N
    
    public static final String moveSelectionElseLineDownAction = "move-selection-else-line-down"// NOI18N
    
    public static final String copySelectionElseLineUpAction = "copy-selection-else-line-up"// NOI18N
    
    public static final String copySelectionElseLineDownAction = "copy-selection-else-line-down"// 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

    /** Reindent Line action */
    public static final String reindentLineAction = "reindent-line"// NOI18N

    /** Reformat Line action */
    public static final String reformatLineAction = "reformat-line"// 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

    /** Indent part of the document text using Indent */
    public static final String indentAction = "indent"// 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    
    
    /** Cut text from caret position to line begining action. */
    public static final String cutToLineBeginAction = "cut-to-line-begin"// NOI18N    
    
    /** Cut text from caret position to line end action. */
    public static final String cutToLineEndAction = "cut-to-line-end"// NOI18N
    
    /** Remove all trailing spaces in the document. */
    public static final String removeTrailingSpacesAction = "remove-trailing-spaces"//NOI18N
    
    public static final String DOC_REPLACE_SELECTION_PROPERTY = "doc-replace-selection-property"//NOI18N
    
    private static final int KIT_CNT_PREALLOC = 7;

    static final long serialVersionUID = -8570495408376659348L;

    private static final Map<Class, BaseKit> kits = new HashMap<Class, BaseKit>(KIT_CNT_PREALLOC);

    private static final Object KEYMAPS_AND_ACTIONS_LOCK = new String("BaseKit.KEYMAPS_AND_ACTIONS_LOCK"); //NOI18N
    private static final Map<MimePath, KeybindingsAndPreferencesTracker> keymapTrackers = new WeakHashMap<MimePath, KeybindingsAndPreferencesTracker>(KIT_CNT_PREALLOC);
    private static final Map<MimePath, MultiKeymap> kitKeymaps = new WeakHashMap<MimePath, MultiKeymap>(KIT_CNT_PREALLOC);
    private static final Map<MimePath, Action[]> kitActions = new WeakHashMap<MimePath, Action[]>(KIT_CNT_PREALLOC);
    private static final Map<MimePath, Map<String, Action>> kitActionMaps = new WeakHashMap<MimePath, Map<String, Action>>(KIT_CNT_PREALLOC);
    
    private static CopyAction copyActionDef = new CopyAction();
    private static CutAction cutActionDef = new CutAction();
    private static PasteAction pasteActionDef = new PasteAction(false);
    private static DeleteCharAction deletePrevCharActionDef = new DeleteCharAction(deletePrevCharAction, false);
    private static DeleteCharAction deleteNextCharActionDef = new DeleteCharAction(deleteNextCharAction, true);
    private static ActionFactory.RemoveSelectionAction removeSelectionActionDef = new ActionFactory.RemoveSelectionAction();
    private static final Action insertTabActionDef = new InsertTabAction();
    private static final Action removeTabActionDef = new ActionFactory.RemoveTabAction();
    private static final Action insertBreakActionDef = new InsertBreakAction();

    private static ActionFactory.UndoAction undoActionDef = new ActionFactory.UndoAction();
    private static ActionFactory.RedoAction redoActionDef = new ActionFactory.RedoAction();
    
    public static final int MAGIC_POSITION_MAX = Integer.MAX_VALUE - 1;

    private final SearchableKit searchableKit;
    
    private boolean keyBindingsUpdaterInited;

    /**
     * Navigational boundaries for "home" and "end" actions. If defined on the target component,
     * home/end will move the caret first to the boundary, and only after that proceeds as usual (to the start/end of line).
     * The property must contain {@link PositionRegion} instance
     */

    private static final String PROP_NAVIGATE_BOUNDARIES = "NetBeansEditor.navigateBoundaries"// NOI18N
    
    /**
     * Gets an editor kit from its implemetation class.
     * 
     * <p>Please be careful when using this method and make sure that you understand
     * how it works and what the deference is from using <code>MimeLookup</code>.
     * This method simply creates an instance of <code>BaseKit</code> from
     * its implementation class passed in as a parameter. It completely ignores
     * the registry of editor kits in <code>MimeLookup</code>, which has severe
     * consequences.
     * 
     * <div class="nonnormative">
     * <p>The usuall pattern for using editor kits is to start with a mime type
     * of a document (ie. file) that you want to edit, then use some registry
     * for editor kits to look up the kit for your mime type and finally set the
     * kit in a <code>JTextComponent</code>, let it create a <code>Document</code>
     * and load it with data. The registry can generally be anything, but in Netbeans
     * we use <code>MimeLookup</code> (JDK for example uses 
     * <code>JEditorPane.createEditorKitForContentType</code>).
     * 
     * <p>The editor kits are registered in <code>MimeLookup</code> for each
     * particular mime type and the registry itself does not impose any rules on
     * the editor kit implementations other than extending the <code>EditorKit</code>
     * class. This for example means that the same implemantation of <code>EditorKit</code>
     * can be used for multiple mime types. This is exactly how XML editor kit
     * is reused for various flavors of XML documents (e.g. ant build scripts,
     * web app descriptors, etc).
     * 
     * <p>Netbeans did not always have <code>MimeLookup</code>
     * and it also used a different approach for registering and retrieving
     * editor kits. This old approach was based on implemetation classes rather than on mime
     * types and while it is still more or less functional for the old kit
     * implementations, it is fundamentally broken and should not be used any more.
     * The code below demonstrates probably the biggest mistake when thinking
     * in the old ways.
     * 
     * <pre>
     * // WARNING: The code below is a demonstration of a common mistake that
     * // people do when using <code>BaseKit.getKit</code>.
     * 
     * JTextComponent component = ...; // Let's say we have a component
     * Class kitClass = Utilities.getKitClass(component);
     * String mimeType = BaseKit.getKit(kitClass).getContentType();
     * </pre>
     * 
     * <p>The problem with the above code is that it blindely assumes that each
     * kit class can be uniquely mapped to a mime type. This is not true! The
     * same can be achieved in much easier way, which always works.
     * 
     * <pre>
     * JTextComponent component = ...; // Let's say we have a component
     * String mimeType = component.getUI().getEditorKit(component).getContentType();
     * </pre>
     * </div>
     * 
     * @param kitClass An implementation class of the editor kit that should
     * be returned. If the <code>kitClass</code> is not <code>BaseKit</code> or
     * its subclass the instance of bare <code>BaseKit</code> will be returned.
     * 
     * @return An instance of the <code>kitClass</code> or <code>BaseKit</code>.
     * @deprecated Use <code>CloneableEditorSupport.getEditorKit</code> or
     * <code>MimeLookup</code> instead to find <code>EditorKit</code> for a mime
     * type.
     */

    @Deprecated
    public static BaseKit getKit(Class kitClass) {
        if (kitClass != null && BaseKit.class.isAssignableFrom(kitClass) && BaseKit.class != kitClass) {
            String mimeType = KitsTracker.getInstance().findMimeType(kitClass);
            if (mimeType != null) {
                EditorKit kit = MimeLookup.getLookup(MimePath.parse(mimeType)).lookup(EditorKit.class);
                if (kit instanceof BaseKit) {
                    return (BaseKit) kit;
                }
            }
        } else {
            kitClass = BaseKit.class;
        }
        
        synchronized (kits) {
            Class classToTry = kitClass;
            for(;;) {
                BaseKit kit = (BaseKit)kits.get(classToTry);
                if (kit == null) {
                    try {
                        kit = (BaseKit)classToTry.getDeclaredConstructor().newInstance();
                        kits.put(classToTry, kit);
                        return kit;
                    } catch (ReflectiveOperationException e) {
                        LOG.log(Level.WARNING, "Can't instantiate editor kit from: " + classToTry, e); //NOI18N
                    }
                    //NOI18N
                    
                    if (classToTry != BaseKit.class) {
                        classToTry = BaseKit.class;
                    } else {
                        throw new IllegalStateException("Can't create editor kit for: " + kitClass); //NOI18N
                    }
                } else {
                    return kit;
                }
            }
        }
    }

    /**
     * Creates a new instance of <code>BaseKit</code>.
     * 
     * <div class="nonnormative">
     * <p>You should not need to instantiate editor kits
     * directly under normal circumstances. There is a few ways how you can get
     * instance of <code>EditorKit</code> depending on what you already have
     * available:
     * 
     * <ul>
     * <li><b>mime type</b> - Use <code>CloneableEditorSupport.getEditorKit(yourMimeType)</code>
     * to get the <code>EditorKit</code> registered for your mime type or use
     * the following code <code>MimeLookup.getLookup(MimePath.parse(yourMimeType)).lookup(EditorKit.class)</code>
     * and check for <code>null</code>.
     * <li><b>JTextComponent</b> - Simply call
     * <code>JTextComponent.getUI().getEditorKit(JTextComponent)</code> passing
     * in the same component.
     * </ul>
     * </div>
     */

    public BaseKit() {
        // possibly register
        synchronized (kits) {
            if (kits.get(this.getClass()) == null) {
                kits.put(this.getClass(), this); // register itself
            }
        }
        // Directly implementing searchable editor kit would require module dependency changes
        // of any modules using BaseKit reference so make a wrapper instead
        org.netbeans.modules.editor.lib2.actions.EditorActionUtilities.registerSearchableKit(this,
                searchableKit = new SearchableKit(this));
    }

    /** Clone this editor kit */
    public @Override 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 @Override ViewFactory getViewFactory() {
        return org.netbeans.modules.editor.lib2.view.ViewFactoryImpl.INSTANCE;
    }

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

    /** Create empty document */
    public @Override 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
     * 
     * @deprecated Please use Lexer instead, for details see
     *   <a href="@org-netbeans-modules-lexer@/index.html">Lexer</a>.
     */

    @Deprecated
    public Syntax createSyntax(Document doc) {
        return new DefaultSyntax();
    }

    /** 
     * Create the syntax used for formatting.
     * 
     * @deprecated Please use Editor Indentation API instead, for details see
     *   <a href="@org-netbeans-modules-editor-indent@/index.html">Editor Indentation</a>.
     */

    @Deprecated
    public Syntax createFormatSyntax(Document doc) {
        return createSyntax(doc);
    }

    /** 
     * Create syntax support
     * 
     * @deprecated Please use Lexer instead, for details see
     *   <a href="@org-netbeans-modules-lexer@/index.html">Lexer</a>.
     */

    @Deprecated
    public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
        return new SyntaxSupport(doc);
    }

// XXX: formatting cleanup
//    /**
//     * Create the formatter appropriate for this kit
//     * @deprecated Please use Editor Indentation API instead, for details see
//     *   <a href="@org-netbeans-modules-editor-indent@/index.html">Editor Indentation</a>.
//     */
//    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.
     */

    @Deprecated
    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 (KEYMAPS_AND_ACTIONS_LOCK) {
            MimePath mimePath = MimePath.parse(getContentType());
            MultiKeymap km = (MultiKeymap)kitKeymaps.get(mimePath);
            
            if (km == null) { // keymap not yet constructed
                // construct new keymap
                km = new MultiKeymap("Keymap for " + mimePath.getPath()); // NOI18N
                
                // retrieve key bindings for this kit and super kits
                KeyBindingSettings kbs = MimeLookup.getLookup(mimePath).lookup(KeyBindingSettings.class);
                List<org.netbeans.api.editor.settings.MultiKeyBinding> mkbList = kbs.getKeyBindings();
                List<JTextComponent.KeyBinding> editorMkbList = new  ArrayList<JTextComponent.KeyBinding>();
                
                for(org.netbeans.api.editor.settings.MultiKeyBinding mkb : mkbList) {
                    List<KeyStroke> keyStrokes = mkb.getKeyStrokeList();
                    MultiKeyBinding editorMkb = new MultiKeyBinding(keyStrokes.toArray(new KeyStroke[0]), mkb.getActionName());
                    editorMkbList.add(editorMkb);
                }
                
                // go through all levels and collect key bindings
                km.load(editorMkbList.toArray(new JTextComponent.KeyBinding[0]), getActionMap());
                km.setDefaultAction(getActionMap().get(defaultKeyTypedAction));

                kitKeymaps.put(mimePath, km);
            }
            
            return km;
        }
    }

    /** Inserts content from the given stream. */
    public @Override 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 @Override 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 void addActionsToMap(Map<String, Action> map, Action[] actions, String logActionsType) {
        boolean fineLoggable = LOG.isLoggable(Level.FINE);
        if (fineLoggable) {
            LOG.fine(logActionsType + " start --------------------\n");
        }
        for (int i = 0; i < actions.length; i++) {
            Action a = actions[i];
            if (a == null) {
                LOG.info("actions[] contains null at index " + i +
                        ((i > 0) ? ". Preceding action is " + actions[i - 1] : "."));
                continue;
            }
            String name = (String) a.getValue(Action.NAME);
            if (name == null) {
                LOG.info("Null Action.NAME property of action " + a);
                continue;
            }

            if (fineLoggable) {
                String overriding = map.containsKey(name) ? " OVERRIDING\n" : "\n"// NOI18N
                LOG.fine(" " + name + ": " + a + overriding); // NOI18N
            }

            map.put(name, a); // NOI18N
        }
        if (fineLoggable) {
            LOG.fine(logActionsType + " end ----------------------\n");
        }
    }

    /** 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 @Override void install(JEditorPane c) {
        
        assert (SwingUtilities.isEventDispatchThread()) // expected in AWT only
            : "BaseKit.install() incorrectly called from non-AWT thread."// NOI18N

        BaseTextUI ui = createTextUI();
        c.setUI(ui);
        c.addPropertyChangeListener(ClearUIForNullKitListener.INSTANCE);

        String propName = "netbeans.editor.noinputmethods"// NOI18N
        Object noInputMethods = System.getProperty(propName);
        boolean enableIM;
        if (noInputMethods != null) {
            enableIM = !Boolean.getBoolean(propName);
        } else {
            Preferences prefs = MimeLookup.getLookup(getContentType()).lookup(Preferences.class);
            enableIM = prefs.getBoolean(EditorPreferencesKeys.INPUT_METHODS_ENABLED, EditorPreferencesDefaults.defaultInputMethodsEnabled); //NOI18N
        }

        c.enableInputMethods(enableIM);
        
        org.netbeans.lib.editor.hyperlink.HyperlinkOperation.ensureRegistered(c, getContentType());

        // Mark that the editor's multi keymap adheres to context API in status displayer
        c.putClientProperty("context-api-aware"Boolean.TRUE); // NOI18N
        
        // Add default help IDs derived from the kit's mime type, #61618.
        // If the kit itself is HelpCtx.Provider it will be called from CloneableEditor.getHelpCtx()
        if (!(this instanceof HelpCtx.Provider)) {
            HelpCtx.setHelpIDString(c, getContentType().replace('/''.').replace('+''.')); //NOI18N
        }
        
        // setup the keymap tracker and initialize the keymap
        MultiKeymap keymap;
        synchronized (KEYMAPS_AND_ACTIONS_LOCK) {
            MimePath mimePath = MimePath.get(getContentType());
            KeybindingsAndPreferencesTracker tracker = keymapTrackers.get(mimePath);
            if (tracker == null) {
                tracker = new KeybindingsAndPreferencesTracker(mimePath.getPath());
                keymapTrackers.put(mimePath, tracker);
            }
            tracker.addComponent(c);
            keymap = getKeymap();
        }
        
        c.setKeymap(keymap);
        
        c.addAncestorListener(new AncestorListener() {
            private JScrollPane scrollPane;
            private InputMap origMap;
            int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;

            @Override
            public void ancestorAdded(AncestorEvent event) {
                Component c = (Component) event.getSource();
                Component parent;
                if ((parent = c.getParent()) instanceof JViewport) {
                    c = parent;
                    if ((parent = c.getParent()) instanceof JScrollPane) {
                        scrollPane = (JScrollPane) parent;
                        origMap = scrollPane.getInputMap(condition);
                        scrollPane.setInputMap(condition, null);
                    }
                }
            }

            @Override
            public void ancestorRemoved(AncestorEvent event) {
                if (scrollPane != null && scrollPane.getInputMap(condition) == null) {
                    // Restore original input map
                    scrollPane.setInputMap(condition, origMap);
                }
            }

            @Override
            public void ancestorMoved(AncestorEvent event) {
            }
        });
        
        executeInstallActions(c);
    }

    protected void executeInstallActions(JEditorPane c) {
        MimePath mimePath = MimePath.parse(getContentType());
        Preferences prefs = MimeLookup.getLookup(mimePath).lookup(Preferences.class);

        @SuppressWarnings("unchecked")
        List<String> actionNamesList = (List<String>) SettingsConversions.callFactory(
                prefs, mimePath, EditorPreferencesKeys.KIT_INSTALL_ACTION_NAME_LIST, null); //NOI18N
        
        List<Action> actionsList = translateActionNameList(actionNamesList); // translate names to actions
        for (Action a : actionsList) {
            a.actionPerformed(new ActionEvent(c, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
        }
    }

    public @Override void deinstall(JEditorPane c) {
        assert (SwingUtilities.isEventDispatchThread()) // expected in AWT only
            : "BaseKit.deinstall() incorrectly called from non-AWT thread."// NOI18N

        executeDeinstallActions(c);
        
        // reset the keymap and remove the component from the tracker
        c.setKeymap(null);
        synchronized (KEYMAPS_AND_ACTIONS_LOCK) {
            MimePath mimePath = MimePath.get(getContentType());
            KeybindingsAndPreferencesTracker tracker = keymapTrackers.get(mimePath);
            if (tracker != null) {
                tracker.removeComponent(c);
            }
        }
        
        BaseTextUI.uninstallUIWatcher(c);
        
        // #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) {
        MimePath mimePath = MimePath.parse(getContentType());
        Preferences prefs = MimeLookup.getLookup(mimePath).lookup(Preferences.class);
        
        @SuppressWarnings("unchecked")
        List<String> actionNamesList = (List<String>) SettingsConversions.callFactory(
                prefs, mimePath, EditorPreferencesKeys.KIT_DEINSTALL_ACTION_NAME_LIST, null); //NOI18N
        
        List<Action> actionsList = translateActionNameList(actionNamesList); // translate names to actions
        for (Action a : actionsList) {
            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() - overriden in ExtKit
                   insertBreakActionDef,
                   insertTabActionDef,
                   deletePrevCharActionDef,
                   deleteNextCharActionDef,
                   cutActionDef,
                   copyActionDef,
                   pasteActionDef,
                   new PasteAction(true),
                   removeTabActionDef,
                   //new ActionFactory.RemoveWordAction(), #47709
                   removeSelectionActionDef,
                   undoActionDef,
                   redoActionDef,
                   //new ActionFactory.ToggleLineNumbersAction(),
                   new ActionFactory.ToggleRectangularSelectionAction(),

                   // Self test actions
                   //      new EditorDebug.SelfTestAction(),
                   //      new EditorDebug.DumpPlanesAction(),
                   //      new EditorDebug.DumpSyntaxMarksAction()
               };
    }

    protected Action[] getCustomActions() {
        MimePath mimePath = MimePath.parse(getContentType());
        Preferences prefs = MimeLookup.getLookup(mimePath).lookup(Preferences.class);
        
        @SuppressWarnings("unchecked")
        List<? extends Action> customActions = (List<? extends Action>) SettingsConversions.callFactory(
                prefs, mimePath, EditorPreferencesKeys.CUSTOM_ACTION_LIST, null); //NOI18N
        
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine(EditorPreferencesKeys.CUSTOM_ACTION_LIST + " for '" + getContentType() + "' {"); //NOI18N
            if (customActions != null) {
                for(Action a : customActions) {
                    LOG.fine(" " + a); //NOI18N
                }
            }
            LOG.fine("} End of " + EditorPreferencesKeys.CUSTOM_ACTION_LIST + " for '" + getContentType() + "'"); //NOI18N
        }
        
        return customActions == null ? null : customActions.toArray(new Action[0]);
    }
    
    /**
     * @deprecated Without any replacement. 
     */

    @Deprecated
    protected Action[] getMacroActions() {
        return new Action[0];
    }                               

    /** Get actions associated with this kit. createActions() is called
    * to get basic list and then customActions are added.
    */

    public @Override final Action[] getActions() {
        Action[] actions = (Action []) addActionsToMap()[0];

        if (!keyBindingsUpdaterInited) {
            keyBindingsUpdaterInited = true;
            KeyBindingsUpdater.get(getContentType()).addKit(this); // Update key bindings in actions
        }
        
        return actions;
    }

    /* package */ Map<String, Action> getActionMap() {
        return (Map<String, Action>) addActionsToMap()[1];
    }

    private Object[] addActionsToMap() {
        synchronized (KEYMAPS_AND_ACTIONS_LOCK) {
            MimePath mimePath = MimePath.parse(getContentType());
            Action[] actions = kitActions.get(mimePath);
            Map<String, Action> actionMap = kitActionMaps.get(mimePath);
            
            if (actions == null || actionMap == null) {
                // Initialize actions - use the following actions:
                // 1. Declared "global" actions (declared in the xml layer under "Editors/Actions")
                // 2. Declared "mime-type" actions (declared in the xml layer under "Editors/mime-type/Actions")
                // 3. Result of createActions()
                // 4. Custom actions (EditorPreferencesKeys.CUSTOM_ACTION_LIST)
                // Higher levels override actions with same Action.NAME
                actions = getDeclaredActions(); // non-null
                actionMap = new HashMap<String, Action>(actions.length << 1);
                addActionsToMap(actionMap, actions, "Declared actions"); // NOI18N

                Action[] createActionsMethodResult = createActions();
                if (createActionsMethodResult != null) {
                    addActionsToMap(actionMap, createActionsMethodResult, "Actions from createActions()"); // NOI18N
                }
                
                // add custom actions
                Action[] customActions = getCustomActions();
                if (customActions != null) {
                    addActionsToMap(actionMap, customActions, "Custom actions"); // NOI18N
                }

                actions = actionMap.values().toArray(new Action[actionMap.values().size()]);

                kitActions.put(mimePath, actions);
                kitActionMaps.put(mimePath, actionMap);

                // At this moment the actions are constructed completely
                // The actions will be updated now if necessary
                updateActions();
            }
            
            return new Object [] { actions, actionMap };
        }
    }

    /**
     * Get actions declared in the xml layer. They may be overriden by result
     * of <code>createActions()</code> and finally by result of <code>getCustomActions()</code>.
     *
     * @return non-null list of declared actions.
     */

    protected Action[] getDeclaredActions() {
        return new Action[0];
    }
    
    /** Update the actions right after their creation was finished.
     * The <code>getActions()</code> and <code>getActionByName()</code>
     * can be used safely in this method.
     * The implementation must call <code>super.updateActions()</code> 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<Action> translateActionNameList(List<String> actionNameList) {
        List<Action> ret = new ArrayList<Action>();
        if (actionNameList != null) {
            for(String actionName : actionNameList) {
                Action a = getActionByName(actionName);
                if (a != null) {
                    ret.add(a);
                }
            }
        }
        return ret;
    }

    /**
     * Checks that the action will result in an insertion into document. 
     * Returns true for readonly docs as well.
     * 
     * @param evt action event
     * @return true, if the action event will result in insertion; readonly doc status is not 
     * checked.
     */

    static boolean isValidDefaultTypedAction(ActionEvent evt) {
        // Check whether the modifiers are OK
        int mod = evt.getModifiers();
        boolean ctrl = ((mod & ActionEvent.CTRL_MASK) != 0);
        boolean alt = org.openide.util.Utilities.isMac() ? ((mod & ActionEvent.META_MASK) != 0) :
            ((mod & ActionEvent.ALT_MASK) != 0);
        return !(alt || ctrl);
    }
    
    /**
     * 
     * @param evt
     * @return 
     */

    static boolean isValidDefaultTypedCommand(ActionEvent evt) {
        final String cmd = evt.getActionCommand();
        return (cmd != null && cmd.length() == 1 && cmd.charAt(0) >= 0x20 && cmd.charAt(0) != 0x7F);
    }

    /** 
     * Default typed action
     *
     * @deprecated Please do not subclass this class. Use Typing Hooks instead, for details see
     *   <a href="@org-netbeans-modules-editor-lib2@/index.html">Editor Library 2</a>.
     */

//    @EditorActionRegistration(name = defaultKeyTypedAction)
    @Deprecated
    public static class DefaultKeyTypedAction extends LocalBaseAction {

        static final long serialVersionUID = 3069164318144463899L;

        public DefaultKeyTypedAction() {
            // Construct with defaultKeyTypedAction name to retain full compatibility for extending actions
            super(defaultKeyTypedAction, CLEAR_STATUS_TEXT);
            putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
            LOG.fine("DefaultKeyTypedAction with enhanced logging, see issue #145306"); //NOI18N
        }

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

                if (!isValidDefaultTypedAction(evt)) {
                    return;
                }
                
                // Check whether the target is enabled and editable
                if (!target.isEditable() || !target.isEnabled()) {
                    target.getToolkit().beep();
                    return;
                }

                // reset magic caret position
                if (target.getCaret() != null) {
                    target.getCaret().setMagicCaretPosition(null);
                }
                
                // determine if typed char is valid
                final String cmd = evt.getActionCommand();
                if (isValidDefaultTypedCommand(evt)) {
                    if (LOG.isLoggable(Level.FINE)) {
                        LOG.log(Level.FINE, "Processing command char: {0}", Integer.toHexString(cmd.charAt(0))); //NOI18N
                    }

                    final BaseDocument doc = (BaseDocument)target.getDocument();
                    // Check rectangular selection => special mode
                    if (RectangularSelectionUtils.isRectangularSelection(target)) {
                        final boolean[] changed = new boolean[1];
                        doc.runAtomicAsUser(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    List<Position> regions = RectangularSelectionUtils.regionsCopy(target);
                                    if (regions != null && regions.size() > 2) {
                                        changed[0] = true;
                                        RectangularSelectionUtils.removeSelection(doc, regions);
                                        RectangularSelectionUtils.insertText(doc, regions, cmd);
                                    }
                                } catch (BadLocationException ble) {
                                    LOG.log(Level.FINE, null, ble);
                                    target.getToolkit().beep();
                                }
                            }
                        });
                        Caret caret = target.getCaret();
                        if (caret instanceof EditorCaret) {
                            RectangularSelectionCaretAccessor.get().setRectangularSelectionToDotAndMark((EditorCaret)caret);
                        }
                        if (changed[0]) {
                            return;
                        }
                    }

                    try {
//                        for (final CaretInfo caret : ((EditorCaret)target.getCaret()).getCarets()) {
//                    final Position insertionOffset = doc.createPosition(computeInsertionOffset(caret), Position.Bias.Backward);
//                    String replacedText = "";
//                    if (target.getCaret().isSelectionVisible() && caret.getDotPosition() != caret.getMarkPosition()) {
//                        int p0 = Math.min(caret.getDot(), caret.getMark());
//                        int p1 = Math.max(caret.getDot(), caret.getMark());
//                        replacedText = doc.getText(p0, p1 - p0);
//                    }
//                    final TypedTextInterceptorsManager.Transaction transaction = TypedTextInterceptorsManager.getInstance().openTransaction(
//                            target, insertionOffset, cmd, replacedText);
//                    
//                    try {
//                        if (!transaction.beforeInsertion()) {
//                            final Object [] result = new Object [] { Boolean.FALSE, "" }; //NOI18N
//                            doc.runAtomicAsUser (new Runnable () {
//                                public void run () {
//                                    boolean alreadyBeeped = false;
//                                    if (target.getCaret().isSelectionVisible() && caret.getDot() != caret.getMark()) { // valid selection
//                                        EditorUI editorUI = Utilities.getEditorUI(target);
//                                        Boolean overwriteMode = (Boolean) editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
//                                        boolean ovr = (overwriteMode != null && overwriteMode.booleanValue());
                        final Caret caret = target.getCaret();
                        
                        if(caret instanceof EditorCaret) {
                            EditorCaret editorCaret = (EditorCaret) caret;
                            final List<CaretInfo> carets = editorCaret.getCarets();
                            if(carets.size() > 1) {
                                doc.runAtomicAsUser(new Runnable() {
                                    public void run() {
                                        boolean alreadyBeeped = false;
                                        DocumentUtilities.setTypingModification(doc, true);
                                        try {
                                            EditorUtilities.addCaretUndoableEdit(doc, caret);
                                        for (CaretInfo c : carets) {
                                            if (c.isSelection()) { // valid selection
                                                int p0 = Math.min(c.getDot(), c.getMark());
                                                int p1 = Math.max(c.getDot(), c.getMark());
                                                String replacedText = null;
                                                try {
                                                    replacedText = doc.getText(p0, p1 - p0);
                                                } catch (BadLocationException ble) {
                                                    LOG.log(Level.FINE, null, ble);
                                                    if (!alreadyBeeped) {
                                                        target.getToolkit().beep();
                                                    }
                                                    alreadyBeeped = true;
                                                }
                                                try {
                                                    doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, true);
                                                    doc.remove(p0, p1 - p0);
                                                } catch (BadLocationException ble) {
                                                    LOG.log(Level.FINE, null, ble);
                                                    if (!alreadyBeeped) {
                                                        target.getToolkit().beep();
                                                    }
                                                    alreadyBeeped = true;
                                                } finally {
                                                    doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, null);
                                                }
                                            }
                                            try {
//                                                TBD: Mark for the last caret?
//                                                try {
//                                                    NavigationHistory.getEdits().markWaypoint(target, insertionOffset, false, true);
//                                                } catch (BadLocationException e) {
//                                                    LOG.log(Level.WARNING, "Can't add position to the history of edits.", e); //NOI18N
//                                                }
                                                
                                                final BaseDocument doc = (BaseDocument) target.getDocument();
                                                EditorUI editorUI = Utilities.getEditorUI(target);
                                                editorUI.getWordMatch().clear(); // reset word matching
                                                
                                                int insertionOffset = c.getDot();
                                                Boolean overwriteMode = (Boolean) editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
                                                boolean ovr = (overwriteMode != null && overwriteMode.booleanValue());
                                                if (ovr && insertionOffset < doc.getLength() && doc.getChars(insertionOffset, 1)[0] != '\n') { //NOI18N
                                                    // overwrite current char
                                                    doc.remove(insertionOffset, 1);
                                                    doc.insertString(insertionOffset, cmd, null);
                                                } else { // insert mode
                                                    doc.insertString(insertionOffset, cmd, null);
                                                }
                                            } catch (BadLocationException ble) {
                                                LOG.log(Level.FINE, null, ble);
                                                if (!alreadyBeeped) {
                                                    target.getToolkit().beep();
                                                }
                                            }
                                        }
                                            EditorUtilities.addCaretUndoableEdit(doc, caret);

                                        } finally {
                                            DocumentUtilities.setTypingModification(doc, false);
                                        }
                                    }
                                });
                                return;
                            }
                        }
                        
                        final Position insertionOffset = doc.createPosition(computeInsertionOffset(caret), Position.Bias.Backward);
                        String replacedText = "";
                        if (target.getCaret().isSelectionVisible() && caret.getDot() != caret.getMark()) {
                            int p0 = Math.min(caret.getDot(), caret.getMark());
                            int p1 = Math.max(caret.getDot(), caret.getMark());
                            replacedText = doc.getText(p0, p1 - p0);
                        }
                        final TypedTextInterceptorsManager.Transaction transaction = TypedTextInterceptorsManager.getInstance().openTransaction(
                                target, insertionOffset, cmd, replacedText);

                        try {
                            if (!transaction.beforeInsertion()) {
                                final Object[] result = new Object[]{Boolean.FALSE""}; //NOI18N
                                doc.runAtomicAsUser(new Runnable() {
                                    public void run() {
                                        boolean alreadyBeeped = false;
                                        EditorUtilities.addCaretUndoableEdit(doc, caret);
                                        if (target.getCaret().isSelectionVisible() && caret.getDot() != caret.getMark()) { // valid selection
                                            EditorUI editorUI = Utilities.getEditorUI(target);
                                            Boolean overwriteMode = (Boolean) editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
                                            boolean ovr = (overwriteMode != null && overwriteMode.booleanValue());
                                            try {
                                                doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, true);
                                                replaceSelection(target, insertionOffset.getOffset(), target.getCaret(), "", ovr);
                                            } catch (BadLocationException ble) {
                                                LOG.log(Level.FINE, null, ble);
                                                target.getToolkit().beep();
                                                alreadyBeeped = true;
                                            } finally {
                                                doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, null);
                                            }
                                        }
                                        Object[] r = transaction.textTyped();
                                        String insertionText = r == null ? cmd : (String) r[0];
                                        int caretPosition = r == null ? -1 : (Integer) r[1];
                                        boolean formatNewLines = r == null ? false : (Boolean) r[2];

                                        try {
                                            performTextInsertion(target, insertionOffset.getOffset(), insertionText, caretPosition, formatNewLines);
                                            result[0] = Boolean.TRUE;
                                            result[1] = insertionText;
                                        } catch (BadLocationException ble) {
                                            LOG.log(Level.FINE, null, ble);
                                            if (!alreadyBeeped) {
                                                target.getToolkit().beep();
                                            }
                                        }
                                        EditorUtilities.addCaretUndoableEdit(doc, caret);
                                    }
                                });

                                if (((Boolean) result[0]).booleanValue()) {
                                    transaction.afterInsertion();

                                    // XXX: this is potentially wrong and we may need to call this with
                                    // the original cmd; or maybe only if insertionText == cmd; but maybe
                                    // it does not matter, because nobody seems to be overwriting this method anyway
                                    checkIndent(target, (String) result[1]);
                                } // else text insertion failed
                            }
                        } finally {
                            transaction.close();
                        }
                    } catch (BadLocationException ble) {
                        LOG.log(Level.FINE, null, ble);
                        target.getToolkit().beep();
                    }
                } else {
                    if (LOG.isLoggable(Level.FINE)) {
                        StringBuilder sb = new StringBuilder();
                        for(int i = 0; i < cmd.length(); i++) {
                            String hex = Integer.toHexString(cmd.charAt(i));
                            sb.append(hex);
                            if (i + 1 < cmd.length()) {
                                sb.append(" ");
                            }
                        }
                        LOG.log(Level.FINE, "Invalid command: {0}", sb); //NOI18N
                    }                    
                }
            }
        }

        // --------------------------------------------------------------------
        // SPI
        // --------------------------------------------------------------------

        /**
         * 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.
         *
         * @deprecated Please use Typing Hooks instead, for details see
         *   <a href="@org-netbeans-modules-editor-lib2@/index.html">Editor Library 2</a>.
         */

        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);
        }

        /**
         * Hook to insert the given string at the given position into
         * the given document in insert-mode with selection visible
         * Designed to be overridden by subclasses that want
         * to intercept inserted characters.
         *
         * @deprecated Please use Typing Hooks instead, for details see
         *   <a href="@org-netbeans-modules-editor-lib2@/index.html">Editor Library 2</a>.
         */

        protected void replaceSelection(
                JTextComponent target,
                int dotPos,
                Caret caret,
                String str,
                boolean overwrite) throws BadLocationException
        {
            target.replaceSelection(str);
        }

        /**
         * Check whether there was any important character typed
         * so that the line should be possibly reformatted.
         *
         * @deprecated Please use <a href="@org-netbeans-modules-editor-indent-support@/org/netbeans/modules/editor/indent/spi/support/AutomatedIndenting.html">AutomatedIndentig</a>
         *   or Typing Hooks instead, for details see
         *   <a href="@org-netbeans-modules-editor-lib2@/index.html">Editor Library 2</a>.
         */

        protected void checkIndent(JTextComponent target, String typedText) {
        }

        // --------------------------------------------------------------------
        // Private implementation
        // --------------------------------------------------------------------

        private void performTextInsertion(JTextComponent target, int insertionOffset, String insertionText, int caretPosition, boolean formatNewLines) throws BadLocationException {
            final BaseDocument doc = (BaseDocument)target.getDocument();
            
            try {
                NavigationHistory.getEdits().markWaypoint(target, insertionOffset, falsetrue);
            } catch (BadLocationException e) {
                LOG.log(Level.WARNING, "Can't add position to the history of edits.", e); //NOI18N
            }

            DocumentUtilities.setTypingModification(doc, true);
            try {
                EditorUI editorUI = Utilities.getEditorUI(target);
                Caret caret = target.getCaret();

                editorUI.getWordMatch().clear(); // reset word matching
                Boolean overwriteMode = (Boolean)editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
                boolean ovr = (overwriteMode != null && overwriteMode.booleanValue());
                int currentInsertOffset = insertionOffset;
                int targetCaretOffset = caretPosition;
                for (int i = 0; i < insertionText.length();) {
                    int end = insertionText.indexOf('\n', i);
                    if (end == (-1) || !formatNewLines) end = insertionText.length();
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=91 H=91 G=90

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.