void addShortcut(String name) {
   int index1 = name.indexOf('[');
   if (index1 == -1) return;
   int index2 = name.lastIndexOf(']');
   if (index2 <= (index1 + 1)) return;
   String shortcut = name.substring(index1 + 1, index2);
   int len = shortcut.length();
   if (len > 1) shortcut = shortcut.toUpperCase(Locale.US);
   ;
   if (len > 3 || (len > 1 && shortcut.charAt(0) != 'F' && shortcut.charAt(0) != 'N')) return;
   int code = Menus.convertShortcutToCode(shortcut);
   if (code == 0) return;
   if (nShortcuts == 0) removeShortcuts();
   // One character shortcuts go in a separate hash table to
   // avoid conflicts with ImageJ menu shortcuts.
   if (len == 1 || shortcut.equals("N+") || shortcut.equals("N-")) {
     Hashtable macroShortcuts = Menus.getMacroShortcuts();
     macroShortcuts.put(new Integer(code), commandPrefix + name);
     nShortcuts++;
     return;
   }
   Hashtable shortcuts = Menus.getShortcuts();
   if (shortcuts.get(new Integer(code)) != null) {
     if (shortcutsInUse == null) shortcutsInUse = "\n \n";
     shortcutsInUse += "	  " + name + "\n";
     inUseCount++;
     return;
   }
   shortcuts.put(new Integer(code), commandPrefix + name);
   nShortcuts++;
   // IJ.log("addShortcut3: "+name+"	  "+shortcut+"	  "+code);
 }
示例#2
0
 void updateMenus() {
   if (IJ.debugMode) {
     long start = System.currentTimeMillis();
     Menus.updateImageJMenus();
     IJ.log("Refresh Menus: " + (System.currentTimeMillis() - start) + " ms");
   } else Menus.updateImageJMenus();
 }
示例#3
0
 /** Handle menu events. */
 public void actionPerformed(ActionEvent e) {
   if ((e.getSource() instanceof MenuItem)) {
     MenuItem item = (MenuItem) e.getSource();
     String cmd = e.getActionCommand();
     commandName = cmd;
     ImagePlus imp = null;
     if (item.getParent() == Menus.getOpenRecentMenu()) {
       new RecentOpener(cmd); // open image in separate thread
       return;
     } else if (item.getParent() == Menus.getPopupMenu()) {
       Object parent = Menus.getPopupMenu().getParent();
       if (parent instanceof ImageCanvas) imp = ((ImageCanvas) parent).getImage();
     }
     int flags = e.getModifiers();
     hotkey = false;
     actionPerformedTime = System.currentTimeMillis();
     long ellapsedTime = actionPerformedTime - keyPressedTime;
     if (cmd != null && (ellapsedTime >= 200L || !cmd.equals(lastKeyCommand))) {
       if ((flags & Event.ALT_MASK) != 0) IJ.setKeyDown(KeyEvent.VK_ALT);
       if ((flags & Event.SHIFT_MASK) != 0) IJ.setKeyDown(KeyEvent.VK_SHIFT);
       new Executer(cmd, imp);
     }
     lastKeyCommand = null;
     if (IJ.debugMode) IJ.log("actionPerformed: time=" + ellapsedTime + ", " + e);
   }
 }
 void removeShortcuts() {
   Menus.getMacroShortcuts().clear();
   Hashtable shortcuts = Menus.getShortcuts();
   for (Enumeration en = shortcuts.keys(); en.hasMoreElements(); ) {
     Integer key = (Integer) en.nextElement();
     String value = (String) shortcuts.get(key);
     if (value.charAt(0) == commandPrefix) shortcuts.remove(key);
   }
 }
 public int install(String text) {
   if (text == null && pgm == null) return 0;
   this.text = text;
   macrosMenu = Menus.getMacrosMenu();
   if (listener != null) macrosMenu.removeActionListener(listener);
   macrosMenu.addActionListener(this);
   listener = this;
   install();
   return nShortcuts;
 }
 String showDialog() {
   if (defaultDir == null) defaultDir = Menus.getMacrosPath();
   OpenDialog od = new OpenDialog("Install Macros", defaultDir, fileName);
   String name = od.getFileName();
   if (name == null) return null;
   String dir = od.getDirectory();
   if (!(name.endsWith(".txt") || name.endsWith(".ijm"))) {
     IJ.showMessage("Macro Installer", "File name must end with \".txt\" or \".ijm\" .");
     return null;
   }
   fileName = name;
   defaultDir = dir;
   return dir + name;
 }
 void installPopupMenu(String name, Program pgm) {
   Hashtable h = pgm.getMenus();
   if (h == null) return;
   String[] commands = (String[]) h.get(name);
   if (commands == null) return;
   PopupMenu popup = Menus.getPopupMenu();
   if (popup == null) return;
   popup.removeAll();
   for (int i = 0; i < commands.length; i++) {
     if (commands[i].equals("-")) popup.addSeparator();
     else {
       MenuItem mi = new MenuItem(commands[i]);
       mi.addActionListener(this);
       popup.add(mi);
     }
   }
 }
