[sikuli] 215/385: more on multi scripting support

Gilles Filippini pini at moszumanska.debian.org
Sun Jun 29 19:26:15 UTC 2014


This is an automated email from the git hooks/post-receive script.

pini pushed a commit to tag upstream/1.1.0_beta1
in repository sikuli.

commit f934483b0871d05ff575da5a589183642497e751
Author: Raimund Hocke <info at its-me-raiman.de>
Date:   Sun Feb 16 14:41:31 2014 +0100

    more on multi scripting support
---
 API/src/main/java/org/sikuli/script/Region.java    |   42 +-
 .../main/java/org/sikuli/basics/IDESupport.java    |    4 +
 .../java/org/sikuli/basics/IndentationLogic.java   |   10 +
 Basics/src/main/resources/Lib/sikuli/Region.py     |   15 +-
 .../main/java/org/sikuli/ide/ButtonGenCommand.java |    2 +-
 .../java/org/sikuli/ide/EditorLineNumberView.java  |    2 +-
 IDE/src/main/java/org/sikuli/ide/EditorPane.java   | 2052 ++++-----
 .../ide/{EditorKit.java => SikuliEditorKit.java}   |   11 +-
 IDE/src/main/java/org/sikuli/ide/SikuliIDE.java    | 4609 ++++++++++----------
 .../org/sikuli/idesupport/JRubyIDESupport.java     |   11 +
 .../org/sikuli/idesupport/JythonIDESupport.java    |    8 +-
 .../org/sikuli/idesupport/PythonIndentation.java   |   47 +-
 12 files changed, 3453 insertions(+), 3360 deletions(-)

diff --git a/API/src/main/java/org/sikuli/script/Region.java b/API/src/main/java/org/sikuli/script/Region.java
index c48fd7d..592192f 100755
--- a/API/src/main/java/org/sikuli/script/Region.java
+++ b/API/src/main/java/org/sikuli/script/Region.java
@@ -155,7 +155,7 @@ public class Region {
   }
 
   //<editor-fold defaultstate="collapsed" desc="OFF: Specials for scripting environment">
-  /* 
+  /*
    public Object __enter__() {
    Debug.error("Region: with(__enter__): Trying to make it a Jython Region for with: usage");
    IScriptRunner runner = Settings.getScriptRunner("jython", null, null);
@@ -2472,12 +2472,28 @@ public class Region {
   }
 
   public <PSI> String onAppear(PSI target, Object observer) {
+		return onAppearDo(target, observer);
+	}
+
+  public <PSI> String onAppearJ(PSI target, Object observer) {
+		return onAppearDo(target, observer);
+	}
+
+  public <PSI> String onAppearDo(PSI target, Object observer) {
     String name = Observer.add(this, (ObserverCallBack) observer, SikuliEvent.Type.APPEAR);
     getEventManager().addAppearObserver(target, (SikuliEventObserver) observer, name);
     return name;
   }
 
   public <PSI> String onVanish(PSI target, Object observer) {
+		return onVanishDo(target, observer);
+	}
+
+  public <PSI> String onVanishJ(PSI target, Object observer) {
+		return onVanishDo(target, observer);
+	}
+
+  public <PSI> String onVanishDo(PSI target, Object observer) {
     String name = Observer.add(this, (ObserverCallBack) observer, SikuliEvent.Type.VANISH);
     getEventManager().addVanishObserver(target, (SikuliEventObserver) observer, name);
     return name;
@@ -2491,12 +2507,6 @@ public class Region {
     return onChangeDo(rows, observer);
   }
 
-  public String onChangeDo(int threshold, Object observer) {
-    String name = Observer.add(this, (ObserverCallBack) observer, SikuliEvent.Type.CHANGE);
-    getEventManager().addChangeObserver(threshold, (SikuliEventObserver) observer, name);
-    return name;
-  }
-
   public String onChangeJ(int minSize, Object observer) {
     if (minSize == 0) {
       return onChangeDo(Settings.ObserveMinChangedPixels, observer);
@@ -2505,12 +2515,10 @@ public class Region {
     }
   }
 
-  public void observeJ(double secs, boolean bg) {
-    if (bg) {
-      observeInBackground(secs);
-    } else {
-      observeDo(secs);
-    }
+  public String onChangeDo(int threshold, Object observer) {
+    String name = Observer.add(this, (ObserverCallBack) observer, SikuliEvent.Type.CHANGE);
+    getEventManager().addChangeObserver(threshold, (SikuliEventObserver) observer, name);
+    return name;
   }
 
   public void observe() {
@@ -2521,6 +2529,14 @@ public class Region {
     return observeDo(secs);
   }
 
+  public void observeJ(double secs, boolean bg) {
+    if (bg) {
+      observeInBackground(secs);
+    } else {
+      observeDo(secs);
+    }
+  }
+
   public boolean observeDo(double secs) {
     if (evtMgr == null) {
       Debug.error("Region: observe: Nothing to observe (Region might be invalid): " + this.toStringShort());
diff --git a/Basics/src/main/java/org/sikuli/basics/IDESupport.java b/Basics/src/main/java/org/sikuli/basics/IDESupport.java
index c655b48..6518caf 100644
--- a/Basics/src/main/java/org/sikuli/basics/IDESupport.java
+++ b/Basics/src/main/java/org/sikuli/basics/IDESupport.java
@@ -2,4 +2,8 @@ package org.sikuli.basics;
 
 public interface IDESupport {
 
+	public String[] getEndings();
+
+	public IndentationLogic getIndentationLogic();
+
 }
diff --git a/Basics/src/main/java/org/sikuli/basics/IndentationLogic.java b/Basics/src/main/java/org/sikuli/basics/IndentationLogic.java
index a9f8a23..3d00ff5 100644
--- a/Basics/src/main/java/org/sikuli/basics/IndentationLogic.java
+++ b/Basics/src/main/java/org/sikuli/basics/IndentationLogic.java
@@ -5,6 +5,9 @@
  */
 package org.sikuli.basics;
 
