PageRenderTime 54ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

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

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