示例#8
0
 public void run(String arg) {
   if (arg.equals("menus")) {
     updateMenus();
     return;
   }
   if (IJ.getApplet() != null) return;
   // File file = new File(Prefs.getHomeDir() + File.separator + "ij.jar");
   // if (isMac() && !file.exists())
   //	file = new File(Prefs.getHomeDir() + File.separator +
   // "ImageJ.app/Contents/Resources/Java/ij.jar");
   URL url = getClass().getResource("/ij/IJ.class");
   String ij_jar = url == null ? null : url.toString().replaceAll("%20", " ");
   if (ij_jar == null || !ij_jar.startsWith("jar:file:")) {
     error("Could not determine location of ij.jar");
     return;
   }
   int exclamation = ij_jar.indexOf('!');
   ij_jar = ij_jar.substring(9, exclamation);
   if (IJ.debugMode) IJ.log("Updater: " + ij_jar);
   File file = new File(ij_jar);
   if (!file.exists()) {
     error("File not found: " + file.getPath());
     return;
   }
   if (!file.canWrite()) {
     String msg = "No write access: " + file.getPath();
     if (IJ.isVista()) msg += Prefs.vistaHint;
     error(msg);
     return;
   }
   String[] list = openUrlAsList(IJ.URL + "/download/jars/list.txt");
   int count = list.length + 2;
   String[] versions = new String[count];
   String[] urls = new String[count];
   String uv = getUpgradeVersion();
   if (uv == null) return;
   versions[0] = "v" + uv;
   urls[0] = IJ.URL + "/upgrade/ij.jar";
   if (versions[0] == null) return;
   for (int i = 1; i < count - 1; i++) {
     String version = list[i - 1];
     versions[i] = version.substring(0, version.length() - 1); // remove letter
     urls[i] =
         IJ.URL + "/download/jars/ij" + version.substring(1, 2) + version.substring(3, 6) + ".jar";
   }
   versions[count - 1] = "daily build";
   urls[count - 1] = IJ.URL + "/ij.jar";
   int choice = showDialog(versions);
   if (choice == -1) return;
   if (!versions[choice].startsWith("daily")
       && versions[choice].compareTo("v1.39") < 0
       && Menus.getCommands().get("ImageJ Updater") == null) {
     String msg =
         "This command is not available in versions of ImageJ prior\n"
             + "to 1.39 so you will need to install the plugin version at\n"
             + "<"
             + IJ.URL
             + "/plugins/imagej-updater.html>.";
     if (!IJ.showMessageWithCancel("Update ImageJ", msg)) return;
   }
   byte[] jar = getJar(urls[choice]);
   // file.renameTo(new File(file.getParent()+File.separator+"ij.bak"));
   if (version().compareTo("1.37v") >= 0) Prefs.savePreferences();
   // if (!renameJar(file)) return; // doesn't work on Vista
   saveJar(file, jar);
   if (choice < count - 1) // force macro Function Finder to download fresh list
   new File(IJ.getDirectory("macros") + "functions.html").delete();
   System.exit(0);
 }
示例#9
0
 public void windowActivated(WindowEvent e) {
   if (IJ.isMacintosh() && !quitting) {
     IJ.wait(10); // may be needed for Java 1.4 on OS X
     setMenuBar(Menus.getMenuBar());
   }
 }