+import javax.swing.text.BadLocationException;
+import javax.swing.text.StyledDocument;
+
 /**
  *
  * @author rhocke
@@ -28,4 +31,11 @@ public interface IndentationLogic {
 	public void reset();
 
 	public void addText(String text);
+
+  public String getLeadingWhitespace(String text) ;
+
+  public String getLeadingWhitespace(StyledDocument doc, int head, int len) throws BadLocationException;
+
+  public int atEndOfLine(StyledDocument doc, int cpos, int start, String s, int sLen);
+
 }
diff --git a/Basics/src/main/resources/Lib/sikuli/Region.py b/Basics/src/main/resources/Lib/sikuli/Region.py
index 9cccb3f..cacd093 100755
--- a/Basics/src/main/resources/Lib/sikuli/Region.py
+++ b/Basics/src/main/resources/Lib/sikuli/Region.py
@@ -12,7 +12,7 @@ import inspect
 DEBUG=False
 
 class Region(JRegion):
-    
+
     # support for with:
     # override all global sikuli functions by this region's methods.
     def __enter__(self):
@@ -39,7 +39,7 @@ class Region(JRegion):
         dict = sys.modules['__main__'].__dict__
         for name in self._global_funcs.keys():
             dict[name] = self._global_funcs[name]
-            if DEBUG and name == 'checkWith': 
+            if DEBUG and name == 'checkWith':
                 print "with restore: %s"%(str(dict[name])[1:])
         self._global_funcs = None
 
@@ -62,17 +62,18 @@ class Region(JRegion):
         return JRegion.text(self).encode("utf8")
 
 # observe(): Special setup for Jython
+# assures, that in any case the same region object is used
     def onAppear(self, target, handler):
         class AnonyObserver(ObserverCallBack):
             def targetAppeared(self, event):
                 handler(event)
-        return JRegion.onAppear(self, target, AnonyObserver())
-    
+        return self.onAppearJ(self, target, AnonyObserver())
+
     def onVanish(self, target, handler):
         class AnonyObserver(ObserverCallBack):
             def targetVanished(self, event):
                 handler(event)
-        return JRegion.onVanish(self, target, AnonyObserver())
+        return self.onVanishJ(self, target, AnonyObserver())
 
     def onChange(self, arg1, arg2=None):
         if isinstance(arg1, int):
@@ -83,12 +84,10 @@ class Region(JRegion):
                 raise Exception("onChange: Invalid parameters set")
             min_size = 0
             handler = arg1
-        
         class AnonyObserver(ObserverCallBack):
             def targetChanged(self, event):
                 handler(event)
-                
         return self.onChangeJ(min_size, AnonyObserver())
-    
+
     def observe(self, time=FOREVER, background=False):
         self.observeJ(time, background)
\ No newline at end of file
diff --git a/IDE/src/main/java/org/sikuli/ide/ButtonGenCommand.java b/IDE/src/main/java/org/sikuli/ide/ButtonGenCommand.java
index 3fa14d0..d962a83 100755
--- a/IDE/src/main/java/org/sikuli/ide/ButtonGenCommand.java
+++ b/IDE/src/main/java/org/sikuli/ide/ButtonGenCommand.java
@@ -156,7 +156,7 @@ public class ButtonGenCommand extends JButton implements ActionListener,
       }
     }
     pane.insertString(")");
-    (new EditorKit.InsertBreakAction()).insertBreak(pane);
+    (new SikuliEditorKit.InsertBreakAction()).insertBreak(pane);
     if (endPos >= 0) {
       pane.requestFocus();
       pane.setCaretPosition(endPos);
diff --git a/IDE/src/main/java/org/sikuli/ide/EditorLineNumberView.java b/IDE/src/main/java/org/sikuli/ide/EditorLineNumberView.java
index bf1cd7a..f90cae8 100755
--- a/IDE/src/main/java/org/sikuli/ide/EditorLineNumberView.java
+++ b/IDE/src/main/java/org/sikuli/ide/EditorLineNumberView.java
@@ -205,7 +205,7 @@ public class EditorLineNumberView extends JComponent implements MouseListener {
         r = text.modelToView(l.getEndOffset() - 1);
       }
       h = (r.y - lastPos) + r.height;
-    } catch (BadLocationException ble) {
+    } catch (Exception ex) {
     }
     return h;
   }
diff --git a/IDE/src/main/java/org/sikuli/ide/EditorPane.java b/IDE/src/main/java/org/sikuli/ide/EditorPane.java
index dabe003..c454564 100755
--- a/IDE/src/main/java/org/sikuli/ide/EditorPane.java
+++ b/IDE/src/main/java/org/sikuli/ide/EditorPane.java
@@ -36,1060 +36,1068 @@ import org.sikuli.script.ImagePath;
 
 public class EditorPane extends JTextPane implements KeyListener, CaretListener {
 
-  private static final String me = "EditorPane: ";
-  private static TransferHandler transferHandler = null;
-  private PreferencesUser pref;
-  private File _editingFile;
+	private static final String me = "EditorPane: ";
+	private static TransferHandler transferHandler = null;
+	private PreferencesUser pref;
+	private File _editingFile;
 	private String editingType = null;
-  private String _srcBundlePath = null;
-  private boolean _srcBundleTemp = false;
-  private boolean _dirty = false;
-  private EditorCurrentLineHighlighter _highlighter;
-  private EditorUndoManager _undo = null;
-  private boolean hasErrorHighlight = false;
-  public boolean showThumbs;
-  // TODO: move to SikuliDocument ????
-  private IndentationLogic _indentationLogic = null;
-  static Pattern patPngStr = Pattern.compile("(\"[^\"]+?\\.(?i)(png|jpg)\")");
-  static Pattern patCaptureBtn = Pattern.compile("(\"__CLICK-TO-CAPTURE__\")");
-  static Pattern patPatternStr = Pattern.compile(
-          "\\b(Pattern\\s*\\(\".*?\"\\)(\\.\\w+\\([^)]*\\))+)");
-  static Pattern patRegionStr = Pattern.compile(
-          "\\b(Region\\s*\\([\\d\\s,]+\\))");
-  //TODO what is it for???
-  private int _caret_last_x = -1;
-  private boolean _can_update_caret_last_x = true;
-  private SikuliIDEPopUpMenu popMenuImage;
-  private SikuliIDE theIDE;
-  
-
-  //<editor-fold defaultstate="collapsed" desc="Initialization">
-  public EditorPane(SikuliIDE ide) {
-    theIDE = ide;
-    pref = PreferencesUser.getInstance();
-    showThumbs = !pref.getPrefMorePlainText();
-    initKeyMap();
-    if (transferHandler == null) {
-      transferHandler = new MyTransferHandler();
-    }
-    setTransferHandler(transferHandler);
-    _highlighter = new EditorCurrentLineHighlighter(this);
-    addCaretListener(_highlighter);
-    setFont(new Font(pref.getFontName(), Font.PLAIN, pref.getFontSize()));
-    setMargin(new Insets(3, 3, 3, 3));
-    setBackground(Color.WHITE);
-    if (!Settings.isMac()) {
-      setSelectionColor(new Color(170, 200, 255));
-    }
-    updateDocumentListeners();
-
-    initEditorPane();
-  }
-
-  private void initEditorPane() {
-    addKeyListener(this);
-    addCaretListener(this);
-    popMenuImage = new SikuliIDEPopUpMenu("POP_IMAGE", this);
-    if (!popMenuImage.isValidMenu()) {
-      popMenuImage = null;
-    }
-  }
+	private String _srcBundlePath = null;
+	private boolean _srcBundleTemp = false;
+	private boolean _dirty = false;
+	private EditorCurrentLineHighlighter _highlighter;
+	private EditorUndoManager _undo = null;
+	private boolean hasErrorHighlight = false;
+	public boolean showThumbs;
+	// TODO: move to SikuliDocument ????
+	private IndentationLogic _indentationLogic = null;
+	static Pattern patPngStr = Pattern.compile("(\"[^\"]+?\\.(?i)(png|jpg)\")");
+	static Pattern patCaptureBtn = Pattern.compile("(\"__CLICK-TO-CAPTURE__\")");
+	static Pattern patPatternStr = Pattern.compile(
+					"\\b(Pattern\\s*\\(\".*?\"\\)(\\.\\w+\\([^)]*\\))+)");
+	static Pattern patRegionStr = Pattern.compile(
+					"\\b(Region\\s*\\([\\d\\s,]+\\))");
+	//TODO what is it for???
+	private int _caret_last_x = -1;
+	private boolean _can_update_caret_last_x = true;
+	private SikuliIDEPopUpMenu popMenuImage;
+	private SikuliIDE theIDE;
+	private static Map<String, SikuliEditorKit> editorKits = new HashMap<String, SikuliEditorKit>();
+
+	//<editor-fold defaultstate="collapsed" desc="Initialization">
+	public EditorPane(SikuliIDE ide) {
+		theIDE = ide;
+		pref = PreferencesUser.getInstance();
+		showThumbs = !pref.getPrefMorePlainText();
+		initKeyMap();
+		if (transferHandler == null) {
+			transferHandler = new MyTransferHandler();
+		}
+		setTransferHandler(transferHandler);
+		_highlighter = new EditorCurrentLineHighlighter(this);
+		addCaretListener(_highlighter);
+		setFont(new Font(pref.getFontName(), Font.PLAIN, pref.getFontSize()));
+		setMargin(new Insets(3, 3, 3, 3));
+		setBackground(Color.WHITE);
+		if (!Settings.isMac()) {
+			setSelectionColor(new Color(170, 200, 255));
+		}
+		updateDocumentListeners();
+
+		initEditorPane();
+	}
+
+	private void initEditorPane() {
+		addKeyListener(this);
+		addCaretListener(this);
+		popMenuImage = new SikuliIDEPopUpMenu("POP_IMAGE", this);
+		if (!popMenuImage.isValidMenu()) {
+			popMenuImage = null;
+		}
+	}
 
 	public void initBeforeLoad(String scriptType) {
 		//TODO ask for scripttype on new pane
-    String scrType = null;
-		if (scriptType == null || "py".equals(scriptType)) {
+		String scrType = null;
+		if (scriptType == null) {
+			scriptType = "py";
+		}
+		if ("py".equals(scriptType)) {
 			scrType = "text/python";
-			_indentationLogic = JythonIDESupport.getIndentationLogic();
+			_indentationLogic = SikuliIDE.getIDESupport(scriptType).getIndentationLogic();
 			_indentationLogic.setTabWidth(pref.getTabWidth());
-			pref.addPreferenceChangeListener(new PreferenceChangeListener() {
-				@Override
-				public void preferenceChange(PreferenceChangeEvent event) {
-					if (event.getKey().equals("TAB_WIDTH")) {
-						_indentationLogic.setTabWidth(Integer.parseInt(event.getNewValue()));
-					}
-				}
-			});
 		} else if ("rb".equals(scriptType)) {
 			scrType = "text/ruby";
 		}
-    if (scrType != null) {
-      setEditorKitForContentType(scrType, new EditorKit(this));
-      setContentType(scrType);
-    }
-	}
-
-  public SikuliIDEPopUpMenu getPopMenuImage() {
-    return popMenuImage;
-  }
-
-  private void updateDocumentListeners() {
-    getDocument().addDocumentListener(new DirtyHandler());
-    getDocument().addUndoableEditListener(getUndoManager());
-  }
-
-  public EditorUndoManager getUndoManager() {
-    if (_undo == null) {
-      _undo = new EditorUndoManager();
-    }
-    return _undo;
-  }
-
-  public IndentationLogic getIndentationLogic() {
-    return _indentationLogic;
-  }
-
-  private void initKeyMap() {
-    InputMap map = this.getInputMap();
-    int shift = InputEvent.SHIFT_MASK;
-    int ctrl = InputEvent.CTRL_MASK;
-    map.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, shift), EditorKit.deIndentAction);
-    map.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, ctrl), EditorKit.deIndentAction);
-  }
-
-  @Override
-  public void keyPressed(java.awt.event.KeyEvent ke) {
-  }
-
-  @Override
-  public void keyReleased(java.awt.event.KeyEvent ke) {
-  }
-
-  @Override
-  public void keyTyped(java.awt.event.KeyEvent ke) {
-    //TODO implement code completion * checkCompletion(ke);
-  }
+		if (scrType != null) {
+			if (!editorKits.containsKey(scrType)) {
+				SikuliEditorKit ek = new SikuliEditorKit(this);
+				editorKits.put(scrType, ek);
+				setEditorKitForContentType(scrType, ek);
+			}
+			setEditorKit(editorKits.get(scrType));
+			setContentType(scrType);
+		}
+		pref.addPreferenceChangeListener(new PreferenceChangeListener() {
+			@Override
+			public void preferenceChange(PreferenceChangeEvent event) {
+				if (event.getKey().equals("TAB_WIDTH")) {
+					_indentationLogic.setTabWidth(Integer.parseInt(event.getNewValue()));
+				}
+			}
+		});
+		Debug.log(3, "InitTab: %s :--: %s", getContentType(), getEditorKit());
+	}
+
+	public SikuliIDEPopUpMenu getPopMenuImage() {
+		return popMenuImage;
+	}
+
+	private void updateDocumentListeners() {
+		getDocument().addDocumentListener(new DirtyHandler());
+		getDocument().addUndoableEditListener(getUndoManager());
+	}
+
+	public EditorUndoManager getUndoManager() {
+		if (_undo == null) {
+			_undo = new EditorUndoManager();
+		}
+		return _undo;
+	}
+
+	public IndentationLogic getIndentationLogic() {
+		return _indentationLogic;
+	}
+
+	private void initKeyMap() {
+		InputMap map = this.getInputMap();
+		int shift = InputEvent.SHIFT_MASK;
+		int ctrl = InputEvent.CTRL_MASK;
+		map.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, shift), SikuliEditorKit.deIndentAction);
+		map.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, ctrl), SikuliEditorKit.deIndentAction);
+	}
+
+	@Override
+	public void keyPressed(java.awt.event.KeyEvent ke) {
+	}
+
+	@Override
+	public void keyReleased(java.awt.event.KeyEvent ke) {
+	}
+
+	@Override
+	public void keyTyped(java.awt.event.KeyEvent ke) {
+		//TODO implement code completion * checkCompletion(ke);
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="file handling">
-  public String loadFile(boolean accessingAsFile) throws IOException {
-    File file = new SikuliIDEFileChooser(SikuliIDE.getInstance(), accessingAsFile).load();
-    if (file == null) {
-      return null;
-    }
-    String fname = FileManager.slashify(file.getAbsolutePath(), false);
-    SikuliIDE ide = SikuliIDE.getInstance();
-    int i = ide.isAlreadyOpen(fname);
-    if (i > -1) {
-      Debug.log(2, "Already open in IDE: " + fname);
-      return null;
-    }
-    loadFile(fname);
-    if (_editingFile == null) {
-      return null;
-    }
-    return fname;
-  }
-
-  public void loadFile(String filename) {
-    filename = FileManager.slashify(filename, false);
-    setSrcBundle(filename + "/");
-    File script = new File(filename);
-    _editingFile = FileManager.getScriptFile(script, null, null);
+	//<editor-fold defaultstate="collapsed" desc="file handling">
+	public String loadFile(boolean accessingAsFile) throws IOException {
+		File file = new SikuliIDEFileChooser(SikuliIDE.getInstance(), accessingAsFile).load();
+		if (file == null) {
+			return null;
+		}
+		String fname = FileManager.slashify(file.getAbsolutePath(), false);
+		SikuliIDE ide = SikuliIDE.getInstance();
+		int i = ide.isAlreadyOpen(fname);
+		if (i > -1) {
+			Debug.log(2, "Already open in IDE: " + fname);
+			return null;
+		}
+		loadFile(fname);
+		if (_editingFile == null) {
+			return null;
+		}
+		return fname;
+	}
+
+	public void loadFile(String filename) {
+		filename = FileManager.slashify(filename, false);
+		setSrcBundle(filename + "/");
+		File script = new File(filename);
+		_editingFile = FileManager.getScriptFile(script, null, null);
 		editingType = _editingFile.getAbsolutePath().substring(_editingFile.getAbsolutePath().lastIndexOf(".") + 1);
 		initBeforeLoad(editingType);
-    try {
-      this.read(new BufferedReader(new InputStreamReader(
-              new FileInputStream(_editingFile), "UTF8")), null);
-    } catch (Exception ex) {
-      _editingFile = null;
-    }
-    if (_editingFile != null) {
-      updateDocumentListeners();
-      setDirty(false);
-      _srcBundleTemp = false;
-    } else {
-      _srcBundlePath = null;
-    }
-  }
-
-  public boolean hasEditingFile() {
-    return _editingFile != null;
-  }
-
-  public String saveFile() throws IOException {
-    if (_editingFile == null) {
-      return saveAsFile(Settings.isMac());
-    } else {
-      ImagePath.remove(_srcBundlePath);
-      writeSrcFile();
-      return getCurrentShortFilename();
-    }
-  }
-
-  public String saveAsFile(boolean accessingAsFile) throws IOException {
-    File file = new SikuliIDEFileChooser(SikuliIDE.getInstance(), accessingAsFile).save();
-    if (file == null) {
-      return null;
-    }
-    String bundlePath = FileManager.slashify(file.getAbsolutePath(), false);
-    if (!file.getAbsolutePath().endsWith(".sikuli")) {
-      bundlePath += ".sikuli";
-    }
-    if (FileManager.exists(bundlePath)) {
-      int res = JOptionPane.showConfirmDialog(
-              null, SikuliIDEI18N._I("msgFileExists", bundlePath),
-              SikuliIDEI18N._I("dlgFileExists"), JOptionPane.YES_NO_OPTION);
-      if (res != JOptionPane.YES_OPTION) {
-        return null;
-      }
-    } else {
-      FileManager.mkdir(bundlePath);
-    }
-    try {
-      saveAsBundle(bundlePath, (SikuliIDE.getInstance().getCurrentFileTabTitle()));
-      if (Settings.isMac()) {
-        if (!Settings.handlesMacBundles) {
-          makeBundle(bundlePath, accessingAsFile);
-        }
-      }
-    } catch (IOException iOException) {
-    }
-    return getCurrentShortFilename();
-  }
-
-  private void makeBundle(String path, boolean asFile) {
-    String isBundle = asFile ? "B" : "b";
-    IResourceLoader loader = FileManager.getNativeLoader("basic", new String[0]);
-    String[] cmd = new String[] {"#SetFile", "-a", isBundle, path};
-    loader.doSomethingSpecial("runcmd", cmd);
-    if (!cmd[0].isEmpty()) {
-      Debug.error("makeBundle: return: " + cmd[0]);
-    }
-    if (asFile) {
-      if (! FileManager.writeStringToFile("/Applications/SikuliX-IDE.app",
-              (new File(path, ".LSOverride")).getAbsolutePath())) {
-        Debug.error("makeBundle: not possible: .LSOverride");
-      }
-    } else {
-      new File(path, ".LSOverride").delete();
-    }
-  }
-
-  private void saveAsBundle(String bundlePath, String current) throws IOException {
+		try {
+			this.read(new BufferedReader(new InputStreamReader(
+							new FileInputStream(_editingFile), "UTF8")), null);
+		} catch (Exception ex) {
+			_editingFile = null;
+		}
+		if (_editingFile != null) {
+			updateDocumentListeners();
+			setDirty(false);
+			_srcBundleTemp = false;
+		} else {
+			_srcBundlePath = null;
+		}
+	}
+
+	public boolean hasEditingFile() {
+		return _editingFile != null;
+	}
+
+	public String saveFile() throws IOException {
+		if (_editingFile == null) {
+			return saveAsFile(Settings.isMac());
+		} else {
+			ImagePath.remove(_srcBundlePath);
+			writeSrcFile();
+			return getCurrentShortFilename();
+		}
+	}
+
+	public String saveAsFile(boolean accessingAsFile) throws IOException {
+		File file = new SikuliIDEFileChooser(SikuliIDE.getInstance(), accessingAsFile).save();
+		if (file == null) {
+			return null;
+		}
+		String bundlePath = FileManager.slashify(file.getAbsolutePath(), false);
+		if (!file.getAbsolutePath().endsWith(".sikuli")) {
+			bundlePath += ".sikuli";
+		}
+		if (FileManager.exists(bundlePath)) {
+			int res = JOptionPane.showConfirmDialog(
+							null, SikuliIDEI18N._I("msgFileExists", bundlePath),
+							SikuliIDEI18N._I("dlgFileExists"), JOptionPane.YES_NO_OPTION);
+			if (res != JOptionPane.YES_OPTION) {
+				return null;
+			}
+		} else {
+			FileManager.mkdir(bundlePath);
+		}
+		try {
+			saveAsBundle(bundlePath, (SikuliIDE.getInstance().getCurrentFileTabTitle()));
+			if (Settings.isMac()) {
+				if (!Settings.handlesMacBundles) {
+					makeBundle(bundlePath, accessingAsFile);
+				}
+			}
+		} catch (IOException iOException) {
+		}
+		return getCurrentShortFilename();
+	}
+
+	private void makeBundle(String path, boolean asFile) {
+		String isBundle = asFile ? "B" : "b";
+		IResourceLoader loader = FileManager.getNativeLoader("basic", new String[0]);
+		String[] cmd = new String[]{"#SetFile", "-a", isBundle, path};
+		loader.doSomethingSpecial("runcmd", cmd);
+		if (!cmd[0].isEmpty()) {
+			Debug.error("makeBundle: return: " + cmd[0]);
+		}
+		if (asFile) {
+			if (!FileManager.writeStringToFile("/Applications/SikuliX-IDE.app",
+							(new File(path, ".LSOverride")).getAbsolutePath())) {
+				Debug.error("makeBundle: not possible: .LSOverride");
+			}
+		} else {
+			new File(path, ".LSOverride").delete();
+		}
+	}
+
+	private void saveAsBundle(String bundlePath, String current) throws IOException {
 //TODO allow other file types
-    bundlePath = FileManager.slashify(bundlePath, true);
-    if (_srcBundlePath != null) {
-      FileManager.xcopy(_srcBundlePath, bundlePath, current);
-    }
-    if (_srcBundleTemp) {
-      FileManager.deleteTempDir(_srcBundlePath);
-      _srcBundleTemp = false;
-    }
-    ImagePath.remove(_srcBundlePath);
-    setSrcBundle(bundlePath);
-    _editingFile = createSourceFile(bundlePath, ".py");
-    Debug.log(2, "save to bundle: " + getSrcBundle());
-    writeSrcFile();
-    reparse();
-  }
-
-  private File createSourceFile(String bundlePath, String ext) {
-    if (ext != null) {
-      String name = new File(bundlePath).getName();
-      name = name.substring(0, name.lastIndexOf("."));
-      return new File(bundlePath, name + ext);
-    } else {
-      return new File(bundlePath);
-    }
-  }
-
-  private void writeSrcFile() throws IOException {
-    writeFile(_editingFile.getAbsolutePath());
-    if (PreferencesUser.getInstance().getAtSaveMakeHTML()) {
-      convertSrcToHtml(getSrcBundle());
-    } else {
-      (new File(_editingFile.getAbsolutePath().replaceFirst("py", "html"))).delete();
-    }
-    if (PreferencesUser.getInstance().getAtSaveCleanBundle()) {
-      cleanBundle(getSrcBundle());
-    }
-    setDirty(false);
-  }
-
-  public String exportAsZip() throws IOException, FileNotFoundException {
-    File file = new SikuliIDEFileChooser(SikuliIDE.getInstance()).export();
-    if (file == null) {
-      return null;
-    }
-
-    String zipPath = file.getAbsolutePath();
-    String srcName = file.getName();
-    if (!file.getAbsolutePath().endsWith(".skl")) {
-      zipPath += ".skl";
-    } else {
-      srcName = srcName.substring(0, srcName.lastIndexOf('.'));
-    }
-    writeFile(getSrcBundle() + srcName + ".py");
-    FileManager.zip(getSrcBundle(), zipPath);
-    Debug.log(2, "export to executable file: " + zipPath);
-    return zipPath;
-  }
-
-  private void writeFile(String filename) throws IOException {
-    this.write(new BufferedWriter(new OutputStreamWriter(
-            new FileOutputStream(filename), "UTF8")));
-  }
-
-  public boolean close() throws IOException {
-    if (isDirty()) {
-      Object[] options = {SikuliIDEI18N._I("yes"), SikuliIDEI18N._I("no"), SikuliIDEI18N._I("cancel")};
-      int ans = JOptionPane.showOptionDialog(this,
-              SikuliIDEI18N._I("msgAskSaveChanges", getCurrentShortFilename()),
-              SikuliIDEI18N._I("dlgAskCloseTab"),
-              JOptionPane.YES_NO_CANCEL_OPTION,
-              JOptionPane.WARNING_MESSAGE,
-              null,
-              options, options[0]);
-      if (ans == JOptionPane.CANCEL_OPTION
-              || ans == JOptionPane.CLOSED_OPTION) {
-        return false;
-      } else if (ans == JOptionPane.YES_OPTION) {
-        if (saveFile() == null) {
-          return false;
-        }
-      } else {
-        SikuliIDE.getInstance().getTabPane().resetLastClosed();
-      }
-      if (_srcBundleTemp) {
-        FileManager.deleteTempDir(_srcBundlePath);
-      }
-      setDirty(false);
-    }
-    if (_srcBundlePath != null) {
-      ImagePath.remove(_srcBundlePath);
-    }
-    return true;
-  }
-
-  private void setSrcBundle(String newBundlePath) {
-    _srcBundlePath = newBundlePath;
-    ImagePath.setBundlePath(_srcBundlePath);
-  }
-
-  public String getSrcBundle() {
-    if (_srcBundlePath == null) {
-      File tmp = FileManager.createTempDir();
-      setSrcBundle(FileManager.slashify(tmp.getAbsolutePath(), true));
-      _srcBundleTemp = true;
-    }
-    return _srcBundlePath;
-  }
-
-  public boolean isSourceBundleTemp() {
-    return _srcBundleTemp;
-  }
-
-  public String getCurrentSrcDir() {
-    if(_srcBundlePath != null) {
-      if (_editingFile == null || _srcBundleTemp) {
-        return null;
-      } else {
-        return _editingFile.getParent();
-      }
-    } else {
-      return null;
-    }
-  }
-
-  private String getCurrentShortFilename() {
-    if (_srcBundlePath != null) {
-      File f = new File(_srcBundlePath);
-      return f.getName();
-    }
-    return "Untitled";
-  }
-
-  public File getCurrentFile() {
-    return getCurrentFile(true);
-  }
-
-  public File getCurrentFile(boolean shouldSave) {
-    if (shouldSave && _editingFile == null && isDirty()) {
-      try {
-        saveAsFile(Settings.isMac());
-      } catch (IOException e) {
-        Debug.error(me + "getCurrentFile: Problem while trying to save %s\n%s",
-                _editingFile.getAbsolutePath(), e.getMessage());
-      }
-    }
-    return _editingFile;
-  }
-
-  public String getCurrentFilename() {
-    if (_editingFile == null) {
-      return null;
-    }
-    return _editingFile.getAbsolutePath();
-  }
-
-  private void convertSrcToHtml(String bundle) {
-    SikuliX.getScriptRunner("jython", null, null).doSomethingSpecial("convertSrcToHtml",
-            new String[]{bundle});
-  }
-
-  private void cleanBundle(String bundle) {
-    if (!PreferencesUser.getInstance().getAtSaveCleanBundle()) {
-      return;
-    }
-    SikuliX.getScriptRunner("jython", null, null).doSomethingSpecial("cleanBundle",
-            new String[]{bundle});
-  }
-
-  public File copyFileToBundle(String filename) {
-    File f = new File(filename);
-    String bundlePath = getSrcBundle();
-    if (f.exists()) {
-      try {
-        File newFile = FileManager.smartCopy(filename, bundlePath);
-        return newFile;
-      } catch (IOException e) {
-        Debug.error(me + "copyFileToBundle: Problem while trying to save %s\n%s",
-                filename, e.getMessage());
-        return f;
-      }
-    }
-    return null;
-  }
-
-  public File getFileInBundle(String filename) {
-      String fullpath = Image.create(filename).getFilename();
-      if (fullpath != null) {
-        return new File(fullpath);
-      }
-      return null;
-  }
-
-  public Image getImageInBundle(String filename) {
-      return Image.createThumbNail(filename);
-  }
+		bundlePath = FileManager.slashify(bundlePath, true);
+		if (_srcBundlePath != null) {
+			FileManager.xcopy(_srcBundlePath, bundlePath, current);
+		}
+		if (_srcBundleTemp) {
+			FileManager.deleteTempDir(_srcBundlePath);
+			_srcBundleTemp = false;
+		}
+		ImagePath.remove(_srcBundlePath);
+		setSrcBundle(bundlePath);
+		_editingFile = createSourceFile(bundlePath, ".py");
+		Debug.log(2, "save to bundle: " + getSrcBundle());
+		writeSrcFile();
+		reparse();
+	}
 
-//</editor-fold>
+	private File createSourceFile(String bundlePath, String ext) {
+		if (ext != null) {
+			String name = new File(bundlePath).getName();
+			name = name.substring(0, name.lastIndexOf("."));
+			return new File(bundlePath, name + ext);
+		} else {
+			return new File(bundlePath);
+		}
+	}
 
-  //<editor-fold defaultstate="collapsed" desc="fill pane content">
-  @Override
-  public void read(Reader in, Object desc) throws IOException {
-    super.read(in, desc);
-    Document doc = getDocument();
-    Element root = doc.getDefaultRootElement();
-    parse(root);
-    setCaretPosition(0);
-  }
-  //</editor-fold>
+	private void writeSrcFile() throws IOException {
+		writeFile(_editingFile.getAbsolutePath());
+		if (PreferencesUser.getInstance().getAtSaveMakeHTML()) {
+			convertSrcToHtml(getSrcBundle());
+		} else {
+			(new File(_editingFile.getAbsolutePath().replaceFirst("py", "html"))).delete();
+		}
+		if (PreferencesUser.getInstance().getAtSaveCleanBundle()) {
+			cleanBundle(getSrcBundle());
+		}
+		setDirty(false);
+	}
+
+	public String exportAsZip() throws IOException, FileNotFoundException {
+		File file = new SikuliIDEFileChooser(SikuliIDE.getInstance()).export();
+		if (file == null) {
+			return null;
+		}
+
+		String zipPath = file.getAbsolutePath();
+		String srcName = file.getName();
+		if (!file.getAbsolutePath().endsWith(".skl")) {
+			zipPath += ".skl";
+		} else {
+			srcName = srcName.substring(0, srcName.lastIndexOf('.'));
+		}
+		writeFile(getSrcBundle() + srcName + ".py");
+		FileManager.zip(getSrcBundle(), zipPath);
+		Debug.log(2, "export to executable file: " + zipPath);
+		return zipPath;
+	}
+
+	private void writeFile(String filename) throws IOException {
+		this.write(new BufferedWriter(new OutputStreamWriter(
+						new FileOutputStream(filename), "UTF8")));
+	}
+
+	public boolean close() throws IOException {
+		if (isDirty()) {
+			Object[] options = {SikuliIDEI18N._I("yes"), SikuliIDEI18N._I("no"), SikuliIDEI18N._I("cancel")};
+			int ans = JOptionPane.showOptionDialog(this,
+							SikuliIDEI18N._I("msgAskSaveChanges", getCurrentShortFilename()),
+							SikuliIDEI18N._I("dlgAskCloseTab"),
+							JOptionPane.YES_NO_CANCEL_OPTION,
+							JOptionPane.WARNING_MESSAGE,
+							null,
+							options, options[0]);
+			if (ans == JOptionPane.CANCEL_OPTION
+							|| ans == JOptionPane.CLOSED_OPTION) {
+				return false;
+			} else if (ans == JOptionPane.YES_OPTION) {
+				if (saveFile() == null) {
+					return false;
+				}
+			} else {
+				SikuliIDE.getInstance().getTabPane().resetLastClosed();
+			}
+			if (_srcBundleTemp) {
+				FileManager.deleteTempDir(_srcBundlePath);
+			}
+			setDirty(false);
+		}
+		if (_srcBundlePath != null) {
+			ImagePath.remove(_srcBundlePath);
+		}
+		return true;
+	}
+
+	private void setSrcBundle(String newBundlePath) {
+		_srcBundlePath = newBundlePath;
+		ImagePath.setBundlePath(_srcBundlePath);
+	}
 
-  //<editor-fold defaultstate="collapsed" desc="Dirty handling">
-  public boolean isDirty() {
-    return _dirty;
-  }
-
-  public void setDirty(boolean flag) {
-    if (_dirty == flag) {
-      return;
-    }
-    _dirty = flag;
-    //<editor-fold defaultstate="collapsed" desc="RaiMan no global dirty">
-    if (flag) {
-      //RaiManMod getRootPane().putClientProperty("Window.documentModified", true);
-    } else {
-      //SikuliIDE.getInstance().checkDirtyPanes();
-    }
-    //</editor-fold>
-    SikuliIDE.getInstance().setCurrentFileTabTitleDirty(_dirty);
-  }
-
-  private class DirtyHandler implements DocumentListener {
-
-    @Override
-    public void changedUpdate(DocumentEvent ev) {
-      Debug.log(9, "change update");
-      //setDirty(true);
-    }
-
-    @Override
-    public void insertUpdate(DocumentEvent ev) {
-      Debug.log(9, "insert update");
-      setDirty(true);
-    }
-
-    @Override
-    public void removeUpdate(DocumentEvent ev) {
-      Debug.log(9, "remove update");
-      setDirty(true);
-    }
-  }
+	public String getSrcBundle() {
+		if (_srcBundlePath == null) {
+			File tmp = FileManager.createTempDir();
+			setSrcBundle(FileManager.slashify(tmp.getAbsolutePath(), true));
+			_srcBundleTemp = true;
+		}
+		return _srcBundlePath;
+	}
+
+	public boolean isSourceBundleTemp() {
+		return _srcBundleTemp;
+	}
 
+	public String getCurrentSrcDir() {
+		if (_srcBundlePath != null) {
+			if (_editingFile == null || _srcBundleTemp) {
+				return null;
+			} else {
+				return _editingFile.getParent();
+			}
+		} else {
+			return null;
+		}
+	}
+
+	private String getCurrentShortFilename() {
+		if (_srcBundlePath != null) {
+			File f = new File(_srcBundlePath);
+			return f.getName();
+		}
+		return "Untitled";
+	}
+
+	public File getCurrentFile() {
+		return getCurrentFile(true);
+	}
+
+	public File getCurrentFile(boolean shouldSave) {
+		if (shouldSave && _editingFile == null && isDirty()) {
+			try {
+				saveAsFile(Settings.isMac());
+			} catch (IOException e) {
+				Debug.error(me + "getCurrentFile: Problem while trying to save %s\n%s",
+								_editingFile.getAbsolutePath(), e.getMessage());
+			}
+		}
+		return _editingFile;
+	}
+
+	public String getCurrentFilename() {
+		if (_editingFile == null) {
+			return null;
+		}
+		return _editingFile.getAbsolutePath();
+	}
+
+	private void convertSrcToHtml(String bundle) {
+		SikuliX.getScriptRunner("jython", null, null).doSomethingSpecial("convertSrcToHtml",
+						new String[]{bundle});
+	}
+
+	private void cleanBundle(String bundle) {
+		if (!PreferencesUser.getInstance().getAtSaveCleanBundle()) {
+			return;
+		}
+		SikuliX.getScriptRunner("jython", null, null).doSomethingSpecial("cleanBundle",
+						new String[]{bundle});
+	}
+
+	public File copyFileToBundle(String filename) {
+		File f = new File(filename);
+		String bundlePath = getSrcBundle();
+		if (f.exists()) {
+			try {
+				File newFile = FileManager.smartCopy(filename, bundlePath);
+				return newFile;
+			} catch (IOException e) {
+				Debug.error(me + "copyFileToBundle: Problem while trying to save %s\n%s",
+								filename, e.getMessage());
+				return f;
+			}
+		}
+		return null;
+	}
+
+	public File getFileInBundle(String filename) {
+		String fullpath = Image.create(filename).getFilename();
+		if (fullpath != null) {
+			return new File(fullpath);
+		}
+		return null;
+	}
+
+	public Image getImageInBundle(String filename) {
+		return Image.createThumbNail(filename);
+	}
+
+//</editor-fold>
+	//<editor-fold defaultstate="collapsed" desc="fill pane content">
+	@Override
+	public void read(Reader in, Object desc) throws IOException {
+		super.read(in, desc);
+		Document doc = getDocument();
+		Element root = doc.getDefaultRootElement();
+		parse(root);
+		setCaretPosition(0);
+	}
   //</editor-fold>
-  //<editor-fold defaultstate="collapsed" desc="Caret handling">
+
+	//<editor-fold defaultstate="collapsed" desc="Dirty handling">
+	public boolean isDirty() {
+		return _dirty;
+	}
+
+	public void setDirty(boolean flag) {
+		if (_dirty == flag) {
+			return;
+		}
+		_dirty = flag;
+		//<editor-fold defaultstate="collapsed" desc="RaiMan no global dirty">
+		if (flag) {
+			//RaiManMod getRootPane().putClientProperty("Window.documentModified", true);
+		} else {
+			//SikuliIDE.getInstance().checkDirtyPanes();
+		}
+		//</editor-fold>
+		SikuliIDE.getInstance().setCurrentFileTabTitleDirty(_dirty);
+	}
+
+	private class DirtyHandler implements DocumentListener {
+
+		@Override
+		public void changedUpdate(DocumentEvent ev) {
+			Debug.log(9, "change update");
+			//setDirty(true);
+		}
+
+		@Override
+		public void insertUpdate(DocumentEvent ev) {
+			Debug.log(9, "insert update");
+			setDirty(true);
+		}
+
+		@Override
+		public void removeUpdate(DocumentEvent ev) {
+			Debug.log(9, "remove update");
+			setDirty(true);
+		}
+	}
+
+	//</editor-fold>
+	//<editor-fold defaultstate="collapsed" desc="Caret handling">
 //TODO not used
-  @Override
-  public void caretUpdate(CaretEvent evt) {
-    /* seems not to be used
-     * if (_can_update_caret_last_x) {
-     * _caret_last_x = -1;
-     * } else {
-     * _can_update_caret_last_x = true;
-     * }
-     */
-  }
-
-  public int getLineNumberAtCaret(int caretPosition) {
-    Element root = getDocument().getDefaultRootElement();
-    return root.getElementIndex(caretPosition) + 1;
-  }
-
-  public Element getLineAtCaret(int caretPosition) {
-    Element root = getDocument().getDefaultRootElement();
-    if (caretPosition == -1) {
-      return root.getElement(root.getElementIndex(getCaretPosition()));
-    } else {
-      return root.getElement(root.getElementIndex(root.getElementIndex(caretPosition)));
-    }
-  }
-
-  public Element getLineAtPoint(MouseEvent me) {
-    Point p = me.getLocationOnScreen();
-    Point pp = getLocationOnScreen();
-    p.translate(-pp.x, -pp.y);
-    int pos = viewToModel(p);
-    Element root = getDocument().getDefaultRootElement();
-    int e = root.getElementIndex(pos);
-    if (e == -1) {
-      return null;
-    }
-    return root.getElement(e);
-  }
-
-  public boolean jumpTo(int lineNo, int column) {
-    Debug.log(6, "jumpTo: " + lineNo + "," + column);
-    try {
-      int off = getLineStartOffset(lineNo - 1) + column - 1;
-      int lineCount = getDocument().getDefaultRootElement().getElementCount();
-      if (lineNo < lineCount) {
-        int nextLine = getLineStartOffset(lineNo);
-        if (off >= nextLine) {
-          off = nextLine - 1;
-        }
-      }
-      if (off >= 0) {
-        setCaretPosition(off);
-      }
-    } catch (BadLocationException ex) {
-      jumpTo(lineNo);
-      return false;
-    }
-    return true;
-  }
-
-  public boolean jumpTo(int lineNo) {
-    Debug.log(6, "jumpTo: " + lineNo);
-    try {
-      setCaretPosition(getLineStartOffset(lineNo - 1));
-    } catch (BadLocationException ex) {
-      return false;
-    }
-    return true;
-  }
-
-  public int getLineStartOffset(int line) throws BadLocationException {
-    // line starting from 0
-    Element map = getDocument().getDefaultRootElement();
-    if (line < 0) {
-      throw new BadLocationException("Negative line", -1);
-    } else if (line >= map.getElementCount()) {
-      throw new BadLocationException("No such line", getDocument().getLength() + 1);
-    } else {
-      Element lineElem = map.getElement(line);
-      return lineElem.getStartOffset();
-    }
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="TODO only used for UnitTest">
-  public void jumpTo(String funcName) throws BadLocationException {
-    Debug.log(6, "jumpTo: " + funcName);
-    Element root = getDocument().getDefaultRootElement();
-    int pos = getFunctionStartOffset(funcName, root);
-    if (pos >= 0) {
-      setCaretPosition(pos);
-    } else {
-      throw new BadLocationException("Can't find function " + funcName, -1);
-    }
-  }
-
-  private int getFunctionStartOffset(String func, Element node) throws BadLocationException {
-    Document doc = getDocument();
-    int count = node.getElementCount();
-    Pattern patDef = Pattern.compile("def\\s+" + func + "\\s*\\(");
-    for (int i = 0; i < count; i++) {
-      Element elm = node.getElement(i);
-      if (elm.isLeaf()) {
-        int start = elm.getStartOffset(), end = elm.getEndOffset();
-        String line = doc.getText(start, end - start);
-        Matcher matcher = patDef.matcher(line);
-        if (matcher.find()) {
-          return start;
-        }
-      } else {
-        int p = getFunctionStartOffset(func, elm);
-        if (p >= 0) {
-          return p;
-        }
-      }
-    }
-    return -1;
-  }
-  //</editor-fold>
+	@Override
+	public void caretUpdate(CaretEvent evt) {
+		/* seems not to be used
+		 * if (_can_update_caret_last_x) {
+		 * _caret_last_x = -1;
+		 * } else {
+		 * _can_update_caret_last_x = true;
+		 * }
+		 */
+	}
+
+	public int getLineNumberAtCaret(int caretPosition) {
+		Element root = getDocument().getDefaultRootElement();
+		return root.getElementIndex(caretPosition) + 1;
+	}
+
+	public Element getLineAtCaret(int caretPosition) {
+		Element root = getDocument().getDefaultRootElement();
+		if (caretPosition == -1) {
+			return root.getElement(root.getElementIndex(getCaretPosition()));
+		} else {
+			return root.getElement(root.getElementIndex(root.getElementIndex(caretPosition)));
+		}
+	}
+
+	public Element getLineAtPoint(MouseEvent me) {
+		Point p = me.getLocationOnScreen();
+		Point pp = getLocationOnScreen();
+		p.translate(-pp.x, -pp.y);
+		int pos = viewToModel(p);
+		Element root = getDocument().getDefaultRootElement();
+		int e = root.getElementIndex(pos);
+		if (e == -1) {
+			return null;
+		}
+		return root.getElement(e);
+	}
+
+	public boolean jumpTo(int lineNo, int column) {
+		Debug.log(6, "jumpTo: " + lineNo + "," + column);
+		try {
+			int off = getLineStartOffset(lineNo - 1) + column - 1;
+			int lineCount = getDocument().getDefaultRootElement().getElementCount();
+			if (lineNo < lineCount) {
+				int nextLine = getLineStartOffset(lineNo);
+				if (off >= nextLine) {
+					off = nextLine - 1;
+				}
+			}
+			if (off >= 0) {
+				setCaretPosition(off);
+			}
+		} catch (BadLocationException ex) {
+			jumpTo(lineNo);
+			return false;
+		}
+		return true;
+	}
+
+	public boolean jumpTo(int lineNo) {
+		Debug.log(6, "jumpTo: " + lineNo);
+		try {
+			setCaretPosition(getLineStartOffset(lineNo - 1));
+		} catch (BadLocationException ex) {
+			return false;
+		}
+		return true;
+	}
+
+	public int getLineStartOffset(int line) throws BadLocationException {
+		// line starting from 0
+		Element map = getDocument().getDefaultRootElement();
+		if (line < 0) {
+			throw new BadLocationException("Negative line", -1);
+		} else if (line >= map.getElementCount()) {
+			throw new BadLocationException("No such line", getDocument().getLength() + 1);
+		} else {
+			Element lineElem = map.getElement(line);
+			return lineElem.getStartOffset();
+		}
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="TODO only used for UnitTest">
+	public void jumpTo(String funcName) throws BadLocationException {
+		Debug.log(6, "jumpTo: " + funcName);
+		Element root = getDocument().getDefaultRootElement();
+		int pos = getFunctionStartOffset(funcName, root);
+		if (pos >= 0) {
+			setCaretPosition(pos);
+		} else {
+			throw new BadLocationException("Can't find function " + funcName, -1);
+		}
+	}
+
+	private int getFunctionStartOffset(String func, Element node) throws BadLocationException {
+		Document doc = getDocument();
+		int count = node.getElementCount();
+		Pattern patDef = Pattern.compile("def\\s+" + func + "\\s*\\(");
+		for (int i = 0; i < count; i++) {
+			Element elm = node.getElement(i);
+			if (elm.isLeaf()) {
+				int start = elm.getStartOffset(), end = elm.getEndOffset();
+				String line = doc.getText(start, end - start);
+				Matcher matcher = patDef.matcher(line);
+				if (matcher.find()) {
+					return start;
+				}
+			} else {
+				int p = getFunctionStartOffset(func, elm);
+				if (p >= 0) {
+					return p;
+				}
+			}
+		}
+		return -1;
+	}
   //</editor-fold>
+	//</editor-fold>
+
+	//<editor-fold defaultstate="collapsed" desc="replace text patterns with image buttons">
+	public boolean reparse() {
+		File temp = FileManager.createTempFile("py");
+		Element e = this.getDocument().getDefaultRootElement();
+		if (e.getEndOffset() - e.getStartOffset() == 1) {
+			return true;
+		}
+		try {
+			writeFile(temp.getAbsolutePath());
+			this.read(new BufferedReader(new InputStreamReader(new FileInputStream(temp), "UTF8")), null);
+			updateDocumentListeners();
+			return true;
+		} catch (IOException ex) {
+		}
+		return false;
+	}
+
+	private void parse(Element node) {
+		if (!showThumbs) {
+			// do not show any thumbnails
+			return;
+		}
+		int count = node.getElementCount();
+		for (int i = 0; i < count; i++) {
+			Element elm = node.getElement(i);
+			Debug.log(8, elm.toString());
+			if (elm.isLeaf()) {
+				int start = elm.getStartOffset(), end = elm.getEndOffset();
+				parseRange(start, end);
+			} else {
+				parse(elm);
+			}
+		}
+	}
+
+	private int parseRange(int start, int end) {
+		if (!showThumbs) {
+			// do not show any thumbnails
+			return end;
+		}
+		try {
+			end = parseLine(start, end, patCaptureBtn);
+			end = parseLine(start, end, patPatternStr);
+			end = parseLine(start, end, patRegionStr);
+			end = parseLine(start, end, patPngStr);
+		} catch (BadLocationException e) {
+			Debug.error(me + "parseRange: Problem while trying to parse line\n%s", e.getMessage());
+		}
+		return end;
+	}
+
+	private int parseLine(int startOff, int endOff, Pattern ptn) throws BadLocationException {
+		if (endOff <= startOff) {
+			return endOff;
+		}
+		Document doc = getDocument();
+		while (true) {
+			String line = doc.getText(startOff, endOff - startOff);
+			Matcher m = ptn.matcher(line);
+			//System.out.println("["+line+"]");
+			if (m.find()) {
+				int len = m.end() - m.start();
+				if (replaceWithImage(startOff + m.start(), startOff + m.end(), ptn)) {
+					startOff += m.start() + 1;
+					endOff -= len - 1;
+				} else {
+					startOff += m.end() + 1;
+				}
+			} else {
+				break;
+			}
+		}
+		return endOff;
+	}
 
-  //<editor-fold defaultstate="collapsed" desc="replace text patterns with image buttons">
-  public boolean reparse() {
-    File temp = FileManager.createTempFile("py");
-    Element e = this.getDocument().getDefaultRootElement();
-    if (e.getEndOffset() - e.getStartOffset() == 1) {
-      return true;
-    }
-    try {
-      writeFile(temp.getAbsolutePath());
-      this.read(new BufferedReader(new InputStreamReader(new FileInputStream(temp), "UTF8")), null);
-      updateDocumentListeners();
-      return true;
-    } catch (IOException ex) {
-    }
-    return false;
-  }
-
-  private void parse(Element node) {
-    if (!showThumbs) {
-      // do not show any thumbnails
-      return;
-    }
-    int count = node.getElementCount();
-    for (int i = 0; i < count; i++) {
-      Element elm = node.getElement(i);
-      Debug.log(8, elm.toString());
-      if (elm.isLeaf()) {
-        int start = elm.getStartOffset(), end = elm.getEndOffset();
-        parseRange(start, end);
-      } else {
-        parse(elm);
-      }
-    }
-  }
-
-  private int parseRange(int start, int end) {
-    if (!showThumbs) {
-      // do not show any thumbnails
-      return end;
-    }
-    try {
-      end = parseLine(start, end, patCaptureBtn);
-      end = parseLine(start, end, patPatternStr);
-      end = parseLine(start, end, patRegionStr);
-      end = parseLine(start, end, patPngStr);
-    } catch (BadLocationException e) {
-      Debug.error(me + "parseRange: Problem while trying to parse line\n%s", e.getMessage());
-    }
-    return end;
-  }
-
-  private int parseLine(int startOff, int endOff, Pattern ptn) throws BadLocationException {
-    if (endOff <= startOff) {
-      return endOff;
-    }
-    Document doc = getDocument();
-    while (true) {
-      String line = doc.getText(startOff, endOff - startOff);
-      Matcher m = ptn.matcher(line);
-      //System.out.println("["+line+"]");
-      if (m.find()) {
-        int len = m.end() - m.start();
-        if (replaceWithImage(startOff + m.start(), startOff + m.end(), ptn)) {
-          startOff += m.start() + 1;
-          endOff -= len - 1;
-        } else {
-          startOff += m.end() + 1;
-        }
-      } else {
-        break;
-      }
-    }
-    return endOff;
-  }
-
-  private boolean replaceWithImage(int startOff, int endOff, Pattern ptn)
-          throws BadLocationException {
-    Document doc = getDocument();
-    String imgStr = doc.getText(startOff, endOff - startOff);
-    JComponent comp = null;
-
-    if (ptn == patPatternStr || ptn == patPngStr) {
-      if (pref.getPrefMoreImageThumbs()) {
-        comp = EditorPatternButton.createFromString(this, imgStr, null);
-      } else {
-        comp = EditorPatternLabel.labelFromString(this, imgStr);
-      }
-    } else if (ptn == patRegionStr) {
-      if (pref.getPrefMoreImageThumbs()) {
-        comp = EditorRegionButton.createFromString(this, imgStr);
-      } else {
-        comp = EditorRegionLabel.labelFromString(this, imgStr);
-      }
-    } else if (ptn == patCaptureBtn) {
-      comp = EditorPatternLabel.labelFromString(this, "");
-    }
-    if (comp != null) {
-      this.select(startOff, endOff);
-      this.insertComponent(comp);
-      return true;
-    }
-    return false;
-  }
-
-  public String getRegionString(int x, int y, int w, int h) {
-    return String.format("Region(%d,%d,%d,%d)", x, y, w, h);
-  }
-
-  public String getPatternString(String ifn, float sim, Location off) {
-    if (ifn == null) {
-      return "\"" + EditorPatternLabel.CAPTURE + "\"";
-    }
-    String img = new File(ifn).getName();
-    String pat = "Pattern(\"" + img + "\")";
-    String ret = "";
-    if (sim > 0) {
-      if (sim >= 0.99F) {
-        ret += ".exact()";
-      } else if (sim != 0.7F) {
-        ret += String.format(Locale.ENGLISH, ".similar(%.2f)", sim);
-      }
-    }
-    if (off != null && (off.x != 0 || off.y != 0)) {
-      ret += ".targetOffset(" + off.x + "," + off.y + ")";
-    }
-    if (!ret.equals("")) {
-      ret = pat + ret;
-    } else {
-      ret = "\"" + img + "\"";
-    }
-    return ret;
-  }
+	private boolean replaceWithImage(int startOff, int endOff, Pattern ptn)
+					throws BadLocationException {
+		Document doc = getDocument();
+		String imgStr = doc.getText(startOff, endOff - startOff);
+		JComponent comp = null;
+
+		if (ptn == patPatternStr || ptn == patPngStr) {
+			if (pref.getPrefMoreImageThumbs()) {
+				comp = EditorPatternButton.createFromString(this, imgStr, null);
+			} else {
+				comp = EditorPatternLabel.labelFromString(this, imgStr);
+			}
+		} else if (ptn == patRegionStr) {
+			if (pref.getPrefMoreImageThumbs()) {
+				comp = EditorRegionButton.createFromString(this, imgStr);
+			} else {
+				comp = EditorRegionLabel.labelFromString(this, imgStr);
+			}
+		} else if (ptn == patCaptureBtn) {
+			comp = EditorPatternLabel.labelFromString(this, "");
+		}
+		if (comp != null) {
+			this.select(startOff, endOff);
+			this.insertComponent(comp);
+			return true;
+		}
+		return false;
+	}
+
+	public String getRegionString(int x, int y, int w, int h) {
+		return String.format("Region(%d,%d,%d,%d)", x, y, w, h);
+	}
+
+	public String getPatternString(String ifn, float sim, Location off) {
+		if (ifn == null) {
+			return "\"" + EditorPatternLabel.CAPTURE + "\"";
+		}
+		String img = new File(ifn).getName();
+		String pat = "Pattern(\"" + img + "\")";
+		String ret = "";
+		if (sim > 0) {
+			if (sim >= 0.99F) {
+				ret += ".exact()";
+			} else if (sim != 0.7F) {
+				ret += String.format(Locale.ENGLISH, ".similar(%.2f)", sim);
+			}
+		}
+		if (off != null && (off.x != 0 || off.y != 0)) {
+			ret += ".targetOffset(" + off.x + "," + off.y + ")";
+		}
+		if (!ret.equals("")) {
+			ret = pat + ret;
+		} else {
+			ret = "\"" + img + "\"";
+		}
+		return ret;
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="content insert append">
-  public void insertString(String str) {
-    int sel_start = getSelectionStart();
-    int sel_end = getSelectionEnd();
-    if (sel_end != sel_start) {
-      try {
-        getDocument().remove(sel_start, sel_end - sel_start);
-      } catch (BadLocationException e) {
-        Debug.error(me + "insertString: Problem while trying to insert\n%s", e.getMessage());
-      }
-    }
-    int pos = getCaretPosition();
-    insertString(pos, str);
-    int new_pos = getCaretPosition();
-    int end = parseRange(pos, new_pos);
-    setCaretPosition(end);
-  }
-
-  private void insertString(int pos, String str) {
-    Document doc = getDocument();
-    try {
-      doc.insertString(pos, str, null);
-    } catch (Exception e) {
-      Debug.error(me + "insertString: Problem while trying to insert at pos\n%s", e.getMessage());
-    }
-  }
+	//<editor-fold defaultstate="collapsed" desc="content insert append">
+	public void insertString(String str) {
+		int sel_start = getSelectionStart();
+		int sel_end = getSelectionEnd();
+		if (sel_end != sel_start) {
+			try {
+				getDocument().remove(sel_start, sel_end - sel_start);
+			} catch (BadLocationException e) {
+				Debug.error(me + "insertString: Problem while trying to insert\n%s", e.getMessage());
+			}
+		}
+		int pos = getCaretPosition();
+		insertString(pos, str);
+		int new_pos = getCaretPosition();
+		int end = parseRange(pos, new_pos);
+		setCaretPosition(end);
+	}
+
+	private void insertString(int pos, String str) {
+		Document doc = getDocument();
+		try {
+			doc.insertString(pos, str, null);
+		} catch (Exception e) {
+			Debug.error(me + "insertString: Problem while trying to insert at pos\n%s", e.getMessage());
+		}
+	}
 
 //TODO not used
-  public void appendString(String str) {
-    Document doc = getDocument();
-    try {
-      int start = doc.getLength();
-      doc.insertString(doc.getLength(), str, null);
-      int end = doc.getLength();
-      //end = parseLine(start, end, patHistoryBtnStr);
-    } catch (Exception e) {
-      Debug.error(me + "appendString: Problem while trying to append\n%s", e.getMessage());
-    }
-  }
+	public void appendString(String str) {
+		Document doc = getDocument();
+		try {
+			int start = doc.getLength();
+			doc.insertString(doc.getLength(), str, null);
+			int end = doc.getLength();
+			//end = parseLine(start, end, patHistoryBtnStr);
+		} catch (Exception e) {
+			Debug.error(me + "appendString: Problem while trying to append\n%s", e.getMessage());
+		}
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="feature search">
+	//<editor-fold defaultstate="collapsed" desc="feature search">
   /*
-   * public int search(Pattern pattern){
-   * return search(pattern, true);
-   * }
-   *
-   * public int search(Pattern pattern, boolean forward){
-   * if(!pattern.equals(_lastSearchPattern)){
-   * _lastSearchPattern = pattern;
-   * Document doc = getDocument();
-   * int pos = getCaretPosition();
-   * Debug.log("caret: "  + pos);
-   * try{
-   * String body = doc.getText(pos, doc.getLength()-pos);
-   * _lastSearchMatcher = pattern.matcher(body);
-   * }
-   * catch(BadLocationException e){
-   * e.printStackTrace();
-   * }
-   * }
-   * return continueSearch(forward);
-   * }
-   */
+	 * public int search(Pattern pattern){
+	 * return search(pattern, true);
+	 * }
+	 *
+	 * public int search(Pattern pattern, boolean forward){
+	 * if(!pattern.equals(_lastSearchPattern)){
+	 * _lastSearchPattern = pattern;
+	 * Document doc = getDocument();
+	 * int pos = getCaretPosition();
+	 * Debug.log("caret: "  + pos);
+	 * try{
+	 * String body = doc.getText(pos, doc.getLength()-pos);
+	 * _lastSearchMatcher = pattern.matcher(body);
+	 * }
+	 * catch(BadLocationException e){
+	 * e.printStackTrace();
+	 * }
+	 * }
+	 * return continueSearch(forward);
+	 * }
+	 */
+
+	/*
+	 * public int search(String str){
+	 * return search(str, true);
+	 * }
+	 */
+	public int search(String str, int pos, boolean forward) {
+		boolean isCaseSensitive = true;
+		String toSearch = str;
+		if (str.startsWith("!")) {
+			str = str.substring(1).toUpperCase();
+			isCaseSensitive = false;
+		}
+		int ret = -1;
+		Document doc = getDocument();
+		Debug.log(9, "search caret: " + pos + ", " + doc.getLength());
+		try {
+			String body;
+			int begin;
+			if (forward) {
+				int len = doc.getLength() - pos;
+				body = doc.getText(pos, len > 0 ? len : 0);
+				begin = pos;
+			} else {
+				body = doc.getText(0, pos);
+				begin = 0;
+			}
+			if (!isCaseSensitive) {
+				body = body.toUpperCase();
+			}
+			Pattern pattern = Pattern.compile(Pattern.quote(str));
+			Matcher matcher = pattern.matcher(body);
+			ret = continueSearch(matcher, begin, forward);
+			if (ret < 0) {
+				if (forward && pos != 0) {
+					return search(toSearch, 0, forward);
+				}
+				if (!forward && pos != doc.getLength()) {
+					return search(toSearch, doc.getLength(), forward);
+				}
+			}
+		} catch (BadLocationException e) {
+			Debug.log(7, "search caret: " + pos + ", " + doc.getLength()
+							+ e.getStackTrace());
+		}
+		return ret;
+	}
 
-  /*
-   * public int search(String str){
-   * return search(str, true);
-   * }
-   */
-  public int search(String str, int pos, boolean forward) {
-    boolean isCaseSensitive = true;
-    String toSearch = str;
-    if (str.startsWith("!")) {
-      str = str.substring(1).toUpperCase();
-      isCaseSensitive = false;
-    }
-    int ret = -1;
-    Document doc = getDocument();
-    Debug.log(9, "search caret: " + pos + ", " + doc.getLength());
-    try {
-      String body;
-      int begin;
-      if (forward) {
-        int len = doc.getLength() - pos;
-        body = doc.getText(pos, len > 0 ? len : 0);
-        begin = pos;
-      } else {
-        body = doc.getText(0, pos);
-        begin = 0;
-      }
-      if (!isCaseSensitive) {
-        body = body.toUpperCase();
-      }
-      Pattern pattern = Pattern.compile(Pattern.quote(str));
-      Matcher matcher = pattern.matcher(body);
-      ret = continueSearch(matcher, begin, forward);
-      if (ret < 0) {
-        if (forward && pos != 0) {
-          return search(toSearch, 0, forward);
-        }
-        if (!forward && pos != doc.getLength()) {
-          return search(toSearch, doc.getLength(), forward);
-        }
-      }
-    } catch (BadLocationException e) {
-      Debug.log(7, "search caret: " + pos + ", " + doc.getLength()
-              + e.getStackTrace());
-    }
-    return ret;
-  }
-
-  protected int continueSearch(Matcher matcher, int pos, boolean forward) {
-    boolean hasNext = false;
-    int start = 0, end = 0;
-    if (!forward) {
-      while (matcher.find()) {
-        hasNext = true;
-        start = matcher.start();
-        end = matcher.end();
-      }
-    } else {
-      hasNext = matcher.find();
-      if (!hasNext) {
-        return -1;
-      }
-      start = matcher.start();
-      end = matcher.end();
-    }
-    if (hasNext) {
-      Document doc = getDocument();
-      getCaret().setDot(pos + end);
-      getCaret().moveDot(pos + start);
-      getCaret().setSelectionVisible(true);
-      return pos + start;
-    }
-    return -1;
-  }
+	protected int continueSearch(Matcher matcher, int pos, boolean forward) {
+		boolean hasNext = false;
+		int start = 0, end = 0;
+		if (!forward) {
+			while (matcher.find()) {
+				hasNext = true;
+				start = matcher.start();
+				end = matcher.end();
+			}
+		} else {
+			hasNext = matcher.find();
+			if (!hasNext) {
+				return -1;
+			}
+			start = matcher.start();
+			end = matcher.end();
+		}
+		if (hasNext) {
+			Document doc = getDocument();
+			getCaret().setDot(pos + end);
+			getCaret().moveDot(pos + start);
+			getCaret().setSelectionVisible(true);
+			return pos + start;
+		}
+		return -1;
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Transfer code incl. images between code panes">
-  private class MyTransferHandler extends TransferHandler {
-
-    private static final String me = "EditorPaneTransferHandler: ";
-    Map<String, String> _copiedImgs = new HashMap<String, String>();
-
-    @Override
-    public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
-      super.exportToClipboard(comp, clip, action);
-    }
-
-    @Override
-    protected void exportDone(JComponent source,
-            Transferable data,
-            int action) {
-      if (action == TransferHandler.MOVE) {
-        JTextPane aTextPane = (JTextPane) source;
-        int sel_start = aTextPane.getSelectionStart();
-        int sel_end = aTextPane.getSelectionEnd();
-        Document doc = aTextPane.getDocument();
-        try {
-          doc.remove(sel_start, sel_end - sel_start);
-        } catch (BadLocationException e) {
-          Debug.error(me + "exportDone: Problem while trying to remove text\n%s", e.getMessage());
-        }
-      }
-    }
-
-    @Override
-    public int getSourceActions(JComponent c) {
-      return COPY_OR_MOVE;
-    }
-
-    @Override
-    protected Transferable createTransferable(JComponent c) {
-      JTextPane aTextPane = (JTextPane) c;
-
-      EditorKit kit = ((EditorKit) aTextPane.getEditorKit());
-      Document doc = aTextPane.getDocument();
-      int sel_start = aTextPane.getSelectionStart();
-      int sel_end = aTextPane.getSelectionEnd();
-
-      StringWriter writer = new StringWriter();
-      try {
-        _copiedImgs.clear();
-        kit.write(writer, doc, sel_start, sel_end - sel_start, _copiedImgs);
-        return new StringSelection(writer.toString());
-      } catch (Exception e) {
-        Debug.error(me + "createTransferable: Problem creating text to copy\n%s", e.getMessage());
-      }
-      return null;
-    }
-
-    @Override
-    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
-      for (int i = 0; i < transferFlavors.length; i++) {
-        //System.out.println(transferFlavors[i]);
-        if (transferFlavors[i].equals(DataFlavor.stringFlavor)) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    @Override
-    public boolean importData(JComponent comp, Transferable t) {
-      DataFlavor htmlFlavor = DataFlavor.stringFlavor;
-      if (canImport(comp, t.getTransferDataFlavors())) {
-        try {
-          String transferString = (String) t.getTransferData(htmlFlavor);
-          EditorPane targetTextPane = (EditorPane) comp;
-          for (Map.Entry<String, String> entry : _copiedImgs.entrySet()) {
-            String imgName = entry.getKey();
-            String imgPath = entry.getValue();
-            File destFile = targetTextPane.copyFileToBundle(imgPath);
-            String newName = destFile.getName();
-            if (!newName.equals(imgName)) {
-              String ptnImgName = "\"" + imgName + "\"";
-              newName = "\"" + newName + "\"";
-              transferString = transferString.replaceAll(ptnImgName, newName);
-              Debug.info(ptnImgName + " exists. Rename it to " + newName);
-            }
-          }
-          targetTextPane.insertString(transferString);
-        } catch (Exception e) {
-          Debug.error(me + "importData: Problem pasting text\n%s", e.getMessage());
-        }
-        return true;
-      }
-      return false;
-    }
-  }
+	//<editor-fold defaultstate="collapsed" desc="Transfer code incl. images between code panes">
+	private class MyTransferHandler extends TransferHandler {
+
+		private static final String me = "EditorPaneTransferHandler: ";
+		Map<String, String> _copiedImgs = new HashMap<String, String>();
+
+		@Override
+		public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
+			super.exportToClipboard(comp, clip, action);
+		}
+
+		@Override
+		protected void exportDone(JComponent source,
+						Transferable data,
+						int action) {
+			if (action == TransferHandler.MOVE) {
+				JTextPane aTextPane = (JTextPane) source;
+				int sel_start = aTextPane.getSelectionStart();
+				int sel_end = aTextPane.getSelectionEnd();
+				Document doc = aTextPane.getDocument();
+				try {
+					doc.remove(sel_start, sel_end - sel_start);
+				} catch (BadLocationException e) {
+					Debug.error(me + "exportDone: Problem while trying to remove text\n%s", e.getMessage());
+				}
+			}
+		}
+
+		@Override
+		public int getSourceActions(JComponent c) {
+			return COPY_OR_MOVE;
+		}
+
+		@Override
+		protected Transferable createTransferable(JComponent c) {
+			JTextPane aTextPane = (JTextPane) c;
+
+			SikuliEditorKit kit = ((SikuliEditorKit) aTextPane.getEditorKit());
+			Document doc = aTextPane.getDocument();
+			int sel_start = aTextPane.getSelectionStart();
+			int sel_end = aTextPane.getSelectionEnd();
+
+			StringWriter writer = new StringWriter();
+			try {
+				_copiedImgs.clear();
+				kit.write(writer, doc, sel_start, sel_end - sel_start, _copiedImgs);
+				return new StringSelection(writer.toString());
+			} catch (Exception e) {
+				Debug.error(me + "createTransferable: Problem creating text to copy\n%s", e.getMessage());
+			}
+			return null;
+		}
+
+		@Override
+		public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
+			for (int i = 0; i < transferFlavors.length; i++) {
+				//System.out.println(transferFlavors[i]);
+				if (transferFlavors[i].equals(DataFlavor.stringFlavor)) {
+					return true;
+				}
+			}
+			return false;
+		}
+
+		@Override
+		public boolean importData(JComponent comp, Transferable t) {
+			DataFlavor htmlFlavor = DataFlavor.stringFlavor;
+			if (canImport(comp, t.getTransferDataFlavors())) {
+				try {
+					String transferString = (String) t.getTransferData(htmlFlavor);
+					EditorPane targetTextPane = (EditorPane) comp;
+					for (Map.Entry<String, String> entry : _copiedImgs.entrySet()) {
+						String imgName = entry.getKey();
+						String imgPath = entry.getValue();
+						File destFile = targetTextPane.copyFileToBundle(imgPath);
+						String newName = destFile.getName();
+						if (!newName.equals(imgName)) {
+							String ptnImgName = "\"" + imgName + "\"";
+							newName = "\"" + newName + "\"";
+							transferString = transferString.replaceAll(ptnImgName, newName);
+							Debug.info(ptnImgName + " exists. Rename it to " + newName);
+						}
+					}
+					targetTextPane.insertString(transferString);
+				} catch (Exception e) {
+					Debug.error(me + "importData: Problem pasting text\n%s", e.getMessage());
+				}
+				return true;
+			}
+			return false;
+		}
+	}
 //</editor-fold>
-  //<editor-fold defaultstate="collapsed" desc="currently not used">
-  private String _tabString = "   ";
-
-  private void setTabSize(int charactersPerTab) {
-    FontMetrics fm = this.getFontMetrics(this.getFont());
-    int charWidth = fm.charWidth('w');
-    int tabWidth = charWidth * charactersPerTab;
-
-    TabStop[] tabs = new TabStop[10];
-
-    for (int j = 0; j < tabs.length; j++) {
-      int tab = j + 1;
-      tabs[j] = new TabStop(tab * tabWidth);
-    }
-
-    TabSet tabSet = new TabSet(tabs);
-    SimpleAttributeSet attributes = new SimpleAttributeSet();
-    StyleConstants.setFontSize(attributes, 18);
-    StyleConstants.setFontFamily(attributes, "Osaka-Mono");
-    StyleConstants.setTabSet(attributes, tabSet);
-    int length = getDocument().getLength();
-    getStyledDocument().setParagraphAttributes(0, length, attributes, true);
-  }
-
-  private void setTabs(int spaceForTab) {
-    String t = "";
-    for (int i = 0; i < spaceForTab; i++) {
-      t += " ";
-    }
-    _tabString = t;
-  }
-
-  private void expandTab() throws BadLocationException {
-    int pos = getCaretPosition();
-    Document doc = getDocument();
-    doc.remove(pos - 1, 1);
-    doc.insertString(pos - 1, _tabString, null);
-  }
-  private Class _historyBtnClass;
-
-  private void setHistoryCaptureButton(ButtonCapture btn) {
-    _historyBtnClass = btn.getClass();
-  }
-
-  private void indent(int startLine, int endLine, int level) {
-    Document doc = getDocument();
-    String strIndent = "";
-    if (level > 0) {
-      for (int i = 0; i < level; i++) {
-        strIndent += "  ";
-      }
-    } else {
-      Debug.error("negative indentation not supported yet!!");
-    }
-    for (int i = startLine; i < endLine; i++) {
-      try {
-        int off = getLineStartOffset(i);
-        if (level > 0) {
-          doc.insertString(off, strIndent, null);
-        }
-      } catch (Exception e) {
-        e.printStackTrace();
-      }
-    }
-  }
-
-  private void checkCompletion(java.awt.event.KeyEvent ke) throws BadLocationException {
-    Document doc = getDocument();
-    Element root = doc.getDefaultRootElement();
-    int pos = getCaretPosition();
-    int lineIdx = root.getElementIndex(pos);
-    Element line = root.getElement(lineIdx);
-    int start = line.getStartOffset(), len = line.getEndOffset() - start;
-    String strLine = doc.getText(start, len - 1);
-    Debug.log(9, "[" + strLine + "]");
-    if (strLine.endsWith("find") && ke.getKeyChar() == '(') {
-      ke.consume();
-      doc.insertString(pos, "(", null);
-      ButtonCapture btnCapture = new ButtonCapture(this, line);
-      insertComponent(btnCapture);
-      doc.insertString(pos + 2, ")", null);
-    }
-
-  }
+	//<editor-fold defaultstate="collapsed" desc="currently not used">
+	private String _tabString = "   ";
+
+	private void setTabSize(int charactersPerTab) {
+		FontMetrics fm = this.getFontMetrics(this.getFont());
+		int charWidth = fm.charWidth('w');
+		int tabWidth = charWidth * charactersPerTab;
+
+		TabStop[] tabs = new TabStop[10];
+
+		for (int j = 0; j < tabs.length; j++) {
+			int tab = j + 1;
+			tabs[j] = new TabStop(tab * tabWidth);
+		}
+
+		TabSet tabSet = new TabSet(tabs);
+		SimpleAttributeSet attributes = new SimpleAttributeSet();
+		StyleConstants.setFontSize(attributes, 18);
+		StyleConstants.setFontFamily(attributes, "Osaka-Mono");
+		StyleConstants.setTabSet(attributes, tabSet);
+		int length = getDocument().getLength();
+		getStyledDocument().setParagraphAttributes(0, length, attributes, true);
+	}
+
+	private void setTabs(int spaceForTab) {
+		String t = "";
+		for (int i = 0; i < spaceForTab; i++) {
+			t += " ";
+		}
+		_tabString = t;
+	}
+
+	private void expandTab() throws BadLocationException {
+		int pos = getCaretPosition();
+		Document doc = getDocument();
+		doc.remove(pos - 1, 1);
+		doc.insertString(pos - 1, _tabString, null);
+	}
+	private Class _historyBtnClass;
+
+	private void setHistoryCaptureButton(ButtonCapture btn) {
+		_historyBtnClass = btn.getClass();
+	}
+
+	private void indent(int startLine, int endLine, int level) {
+		Document doc = getDocument();
+		String strIndent = "";
+		if (level > 0) {
+			for (int i = 0; i < level; i++) {
+				strIndent += "  ";
+			}
+		} else {
+			Debug.error("negative indentation not supported yet!!");
+		}
+		for (int i = startLine; i < endLine; i++) {
+			try {
+				int off = getLineStartOffset(i);
+				if (level > 0) {
+					doc.insertString(off, strIndent, null);
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private void checkCompletion(java.awt.event.KeyEvent ke) throws BadLocationException {
+		Document doc = getDocument();
+		Element root = doc.getDefaultRootElement();
+		int pos = getCaretPosition();
+		int lineIdx = root.getElementIndex(pos);
+		Element line = root.getElement(lineIdx);
+		int start = line.getStartOffset(), len = line.getEndOffset() - start;
+		String strLine = doc.getText(start, len - 1);
+		Debug.log(9, "[" + strLine + "]");
+		if (strLine.endsWith("find") && ke.getKeyChar() == '(') {
+			ke.consume();
+			doc.insertString(pos, "(", null);
+			ButtonCapture btnCapture = new ButtonCapture(this, line);
+			insertComponent(btnCapture);
+			doc.insertString(pos + 2, ")", null);
+		}
+
+	}
   //</editor-fold>
 }
diff --git a/IDE/src/main/java/org/sikuli/ide/EditorKit.java b/IDE/src/main/java/org/sikuli/ide/SikuliEditorKit.java
similarity index 97%
rename from IDE/src/main/java/org/sikuli/ide/EditorKit.java
rename to IDE/src/main/java/org/sikuli/ide/SikuliEditorKit.java
index 8cafded..6ded5e6 100755
--- a/IDE/src/main/java/org/sikuli/ide/EditorKit.java
+++ b/IDE/src/main/java/org/sikuli/ide/SikuliEditorKit.java
@@ -13,17 +13,16 @@ import java.io.*;
 import java.util.Map;
 import javax.swing.*;
 import javax.swing.text.*;
-import org.sikuli.idesupport.PythonIndentation;
 import org.sikuli.basics.Debug;
 import org.sikuli.basics.IndentationLogic;
 
-public class EditorKit extends StyledEditorKit {
+public class SikuliEditorKit extends StyledEditorKit {
 
 	private static final String me = "EditorKit: ";
 	private ViewFactory _viewFactory;
 	private EditorPane pane;
 
-	public EditorKit(EditorPane p) {
+	public SikuliEditorKit(EditorPane p) {
 		_viewFactory = new EditorViewFactory();
 		pane = p;
 	}
@@ -175,7 +174,7 @@ public class EditorKit extends StyledEditorKit {
 			int i = segLine.offset;
 			end = i + segLine.count;
 			if (end > i) {
-				String leadingWS = PythonIndentation.getLeadingWhitespace(doc, start, end - start);
+				String leadingWS = indentationLogic.getLeadingWhitespace(doc, start, end - start);
 				int toRemove = indentationLogic.checkDedent(leadingWS, line + 1);
 				doc.remove(start, toRemove);
 			}
@@ -229,7 +228,7 @@ public class EditorKit extends StyledEditorKit {
 				String s = doc.getText(start, len);
 				StringBuilder sb = new StringBuilder("\n");
 
-				String leadingWS = PythonIndentation.getLeadingWhitespace(doc, start, caretPos - start);
+				String leadingWS = indentationLogic.getLeadingWhitespace(doc, start, caretPos - start);
 				sb.append(leadingWS);
 //TODO better control over automatic indentation
 				indentationLogic.checkIndent(leadingWS, lineNum + 1);
@@ -237,7 +236,7 @@ public class EditorKit extends StyledEditorKit {
 				// If there is only whitespace between the caret and
 				// the EOL, pressing Enter auto-indents the new line to
 				// the same place as the previous line.
-				int nonWhitespacePos = PythonIndentation.atEndOfLine(doc, caretPos, start, s, len);
+				int nonWhitespacePos = indentationLogic.atEndOfLine(doc, caretPos, start, s, len);
 				if (nonWhitespacePos == -1) {
 					if (leadingWS.length() == len) {
 						// If the line was nothing but whitespace, select it
diff --git a/IDE/src/main/java/org/sikuli/ide/SikuliIDE.java b/IDE/src/main/java/org/sikuli/ide/SikuliIDE.java
index 6eb2362..8412f62 100755
--- a/IDE/src/main/java/org/sikuli/ide/SikuliIDE.java
+++ b/IDE/src/main/java/org/sikuli/ide/SikuliIDE.java
@@ -42,6 +42,7 @@ import org.sikuli.basics.PreferencesUser;
 import org.sikuli.basics.Settings;
 import org.sikuli.basics.AutoUpdater;
 import org.sikuli.basics.CommandArgsEnum;
+import org.sikuli.basics.IDESupport;
 import org.sikuli.basics.IResourceLoader;
 import org.sikuli.script.ImagePath;
 import org.sikuli.basics.MultiFrame;
@@ -52,2343 +53,2365 @@ import org.sikuli.script.Key;
 
 public class SikuliIDE extends JFrame {
 
-  private static String me = "IDE";
-  private static String mem = "";
-  private static int lvl = 3;
-
-  private static void log(int level, String message, Object... args) {
-    Debug.logx(level, "", me + ": " + message, args);
-  }
-  // RaiMan not used final static boolean ENABLE_RECORDING = false;
-  final static boolean ENABLE_UNIFIED_TOOLBAR = true;
-  final static Color COLOR_SEARCH_FAILED = Color.red;
-  final static Color COLOR_SEARCH_NORMAL = Color.black;
-  final static int WARNING_CANCEL = 2;
-  final static int WARNING_ACCEPTED = 1;
-  final static int WARNING_DO_NOTHING = 0;
-  final static int IS_SAVE_ALL = 3;
-  static boolean _runningSkl = false;
-  private static NativeLayer _native;
-  private Dimension _windowSize = null;
-  private Point _windowLocation = null;
-  private boolean smallScreen = false;
-  private int commandBarHeight = 800;
-  private CloseableTabbedPane _mainPane;
-  private EditorLineNumberView lineNumberColumn;
-  private JSplitPane _mainSplitPane;
-  private JTabbedPane msgPane;
-  private boolean msgPaneCollapsed = false;
-  private EditorConsolePane _console;
-  private JXCollapsiblePane _cmdList;
-  private SikuliIDEStatusBar _status = null;
-  private ButtonCapture _btnCapture;
-  private ButtonRun _btnRun, _btnRunViz;
-  private boolean ideIsRunningScript = false;
-  private JXSearchField _searchField;
-  private JMenuBar _menuBar = new JMenuBar();
-  private JMenu _fileMenu = new JMenu(_I("menuFile"));
-  private JMenu _editMenu = new JMenu(_I("menuEdit"));
-  private UndoAction _undoAction = new UndoAction();
-  private RedoAction _redoAction = new RedoAction();
-  private FindAction _findHelper;
-  private JMenu _runMenu = new JMenu(_I("menuRun"));
-  private JMenu _viewMenu = new JMenu(_I("menuView"));
-  private JMenu _toolMenu = new JMenu(_I("menuTool"));
-  private JMenu _helpMenu = new JMenu(_I("menuHelp"));
-  private JXCollapsiblePane _sidePane;
-  private JCheckBoxMenuItem _chkShowUnitTest;
-  private JMenuItem chkShowCmdList = null;
-  private JCheckBoxMenuItem chkShowThumbs;
-  //private UnitTestRunner _testRunner;
-  private static CommandLine cmdLine;
-  private static String cmdValue;
-  private static String[] loadScript = null;
-  private static SikuliIDE _instance = null;
-  private boolean _inited = false;
-  private static boolean runMe = false;
-  private int restoredScripts = 0;
-  private int alreadyOpenedTab = -1;
-  private PreferencesUser prefs;
-  private boolean ACCESSING_AS_FOLDER = false;
-  private static JFrame splash;
-  private boolean firstRun = true;
-  private static long start;
-
-  public static String _I(String key, Object... args) {
-    try {
-      return SikuliIDEI18N._I(key, args);
-    } catch (Exception e) {
-      Debug.log(3, "[I18N] " + key);
-      return key;
-    }
-  }
-
-  public static ImageIcon getIconResource(String name) {
-    URL url = SikuliIDE.class.getResource(name);
-    if (url == null) {
-      Debug.error("Warning: could not load \"" + name + "\" icon");
-      return null;
-    }
-    return new ImageIcon(url);
-  }
+	private static String me = "IDE";
+	private static String mem = "";
+	private static int lvl = 3;
+
+	private static void log(int level, String message, Object... args) {
+		Debug.logx(level, "", me + ": " + message, args);
+	}
+	// RaiMan not used final static boolean ENABLE_RECORDING = false;
+	final static boolean ENABLE_UNIFIED_TOOLBAR = true;
+	final static Color COLOR_SEARCH_FAILED = Color.red;
+	final static Color COLOR_SEARCH_NORMAL = Color.black;
+	final static int WARNING_CANCEL = 2;
+	final static int WARNING_ACCEPTED = 1;
+	final static int WARNING_DO_NOTHING = 0;
+	final static int IS_SAVE_ALL = 3;
+	static boolean _runningSkl = false;
+	private static NativeLayer _native;
+	private Dimension _windowSize = null;
+	private Point _windowLocation = null;
+	private boolean smallScreen = false;
+	private int commandBarHeight = 800;
+	private CloseableTabbedPane _mainPane;
+	private EditorLineNumberView lineNumberColumn;
+	private JSplitPane _mainSplitPane;
+	private JTabbedPane msgPane;
+	private boolean msgPaneCollapsed = false;
+	private EditorConsolePane _console;
+	private JXCollapsiblePane _cmdList;
+	private SikuliIDEStatusBar _status = null;
+	private ButtonCapture _btnCapture;
+	private ButtonRun _btnRun, _btnRunViz;
+	private boolean ideIsRunningScript = false;
+	private JXSearchField _searchField;
+	private JMenuBar _menuBar = new JMenuBar();
+	private JMenu _fileMenu = new JMenu(_I("menuFile"));
+	private JMenu _editMenu = new JMenu(_I("menuEdit"));
+	private UndoAction _undoAction = new UndoAction();
+	private RedoAction _redoAction = new RedoAction();
+	private FindAction _findHelper;
+	private JMenu _runMenu = new JMenu(_I("menuRun"));
+	private JMenu _viewMenu = new JMenu(_I("menuView"));
+	private JMenu _toolMenu = new JMenu(_I("menuTool"));
+	private JMenu _helpMenu = new JMenu(_I("menuHelp"));
+	private JXCollapsiblePane _sidePane;
+	private JCheckBoxMenuItem _chkShowUnitTest;
+	private JMenuItem chkShowCmdList = null;
+	private JCheckBoxMenuItem chkShowThumbs;
+	//private UnitTestRunner _testRunner;
+	private static CommandLine cmdLine;
+	private static String cmdValue;
+	private static String[] loadScript = null;
+	private static SikuliIDE _instance = null;
+	private boolean _inited = false;
+	private static boolean runMe = false;
+	private int restoredScripts = 0;
+	private int alreadyOpenedTab = -1;
+	private PreferencesUser prefs;
+	private boolean ACCESSING_AS_FOLDER = false;
+	private static JFrame splash;
+	private boolean firstRun = true;
+	private static long start;
+	private static Map<String, IDESupport> ideSupporter = new HashMap<String, IDESupport>();
+
+	static {
+		ServiceLoader<IDESupport> sloader = ServiceLoader.load(IDESupport.class);
+		Iterator<IDESupport> supIterator = sloader.iterator();
+		while (supIterator.hasNext()) {
+			IDESupport current = supIterator.next();
+			for (String ending : current.getEndings()) {
+				ideSupporter.put(ending, current);
+			}
+		}
+	}
+
+	public static IDESupport getIDESupport(String ending) {
+		return ideSupporter.get(ending);
+	}
+
+	public static String _I(String key, Object... args) {
+		try {
+			return SikuliIDEI18N._I(key, args);
+		} catch (Exception e) {
+			Debug.log(3, "[I18N] " + key);
+			return key;
+		}
+	}
+
+	public static ImageIcon getIconResource(String name) {
+		URL url = SikuliIDE.class.getResource(name);
+		if (url == null) {
+			Debug.error("Warning: could not load \"" + name + "\" icon");
+			return null;
+		}
+		return new ImageIcon(url);
+	}
 
 //TODO run only one windowed instance of IDE
-  public static void main(String[] args) {
-    String[] splashArgs = new String[]{
-      "splash", "#", "#" + Settings.SikuliVersionIDE, "", "#", "#... starting - please wait ..."};
-
-    File isRunning;
-    new File(Settings.BaseTempPath).mkdirs();
-    isRunning = new File(Settings.BaseTempPath, "sikuli-ide-isrunning");
-    FileOutputStream isRunningFile = null;
-    try {
-      isRunning.createNewFile();
-      isRunningFile = new FileOutputStream(isRunning);
-      if (null == isRunningFile.getChannel().tryLock()) {
-        splashArgs[5] = "Terminating on FatalError: IDE already running";
-        splash = new MultiFrame(splashArgs);
-        log(-1, splashArgs[5]);
-        SikuliX.pause(3);
-        System.exit(1);
-      }
-    } catch (Exception ex) {
-      splashArgs[5] = "Terminating on FatalError: cannot access IDE lock ";
-      splash = new MultiFrame(splashArgs);
-      log(-1, splashArgs[5] + isRunning.getAbsolutePath());
-      SikuliX.pause(3);
-      System.exit(1);
-    }
-
-    if (System.getProperty("sikuli.FromCommandLine") == null) {
-      String[] userOptions = SikuliX.collectOptions("IDE", args);
-      if (userOptions == null) {
-        System.exit(0);
-      }
-      if (userOptions.length > 0) {
-        for (String e : userOptions) {
-          log(lvl, "arg: " + e);
-        }
-        args = userOptions;
-      }
-    }
-
-    start = (new Date()).getTime();
-    for (String e : args) {
-      splashArgs[3] += e + " ";
-    }
-    splashArgs[3] = splashArgs[3].trim();
-    splash = new MultiFrame(splashArgs);
-
-    CommandArgs cmdArgs = new CommandArgs("IDE");
-    cmdLine = cmdArgs.getCommandLine(CommandArgs.scanArgs(args));
-
-    if (cmdLine == null) {
-      Debug.error("Did not find any valid option on command line!");
-      System.exit(1);
-    }
-
-    if (cmdLine.hasOption("h")) {
-      cmdArgs.printHelp();
-      System.exit(0);
-    }
-
-    if (cmdLine.hasOption("c")) {
-      System.setProperty("sikuli.console", "false");
-    }
-
-    if (cmdLine.hasOption(CommandArgsEnum.LOGFILE.shortname())) {
-      cmdValue = cmdLine.getOptionValue(CommandArgsEnum.LOGFILE.longname());
-      if (!Debug.setLogFile(cmdValue == null ? "" : cmdValue)) {
-        System.exit(1);
-      }
-    }
-
-    if (cmdLine.hasOption(CommandArgsEnum.USERLOGFILE.shortname())) {
-      cmdValue = cmdLine.getOptionValue(CommandArgsEnum.USERLOGFILE.longname());
-      if (!Debug.setUserLogFile(cmdValue == null ? "" : cmdValue)) {
-        System.exit(1);
-      }
-    }
-
-    if (cmdLine.hasOption(CommandArgsEnum.DEBUG.shortname())) {
-      cmdValue = cmdLine.getOptionValue(CommandArgsEnum.DEBUG.longname());
-      if (cmdValue == null) {
-        Debug.setDebugLevel(3);
-        Debug.setLogFile("");
-        Settings.LogTime = true;
-      } else {
-        Debug.setDebugLevel(cmdValue);
-      }
-    }
-
-    if (cmdLine.hasOption(CommandArgsEnum.LOAD.shortname())) {
-      loadScript = cmdLine.getOptionValues(CommandArgsEnum.LOAD.longname());
-      log(lvl, "requested to load: " + loadScript);
-      if (loadScript[0].endsWith(".skl")) {
-        log(lvl, "Switching to SikuliScript to run " + loadScript);
-        splash.dispose();
-        SikuliScript.main(args);
-      }
-    }
-
-    if (cmdLine.hasOption(CommandArgsEnum.RUN.shortname())
-            || cmdLine.hasOption(CommandArgsEnum.TEST.shortname())
-            || cmdLine.hasOption(CommandArgsEnum.INTERACTIVE.shortname())) {
-      log(lvl, "Switching to SikuliScript with option -r, -t or -i");
-      splash.dispose();
-      SikuliScript.main(args);
-    }
-
-    Settings.setArgs(cmdArgs.getUserArgs(), cmdArgs.getSikuliArgs());
-    Settings.showJavaInfo();
-    Settings.printArgs();
+	public static void main(String[] args) {
+		String[] splashArgs = new String[]{
+			"splash", "#", "#" + Settings.SikuliVersionIDE, "", "#", "#... starting - please wait ..."};
+
+		File isRunning;
+		new File(Settings.BaseTempPath).mkdirs();
+		isRunning = new File(Settings.BaseTempPath, "sikuli-ide-isrunning");
+		FileOutputStream isRunningFile = null;
+		try {
+			isRunning.createNewFile();
+			isRunningFile = new FileOutputStream(isRunning);
+			if (null == isRunningFile.getChannel().tryLock()) {
+				splashArgs[5] = "Terminating on FatalError: IDE already running";
+				splash = new MultiFrame(splashArgs);
+				log(-1, splashArgs[5]);
+				SikuliX.pause(3);
+				System.exit(1);
+			}
+		} catch (Exception ex) {
+			splashArgs[5] = "Terminating on FatalError: cannot access IDE lock ";
+			splash = new MultiFrame(splashArgs);
+			log(-1, splashArgs[5] + isRunning.getAbsolutePath());
+			SikuliX.pause(3);
+			System.exit(1);
+		}
+
+		if (System.getProperty("sikuli.FromCommandLine") == null) {
+			String[] userOptions = SikuliX.collectOptions("IDE", args);
+			if (userOptions == null) {
+				System.exit(0);
+			}
+			if (userOptions.length > 0) {
+				for (String e : userOptions) {
+					log(lvl, "arg: " + e);
+				}
+				args = userOptions;
+			}
+		}
+
+		start = (new Date()).getTime();
+		for (String e : args) {
+			splashArgs[3] += e + " ";
+		}
+		splashArgs[3] = splashArgs[3].trim();
+		splash = new MultiFrame(splashArgs);
+
+		CommandArgs cmdArgs = new CommandArgs("IDE");
+		cmdLine = cmdArgs.getCommandLine(CommandArgs.scanArgs(args));
+
+		if (cmdLine == null) {
+			Debug.error("Did not find any valid option on command line!");
+			System.exit(1);
+		}
+
+		if (cmdLine.hasOption("h")) {
+			cmdArgs.printHelp();
+			System.exit(0);
+		}
+
+		if (cmdLine.hasOption("c")) {
+			System.setProperty("sikuli.console", "false");
+		}
+
+		if (cmdLine.hasOption(CommandArgsEnum.LOGFILE.shortname())) {
+			cmdValue = cmdLine.getOptionValue(CommandArgsEnum.LOGFILE.longname());
+			if (!Debug.setLogFile(cmdValue == null ? "" : cmdValue)) {
+				System.exit(1);
+			}
+		}
+
+		if (cmdLine.hasOption(CommandArgsEnum.USERLOGFILE.shortname())) {
+			cmdValue = cmdLine.getOptionValue(CommandArgsEnum.USERLOGFILE.longname());
+			if (!Debug.setUserLogFile(cmdValue == null ? "" : cmdValue)) {
+				System.exit(1);
+			}
+		}
+
+		if (cmdLine.hasOption(CommandArgsEnum.DEBUG.shortname())) {
+			cmdValue = cmdLine.getOptionValue(CommandArgsEnum.DEBUG.longname());
+			if (cmdValue == null) {
+				Debug.setDebugLevel(3);
+				Debug.setLogFile("");
+				Settings.LogTime = true;
+			} else {
+				Debug.setDebugLevel(cmdValue);
+			}
+		}
+
+		if (cmdLine.hasOption(CommandArgsEnum.LOAD.shortname())) {
+			loadScript = cmdLine.getOptionValues(CommandArgsEnum.LOAD.longname());
+			log(lvl, "requested to load: " + loadScript);
+			if (loadScript[0].endsWith(".skl")) {
+				log(lvl, "Switching to SikuliScript to run " + loadScript);
+				splash.dispose();
+				SikuliScript.main(args);
+			}
+		}
+
+		if (cmdLine.hasOption(CommandArgsEnum.RUN.shortname())
+						|| cmdLine.hasOption(CommandArgsEnum.TEST.shortname())
+						|| cmdLine.hasOption(CommandArgsEnum.INTERACTIVE.shortname())) {
+			log(lvl, "Switching to SikuliScript with option -r, -t or -i");
+			splash.dispose();
+			SikuliScript.main(args);
+		}
+
+		Settings.setArgs(cmdArgs.getUserArgs(), cmdArgs.getSikuliArgs());
+		Settings.showJavaInfo();
+		Settings.printArgs();
 
 // we should open the IDE
-    initNativeLayer();
-    try {
-      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-      //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
-    } catch (Exception e) {
-      log(-1, "Problem loading UIManager!\nError: %s", e.getMessage());
-    }
-
-    if (Settings.isMac()) {
-      _native.initApp();
-      try {
-        Thread.sleep(1000);
-      } catch (InterruptedException ie) {
-      }
-    }
-    SikuliIDE.getInstance(args);
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="IDE setup and general">
-  private SikuliIDE(String[] args) {
-    super("Sikuli IDE");
-    initSikuliIDE(args);
-  }
-
-  private void initSikuliIDE(String[] args) {
-    prefs = PreferencesUser.getInstance();
-    if (prefs.getUserType() < 0) {
-      prefs.setUserType(PreferencesUser.NEWBEE);
-      prefs.setIdeSession("");
-      prefs.setDefaults(prefs.getUserType());
-    }
-
-    _native.initIDE(this);
-
-    IResourceLoader loader = FileManager.getNativeLoader("basic", args);
-    loader.check(Settings.SIKULI_LIB);
-
-    _windowSize = prefs.getIdeSize();
-    _windowLocation = prefs.getIdeLocation();
-    Screen m = (new Location(_windowLocation)).getScreen();
-    if (m == null) {
-      Debug.error("IDE: remembered window not valid - going to primary screen");
-      m = Screen.getPrimaryScreen();
-      _windowSize.width = 0;
-    }
-    Rectangle s = m.getBounds();
-    if (_windowSize.width == 0 || _windowSize.width > s.width
-            || _windowSize.height > s.height) {
-      if (s.width < 1025) {
-        _windowSize = new Dimension(1024, 700);
-        _windowLocation = new Point(0, 0);
-      } else {
-        _windowSize = new Dimension(s.width - 150, s.height - 100);
-        _windowLocation = new Point(75, 0);
-      }
-    }
-    if (_windowSize.getHeight() < commandBarHeight) {
-      smallScreen = true;
-    }
-    setSize(_windowSize);
-    setLocation(_windowLocation);
-
-    initMenuBars(this);
-    final Container c = getContentPane();
-    c.setLayout(new BorderLayout());
-    initTabPane();
-    initMsgPane(prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL);
+		initNativeLayer();
+		try {
+			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+			//UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
+		} catch (Exception e) {
+			log(-1, "Problem loading UIManager!\nError: %s", e.getMessage());
+		}
+
+		if (Settings.isMac()) {
+			_native.initApp();
+			try {
+				Thread.sleep(1000);
+			} catch (InterruptedException ie) {
+			}
+		}
+		SikuliIDE.getInstance(args);
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="IDE setup and general">
+	private SikuliIDE(String[] args) {
+		super("Sikuli IDE");
+		initSikuliIDE(args);
+	}
+
+	private void initSikuliIDE(String[] args) {
+		prefs = PreferencesUser.getInstance();
+		if (prefs.getUserType() < 0) {
+			prefs.setUserType(PreferencesUser.NEWBEE);
+			prefs.setIdeSession("");
+			prefs.setDefaults(prefs.getUserType());
+		}
+
+		_native.initIDE(this);
+
+		IResourceLoader loader = FileManager.getNativeLoader("basic", args);
+		loader.check(Settings.SIKULI_LIB);
+
+		_windowSize = prefs.getIdeSize();
+		_windowLocation = prefs.getIdeLocation();
+		Screen m = (new Location(_windowLocation)).getScreen();
+		if (m == null) {
+			Debug.error("IDE: remembered window not valid - going to primary screen");
+			m = Screen.getPrimaryScreen();
+			_windowSize.width = 0;
+		}
+		Rectangle s = m.getBounds();
+		if (_windowSize.width == 0 || _windowSize.width > s.width
+						|| _windowSize.height > s.height) {
+			if (s.width < 1025) {
+				_windowSize = new Dimension(1024, 700);
+				_windowLocation = new Point(0, 0);
+			} else {
+				_windowSize = new Dimension(s.width - 150, s.height - 100);
+				_windowLocation = new Point(75, 0);
+			}
+		}
+		if (_windowSize.getHeight() < commandBarHeight) {
+			smallScreen = true;
+		}
+		setSize(_windowSize);
+		setLocation(_windowLocation);
+
+		initMenuBars(this);
+		final Container c = getContentPane();
+		c.setLayout(new BorderLayout());
+		initTabPane();
+		initMsgPane(prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL);
 // RaiMan not used		initSidePane(); // IDE UnitTest
 
-    JPanel codeAndUnitPane = new JPanel(new BorderLayout(10, 10));
-    codeAndUnitPane.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
-    codeAndUnitPane.add(_mainPane, BorderLayout.CENTER);
+		JPanel codeAndUnitPane = new JPanel(new BorderLayout(10, 10));
+		codeAndUnitPane.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
+		codeAndUnitPane.add(_mainPane, BorderLayout.CENTER);
 // RaiMan not used		codeAndUnitPane.add(_sidePane, BorderLayout.EAST);
-    if (prefs.getPrefMoreMessage() == PreferencesUser.VERTICAL) {
-      _mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, codeAndUnitPane, msgPane);
-    } else {
-      _mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, codeAndUnitPane, msgPane);
-    }
-    _mainSplitPane.setResizeWeight(0.6);
-    _mainSplitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
-
-    JPanel editPane = new JPanel(new BorderLayout(0, 0));
-
-    JComponent cp = createCommandPane();
-
-    if (PreferencesUser.getInstance().getPrefMoreCommandBar()) {
-      editPane.add(cp, BorderLayout.WEST);
-    }
-
-    editPane.add(_mainSplitPane, BorderLayout.CENTER);
-    c.add(editPane, BorderLayout.CENTER);
-
-    JToolBar tb = initToolbar();
-    c.add(tb, BorderLayout.NORTH); // the buttons
-
-    c.add(initStatusbar(), BorderLayout.SOUTH);
-    c.doLayout();
-
-    initShortcutKeys();
-    initHotkeys();
-    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
-    initWindowListener();
-    initTooltip();
-    restoreSession();
+		if (prefs.getPrefMoreMessage() == PreferencesUser.VERTICAL) {
+			_mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, codeAndUnitPane, msgPane);
+		} else {
+			_mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, codeAndUnitPane, msgPane);
+		}
+		_mainSplitPane.setResizeWeight(0.6);
+		_mainSplitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+		JPanel editPane = new JPanel(new BorderLayout(0, 0));
+
+		JComponent cp = createCommandPane();
+
+		if (PreferencesUser.getInstance().getPrefMoreCommandBar()) {
+			editPane.add(cp, BorderLayout.WEST);
+		}
+
+		editPane.add(_mainSplitPane, BorderLayout.CENTER);
+		c.add(editPane, BorderLayout.CENTER);
+
+		JToolBar tb = initToolbar();
+		c.add(tb, BorderLayout.NORTH); // the buttons
+
+		c.add(initStatusbar(), BorderLayout.SOUTH);
+		c.doLayout();
+
+		initShortcutKeys();
+		initHotkeys();
+		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+		initWindowListener();
+		initTooltip();
+
+		autoCheckUpdate();
+
+		_inited = true;
+		try {
+			getCurrentCodePane().requestFocus();
+		} catch (Exception e) {
+		}
+		splash.dispose();
+		Debug.log(3, "Sikuli-IDE startup: " + ((new Date()).getTime() - start));
+		setVisible(true);
+		_mainSplitPane.setDividerLocation(0.6);
+		return; // as breakpoint
+	}
+
+	public static synchronized SikuliIDE getInstance(String args[]) {
+		if (_instance == null) {
+			_instance = new SikuliIDE(args);
 //TODO restore selected tab
-
-    autoCheckUpdate();
-
-    if (_mainPane.getTabCount() == 0) {
-      (new FileAction()).doNew(null);
-    }
-    _mainPane.setSelectedIndex(0);
-
-    _inited = true;
-    try {
-      getCurrentCodePane().requestFocus();
-    } catch (Exception e) {
-    }
-    splash.dispose();
-    Debug.log(3, "Sikuli-IDE startup: " + ((new Date()).getTime() - start));
-    setVisible(true);
-    _mainSplitPane.setDividerLocation(0.6);
-    return; // as breakpoint
-  }
-
-  public static synchronized SikuliIDE getInstance(String args[]) {
-    if (_instance == null) {
-      _instance = new SikuliIDE(args);
-    }
-    return _instance;
-  }
-
-  public static synchronized SikuliIDE getInstance() {
-    return getInstance(null);
-  }
-
-  @Override
-  public void setTitle(String title) {
-    super.setTitle(SikuliIDESettings.SikuliVersion + " - " + title);
-  }
-
-  static private void initNativeLayer() {
-    String os = "unknown";
-    if (Settings.isWindows()) {
-      os = "Windows";
-    } else if (Settings.isMac()) {
-      os = "Mac";
-    } else if (Settings.isLinux()) {
-      os = "Linux";
-    }
-    String className = "org.sikuli.ide.NativeLayerFor" + os;
-
-    try {
-      Class c = Class.forName(className);
-      Constructor constr = c.getConstructor();
-      _native = (NativeLayer) constr.newInstance();
-    } catch (Exception e) {
-      log(-1, "Reflection problem: org.sikuli.ide.NativeLayerFor...!\nError: %s", e.getMessage());
-    }
-  }
-
-  private boolean saveSession(int action, boolean quitting) {
-    int nTab = _mainPane.getTabCount();
-    StringBuilder sbuf = new StringBuilder();
-    for (int tabIndex = 0; tabIndex < nTab; tabIndex++) {
-      try {
-        JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
-        EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
-        if (action == WARNING_DO_NOTHING) {
-          if (quitting) {
-            codePane.setDirty(false);
-            if (codePane.isSourceBundleTemp()) {
-              FileManager.deleteTempDir(codePane.getSrcBundle());
-            }
-          }
-          if (codePane.getCurrentFilename() == null) {
-            continue;
-          }
-        } else if (codePane.isDirty()) {
-          if (!(new FileAction()).doSaveIntern(tabIndex)) {
-            if (quitting) {
-              codePane.setDirty(false);
-            }
-            continue;
-          }
-        }
-        if (action == IS_SAVE_ALL) {
-          continue;
-        }
-        File f = codePane.getCurrentFile();
-        if (f != null) {
-          String bundlePath = codePane.getSrcBundle();
-          Debug.log(5, "save session: " + bundlePath);
-          if (tabIndex != 0) {
-            sbuf.append(";");
-          }
-          sbuf.append(bundlePath);
-        }
-      } catch (Exception e) {
-        log(-1, "Problem while trying to save all changed-not-saved scripts!\nError: %s", e.getMessage());
-        return false;
-      }
-    }
-    PreferencesUser.getInstance().setIdeSession(sbuf.toString());
-    return true;
-  }
-
-  private void restoreSession() {
-    String session_str = PreferencesUser.getInstance().getIdeSession();
-    String[] filenames = null;
-    if (session_str == null && loadScript == null) {
-      return;
-    }
-    filenames = session_str.split(";");
-    for (int i = 0; i < filenames.length; i++) {
-      if (filenames[i].isEmpty()) {
-        continue;
-      }
-      Debug.log(3, "restore session at %d: " + filenames[i], restoredScripts+1);
-      File f = new File(filenames[i]);
-      if (f.exists()) {
-        if (loadFile(filenames[i])) {
-          restoredScripts += 1;
-        }
-      }
-    }
-    if (loadScript == null) {
-      return;
-    }
-    int ao;
-    for (int i = 0; i < loadScript.length; i++) {
-      if (loadScript[i].isEmpty()) {
-        continue;
-      }
-      File f = new File(loadScript[i]);
-      if (f.exists()) {
-        if (loadFile(loadScript[i])) {
-          ao = isAlreadyOpen(getCurrentCodePane().getCurrentSrcDir());
-          if (ao < 0) {
-            restoredScripts += 1;
-            Debug.log(3, "preload script at %d: " + loadScript[i], restoredScripts+1);
-          } else {
-            _mainPane.remove(ao);
-            Debug.log(3, "preload session script at %d: " + loadScript[i], restoredScripts+1);
-          }
-        }
-      }
-    }
-  }
+			_instance.restoreSession();
+			_instance.makeTabNull();
+		}
+		return _instance;
+	}
+
+	public static synchronized SikuliIDE getInstance() {
+		return getInstance(null);
+	}
+
+	public void makeTabNull() {
+		if (_mainPane.getTabCount() == 0) {
+			(new FileAction()).doNew(null);
+		}
+		_mainPane.setSelectedIndex(0);
+	}
+
+	@Override
+	public void setTitle(String title) {
+		super.setTitle(SikuliIDESettings.SikuliVersion + " - " + title);
+	}
+
+	static private void initNativeLayer() {
+		String os = "unknown";
+		if (Settings.isWindows()) {
+			os = "Windows";
+		} else if (Settings.isMac()) {
+			os = "Mac";
+		} else if (Settings.isLinux()) {
+			os = "Linux";
+		}
+		String className = "org.sikuli.ide.NativeLayerFor" + os;
+
+		try {
+			Class c = Class.forName(className);
+			Constructor constr = c.getConstructor();
+			_native = (NativeLayer) constr.newInstance();
+		} catch (Exception e) {
+			log(-1, "Reflection problem: org.sikuli.ide.NativeLayerFor...!\nError: %s", e.getMessage());
+		}
+	}
+
+	private boolean saveSession(int action, boolean quitting) {
+		int nTab = _mainPane.getTabCount();
+		StringBuilder sbuf = new StringBuilder();
+		for (int tabIndex = 0; tabIndex < nTab; tabIndex++) {
+			try {
+				JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
+				EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
+				if (action == WARNING_DO_NOTHING) {
+					if (quitting) {
+						codePane.setDirty(false);
+						if (codePane.isSourceBundleTemp()) {
+							FileManager.deleteTempDir(codePane.getSrcBundle());
+						}
+					}
+					if (codePane.getCurrentFilename() == null) {
+						continue;
+					}
+				} else if (codePane.isDirty()) {
+					if (!(new FileAction()).doSaveIntern(tabIndex)) {
+						if (quitting) {
+							codePane.setDirty(false);
+						}
+						continue;
+					}
+				}
+				if (action == IS_SAVE_ALL) {
+					continue;
+				}
+				File f = codePane.getCurrentFile();
+				if (f != null) {
+					String bundlePath = codePane.getSrcBundle();
+					Debug.log(5, "save session: " + bundlePath);
+					if (tabIndex != 0) {
+						sbuf.append(";");
+					}
+					sbuf.append(bundlePath);
+				}
+			} catch (Exception e) {
+				log(-1, "Problem while trying to save all changed-not-saved scripts!\nError: %s", e.getMessage());
+				return false;
+			}
+		}
+		PreferencesUser.getInstance().setIdeSession(sbuf.toString());
+		return true;
+	}
+
+	private void restoreSession() {
+		String session_str = PreferencesUser.getInstance().getIdeSession();
+		String[] filenames = null;
+		if (session_str == null && loadScript == null) {
+			return;
+		}
+		filenames = session_str.split(";");
+		for (int i = 0; i < filenames.length; i++) {
+			if (filenames[i].isEmpty()) {
+				continue;
+			}
+			Debug.log(3, "restore session at %d: " + filenames[i], restoredScripts + 1);
+			File f = new File(filenames[i]);
+			if (f.exists()) {
+				if (loadFile(filenames[i])) {
+					restoredScripts += 1;
+				}
+			}
+		}
+		if (loadScript == null) {
+			return;
+		}
+		int ao;
+		for (int i = 0; i < loadScript.length; i++) {
+			if (loadScript[i].isEmpty()) {
+				continue;
+			}
+			File f = new File(loadScript[i]);
+			if (f.exists()) {
+				if (loadFile(loadScript[i])) {
+					ao = isAlreadyOpen(getCurrentCodePane().getCurrentSrcDir());
+					if (ao < 0) {
+						restoredScripts += 1;
+						Debug.log(3, "preload script at %d: " + loadScript[i], restoredScripts + 1);
+					} else {
+						_mainPane.remove(ao);
+						Debug.log(3, "preload session script at %d: " + loadScript[i], restoredScripts + 1);
+					}
+				}
+			}
+		}
+	}
 
   //</editor-fold>
-  //<editor-fold defaultstate="collapsed" desc="Support SikuliIDE">
-  public JMenu getFileMenu() {
-    return _fileMenu;
-  }
-
-  public JMenu getRunMenu() {
-    return _runMenu;
-  }
-
-  public CloseableTabbedPane getTabPane() {
-    return _mainPane;
-  }
-
-  public EditorPane getCurrentCodePane() {
-    if (_mainPane.getSelectedIndex() == -1) {
-      return null;
-    }
-    JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
-    EditorPane ret = (EditorPane) scrPane.getViewport().getView();
-    return ret;
-  }
-
-  public void setCurrentFileTabTitle(String fname) {
-    int tabIndex = _mainPane.getSelectedIndex();
-    setFileTabTitle(fname, tabIndex);
-  }
-
-  public String getCurrentFileTabTitle() {
-    String fname = _mainPane.getTitleAt(_mainPane.getSelectedIndex());
-    if (fname.startsWith("*")) {
-      return fname.substring(1);
-    } else {
-      return fname;
-    }
-  }
-
-  public void setFileTabTitle(String fname, int tabIndex) {
-    String fullName = fname;
-    if (fname.endsWith("/")) {
-      fname = fname.substring(0, fname.length() - 1);
-    }
-    fname = fname.substring(fname.lastIndexOf("/") + 1);
-    fname = fname.substring(0, fname.lastIndexOf("."));
-    _mainPane.setTitleAt(tabIndex, fname);
-    this.setTitle(fullName);
-  }
-
-  public void setCurrentFileTabTitleDirty(boolean isDirty) {
-    int i = _mainPane.getSelectedIndex();
-    String title = _mainPane.getTitleAt(i);
-    if (!isDirty && title.startsWith("*")) {
-      title = title.substring(1);
-      _mainPane.setTitleAt(i, title);
-    } else if (isDirty && !title.startsWith("*")) {
-      title = "*" + title;
-      _mainPane.setTitleAt(i, title);
-    }
-  }
-
-  public boolean loadFile(String file) {
-    (new FileAction()).doNew(null);
-    getCurrentCodePane().loadFile(file);
-    if (getCurrentCodePane().hasEditingFile()) {
-      setCurrentFileTabTitle(file);
-      return true;
-    }
-    Debug.error("Can't load file " + file);
+	//<editor-fold defaultstate="collapsed" desc="Support SikuliIDE">
+	public JMenu getFileMenu() {
+		return _fileMenu;
+	}
+
+	public JMenu getRunMenu() {
+		return _runMenu;
+	}
+
+	public CloseableTabbedPane getTabPane() {
+		return _mainPane;
+	}
+
+	public EditorPane getCurrentCodePane() {
+		if (_mainPane.getSelectedIndex() == -1) {
+			return null;
+		}
+		JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
+		EditorPane ret = (EditorPane) scrPane.getViewport().getView();
+		return ret;
+	}
+
+	public void setCurrentFileTabTitle(String fname) {
+		int tabIndex = _mainPane.getSelectedIndex();
+		setFileTabTitle(fname, tabIndex);
+	}
+
+	public String getCurrentFileTabTitle() {
+		String fname = _mainPane.getTitleAt(_mainPane.getSelectedIndex());
+		if (fname.startsWith("*")) {
+			return fname.substring(1);
+		} else {
+			return fname;
+		}
+	}
+
+	public void setFileTabTitle(String fname, int tabIndex) {
+		String fullName = fname;
+		if (fname.endsWith("/")) {
+			fname = fname.substring(0, fname.length() - 1);
+		}
+		fname = fname.substring(fname.lastIndexOf("/") + 1);
+		fname = fname.substring(0, fname.lastIndexOf("."));
+		_mainPane.setTitleAt(tabIndex, fname);
+		this.setTitle(fullName);
+	}
+
+	public void setCurrentFileTabTitleDirty(boolean isDirty) {
+		int i = _mainPane.getSelectedIndex();
+		String title = _mainPane.getTitleAt(i);
+		if (!isDirty && title.startsWith("*")) {
+			title = title.substring(1);
+			_mainPane.setTitleAt(i, title);
+		} else if (isDirty && !title.startsWith("*")) {
+			title = "*" + title;
+			_mainPane.setTitleAt(i, title);
+		}
+	}
+
+	public boolean loadFile(String file) {
+		(new FileAction()).doNew(null);
+		getCurrentCodePane().loadFile(file);
+		if (getCurrentCodePane().hasEditingFile()) {
+			setCurrentFileTabTitle(file);
+			return true;
+		}
+		Debug.error("Can't load file " + file);
 //    (new FileAction()).doCloseTab(null);
-    return false;
-  }
-
-  public ArrayList<String> getOpenedFilenames() {
-    int nTab = _mainPane.getTabCount();
-    File file = null;
-    String filePath;
-    ArrayList<String> filenames = new ArrayList<String>(0);
-    if (nTab > 0) {
-      for (int i = 0; i < nTab; i++) {
-        JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
-        EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
-        file = codePane.getCurrentFile(false);
-        if (file != null) {
-          filePath = FileManager.slashify(file.getAbsolutePath(), false);
-          filePath = filePath.substring(0, filePath.lastIndexOf("/"));
-          filenames.add(filePath);
-        } else {
-          filenames.add("");
-        }
-      }
-    }
-    return filenames;
-  }
-
-  public int isAlreadyOpen(String filename) {
-    int aot = getOpenedFilenames().indexOf(filename);
-    if (aot > -1 && aot < (_mainPane.getTabCount() - 1)) {
-      alreadyOpenedTab = aot;
-      return aot;
-    }
-    return -1;
-  }
-
-  private void autoCheckUpdate() {
-    PreferencesUser pref = PreferencesUser.getInstance();
-    if (!pref.getCheckUpdate()) {
-      return;
-    }
-    long last_check = pref.getCheckUpdateTime();
-    long now = (new Date()).getTime();
-    if (now - last_check > 1000 * 604800) {
-      Debug.log(3, "autocheck update");
-      (new HelpAction()).checkUpdate(true);
-    }
-    pref.setCheckUpdateTime();
-  }
-
-  public boolean isRunningScript() {
-    return ideIsRunningScript;
-  }
-
-  public void setIsRunningScript(boolean state) {
-    ideIsRunningScript = state;
-  }
-
-  protected boolean doBeforeRun() {
-    int action;
-    if (checkDirtyPanes()) {
-      if (prefs.getPrefMoreRunSave()) {
-        action = WARNING_ACCEPTED;
-      } else {
-        action = askForSaveAll("Run");
-        if (action < 0) {
-          return false;
-        }
-      }
-      saveSession(action, false);
-    }
-    Settings.ActionLogs = prefs.getPrefMoreLogActions();
-    Settings.DebugLogs = prefs.getPrefMoreLogDebug();
-    Settings.InfoLogs = prefs.getPrefMoreLogInfo();
-    Settings.Highlight = prefs.getPrefMoreHighlight();
-    Settings.OcrTextSearch = prefs.getPrefMoreTextSearch();
-    Settings.OcrTextRead = prefs.getPrefMoreTextOCR();
-    return true;
-  }
-
-  protected boolean doBeforeQuit() {
-    if (checkDirtyPanes()) {
-      int action = askForSaveAll("Quit");
-      if (action < 0) {
-        return false;
-      }
-      return saveSession(action, true);
-    }
-    return saveSession(WARNING_DO_NOTHING, true);
-  }
-
-  private int askForSaveAll(String typ) {
+		return false;
+	}
+
+	public ArrayList<String> getOpenedFilenames() {
+		int nTab = _mainPane.getTabCount();
+		File file = null;
+		String filePath;
+		ArrayList<String> filenames = new ArrayList<String>(0);
+		if (nTab > 0) {
+			for (int i = 0; i < nTab; i++) {
+				JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
+				EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
+				file = codePane.getCurrentFile(false);
+				if (file != null) {
+					filePath = FileManager.slashify(file.getAbsolutePath(), false);
+					filePath = filePath.substring(0, filePath.lastIndexOf("/"));
+					filenames.add(filePath);
+				} else {
+					filenames.add("");
+				}
+			}
+		}
+		return filenames;
+	}
+
+	public int isAlreadyOpen(String filename) {
+		int aot = getOpenedFilenames().indexOf(filename);
+		if (aot > -1 && aot < (_mainPane.getTabCount() - 1)) {
+			alreadyOpenedTab = aot;
+			return aot;
+		}
+		return -1;
+	}
+
+	private void autoCheckUpdate() {
+		PreferencesUser pref = PreferencesUser.getInstance();
+		if (!pref.getCheckUpdate()) {
+			return;
+		}
+		long last_check = pref.getCheckUpdateTime();
+		long now = (new Date()).getTime();
+		if (now - last_check > 1000 * 604800) {
+			Debug.log(3, "autocheck update");
+			(new HelpAction()).checkUpdate(true);
+		}
+		pref.setCheckUpdateTime();
+	}
+
+	public boolean isRunningScript() {
+		return ideIsRunningScript;
+	}
+
+	public void setIsRunningScript(boolean state) {
+		ideIsRunningScript = state;
+	}
+
+	protected boolean doBeforeRun() {
+		int action;
+		if (checkDirtyPanes()) {
+			if (prefs.getPrefMoreRunSave()) {
+				action = WARNING_ACCEPTED;
+			} else {
+				action = askForSaveAll("Run");
+				if (action < 0) {
+					return false;
+				}
+			}
+			saveSession(action, false);
+		}
+		Settings.ActionLogs = prefs.getPrefMoreLogActions();
+		Settings.DebugLogs = prefs.getPrefMoreLogDebug();
+		Settings.InfoLogs = prefs.getPrefMoreLogInfo();
+		Settings.Highlight = prefs.getPrefMoreHighlight();
+		Settings.OcrTextSearch = prefs.getPrefMoreTextSearch();
+		Settings.OcrTextRead = prefs.getPrefMoreTextOCR();
+		return true;
+	}
+
+	protected boolean doBeforeQuit() {
+		if (checkDirtyPanes()) {
+			int action = askForSaveAll("Quit");
+			if (action < 0) {
+				return false;
+			}
+			return saveSession(action, true);
+		}
+		return saveSession(WARNING_DO_NOTHING, true);
+	}
+
+	private int askForSaveAll(String typ) {
 //TODO I18N
-    String warn = "Some scripts are not saved yet!";
-    String title = SikuliIDEI18N._I("dlgAskCloseTab");
-    String[] options = new String[3];
-    options[WARNING_DO_NOTHING] = typ + " immediately";
-    options[WARNING_ACCEPTED] = "Save all and " + typ;
-    options[WARNING_CANCEL] = SikuliIDEI18N._I("cancel");
-    int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
-    if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
-      return -1;
-    }
-    return ret;
-  }
-
-  public void doAbout() {
-    //TODO full featured About
-    String info = "You are running " + Settings.SikuliVersionIDE
-            + "\n\nNeed help? -> start with Help Menu\n\n"
-            + "*** Have fun ;-)\n\n"
-            + "Tsung-Hsiang Chang aka vgod\n"
-            + "Tom Yeh\n"
-            + "Raimund Hocke aka RaiMan\n\n"
-            + Settings.versionMonth
-            + "\n\nBuild: " + RunSetup.timestampBuilt;
-    JOptionPane.showMessageDialog(this, info,
-            "Sikuli About", JOptionPane.PLAIN_MESSAGE);
-  }
+		String warn = "Some scripts are not saved yet!";
+		String title = SikuliIDEI18N._I("dlgAskCloseTab");
+		String[] options = new String[3];
+		options[WARNING_DO_NOTHING] = typ + " immediately";
+		options[WARNING_ACCEPTED] = "Save all and " + typ;
+		options[WARNING_CANCEL] = SikuliIDEI18N._I("cancel");
+		int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
+		if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
+			return -1;
+		}
+		return ret;
+	}
+
+	public void doAbout() {
+		//TODO full featured About
+		String info = "You are running " + Settings.SikuliVersionIDE
+						+ "\n\nNeed help? -> start with Help Menu\n\n"
+						+ "*** Have fun ;-)\n\n"
+						+ "Tsung-Hsiang Chang aka vgod\n"
+						+ "Tom Yeh\n"
+						+ "Raimund Hocke aka RaiMan\n\n"
+						+ Settings.versionMonth
+						+ "\n\nBuild: " + RunSetup.timestampBuilt;
+		JOptionPane.showMessageDialog(this, info,
+						"Sikuli About", JOptionPane.PLAIN_MESSAGE);
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="isInited --- RaiMan not used">
-  public boolean isInited() {
-    return _inited;
-  }
-  //</editor-fold>
-
-  private JMenuItem createMenuItem(JMenuItem item, KeyStroke shortcut, ActionListener listener) {
-    if (shortcut != null) {
-      item.setAccelerator(shortcut);
-    }
-    item.addActionListener(listener);
-    return item;
-  }
-
-  private JMenuItem createMenuItem(String name, KeyStroke shortcut, ActionListener listener) {
-    JMenuItem item = new JMenuItem(name);
-    return createMenuItem(item, shortcut, listener);
-  }
-
-  class MenuAction implements ActionListener {
-
-    protected Method actMethod = null;
-    protected String action;
-
-    public MenuAction() {
-    }
-
-    public MenuAction(String item) throws NoSuchMethodException {
-      Class[] paramsWithEvent = new Class[1];
-      try {
-        paramsWithEvent[0] = Class.forName("java.awt.event.ActionEvent");
-        actMethod = this.getClass().getMethod(item, paramsWithEvent);
-        action = item;
-      } catch (ClassNotFoundException cnfe) {
-        log(-1, "Can't find menu action: " + cnfe);
-      }
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-      if (actMethod != null) {
-        try {
-          Debug.log(3, "MenuAction." + action);
-          Object[] params = new Object[1];
-          params[0] = e;
-          actMethod.invoke(this, params);
-        } catch (Exception ex) {
-          log(-1, "Problem when trying to invoke menu action %s\nError: %s",
-                  action, ex.getMessage());
-        }
-      }
-    }
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="Init FileMenu">
-  private void initFileMenu() throws NoSuchMethodException {
-    JMenuItem jmi;
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _fileMenu.setMnemonic(java.awt.event.KeyEvent.VK_F);
-
-    if (!Settings.isMac()) {
-      _fileMenu.add(createMenuItem("About SikuliX",
-              KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
-              new FileAction(FileAction.ABOUT)));
-      _fileMenu.addSeparator();
-    }
-
-    _fileMenu.add(createMenuItem(_I("menuFileNew"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, scMask),
-            new FileAction(FileAction.NEW)));
-
-    jmi = _fileMenu.add(createMenuItem(_I("menuFileOpen"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, scMask),
-            new FileAction(FileAction.OPEN)));
-    jmi.setName("OPEN");
-
-    if (Settings.isMac() && !Settings.handlesMacBundles) {
-      _fileMenu.add(createMenuItem("Open folder.sikuli ...",
-              null,
-              //            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, scMask),
-              new FileAction(FileAction.OPEN_FOLDER)));
-    }
-
-    jmi = _fileMenu.add(createMenuItem(_I("menuFileSave"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, scMask),
-            new FileAction(FileAction.SAVE)));
-    jmi.setName("SAVE");
-
-    jmi = _fileMenu.add(createMenuItem(_I("menuFileSaveAs"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
-            InputEvent.SHIFT_MASK | scMask),
-            new FileAction(FileAction.SAVE_AS)));
-    jmi.setName("SAVE_AS");
-
-    if (Settings.isMac() && !Settings.handlesMacBundles) {
-      _fileMenu.add(createMenuItem(_I("Save as folder.sikuli ..."),
-              //            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
-              //            InputEvent.SHIFT_MASK | scMask),
-              null,
-              new FileAction(FileAction.SAVE_AS_FOLDER)));
-    }
+	//<editor-fold defaultstate="collapsed" desc="isInited --- RaiMan not used">
+	public boolean isInited() {
+		return _inited;
+	}
+	//</editor-fold>
+
+	private JMenuItem createMenuItem(JMenuItem item, KeyStroke shortcut, ActionListener listener) {
+		if (shortcut != null) {
+			item.setAccelerator(shortcut);
+		}
+		item.addActionListener(listener);
+		return item;
+	}
+
+	private JMenuItem createMenuItem(String name, KeyStroke shortcut, ActionListener listener) {
+		JMenuItem item = new JMenuItem(name);
+		return createMenuItem(item, shortcut, listener);
+	}
+
+	class MenuAction implements ActionListener {
+
+		protected Method actMethod = null;
+		protected String action;
+
+		public MenuAction() {
+		}
+
+		public MenuAction(String item) throws NoSuchMethodException {
+			Class[] paramsWithEvent = new Class[1];
+			try {
+				paramsWithEvent[0] = Class.forName("java.awt.event.ActionEvent");
+				actMethod = this.getClass().getMethod(item, paramsWithEvent);
+				action = item;
+			} catch (ClassNotFoundException cnfe) {
+				log(-1, "Can't find menu action: " + cnfe);
+			}
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			if (actMethod != null) {
+				try {
+					Debug.log(3, "MenuAction." + action);
+					Object[] params = new Object[1];
+					params[0] = e;
+					actMethod.invoke(this, params);
+				} catch (Exception ex) {
+					log(-1, "Problem when trying to invoke menu action %s\nError: %s",
+									action, ex.getMessage());
+				}
+			}
+		}
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="Init FileMenu">
+	private void initFileMenu() throws NoSuchMethodException {
+		JMenuItem jmi;
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_fileMenu.setMnemonic(java.awt.event.KeyEvent.VK_F);
+
+		if (!Settings.isMac()) {
+			_fileMenu.add(createMenuItem("About SikuliX",
+							KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
+							new FileAction(FileAction.ABOUT)));
+			_fileMenu.addSeparator();
+		}
+
+		_fileMenu.add(createMenuItem(_I("menuFileNew"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, scMask),
+						new FileAction(FileAction.NEW)));
+
+		jmi = _fileMenu.add(createMenuItem(_I("menuFileOpen"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, scMask),
+						new FileAction(FileAction.OPEN)));
+		jmi.setName("OPEN");
+
+		if (Settings.isMac() && !Settings.handlesMacBundles) {
+			_fileMenu.add(createMenuItem("Open folder.sikuli ...",
+							null,
+							//            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, scMask),
+							new FileAction(FileAction.OPEN_FOLDER)));
+		}
+
+		jmi = _fileMenu.add(createMenuItem(_I("menuFileSave"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, scMask),
+						new FileAction(FileAction.SAVE)));
+		jmi.setName("SAVE");
+
+		jmi = _fileMenu.add(createMenuItem(_I("menuFileSaveAs"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
+										InputEvent.SHIFT_MASK | scMask),
+						new FileAction(FileAction.SAVE_AS)));
+		jmi.setName("SAVE_AS");
+
+		if (Settings.isMac() && !Settings.handlesMacBundles) {
+			_fileMenu.add(createMenuItem(_I("Save as folder.sikuli ..."),
+							//            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
+							//            InputEvent.SHIFT_MASK | scMask),
+							null,
+							new FileAction(FileAction.SAVE_AS_FOLDER)));
+		}
 
 //TODO    _fileMenu.add(createMenuItem(_I("menuFileSaveAll"),
-    _fileMenu.add(createMenuItem("Save all",
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
-            InputEvent.CTRL_MASK | scMask),
-            new FileAction(FileAction.SAVE_ALL)));
-
-    _fileMenu.add(createMenuItem(_I("menuFileExport"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E,
-            InputEvent.SHIFT_MASK | scMask),
-            new FileAction(FileAction.EXPORT)));
-
-    jmi = _fileMenu.add(createMenuItem(_I("menuFileCloseTab"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, scMask),
-            new FileAction(FileAction.CLOSE_TAB)));
-    jmi.setName("CLOSE_TAB");
-
-    if (!Settings.isMac()) {
-      _fileMenu.addSeparator();
-      _fileMenu.add(createMenuItem(_I("menuFilePreferences"),
-              KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, scMask),
-              new FileAction(FileAction.PREFERENCES)));
-    }
-
-    if (!Settings.isMac()) {
-      _fileMenu.addSeparator();
-      _fileMenu.add(createMenuItem(_I("menuFileQuit"),
-              null, new FileAction(FileAction.QUIT)));
-    }
-  }
-
-  public FileAction getFileAction(int tabIndex) {
-    return new FileAction(tabIndex);
-  }
-
-  class FileAction extends MenuAction {
-
-    static final String ABOUT = "doAbout";
-    static final String NEW = "doNew";
-    static final String INSERT = "doInsert";
-    static final String OPEN = "doLoad";
-    static final String OPEN_FOLDER = "doLoadFolder";
-    static final String SAVE = "doSave";
-    static final String SAVE_AS = "doSaveAs";
-    static final String SAVE_AS_FOLDER = "doSaveAsFolder";
-    static final String SAVE_ALL = "doSaveAll";
-    static final String EXPORT = "doExport";
-    static final String CLOSE_TAB = "doCloseTab";
-    static final String PREFERENCES = "doPreferences";
-    static final String QUIT = "doQuit";
-    private int targetTab = -1;
-
-    public FileAction() {
-      super();
-    }
-
-    public FileAction(int tabIndex) {
-      super();
-      targetTab = tabIndex;
-    }
-
-    public FileAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void doAbout(ActionEvent ae) {
-      SikuliIDE.getInstance().doAbout();
-    }
-
-    public void doQuit(ActionEvent ae) {
-      SikuliIDE ide = SikuliIDE.getInstance();
-      if (!doBeforeQuit()) {
-        return;
-      }
-      while (true) {
-        EditorPane codePane = ide.getCurrentCodePane();
-        if (codePane == null) {
-          break;
-        }
-        if (!ide.closeCurrentTab()) {
-          return;
-        }
-      }
-      SikuliX.cleanUp(0);
-      HotkeyManager.getInstance().cleanUp();
-      System.exit(0);
-    }
-
-    public void doPreferences(ActionEvent ae) {
-      SikuliIDE.getInstance().showPreferencesWindow();
-    }
-
-    public void doNew(ActionEvent ae) {
-      doNew(ae, -1).initBeforeLoad(null);
-    }
-
-    public EditorPane doNew(ActionEvent ae, int tabIndex) {
-      EditorPane codePane = new EditorPane(SikuliIDE.getInstance());
-      JScrollPane scrPane = new JScrollPane(codePane);
-      lineNumberColumn = new EditorLineNumberView(codePane);
-      scrPane.setRowHeaderView(lineNumberColumn);
-      if (ae == null) {
-        if (tabIndex < 0 || tabIndex >= _mainPane.getTabCount()) {
-          _mainPane.addTab(_I("tabUntitled"), scrPane);
-        } else {
-          _mainPane.addTab(_I("tabUntitled"), scrPane, tabIndex);
-        }
-        _mainPane.setSelectedIndex(tabIndex < 0 ? _mainPane.getTabCount() - 1 : tabIndex);
-      } else {
-        _mainPane.addTab(_I("tabUntitled"), scrPane, 0);
-        _mainPane.setSelectedIndex(0);
-      }
-      codePane.getSrcBundle();
-      codePane.requestFocus();
+		_fileMenu.add(createMenuItem("Save all",
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
+										InputEvent.CTRL_MASK | scMask),
+						new FileAction(FileAction.SAVE_ALL)));
+
+		_fileMenu.add(createMenuItem(_I("menuFileExport"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E,
+										InputEvent.SHIFT_MASK | scMask),
+						new FileAction(FileAction.EXPORT)));
+
+		jmi = _fileMenu.add(createMenuItem(_I("menuFileCloseTab"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, scMask),
+						new FileAction(FileAction.CLOSE_TAB)));
+		jmi.setName("CLOSE_TAB");
+
+		if (!Settings.isMac()) {
+			_fileMenu.addSeparator();
+			_fileMenu.add(createMenuItem(_I("menuFilePreferences"),
+							KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, scMask),
+							new FileAction(FileAction.PREFERENCES)));
+		}
+
+		if (!Settings.isMac()) {
+			_fileMenu.addSeparator();
+			_fileMenu.add(createMenuItem(_I("menuFileQuit"),
+							null, new FileAction(FileAction.QUIT)));
+		}
+	}
+
+	public FileAction getFileAction(int tabIndex) {
+		return new FileAction(tabIndex);
+	}
+
+	class FileAction extends MenuAction {
+
+		static final String ABOUT = "doAbout";
+		static final String NEW = "doNew";
+		static final String INSERT = "doInsert";
+		static final String OPEN = "doLoad";
+		static final String OPEN_FOLDER = "doLoadFolder";
+		static final String SAVE = "doSave";
+		static final String SAVE_AS = "doSaveAs";
+		static final String SAVE_AS_FOLDER = "doSaveAsFolder";
+		static final String SAVE_ALL = "doSaveAll";
+		static final String EXPORT = "doExport";
+		static final String CLOSE_TAB = "doCloseTab";
+		static final String PREFERENCES = "doPreferences";
+		static final String QUIT = "doQuit";
+		private int targetTab = -1;
+
+		public FileAction() {
+			super();
+		}
+
+		public FileAction(int tabIndex) {
+			super();
+			targetTab = tabIndex;
+		}
+
+		public FileAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void doAbout(ActionEvent ae) {
+			SikuliIDE.getInstance().doAbout();
+		}
+
+		public void doQuit(ActionEvent ae) {
+			SikuliIDE ide = SikuliIDE.getInstance();
+			if (!doBeforeQuit()) {
+				return;
+			}
+			while (true) {
+				EditorPane codePane = ide.getCurrentCodePane();
+				if (codePane == null) {
+					break;
+				}
+				if (!ide.closeCurrentTab()) {
+					return;
+				}
+			}
+			SikuliX.cleanUp(0);
+			HotkeyManager.getInstance().cleanUp();
+			System.exit(0);
+		}
+
+		public void doPreferences(ActionEvent ae) {
+			SikuliIDE.getInstance().showPreferencesWindow();
+		}
+
+		public void doNew(ActionEvent ae) {
+			doNew(ae, -1).initBeforeLoad(null);
+		}
+
+		public EditorPane doNew(ActionEvent ae, int tabIndex) {
+			EditorPane codePane = new EditorPane(SikuliIDE.getInstance());
+			JScrollPane scrPane = new JScrollPane(codePane);
+			lineNumberColumn = new EditorLineNumberView(codePane);
+			scrPane.setRowHeaderView(lineNumberColumn);
+			if (ae == null) {
+				if (tabIndex < 0 || tabIndex >= _mainPane.getTabCount()) {
+					_mainPane.addTab(_I("tabUntitled"), scrPane);
+				} else {
+					_mainPane.addTab(_I("tabUntitled"), scrPane, tabIndex);
+				}
+				_mainPane.setSelectedIndex(tabIndex < 0 ? _mainPane.getTabCount() - 1 : tabIndex);
+			} else {
+				_mainPane.addTab(_I("tabUntitled"), scrPane, 0);
+				_mainPane.setSelectedIndex(0);
+			}
+			codePane.getSrcBundle();
+			codePane.requestFocus();
 			return codePane;
-    }
-
-    public void doInsert(ActionEvent ae) {
-      doLoad(null);
-    }
-
-    public void doLoad(ActionEvent ae) {
-      boolean accessingAsFile = false;
-      if (Settings.isMac()) {
-        accessingAsFile = !ACCESSING_AS_FOLDER;
-        ACCESSING_AS_FOLDER = false;
-      }
-      alreadyOpenedTab = _mainPane.getSelectedIndex();
-      String fname = _mainPane.getLastClosed();
-      try {
-        doNew(null, targetTab);
-        EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-        if (ae != null || fname == null) {
-          codePane.isSourceBundleTemp();
-          fname = codePane.loadFile(accessingAsFile);
-        } else {
-          codePane.loadFile(fname);
-          if (codePane.hasEditingFile()) {
-            setCurrentFileTabTitle(fname);
-          } else {
-            fname = null;
-          }
-        }
-        if (fname != null) {
-          SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
-        } else {
-          if (ae != null) {
-            doCloseTab(null);
-          }
-          _mainPane.setSelectedIndex(alreadyOpenedTab);
-        }
-      } catch (IOException eio) {
-        log(-1, "Problem when trying to load %s\nError: %s",
-                fname, eio.getMessage());
-      }
-    }
-
-    public void doLoadFolder(ActionEvent ae) {
-      Debug.log(3, "IDE: doLoadFolder requested");
-      ACCESSING_AS_FOLDER = true;
-      doLoad(ae);
-    }
-
-    public void doSave(ActionEvent ae) {
-      String fname = null;
-      try {
-        EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-        fname = codePane.saveFile();
-        if (fname != null) {
-          fname = codePane.getSrcBundle();
-          SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
-          _mainPane.setLastClosed(fname);
-        }
-      } catch (IOException eio) {
-        log(-1, "Problem when trying to save %s\nError: %s",
-                fname, eio.getMessage());
-      }
-    }
-
-    public boolean doSaveIntern(int tabIndex) {
-      int currentTab = _mainPane.getSelectedIndex();
-      _mainPane.setSelectedIndex(tabIndex);
-      boolean retval = true;
-      JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
-      EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
-      String fname = null;
-      try {
-        fname = codePane.saveFile();
-        if (fname != null) {
-          SikuliIDE.getInstance().setFileTabTitle(fname, tabIndex);
-        } else {
-          retval = false;
-        }
-      } catch (IOException eio) {
-        log(-1, "Problem when trying to save %s\nError: %s",
-                fname, eio.getMessage());
-        retval = false;
-      }
-      _mainPane.setSelectedIndex(currentTab);
-      return retval;
-    }
-
-    public void doSaveAs(ActionEvent ae) {
-      boolean accessingAsFile = false;
-      if (Settings.isMac()) {
-        accessingAsFile = !ACCESSING_AS_FOLDER;
-        ACCESSING_AS_FOLDER = false;
-      }
-      String fname = null;
-      try {
-        EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-        fname = codePane.saveAsFile(accessingAsFile);
-        if (fname != null) {
-          SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
-        }
-      } catch (IOException eio) {
-        log(-1, "Problem when trying to save %s\nError: %s",
-                fname, eio.getMessage());
-      }
-    }
-
-    public void doSaveAsFolder(ActionEvent ae) {
-      Debug.log(3, "IDE: doSaveAsFolder requested");
-      ACCESSING_AS_FOLDER = true;
-      doSaveAs(ae);
-    }
-
-    public void doSaveAll(ActionEvent ae) {
-      Debug.log(3, "IDE: doSaveAll requested");
-      if (!checkDirtyPanes()) {
-        return;
-      }
-      saveSession(IS_SAVE_ALL, false);
-    }
-
-    public void doExport(ActionEvent ae) {
-      String fname = null;
-      try {
-        EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-        fname = codePane.exportAsZip();
-      } catch (Exception ex) {
-        log(-1, "Problem when trying to save %s\nError: %s",
-                fname, ex.getMessage());
-      }
-    }
-
-    public void doCloseTab(ActionEvent ae) {
-      EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-      if (ae == null) {
-        _mainPane.remove(_mainPane.getSelectedIndex());
-        return;
-      }
-      try {
-        if (codePane.close()) {
-          _mainPane.remove(_mainPane.getSelectedIndex());
-        }
-      } catch (IOException e) {
-        Debug.info("Can't close this tab: " + e.getStackTrace());
-      }
-      codePane = SikuliIDE.getInstance().getCurrentCodePane();
-      if (codePane != null) {
-        codePane.requestFocus();
-      } else if (ae != null) {
-        (new FileAction()).doNew(null);
-      }
-    }
-  }
-
-  public void showPreferencesWindow() {
-    PreferencesWin pwin = new PreferencesWin();
-    pwin.setAlwaysOnTop(true);
-    pwin.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
-    if (!Settings.isJava7()) {
-      pwin.setLocation(SikuliIDE.getInstance().getLocation());
-    }
-    pwin.setVisible(true);
-  }
-
-  public boolean closeCurrentTab() {
-    EditorPane pane = getCurrentCodePane();
-    (new FileAction()).doCloseTab(null);
-    if (pane == getCurrentCodePane()) {
-      return false;
-    }
-    return true;
-  }
-
-  protected boolean quit() {
-    SikuliIDE ide = SikuliIDE.getInstance();
-    (new FileAction()).doQuit(null);
-    if (ide.getCurrentCodePane() == null) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  protected boolean checkDirtyPanes() {
-    for (int i = 0; i < _mainPane.getTabCount(); i++) {
-      try {
-        JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
-        EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
-        if (codePane.isDirty()) {
-          //RaiMan not used: getRootPane().putClientProperty("Window.documentModified", true);
-          return true;
-        }
-      } catch (Exception e) {
-        Debug.error("checkDirtyPanes: " + e.getMessage());
-      }
-    }
-    //RaiMan not used: getRootPane().putClientProperty("Window.documentModified", false);
-    return false;
-  }
+		}
+
+		public void doInsert(ActionEvent ae) {
+			doLoad(null);
+		}
+
+		public void doLoad(ActionEvent ae) {
+			boolean accessingAsFile = false;
+			if (Settings.isMac()) {
+				accessingAsFile = !ACCESSING_AS_FOLDER;
+				ACCESSING_AS_FOLDER = false;
+			}
+			alreadyOpenedTab = _mainPane.getSelectedIndex();
+			String fname = _mainPane.getLastClosed();
+			try {
+				doNew(null, targetTab);
+				EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+				if (ae != null || fname == null) {
+					codePane.isSourceBundleTemp();
+					fname = codePane.loadFile(accessingAsFile);
+				} else {
+					codePane.loadFile(fname);
+					if (codePane.hasEditingFile()) {
+						setCurrentFileTabTitle(fname);
+					} else {
+						fname = null;
+					}
+				}
+				if (fname != null) {
+					SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
+				} else {
+					if (ae != null) {
+						doCloseTab(null);
+					}
+					_mainPane.setSelectedIndex(alreadyOpenedTab);
+				}
+			} catch (IOException eio) {
+				log(-1, "Problem when trying to load %s\nError: %s",
+								fname, eio.getMessage());
+			}
+		}
+
+		public void doLoadFolder(ActionEvent ae) {
+			Debug.log(3, "IDE: doLoadFolder requested");
+			ACCESSING_AS_FOLDER = true;
+			doLoad(ae);
+		}
+
+		public void doSave(ActionEvent ae) {
+			String fname = null;
+			try {
+				EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+				fname = codePane.saveFile();
+				if (fname != null) {
+					fname = codePane.getSrcBundle();
+					SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
+					_mainPane.setLastClosed(fname);
+				}
+			} catch (IOException eio) {
+				log(-1, "Problem when trying to save %s\nError: %s",
+								fname, eio.getMessage());
+			}
+		}
+
+		public boolean doSaveIntern(int tabIndex) {
+			int currentTab = _mainPane.getSelectedIndex();
+			_mainPane.setSelectedIndex(tabIndex);
+			boolean retval = true;
+			JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
+			EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
+			String fname = null;
+			try {
+				fname = codePane.saveFile();
+				if (fname != null) {
+					SikuliIDE.getInstance().setFileTabTitle(fname, tabIndex);
+				} else {
+					retval = false;
+				}
+			} catch (IOException eio) {
+				log(-1, "Problem when trying to save %s\nError: %s",
+								fname, eio.getMessage());
+				retval = false;
+			}
+			_mainPane.setSelectedIndex(currentTab);
+			return retval;
+		}
+
+		public void doSaveAs(ActionEvent ae) {
+			boolean accessingAsFile = false;
+			if (Settings.isMac()) {
+				accessingAsFile = !ACCESSING_AS_FOLDER;
+				ACCESSING_AS_FOLDER = false;
+			}
+			String fname = null;
+			try {
+				EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+				fname = codePane.saveAsFile(accessingAsFile);
+				if (fname != null) {
+					SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
+				}
+			} catch (IOException eio) {
+				log(-1, "Problem when trying to save %s\nError: %s",
+								fname, eio.getMessage());
+			}
+		}
+
+		public void doSaveAsFolder(ActionEvent ae) {
+			Debug.log(3, "IDE: doSaveAsFolder requested");
+			ACCESSING_AS_FOLDER = true;
+			doSaveAs(ae);
+		}
+
+		public void doSaveAll(ActionEvent ae) {
+			Debug.log(3, "IDE: doSaveAll requested");
+			if (!checkDirtyPanes()) {
+				return;
+			}
+			saveSession(IS_SAVE_ALL, false);
+		}
+
+		public void doExport(ActionEvent ae) {
+			String fname = null;
+			try {
+				EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+				fname = codePane.exportAsZip();
+			} catch (Exception ex) {
+				log(-1, "Problem when trying to save %s\nError: %s",
+								fname, ex.getMessage());
+			}
+		}
+
+		public void doCloseTab(ActionEvent ae) {
+			EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+			if (ae == null) {
+				_mainPane.remove(_mainPane.getSelectedIndex());
+				return;
+			}
+			try {
+				if (codePane.close()) {
+					_mainPane.remove(_mainPane.getSelectedIndex());
+				}
+			} catch (IOException e) {
+				Debug.info("Can't close this tab: " + e.getStackTrace());
+			}
+			codePane = SikuliIDE.getInstance().getCurrentCodePane();
+			if (codePane != null) {
+				codePane.requestFocus();
+			} else if (ae != null) {
+				(new FileAction()).doNew(null);
+			}
+		}
+	}
+
+	public void showPreferencesWindow() {
+		PreferencesWin pwin = new PreferencesWin();
+		pwin.setAlwaysOnTop(true);
+		pwin.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+		if (!Settings.isJava7()) {
+			pwin.setLocation(SikuliIDE.getInstance().getLocation());
+		}
+		pwin.setVisible(true);
+	}
+
+	public boolean closeCurrentTab() {
+		EditorPane pane = getCurrentCodePane();
+		(new FileAction()).doCloseTab(null);
+		if (pane == getCurrentCodePane()) {
+			return false;
+		}
+		return true;
+	}
+
+	protected boolean quit() {
+		SikuliIDE ide = SikuliIDE.getInstance();
+		(new FileAction()).doQuit(null);
+		if (ide.getCurrentCodePane() == null) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	protected boolean checkDirtyPanes() {
+		for (int i = 0; i < _mainPane.getTabCount(); i++) {
+			try {
+				JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
+				EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
+				if (codePane.isDirty()) {
+					//RaiMan not used: getRootPane().putClientProperty("Window.documentModified", true);
+					return true;
+				}
+			} catch (Exception e) {
+				Debug.error("checkDirtyPanes: " + e.getMessage());
+			}
+		}
+		//RaiMan not used: getRootPane().putClientProperty("Window.documentModified", false);
+		return false;
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Init EditMenu">
-  private void initEditMenu() throws NoSuchMethodException {
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _editMenu.setMnemonic(java.awt.event.KeyEvent.VK_E);
-    JMenuItem undoItem = _editMenu.add(_undoAction);
-    undoItem.setAccelerator(
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask));
-    JMenuItem redoItem = _editMenu.add(_redoAction);
-    redoItem.setAccelerator(
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask | InputEvent.SHIFT_MASK));
-    _editMenu.addSeparator();
-
-    _editMenu.add(createMenuItem(_I("menuEditCut"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, scMask),
-            new EditAction(EditAction.CUT)));
-    _editMenu.add(createMenuItem(_I("menuEditCopy"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, scMask),
-            new EditAction(EditAction.COPY)));
-    _editMenu.add(createMenuItem(_I("menuEditPaste"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, scMask),
-            new EditAction(EditAction.PASTE)));
-    _editMenu.add(createMenuItem(_I("menuEditSelectAll"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
-            new EditAction(EditAction.SELECT_ALL)));
-    _editMenu.addSeparator();
-
-    JMenu findMenu = new JMenu(_I("menuFind"));
-    _findHelper = new FindAction();
-    findMenu.setMnemonic(KeyEvent.VK_F);
-    findMenu.add(createMenuItem(_I("menuFindFind"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, scMask),
-            new FindAction(FindAction.FIND)));
-    findMenu.add(createMenuItem(_I("menuFindFindNext"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask),
-            new FindAction(FindAction.FIND_NEXT)));
-    findMenu.add(createMenuItem(_I("menuFindFindPrev"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask | InputEvent.SHIFT_MASK),
-            new FindAction(FindAction.FIND_PREV)));
-    _editMenu.add(findMenu);
-    _editMenu.addSeparator();
-    _editMenu.add(createMenuItem(_I("menuEditIndent"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, 0),
-            new EditAction(EditAction.INDENT)));
-    _editMenu.add(createMenuItem(_I("menuEditUnIndent"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, InputEvent.SHIFT_MASK),
-            new EditAction(EditAction.UNINDENT)));
-  }
-
-  class EditAction extends MenuAction {
-
-    static final String CUT = "doCut";
-    static final String COPY = "doCopy";
-    static final String PASTE = "doPaste";
-    static final String SELECT_ALL = "doSelectAll";
-    static final String INDENT = "doIndent";
-    static final String UNINDENT = "doUnindent";
-
-    public EditAction() {
-      super();
-    }
-
-    public EditAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    private void performEditorAction(String action, ActionEvent ae) {
-      SikuliIDE ide = SikuliIDE.getInstance();
-      EditorPane pane = ide.getCurrentCodePane();
-      pane.getActionMap().get(action).actionPerformed(ae);
-    }
-
-    public void doCut(ActionEvent ae) {
+	//<editor-fold defaultstate="collapsed" desc="Init EditMenu">
+	private void initEditMenu() throws NoSuchMethodException {
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_editMenu.setMnemonic(java.awt.event.KeyEvent.VK_E);
+		JMenuItem undoItem = _editMenu.add(_undoAction);
+		undoItem.setAccelerator(
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask));
+		JMenuItem redoItem = _editMenu.add(_redoAction);
+		redoItem.setAccelerator(
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask | InputEvent.SHIFT_MASK));
+		_editMenu.addSeparator();
+
+		_editMenu.add(createMenuItem(_I("menuEditCut"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, scMask),
+						new EditAction(EditAction.CUT)));
+		_editMenu.add(createMenuItem(_I("menuEditCopy"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, scMask),
+						new EditAction(EditAction.COPY)));
+		_editMenu.add(createMenuItem(_I("menuEditPaste"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, scMask),
+						new EditAction(EditAction.PASTE)));
+		_editMenu.add(createMenuItem(_I("menuEditSelectAll"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
+						new EditAction(EditAction.SELECT_ALL)));
+		_editMenu.addSeparator();
+
+		JMenu findMenu = new JMenu(_I("menuFind"));
+		_findHelper = new FindAction();
+		findMenu.setMnemonic(KeyEvent.VK_F);
+		findMenu.add(createMenuItem(_I("menuFindFind"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, scMask),
+						new FindAction(FindAction.FIND)));
+		findMenu.add(createMenuItem(_I("menuFindFindNext"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask),
+						new FindAction(FindAction.FIND_NEXT)));
+		findMenu.add(createMenuItem(_I("menuFindFindPrev"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask | InputEvent.SHIFT_MASK),
+						new FindAction(FindAction.FIND_PREV)));
+		_editMenu.add(findMenu);
+		_editMenu.addSeparator();
+		_editMenu.add(createMenuItem(_I("menuEditIndent"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, 0),
+						new EditAction(EditAction.INDENT)));
+		_editMenu.add(createMenuItem(_I("menuEditUnIndent"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, InputEvent.SHIFT_MASK),
+						new EditAction(EditAction.UNINDENT)));
+	}
+
+	class EditAction extends MenuAction {
+
+		static final String CUT = "doCut";
+		static final String COPY = "doCopy";
+		static final String PASTE = "doPaste";
+		static final String SELECT_ALL = "doSelectAll";
+		static final String INDENT = "doIndent";
+		static final String UNINDENT = "doUnindent";
+
+		public EditAction() {
+			super();
+		}
+
+		public EditAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		private void performEditorAction(String action, ActionEvent ae) {
+			SikuliIDE ide = SikuliIDE.getInstance();
+			EditorPane pane = ide.getCurrentCodePane();
+			pane.getActionMap().get(action).actionPerformed(ae);
+		}
+
+		public void doCut(ActionEvent ae) {
 //TODO delete current line if no selection
-      performEditorAction(DefaultEditorKit.cutAction, ae);
-    }
+			performEditorAction(DefaultEditorKit.cutAction, ae);
+		}
 
-    public void doCopy(ActionEvent ae) {
+		public void doCopy(ActionEvent ae) {
 //TODO copy current line if no selection
-      performEditorAction(DefaultEditorKit.copyAction, ae);
-    }
-
-    public void doPaste(ActionEvent ae) {
-      performEditorAction(DefaultEditorKit.pasteAction, ae);
-    }
-
-    public void doSelectAll(ActionEvent ae) {
-      performEditorAction(DefaultEditorKit.selectAllAction, ae);
-    }
-
-    public void doIndent(ActionEvent ae) {
-      SikuliIDE ide = SikuliIDE.getInstance();
-      EditorPane pane = ide.getCurrentCodePane();
-      (new EditorKit.InsertTabAction()).actionPerformed(pane);
-    }
-
-    public void doUnindent(ActionEvent ae) {
-      SikuliIDE ide = SikuliIDE.getInstance();
-      EditorPane pane = ide.getCurrentCodePane();
-      (new EditorKit.DeindentAction()).actionPerformed(pane);
-    }
-  }
-
-  class FindAction extends MenuAction {
-
-    static final String FIND = "doFind";
-    static final String FIND_NEXT = "doFindNext";
-    static final String FIND_PREV = "doFindPrev";
-
-    public FindAction() {
-      super();
-    }
-
-    public FindAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void doFind(ActionEvent ae) {
-      _searchField.selectAll();
-      _searchField.requestFocus();
-    }
-
-    public void doFindNext(ActionEvent ae) {
-      findNext(_searchField.getText());
-    }
-
-    public void doFindPrev(ActionEvent ae) {
-      findPrev(_searchField.getText());
-    }
-
-    private boolean _find(String str, int begin, boolean forward) {
-      if (str == "!") {
-        return false;
-      }
-      EditorPane codePane = getCurrentCodePane();
-      int pos = codePane.search(str, begin, forward);
-      Debug.log(7, "find \"" + str + "\" at " + begin + ", found: " + pos);
-      if (pos < 0) {
-        return false;
-      }
-      return true;
-    }
-
-    public boolean findStr(String str) {
-      if (getCurrentCodePane() != null) {
-        return _find(str, getCurrentCodePane().getCaretPosition(), true);
-      }
-      return false;
-    }
-
-    public boolean findPrev(String str) {
-      if (getCurrentCodePane() != null) {
-        return _find(str, getCurrentCodePane().getCaretPosition(), false);
-      }
-      return false;
-    }
-
-    public boolean findNext(String str) {
-      if (getCurrentCodePane() != null) {
-        return _find(str,
-                getCurrentCodePane().getCaretPosition() + str.length(),
-                true);
-      }
-      return false;
-    }
-
-    public void setFailed(boolean failed) {
-      Debug.log(7, "search failed: " + failed);
-      _searchField.setBackground(Color.white);
-      if (failed) {
-        _searchField.setForeground(COLOR_SEARCH_FAILED);
-      } else {
-        _searchField.setForeground(COLOR_SEARCH_NORMAL);
-      }
-    }
-  }
-
-  class UndoAction extends AbstractAction {
-
-    public UndoAction() {
-      super(_I("menuEditUndo"));
-      setEnabled(false);
-    }
-
-    public void updateUndoState() {
-      if (getCurrentCodePane() != null
-              && getCurrentCodePane().getUndoManager().canUndo()) {
-        setEnabled(true);
-      } else {
-        setEnabled(false);
-      }
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-      EditorUndoManager undo = getCurrentCodePane().getUndoManager();
-      try {
-        undo.undo();
-      } catch (CannotUndoException ex) {
-      }
-      updateUndoState();
-      _redoAction.updateRedoState();
-    }
-  }
-
-  class RedoAction extends AbstractAction {
-
-    public RedoAction() {
-      super(_I("menuEditRedo"));
-      setEnabled(false);
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-      EditorUndoManager undo = getCurrentCodePane().getUndoManager();
-      try {
-        undo.redo();
-      } catch (CannotRedoException ex) {
-      }
-      updateRedoState();
-      _undoAction.updateUndoState();
-    }
-
-    protected void updateRedoState() {
-      if (getCurrentCodePane() != null
-              && getCurrentCodePane().getUndoManager().canRedo()) {
-        setEnabled(true);
-      } else {
-        setEnabled(false);
-      }
-    }
-  }
-
-  public void updateUndoRedoStates() {
-    _undoAction.updateUndoState();
-    _redoAction.updateRedoState();
-  }
+			performEditorAction(DefaultEditorKit.copyAction, ae);
+		}
+
+		public void doPaste(ActionEvent ae) {
+			performEditorAction(DefaultEditorKit.pasteAction, ae);
+		}
+
+		public void doSelectAll(ActionEvent ae) {
+			performEditorAction(DefaultEditorKit.selectAllAction, ae);
+		}
+
+		public void doIndent(ActionEvent ae) {
+			SikuliIDE ide = SikuliIDE.getInstance();
+			EditorPane pane = ide.getCurrentCodePane();
+			(new SikuliEditorKit.InsertTabAction()).actionPerformed(pane);
+		}
+
+		public void doUnindent(ActionEvent ae) {
+			SikuliIDE ide = SikuliIDE.getInstance();
+			EditorPane pane = ide.getCurrentCodePane();
+			(new SikuliEditorKit.DeindentAction()).actionPerformed(pane);
+		}
+	}
+
+	class FindAction extends MenuAction {
+
+		static final String FIND = "doFind";
+		static final String FIND_NEXT = "doFindNext";
+		static final String FIND_PREV = "doFindPrev";
+
+		public FindAction() {
+			super();
+		}
+
+		public FindAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void doFind(ActionEvent ae) {
+			_searchField.selectAll();
+			_searchField.requestFocus();
+		}
+
+		public void doFindNext(ActionEvent ae) {
+			findNext(_searchField.getText());
+		}
+
+		public void doFindPrev(ActionEvent ae) {
+			findPrev(_searchField.getText());
+		}
+
+		private boolean _find(String str, int begin, boolean forward) {
+			if (str == "!") {
+				return false;
+			}
+			EditorPane codePane = getCurrentCodePane();
+			int pos = codePane.search(str, begin, forward);
+			Debug.log(7, "find \"" + str + "\" at " + begin + ", found: " + pos);
+			if (pos < 0) {
+				return false;
+			}
+			return true;
+		}
+
+		public boolean findStr(String str) {
+			if (getCurrentCodePane() != null) {
+				return _find(str, getCurrentCodePane().getCaretPosition(), true);
+			}
+			return false;
+		}
+
+		public boolean findPrev(String str) {
+			if (getCurrentCodePane() != null) {
+				return _find(str, getCurrentCodePane().getCaretPosition(), false);
+			}
+			return false;
+		}
+
+		public boolean findNext(String str) {
+			if (getCurrentCodePane() != null) {
+				return _find(str,
+								getCurrentCodePane().getCaretPosition() + str.length(),
+								true);
+			}
+			return false;
+		}
+
+		public void setFailed(boolean failed) {
+			Debug.log(7, "search failed: " + failed);
+			_searchField.setBackground(Color.white);
+			if (failed) {
+				_searchField.setForeground(COLOR_SEARCH_FAILED);
+			} else {
+				_searchField.setForeground(COLOR_SEARCH_NORMAL);
+			}
+		}
+	}
+
+	class UndoAction extends AbstractAction {
+
+		public UndoAction() {
+			super(_I("menuEditUndo"));
+			setEnabled(false);
+		}
+
+		public void updateUndoState() {
+			if (getCurrentCodePane() != null
+							&& getCurrentCodePane().getUndoManager().canUndo()) {
+				setEnabled(true);
+			} else {
+				setEnabled(false);
+			}
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			EditorUndoManager undo = getCurrentCodePane().getUndoManager();
+			try {
+				undo.undo();
+			} catch (CannotUndoException ex) {
+			}
+			updateUndoState();
+			_redoAction.updateRedoState();
+		}
+	}
+
+	class RedoAction extends AbstractAction {
+
+		public RedoAction() {
+			super(_I("menuEditRedo"));
+			setEnabled(false);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			EditorUndoManager undo = getCurrentCodePane().getUndoManager();
+			try {
+				undo.redo();
+			} catch (CannotRedoException ex) {
+			}
+			updateRedoState();
+			_undoAction.updateUndoState();
+		}
+
+		protected void updateRedoState() {
+			if (getCurrentCodePane() != null
+							&& getCurrentCodePane().getUndoManager().canRedo()) {
+				setEnabled(true);
+			} else {
+				setEnabled(false);
+			}
+		}
+	}
+
+	public void updateUndoRedoStates() {
+		_undoAction.updateUndoState();
+		_redoAction.updateRedoState();
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Init Run Menu">
-  private void initRunMenu() throws NoSuchMethodException {
-    JMenuItem item;
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _runMenu.setMnemonic(java.awt.event.KeyEvent.VK_R);
-    item = _runMenu.add(createMenuItem(_I("menuRunRun"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, scMask),
-            new RunAction(RunAction.RUN)));
-    item.setName("RUN");
-    item = _runMenu.add(createMenuItem(_I("menuRunRunAndShowActions"),
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,
-            InputEvent.ALT_MASK | scMask),
-            new RunAction(RunAction.RUN_SHOW_ACTIONS)));
-    item.setName("RUN_SLOWLY");
-
-    PreferencesUser pref = PreferencesUser.getInstance();
-    item = createMenuItem(_I("menuRunStop"),
-            KeyStroke.getKeyStroke(
-            pref.getStopHotkey(), pref.getStopHotkeyModifiers()),
-            new RunAction(RunAction.RUN_SHOW_ACTIONS));
-    item.setEnabled(false);
-    _runMenu.add(item);
-  }
-
-  class RunAction extends MenuAction {
-
-    static final String RUN = "run";
-    static final String RUN_SHOW_ACTIONS = "runShowActions";
-
-    public RunAction() {
-      super();
-    }
-
-    public RunAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void run(ActionEvent ae) {
-      doRun(_btnRun);
-    }
-
-    public void runShowActions(ActionEvent ae) {
-      doRun(_btnRunViz);
-    }
-
-    private void doRun(ButtonRun btn) {
-      btn.runCurrentScript();
-    }
-  }
+	//<editor-fold defaultstate="collapsed" desc="Init Run Menu">
+	private void initRunMenu() throws NoSuchMethodException {
+		JMenuItem item;
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_runMenu.setMnemonic(java.awt.event.KeyEvent.VK_R);
+		item = _runMenu.add(createMenuItem(_I("menuRunRun"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, scMask),
+						new RunAction(RunAction.RUN)));
+		item.setName("RUN");
+		item = _runMenu.add(createMenuItem(_I("menuRunRunAndShowActions"),
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,
+										InputEvent.ALT_MASK | scMask),
+						new RunAction(RunAction.RUN_SHOW_ACTIONS)));
+		item.setName("RUN_SLOWLY");
+
+		PreferencesUser pref = PreferencesUser.getInstance();
+		item = createMenuItem(_I("menuRunStop"),
+						KeyStroke.getKeyStroke(
+										pref.getStopHotkey(), pref.getStopHotkeyModifiers()),
+						new RunAction(RunAction.RUN_SHOW_ACTIONS));
+		item.setEnabled(false);
+		_runMenu.add(item);
+	}
+
+	class RunAction extends MenuAction {
+
+		static final String RUN = "run";
+		static final String RUN_SHOW_ACTIONS = "runShowActions";
+
+		public RunAction() {
+			super();
+		}
+
+		public RunAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void run(ActionEvent ae) {
+			doRun(_btnRun);
+		}
+
+		public void runShowActions(ActionEvent ae) {
+			doRun(_btnRunViz);
+		}
+
+		private void doRun(ButtonRun btn) {
+			btn.runCurrentScript();
+		}
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Init View Menu">
-  private void initViewMenu() throws NoSuchMethodException {
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _viewMenu.setMnemonic(java.awt.event.KeyEvent.VK_V);
+	//<editor-fold defaultstate="collapsed" desc="Init View Menu">
+	private void initViewMenu() throws NoSuchMethodException {
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_viewMenu.setMnemonic(java.awt.event.KeyEvent.VK_V);
 
-    if (prefs.getPrefMoreCommandBar()) {
-      chkShowCmdList = new JCheckBoxMenuItem(_I("menuViewCommandList"), true);
-      _viewMenu.add(createMenuItem(chkShowCmdList,
-              KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, scMask),
-              new ViewAction(ViewAction.CMD_LIST)));
-    }
+		if (prefs.getPrefMoreCommandBar()) {
+			chkShowCmdList = new JCheckBoxMenuItem(_I("menuViewCommandList"), true);
+			_viewMenu.add(createMenuItem(chkShowCmdList,
+							KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, scMask),
+							new ViewAction(ViewAction.CMD_LIST)));
+		}
 
-    chkShowThumbs = new JCheckBoxMenuItem(_I("menuShowThumbs"), false);
-    _viewMenu.add(createMenuItem(chkShowThumbs,
-            KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, scMask),
-            new ViewAction(ViewAction.SHOW_THUMBS)));
+		chkShowThumbs = new JCheckBoxMenuItem(_I("menuShowThumbs"), false);
+		_viewMenu.add(createMenuItem(chkShowThumbs,
+						KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, scMask),
+						new ViewAction(ViewAction.SHOW_THUMBS)));
 
 //TODO Message Area clear
 //TODO Message Area LineBreak
-  }
-
-  class ViewAction extends MenuAction {
-
-    static final String UNIT_TEST = "toggleUnitTest";
-    static final String CMD_LIST = "toggleCmdList";
-    static final String SHOW_THUMBS = "toggleShowThumbs";
-
-    public ViewAction() {
-      super();
-    }
-
-    public ViewAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void toggleCmdList(ActionEvent ae) {
-      _cmdList.setCollapsed(!_cmdList.isCollapsed());
-    }
-
-    public void toggleShowThumbs(ActionEvent ae) {
-      getCurrentCodePane().showThumbs = chkShowThumbs.getState();
-      if (!getCurrentCodePane().reparse()) {
-        chkShowThumbs.setState(!chkShowThumbs.getState());
-        getCurrentCodePane().showThumbs = chkShowThumbs.getState();
-      }
-    }
-
-    public void toggleUnitTest(ActionEvent ae) {
-      if (_chkShowUnitTest.getState()) {
-        _sidePane.setCollapsed(false);
-      } else {
-        _sidePane.setCollapsed(true);
-      }
-    }
-  }
+	}
+
+	class ViewAction extends MenuAction {
+
+		static final String UNIT_TEST = "toggleUnitTest";
+		static final String CMD_LIST = "toggleCmdList";
+		static final String SHOW_THUMBS = "toggleShowThumbs";
+
+		public ViewAction() {
+			super();
+		}
+
+		public ViewAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void toggleCmdList(ActionEvent ae) {
+			_cmdList.setCollapsed(!_cmdList.isCollapsed());
+		}
+
+		public void toggleShowThumbs(ActionEvent ae) {
+			getCurrentCodePane().showThumbs = chkShowThumbs.getState();
+			if (!getCurrentCodePane().reparse()) {
+				chkShowThumbs.setState(!chkShowThumbs.getState());
+				getCurrentCodePane().showThumbs = chkShowThumbs.getState();
+			}
+		}
+
+		public void toggleUnitTest(ActionEvent ae) {
+			if (_chkShowUnitTest.getState()) {
+				_sidePane.setCollapsed(false);
+			} else {
+				_sidePane.setCollapsed(true);
+			}
+		}
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Init ToolMenu">
-  private void initToolMenu() throws NoSuchMethodException {
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _toolMenu.setMnemonic(java.awt.event.KeyEvent.VK_T);
-
-    if (Settings.SikuliRepo != null) {
-      _toolMenu.add(createMenuItem(_I("menuToolExtensions"),
-              null,
-              new ToolAction(ToolAction.EXTENSIONS)));
-    }
-  }
-
-  class ToolAction extends MenuAction {
-
-    static final String EXTENSIONS = "extensions";
-
-    public ToolAction() {
-      super();
-    }
-
-    public ToolAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void extensions(ActionEvent ae) {
-      showExtensionsFrame();
-    }
-  }
-
-  public void showExtensionsFrame() {
-    String warn = "You might proceed, if you\n"
-            + "- have some programming skills\n"
-            + "- read the docs about extensions\n"
-            + "- know what you are doing\n\n"
-            + "Otherwise you should press Cancel!";
-    String title = "Need your attention!";
-    String[] options = new String[3];
-    options[WARNING_DO_NOTHING] = "OK";
-    options[WARNING_ACCEPTED] = "Be quiet!";
-    options[WARNING_CANCEL] = "Cancel";
-    int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
-    if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
-      return;
-    }
-    if (ret == WARNING_ACCEPTED) {
-      //TODO set prefs to be quiet on extensions warning
-    };
-    ExtensionManagerFrame extmg = ExtensionManagerFrame.getInstance();
-    extmg.setVisible(true);
-  }
+	//<editor-fold defaultstate="collapsed" desc="Init ToolMenu">
+	private void initToolMenu() throws NoSuchMethodException {
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_toolMenu.setMnemonic(java.awt.event.KeyEvent.VK_T);
+
+		if (Settings.SikuliRepo != null) {
+			_toolMenu.add(createMenuItem(_I("menuToolExtensions"),
+							null,
+							new ToolAction(ToolAction.EXTENSIONS)));
+		}
+	}
+
+	class ToolAction extends MenuAction {
+
+		static final String EXTENSIONS = "extensions";
+
+		public ToolAction() {
+			super();
+		}
+
+		public ToolAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void extensions(ActionEvent ae) {
+			showExtensionsFrame();
+		}
+	}
+
+	public void showExtensionsFrame() {
+		String warn = "You might proceed, if you\n"
+						+ "- have some programming skills\n"
+						+ "- read the docs about extensions\n"
+						+ "- know what you are doing\n\n"
+						+ "Otherwise you should press Cancel!";
+		String title = "Need your attention!";
+		String[] options = new String[3];
+		options[WARNING_DO_NOTHING] = "OK";
+		options[WARNING_ACCEPTED] = "Be quiet!";
+		options[WARNING_CANCEL] = "Cancel";
+		int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
+		if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
+			return;
+		}
+		if (ret == WARNING_ACCEPTED) {
+			//TODO set prefs to be quiet on extensions warning
+		};
+		ExtensionManagerFrame extmg = ExtensionManagerFrame.getInstance();
+		extmg.setVisible(true);
+	}
   //</editor-fold>
 
-  //<editor-fold defaultstate="collapsed" desc="Init Help Menu">
-  private void initHelpMenu() throws NoSuchMethodException {
-    int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    _helpMenu.setMnemonic(java.awt.event.KeyEvent.VK_H);
-
-    _helpMenu.add(createMenuItem(_I("menuHelpQuickStart"),
-            null, new HelpAction(HelpAction.QUICK_START)));
-    _helpMenu.addSeparator();
-
-    _helpMenu.add(createMenuItem(_I("menuHelpGuide"),
-            null, new HelpAction(HelpAction.OPEN_DOC)));
-    _helpMenu.add(createMenuItem(_I("menuHelpDocumentations"),
-            null, new HelpAction(HelpAction.OPEN_GUIDE)));
-    _helpMenu.add(createMenuItem(_I("menuHelpFAQ"),
-            null, new HelpAction(HelpAction.OPEN_FAQ)));
-    _helpMenu.add(createMenuItem(_I("menuHelpAsk"),
-            null, new HelpAction(HelpAction.OPEN_ASK)));
-    _helpMenu.add(createMenuItem(_I("menuHelpBugReport"),
-            null, new HelpAction(HelpAction.OPEN_BUG_REPORT)));
+	//<editor-fold defaultstate="collapsed" desc="Init Help Menu">
+	private void initHelpMenu() throws NoSuchMethodException {
+		int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		_helpMenu.setMnemonic(java.awt.event.KeyEvent.VK_H);
+
+		_helpMenu.add(createMenuItem(_I("menuHelpQuickStart"),
+						null, new HelpAction(HelpAction.QUICK_START)));
+		_helpMenu.addSeparator();
+
+		_helpMenu.add(createMenuItem(_I("menuHelpGuide"),
+						null, new HelpAction(HelpAction.OPEN_DOC)));
+		_helpMenu.add(createMenuItem(_I("menuHelpDocumentations"),
+						null, new HelpAction(HelpAction.OPEN_GUIDE)));
+		_helpMenu.add(createMenuItem(_I("menuHelpFAQ"),
+						null, new HelpAction(HelpAction.OPEN_FAQ)));
+		_helpMenu.add(createMenuItem(_I("menuHelpAsk"),
+						null, new HelpAction(HelpAction.OPEN_ASK)));
+		_helpMenu.add(createMenuItem(_I("menuHelpBugReport"),
+						null, new HelpAction(HelpAction.OPEN_BUG_REPORT)));
 
 //    _helpMenu.add(createMenuItem(_I("menuHelpTranslation"),
 //            null, new HelpAction(HelpAction.OPEN_TRANSLATION)));
-
-    _helpMenu.addSeparator();
-    _helpMenu.add(createMenuItem(_I("menuHelpHomepage"),
-            null, new HelpAction(HelpAction.OPEN_HOMEPAGE)));
-
-    _helpMenu.addSeparator();
-    _helpMenu.add(createMenuItem(_I("menuHelpCheckUpdate"),
-            null, new HelpAction(HelpAction.CHECK_UPDATE)));
-  }
-
-  class HelpAction extends MenuAction {
-
-    static final String CHECK_UPDATE = "doCheckUpdate";
-    static final String QUICK_START = "openQuickStart";
-    static final String OPEN_DOC = "openDoc";
-    static final String OPEN_GUIDE = "openTutor";
-    static final String OPEN_FAQ = "openFAQ";
-    static final String OPEN_ASK = "openAsk";
-    static final String OPEN_BUG_REPORT = "openBugReport";
-    static final String OPEN_TRANSLATION = "openTranslation";
-    static final String OPEN_HOMEPAGE = "openHomepage";
-
-    public HelpAction() {
-      super();
-    }
-
-    public HelpAction(String item) throws NoSuchMethodException {
-      super(item);
-    }
-
-    public void openQuickStart(ActionEvent ae) {
-      FileManager.openURL("https://github.com/RaiMan/SikuliX-IDE/wiki/Release-Notes-IDE");
-    }
-
-    public void openDoc(ActionEvent ae) {
-      FileManager.openURL("http://doc.sikuli.org");
-    }
-
-    public void openTutor(ActionEvent ae) {
-      FileManager.openURL("http://www.sikuli.org/videos.html");
-    }
-
-    public void openFAQ(ActionEvent ae) {
-      FileManager.openURL("https://answers.launchpad.net/sikuli/+faqs");
-    }
-
-    public void openAsk(ActionEvent ae) {
-      FileManager.openURL("https://answers.launchpad.net/sikuli");
-    }
-
-    public void openBugReport(ActionEvent ae) {
-      FileManager.openURL("https://bugs.launchpad.net/sikuli/+filebug");
-    }
-
-    public void openTranslation(ActionEvent ae) {
-      FileManager.openURL("https://translations.launchpad.net/sikuli/sikuli-x/+translations");
-    }
-
-    public void openHomepage(ActionEvent ae) {
-      FileManager.openURL("http://sikuli.org");
-    }
-
-    public void doCheckUpdate(ActionEvent ae) {
-      if (!checkUpdate(false)) {
-        JOptionPane.showMessageDialog(null,
-                _I("msgNoUpdate"), SikuliIDESettings.SikuliVersion,
-                JOptionPane.INFORMATION_MESSAGE);
-      }
-    }
-
-    public boolean checkUpdate(boolean isAutoCheck) {
-      JFrame f = null;
-      String ver = "";
-      String details;
-      AutoUpdater au = new AutoUpdater();
-      if (!isAutoCheck) {
+		_helpMenu.addSeparator();
+		_helpMenu.add(createMenuItem(_I("menuHelpHomepage"),
+						null, new HelpAction(HelpAction.OPEN_HOMEPAGE)));
+
+		_helpMenu.addSeparator();
+		_helpMenu.add(createMenuItem(_I("menuHelpCheckUpdate"),
+						null, new HelpAction(HelpAction.CHECK_UPDATE)));
+	}
+
+	class HelpAction extends MenuAction {
+
+		static final String CHECK_UPDATE = "doCheckUpdate";
+		static final String QUICK_START = "openQuickStart";
+		static final String OPEN_DOC = "openDoc";
+		static final String OPEN_GUIDE = "openTutor";
+		static final String OPEN_FAQ = "openFAQ";
+		static final String OPEN_ASK = "openAsk";
+		static final String OPEN_BUG_REPORT = "openBugReport";
+		static final String OPEN_TRANSLATION = "openTranslation";
+		static final String OPEN_HOMEPAGE = "openHomepage";
+
+		public HelpAction() {
+			super();
+		}
+
+		public HelpAction(String item) throws NoSuchMethodException {
+			super(item);
+		}
+
+		public void openQuickStart(ActionEvent ae) {
+			FileManager.openURL("https://github.com/RaiMan/SikuliX-IDE/wiki/Release-Notes-IDE");
+		}
+
+		public void openDoc(ActionEvent ae) {
+			FileManager.openURL("http://doc.sikuli.org");
+		}
+
+		public void openTutor(ActionEvent ae) {
+			FileManager.openURL("http://www.sikuli.org/videos.html");
+		}
+
+		public void openFAQ(ActionEvent ae) {
+			FileManager.openURL("https://answers.launchpad.net/sikuli/+faqs");
+		}
+
+		public void openAsk(ActionEvent ae) {
+			FileManager.openURL("https://answers.launchpad.net/sikuli");
+		}
+
+		public void openBugReport(ActionEvent ae) {
+			FileManager.openURL("https://bugs.launchpad.net/sikuli/+filebug");
+		}
+
+		public void openTranslation(ActionEvent ae) {
+			FileManager.openURL("https://translations.launchpad.net/sikuli/sikuli-x/+translations");
+		}
+
+		public void openHomepage(ActionEvent ae) {
+			FileManager.openURL("http://sikuli.org");
+		}
+
+		public void doCheckUpdate(ActionEvent ae) {
+			if (!checkUpdate(false)) {
+				JOptionPane.showMessageDialog(null,
+								_I("msgNoUpdate"), SikuliIDESettings.SikuliVersion,
+								JOptionPane.INFORMATION_MESSAGE);
+			}
+		}
+
+		public boolean checkUpdate(boolean isAutoCheck) {
+			JFrame f = null;
+			String ver = "";
+			String details;
+			AutoUpdater au = new AutoUpdater();
+			if (!isAutoCheck) {
 //TODO replace this hack: wait update check
-        f = au.showUpdateFrame("Checking for new version ... please wait!",
-                "Checking for new version ... please wait! Checking for new version ... please wait!", -1);
-      }
-      PreferencesUser pref = PreferencesUser.getInstance();
-      Debug.log(3, "being asked to check update");
-      int whatUpdate = au.checkUpdate();
-      if (f != null) {
-        f.dispose();
-      }
-      if (whatUpdate >= AutoUpdater.SOMEBETA) {
+				f = au.showUpdateFrame("Checking for new version ... please wait!",
+								"Checking for new version ... please wait! Checking for new version ... please wait!", -1);
+			}
+			PreferencesUser pref = PreferencesUser.getInstance();
+			Debug.log(3, "being asked to check update");
+			int whatUpdate = au.checkUpdate();
+			if (f != null) {
+				f.dispose();
+			}
+			if (whatUpdate >= AutoUpdater.SOMEBETA) {
 //TODO add Prefs wantBeta check
-        whatUpdate -= AutoUpdater.SOMEBETA;
-      }
-      if (whatUpdate > 0) {
-        if (whatUpdate == AutoUpdater.BETA) {
-          ver = au.getBeta();
-          details = au.getBetaDetails();
-        } else {
-          ver = au.getVersion();
-          details = au.getDetails();
-        }
-        if (isAutoCheck && pref.getLastSeenUpdate().equals(ver)) {
-          return false;
-        }
-        au.showUpdateFrame(_I("dlgUpdateAvailable", ver), details, whatUpdate);
-        PreferencesUser.getInstance().setLastSeenUpdate(ver);
-        return true;
-      }
-      return false;
-    }
-  }
-
-  private void initMenuBars(JFrame frame) {
-    try {
-      initFileMenu();
-      initEditMenu();
-      initRunMenu();
-      initViewMenu();
-      initToolMenu();
-      initHelpMenu();
-    } catch (NoSuchMethodException e) {
-      log(-1, "Problem when initializing menues\nError: %s", e.getMessage());
-    }
-
-    _menuBar.add(_fileMenu);
-    _menuBar.add(_editMenu);
-    _menuBar.add(_runMenu);
-    _menuBar.add(_viewMenu);
-    _menuBar.add(_toolMenu);
-    _menuBar.add(_helpMenu);
-    frame.setJMenuBar(_menuBar);
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="Init LeftBar Commands">
-  private String[] getCommandCategories() {
-    String[] CommandCategories = {
-      _I("cmdListFind"),
-      _I("cmdListMouse"),
-      _I("cmdListKeyboard"),
-      _I("cmdListObserver")
-    };
-    return CommandCategories;
-  }
-
-  private String[][] getCommandsOnToolbar() {
-    String[][] CommandsOnToolbar = {
-      {"find"}, {"PATTERN"},
-      {_I("cmdFind")},
-      {"findAll"}, {"PATTERN"},
-      {_I("cmdFindAll")},
-      {"wait"}, {"PATTERN", "[timeout]"},
-      {_I("cmdWait")},
-      {"waitVanish"}, {"PATTERN", "[timeout]"},
-      {_I("cmdWaitVanish")},
-      {"exists"}, {"PATTERN", "[timeout]"},
-      {_I("cmdExists")},
-      {"----"}, {}, {},
-      {"click"}, {"PATTERN", "[modifiers]"},
-      {_I("cmdClick")},
-      {"doubleClick"}, {"PATTERN", "[modifiers]"},
-      {_I("cmdDoubleClick")},
-      {"rightClick"}, {"PATTERN", "[modifiers]"},
-      {_I("cmdRightClick")},
-      {"hover"}, {"PATTERN"},
-      {_I("cmdHover")},
-      {"dragDrop"}, {"PATTERN", "PATTERN", "[modifiers]"},
-      {_I("cmdDragDrop")},
-      /* RaiMan not used
-       * {"drag"}, {"PATTERN"},
-       * {"dropAt"}, {"PATTERN", "[delay]"},
-       * RaiMan not used */
-      {"----"}, {}, {},
-      {"type"}, {"_text", "[modifiers]"},
-      {_I("cmdType")},
-      {"type"}, {"PATTERN", "_text", "[modifiers]"},
-      {_I("cmdType2")},
-      {"paste"}, {"_text", "[modifiers]"},
-      {_I("cmdPaste")},
-      {"paste"}, {"PATTERN", "_text", "[modifiers]"},
-      {_I("cmdPaste2")},
-      {"----"}, {}, {},
-      {"onAppear"}, {"PATTERN", "_hnd"},
-      {_I("cmdOnAppear")},
-      {"onVanish"}, {"PATTERN", "_hnd"},
-      {_I("cmdOnVanish")},
-      {"onChange"}, {"_hnd"},
-      {_I("cmdOnChange")},
-      {"observe"}, {"[time]", "[background]"},
-      {_I("cmdObserve")},};
-    return CommandsOnToolbar;
-  }
-
-  private JComponent createCommandPane() {
-    JXTaskPaneContainer con = new JXTaskPaneContainer();
-
-    PreferencesUser pref = PreferencesUser.getInstance();
-    JCheckBox chkAutoCapture =
-            new JCheckBox(_I("cmdListAutoCapture"),
-            pref.getAutoCaptureForCmdButtons());
-    chkAutoCapture.addChangeListener(new ChangeListener() {
-      @Override
-      public void stateChanged(javax.swing.event.ChangeEvent e) {
-        boolean flag = ((JCheckBox) e.getSource()).isSelected();
-        PreferencesUser pref = PreferencesUser.getInstance();
-        pref.setAutoCaptureForCmdButtons(flag);
-      }
-    });
-    JXTaskPane setPane = new JXTaskPane();
-    setPane.setTitle(_I("cmdListSettings"));
-    setPane.add(chkAutoCapture);
-    setPane.setCollapsed(true);
-    con.add(setPane);
-    int cat = 0;
-    JXTaskPane taskPane = new JXTaskPane();
-    taskPane.setTitle(getCommandCategories()[cat++]);
-    con.add(taskPane);
-    String[][] CommandsOnToolbar = getCommandsOnToolbar();
-    boolean collapsed;
-    for (int i = 0; i < CommandsOnToolbar.length; i++) {
-      String cmd = CommandsOnToolbar[i++][0];
-      String[] params = CommandsOnToolbar[i++];
-      String[] desc = CommandsOnToolbar[i];
+				whatUpdate -= AutoUpdater.SOMEBETA;
+			}
+			if (whatUpdate > 0) {
+				if (whatUpdate == AutoUpdater.BETA) {
+					ver = au.getBeta();
+					details = au.getBetaDetails();
+				} else {
+					ver = au.getVersion();
+					details = au.getDetails();
+				}
+				if (isAutoCheck && pref.getLastSeenUpdate().equals(ver)) {
+					return false;
+				}
+				au.showUpdateFrame(_I("dlgUpdateAvailable", ver), details, whatUpdate);
+				PreferencesUser.getInstance().setLastSeenUpdate(ver);
+				return true;
+			}
+			return false;
+		}
+	}
+
+	private void initMenuBars(JFrame frame) {
+		try {
+			initFileMenu();
+			initEditMenu();
+			initRunMenu();
+			initViewMenu();
+			initToolMenu();
+			initHelpMenu();
+		} catch (NoSuchMethodException e) {
+			log(-1, "Problem when initializing menues\nError: %s", e.getMessage());
+		}
+
+		_menuBar.add(_fileMenu);
+		_menuBar.add(_editMenu);
+		_menuBar.add(_runMenu);
+		_menuBar.add(_viewMenu);
+		_menuBar.add(_toolMenu);
+		_menuBar.add(_helpMenu);
+		frame.setJMenuBar(_menuBar);
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="Init LeftBar Commands">
+	private String[] getCommandCategories() {
+		String[] CommandCategories = {
+			_I("cmdListFind"),
+			_I("cmdListMouse"),
+			_I("cmdListKeyboard"),
+			_I("cmdListObserver")
+		};
+		return CommandCategories;
+	}
+
+	private String[][] getCommandsOnToolbar() {
+		String[][] CommandsOnToolbar = {
+			{"find"}, {"PATTERN"},
+			{_I("cmdFind")},
+			{"findAll"}, {"PATTERN"},
+			{_I("cmdFindAll")},
+			{"wait"}, {"PATTERN", "[timeout]"},
+			{_I("cmdWait")},
+			{"waitVanish"}, {"PATTERN", "[timeout]"},
+			{_I("cmdWaitVanish")},
+			{"exists"}, {"PATTERN", "[timeout]"},
+			{_I("cmdExists")},
+			{"----"}, {}, {},
+			{"click"}, {"PATTERN", "[modifiers]"},
+			{_I("cmdClick")},
+			{"doubleClick"}, {"PATTERN", "[modifiers]"},
+			{_I("cmdDoubleClick")},
+			{"rightClick"}, {"PATTERN", "[modifiers]"},
+			{_I("cmdRightClick")},
+			{"hover"}, {"PATTERN"},
+			{_I("cmdHover")},
+			{"dragDrop"}, {"PATTERN", "PATTERN", "[modifiers]"},
+			{_I("cmdDragDrop")},
+			/* RaiMan not used
+			 * {"drag"}, {"PATTERN"},
+			 * {"dropAt"}, {"PATTERN", "[delay]"},
+			 * RaiMan not used */
+			{"----"}, {}, {},
+			{"type"}, {"_text", "[modifiers]"},
+			{_I("cmdType")},
+			{"type"}, {"PATTERN", "_text", "[modifiers]"},
+			{_I("cmdType2")},
+			{"paste"}, {"_text", "[modifiers]"},
+			{_I("cmdPaste")},
+			{"paste"}, {"PATTERN", "_text", "[modifiers]"},
+			{_I("cmdPaste2")},
+			{"----"}, {}, {},
+			{"onAppear"}, {"PATTERN", "_hnd"},
+			{_I("cmdOnAppear")},
+			{"onVanish"}, {"PATTERN", "_hnd"},
+			{_I("cmdOnVanish")},
+			{"onChange"}, {"_hnd"},
+			{_I("cmdOnChange")},
+			{"observe"}, {"[time]", "[background]"},
+			{_I("cmdObserve")},};
+		return CommandsOnToolbar;
+	}
+
+	private JComponent createCommandPane() {
+		JXTaskPaneContainer con = new JXTaskPaneContainer();
+
+		PreferencesUser pref = PreferencesUser.getInstance();
+		JCheckBox chkAutoCapture
+						= new JCheckBox(_I("cmdListAutoCapture"),
+										pref.getAutoCaptureForCmdButtons());
+		chkAutoCapture.addChangeListener(new ChangeListener() {
+			@Override
+			public void stateChanged(javax.swing.event.ChangeEvent e) {
+				boolean flag = ((JCheckBox) e.getSource()).isSelected();
+				PreferencesUser pref = PreferencesUser.getInstance();
+				pref.setAutoCaptureForCmdButtons(flag);
+			}
+		});
+		JXTaskPane setPane = new JXTaskPane();
+		setPane.setTitle(_I("cmdListSettings"));
+		setPane.add(chkAutoCapture);
+		setPane.setCollapsed(true);
+		con.add(setPane);
+		int cat = 0;
+		JXTaskPane taskPane = new JXTaskPane();
+		taskPane.setTitle(getCommandCategories()[cat++]);
+		con.add(taskPane);
+		String[][] CommandsOnToolbar = getCommandsOnToolbar();
+		boolean collapsed;
+		for (int i = 0; i < CommandsOnToolbar.length; i++) {
+			String cmd = CommandsOnToolbar[i++][0];
+			String[] params = CommandsOnToolbar[i++];
+			String[] desc = CommandsOnToolbar[i];
 //TODO: more elegeant way, to handle special cases
-      if (cmd.equals("----")) {
-        if (cat == 2) {
-          collapsed = true;
-        } else {
-          collapsed = false;
-        }
-        if (cat == 3) {
-          if (prefs.getUserType() == PreferencesUser.NEWBEE) {
-            break;
-          } else {
-            collapsed = true;
-          }
-        }
-        taskPane = new JXTaskPane();
-        taskPane.setTitle(getCommandCategories()[cat++]);
-        con.add(taskPane);
-        taskPane.setCollapsed(collapsed);
-      } else {
-        taskPane.add(new ButtonGenCommand(cmd, desc[0], params));
-      }
-    }
-    Dimension conDim = con.getSize();
-    con.setPreferredSize(new Dimension(250, 1000));
-    _cmdList = new JXCollapsiblePane(JXCollapsiblePane.Direction.LEFT);
-    _cmdList.setMinimumSize(new Dimension(0, 0));
-    _cmdList.add(new JScrollPane(con));
-    _cmdList.setCollapsed(false);
-    return _cmdList;
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="RaiMan obsolete">
-  private JToolBar initCmdToolbar() {
-    JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
-    toolbar.add(createCommandPane());
-    return toolbar;
-  }
-  //</editor-fold>
+			if (cmd.equals("----")) {
+				if (cat == 2) {
+					collapsed = true;
+				} else {
+					collapsed = false;
+				}
+				if (cat == 3) {
+					if (prefs.getUserType() == PreferencesUser.NEWBEE) {
+						break;
+					} else {
+						collapsed = true;
+					}
+				}
+				taskPane = new JXTaskPane();
+				taskPane.setTitle(getCommandCategories()[cat++]);
+				con.add(taskPane);
+				taskPane.setCollapsed(collapsed);
+			} else {
+				taskPane.add(new ButtonGenCommand(cmd, desc[0], params));
+			}
+		}
+		Dimension conDim = con.getSize();
+		con.setPreferredSize(new Dimension(250, 1000));
+		_cmdList = new JXCollapsiblePane(JXCollapsiblePane.Direction.LEFT);
+		_cmdList.setMinimumSize(new Dimension(0, 0));
+		_cmdList.add(new JScrollPane(con));
+		_cmdList.setCollapsed(false);
+		return _cmdList;
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="RaiMan obsolete">
+	private JToolBar initCmdToolbar() {
+		JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
+		toolbar.add(createCommandPane());
+		return toolbar;
+	}
   //</editor-fold>
-
-  //<editor-fold defaultstate="collapsed" desc="Init ToolBar Buttons">
-  private JToolBar initToolbar() {
-    if (ENABLE_UNIFIED_TOOLBAR) {
-      MacUtils.makeWindowLeopardStyle(this.getRootPane());
-    }
-
-    JToolBar toolbar = new JToolBar();
-    JButton btnInsertImage = new ButtonInsertImage();
-    _btnCapture = new ButtonCapture();
-    JButton btnSubregion = new ButtonSubregion();
-    toolbar.add(_btnCapture);
-    toolbar.add(btnInsertImage);
-    toolbar.add(btnSubregion);
-    toolbar.add(Box.createHorizontalGlue());
-    /* RaiMan not used
-     * if( ENABLE_RECORDING ){
-     * JToggleButton btnRecord = new ButtonRecord();
-     * toolbar.add(btnRecord);
-     * }
-     * RaiMan not used */
-    _btnRun = new ButtonRun();
-    toolbar.add(_btnRun);
-    _btnRunViz = new ButtonRunViz();
-    toolbar.add(_btnRunViz);
-    toolbar.add(Box.createHorizontalGlue());
-    toolbar.add(createSearchField());
-    toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
-    toolbar.setFloatable(false);
-    //toolbar.setMargin(new Insets(0, 0, 0, 5));
-    return toolbar;
-  }
-
-  class ButtonInsertImage extends ButtonOnToolbar implements ActionListener {
-
-    public ButtonInsertImage() {
-      super();
-      URL imageURL = SikuliIDE.class.getResource("/icons/insert-image-icon.png");
-      setIcon(new ImageIcon(imageURL));
-      setText(SikuliIDE._I("btnInsertImageLabel"));
-      //setMaximumSize(new Dimension(26,26));
-      setToolTipText(SikuliIDE._I("btnInsertImageHint"));
-      addActionListener(this);
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent ae) {
-      EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-      File file = new SikuliIDEFileChooser(SikuliIDE.getInstance()).loadImage();
-      if (file == null) {
-        return;
-      }
-      String path = FileManager.slashify(file.getAbsolutePath(), false);
-      Debug.info("load image: " + path);
-      EditorPatternButton icon;
-      String img = codePane.copyFileToBundle(path).getAbsolutePath();
-      if (prefs.getDefaultThumbHeight() > 0) {
-        icon = new EditorPatternButton(codePane, img);
-        codePane.insertComponent(icon);
-      } else {
-        codePane.insertString("\"" + (new File(img)).getName() + "\"");
-      }
-    }
-  }
-
-  class ButtonSubregion extends ButtonOnToolbar implements ActionListener, EventObserver {
-
-    public ButtonSubregion() {
-      super();
-      URL imageURL = SikuliIDE.class.getResource("/icons/region-icon.png");
-      setIcon(new ImageIcon(imageURL));
-      setText(SikuliIDE._I("btnRegionLabel"));
-      //setMaximumSize(new Dimension(26,26));
-      setToolTipText(SikuliIDE._I("btnRegionHint"));
-      addActionListener(this);
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent ae) {
-      SikuliIDE ide = SikuliIDE.getInstance();
-      EditorPane codePane = ide.getCurrentCodePane();
-      ide.setVisible(false);
-      OverlayCapturePrompt prompt = new OverlayCapturePrompt(null, this);
-      prompt.prompt(SikuliIDE._I("msgCapturePrompt"), 500);
-    }
-
-    @Override
-    public void update(EventSubject s) {
-      if (s instanceof OverlayCapturePrompt) {
-        complete((OverlayCapturePrompt) s);
-      }
-    }
-
-    public void complete(OverlayCapturePrompt cp) {
-      int x, y, w, h;
-      SikuliIDE ide = SikuliIDE.getInstance();
-      EditorPane codePane = ide.getCurrentCodePane();
-      ScreenImage r = cp.getSelection();
-      cp.close();
-      if (r != null) {
-        Rectangle roi = r.getROI();
-        x = (int) roi.getX();
-        y = (int) roi.getY();
-        w = (int) roi.getWidth();
-        h = (int) roi.getHeight();
-        ide.setVisible(false);
-        if (codePane.showThumbs) {
-          if (prefs.getPrefMoreImageThumbs()) {
-            codePane.insertComponent(new EditorRegionButton(codePane, x, y, w, h));
-          } else {
-            codePane.insertComponent(new EditorRegionLabel(codePane,
-                    new EditorRegionButton(codePane, x, y, w, h).toString()));
-          }
-        } else {
-          codePane.insertString(codePane.getRegionString(x, y, w, h));
-        }
-      }
-      ide.setVisible(true);
-      codePane.requestFocus();
-    }
-  }
-
-  class ButtonRun extends ButtonOnToolbar implements ActionListener {
-
-    private Thread _runningThread = null;
-
-    public ButtonRun() {
-      super();
-
-      URL imageURL = SikuliIDE.class.getResource("/icons/run_big_green.png");
-      setIcon(new ImageIcon(imageURL));
-      initTooltip();
-      addActionListener(this);
-      setText(_I("btnRunLabel"));
-      //setMaximumSize(new Dimension(45,45));
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent ae) {
-      runCurrentScript();
-    }
-
-    public void runCurrentScript() {
-      SikuliIDE.getStatusbar().setMessage("... PLEASE WAIT ... checking IDE state before running script");
-      SikuliIDE ide = SikuliIDE.getInstance();
-      if (ideIsRunningScript || !ide.doBeforeRun()) {
-        return;
-      }
-      SikuliIDE.getStatusbar().resetMessage();
-      ide.setVisible(false);
-      if (ide.firstRun) {
-        SikuliX.displaySplashFirstTime(new String[0]);
-        ide.firstRun = false;
-      }
-      ide.setIsRunningScript(true);
-      _runningThread = new Thread() {
-        @Override
-        public void run() {
-          EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
-          File tmpFile;
-          tmpFile = FileManager.createTempFile("py");
-          if (tmpFile == null) {
-            return;
-          }
-          try {
-            BufferedWriter bw = new BufferedWriter(
-                    new OutputStreamWriter(
-                    new FileOutputStream(tmpFile),
-                    "UTF8"));
-            codePane.write(bw);
-            //SikuliIDE.getInstance().setVisible(false);
-            _console.clear();
-            resetErrorMark();
-            runPython(tmpFile);
-          } catch (Exception e) {
-          } finally {
-            SikuliIDE.getInstance().setIsRunningScript(false);
-            SikuliIDE.getInstance().setVisible(true);
-            _runningThread = null;
-            SikuliX.cleanUp(0);
-          }
-        }
-      };
-      _runningThread.start();
-    }
-
-    protected void runPython(File f) throws Exception {
-      File path = new File(SikuliIDE.getInstance().getCurrentBundlePath());
-      File parent = path.getParentFile();
-      //TODO implement alternative script types
-      IScriptRunner srunner = SikuliX.getScriptRunner("jython", null, Settings.getArgs());
-      if (srunner == null) {
-        Debug.error("Could not load the Jython script runner");
-        return;
-      }
-      addPythonCode(srunner);
-      try {
-        ImagePath.resetBundlePath(path.getAbsolutePath());
-        int ret = srunner.runScript(f, path,
-                Settings.getArgs(),
-                new String[]{parent.getAbsolutePath(),
-          _mainPane.getTitleAt(_mainPane.getSelectedIndex())});
-        addErrorMark(ret);
-        srunner.close();
-      } catch (Exception e) {
-        srunner.close();
-        throw e;
-      }
-    }
-
-    protected void addPythonCode(IScriptRunner srunner) {
-    }
-
-    public void stopRunning() {
-      if (_runningThread != null) {
-        _runningThread.interrupt();
-        _runningThread.stop();
-      }
-    }
-
-    private void initTooltip() {
-      PreferencesUser pref = PreferencesUser.getInstance();
-      String strHotkey = Key.convertKeyToText(
-              pref.getStopHotkey(), pref.getStopHotkeyModifiers());
-      String stopHint = _I("btnRunStopHint", strHotkey);
-      setToolTipText(_I("btnRun", stopHint));
-    }
-
-    public void addErrorMark(int line) {
-      if (line < 0) {
-        line *= -1;
-      } else {
-        return;
-      }
-      JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
-      EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
-      lnview.addErrorMark(line);
-      EditorPane codePane = SikuliIDE.this.getCurrentCodePane();
-      codePane.jumpTo(line);
-      codePane.requestFocus();
-    }
-
-    public void resetErrorMark() {
-      JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
-      EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
-      lnview.resetErrorMark();
-    }
-  }
-
-  class ButtonRunViz extends ButtonRun {
-
-    public ButtonRunViz() {
-      super();
-      URL imageURL = SikuliIDE.class.getResource("/icons/run_big_yl.png");
-      setIcon(new ImageIcon(imageURL));
-      setToolTipText(_I("menuRunRunAndShowActions"));
-      setText(_I("btnRunSlowMotionLabel"));
-    }
-
-    @Override
-    protected void addPythonCode(IScriptRunner srunner) {
-      srunner.execBefore(null);
-      srunner.execBefore(new String[]{"setShowActions(True)"});
-    }
-  }
-
-  public String getCurrentBundlePath() {
-    EditorPane pane = getCurrentCodePane();
-    return pane.getSrcBundle();
-  }
-
-  private JComponent createSearchField() {
-    _searchField = new JXSearchField("Find");
-    _searchField.setUseNativeSearchFieldIfPossible(true);
-    //_searchField.setLayoutStyle(JXSearchField.LayoutStyle.MAC);
-    _searchField.setMinimumSize(new Dimension(220, 30));
-    _searchField.setPreferredSize(new Dimension(220, 30));
-    _searchField.setMaximumSize(new Dimension(380, 30));
-    _searchField.setMargin(new Insets(0, 3, 0, 3));
-    _searchField.setToolTipText("Search is case sensitive - "
-            + "start with ! to make search not case sensitive");
-
-    _searchField.setCancelAction(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent evt) {
-        getCurrentCodePane().requestFocus();
-        _findHelper.setFailed(false);
-      }
-    });
-    _searchField.setFindAction(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent evt) {
-        //FIXME: On Linux the found selection disappears somehow
-        if (!Settings.isLinux()) //HACK
-        {
-          _searchField.selectAll();
-        }
-        boolean ret = _findHelper.findNext(_searchField.getText());
-        _findHelper.setFailed(!ret);
-      }
-    });
-    _searchField.addKeyListener(new KeyAdapter() {
-      @Override
-      public void keyReleased(java.awt.event.KeyEvent ke) {
-        boolean ret;
-        if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
-          //FIXME: On Linux the found selection disappears somehow
-          if (!Settings.isLinux()) //HACK
-          {
-            _searchField.selectAll();
-          }
-          ret = _findHelper.findNext(_searchField.getText());
-        } else {
-          ret = _findHelper.findStr(_searchField.getText());
-        }
-        _findHelper.setFailed(!ret);
-      }
-    });
-    return _searchField;
-  }
-  //</editor-fold>
-
-  private void initTabPane() {
-    _mainPane = new CloseableTabbedPane();
-    _mainPane.setUI(new AquaCloseableTabbedPaneUI());
-    _mainPane.addCloseableTabbedPaneListener(
-            new CloseableTabbedPaneListener() {
-      @Override
-      public boolean closeTab(int i) {
-        EditorPane codePane;
-        try {
-          JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
-          codePane = (EditorPane) scrPane.getViewport().getView();
-          _mainPane.setLastClosed(codePane.getSrcBundle());
-          Debug.log(4, "close tab " + i + " n:" + _mainPane.getComponentCount());
-          boolean ret = codePane.close();
-          Debug.log(4, "after close tab n:" + _mainPane.getComponentCount());
-          if (ret && _mainPane.getTabCount() < 2) {
-            (new FileAction()).doNew(null);
-          }
-          return ret;
-        } catch (Exception e) {
-          log(-1, "Problem closing tab %d\nError: %s", i, e.getMessage());
-          return false;
-        }
-      }
-    });
-
-    _mainPane.addChangeListener(new ChangeListener() {
-      @Override
-      public void stateChanged(javax.swing.event.ChangeEvent e) {
-        JTabbedPane tab = (JTabbedPane) e.getSource();
-        int i = tab.getSelectedIndex();
-        if (i >= 0) {
-          JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
-          EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
-          String fname = codePane.getCurrentSrcDir();
-          if (fname == null) {
-            SikuliIDE.this.setTitle(tab.getTitleAt(i));
-          } else {
-            ImagePath.setBundlePath(fname);
-            SikuliIDE.this.setTitle(fname);
-          }
-          SikuliIDE.this.chkShowThumbs.setState(SikuliIDE.this.getCurrentCodePane().showThumbs);
-        }
-        updateUndoRedoStates();
-      }
-    });
-
-  }
-
-  private void initMsgPane(boolean atBottom) {
-    msgPane = new JTabbedPane();
-    _console = new EditorConsolePane();
-    msgPane.addTab(_I("paneMessage"), null, _console, "DoubleClick to hide/unhide");
-    if (Settings.isWindows() || Settings.isLinux()) {
-      msgPane.setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
-    }
-    msgPane.addMouseListener(new MouseListener() {
-      @Override
-      public void mouseClicked(MouseEvent me) {
-        if (me.getClickCount() < 2) {
-          return;
-        }
-        if (msgPaneCollapsed) {
-          _mainSplitPane.setDividerLocation(_mainSplitPane.getLastDividerLocation());
-          msgPaneCollapsed = false;
-        } else {
-          int pos = _mainSplitPane.getWidth() - 35;
-          if (prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL) {
-            pos = _mainSplitPane.getHeight() - 35;
-          }
-          _mainSplitPane.setDividerLocation(pos);
-          msgPaneCollapsed = true;
-        }
-      }
-      //<editor-fold defaultstate="collapsed" desc="mouse events not used">
-
-      @Override
-      public void mousePressed(MouseEvent me) {
-      }
-
-      @Override
-      public void mouseReleased(MouseEvent me) {
-      }
-
-      @Override
-      public void mouseEntered(MouseEvent me) {
-      }
-
-      @Override
-      public void mouseExited(MouseEvent me) {
-      }
-      //</editor-fold>
-    });
-  }
-
-  public Container getMsgPane() {
-    return msgPane;
-  }
-
-  private SikuliIDEStatusBar initStatusbar() {
-    _status = new SikuliIDEStatusBar();
-    return _status;
-  }
-
-  public static SikuliIDEStatusBar getStatusbar() {
-    if (_instance == null) {
-      return null;
-    } else {
-      return _instance._status;
-    }
-  }
-
-  private void initWindowListener() {
-    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
-    addWindowListener(new WindowAdapter() {
-      @Override
-      public void windowClosing(WindowEvent e) {
-        SikuliIDE.this.quit();
-      }
-    });
-    addComponentListener(new ComponentAdapter() {
-      @Override
-      public void componentResized(ComponentEvent e) {
-        PreferencesUser.getInstance().setIdeSize(SikuliIDE.this.getSize());
-      }
-
-      @Override
-      public void componentMoved(ComponentEvent e) {
-        PreferencesUser.getInstance().setIdeLocation(SikuliIDE.this.getLocation());
-      }
-    });
-  }
-
-  private void initTooltip() {
-    ToolTipManager tm = ToolTipManager.sharedInstance();
-    tm.setDismissDelay(30000);
-  }
-
-  //<editor-fold defaultstate="collapsed" desc="Init ShortCuts HotKeys">
-  private void nextTab() {
-    int i = _mainPane.getSelectedIndex();
-    int next = (i + 1) % _mainPane.getTabCount();
-    _mainPane.setSelectedIndex(next);
-  }
-
-  private void prevTab() {
-    int i = _mainPane.getSelectedIndex();
-    int prev = (i - 1 + _mainPane.getTabCount()) % _mainPane.getTabCount();
-    _mainPane.setSelectedIndex(prev);
-  }
-
-  private void initShortcutKeys() {
-    final int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
-      private boolean isKeyNextTab(java.awt.event.KeyEvent ke) {
-        if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
-                && ke.getModifiers() == InputEvent.CTRL_MASK) {
-          return true;
-        }
-        if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_CLOSE_BRACKET
-                && ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
-          return true;
-        }
-        return false;
-      }
-
-      private boolean isKeyPrevTab(java.awt.event.KeyEvent ke) {
-        if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
-                && ke.getModifiers() == (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK)) {
-          return true;
-        }
-        if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_OPEN_BRACKET
-                && ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
-          return true;
-        }
-        return false;
-      }
-
-      public void eventDispatched(AWTEvent e) {
-        java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent) e;
-        //Debug.log(ke.toString());
-        if (ke.getID() == java.awt.event.KeyEvent.KEY_PRESSED) {
-          if (isKeyNextTab(ke)) {
-            nextTab();
-          } else if (isKeyPrevTab(ke)) {
-            prevTab();
-          }
-        }
-      }
-    }, AWTEvent.KEY_EVENT_MASK);
-
-  }
-
-  public void removeCaptureHotkey(int key, int mod) {
-    HotkeyManager.getInstance()._removeHotkey(key, mod);
-  }
-
-  public void installCaptureHotkey(int key, int mod) {
-    HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
-      @Override
-      public void hotkeyPressed(HotkeyEvent e) {
-        if (!SikuliIDE.getInstance().isRunningScript()) {
-          onQuickCapture();
-        }
-      }
-    });
-  }
-
-  public void onQuickCapture() {
-    onQuickCapture(null);
-  }
-
-  public void onQuickCapture(String arg) {
-    Debug.log(3, "QuickCapture");
-    _btnCapture.capture(0);
-  }
-
-  public void removeStopHotkey(int key, int mod) {
-    HotkeyManager.getInstance()._removeHotkey(key, mod);
-  }
-
-  public void installStopHotkey(int key, int mod) {
-    HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
-      @Override
-      public void hotkeyPressed(HotkeyEvent e) {
-        onStopRunning();
-      }
-    });
-  }
-
-  public void onStopRunning() {
-    Debug.log(3, "StopRunning");
-    this.setVisible(true);
-    _btnRun.stopRunning();
-    _btnRunViz.stopRunning();
-  }
-
-  private void initHotkeys() {
-    PreferencesUser pref = PreferencesUser.getInstance();
-    int key = pref.getCaptureHotkey();
-    int mod = pref.getCaptureHotkeyModifiers();
-    installCaptureHotkey(key, mod);
-
-    key = pref.getStopHotkey();
-    mod = pref.getStopHotkeyModifiers();
-    installStopHotkey(key, mod);
-  }
+	//</editor-fold>
+
+	//<editor-fold defaultstate="collapsed" desc="Init ToolBar Buttons">
+	private JToolBar initToolbar() {
+		if (ENABLE_UNIFIED_TOOLBAR) {
+			MacUtils.makeWindowLeopardStyle(this.getRootPane());
+		}
+
+		JToolBar toolbar = new JToolBar();
+		JButton btnInsertImage = new ButtonInsertImage();
+		_btnCapture = new ButtonCapture();
+		JButton btnSubregion = new ButtonSubregion();
+		toolbar.add(_btnCapture);
+		toolbar.add(btnInsertImage);
+		toolbar.add(btnSubregion);
+		toolbar.add(Box.createHorizontalGlue());
+		/* RaiMan not used
+		 * if( ENABLE_RECORDING ){
+		 * JToggleButton btnRecord = new ButtonRecord();
+		 * toolbar.add(btnRecord);
+		 * }
+		 * RaiMan not used */
+		_btnRun = new ButtonRun();
+		toolbar.add(_btnRun);
+		_btnRunViz = new ButtonRunViz();
+		toolbar.add(_btnRunViz);
+		toolbar.add(Box.createHorizontalGlue());
+		toolbar.add(createSearchField());
+		toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
+		toolbar.setFloatable(false);
+		//toolbar.setMargin(new Insets(0, 0, 0, 5));
+		return toolbar;
+	}
+
+	class ButtonInsertImage extends ButtonOnToolbar implements ActionListener {
+
+		public ButtonInsertImage() {
+			super();
+			URL imageURL = SikuliIDE.class.getResource("/icons/insert-image-icon.png");
+			setIcon(new ImageIcon(imageURL));
+			setText(SikuliIDE._I("btnInsertImageLabel"));
+			//setMaximumSize(new Dimension(26,26));
+			setToolTipText(SikuliIDE._I("btnInsertImageHint"));
+			addActionListener(this);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent ae) {
+			EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+			File file = new SikuliIDEFileChooser(SikuliIDE.getInstance()).loadImage();
+			if (file == null) {
+				return;
+			}
+			String path = FileManager.slashify(file.getAbsolutePath(), false);
+			Debug.info("load image: " + path);
+			EditorPatternButton icon;
+			String img = codePane.copyFileToBundle(path).getAbsolutePath();
+			if (prefs.getDefaultThumbHeight() > 0) {
+				icon = new EditorPatternButton(codePane, img);
+				codePane.insertComponent(icon);
+			} else {
+				codePane.insertString("\"" + (new File(img)).getName() + "\"");
+			}
+		}
+	}
+
+	class ButtonSubregion extends ButtonOnToolbar implements ActionListener, EventObserver {
+
+		public ButtonSubregion() {
+			super();
+			URL imageURL = SikuliIDE.class.getResource("/icons/region-icon.png");
+			setIcon(new ImageIcon(imageURL));
+			setText(SikuliIDE._I("btnRegionLabel"));
+			//setMaximumSize(new Dimension(26,26));
+			setToolTipText(SikuliIDE._I("btnRegionHint"));
+			addActionListener(this);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent ae) {
+			SikuliIDE ide = SikuliIDE.getInstance();
+			EditorPane codePane = ide.getCurrentCodePane();
+			ide.setVisible(false);
+			OverlayCapturePrompt prompt = new OverlayCapturePrompt(null, this);
+			prompt.prompt(SikuliIDE._I("msgCapturePrompt"), 500);
+		}
+
+		@Override
+		public void update(EventSubject s) {
+			if (s instanceof OverlayCapturePrompt) {
+				complete((OverlayCapturePrompt) s);
+			}
+		}
+
+		public void complete(OverlayCapturePrompt cp) {
+			int x, y, w, h;
+			SikuliIDE ide = SikuliIDE.getInstance();
+			EditorPane codePane = ide.getCurrentCodePane();
+			ScreenImage r = cp.getSelection();
+			cp.close();
+			if (r != null) {
+				Rectangle roi = r.getROI();
+				x = (int) roi.getX();
+				y = (int) roi.getY();
+				w = (int) roi.getWidth();
+				h = (int) roi.getHeight();
+				ide.setVisible(false);
+				if (codePane.showThumbs) {
+					if (prefs.getPrefMoreImageThumbs()) {
+						codePane.insertComponent(new EditorRegionButton(codePane, x, y, w, h));
+					} else {
+						codePane.insertComponent(new EditorRegionLabel(codePane,
+										new EditorRegionButton(codePane, x, y, w, h).toString()));
+					}
+				} else {
+					codePane.insertString(codePane.getRegionString(x, y, w, h));
+				}
+			}
+			ide.setVisible(true);
+			codePane.requestFocus();
+		}
+	}
+
+	class ButtonRun extends ButtonOnToolbar implements ActionListener {
+
+		private Thread _runningThread = null;
+
+		public ButtonRun() {
+			super();
+
+			URL imageURL = SikuliIDE.class.getResource("/icons/run_big_green.png");
+			setIcon(new ImageIcon(imageURL));
+			initTooltip();
+			addActionListener(this);
+			setText(_I("btnRunLabel"));
+			//setMaximumSize(new Dimension(45,45));
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent ae) {
+			runCurrentScript();
+		}
+
+		public void runCurrentScript() {
+			SikuliIDE.getStatusbar().setMessage("... PLEASE WAIT ... checking IDE state before running script");
+			SikuliIDE ide = SikuliIDE.getInstance();
+			if (ideIsRunningScript || !ide.doBeforeRun()) {
+				return;
+			}
+			SikuliIDE.getStatusbar().resetMessage();
+			ide.setVisible(false);
+			if (ide.firstRun) {
+				SikuliX.displaySplashFirstTime(new String[0]);
+				ide.firstRun = false;
+			}
+			ide.setIsRunningScript(true);
+			_runningThread = new Thread() {
+				@Override
+				public void run() {
+					EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
+					File tmpFile;
+					tmpFile = FileManager.createTempFile("py");
+					if (tmpFile == null) {
+						return;
+					}
+					try {
+						BufferedWriter bw = new BufferedWriter(
+										new OutputStreamWriter(
+														new FileOutputStream(tmpFile),
+														"UTF8"));
+						codePane.write(bw);
+						//SikuliIDE.getInstance().setVisible(false);
+						_console.clear();
+						resetErrorMark();
+						runPython(tmpFile);
+					} catch (Exception e) {
+					} finally {
+						SikuliIDE.getInstance().setIsRunningScript(false);
+						SikuliIDE.getInstance().setVisible(true);
+						_runningThread = null;
+						SikuliX.cleanUp(0);
+					}
+				}
+			};
+			_runningThread.start();
+		}
+
+		protected void runPython(File f) throws Exception {
+			File path = new File(SikuliIDE.getInstance().getCurrentBundlePath());
+			File parent = path.getParentFile();
+			//TODO implement alternative script types
+			IScriptRunner srunner = SikuliX.getScriptRunner("jython", null, Settings.getArgs());
+			if (srunner == null) {
+				Debug.error("Could not load the Jython script runner");
+				return;
+			}
+			addPythonCode(srunner);
+			try {
+				ImagePath.resetBundlePath(path.getAbsolutePath());
+				int ret = srunner.runScript(f, path,
+								Settings.getArgs(),
+								new String[]{parent.getAbsolutePath(),
+									_mainPane.getTitleAt(_mainPane.getSelectedIndex())});
+				addErrorMark(ret);
+				srunner.close();
+			} catch (Exception e) {
+				srunner.close();
+				throw e;
+			}
+		}
+
+		protected void addPythonCode(IScriptRunner srunner) {
+		}
+
+		public void stopRunning() {
+			if (_runningThread != null) {
+				_runningThread.interrupt();
+				_runningThread.stop();
+			}
+		}
+
+		private void initTooltip() {
+			PreferencesUser pref = PreferencesUser.getInstance();
+			String strHotkey = Key.convertKeyToText(
+							pref.getStopHotkey(), pref.getStopHotkeyModifiers());
+			String stopHint = _I("btnRunStopHint", strHotkey);
+			setToolTipText(_I("btnRun", stopHint));
+		}
+
+		public void addErrorMark(int line) {
+			if (line < 0) {
+				line *= -1;
+			} else {
+				return;
+			}
+			JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
+			EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
+			lnview.addErrorMark(line);
+			EditorPane codePane = SikuliIDE.this.getCurrentCodePane();
+			codePane.jumpTo(line);
+			codePane.requestFocus();
+		}
+
+		public void resetErrorMark() {
+			JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
+			EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
+			lnview.resetErrorMark();
+		}
+	}
+
+	class ButtonRunViz extends ButtonRun {
+
+		public ButtonRunViz() {
+			super();
+			URL imageURL = SikuliIDE.class.getResource("/icons/run_big_yl.png");
+			setIcon(new ImageIcon(imageURL));
+			setToolTipText(_I("menuRunRunAndShowActions"));
+			setText(_I("btnRunSlowMotionLabel"));
+		}
+
+		@Override
+		protected void addPythonCode(IScriptRunner srunner) {
+			srunner.execBefore(null);
+			srunner.execBefore(new String[]{"setShowActions(True)"});
+		}
+	}
+
+	public String getCurrentBundlePath() {
+		EditorPane pane = getCurrentCodePane();
+		return pane.getSrcBundle();
+	}
+
+	private JComponent createSearchField() {
+		_searchField = new JXSearchField("Find");
+		_searchField.setUseNativeSearchFieldIfPossible(true);
+		//_searchField.setLayoutStyle(JXSearchField.LayoutStyle.MAC);
+		_searchField.setMinimumSize(new Dimension(220, 30));
+		_searchField.setPreferredSize(new Dimension(220, 30));
+		_searchField.setMaximumSize(new Dimension(380, 30));
+		_searchField.setMargin(new Insets(0, 3, 0, 3));
+		_searchField.setToolTipText("Search is case sensitive - "
+						+ "start with ! to make search not case sensitive");
+
+		_searchField.setCancelAction(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				getCurrentCodePane().requestFocus();
+				_findHelper.setFailed(false);
+			}
+		});
+		_searchField.setFindAction(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				//FIXME: On Linux the found selection disappears somehow
+				if (!Settings.isLinux()) //HACK
+				{
+					_searchField.selectAll();
+				}
+				boolean ret = _findHelper.findNext(_searchField.getText());
+				_findHelper.setFailed(!ret);
+			}
+		});
+		_searchField.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyReleased(java.awt.event.KeyEvent ke) {
+				boolean ret;
+				if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
+					//FIXME: On Linux the found selection disappears somehow
+					if (!Settings.isLinux()) //HACK
+					{
+						_searchField.selectAll();
+					}
+					ret = _findHelper.findNext(_searchField.getText());
+				} else {
+					ret = _findHelper.findStr(_searchField.getText());
+				}
+				_findHelper.setFailed(!ret);
+			}
+		});
+		return _searchField;
+	}
+	//</editor-fold>
+
+	private void initTabPane() {
+		_mainPane = new CloseableTabbedPane();
+		_mainPane.setUI(new AquaCloseableTabbedPaneUI());
+		_mainPane.addCloseableTabbedPaneListener(
+						new CloseableTabbedPaneListener() {
+							@Override
+							public boolean closeTab(int i) {
+								EditorPane codePane;
+								try {
+									JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
+									codePane = (EditorPane) scrPane.getViewport().getView();
+									_mainPane.setLastClosed(codePane.getSrcBundle());
+									Debug.log(4, "close tab " + i + " n:" + _mainPane.getComponentCount());
+									boolean ret = codePane.close();
+									Debug.log(4, "after close tab n:" + _mainPane.getComponentCount());
+									if (ret && _mainPane.getTabCount() < 2) {
+										(new FileAction()).doNew(null);
+									}
+									return ret;
+								} catch (Exception e) {
+									log(-1, "Problem closing tab %d\nError: %s", i, e.getMessage());
+									return false;
+								}
+							}
+						});
+
+		_mainPane.addChangeListener(new ChangeListener() {
+			@Override
+			public void stateChanged(javax.swing.event.ChangeEvent e) {
+				EditorPane codePane = null ;
+				JTabbedPane tab = (JTabbedPane) e.getSource();
+				int i = tab.getSelectedIndex();
+				if (i >= 0) {
+					JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
+					codePane = (EditorPane) scrPane.getViewport().getView();
+					String fname = codePane.getCurrentSrcDir();
+					if (fname == null) {
+						SikuliIDE.this.setTitle(tab.getTitleAt(i));
+					} else {
+						ImagePath.setBundlePath(fname);
+						SikuliIDE.this.setTitle(fname);
+					}
+					SikuliIDE.this.chkShowThumbs.setState(SikuliIDE.this.getCurrentCodePane().showThumbs);
+				}
+				updateUndoRedoStates();
+				if (codePane != null) {
+					Debug.log(3, "SelectTab: %s :--: %s", codePane.getContentType(), codePane.getEditorKit());
+				}
+			}
+		});
+
+	}
+
+	private void initMsgPane(boolean atBottom) {
+		msgPane = new JTabbedPane();
+		_console = new EditorConsolePane();
+		msgPane.addTab(_I("paneMessage"), null, _console, "DoubleClick to hide/unhide");
+		if (Settings.isWindows() || Settings.isLinux()) {
+			msgPane.setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
+		}
+		msgPane.addMouseListener(new MouseListener() {
+			@Override
+			public void mouseClicked(MouseEvent me) {
+				if (me.getClickCount() < 2) {
+					return;
+				}
+				if (msgPaneCollapsed) {
+					_mainSplitPane.setDividerLocation(_mainSplitPane.getLastDividerLocation());
+					msgPaneCollapsed = false;
+				} else {
+					int pos = _mainSplitPane.getWidth() - 35;
+					if (prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL) {
+						pos = _mainSplitPane.getHeight() - 35;
+					}
+					_mainSplitPane.setDividerLocation(pos);
+					msgPaneCollapsed = true;
+				}
+			}
+			//<editor-fold defaultstate="collapsed" desc="mouse events not used">
+
+			@Override
+			public void mousePressed(MouseEvent me) {
+			}
+
+			@Override
+			public void mouseReleased(MouseEvent me) {
+			}
+
+			@Override
+			public void mouseEntered(MouseEvent me) {
+			}
+
+			@Override
+			public void mouseExited(MouseEvent me) {
+			}
+			//</editor-fold>
+		});
+	}
+
+	public Container getMsgPane() {
+		return msgPane;
+	}
+
+	private SikuliIDEStatusBar initStatusbar() {
+		_status = new SikuliIDEStatusBar();
+		return _status;
+	}
+
+	public static SikuliIDEStatusBar getStatusbar() {
+		if (_instance == null) {
+			return null;
+		} else {
+			return _instance._status;
+		}
+	}
+
+	private void initWindowListener() {
+		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent e) {
+				SikuliIDE.this.quit();
+			}
+		});
+		addComponentListener(new ComponentAdapter() {
+			@Override
+			public void componentResized(ComponentEvent e) {
+				PreferencesUser.getInstance().setIdeSize(SikuliIDE.this.getSize());
+			}
+
+			@Override
+			public void componentMoved(ComponentEvent e) {
+				PreferencesUser.getInstance().setIdeLocation(SikuliIDE.this.getLocation());
+			}
+		});
+	}
+
+	private void initTooltip() {
+		ToolTipManager tm = ToolTipManager.sharedInstance();
+		tm.setDismissDelay(30000);
+	}
+
+	//<editor-fold defaultstate="collapsed" desc="Init ShortCuts HotKeys">
+	private void nextTab() {
+		int i = _mainPane.getSelectedIndex();
+		int next = (i + 1) % _mainPane.getTabCount();
+		_mainPane.setSelectedIndex(next);
+	}
+
+	private void prevTab() {
+		int i = _mainPane.getSelectedIndex();
+		int prev = (i - 1 + _mainPane.getTabCount()) % _mainPane.getTabCount();
+		_mainPane.setSelectedIndex(prev);
+	}
+
+	private void initShortcutKeys() {
+		final int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+		Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
+			private boolean isKeyNextTab(java.awt.event.KeyEvent ke) {
+				if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
+								&& ke.getModifiers() == InputEvent.CTRL_MASK) {
+					return true;
+				}
+				if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_CLOSE_BRACKET
+								&& ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
+					return true;
+				}
+				return false;
+			}
+
+			private boolean isKeyPrevTab(java.awt.event.KeyEvent ke) {
+				if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
+								&& ke.getModifiers() == (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK)) {
+					return true;
+				}
+				if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_OPEN_BRACKET
+								&& ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
+					return true;
+				}
+				return false;
+			}
+
+			public void eventDispatched(AWTEvent e) {
+				java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent) e;
+				//Debug.log(ke.toString());
+				if (ke.getID() == java.awt.event.KeyEvent.KEY_PRESSED) {
+					if (isKeyNextTab(ke)) {
+						nextTab();
+					} else if (isKeyPrevTab(ke)) {
+						prevTab();
+					}
+				}
+			}
+		}, AWTEvent.KEY_EVENT_MASK);
+
+	}
+
+	public void removeCaptureHotkey(int key, int mod) {
+		HotkeyManager.getInstance()._removeHotkey(key, mod);
+	}
+
+	public void installCaptureHotkey(int key, int mod) {
+		HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
+			@Override
+			public void hotkeyPressed(HotkeyEvent e) {
+				if (!SikuliIDE.getInstance().isRunningScript()) {
+					onQuickCapture();
+				}
+			}
+		});
+	}
+
+	public void onQuickCapture() {
+		onQuickCapture(null);
+	}
+
+	public void onQuickCapture(String arg) {
+		Debug.log(3, "QuickCapture");
+		_btnCapture.capture(0);
+	}
+
+	public void removeStopHotkey(int key, int mod) {
+		HotkeyManager.getInstance()._removeHotkey(key, mod);
+	}
+
+	public void installStopHotkey(int key, int mod) {
+		HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
+			@Override
+			public void hotkeyPressed(HotkeyEvent e) {
+				onStopRunning();
+			}
+		});
+	}
+
+	public void onStopRunning() {
+		Debug.log(3, "StopRunning");
+		this.setVisible(true);
+		_btnRun.stopRunning();
+		_btnRunViz.stopRunning();
+	}
+
+	private void initHotkeys() {
+		PreferencesUser pref = PreferencesUser.getInstance();
+		int key = pref.getCaptureHotkey();
+		int mod = pref.getCaptureHotkeyModifiers();
+		installCaptureHotkey(key, mod);
+
+		key = pref.getStopHotkey();
+		mod = pref.getStopHotkeyModifiers();
+		installStopHotkey(key, mod);
+	}
   //</editor-fold>
 
   //<editor-fold defaultstate="collapsed" desc="IDE Unit Testing --- RaiMan not used">
   /*
-   private void initSidePane() {
-   initUnitPane();
-   _sidePane = new JXCollapsiblePane(JXCollapsiblePane.Direction.RIGHT);
-   _sidePane.setMinimumSize(new Dimension(0, 0));
-   CloseableTabbedPane tabPane = new CloseableTabbedPane();
-   _sidePane.getContentPane().add(tabPane);
-   tabPane.setMinimumSize(new Dimension(0, 0));
-   tabPane.addTab(_I("tabUnitTest"), _unitPane);
-   tabPane.addCloseableTabbedPaneListener(new CloseableTabbedPaneListener() {
-   @Override
-   public boolean closeTab(int tabIndexToClose) {
-   _sidePane.setCollapsed(true);
-   _chkShowUnitTest.setState(false);
-   return false;
-   }
-   });
-   _sidePane.setCollapsed(true);
-   }
-
-   private void initUnitPane() {
-   _testRunner = new UnitTestRunner();
-   _unitPane = _testRunner.getPanel();
-   _chkShowUnitTest.setState(false);
-   addAuxTab(_I("paneTestTrace"), _testRunner.getTracePane());
-   }
-   */
-  public void addAuxTab(String tabName, JComponent com) {
-    msgPane.addTab(tabName, com);
-  }
-
-  public void jumpTo(String funcName) throws BadLocationException {
-    EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
-    pane.jumpTo(funcName);
-    pane.grabFocus();
-  }
-
-  public void jumpTo(int lineNo) throws BadLocationException {
-    EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
-    pane.jumpTo(lineNo);
-    pane.grabFocus();
-  }
+	 private void initSidePane() {
+	 initUnitPane();
+	 _sidePane = new JXCollapsiblePane(JXCollapsiblePane.Direction.RIGHT);
+	 _sidePane.setMinimumSize(new Dimension(0, 0));
+	 CloseableTabbedPane tabPane = new CloseableTabbedPane();
+	 _sidePane.getContentPane().add(tabPane);
+	 tabPane.setMinimumSize(new Dimension(0, 0));
+	 tabPane.addTab(_I("tabUnitTest"), _unitPane);
+	 tabPane.addCloseableTabbedPaneListener(new CloseableTabbedPaneListener() {
+	 @Override
+	 public boolean closeTab(int tabIndexToClose) {
+	 _sidePane.setCollapsed(true);
+	 _chkShowUnitTest.setState(false);
+	 return false;
+	 }
+	 });
+	 _sidePane.setCollapsed(true);
+	 }
+
+	 private void initUnitPane() {
+	 _testRunner = new UnitTestRunner();
+	 _unitPane = _testRunner.getPanel();
+	 _chkShowUnitTest.setState(false);
+	 addAuxTab(_I("paneTestTrace"), _testRunner.getTracePane());
+	 }
+	 */
+	public void addAuxTab(String tabName, JComponent com) {
+		msgPane.addTab(tabName, com);
+	}
+
+	public void jumpTo(String funcName) throws BadLocationException {
+		EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
+		pane.jumpTo(funcName);
+		pane.grabFocus();
+	}
+
+	public void jumpTo(int lineNo) throws BadLocationException {
+		EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
+		pane.jumpTo(lineNo);
+		pane.grabFocus();
+	}
   //</editor-fold>
