/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/jEdit.java
Java | 2602 lines | 1497 code | 276 blank | 829 comment | 316 complexity | 4f3bb46130d1da504100e24028380e55 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
Large files files are truncated, but you can 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 *
6 * Copyright (C) 1998, 2005 Slava Pestov
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22package org.gjt.sp.jedit;
23
24//{{{ Imports
25import org.gjt.sp.jedit.datatransfer.JEditTransferableService;
26import org.gjt.sp.jedit.gui.tray.JEditSwingTrayIcon;
27import org.gjt.sp.jedit.gui.tray.JTrayIconManager;
28import org.gjt.sp.jedit.visitors.JEditVisitor;
29
30import java.awt.*;
31
32import org.gjt.sp.jedit.View.ViewConfig;
33import org.gjt.sp.jedit.bsh.UtilEvalError;
34import javax.swing.*;
35import java.awt.event.*;
36import java.io.*;
37import java.net.*;
38import java.text.MessageFormat;
39import java.util.*;
40import java.util.List;
41
42import org.xml.sax.SAXParseException;
43
44import org.gjt.sp.jedit.bufferio.BufferIORequest;
45import org.gjt.sp.jedit.buffer.KillRing;
46import org.gjt.sp.jedit.buffer.JEditBuffer;
47import org.gjt.sp.jedit.buffer.FoldHandler;
48import org.gjt.sp.jedit.msg.*;
49import org.gjt.sp.jedit.gui.*;
50import org.gjt.sp.jedit.help.HelpViewer;
51import org.gjt.sp.jedit.io.*;
52import org.gjt.sp.jedit.pluginmgr.PluginManager;
53import org.gjt.sp.jedit.search.SearchAndReplace;
54import org.gjt.sp.jedit.syntax.Chunk;
55import org.gjt.sp.jedit.syntax.ModeProvider;
56import org.gjt.sp.jedit.syntax.TokenMarker;
57import org.gjt.sp.jedit.syntax.XModeHandler;
58import org.gjt.sp.jedit.textarea.*;
59import org.gjt.sp.jedit.visitors.SaveCaretInfoVisitor;
60import org.gjt.sp.jedit.bufferset.BufferSetManager;
61import org.gjt.sp.jedit.bufferset.BufferSet;
62import org.gjt.sp.util.Log;
63import org.gjt.sp.util.StandardUtilities;
64import org.gjt.sp.util.XMLUtilities;
65import org.gjt.sp.util.IOUtilities;
66import org.gjt.sp.util.SyntaxUtilities;
67//}}}
68
69/**
70 * The main class of the jEdit text editor.
71 * @author Slava Pestov
72 * @version $Id: jEdit.java 20100 2011-10-17 18:06:26Z kpouer $
73 */
74public class jEdit
75{
76 //{{{ getVersion() method
77 /**
78 * Returns the jEdit version as a human-readable string.
79 */
80 public static String getVersion()
81 {
82 return MiscUtilities.buildToVersion(getBuild());
83 } //}}}
84
85 //{{{ getBuild() method
86 /**
87 * Returns the internal version. MiscUtilities.compareStrings() can be used
88 * to compare different internal versions.
89 */
90 public static String getBuild()
91 {
92 // (major).(minor).(<99 = preX, 99 = "final").(bug fix)
93 return "04.05.01.00";
94 } //}}}
95
96 //{{{ main() method
97 /**
98 * The main method of the jEdit application.
99 * This should never be invoked directly.
100 * @param args The command line arguments
101 */
102 public static void main(String[] args)
103 {
104 //{{{ Check for Java 1.6 or later
105 String javaVersion = System.getProperty("java.version");
106 if(javaVersion.compareTo("1.6") < 0)
107 {
108 System.err.println("You are running Java version "
109 + javaVersion + '.');
110 System.err.println("jEdit requires Java 1.6 or later.");
111 System.exit(1);
112 } //}}}
113
114 startupDone.add(false);
115
116 // later on we need to know if certain code is called from
117 // the main thread
118 mainThread = Thread.currentThread();
119
120 settingsDirectory = ".jedit";
121 // On mac, different rules (should) apply
122 if(OperatingSystem.isMacOS())
123 settingsDirectory = "Library/jEdit";
124
125 // MacOS users expect the app to keep running after all windows
126 // are closed
127 background = OperatingSystem.isMacOS();
128
129 //{{{ Parse command line
130 boolean endOpts = false;
131 int level = Log.WARNING;
132 String portFile = "server";
133 boolean restore = true;
134 boolean newView = true;
135 boolean newPlainView = false;
136 boolean gui = true; // open initial view?
137 boolean loadPlugins = true;
138 boolean runStartupScripts = true;
139 boolean quit = false;
140 boolean wait = false;
141 boolean shouldRelocateSettings = true;
142 String userDir = System.getProperty("user.dir");
143 boolean splash = true;
144
145 // script to run
146 String scriptFile = null;
147
148 for(int i = 0; i < args.length; i++)
149 {
150 String arg = args[i];
151 if(arg == null)
152 continue;
153 else if(arg.length() == 0)
154 args[i] = null;
155 else if(arg.startsWith("-") && !endOpts)
156 {
157 if(arg.equals("--"))
158 endOpts = true;
159 else if(arg.equals("-usage"))
160 {
161 version();
162 System.err.println();
163 usage();
164 System.exit(1);
165 }
166 else if(arg.equals("-version"))
167 {
168 version();
169 System.exit(1);
170 }
171 else if(arg.startsWith("-log="))
172 {
173 try
174 {
175 level = Integer.parseInt(arg.substring("-log=".length()));
176 }
177 catch(NumberFormatException nf)
178 {
179 System.err.println("Malformed option: " + arg);
180 }
181 }
182 else if(arg.equals("-nosettings"))
183 settingsDirectory = null;
184 else if(arg.startsWith("-settings="))
185 {
186 settingsDirectory = arg.substring(10);
187 shouldRelocateSettings = false;
188 }
189 else if(arg.startsWith("-noserver"))
190 portFile = null;
191 else if(arg.equals("-server"))
192 portFile = "server";
193 else if(arg.startsWith("-server="))
194 portFile = arg.substring(8);
195 else if(arg.startsWith("-background"))
196 background = true;
197 else if(arg.startsWith("-nobackground"))
198 background = false;
199 else if(arg.equals("-gui"))
200 gui = true;
201 else if(arg.equals("-nogui"))
202 gui = false;
203 else if(arg.equals("-newview"))
204 newView = true;
205 else if(arg.equals("-newplainview"))
206 newPlainView = true;
207 else if(arg.equals("-reuseview"))
208 newPlainView = newView = false;
209 else if(arg.equals("-restore"))
210 restore = true;
211 else if(arg.equals("-norestore"))
212 restore = false;
213 else if(arg.equals("-plugins"))
214 loadPlugins = true;
215 else if(arg.equals("-noplugins"))
216 loadPlugins = false;
217 else if(arg.equals("-startupscripts"))
218 runStartupScripts = true;
219 else if(arg.equals("-nostartupscripts"))
220 runStartupScripts = false;
221 else if(arg.startsWith("-run="))
222 scriptFile = arg.substring(5);
223 else if(arg.equals("-wait"))
224 wait = true;
225 else if(arg.equals("-quit"))
226 quit = true;
227 else if(arg.equals("-nosplash"))
228 splash = false;
229 else
230 {
231 System.err.println("Unknown option: "
232 + arg);
233 usage();
234 System.exit(1);
235 }
236 args[i] = null;
237 }
238 } //}}}
239
240 JTrayIconManager.setTrayIconArgs(restore, userDir, args);
241
242
243 //{{{ We need these initializations very early on
244 if(settingsDirectory != null)
245 {
246 settingsDirectory = MiscUtilities.constructPath(
247 System.getProperty("user.home"),
248 settingsDirectory);
249 settingsDirectory = MiscUtilities.resolveSymlinks(
250 settingsDirectory);
251 }
252
253 if(settingsDirectory != null && portFile != null)
254 portFile = MiscUtilities.constructPath(settingsDirectory,portFile);
255 else
256 portFile = null;
257
258 Log.init(true,level);
259 //}}}
260
261 //{{{ Try connecting to another running jEdit instance
262 if(portFile != null && new File(portFile).exists())
263 {
264 try
265 {
266 BufferedReader in = new BufferedReader(new FileReader(portFile));
267 String check = in.readLine();
268 if(!"b".equals(check))
269 throw new Exception("Wrong port file format");
270
271 int port = Integer.parseInt(in.readLine());
272 int key = Integer.parseInt(in.readLine());
273
274 Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),port);
275 DataOutputStream out = new DataOutputStream(
276 socket.getOutputStream());
277 out.writeInt(key);
278
279 String script;
280 if(quit)
281 {
282 script = "socket.close();\n"
283 + "jEdit.exit(null,true);\n";
284 }
285 else
286 {
287 script = makeServerScript(wait,restore,
288 newView,newPlainView,args,
289 scriptFile);
290 }
291
292 out.writeUTF(script);
293
294 Log.log(Log.DEBUG,jEdit.class,"Waiting for server");
295 // block until its closed
296 try
297 {
298 socket.getInputStream().read();
299 }
300 catch(Exception e)
301 {
302 }
303
304 in.close();
305 out.close();
306
307 System.exit(0);
308 }
309 catch(Exception e)
310 {
311 // ok, this one seems to confuse newbies
312 // endlessly, so log it as NOTICE, not
313 // ERROR
314 Log.log(Log.NOTICE,jEdit.class,"An error occurred"
315 + " while connecting to the jEdit server instance.");
316 Log.log(Log.NOTICE,jEdit.class,"This probably means that"
317 + " jEdit crashed and/or exited abnormally");
318 Log.log(Log.NOTICE,jEdit.class,"the last time it was run.");
319 Log.log(Log.NOTICE,jEdit.class,"If you don't"
320 + " know what this means, don't worry.");
321 Log.log(Log.NOTICE,jEdit.class,e);
322 }
323 }
324
325 if(quit)
326 {
327 // if no server running and user runs jedit -quit,
328 // just exit
329 System.exit(0);
330 } //}}}
331
332 // don't show splash screen if there is a file named
333 // 'nosplash' in the settings directory
334 if(splash && (!new File(settingsDirectory,"nosplash").exists()))
335 GUIUtilities.showSplashScreen();
336
337 //{{{ Mac settings migration code. Should eventually be removed
338 if(OperatingSystem.isMacOS() && shouldRelocateSettings && settingsDirectory != null)
339 {
340 relocateSettings();
341 }
342 // }}}
343
344 //{{{ Initialize settings directory
345 Writer stream;
346 if(settingsDirectory != null)
347 {
348 File _settingsDirectory = new File(settingsDirectory);
349 if(!_settingsDirectory.exists())
350 _settingsDirectory.mkdirs();
351 File _macrosDirectory = new File(settingsDirectory,"macros");
352 if(!_macrosDirectory.exists())
353 _macrosDirectory.mkdir();
354
355 String logPath = MiscUtilities.constructPath(
356 settingsDirectory,"activity.log");
357
358 backupSettingsFile(new File(logPath));
359
360 try
361 {
362 stream = new BufferedWriter(new FileWriter(logPath));
363
364 // Write a warning message:
365 String lineSep = System.getProperty("line.separator");
366 stream.write("Log file created on " + new Date());
367 stream.write(lineSep);
368 stream.write("IMPORTANT:");
369 stream.write(lineSep);
370 stream.write("Because updating this file after "
371 + "every log message would kill");
372 stream.write(lineSep);
373 stream.write("performance, it will be *incomplete* "
374 + "unless you invoke the");
375 stream.write(lineSep);
376 stream.write("Utilities->Troubleshooting->Update "
377 + "Activity Log on Disk command!");
378 stream.write(lineSep);
379 }
380 catch(Exception e)
381 {
382 e.printStackTrace();
383 stream = null;
384 }
385 }
386 else
387 {
388 stream = null;
389 } //}}}
390
391 Log.setLogWriter(stream);
392
393 Log.log(Log.NOTICE,jEdit.class,"jEdit version " + getVersion());
394 Log.log(Log.MESSAGE,jEdit.class,"Settings directory is "
395 + settingsDirectory);
396
397 //{{{ Get things rolling
398 GUIUtilities.advanceSplashProgress("init");
399 initMisc();
400 GUIUtilities.advanceSplashProgress("init system properties");
401 initSystemProperties();
402
403 GUIUtilities.advanceSplashProgress("init beanshell");
404 BeanShell.init();
405
406 GUIUtilities.advanceSplashProgress("loading site properties");
407 if(jEditHome != null)
408 initSiteProperties();
409
410 GUIUtilities.advanceSplashProgress("loading user properties");
411 initUserProperties();
412
413 GUIUtilities.advanceSplashProgress("init GUI");
414 GUIUtilities.init();
415
416 bufferSetManager = new BufferSetManager();
417 //}}}
418
419 //{{{ Initialize server
420 if(portFile != null)
421 {
422 GUIUtilities.advanceSplashProgress("init server");
423 server = new EditServer(portFile);
424 if(!server.isOK())
425 server = null;
426 }
427 else
428 {
429 GUIUtilities.advanceSplashProgress();
430 if(background)
431 {
432 background = false;
433 Log.log(Log.WARNING,jEdit.class,"You cannot specify both the"
434 + " -background and -noserver switches");
435 }
436 } //}}}
437
438 //{{{ Do more stuff
439 GUIUtilities.advanceSplashProgress("init look and feel");
440 initPLAF();
441 GUIUtilities.advanceSplashProgress("init VFS Manager");
442 VFSManager.init();
443 GUIUtilities.advanceSplashProgress("init resources");
444 initResources();
445 SearchAndReplace.load();
446
447 if(loadPlugins)
448 {
449 GUIUtilities.advanceSplashProgress("init plugins");
450 initPlugins();
451 }
452 else
453 GUIUtilities.advanceSplashProgress();
454
455 Registers.setSaver(new JEditRegisterSaver());
456 Registers.setListener(new JEditRegistersListener());
457 GUIUtilities.advanceSplashProgress("init history model");
458 HistoryModel.setSaver(new JEditHistoryModelSaver());
459 HistoryModel.loadHistory();
460 GUIUtilities.advanceSplashProgress("init buffer history");
461 BufferHistory.load();
462 GUIUtilities.advanceSplashProgress("init killring");
463 KillRing.setInstance(new JEditKillRing());
464 KillRing.getInstance().load();
465 GUIUtilities.advanceSplashProgress("init various properties");
466 propertiesChanged();
467
468 GUIUtilities.advanceSplashProgress("init modes");
469
470 // Buffer sort
471 sortBuffers = getBooleanProperty("sortBuffers");
472 sortByName = getBooleanProperty("sortByName");
473
474 reloadModes();
475
476 GUIUtilities.advanceSplashProgress("activate plugins");
477 //}}}
478
479 //{{{ Activate plugins that must be activated at startup
480 for(int i = 0; i < jars.size(); i++)
481 {
482 jars.elementAt(i).activatePluginIfNecessary();
483 } //}}}
484
485 String[] serviceNames = ServiceManager.getServiceNames(JEditTransferableService.class);
486 for (String serviceName : serviceNames)
487 {
488 JEditTransferableService service = ServiceManager.getService(JEditTransferableService.class, serviceName);
489 org.gjt.sp.jedit.datatransfer.TransferHandler.getInstance().registerTransferableService(service);
490 }
491
492 //{{{ Load macros and run startup scripts, after plugins and settings are loaded
493 GUIUtilities.advanceSplashProgress("init macros");
494 Macros.loadMacros();
495 Macros.getMacroActionSet().initKeyBindings();
496
497 if(runStartupScripts && jEditHome != null)
498 {
499 String path = MiscUtilities.constructPath(jEditHome,"startup");
500 File file = new File(path);
501 if(file.exists())
502 {
503 runStartupScripts(file);
504 }
505 else
506 GUIUtilities.advanceSplashProgress();
507 }
508 else
509 GUIUtilities.advanceSplashProgress("run startup scripts");
510
511 if(runStartupScripts && settingsDirectory != null)
512 {
513 String path = MiscUtilities.constructPath(settingsDirectory,"startup");
514 File file = new File(path);
515 if (file.exists())
516 {
517 GUIUtilities.advanceSplashProgress("run startup scripts");
518 runStartupScripts(file);
519 }
520 else
521 {
522 GUIUtilities.advanceSplashProgress();
523 file.mkdirs();
524 }
525 }
526 else
527 {
528 GUIUtilities.advanceSplashProgress();
529 } //}}}
530
531 //{{{ Run script specified with -run= parameter
532 if(scriptFile != null)
533 {
534 GUIUtilities.advanceSplashProgress("run script file");
535 scriptFile = MiscUtilities.constructPath(userDir,scriptFile);
536 try
537 {
538 BeanShell.getNameSpace().setVariable("args",args);
539 }
540 catch(UtilEvalError e)
541 {
542 Log.log(Log.ERROR,jEdit.class,e);
543 }
544 BeanShell.runScript(null,scriptFile,null,false);
545 }
546 else
547 {
548 GUIUtilities.advanceSplashProgress();
549 }
550 //}}}
551
552 GUIUtilities.advanceSplashProgress();
553
554 // Create dynamic actions for switching to saved layouts.
555 // The list of saved layouts is retrieved from the docking framework,
556 // which can be provided by a plugin, so this must be called only after
557 // the plugins are loaded.
558 DockingLayoutManager.init();
559
560 // Open files, create the view and hide the splash screen.
561 SyntaxUtilities.propertyManager = jEdit.propertyManager;
562 finishStartup(gui,restore,newPlainView,userDir,args);
563 } //}}}
564
565 //{{{ Property methods
566
567 //{{{ getProperties() method
568 /**
569 * Returns the properties object which contains all known
570 * jEdit properties. Note that as of jEdit 4.2pre10, this returns a
571 * new collection, not the existing properties instance.
572 * @since jEdit 3.1pre4
573 */
574 public static Properties getProperties()
575 {
576 return propMgr.getProperties();
577 } //}}}
578
579 //{{{ getProperty() method
580 /**
581 * Fetches a property, returning null if it's not defined.
582 * @param name The property
583 */
584 public static String getProperty(String name)
585 {
586 return propMgr.getProperty(name);
587 } //}}}
588
589 //{{{ getProperty() method
590 /**
591 * Fetches a property, returning the default value if it's not
592 * defined.
593 * @param name The property
594 * @param def The default value
595 */
596 public static String getProperty(String name, String def)
597 {
598 String value = propMgr.getProperty(name);
599 if(value == null)
600 return def;
601 else
602 return value;
603 } //}}}
604
605 //{{{ getProperty() method
606 /**
607 * Returns the property with the specified name.<p>
608 *
609 * The elements of the <code>args</code> array are substituted
610 * into the value of the property in place of strings of the
611 * form <code>{<i>n</i>}</code>, where <code><i>n</i></code> is an index
612 * in the array.<p>
613 *
614 * You can find out more about this feature by reading the
615 * documentation for the <code>format</code> method of the
616 * <code>java.text.MessageFormat</code> class.
617 *
618 * @param name The property
619 * @param args The positional parameters
620 */
621 public static String getProperty(String name, Object[] args)
622 {
623 if(name == null)
624 return null;
625 if(args == null)
626 return getProperty(name);
627 else
628 {
629 String value = getProperty(name);
630 if(value == null)
631 return null;
632 else
633 return MessageFormat.format(value,args);
634 }
635 } //}}}
636
637 //{{{ getBooleanProperty() method
638 /**
639 * Returns the value of a boolean property.
640 * @param name The property
641 */
642 public static boolean getBooleanProperty(String name)
643 {
644 return getBooleanProperty(name,false);
645 } //}}}
646
647 //{{{ getBooleanProperty() method
648 /**
649 * Returns the value of a boolean property.
650 * @param name The property
651 * @param def The default value
652 */
653 public static boolean getBooleanProperty(String name, boolean def)
654 {
655 String value = getProperty(name);
656 return StandardUtilities.getBoolean(value, def);
657 } //}}}
658
659 //{{{ getIntegerProperty() method
660 /**
661 * Returns the value of an integer property.
662 * @param name The property
663 */
664 public static int getIntegerProperty(String name)
665 {
666 return getIntegerProperty(name,0);
667 } //}}}
668
669 //{{{ getIntegerProperty() method
670 /**
671 * Returns the value of an integer property.
672 * @param name The property
673 * @param def The default value
674 * @since jEdit 4.0pre1
675 */
676 public static int getIntegerProperty(String name, int def)
677 {
678 String value = getProperty(name);
679 if(value == null)
680 return def;
681 else
682 {
683 try
684 {
685 return Integer.parseInt(value.trim());
686 }
687 catch(NumberFormatException nf)
688 {
689 return def;
690 }
691 }
692 } //}}}
693
694 //{{{ getDoubleProperty() method
695 public static double getDoubleProperty(String name, double def)
696 {
697 String value = getProperty(name);
698 if(value == null)
699 return def;
700 else
701 {
702 try
703 {
704 return Double.parseDouble(value.trim());
705 }
706 catch(NumberFormatException nf)
707 {
708 return def;
709 }
710 }
711 }
712 //}}}
713
714 //{{{ getFontProperty() method
715 /**
716 * Returns the value of a font property. The family is stored
717 * in the <code><i>name</i></code> property, the font size is stored
718 * in the <code><i>name</i>size</code> property, and the font style is
719 * stored in <code><i>name</i>style</code>. For example, if
720 * <code><i>name</i></code> is <code>view.gutter.font</code>, the
721 * properties will be named <code>view.gutter.font</code>,
722 * <code>view.gutter.fontsize</code>, and
723 * <code>view.gutter.fontstyle</code>.
724 *
725 * @param name The property
726 * @since jEdit 4.0pre1
727 */
728 public static Font getFontProperty(String name)
729 {
730 return getFontProperty(name,null);
731 } //}}}
732
733 //{{{ getFontProperty() method
734 /**
735 * Returns the value of a font property. The family is stored
736 * in the <code><i>name</i></code> property, the font size is stored
737 * in the <code><i>name</i>size</code> property, and the font style is
738 * stored in <code><i>name</i>style</code>. For example, if
739 * <code><i>name</i></code> is <code>view.gutter.font</code>, the
740 * properties will be named <code>view.gutter.font</code>,
741 * <code>view.gutter.fontsize</code>, and
742 * <code>view.gutter.fontstyle</code>.
743 *
744 * @param name The property
745 * @param def The default value
746 * @since jEdit 4.0pre1
747 */
748 public static Font getFontProperty(String name, Font def)
749 {
750 String family = getProperty(name);
751 String sizeString = getProperty(name + "size");
752 String styleString = getProperty(name + "style");
753
754 if(family == null || sizeString == null || styleString == null)
755 return def;
756 else
757 {
758 int size, style;
759
760 try
761 {
762 size = Integer.parseInt(sizeString);
763 }
764 catch(NumberFormatException nf)
765 {
766 return def;
767 }
768
769 try
770 {
771 style = Integer.parseInt(styleString);
772 }
773 catch(NumberFormatException nf)
774 {
775 return def;
776 }
777
778 return new Font(family,style,size);
779 }
780 } //}}}
781
782 //{{{ getColorProperty() method
783 /**
784 * Returns the value of a color property.
785 * @param name The property name
786 * @since jEdit 4.0pre1
787 */
788 public static Color getColorProperty(String name)
789 {
790 return getColorProperty(name,Color.black);
791 } //}}}
792
793 //{{{ getColorProperty() method
794 /**
795 * Returns the value of a color property.
796 * @param name The property name
797 * @param def The default value
798 * @since jEdit 4.0pre1
799 */
800 public static Color getColorProperty(String name, Color def)
801 {
802 String value = getProperty(name);
803 if(value == null)
804 return def;
805 else
806 return SyntaxUtilities.parseColor(value, def);
807 } //}}}
808
809 //{{{ setColorProperty() method
810 /**
811 * Sets the value of a color property.
812 * @param name The property name
813 * @param value The value
814 * @since jEdit 4.0pre1
815 */
816 public static void setColorProperty(String name, Color value)
817 {
818 setProperty(name, SyntaxUtilities.getColorHexString(value));
819 } //}}}
820
821 //{{{ setProperty() method
822 /**
823 * Sets a property to a new value.
824 * @param name The property
825 * @param value The new value
826 */
827 public static void setProperty(String name, String value)
828 {
829 propMgr.setProperty(name,value);
830 } //}}}
831
832 //{{{ setTemporaryProperty() method
833 /**
834 * Sets a property to a new value. Properties set using this
835 * method are not saved to the user properties list.
836 * @param name The property
837 * @param value The new value
838 * @since jEdit 2.3final
839 */
840 public static void setTemporaryProperty(String name, String value)
841 {
842 propMgr.setTemporaryProperty(name,value);
843 } //}}}
844
845 //{{{ setBooleanProperty() method
846 /**
847 * Sets a boolean property.
848 * @param name The property
849 * @param value The value
850 */
851 public static void setBooleanProperty(String name, boolean value)
852 {
853 setProperty(name,value ? "true" : "false");
854 } //}}}
855
856 //{{{ setIntegerProperty() method
857 /**
858 * Sets the value of an integer property.
859 * @param name The property
860 * @param value The value
861 * @since jEdit 4.0pre1
862 */
863 public static void setIntegerProperty(String name, int value)
864 {
865 setProperty(name,String.valueOf(value));
866 } //}}}
867
868 //{{{ setDoubleProperty() method
869 public static void setDoubleProperty(String name, double value)
870 {
871 setProperty(name,String.valueOf(value));
872 }
873 //}}}
874
875 //{{{ setFontProperty() method
876 /**
877 * Sets the value of a font property. The family is stored
878 * in the <code><i>name</i></code> property, the font size is stored
879 * in the <code><i>name</i>size</code> property, and the font style is
880 * stored in <code><i>name</i>style</code>. For example, if
881 * <code><i>name</i></code> is <code>view.gutter.font</code>, the
882 * properties will be named <code>view.gutter.font</code>,
883 * <code>view.gutter.fontsize</code>, and
884 * <code>view.gutter.fontstyle</code>.
885 *
886 * @param name The property
887 * @param value The value
888 * @since jEdit 4.0pre1
889 */
890 public static void setFontProperty(String name, Font value)
891 {
892 setProperty(name,value.getFamily());
893 setIntegerProperty(name + "size",value.getSize());
894 setIntegerProperty(name + "style",value.getStyle());
895 } //}}}
896
897 //{{{ unsetProperty() method
898 /**
899 * Unsets (clears) a property.
900 * @param name The property
901 */
902 public static void unsetProperty(String name)
903 {
904 propMgr.unsetProperty(name);
905 } //}}}
906
907 //{{{ resetProperty() method
908 /**
909 * Resets a property to its default value.
910 * @param name The property
911 *
912 * @since jEdit 2.5pre3
913 */
914 public static void resetProperty(String name)
915 {
916 propMgr.resetProperty(name);
917 } //}}}
918
919 //{{{ propertiesChanged() method
920 /**
921 * Reloads various settings from the properties.
922 */
923 public static void propertiesChanged()
924 {
925 initPLAF();
926
927 initKeyBindings();
928
929 Autosave.setInterval(getIntegerProperty("autosave",30));
930
931 saveCaret = getBooleanProperty("saveCaret");
932
933 UIDefaults defaults = UIManager.getDefaults();
934
935 // give all text areas the same font
936 Font font = getFontProperty("view.font");
937
938 //defaults.put("TextField.font",font);
939 defaults.put("TextArea.font",font);
940 defaults.put("TextPane.font",font);
941
942 // Enable/Disable tooltips
943 ToolTipManager.sharedInstance().setEnabled(
944 jEdit.getBooleanProperty("showTooltips"));
945
946 initProxy();
947
948 // we do this here instead of adding buffers to the bus.
949 Buffer buffer = buffersFirst;
950 while(buffer != null)
951 {
952 buffer.resetCachedProperties();
953 buffer.propertiesChanged();
954 buffer = buffer.next;
955 }
956
957 HistoryModel.setDefaultMax(getIntegerProperty("history",25));
958 HistoryModel.setDefaultMaxSize(getIntegerProperty("historyMaxSize", 5000000));
959 KillRing.getInstance().propertiesChanged(getIntegerProperty("history",25));
960 Chunk.propertiesChanged(propertyManager);
961
962 if (getBooleanProperty("systrayicon"))
963 {
964 JTrayIconManager.addTrayIcon();
965 }
966 else
967 {
968 JTrayIconManager.removeTrayIcon();
969 }
970 EditBus.send(new PropertiesChanged(null));
971 } //}}}
972
973 //}}}
974
975 //{{{ Plugin management methods
976
977 //{{{ getNotLoadedPluginJARs() method
978 /**
979 * Returns a list of plugin JARs pathnames that are not currently loaded
980 * by examining the user and system plugin directories.
981 * @since jEdit 3.2pre1
982 */
983 public static String[] getNotLoadedPluginJARs()
984 {
985 List<String> returnValue = new ArrayList<String>();
986
987 if(jEditHome != null)
988 {
989 String systemPluginDir = MiscUtilities
990 .constructPath(jEditHome,"jars");
991
992 String[] list = new File(systemPluginDir).list();
993 if(list != null)
994 getNotLoadedPluginJARs(returnValue,systemPluginDir,list);
995 }
996
997 if(settingsDirectory != null)
998 {
999 String userPluginDir = MiscUtilities
1000 .constructPath(settingsDirectory,"jars");
1001 String[] list = new File(userPluginDir).list();
1002 if(list != null)
1003 {
1004 getNotLoadedPluginJARs(returnValue,
1005 userPluginDir,list);
1006 }
1007 }
1008
1009 String[] _returnValue = new String[returnValue.size()];
1010 returnValue.toArray(_returnValue);
1011 return _returnValue;
1012 } //}}}
1013
1014 //{{{ getPlugin() method
1015 /**
1016 * Returns the plugin with the specified class name.
1017 * Only works for plugins that were loaded.
1018 */
1019 public static EditPlugin getPlugin(String name)
1020 {
1021 return getPlugin(name, false);
1022 } //}}}
1023
1024 //{{{ getPlugin(String, boolean) method
1025 /**
1026 * Returns the plugin with the specified class name.
1027 * If * <code>loadIfNecessary</code> is true, the plugin will be searched for,
1028 * loaded, and activated in case it has not yet been loaded.
1029 *
1030 * @param name the classname of the main Plugin class.
1031 * @param loadIfNecessary - loads plugin + dependencies if it is not loaded yet.
1032 * @since jEdit 4.2pre4
1033 */
1034 public static EditPlugin getPlugin(String name, boolean loadIfNecessary)
1035 {
1036 EditPlugin[] plugins = getPlugins();
1037 EditPlugin plugin = null;
1038 for(int i = 0; i < plugins.length; i++)
1039 {
1040 if(plugins[i].getClassName().equals(name))
1041 plugin = plugins[i];
1042 if(loadIfNecessary)
1043 {
1044 if(plugin instanceof EditPlugin.Deferred)
1045 {
1046 plugin.getPluginJAR().activatePlugin();
1047 plugin = plugin.getPluginJAR().getPlugin();
1048 break;
1049 }
1050 }
1051 }
1052 if (!loadIfNecessary) return plugin;
1053 String jarPath = PluginJAR.findPlugin(name);
1054 PluginJAR pjar = PluginJAR.load(jarPath, true);
1055 return pjar.getPlugin();
1056 } //}}}
1057
1058 //{{{ getPlugins() method
1059 /**
1060 * Returns an array of installed plugins.
1061 */
1062 public static EditPlugin[] getPlugins()
1063 {
1064 Collection<EditPlugin> pluginList = new ArrayList<EditPlugin>();
1065 for(int i = 0; i < jars.size(); i++)
1066 {
1067 EditPlugin plugin = jars.elementAt(i).getPlugin();
1068 if(plugin != null)
1069 pluginList.add(plugin);
1070 }
1071
1072 EditPlugin[] array = new EditPlugin[pluginList.size()];
1073 pluginList.toArray(array);
1074 return array;
1075 } //}}}
1076
1077 //{{{ getPluginJARs() method
1078 /**
1079 * Returns an array of installed plugins.
1080 * @since jEdit 4.2pre1
1081 */
1082 public static PluginJAR[] getPluginJARs()
1083 {
1084 PluginJAR[] array = new PluginJAR[jars.size()];
1085 jars.copyInto(array);
1086 return array;
1087 } //}}}
1088
1089 //{{{ getPluginJAR() method
1090 /**
1091 * Returns the JAR with the specified path name.
1092 * @param path The path name
1093 * @since jEdit 4.2pre1
1094 */
1095 public static PluginJAR getPluginJAR(String path)
1096 {
1097 for(int i = 0; i < jars.size(); i++)
1098 {
1099 PluginJAR jar = jars.elementAt(i);
1100 if(jar.getPath().equals(path))
1101 return jar;
1102 }
1103
1104 return null;
1105 } //}}}
1106
1107 //{{{ addPluginJAR() method
1108 /**
1109 * Loads the plugin JAR with the specified path. Some notes about this
1110 * method:
1111 *
1112 * <ul>
1113 * <li>Calling this at a time other than jEdit startup can have
1114 * unpredictable results if the plugin has not been updated for the
1115 * jEdit 4.2 plugin API.
1116 * <li>You must make sure yourself the plugin is not already loaded.
1117 * <li>After loading, you just make sure all the plugin's dependencies
1118 * are satisified before activating the plugin, using the
1119 * {@link PluginJAR#checkDependencies()} method.
1120 * </ul>
1121 *
1122 * @param path The JAR file path
1123 * @since jEdit 4.2pre1
1124 */
1125 public static void addPluginJAR(String path)
1126 {
1127 PluginJAR jar = new PluginJAR(new File(path));
1128 jars.addElement(jar);
1129 jar.init();
1130 jEdit.unsetProperty("plugin-blacklist."+MiscUtilities.getFileName(path));
1131 EditBus.send(new PluginUpdate(jar,PluginUpdate.LOADED,false));
1132 if(!isMainThread())
1133 {
1134 EditBus.send(new DynamicMenuChanged("plugins"));
1135 initKeyBindings();
1136 }
1137 } //}}}
1138
1139 //{{{ addPluginJARsFromDirectory() method
1140 /**
1141 * Loads all plugins in a directory.
1142 * @param directory The directory
1143 * @since jEdit 4.2pre1
1144 */
1145 private static void addPluginJARsFromDirectory(String directory)
1146 {
1147 Log.log(Log.NOTICE,jEdit.class,"Loading plugins from "
1148 + directory);
1149
1150 File file = new File(directory);
1151 if(!(file.exists() && file.isDirectory()))
1152 return;
1153 String[] plugins = file.list();
1154 if(plugins == null)
1155 return;
1156
1157 for(int i = 0; i < plugins.length; i++)
1158 {
1159 String plugin = plugins[i];
1160 if(!plugin.toLowerCase().endsWith(".jar"))
1161 continue;
1162
1163 String path = MiscUtilities.constructPath(directory,plugin);
1164 if (jEdit.getBooleanProperty("plugin-blacklist."+plugin))
1165 continue;
1166
1167 addPluginJAR(path);
1168 }
1169 } //}}}
1170
1171 //{{{ removePluginJAR() method
1172 /**
1173 * Unloads the given plugin JAR with the specified path. Note that
1174 * calling this at a time other than jEdit shutdown can have
1175 * unpredictable results if the plugin has not been updated for the
1176 * jEdit 4.2 plugin API.
1177 *
1178 * @param jar The <code>PluginJAR</code> instance
1179 * @param exit Set to true if jEdit is exiting; enables some
1180 * shortcuts so the editor can close faster.
1181 * @since jEdit 4.2pre1
1182 */
1183 public static void removePluginJAR(PluginJAR jar, boolean exit)
1184 {
1185 if(exit)
1186 {
1187 jar.uninit(true);
1188 }
1189 else
1190 {
1191 jar.uninit(false);
1192 jars.removeElement(jar);
1193 initKeyBindings();
1194 }
1195
1196 EditBus.send(new PluginUpdate(jar,PluginUpdate.UNLOADED,exit));
1197 if(!isMainThread() && !exit)
1198 EditBus.send(new DynamicMenuChanged("plugins"));
1199 } //}}}
1200
1201 //}}}
1202
1203 //{{{ Action methods
1204
1205 //{{{ getActionContext() method
1206 /**
1207 * Returns the action context used to store editor actions.
1208 * @since jEdit 4.2pre1
1209 */
1210 public static ActionContext getActionContext()
1211 {
1212 return actionContext;
1213 } //}}}
1214
1215 //{{{ addActionSet() method
1216 /**
1217 * Adds a new action set to jEdit's list of ActionSets (viewable from the shortcuts
1218 * option pane). By default, each plugin has one ActionSet,
1219 * but some plugins may create dynamic action sets, such as ProjectViewer and Console.
1220 * These plugins must call removeActionSet() when the plugin is unloaded.
1221 *
1222 * @since jEdit 4.0pre1
1223 * @see #removeActionSet(ActionSet)
1224 */
1225 public static void addActionSet(ActionSet actionSet)
1226 {
1227 actionContext.addActionSet(actionSet);
1228 } //}}}
1229
1230 //{{{ removeActionSet() method
1231 /**
1232 * Removes an action set from jEdit's list.
1233 * Plugins that add a dynamic action set must call this method at plugin
1234 * unload time.
1235 * @since jEdit 4.2pre1
1236 */
1237 public static void removeActionSet(ActionSet actionSet)
1238 {
1239 actionContext.removeActionSet(actionSet);
1240 } //}}}
1241
1242 //{{{ getBuiltInActionSet() method
1243 /**
1244 * Returns the set of commands built into jEdit.
1245 * @since jEdit 4.2pre1
1246 */
1247 public static ActionSet getBuiltInActionSet()
1248 {
1249 return builtInActionSet;
1250 } //}}}
1251
1252 // {{{ getActionSets() method
1253 /**
1254 * Returns all registered action sets.
1255 *
1256 * @return the ActionSet(s)
1257 * @since jEdit 4.0pre1
1258 */
1259 public static ActionSet[] getActionSets()
1260 {
1261 return actionContext.getActionSets();
1262 } // }}}
1263
1264 //{{{ getAction() method
1265 /**
1266 * Returns the specified action.
1267 * @param name The action name
1268 */
1269 public static EditAction getAction(String name)
1270 {
1271 return actionContext.getAction(name);
1272 } //}}}
1273
1274 //{{{ getActionSetForAction() method
1275 /**
1276 * Returns the action set that contains the specified action.
1277 *
1278 * @param action The action
1279 * @since jEdit 4.2pre1
1280 */
1281 public static ActionSet getActionSetForAction(String action)
1282 {
1283 return actionContext.getActionSetForAction(action);
1284 } //}}}
1285
1286 //{{{ getActionNames() method
1287 /**
1288 * Returns all registered action names.
1289 */
1290 public static String[] getActionNames()
1291 {
1292 return actionContext.getActionNames();
1293 } //}}}
1294
1295 //}}}
1296
1297 //{{{ Edit mode methods
1298
1299 //{{{ reloadModes() method
1300 /**
1301 * Reloads all edit modes. User defined edit modes are loaded after
1302 * global modes so that user modes supercede global modes.
1303 * @since jEdit 3.2pre2
1304 */
1305 public static void reloadModes()
1306 {
1307 ModeProvider.instance.removeAll();
1308
1309 //{{{ Load the global catalog first
1310 if(jEditHome == null)
1311 loadModeCatalog("/modes/catalog",true);
1312 else
1313 {
1314 loadModeCatalog(MiscUtilities.constructPath(jEditHome,
1315 "modes","catalog"),false);
1316 } //}}}
1317
1318 //{{{ Load user catalog second so user modes override global modes.
1319 if(settingsDirectory != null)
1320 {
1321 File userModeDir = new File(MiscUtilities.constructPath(
1322 settingsDirectory,"modes"));
1323 if(!userModeDir.exists())
1324 userModeDir.mkdirs();
1325
1326 File userCatalog = new File(MiscUtilities.constructPath(
1327 settingsDirectory,"modes","catalog"));
1328 if(!userCatalog.exists())
1329 {
1330 // create dummy catalog
1331 FileWriter out = null;
1332 try
1333 {
1334 out = new FileWriter(userCatalog);
1335 out.write(jEdit.getProperty("defaultCatalog"));
1336 }
1337 catch(IOException io)
1338 {
1339 Log.log(Log.ERROR,jEdit.class,io);
1340 }
1341 finally
1342 {
1343 IOUtilities.closeQuietly(out);
1344 }
1345 }
1346
1347 loadModeCatalog(userCatalog.getPath(),false);
1348 } //}}}
1349
1350 Buffer buffer = buffersFirst;
1351 while(buffer != null)
1352 {
1353 // This reloads the token marker and sends a message
1354 // which causes edit panes to repaint their text areas
1355 buffer.setMode();
1356
1357 buffer = buffer.next;
1358 }
1359 } //}}}
1360
1361 //{{{ getMode() method
1362 /**
1363 * Returns the edit mode with the specified name.
1364 * @param name The edit mode
1365 */
1366 public static Mode getMode(String name)
1367 {
1368 return ModeProvider.instance.getMode(name);
1369 } //}}}
1370
1371 //{{{ getModes() method
1372 /**
1373 * Returns an array of installed edit modes.
1374 */
1375 public static Mode[] getModes()
1376 {
1377 return ModeProvider.instance.getModes();
1378 } //}}}
1379
1380 //}}}
1381
1382 //{{{ Buffer creation methods
1383
1384 //{{{ openFiles() method
1385 /**
1386 * Opens the file names specified in the argument array. This
1387 * handles +line and +marker arguments just like the command
1388 * line parser.
1389 * @param parent The parent directory
1390 * @param args The file names to open
1391 * @since jEdit 3.2pre4
1392 */
1393 public static Buffer openFiles(View view, String parent, String[] args)
1394 {
1395 Buffer retVal = null;
1396 Buffer lastBuffer = null;
1397
1398 for(int i = 0; i < args.length; i++)
1399 {
1400 String arg = args[i];
1401 if(arg == null)
1402 continue;
1403 else if(arg.startsWith("+line:") || arg.startsWith("+marker:"))
1404 {
1405 if(lastBuffer != null)
1406 gotoMarker(view,lastBuffer,arg);
1407 continue;
1408 }
1409
1410 lastBuffer = openFile((View)null,parent,arg,false,null);
1411
1412 if(retVal == null && lastBuffer != null)
1413 retVal = lastBuffer;
1414 }
1415
1416 if(view != null && retVal != null)
1417 view.setBuffer(retVal,true);
1418
1419 return retVal;
1420 } //}}}
1421
1422 //{{{ openFile() methods
1423 /**
1424 * Opens a file, either immediately if the application is finished starting up,
1425 * or after the first view has been created if not.
1426 * @param path The file path
1427 *
1428 * @return the buffer if succesfully loaded immediately, or null otherwise
1429 *
1430 * @since jEdit 4.5pre1
1431 */
1432 public static Buffer openFileAfterStartup(String path)
1433 {
1434 if (isStartupDone())
1435 {
1436 return openFile(getActiveView(), path);
1437 }
1438 else
1439 {
1440 // These additional file names will be treated just as if they had
1441 // been passed on the command line
1442 additionalFiles.add(path);
1443 return null;
1444 }
1445 }
1446
1447 /**
1448 * Opens a file. Note that as of jEdit 2.5pre1, this may return
1449 * null if the buffer could not be opened.
1450 * @param view The view to open the file in
1451 * @param path The file path
1452 *
1453 * @return the buffer, or null if jEdit was unable to load it
1454 *
1455 * @since jEdit 2.4pre1
1456 */
1457 public static Buffer openFile(View view, String path)
1458 {
1459 return openFile(view,null,path,false,new Hashtable());
1460 }
1461
1462 /**
1463 * Opens a file. This may return null if the buffer could not be
1464 * opened for some reason.
1465 * @param view The view to open the file in. If it is null, the file
1466 * will be opened and added to the bufferSet of the current edit pane,
1467 * but not selected
1468 * @param parent The parent directory of the file
1469 * @param path The path name of the file
1470 * @param newFile True if the file should not be loaded from disk
1471 * be prompted if it should be reloaded
1472 * @param props Buffer-local properties to set in the buffer
1473 *
1474 * @return the buffer, or null if jEdit was unable to load it
1475 *
1476 * @since jEdit 3.2pre10
1477 */
1478 public static Buffer openFile(View view, String parent,
1479 String path, boolean newFile, Hashtable props)
1480 {
1481 return openFile(view == null ? null : view.getEditPane(), parent, path, newFile, props);
1482 }
1483
1484 /**
1485 * Opens a file. Note that as of jEdit 2.5pre1, this may return
1486 * null if the buffer could not be opened.
1487 * @param editPane the EditPane to open the file in.
1488 * @param path The file path
1489 *
1490 * @return the buffer, or null if jEdit was unable to load it
1491 *
1492 * @since jEdit 4.3pre17
1493 */
1494 public static Buffer openFile(EditPane editPane, String path)
1495 {
1496 return openFile(editPane,null,path,false,new Hashtable());
1497 }
1498
1499 /**
1500 * Opens a file. This may return null if the buffer could not be
1501 * opened for some reason.
1502 * @param editPane the EditPane to open the file in.
1503 * @param parent The parent directory of the file
1504 * @param path The path name of the file
1505 * @param newFile True if the file should not be loaded from disk
1506 * be prompted if it should be reloaded
1507 * @param props Buffer-local properties to set in the buffer
1508 *
1509 * @return the buffer, or null if jEdit was unable to load it
1510 *
1511 * @since jEdit 4.3pre17
1512 */
1513 public static Buffer openFile(EditPane editPane, String parent,
1514 String path, boolean newFile, Hashtable props)
1515 {
1516 PerspectiveManager.setPerspectiveDirty(true);
1517
1518 if(editPane != null && parent == null && editPane.getBuffer() != null)
1519 parent = editPane.getBuffer().getDirectory();
1520
1521 try
1522 {
1523 URL u = new URL(path);
1524 if ("file".equals(u.getProtocol()))
1525 path = URLDecoder.decode(u.getPath());
1526 }
1527 catch (MalformedURLException mue)
1528 {
1529 path = MiscUtilities.constructPath(parent,path);
1530 }
1531
1532
1533 if(props == null)
1534 props = new Hashtable();
1535 composeBufferPropsFromHistory(props, path);
1536
1537 Buffer newBuffer;
1538
1539 synchronized (editBusOrderingLock)
1540 {
1541 View view = editPane == null ? null : editPane.getView();
1542 synchronized(bufferListLock)
1543 {
1544 Buffer buffer = getBuffer(path);
1545 if(buffer != null)
1546 {
1547 if(editPane != null)
1548 editPane.setBuffer(buffer,true);
1549
1550 return buffer;
1551 }
1552
1553 newBuffer = new Buffer(path,newFile,false,props);
1554
1555 if(!newBuffer.load(view,false))
1556 return null;
1557 addBufferToList(newBuffer);
1558 if (editPane != null)
1559 bufferSetManager.addBuffer(editPane, newBuffer);
1560 else
1561 bufferSetManager.addBuffer(jEdit.getActiveView(), newBuffer);
1562 }
1563
1564 EditBus.send(new BufferUpdate(newBuffer,view,BufferUpdate.CREATED));
1565 }
1566
1567 if(editPane != null)
1568 editPane.setBuffer(newBuffer,true);
1569
1570 return newBuffer;
1571 } //}}}
1572
1573 //{{{ openTemporary() methods
1574 /**
1575 * Opens a temporary buffer. A temporary buffer is like a normal
1576 * buffer, except that an event is not fired, the the buffer is
1577 * not added to the buffers list.
1578 *
1579 * @param view The view to open the file in
1580 * @param parent The parent directory of the file
1581 * @param path The path name of the file
1582 * @param newFile True if the file should not be loaded from disk
1583 *
1584 * @return the buffer, or null if jEdit was unable to load it
1585 *
1586 * @since jEdit 3.2pre10
1587 */
1588 public static Buffer openTemporary(View view, String parent,
1589 String path, boolean newFile)
1590 {
1591 return openTemporary(view, parent, path, newFile, null);
1592 }
1593 /**
1594 * Opens a temporary buffer. A temporary buffer is like a normal
1595 * buffer, except that an event is not fired, the the buffer is
1596 * not added to the buffers list.
1597 *
1598 * @param view The view to open the file in
1599 * @param parent The parent directory of the file
1600 * @param path The path name of the file
1601 * @param newFile True if the file should not be loaded from disk
1602 * @param props Buffer-local properties to set in the buffer
1603 *
1604 * @return the buffer, or null if jEdit was unable to load it
1605 *
1606 * @since jEdit 4.3pre10
1607 */
1608 public static Buffer openTemporary(View view, String parent,
1609 String path, boolean newFile, Hashtable props)
1610 {
1611 if(view != null && parent == null)
1612 parent = view.getBuffer().getDirectory();
1613
1614 if(MiscUtilities.isURL(path))
1615 {
1616 if("file".equals(MiscUtilities.getProtocolOfURL(path)))
1617 path = path.substring(5);
1618 }
1619
1620 path = MiscUtilities.constructPath(parent,path);
1621
1622 if(props == null)
1623 props = new Hashtable();
1624 composeBufferPropsFromHistory(props, path);
1625
1626 synchronized(bufferListLock)
1627 {
1628 Buffer buffer = getBuffer(path);
1629 if(buffer != null)
1630 return buffer;
1631
1632 buffer = new Buffer(path,newFile,true,props);
1633 buffer.setBooleanProperty(Buffer.ENCODING_AUTODETECT, true);
1634 if(!buffer.load(view,false))
1635 return null;
1636 else
1637 return buffer;
1638 }
1639 } //}}}
1640
1641 //{{{ commitTemporary() method
1642 /**
1643 * Adds a temporary buffer to the buffer list. This must be done
1644 * before allowing the user to interact with the buffer in any
1645 * way.
1646 * @param buffer The buffer
1647 */
1648 public static void commitTemporary(Buffer buffer)
1649 {
1650 if(!buffer.isTemporary())
1651 return;
1652
1653 PerspectiveManager.setPerspectiveDirty(true);
1654
1655 addBufferToList(buffer);
1656 buffer.commitTemporary();
1657
1658 // send full range of events to avoid breaking plugins
1659 EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.CREATED));
1660 EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOAD_STARTED));
1661 EditBus.send(new BufferUpdate(buffer,null,BufferUpdate.LOADED));
1662 } //}}}
1663
1664 //{{{ newFile() methods
1665 /**
1666 * Creates a new `untitled' file.
1667 *
1668 * @param view The view to create the file in
1669 *
1670 * @return the new buffer
1671 */
1672 public static Buffer newFile(View view)
1673 {
1674 return newFile(view == null ? null : view.getEditPane());
1675 }
1676
1677 /**
1678 * Creates a new `untitled' file.
1679 * @param view The view to create the file in
1680 * @param dir The directory to create the file in
1681 *
1682 * @return the new buffer
1683 *
1684 * @since jEdit 3.1pre2
1685 */
1686 public static Buffer newFile(View view, String dir)
1687 {
1688 EditPane editPane = null;
1689 if (view != null)
1690 {
1691 editPane = view.getEditPane();
1692 }
1693 else
1694 {
1695 View v = getActiveView();
1696 if (v != null)
1697 {
1698 editPane = v.getEditPane();
1699 }
1700 }
1701 return newFile(editPane, dir);
1702 }
1703
1704 /**
1705 * Creates a new `untitled' file.
1706 *
1707 * @param editPane The editPane to create the file in
1708 *
1709 * @return the new buffer
1710 * @since jEdit 4.3pre17
1711 */
1712 public static Buffer newFile(EditPane editPane)
1713 {
1714 String path;
1715
1716 if(editPane != null && editPane.getBuffer() != null)
1717 {
1718 path = editPane.getBuffer().getDirectory();
1719 VFS vfs = VFSManager.getVFSForPath(path);
1720 // don't want 'New File' to create a read only buffer
1721 // if current file is on SQL VFS or something
1722 if((vfs.getCapabilities() & VFS.WRITE_CAP) == 0)
1723 path = System.getProperty("user.home");
1724 }
1725 else
1726 path = null;
1727
1728 return newFile(editPane,path);
1729 }
1730
1731 /**
1732 * Creates a new `untitled' file.
1733 *
1734 * @param editPane The editPane to create the file in
1735 * @param dir The directory to create the file in
1736 *
1737 * @return the new buffer
1738 *
1739 * @since jEdit 4.3pre17
1740 */
1741 public static Buffer newFile(EditPane editPane, String dir)
1742 {
1743 if (editPane != null)
1744 {
1745 BufferSet bufferSet = editPane.getBufferSet();
1746 Buffer[] buffers = bufferSet.getAllBuffers();
1747 for (Buffer buf:buffers)
1748 {
1749 if (buf.isUntitled() && !buf.isDirty())
1750 {
1751
1752 if (!MiscUtilities.getParentOfPath(buf.getPath()).equals(dir))
1753 {
1754 // Find the highest Untitled-n file
1755 int untitledCount = getNextUntitledBufferId();
1756
1757 Buffer newBuffer = openFile(editPane,dir,"Untitled-" + untitledCount,true,null);
1758 jEdit.closeBuffer(editPane, buf);
1759 return newBuffer;
1760 }
1761 /* if "never mark untitled buffers dirty"
1762 * is selected, we might have contents in non-dirty
1763 * untitled buffers. We must clear those contents
1764 * if user requested new file.
1765 */
1766 int l = buf.getLength();
1767 if (l > 0)
1768 buf.remove(0, l);
1769 editPane.setBuffer(buf);
1770 return buf;
1771 }
1772 }
1773 }
1774
1775 // Find the highest Untitled-n file
1776 int untitledCount = getNextUntitledBufferId();
1777
1778 return openFile(editPane,dir,"Untitled-" + untitledCount,true,null);
1779 } //}}}
1780
1781 //}}}
1782
1783 //{{{ Buffer management methods
1784
1785 //{{{ closeBuffer() method
1786 /**
1787 * Closes a buffer. If there are unsaved changes, the user is
1788 * prompted if they should be saved first.
1789 * @param view The view
1790 * @param buffer The buffer
1791 * @return True if the buffer was really closed, false otherwise
1792 */
1793 public static boolean closeBuffer(View view, Buffer buffer)
1794 {
1795 // Wait for pending I/O requests
1796 if(buffer.isPerformingIO())
1797 {
1798 VFSManager.waitForRequests();
1799 if(VFSManager.errorOccurred())
1800 return false;
1801 }
1802
1803 if(buffer.isDirty())
1804 {
1805 Object[] args = { buffer.getName() };
1806 int result = GUIUtilities.confirm(view,"notsaved",args,
1807 JOptionPane.YES_NO_CANCEL_OPTION,
1808 JOptionPane.WARNING_MESSAGE);
1809 if(result == JOptionPane.YES_OPTION)
1810 {
1811 if(!buffer.save(view,null,true))
1812 return false;
1813
1814 VFSManager.waitForRequests();
1815 if(buffer.getBooleanProperty(BufferIORequest
1816 .ERROR_OCCURRED))
1817 {
1818 return false;
1819 }
1820 }
1821 else if(result != JOptionPane.NO_OPTION)
1822 return false;
1823 }
1824
1825 _closeBuffer(view,buffer);
1826
1827 return true;
1828 } //}}}
1829
1830 //{{{ closeBuffer() method
1831 /**
1832 * Close a buffer.
1833 * The buffer is first removed from the EditPane's bufferSet.
1834 * If the buffer is not in any bufferSet after that, it is closed
1835 * @param editPane the edit pane (it cannot be null)
1836 * @param buffer the buffer (it cannot be null)
1837 * @since jEdit 4.3pre15
1838 */
1839 public static void closeBuffer(EditPane editPane, Buffer buffer)
1840 {
1841 switch (bufferSetManager.getScope())
1842 {
1843 case global:
1844 closeBuffer(editPane.getView(), buffer);
1845 break;
1846 case view:
1847 View[] views = jEdit.getViews();
1848 int viewOwner = 0;
1849 for (View view : views)
1850 {
1851 BufferSet bufferSet = view.getEditPane().getBufferSet();
1852 // no need to check every bufferSet since it's view scope
1853 if (bufferSet.indexOf(buffer) != -1)
1854 {
1855 viewOwner++;
1856 if (viewOwner > 1)
1857 break;
1858 }
1859 }
1860 if (viewOwner > 1)
1861 {
1862 // the buffer is in several view, we can remove it from bufferSet
1863 bufferSetManager.removeBuffer(editPane, buffer);
1864 }
1865 else
1866 {
1867 closeBuffer(editPane.getView(), buffer);
1868 }
1869 break;
1870 case editpane:
1871 int bufferSetsCount = bufferSetManager.countBufferSets(buffer);
1872 if (bufferSetsCount < 2)
1873 {
1874 closeBuffer(editPane.getView(), buffer);
1875 }
1876 else
1877 {
1878 bufferSetManager.removeBuffer(editPane, buffer);
1879 }
1880 break;
1881 }
1882 } //}}}
1883
1884 //{{{ _closeBuffer() method
1885 /**
1886 * Closes the buffer, even if it has unsaved changes.
1887 * @param view The view, may be null
1888 * @param buffer The buffer
1889 *
1890 * @exception NullPointerException if the buffer is null
1891 *
1892 * @since jEdit 2.2pre1
1893 */
1894 public static void _closeBuffer(View view, Buffer buffer)
1895 {
1896 if(buffer.isClosed())
1897 {
1898 // can happen if the user presses C+w twice real
1899 // quick and the buffer has unsaved changes
1900 return;
1901 }
1902
1903 PerspectiveManager.setPerspectiveDirty(true);
1904
1905 if(!buffer.isNewFile())
1906 {
1907 if(view != null)
1908 view.getEditPane().saveCaretInfo();
1909 Integer _caret = (Integer)buffer.getProperty(Buffer.CARET);
1910 int caret = _caret == null ? 0 : _caret.intValue();
1911
1912 BufferHistory.setEntry(buffer.getPath(),caret,
1913 (Selection[])buffer.getProperty(Buffer.SELECTION),
1914 buffer.getStringProperty(JEditBuffer.ENCODING),
1915 buffer.getMode().getName());
1916 }
1917
1918 String path = buffer.getSymlinkPath();
1919 if((VFSManager.getVFSForPath(path).getCapabilities()
1920 & VFS.CASE_INSENSITIVE_CAP) != 0)
1921 {
1922 path = path.toLowerCase();
1923 }
1924 EditBus.send(new BufferUpdate(buffer,view,BufferUpdate.CLOSING));
1925 bufferHash.remove(path);
1926 removeBufferFromLis…
Large files files are truncated, but you can click here to view the full file