示例#10
0
  public void keyPressed(KeyEvent e) {
    // if (e.isConsumed()) return;
    int keyCode = e.getKeyCode();
    IJ.setKeyDown(keyCode);
    hotkey = false;
    if (keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT) return;
    char keyChar = e.getKeyChar();
    int flags = e.getModifiers();
    if (IJ.debugMode)
      IJ.log(
          "keyPressed: code="
              + keyCode
              + " ("
              + KeyEvent.getKeyText(keyCode)
              + "), char=\""
              + keyChar
              + "\" ("
              + (int) keyChar
              + "), flags="
              + KeyEvent.getKeyModifiersText(flags));
    boolean shift = (flags & KeyEvent.SHIFT_MASK) != 0;
    boolean control = (flags & KeyEvent.CTRL_MASK) != 0;
    boolean alt = (flags & KeyEvent.ALT_MASK) != 0;
    boolean meta = (flags & KeyEvent.META_MASK) != 0;
    String cmd = null;
    ImagePlus imp = WindowManager.getCurrentImage();
    boolean isStack = (imp != null) && (imp.getStackSize() > 1);

    if (imp != null
        && !control
        && ((keyChar >= 32 && keyChar <= 255) || keyChar == '\b' || keyChar == '\n')) {
      Roi roi = imp.getRoi();
      if (roi instanceof TextRoi) {
        if ((flags & KeyEvent.META_MASK) != 0 && IJ.isMacOSX()) return;
        if (alt) {
          switch (keyChar) {
            case 'u':
            case 'm':
              keyChar = IJ.micronSymbol;
              break;
            case 'A':
              keyChar = IJ.angstromSymbol;
              break;
            default:
          }
        }
        ((TextRoi) roi).addChar(keyChar);
        return;
      }
    }

    // Handle one character macro shortcuts
    if (!control && !meta) {
      Hashtable macroShortcuts = Menus.getMacroShortcuts();
      if (macroShortcuts.size() > 0) {
        if (shift) cmd = (String) macroShortcuts.get(new Integer(keyCode + 200));
        else cmd = (String) macroShortcuts.get(new Integer(keyCode));
        if (cmd != null) {
          // MacroInstaller.runMacroCommand(cmd);
          commandName = cmd;
          MacroInstaller.runMacroShortcut(cmd);
          return;
        }
      }
    }

    if ((!Prefs.requireControlKey || control || meta) && keyChar != '+') {
      Hashtable shortcuts = Menus.getShortcuts();
      if (shift) cmd = (String) shortcuts.get(new Integer(keyCode + 200));
      else cmd = (String) shortcuts.get(new Integer(keyCode));
    }

    if (cmd == null) {
      switch (keyChar) {
        case '<':
        case ',':
          if (isStack) cmd = "Previous Slice [<]";
          break;
        case '>':
        case '.':
        case ';':
          if (isStack) cmd = "Next Slice [>]";
          break;
        case '+':
        case '=':
          cmd = "In [+]";
          break;
        case '-':
          cmd = "Out [-]";
          break;
        case '/':
          cmd = "Reslice [/]...";
          break;
        default:
      }
    }

    if (cmd == null) {
      switch (keyCode) {
        case KeyEvent.VK_TAB:
          WindowManager.putBehind();
          return;
        case KeyEvent.VK_BACK_SPACE: // delete
          if (deleteOverlayRoi(imp)) return;
          cmd = "Clear";
          hotkey = true;
          break;
          // case KeyEvent.VK_BACK_SLASH: cmd=IJ.altKeyDown()?"Animation Options...":"Start
          // Animation"; break;
        case KeyEvent.VK_EQUALS:
          cmd = "In [+]";
          break;
        case KeyEvent.VK_MINUS:
          cmd = "Out [-]";
          break;
        case KeyEvent.VK_SLASH:
        case 0xbf:
          cmd = "Reslice [/]...";
          break;
        case KeyEvent.VK_COMMA:
        case 0xbc:
          if (isStack) cmd = "Previous Slice [<]";
          break;
        case KeyEvent.VK_PERIOD:
        case 0xbe:
          if (isStack) cmd = "Next Slice [>]";
          break;
        case KeyEvent.VK_LEFT:
        case KeyEvent.VK_RIGHT:
        case KeyEvent.VK_UP:
        case KeyEvent.VK_DOWN: // arrow keys
          if (imp == null) return;
          Roi roi = imp.getRoi();
          if (IJ.shiftKeyDown() && imp == Orthogonal_Views.getImage()) return;
          boolean stackKey = imp.getStackSize() > 1 && (roi == null || IJ.shiftKeyDown());
          boolean zoomKey = roi == null || IJ.shiftKeyDown() || IJ.controlKeyDown();
          if (stackKey && keyCode == KeyEvent.VK_RIGHT) cmd = "Next Slice [>]";
          else if (stackKey && keyCode == KeyEvent.VK_LEFT) cmd = "Previous Slice [<]";
          else if (zoomKey
              && keyCode == KeyEvent.VK_DOWN
              && !ignoreArrowKeys(imp)
              && Toolbar.getToolId() < Toolbar.SPARE6) cmd = "Out [-]";
          else if (zoomKey
              && keyCode == KeyEvent.VK_UP
              && !ignoreArrowKeys(imp)
              && Toolbar.getToolId() < Toolbar.SPARE6) cmd = "In [+]";
          else if (roi != null) {
            if ((flags & KeyEvent.ALT_MASK) != 0) roi.nudgeCorner(keyCode);
            else roi.nudge(keyCode);
            return;
          }
          break;
        case KeyEvent.VK_ESCAPE:
          abortPluginOrMacro(imp);
          return;
        case KeyEvent.VK_ENTER:
          WindowManager.toFront(this);
          return;
        default:
          break;
      }
    }

    if (cmd != null && !cmd.equals("")) {
      commandName = cmd;
      if (cmd.equals("Fill") || cmd.equals("Draw")) hotkey = true;
      if (cmd.charAt(0) == MacroInstaller.commandPrefix) MacroInstaller.runMacroShortcut(cmd);
      else {
        doCommand(cmd);
        keyPressedTime = System.currentTimeMillis();
        lastKeyCommand = cmd;
      }
    }
  }