-}
\ No newline at end of file
+}
diff --git a/JRuby/src/main/java/org/sikuli/idesupport/JRubyIDESupport.java b/JRuby/src/main/java/org/sikuli/idesupport/JRubyIDESupport.java
index 5ec8b15..159295e 100644
--- a/JRuby/src/main/java/org/sikuli/idesupport/JRubyIDESupport.java
+++ b/JRuby/src/main/java/org/sikuli/idesupport/JRubyIDESupport.java
@@ -7,10 +7,21 @@
 package org.sikuli.idesupport;
 
 import org.sikuli.basics.IDESupport;
+import org.sikuli.basics.IndentationLogic;
 
 /**
  * all methods from/for IDE, that are JRuby specific
  */
 public class JRubyIDESupport implements IDESupport {
 
+	@Override
+	public String[] getEndings() {
+		return new String [] {"rb"};
+	}
+
+	@Override
+	public IndentationLogic getIndentationLogic() {
+		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+	}
+
 }
diff --git a/Jython/src/main/java/org/sikuli/idesupport/JythonIDESupport.java b/Jython/src/main/java/org/sikuli/idesupport/JythonIDESupport.java
index 50191ae..820ecda 100644
--- a/Jython/src/main/java/org/sikuli/idesupport/JythonIDESupport.java
+++ b/Jython/src/main/java/org/sikuli/idesupport/JythonIDESupport.java
@@ -14,7 +14,13 @@ import org.sikuli.basics.IndentationLogic;
  */
 public class JythonIDESupport implements IDESupport {
 
-	public static IndentationLogic getIndentationLogic() {
+	@Override
+	public String[] getEndings() {
+		return new String [] {"py"};
+	}
+
+	@Override
+	public IndentationLogic getIndentationLogic() {
 		return new PythonIndentation();
 	}
 }
diff --git a/Jython/src/main/java/org/sikuli/idesupport/PythonIndentation.java b/Jython/src/main/java/org/sikuli/idesupport/PythonIndentation.java
index afcf5c4..381d536 100755
--- a/Jython/src/main/java/org/sikuli/idesupport/PythonIndentation.java
+++ b/Jython/src/main/java/org/sikuli/idesupport/PythonIndentation.java
@@ -98,6 +98,7 @@ public class PythonIndentation implements IndentationLogic {
       wasColonAdded = false;
    }
 
+	 @Override
    public void checkIndent(String leadingWhitespace, int line) {
      if(leadingWhitespace.contains("\t") && leadingWhitespace.contains(" ")) {
 
@@ -114,6 +115,7 @@ public class PythonIndentation implements IndentationLogic {
      Debug.error("PythonIndentation: indent not consistent with tab settings in line " + line);
    }
 
+	 @Override
    public int checkDedent(String leadingWhitespace, int line) {
      int lws = leadingWhitespace.length();
      int tws = PreferencesUser.getInstance().getTabWhitespace().length();
@@ -138,8 +140,9 @@ public class PythonIndentation implements IndentationLogic {
     */
    public boolean endsLastLogicalLineWithColon(){
       // not thread safe!
-      if( wasColonAdded )
-         return true;
+      if( wasColonAdded ) {
+				return true;
+			}
       return endsWithColonMatcher.reset(
             pythonState.getLastLogicalLineStructure()).matches();
    }
@@ -152,8 +155,9 @@ public class PythonIndentation implements IndentationLogic {
     * @return true if the last logical line logically contains a colon
     */
    public boolean hasLastLogicalLineColon(){
-      if( wasColonAdded )
-         return true;
+      if( wasColonAdded ) {
+				return true;
+			}
       return pythonState.getLastLogicalLineStructure().contains(":");
    }
 
@@ -237,6 +241,7 @@ public class PythonIndentation implements IndentationLogic {
     * Resets the state of this object. The new state will be as if no text had
     * been fed to this object.
     */
+	 @Override
    public void reset(){
       pythonState.reset();
    }
@@ -250,6 +255,7 @@ public class PythonIndentation implements IndentationLogic {
     * @param text
     *           a chunk of code
     */
+	 @Override
    public void addText(String text){
       wasColonAdded = false;
       pythonState.update(text);
@@ -270,6 +276,7 @@ public class PythonIndentation implements IndentationLogic {
     * fed to this object must call this method to notify this object that a
     * colon was added. This affects the hints for line indentation.
     */
+	 @Override
    public void setLastLineEndsWithColon(){
       wasColonAdded = true;
    }
@@ -281,17 +288,20 @@ public class PythonIndentation implements IndentationLogic {
     *
     * @return the number of columns by which the indentation should be changed
     */
+	 @Override
    public int shouldChangeLastLineIndentation(){
       // only change indentation of the first physical line of a logical line
       if( pythonState.getPhysicalLineNumber() > pythonState
-            .getLogicalLinePhysicalStartLineNumber() )
-         return 0;
+            .getLogicalLinePhysicalStartLineNumber() ) {
+				return 0;
+			}
       // if this is not the first logical line and the indentation level is
       // already less than the previous logical line, do not unindent further
       if( pythonState.getLogicalLineNumber() > 0
             && pythonState.getLastLogicalLineIndentation() < pythonState
-                  .getPrevLogicalLineIndentation() )
-         return 0;
+                  .getPrevLogicalLineIndentation() ) {
+				return 0;
+			}
       int change;
       if( isUnindentLastLineStatement() ){
          change = -pythonState.getTabSize();
@@ -314,9 +324,11 @@ public class PythonIndentation implements IndentationLogic {
     *
     * @return the number of columns by which the indentation should be changed
     */
+	 @Override
    public int shouldChangeNextLineIndentation(){
-      if( !pythonState.isPhysicalLineComplete() )
-         return 0;
+      if( !pythonState.isPhysicalLineComplete() ) {
+				return 0;
+			}
       int logicalIndentation = pythonState.getLastLogicalLineIndentation();
       int physicalIndentation = pythonState.getLastPhysicalLineIndentation();
       int change = logicalIndentation - physicalIndentation;
@@ -413,15 +425,18 @@ public class PythonIndentation implements IndentationLogic {
     *
     * @return true if the last logical line should end with a colon but does not
     */
+	 @Override
    public boolean shouldAddColon(){
-      if( !pythonState.isLogicalLineComplete() )
-         return false;
+      if( !pythonState.isLogicalLineComplete() ) {
+				return false;
+			}
       return isLastLogicalLineCompoundHeaderStatement()
             && !hasLastLogicalLineColon();
    }
 
    //<editor-fold defaultstate="collapsed" desc="support for detecting whitespace">
-   public static String getLeadingWhitespace(String text) {
+	 @Override
+   public String getLeadingWhitespace(String text) {
      int len = text.length();
      int count = 0;
      while (count < len && isWhitespace(text.charAt(count))) {
@@ -430,7 +445,8 @@ public class PythonIndentation implements IndentationLogic {
      return text.substring(0, count);
    }
 
-   public static String getLeadingWhitespace(StyledDocument doc, int head, int len) throws BadLocationException {
+	 @Override
+   public String getLeadingWhitespace(StyledDocument doc, int head, int len) throws BadLocationException {
      String ret = "";
      int pos = head;
      while (pos < head + len) {
@@ -450,7 +466,8 @@ public class PythonIndentation implements IndentationLogic {
      return ret;
    }
 
-   public static int atEndOfLine(StyledDocument doc, int cpos, int start, String s, int sLen) {
+	 @Override
+   public int atEndOfLine(StyledDocument doc, int cpos, int start, String s, int sLen) {
      for (int i = cpos - start; i < sLen; i++) {
        if (doc.getCharacterElement(cpos).getName().equals(StyleConstants.ComponentElementName) || !isWhitespace(s.charAt(i))) {
          return i + start;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/sikuli.git



More information about the pkg-java-commits mailing list