PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre5/org/gjt/sp/jedit/jEdit.java

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