示例#11
0
  /**
   * If 'applet' is not null, creates a new ImageJ frame that runs as an applet. If 'mode' is
   * ImageJ.EMBEDDED and 'applet is null, creates an embedded (non-standalone) version of ImageJ.
   */
  public ImageJ(java.applet.Applet applet, int mode) {
    super("ImageJ");
    if ((mode & DEBUG) != 0) IJ.setDebugMode(true);
    mode = mode & 255;
    if (IJ.debugMode) IJ.log("ImageJ starting in debug mode: " + mode);
    embedded = applet == null && (mode == EMBEDDED || mode == NO_SHOW);
    this.applet = applet;
    String err1 = Prefs.load(this, applet);
    setBackground(backgroundColor);
    Menus m = new Menus(this, applet);
    String err2 = m.addMenuBar();
    m.installPopupMenu(this);
    setLayout(new BorderLayout());

    // Tool bar
    toolbar = new Toolbar();
    toolbar.addKeyListener(this);
    add("Center", toolbar);

    // Status bar
    statusBar = new Panel();
    statusBar.setLayout(new BorderLayout());
    statusBar.setForeground(Color.black);
    statusBar.setBackground(backgroundColor);
    statusLine = new JLabel();
    statusLine.setFont(new Font("SansSerif", Font.PLAIN, 13));
    statusLine.addKeyListener(this);
    statusLine.addMouseListener(this);
    statusBar.add("Center", statusLine);
    progressBar = new ProgressBar(120, 20);
    progressBar.addKeyListener(this);
    progressBar.addMouseListener(this);
    statusBar.add("East", progressBar);
    add("South", statusBar);

    IJ.init(this, applet);
    addKeyListener(this);
    addWindowListener(this);
    setFocusTraversalKeysEnabled(false);
    m.installStartupMacroSet(); // add custom tools
    runStartupMacro();

    Point loc = getPreferredLocation();
    Dimension tbSize = toolbar.getPreferredSize();
    setCursor(Cursor.getDefaultCursor()); // work-around for JDK 1.1.8 bug
    if (mode != NO_SHOW) {
      if (IJ.isWindows())
        try {
          setIcon();
        } catch (Exception e) {
        }
      setLocation(loc.x, loc.y);
      setResizable(!IJ.isMacOSX());
      pack();
      setVisible(true);
    }
    if (err1 != null) IJ.error(err1);
    if (err2 != null) {
      IJ.error(err2);
      IJ.runPlugIn("ij.plugin.ClassChecker", "");
    }
    if (IJ.isMacintosh() && applet == null) {
      Object qh = null;
      qh = IJ.runPlugIn("MacAdapter", "");
      if (qh == null) IJ.runPlugIn("QuitHandler", "");
    }
    if (applet == null) IJ.runPlugIn("ij.plugin.DragAndDrop", "");
    String str = m.getMacroCount() == 1 ? " macro" : " macros";
    IJ.showStatus(version() + m.getPluginCount() + " commands; " + m.getMacroCount() + str);
    configureProxy();
    if (applet == null) loadCursors();
  }
