PageRenderTime 72ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/jEdit.java

#
Java | 2748 lines | 1624 code | 333 blank | 791 comment | 377 complexity | b9734d3831fe104fde059ae39542be5a MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * jEdit.java - Main class of the jEdit editor
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1998, 2004 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. package org.gjt.sp.jedit;
  22. //{{{ Imports
  23. import bsh.UtilEvalError;
  24. import com.microstar.xml.*;
  25. import javax.swing.plaf.metal.*;
  26. import javax.swing.*;
  27. import java.awt.*;
  28. import java.io.*;
  29. import java.net.*;
  30. import java.text.MessageFormat;
  31. import java.util.*;
  32. import org.gjt.sp.jedit.buffer.BufferIORequest;
  33. import org.gjt.sp.jedit.buffer.KillRing;
  34. import org.gjt.sp.jedit.msg.*;
  35. import org.gjt.sp.jedit.gui.*;
  36. import org.gjt.sp.jedit.help.HelpViewer;
  37. import org.gjt.sp.jedit.io.*;
  38. import org.gjt.sp.jedit.pluginmgr.PluginManager;
  39. import org.gjt.sp.jedit.search.SearchAndReplace;
  40. import org.gjt.sp.jedit.syntax.*;
  41. import org.gjt.sp.jedit.textarea.*;
  42. import org.gjt.sp.util.Log;
  43. //}}}
  44. /**
  45. * The main class of the jEdit text editor.
  46. * @author Slava Pestov
  47. * @version $Id: jEdit.java 5053 2004-05-29 01:55:26Z spestov $
  48. */
  49. public class jEdit
  50. {
  51. //{{{ getVersion() method
  52. /**
  53. * Returns the jEdit version as a human-readable string.
  54. */
  55. public static String getVersion()
  56. {
  57. return MiscUtilities.buildToVersion(getBuild());
  58. } //}}}
  59. //{{{ getBuild() method
  60. /**
  61. * Returns the internal version. MiscUtilities.compareStrings() can be used
  62. * to compare different internal versions.
  63. */
  64. public static String getBuild()
  65. {
  66. // (major).(minor).(<99 = preX, 99 = final).(bug fix)
  67. return "04.02.14.00";
  68. } //}}}
  69. //{{{ main() method
  70. /**
  71. * The main method of the jEdit application.
  72. * This should never be invoked directly.
  73. * @param args The command line arguments
  74. */
  75. public static void main(String[] args)
  76. {
  77. //{{{ Check for Java 1.3 or later
  78. String javaVersion = System.getProperty("java.version");
  79. if(javaVersion.compareTo("1.3") < 0)
  80. {
  81. System.err.println("You are running Java version "
  82. + javaVersion + ".");
  83. System.err.println("jEdit requires Java 1.3 or later.");
  84. System.exit(1);
  85. } //}}}
  86. // later on we need to know if certain code is called from
  87. // the main thread
  88. mainThread = Thread.currentThread();
  89. settingsDirectory = ".jedit";
  90. // MacOS users expect the app to keep running after all windows
  91. // are closed
  92. background = OperatingSystem.isMacOS();
  93. //{{{ Parse command line
  94. boolean endOpts = false;
  95. int level = Log.WARNING;
  96. String portFile = "server";
  97. boolean restore = true;
  98. boolean newView = true;
  99. boolean newPlainView = false;
  100. boolean gui = true; // open initial view?
  101. boolean loadPlugins = true;
  102. boolean runStartupScripts = true;
  103. boolean quit = false;
  104. boolean wait = false;
  105. String userDir = System.getProperty("user.dir");
  106. // script to run
  107. String scriptFile = null;
  108. for(int i = 0; i < args.length; i++)
  109. {
  110. String arg = args[i];
  111. if(arg == null)
  112. continue;
  113. else if(arg.length() == 0)
  114. args[i] = null;
  115. else if(arg.startsWith("-") && !endOpts)
  116. {
  117. if(arg.equals("--"))
  118. endOpts = true;
  119. else if(arg.equals("-usage"))
  120. {
  121. version();
  122. System.err.println();
  123. usage();
  124. System.exit(1);
  125. }
  126. else if(arg.equals("-version"))
  127. {
  128. version();
  129. System.exit(1);
  130. }
  131. else if(arg.startsWith("-log="))
  132. {
  133. try
  134. {
  135. level = Integer.parseInt(arg.substring("-log=".length()));
  136. }
  137. catch(NumberFormatException nf)
  138. {
  139. System.err.println("Malformed option: " + arg);
  140. }
  141. }
  142. else if(arg.equals("-nosettings"))
  143. settingsDirectory = null;
  144. else if(arg.startsWith("-settings="))
  145. settingsDirectory = arg.substring(10);
  146. else if(arg.startsWith("-noserver"))
  147. portFile = null;
  148. else if(arg.equals("-server"))
  149. portFile = "server";
  150. else if(arg.startsWith("-server="))
  151. portFile = arg.substring(8);
  152. else if(arg.startsWith("-background"))
  153. background = true;
  154. else if(arg.startsWith("-nobackground"))
  155. background = false;
  156. else if(arg.equals("-gui"))
  157. gui = true;
  158. else if(arg.equals("-nogui"))
  159. gui = false;
  160. else if(arg.equals("-newview"))
  161. newView = true;
  162. else if(arg.equals("-newplainview"))
  163. newPlainView = true;
  164. else if(arg.equals("-reuseview"))
  165. newPlainView = newView = false;
  166. else if(arg.equals("-restore"))
  167. restore = true;
  168. else if(arg.equals("-norestore"))
  169. restore = false;
  170. else if(arg.equals("-plugins"))
  171. loadPlugins = true;
  172. else if(arg.equals("-noplugins"))
  173. loadPlugins = false;
  174. else if(arg.equals("-startupscripts"))
  175. runStartupScripts = true;
  176. else if(arg.equals("-nostartupscripts"))
  177. runStartupScripts = false;
  178. else if(arg.startsWith("-run="))
  179. scriptFile = arg.substring(5);
  180. else if(arg.equals("-wait"))
  181. wait = true;
  182. else if(arg.equals("-quit"))
  183. quit = true;
  184. else
  185. {
  186. System.err.println("Unknown option: "
  187. + arg);
  188. usage();
  189. System.exit(1);
  190. }
  191. args[i] = null;
  192. }
  193. } //}}}
  194. //{{{ We need these initializations very early on
  195. if(settingsDirectory != null)
  196. {
  197. settingsDirectory = MiscUtilities.constructPath(
  198. System.getProperty("user.home"),
  199. settingsDirectory);
  200. settingsDirectory = MiscUtilities.resolveSymlinks(
  201. settingsDirectory);
  202. }
  203. if(settingsDirectory != null && portFile != null)
  204. portFile = MiscUtilities.constructPath(settingsDirectory,portFile);
  205. else
  206. portFile = null;
  207. Log.init(true,level);
  208. //}}}
  209. //{{{ Try connecting to another running jEdit instance
  210. if(portFile != null && new File(portFile).exists())
  211. {
  212. int port, key;
  213. try
  214. {
  215. BufferedReader in = new BufferedReader(new FileReader(portFile));
  216. String check = in.readLine();
  217. if(!check.equals("b"))
  218. throw new Exception("Wrong port file format");
  219. port = Integer.parseInt(in.readLine());
  220. key = Integer.parseInt(in.readLine());
  221. Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),port);
  222. DataOutputStream out = new DataOutputStream(
  223. socket.getOutputStream());
  224. out.writeInt(key);
  225. String script;
  226. if(quit)
  227. {
  228. script = "socket.close();\n"
  229. + "jEdit.exit(null,true);\n";
  230. }
  231. else
  232. {
  233. script = makeServerScript(wait,restore,
  234. newView,newPlainView,args,
  235. scriptFile);
  236. }
  237. out.writeUTF(script);
  238. Log.log(Log.DEBUG,jEdit.class,"Waiting for server");
  239. // block until its closed
  240. try
  241. {
  242. socket.getInputStream().read();
  243. }
  244. catch(Exception e)
  245. {
  246. }
  247. in.close();
  248. out.close();
  249. System.exit(0);
  250. }
  251. catch(Exception e)
  252. {
  253. // ok, this one seems to confuse newbies
  254. // endlessly, so log it as NOTICE, not
  255. // ERROR
  256. Log.log(Log.NOTICE,jEdit.class,"An error occurred"
  257. + " while connecting to the jEdit server instance.");
  258. Log.log(Log.NOTICE,jEdit.class,"This probably means that"
  259. + " jEdit crashed and/or exited abnormally");
  260. Log.log(Log.NOTICE,jEdit.class,"the last time it was run.");
  261. Log.log(Log.NOTICE,jEdit.class,"If you don't"
  262. + " know what this means, don't worry.");
  263. Log.log(Log.NOTICE,jEdit.class,e);
  264. }
  265. }
  266. if(quit)
  267. {
  268. // if no server running and user runs jedit -quit,
  269. // just exit
  270. System.exit(0);
  271. } //}}}
  272. // don't show splash screen if there is a file named
  273. // 'nosplash' in the settings directory
  274. if(!new File(settingsDirectory,"nosplash").exists())
  275. GUIUtilities.showSplashScreen();
  276. //{{{ Initialize settings directory
  277. Writer stream;
  278. if(settingsDirectory != null)
  279. {
  280. File _settingsDirectory = new File(settingsDirectory);
  281. if(!_settingsDirectory.exists())
  282. _settingsDirectory.mkdirs();
  283. File _macrosDirectory = new File(settingsDirectory,"macros");
  284. if(!_macrosDirectory.exists())
  285. _macrosDirectory.mkdir();
  286. String logPath = MiscUtilities.constructPath(
  287. settingsDirectory,"activity.log");
  288. backupSettingsFile(new File(logPath));
  289. try
  290. {
  291. stream = new BufferedWriter(new FileWriter(logPath));
  292. // Write a warning message:
  293. String lineSep = System.getProperty("line.separator");
  294. stream.write("Log file created on " + new Date());
  295. stream.write(lineSep);
  296. stream.write("IMPORTANT:");
  297. stream.write(lineSep);
  298. stream.write("Because updating this file after "
  299. + "every log message would kill");
  300. stream.write(lineSep);
  301. stream.write("performance, it will be *incomplete* "
  302. + "unless you invoke the");
  303. stream.write(lineSep);
  304. stream.write("Utilities->Troubleshooting->Update "
  305. + "Activity Log on Disk command!");
  306. stream.write(lineSep);
  307. }
  308. catch(Exception e)
  309. {
  310. e.printStackTrace();
  311. stream = null;
  312. }
  313. }
  314. else
  315. {
  316. stream = null;
  317. } //}}}
  318. Log.setLogWriter(stream);
  319. Log.log(Log.NOTICE,jEdit.class,"jEdit version " + getVersion());
  320. Log.log(Log.MESSAGE,jEdit.class,"Settings directory is "
  321. + settingsDirectory);
  322. //{{{ Get things rolling
  323. initMisc();
  324. initSystemProperties();
  325. GUIUtilities.advanceSplashProgress();
  326. GUIUtilities.init();
  327. BeanShell.init();
  328. if(jEditHome != null)
  329. initSiteProperties();
  330. initUserProperties();
  331. //}}}
  332. //{{{ Initialize server
  333. if(portFile != null)
  334. {
  335. server = new EditServer(portFile);
  336. if(!server.isOK())
  337. server = null;
  338. }
  339. else
  340. {
  341. if(background)
  342. {
  343. background = false;
  344. Log.log(Log.WARNING,jEdit.class,"You cannot specify both the"
  345. + " -background and -noserver switches");
  346. }
  347. } //}}}
  348. //{{{ Do more stuff
  349. initPLAF();
  350. VFSManager.init();
  351. initResources();
  352. SearchAndReplace.load();
  353. GUIUtilities.advanceSplashProgress();
  354. if(loadPlugins)
  355. initPlugins();
  356. HistoryModel.loadHistory();
  357. BufferHistory.load();
  358. KillRing.load();
  359. propertiesChanged();
  360. GUIUtilities.advanceSplashProgress();
  361. // Buffer sort
  362. sortBuffers = getBooleanProperty("sortBuffers");
  363. sortByName = getBooleanProperty("sortByName");
  364. reloadModes();
  365. GUIUtilities.advanceSplashProgress();
  366. //}}}
  367. //{{{ Initialize Java 1.4-specific code
  368. if(OperatingSystem.hasJava14())
  369. {
  370. try
  371. {
  372. ClassLoader loader = jEdit.class.getClassLoader();
  373. Class clazz;
  374. if(loader != null)
  375. clazz = loader.loadClass("org.gjt.sp.jedit.Java14");
  376. else
  377. clazz = Class.forName("org.gjt.sp.jedit.Java14");
  378. java.lang.reflect.Method meth = clazz
  379. .getMethod("init",new Class[0]);
  380. meth.invoke(null,new Object[0]);
  381. }
  382. catch(Exception e)
  383. {
  384. Log.log(Log.ERROR,jEdit.class,e);
  385. System.exit(1);
  386. }
  387. } //}}}
  388. //{{{ Activate plugins that must be activated at startup
  389. for(int i = 0; i < jars.size(); i++)
  390. {
  391. ((PluginJAR)jars.elementAt(i)).activatePluginIfNecessary();
  392. } //}}}
  393. //{{{ Load macros and run startup scripts, after plugins and settings are loaded
  394. Macros.loadMacros();
  395. Macros.getMacroActionSet().initKeyBindings();
  396. if(runStartupScripts && jEditHome != null)
  397. {
  398. String path = MiscUtilities.constructPath(jEditHome,"startup");
  399. File file = new File(path);
  400. if(file.exists())
  401. runStartupScripts(file);
  402. }
  403. if(runStartupScripts && settingsDirectory != null)
  404. {
  405. String path = MiscUtilities.constructPath(settingsDirectory,"startup");
  406. File file = new File(path);
  407. if(!file.exists())
  408. file.mkdirs();
  409. else
  410. runStartupScripts(file);
  411. } //}}}
  412. //{{{ Run script specified with -run= parameter
  413. if(scriptFile != null)
  414. {
  415. scriptFile = MiscUtilities.constructPath(userDir,scriptFile);
  416. try
  417. {
  418. BeanShell.getNameSpace().setVariable("args",args);
  419. }
  420. catch(UtilEvalError e)
  421. {
  422. Log.log(Log.ERROR,jEdit.class,e);
  423. }
  424. BeanShell.runScript(null,scriptFile,null,false);
  425. } //}}}
  426. GUIUtilities.advanceSplashProgress();
  427. // Open files, create the view and hide the splash screen.
  428. finishStartup(gui,restore,userDir,args);
  429. } //}}}
  430. //{{{ Property methods
  431. //{{{ getProperties() method
  432. /**
  433. * Returns the properties object which contains all known
  434. * jEdit properties. Note that as of jEdit 4.2pre10, this returns a
  435. * new collection, not the existing properties instance.
  436. * @since jEdit 3.1pre4
  437. */
  438. public static final Properties getProperties()
  439. {
  440. return propMgr.getProperties();
  441. } //}}}
  442. //{{{ getProperty() method
  443. /**
  444. * Fetches a property, returning null if it's not defined.
  445. * @param name The property
  446. */
  447. public static final String getProperty(String name)
  448. {
  449. return propMgr.getProperty(name);
  450. } //}}}
  451. //{{{ getProperty() method
  452. /**
  453. * Fetches a property, returning the default value if it's not
  454. * defined.
  455. * @param name The property
  456. * @param def The default value
  457. */
  458. public static final String getProperty(String name, String def)
  459. {
  460. String value = propMgr.getProperty(name);
  461. if(value == null)
  462. return def;
  463. else
  464. return value;
  465. } //}}}
  466. //{{{ getProperty() method
  467. /**
  468. * Returns the property with the specified name.<p>
  469. *
  470. * The elements of the <code>args</code> array are substituted
  471. * into the value of the property in place of strings of the
  472. * form <code>{<i>n</i>}</code>, where <code><i>n</i></code> is an index
  473. * in the array.<p>
  474. *
  475. * You can find out more about this feature by reading the
  476. * documentation for the <code>format</code> method of the
  477. * <code>java.text.MessageFormat</code> class.
  478. *
  479. * @param name The property
  480. * @param args The positional parameters
  481. */
  482. public static final String getProperty(String name, Object[] args)
  483. {
  484. if(name == null)
  485. return null;
  486. if(args == null)
  487. return getProperty(name);
  488. else
  489. {
  490. String value = getProperty(name);
  491. if(value == null)
  492. return null;
  493. else
  494. return MessageFormat.format(value,args);
  495. }
  496. } //}}}
  497. //{{{ getBooleanProperty() method
  498. /**
  499. * Returns the value of a boolean property.
  500. * @param name The property
  501. */
  502. public static final boolean getBooleanProperty(String name)
  503. {
  504. return getBooleanProperty(name,false);
  505. } //}}}
  506. //{{{ getBooleanProperty() method
  507. /**
  508. * Returns the value of a boolean property.
  509. * @param name The property
  510. * @param def The default value
  511. */
  512. public static final boolean getBooleanProperty(String name, boolean def)
  513. {
  514. String value = getProperty(name);
  515. if(value == null)
  516. return def;
  517. else if(value.equals("true") || value.equals("yes")
  518. || value.equals("on"))
  519. return true;
  520. else if(value.equals("false") || value.equals("no")
  521. || value.equals("off"))
  522. return false;
  523. else
  524. return def;
  525. } //}}}
  526. //{{{ getIntegerProperty() method
  527. /**
  528. * Returns the value of an integer property.
  529. * @param name The property
  530. * @param def The default value
  531. * @since jEdit 4.0pre1
  532. */
  533. public static final int getIntegerProperty(String name, int def)
  534. {
  535. String value = getProperty(name);
  536. if(value == null)
  537. return def;
  538. else
  539. {
  540. try
  541. {
  542. return Integer.parseInt(value.trim());
  543. }
  544. catch(NumberFormatException nf)
  545. {
  546. return def;
  547. }
  548. }
  549. } //}}}
  550. //{{{ getDoubleProperty() method
  551. public static double getDoubleProperty(String name, double def)
  552. {
  553. String value = getProperty(name);
  554. if(value == null)
  555. return def;
  556. else
  557. {
  558. try
  559. {
  560. return Double.parseDouble(value.trim());
  561. }
  562. catch(NumberFormatException nf)
  563. {
  564. return def;
  565. }
  566. }
  567. }
  568. //}}}
  569. //{{{ getFontProperty() method
  570. /**
  571. * Returns the value of a font property. The family is stored
  572. * in the <code><i>name</i></code> property, the font size is stored
  573. * in the <code><i>name</i>size</code> property, and the font style is
  574. * stored in <code><i>name</i>style</code>. For example, if
  575. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  576. * properties will be named <code>view.gutter.font</code>,
  577. * <code>view.gutter.fontsize</code>, and
  578. * <code>view.gutter.fontstyle</code>.
  579. *
  580. * @param name The property
  581. * @since jEdit 4.0pre1
  582. */
  583. public static final Font getFontProperty(String name)
  584. {
  585. return getFontProperty(name,null);
  586. } //}}}
  587. //{{{ getFontProperty() method
  588. /**
  589. * Returns the value of a font property. The family is stored
  590. * in the <code><i>name</i></code> property, the font size is stored
  591. * in the <code><i>name</i>size</code> property, and the font style is
  592. * stored in <code><i>name</i>style</code>. For example, if
  593. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  594. * properties will be named <code>view.gutter.font</code>,
  595. * <code>view.gutter.fontsize</code>, and
  596. * <code>view.gutter.fontstyle</code>.
  597. *
  598. * @param name The property
  599. * @param def The default value
  600. * @since jEdit 4.0pre1
  601. */
  602. public static final Font getFontProperty(String name, Font def)
  603. {
  604. String family = getProperty(name);
  605. String sizeString = getProperty(name + "size");
  606. String styleString = getProperty(name + "style");
  607. if(family == null || sizeString == null || styleString == null)
  608. return def;
  609. else
  610. {
  611. int size, style;
  612. try
  613. {
  614. size = Integer.parseInt(sizeString);
  615. }
  616. catch(NumberFormatException nf)
  617. {
  618. return def;
  619. }
  620. try
  621. {
  622. style = Integer.parseInt(styleString);
  623. }
  624. catch(NumberFormatException nf)
  625. {
  626. return def;
  627. }
  628. return new Font(family,style,size);
  629. }
  630. } //}}}
  631. //{{{ getColorProperty() method
  632. /**
  633. * Returns the value of a color property.
  634. * @param name The property name
  635. * @since jEdit 4.0pre1
  636. */
  637. public static Color getColorProperty(String name)
  638. {
  639. return getColorProperty(name,Color.black);
  640. } //}}}
  641. //{{{ getColorProperty() method
  642. /**
  643. * Returns the value of a color property.
  644. * @param name The property name
  645. * @param def The default value
  646. * @since jEdit 4.0pre1
  647. */
  648. public static Color getColorProperty(String name, Color def)
  649. {
  650. String value = getProperty(name);
  651. if(value == null)
  652. return def;
  653. else
  654. return GUIUtilities.parseColor(value,def);
  655. } //}}}
  656. //{{{ setColorProperty() method
  657. /**
  658. * Sets the value of a color property.
  659. * @param name The property name
  660. * @param value The value
  661. * @since jEdit 4.0pre1
  662. */
  663. public static void setColorProperty(String name, Color value)
  664. {
  665. setProperty(name,GUIUtilities.getColorHexString(value));
  666. } //}}}
  667. //{{{ setProperty() method
  668. /**
  669. * Sets a property to a new value.
  670. * @param name The property
  671. * @param value The new value
  672. */
  673. public static final void setProperty(String name, String value)
  674. {
  675. propMgr.setProperty(name,value);
  676. } //}}}
  677. //{{{ setTemporaryProperty() method
  678. /**
  679. * Sets a property to a new value. Properties set using this
  680. * method are not saved to the user properties list.
  681. * @param name The property
  682. * @param value The new value
  683. * @since jEdit 2.3final
  684. */
  685. public static final void setTemporaryProperty(String name, String value)
  686. {
  687. propMgr.setTemporaryProperty(name,value);
  688. } //}}}
  689. //{{{ setBooleanProperty() method
  690. /**
  691. * Sets a boolean property.
  692. * @param name The property
  693. * @param value The value
  694. */
  695. public static final void setBooleanProperty(String name, boolean value)
  696. {
  697. setProperty(name,value ? "true" : "false");
  698. } //}}}
  699. //{{{ setIntegerProperty() method
  700. /**
  701. * Sets the value of an integer property.
  702. * @param name The property
  703. * @param value The value
  704. * @since jEdit 4.0pre1
  705. */
  706. public static final void setIntegerProperty(String name, int value)
  707. {
  708. setProperty(name,String.valueOf(value));
  709. } //}}}
  710. //{{{ setDoubleProperty() method
  711. public static final void setDoubleProperty(String name, double value)
  712. {
  713. setProperty(name,String.valueOf(value));
  714. }
  715. //}}}
  716. //{{{ setFontProperty() method
  717. /**
  718. * Sets the value of a font property. The family is stored
  719. * in the <code><i>name</i></code> property, the font size is stored
  720. * in the <code><i>name</i>size</code> property, and the font style is
  721. * stored in <code><i>name</i>style</code>. For example, if
  722. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  723. * properties will be named <code>view.gutter.font</code>,
  724. * <code>view.gutter.fontsize</code>, and
  725. * <code>view.gutter.fontstyle</code>.
  726. *
  727. * @param name The property
  728. * @param value The value
  729. * @since jEdit 4.0pre1
  730. */
  731. public static final void setFontProperty(String name, Font value)
  732. {
  733. setProperty(name,value.getFamily());
  734. setIntegerProperty(name + "size",value.getSize());
  735. setIntegerProperty(name + "style",value.getStyle());
  736. } //}}}
  737. //{{{ unsetProperty() method
  738. /**
  739. * Unsets (clears) a property.
  740. * @param name The property
  741. */
  742. public static final void unsetProperty(String name)
  743. {
  744. propMgr.unsetProperty(name);
  745. } //}}}
  746. //{{{ resetProperty() method
  747. /**
  748. * Resets a property to its default value.
  749. * @param name The property
  750. *
  751. * @since jEdit 2.5pre3
  752. */
  753. public static final void resetProperty(String name)
  754. {
  755. propMgr.resetProperty(name);
  756. } //}}}
  757. //{{{ propertiesChanged() method
  758. /**
  759. * Reloads various settings from the properties.
  760. */
  761. public static void propertiesChanged()
  762. {
  763. initKeyBindings();
  764. Autosave.setInterval(getIntegerProperty("autosave",30));
  765. saveCaret = getBooleanProperty("saveCaret");
  766. //theme = new JEditMetalTheme();
  767. //theme.propertiesChanged();
  768. //MetalLookAndFeel.setCurrentTheme(theme);
  769. UIDefaults defaults = UIManager.getDefaults();
  770. // give all text areas the same font
  771. Font font = getFontProperty("view.font");
  772. //defaults.put("TextField.font",font);
  773. defaults.put("TextArea.font",font);
  774. defaults.put("TextPane.font",font);
  775. // Enable/Disable tooltips
  776. ToolTipManager.sharedInstance().setEnabled(
  777. jEdit.getBooleanProperty("showTooltips"));
  778. initProxy();
  779. // we do this here instead of adding buffers to the bus.
  780. Buffer buffer = buffersFirst;
  781. while(buffer != null)
  782. {
  783. buffer.resetCachedProperties();
  784. buffer.propertiesChanged();
  785. buffer = buffer.next;
  786. }
  787. HistoryModel.propertiesChanged();
  788. KillRing.propertiesChanged();
  789. EditBus.send(new PropertiesChanged(null));
  790. } //}}}
  791. //}}}
  792. //{{{ Plugin management methods
  793. //{{{ getNotLoadedPluginJARs() method
  794. /**
  795. * Returns a list of plugin JARs that are not currently loaded
  796. * by examining the user and system plugin directories.
  797. * @since jEdit 3.2pre1
  798. */
  799. public static String[] getNotLoadedPluginJARs()
  800. {
  801. Vector returnValue = new Vector();
  802. if(jEditHome != null)
  803. {
  804. String systemPluginDir = MiscUtilities
  805. .constructPath(jEditHome,"jars");
  806. String[] list = new File(systemPluginDir).list();
  807. if(list != null)
  808. getNotLoadedPluginJARs(returnValue,systemPluginDir,list);
  809. }
  810. if(settingsDirectory != null)
  811. {
  812. String userPluginDir = MiscUtilities
  813. .constructPath(settingsDirectory,"jars");
  814. String[] list = new File(userPluginDir).list();
  815. if(list != null)
  816. {
  817. getNotLoadedPluginJARs(returnValue,
  818. userPluginDir,list);
  819. }
  820. }
  821. String[] _returnValue = new String[returnValue.size()];
  822. returnValue.copyInto(_returnValue);
  823. return _returnValue;
  824. } //}}}
  825. //{{{ getPlugin() method
  826. /**
  827. * Returns the plugin with the specified class name.
  828. */
  829. public static EditPlugin getPlugin(String name)
  830. {
  831. return getPlugin(name, false);
  832. } //}}}
  833. //{{{ getPlugin(String, boolean) method
  834. /**
  835. * Returns the plugin with the specified class name. If
  836. * <code>loadIfNecessary</code> is true, the plugin will be activated in
  837. * case it has not yet been started.
  838. * @since jEdit 4.2pre4
  839. */
  840. public static EditPlugin getPlugin(String name, boolean loadIfNecessary)
  841. {
  842. EditPlugin[] plugins = getPlugins();
  843. EditPlugin plugin = null;
  844. for(int i = 0; i < plugins.length; i++)
  845. {
  846. if(plugins[i].getClassName().equals(name))
  847. plugin = plugins[i];
  848. if(loadIfNecessary)
  849. {
  850. if(plugin instanceof EditPlugin.Deferred)
  851. {
  852. plugin.getPluginJAR().activatePlugin();
  853. plugin = plugin.getPluginJAR().getPlugin();
  854. break;
  855. }
  856. }
  857. }
  858. return plugin;
  859. } //}}}
  860. //{{{ getPlugins() method
  861. /**
  862. * Returns an array of installed plugins.
  863. */
  864. public static EditPlugin[] getPlugins()
  865. {
  866. Vector vector = new Vector();
  867. for(int i = 0; i < jars.size(); i++)
  868. {
  869. EditPlugin plugin = ((PluginJAR)jars.elementAt(i))
  870. .getPlugin();
  871. if(plugin != null)
  872. vector.add(plugin);
  873. }
  874. EditPlugin[] array = new EditPlugin[vector.size()];
  875. vector.copyInto(array);
  876. return array;
  877. } //}}}
  878. //{{{ getPluginJARs() method
  879. /**
  880. * Returns an array of installed plugins.
  881. * @since jEdit 4.2pre1
  882. */
  883. public static PluginJAR[] getPluginJARs()
  884. {
  885. PluginJAR[] array = new PluginJAR[jars.size()];
  886. jars.copyInto(array);
  887. return array;
  888. } //}}}
  889. //{{{ getPluginJAR() method
  890. /**
  891. * Returns the JAR with the specified path name.
  892. * @param path The path name
  893. * @since jEdit 4.2pre1
  894. */
  895. public static PluginJAR getPluginJAR(String path)
  896. {
  897. for(int i = 0; i < jars.size(); i++)
  898. {
  899. PluginJAR jar = (PluginJAR)jars.elementAt(i);
  900. if(jar.getPath().equals(path))
  901. return jar;
  902. }
  903. return null;
  904. } //}}}
  905. //{{{ addPluginJAR() method
  906. /**
  907. * Loads the plugin JAR with the specified path. Some notes about this
  908. * method:
  909. *
  910. * <ul>
  911. * <li>Calling this at a time other than jEdit startup can have
  912. * unpredictable results if the plugin has not been updated for the
  913. * jEdit 4.2 plugin API.
  914. * <li>You must make sure yourself the plugin is not already loaded.
  915. * <li>After loading, you just make sure all the plugin's dependencies
  916. * are satisified before activating the plugin, using the
  917. * {@link PluginJAR#checkDependencies()} method.
  918. * </ul>
  919. *
  920. * @param path The JAR file path
  921. * @since jEdit 4.2pre1
  922. */
  923. public static void addPluginJAR(String path)
  924. {
  925. // backwards compatibility...
  926. PluginJAR jar = new EditPlugin.JAR(new File(path));
  927. jars.addElement(jar);
  928. jar.init();
  929. EditBus.send(new PluginUpdate(jar,PluginUpdate.LOADED,false));
  930. if(!isMainThread())
  931. {
  932. EditBus.send(new DynamicMenuChanged("plugins"));
  933. initKeyBindings();
  934. }
  935. } //}}}
  936. //{{{ addPluginJARsFromDirectory() method
  937. /**
  938. * Loads all plugins in a directory.
  939. * @param directory The directory
  940. * @since jEdit 4.2pre1
  941. */
  942. private static void addPluginJARsFromDirectory(String directory)
  943. {
  944. Log.log(Log.NOTICE,jEdit.class,"Loading plugins from "
  945. + directory);
  946. File file = new File(directory);
  947. if(!(file.exists() && file.isDirectory()))
  948. return;
  949. String[] plugins = file.list();
  950. if(plugins == null)
  951. return;
  952. for(int i = 0; i < plugins.length; i++)
  953. {
  954. String plugin = plugins[i];
  955. if(!plugin.toLowerCase().endsWith(".jar"))
  956. continue;
  957. String path = MiscUtilities.constructPath(directory,plugin);
  958. // remove this when 4.1 plugin API is deprecated
  959. if(plugin.equals("EditBuddy.jar")
  960. || plugin.equals("PluginManager.jar")
  961. || plugin.equals("Firewall.jar")
  962. || plugin.equals("Tidy.jar")
  963. || plugin.equals("DragAndDrop.jar"))
  964. {
  965. pluginError(path,"plugin-error.obsolete",null);
  966. continue;
  967. }
  968. addPluginJAR(path);
  969. }
  970. } //}}}
  971. //{{{ removePluginJAR() method
  972. /**
  973. * Unloads the given plugin JAR with the specified path. Note that
  974. * calling this at a time other than jEdit shutdown can have
  975. * unpredictable results if the plugin has not been updated for the
  976. * jEdit 4.2 plugin API.
  977. *
  978. * @param jar The <code>PluginJAR</code> instance
  979. * @param exit Set to true if jEdit is exiting; enables some
  980. * shortcuts so the editor can close faster.
  981. * @since jEdit 4.2pre1
  982. */
  983. public static void removePluginJAR(PluginJAR jar, boolean exit)
  984. {
  985. if(exit)
  986. {
  987. jar.uninit(true);
  988. }
  989. else
  990. {
  991. jar.uninit(false);
  992. jars.removeElement(jar);
  993. initKeyBindings();
  994. }
  995. EditBus.send(new PluginUpdate(jar,PluginUpdate.UNLOADED,exit));
  996. if(!isMainThread() && !exit)
  997. EditBus.send(new DynamicMenuChanged("plugins"));
  998. } //}}}
  999. //}}}
  1000. //{{{ Action methods
  1001. //{{{ getActionContext() method
  1002. /**
  1003. * Returns the action context used to store editor actions.
  1004. * @since jEdit 4.2pre1
  1005. */
  1006. public static ActionContext getActionContext()
  1007. {
  1008. return actionContext;
  1009. } //}}}
  1010. //{{{ addActionSet() method
  1011. /**
  1012. * Adds a new action set to jEdit's list. Plugins probably won't
  1013. * need to call this method.
  1014. * @since jEdit 4.0pre1
  1015. */
  1016. public static void addActionSet(ActionSet actionSet)
  1017. {
  1018. actionContext.addActionSet(actionSet);
  1019. } //}}}
  1020. //{{{ removeActionSet() method
  1021. /**
  1022. * Removes an action set from jEdit's list. Plugins probably won't
  1023. * need to call this method.
  1024. * @since jEdit 4.2pre1
  1025. */
  1026. public static void removeActionSet(ActionSet actionSet)
  1027. {
  1028. actionContext.removeActionSet(actionSet);
  1029. } //}}}
  1030. //{{{ getBuiltInActionSet() method
  1031. /**
  1032. * Returns the set of commands built into jEdit.
  1033. * @since jEdit 4.2pre1
  1034. */
  1035. public static ActionSet getBuiltInActionSet()
  1036. {
  1037. return builtInActionSet;
  1038. } //}}}
  1039. //{{{ getActionSets() method
  1040. /**
  1041. * Returns all registered action sets.
  1042. * @since jEdit 4.0pre1
  1043. */
  1044. public static ActionSet[] getActionSets()
  1045. {
  1046. return actionContext.getActionSets();
  1047. } //}}}
  1048. //{{{ getAction() method
  1049. /**
  1050. * Returns the specified action.
  1051. * @param name The action name
  1052. */
  1053. public static EditAction getAction(String name)
  1054. {
  1055. return actionContext.getAction(name);
  1056. } //}}}
  1057. //{{{ getActionSetForAction() method
  1058. /**
  1059. * Returns the action set that contains the specified action.
  1060. *
  1061. * @param action The action
  1062. * @since jEdit 4.2pre1
  1063. */
  1064. public static ActionSet getActionSetForAction(String action)
  1065. {
  1066. return actionContext.getActionSetForAction(action);
  1067. } //}}}
  1068. //{{{ getActionSetForAction() method
  1069. /**
  1070. * @deprecated Use the form that takes a String instead
  1071. */
  1072. public static ActionSet getActionSetForAction(EditAction action)
  1073. {
  1074. return actionContext.getActionSetForAction(action.getName());
  1075. } //}}}
  1076. //{{{ getActions() method
  1077. /**
  1078. * @deprecated Call getActionNames() instead
  1079. */
  1080. public static EditAction[] getActions()
  1081. {
  1082. String[] names = actionContext.getActionNames();
  1083. EditAction[] actions = new EditAction[names.length];
  1084. for(int i = 0; i < actions.length; i++)
  1085. {
  1086. actions[i] = actionContext.getAction(names[i]);
  1087. if(actions[i] == null)
  1088. Log.log(Log.ERROR,jEdit.class,"wtf: " + names[i]);
  1089. }
  1090. return actions;
  1091. } //}}}
  1092. //{{{ getActionNames() method
  1093. /**
  1094. * Returns all registered action names.
  1095. */
  1096. public static String[] getActionNames()
  1097. {
  1098. return actionContext.getActionNames();
  1099. } //}}}
  1100. //}}}
  1101. //{{{ Edit mode methods
  1102. //{{{ reloadModes() method
  1103. /**
  1104. * Reloads all edit modes.
  1105. * @since jEdit 3.2pre2
  1106. */
  1107. public static void reloadModes()
  1108. {
  1109. /* Try to guess the eventual size to avoid unnecessary
  1110. * copying */
  1111. modes = new Vector(50);
  1112. //{{{ Load the global catalog
  1113. if(jEditHome == null)
  1114. loadModeCatalog("/modes/catalog",true);
  1115. else
  1116. {
  1117. loadModeCatalog(MiscUtilities.constructPath(jEditHome,
  1118. "modes","catalog"),false);
  1119. } //}}}
  1120. //{{{ Load user catalog
  1121. if(settingsDirectory != null)
  1122. {
  1123. File userModeDir = new File(MiscUtilities.constructPath(
  1124. settingsDirectory,"modes"));
  1125. if(!userModeDir.exists())
  1126. userModeDir.mkdirs();
  1127. File userCatalog = new File(MiscUtilities.constructPath(
  1128. settingsDirectory,"modes","catalog"));
  1129. if(!userCatalog.exists())
  1130. {
  1131. // create dummy catalog
  1132. FileWriter out = null;
  1133. try
  1134. {
  1135. out = new FileWriter(userCatalog);
  1136. out.write(jEdit.getProperty("defaultCatalog"));
  1137. out.close();
  1138. }
  1139. catch(IOException io)
  1140. {
  1141. Log.log(Log.ERROR,jEdit.class,io);
  1142. }
  1143. finally
  1144. {
  1145. try
  1146. {
  1147. if(out != null)
  1148. out.close();
  1149. }
  1150. catch(IOException e)
  1151. {
  1152. }
  1153. }
  1154. }
  1155. loadModeCatalog(userCatalog.getPath(),false);
  1156. } //}}}
  1157. Buffer buffer = buffersFirst;
  1158. while(buffer != null)
  1159. {
  1160. // This reloads the token marker and sends a message
  1161. // which causes edit panes to repaint their text areas
  1162. buffer.setMode();
  1163. buffer = buffer.next;
  1164. }
  1165. } //}}}
  1166. //{{{ getMode() method
  1167. /**
  1168. * Returns the edit mode with the specified name.
  1169. * @param name The edit mode
  1170. */
  1171. public static Mode getMode(String name)
  1172. {
  1173. for(int i = 0; i < modes.size(); i++)
  1174. {
  1175. Mode mode = (Mode)modes.elementAt(i);
  1176. if(mode.getName().equals(name))
  1177. return mode;
  1178. }
  1179. return null;
  1180. } //}}}
  1181. //{{{ getModes() method
  1182. /**
  1183. * Returns an array of installed edit modes.
  1184. */
  1185. public static Mode[] getModes()
  1186. {
  1187. Mode[] array = new Mode[modes.size()];
  1188. modes.copyInto(array);
  1189. return array;
  1190. } //}}}
  1191. //}}}
  1192. //{{{ Buffer creation methods
  1193. //{{{ openFiles() method
  1194. /**
  1195. * Opens the file names specified in the argument array. This
  1196. * handles +line and +marker arguments just like the command
  1197. * line parser.
  1198. * @param parent The parent directory
  1199. * @param args The file names to open
  1200. * @since jEdit 3.2pre4
  1201. */
  1202. public static Buffer openFiles(View view, String parent, String[] args)
  1203. {
  1204. Buffer retVal = null;
  1205. Buffer lastBuffer = null;
  1206. for(int i = 0; i < args.length; i++)
  1207. {
  1208. String arg = args[i];
  1209. if(arg == null)
  1210. continue;
  1211. else if(arg.startsWith("+line:") || arg.startsWith("+marker:"))
  1212. {
  1213. if(lastBuffer != null)
  1214. gotoMarker(view,lastBuffer,arg);
  1215. continue;
  1216. }
  1217. lastBuffer = openFile(null,parent,arg,false,null);
  1218. if(retVal == null && lastBuffer != null)
  1219. retVal = lastBuffer;
  1220. }
  1221. if(view != null && retVal != null)
  1222. view.setBuffer(retVal);
  1223. return retVal;
  1224. } //}}}
  1225. //{{{ openFile() method
  1226. /**
  1227. * Opens a file. Note that as of jEdit 2.5pre1, this may return
  1228. * null if the buffer could not be opened.
  1229. * @param view The view to open the file in
  1230. * @param path The file path
  1231. *
  1232. * @since jEdit 2.4pre1
  1233. */
  1234. public static Buffer openFile(View view, String path)
  1235. {
  1236. return openFile(view,null,path,false,new Hashtable());
  1237. } //}}}
  1238. //{{{ openFile() method
  1239. /**
  1240. * @deprecated The openFile() forms with the readOnly parameter
  1241. * should not be used. The readOnly prameter is no longer supported.
  1242. */
  1243. public static Buffer openFile(View view, String parent,
  1244. String path, boolean readOnly, boolean newFile)
  1245. {
  1246. return openFile(view,parent,path,newFile,new Hashtable());
  1247. } //}}}
  1248. //{{{ openFile() method
  1249. /**
  1250. * @deprecated The openFile() forms with the readOnly parameter
  1251. * should not be used. The readOnly prameter is no longer supported.
  1252. */
  1253. public static Buffer openFile(View view, String parent,
  1254. String path, boolean readOnly, boolean newFile,
  1255. Hashtable props)
  1256. {
  1257. return openFile(view,parent,path,newFile,props);
  1258. } //}}}
  1259. //{{{ openFile() method
  1260. /**
  1261. * Opens a file. This may return null if the buffer could not be
  1262. * opened for some reason.
  1263. * @param view The view to open the file in
  1264. * @param parent The parent directory of the file
  1265. * @param path The path name of the file
  1266. * @param newFile True if the file should not be loaded from disk
  1267. * be prompted if it should be reloaded
  1268. * @param props Buffer-local properties to set in the buffer
  1269. *
  1270. * @since jEdit 3.2pre10
  1271. */
  1272. public static Buffer openFile(View view, String parent,
  1273. String path, boolean newFile, Hashtable props)
  1274. {
  1275. PerspectiveManager.setPerspectiveDirty(true);
  1276. if(view != null && parent == null)
  1277. parent = view.getBuffer().getDirectory();
  1278. if(MiscUtilities.isURL(path))
  1279. {
  1280. if(MiscUtilities.getProtocolOfURL(path).equals("file"))
  1281. path = path.substring(5);
  1282. }
  1283. path = MiscUtilities.constructPath(parent,path);
  1284. Buffer newBuffer;
  1285. synchronized(bufferListLock)
  1286. {
  1287. Buffer buffer = getBuffer(path);
  1288. if(buffer != null)
  1289. {
  1290. if(view != null)
  1291. view.setBuffer(buffer);
  1292. return buffer;
  1293. }
  1294. if(props == null)
  1295. props = new Hashtable();
  1296. BufferHistory.Entry entry = BufferHistory.getEntry(path);
  1297. if(entry != null && saveCaret && props.get(Buffer.CARET) == null)
  1298. {
  1299. props.put(Buffer.CARET,new Integer(entry.caret));
  1300. /* if(entry.selection != null)
  1301. {
  1302. // getSelection() converts from string to
  1303. // Selection[]
  1304. props.put(Buffer.SELECTION,entry.getSelection());
  1305. } */
  1306. }
  1307. if(entry != null && props.get(Buffer.ENCODING) == null)
  1308. {
  1309. if(entry.encoding != null)
  1310. props.put(Buffer.ENCODING,entry.encoding);
  1311. }
  1312. newBuffer = new Buffer(path,newFile,false,props);
  1313. if(!newBuffer.load(view,false))
  1314. return null;
  1315. addBufferToList(newBuffer);
  1316. }
  1317. EditBus.send(new BufferUpdate(newBuffer,view,BufferUpdate.CREATED));
  1318. if(view != null)
  1319. view.setBuffer(newBuffer);
  1320. return newBuffer;
  1321. } //}}}
  1322. //{{{ openTemporary() method
  1323. /**
  1324. * Opens a temporary buffer. A temporary buffer is like a normal
  1325. * buffer, except that an event is not fired, the the buffer is
  1326. * not added to the buffers list.
  1327. *
  1328. * @param view The view to open the file in
  1329. * @param parent The parent directory of the file
  1330. * @param path The path name of the file
  1331. * @param newFile True if the file should not be loaded from disk
  1332. *
  1333. * @since jEdit 3.2pre10
  1334. */
  1335. public static Buffer openTemporary(View view, String parent,
  1336. String path, boolean newFile)
  1337. {
  1338. if(view != null && parent == null)
  1339. parent = view.getBuffer().getDirectory();
  1340. if(MiscUtilities.isURL(path))
  1341. {
  1342. if(MiscUtilities.getProtocolOfURL(path).equals("file"))
  1343. path = path.substring(5);
  1344. }
  1345. path = MiscUtilities.constructPath(parent,path);
  1346. synchronized(bufferListLock)
  1347. {
  1348. Buffer buffer = getBuffer(path);
  1349. if(buffer != null)
  1350. return buffer;
  1351. buffer = new Buffer(path,newFile,true,new Hashtable());
  1352. if(!buffer.load(view,false))
  1353. return null;
  1354. else
  1355. return buffer;
  1356. }
  1357. } //}}}
  1358. //{{{ commitTemporary() method
  1359. /**
  1360. * Adds a temporary buffer to the buffer list. This must be done
  1361. * before allowing the user to interact with the buffer in any
  1362. * way.
  1363. * @param buffer The buffer
  1364. */
  1365. public static void commitTemporary(Buffer buffer)
  1366. {
  1367. if(!buffer.isTemporary())
  1368. return;
  1369. PerspectiveManager.setPerspectiveDirty(true);
  1370. addBufferToList(buffer);
  1371. buffer.commitTemporary();
  1372. // send full range of events to avoid breaking plugins
  1373. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.CREATED));
  1374. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOAD_STARTED));
  1375. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOADED));
  1376. } //}}}
  1377. //{{{ newFile() method
  1378. /**
  1379. * Creates a new `untitled' file.
  1380. * @param view The view to create the file in
  1381. */
  1382. public static Buffer newFile(View view)
  1383. {
  1384. String path;
  1385. if(view != null && view.getBuffer() != null)
  1386. {
  1387. path = view.getBuffer().getDirectory();
  1388. VFS vfs = VFSManager.getVFSForPath(path);
  1389. // don't want 'New File' to create a read only buffer
  1390. // if current file is on SQL VFS or something
  1391. if((vfs.getCapabilities() & VFS.WRITE_CAP) == 0)
  1392. path = System.getProperty("user.home");
  1393. }
  1394. else
  1395. path = null;
  1396. return newFile(view,path);
  1397. } //}}}
  1398. //{{{ newFile() method
  1399. /**
  1400. * Creates a new `untitled' file.
  1401. * @param view The view to create the file in
  1402. * @param dir The directory to create the file in
  1403. * @since jEdit 3.1pre2
  1404. */
  1405. public static Buffer newFile(View view, String dir)
  1406. {
  1407. // If only one new file is open which is clean, just close
  1408. // it, which will create an 'Untitled-1'
  1409. if(dir != null
  1410. && buffersFirst != null
  1411. && buffersFirst == buffersLast
  1412. && buffersFirst.isUntitled()
  1413. && !buffersFirst.isDirty())
  1414. {
  1415. closeBuffer(view,buffersFirst);
  1416. // return the newly created 'untitled-1'
  1417. return buffersFirst;
  1418. }
  1419. // Find the highest Untitled-n file
  1420. int untitledCount = 0;
  1421. Buffer buffer = buffersFirst;
  1422. while(buffer != null)
  1423. {
  1424. if(buffer.getName().startsWith("Untitled-"))
  1425. {
  1426. try
  1427. {
  1428. untitledCount = Math.max(untitledCount,
  1429. Integer.parseInt(buffer.getName()
  1430. .substring(9)));
  1431. }
  1432. catch(NumberFormatException nf)
  1433. {
  1434. }
  1435. }
  1436. buffer = buffer.next;
  1437. }
  1438. return openFile(view,dir,"Untitled-" + (untitledCount+1),true,null);
  1439. } //}}}
  1440. //}}}
  1441. //{{{ Buffer management methods
  1442. //{{{ closeBuffer() method
  1443. /**
  1444. * Closes a buffer. If there are unsaved changes, the user is
  1445. * prompted if they should be saved first.
  1446. * @param view The view
  1447. * @param buffer The buffer
  1448. * @return True if the buffer was really closed, false otherwise
  1449. */
  1450. public static boolean closeBuffer(View view, Buffer buffer)
  1451. {
  1452. // Wait for pending I/O requests
  1453. if(buffer.isPerformingIO())
  1454. {
  1455. VFSManager.waitForRequests();
  1456. if(VFSManager.errorOccurred())
  1457. return false;
  1458. }
  1459. if(buffer.isDirty())
  1460. {
  1461. Object[] args = { buffer.getName() };
  1462. int result = GUIUtilities.confirm(view,"notsaved",args,
  1463. JOptionPane.YES_NO_CANCEL_OPTION,
  1464. JOptionPane.WARNING_MESSAGE);
  1465. if(result == JOptionPane.YES_OPTION)
  1466. {
  1467. if(!buffer.save(view,null,true))
  1468. return false;
  1469. VFSManager.waitForRequests();
  1470. if(buffer.getBooleanProperty(BufferIORequest
  1471. .ERROR_OCCURRED))
  1472. {
  1473. return false;
  1474. }
  1475. }
  1476. else if(result != JOptionPane.NO_OPTION)
  1477. return false;
  1478. }
  1479. _closeBuffer(view,buffer);
  1480. return true;
  1481. } //}}}
  1482. //{{{ _closeBuffer() method
  1483. /**
  1484. * Closes the buffer, even if it has unsaved changes.
  1485. * @param view The view
  1486. * @param buffer The buffer
  1487. *
  1488. * @since jEdit 2.2pre1
  1489. */
  1490. public static void _closeBuffer(View view, Buffer buffer)
  1491. {
  1492. if(buffer.isClosed())
  1493. {
  1494. // can happen if the user presses C+w twice real
  1495. // quick and the buffer has unsaved changes
  1496. return;
  1497. }
  1498. PerspectiveManager.setPerspectiveDirty(true);
  1499. if(!buffer.isNewFile())
  1500. {
  1501. view.getEditPane().saveCaretInfo();
  1502. Integer _caret = (Integer)buffer.getProperty(Buffer.CARET);
  1503. int caret = (_caret == null ? 0 : _caret.intValue());
  1504. BufferHistory.setEntry(buffer.getPath(),caret,
  1505. (Selection[])buffer.getProperty(Buffer.SELECTION),
  1506. buffer.getStringProperty(Buffer.ENCODING));
  1507. }
  1508. String path = buffer.getSymlinkPath();
  1509. if((VFSManager.getVFSForPath(path).getCapabilities()
  1510. & VFS.CASE_INSENSITIVE_CAP) != 0)
  1511. {
  1512. path = path.toLowerCase();
  1513. }
  1514. bufferHash.remove(path);
  1515. removeBufferFromList(buffer);
  1516. buffer.close();
  1517. DisplayManager.bufferClosed(buffer);
  1518. EditBus.send(new BufferUpdate(buffer,view,BufferUpdate.CLOSED));
  1519. // Create a new file when the last is closed
  1520. if(buffersFirst == null && buffersLast == null)
  1521. newFile(view);
  1522. } //}}}
  1523. //{{{ closeAllBuffers() method
  1524. /**
  1525. * Closes all open buffers.
  1526. * @param view The view
  1527. */
  1528. public static boolean closeAllBuffers(View view)
  1529. {
  1530. return closeAllBuffers(view,false);
  1531. } //}}}
  1532. //{{{ closeAllBuffers() method
  1533. /**
  1534. * Closes all open buffers.
  1535. * @param view The view
  1536. * @param isExiting This must be false unless this method is
  1537. * being called by the exit() method
  1538. */
  1539. public static boolean closeAllBuffers(View view, boolean isExiting)
  1540. {
  1541. boolean dirty = false;
  1542. Buffer buffer = buffersFirst;
  1543. while(buffer != null)
  1544. {
  1545. if(buffer.isDirty())
  1546. {
  1547. dirty = true;
  1548. break;
  1549. }
  1550. buffer = buffer.next;
  1551. }
  1552. if(dirty)
  1553. {
  1554. boolean ok = new CloseDialog(view).isOK();
  1555. if(!ok)
  1556. return false;
  1557. }
  1558. // Wait for pending I/O requests
  1559. VFSManager.waitForRequests();
  1560. if(VFSManager.errorOccurred())
  1561. return false;
  1562. // close remaining buffers (the close dialog only deals with
  1563. // dirty ones)
  1564. buffer = buffersFirst;
  1565. // zero it here so that BufferTabs doesn't have any problems
  1566. buffersFirst = buffersLast = null;
  1567. bufferHash.clear();
  1568. bufferCount = 0;
  1569. while(buffer != null)
  1570. {
  1571. if(!buffer.isNewFile())
  1572. {
  1573. Integer _caret = (Integer)buffer.getProperty(Buffer.CARET);
  1574. int caret = (_caret == null ? 0 : _caret.intValue());
  1575. BufferHistory.setEntry(buffer.getPath(),caret,
  1576. (Selection[])buffer.getProperty(Buffer.SELECTION),
  1577. buffer.getStringProperty(Buffer.ENCODING));
  1578. }
  1579. buffer.close();
  1580. DisplayManager.bufferClosed(buffer);
  1581. if(!isExiting)
  1582. {
  1583. EditBus.send(new BufferUpdate(buffer,view,
  1584. BufferUpdate.CLOSED));
  1585. }
  1586. buffer = buffer.next;
  1587. }
  1588. if(!isExiting)
  1589. newFile(view);
  1590. PerspectiveManager.setPerspectiveDirty(true);
  1591. return true;
  1592. } //}}}
  1593. //{{{ saveAllBuffers() method
  1594. /**
  1595. * Saves all open buffers.
  1596. * @param view The view
  1597. * @since jEdit 4.2pre1
  1598. */
  1599. public static void saveAllBuffers(View view)
  1600. {
  1601. saveAllBuffers(view,jEdit.getBooleanProperty("confirmSaveAll"));
  1602. } //}}}
  1603. //{{{ saveAllBuffers() method
  1604. /**
  1605. * Saves all open buffers.
  1606. * @param view The view
  1607. * @param confirm If true, a confirmation dialog will be shown first
  1608. * @since jEdit 2.7pre2
  1609. */
  1610. public static void saveAllBuffers(View view, boolean confirm)
  1611. {
  1612. if(confirm)
  1613. {
  1614. int result = GUIUtilities.confirm(view,"saveall",null,
  1615. JOptionPane.YES_NO_OPTION,
  1616. JOptionPane.QUESTION_MESSAGE);
  1617. if(result != JOptionPane.YES_OPTION)
  1618. return;
  1619. }
  1620. Buffer current = view.getBuffer();
  1621. Buffer buffer = buffersFirst;
  1622. while(buffer != null)
  1623. {
  1624. if(buffer.isDirty())
  1625. {
  1626. if(buffer.isNewFile())
  1627. view.setBuffer(buffer);
  1628. buffer.save(view,null,true);
  1629. }
  1630. buffer = buffer.next;
  1631. }
  1632. view.setBuffer(current);
  1633. } //}}}
  1634. //{{{ reloadAllBuffers() method
  1635. /**
  1636. * Reloads all open buffers.
  1637. * @param view The view
  1638. * @param confirm If true, a confirmation dialog will be shown first
  1639. * if any buffers are dirty
  1640. * @since jEdit 2.7pre2
  1641. */
  1642. public static void reloadAllBuffers(final View view, boolean confirm)
  1643. {
  1644. boolean hasDirty = false;
  1645. Buffer[] buffers = jEdit.getBuffers();
  1646. for(int i = 0; i < buffers.length && hasDirty == false; i++)
  1647. hasDirty = buffers[i].isDirty();
  1648. if(confirm && hasDirty)
  1649. {
  1650. int result = GUIUtilities.confirm(view,"reload-all",null,
  1651. JOptionPane.YES_NO_OPTION,
  1652. JOptionPane.QUESTION_MESSAGE);
  1653. if(result != JOptionPane.YES_OPTION)
  1654. return;
  1655. }
  1656. // save caret info. Buffer.load() will load it.
  1657. View _view = viewsFirst;
  1658. while(_view != null)
  1659. {
  1660. EditPane[] panes = _view.getEditPanes();
  1661. for(int i = 0; i < panes.length; i++)
  1662. {
  1663. panes[i].saveCaretInfo();
  1664. }
  1665. _view = _view.next;
  1666. }
  1667. for(int i = 0; i < buffers.length; i++)
  1668. {
  1669. Buffer buffer = buffers[i];
  1670. buffer.load(view,true);
  1671. }
  1672. } //}}}
  1673. //{{{ _getBuffer() method
  1674. /**
  1675. * Returns the buffer with the specified path name. The path name
  1676. * must be an absolute, canonical, path.
  1677. *
  1678. * @param path The path name
  1679. * @see MiscUtilities#constructPath(String,String)
  1680. * @see MiscUtilities#resolveSymlinks(String)
  1681. * @see #getBuffer(String)
  1682. *
  1683. * @since jEdit 4.2pre7
  1684. */
  1685. public static Buffer _getBuffer(String path)
  1686. {
  1687. // paths on case-insensitive filesystems are stored as lower
  1688. // case in the hash.
  1689. if((VFSManager.getVFSForPath(path).getCapabilities()
  1690. & VFS.CASE_INSENSITIVE_CAP) != 0)
  1691. {
  1692. path = path.toLowerCase();
  1693. }
  1694. synchronized(bufferListLock)
  1695. {
  1696. return (Buffer)bufferHash.get(path);
  1697. }
  1698. } //}}}
  1699. //{{{ getBuffer() method
  1700. /**
  1701. * Returns the buffer with the specified path name. The path name
  1702. * must be an absolute path. This method automatically resolves
  1703. * symbolic links. If performance is critical, cache the canonical
  1704. * path and call {@link #_getBuffer(String)} instead.
  1705. *
  1706. * @param path The path name
  1707. * @see MiscUtilities#constructPath(String,String)
  1708. * @see MiscUtilities#resolveSymlinks(String)
  1709. */
  1710. public static Buffer getBuffer(String path)
  1711. {
  1712. if(MiscUtilities.isURL(path))
  1713. return _getBuffer(path);
  1714. else
  1715. return _getBuffer(MiscUtilities.resolveSymlinks(path));
  1716. } //}}}
  1717. //{{{ getBuffers() method
  1718. /**
  1719. * Returns an array of open buffers.
  1720. */
  1721. public static Buffer[] getBuffers()
  1722. {
  1723. synchronized(bufferListLock)
  1724. {
  1725. Buffer[] buffers = new Buffer[bufferCount];
  1726. Buffer buffer = buffersFirst;
  1727. for(int i = 0; i < bufferCount; i++)
  1728. {
  1729. buffers[i] = buffer;
  1730. buffer = buffer.next;
  1731. }
  1732. return buffers;
  1733. }
  1734. } //}}}
  1735. //{{{ getBufferCount() method
  1736. /**
  1737. * Returns the number of open buffers.
  1738. */
  1739. public static int getBufferCount()
  1740. {
  1741. return bufferCount;
  1742. } //}}}
  1743. //{{{ getFirstBuffer() method
  1744. /**
  1745. * Returns the first buffer.
  1746. */
  1747. public static Buffer getFirstBuffer()
  1748. {
  1749. return buffersFirst;
  1750. } //}}}
  1751. //{{{ getLastBuffer() method
  1752. /**
  1753. * Returns the last buffer.
  1754. */
  1755. public static Buffer getLastBuffer()
  1756. {
  1757. return buffersLast;
  1758. } //}}}
  1759. //{{{ checkBufferStatus() method
  1760. /**
  1761. * Checks each buffer's status on disk and shows the dialog box
  1762. * informing the user that buffers changed on disk, if necessary.
  1763. * @param view The view
  1764. * @since jEdit 4.2pre1
  1765. */
  1766. public static void checkBufferStatus(View view)
  1767. {
  1768. // still need to call the status check even if the option is
  1769. // off, so that the write protection is updated if it changes
  1770. // on disk
  1771. boolean showDialogSetting = getBooleanProperty(
  1772. "autoReloadDialog");
  1773. // auto reload changed buffers?
  1774. boolean autoReloadSetting = getBooleanProperty(
  1775. "autoReload");
  1776. // the problem with this is that if we have two edit panes
  1777. // looking at the same buffer and the file is reloaded both
  1778. // will jump to the same location
  1779. View _view = viewsFirst;
  1780. while(_view != null)
  1781. {
  1782. EditPane[] editPanes = _view.getEditPanes();
  1783. for(int i = 0; i < editPanes.length; i++)
  1784. {
  1785. editPanes[i].saveCaretInfo();
  1786. }
  1787. _view = _view.next;
  1788. }
  1789. Buffer buffer = buffersFirst;
  1790. int[] states = new int[bufferCount];
  1791. int i = 0;
  1792. boolean show = false;
  1793. while(buffer != null)
  1794. {
  1795. states[i] = buffer.checkFileStatus(view);
  1796. switch(states[i])
  1797. {
  1798. case Buffer.FILE_CHANGED:
  1799. if(autoReloadSetting
  1800. && showDialogSetting
  1801. && !buffer.isDirty())
  1802. {
  1803. buffer.load(view,true);
  1804. }
  1805. /* fall through */
  1806. case Buffer.FILE_DELETED:
  1807. show = true;
  1808. break;
  1809. }
  1810. buffer = buffer.next;
  1811. i++;
  1812. }
  1813. if(show && showDialogSetting)
  1814. new FilesChangedDialog(view,states,autoReloadSetting);
  1815. } //}}}
  1816. //}}}
  1817. //{{{ View methods
  1818. //{{{ getInputHandler() method
  1819. /**
  1820. * Returns the current input handler (key binding to action mapping)
  1821. * @see org.gjt.sp.jedit.gui.InputHandler
  1822. */
  1823. public static InputHandler getInputHandler()
  1824. {
  1825. return inputHandler;
  1826. } //}}}
  1827. /* public static void newViewTest()
  1828. {
  1829. long time = System.currentTimeMillis();
  1830. for(int i = 0; i < 30; i++)
  1831. {
  1832. Buffer b = newFile(null);
  1833. b.insert(0,"x");
  1834. new View(b,null,false);
  1835. }
  1836. System.err.println(System.currentTimeMillis() - time);
  1837. } */
  1838. //{{{ newView() method
  1839. /**
  1840. * Creates a new view.
  1841. * @param view An existing view
  1842. * @since jEdit 3.2pre2
  1843. */
  1844. public static View newView(View view)
  1845. {
  1846. return newView(view,null,false);
  1847. } //}}}
  1848. //{{{ newView() method
  1849. /**
  1850. * Creates a new view of a buffer.
  1851. * @param view An existing view
  1852. * @param buffer The buffer
  1853. */
  1854. public static View newView(View view, Buffer buffer)
  1855. {
  1856. return newView(view,buffer,false);
  1857. } //}}}
  1858. //{{{ newView() method
  1859. /**
  1860. * Creates a new view of a buffer.
  1861. * @param view An existing view
  1862. * @param buffer The buffer
  1863. * @param plainView If true, the view will not have dockable windows or
  1864. * tool bars.
  1865. *
  1866. * @since 4.1pre2
  1867. */
  1868. public static View newView(View view, Buffer buffer, boolean plainView)
  1869. {
  1870. View.ViewConfig config;
  1871. if(view != null && (plainView == view.isPlainView()))
  1872. config = view.getViewConfig();
  1873. else
  1874. config = new View.ViewConfig(plainView);
  1875. return newView(view,buffer,config);
  1876. } //}}}
  1877. //{{{ newView() method
  1878. /**
  1879. * Creates a new view.
  1880. * @param view An existing view
  1881. * @param buffer A buffer to display, or null
  1882. * @param config Encapsulates the view geometry, split configuration
  1883. * and if the view is a plain view
  1884. * @since jEdit 4.2pre1
  1885. */
  1886. public static View newView(View view, Buffer buffer, View.ViewConfig config)
  1887. {
  1888. PerspectiveManager.setPerspectiveDirty(true);
  1889. try
  1890. {
  1891. if(view != null)
  1892. {
  1893. view.showWaitCursor();
  1894. view.getEditPane().saveCaretInfo();
  1895. }
  1896. View newView = new View(buffer,config);
  1897. addViewToList(newView);
  1898. if(!config.plainView)
  1899. {
  1900. DockableWindowManager wm = newView.getDockableWindowManager();
  1901. if(config.top != null
  1902. && config.top.length() != 0)
  1903. wm.showDockableWindow(config.top);
  1904. if(config.left != null
  1905. && config.left.length() != 0)
  1906. wm.showDockableWindow(config.left);
  1907. if(config.bottom != null
  1908. && config.bottom.length() != 0)
  1909. wm.showDockableWindow(config.bottom);
  1910. if(config.right != null
  1911. && config.right.length() != 0)
  1912. wm.showDockableWindow(config.right);
  1913. }
  1914. newView.pack();
  1915. if(config.width != 0 && config.height != 0)
  1916. {
  1917. Rectangle desired = new Rectangle(
  1918. config.x,config.y,config.width,
  1919. config.height);
  1920. if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
  1921. {
  1922. new GUIUtilities.UnixWorkaround(newView,
  1923. "view",desired,config.extState);
  1924. }
  1925. else
  1926. {
  1927. newView.setBounds(desired);
  1928. GUIUtilities.setExtendedState(newView,
  1929. config.extState);
  1930. }
  1931. }
  1932. else
  1933. GUIUtilities.centerOnScreen(newView);
  1934. EditBus.send(new ViewUpdate(newView,ViewUpdate.CREATED));
  1935. newView.show();
  1936. // show tip of the day
  1937. if(newView == viewsFirst)
  1938. {
  1939. newView.getTextArea().requestFocus();
  1940. // Don't show the welcome message if jEdit was started
  1941. // with the -nosettings switch
  1942. if(settingsDirectory != null && getBooleanProperty("firstTime"))
  1943. new HelpViewer();
  1944. else if(jEdit.getBooleanProperty("tip.show"))
  1945. new TipOfTheDay(newView);
  1946. setBooleanProperty("firstTime",false);
  1947. }
  1948. else
  1949. GUIUtilities.requestFocus(newView,newView.getTextArea());
  1950. return newView;
  1951. }
  1952. finally
  1953. {
  1954. if(view != null)
  1955. view.hideWaitCursor();
  1956. }
  1957. } //}}}
  1958. //{{{ closeView() method
  1959. /**
  1960. * Closes a view.
  1961. *
  1962. * jEdit will exit if this was the last open view.
  1963. */
  1964. public static void closeView(View view)
  1965. {
  1966. closeView(view,true);
  1967. } //}}}
  1968. //{{{ getViews() method
  1969. /**
  1970. * Returns an array of all open views.
  1971. */
  1972. public static View[] getViews()
  1973. {
  1974. View[] views = new View[viewCount];
  1975. View view = viewsFirst;
  1976. for(int i = 0; i < viewCount; i++)
  1977. {
  1978. views[i] = view;
  1979. view = view.next;
  1980. }
  1981. return views;
  1982. } //}}}
  1983. //{{{ getViewCount() method
  1984. /**
  1985. * Returns the number of open views.
  1986. */
  1987. public static int getViewCount()
  1988. {
  1989. return viewCount;
  1990. } //}}}
  1991. //{{{ getFirstView() method
  1992. /**
  1993. * Returns the first view.
  1994. */
  1995. public static View getFirstView()
  1996. {
  1997. return viewsFirst;
  1998. } //}}}
  1999. //{{{ getLastView() method
  2000. /**
  2001. * Returns the last view.
  2002. */
  2003. public static View getLastView()
  2004. {
  2005. return viewsLast;
  2006. } //}}}
  2007. //{{{ getActiveView() method
  2008. /**
  2009. * Returns the currently focused view.
  2010. * @since jEdit 4.1pre1
  2011. */
  2012. public static View getActiveView()
  2013. {
  2014. if(activeView == null)
  2015. {
  2016. // eg user just closed a view and didn't focus another
  2017. return viewsFirst;
  2018. }
  2019. else
  2020. return activeView;
  2021. } //}}}
  2022. //}}}
  2023. //{{{ Miscellaneous methods
  2024. //{{{ isMainThread() method
  2025. /**
  2026. * Returns true if the currently running thread is the main thread.
  2027. * @since jEdit 4.2pre1
  2028. */
  2029. public static boolean isMainThread()
  2030. {
  2031. return (Thread.currentThread() == mainThread);
  2032. } //}}}
  2033. //{{{ isBackgroundMode() method
  2034. /**
  2035. * Returns true if jEdit was started with the <code>-background</code>
  2036. * command-line switch.
  2037. * @since jEdit 4.0pre4
  2038. */
  2039. public static boolean isBackgroundModeEnabled()
  2040. {
  2041. return background;
  2042. } //}}}
  2043. //{{{ showMemoryStatusDialog() method
  2044. /**
  2045. * Performs garbage collection and displays a dialog box showing
  2046. * memory status.
  2047. * @param view The view
  2048. * @since jEdit 4.0pre1
  2049. */
  2050. public static void showMemoryDialog(View view)
  2051. {
  2052. Runtime rt = Runtime.getRuntime();
  2053. int before = (int) (rt.freeMemory() / 1024);
  2054. System.gc();
  2055. int after = (int) (rt.freeMemory() / 1024);
  2056. int total = (int) (rt.totalMemory() / 1024);
  2057. JProgressBar progress = new JProgressBar(0,total);
  2058. progress.setValue(total - after);
  2059. progress.setStringPainted(true);
  2060. progress.setString(jEdit.getProperty("memory-status.use",
  2061. new Object[] { new Integer(total - after),
  2062. new Integer(total) }));
  2063. Object[] message = new Object[4];
  2064. message[0] = getProperty("memory-status.gc",
  2065. new Object[] { new Integer(after - before) });
  2066. message[1] = Box.createVerticalStrut(12);
  2067. message[2] = progress;
  2068. message[3] = Box.createVerticalStrut(6);
  2069. JOptionPane.showMessageDialog(view,message,
  2070. jEdit.getProperty("memory-status.title"),
  2071. JOptionPane.INFORMATION_MESSAGE);
  2072. } //}}}
  2073. //{{{ getJEditHome() method
  2074. /**
  2075. * Returns the jEdit install directory.
  2076. */
  2077. public static String getJEditHome()
  2078. {
  2079. return jEditHome;
  2080. } //}}}
  2081. //{{{ getSettingsDirectory() method
  2082. /**
  2083. * Returns the path of the directory where user-specific settings
  2084. * are stored. This will be <code>null</code> if jEdit was
  2085. * started with the <code>-nosettings</code> command-line switch; do not
  2086. * blindly use this method without checking for a <code>null</code>
  2087. * return value first.
  2088. */
  2089. public static String getSettingsDirectory()
  2090. {
  2091. return settingsDirectory;
  2092. } //}}}
  2093. //{{{ getJARCacheDirectory() method
  2094. /**
  2095. * Returns the directory where plugin cache files are stored.
  2096. * @since jEdit 4.2pre1
  2097. */
  2098. public static String getJARCacheDirectory()
  2099. {
  2100. return jarCacheDirectory;
  2101. } //}}}
  2102. //{{{ backupSettingsFile() method
  2103. /**
  2104. * Backs up the specified file in the settings directory.
  2105. * You should call this on any settings files your plugin
  2106. * writes.
  2107. * @param file The file
  2108. * @since jEdit 4.0pre1
  2109. */
  2110. public static void backupSettingsFile(File file)
  2111. {
  2112. if(settingsDirectory == null)
  2113. return;
  2114. String backupDir = MiscUtilities.constructPath(
  2115. settingsDirectory,"settings-backup");
  2116. File dir = new File(backupDir);
  2117. if(!dir.exists())
  2118. dir.mkdirs();
  2119. // ... sweet. saveBackup() will create backupDir if it
  2120. // doesn't exist.
  2121. MiscUtilities.saveBackup(file,5,null,"~",backupDir);
  2122. } //}}}
  2123. //{{{ saveSettings() method
  2124. /**
  2125. * Saves all user preferences to disk.
  2126. */
  2127. public static void saveSettings()
  2128. {
  2129. if(settingsDirectory == null)
  2130. return;
  2131. Abbrevs.save();
  2132. FavoritesVFS.saveFavorites();
  2133. HistoryModel.saveHistory();
  2134. Registers.saveRegisters();
  2135. SearchAndReplace.save();
  2136. BufferHistory.save();
  2137. KillRing.save();
  2138. File file1 = new File(MiscUtilities.constructPath(
  2139. settingsDirectory,"#properties#save#"));
  2140. File file2 = new File(MiscUtilities.constructPath(
  2141. settingsDirectory,"properties"));
  2142. if(file2.exists() && file2.lastModified() != propsModTime)
  2143. {
  2144. Log.log(Log.WARNING,jEdit.class,file2 + " changed"
  2145. + " on disk; will not save user properties");
  2146. }
  2147. else
  2148. {
  2149. backupSettingsFile(file2);
  2150. try
  2151. {
  2152. OutputStream out = new FileOutputStream(file1);
  2153. propMgr.saveUserProps(out);
  2154. file2.delete();
  2155. file1.renameTo(file2);
  2156. }
  2157. catch(IOException io)
  2158. {
  2159. Log.log(Log.ERROR,jEdit.class,io);
  2160. }
  2161. propsModTime = file2.lastModified();
  2162. }
  2163. } //}}}
  2164. //{{{ exit() method
  2165. /**
  2166. * Exits cleanly from jEdit, prompting the user if any unsaved files
  2167. * should be saved first.
  2168. * @param view The view from which this exit was called
  2169. * @param reallyExit If background mode is enabled and this parameter
  2170. * is true, then jEdit will close all open views instead of exiting
  2171. * entirely.
  2172. */
  2173. public static void exit(View view, boolean reallyExit)
  2174. {
  2175. // Close dialog, view.close() call need a view...
  2176. if(view == null)
  2177. view = activeView;
  2178. // Wait for pending I/O requests
  2179. VFSManager.waitForRequests();
  2180. // Send EditorExitRequested
  2181. EditBus.send(new EditorExitRequested(view));
  2182. // Even if reallyExit is false, we still exit properly
  2183. // if background mode is off
  2184. reallyExit |= !background;
  2185. PerspectiveManager.savePerspective(false);
  2186. // Close all buffers
  2187. if(!closeAllBuffers(view,reallyExit))
  2188. return;
  2189. // If we are running in background mode and
  2190. // reallyExit was not specified, then return here.
  2191. if(!reallyExit)
  2192. {
  2193. // in this case, we can't directly call
  2194. // view.close(); we have to call closeView()
  2195. // for all open views
  2196. view = viewsFirst;
  2197. while(view != null)
  2198. {
  2199. closeView(view,false);
  2200. view = view.next;
  2201. }
  2202. // Save settings in case user kills the backgrounded
  2203. // jEdit process
  2204. saveSettings();
  2205. }
  2206. else
  2207. {
  2208. // Save view properties here
  2209. if(view != null)
  2210. view.close();
  2211. // Stop autosave timer
  2212. Autosave.stop();
  2213. // Stop server
  2214. if(server != null)
  2215. server.stopServer();
  2216. // Stop all plugins
  2217. PluginJAR[] plugins = getPluginJARs();
  2218. for(int i = 0; i < plugins.length; i++)
  2219. {
  2220. removePluginJAR(plugins[i],true);
  2221. }
  2222. // Send EditorExiting
  2223. EditBus.send(new EditorExiting(null));
  2224. // Save settings
  2225. saveSettings();
  2226. // Close activity log stream
  2227. Log.closeStream();
  2228. // Byebye...
  2229. System.exit(0);
  2230. }
  2231. } //}}}
  2232. //{{{ getEditServer() method
  2233. /**
  2234. * Returns the edit server instance. You can use this to find out the
  2235. * port number jEdit is listening on.
  2236. * @since jEdit 4.2pre10
  2237. */
  2238. public static EditServer getEditServer()
  2239. {
  2240. return server;
  2241. } //}}}
  2242. //}}}
  2243. //{{{ Package-private members
  2244. //{{{ updatePosition() method
  2245. /**
  2246. * If buffer sorting is enabled, this repositions the buffer.
  2247. */
  2248. static void updatePosition(String oldPath, Buffer buffer)
  2249. {
  2250. if((VFSManager.getVFSForPath(oldPath).getCapabilities()
  2251. & VFS.CASE_INSENSITIVE_CAP) != 0)
  2252. {
  2253. oldPath = oldPath.toLowerCase();
  2254. }
  2255. bufferHash.remove(oldPath);
  2256. String path = buffer.getSymlinkPath();
  2257. if((VFSManager.getVFSForPath(path).getCapabilities()
  2258. & VFS.CASE_INSENSITIVE_CAP) != 0)
  2259. {
  2260. path = path.toLowerCase();
  2261. }
  2262. bufferHash.put(path,buffer);
  2263. if(sortBuffers)
  2264. {
  2265. removeBufferFromList(buffer);
  2266. addBufferToList(buffer);
  2267. }
  2268. } //}}}
  2269. //{{{ addMode() method
  2270. /**
  2271. * Do not call this method. It is only public so that classes
  2272. * in the org.gjt.sp.jedit.syntax package can access it.
  2273. * @param mode The edit mode
  2274. */
  2275. public static void addMode(Mode mode)
  2276. {
  2277. //Log.log(Log.DEBUG,jEdit.class,"Adding edit mode "
  2278. // + mode.getName());
  2279. modes.addElement(mode);
  2280. } //}}}
  2281. //{{{ loadMode() method
  2282. /**
  2283. * Loads an XML-defined edit mode from the specified reader.
  2284. * @param mode The edit mode
  2285. */
  2286. /* package-private */ static void loadMode(Mode mode)
  2287. {
  2288. final String fileName = (String)mode.getProperty("file");
  2289. Log.log(Log.NOTICE,jEdit.class,"Loading edit mode " + fileName);
  2290. final XmlParser parser = new XmlParser();
  2291. XModeHandler xmh = new XModeHandler(mode.getName())
  2292. {
  2293. public void error(String what, Object subst)
  2294. {
  2295. int line = parser.getLineNumber();
  2296. int column = parser.getColumnNumber();
  2297. String msg;
  2298. if(subst == null)
  2299. msg = jEdit.getProperty("xmode-error." + what);
  2300. else
  2301. {
  2302. msg = jEdit.getProperty("xmode-error." + what,
  2303. new String[] { subst.toString() });
  2304. if(subst instanceof Throwable)
  2305. Log.log(Log.ERROR,this,subst);
  2306. }
  2307. Object[] args = { fileName, new Integer(line),
  2308. new Integer(column), msg };
  2309. GUIUtilities.error(null,"xmode-error",args);
  2310. }
  2311. public TokenMarker getTokenMarker(String modeName)
  2312. {
  2313. Mode mode = getMode(modeName);
  2314. if(mode == null)
  2315. return null;
  2316. else
  2317. return mode.getTokenMarker();
  2318. }
  2319. };
  2320. mode.setTokenMarker(xmh.getTokenMarker());
  2321. Reader grammar = null;
  2322. parser.setHandler(xmh);
  2323. try
  2324. {
  2325. grammar = new BufferedReader(new FileReader(fileName));
  2326. parser.parse(null, null, grammar);
  2327. mode.setProperties(xmh.getModeProperties());
  2328. }
  2329. catch (Throwable e)
  2330. {
  2331. Log.log(Log.ERROR, jEdit.class, e);
  2332. if (e instanceof XmlException)
  2333. {
  2334. XmlException xe = (XmlException) e;
  2335. int line = xe.getLine();
  2336. String message = xe.getMessage();
  2337. Object[] args = { fileName, new Integer(line), null,
  2338. message };
  2339. GUIUtilities.error(null,"xmode-error",args);
  2340. }
  2341. }
  2342. finally
  2343. {
  2344. try
  2345. {
  2346. if(grammar != null)
  2347. grammar.close();
  2348. }
  2349. catch(IOException io)
  2350. {
  2351. Log.log(Log.ERROR,jEdit.class,io);
  2352. }
  2353. }
  2354. } //}}}
  2355. //{{{ addPluginProps() method
  2356. static void addPluginProps(Properties map)
  2357. {
  2358. propMgr.addPluginProps(map);
  2359. } //}}}
  2360. //{{{ removePluginProps() method
  2361. static void removePluginProps(Properties map)
  2362. {
  2363. propMgr.removePluginProps(map);
  2364. } //}}}
  2365. //{{{ pluginError() method
  2366. static void pluginError(String path, String messageProp,
  2367. Object[] args)
  2368. {
  2369. synchronized(pluginErrorLock)
  2370. {
  2371. if(pluginErrors == null)
  2372. pluginErrors = new Vector();
  2373. ErrorListDialog.ErrorEntry newEntry =
  2374. new ErrorListDialog.ErrorEntry(
  2375. path,messageProp,args);
  2376. for(int i = 0; i < pluginErrors.size(); i++)
  2377. {
  2378. if(pluginErrors.get(i).equals(newEntry))
  2379. return;
  2380. }
  2381. pluginErrors.addElement(newEntry);
  2382. if(startupDone)
  2383. {
  2384. SwingUtilities.invokeLater(new Runnable()
  2385. {
  2386. public void run()
  2387. {
  2388. showPluginErrorDialog();
  2389. }
  2390. });
  2391. }
  2392. }
  2393. } //}}}
  2394. //{{{ setActiveView() method
  2395. static void setActiveView(View view)
  2396. {
  2397. jEdit.activeView = view;
  2398. } //}}}
  2399. //}}}
  2400. //{{{ Private members
  2401. //{{{ Static variables
  2402. private static String jEditHome;
  2403. private static String settingsDirectory;
  2404. private static String jarCacheDirectory;
  2405. private static long propsModTime;
  2406. private static PropertyManager propMgr;
  2407. private static EditServer server;
  2408. private static boolean background;
  2409. private static ActionContext actionContext;
  2410. private static ActionSet builtInActionSet;
  2411. private static Vector pluginErrors;
  2412. private static Object pluginErrorLock = new Object();
  2413. private static Vector jars;
  2414. private static Vector modes;
  2415. private stat