0001: /*
0002: * jEdit.java - Main class of the jEdit editor
0003: * :tabSize=8:indentSize=8:noTabs=false:
0004: * :folding=explicit:collapseFolds=1:
0005: *
0006: * Copyright (C) 1998, 2005 Slava Pestov
0007: *
0008: * This program is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU General Public License
0010: * as published by the Free Software Foundation; either version 2
0011: * of the License, or any later version.
0012: * This program is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0015: * GNU General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * along with this program; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0020: */
0021:
0022: package org.gjt.sp.jedit;
0023:
0024: //{{{ Imports
0025: import org.gjt.sp.jedit.bsh.UtilEvalError;
0026: import javax.swing.*;
0027: import java.awt.event.KeyEvent;
0028: import java.awt.*;
0029: import java.io.*;
0030: import java.net.*;
0031: import java.text.MessageFormat;
0032: import java.util.*;
0033: import java.util.List;
0034:
0035: import org.xml.sax.SAXParseException;
0036:
0037: import org.gjt.sp.jedit.bufferio.BufferIORequest;
0038: import org.gjt.sp.jedit.buffer.KillRing;
0039: import org.gjt.sp.jedit.buffer.JEditBuffer;
0040: import org.gjt.sp.jedit.buffer.FoldHandler;
0041: import org.gjt.sp.jedit.msg.*;
0042: import org.gjt.sp.jedit.gui.*;
0043: import org.gjt.sp.jedit.gui.InputHandler;
0044: import org.gjt.sp.jedit.gui.DefaultInputHandler;
0045: import org.gjt.sp.jedit.help.HelpViewer;
0046: import org.gjt.sp.jedit.io.*;
0047: import org.gjt.sp.jedit.pluginmgr.PluginManager;
0048: import org.gjt.sp.jedit.search.SearchAndReplace;
0049: import org.gjt.sp.jedit.syntax.*;
0050: import org.gjt.sp.jedit.textarea.*;
0051: import org.gjt.sp.util.Log;
0052: import org.gjt.sp.util.StandardUtilities;
0053: import org.gjt.sp.util.XMLUtilities;
0054: import org.gjt.sp.util.IOUtilities;
0055:
0056: //}}}
0057:
0058: /**
0059: * The main class of the jEdit text editor.
0060: * @author Slava Pestov
0061: * @version $Id: jEdit.java 11204 2007-12-07 19:46:49Z k_satoda $
0062: */
0063: public class jEdit {
0064: //{{{ getVersion() method
0065: /**
0066: * Returns the jEdit version as a human-readable string.
0067: */
0068: public static String getVersion() {
0069: return MiscUtilities.buildToVersion(getBuild());
0070: } //}}}
0071:
0072: //{{{ getBuild() method
0073: /**
0074: * Returns the internal version. MiscUtilities.compareStrings() can be used
0075: * to compare different internal versions.
0076: */
0077: public static String getBuild() {
0078: // (major).(minor).(<99 = preX, 99 = final).(bug fix)
0079: return "04.03.12.00";
0080: } //}}}
0081:
0082: //{{{ main() method
0083: /**
0084: * The main method of the jEdit application.
0085: * This should never be invoked directly.
0086: * @param args The command line arguments
0087: */
0088: public static void main(String[] args) {
0089: //{{{ Check for Java 1.5 or later
0090: String javaVersion = System.getProperty("java.version");
0091: if (javaVersion.compareTo("1.5") < 0) {
0092: System.err.println("You are running Java version "
0093: + javaVersion + '.');
0094: System.err.println("jEdit requires Java 1.5 or later.");
0095: System.exit(1);
0096: } //}}}
0097:
0098: // later on we need to know if certain code is called from
0099: // the main thread
0100: mainThread = Thread.currentThread();
0101:
0102: settingsDirectory = ".jedit";
0103:
0104: // MacOS users expect the app to keep running after all windows
0105: // are closed
0106: background = OperatingSystem.isMacOS();
0107:
0108: //{{{ Parse command line
0109: boolean endOpts = false;
0110: int level = Log.WARNING;
0111: String portFile = "server";
0112: boolean restore = true;
0113: boolean newView = true;
0114: boolean newPlainView = false;
0115: boolean gui = true; // open initial view?
0116: boolean loadPlugins = true;
0117: boolean runStartupScripts = true;
0118: boolean quit = false;
0119: boolean wait = false;
0120: String userDir = System.getProperty("user.dir");
0121:
0122: // script to run
0123: String scriptFile = null;
0124:
0125: for (int i = 0; i < args.length; i++) {
0126: String arg = args[i];
0127: if (arg == null)
0128: continue;
0129: else if (arg.length() == 0)
0130: args[i] = null;
0131: else if (arg.startsWith("-") && !endOpts) {
0132: if (arg.equals("--"))
0133: endOpts = true;
0134: else if (arg.equals("-usage")) {
0135: version();
0136: System.err.println();
0137: usage();
0138: System.exit(1);
0139: } else if (arg.equals("-version")) {
0140: version();
0141: System.exit(1);
0142: } else if (arg.startsWith("-log=")) {
0143: try {
0144: level = Integer.parseInt(arg.substring("-log="
0145: .length()));
0146: } catch (NumberFormatException nf) {
0147: System.err.println("Malformed option: " + arg);
0148: }
0149: } else if (arg.equals("-nosettings"))
0150: settingsDirectory = null;
0151: else if (arg.startsWith("-settings="))
0152: settingsDirectory = arg.substring(10);
0153: else if (arg.startsWith("-noserver"))
0154: portFile = null;
0155: else if (arg.equals("-server"))
0156: portFile = "server";
0157: else if (arg.startsWith("-server="))
0158: portFile = arg.substring(8);
0159: else if (arg.startsWith("-background"))
0160: background = true;
0161: else if (arg.startsWith("-nobackground"))
0162: background = false;
0163: else if (arg.equals("-gui"))
0164: gui = true;
0165: else if (arg.equals("-nogui"))
0166: gui = false;
0167: else if (arg.equals("-newview"))
0168: newView = true;
0169: else if (arg.equals("-newplainview"))
0170: newPlainView = true;
0171: else if (arg.equals("-reuseview"))
0172: newPlainView = newView = false;
0173: else if (arg.equals("-restore"))
0174: restore = true;
0175: else if (arg.equals("-norestore"))
0176: restore = false;
0177: else if (arg.equals("-plugins"))
0178: loadPlugins = true;
0179: else if (arg.equals("-noplugins"))
0180: loadPlugins = false;
0181: else if (arg.equals("-startupscripts"))
0182: runStartupScripts = true;
0183: else if (arg.equals("-nostartupscripts"))
0184: runStartupScripts = false;
0185: else if (arg.startsWith("-run="))
0186: scriptFile = arg.substring(5);
0187: else if (arg.equals("-wait"))
0188: wait = true;
0189: else if (arg.equals("-quit"))
0190: quit = true;
0191: else {
0192: System.err.println("Unknown option: " + arg);
0193: usage();
0194: System.exit(1);
0195: }
0196: args[i] = null;
0197: }
0198: } //}}}
0199:
0200: //{{{ We need these initializations very early on
0201: if (settingsDirectory != null) {
0202: settingsDirectory = MiscUtilities.constructPath(System
0203: .getProperty("user.home"), settingsDirectory);
0204: settingsDirectory = MiscUtilities
0205: .resolveSymlinks(settingsDirectory);
0206: }
0207:
0208: if (settingsDirectory != null && portFile != null)
0209: portFile = MiscUtilities.constructPath(settingsDirectory,
0210: portFile);
0211: else
0212: portFile = null;
0213:
0214: Log.init(true, level);
0215: //}}}
0216:
0217: //{{{ Try connecting to another running jEdit instance
0218: if (portFile != null && new File(portFile).exists()) {
0219: try {
0220: BufferedReader in = new BufferedReader(new FileReader(
0221: portFile));
0222: String check = in.readLine();
0223: if (!check.equals("b"))
0224: throw new Exception("Wrong port file format");
0225:
0226: int port = Integer.parseInt(in.readLine());
0227: int key = Integer.parseInt(in.readLine());
0228:
0229: Socket socket = new Socket(InetAddress
0230: .getByName("127.0.0.1"), port);
0231: DataOutputStream out = new DataOutputStream(socket
0232: .getOutputStream());
0233: out.writeInt(key);
0234:
0235: String script;
0236: if (quit) {
0237: script = "socket.close();\n"
0238: + "jEdit.exit(null,true);\n";
0239: } else {
0240: script = makeServerScript(wait, restore, newView,
0241: newPlainView, args, scriptFile);
0242: }
0243:
0244: out.writeUTF(script);
0245:
0246: Log.log(Log.DEBUG, jEdit.class, "Waiting for server");
0247: // block until its closed
0248: try {
0249: socket.getInputStream().read();
0250: } catch (Exception e) {
0251: }
0252:
0253: in.close();
0254: out.close();
0255:
0256: System.exit(0);
0257: } catch (Exception e) {
0258: // ok, this one seems to confuse newbies
0259: // endlessly, so log it as NOTICE, not
0260: // ERROR
0261: Log
0262: .log(
0263: Log.NOTICE,
0264: jEdit.class,
0265: "An error occurred"
0266: + " while connecting to the jEdit server instance.");
0267: Log
0268: .log(
0269: Log.NOTICE,
0270: jEdit.class,
0271: "This probably means that"
0272: + " jEdit crashed and/or exited abnormally");
0273: Log.log(Log.NOTICE, jEdit.class,
0274: "the last time it was run.");
0275: Log.log(Log.NOTICE, jEdit.class, "If you don't"
0276: + " know what this means, don't worry.");
0277: Log.log(Log.NOTICE, jEdit.class, e);
0278: }
0279: }
0280:
0281: if (quit) {
0282: // if no server running and user runs jedit -quit,
0283: // just exit
0284: System.exit(0);
0285: } //}}}
0286:
0287: // don't show splash screen if there is a file named
0288: // 'nosplash' in the settings directory
0289: if (!new File(settingsDirectory, "nosplash").exists())
0290: GUIUtilities.showSplashScreen();
0291:
0292: //{{{ Initialize settings directory
0293: Writer stream;
0294: if (settingsDirectory != null) {
0295: File _settingsDirectory = new File(settingsDirectory);
0296: if (!_settingsDirectory.exists())
0297: _settingsDirectory.mkdirs();
0298: File _macrosDirectory = new File(settingsDirectory,
0299: "macros");
0300: if (!_macrosDirectory.exists())
0301: _macrosDirectory.mkdir();
0302:
0303: String logPath = MiscUtilities.constructPath(
0304: settingsDirectory, "activity.log");
0305:
0306: backupSettingsFile(new File(logPath));
0307:
0308: try {
0309: stream = new BufferedWriter(new FileWriter(logPath));
0310:
0311: // Write a warning message:
0312: String lineSep = System.getProperty("line.separator");
0313: stream.write("Log file created on " + new Date());
0314: stream.write(lineSep);
0315: stream.write("IMPORTANT:");
0316: stream.write(lineSep);
0317: stream.write("Because updating this file after "
0318: + "every log message would kill");
0319: stream.write(lineSep);
0320: stream.write("performance, it will be *incomplete* "
0321: + "unless you invoke the");
0322: stream.write(lineSep);
0323: stream.write("Utilities->Troubleshooting->Update "
0324: + "Activity Log on Disk command!");
0325: stream.write(lineSep);
0326: } catch (Exception e) {
0327: e.printStackTrace();
0328: stream = null;
0329: }
0330: } else {
0331: stream = null;
0332: } //}}}
0333:
0334: Log.setLogWriter(stream);
0335:
0336: Log.log(Log.NOTICE, jEdit.class, "jEdit version "
0337: + getVersion());
0338: Log.log(Log.MESSAGE, jEdit.class, "Settings directory is "
0339: + settingsDirectory);
0340:
0341: //{{{ Get things rolling
0342: GUIUtilities.advanceSplashProgress("init");
0343: initMisc();
0344: GUIUtilities.advanceSplashProgress("init system properties");
0345: initSystemProperties();
0346:
0347: GUIUtilities.advanceSplashProgress("init GUI");
0348: GUIUtilities.init();
0349: GUIUtilities.advanceSplashProgress("init beanshell");
0350: BeanShell.init();
0351:
0352: GUIUtilities.advanceSplashProgress("loading site properties");
0353: if (jEditHome != null)
0354: initSiteProperties();
0355:
0356: GUIUtilities.advanceSplashProgress("loading user properties");
0357: initUserProperties();
0358: Options.SIMPLIFIED_KEY_HANDLING = jEdit
0359: .getBooleanProperty("newkeyhandling");
0360: //}}}
0361:
0362: //{{{ Initialize server
0363: if (portFile != null) {
0364: GUIUtilities.advanceSplashProgress("init server");
0365: server = new EditServer(portFile);
0366: if (!server.isOK())
0367: server = null;
0368: } else {
0369: GUIUtilities.advanceSplashProgress();
0370: if (background) {
0371: background = false;
0372: Log
0373: .log(
0374: Log.WARNING,
0375: jEdit.class,
0376: "You cannot specify both the"
0377: + " -background and -noserver switches");
0378: }
0379: } //}}}
0380:
0381: //{{{ Do more stuff
0382: GUIUtilities.advanceSplashProgress("init look and feel");
0383: initPLAF();
0384: GUIUtilities.advanceSplashProgress("init VFS Manager");
0385: VFSManager.init();
0386: GUIUtilities.advanceSplashProgress("init resources");
0387: initResources();
0388: SearchAndReplace.load();
0389:
0390: if (loadPlugins) {
0391: GUIUtilities.advanceSplashProgress("init plugins");
0392: initPlugins();
0393: } else
0394: GUIUtilities.advanceSplashProgress();
0395:
0396: Registers.setSaver(new JEditRegisterSaver());
0397: Registers.setListener(new JEditRegistersListener());
0398: GUIUtilities.advanceSplashProgress("init history model");
0399: HistoryModel.setSaver(new JEditHistoryModelSaver());
0400: HistoryModel.loadHistory();
0401: GUIUtilities.advanceSplashProgress("init buffer history");
0402: BufferHistory.load();
0403: GUIUtilities.advanceSplashProgress("init killring");
0404: KillRing.setInstance(new JEditKillRing());
0405: KillRing.getInstance().load();
0406: GUIUtilities.advanceSplashProgress("init various properties");
0407: propertiesChanged();
0408:
0409: GUIUtilities.advanceSplashProgress("init modes");
0410:
0411: // Buffer sort
0412: sortBuffers = getBooleanProperty("sortBuffers");
0413: sortByName = getBooleanProperty("sortByName");
0414:
0415: reloadModes();
0416:
0417: GUIUtilities.advanceSplashProgress("activate plugins");
0418: //}}}
0419:
0420: //{{{ Activate plugins that must be activated at startup
0421: for (int i = 0; i < jars.size(); i++) {
0422: jars.elementAt(i).activatePluginIfNecessary();
0423: } //}}}
0424:
0425: //{{{ Load macros and run startup scripts, after plugins and settings are loaded
0426: GUIUtilities.advanceSplashProgress("init macros");
0427: Macros.loadMacros();
0428: Macros.getMacroActionSet().initKeyBindings();
0429:
0430: if (runStartupScripts && jEditHome != null) {
0431: String path = MiscUtilities.constructPath(jEditHome,
0432: "startup");
0433: File file = new File(path);
0434: if (file.exists()) {
0435: runStartupScripts(file);
0436: } else
0437: GUIUtilities.advanceSplashProgress();
0438: } else
0439: GUIUtilities.advanceSplashProgress("run startup scripts");
0440:
0441: if (runStartupScripts && settingsDirectory != null) {
0442: String path = MiscUtilities.constructPath(
0443: settingsDirectory, "startup");
0444: File file = new File(path);
0445: if (file.exists()) {
0446: GUIUtilities
0447: .advanceSplashProgress("run startup scripts");
0448: runStartupScripts(file);
0449: } else {
0450: GUIUtilities.advanceSplashProgress();
0451: file.mkdirs();
0452: }
0453: } else {
0454: GUIUtilities.advanceSplashProgress();
0455: } //}}}
0456:
0457: //{{{ Run script specified with -run= parameter
0458: if (scriptFile != null) {
0459: GUIUtilities.advanceSplashProgress("run script file");
0460: scriptFile = MiscUtilities.constructPath(userDir,
0461: scriptFile);
0462: try {
0463: BeanShell.getNameSpace().setVariable("args", args);
0464: } catch (UtilEvalError e) {
0465: Log.log(Log.ERROR, jEdit.class, e);
0466: }
0467: BeanShell.runScript(null, scriptFile, null, false);
0468: } else {
0469: GUIUtilities.advanceSplashProgress();
0470: }
0471: //}}}
0472:
0473: GUIUtilities.advanceSplashProgress();
0474:
0475: // Open files, create the view and hide the splash screen.
0476: finishStartup(gui, restore, userDir, args);
0477: } //}}}
0478:
0479: //{{{ Property methods
0480:
0481: //{{{ getProperties() method
0482: /**
0483: * Returns the properties object which contains all known
0484: * jEdit properties. Note that as of jEdit 4.2pre10, this returns a
0485: * new collection, not the existing properties instance.
0486: * @since jEdit 3.1pre4
0487: */
0488: public static final Properties getProperties() {
0489: return propMgr.getProperties();
0490: } //}}}
0491:
0492: //{{{ getProperty() method
0493: /**
0494: * Fetches a property, returning null if it's not defined.
0495: * @param name The property
0496: */
0497: public static final String getProperty(String name) {
0498: return propMgr.getProperty(name);
0499: } //}}}
0500:
0501: //{{{ getProperty() method
0502: /**
0503: * Fetches a property, returning the default value if it's not
0504: * defined.
0505: * @param name The property
0506: * @param def The default value
0507: */
0508: public static final String getProperty(String name, String def) {
0509: String value = propMgr.getProperty(name);
0510: if (value == null)
0511: return def;
0512: else
0513: return value;
0514: } //}}}
0515:
0516: //{{{ getProperty() method
0517: /**
0518: * Returns the property with the specified name.<p>
0519: *
0520: * The elements of the <code>args</code> array are substituted
0521: * into the value of the property in place of strings of the
0522: * form <code>{<i>n</i>}</code>, where <code><i>n</i></code> is an index
0523: * in the array.<p>
0524: *
0525: * You can find out more about this feature by reading the
0526: * documentation for the <code>format</code> method of the
0527: * <code>java.text.MessageFormat</code> class.
0528: *
0529: * @param name The property
0530: * @param args The positional parameters
0531: */
0532: public static final String getProperty(String name, Object[] args) {
0533: if (name == null)
0534: return null;
0535: if (args == null)
0536: return getProperty(name);
0537: else {
0538: String value = getProperty(name);
0539: if (value == null)
0540: return null;
0541: else
0542: return MessageFormat.format(value, args);
0543: }
0544: } //}}}
0545:
0546: //{{{ getBooleanProperty() method
0547: /**
0548: * Returns the value of a boolean property.
0549: * @param name The property
0550: */
0551: public static final boolean getBooleanProperty(String name) {
0552: return getBooleanProperty(name, false);
0553: } //}}}
0554:
0555: //{{{ getBooleanProperty() method
0556: /**
0557: * Returns the value of a boolean property.
0558: * @param name The property
0559: * @param def The default value
0560: */
0561: public static final boolean getBooleanProperty(String name,
0562: boolean def) {
0563: String value = getProperty(name);
0564: if (value == null)
0565: return def;
0566: else if (value.equals("true") || value.equals("yes")
0567: || value.equals("on"))
0568: return true;
0569: else if (value.equals("false") || value.equals("no")
0570: || value.equals("off"))
0571: return false;
0572: else
0573: return def;
0574: } //}}}
0575:
0576: //{{{ getIntegerProperty() method
0577: /**
0578: * Returns the value of an integer property.
0579: * @param name The property
0580: */
0581: public static final int getIntegerProperty(String name) {
0582: return getIntegerProperty(name, 0);
0583: } //}}}
0584:
0585: //{{{ getIntegerProperty() method
0586: /**
0587: * Returns the value of an integer property.
0588: * @param name The property
0589: * @param def The default value
0590: * @since jEdit 4.0pre1
0591: */
0592: public static final int getIntegerProperty(String name, int def) {
0593: String value = getProperty(name);
0594: if (value == null)
0595: return def;
0596: else {
0597: try {
0598: return Integer.parseInt(value.trim());
0599: } catch (NumberFormatException nf) {
0600: return def;
0601: }
0602: }
0603: } //}}}
0604:
0605: //{{{ getDoubleProperty() method
0606: public static double getDoubleProperty(String name, double def) {
0607: String value = getProperty(name);
0608: if (value == null)
0609: return def;
0610: else {
0611: try {
0612: return Double.parseDouble(value.trim());
0613: } catch (NumberFormatException nf) {
0614: return def;
0615: }
0616: }
0617: }
0618:
0619: //}}}
0620:
0621: //{{{ getFontProperty() method
0622: /**
0623: * Returns the value of a font property. The family is stored
0624: * in the <code><i>name</i></code> property, the font size is stored
0625: * in the <code><i>name</i>size</code> property, and the font style is
0626: * stored in <code><i>name</i>style</code>. For example, if
0627: * <code><i>name</i></code> is <code>view.gutter.font</code>, the
0628: * properties will be named <code>view.gutter.font</code>,
0629: * <code>view.gutter.fontsize</code>, and
0630: * <code>view.gutter.fontstyle</code>.
0631: *
0632: * @param name The property
0633: * @since jEdit 4.0pre1
0634: */
0635: public static final Font getFontProperty(String name) {
0636: return getFontProperty(name, null);
0637: } //}}}
0638:
0639: //{{{ getFontProperty() method
0640: /**
0641: * Returns the value of a font property. The family is stored
0642: * in the <code><i>name</i></code> property, the font size is stored
0643: * in the <code><i>name</i>size</code> property, and the font style is
0644: * stored in <code><i>name</i>style</code>. For example, if
0645: * <code><i>name</i></code> is <code>view.gutter.font</code>, the
0646: * properties will be named <code>view.gutter.font</code>,
0647: * <code>view.gutter.fontsize</code>, and
0648: * <code>view.gutter.fontstyle</code>.
0649: *
0650: * @param name The property
0651: * @param def The default value
0652: * @since jEdit 4.0pre1
0653: */
0654: public static final Font getFontProperty(String name, Font def) {
0655: String family = getProperty(name);
0656: String sizeString = getProperty(name + "size");
0657: String styleString = getProperty(name + "style");
0658:
0659: if (family == null || sizeString == null || styleString == null)
0660: return def;
0661: else {
0662: int size, style;
0663:
0664: try {
0665: size = Integer.parseInt(sizeString);
0666: } catch (NumberFormatException nf) {
0667: return def;
0668: }
0669:
0670: try {
0671: style = Integer.parseInt(styleString);
0672: } catch (NumberFormatException nf) {
0673: return def;
0674: }
0675:
0676: return new Font(family, style, size);
0677: }
0678: } //}}}
0679:
0680: //{{{ getColorProperty() method
0681: /**
0682: * Returns the value of a color property.
0683: * @param name The property name
0684: * @since jEdit 4.0pre1
0685: */
0686: public static Color getColorProperty(String name) {
0687: return getColorProperty(name, Color.black);
0688: } //}}}
0689:
0690: //{{{ getColorProperty() method
0691: /**
0692: * Returns the value of a color property.
0693: * @param name The property name
0694: * @param def The default value
0695: * @since jEdit 4.0pre1
0696: */
0697: public static Color getColorProperty(String name, Color def) {
0698: String value = getProperty(name);
0699: if (value == null)
0700: return def;
0701: else
0702: return GUIUtilities.parseColor(value, def);
0703: } //}}}
0704:
0705: //{{{ setColorProperty() method
0706: /**
0707: * Sets the value of a color property.
0708: * @param name The property name
0709: * @param value The value
0710: * @since jEdit 4.0pre1
0711: */
0712: public static void setColorProperty(String name, Color value) {
0713: setProperty(name, GUIUtilities.getColorHexString(value));
0714: } //}}}
0715:
0716: //{{{ setProperty() method
0717: /**
0718: * Sets a property to a new value.
0719: * @param name The property
0720: * @param value The new value
0721: */
0722: public static final void setProperty(String name, String value) {
0723: propMgr.setProperty(name, value);
0724: } //}}}
0725:
0726: //{{{ setTemporaryProperty() method
0727: /**
0728: * Sets a property to a new value. Properties set using this
0729: * method are not saved to the user properties list.
0730: * @param name The property
0731: * @param value The new value
0732: * @since jEdit 2.3final
0733: */
0734: public static final void setTemporaryProperty(String name,
0735: String value) {
0736: propMgr.setTemporaryProperty(name, value);
0737: } //}}}
0738:
0739: //{{{ setBooleanProperty() method
0740: /**
0741: * Sets a boolean property.
0742: * @param name The property
0743: * @param value The value
0744: */
0745: public static final void setBooleanProperty(String name,
0746: boolean value) {
0747: setProperty(name, value ? "true" : "false");
0748: } //}}}
0749:
0750: //{{{ setIntegerProperty() method
0751: /**
0752: * Sets the value of an integer property.
0753: * @param name The property
0754: * @param value The value
0755: * @since jEdit 4.0pre1
0756: */
0757: public static final void setIntegerProperty(String name, int value) {
0758: setProperty(name, String.valueOf(value));
0759: } //}}}
0760:
0761: //{{{ setDoubleProperty() method
0762: public static final void setDoubleProperty(String name, double value) {
0763: setProperty(name, String.valueOf(value));
0764: }
0765:
0766: //}}}
0767:
0768: //{{{ setFontProperty() method
0769: /**
0770: * Sets the value of a font property. The family is stored
0771: * in the <code><i>name</i></code> property, the font size is stored
0772: * in the <code><i>name</i>size</code> property, and the font style is
0773: * stored in <code><i>name</i>style</code>. For example, if
0774: * <code><i>name</i></code> is <code>view.gutter.font</code>, the
0775: * properties will be named <code>view.gutter.font</code>,
0776: * <code>view.gutter.fontsize</code>, and
0777: * <code>view.gutter.fontstyle</code>.
0778: *
0779: * @param name The property
0780: * @param value The value
0781: * @since jEdit 4.0pre1
0782: */
0783: public static final void setFontProperty(String name, Font value) {
0784: setProperty(name, value.getFamily());
0785: setIntegerProperty(name + "size", value.getSize());
0786: setIntegerProperty(name + "style", value.getStyle());
0787: } //}}}
0788:
0789: //{{{ unsetProperty() method
0790: /**
0791: * Unsets (clears) a property.
0792: * @param name The property
0793: */
0794: public static final void unsetProperty(String name) {
0795: propMgr.unsetProperty(name);
0796: } //}}}
0797:
0798: //{{{ resetProperty() method
0799: /**
0800: * Resets a property to its default value.
0801: * @param name The property
0802: *
0803: * @since jEdit 2.5pre3
0804: */
0805: public static final void resetProperty(String name) {
0806: propMgr.resetProperty(name);
0807: } //}}}
0808:
0809: //{{{ propertiesChanged() method
0810: /**
0811: * Reloads various settings from the properties.
0812: */
0813: public static void propertiesChanged() {
0814: initKeyBindings();
0815:
0816: Autosave.setInterval(getIntegerProperty("autosave", 30));
0817:
0818: saveCaret = getBooleanProperty("saveCaret");
0819:
0820: UIDefaults defaults = UIManager.getDefaults();
0821:
0822: // give all text areas the same font
0823: Font font = getFontProperty("view.font");
0824:
0825: //defaults.put("TextField.font",font);
0826: defaults.put("TextArea.font", font);
0827: defaults.put("TextPane.font", font);
0828:
0829: // Enable/Disable tooltips
0830: ToolTipManager.sharedInstance().setEnabled(
0831: jEdit.getBooleanProperty("showTooltips"));
0832:
0833: initProxy();
0834:
0835: // we do this here instead of adding buffers to the bus.
0836: Buffer buffer = buffersFirst;
0837: while (buffer != null) {
0838: buffer.resetCachedProperties();
0839: buffer.propertiesChanged();
0840: buffer = buffer.next;
0841: }
0842:
0843: HistoryModel.setMax(getIntegerProperty("history", 25));
0844: KillRing.getInstance().propertiesChanged(
0845: getIntegerProperty("history", 25));
0846:
0847: EditBus.send(new PropertiesChanged(null));
0848: } //}}}
0849:
0850: //}}}
0851:
0852: //{{{ Plugin management methods
0853:
0854: //{{{ getNotLoadedPluginJARs() method
0855: /**
0856: * Returns a list of plugin JARs pathnames that are not currently loaded
0857: * by examining the user and system plugin directories.
0858: * @since jEdit 3.2pre1
0859: */
0860: public static String[] getNotLoadedPluginJARs() {
0861: List<String> returnValue = new ArrayList<String>();
0862:
0863: if (jEditHome != null) {
0864: String systemPluginDir = MiscUtilities.constructPath(
0865: jEditHome, "jars");
0866:
0867: String[] list = new File(systemPluginDir).list();
0868: if (list != null)
0869: getNotLoadedPluginJARs(returnValue, systemPluginDir,
0870: list);
0871: }
0872:
0873: if (settingsDirectory != null) {
0874: String userPluginDir = MiscUtilities.constructPath(
0875: settingsDirectory, "jars");
0876: String[] list = new File(userPluginDir).list();
0877: if (list != null) {
0878: getNotLoadedPluginJARs(returnValue, userPluginDir, list);
0879: }
0880: }
0881:
0882: String[] _returnValue = new String[returnValue.size()];
0883: returnValue.toArray(_returnValue);
0884: return _returnValue;
0885: } //}}}
0886:
0887: //{{{ getPlugin() method
0888: /**
0889: * Returns the plugin with the specified class name.
0890: * Only works for plugins that were loaded.
0891: */
0892: public static EditPlugin getPlugin(String name) {
0893: return getPlugin(name, false);
0894: } //}}}
0895:
0896: //{{{ getPlugin(String, boolean) method
0897: /**
0898: * Returns the plugin with the specified class name.
0899: * If * <code>loadIfNecessary</code> is true, the plugin will be searched for,
0900: * loaded, and activated in case it has not yet been loaded.
0901: *
0902: * @param name the classname of the main Plugin class.
0903: * @param loadIfNecessary - loads plugin + dependencies if it is not loaded yet.
0904: * @since jEdit 4.2pre4
0905: */
0906: public static EditPlugin getPlugin(String name,
0907: boolean loadIfNecessary) {
0908: EditPlugin[] plugins = getPlugins();
0909: EditPlugin plugin = null;
0910: for (int i = 0; i < plugins.length; i++) {
0911: if (plugins[i].getClassName().equals(name))
0912: plugin = plugins[i];
0913: if (loadIfNecessary) {
0914: if (plugin instanceof EditPlugin.Deferred) {
0915: plugin.getPluginJAR().activatePlugin();
0916: plugin = plugin.getPluginJAR().getPlugin();
0917: break;
0918: }
0919: }
0920: }
0921: if (!loadIfNecessary)
0922: return plugin;
0923: String jarPath = PluginJAR.findPlugin(name);
0924: PluginJAR pjar = PluginJAR.load(jarPath, true);
0925: return pjar.getPlugin();
0926: } //}}}
0927:
0928: //{{{ getPlugins() method
0929: /**
0930: * Returns an array of installed plugins.
0931: */
0932: public static EditPlugin[] getPlugins() {
0933: List<EditPlugin> vector = new ArrayList<EditPlugin>();
0934: for (int i = 0; i < jars.size(); i++) {
0935: EditPlugin plugin = jars.elementAt(i).getPlugin();
0936: if (plugin != null)
0937: vector.add(plugin);
0938: }
0939:
0940: EditPlugin[] array = new EditPlugin[vector.size()];
0941: vector.toArray(array);
0942: return array;
0943: } //}}}
0944:
0945: //{{{ getPluginJARs() method
0946: /**
0947: * Returns an array of installed plugins.
0948: * @since jEdit 4.2pre1
0949: */
0950: public static PluginJAR[] getPluginJARs() {
0951: PluginJAR[] array = new PluginJAR[jars.size()];
0952: jars.copyInto(array);
0953: return array;
0954: } //}}}
0955:
0956: //{{{ getPluginJAR() method
0957: /**
0958: * Returns the JAR with the specified path name.
0959: * @param path The path name
0960: * @since jEdit 4.2pre1
0961: */
0962: public static PluginJAR getPluginJAR(String path) {
0963: for (int i = 0; i < jars.size(); i++) {
0964: PluginJAR jar = jars.elementAt(i);
0965: if (jar.getPath().equals(path))
0966: return jar;
0967: }
0968:
0969: return null;
0970: } //}}}
0971:
0972: //{{{ addPluginJAR() method
0973: /**
0974: * Loads the plugin JAR with the specified path. Some notes about this
0975: * method:
0976: *
0977: * <ul>
0978: * <li>Calling this at a time other than jEdit startup can have
0979: * unpredictable results if the plugin has not been updated for the
0980: * jEdit 4.2 plugin API.
0981: * <li>You must make sure yourself the plugin is not already loaded.
0982: * <li>After loading, you just make sure all the plugin's dependencies
0983: * are satisified before activating the plugin, using the
0984: * {@link PluginJAR#checkDependencies()} method.
0985: * </ul>
0986: *
0987: * @param path The JAR file path
0988: * @since jEdit 4.2pre1
0989: */
0990: public static void addPluginJAR(String path) {
0991: PluginJAR jar = new PluginJAR(new File(path));
0992: jars.addElement(jar);
0993: jar.init();
0994: jEdit.unsetProperty("plugin-blacklist."
0995: + MiscUtilities.getFileName(path));
0996: EditBus.send(new PluginUpdate(jar, PluginUpdate.LOADED, false));
0997: if (!isMainThread()) {
0998: EditBus.send(new DynamicMenuChanged("plugins"));
0999: initKeyBindings();
1000: }
1001: } //}}}
1002:
1003: //{{{ addPluginJARsFromDirectory() method
1004: /**
1005: * Loads all plugins in a directory.
1006: * @param directory The directory
1007: * @since jEdit 4.2pre1
1008: */
1009: private static void addPluginJARsFromDirectory(String directory) {
1010: Log.log(Log.NOTICE, jEdit.class, "Loading plugins from "
1011: + directory);
1012:
1013: File file = new File(directory);
1014: if (!(file.exists() && file.isDirectory()))
1015: return;
1016: String[] plugins = file.list();
1017: if (plugins == null)
1018: return;
1019:
1020: for (int i = 0; i < plugins.length; i++) {
1021: String plugin = plugins[i];
1022: if (!plugin.toLowerCase().endsWith(".jar"))
1023: continue;
1024:
1025: String path = MiscUtilities
1026: .constructPath(directory, plugin);
1027: if (jEdit.getBooleanProperty("plugin-blacklist." + plugin))
1028: continue;
1029: // remove this when 4.1 plugin API is deprecated
1030: if (plugin.equals("EditBuddy.jar")
1031: || plugin.equals("PluginManager.jar")
1032: || plugin.equals("Firewall.jar")
1033: || plugin.equals("Tidy.jar")
1034: || plugin.equals("DragAndDrop.jar")) {
1035: pluginError(path, "plugin-error.obsolete", null);
1036: continue;
1037: }
1038:
1039: addPluginJAR(path);
1040: }
1041: } //}}}
1042:
1043: //{{{ removePluginJAR() method
1044: /**
1045: * Unloads the given plugin JAR with the specified path. Note that
1046: * calling this at a time other than jEdit shutdown can have
1047: * unpredictable results if the plugin has not been updated for the
1048: * jEdit 4.2 plugin API.
1049: *
1050: * @param jar The <code>PluginJAR</code> instance
1051: * @param exit Set to true if jEdit is exiting; enables some
1052: * shortcuts so the editor can close faster.
1053: * @since jEdit 4.2pre1
1054: */
1055: public static void removePluginJAR(PluginJAR jar, boolean exit) {
1056: if (exit) {
1057: jar.uninit(true);
1058: } else {
1059: jar.uninit(false);
1060: jars.removeElement(jar);
1061: initKeyBindings();
1062: }
1063:
1064: EditBus
1065: .send(new PluginUpdate(jar, PluginUpdate.UNLOADED, exit));
1066: if (!isMainThread() && !exit)
1067: EditBus.send(new DynamicMenuChanged("plugins"));
1068: } //}}}
1069:
1070: //}}}
1071:
1072: //{{{ Action methods
1073:
1074: //{{{ getActionContext() method
1075: /**
1076: * Returns the action context used to store editor actions.
1077: * @since jEdit 4.2pre1
1078: */
1079: public static ActionContext getActionContext() {
1080: return actionContext;
1081: } //}}}
1082:
1083: //{{{ addActionSet() method
1084: /**
1085: * Adds a new action set to jEdit's list of ActionSets (viewable from the shortcuts
1086: * option pane). By default, each plugin has one ActionSet,
1087: * but some plugins may create dynamic action sets, such as ProjectViewer and Console.
1088: * These plugins must call removeActionSet() when the plugin is unloaded.
1089: *
1090: * @since jEdit 4.0pre1
1091: * @see #removeActionSet(ActionSet)
1092: */
1093: public static void addActionSet(ActionSet actionSet) {
1094: actionContext.addActionSet(actionSet);
1095: } //}}}
1096:
1097: //{{{ removeActionSet() method
1098: /**
1099: * Removes an action set from jEdit's list.
1100: * Plugins that add a dynamic action set must call this method at plugin
1101: * unload time.
1102: * @since jEdit 4.2pre1
1103: */
1104: public static void removeActionSet(ActionSet actionSet) {
1105: actionContext.removeActionSet(actionSet);
1106: } //}}}
1107:
1108: //{{{ getBuiltInActionSet() method
1109: /**
1110: * Returns the set of commands built into jEdit.
1111: * @since jEdit 4.2pre1
1112: */
1113: public static ActionSet getBuiltInActionSet() {
1114: return builtInActionSet;
1115: } //}}}
1116:
1117: //{{{ getActionSets() method
1118: /**
1119: * Returns all registered action sets.
1120: * @since jEdit 4.0pre1
1121: */
1122: public static ActionSet[] getActionSets() {
1123: return actionContext.getActionSets();
1124: } //}}}
1125:
1126: //{{{ getAction() method
1127: /**
1128: * Returns the specified action.
1129: * @param name The action name
1130: */
1131: public static EditAction getAction(String name) {
1132: return actionContext.getAction(name);
1133: } //}}}
1134:
1135: //{{{ getActionSetForAction() method
1136: /**
1137: * Returns the action set that contains the specified action.
1138: *
1139: * @param action The action
1140: * @since jEdit 4.2pre1
1141: */
1142: public static ActionSet getActionSetForAction(String action) {
1143: return actionContext.getActionSetForAction(action);
1144: } //}}}
1145:
1146: //{{{ getActionSetForAction() method
1147: /**
1148: * @deprecated Use the form that takes a String instead
1149: */
1150: public static ActionSet getActionSetForAction(EditAction action) {
1151: return actionContext.getActionSetForAction(action.getName());
1152: } //}}}
1153:
1154: //{{{ getActions() method
1155: /**
1156: * @deprecated Call getActionNames() instead
1157: */
1158: public static EditAction[] getActions() {
1159: String[] names = actionContext.getActionNames();
1160: EditAction[] actions = new EditAction[names.length];
1161: for (int i = 0; i < actions.length; i++) {
1162: actions[i] = actionContext.getAction(names[i]);
1163: if (actions[i] == null)
1164: Log.log(Log.ERROR, jEdit.class, "wtf: " + names[i]);
1165: }
1166: return actions;
1167: } //}}}
1168:
1169: //{{{ getActionNames() method
1170: /**
1171: * Returns all registered action names.
1172: */
1173: public static String[] getActionNames() {
1174: return actionContext.getActionNames();
1175: } //}}}
1176:
1177: //}}}
1178:
1179: //{{{ Edit mode methods
1180:
1181: //{{{ reloadModes() method
1182: /**
1183: * Reloads all edit modes.
1184: * @since jEdit 3.2pre2
1185: */
1186: public static void reloadModes() {
1187: /* Try to guess the eventual size to avoid unnecessary
1188: * copying */
1189: ModeProvider.instance.removeAll();
1190:
1191: //{{{ Load the global catalog
1192: if (jEditHome == null)
1193: loadModeCatalog("/modes/catalog", true);
1194: else {
1195: loadModeCatalog(MiscUtilities.constructPath(jEditHome,
1196: "modes", "catalog"), false);
1197: } //}}}
1198:
1199: //{{{ Load user catalog
1200: if (settingsDirectory != null) {
1201: File userModeDir = new File(MiscUtilities.constructPath(
1202: settingsDirectory, "modes"));
1203: if (!userModeDir.exists())
1204: userModeDir.mkdirs();
1205:
1206: File userCatalog = new File(MiscUtilities.constructPath(
1207: settingsDirectory, "modes", "catalog"));
1208: if (!userCatalog.exists()) {
1209: // create dummy catalog
1210: FileWriter out = null;
1211: try {
1212: out = new FileWriter(userCatalog);
1213: out.write(jEdit.getProperty("defaultCatalog"));
1214: } catch (IOException io) {
1215: Log.log(Log.ERROR, jEdit.class, io);
1216: } finally {
1217: IOUtilities.closeQuietly(out);
1218: }
1219: }
1220:
1221: loadModeCatalog(userCatalog.getPath(), false);
1222: } //}}}
1223:
1224: Buffer buffer = buffersFirst;
1225: while (buffer != null) {
1226: // This reloads the token marker and sends a message
1227: // which causes edit panes to repaint their text areas
1228: buffer.setMode();
1229:
1230: buffer = buffer.next;
1231: }
1232: } //}}}
1233:
1234: //{{{ getMode() method
1235: /**
1236: * Returns the edit mode with the specified name.
1237: * @param name The edit mode
1238: */
1239: public static Mode getMode(String name) {
1240: return ModeProvider.instance.getMode(name);
1241: } //}}}
1242:
1243: //{{{ getModes() method
1244: /**
1245: * Returns an array of installed edit modes.
1246: */
1247: public static Mode[] getModes() {
1248: return ModeProvider.instance.getModes();
1249: } //}}}
1250:
1251: //}}}
1252:
1253: //{{{ Buffer creation methods
1254:
1255: //{{{ openFiles() method
1256: /**
1257: * Opens the file names specified in the argument array. This
1258: * handles +line and +marker arguments just like the command
1259: * line parser.
1260: * @param parent The parent directory
1261: * @param args The file names to open
1262: * @since jEdit 3.2pre4
1263: */
1264: public static Buffer openFiles(View view, String parent,
1265: String[] args) {
1266: Buffer retVal = null;
1267: Buffer lastBuffer = null;
1268:
1269: for (int i = 0; i < args.length; i++) {
1270: String arg = args[i];
1271: if (arg == null)
1272: continue;
1273: else if (arg.startsWith("+line:")
1274: || arg.startsWith("+marker:")) {
1275: if (lastBuffer != null)
1276: gotoMarker(view, lastBuffer, arg);
1277: continue;
1278: }
1279:
1280: lastBuffer = openFile(null, parent, arg, false, null);
1281:
1282: if (retVal == null && lastBuffer != null)
1283: retVal = lastBuffer;
1284: }
1285:
1286: if (view != null && retVal != null)
1287: view.setBuffer(retVal, true);
1288:
1289: return retVal;
1290: } //}}}
1291:
1292: //{{{ openFile() methods
1293: /**
1294: * Opens a file. Note that as of jEdit 2.5pre1, this may return
1295: * null if the buffer could not be opened.
1296: * @param view The view to open the file in
1297: * @param path The file path
1298: *
1299: * @since jEdit 2.4pre1
1300: */
1301: public static Buffer openFile(View view, String path) {
1302: return openFile(view, null, path, false, new Hashtable());
1303: }
1304:
1305: /**
1306: * @deprecated The openFile() forms with the readOnly parameter
1307: * should not be used. The readOnly prameter is no longer supported.
1308: */
1309: public static Buffer openFile(View view, String parent,
1310: String path, boolean readOnly, boolean newFile) {
1311: return openFile(view, parent, path, newFile, new Hashtable());
1312: }
1313:
1314: /**
1315: * @deprecated The openFile() forms with the readOnly parameter
1316: * should not be used. The readOnly prameter is no longer supported.
1317: */
1318: public static Buffer openFile(View view, String parent,
1319: String path, boolean readOnly, boolean newFile,
1320: Hashtable props) {
1321: return openFile(view, parent, path, newFile, props);
1322: }
1323:
1324: /**
1325: * Opens a file. This may return null if the buffer could not be
1326: * opened for some reason.
1327: * @param view The view to open the file in
1328: * @param parent The parent directory of the file
1329: * @param path The path name of the file
1330: * @param newFile True if the file should not be loaded from disk
1331: * be prompted if it should be reloaded
1332: * @param props Buffer-local properties to set in the buffer
1333: *
1334: * @since jEdit 3.2pre10
1335: */
1336: public static Buffer openFile(View view, String parent,
1337: String path, boolean newFile, Hashtable props) {
1338: PerspectiveManager.setPerspectiveDirty(true);
1339:
1340: if (view != null && parent == null)
1341: parent = view.getBuffer().getDirectory();
1342:
1343: try {
1344: URL u = new URL(path);
1345: if (u.getProtocol().equals("file"))
1346: path = URLDecoder.decode(u.getPath());
1347: } catch (MalformedURLException mue) {
1348: path = MiscUtilities.constructPath(parent, path);
1349: }
1350:
1351: if (props == null)
1352: props = new Hashtable();
1353: composeBufferPropsFromHistory(props, path);
1354:
1355: Buffer newBuffer;
1356:
1357: synchronized (editBusOrderingLock) {
1358: synchronized (bufferListLock) {
1359: Buffer buffer = getBuffer(path);
1360: if (buffer != null) {
1361: if (view != null)
1362: view.setBuffer(buffer, true);
1363:
1364: return buffer;
1365: }
1366:
1367: newBuffer = new Buffer(path, newFile, false, props);
1368:
1369: if (!newBuffer.load(view, false))
1370: return null;
1371:
1372: addBufferToList(newBuffer);
1373: }
1374:
1375: EditBus.send(new BufferUpdate(newBuffer, view,
1376: BufferUpdate.CREATED));
1377: }
1378:
1379: if (view != null)
1380: view.setBuffer(newBuffer, true);
1381:
1382: return newBuffer;
1383: } //}}}
1384:
1385: //{{{ openTemporary() methods
1386: /**
1387: * Opens a temporary buffer. A temporary buffer is like a normal
1388: * buffer, except that an event is not fired, the the buffer is
1389: * not added to the buffers list.
1390: *
1391: * @param view The view to open the file in
1392: * @param parent The parent directory of the file
1393: * @param path The path name of the file
1394: * @param newFile True if the file should not be loaded from disk
1395: *
1396: * @since jEdit 3.2pre10
1397: */
1398: public static Buffer openTemporary(View view, String parent,
1399: String path, boolean newFile) {
1400: return openTemporary(view, parent, path, newFile, null);
1401: }
1402:
1403: /**
1404: * Opens a temporary buffer. A temporary buffer is like a normal
1405: * buffer, except that an event is not fired, the the buffer is
1406: * not added to the buffers list.
1407: *
1408: * @param view The view to open the file in
1409: * @param parent The parent directory of the file
1410: * @param path The path name of the file
1411: * @param newFile True if the file should not be loaded from disk
1412: * @param props Buffer-local properties to set in the buffer
1413: *
1414: * @since jEdit 4.3pre10
1415: */
1416: public static Buffer openTemporary(View view, String parent,
1417: String path, boolean newFile, Hashtable props) {
1418: if (view != null && parent == null)
1419: parent = view.getBuffer().getDirectory();
1420:
1421: if (MiscUtilities.isURL(path)) {
1422: if (MiscUtilities.getProtocolOfURL(path).equals("file"))
1423: path = path.substring(5);
1424: }
1425:
1426: path = MiscUtilities.constructPath(parent, path);
1427:
1428: if (props == null)
1429: props = new Hashtable();
1430: composeBufferPropsFromHistory(props, path);
1431:
1432: synchronized (bufferListLock) {
1433: Buffer buffer = getBuffer(path);
1434: if (buffer != null)
1435: return buffer;
1436:
1437: buffer = new Buffer(path, newFile, true, props);
1438: buffer.setBooleanProperty(Buffer.ENCODING_AUTODETECT, true);
1439: if (!buffer.load(view, false))
1440: return null;
1441: else
1442: return buffer;
1443: }
1444: } //}}}
1445:
1446: //{{{ commitTemporary() method
1447: /**
1448: * Adds a temporary buffer to the buffer list. This must be done
1449: * before allowing the user to interact with the buffer in any
1450: * way.
1451: * @param buffer The buffer
1452: */
1453: public static void commitTemporary(Buffer buffer) {
1454: if (!buffer.isTemporary())
1455: return;
1456:
1457: PerspectiveManager.setPerspectiveDirty(true);
1458:
1459: addBufferToList(buffer);
1460: buffer.commitTemporary();
1461:
1462: // send full range of events to avoid breaking plugins
1463: EditBus.send(new BufferUpdate(buffer, null,
1464: BufferUpdate.CREATED));
1465: EditBus.send(new BufferUpdate(buffer, null,
1466: BufferUpdate.LOAD_STARTED));
1467: EditBus
1468: .send(new BufferUpdate(buffer, null,
1469: BufferUpdate.LOADED));
1470: } //}}}
1471:
1472: //{{{ newFile() method
1473: /**
1474: * Creates a new `untitled' file.
1475: * @param view The view to create the file in
1476: */
1477: public static Buffer newFile(View view) {
1478: String path;
1479:
1480: if (view != null && view.getBuffer() != null) {
1481: path = view.getBuffer().getDirectory();
1482: VFS vfs = VFSManager.getVFSForPath(path);
1483: // don't want 'New File' to create a read only buffer
1484: // if current file is on SQL VFS or something
1485: if ((vfs.getCapabilities() & VFS.WRITE_CAP) == 0)
1486: path = System.getProperty("user.home");
1487: } else
1488: path = null;
1489:
1490: return newFile(view, path);
1491: } //}}}
1492:
1493: //{{{ newFile() method
1494: /**
1495: * Creates a new `untitled' file.
1496: * @param view The view to create the file in
1497: * @param dir The directory to create the file in
1498: * @since jEdit 3.1pre2
1499: */
1500: public static Buffer newFile(View view, String dir) {
1501: // If only one new file is open which is clean, just close
1502: // it, which will create an 'Untitled-1'
1503: if (dir != null && buffersFirst != null
1504: && buffersFirst == buffersLast
1505: && buffersFirst.isUntitled() && !buffersFirst.isDirty()) {
1506: closeBuffer(view, buffersFirst);
1507: // return the newly created 'untitled-1'
1508: return buffersFirst;
1509: }
1510:
1511: // Find the highest Untitled-n file
1512: int untitledCount = 0;
1513: Buffer buffer = buffersFirst;
1514: while (buffer != null) {
1515: if (buffer.getName().startsWith("Untitled-")) {
1516: try {
1517: untitledCount = Math.max(untitledCount, Integer
1518: .parseInt(buffer.getName().substring(9)));
1519: } catch (NumberFormatException nf) {
1520: }
1521: }
1522: buffer = buffer.next;
1523: }
1524:
1525: return openFile(view, dir, "Untitled-" + (untitledCount + 1),
1526: true, null);
1527: } //}}}
1528:
1529: //}}}
1530:
1531: //{{{ Buffer management methods
1532:
1533: //{{{ closeBuffer() method
1534: /**
1535: * Closes a buffer. If there are unsaved changes, the user is
1536: * prompted if they should be saved first.
1537: * @param view The view
1538: * @param buffer The buffer
1539: * @return True if the buffer was really closed, false otherwise
1540: */
1541: public static boolean closeBuffer(View view, Buffer buffer) {
1542: // Wait for pending I/O requests
1543: if (buffer.isPerformingIO()) {
1544: VFSManager.waitForRequests();
1545: if (VFSManager.errorOccurred())
1546: return false;
1547: }
1548:
1549: if (buffer.isDirty()) {
1550: Object[] args = { buffer.getName() };
1551: int result = GUIUtilities.confirm(view, "notsaved", args,
1552: JOptionPane.YES_NO_CANCEL_OPTION,
1553: JOptionPane.WARNING_MESSAGE);
1554: if (result == JOptionPane.YES_OPTION) {
1555: if (!buffer.save(view, null, true))
1556: return false;
1557:
1558: VFSManager.waitForRequests();
1559: if (buffer
1560: .getBooleanProperty(BufferIORequest.ERROR_OCCURRED)) {
1561: return false;
1562: }
1563: } else if (result != JOptionPane.NO_OPTION)
1564: return false;
1565: } else {
1566: // if the buffer is untitled, not dirty and alone, no need to close it
1567: if (buffer.isUntitled() && bufferCount == 1)
1568: return false;
1569: }
1570:
1571: _closeBuffer(view, buffer);
1572:
1573: return true;
1574: } //}}}
1575:
1576: //{{{ _closeBuffer() method
1577: /**
1578: * Closes the buffer, even if it has unsaved changes.
1579: * @param view The view, may be null
1580: * @param buffer The buffer
1581: *
1582: * @exception NullPointerException if the buffer is null
1583: *
1584: * @since jEdit 2.2pre1
1585: */
1586: public static void _closeBuffer(View view, Buffer buffer) {
1587: if (buffer.isClosed()) {
1588: // can happen if the user presses C+w twice real
1589: // quick and the buffer has unsaved changes
1590: return;
1591: }
1592:
1593: PerspectiveManager.setPerspectiveDirty(true);
1594:
1595: if (!buffer.isNewFile()) {
1596: if (view != null)
1597: view.getEditPane().saveCaretInfo();
1598: Integer _caret = (Integer) buffer.getProperty(Buffer.CARET);
1599: int caret = _caret == null ? 0 : _caret.intValue();
1600:
1601: BufferHistory.setEntry(buffer.getPath(), caret,
1602: (Selection[]) buffer.getProperty(Buffer.SELECTION),
1603: buffer.getStringProperty(JEditBuffer.ENCODING),
1604: buffer.getMode().getName());
1605: }
1606:
1607: String path = buffer.getSymlinkPath();
1608: if ((VFSManager.getVFSForPath(path).getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0) {
1609: path = path.toLowerCase();
1610: }
1611: EditBus.send(new BufferUpdate(buffer, view,
1612: BufferUpdate.CLOSING));
1613: bufferHash.remove(path);
1614: removeBufferFromList(buffer);
1615: buffer.close();
1616: DisplayManager.bufferClosed(buffer);
1617:
1618: EditBus
1619: .send(new BufferUpdate(buffer, view,
1620: BufferUpdate.CLOSED));
1621: if (jEdit.getBooleanProperty("persistentMarkers"))
1622: buffer.updateMarkersFile(view);
1623:
1624: // Create a new file when the last is closed
1625: if (buffersFirst == null && buffersLast == null)
1626: newFile(view);
1627: } //}}}
1628:
1629: //{{{ closeAllBuffers() methods
1630: /**
1631: * Closes all open buffers.
1632: * @param view The view
1633: */
1634: public static boolean closeAllBuffers(View view) {
1635: return closeAllBuffers(view, false);
1636: }
1637:
1638: /**
1639: * Closes all open buffers.
1640: * @param view The view
1641: * @param isExiting This must be false unless this method is
1642: * being called by the exit() method
1643: */
1644: public static boolean closeAllBuffers(View view, boolean isExiting) {
1645: if (view != null)
1646: view.getEditPane().saveCaretInfo();
1647:
1648: boolean dirty = false;
1649:
1650: boolean saveRecent = !(isExiting && jEdit
1651: .getBooleanProperty("restore"));
1652:
1653: Buffer buffer = buffersFirst;
1654: while (buffer != null) {
1655: if (buffer.isDirty()) {
1656: dirty = true;
1657: break;
1658: }
1659: buffer = buffer.next;
1660: }
1661:
1662: if (dirty) {
1663: boolean ok = new CloseDialog(view).isOK();
1664: if (!ok)
1665: return false;
1666: }
1667:
1668: // Wait for pending I/O requests
1669: VFSManager.waitForRequests();
1670: if (VFSManager.errorOccurred())
1671: return false;
1672:
1673: // close remaining buffers (the close dialog only deals with
1674: // dirty ones)
1675:
1676: buffer = buffersFirst;
1677:
1678: // zero it here so that BufferTabs doesn't have any problems
1679: buffersFirst = buffersLast = null;
1680: bufferHash.clear();
1681: bufferCount = 0;
1682:
1683: while (buffer != null) {
1684: if (!buffer.isNewFile() && saveRecent) {
1685: Integer _caret = (Integer) buffer
1686: .getProperty(Buffer.CARET);
1687: int caret = _caret == null ? 0 : _caret.intValue();
1688: BufferHistory.setEntry(buffer.getPath(), caret,
1689: (Selection[]) buffer
1690: .getProperty(Buffer.SELECTION),
1691: buffer.getStringProperty(JEditBuffer.ENCODING),
1692: buffer.getMode().getName());
1693: }
1694:
1695: buffer.close();
1696: DisplayManager.bufferClosed(buffer);
1697: if (!isExiting) {
1698: EditBus.send(new BufferUpdate(buffer, view,
1699: BufferUpdate.CLOSED));
1700: }
1701: if (jEdit.getBooleanProperty("persistentMarkers"))
1702: buffer.updateMarkersFile(view);
1703: buffer = buffer.next;
1704: }
1705:
1706: if (!isExiting)
1707: newFile(view);
1708:
1709: PerspectiveManager.setPerspectiveDirty(true);
1710:
1711: return true;
1712: } //}}}
1713:
1714: //{{{ saveAllBuffers() method
1715: /**
1716: * Saves all open buffers.
1717: * @param view The view
1718: * @since jEdit 4.2pre1
1719: */
1720: public static void saveAllBuffers(View view) {
1721: saveAllBuffers(view, jEdit.getBooleanProperty("confirmSaveAll"));
1722: } //}}}
1723:
1724: //{{{ saveAllBuffers() method
1725: /**
1726: * Saves all open buffers.
1727: * @param view The view
1728: * @param confirm If true, a confirmation dialog will be shown first
1729: * @since jEdit 2.7pre2
1730: */
1731: public static void saveAllBuffers(View view, boolean confirm) {
1732: if (confirm) {
1733: int result = GUIUtilities.confirm(view, "saveall", null,
1734: JOptionPane.YES_NO_OPTION,
1735: JOptionPane.QUESTION_MESSAGE);
1736: if (result != JOptionPane.YES_OPTION)
1737: return;
1738: }
1739:
1740: Buffer current = view.getBuffer();
1741:
1742: Buffer buffer = buffersFirst;
1743: while (buffer != null) {
1744: if (buffer.isDirty()) {
1745: if (buffer.isNewFile())
1746: view.setBuffer(buffer, true);
1747: buffer.save(view, null, true, true);
1748: }
1749:
1750: buffer = buffer.next;
1751: }
1752:
1753: view.setBuffer(current, true);
1754: } //}}}
1755:
1756: //{{{ reloadAllBuffers() method
1757: /**
1758: * Reloads all open buffers.
1759: * @param view The view
1760: * @param confirm If true, a confirmation dialog will be shown first
1761: * if any buffers are dirty
1762: * @since jEdit 2.7pre2
1763: */
1764: public static void reloadAllBuffers(View view, boolean confirm) {
1765: boolean hasDirty = false;
1766: Buffer[] buffers = jEdit.getBuffers();
1767:
1768: for (int i = 0; i < buffers.length && !hasDirty; i++)
1769: hasDirty = !buffers[i].isUntitled() && buffers[i].isDirty();
1770:
1771: if (confirm && hasDirty) {
1772: int result = GUIUtilities.confirm(view, "reload-all", null,
1773: JOptionPane.YES_NO_OPTION,
1774: JOptionPane.QUESTION_MESSAGE);
1775: if (result != JOptionPane.YES_OPTION)
1776: return;
1777: }
1778:
1779: // save caret info. Buffer.load() will load it.
1780: View _view = viewsFirst;
1781: while (_view != null) {
1782: EditPane[] panes = _view.getEditPanes();
1783: for (int i = 0; i < panes.length; i++) {
1784: panes[i].saveCaretInfo();
1785: }
1786:
1787: _view = _view.next;
1788: }
1789:
1790: for (int i = 0; i < buffers.length; i++) {
1791: Buffer buffer = buffers[i];
1792: if (buffer.isUntitled())
1793: continue;
1794: buffer.load(view, true);
1795: }
1796: } //}}}
1797:
1798: //{{{ _getBuffer() method
1799: /**
1800: * Returns the buffer with the specified path name. The path name
1801: * must be an absolute, canonical, path.
1802: *
1803: * @param path The path name
1804: * @see MiscUtilities#constructPath(String,String)
1805: * @see MiscUtilities#resolveSymlinks(String)
1806: * @see #getBuffer(String)
1807: *
1808: * @since jEdit 4.2pre7
1809: */
1810: public static Buffer _getBuffer(String path) {
1811: // paths on case-insensitive filesystems are stored as lower
1812: // case in the hash.
1813: if ((VFSManager.getVFSForPath(path).getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0) {
1814: path = path.toLowerCase();
1815: }
1816:
1817: synchronized (bufferListLock) {
1818: return bufferHash.get(path);
1819: }
1820: } //}}}
1821:
1822: //{{{ getBuffer() method
1823: /**
1824: * Returns the buffer with the specified path name. The path name
1825: * must be an absolute path. This method automatically resolves
1826: * symbolic links. If performance is critical, cache the canonical
1827: * path and call {@link #_getBuffer(String)} instead.
1828: *
1829: * @param path The path name
1830: * @see MiscUtilities#constructPath(String,String)
1831: * @see MiscUtilities#resolveSymlinks(String)
1832: */
1833: public static Buffer getBuffer(String path) {
1834: return _getBuffer(MiscUtilities.resolveSymlinks(path));
1835: } //}}}
1836:
1837: //{{{ getBuffers() method
1838: /**
1839: * Returns an array of open buffers.
1840: */
1841: public static Buffer[] getBuffers() {
1842: synchronized (bufferListLock) {
1843: Buffer[] buffers = new Buffer[bufferCount];
1844: Buffer buffer = buffersFirst;
1845: for (int i = 0; i < bufferCount; i++) {
1846: buffers[i] = buffer;
1847: buffer = buffer.next;
1848: }
1849: return buffers;
1850: }
1851: } //}}}
1852:
1853: //{{{ getBufferCount() method
1854: /**
1855: * Returns the number of open buffers.
1856: */
1857: public static int getBufferCount() {
1858: return bufferCount;
1859: } //}}}
1860:
1861: //{{{ getFirstBuffer() method
1862: /**
1863: * Returns the first buffer.
1864: */
1865: public static Buffer getFirstBuffer() {
1866: return buffersFirst;
1867: } //}}}
1868:
1869: //{{{ getLastBuffer() method
1870: /**
1871: * Returns the last buffer.
1872: */
1873: public static Buffer getLastBuffer() {
1874: return buffersLast;
1875: } //}}}
1876:
1877: //{{{ checkBufferStatus() methods
1878: /**
1879: * Checks each buffer's status on disk and shows the dialog box
1880: * informing the user that buffers changed on disk, if necessary.
1881: * @param view The view
1882: * @since jEdit 4.2pre1
1883: */
1884: public static void checkBufferStatus(View view) {
1885: checkBufferStatus(view, false);
1886: }
1887:
1888: /**
1889: * Checks buffer status on disk and shows the dialog box
1890: * informing the user that buffers changed on disk, if necessary.
1891: * @param view The view
1892: * @param currentBuffer indicates whether to check only the current buffer
1893: * @since jEdit 4.2pre1
1894: */
1895: public static void checkBufferStatus(View view,
1896: boolean currentBuffer) {
1897: // still need to call the status check even if the option is
1898: // off, so that the write protection is updated if it changes
1899: // on disk
1900:
1901: // auto reload changed buffers?
1902: boolean autoReload = getBooleanProperty("autoReload");
1903:
1904: // the problem with this is that if we have two edit panes
1905: // looking at the same buffer and the file is reloaded both
1906: // will jump to the same location
1907: View _view = viewsFirst;
1908: while (_view != null) {
1909: EditPane[] editPanes = _view.getEditPanes();
1910: for (int i = 0; i < editPanes.length; i++) {
1911: editPanes[i].saveCaretInfo();
1912: }
1913: _view = _view.next;
1914: }
1915:
1916: Buffer buffer;
1917: buffer = buffersFirst;
1918:
1919: int[] states = new int[bufferCount];
1920: int i = 0;
1921: boolean notifyFileChanged = false;
1922: while (buffer != null) {
1923: if (currentBuffer && buffer != view.getBuffer()) {
1924: buffer = buffer.next;
1925: i++;
1926: continue;
1927: }
1928:
1929: states[i] = buffer.checkFileStatus(view);
1930:
1931: switch (states[i]) {
1932: case Buffer.FILE_CHANGED:
1933: if (buffer.getAutoReload()) {
1934: if (buffer.isDirty())
1935: notifyFileChanged = true;
1936: else
1937: buffer.load(view, true);
1938: } else
1939: // no automatic reload even if general setting is true
1940: autoReload = false;
1941: // don't notify user if "do nothing" was chosen
1942: if (buffer.getAutoReloadDialog())
1943: notifyFileChanged = true;
1944: break;
1945: case Buffer.FILE_DELETED:
1946: notifyFileChanged = true;
1947: break;
1948: }
1949:
1950: buffer = buffer.next;
1951: i++;
1952: }
1953:
1954: if (notifyFileChanged)
1955: new FilesChangedDialog(view, states, autoReload);
1956: } //}}}
1957:
1958: //}}}
1959:
1960: //{{{ View methods
1961:
1962: //{{{ getInputHandler() method
1963: /**
1964: * Returns the current input handler (key binding to action mapping)
1965: * @see org.gjt.sp.jedit.gui.InputHandler
1966: */
1967: public static InputHandler getInputHandler() {
1968: return inputHandler;
1969: } //}}}
1970:
1971: /* public static void newViewTest()
1972: {
1973: long time = System.currentTimeMillis();
1974: for(int i = 0; i < 30; i++)
1975: {
1976: Buffer b = newFile(null);
1977: b.insert(0,"x");
1978: new View(b,null,false);
1979: }
1980: System.err.println(System.currentTimeMillis() - time);
1981: } */
1982:
1983: //{{{ newView() methods
1984: /**
1985: * Creates a new view.
1986: * @param view An existing view
1987: * @since jEdit 3.2pre2
1988: */
1989: public static View newView(View view) {
1990: return newView(view, null, false);
1991: }
1992:
1993: /**
1994: * Creates a new view of a buffer.
1995: * @param view An existing view
1996: * @param buffer The buffer
1997: */
1998: public static View newView(View view, Buffer buffer) {
1999: return newView(view, buffer, false);
2000: }
2001:
2002: /**
2003: * Creates a new view of a buffer.
2004: * @param view An existing view
2005: * @param buffer The buffer
2006: * @param plainView If true, the view will not have dockable windows or
2007: * tool bars.
2008: *
2009: * @since 4.1pre2
2010: */
2011: public static View newView(View view, Buffer buffer,
2012: boolean plainView) {
2013: View.ViewConfig config;
2014: if (view != null && (plainView == view.isPlainView()))
2015: config = view.getViewConfig();
2016: else
2017: config = new View.ViewConfig(plainView);
2018: return newView(view, buffer, config);
2019: }
2020:
2021: /**
2022: * Creates a new view.
2023: * @param view An existing view
2024: * @param buffer A buffer to display, or null
2025: * @param config Encapsulates the view geometry, split configuration
2026: * and if the view is a plain view
2027: * @since jEdit 4.2pre1
2028: */
2029: public static View newView(View view, Buffer buffer,
2030: View.ViewConfig config) {
2031: PerspectiveManager.setPerspectiveDirty(true);
2032:
2033: try {
2034: if (view != null) {
2035: view.showWaitCursor();
2036: view.getEditPane().saveCaretInfo();
2037: }
2038:
2039: View newView = new View(buffer, config);
2040: addViewToList(newView);
2041:
2042: if (!config.plainView) {
2043: DockableWindowManager wm = newView
2044: .getDockableWindowManager();
2045: if (config.top != null && config.top.length() != 0)
2046: wm.showDockableWindow(config.top);
2047:
2048: if (config.left != null && config.left.length() != 0)
2049: wm.showDockableWindow(config.left);
2050:
2051: if (config.bottom != null
2052: && config.bottom.length() != 0)
2053: wm.showDockableWindow(config.bottom);
2054:
2055: if (config.right != null && config.right.length() != 0)
2056: wm.showDockableWindow(config.right);
2057: }
2058:
2059: newView.pack();
2060:
2061: if (config.width != 0 && config.height != 0) {
2062: Rectangle desired = new Rectangle(config.x, config.y,
2063: config.width, config.height);
2064: if (OperatingSystem.isX11()
2065: && Debug.GEOMETRY_WORKAROUND) {
2066: new GUIUtilities.UnixWorkaround(newView, "view",
2067: desired, config.extState);
2068: } else {
2069: newView.setBounds(desired);
2070: newView.setExtendedState(config.extState);
2071: }
2072: } else
2073: newView.setLocationRelativeTo(view);
2074:
2075: EditBus.send(new ViewUpdate(newView, ViewUpdate.CREATED));
2076:
2077: newView.setVisible(true);
2078:
2079: // show tip of the day
2080: if (newView == viewsFirst) {
2081: newView.getTextArea().requestFocus();
2082:
2083: // Don't show the welcome message if jEdit was started
2084: // with the -nosettings switch
2085: if (settingsDirectory != null
2086: && getBooleanProperty("firstTime"))
2087: new HelpViewer("welcome.html");
2088: else if (jEdit.getBooleanProperty("tip.show"))
2089: new TipOfTheDay(newView);
2090:
2091: setBooleanProperty("firstTime", false);
2092: } else
2093: GUIUtilities.requestFocus(newView, newView
2094: .getTextArea());
2095:
2096: return newView;
2097: } finally {
2098: if (view != null)
2099: view.hideWaitCursor();
2100: }
2101: } //}}}
2102:
2103: //{{{ closeView() method
2104: /**
2105: * Closes a view.
2106: *
2107: * jEdit will exit if this was the last open view.
2108: */
2109: public static void closeView(View view) {
2110: closeView(view, true);
2111: } //}}}
2112:
2113: //{{{ getViews() method
2114: /**
2115: * Returns an array of all open views.
2116: */
2117: public static View[] getViews() {
2118: View[] views = new View[viewCount];
2119: View view = viewsFirst;
2120: for (int i = 0; i < viewCount; i++) {
2121: views[i] = view;
2122: view = view.next;
2123: }
2124: return views;
2125: } //}}}
2126:
2127: //{{{ getViewCount() method
2128: /**
2129: * Returns the number of open views.
2130: */
2131: public static int getViewCount() {
2132: return viewCount;
2133: } //}}}
2134:
2135: //{{{ getFirstView() method
2136: /**
2137: * Returns the first view.
2138: */
2139: public static View getFirstView() {
2140: return viewsFirst;
2141: } //}}}
2142:
2143: //{{{ getLastView() method
2144: /**
2145: * Returns the last view.
2146: */
2147: public static View getLastView() {
2148: return viewsLast;
2149: } //}}}
2150:
2151: //{{{ getActiveView() method
2152: /**
2153: * Returns the currently focused view.
2154: * @since jEdit 4.1pre1
2155: */
2156: public static View getActiveView() {
2157: if (activeView == null) {
2158: // eg user just closed a view and didn't focus another
2159: return viewsFirst;
2160: } else
2161: return activeView;
2162: } //}}}
2163:
2164: //}}}
2165:
2166: //{{{ Miscellaneous methods
2167:
2168: //{{{ isMainThread() method
2169: /**
2170: * Returns true if the currently running thread is the main thread.
2171: * @since jEdit 4.2pre1
2172: */
2173: public static boolean isMainThread() {
2174: return Thread.currentThread() == mainThread;
2175: } //}}}
2176:
2177: //{{{ isBackgroundMode() method
2178: /**
2179: * Returns true if jEdit was started with the <code>-background</code>
2180: * command-line switch.
2181: * @since jEdit 4.0pre4
2182: */
2183: public static boolean isBackgroundModeEnabled() {
2184: return background;
2185: } //}}}
2186:
2187: //{{{ showMemoryStatusDialog() method
2188: /**
2189: * Performs garbage collection and displays a dialog box showing
2190: * memory status.
2191: * @param view The view
2192: * @since jEdit 4.0pre1
2193: */
2194: public static void showMemoryDialog(View view) {
2195: Runtime rt = Runtime.getRuntime();
2196: int before = (int) (rt.freeMemory() / 1024);
2197: System.gc();
2198: int after = (int) (rt.freeMemory() / 1024);
2199: int total = (int) (rt.totalMemory() / 1024);
2200:
2201: JProgressBar progress = new JProgressBar(0, total);
2202: progress.setValue(total - after);
2203: progress.setStringPainted(true);
2204: progress.setString(jEdit.getProperty("memory-status.use",
2205: new Object[] { total - after, total }));
2206:
2207: Object[] message = new Object[4];
2208: message[0] = getProperty("memory-status.gc",
2209: new Object[] { after - before });
2210: message[1] = Box.createVerticalStrut(12);
2211: message[2] = progress;
2212: message[3] = Box.createVerticalStrut(6);
2213:
2214: JOptionPane.showMessageDialog(view, message, jEdit
2215: .getProperty("memory-status.title"),
2216: JOptionPane.INFORMATION_MESSAGE);
2217: } //}}}
2218:
2219: //{{{ getJEditHome() method
2220: /**
2221: * Returns the jEdit install directory.
2222: */
2223: public static String getJEditHome() {
2224: return jEditHome;
2225: } //}}}
2226:
2227: //{{{ getSettingsDirectory() method
2228: /**
2229: * Returns the path of the directory where user-specific settings
2230: * are stored. This will be <code>null</code> if jEdit was
2231: * started with the <code>-nosettings</code> command-line switch; do not
2232: * blindly use this method without checking for a <code>null</code>
2233: * return value first.
2234: */
2235: public static String getSettingsDirectory() {
2236: return settingsDirectory;
2237: } //}}}
2238:
2239: //{{{ getJARCacheDirectory() method
2240: /**
2241: * Returns the directory where plugin cache files are stored.
2242: * @since jEdit 4.2pre1
2243: */
2244: public static String getJARCacheDirectory() {
2245: return jarCacheDirectory;
2246: } //}}}
2247:
2248: //{{{ backupSettingsFile() method
2249: /**
2250: * Backs up the specified file in the settings directory.
2251: * You should call this on any settings files your plugin
2252: * writes.
2253: * @param file The file
2254: * @since jEdit 4.0pre1
2255: */
2256: public static void backupSettingsFile(File file) {
2257: if (settingsDirectory == null)
2258: return;
2259:
2260: String backupDir = MiscUtilities.constructPath(
2261: settingsDirectory, "settings-backup");
2262: File dir = new File(backupDir);
2263: if (!dir.exists())
2264: dir.mkdirs();
2265:
2266: // ... sweet. saveBackup() will create backupDir if it
2267: // doesn't exist.
2268:
2269: MiscUtilities.saveBackup(file, 5, null, "~", backupDir);
2270: } //}}}
2271:
2272: //{{{ saveSettings() method
2273: /**
2274: * Saves all user preferences to disk.
2275: */
2276: public static void saveSettings() {
2277: if (settingsDirectory == null)
2278: return;
2279:
2280: Abbrevs.save();
2281: FavoritesVFS.saveFavorites();
2282: HistoryModel.saveHistory();
2283: Registers.saveRegisters();
2284: SearchAndReplace.save();
2285: BufferHistory.save();
2286: KillRing.getInstance().save();
2287:
2288: File file1 = new File(MiscUtilities.constructPath(
2289: settingsDirectory, "#properties#save#"));
2290: File file2 = new File(MiscUtilities.constructPath(
2291: settingsDirectory, "properties"));
2292: if (file2.exists() && file2.lastModified() != propsModTime) {
2293: Log.log(Log.WARNING, jEdit.class, file2 + " changed"
2294: + " on disk; will not save user properties");
2295: } else {
2296: backupSettingsFile(file2);
2297:
2298: try {
2299: OutputStream out = new FileOutputStream(file1);
2300: propMgr.saveUserProps(out);
2301: file2.delete();
2302: file1.renameTo(file2);
2303: } catch (IOException io) {
2304: Log.log(Log.ERROR, jEdit.class, io);
2305: }
2306:
2307: propsModTime = file2.lastModified();
2308: }
2309: } //}}}
2310:
2311: //{{{ exit() method
2312: /**
2313: * Exits cleanly from jEdit, prompting the user if any unsaved files
2314: * should be saved first.
2315: * @param view The view from which this exit was called
2316: * @param reallyExit If background mode is enabled and this parameter
2317: * is true, then jEdit will close all open views instead of exiting
2318: * entirely.
2319: */
2320: public static void exit(View view, boolean reallyExit) {
2321: // Close dialog, view.close() call need a view...
2322: if (view == null)
2323: view = activeView;
2324:
2325: // Wait for pending I/O requests
2326: VFSManager.waitForRequests();
2327:
2328: // Create a new EditorExitRequested
2329: EditorExitRequested eer = new EditorExitRequested(view);
2330:
2331: // Send EditorExitRequested
2332: EditBus.send(eer);
2333:
2334: // Check if the ExitRequest has been cancelled
2335: // if so, do not proceed anymore in the exiting
2336: if (eer.hasBeenExitCancelled()) {
2337: Log
2338: .log(Log.MESSAGE, jEdit.class,
2339: "Exit has been cancelled");
2340: return;
2341: }
2342:
2343: // Even if reallyExit is false, we still exit properly
2344: // if background mode is off
2345: reallyExit |= !background;
2346:
2347: PerspectiveManager.savePerspective(false);
2348:
2349: try {
2350: PerspectiveManager.setPerspectiveEnabled(false);
2351:
2352: // Close all buffers
2353: if (!closeAllBuffers(view, reallyExit))
2354: return;
2355: } finally {
2356: PerspectiveManager.setPerspectiveEnabled(true);
2357: }
2358:
2359: // If we are running in background mode and
2360: // reallyExit was not specified, then return here.
2361: if (!reallyExit) {
2362: // in this case, we can't directly call
2363: // view.close(); we have to call closeView()
2364: // for all open views
2365: view = viewsFirst;
2366: while (view != null) {
2367: closeView(view, false);
2368: view = view.next;
2369: }
2370:
2371: // Save settings in case user kills the backgrounded
2372: // jEdit process
2373: saveSettings();
2374: } else {
2375: // Save view properties here
2376: if (view != null) {
2377: view.close();
2378: removeViewFromList(view);
2379: }
2380:
2381: // Stop autosave timer
2382: Autosave.stop();
2383:
2384: // Stop server
2385: if (server != null)
2386: server.stopServer();
2387:
2388: // Stop all plugins
2389: PluginJAR[] plugins = getPluginJARs();
2390: for (int i = 0; i < plugins.length; i++) {
2391: removePluginJAR(plugins[i], true);
2392: }
2393:
2394: // Send EditorExiting
2395: EditBus.send(new EditorExiting(null));
2396:
2397: // Save settings
2398: saveSettings();
2399:
2400: // Close activity log stream
2401: Log.closeStream();
2402:
2403: // Byebye...
2404: System.exit(0);
2405: }
2406: } //}}}
2407:
2408: //{{{ getEditServer() method
2409: /**
2410: * Returns the edit server instance. You can use this to find out the
2411: * port number jEdit is listening on.
2412: * @since jEdit 4.2pre10
2413: */
2414: public static EditServer getEditServer() {
2415: return server;
2416: } //}}}
2417:
2418: //}}}
2419:
2420: //{{{ Package-private members
2421:
2422: //{{{ updatePosition() method
2423: /**
2424: * If buffer sorting is enabled, this repositions the buffer.
2425: */
2426: static void updatePosition(String oldPath, Buffer buffer) {
2427: if ((VFSManager.getVFSForPath(oldPath).getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0) {
2428: oldPath = oldPath.toLowerCase();
2429: }
2430:
2431: bufferHash.remove(oldPath);
2432:
2433: String path = buffer.getSymlinkPath();
2434: if ((VFSManager.getVFSForPath(path).getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0) {
2435: path = path.toLowerCase();
2436: }
2437:
2438: bufferHash.put(path, buffer);
2439:
2440: if (sortBuffers) {
2441: removeBufferFromList(buffer);
2442: addBufferToList(buffer);
2443: }
2444: } //}}}
2445:
2446: //{{{ loadMode() method
2447: /**
2448: * Loads an XML-defined edit mode from the specified reader.
2449: * @param mode The edit mode
2450: */
2451: /* package-private */static void loadMode(Mode mode) {
2452: final String fileName = (String) mode.getProperty("file");
2453: XModeHandler xmh = new XModeHandler(mode.getName()) {
2454: public void error(String what, Object subst) {
2455: String msg;
2456:
2457: Object line = "<unknown>";
2458: if (subst == null)
2459: msg = jEdit.getProperty("xmode-error." + what);
2460: else {
2461: msg = jEdit.getProperty("xmode-error." + what,
2462: new String[] { subst.toString() });
2463: if (subst instanceof Throwable)
2464: Log.log(Log.ERROR, this , subst);
2465: if (subst instanceof SAXParseException) {
2466: line = ((SAXParseException) subst)
2467: .getLineNumber();
2468: }
2469: }
2470:
2471: Object[] args = { fileName, line, null, msg };
2472: GUIUtilities.error(null, "xmode-error", args);
2473: }
2474:
2475: public TokenMarker getTokenMarker(String modeName) {
2476: Mode mode = getMode(modeName);
2477: if (mode == null)
2478: return null;
2479: else
2480: return mode.getTokenMarker();
2481: }
2482: };
2483: ModeProvider.instance.loadMode(mode, xmh);
2484: } //}}}
2485:
2486: //{{{ addPluginProps() method
2487: static void addPluginProps(Properties map) {
2488: propMgr.addPluginProps(map);
2489: } //}}}
2490:
2491: //{{{ removePluginProps() method
2492: static void removePluginProps(Properties map) {
2493: propMgr.removePluginProps(map);
2494: } //}}}
2495:
2496: //{{{ pluginError() method
2497: /**
2498: *
2499: * @param messageProp - a property of a message to print
2500: * @param args a list of arguments whch correspond to {0} and {1} in the string to print.
2501: */
2502: static void pluginError(String path, String messageProp,
2503: Object[] args) {
2504: synchronized (pluginErrorLock) {
2505: if (pluginErrors == null)
2506: pluginErrors = new Vector<ErrorListDialog.ErrorEntry>();
2507:
2508: ErrorListDialog.ErrorEntry newEntry = new ErrorListDialog.ErrorEntry(
2509: path, messageProp, args);
2510:
2511: for (int i = 0; i < pluginErrors.size(); i++) {
2512: if (pluginErrors.get(i).equals(newEntry))
2513: return;
2514: }
2515: pluginErrors.addElement(newEntry);
2516:
2517: if (startupDone) {
2518: SwingUtilities.invokeLater(new Runnable() {
2519: public void run() {
2520: showPluginErrorDialog();
2521: }
2522: });
2523: }
2524: }
2525: } //}}}
2526:
2527: //{{{ setActiveView() method
2528: static void setActiveView(View view) {
2529: jEdit.activeView = view;
2530: } //}}}
2531:
2532: //{{{ getActiveViewInternal() method
2533: /**
2534: * Returns the internal active view, which might be null.
2535: *
2536: * @since 4.3pre10
2537: */
2538: public static View getActiveViewInternal() {
2539: return activeView;
2540: } //}}}
2541:
2542: //}}}
2543:
2544: //{{{ Private members
2545:
2546: //{{{ Static variables
2547: private static String jEditHome;
2548: private static String settingsDirectory;
2549: private static String jarCacheDirectory;
2550: private static long propsModTime;
2551: private static PropertyManager propMgr;
2552: private static EditServer server;
2553: private static boolean background;
2554: private static ActionContext actionContext;
2555: private static ActionSet builtInActionSet;
2556: private static Vector<ErrorListDialog.ErrorEntry> pluginErrors;
2557: private static final Object pluginErrorLock = new Object();
2558: private static Vector<PluginJAR> jars;
2559:
2560: private static boolean saveCaret;
2561: private static InputHandler inputHandler;
2562:
2563: // buffer link list
2564: private static boolean sortBuffers;
2565: private static boolean sortByName;
2566: private static int bufferCount;
2567: private static Buffer buffersFirst;
2568: private static Buffer buffersLast;
2569: private static Map<String, Buffer> bufferHash;
2570:
2571: // makes openTemporary() thread-safe
2572: private static final Object bufferListLock = new Object();
2573:
2574: private static final Object editBusOrderingLock = new Object();
2575:
2576: // view link list
2577: private static int viewCount;
2578: private static View viewsFirst;
2579: private static View viewsLast;
2580: private static View activeView;
2581:
2582: private static boolean startupDone;
2583:
2584: private static Thread mainThread;
2585:
2586: //}}}
2587:
2588: private jEdit() {
2589: }
2590:
2591: //{{{ usage() method
2592: private static void usage() {
2593: System.out.println("Usage: jedit [<options>] [<files>]");
2594:
2595: System.out.println(" <file> +marker:<marker>: Positions caret"
2596: + " at marker <marker>");
2597: System.out.println(" <file> +line:<line>: Positions caret"
2598: + " at line number <line>");
2599: System.out
2600: .println(" <file> +line:<line>,<column>: Positions caret"
2601: + " at line number <line> and column number <column>");
2602: System.out.println(" --: End of options");
2603: System.out.println(" -background: Run in background mode");
2604: System.out
2605: .println(" -nobackground: Disable background mode (default)");
2606: System.out
2607: .println(" -gui: Only if running in background mode; open initial view (default)");
2608: System.out
2609: .println(" -nogui: Only if running in background mode; don't open initial view");
2610: System.out
2611: .println(" -log=<level>: Log messages with level equal to or higher than this to");
2612: System.out
2613: .println(" standard error. <level> must be between 1 and 9. Default is 7.");
2614: System.out
2615: .println(" -newplainview: Client instance opens a new plain view");
2616: System.out
2617: .println(" -newview: Client instance opens a new view (default)");
2618: System.out.println(" -plugins: Load plugins (default)");
2619: System.out.println(" -noplugins: Don't load any plugins");
2620: System.out
2621: .println(" -restore: Restore previously open files (default)");
2622: System.out
2623: .println(" -norestore: Don't restore previously open files");
2624: System.out
2625: .println(" -reuseview: Client instance reuses existing view");
2626: System.out.println(" -quit: Quit a running instance");
2627: System.out
2628: .println(" -run=<script>: Run the specified BeanShell script");
2629: System.out
2630: .println(" -server: Read/write server info from/to $HOME/.jedit/server (default)");
2631: System.out
2632: .println(" -server=<name>: Read/write server info from/to $HOME/.jedit/<name>");
2633: System.out.println(" -noserver: Don't start edit server");
2634: System.out
2635: .println(" -settings=<path>: Load user-specific settings from <path>");
2636: System.out
2637: .println(" -nosettings: Don't load user-specific settings");
2638: System.out
2639: .println(" -startupscripts: Run startup scripts (default)");
2640: System.out
2641: .println(" -nostartupscripts: Don't run startup scripts");
2642: System.out.println(" -usage: Print this message and exit");
2643: System.out.println(" -version: Print jEdit version and exit");
2644: System.out
2645: .println(" -wait: Wait until the user closes the specified buffer in the server");
2646: System.out
2647: .println(" instance. Does nothing if passed to the initial jEdit instance.");
2648: System.out.println();
2649: System.out
2650: .println("Report bugs to http://sourceforge.net/tracker/?group_id=588&atid=100588");
2651: } //}}}
2652:
2653: //{{{ version() method
2654: private static void version() {
2655: System.out.println("jEdit " + getVersion());
2656: } //}}}
2657:
2658: //{{{ makeServerScript() method
2659: /**
2660: * Creates a BeanShell script that can be sent to a running edit server.
2661: */
2662: private static String makeServerScript(boolean wait,
2663: boolean restore, boolean newView, boolean newPlainView,
2664: String[] args, String scriptFile) {
2665: StringBuilder script = new StringBuilder();
2666:
2667: String userDir = System.getProperty("user.dir");
2668:
2669: script.append("parent = \"");
2670: script.append(MiscUtilities.charsToEscapes(userDir));
2671: script.append("\";\n");
2672:
2673: script.append("args = new String[");
2674: script.append(args.length);
2675: script.append("];\n");
2676:
2677: for (int i = 0; i < args.length; i++) {
2678: script.append("args[");
2679: script.append(i);
2680: script.append("] = ");
2681:
2682: if (args[i] == null)
2683: script.append("null");
2684: else {
2685: script.append('"');
2686: script.append(MiscUtilities.charsToEscapes(args[i]));
2687: script.append('"');
2688: }
2689:
2690: script.append(";\n");
2691: }
2692:
2693: script.append("view = jEdit.getLastView();\n");
2694: script.append("buffer = EditServer.handleClient(");
2695: script.append(restore).append(',').append(newView).append(',')
2696: .append(newPlainView);
2697: script.append(",parent,args);\n");
2698: script.append("if(buffer != null && ").append(wait).append(
2699: ") {\n");
2700: script.append("\tbuffer.setWaitSocket(socket);\n");
2701: script.append("\tdoNotCloseSocket = true;\n");
2702: script.append("}\n");
2703: script.append("if(view != jEdit.getLastView() && ")
2704: .append(wait).append(") {\n");
2705: script.append("\tjEdit.getLastView().setWaitSocket(socket);\n");
2706: script.append("\tdoNotCloseSocket = true;\n");
2707: script.append("}\n");
2708: script.append("if(doNotCloseSocket == void)\n");
2709: script.append("\tsocket.close();\n");
2710:
2711: if (scriptFile != null) {
2712: scriptFile = MiscUtilities.constructPath(userDir,
2713: scriptFile);
2714: script.append("BeanShell.runScript(view,\"").append(
2715: MiscUtilities.charsToEscapes(scriptFile)).append(
2716: "\",null,this.namespace);\n");
2717: }
2718:
2719: return script.toString();
2720: } //}}}
2721:
2722: //{{{ initMisc() method
2723: /**
2724: * Initialise various objects, register protocol handlers.
2725: */
2726: private static void initMisc() {
2727: jars = new Vector<PluginJAR>();
2728: FoldHandler.foldHandlerProvider = new ServiceManager.ServiceFoldHandlerProvider();
2729: actionContext = new ActionContext() {
2730: public void invokeAction(EventObject evt, EditAction action) {
2731: View view = GUIUtilities.getView((Component) evt
2732: .getSource());
2733:
2734: boolean actionBarVisible;
2735: if (view.getActionBar() == null
2736: || !view.getActionBar().isShowing())
2737: actionBarVisible = false;
2738: else {
2739: actionBarVisible = view.getActionBar().isVisible();
2740: }
2741:
2742: view.getInputHandler().invokeAction(action);
2743:
2744: if (actionBarVisible) {
2745: // XXX: action bar might not be 'temp'
2746: ActionBar actionBar = view.getActionBar();
2747: if (actionBar != null)
2748: view.removeToolBar(actionBar);
2749: }
2750: }
2751: };
2752:
2753: bufferHash = new HashMap<String, Buffer>();
2754:
2755: inputHandler = new DefaultInputHandler(null);
2756:
2757: // Add our protocols to java.net.URL's list
2758: System.getProperties().put(
2759: "java.protocol.handler.pkgs",
2760: "org.gjt.sp.jedit.proto|"
2761: + System.getProperty(
2762: "java.protocol.handler.pkgs", ""));
2763:
2764: // Set the User-Agent string used by the java.net HTTP handler
2765: String userAgent = "jEdit/" + getVersion() + " (Java "
2766: + System.getProperty("java.version") + ". "
2767: + System.getProperty("java.vendor") + "; "
2768: + System.getProperty("os.arch") + ')';
2769: System.getProperties().put("http.agent", userAgent);
2770:
2771: /* Determine installation directory.
2772: * If the jedit.home property is set, use that.
2773: * Then, look for jedit.jar in the classpath.
2774: * If that fails, assume this is the web start version. */
2775: jEditHome = System.getProperty("jedit.home");
2776: if (jEditHome == null) {
2777: String classpath = System.getProperty("java.class.path");
2778: int index = classpath.toLowerCase().indexOf("jedit.jar");
2779: int start = classpath
2780: .lastIndexOf(File.pathSeparator, index) + 1;
2781: // if started with java -jar jedit.jar
2782: if (start == index) {
2783: jEditHome = System.getProperty("user.dir");
2784: } else if (index > start) {
2785: jEditHome = classpath.substring(start, index - 1);
2786: } else {
2787: // check if web start
2788: /* if(jEdit.class.getResource("/modes/catalog") != null)
2789: {
2790: // modes bundled in; hence web start
2791: jEditHome = null;
2792: }
2793: else */
2794: {
2795: // use user.dir as last resort
2796: jEditHome = System.getProperty("user.dir");
2797:
2798: Log.log(Log.WARNING, jEdit.class,
2799: "jedit.jar not in class path!");
2800: Log.log(Log.WARNING, jEdit.class,
2801: "Assuming jEdit is installed in "
2802: + jEditHome + '.');
2803: Log.log(Log.WARNING, jEdit.class,
2804: "Override with jedit.home "
2805: + "system property.");
2806: }
2807: }
2808: }
2809:
2810: jEditHome = MiscUtilities.resolveSymlinks(jEditHome);
2811:
2812: Log.log(Log.MESSAGE, jEdit.class, "jEdit home directory is "
2813: + jEditHome);
2814:
2815: if (settingsDirectory != null) {
2816: jarCacheDirectory = MiscUtilities.constructPath(
2817: settingsDirectory, "jars-cache");
2818: new File(jarCacheDirectory).mkdirs();
2819: }
2820:
2821: //if(jEditHome == null)
2822: // Log.log(Log.DEBUG,jEdit.class,"Web start mode");
2823:
2824: // Add an EditBus component that will reload edit modes and
2825: // macros if they are changed from within the editor
2826: EditBus.addToBus(new SettingsReloader());
2827:
2828: // Perhaps if Xerces wasn't slightly brain-damaged, we would
2829: // not need this
2830: SwingUtilities.invokeLater(new Runnable() {
2831: public void run() {
2832: Thread.currentThread().setContextClassLoader(
2833: new JARClassLoader());
2834: }
2835: });
2836: } //}}}
2837:
2838: //{{{ initSystemProperties() method
2839: /**
2840: * Load system properties.
2841: */
2842: private static void initSystemProperties() {
2843: propMgr = new PropertyManager();
2844:
2845: try {
2846: propMgr
2847: .loadSystemProps(jEdit.class
2848: .getResourceAsStream("/org/gjt/sp/jedit/jedit.props"));
2849: propMgr
2850: .loadSystemProps(jEdit.class
2851: .getResourceAsStream("/org/gjt/sp/jedit/jedit_gui.props"));
2852: propMgr
2853: .loadSystemProps(jEdit.class
2854: .getResourceAsStream("/org/gjt/sp/jedit/jedit_keys.props"));
2855: } catch (Exception e) {
2856: Log.log(Log.ERROR, jEdit.class,
2857: "Error while loading system properties!");
2858: Log.log(Log.ERROR, jEdit.class,
2859: "One of the following property files could not be loaded:\n"
2860: + "- jedit.props\n" + "- jedit_gui.props\n"
2861: + "- jedit_keys.props\n"
2862: + "jedit.jar is probably corrupt.");
2863: Log.log(Log.ERROR, jEdit.class, e);
2864: System.exit(1);
2865: }
2866: } //}}}
2867:
2868: //{{{ initSiteProperties() method
2869: /**
2870: * Load site properties.
2871: */
2872: private static void initSiteProperties() {
2873: // site properties are loaded as default properties, overwriting
2874: // jEdit's system properties
2875:
2876: String siteSettingsDirectory = MiscUtilities.constructPath(
2877: jEditHome, "properties");
2878: File siteSettings = new File(siteSettingsDirectory);
2879:
2880: if (!(siteSettings.exists() && siteSettings.isDirectory()))
2881: return;
2882:
2883: String[] snippets = siteSettings.list();
2884: if (snippets == null)
2885: return;
2886:
2887: Arrays.sort(snippets, new MiscUtilities.StringICaseCompare());
2888:
2889: for (int i = 0; i < snippets.length; ++i) {
2890: String snippet = snippets[i];
2891: if (!snippet.toLowerCase().endsWith(".props"))
2892: continue;
2893:
2894: try {
2895: String path = MiscUtilities.constructPath(
2896: siteSettingsDirectory, snippet);
2897: Log.log(Log.DEBUG, jEdit.class,
2898: "Loading site snippet: " + path);
2899:
2900: propMgr.loadSiteProps(new FileInputStream(
2901: new File(path)));
2902: } catch (FileNotFoundException fnf) {
2903: Log.log(Log.DEBUG, jEdit.class, fnf);
2904: } catch (IOException e) {
2905: Log.log(Log.ERROR, jEdit.class,
2906: "Cannot load site snippet " + snippet);
2907: Log.log(Log.ERROR, jEdit.class, e);
2908: }
2909: }
2910: } //}}}
2911:
2912: //{{{ initResources() method
2913: private static void initResources() {
2914: builtInActionSet = new ActionSet(null, null, null, jEdit.class
2915: .getResource("actions.xml"));
2916: builtInActionSet.setLabel(getProperty("action-set.jEdit"));
2917: builtInActionSet.load();
2918:
2919: actionContext.addActionSet(builtInActionSet);
2920:
2921: DockableWindowFactory.getInstance().loadDockableWindows(null,
2922: jEdit.class.getResource("dockables.xml"), null);
2923:
2924: ServiceManager.loadServices(null, jEdit.class
2925: .getResource("services.xml"), null);
2926: } //}}}
2927:
2928: //{{{ initPlugins() method
2929: /**
2930: * Loads plugins.
2931: */
2932: private static void initPlugins() {
2933: if (jEditHome != null) {
2934: addPluginJARsFromDirectory(MiscUtilities.constructPath(
2935: jEditHome, "jars"));
2936: }
2937:
2938: if (settingsDirectory != null) {
2939: File jarsDirectory = new File(settingsDirectory, "jars");
2940: if (!jarsDirectory.exists())
2941: jarsDirectory.mkdir();
2942: addPluginJARsFromDirectory(jarsDirectory.getPath());
2943: }
2944:
2945: PluginJAR[] jars = getPluginJARs();
2946: for (int i = 0; i < jars.length; i++) {
2947: jars[i].checkDependencies();
2948: }
2949: } //}}}
2950:
2951: //{{{ initUserProperties() method
2952: /**
2953: * Loads user properties.
2954: */
2955: private static void initUserProperties() {
2956: if (settingsDirectory != null) {
2957: File file = new File(MiscUtilities.constructPath(
2958: settingsDirectory, "properties"));
2959: propsModTime = file.lastModified();
2960:
2961: try {
2962: propMgr.loadUserProps(new FileInputStream(file));
2963: } catch (FileNotFoundException fnf) {
2964: //Log.log(Log.DEBUG,jEdit.class,fnf);
2965: } catch (Exception e) {
2966: Log.log(Log.ERROR, jEdit.class, e);
2967: }
2968: }
2969: } //}}}
2970:
2971: //{{{ fontStyleToString() method
2972: private static String fontStyleToString(int style) {
2973: if (style == 0)
2974: return "PLAIN";
2975: else if (style == Font.BOLD)
2976: return "BOLD";
2977: else if (style == Font.ITALIC)
2978: return "ITALIC";
2979: else if (style == (Font.BOLD | Font.ITALIC))
2980: return "BOLDITALIC";
2981: else
2982: throw new RuntimeException("Invalid style: " + style);
2983: } //}}}
2984:
2985: //{{{ fontToString() method
2986: private static String fontToString(Font font) {
2987: return font.getFamily() + '-'
2988: + fontStyleToString(font.getStyle()) + '-'
2989: + font.getSize();
2990: } //}}}
2991:
2992: //{{{ initPLAF() method
2993: /**
2994: * Sets the Swing look and feel.
2995: */
2996: private static void initPLAF() {
2997: Font primaryFont = jEdit.getFontProperty("metal.primary.font");
2998: if (primaryFont != null) {
2999: String primaryFontString = fontToString(primaryFont);
3000:
3001: System.getProperties().put("swing.plaf.metal.controlFont",
3002: primaryFontString);
3003: System.getProperties().put("swing.plaf.metal.menuFont",
3004: primaryFontString);
3005: }
3006:
3007: Font secondaryFont = jEdit
3008: .getFontProperty("metal.secondary.font");
3009: if (secondaryFont != null) {
3010: String secondaryFontString = fontToString(secondaryFont);
3011:
3012: System.getProperties().put("swing.plaf.metal.systemFont",
3013: secondaryFontString);
3014: System.getProperties().put("swing.plaf.metal.userFont",
3015: secondaryFontString);
3016: }
3017:
3018: try {
3019: String lf = getProperty("lookAndFeel");
3020: if (lf != null && lf.length() != 0)
3021: UIManager.setLookAndFeel(lf);
3022: else if (OperatingSystem.isMacOS()) {
3023: UIManager.setLookAndFeel(UIManager
3024: .getSystemLookAndFeelClassName());
3025: } else {
3026: UIManager.setLookAndFeel(UIManager
3027: .getCrossPlatformLookAndFeelClassName());
3028: }
3029: } catch (Exception e) {
3030: Log.log(Log.ERROR, jEdit.class, e);
3031: }
3032:
3033: UIDefaults defaults = UIManager.getDefaults();
3034:
3035: // give all Swing components our colors
3036: if (jEdit.getBooleanProperty("textColors")) {
3037: Color background = new javax.swing.plaf.ColorUIResource(
3038: jEdit.getColorProperty("view.bgColor"));
3039: Color foreground = new javax.swing.plaf.ColorUIResource(
3040: jEdit.getColorProperty("view.fgColor"));
3041: Color caretColor = new javax.swing.plaf.ColorUIResource(
3042: jEdit.getColorProperty("view.caretColor"));
3043: Color selectionColor = new javax.swing.plaf.ColorUIResource(
3044: jEdit.getColorProperty("view.selectionColor"));
3045:
3046: String[] prefixes = { "TextField", "TextArea", "List",
3047: "Table" };
3048: for (int i = 0; i < prefixes.length; i++) {
3049: String prefix = prefixes[i];
3050: defaults
3051: .put(prefix + ".disabledBackground", background);
3052: defaults.put(prefix + ".background", background);
3053: defaults
3054: .put(prefix + ".disabledForeground", foreground);
3055: defaults.put(prefix + ".foreground", foreground);
3056: defaults.put(prefix + ".caretForeground", caretColor);
3057: defaults.put(prefix + ".selectionForeground",
3058: foreground);
3059: defaults.put(prefix + ".selectionBackground",
3060: selectionColor);
3061: //defaults.put(prefix + ".inactiveForeground",foreground);
3062: }
3063:
3064: defaults.put("Tree.background", background);
3065: defaults.put("Tree.foreground", foreground);
3066: defaults.put("Tree.textBackground", background);
3067: defaults.put("Tree.textForeground", foreground);
3068: defaults.put("Tree.selectionForeground", foreground);
3069: defaults.put("Tree.selectionBackground", selectionColor);
3070: }
3071:
3072: defaults.remove("SplitPane.border");
3073: defaults.remove("SplitPaneDivider.border");
3074:
3075: JFrame
3076: .setDefaultLookAndFeelDecorated(getBooleanProperty("decorate.frames"));
3077: JDialog
3078: .setDefaultLookAndFeelDecorated(getBooleanProperty("decorate.dialogs"));
3079:
3080: KeyboardFocusManager
3081: .setCurrentKeyboardFocusManager(new MyFocusManager());
3082: } //}}}
3083:
3084: //{{{ runStartupScripts() method
3085: /**
3086: * Runs scripts in a directory.
3087: */
3088: private static void runStartupScripts(File directory) {
3089: if (!directory.isDirectory())
3090: return;
3091:
3092: File[] snippets = directory.listFiles();
3093: if (snippets == null)
3094: return;
3095:
3096: Arrays.sort(snippets, new MiscUtilities.StringICaseCompare());
3097:
3098: /*
3099: * Force the default encoding to UTF-8 temporarily.
3100: * The shipped scripts use that encoding, so we need
3101: * to make sure we can load them correctly. If users
3102: * want to write script with a different encoding,
3103: * they can use buffer-local properties on the
3104: * script to set it.
3105: */
3106: String defaultEncoding = getProperty("buffer.encoding");
3107: setProperty("buffer.encoding", "UTF-8");
3108:
3109: for (int i = 0; i < snippets.length; ++i) {
3110: File snippet = snippets[i];
3111:
3112: Macros.Handler handler = Macros
3113: .getHandlerForPathName(snippet.getPath());
3114: if (handler == null)
3115: continue;
3116:
3117: try {
3118: Macros.Macro newMacro = handler.createMacro(snippet
3119: .getName(), snippet.getPath());
3120: handler.runMacro(null, newMacro, false);
3121: } catch (Exception e) {
3122: Log.log(Log.ERROR, jEdit.class, e);
3123: }
3124: }
3125:
3126: setProperty("buffer.encoding", defaultEncoding);
3127: } //}}}
3128:
3129: //{{{ initProxy() method
3130: private static void initProxy() {
3131: boolean socksEnabled = jEdit
3132: .getBooleanProperty("socks.enabled");
3133: if (!socksEnabled) {
3134: Log.log(Log.DEBUG, jEdit.class, "SOCKS proxy disabled");
3135: System.getProperties().remove("socksProxyHost");
3136: System.getProperties().remove("socksProxyPort");
3137: } else {
3138: String socksHost = jEdit.getProperty("firewall.socks.host");
3139: if (socksHost != null) {
3140: System.setProperty("socksProxyHost", socksHost);
3141: Log.log(Log.DEBUG, jEdit.class, "SOCKS proxy enabled: "
3142: + socksHost);
3143: }
3144:
3145: String socksPort = jEdit.getProperty("firewall.socks.port");
3146: if (socksPort != null)
3147: System.setProperty("socksProxyPort", socksPort);
3148: }
3149:
3150: boolean httpEnabled = jEdit
3151: .getBooleanProperty("firewall.enabled");
3152: if (!httpEnabled) {
3153: Log.log(Log.DEBUG, jEdit.class, "HTTP proxy disabled");
3154: System.getProperties().remove("proxySet");
3155: System.getProperties().remove("proxyHost");
3156: System.getProperties().remove("proxyPort");
3157: System.getProperties().remove("http.proxyHost");
3158: System.getProperties().remove("http.proxyPort");
3159: System.getProperties().remove("http.nonProxyHosts");
3160: Authenticator.setDefault(null);
3161: } else {
3162: // set proxy host
3163: String host = jEdit.getProperty("firewall.host");
3164: if (host == null)
3165: return;
3166:
3167: System.setProperty("http.proxyHost", host);
3168: Log.log(Log.DEBUG, jEdit.class, "HTTP proxy enabled: "
3169: + host);
3170: // set proxy port
3171: String port = jEdit.getProperty("firewall.port");
3172: if (port != null)
3173: System.setProperty("http.proxyPort", port);
3174:
3175: // set non proxy hosts list
3176: String nonProxyHosts = jEdit
3177: .getProperty("firewall.nonProxyHosts");
3178: if (nonProxyHosts != null)
3179: System.setProperty("http.nonProxyHosts", nonProxyHosts);
3180:
3181: // set proxy authentication
3182: String username = jEdit.getProperty("firewall.user");
3183: String password = jEdit.getProperty("firewall.password");
3184:
3185: // null not supported?
3186: if (password == null)
3187: password = "";
3188:
3189: if (username == null || username.length() == 0) {
3190: Log.log(Log.DEBUG, jEdit.class,
3191: "HTTP proxy without user");
3192: Authenticator
3193: .setDefault(new FirewallAuthenticator(null));
3194: } else {
3195: Log.log(Log.DEBUG, jEdit.class, "HTTP proxy user: "
3196: + username);
3197: PasswordAuthentication pw = new PasswordAuthentication(
3198: username, password.toCharArray());
3199: Authenticator.setDefault(new FirewallAuthenticator(pw));
3200: }
3201: }
3202: } //}}}
3203:
3204: //{{{ FirewallAuthenticator class
3205: static class FirewallAuthenticator extends Authenticator {
3206: PasswordAuthentication pw;
3207:
3208: FirewallAuthenticator(PasswordAuthentication pw) {
3209: this .pw = pw;
3210: }
3211:
3212: protected PasswordAuthentication getPasswordAuthentication() {
3213: return pw;
3214: }
3215: } //}}}
3216:
3217: //{{{ finishStartup() method
3218: private static void finishStartup(final boolean gui,
3219: final boolean restore, final String userDir,
3220: final String[] args) {
3221: SwingUtilities.invokeLater(new Runnable() {
3222: public void run() {
3223: Buffer buffer = openFiles(null, userDir, args);
3224:
3225: int count = getBufferCount();
3226: if (count == 0)
3227: newFile(null);
3228:
3229: View view;
3230:
3231: boolean restoreFiles = restore
3232: && jEdit.getBooleanProperty("restore")
3233: && (count == 0 || jEdit
3234: .getBooleanProperty("restore.cli"));
3235:
3236: if (gui || count != 0) {
3237: view = PerspectiveManager
3238: .loadPerspective(restoreFiles);
3239:
3240: if (view == null)
3241: view = newView(null, buffer);
3242: else if (buffer != null)
3243: view.setBuffer(buffer, true);
3244: }
3245:
3246: // Start I/O threads
3247: EditBus.send(new EditorStarted(null));
3248:
3249: VFSManager.start();
3250:
3251: // Start edit server
3252: if (server != null)
3253: server.start();
3254:
3255: GUIUtilities.hideSplashScreen();
3256:
3257: Log.log(Log.MESSAGE, jEdit.class, "Startup "
3258: + "complete");
3259:
3260: //{{{ Report any plugin errors
3261: if (pluginErrors != null) {
3262: showPluginErrorDialog();
3263: } //}}}
3264:
3265: startupDone = true;
3266:
3267: // in one case not a single AWT class will
3268: // have been touched (splash screen off +
3269: // -nogui -nobackground switches on command
3270: // line)
3271: Toolkit.getDefaultToolkit();
3272: }
3273: });
3274: } //}}}
3275:
3276: //{{{ showPluginErrorDialog() method
3277: private static void showPluginErrorDialog() {
3278: if (pluginErrors == null)
3279: return;
3280:
3281: String caption = getProperty("plugin-error.caption"
3282: + (pluginErrors.size() == 1 ? "-1" : ""));
3283:
3284: Frame frame = (PluginManager.getInstance() == null ? viewsFirst
3285: : PluginManager.getInstance());
3286:
3287: new ErrorListDialog(frame, getProperty("plugin-error.title"),
3288: caption, pluginErrors, true);
3289: pluginErrors = null;
3290: } //}}}
3291:
3292: //{{{ getNotLoadedPluginJARs() method
3293: private static void getNotLoadedPluginJARs(
3294: List<String> returnValue, String dir, String[] list) {
3295: loop: for (int i = 0; i < list.length; i++) {
3296: String name = list[i];
3297: if (!name.toLowerCase().endsWith(".jar"))
3298: continue loop;
3299:
3300: String path = MiscUtilities.constructPath(dir, name);
3301:
3302: for (int j = 0; j < jars.size(); j++) {
3303: PluginJAR jar = jars.elementAt(j);
3304: String jarPath = jar.getPath();
3305: String jarName = MiscUtilities.getFileName(jarPath);
3306:
3307: if (path.equals(jarPath))
3308: continue loop;
3309: else if (!new File(jarPath).exists()
3310: && name.equals(jarName))
3311: continue loop;
3312: }
3313:
3314: returnValue.add(path);
3315: }
3316: } //}}}
3317:
3318: //{{{ gotoMarker() method
3319: private static void gotoMarker(final View view,
3320: final Buffer buffer, final String marker) {
3321: VFSManager.runInAWTThread(new Runnable() {
3322: public void run() {
3323: int pos;
3324:
3325: // Handle line number
3326: if (marker.startsWith("+line:")) {
3327: try {
3328: String arg = marker.substring(6);
3329: String[] lineCol = arg.split(",");
3330: int line, col;
3331: if (lineCol.length > 1) {
3332: line = Integer.parseInt(lineCol[0]);
3333: col = Integer.parseInt(lineCol[1]);
3334: } else {
3335: line = Integer
3336: .parseInt(marker.substring(6));
3337: col = 1;
3338: }
3339: pos = buffer.getLineStartOffset(line - 1)
3340: + (col - 1);
3341: } catch (Exception e) {
3342: return;
3343: }
3344: }
3345: // Handle marker
3346: else if (marker.startsWith("+marker:")) {
3347: if (marker.length() != 9)
3348: return;
3349:
3350: Marker m = buffer.getMarker(marker.charAt(8));
3351: if (m == null)
3352: return;
3353: pos = m.getPosition();
3354: }
3355: // Can't happen
3356: else
3357: throw new InternalError();
3358:
3359: if (view != null && view.getBuffer() == buffer) {
3360: view.getTextArea().setCaretPosition(pos);
3361: buffer.setIntegerProperty(Buffer.CARET, pos);
3362: buffer.setBooleanProperty(Buffer.CARET_POSITIONED,
3363: true);
3364: } else {
3365: buffer.setIntegerProperty(Buffer.CARET, pos);
3366: buffer.setBooleanProperty(Buffer.CARET_POSITIONED,
3367: true);
3368: buffer.unsetProperty(Buffer.SCROLL_VERT);
3369: }
3370: }
3371: });
3372: } //}}}
3373:
3374: //{{{ addBufferToList() method
3375: private static void addBufferToList(Buffer buffer) {
3376: synchronized (bufferListLock) {
3377: String symlinkPath = buffer.getSymlinkPath();
3378: if ((VFSManager.getVFSForPath(symlinkPath)
3379: .getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0) {
3380: symlinkPath = symlinkPath.toLowerCase();
3381: }
3382:
3383: // if only one, clean, 'untitled' buffer is open, we
3384: // replace it
3385: if (viewCount <= 1 && buffersFirst != null
3386: && buffersFirst == buffersLast
3387: && buffersFirst.isUntitled()
3388: && !buffersFirst.isDirty()) {
3389: Buffer oldBuffersFirst = buffersFirst;
3390: buffersFirst = buffersLast = buffer;
3391: DisplayManager.bufferClosed(oldBuffersFirst);
3392: EditBus.send(new BufferUpdate(oldBuffersFirst, null,
3393: BufferUpdate.CLOSED));
3394:
3395: bufferHash.clear();
3396:
3397: bufferHash.put(symlinkPath, buffer);
3398: return;
3399: }
3400:
3401: bufferCount++;
3402:
3403: bufferHash.put(symlinkPath, buffer);
3404:
3405: if (buffersFirst == null) {
3406: buffersFirst = buffersLast = buffer;
3407: return;
3408: }
3409: //{{{ Sort buffer list
3410: else if (sortBuffers) {
3411: String str11, str12;
3412: if (sortByName) {
3413: str11 = buffer.getName();
3414: str12 = buffer.getDirectory();
3415: } else {
3416: str11 = buffer.getDirectory();
3417: str12 = buffer.getName();
3418: }
3419:
3420: Buffer _buffer = buffersFirst;
3421: while (_buffer != null) {
3422: String str21, str22;
3423: if (sortByName) {
3424: str21 = _buffer.getName();
3425: str22 = _buffer.getDirectory();
3426: } else {
3427: str21 = _buffer.getDirectory();
3428: str22 = _buffer.getName();
3429: }
3430:
3431: int comp = StandardUtilities.compareStrings(str11,
3432: str21, true);
3433: if (comp < 0
3434: || (comp == 0 && StandardUtilities
3435: .compareStrings(str12, str22, true) < 0)) {
3436: buffer.next = _buffer;
3437: buffer.prev = _buffer.prev;
3438: _buffer.prev = buffer;
3439: if (_buffer != buffersFirst)
3440: buffer.prev.next = buffer;
3441: else
3442: buffersFirst = buffer;
3443: return;
3444: }
3445:
3446: _buffer = _buffer.next;
3447: }
3448: } //}}}
3449:
3450: buffer.prev = buffersLast;
3451: // fixes the hang that can occur if we 'save as' to a
3452: // new filename which requires re-sorting
3453: buffer.next = null;
3454: buffersLast.next = buffer;
3455: buffersLast = buffer;
3456: }
3457: } //}}}
3458:
3459: //{{{ removeBufferFromList() method
3460: private static void removeBufferFromList(Buffer buffer) {
3461: synchronized (bufferListLock) {
3462: bufferCount--;
3463:
3464: String path = buffer.getPath();
3465: if (OperatingSystem.isCaseInsensitiveFS())
3466: path = path.toLowerCase();
3467:
3468: bufferHash.remove(path);
3469:
3470: if (buffer == buffersFirst && buffer == buffersLast) {
3471: buffersFirst = buffersLast = null;
3472: return;
3473: }
3474:
3475: if (buffer == buffersFirst) {
3476: buffersFirst = buffer.next;
3477: buffer.next.prev = null;
3478: } else {
3479: buffer.prev.next = buffer.next;
3480: }
3481:
3482: if (buffer == buffersLast) {
3483: buffersLast = buffersLast.prev;
3484: buffer.prev.next = null;
3485: } else {
3486: buffer.next.prev = buffer.prev;
3487: }
3488:
3489: // fixes the hang that can occur if we 'save as' to a new
3490: // filename which requires re-sorting
3491: buffer.next = buffer.prev = null;
3492: }
3493: } //}}}
3494:
3495: //{{{ addViewToList() method
3496: private static void addViewToList(View view) {
3497: viewCount++;
3498:
3499: if (viewsFirst == null)
3500: viewsFirst = viewsLast = view;
3501: else {
3502: view.prev = viewsLast;
3503: viewsLast.next = view;
3504: viewsLast = view;
3505: }
3506: } //}}}
3507:
3508: //{{{ removeViewFromList() method
3509: private static void removeViewFromList(View view) {
3510: viewCount--;
3511:
3512: if (viewsFirst == viewsLast) {
3513: viewsFirst = viewsLast = null;
3514: return;
3515: }
3516:
3517: if (view == viewsFirst) {
3518: viewsFirst = view.next;
3519: view.next.prev = null;
3520: } else {
3521: view.prev.next = view.next;
3522: }
3523:
3524: if (view == viewsLast) {
3525: viewsLast = viewsLast.prev;
3526: view.prev.next = null;
3527: } else {
3528: view.next.prev = view.prev;
3529: }
3530: } //}}}
3531:
3532: //{{{ closeView() method
3533: /**
3534: * closeView() used by exit().
3535: */
3536: private static void closeView(View view, boolean callExit) {
3537: PerspectiveManager.setPerspectiveDirty(true);
3538:
3539: if (viewsFirst == viewsLast && callExit)
3540: exit(view, false); /* exit does editor event & save */
3541: else {
3542: view.close();
3543: view.dispose();
3544: removeViewFromList(view);
3545:
3546: if (view == activeView)
3547: activeView = null;
3548: }
3549: } //}}}
3550:
3551: //{{{ loadModeCatalog() method
3552: /**
3553: * Loads a mode catalog file.
3554: * @since jEdit 3.2pre2
3555: */
3556: private static void loadModeCatalog(String path, boolean resource) {
3557: Log.log(Log.MESSAGE, jEdit.class, "Loading mode catalog file "
3558: + path);
3559:
3560: ModeCatalogHandler handler = new ModeCatalogHandler(
3561: MiscUtilities.getParentOfPath(path), resource) {
3562: protected Mode instantiateMode(String modeName) {
3563: return new JEditMode(modeName);
3564: }
3565: };
3566: try {
3567: InputStream _in;
3568: if (resource)
3569: _in = jEdit.class.getResourceAsStream(path);
3570: else
3571: _in = new FileInputStream(path);
3572: XMLUtilities.parseXML(_in, handler);
3573: } catch (IOException e) {
3574: Log.log(Log.ERROR, jEdit.class, e);
3575: }
3576: } //}}}
3577:
3578: //{{{ initKeyBindings() method
3579: /**
3580: * Loads all key bindings from the properties.
3581: * @since 3.1pre1
3582: */
3583: private static void initKeyBindings() {
3584: inputHandler.removeAllKeyBindings();
3585:
3586: ActionSet[] actionSets = getActionSets();
3587: for (int i = 0; i < actionSets.length; i++) {
3588: actionSets[i].initKeyBindings();
3589: }
3590: } //}}}
3591:
3592: //{{{ composeBufferPropsFromHistory() method
3593: /**
3594: * Compose buffer-local properties which can be got from history.
3595: * @since 4.3pre10
3596: */
3597: private static void composeBufferPropsFromHistory(Hashtable props,
3598: String path) {
3599: BufferHistory.Entry entry = BufferHistory.getEntry(path);
3600:
3601: if (entry != null && saveCaret
3602: && props.get(Buffer.CARET) == null) {
3603: props.put(Buffer.CARET, entry.caret);
3604: /* if(entry.selection != null)
3605: {
3606: // getSelection() converts from string to
3607: // Selection[]
3608: props.put(Buffer.SELECTION,entry.getSelection());
3609: } */
3610: }
3611:
3612: if (entry != null && props.get(JEditBuffer.ENCODING) == null) {
3613: if (entry.encoding != null)
3614: props.put(JEditBuffer.ENCODING, entry.encoding);
3615: }
3616:
3617: if (entry != null && props.get("mode") == null) {
3618: if (entry.mode != null)
3619: props.put("mode", entry.mode);
3620: }
3621: } //}}}
3622:
3623: //}}}
3624:
3625: //{{{ MyFocusManager class
3626: static class MyFocusManager extends DefaultKeyboardFocusManager {
3627: MyFocusManager() {
3628: setDefaultFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
3629: }
3630:
3631: public boolean postProcessKeyEvent(KeyEvent evt) {
3632: if (Options.SIMPLIFIED_KEY_HANDLING) {
3633: boolean result;
3634:
3635: /*
3636: Commenting this out is experimental.
3637:
3638: This code (if not commented out) seems to be the cause for
3639: https://sourceforge.net/tracker/index.php?func=detail&aid=1542026&group_id=588&atid=100588
3640:
3641: Because the simplified key handling is still experimental, breaking things here is still allowed. ;-)
3642:
3643: My intuition says that we should separate
3644: (1) key sequences which invoke some special actions against
3645: (2) key sequences which are ordinary input.
3646:
3647: While the former should be available in most or all jEdit windows,
3648: the latter should be available only within jEdit buffers.
3649:
3650: Currently, it seems, both former and latter are handled globally, leading to the errorneous behaviour
3651: of emitting keys to the buffer which are intendet to popup menus.
3652:
3653: Commenting this out leads to an inavailability of keyboard shortcuts if other windows than a View have the focus. (This is a regression.)
3654: In the long term, we should really separate global key-sequence triggered actions from local input.
3655: */
3656: if (!evt.isConsumed()) {
3657: Component comp = (Component) evt.getSource();
3658: if (!comp.isShowing())
3659: return true;
3660:
3661: for (;;) {
3662: if (comp instanceof View) {
3663: ((View) comp).processKeyEvent(evt,
3664: View.VIEW, true);
3665: return true;
3666: } else if (comp == null
3667: || comp instanceof Window
3668: || comp instanceof JEditTextArea) {
3669: if (comp instanceof PluginManager) {
3670: evt.setSource(comp);
3671: ((PluginManager) comp)
3672: .processKeyEvents(evt);
3673: }
3674: break;
3675: } else
3676: comp = comp.getParent();
3677: }
3678: }
3679:
3680: result = super .postProcessKeyEvent(evt);
3681:
3682: return result;
3683: } else {
3684: if (!evt.isConsumed()) {
3685: Component comp = (Component) evt.getSource();
3686: if (!comp.isShowing())
3687: return true;
3688:
3689: for (;;) {
3690: if (comp instanceof View) {
3691: ((View) comp).getInputHandler()
3692: .processKeyEvent(evt, View.VIEW,
3693: false);
3694: return true;
3695: } else if (comp == null
3696: || comp instanceof Window
3697: || comp instanceof JEditTextArea) {
3698: if (comp instanceof PluginManager) {
3699: evt.setSource(comp);
3700: ((PluginManager) comp)
3701: .processKeyEvents(evt);
3702: }
3703: break;
3704: } else
3705: comp = comp.getParent();
3706: }
3707: }
3708:
3709: return super .postProcessKeyEvent(evt);
3710: }
3711: }
3712: } //}}}
3713: }
|