示例#12
0
  /**
   * If 'applet' is not null, creates a new ImageJ frame that runs as an applet. If 'mode' is
   * ImageJ.EMBEDDED and 'applet is null, creates an embedded (non-standalone) version of ImageJ.
   */
  public ImageJ(java.applet.Applet applet, int mode) {
    super("ImageJ");
    embedded = applet == null && (mode == EMBEDDED || mode == NO_SHOW);
    this.applet = applet;
    String err1 = Prefs.load(this, applet);
    if (IJ.isLinux()) {
      backgroundColor = new Color(240, 240, 240);
      setBackground(backgroundColor);
    }
    Menus m = new Menus(this, applet);
    String err2 = m.addMenuBar();
    m.installPopupMenu(this);
    setLayout(new GridLayout(2, 1));

    // Tool bar
    toolbar = new Toolbar();
    toolbar.addKeyListener(this);
    add(toolbar);

    // Status bar
    statusBar = new Panel();
    statusBar.setLayout(new BorderLayout());
    statusBar.setForeground(Color.black);
    statusBar.setBackground(backgroundColor);
    statusLine = new Label();
    statusLine.setFont(SansSerif12);
    statusLine.addKeyListener(this);
    statusLine.addMouseListener(this);
    statusBar.add("Center", statusLine);
    progressBar = new ProgressBar(120, 20);
    progressBar.addKeyListener(this);
    progressBar.addMouseListener(this);
    statusBar.add("East", progressBar);
    statusBar.setSize(toolbar.getPreferredSize());
    add(statusBar);

    IJ.init(this, applet);
    addKeyListener(this);
    addWindowListener(this);
    setFocusTraversalKeysEnabled(false);

    Point loc = getPreferredLocation();
    Dimension tbSize = toolbar.getPreferredSize();
    int ijWidth = tbSize.width + 10;
    int ijHeight = 100;
    setCursor(Cursor.getDefaultCursor()); // work-around for JDK 1.1.8 bug
    if (mode != NO_SHOW) {
      if (IJ.isWindows())
        try {
          setIcon();
        } catch (Exception e) {
        }
      setBounds(loc.x, loc.y, ijWidth, ijHeight); // needed for pack to work
      setLocation(loc.x, loc.y);
      pack();
      setResizable(!(IJ.isMacintosh() || IJ.isWindows())); // make resizable on Linux
      show();
    }
    if (err1 != null) IJ.error(err1);
    if (err2 != null) {
      IJ.error(err2);
      IJ.runPlugIn("ij.plugin.ClassChecker", "");
    }
    m.installStartupMacroSet();
    if (IJ.isMacintosh() && applet == null) {
      Object qh = null;
      qh = IJ.runPlugIn("MacAdapter", "");
      if (qh == null) IJ.runPlugIn("QuitHandler", "");
    }
    if (applet == null) IJ.runPlugIn("ij.plugin.DragAndDrop", "");
    String str = m.getMacroCount() == 1 ? " macro" : " macros";
    IJ.showStatus(version() + m.getPluginCount() + " commands; " + m.getMacroCount() + str);
    // if (applet==null && !embedded && Prefs.runSocketListener)
    //	new SocketListener();
    configureProxy();
    if (applet == null) loadCursors();
  }
