001: /*
002: * KeyMap.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: KeyMap.java,v 1.20 2004/09/13 02:03:08 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.awt.event.KeyEvent;
025: import java.io.BufferedReader;
026: import java.io.IOException;
027: import java.io.InputStreamReader;
028: import java.io.PrintWriter;
029: import java.util.ArrayList;
030: import java.util.Iterator;
031: import java.util.List;
032: import javax.swing.KeyStroke;
033:
034: public final class KeyMap implements Constants {
035: private static KeyMap globalKeyMap;
036: private static KeyMap globalOverrides;
037: private static File globalKeyMapFile;
038:
039: private ArrayList mappings = new ArrayList();
040:
041: public KeyMap() {
042: }
043:
044: public static synchronized KeyMap getGlobalKeyMap() {
045: if (globalKeyMap == null) {
046: String filename = Editor.preferences().getStringProperty(
047: Property.GLOBAL_KEY_MAP);
048: if (filename != null) {
049: globalKeyMapFile = File.getInstance(filename);
050: if (globalKeyMapFile != null) {
051: globalKeyMap = new KeyMap();
052: if (globalKeyMap.load(globalKeyMapFile))
053: return globalKeyMap;
054: globalKeyMapFile = null;
055: }
056: }
057: globalKeyMap = new KeyMap();
058: globalKeyMap.setGlobalDefaults();
059: }
060: return globalKeyMap;
061: }
062:
063: public static synchronized final File getGlobalKeyMapFile() {
064: return globalKeyMapFile;
065: }
066:
067: public static synchronized final void deleteGlobalKeyMap() {
068: globalKeyMap = null;
069: }
070:
071: public synchronized KeyMapping[] getMappings() {
072: KeyMapping[] array = new KeyMapping[mappings.size()];
073: return (KeyMapping[]) mappings.toArray(array);
074: }
075:
076: public synchronized boolean load(File file) {
077: boolean error = false;
078: String message = null;
079: if (!file.isRemote() && file.isFile()) {
080: int lineNumber = 0;
081: try {
082: BufferedReader in = new BufferedReader(
083: new InputStreamReader(file.getInputStream()));
084: while (true) {
085: String s = in.readLine();
086: if (s == null) {
087: // Reached end of file.
088: break;
089: }
090: ++lineNumber;
091: s = s.trim();
092: // Ignore blank lines.
093: if (s.trim().length() == 0)
094: continue;
095: // Ignore comment lines.
096: if (s.charAt(0) == '#')
097: continue;
098: if (!mapKey(s)) {
099: error = true;
100: message = "Error loading key map from "
101: + file.canonicalPath() + " (line "
102: + lineNumber + "); will use defaults.";
103: break;
104: }
105: }
106: } catch (IOException e) {
107: Log.error(e);
108: message = "Error loading key map from "
109: + file.canonicalPath() + "; will use defaults.";
110: }
111: } else {
112: error = true;
113: message = "Error loading key map from "
114: + file.canonicalPath()
115: + " (file not found); will use defaults.";
116: }
117: if (error)
118: MessageDialog.showMessageDialog(message, "Error");
119: return !error;
120: }
121:
122: private void setGlobalDefaults() {
123: // File menu.
124: mapKey(KeyEvent.VK_O, CTRL_MASK, "openFile");
125: mapKey(KeyEvent.VK_O, CTRL_MASK | ALT_MASK,
126: "openFileInOtherWindow");
127: mapKey(KeyEvent.VK_O, CTRL_MASK | SHIFT_MASK,
128: "openFileInOtherFrame");
129: mapKey(KeyEvent.VK_N, CTRL_MASK, "newBuffer");
130: mapKey(KeyEvent.VK_R, ALT_MASK, "recentFiles");
131: mapKey(KeyEvent.VK_S, CTRL_MASK, "save");
132: mapKey(KeyEvent.VK_S, CTRL_MASK | SHIFT_MASK, "saveAs");
133: mapKey(KeyEvent.VK_S, CTRL_MASK | ALT_MASK, "saveCopy");
134: mapKey(KeyEvent.VK_F2, 0, "saveAll");
135: mapKey(KeyEvent.VK_F4, CTRL_MASK, "killBuffer");
136: mapKey(KeyEvent.VK_W, CTRL_MASK, "killBuffer");
137: mapKey(KeyEvent.VK_P, ALT_MASK, "properties");
138: mapKey(KeyEvent.VK_RIGHT, ALT_MASK, "nextBuffer");
139: mapKey(KeyEvent.VK_KP_RIGHT, ALT_MASK, "nextBuffer");
140: mapKey(KeyEvent.VK_LEFT, ALT_MASK, "prevBuffer");
141: mapKey(KeyEvent.VK_KP_LEFT, ALT_MASK, "prevBuffer");
142: mapKey(KeyEvent.VK_N, CTRL_MASK | SHIFT_MASK, "newFrame");
143: mapKey(KeyEvent.VK_X, ALT_MASK, "executeCommand");
144: mapKey(KeyEvent.VK_P, CTRL_MASK, "print");
145: mapKey(KeyEvent.VK_Q, CTRL_MASK | SHIFT_MASK, "saveAllExit");
146: mapKey(KeyEvent.VK_Q, CTRL_MASK, "quit");
147:
148: // Edit menu.
149: mapKey(KeyEvent.VK_BACK_SPACE, ALT_MASK, "undo");
150: mapKey(KeyEvent.VK_Z, CTRL_MASK, "undo");
151: mapKey(KeyEvent.VK_Y, CTRL_MASK, "redo");
152: mapKey(KeyEvent.VK_DELETE, SHIFT_MASK, "killRegion");
153: mapKey(KeyEvent.VK_X, CTRL_MASK, "killRegion");
154: mapKey(KeyEvent.VK_X, CTRL_MASK | SHIFT_MASK, "killAppend");
155: mapKey(KeyEvent.VK_C, CTRL_MASK, "copyRegion");
156: mapKey(KeyEvent.VK_C, CTRL_MASK | SHIFT_MASK, "copyAppend");
157: mapKey(KeyEvent.VK_V, CTRL_MASK, "paste");
158: mapKey(KeyEvent.VK_V, CTRL_MASK | SHIFT_MASK, "cyclePaste");
159: mapKey(KeyEvent.VK_T, ALT_MASK, "cycleTabWidth");
160:
161: // Goto menu.
162: mapKey(KeyEvent.VK_J, CTRL_MASK, "jumpToLine");
163: mapKey(KeyEvent.VK_J, CTRL_MASK | SHIFT_MASK, "jumpToColumn");
164: mapKey(KeyEvent.VK_M, CTRL_MASK, "findMatchingChar");
165: mapKey(KeyEvent.VK_M, CTRL_MASK | SHIFT_MASK, "selectSyntax");
166: mapKey(KeyEvent.VK_UP, CTRL_MASK | ALT_MASK,
167: "findFirstOccurrence");
168: mapKey(KeyEvent.VK_KP_UP, CTRL_MASK | ALT_MASK,
169: "findFirstOccurrence");
170: mapKey(KeyEvent.VK_UP, ALT_MASK, "findPrevWord");
171: mapKey(KeyEvent.VK_KP_UP, ALT_MASK, "findPrevWord");
172: mapKey(KeyEvent.VK_DOWN, ALT_MASK, "findNextWord");
173: mapKey(KeyEvent.VK_KP_DOWN, ALT_MASK, "findNextWord");
174: mapKey(KeyEvent.VK_N, CTRL_MASK | ALT_MASK, "nextChange");
175: mapKey(KeyEvent.VK_P, CTRL_MASK | ALT_MASK, "previousChange");
176: mapKey(KeyEvent.VK_F5, 0, "pushPosition");
177: mapKey(KeyEvent.VK_F5, SHIFT_MASK, "popPosition");
178:
179: // Search menu.
180: if (Editor.preferences().getBooleanProperty(
181: Property.USE_INCREMENTAL_FIND))
182: mapKey(KeyEvent.VK_F, CTRL_MASK, "incrementalFind");
183: else
184: mapKey(KeyEvent.VK_F, CTRL_MASK, "find");
185: mapKey(KeyEvent.VK_F3, ALT_MASK, "find");
186:
187: mapKey(KeyEvent.VK_L, CTRL_MASK | ALT_MASK,
188: "listOccurrencesOfPatternAtDot");
189:
190: mapKey(KeyEvent.VK_F3, 0, "findNext");
191: mapKey(KeyEvent.VK_G, CTRL_MASK, "findNext");
192: mapKey(KeyEvent.VK_F3, SHIFT_MASK, "findPrev");
193: mapKey(KeyEvent.VK_H, CTRL_MASK, "findPrev");
194: mapKey(KeyEvent.VK_F6, 0, "findInFiles");
195: mapKey(KeyEvent.VK_F, CTRL_MASK | SHIFT_MASK, "findInFiles");
196: mapKey(KeyEvent.VK_L, CTRL_MASK, "listOccurrences");
197: mapKey(KeyEvent.VK_L, CTRL_MASK | SHIFT_MASK, "listFiles");
198: mapKey(KeyEvent.VK_R, CTRL_MASK, "replace");
199: mapKey(KeyEvent.VK_R, CTRL_MASK | SHIFT_MASK, "replaceInFiles");
200:
201: mapKey(KeyEvent.VK_K, CTRL_MASK, "killLine");
202: mapKey(KeyEvent.VK_DELETE, CTRL_MASK, "deleteWordRight");
203:
204: mapKey(KeyEvent.VK_HOME, 0, "home");
205: mapKey(KeyEvent.VK_END, 0, "end");
206: mapKey(KeyEvent.VK_HOME, SHIFT_MASK, "selectHome");
207: mapKey(KeyEvent.VK_END, SHIFT_MASK, "selectEnd");
208: mapKey(KeyEvent.VK_HOME, CTRL_MASK, "bob");
209: mapKey(KeyEvent.VK_HOME, CTRL_MASK | SHIFT_MASK, "selectBob");
210: mapKey(KeyEvent.VK_END, CTRL_MASK, "eob");
211: mapKey(KeyEvent.VK_END, CTRL_MASK | SHIFT_MASK, "selectEob");
212: mapKey(KeyEvent.VK_UP, 0, "up");
213: mapKey(KeyEvent.VK_KP_UP, 0, "up");
214: mapKey(KeyEvent.VK_DOWN, 0, "down");
215: mapKey(KeyEvent.VK_KP_DOWN, 0, "down");
216: mapKey(KeyEvent.VK_UP, SHIFT_MASK, "selectUp");
217: mapKey(KeyEvent.VK_KP_UP, SHIFT_MASK, "selectUp");
218: mapKey(KeyEvent.VK_DOWN, SHIFT_MASK, "selectDown");
219: mapKey(KeyEvent.VK_KP_DOWN, SHIFT_MASK, "selectDown");
220: mapKey(KeyEvent.VK_LEFT, 0, "left");
221: mapKey(KeyEvent.VK_KP_LEFT, 0, "left");
222: mapKey(KeyEvent.VK_RIGHT, 0, "right");
223: mapKey(KeyEvent.VK_KP_RIGHT, 0, "right");
224: mapKey(KeyEvent.VK_LEFT, SHIFT_MASK, "selectLeft");
225: mapKey(KeyEvent.VK_KP_LEFT, SHIFT_MASK, "selectLeft");
226: mapKey(KeyEvent.VK_RIGHT, SHIFT_MASK, "selectRight");
227: mapKey(KeyEvent.VK_KP_RIGHT, SHIFT_MASK, "selectRight");
228: mapKey(KeyEvent.VK_UP, CTRL_MASK, "windowUp");
229: mapKey(KeyEvent.VK_KP_UP, CTRL_MASK, "windowUp");
230: mapKey(KeyEvent.VK_DOWN, CTRL_MASK, "windowDown");
231: mapKey(KeyEvent.VK_KP_DOWN, CTRL_MASK, "windowDown");
232: mapKey(KeyEvent.VK_PAGE_UP, 0, "pageUp");
233: mapKey(KeyEvent.VK_PAGE_UP, ALT_MASK, "pageUpOtherWindow");
234: mapKey(KeyEvent.VK_PAGE_UP, SHIFT_MASK, "selectPageUp");
235: mapKey(KeyEvent.VK_PAGE_DOWN, 0, "pageDown");
236: mapKey(KeyEvent.VK_PAGE_DOWN, ALT_MASK, "pageDownOtherWindow");
237: mapKey(KeyEvent.VK_PAGE_DOWN, SHIFT_MASK, "selectPageDown");
238: mapKey(KeyEvent.VK_PAGE_UP, CTRL_MASK, "top");
239: mapKey(KeyEvent.VK_PAGE_DOWN, CTRL_MASK, "bottom");
240: mapKey(KeyEvent.VK_LEFT, CTRL_MASK, "wordLeft");
241: mapKey(KeyEvent.VK_KP_LEFT, CTRL_MASK, "wordLeft");
242: mapKey(KeyEvent.VK_RIGHT, CTRL_MASK, "wordRight");
243: mapKey(KeyEvent.VK_KP_RIGHT, CTRL_MASK, "wordRight");
244: mapKey(KeyEvent.VK_LEFT, CTRL_MASK | SHIFT_MASK,
245: "selectWordLeft");
246: mapKey(KeyEvent.VK_KP_LEFT, CTRL_MASK | SHIFT_MASK,
247: "selectWordLeft");
248: mapKey(KeyEvent.VK_RIGHT, CTRL_MASK | SHIFT_MASK,
249: "selectWordRight");
250: mapKey(KeyEvent.VK_KP_RIGHT, CTRL_MASK | SHIFT_MASK,
251: "selectWordRight");
252: mapKey(KeyEvent.VK_DELETE, 0, "delete");
253: mapKey(KeyEvent.VK_BACK_SPACE, 0, "backspace");
254: mapKey(KeyEvent.VK_BACK_SPACE, SHIFT_MASK, "backspace");
255: mapKey(KeyEvent.VK_BACK_SPACE, CTRL_MASK, "deleteWordLeft");
256: mapKey(KeyEvent.VK_ENTER, 0, "newline");
257:
258: mapKey(KeyEvent.VK_ESCAPE, 0, "escape");
259:
260: mapKey(KeyEvent.VK_G, CTRL_MASK | SHIFT_MASK, "gotoFile");
261: mapKey(KeyEvent.VK_B, CTRL_MASK | SHIFT_MASK, "browseFileAtDot");
262:
263: mapKey(KeyEvent.VK_D, CTRL_MASK, "dir");
264:
265: mapKey(KeyEvent.VK_F2, SHIFT_MASK, "stamp");
266:
267: mapKey(KeyEvent.VK_A, CTRL_MASK, "selectAll");
268:
269: mapKey(KeyEvent.VK_OPEN_BRACKET, ALT_MASK, "slideOut");
270: mapKey(KeyEvent.VK_CLOSE_BRACKET, ALT_MASK, "slideIn");
271:
272: // Bookmarks MUST be mapped like this!
273: mapKey(KeyEvent.VK_0, ALT_MASK, "dropBookmark");
274: mapKey(KeyEvent.VK_1, ALT_MASK, "dropBookmark");
275: mapKey(KeyEvent.VK_2, ALT_MASK, "dropBookmark");
276: mapKey(KeyEvent.VK_3, ALT_MASK, "dropBookmark");
277: mapKey(KeyEvent.VK_4, ALT_MASK, "dropBookmark");
278: mapKey(KeyEvent.VK_5, ALT_MASK, "dropBookmark");
279: mapKey(KeyEvent.VK_6, ALT_MASK, "dropBookmark");
280: mapKey(KeyEvent.VK_7, ALT_MASK, "dropBookmark");
281: mapKey(KeyEvent.VK_8, ALT_MASK, "dropBookmark");
282: mapKey(KeyEvent.VK_9, ALT_MASK, "dropBookmark");
283: mapKey(KeyEvent.VK_0, CTRL_MASK, "gotoBookmark");
284: mapKey(KeyEvent.VK_1, CTRL_MASK, "gotoBookmark");
285: mapKey(KeyEvent.VK_2, CTRL_MASK, "gotoBookmark");
286: mapKey(KeyEvent.VK_3, CTRL_MASK, "gotoBookmark");
287: mapKey(KeyEvent.VK_4, CTRL_MASK, "gotoBookmark");
288: mapKey(KeyEvent.VK_5, CTRL_MASK, "gotoBookmark");
289: mapKey(KeyEvent.VK_6, CTRL_MASK, "gotoBookmark");
290: mapKey(KeyEvent.VK_7, CTRL_MASK, "gotoBookmark");
291: mapKey(KeyEvent.VK_8, CTRL_MASK, "gotoBookmark");
292: mapKey(KeyEvent.VK_9, CTRL_MASK, "gotoBookmark");
293:
294: // Temporary marker commands.
295: mapKey(KeyEvent.VK_BACK_SLASH, ALT_MASK, "dropTemporaryMarker");
296: mapKey(KeyEvent.VK_BACK_SLASH, CTRL_MASK, "gotoTemporaryMarker");
297: mapKey(KeyEvent.VK_BACK_SLASH, CTRL_MASK | SHIFT_MASK,
298: "selectToTemporaryMarker");
299:
300: mapKey(KeyEvent.VK_F11, 0, "commentRegion");
301: mapKey(KeyEvent.VK_F11, SHIFT_MASK, "uncommentRegion");
302:
303: // Duplicate mappings to support IBM 1.3 for Linux.
304: mapKey(0xffc8, 0, "commentRegion");
305: mapKey(0xffc8, SHIFT_MASK, "uncommentRegion");
306:
307: mapKey(KeyEvent.VK_F12, 0, "wrapParagraph");
308: mapKey(KeyEvent.VK_F12, SHIFT_MASK, "unwrapParagraph");
309: mapKey(KeyEvent.VK_F12, CTRL_MASK, "toggleWrap");
310:
311: // Duplicate mappings to support IBM 1.3 for Linux.
312: mapKey(0xffc9, 0, "wrapParagraph"); // F12
313: mapKey(0xffc9, SHIFT_MASK, "unwrapParagraph"); // Shift F12
314: mapKey(0xffc9, CTRL_MASK, "toggleWrap"); // Ctrl F12
315:
316: mapKey(KeyEvent.VK_T, CTRL_MASK | ALT_MASK, "visibleTabs");
317:
318: // Help menu.
319: mapKey(KeyEvent.VK_F1, 0, "help");
320: mapKey(KeyEvent.VK_K, ALT_MASK, "describeKey");
321:
322: mapKey(KeyEvent.VK_SLASH, ALT_MASK, "expand");
323:
324: // On Windows, Alt Space drops down the window menu.
325: if (!Platform.isPlatformWindows())
326: mapKey(KeyEvent.VK_SPACE, ALT_MASK, "expand");
327:
328: mapKey(KeyEvent.VK_N, ALT_MASK, "nextFrame");
329:
330: mapKey(KeyEvent.VK_W, ALT_MASK, "selectWord");
331:
332: mapKey(VK_MOUSE_1, 0, "mouseMoveDotToPoint");
333: mapKey(VK_MOUSE_1, SHIFT_MASK, "mouseSelect");
334: mapKey(VK_MOUSE_1, CTRL_MASK | SHIFT_MASK, "mouseSelectColumn");
335: mapKey(VK_DOUBLE_MOUSE_1, 0, "selectWord");
336:
337: if (Platform.isPlatformUnix()) {
338: mapKey(VK_MOUSE_2, 0, "pastePrimarySelection");
339: mapKey(KeyEvent.VK_INSERT, SHIFT_MASK,
340: "pastePrimarySelection");
341: }
342:
343: mapKey(VK_MOUSE_3, 0, "mouseShowContextMenu");
344:
345: mapKey(KeyEvent.VK_F7, 0, "recordMacro");
346: mapKey(KeyEvent.VK_F8, 0, "playbackMacro");
347:
348: mapKey(KeyEvent.VK_W, CTRL_MASK | SHIFT_MASK, "killFrame");
349:
350: // Sidebar.
351: mapKey(KeyEvent.VK_EQUALS, ALT_MASK, "toggleSidebar");
352: mapKey(KeyEvent.VK_B, ALT_MASK, "sidebarListBuffers");
353: mapKey(KeyEvent.VK_T, CTRL_MASK | SHIFT_MASK, "sidebarListTags");
354:
355: mapKey(KeyEvent.VK_F10, 0, "splitWindow");
356: mapKey(KeyEvent.VK_F10, SHIFT_MASK, "unsplitWindow");
357: mapKey(KeyEvent.VK_F10, CTRL_MASK | SHIFT_MASK, "killWindow");
358: mapKey(KeyEvent.VK_O, ALT_MASK, "otherWindow");
359:
360: if (Editor.preferences().getBooleanProperty(
361: Property.ENABLE_EXPERIMENTAL_FEATURES))
362: mapKey(KeyEvent.VK_F9, ALT_MASK, "shell");
363:
364: // Map these globally so they're available in the compilation buffer too.
365: mapKey(KeyEvent.VK_F4, 0, "nextError");
366: mapKey(KeyEvent.VK_F4, SHIFT_MASK, "previousError");
367: mapKey(KeyEvent.VK_M, CTRL_MASK | ALT_MASK, "showMessage");
368:
369: // Windows VM seems to need this mapping for the tab key to work properly.
370: // There's also code in Dispatcher.dispatchKeyTyped to handle the tab key.
371: mapKey(KeyEvent.VK_TAB, 0, "insertTab");
372:
373: if (Platform.isPlatformLinux()) {
374: // These mappings work with Blackdown 1.2.2 (and 1.2 pre-release v2).
375: mapKey(0x2d, CTRL_MASK, "toCenter"); // Ctrl -
376: mapKey(0x5f, CTRL_MASK | SHIFT_MASK, "toTop"); // Ctrl Shift -
377:
378: // IBM 1.3, Sun 1.4.0 beta 2.
379: mapKey(0x2d, CTRL_MASK | SHIFT_MASK, "toTop"); // Ctrl Shift -
380: } else if (Platform.isPlatformWindows()) {
381: mapKey(0x2d, CTRL_MASK, "toCenter"); // Ctrl -
382: mapKey(0x2d, CTRL_MASK | SHIFT_MASK, "toTop"); // Ctrl Shift -
383: }
384: }
385:
386: public synchronized final KeyMapping lookup(char keyChar,
387: int keyCode, int modifiers) {
388: // Mask off the bits we don't care about (Java 1.4).
389: modifiers &= 0x0f;
390: if (keyCode == 0 && modifiers == 0) {
391: // This is the keyTyped() case. Ignore keyCode and modifiers;
392: // keyChar must match the mapping.
393: for (int i = mappings.size(); i-- > 0;) {
394: KeyMapping mapping = (KeyMapping) mappings.get(i);
395: if (keyChar == mapping.getKeyChar())
396: return mapping;
397: }
398: } else {
399: for (int i = mappings.size(); i-- > 0;) {
400: // This is the keyPressed() case. keyCode and modifiers must
401: // match the mapping. mapping.getKeyChar() must be zero, but
402: // we ignore the keyChar argument.
403: KeyMapping mapping = (KeyMapping) mappings.get(i);
404: if (mapping.getKeyChar() == 0
405: && keyCode == mapping.getKeyCode()
406: && modifiers == mapping.getModifiers())
407: return mapping;
408: }
409: }
410: return null;
411: }
412:
413: public synchronized final KeyMapping lookup(KeyStroke keyStroke) {
414: return lookup(keyStroke.getKeyChar(), keyStroke.getKeyCode(),
415: keyStroke.getModifiers());
416: }
417:
418: public synchronized final KeyMapping getKeyMapping(String command) {
419: command = command.intern();
420: for (int i = 0, limit = mappings.size(); i < limit; i++) {
421: KeyMapping mapping = (KeyMapping) mappings.get(i);
422: if (command == mapping.getCommand())
423: return mapping;
424: }
425: return null;
426: }
427:
428: public synchronized List listKeys(String command) {
429: command = command.intern();
430: ArrayList list = new ArrayList();
431: for (int i = mappings.size(); i-- > 0;) {
432: KeyMapping mapping = (KeyMapping) mappings.get(i);
433: if (command == mapping.getCommand())
434: list.add(mapping.getKeyText());
435: }
436: return list;
437: }
438:
439: // Add all mappings for command from source key map.
440: public synchronized void addMappingsForCommand(String command,
441: KeyMap source) {
442: command = command.intern();
443: final KeyMapping[] sourceMappings = source.getMappings();
444: final int limit = sourceMappings.length;
445: for (int i = 0; i < limit; i++) {
446: KeyMapping mapping = sourceMappings[i];
447: if (command == mapping.getCommand())
448: mappings.add(mapping);
449: }
450: }
451:
452: public synchronized void mapKey(int keyCode, int modifiers,
453: String command) {
454: // See if we already have a mapping for this keystroke.
455: for (int i = 0; i < mappings.size(); i++) {
456: KeyMapping mapping = (KeyMapping) mappings.get(i);
457: if (keyCode == mapping.getKeyCode()
458: && modifiers == mapping.getModifiers()) {
459: mappings.set(i, new KeyMapping(keyCode, modifiers,
460: command));
461: return;
462: }
463: }
464: // No mapping found.
465: mappings.add(new KeyMapping(keyCode, modifiers, command));
466: }
467:
468: public synchronized void mapKey(char keyChar, String command) {
469: // See if we already have a mapping for this keystroke.
470: for (int i = 0; i < mappings.size(); i++) {
471: KeyMapping mapping = (KeyMapping) mappings.get(i);
472: if (keyChar == mapping.getKeyChar()) {
473: mappings.set(i, new KeyMapping(keyChar, command));
474: return;
475: }
476: }
477: // No mapping found.
478: mappings.add(new KeyMapping(keyChar, command));
479: }
480:
481: // Only called from synchronized methods.
482: private boolean mapKey(String s) {
483: KeyMapping mapping = KeyMapping.createKeyMapping(s);
484: if (mapping != null) {
485: mappings.add(mapping);
486: return true;
487: }
488: return false;
489: }
490:
491: // For Lisp API.
492: public synchronized boolean mapKey(String keyText, Object command) {
493: KeyStroke keyStroke = Utilities.getKeyStroke(keyText);
494: if (keyStroke == null)
495: return false;
496: char keyChar = keyStroke.getKeyChar();
497: int keyCode = keyStroke.getKeyCode();
498: // Mask off the bits we don't care about (Java 1.4).
499: int modifiers = keyStroke.getModifiers() & 0x0f;
500: if (keyCode == 0 && modifiers == 0) {
501: // This is the keyTyped() case. Ignore keyCode and modifiers;
502: // keyChar must match the mapping.
503: for (int i = mappings.size(); i-- > 0;) {
504: KeyMapping mapping = (KeyMapping) mappings.get(i);
505: if (keyChar == mapping.getKeyChar()) {
506: mappings.set(i, new KeyMapping(keyChar, command));
507: return true;
508: }
509: }
510: // Not found.
511: mappings.add(new KeyMapping(keyChar, command));
512: } else {
513: for (int i = mappings.size(); i-- > 0;) {
514: // This is the keyPressed() case. keyCode and modifiers must
515: // match the mapping. mapping.getKeyChar() must be zero, but
516: // we ignore the keyChar argument.
517: KeyMapping mapping = (KeyMapping) mappings.get(i);
518: if (mapping.getKeyChar() == 0
519: && keyCode == mapping.getKeyCode()
520: && modifiers == mapping.getModifiers()) {
521: mappings.set(i, new KeyMapping(keyCode, modifiers,
522: command));
523: return true;
524: }
525: }
526: // Not found.
527: mappings.add(new KeyMapping(keyCode, modifiers, command));
528: }
529: return true;
530: }
531:
532: public synchronized void unmapKey(char keyChar) {
533: for (int i = 0; i < mappings.size(); i++) {
534: KeyMapping mapping = (KeyMapping) mappings.get(i);
535: if (keyChar == mapping.getKeyChar()) {
536: mappings.remove(i);
537: return;
538: }
539: }
540: }
541:
542: public synchronized void unmapKey(int keyCode, int modifiers) {
543: for (int i = 0; i < mappings.size(); i++) {
544: KeyMapping mapping = (KeyMapping) mappings.get(i);
545: if (keyCode == mapping.getKeyCode()
546: && modifiers == mapping.getModifiers()) {
547: mappings.remove(i);
548: return;
549: }
550: }
551: }
552:
553: // For Lisp API.
554: public synchronized boolean unmapKey(String keyText) {
555: KeyStroke keyStroke = Utilities.getKeyStroke(keyText);
556: if (keyStroke != null) {
557: char keyChar = keyStroke.getKeyChar();
558: int keyCode = keyStroke.getKeyCode();
559: // Mask off the bits we don't care about (Java 1.4).
560: int modifiers = keyStroke.getModifiers() & 0x0f;
561: if (keyCode == 0 && modifiers == 0) {
562: // This is the keyTyped() case. Ignore keyCode and modifiers;
563: // keyChar must match the mapping.
564: for (int i = mappings.size(); i-- > 0;) {
565: KeyMapping mapping = (KeyMapping) mappings.get(i);
566: if (keyChar == mapping.getKeyChar()) {
567: mappings.remove(i);
568: return true;
569: }
570: }
571: } else {
572: for (int i = mappings.size(); i-- > 0;) {
573: // This is the keyPressed() case. keyCode and modifiers must
574: // match the mapping. mapping.getKeyChar() must be zero, but
575: // we ignore the keyChar argument.
576: KeyMapping mapping = (KeyMapping) mappings.get(i);
577: if (mapping.getKeyChar() == 0
578: && keyCode == mapping.getKeyCode()
579: && modifiers == mapping.getModifiers()) {
580: mappings.remove(i);
581: return true;
582: }
583: }
584: }
585: }
586: return false;
587: }
588:
589: public synchronized void writeKeyMap(File file) {
590: try {
591: PrintWriter out = new PrintWriter(file.getOutputStream());
592: for (int i = 0; i < mappings.size(); i++)
593: out.println(mappings.get(i).toString());
594: out.close();
595: } catch (IOException e) {
596: Log.error(e);
597: }
598: }
599:
600: private static synchronized void useGlobalDefaults() {
601: globalKeyMap = new KeyMap();
602: globalKeyMap.setGlobalDefaults();
603: }
604:
605: public static void defaultKeyMaps() {
606: useGlobalDefaults();
607: for (Iterator it = Editor.getModeList().iterator(); it
608: .hasNext();) {
609: ModeListEntry entry = (ModeListEntry) it.next();
610: Mode mode = entry.getMode(false);
611: if (mode != null)
612: mode.useDefaultKeyMap();
613: }
614: }
615:
616: public static void reloadKeyMaps() {
617: deleteGlobalKeyMap();
618: for (Iterator it = Editor.getModeList().iterator(); it
619: .hasNext();) {
620: ModeListEntry entry = (ModeListEntry) it.next();
621: Mode mode = entry.getMode(false);
622: if (mode != null)
623: mode.deleteKeyMap();
624: }
625: }
626: }
|