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

# · Java · 2730 lines · 1631 code · 331 blank · 768 comment · 379 complexity · 9494905bc20a8630c935d086bf7884d8 MD5 · raw file

Large files are truncated click here to view the full file

  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 4809 2003-06-24 23:24:39Z 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.03.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. mainThread = Thread.currentThread();
  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. settingsDirectory = ".jedit";
  85. // MacOS users expect the app to keep running after all windows
  86. // are closed
  87. background = OperatingSystem.isMacOS();
  88. //{{{ Parse command line
  89. boolean endOpts = false;
  90. int level = Log.WARNING;
  91. String portFile = "server";
  92. boolean restore = true;
  93. boolean newView = true;
  94. boolean newPlainView = false;
  95. boolean gui = true; // open initial view?
  96. boolean loadPlugins = true;
  97. boolean runStartupScripts = true;
  98. boolean quit = false;
  99. boolean wait = false;
  100. String userDir = System.getProperty("user.dir");
  101. // script to run
  102. String scriptFile = null;
  103. for(int i = 0; i < args.length; i++)
  104. {
  105. String arg = args[i];
  106. if(arg == null)
  107. continue;
  108. else if(arg.length() == 0)
  109. args[i] = null;
  110. else if(arg.startsWith("-") && !endOpts)
  111. {
  112. if(arg.equals("--"))
  113. endOpts = true;
  114. else if(arg.equals("-usage"))
  115. {
  116. version();
  117. System.err.println();
  118. usage();
  119. System.exit(1);
  120. }
  121. else if(arg.equals("-version"))
  122. {
  123. version();
  124. System.exit(1);
  125. }
  126. else if(arg.startsWith("-log="))
  127. {
  128. try
  129. {
  130. level = Integer.parseInt(arg.substring("-log=".length()));
  131. }
  132. catch(NumberFormatException nf)
  133. {
  134. System.err.println("Malformed option: " + arg);
  135. }
  136. }
  137. else if(arg.equals("-nosettings"))
  138. settingsDirectory = null;
  139. else if(arg.startsWith("-settings="))
  140. settingsDirectory = arg.substring(10);
  141. else if(arg.startsWith("-noserver"))
  142. portFile = null;
  143. else if(arg.equals("-server"))
  144. portFile = "server";
  145. else if(arg.startsWith("-server="))
  146. portFile = arg.substring(8);
  147. else if(arg.startsWith("-background"))
  148. background = true;
  149. else if(arg.startsWith("-nobackground"))
  150. background = false;
  151. else if(arg.equals("-gui"))
  152. gui = true;
  153. else if(arg.equals("-nogui"))
  154. gui = false;
  155. else if(arg.equals("-newview"))
  156. newView = true;
  157. else if(arg.equals("-newplainview"))
  158. newPlainView = true;
  159. else if(arg.equals("-reuseview"))
  160. newPlainView = newView = false;
  161. else if(arg.equals("-restore"))
  162. restore = true;
  163. else if(arg.equals("-norestore"))
  164. restore = false;
  165. else if(arg.equals("-plugins"))
  166. loadPlugins = true;
  167. else if(arg.equals("-noplugins"))
  168. loadPlugins = false;
  169. else if(arg.equals("-startupscripts"))
  170. runStartupScripts = true;
  171. else if(arg.equals("-nostartupscripts"))
  172. runStartupScripts = false;
  173. else if(arg.startsWith("-run="))
  174. scriptFile = arg.substring(5);
  175. else if(arg.equals("-wait"))
  176. wait = true;
  177. else if(arg.equals("-quit"))
  178. quit = true;
  179. else
  180. {
  181. System.err.println("Unknown option: "
  182. + arg);
  183. usage();
  184. System.exit(1);
  185. }
  186. args[i] = null;
  187. }
  188. } //}}}
  189. if(settingsDirectory != null)
  190. {
  191. settingsDirectory = MiscUtilities.constructPath(
  192. System.getProperty("user.home"),
  193. settingsDirectory);
  194. }
  195. if(settingsDirectory != null && portFile != null)
  196. portFile = MiscUtilities.constructPath(settingsDirectory,portFile);
  197. else
  198. portFile = null;
  199. Log.init(true,level);
  200. //{{{ Try connecting to another running jEdit instance
  201. if(portFile != null && new File(portFile).exists())
  202. {
  203. int port, key;
  204. try
  205. {
  206. BufferedReader in = new BufferedReader(new FileReader(portFile));
  207. String check = in.readLine();
  208. if(!check.equals("b"))
  209. throw new Exception("Wrong port file format");
  210. port = Integer.parseInt(in.readLine());
  211. key = Integer.parseInt(in.readLine());
  212. Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),port);
  213. DataOutputStream out = new DataOutputStream(
  214. socket.getOutputStream());
  215. out.writeInt(key);
  216. String script;
  217. if(quit)
  218. {
  219. script = "socket.close();\n"
  220. + "jEdit.exit(null,true);\n";
  221. }
  222. else
  223. {
  224. script = makeServerScript(wait,restore,
  225. newView,newPlainView,args,
  226. scriptFile);
  227. }
  228. out.writeUTF(script);
  229. Log.log(Log.DEBUG,jEdit.class,"Waiting for server");
  230. // block until its closed
  231. try
  232. {
  233. socket.getInputStream().read();
  234. }
  235. catch(Exception e)
  236. {
  237. }
  238. in.close();
  239. out.close();
  240. System.exit(0);
  241. }
  242. catch(Exception e)
  243. {
  244. // ok, this one seems to confuse newbies
  245. // endlessly, so log it as NOTICE, not
  246. // ERROR
  247. Log.log(Log.NOTICE,jEdit.class,"An error occurred"
  248. + " while connecting to the jEdit server instance.");
  249. Log.log(Log.NOTICE,jEdit.class,"This probably means that"
  250. + " jEdit crashed and/or exited abnormally");
  251. Log.log(Log.NOTICE,jEdit.class,"the last time it was run.");
  252. Log.log(Log.NOTICE,jEdit.class,"If you don't"
  253. + " know what this means, don't worry.");
  254. Log.log(Log.NOTICE,jEdit.class,e);
  255. }
  256. } //}}}
  257. if(quit)
  258. {
  259. // if no server running and user runs jedit -quit,
  260. // just exit
  261. System.exit(0);
  262. }
  263. // don't show splash screen if there is a file named
  264. // 'nosplash' in the settings directory
  265. if(!new File(settingsDirectory,"nosplash").exists())
  266. GUIUtilities.showSplashScreen();
  267. //{{{ Initialize settings directory
  268. Writer stream;
  269. if(settingsDirectory != null)
  270. {
  271. File _settingsDirectory = new File(settingsDirectory);
  272. if(!_settingsDirectory.exists())
  273. _settingsDirectory.mkdirs();
  274. File _macrosDirectory = new File(settingsDirectory,"macros");
  275. if(!_macrosDirectory.exists())
  276. _macrosDirectory.mkdir();
  277. String logPath = MiscUtilities.constructPath(
  278. settingsDirectory,"activity.log");
  279. backupSettingsFile(new File(logPath));
  280. try
  281. {
  282. stream = new BufferedWriter(new FileWriter(logPath));
  283. // Write a warning message:
  284. String lineSep = System.getProperty("line.separator");
  285. stream.write("Log file created on " + new Date());
  286. stream.write(lineSep);
  287. stream.write("IMPORTANT:");
  288. stream.write(lineSep);
  289. stream.write("Because updating this file after "
  290. + "every log message would kill");
  291. stream.write(lineSep);
  292. stream.write("performance, it will be *incomplete* "
  293. + "unless you invoke the");
  294. stream.write(lineSep);
  295. stream.write("Utilities->Troubleshooting->Update "
  296. + "Activity Log on Disk command!");
  297. stream.write(lineSep);
  298. }
  299. catch(Exception e)
  300. {
  301. e.printStackTrace();
  302. stream = null;
  303. }
  304. }
  305. else
  306. {
  307. stream = null;
  308. } //}}}
  309. Log.setLogWriter(stream);
  310. Log.log(Log.NOTICE,jEdit.class,"jEdit version " + getVersion());
  311. Log.log(Log.MESSAGE,jEdit.class,"Settings directory is "
  312. + settingsDirectory);
  313. //{{{ Initialize server
  314. if(portFile != null)
  315. {
  316. server = new EditServer(portFile);
  317. if(!server.isOK())
  318. server = null;
  319. }
  320. else
  321. {
  322. if(background)
  323. {
  324. background = false;
  325. Log.log(Log.WARNING,jEdit.class,"You cannot specify both the"
  326. + " -background and -noserver switches");
  327. }
  328. } //}}}
  329. //{{{ Get things rolling
  330. initMisc();
  331. initSystemProperties();
  332. GUIUtilities.advanceSplashProgress();
  333. BeanShell.init();
  334. initUserProperties();
  335. initPLAF();
  336. if(OperatingSystem.hasJava14())
  337. {
  338. try
  339. {
  340. ClassLoader loader = jEdit.class.getClassLoader();
  341. Class clazz;
  342. if(loader != null)
  343. clazz = loader.loadClass("org.gjt.sp.jedit.Java14");
  344. else
  345. clazz = Class.forName("org.gjt.sp.jedit.Java14");
  346. java.lang.reflect.Method meth = clazz
  347. .getMethod("init",new Class[0]);
  348. meth.invoke(null,new Object[0]);
  349. }
  350. catch(Exception e)
  351. {
  352. Log.log(Log.ERROR,jEdit.class,e);
  353. System.exit(1);
  354. }
  355. }
  356. VFSManager.init();
  357. initResources();
  358. SearchAndReplace.load();
  359. GUIUtilities.advanceSplashProgress();
  360. if(loadPlugins)
  361. initPlugins();
  362. if(jEditHome != null)
  363. initSiteProperties();
  364. if(settingsDirectory != null)
  365. {
  366. File recent = new File(MiscUtilities.constructPath(
  367. settingsDirectory,"recent.xml"));
  368. if(recent.exists())
  369. {
  370. recentModTime = recent.lastModified();
  371. BufferHistory.load(recent);
  372. }
  373. }
  374. propertiesChanged();
  375. GUIUtilities.advanceSplashProgress();
  376. // Buffer sort
  377. sortBuffers = getBooleanProperty("sortBuffers");
  378. sortByName = getBooleanProperty("sortByName");
  379. reloadModes();
  380. GUIUtilities.advanceSplashProgress();
  381. //}}}
  382. //{{{ Activate plugins that must be activated at startup
  383. for(int i = 0; i < jars.size(); i++)
  384. {
  385. ((PluginJAR)jars.elementAt(i)).activatePluginIfNecessary();
  386. }
  387. //}}}
  388. //{{{ Load macros and run startup scripts, after plugins and settings are loaded
  389. Macros.loadMacros();
  390. Macros.getMacroActionSet().initKeyBindings();
  391. if(runStartupScripts && jEditHome != null)
  392. {
  393. String path = MiscUtilities.constructPath(jEditHome,"startup");
  394. File file = new File(path);
  395. if(file.exists())
  396. runStartupScripts(file);
  397. }
  398. if(runStartupScripts && settingsDirectory != null)
  399. {
  400. String path = MiscUtilities.constructPath(settingsDirectory,"startup");
  401. File file = new File(path);
  402. if(!file.exists())
  403. file.mkdirs();
  404. else
  405. runStartupScripts(file);
  406. } //}}}
  407. //{{{ Run script specified with -run= parameter
  408. if(scriptFile != null)
  409. {
  410. scriptFile = MiscUtilities.constructPath(userDir,scriptFile);
  411. BeanShell.runScript(null,scriptFile,null,false);
  412. } //}}}
  413. GUIUtilities.advanceSplashProgress();
  414. // Open files, create the view and hide the splash screen.
  415. finishStartup(gui,restore,userDir,args);
  416. } //}}}
  417. //{{{ Property methods
  418. //{{{ getProperties() method
  419. /**
  420. * Returns the properties object which contains all known
  421. * jEdit properties.
  422. * @since jEdit 3.1pre4
  423. */
  424. public static final Properties getProperties()
  425. {
  426. return props;
  427. } //}}}
  428. //{{{ getProperty() method
  429. /**
  430. * Fetches a property, returning null if it's not defined.
  431. * @param name The property
  432. */
  433. public static final String getProperty(String name)
  434. {
  435. return props.getProperty(name);
  436. } //}}}
  437. //{{{ getProperty() method
  438. /**
  439. * Fetches a property, returning the default value if it's not
  440. * defined.
  441. * @param name The property
  442. * @param def The default value
  443. */
  444. public static final String getProperty(String name, String def)
  445. {
  446. return props.getProperty(name,def);
  447. } //}}}
  448. //{{{ getProperty() method
  449. /**
  450. * Returns the property with the specified name.<p>
  451. *
  452. * The elements of the <code>args</code> array are substituted
  453. * into the value of the property in place of strings of the
  454. * form <code>{<i>n</i>}</code>, where <code><i>n</i></code> is an index
  455. * in the array.<p>
  456. *
  457. * You can find out more about this feature by reading the
  458. * documentation for the <code>format</code> method of the
  459. * <code>java.text.MessageFormat</code> class.
  460. *
  461. * @param name The property
  462. * @param args The positional parameters
  463. */
  464. public static final String getProperty(String name, Object[] args)
  465. {
  466. if(name == null)
  467. return null;
  468. if(args == null)
  469. return props.getProperty(name);
  470. else
  471. {
  472. String value = props.getProperty(name);
  473. if(value == null)
  474. return null;
  475. else
  476. return MessageFormat.format(value,args);
  477. }
  478. } //}}}
  479. //{{{ getBooleanProperty() method
  480. /**
  481. * Returns the value of a boolean property.
  482. * @param name The property
  483. */
  484. public static final boolean getBooleanProperty(String name)
  485. {
  486. return getBooleanProperty(name,false);
  487. } //}}}
  488. //{{{ getBooleanProperty() method
  489. /**
  490. * Returns the value of a boolean property.
  491. * @param name The property
  492. * @param def The default value
  493. */
  494. public static final boolean getBooleanProperty(String name, boolean def)
  495. {
  496. String value = getProperty(name);
  497. if(value == null)
  498. return def;
  499. else if(value.equals("true") || value.equals("yes")
  500. || value.equals("on"))
  501. return true;
  502. else if(value.equals("false") || value.equals("no")
  503. || value.equals("off"))
  504. return false;
  505. else
  506. return def;
  507. } //}}}
  508. //{{{ getIntegerProperty() method
  509. /**
  510. * Returns the value of an integer property.
  511. * @param name The property
  512. * @param def The default value
  513. * @since jEdit 4.0pre1
  514. */
  515. public static final int getIntegerProperty(String name, int def)
  516. {
  517. String value = getProperty(name);
  518. if(value == null)
  519. return def;
  520. else
  521. {
  522. try
  523. {
  524. return Integer.parseInt(value.trim());
  525. }
  526. catch(NumberFormatException nf)
  527. {
  528. return def;
  529. }
  530. }
  531. } //}}}
  532. //{{{ getDoubleProperty() method
  533. public static double getDoubleProperty(String name, double def)
  534. {
  535. String value = getProperty(name);
  536. if(value == null)
  537. return def;
  538. else
  539. {
  540. try
  541. {
  542. return Double.parseDouble(value.trim());
  543. }
  544. catch(NumberFormatException nf)
  545. {
  546. return def;
  547. }
  548. }
  549. }
  550. //}}}
  551. //{{{ getFontProperty() method
  552. /**
  553. * Returns the value of a font property. The family is stored
  554. * in the <code><i>name</i></code> property, the font size is stored
  555. * in the <code><i>name</i>size</code> property, and the font style is
  556. * stored in <code><i>name</i>style</code>. For example, if
  557. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  558. * properties will be named <code>view.gutter.font</code>,
  559. * <code>view.gutter.fontsize</code>, and
  560. * <code>view.gutter.fontstyle</code>.
  561. *
  562. * @param name The property
  563. * @since jEdit 4.0pre1
  564. */
  565. public static final Font getFontProperty(String name)
  566. {
  567. return getFontProperty(name,null);
  568. } //}}}
  569. //{{{ getFontProperty() method
  570. /**
  571. * Returns the value of a font property. The family is stored
  572. * in the <code><i>name</i></code> property, the font size is stored
  573. * in the <code><i>name</i>size</code> property, and the font style is
  574. * stored in <code><i>name</i>style</code>. For example, if
  575. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  576. * properties will be named <code>view.gutter.font</code>,
  577. * <code>view.gutter.fontsize</code>, and
  578. * <code>view.gutter.fontstyle</code>.
  579. *
  580. * @param name The property
  581. * @param def The default value
  582. * @since jEdit 4.0pre1
  583. */
  584. public static final Font getFontProperty(String name, Font def)
  585. {
  586. String family = getProperty(name);
  587. String sizeString = getProperty(name + "size");
  588. String styleString = getProperty(name + "style");
  589. if(family == null || sizeString == null || styleString == null)
  590. return def;
  591. else
  592. {
  593. int size, style;
  594. try
  595. {
  596. size = Integer.parseInt(sizeString);
  597. }
  598. catch(NumberFormatException nf)
  599. {
  600. return def;
  601. }
  602. try
  603. {
  604. style = Integer.parseInt(styleString);
  605. }
  606. catch(NumberFormatException nf)
  607. {
  608. return def;
  609. }
  610. return new Font(family,style,size);
  611. }
  612. } //}}}
  613. //{{{ getColorProperty() method
  614. /**
  615. * Returns the value of a color property.
  616. * @param name The property name
  617. * @since jEdit 4.0pre1
  618. */
  619. public static Color getColorProperty(String name)
  620. {
  621. return getColorProperty(name,Color.black);
  622. } //}}}
  623. //{{{ getColorProperty() method
  624. /**
  625. * Returns the value of a color property.
  626. * @param name The property name
  627. * @param def The default value
  628. * @since jEdit 4.0pre1
  629. */
  630. public static Color getColorProperty(String name, Color def)
  631. {
  632. String value = getProperty(name);
  633. if(value == null)
  634. return def;
  635. else
  636. return GUIUtilities.parseColor(value,def);
  637. } //}}}
  638. //{{{ setColorProperty() method
  639. /**
  640. * Sets the value of a color property.
  641. * @param name The property name
  642. * @param value The value
  643. * @since jEdit 4.0pre1
  644. */
  645. public static void setColorProperty(String name, Color value)
  646. {
  647. setProperty(name,GUIUtilities.getColorHexString(value));
  648. } //}}}
  649. //{{{ setProperty() method
  650. /**
  651. * Sets a property to a new value.
  652. * @param name The property
  653. * @param value The new value
  654. */
  655. public static final void setProperty(String name, String value)
  656. {
  657. /* if value is null:
  658. * - if default is null, unset user prop
  659. * - else set user prop to ""
  660. * else
  661. * - if default equals value, ignore
  662. * - if default doesn't equal value, set user
  663. */
  664. if(value == null)
  665. {
  666. String prop = (String)defaultProps.get(name);
  667. if(prop == null || prop.length() == 0)
  668. props.remove(name);
  669. else
  670. props.put(name,"");
  671. }
  672. else
  673. {
  674. String prop = (String)defaultProps.get(name);
  675. if(value.equals(prop))
  676. props.remove(name);
  677. else
  678. props.put(name,value);
  679. }
  680. } //}}}
  681. //{{{ setTemporaryProperty() method
  682. /**
  683. * Sets a property to a new value. Properties set using this
  684. * method are not saved to the user properties list.
  685. * @param name The property
  686. * @param value The new value
  687. * @since jEdit 2.3final
  688. */
  689. public static final void setTemporaryProperty(String name, String value)
  690. {
  691. props.remove(name);
  692. defaultProps.put(name,value);
  693. } //}}}
  694. //{{{ setBooleanProperty() method
  695. /**
  696. * Sets a boolean property.
  697. * @param name The property
  698. * @param value The value
  699. */
  700. public static final void setBooleanProperty(String name, boolean value)
  701. {
  702. setProperty(name,value ? "true" : "false");
  703. } //}}}
  704. //{{{ setIntegerProperty() method
  705. /**
  706. * Sets the value of an integer property.
  707. * @param name The property
  708. * @param value The value
  709. * @since jEdit 4.0pre1
  710. */
  711. public static final void setIntegerProperty(String name, int value)
  712. {
  713. setProperty(name,String.valueOf(value));
  714. } //}}}
  715. //{{{ setDoubleProperty() method
  716. public static final void setDoubleProperty(String name, double value)
  717. {
  718. setProperty(name,String.valueOf(value));
  719. }
  720. //}}}
  721. //{{{ setFontProperty() method
  722. /**
  723. * Sets the value of a font property. The family is stored
  724. * in the <code><i>name</i></code> property, the font size is stored
  725. * in the <code><i>name</i>size</code> property, and the font style is
  726. * stored in <code><i>name</i>style</code>. For example, if
  727. * <code><i>name</i></code> is <code>view.gutter.font</code>, the
  728. * properties will be named <code>view.gutter.font</code>,
  729. * <code>view.gutter.fontsize</code>, and
  730. * <code>view.gutter.fontstyle</code>.
  731. *
  732. * @param name The property
  733. * @param value The value
  734. * @since jEdit 4.0pre1
  735. */
  736. public static final void setFontProperty(String name, Font value)
  737. {
  738. setProperty(name,value.getFamily());
  739. setIntegerProperty(name + "size",value.getSize());
  740. setIntegerProperty(name + "style",value.getStyle());
  741. } //}}}
  742. //{{{ unsetProperty() method
  743. /**
  744. * Unsets (clears) a property.
  745. * @param name The property
  746. */
  747. public static final void unsetProperty(String name)
  748. {
  749. if(defaultProps.get(name) != null)
  750. props.put(name,"");
  751. else
  752. props.remove(name);
  753. } //}}}
  754. //{{{ resetProperty() method
  755. /**
  756. * Resets a property to its default value.
  757. * @param name The property
  758. *
  759. * @since jEdit 2.5pre3
  760. */
  761. public static final void resetProperty(String name)
  762. {
  763. props.remove(name);
  764. } //}}}
  765. //{{{ propertiesChanged() method
  766. /**
  767. * Reloads various settings from the properties.
  768. */
  769. public static void propertiesChanged()
  770. {
  771. initKeyBindings();
  772. Autosave.setInterval(getIntegerProperty("autosave",30));
  773. saveCaret = getBooleanProperty("saveCaret");
  774. //theme = new JEditMetalTheme();
  775. //theme.propertiesChanged();
  776. //MetalLookAndFeel.setCurrentTheme(theme);
  777. UIDefaults defaults = UIManager.getDefaults();
  778. // give all text areas the same font
  779. Font font = getFontProperty("view.font");
  780. //defaults.put("TextField.font",font);
  781. defaults.put("TextArea.font",font);
  782. defaults.put("TextPane.font",font);
  783. // Enable/Disable tooltips
  784. ToolTipManager.sharedInstance().setEnabled(
  785. jEdit.getBooleanProperty("showTooltips"));
  786. initProxy();
  787. // we do this here instead of adding buffers to the bus.
  788. Buffer buffer = buffersFirst;
  789. while(buffer != null)
  790. {
  791. buffer.resetCachedProperties();
  792. buffer.propertiesChanged();
  793. buffer = buffer.next;
  794. }
  795. HistoryModel.propertiesChanged();
  796. KillRing.propertiesChanged();
  797. EditBus.send(new PropertiesChanged(null));
  798. } //}}}
  799. //}}}
  800. //{{{ Plugin management methods
  801. //{{{ getNotLoadedPluginJARs() method
  802. /**
  803. * Returns a list of plugin JARs that are not currently loaded
  804. * by examining the user and system plugin directories.
  805. * @since jEdit 3.2pre1
  806. */
  807. public static String[] getNotLoadedPluginJARs()
  808. {
  809. Vector returnValue = new Vector();
  810. if(jEditHome != null)
  811. {
  812. String systemPluginDir = MiscUtilities
  813. .constructPath(jEditHome,"jars");
  814. String[] list = new File(systemPluginDir).list();
  815. if(list != null)
  816. getNotLoadedPluginJARs(returnValue,systemPluginDir,list);
  817. }
  818. if(settingsDirectory != null)
  819. {
  820. String userPluginDir = MiscUtilities
  821. .constructPath(settingsDirectory,"jars");
  822. String[] list = new File(userPluginDir).list();
  823. if(list != null)
  824. {
  825. getNotLoadedPluginJARs(returnValue,
  826. userPluginDir,list);
  827. }
  828. }
  829. String[] _returnValue = new String[returnValue.size()];
  830. returnValue.copyInto(_returnValue);
  831. return _returnValue;
  832. } //}}}
  833. //{{{ getPlugin() method
  834. /**
  835. * Returns the plugin with the specified class name.
  836. */
  837. public static EditPlugin getPlugin(String name)
  838. {
  839. EditPlugin[] plugins = getPlugins();
  840. for(int i = 0; i < plugins.length; i++)
  841. {
  842. if(plugins[i].getClassName().equals(name))
  843. return plugins[i];
  844. }
  845. return null;
  846. } //}}}
  847. //{{{ getPlugins() method
  848. /**
  849. * Returns an array of installed plugins.
  850. */
  851. public static EditPlugin[] getPlugins()
  852. {
  853. Vector vector = new Vector();
  854. for(int i = 0; i < jars.size(); i++)
  855. {
  856. EditPlugin plugin = ((PluginJAR)jars.elementAt(i))
  857. .getPlugin();
  858. if(plugin != null)
  859. vector.add(plugin);
  860. }
  861. EditPlugin[] array = new EditPlugin[vector.size()];
  862. vector.copyInto(array);
  863. return array;
  864. } //}}}
  865. //{{{ getPluginJARs() method
  866. /**
  867. * Returns an array of installed plugins.
  868. * @since jEdit 4.2pre1
  869. */
  870. public static PluginJAR[] getPluginJARs()
  871. {
  872. PluginJAR[] array = new PluginJAR[jars.size()];
  873. jars.copyInto(array);
  874. return array;
  875. } //}}}
  876. //{{{ getPluginJAR() method
  877. /**
  878. * Returns the JAR with the specified path name.
  879. * @param path The path name
  880. * @since jEdit 4.2pre1
  881. */
  882. public static PluginJAR getPluginJAR(String path)
  883. {
  884. for(int i = 0; i < jars.size(); i++)
  885. {
  886. PluginJAR jar = (PluginJAR)jars.elementAt(i);
  887. if(jar.getPath().equals(path))
  888. return jar;
  889. }
  890. return null;
  891. } //}}}
  892. //{{{ addPluginJAR() method
  893. /**
  894. * Loads the plugin JAR with the specified path. Some notes about this
  895. * method:
  896. *
  897. * <ul>
  898. * <li>Calling this at a time other than jEdit startup can have
  899. * unpredictable results if the plugin has not been updated for the
  900. * jEdit 4.2 plugin API.
  901. * <li>You must make sure yourself the plugin is not already loaded.
  902. * <li>After loading, you just make sure all the plugin's dependencies
  903. * are satisified before activating the plugin, using the
  904. * {@link PluginJAR#checkDependencies()} method.
  905. * </ul>
  906. *
  907. * @param path The JAR file path
  908. * @since jEdit 4.2pre1
  909. */
  910. public static void addPluginJAR(String path)
  911. {
  912. // backwards compatibility...
  913. PluginJAR jar = new EditPlugin.JAR(new File(path));
  914. jars.addElement(jar);
  915. jar.init();
  916. EditBus.send(new PluginUpdate(jar,PluginUpdate.LOADED,false));
  917. if(!isMainThread())
  918. EditBus.send(new DynamicMenuChanged("plugins"));
  919. } //}}}
  920. //{{{ addPluginJARsFromDirectory() method
  921. /**
  922. * Loads all plugins in a directory.
  923. * @param directory The directory
  924. * @since jEdit 4.2pre1
  925. */
  926. private static void addPluginJARsFromDirectory(String directory)
  927. {
  928. Log.log(Log.NOTICE,jEdit.class,"Loading plugins from "
  929. + directory);
  930. File file = new File(directory);
  931. if(!(file.exists() && file.isDirectory()))
  932. return;
  933. String[] plugins = file.list();
  934. if(plugins == null)
  935. return;
  936. for(int i = 0; i < plugins.length; i++)
  937. {
  938. String plugin = plugins[i];
  939. if(!plugin.toLowerCase().endsWith(".jar"))
  940. continue;
  941. String path = MiscUtilities.constructPath(directory,plugin);
  942. if(plugin.equals("EditBuddy.jar")
  943. || plugin.equals("PluginManager.jar")
  944. || plugin.equals("Firewall.jar")
  945. || plugin.equals("Tidy.jar"))
  946. {
  947. pluginError(path,"plugin-error.obsolete",null);
  948. continue;
  949. }
  950. addPluginJAR(path);
  951. }
  952. } //}}}
  953. //{{{ removePluginJAR() method
  954. /**
  955. * Unloads the given plugin JAR with the specified path. Note that
  956. * calling this at a time other than jEdit shutdown can have
  957. * unpredictable results if the plugin has not been updated for the
  958. * jEdit 4.2 plugin API.
  959. *
  960. * @param jar The <code>PluginJAR</code> instance
  961. * @param exit Set to true if jEdit is exiting; enables some
  962. * shortcuts so the editor can close faster.
  963. * @since jEdit 4.2pre1
  964. */
  965. public static void removePluginJAR(PluginJAR jar, boolean exit)
  966. {
  967. if(exit)
  968. {
  969. jar.uninit(true);
  970. }
  971. else
  972. {
  973. jar.uninit(false);
  974. jars.removeElement(jar);
  975. }
  976. EditBus.send(new PluginUpdate(jar,PluginUpdate.UNLOADED,exit));
  977. if(!isMainThread() && !exit)
  978. EditBus.send(new DynamicMenuChanged("plugins"));
  979. } //}}}
  980. //}}}
  981. //{{{ Action methods
  982. //{{{ getActionContext() method
  983. /**
  984. * Returns the action context used to store editor actions.
  985. * @since jEdit 4.2pre1
  986. */
  987. public static ActionContext getActionContext()
  988. {
  989. return actionContext;
  990. } //}}}
  991. //{{{ addActionSet() method
  992. /**
  993. * Adds a new action set to jEdit's list. Plugins probably won't
  994. * need to call this method.
  995. * @since jEdit 4.0pre1
  996. */
  997. public static void addActionSet(ActionSet actionSet)
  998. {
  999. actionContext.addActionSet(actionSet);
  1000. } //}}}
  1001. //{{{ removeActionSet() method
  1002. /**
  1003. * Removes an action set from jEdit's list. Plugins probably won't
  1004. * need to call this method.
  1005. * @since jEdit 4.2pre1
  1006. */
  1007. public static void removeActionSet(ActionSet actionSet)
  1008. {
  1009. actionContext.removeActionSet(actionSet);
  1010. } //}}}
  1011. //{{{ getBuiltInActionSet() method
  1012. /**
  1013. * Returns the set of commands built into jEdit.
  1014. * @since jEdit 4.2pre1
  1015. */
  1016. public static ActionSet getBuiltInActionSet()
  1017. {
  1018. return builtInActionSet;
  1019. } //}}}
  1020. //{{{ getActionSets() method
  1021. /**
  1022. * Returns all registered action sets.
  1023. * @since jEdit 4.0pre1
  1024. */
  1025. public static ActionSet[] getActionSets()
  1026. {
  1027. return actionContext.getActionSets();
  1028. } //}}}
  1029. //{{{ getAction() method
  1030. /**
  1031. * Returns the specified action.
  1032. * @param name The action name
  1033. */
  1034. public static EditAction getAction(String name)
  1035. {
  1036. return actionContext.getAction(name);
  1037. } //}}}
  1038. //{{{ getActionSetForAction() method
  1039. /**
  1040. * Returns the action set that contains the specified action.
  1041. *
  1042. * @param action The action
  1043. * @since jEdit 4.2pre1
  1044. */
  1045. public static ActionSet getActionSetForAction(String action)
  1046. {
  1047. return actionContext.getActionSetForAction(action);
  1048. } //}}}
  1049. //{{{ getActionSetForAction() method
  1050. /**
  1051. * @deprecated Use the form that takes a String instead
  1052. */
  1053. public static ActionSet getActionSetForAction(EditAction action)
  1054. {
  1055. return actionContext.getActionSetForAction(action.getName());
  1056. } //}}}
  1057. //{{{ getActions() method
  1058. /**
  1059. * @deprecated Call getActionNames() instead
  1060. */
  1061. public static EditAction[] getActions()
  1062. {
  1063. String[] names = actionContext.getActionNames();
  1064. EditAction[] actions = new EditAction[names.length];
  1065. for(int i = 0; i < actions.length; i++)
  1066. {
  1067. actions[i] = actionContext.getAction(names[i]);
  1068. if(actions[i] == null)
  1069. Log.log(Log.ERROR,jEdit.class,"wtf: " + names[i]);
  1070. }
  1071. return actions;
  1072. } //}}}
  1073. //{{{ getActionNames() method
  1074. /**
  1075. * Returns all registered action names.
  1076. */
  1077. public static String[] getActionNames()
  1078. {
  1079. return actionContext.getActionNames();
  1080. } //}}}
  1081. //}}}
  1082. //{{{ Edit mode methods
  1083. //{{{ reloadModes() method
  1084. /**
  1085. * Reloads all edit modes.
  1086. * @since jEdit 3.2pre2
  1087. */
  1088. public static void reloadModes()
  1089. {
  1090. /* Try to guess the eventual size to avoid unnecessary
  1091. * copying */
  1092. modes = new Vector(50);
  1093. //{{{ Load the global catalog
  1094. if(jEditHome == null)
  1095. loadModeCatalog("/modes/catalog",true);
  1096. else
  1097. {
  1098. loadModeCatalog(MiscUtilities.constructPath(jEditHome,
  1099. "modes","catalog"),false);
  1100. } //}}}
  1101. //{{{ Load user catalog
  1102. if(settingsDirectory != null)
  1103. {
  1104. File userModeDir = new File(MiscUtilities.constructPath(
  1105. settingsDirectory,"modes"));
  1106. if(!userModeDir.exists())
  1107. userModeDir.mkdirs();
  1108. File userCatalog = new File(MiscUtilities.constructPath(
  1109. settingsDirectory,"modes","catalog"));
  1110. if(!userCatalog.exists())
  1111. {
  1112. // create dummy catalog
  1113. try
  1114. {
  1115. FileWriter out = new FileWriter(userCatalog);
  1116. out.write(jEdit.getProperty("defaultCatalog"));
  1117. out.close();
  1118. }
  1119. catch(IOException io)
  1120. {
  1121. Log.log(Log.ERROR,jEdit.class,io);
  1122. }
  1123. }
  1124. loadModeCatalog(userCatalog.getPath(),false);
  1125. } //}}}
  1126. Buffer buffer = buffersFirst;
  1127. while(buffer != null)
  1128. {
  1129. // This reloads the token marker and sends a message
  1130. // which causes edit panes to repaint their text areas
  1131. buffer.setMode();
  1132. buffer = buffer.next;
  1133. }
  1134. } //}}}
  1135. //{{{ getMode() method
  1136. /**
  1137. * Returns the edit mode with the specified name.
  1138. * @param name The edit mode
  1139. */
  1140. public static Mode getMode(String name)
  1141. {
  1142. for(int i = 0; i < modes.size(); i++)
  1143. {
  1144. Mode mode = (Mode)modes.elementAt(i);
  1145. if(mode.getName().equals(name))
  1146. return mode;
  1147. }
  1148. return null;
  1149. } //}}}
  1150. //{{{ getModes() method
  1151. /**
  1152. * Returns an array of installed edit modes.
  1153. */
  1154. public static Mode[] getModes()
  1155. {
  1156. Mode[] array = new Mode[modes.size()];
  1157. modes.copyInto(array);
  1158. return array;
  1159. } //}}}
  1160. //}}}
  1161. //{{{ Buffer creation methods
  1162. //{{{ openFiles() method
  1163. /**
  1164. * Opens the file names specified in the argument array. This
  1165. * handles +line and +marker arguments just like the command
  1166. * line parser.
  1167. * @param parent The parent directory
  1168. * @param args The file names to open
  1169. * @since jEdit 3.2pre4
  1170. */
  1171. public static Buffer openFiles(View view, String parent, String[] args)
  1172. {
  1173. Buffer retVal = null;
  1174. Buffer lastBuffer = null;
  1175. for(int i = 0; i < args.length; i++)
  1176. {
  1177. String arg = args[i];
  1178. if(arg == null)
  1179. continue;
  1180. else if(arg.startsWith("+line:") || arg.startsWith("+marker:"))
  1181. {
  1182. if(lastBuffer != null)
  1183. gotoMarker(view,lastBuffer,arg);
  1184. continue;
  1185. }
  1186. lastBuffer = openFile(null,parent,arg,false,null);
  1187. if(retVal == null && lastBuffer != null)
  1188. retVal = lastBuffer;
  1189. }
  1190. if(view != null && retVal != null)
  1191. view.setBuffer(retVal);
  1192. return retVal;
  1193. } //}}}
  1194. //{{{ openFile() method
  1195. /**
  1196. * Opens a file. Note that as of jEdit 2.5pre1, this may return
  1197. * null if the buffer could not be opened.
  1198. * @param view The view to open the file in
  1199. * @param path The file path
  1200. *
  1201. * @since jEdit 2.4pre1
  1202. */
  1203. public static Buffer openFile(View view, String path)
  1204. {
  1205. return openFile(view,null,path,false,new Hashtable());
  1206. } //}}}
  1207. //{{{ openFile() method
  1208. /**
  1209. * @deprecated The openFile() forms with the readOnly parameter
  1210. * should not be used. The readOnly prameter is no longer supported.
  1211. */
  1212. public static Buffer openFile(View view, String parent,
  1213. String path, boolean readOnly, boolean newFile)
  1214. {
  1215. return openFile(view,parent,path,newFile,new Hashtable());
  1216. } //}}}
  1217. //{{{ openFile() method
  1218. /**
  1219. * @deprecated The openFile() forms with the readOnly parameter
  1220. * should not be used. The readOnly prameter is no longer supported.
  1221. */
  1222. public static Buffer openFile(View view, String parent,
  1223. String path, boolean readOnly, boolean newFile,
  1224. Hashtable props)
  1225. {
  1226. return openFile(view,parent,path,newFile,props);
  1227. } //}}}
  1228. //{{{ openFile() method
  1229. /**
  1230. * Opens a file. This may return null if the buffer could not be
  1231. * opened for some reason.
  1232. * @param view The view to open the file in
  1233. * @param parent The parent directory of the file
  1234. * @param path The path name of the file
  1235. * @param newFile True if the file should not be loaded from disk
  1236. * be prompted if it should be reloaded
  1237. * @param props Buffer-local properties to set in the buffer
  1238. *
  1239. * @since jEdit 3.2pre10
  1240. */
  1241. public static Buffer openFile(View view, String parent,
  1242. String path, boolean newFile, Hashtable props)
  1243. {
  1244. if(view != null && parent == null)
  1245. parent = view.getBuffer().getDirectory();
  1246. if(MiscUtilities.isURL(path))
  1247. {
  1248. if(MiscUtilities.getProtocolOfURL(path).equals("file"))
  1249. path = path.substring(5);
  1250. }
  1251. path = MiscUtilities.constructPath(parent,path);
  1252. synchronized(bufferListLock)
  1253. {
  1254. Buffer buffer = getBuffer(path);
  1255. if(buffer != null)
  1256. {
  1257. if(view != null)
  1258. view.setBuffer(buffer);
  1259. return buffer;
  1260. }
  1261. if(props == null)
  1262. props = new Hashtable();
  1263. BufferHistory.Entry entry = BufferHistory.getEntry(path);
  1264. if(entry != null && saveCaret && props.get(Buffer.CARET) == null)
  1265. {
  1266. props.put(Buffer.CARET,new Integer(entry.caret));
  1267. /* if(entry.selection != null)
  1268. {
  1269. // getSelection() converts from string to
  1270. // Selection[]
  1271. props.put(Buffer.SELECTION,entry.getSelection());
  1272. } */
  1273. }
  1274. if(entry != null && props.get(Buffer.ENCODING) == null)
  1275. {
  1276. if(entry.encoding != null)
  1277. props.put(Buffer.ENCODING,entry.encoding);
  1278. }
  1279. Buffer newBuffer = new Buffer(path,newFile,false,props);
  1280. if(!newBuffer.load(view,false))
  1281. return null;
  1282. addBufferToList(newBuffer);
  1283. EditBus.send(new BufferUpdate(newBuffer,view,BufferUpdate.CREATED));
  1284. if(view != null)
  1285. view.setBuffer(newBuffer);
  1286. return newBuffer;
  1287. }
  1288. } //}}}
  1289. //{{{ openTemporary() method
  1290. /**
  1291. * Opens a temporary buffer. A temporary buffer is like a normal
  1292. * buffer, except that an event is not fired, the the buffer is
  1293. * not added to the buffers list.
  1294. *
  1295. * @param view The view to open the file in
  1296. * @param parent The parent directory of the file
  1297. * @param path The path name of the file
  1298. * @param newFile True if the file should not be loaded from disk
  1299. *
  1300. * @since jEdit 3.2pre10
  1301. */
  1302. public static Buffer openTemporary(View view, String parent,
  1303. String path, boolean newFile)
  1304. {
  1305. if(view != null && parent == null)
  1306. parent = view.getBuffer().getDirectory();
  1307. if(MiscUtilities.isURL(path))
  1308. {
  1309. if(MiscUtilities.getProtocolOfURL(path).equals("file"))
  1310. path = path.substring(5);
  1311. }
  1312. path = MiscUtilities.constructPath(parent,path);
  1313. synchronized(bufferListLock)
  1314. {
  1315. Buffer buffer = getBuffer(path);
  1316. if(buffer != null)
  1317. return buffer;
  1318. buffer = new Buffer(path,newFile,true,new Hashtable());
  1319. if(!buffer.load(view,false))
  1320. return null;
  1321. else
  1322. return buffer;
  1323. }
  1324. } //}}}
  1325. //{{{ commitTemporary() method
  1326. /**
  1327. * Adds a temporary buffer to the buffer list. This must be done
  1328. * before allowing the user to interact with the buffer in any
  1329. * way.
  1330. * @param buffer The buffer
  1331. */
  1332. public static void commitTemporary(Buffer buffer)
  1333. {
  1334. if(!buffer.isTemporary())
  1335. return;
  1336. addBufferToList(buffer);
  1337. buffer.commitTemporary();
  1338. // send full range of events to avoid breaking plugins
  1339. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.CREATED));
  1340. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOAD_STARTED));
  1341. EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOADED));
  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. String path;
  1351. if(view != null && view.getBuffer() != null)
  1352. {
  1353. path = view.getBuffer().getDirectory();
  1354. VFS vfs = VFSManager.getVFSForPath(path);
  1355. // don't want 'New File' to create a read only buffer
  1356. // if current file is on SQL VFS or something
  1357. if((vfs.getCapabilities() & VFS.WRITE_CAP) == 0)
  1358. path = System.getProperty("user.home");
  1359. }
  1360. else
  1361. path = null;
  1362. return newFile(view,path);
  1363. } //}}}
  1364. //{{{ newFile() method
  1365. /**
  1366. * Creates a new `untitled' file.
  1367. * @param view The view to create the file in
  1368. * @param dir The directory to create the file in
  1369. * @since jEdit 3.1pre2
  1370. */
  1371. public static Buffer newFile(View view, String dir)
  1372. {
  1373. // If only one new file is open which is clean, just close
  1374. // it, which will create an 'Untitled-1'
  1375. if(dir != null
  1376. && buffersFirst != null
  1377. && buffersFirst == buffersLast
  1378. && buffersFirst.isUntitled()
  1379. && !buffersFirst.isDirty())
  1380. {
  1381. closeBuffer(view,buffersFirst);
  1382. // return the newly created 'untitled-1'
  1383. return buffersFirst;
  1384. }
  1385. // Find the highest Untitled-n file
  1386. int untitledCount = 0;
  1387. Buffer buffer = buffersFirst;
  1388. while(buffer != null)
  1389. {
  1390. if(buffer.getName().startsWith("Untitled-"))
  1391. {
  1392. try
  1393. {
  1394. untitledCount = Math.max(untitledCount,
  1395. Integer.parseInt(buffer.getName()
  1396. .substring(9)));
  1397. }
  1398. catch(NumberFormatException nf)
  1399. {
  1400. }
  1401. }
  1402. buffer = buffer.next;
  1403. }
  1404. return openFile(view,dir,"Untitled-" + (untitledCount+1),true,null);
  1405. } //}}}
  1406. //}}}
  1407. //{{{ Buffer management methods
  1408. //{{{ closeBuffer() method
  1409. /**
  1410. * Closes a buffer. If there are unsaved changes, the user is
  1411. * prompted if they should be saved first.
  1412. * @param view The view
  1413. * @param buffer The buffer
  1414. * @return True if the buffer was really closed, false otherwise
  1415. */
  1416. public static boolean closeBuffer(View view, Buffer buffer)
  1417. {
  1418. // Wait for pending I/O requests
  1419. if(buffer.isPerformingIO())
  1420. {
  1421. VFSManager.waitForRequests();
  1422. if(VFSManager.errorOccurred())
  1423. return false;
  1424. }
  1425. if(buffer.isDirty())
  1426. {
  1427. Object[] args = { buffer.getName() };
  1428. int result = GUIUtilities.confirm(view,"notsaved",args,
  1429. JOptionPane.YES_NO_CANCEL_OPTION,
  1430. JOptionPane.WARNING_MESSAGE);
  1431. if(result == JOptionPane.YES_OPTION)
  1432. {
  1433. if(!buffer.save(view,null,true))
  1434. return false;
  1435. VFSManager.waitForRequests();
  1436. if(buffer.getBooleanProperty(BufferIORequest
  1437. .ERROR_OCCURRED))
  1438. {
  1439. return false;
  1440. }
  1441. }
  1442. else if(result != JOptionPane.NO_OPTION)
  1443. return false;
  1444. }
  1445. _closeBuffer(view,buffer);
  1446. return true;
  1447. } //}}}
  1448. //{{{ _closeBuffer() method
  1449. /**
  1450. * Closes the buffer, even if it has unsaved changes.
  1451. * @param view The view
  1452. * @param buffer The buffer
  1453. *
  1454. * @since jEdit 2.2pre1
  1455. */
  1456. public static void _closeBuffer(View view, Buffer buffer)
  1457. {
  1458. if(buffer.isClosed())
  1459. {
  1460. // can happen if the user presses C+w twice real
  1461. // quick and the buffer has unsaved changes
  1462. return;
  1463. }
  1464. if(!buffer.isNewFile())
  1465. {
  1466. view.getEditPane().saveCaretInfo();
  1467. Integer _caret = (Integer)buffer.getProperty(Buffer.CARET);
  1468. int caret = (_caret == null ? 0 : _caret.intValue());
  1469. BufferHistory.setEntry(buffer.getPath(),caret,
  1470. (Selection[])buffer.getProperty(Buffer.SELECTION),
  1471. buffer.getStringProperty(Buffer.ENCODING));
  1472. }
  1473. String path = buffer.getSymlinkPath();
  1474. if((VFSManager.getVFSForPath(path).getCapabilities()
  1475. & VFS.CASE_INSENSITIVE_CAP) != 0)
  1476. {
  1477. path = path.toLowerCase();
  1478. }
  1479. bufferHash.remove(path);
  1480. removeBufferFromList(buffer);
  1481. buffer.close();
  1482. DisplayManager.bufferClosed(buffer);
  1483. EditBus.send(new BufferUpdate(buffer,view,BufferUpdate.CLOSED));
  1484. // Create a new file when the last is closed
  1485. if(buffersFirst == null && buffersLast == null)
  1486. newFile(view);
  1487. } //}}}
  1488. //{{{ closeAllBuffers() method
  1489. /**
  1490. * Closes all open buffers.
  1491. * @param view The view
  1492. */
  1493. public static boolean closeAllBuffers(View view)
  1494. {
  1495. return closeAllBuffers(view,false);
  1496. } //}}}
  1497. //{{{ closeAllBuffers() method
  1498. /**
  1499. * Closes all open buffers.
  1500. * @param view The view
  1501. * @param isExiting This must be false unless this method is
  1502. * being called by the exit() method
  1503. */
  1504. public static boolean closeAllBuffers(View view, boolean isExiting)
  1505. {
  1506. boolean dirty = false;
  1507. Buffer buffer = buffersFirst;
  1508. while(buffer != null)
  1509. {
  1510. if(buffer.isDirty())
  1511. {
  1512. dirty = true;
  1513. break;
  1514. }
  1515. buffer = buffer.next;
  1516. }
  1517. if(dirty)
  1518. {
  1519. boolean ok = new CloseDialog(view).isOK();
  1520. if(!ok)
  1521. return false;
  1522. }
  1523. // Wait for pending I/O requests
  1524. VFSManager.waitForRequests();
  1525. if(VFSManager.errorOccurred())
  1526. return false;
  1527. // close remaining buffers (the close dialog only deals with
  1528. // dirty ones)
  1529. buffer = buffersFirst;
  1530. // zero it here so that BufferTabs doesn't have any problems
  1531. buffersFirst = buffersLast = null;
  1532. bufferHash.clear();
  1533. bufferCount = 0;
  1534. while(buffer != null)
  1535. {
  1536. if(!buffer.isNewFile())
  1537. {
  1538. Integer _caret = (Integer)buffer.getProperty(Buffer.CARET);
  1539. int caret = (_caret == null ? 0 : _caret.intValue());
  1540. BufferHistory.setEntry(buffer.getPath(),caret,
  1541. (Selection[])buffer.getProperty(Buffer.SELECTION),
  1542. buffer.getStringProperty(Buffer.ENCODING));
  1543. }
  1544. buffer.close();
  1545. DisplayManager.bufferClosed(buffer);
  1546. if(!isExiting)
  1547. {
  1548. EditBus.send(new BufferUpdate(buffer,view,
  1549. BufferUpdate.CLOSED));
  1550. }
  1551. buffer = buffer.next;
  1552. }
  1553. if(!isExiting)
  1554. newFile(view);
  1555. return true;
  1556. } //}}}
  1557. //{{{ saveAllBuffers() method
  1558. /**
  1559. * Saves all open buffers.
  1560. * @param view The view
  1561. * @since jEdit 4.2pre1
  1562. */
  1563. public static void saveAllBuffers(View view)
  1564. {
  1565. saveAllBuffers(view,jEdit.getBooleanProperty("confirm.save-all"));
  1566. } //}}}
  1567. //{{{ saveAllBuffers() method
  1568. /**
  1569. * Saves all open buffers.
  1570. * @param view The view
  1571. * @param confirm If true, a confirmation dialog will be shown first
  1572. * @since jEdit 2.7pre2
  1573. */
  1574. public static void saveAllBuffers(View view, boolean confirm)
  1575. {
  1576. if(confirm)
  1577. {
  1578. int result = GUIUtilities.confirm(view,"saveall",null,
  1579. JOptionPane.YES_NO_OPTION,
  1580. JOptionPane.QUESTION_MESSAGE);
  1581. if(result != JOptionPane.YES_OPTION)
  1582. return;
  1583. }
  1584. Buffer current = view.getBuffer();
  1585. Buffer buffer = buffersFirst;
  1586. while(buffer != null)
  1587. {
  1588. if(buffer.isDirty())
  1589. {
  1590. if(buffer.isNewFile())
  1591. view.setBuffer(buffer);
  1592. buffer.save(view,null,true);
  1593. }
  1594. buffer = buffer.next;
  1595. }
  1596. view.setBuffer(current);
  1597. } //}}}
  1598. //{{{ reloadAllBuffers() method
  1599. /**
  1600. * Reloads all open buffers.
  1601. * @param view The view
  1602. * @param confirm If true, a confirmation dialog will be shown first
  1603. * @since jEdit 2.7pre2
  1604. */
  1605. public static void reloadAllBuffers(final View view, boolean confirm)
  1606. {
  1607. if(confirm)
  1608. {
  1609. int result = GUIUtilities.confirm(view,"reload-all",null,
  1610. JOptionPane.YES_NO_OPTION,
  1611. JOptionPane.QUESTION_MESSAGE);
  1612. if(result != JOptionPane.YES_OPTION)
  1613. return;
  1614. }
  1615. // save caret info. Buffer.load() will load it.
  1616. View _view = viewsFirst;
  1617. while(_view != null)
  1618. {
  1619. EditPane[] panes = _view.getEditPanes();
  1620. for(int i = 0; i < panes.length; i++)
  1621. {
  1622. panes[i].saveCaretInfo();
  1623. }
  1624. _view = _view.next;
  1625. }
  1626. Buffer[] buffers = jEdit.getBuffers();
  1627. for(int i = 0; i < buffers.length; i++)
  1628. {
  1629. Buffer buffer = buffers[i];
  1630. buffer.load(view,true);
  1631. }
  1632. } //}}}
  1633. //{{{ getBuffer() method
  1634. /**
  1635. * Returns the buffer with the specified path name. The path name
  1636. * must be an absolute, canonical, path.
  1637. * @param path The path name
  1638. * @see MiscUtilities#constructPath(String,String)
  1639. */
  1640. public static Buffer getBuffer(String path)
  1641. {
  1642. if(!MiscUtilities.isURL(path))
  1643. path = MiscUtilities.resolveSymlinks(path);
  1644. if((VFSManager.getVFSForPath(path).getCapabilities()
  1645. & VFS.CASE_INSENSITIVE_CAP) != 0)
  1646. {
  1647. path = path.toLowerCase();
  1648. }
  1649. synchronized(bufferListLock)
  1650. {
  1651. return (Buffer)bufferHash.get(path);
  1652. }
  1653. } //}}}
  1654. //{{{ getBuffers() method
  1655. /**
  1656. * Returns an array of open buffers.
  1657. */
  1658. public static Buffer[] getBuffers()
  1659. {
  1660. synchronized(bufferListLock)
  1661. {
  1662. Buffer[] buffers = new Buffer[bufferCount];
  1663. Buffer buffer = buffersFirst;
  1664. for(int i = 0; i < bufferCount; i++)
  1665. {
  1666. buffers[i] = buffer;
  1667. buffer = buffer.next;
  1668. }
  1669. return buffers;
  1670. }
  1671. } //}}}
  1672. //{{{ getBufferCount() method
  1673. /**
  1674. * Returns the number of open buffers.
  1675. */
  1676. public static int getBufferCount()
  1677. {
  1678. return bufferCount;
  1679. } //}}}
  1680. //{{{ getFirstBuffer() method
  1681. /**
  1682. * Returns the first buffer.
  1683. */
  1684. public static Buffer getFirstBuffer()
  1685. {
  1686. return buffersFirst;
  1687. } //}}}
  1688. //{{{ getLastBuffer() method
  1689. /**
  1690. * Returns the last buffer.
  1691. */
  1692. public static Buffer getLastBuffer()
  1693. {
  1694. return buffersLast;
  1695. } //}}}
  1696. //{{{ checkBufferStatus() method
  1697. /**
  1698. * Checks each buffer's status on disk and shows the dialog box
  1699. * informing the user that buffers changed on disk, if necessary.
  1700. * @param view The view
  1701. * @since jEdit 4.2pre1
  1702. */
  1703. public static void checkBufferStatus(View view)
  1704. {
  1705. // still need to call the status check even if the option is off,
  1706. // so that the write protection is updated if it changes on disk
  1707. boolean showDialogSetting = getBooleanProperty("view.checkModStatus");
  1708. // the problem with this is that if we have two edit panes
  1709. // looking at the same buffer and the file is reloaded both
  1710. // will jump to the same location
  1711. View _view = viewsFirst;
  1712. while(_view != null)
  1713. {
  1714. EditPane[] editPanes = _view.getEditPanes();
  1715. for(int i = 0; i < editPanes.length; i++)
  1716. {
  1717. editPanes[i].saveCaretInfo();
  1718. }
  1719. _view = _view.next;
  1720. }
  1721. Buffer buffer = buffersFirst;
  1722. int[] states = new int[bufferCount];
  1723. int i = 0;
  1724. boolean show = false;
  1725. while(buffer != null)
  1726. {
  1727. states[i] = buffer.checkFileStatus(view);
  1728. switch(states[i])
  1729. {
  1730. case Buffer.FILE_CHANGED:
  1731. if(showDialogSetting && !buffer.isDirty())
  1732. buffer.load(view,true);
  1733. /* fall through */
  1734. case Buffer.FILE_DELETED:
  1735. show = true;
  1736. break;
  1737. }
  1738. buffer = buffer.next;
  1739. i++;
  1740. }
  1741. if(show && showDialogSetting)
  1742. new FilesChangedDialog(view,states);
  1743. } //}}}
  1744. //}}}
  1745. //{{{ View methods
  1746. //{{{ getInputHandler() method
  1747. /**
  1748. * Returns the current input handler (key binding to action mapping)
  1749. * @see org.gjt.sp.jedit.gui.InputHandler
  1750. */
  1751. public static InputHandler getInputHandler()
  1752. {
  1753. return inputHandler;
  1754. } //}}}
  1755. /* public static void newViewTest()
  1756. {
  1757. long time = System.currentTimeMillis();
  1758. for(int i = 0; i < 30; i++)
  1759. {
  1760. Buffer b = newFile(null);
  1761. b.insert(0,"x");
  1762. new View(b,null,false);
  1763. }
  1764. System.err.println(System.currentTimeMillis() - time);
  1765. } */
  1766. //{{{ newView() method
  1767. /**
  1768. * Creates a new view.
  1769. * @param view An existing view
  1770. * @since jEdit 3.2pre2
  1771. */
  1772. public static View newView(View view)
  1773. {
  1774. return newView(view,null,false);
  1775. } //}}}
  1776. //{{{ newView() method
  1777. /**
  1778. * Creates a new view of a buffer.
  1779. * @param view An existing view
  1780. * @param buffer The buffer
  1781. */
  1782. public static View newView(View view, Buffer buffer)
  1783. {
  1784. return newView(view,buffer,false);
  1785. } //}}}
  1786. //{{{ newView() method
  1787. /**
  1788. * Creates a new view of a buffer.
  1789. * @param view An existing view
  1790. * @param buffer The buffer
  1791. * @param plainView If true, the view will not have dockable windows or
  1792. * tool bars.
  1793. *
  1794. * @since 4.1pre2
  1795. */
  1796. public static View newView(View view, Buffer buffer, boolean plainView)
  1797. {
  1798. View.ViewConfig config;
  1799. if(view != null && (plainView == view.isPlainView()))
  1800. config = view.getViewConfig();
  1801. else
  1802. config = new View.ViewConfig(plainView);
  1803. return newView(view,buffer,config);
  1804. } //}}}
  1805. //{{{ newView() method
  1806. /**
  1807. * Creates a new view.
  1808. * @param view An existing view
  1809. * @param buffer A buffer to display, or null
  1810. * @param config Encapsulates the view geometry, split configuration
  1811. * and if the view is a plain view
  1812. * @since jEdit 4.2pre1
  1813. */
  1814. public static View newView(View view, Buffer buffer, View.ViewConfig config)
  1815. {
  1816. try
  1817. {
  1818. if(view != null)
  1819. {
  1820. view.showWaitCursor();
  1821. view.getEditPane().saveCaretInfo();
  1822. }
  1823. View newView = new View(buffer,config);
  1824. addViewToList(newView);
  1825. if(!config.plainView)
  1826. {
  1827. DockableWindowManager wm = newView.getDockableWindowManager();
  1828. if(config.top != null
  1829. && config.top.length() != 0)
  1830. wm.showDockableWindow(config.top);
  1831. if(config.left !=