示例#13
0
  private Object tryOpen(String directory, String name, String path) {
    // set up a stream to read in 132 bytes from the file header
    // These can be checked for "magic" values which are diagnostic
    // of some image types
    InputStream is;
    byte[] buf = new byte[132];
    try {
      if (0 == path.indexOf("http://")) is = new java.net.URL(path).openStream();
      else is = new FileInputStream(path);
      is.read(buf, 0, 132);
      is.close();
    } catch (IOException e) {
      // couldn't open the file for reading
      return null;
    }
    name = name.toLowerCase();
    width = PLUGIN_NOT_FOUND;

    // Temporarily suppress "plugin not found" errors if LOCI Bio-Formats plugin is installed
    if (Menus.getCommands().get("Bio-Formats Importer") != null
        && IJ.getVersion().compareTo("1.37u") >= 0) IJ.suppressPluginNotFoundError();

    // OK now we get to the interesting bit

    // GJ: added Biorad PIC confocal file handler
    // ------------------------------------------
    // These make 12345 if you read them as the right kind of short
    // and should have this value in every Biorad PIC file
    if (buf[54] == 57 && buf[55] == 48) {
      return tryPlugIn("Biorad_Reader", path);
    }
    // GJ: added Gatan Digital Micrograph DM3 handler
    // ----------------------------------------------
    // check if the file ends in .DM3 or .dm3,
    // and bytes make an int value of 3 which is the DM3 version number
    if (name.endsWith(".dm3") && buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 3) {
      return tryPlugIn("DM3_Reader", path);
    }

    // IPLab file handler
    // Little-endian IPLab files start with "iiii" or "mmmm".
    if (name.endsWith(".ipl")
        || (buf[0] == 105 && buf[1] == 105 && buf[2] == 105 && buf[3] == 105)
        || (buf[0] == 109 && buf[1] == 109 && buf[2] == 109 && buf[3] == 109)) {
      return tryPlugIn("IPLab_Reader", path);
    }

    // Packard InstantImager format (.img) handler -> check HERE
    // before Analyze check below!
    // Check extension and signature bytes KAJ_
    if (name.endsWith(".img") && buf[0] == 75 && buf[1] == 65 && buf[2] == 74 && buf[3] == 0) {
      return tryPlugIn("InstantImager_Reader", path);
    }

    // Analyze format (.img/.hdr) handler
    // Opens the file using the Nifti_Reader if it is installed,
    // otherwise the Analyze_Reader is used. Note that
    // the Analyze_Reader plugin opens and displays the
    // image and does not implement the ImagePlus class.
    if (name.endsWith(".img") || name.endsWith(".hdr")) {
      if (Menus.getCommands().get("NIfTI-Analyze") != null) return tryPlugIn("Nifti_Reader", path);
      else return tryPlugIn("Analyze_Reader", path);
    }

    // NIFTI format (.nii) handler
    if (name.endsWith(".nii") || name.endsWith(".nii.gz") || name.endsWith(".nii.z")) {
      return tryPlugIn("Nifti_Reader", path);
    }

    // Image Cytometry Standard (.ics) handler
    // http://valelab.ucsf.edu/~nico/IJplugins/Ics_Opener.html
    if (name.endsWith(".ics")) {
      return tryPlugIn("Ics_Opener", path);
    }

    // Princeton Instruments SPE image file (.spe) handler
    // http://rsb.info.nih.gov/ij/plugins/spe.html
    if (name.endsWith(".spe")) {
      return tryPlugIn("OpenSPE_", path);
    }

    // Zeiss Confocal LSM 510 image file (.lsm) handler
    // http://rsb.info.nih.gov/ij/plugins/lsm-reader.html
    if (name.endsWith(".lsm")) {
      Object obj = tryPlugIn("LSM_Reader", path);
      if (obj == null && Menus.getCommands().get("Show LSMToolbox") != null)
        obj = tryPlugIn("LSM_Toolbox", "file=" + path);
      return obj;
    }

    // BM: added Bruker file handler 29.07.04
    if (name.equals("ser")
        || name.equals("fid")
        || name.equals("2rr")
        || name.equals("2ii")
        || name.equals("3rrr")
        || name.equals("3iii")
        || name.equals("2dseq")) {
      ij.IJ.showStatus("Opening Bruker " + name + " File");
      return tryPlugIn("BrukerOpener", name + "|" + path);
    }

    // AVI: open AVI files using AVI_Reader plugin
    if (name.endsWith(".avi")) {
      return tryPlugIn("AVI_Reader", path);
    }

    // QuickTime: open .mov and .pict files using QT_Movie_Opener plugin
    if (name.endsWith(".mov") || name.endsWith(".pict")) {
      return tryPlugIn("QT_Movie_Opener", path);
    }

    // ZVI file handler
    // Little-endian ZVI and Thumbs.db files start with d0 cf 11 e0
    // so we can only look at the extension.
    if (name.endsWith(".zvi")) {
      return tryPlugIn("ZVI_Reader", path);
    }

    // University of North Carolina (UNC) file format handler
    // 'magic' numbers are (int) offsets to data structures and
    // may change in future releases.
    if (name.endsWith(".unc")
        || (buf[3] == 117 && buf[7] == -127 && buf[11] == 36 && buf[14] == 32 && buf[15] == -127)) {
      return tryPlugIn("UNC_Reader", path);
    }

    // Amira file handler
    // http://wbgn013.biozentrum.uni-wuerzburg.de/ImageJ/amira-io.html
    if (buf[0] == 0x23
        && buf[1] == 0x20
        && buf[2] == 0x41
        && buf[3] == 0x6d
        && buf[4] == 0x69
        && buf[5] == 0x72
        && buf[6] == 0x61
        && buf[7] == 0x4d
        && buf[8] == 0x65
        && buf[9] == 0x73
        && buf[10] == 0x68
        && buf[11] == 0x20) {
      return tryPlugIn("AmiraMeshReader_", path);
    }

    // Deltavision file handler
    // Open DV files generated on Applied Precision DeltaVision systems
    if (name.endsWith(".dv") || name.endsWith(".r3d")) {
      return tryPlugIn("Deltavision_Opener", path);
    }

    // Albert Cardona: read .mrc files (little endian).
    // Documentation at: http://ami.scripps.edu/prtl_data/mrc_specification.htm.
    // The parsing of the header is a bare minimum of what could be done.
    if (name.endsWith(".mrc")) {
      return tryPlugIn("Open_MRC_Leginon", path);
    }

    // Albert Cardona: read .dat files from the EMMENU software
    if (name.endsWith(".dat") && 1 == buf[1] && 0 == buf[2]) { // 'new format' only
      return tryPlugIn("Open_DAT_EMMENU", path);
    }

    // Timo Rantalainen and Michael Doube: read Stratec pQCT files.
    // File name is IDDDDDDD.MHH, where D is decimal and H is hex.
    if (name.matches("[iI]\\d{7}\\.[mM]\\p{XDigit}{2}")) {
      return tryPlugIn("org.doube.bonej.pqct.Read_Stratec_File", path);
    }

    // Michael Doube: read Scanco ISQ files
    // File name is ADDDDDDD.ISQ;D where D is a decimal and A is a letter
    try {
      String isqMagic = new String(buf, 0, 16, "UTF-8");
      if (name.matches("[a-z]\\d{7}.isq;\\d+") || isqMagic.equals("CTDATA-HEADER_V1"))
        return tryPlugIn("org.bonej.io.ISQReader", path);
    } catch (Exception e) {
    }

    // David Mills: read Queen Mary MCD files
    if (name.endsWith(".mcd")) {
      return tryPlugIn("mcdReader", path);
    }
    // David Mills: read Queen Mary TOM files
    if (name.endsWith(".tom")) {
      return tryPlugIn("tomReader", path);
    }

    // ****************** MODIFY HERE ******************
    // do what ever you have to do to recognise your own file type
    // and then call appropriate plugin using the above as models
    // e.g.:

    /*
    // A. Dent: Added XYZ handler
    // ----------------------------------------------
    // check if the file ends in .xyz, and bytes 0 and 1 equal 42
    if (name.endsWith(".xyz") && buf[0]==42 && buf[1]==42) {
    // Ok we've identified the file type - now load it
    	return tryPlugIn("XYZ_Reader", path);
    }
    */

    return null;
  }
 public boolean install(String path) {
   boolean isURL = path.contains("://");
   String lcPath = path.toLowerCase();
   if (isURL) path = Opener.updateUrl(path);
   boolean isTool =
       lcPath.endsWith("tool.ijm")
           || lcPath.endsWith("tool.txt")
           || lcPath.endsWith("tool.class")
           || lcPath.endsWith("tool.jar");
   boolean isMacro = lcPath.endsWith(".txt") || lcPath.endsWith(".ijm");
   byte[] data = null;
   String name = path;
   if (isURL) {
     int index = path.lastIndexOf("/");
     if (index != -1 && index <= path.length() - 1) name = path.substring(index + 1);
     data = download(path, name);
   } else {
     File f = new File(path);
     name = f.getName();
     data = download(f);
   }
   if (data == null) return false;
   if (name.endsWith(".txt") && !name.contains("_"))
     name = name.substring(0, name.length() - 4) + ".ijm";
   if (name.endsWith(".zip")) {
     if (!name.contains("_")) {
       IJ.error("Plugin Installer", "No underscore in file name:\n \n  " + name);
       return false;
     }
     name = name.substring(0, name.length() - 4) + ".jar";
   }
   String dir = null;
   boolean isLibrary = name.endsWith(".jar") && !name.contains("_");
   if (isLibrary) {
     dir = Menus.getPlugInsPath() + "jars";
     File f = new File(dir);
     if (!f.exists()) {
       boolean ok = f.mkdir();
       if (!ok) dir = Menus.getPlugInsPath();
     }
   }
   if (isTool) {
     dir = Menus.getPlugInsPath() + "Tools" + File.separator;
     File f = new File(dir);
     if (!f.exists()) {
       boolean ok = f.mkdir();
       if (!ok) dir = null;
     }
     if (dir != null && isMacro) {
       String name2 = getToolName(data);
       if (name2 != null) name = name2;
     }
   }
   if (dir == null) {
     SaveDialog sd =
         new SaveDialog("Save Plugin, Macro or Script...", Menus.getPlugInsPath(), name, null);
     String name2 = sd.getFileName();
     if (name2 == null) return false;
     dir = sd.getDirectory();
   }
   // IJ.log(dir+"   "+Menus.getPlugInsPath());
   if (!savePlugin(new File(dir, name), data)) return false;
   if (name.endsWith(".java")) IJ.runPlugIn("ij.plugin.Compiler", dir + name);
   Menus.updateImageJMenus();
   if (isTool) {
     if (isMacro) IJ.runPlugIn("ij.plugin.Macro_Runner", "Tools/" + name);
     else if (name.endsWith(".class")) {
       name = name.replaceAll("_", " ");
       name = name.substring(0, name.length() - 6);
       IJ.run(name);
     }
   }
   return true;
 }
 void install() {
   subMenus.clear();
   if (text != null) {
     Tokenizer tok = new Tokenizer();
     pgm = tok.tokenize(text);
   }
   if (macrosMenu != null) IJ.showStatus("");
   int[] code = pgm.getCode();
   Symbol[] symbolTable = pgm.getSymbolTable();
   int count = 0, token, nextToken, address;
   String name;
   Symbol symbol;
   shortcutsInUse = null;
   inUseCount = 0;
   nShortcuts = 0;
   toolCount = 0;
   macroStarts = new int[MAX_MACROS];
   macroNames = new String[MAX_MACROS];
   boolean isPluginsMacrosMenu = false;
   if (macrosMenu != null) {
     int itemCount = macrosMenu.getItemCount();
     isPluginsMacrosMenu = macrosMenu == Menus.getMacrosMenu();
     int baseCount = isPluginsMacrosMenu ? MACROS_MENU_COMMANDS : Editor.MACROS_MENU_ITEMS;
     if (itemCount > baseCount) {
       for (int i = itemCount - 1; i >= baseCount; i--) macrosMenu.remove(i);
     }
   }
   if (pgm.hasVars() && pgm.macroCount() > 0 && pgm.getGlobals() == null)
     new Interpreter().saveGlobals(pgm);
   ArrayList tools = new ArrayList();
   for (int i = 0; i < code.length; i++) {
     token = code[i] & TOK_MASK;
     if (token == MACRO) {
       nextToken = code[i + 1] & TOK_MASK;
       if (nextToken == STRING_CONSTANT) {
         if (count == MAX_MACROS) {
           if (isPluginsMacrosMenu)
             IJ.error("Macro Installer", "Macro sets are limited to " + MAX_MACROS + " macros.");
           break;
         }
         address = code[i + 1] >> TOK_SHIFT;
         symbol = symbolTable[address];
         name = symbol.str;
         macroStarts[count] = i + 2;
         macroNames[count] = name;
         if (name.indexOf('-') != -1
             && (name.indexOf("Tool") != -1 || name.indexOf("tool") != -1)) {
           tools.add(name);
           toolCount++;
         } else if (name.startsWith("AutoRun")) {
           if (autoRunCount == 0 && !openingStartupMacrosInEditor) {
             new MacroRunner(pgm, macroStarts[count], name, (String) null);
             if (name.equals("AutoRunAndHide")) autoRunAndHideCount++;
           }
           autoRunCount++;
           count--;
         } else if (name.equals("Popup Menu")) installPopupMenu(name, pgm);
         else if (!name.endsWith("Tool Selected")) {
           if (macrosMenu != null) {
             addShortcut(name);
             int pos = name.indexOf(">");
             boolean inSubMenu = name.startsWith("<") && (pos > 1);
             if (inSubMenu) {
               Menu parent = macrosMenu;
               Menu subMenu = null;
               String parentStr = name.substring(1, pos).trim();
               String childStr = name.substring(pos + 1).trim();
               MenuItem mnuItem = new MenuItem();
               mnuItem.setActionCommand(name);
               mnuItem.setLabel(childStr);
               for (int jj = 0; jj < subMenus.size(); jj++) {
                 String aName = subMenus.get(jj).getName();
                 if (aName.equals(parentStr)) subMenu = subMenus.get(jj);
               }
               if (subMenu == null) {
                 subMenu = new Menu(parentStr);
                 subMenu.setName(parentStr);
                 subMenu.addActionListener(this);
                 subMenus.add(subMenu);
                 parent.add(subMenu);
               }
               subMenu.add(mnuItem);
             } else macrosMenu.add(new MenuItem(name));
           }
         }
         // IJ.log(count+" "+name+" "+macroStarts[count]);
         count++;
       }
     } else if (token == EOF) break;
   }
   nMacros = count;
   if (toolCount > 0 && (isPluginsMacrosMenu || macrosMenu == null) && installTools) {
     Toolbar tb = Toolbar.getInstance();
     if (toolCount == 1) tb.addMacroTool((String) tools.get(0), this);
     else {
       for (int i = 0; i < tools.size(); i++) {
         String toolName = (String) tools.get(i);
         if (toolName.startsWith("Abort Macro or Plugin") && toolCount > 6)
           toolName = "Unused " + toolName;
         tb.addMacroTool(toolName, this, i);
       }
     }
     if (toolCount > 1 && Toolbar.getToolId() >= Toolbar.CUSTOM1) tb.setTool(Toolbar.RECTANGLE);
     tb.repaint();
   }
   if (macrosMenu != null) this.instance = this;
   if (shortcutsInUse != null && text != null)
     IJ.showMessage(
         "Install Macros",
         (inUseCount == 1 ? "This keyboard shortcut is" : "These keyboard shortcuts are")
             + " already in use:"
             + shortcutsInUse);
   if (nMacros == 0 && fileName != null) {
     if (text == null || text.length() == 0) return;
     int dotIndex = fileName.lastIndexOf('.');
     if (dotIndex > 0) anonymousName = fileName.substring(0, dotIndex);
     else anonymousName = fileName;
     if (macrosMenu != null) macrosMenu.add(new MenuItem(anonymousName));
     macroNames[0] = anonymousName;
     nMacros = 1;
   }
   String word = nMacros == 1 ? " macro" : " macros";
   if (isPluginsMacrosMenu) IJ.showStatus(nMacros + word + " installed");
 }