org.gjt.sp.jedit.GUIUtilities

public class GUIUtilities
{
	//{{{ Some predefined icons
	/**
	 * @deprecated Use GUIUtilities.loadIcon("new.gif");
	 * instead.
	 */
	@Deprecated
	public static Icon NEW_BUFFER_ICON;

	/**
	 * @deprecated Use GUIUtilities.loadIcon("dirty.gif");
	 * instead.
	 */
	@Deprecated
	public static Icon DIRTY_BUFFER_ICON;

	/**
	 * @deprecated Use GUIUtilities.loadIcon("readonly.gif");
	 * instead.
	 */
	@Deprecated
	public static Icon READ_ONLY_BUFFER_ICON;

	/**
	 * @deprecated Use GUIUtilities.loadIcon("normal.gif");
	 * instead.
	 */
	@Deprecated
	public static Icon NORMAL_BUFFER_ICON;

	/**
	 * @deprecated Use GUIUtilities.loadIcon("jedit-icon.gif");
	 * instead.
	 */
	@Deprecated
	public static Icon WINDOW_ICON;
	//}}}

	//{{{ Icon methods

	//{{{ setIconPath() method
	/**
	 * Sets the path where jEdit looks for icons.
	 * @since jEdit 4.2pre5
	 */
	public static void setIconPath(String iconPath)
	{
		GUIUtilities.iconPath = iconPath;
		if(icons != null)
			icons.clear();
	} //}}}

	//{{{ loadIcon() method
	/**
	 * Loads an icon.
	 * @param iconName The icon name
	 * @since jEdit 2.6pre7
	 */
	public static Icon loadIcon(String iconName)
	{
		if(iconName == null)
			return null;

		// * Enable old icon naming scheme support
		if(deprecatedIcons != null && deprecatedIcons.containsKey(iconName))
			iconName = deprecatedIcons.get(iconName);

		if(icons == null)
			icons = new Hashtable<String, Icon>();

		// check if there is a cached version first
		Icon icon = icons.get(iconName);
		if(icon != null)
			return icon;

		URL url;

		try
		{
			// get the icon
			if(MiscUtilities.isURL(iconName))
				url = new URL(iconName);
			else
				url = new URL(iconPath + iconName);
		}
		catch(Exception e)
		{
			try
			{
				url = new URL(defaultIconPath + iconName);
			}
			catch(Exception ex)
			{
				Log.log(Log.ERROR,GUIUtilities.class,
					"Icon not found: " + iconName);
				Log.log(Log.ERROR,GUIUtilities.class,ex);
				return null;
			}
		}

		icon = new ImageIcon(url);

		icons.put(iconName,icon);
		return icon;
	} //}}}

	//{{{ getEditorIcon() method
	/**
	 * Returns the default editor window image.
	 */
	public static Image getEditorIcon()
	{
		return ((ImageIcon)loadIcon(jEdit.getProperty("logo.icon.medium"))).getImage();
	} //}}}

	//{{{ getPluginIcon() method
	/**
	 * Returns the default plugin window image.
	 */
	public static Image getPluginIcon()
	{
		return getEditorIcon();
	} //}}}

	//}}}

	//{{{ Menus, tool bars

	//{{{ loadMenuBar() method
	/**
	 * Creates a menubar. Plugins should not need to call this method.
	 * @param name The menu bar name
	 * @since jEdit 3.2pre5
	 */
	public static JMenuBar loadMenuBar(String name)
	{
		return loadMenuBar(jEdit.getActionContext(),name);
	} //}}}

	//{{{ loadMenuBar() method
	/**
	 * Creates a menubar. Plugins should not need to call this method.
	 * @param context An action context
	 * @param name The menu bar name
	 * @since jEdit 4.2pre1
	 */
	public static JMenuBar loadMenuBar(ActionContext context, String name)
	{
		String menus = jEdit.getProperty(name);
		StringTokenizer st = new StringTokenizer(menus);

		JMenuBar mbar = new JMenuBar();

		while(st.hasMoreTokens())
		{
			String menuName = st.nextToken();
			mbar.add(loadMenu(context, menuName));
		}

		return mbar;
	} //}}}

	//{{{ loadMenu() method
	/**
	 * Creates a menu. The menu label is set from the
	 * name.label property. The menu contents is taken
	 * from the name property, which is a whitespace
	 * separated list of action names. An action name of -
	 * inserts a separator in the menu.
	 * @param name The menu name
	 * @see #loadMenuItem(String)
	 * @since jEdit 2.6pre2
	 */
	public static JMenu loadMenu(String name)
	{
		return loadMenu(jEdit.getActionContext(),name);
	} //}}}

	//{{{ loadMenu() method
	/**
	 * Creates a menu. The menu label is set from the
	 * name.label property. The menu contents is taken
	 * from the name property, which is a whitespace
	 * separated list of action names. An action name of -
	 * inserts a separator in the menu.
	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The menu name
	 * @see #loadMenuItem(String)
	 * @since jEdit 4.2pre1
	 */
	public static JMenu loadMenu(ActionContext context, String name)
	{
		return new EnhancedMenu(name,
			jEdit.getProperty(name.concat(".label")),
			context);
	} //}}}

	//{{{ loadPopupMenu() method
	/**
	 * Creates a popup menu.
	 * @param name The menu name
	 * @since jEdit 2.6pre2
	 */
	public static JPopupMenu loadPopupMenu(String name, JEditTextArea textArea, MouseEvent evt)
	{
		return loadPopupMenu(jEdit.getActionContext(), name, textArea, evt);
	} //}}}

	//{{{ loadPopupMenu() method
	/**
	 * Creates a popup menu.

	 * @param name The menu name
	 * @since jEdit 2.6pre2
	 */
	public static JPopupMenu loadPopupMenu(String name)
	{
		return loadPopupMenu(jEdit.getActionContext(),name);
	} //}}}

	//{{{ loadPopupMenu() method
	/**
	 * Creates a popup menu.

	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The menu name
	 * @since jEdit 4.2pre1
	 */
	public static JPopupMenu loadPopupMenu(ActionContext context, String name)
	{
		return loadPopupMenu(context, name, null, null);
	}

	//{{{ loadPopupMenu() method
	/**
	 * Creates a popup menu.
	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The menu name
	 * @param textArea the textArea wanting to show the popup.
	 * 	If not null, include context menu items defined by services.
	 * @param evt additional context info about where the mouse was when menu was requested
	 * @since jEdit 4.3pre15
	 */
	public static JPopupMenu loadPopupMenu(ActionContext context, String name, JEditTextArea textArea, MouseEvent evt)
	{
		JPopupMenu menu = new JPopupMenu();

		String menuItems = jEdit.getProperty(name);
		if(menuItems != null)
		{
			StringTokenizer st = new StringTokenizer(menuItems);
			while(st.hasMoreTokens())
			{
				String menuItemName = st.nextToken();
				if(menuItemName.equals("-"))
					menu.addSeparator();
				else
					menu.add(loadMenuItem(context,menuItemName,false));
			}
		}
		// load menu items defined by services
		if (textArea != null)
		{
			List<JMenuItem> list = GUIUtilities.getServiceContextMenuItems(textArea, evt);
			if (!list.isEmpty())
			{
				menu.addSeparator();
			}
			for (JMenuItem mi : list)
			{
				menu.add(mi);
			}
		}

		return menu;
	} //}}}
	//{{{ addServiceContextMenuItems() method
	/**
	 * @return a list of menu items defined by services.
	 *
	 * @param textArea the TextArea desiring to display these menu items
	 * @since jEdit 4.3pre15
	 */
	public static List<JMenuItem> getServiceContextMenuItems(JEditTextArea textArea, MouseEvent evt)
	{
		List<JMenuItem> list = new ArrayList<JMenuItem>();
		String serviceClassName =  DynamicContextMenuService.class.getName();
		String[] menuServiceList = ServiceManager.getServiceNames(serviceClassName);
		for (String menuServiceName : menuServiceList)
		{
			if (menuServiceName != null && menuServiceName.trim().length() > 0)
			{
				DynamicContextMenuService dcms = (DynamicContextMenuService)
						ServiceManager.getService(serviceClassName, menuServiceName);
				if (dcms != null)
				{
					JMenuItem[] items = dcms.createMenu(textArea, evt);
					if (items != null)
					{
						list.addAll(Arrays.asList(items));
					}
				}
			}
		}
		return list;
	} //}}}

	//{{{ loadMenuItem() method
	/**
	 * Creates a menu item. The menu item is bound to the action named by
	 * name with label taken from the return value of the
	 * {@link EditAction#getLabel()} method.
	 *
	 * @param name The menu item name
	 * @see #loadMenu(String)
	 * @since jEdit 2.6pre1
	 */
	public static JMenuItem loadMenuItem(String name)
	{
		return loadMenuItem(jEdit.getActionContext(),name,true);
	} //}}}

	//{{{ loadMenuItem() method
	/**
	 * Creates a menu item.
	 * @param name The menu item name
	 * @param setMnemonic True if the menu item should have a mnemonic
	 * @since jEdit 3.1pre1
	 */
	public static JMenuItem loadMenuItem(String name, boolean setMnemonic)
	{
		return loadMenuItem(jEdit.getActionContext(),name,setMnemonic);
	} //}}}

	//{{{ loadMenuItem() method
	/**
	 * Creates a menu item.
	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The menu item name
	 * @param setMnemonic True if the menu item should have a mnemonic
	 * @since jEdit 4.2pre1
	 */
	public static JMenuItem loadMenuItem(ActionContext context, String name,
		boolean setMnemonic)
	{
		if(name.charAt(0) == '%')
			return loadMenu(context,name.substring(1));

		return _loadMenuItem(name, context, setMnemonic);
	} //}}}

	//{{{ loadMenuItem(EditAction, boolean)
	public static JMenuItem loadMenuItem(EditAction editAction,
		boolean setMnemonic)
	{
		String name = editAction.getName();
		ActionContext context = jEdit.getActionContext();

		return _loadMenuItem(name, context, setMnemonic);
	} //}}}

	//{{{ loadToolBar() method
	/**
	 * Creates a toolbar.
	 * @param name The toolbar name
	 * @since jEdit 4.2pre2
	 */
	public static Container loadToolBar(String name)
	{
		return loadToolBar(jEdit.getActionContext(),name);
	} //}}}

	//{{{ loadToolBar() method
	/**
	 * Creates a toolbar.
	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The toolbar name
	 * @since jEdit 4.2pre2
	 */
	public static Container loadToolBar(ActionContext context, String name)
	{
		JPanel toolBar = new JPanel(new BorderLayout());
		JToolBar toolB = new JToolBar();
		toolB.setFloatable(false);
		toolB.setMargin(new Insets(0,0,0,0));

		String buttons = jEdit.getProperty(name);
		if(buttons != null)
		{
			StringTokenizer st = new StringTokenizer(buttons);
			while(st.hasMoreTokens())
			{
				String button = st.nextToken();
				if(button.equals("-"))
				{
					toolB.addSeparator(new Dimension(12,12));
				}
				else
				{
					JButton b = loadToolButton(context,button);
					if(b != null)
						toolB.add(b);
				}
			}
		}

		toolBar.add(toolB);
		return toolBar;
	} //}}}

	//{{{ loadToolButton() method
	/**
	 * Loads a tool bar button. The tooltip is constructed from
	 * the name.label and
	 * name.shortcut properties and the icon is loaded
	 * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
	 * with the value of the name.icon property.
	 * @param name The name of the button
	 */
	public static EnhancedButton loadToolButton(String name)
	{
		return loadToolButton(jEdit.getActionContext(),name);
	} //}}}

	//{{{ loadToolButton() method
	/**
	 * Loads a tool bar button. The tooltip is constructed from
	 * the name.label and
	 * name.shortcut properties and the icon is loaded
	 * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
	 * with the value of the name.icon property.
	 * @param context An action context; either
	 * jEdit.getActionContext() or
	 * VFSBrowser.getActionContext().
	 * @param name The name of the button
	 * @since jEdit 4.2pre1
	 */
	public static EnhancedButton loadToolButton(ActionContext context,
		String name)
	{
		String label = jEdit.getProperty(name + ".label");

		if(label == null)
			label = name;

		Icon icon;
		String iconName = jEdit.getProperty(name + ".icon");
		if(iconName == null)
			icon = loadIcon(jEdit.getProperty("broken-image.icon"));
		else
		{
			icon = loadIcon(iconName);
			if(icon == null)
				icon = loadIcon(jEdit.getProperty("broken-image.icon"));
		}

		String toolTip = prettifyMenuLabel(label);
		String shortcutLabel = getShortcutLabel(name);
		if(shortcutLabel != null)
		{
			toolTip = toolTip + " (" + shortcutLabel + ')';
		}

		EnhancedButton b = new EnhancedButton(icon,toolTip,name,context);
		b.setPreferredSize(new Dimension(32,32));
		return b;
	} //}}}

	//{{{ prettifyMenuLabel() method
	/**
	 * `Prettifies' a menu item label by removing the `$' sign. This
	 * can be used to process the contents of an action.label
	 * property.
	 */
	public static String prettifyMenuLabel(String label)
	{
		int index = label.indexOf('$');
		if(index != -1)
		{
			label = label.substring(0,index)
				.concat(label.substring(index + 1));
		}
		return label;
	} //}}}

	//{{{ getShortcutLabel() method
	/**
	 * Returns a label string to show users what shortcut are
	 * assigned to the action.
	 */
	public static String getShortcutLabel(String action)
	{
		if(action == null)
			return null;
		else
		{
			String shortcut1 = jEdit.getProperty(action + ".shortcut");
			String shortcut2 = jEdit.getProperty(action + ".shortcut2");

			if(shortcut1 == null || shortcut1.length() == 0)
			{
				if(shortcut2 == null || shortcut2.length() == 0)
					return null;
				else
					return shortcut2;
			}
			else
			{
				if(shortcut2 == null || shortcut2.length() == 0)
					return shortcut1;
				else
					return shortcut1 + " or " + shortcut2;
			}
		}
	} //}}}

	//}}}

	//}}}

	//{{{ Canned dialog boxes

	//{{{ message() method
	/**
	 * Displays a dialog box.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property. The message
	 * is formatted by the property manager with args as
	 * positional parameters.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param args Positional parameters to be substituted into the
	 * message text
	 */
	public static void message(Component comp, String name, Object[] args)
	{
		hideSplashScreen();

		JOptionPane.showMessageDialog(comp,
			jEdit.getProperty(name.concat(".message"),args),
			jEdit.getProperty(name.concat(".title"),args),
			JOptionPane.INFORMATION_MESSAGE);
	} //}}}

	//{{{ error() method
	/**
	 * Displays an error dialog box.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property. The message
	 * is formatted by the property manager with args as
	 * positional parameters.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param args Positional parameters to be substituted into the
	 * message text
	 */
	public static void error(Component comp, String name, Object[] args)
	{
		hideSplashScreen();

		JOptionPane.showMessageDialog(comp,
			jEdit.getProperty(name.concat(".message"),args),
			jEdit.getProperty(name.concat(".title"),args),
			JOptionPane.ERROR_MESSAGE);
	} //}}}

	//{{{ input() method
	/**
	 * Displays an input dialog box and returns any text the user entered.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param def The text to display by default in the input field
	 */
	public static String input(Component comp, String name, Object def)
	{
		return input(comp,name,null,def);
	} //}}}

	//{{{ inputProperty() method
	/**
	 * Displays an input dialog box and returns any text the user entered.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param def The property whose text to display in the input field
	 */
	public static String inputProperty(Component comp, String name,
		String def)
	{
		return inputProperty(comp,name,null,def);
	} //}}}

	//{{{ input() method
	/**
	 * Displays an input dialog box and returns any text the user entered.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param def The text to display by default in the input field
	 * @param args Positional parameters to be substituted into the
	 * message text
	 * @since jEdit 3.1pre3
	 */
	public static String input(Component comp, String name,
		Object[] args, Object def)
	{
		hideSplashScreen();

		String retVal = (String)JOptionPane.showInputDialog(comp,
			jEdit.getProperty(name.concat(".message"),args),
			jEdit.getProperty(name.concat(".title")),
			JOptionPane.QUESTION_MESSAGE,null,null,def);
		return retVal;
	} //}}}

	//{{{ inputProperty() method
	/**
	 * Displays an input dialog box and returns any text the user entered.
	 * The title of the dialog is fetched from
	 * the name.title property. The message is fetched
	 * from the name.message property.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param args Positional parameters to be substituted into the
	 * message text
	 * @param def The property whose text to display in the input field
	 * @since jEdit 3.1pre3
	 */
	public static String inputProperty(Component comp, String name,
		Object[] args, String def)
	{
		hideSplashScreen();

		String retVal = (String)JOptionPane.showInputDialog(comp,
			jEdit.getProperty(name.concat(".message"),args),
			jEdit.getProperty(name.concat(".title")),
			JOptionPane.QUESTION_MESSAGE,
			null,null,jEdit.getProperty(def));
		if(retVal != null)
			jEdit.setProperty(def,retVal);
		return retVal;
	} //}}}

	//{{{ confirm() method
	/**
	 * Displays a confirm dialog box and returns the button pushed by the
	 * user. The title of the dialog is fetched from the
	 * name.title property. The message is fetched
	 * from the name.message property.
	 * @param comp The component to display the dialog for
	 * @param name The name of the dialog
	 * @param args Positional parameters to be substituted into the
	 * message text
	 * @param buttons The buttons to display - for example,
	 * JOptionPane.YES_NO_CANCEL_OPTION
	 * @param type The dialog type - for example,
	 * JOptionPane.WARNING_MESSAGE
	 * @since jEdit 3.1pre3
	 */
	public static int confirm(Component comp, String name,
		Object[] args, int buttons, int type)
	{
		hideSplashScreen();

		return JOptionPane.showConfirmDialog(comp,
			jEdit.getProperty(name + ".message",args),
			jEdit.getProperty(name + ".title"),buttons,type);
	} //}}}

	//{{{ listConfirm() method
	/**
	 * Displays a confirm dialog box and returns the button pushed by the
	 * user. The title of the dialog is fetched from the
	 * name.title property. The message is fetched
	 * from the name.message property. The dialog
	 * also shows a list of entries given by the listModel
	 * parameter.
	 * @param comp the parent component
	 * @param name the name of the confirm dialog
	 * @param args the for the message
	 * @param listModel the items in the list
	 * @return an integer indicating the option selected by the user
	 * @since jEdit 4.3pre1
	 */
	public static int listConfirm(Component comp, String name, String[] args,
		Object[] listModel)
	{
		JList list = new JList(listModel);
		list.setVisibleRowCount(8);

		Object[] message = {
			jEdit.getProperty(name + ".message",args),
			new JScrollPane(list)
		};

		return JOptionPane.showConfirmDialog(comp,
			message,
			jEdit.getProperty(name + ".title"),
			JOptionPane.YES_NO_OPTION,
			JOptionPane.QUESTION_MESSAGE);
	} //}}}

	//{{{ listConfirm() method
	/**
	 * Displays a confirm dialog box and returns the button pushed by the
	 * user. The title of the dialog is fetched from the
	 * name.title property. The message is fetched
	 * from the name.message property. The dialog
	 * also shows a list of entries given by the listModel
	 * parameter.
	 * @param comp the parent component
	 * @param name the name of the confirm dialog
	 * @param args the for the message
	 * @param listModel the items in the list
	 * @param selectedItems give an empty list, it will contains in return the selected items
	 * @return an integer indicating the option selected by the user
	 * @since jEdit 4.3pre12
	 */
	public static int listConfirm(Component comp, String name, String[] args,
		Object[] listModel, List selectedItems)
	{
		JList list = new JList(listModel);
		list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		list.setVisibleRowCount(8);
		list.addSelectionInterval(0,listModel.length - 1);

		Object[] message = {
			jEdit.getProperty(name + ".message",args),
			new JScrollPane(list)
		};

		int ret = JOptionPane.showConfirmDialog(comp,
							message,
							jEdit.getProperty(name + ".title"),
							JOptionPane.YES_NO_OPTION,
							JOptionPane.QUESTION_MESSAGE);
		Object[] selectedValues = list.getSelectedValues();
		selectedItems.addAll(Arrays.asList(selectedValues));
		return ret;
	} //}}}

	//{{{ showVFSFileDialog() methods
	/**
	 * Displays a VFS file selection dialog box.
	 * @param view The view, should be non-null
	 * @param path The initial directory to display. May be null
	 * @param type The dialog type. One of
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
	 * @param multipleSelection True if multiple selection should be allowed
	 * @return The selected file(s)
	 * @since jEdit 2.6pre2
	 */
	public static String[] showVFSFileDialog(View view, String path,
		int type, boolean multipleSelection)
	{
		// the view should not be null, but some plugins might do this
		if(view == null)
		{
			Log.log(Log.WARNING,GUIUtilities.class,
			"showVFSFileDialog(): given null view, assuming jEdit.getActiveView()");
			view = jEdit.getActiveView();
		}

		hideSplashScreen();

		VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
			view,path,type,multipleSelection);
		return fileChooser.getSelectedFiles();
	}

	/**
	 * Displays a VFS file selection dialog box.
	 * This version can specify a dialog as the parent instead
	 * of the view.
	 * @param view The view, should be non-null
	 * @param path The initial directory to display. May be null
	 * @param type The dialog type. One of
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
	 * @param multipleSelection True if multiple selection should be allowed
	 * @return The selected file(s)
	 * @since jEdit 4.3pre10
	 */
	public static String[] showVFSFileDialog(Dialog parent, View view,
		String path, int type, boolean multipleSelection)
	{
		hideSplashScreen();

		VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
			parent, view, path, type, multipleSelection, true);
		return fileChooser.getSelectedFiles();
	}

	/**
	 * Displays a VFS file selection dialog box.
	 * This version can specify a frame as the parent instead
	 * of the view.
	 * @param parent The parent frame
	 * @param view The view, should be non-null
	 * @param path The initial directory to display. May be null
	 * @param type The dialog type. One of
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
	 * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
	 * @param multipleSelection True if multiple selection should be allowed
	 * @return The selected file(s)
	 * @since jEdit 4.3pre10
	 */
	public static String[] showVFSFileDialog(Frame parent, View view,
		String path, int type, boolean multipleSelection)
	{
		hideSplashScreen();
		VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
			parent, view, path, type, multipleSelection, true);
		return fileChooser.getSelectedFiles();
	} //}}}

	//}}}

	//{{{ Colors and styles

	//{{{ parseColor() method
	/**
	 * Converts a color name to a color object. The name must either be
	 * a known string, such as `red', `green', etc (complete list is in
	 * the java.awt.Color class) or a hex color value
	 * prefixed with `#', for example `#ff0088'.
	 * @param name The color name
	 */
	public static Color parseColor(String name)
	{
		return SyntaxUtilities.parseColor(name, Color.black);
	} //}}}

	//{{{ parseColor() method
	/**
	 * @deprecated use {@link SyntaxUtilities#parseColor(String,Color)}
	 */
	@Deprecated
	public static Color parseColor(String name, Color defaultColor)
	{
		return SyntaxUtilities.parseColor(name, defaultColor);
	} //}}}

	//{{{ getColorHexString() method
	/**
	 * Converts a color object to its hex value. The hex value
	 * prefixed is with `#', for example `#ff0088'.
	 * @param c The color object
	 * @deprecated use {@link SyntaxUtilities#parseStyle(String,String,int,boolean)}
	 */
	@Deprecated
	public static String getColorHexString(Color c)
	{
		return SyntaxUtilities.getColorHexString(c);
	} //}}}

	//{{{ parseStyle() method
	/**
	 * Converts a style string to a style object.
	 * @param str The style string
	 * @param family Style strings only specify font style, not font family
	 * @param size Style strings only specify font style, not font family
	 * @exception IllegalArgumentException if the style is invalid
	 * @since jEdit 3.2pre6
	 */
	public static SyntaxStyle parseStyle(String str, String family, int size)
		throws IllegalArgumentException
	{
		return SyntaxUtilities.parseStyle(str,family,size,true);
	} //}}}

	//{{{ parseStyle() method
	/**
	 * Converts a style string to a style object.
	 * @param str The style string
	 * @param family Style strings only specify font style, not font family
	 * @param size Style strings only specify font style, not font family
	 * @param color If false, the styles will be monochrome
	 * @exception IllegalArgumentException if the style is invalid
	 * @since jEdit 4.0pre4
	 * @deprecated use {@link SyntaxUtilities#parseStyle(String,String,int,boolean)}
	 */
	@Deprecated
	public static SyntaxStyle parseStyle(String str, String family, int size,
		boolean color)
		throws IllegalArgumentException
	{
		return SyntaxUtilities.parseStyle(str,family,size,color);
	} //}}}

	//{{{ getStyleString() method
	/**
	 * Converts a style into it's string representation.
	 * @param style The style
	 */
	public static String getStyleString(SyntaxStyle style)
	{
		StringBuilder buf = new StringBuilder();

		if (style.getForegroundColor() != null)
		{
			buf.append("color:").append(SyntaxUtilities.getColorHexString(style.getForegroundColor()));
		}

		if (style.getBackgroundColor() != null)
		{
			buf.append(" bgColor:").append(SyntaxUtilities.getColorHexString(style.getBackgroundColor()));
		}

		Font font = style.getFont();
		if (!font.isPlain())
		{
			buf.append(" style:");
			if (font.isItalic())
				buf.append('i');
			if (font.isBold())
				buf.append('b');
		}

		return buf.toString();
	} //}}}

	//{{{ loadStyles() method
	/**
	 * Loads the syntax styles from the properties, giving them the specified
	 * base font family and size.
	 * @param family The font family
	 * @param size The font size
	 * @since jEdit 3.2pre6
	 * @deprecated use {@link SyntaxUtilities#loadStyles(String,int)}
	 */
	@Deprecated
	public static SyntaxStyle[] loadStyles(String family, int size)
	{
		return SyntaxUtilities.loadStyles(family,size,true);
	}

	/**
	 * Loads the syntax styles from the properties, giving them the specified
	 * base font family and size.
	 * @param family The font family
	 * @param size The font size
	 * @param color If false, the styles will be monochrome
	 * @since jEdit 4.0pre4
	 * @deprecated use {@link SyntaxUtilities#loadStyles(String,int,boolean)}
	 */
	@Deprecated
	public static SyntaxStyle[] loadStyles(String family, int size, boolean color)
	{
		return SyntaxUtilities.loadStyles(family, size, color);
	} //}}}

	//}}}

	//{{{ Loading, saving window geometry

	//{{{ loadGeometry() method
	/**
	 * Loads a windows's geometry from the properties.
	 * The geometry is loaded from the name.x,
	 * name.y, name.width and
	 * name.height properties.
	 *
	 * @param win The window to load geometry from
	 * @param parent The parent frame to be relative to.
	 * @param name The name of the window
	 */
	public static void loadGeometry(Window win, Container parent, String name )
	{
		Dimension size = win.getSize();
		int width = jEdit.getIntegerProperty(name + ".width", size.width);
		int height = jEdit.getIntegerProperty(name + ".height", size.height);
		int x = jEdit.getIntegerProperty(name + ".x",50);
		int y = jEdit.getIntegerProperty(name + ".y",50);
		if(parent != null)
		{
			Point location = parent.getLocation();
			x = location.x + x;
			y = location.y + y;
		}

		int extState = jEdit.getIntegerProperty(name + ".extendedState", Frame.NORMAL);

		Rectangle desired = new Rectangle(x,y,width,height);
		try
		{
			if(!Debug.DISABLE_MULTIHEAD)
				adjustForScreenBounds(desired);
		}
		catch(Exception e)
		{
			/* Workaround for OS X bug. */
			Log.log(Log.ERROR,GUIUtilities.class,e);
		}

		if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
			new UnixWorkaround(win,name,desired,extState);
		else
		{
			win.setBounds(desired);
			if(win instanceof Frame)
				((Frame)win).setExtendedState(extState);
		}

	} //}}}

	//{{{ loadGeometry() method
	/**
	 * Loads a windows's geometry from the properties.
	 * The geometry is loaded from the name.x,
	 * name.y, name.width and
	 * name.height properties.
	 *
	 * @param win The window to load geometry from
	 * @param name The name of the window
	 */
	public static void loadGeometry(Window win, String name)
	{
		loadGeometry(win, win.getParent(), name);
	} //}}}

	//{{{ adjustForScreenBounds() method
	/**
	 * Gives a rectangle the specified bounds, ensuring it is within the
	 * screen bounds.
	 * @since jEdit 4.2pre3
	 */
	public static void adjustForScreenBounds(Rectangle desired)
	{
		// Make sure the window is displayed in visible region
		Rectangle osbounds = OperatingSystem.getScreenBounds(desired);

		if (desired.width > osbounds.width)
		{
			desired.width = osbounds.width;
		}
		if (desired.x < osbounds.x)
		{
			desired.x = osbounds.x;
		}
		if (desired.x + desired.width > osbounds.x + osbounds.width)
		{
			desired.x = osbounds.x + osbounds.width - desired.width;
		}
		if (desired.height > osbounds.height)
		{
			desired.height = osbounds.height;
		}
		if (desired.y < osbounds.y)
		{
			desired.y = osbounds.y;
		}
		if (desired.y + desired.height > osbounds.y + osbounds.height)
		{
			desired.y = osbounds.y + osbounds.height - desired.height;
		}
	} //}}}

	//{{{ UnixWorkaround class
	public static class UnixWorkaround
	{
		Window win;
		String name;
		Rectangle desired;
		Rectangle required;
		long start;
		boolean windowOpened;

		//{{{ UnixWorkaround constructor
		public UnixWorkaround(Window win, String name, Rectangle desired,
			int extState)
		{
			this.win = win;
			this.name = name;
			this.desired = desired;

			int adjust_x = jEdit.getIntegerProperty(name + ".dx",0);
			int adjust_y = jEdit.getIntegerProperty(name + ".dy",0);
			int adjust_width = jEdit.getIntegerProperty(name + ".d-width",0);
			int adjust_height = jEdit.getIntegerProperty(name + ".d-height",0);

			required = new Rectangle(
				desired.x - adjust_x,
				desired.y - adjust_y,
				desired.width - adjust_width,
				desired.height - adjust_height);

			Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
				+ ": desired geometry is " + desired);
			Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
				+ ": setting geometry to " + required);

			start = System.currentTimeMillis();

			win.setBounds(required);
			if(win instanceof Frame)
				((Frame)win).setExtendedState(extState);

			win.addComponentListener(new ComponentHandler());
			win.addWindowListener(new WindowHandler());
		} //}}}

		//{{{ ComponentHandler class
		private class ComponentHandler extends ComponentAdapter
		{
			//{{{ componentMoved() method
			@Override
			public void componentMoved(ComponentEvent evt)
			{
				if(System.currentTimeMillis() - start < 1000L)
				{
					Rectangle r = win.getBounds();
					if(!windowOpened && r.equals(required))
						return;

					if(!r.equals(desired))
					{
						Log.log(Log.DEBUG,GUIUtilities.class,
							"Window resize blocked: " + win.getBounds());
						win.setBounds(desired);
					}
				}

				win.removeComponentListener(this);
			} //}}}

			//{{{ componentResized() method
			@Override
			public void componentResized(ComponentEvent evt)
			{
				if(System.currentTimeMillis() - start < 1000L)
				{
					Rectangle r = win.getBounds();
					if(!windowOpened && r.equals(required))
						return;

					if(!r.equals(desired))
					{
						Log.log(Log.DEBUG,GUIUtilities.class,
							"Window resize blocked: " + win.getBounds());
						win.setBounds(desired);
					}
				}

				win.removeComponentListener(this);
			} //}}}
		} //}}}

		//{{{ WindowHandler class
		private class WindowHandler extends WindowAdapter
		{
			//{{{ windowOpened() method
			@Override
			public void windowOpened(WindowEvent evt)
			{
				windowOpened = true;

				Rectangle r = win.getBounds();
				Log.log(Log.DEBUG,GUIUtilities.class,"Window "
					+ name + ": bounds after opening: " + r);

				jEdit.setIntegerProperty(name + ".dx",
					r.x - required.x);
				jEdit.setIntegerProperty(name + ".dy",
					r.y - required.y);
				jEdit.setIntegerProperty(name + ".d-width",
					r.width - required.width);
				jEdit.setIntegerProperty(name + ".d-height",
					r.height - required.height);

				win.removeWindowListener(this);
			} //}}}
		} //}}}
	} //}}}

	//{{{ saveGeometry() method
	/**
	 * Saves a window's geometry to the properties.
	 * The geometry is saved to the name.x,
	 * name.y, name.width and
	 * name.height properties.

	 * For Frame's and descendents use {@link #addSizeSaver(Frame,String)} to save the sizes
	 * correct even if the Frame is in maximized or iconified state.
	 * @param win The window to load geometry from
	 * @param name The name of the window
	 * @see #addSizeSaver(Frame,String)
	 */
	public static void saveGeometry(Window win, String name)
	{
		saveGeometry (win, win.getParent(), name);
	} //}}}

	//{{{ saveGeometry() method
	/**
	 * Saves a window's geometry to the properties.
	 * The geometry is saved to the name.x,
	 * name.y, name.width and
	 * name.height properties.

	 * For Frame's and descendents use {@link #addSizeSaver(Frame,Container,String)} to save the sizes
	 * correct even if the Frame is in maximized or iconified state.
	 * @param win The window to load geometry from
	 * @param parent The parent frame to be relative to.
	 * @param name The name of the window
	 * @see #addSizeSaver(Frame,Container,String)
	 */
	public static void saveGeometry(Window win, Container parent, String name)
	{
		if(win instanceof Frame)
		{
			jEdit.setIntegerProperty(name + ".extendedState",
				((Frame)win).getExtendedState());
		}

		Rectangle bounds = win.getBounds();
		int x = bounds.x;
		int y = bounds.y;
		if (parent != null)
		{
			Rectangle parentBounds = parent.getBounds();
			x -= parentBounds.x;
			y -= parentBounds.y;
		}
		jEdit.setIntegerProperty(name + ".x",x);
		jEdit.setIntegerProperty(name + ".y",y);
		jEdit.setIntegerProperty(name + ".width", bounds.width);
		jEdit.setIntegerProperty(name + ".height", bounds.height);
	} //}}}

	//{{{ centerOnScreen() method
	/**
	 * Centers the given window on the screen. This method is needed because
	 * JDK 1.3 does not have a JWindow.setLocationRelativeTo()
	 * method.
	 * @since jEdit 4.2pre3
	 * @deprecated use {@link javax.swing.JWindow#setLocationRelativeTo(java.awt.Component)}
	 */
	@Deprecated
	public static void centerOnScreen(Window win)
	{
		GraphicsDevice gd = GraphicsEnvironment
			.getLocalGraphicsEnvironment()
			.getDefaultScreenDevice();
		Rectangle gcbounds = gd.getDefaultConfiguration().getBounds();
		int x = gcbounds.x + (gcbounds.width - win.getWidth()) / 2;
		int y = gcbounds.y + (gcbounds.height - win.getHeight()) / 2;
		win.setLocation(x,y);
	} //}}}

	//}}}

	//{{{ hideSplashScreen() method
	/**
	 * Ensures that the splash screen is not visible. This should be
	 * called before displaying any dialog boxes or windows at
	 * startup.
	 */
	public static void hideSplashScreen()
	{
		if(splash != null)
		{
			splash.dispose();
			splash = null;
		}
	} //}}}

	//{{{ createMultilineLabel() method
	/**
	 * Creates a component that displays a multiple line message. This
	 * is implemented by assembling a number of JLabels in
	 * a JPanel.
	 * @param str The string, with lines delimited by newline
	 * (\n) characters.
	 * @since jEdit 4.1pre3
	 */
	public static JComponent createMultilineLabel(String str)
	{
		JPanel panel = new JPanel(new VariableGridLayout(
			VariableGridLayout.FIXED_NUM_COLUMNS,1,1,1));
		int lastOffset = 0;
		while(true)
		{
			int index = str.indexOf('\n',lastOffset);
			if(index == -1)
				break;
			else
			{
				panel.add(new JLabel(str.substring(lastOffset,index)));
				lastOffset = index + 1;
			}
		}

		if(lastOffset != str.length())
			panel.add(new JLabel(str.substring(lastOffset)));

		return panel;
	} //}}}

	//{{{ requestFocus() method
	/**
	 * Focuses on the specified component as soon as the window becomes
	 * active.
	 * @param win The window
	 * @param comp The component
	 */
	public static void requestFocus(final Window win, final Component comp)
	{
		win.addWindowFocusListener(new WindowAdapter()
		{
			@Override
			public void windowGainedFocus(WindowEvent evt)
			{
				SwingUtilities.invokeLater(new Runnable()
				{
						public void run()
						{
							comp.requestFocusInWindow();
						}
				});
				win.removeWindowFocusListener(this);
			}
		});
	} //}}}

	//{{{ isPopupTrigger() method
	/**
	 * Returns if the specified event is the popup trigger event.
	 * This implements precisely defined behavior, as opposed to
	 * MouseEvent.isPopupTrigger().
	 * @param evt The event
	 * @since jEdit 3.2pre8
	 */
	public static boolean isPopupTrigger(MouseEvent evt)
	{
		return TextAreaMouseHandler.isRightButton(evt.getModifiers());
	} //}}}

	//{{{ isMiddleButton() method
	/**
	 * @param modifiers The modifiers flag from a mouse event
	 * @since jEdit 4.1pre9
	 */
	public static boolean isMiddleButton(int modifiers)
	{
		return TextAreaMouseHandler.isMiddleButton(modifiers);
	} //}}}

	//{{{ isRightButton() method
	/**
	 * @param modifiers The modifiers flag from a mouse event
	 * @since jEdit 4.1pre9
	 */
	public static boolean isRightButton(int modifiers)
	{
		return TextAreaMouseHandler.isRightButton(modifiers);
	} //}}}

	//{{{ getScreenBounds() method
	/**
	 * Returns the screen bounds, taking into account multi-screen
	 * environments.
	 * @since jEdit 4.3pre18
	 */
	public static Rectangle getScreenBounds()
	{
		Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().
			getMaximumWindowBounds();
		GraphicsDevice [] devices = GraphicsEnvironment.
			getLocalGraphicsEnvironment().getScreenDevices();
		if (devices.length > 1)
		{
			for (GraphicsDevice device: devices)
			{
				for (GraphicsConfiguration config: device.getConfigurations())
					bounds = bounds.union(config.getBounds());
			}
		}
		return bounds;
	}

	//{{{ showPopupMenu() method
	/**
	 * Shows the specified popup menu, ensuring it is displayed within
	 * the bounds of the screen.
	 * @param popup The popup menu
	 * @param comp The component to show it for
	 * @param x The x co-ordinate
	 * @param y The y co-ordinate
	 * @since jEdit 4.0pre1
	 * @see javax.swing.JComponent#setComponentPopupMenu(javax.swing.JPopupMenu) setComponentPopupMenu
	 * which works better and is simpler to use: you don't have to write the code to
	 * show/hide popups in response to mouse events anymore.
	 */
	public static void showPopupMenu(JPopupMenu popup, Component comp,
		int x, int y)
	{
		showPopupMenu(popup,comp,x,y,true);
	} //}}}

	//{{{ showPopupMenu() method
	/**
	 * Shows the specified popup menu, ensuring it is displayed within
	 * the bounds of the screen.
	 * @param popup The popup menu
	 * @param comp The component to show it for
	 * @param x The x co-ordinate
	 * @param y The y co-ordinate
	 * @param point If true, then the popup originates from a single point;
	 * otherwise it will originate from the component itself. This affects
	 * positioning in the case where the popup does not fit onscreen.
	 *
	 * @since jEdit 4.1pre1
	 */
	public static void showPopupMenu(JPopupMenu popup, Component comp,
		int x, int y, boolean point)
	{
		int offsetX = 0;
		int offsetY = 0;

		int extraOffset = point ? 1 : 0;

		Component win = comp;
		while(!(win instanceof Window || win == null))
		{
			offsetX += win.getX();
			offsetY += win.getY();
			win = win.getParent();
		}

		if(win != null)
		{
			Dimension size = popup.getPreferredSize();

			Rectangle screenSize = getScreenBounds();

			if(x + offsetX + size.width + win.getX() > screenSize.width
				&& x + offsetX + win.getX() >= size.width)
			{
				//System.err.println("x overflow");
				if(point)
					x -= size.width + extraOffset;
				else
					x = win.getWidth() - size.width - offsetX + extraOffset;
			}
			else
			{
				x += extraOffset;
			}

			//System.err.println("y=" + y + ",offsetY=" + offsetY
			//	+ ",size.height=" + size.height
			//	+ ",win.height=" + win.getHeight());
			if(y + offsetY + size.height + win.getY() > screenSize.height
				&& y + offsetY + win.getY() >= size.height)
			{
				if(point)
					y = win.getHeight() - size.height - offsetY + extraOffset;
				else
					y = -size.height - 1;
			}
			else
			{
				y += extraOffset;
			}

			popup.show(comp,x,y);
		}
		else
			popup.show(comp,x + extraOffset,y + extraOffset);

	} //}}}

	//{{{ isAncestorOf() method
	/**
	 * Returns if the first component is an ancestor of the
	 * second by traversing up the component hierarchy.
	 *
	 * @param comp1 The ancestor
	 * @param comp2 The component to check
	 * @since jEdit 4.1pre5
	 */
	public static boolean isAncestorOf(Component comp1, Component comp2)
	{
		while(comp2 != null)
		{
			if(comp1 == comp2)
				return true;
			else
				comp2 = comp2.getParent();
		}

		return false;
	} //}}}

	//{{{ getParentDialog() method
	/**
	 * Traverses the given component's parent tree looking for an
	 * instance of JDialog, and return it. If not found, return null.
	 * @param c The component
	 */
	public static JDialog getParentDialog(Component c)
	{
		return (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, c);
	} //}}}

	//{{{ getComponentParent() method
	/**
	 * Finds a parent of the specified component.
	 * @param comp The component
	 * @param clazz Looks for a parent with this class (exact match, not
	 * derived).
	 * @since jEdit 4.2pre1
	 */
	public static Component getComponentParent(Component comp, Class clazz)
	{
		while(true)
		{
			if(comp == null)
				break;

			if(comp instanceof JComponent)
			{
				Component real = (Component)((JComponent)comp)
					.getClientProperty("KORTE_REAL_FRAME");
				if(real != null)
					comp = real;
			}

			if(comp.getClass().equals(clazz))
				return comp;
			else if(comp instanceof JPopupMenu)
				comp = ((JPopupMenu)comp).getInvoker();
			else if(comp instanceof FloatingWindowContainer)
			{
				comp = ((FloatingWindowContainer)comp)
					.getDockableWindowManager();
			}
			else
				comp = comp.getParent();
		}
		return null;
	} //}}}

	//{{{ setEnabledRecursively() method
	/**
	 * Call setEnabled() recursively on the container and its descendants.
	 * @param c The container
	 * @param enabled The enabled state to set
	 * @since jEdit 4.3pre17
	 */
	public static void setEnabledRecursively(Container c, boolean enabled)
	{
		for (Component child: c.getComponents())
		{
			if (child instanceof Container)
				setEnabledRecursively((Container)child, enabled);
			else
				child.setEnabled(enabled);
		}
		c.setEnabled(enabled);
	} //}}}

	//{{{ getView() method
	/**
	 * Finds the view parent of the specified component.
	 * @since jEdit 4.0pre2
	 */
	public static View getView(Component comp)
	{
		return (View)getComponentParent(comp,View.class);
	} //}}}

	//{{{ addSizeSaver() method
	/**
	* Adds a SizeSaver to the specified Frame. For non-Frame's use {@link #saveGeometry(Window,String)}
	 *
	 * @param frame The Frame for which to save the size
	 * @param name The prefix for the settings
	 * @since jEdit 4.3pre6
	 * @see #saveGeometry(Window,String)
	 */
	public static void addSizeSaver(Frame frame, String name)
	{
		addSizeSaver(frame,frame.getParent(),name);
	} //}}}

	//{{{ addSizeSaver() method
	/**
	 * Adds a SizeSaver to the specified Frame. For non-Frame's use {@link #saveGeometry(Window,Container,String)}
	 *
	 * @param frame The Frame for which to save the size
	 * @param parent The parent to be relative to
	 * @param name The prefix for the settings
	 * @since jEdit 4.3pre7
	 * @see #saveGeometry(Window,Container,String)
	 */
	public static void addSizeSaver(Frame frame, Container parent, String name)
	{
		SizeSaver ss = new SizeSaver(frame,parent,name);
		frame.addWindowStateListener(ss);
		frame.addComponentListener(ss);
	} //}}}

	//{{{ initContinuousLayout() method
	/**
	 * Init the continuous layout flag using the jEdit's property
	 * appearance.continuousLayout
	 *
	 * @param split the split. It must never be null
	 * @since jEdit 4.3pre9
	 */
	public static void initContinuousLayout(JSplitPane split)
	{
		boolean continuousLayout = split.isContinuousLayout();
		if (continuousLayout != jEdit.getBooleanProperty("appearance.continuousLayout"))
			split.setContinuousLayout(!continuousLayout);
	} //}}}

	//{{{ Package-private members

	//{{{ initializeDeprecatedIcons() method
	/**
	 * Initializes a list of mappings between old icon names and new names
	 */
	private static void initializeDeprecatedIcons()
	{
		deprecatedIcons.put("File.png",       "16x16/mimetypes/text-x-generic.png");
		deprecatedIcons.put("Folder.png",     "16x16/places/folder.png");
		deprecatedIcons.put("OpenFolder.png", "16x16/status/folder-open.png");
		deprecatedIcons.put("OpenFile.png",   "16x16/actions/edit-select-all.png");
		deprecatedIcons.put("ReloadSmall.png","16x16/actions/view-refresh.png");
		deprecatedIcons.put("DriveSmall.png", "16x16/devices/drive-harddisk.png");
		deprecatedIcons.put("New.png",        "22x22/actions/document-new.png");
		deprecatedIcons.put("NewDir.png",     "22x22/actions/folder-new.png");
		deprecatedIcons.put("Reload.png",     "22x22/actions/view-refresh.png");
		deprecatedIcons.put("Load.png",       "22x22/places/plugins.png");
		deprecatedIcons.put("Save.png",       "22x22/actions/document-save.png");
		deprecatedIcons.put("SaveAs.png",     "22x22/actions/document-save-as.png");
		deprecatedIcons.put("SaveAll.png",    "22x22/actions/document-save-all.png");
		deprecatedIcons.put("Open.png",       "22x22/actions/document-open.png");
		deprecatedIcons.put("Print.png",      "22x22/actions/document-print.png");
		deprecatedIcons.put("Drive.png",      "22x22/devices/drive-harddisk.png");
		deprecatedIcons.put("Clear.png",      "22x22/actions/edit-clear.png");
		deprecatedIcons.put("Run.png",        "22x22/actions/application-run.png");
		deprecatedIcons.put("RunAgain.png",   "22x22/actions/application-run-again.png");
		deprecatedIcons.put("RunToBuffer.png",  "22x22/actions/run-to-buffer.png");
		deprecatedIcons.put("CopyToBuffer.png", "22x22/actions/copy-to-buffer.png");
		deprecatedIcons.put("Plus.png",       "22x22/actions/list-add.png");
		deprecatedIcons.put("Minus.png",      "22x22/actions/list-remove.png");
		deprecatedIcons.put("Find.png",       "22x22/actions/edit-find.png");
		deprecatedIcons.put("FindAgain.png",  "22x22/actions/edit-find-next.png");
		deprecatedIcons.put("FindInDir.png",  "22x22/actions/edit-find-in-folder.png");
		deprecatedIcons.put("Parse.png",      "22x22/actions/document-reload2.png");
		deprecatedIcons.put("Delete.png",     "22x22/actions/edit-delete.png");
		deprecatedIcons.put("Paste.png",      "22x22/actions/edit-paste.png");
		deprecatedIcons.put("Cut.png",        "22x22/actions/edit-cut.png");
		deprecatedIcons.put("Copy.png",       "22x22/actions/edit-copy.png");
		deprecatedIcons.put("Undo.png",       "22x22/actions/edit-undo.png");
		deprecatedIcons.put("Redo.png",       "22x22/actions/edit-redo.png");
		deprecatedIcons.put("CurrentDir.png", "22x22/status/folder-visiting.png");
		deprecatedIcons.put("ParentDir.png",  "22x22/actions/go-parent.png");
		deprecatedIcons.put("PageSetup.png",  "22x22/actions/printer-setup.png");
		deprecatedIcons.put("Plugins.png",    "22x22/apps/system-installer.png");
		deprecatedIcons.put("Floppy.png",     "22x22/devices/media-floppy.png");
		deprecatedIcons.put("Stop.png",       "22x22/actions/process-stop.png");
		deprecatedIcons.put("Cancel.png",     "22x22/actions/process-stop.png");
		deprecatedIcons.put("Home.png",       "22x22/actions/go-home.png");
		deprecatedIcons.put("Help.png",       "22x22/apps/help-browser.png");
		deprecatedIcons.put("Properties.png", "22x22/actions/document-properties.png");
		deprecatedIcons.put("Preferences.png","22x22/categories/preferences-system.png");
		deprecatedIcons.put("ZoomIn.png",     "22x22/actions/zoom-in.png");
		deprecatedIcons.put("ZoomOut.png",    "22x22/actions/zoom-out.png");
		deprecatedIcons.put("BrokenImage.png","22x22/status/image-missing.png");
		deprecatedIcons.put("AdjustWidth.png","22x22/actions/resize-horisontal.png");
		deprecatedIcons.put("ToolbarMenu.gif","ToolbarMenu.gif");

		deprecatedIcons.put("Play.png","22x22/actions/media-playback-start.png");
		deprecatedIcons.put("Pause.png","22x22/actions/media-playback-pause.png");

		deprecatedIcons.put("MultipleResults.png", "22x22/actions/edit-find-multiple.png");
		deprecatedIcons.put("SingleResult.png",    "22x22/actions/edit-find-single.png");

		deprecatedIcons.put("NextFile.png",    "22x22/go-last.png");
		deprecatedIcons.put("PreviousFile.png","22x22/go-first.png");

		deprecatedIcons.put("closebox.gif",   "10x10/actions/close.png");
		deprecatedIcons.put("normal.gif",   "10x10/status/document-unmodified.png");
		deprecatedIcons.put("readonly.gif",   "10x10/emblem/emblem-readonly.png");
		deprecatedIcons.put("dirty.gif",    "10x10/status/document-modified.png");
		deprecatedIcons.put("new.gif",    "10x10/status/document-new.png");

		deprecatedIcons.put("ArrowU.png", "22x22/actions/go-up.png");
		deprecatedIcons.put("ArrowR.png", "22x22/actions/go-next.png");
		deprecatedIcons.put("ArrowD.png", "22x22/actions/go-down.png");
		deprecatedIcons.put("ArrowL.png", "22x22/actions/go-previous.png");
		deprecatedIcons.put("arrow1.png", "16x16/actions/group-expand.png");
		deprecatedIcons.put("arrow2.png", "16x16/actions/group-collapse.png");

		deprecatedIcons.put("NewView.png", "22x22/actions/window-new.png");
		deprecatedIcons.put("UnSplit.png", "22x22/actions/window-unsplit.png");
		deprecatedIcons.put("SplitVertical.png", "22x22/actions/window-split-vertical.png");
		deprecatedIcons.put("SplitHorizontal.png", "22x22/actions/window-split-horizontal.png");

		deprecatedIcons.put("ButtonProperties.png", "22x22/actions/document-properties.png");

	}
	//}}}

	//{{{ init() method
	static void init()
	{
		initializeDeprecatedIcons();

		// Load the icon theme but fallback on the old icons
		String theme = jEdit.getProperty("icon-theme", "tango");
		Log.log(Log.DEBUG, GUIUtilities.class, "Icon theme set to: "+theme);
		setIconPath("jeditresource:/org/gjt/sp/jedit/icons/themes/" + theme + '/');
		Log.log(Log.DEBUG, GUIUtilities.class, "Loading icon theme from: "+iconPath);

		// don't do this in static{} since we need jEdit.initMisc()
		// run first so we have the jeditresource: protocol
		NEW_BUFFER_ICON = loadIcon("new.gif");
		DIRTY_BUFFER_ICON = loadIcon("dirty.gif");
		READ_ONLY_BUFFER_ICON = loadIcon("readonly.gif");
		NORMAL_BUFFER_ICON = loadIcon("normal.gif");
		WINDOW_ICON = loadIcon(jEdit.getProperty("logo.icon.medium"));
	} //}}}

	//{{{ showSplashScreen() method
	static void showSplashScreen()
	{
		splash = new SplashScreen();
	} //}}}

	//{{{ advanceSplashProgress() method
	static void advanceSplashProgress()
	{
		if(splash != null)
			splash.advance();
	} //}}}

	//{{{ advanceSplashProgress() method
	static void advanceSplashProgress(String label)
	{
		if(splash != null)
			splash.advance(label);
	} //}}}

	//}}}

	//{{{ Private members
	private static SplashScreen splash;
	private static Map<String, Icon> icons;
	private static String iconPath = "jeditresource:/org/gjt/sp/jedit/icons/themes/";
	private static final String defaultIconPath = "jeditresource:/org/gjt/sp/jedit/icons/themes/";
	private static final HashMap<String, String> deprecatedIcons = new HashMap<String, String>();

	//{{{ _loadMenuItem() method
	private static JMenuItem _loadMenuItem(String name, ActionContext context, boolean setMnemonic)
	{

		String label = jEdit.getProperty(name + ".label");
		if (label == null)
		{
			label = name;
		}
		char mnemonic;
		int index = label.indexOf('$');
		if (index != -1 && label.length() - index > 1)
		{
			mnemonic = Character.toLowerCase(label.charAt(index + 1));
			label = label.substring(0, index).concat(label.substring(++index));
		}
		else
		{
			mnemonic = '\0';
		}
		JMenuItem mi;
		if (jEdit.getBooleanProperty(name + ".toggle"))
		{
			mi = new EnhancedCheckBoxMenuItem(label, name, context);
		}
		else
		{
			mi = new EnhancedMenuItem(label, name, context);
		}
		if (!OperatingSystem.isMacOS() && setMnemonic && mnemonic != '\0')
		{
			mi.setMnemonic(mnemonic);
		}
		Icon itemIcon = loadIcon(jEdit.getProperty(name + ".icon.small"));
		if(itemIcon != null)
		{
			mi.setIcon(itemIcon);
		}

		return mi;
	} //}}}

	private GUIUtilities() {}
	//}}}

	//{{{ Inner classes

	//{{{ SizeSaver class
	/**
	 * A combined ComponentListener and WindowStateListener to continually save a Frames size.

	 * For non-Frame's use {@link GUIUtilities#saveGeometry(Window,String)}
	 *
	 * @author Björn Kautler
	 * @version $Id: GUIUtilities.java 16406 2009-10-22 20:42:36Z shlomy $
	 * @since jEdit 4.3pre6
	 * @see GUIUtilities#saveGeometry(Window,Container,String)
	 */
	private static class SizeSaver extends ComponentAdapter implements WindowStateListener
	{
		private Frame frame;
		private Container parent;
		private String name;

		//{{{ SizeSaver constructors
		/**
		 * Constructs a new SizeSaver.
		 *
		 * @param frame The Frame for which to save the size
		 * @param parent The parent to be relative to.
		 * @param name The prefix for the settings
		 */
		SizeSaver(Frame frame, Container parent, String name)
		{
			if (frame == null || name == null)
			{
				throw new NullPointerException();
			}
			this.frame = frame;
			this.parent = parent;
			this.name = name;
		} //}}}

		//{{{ windowStateChanged() method
		public void windowStateChanged(WindowEvent wse)
		{
			int extendedState = wse.getNewState();
			jEdit.setIntegerProperty(name + ".extendedState",extendedState);
			Rectangle bounds = frame.getBounds();
			save(extendedState, bounds);
		} //}}}

		//{{{ save() method
		private void save(int extendedState, Rectangle bounds)
		{
			switch (extendedState)
			{
				case Frame.MAXIMIZED_VERT:
					jEdit.setIntegerProperty(name + ".x",bounds.x);
					jEdit.setIntegerProperty(name + ".width",bounds.width);
					break;

				case Frame.MAXIMIZED_HORIZ:
					jEdit.setIntegerProperty(name + ".y",bounds.y);
					jEdit.setIntegerProperty(name + ".height",bounds.height);
					break;

				case Frame.NORMAL:
					saveGeometry(frame,parent,name );
					break;
			}
		} //}}}

		//{{{ componentResized() method
		@Override
		public void componentResized(ComponentEvent ce)
		{
			componentMoved(ce);
		} //}}}

		//{{{ componentMoved() method
		@Override
		public void componentMoved(ComponentEvent ce)
		{
			final Rectangle bounds = frame.getBounds();
			final Runnable sizeSaver = new Runnable()
			{
				public void run()
				{
					int extendedState = frame.getExtendedState();
					save(extendedState, bounds);
				}
			};
			new Thread("Sizesavingdelay")
			{
				@Override
				public void run()
				{
					try
					{
						Thread.sleep(500L);
					}
					catch (InterruptedException ie)
					{
					}
					SwingUtilities.invokeLater(sizeSaver);
				}
			}.start();

	public static Image getPluginIcon()
	{
		return getEditorIcon();

	public static JMenuBar loadMenuBar(String name)
	{
		return loadMenuBar(jEdit.getActionContext(),name);

FUNC_DECL RETURN LOOP VAR_DECL VAR_DECL VAR_DECL PARAM PARAM CALL VAR_DECL CALL CALL CALL CALL CALL CALL

	public static JMenu loadMenu(String name)
	{
		return loadMenu(jEdit.getActionContext(),name);

FUNC_DECL RETURN PARAM PARAM CALL CALL CALL LITERAL_ANCHOR

FUNC_DECL RETURN PARAM PARAM PARAM CALL CALL

FUNC_DECL RETURN IF IF VAR_DECL VAR_DECL PARAM PARAM PARAM PARAM BINARY_OP BINARY_OP LOOP IF VAR_DECL LITERAL_ANCHOR LOOP VAR_DECL LITERAL_ANCHOR CALL CALL CALL CALL CALL IF VAR_DECL CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR

FUNC_DECL RETURN PARAM CALL LITERAL_ANCHOR CALL

FUNC_DECL RETURN IF PARAM PARAM PARAM CALL RETURN BINARY_OP CALL LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR

FUNC_DECL RETURN VAR_DECL VAR_DECL PARAM PARAM CALL CALL CALL

	public static Container loadToolBar(String name)
	{
		return loadToolBar(jEdit.getActionContext(),name);

FUNC_DECL PARAM PARAM PARAM CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR

	public static String input(Component comp, String name, Object def)
	{
		return input(comp,name,null,def);

FUNC_DECL RETURN PARAM PARAM PARAM CALL LITERAL_ANCHOR

FUNC_DECL RETURN PARAM PARAM PARAM PARAM PARAM CALL CALL CALL CALL BINARY_OP BINARY_OP LITERAL_ANCHOR LITERAL_ANCHOR

FUNC_DECL RETURN VAR_DECL IF PARAM PARAM PARAM PARAM CALL CALL BINARY_OP CALL LITERAL_ANCHOR ASSIGN CALL CALL LITERAL_ANCHOR

FUNC_DECL RETURN VAR_DECL PARAM PARAM PARAM PARAM PARAM CALL CALL CALL LITERAL_ANCHOR

	public static Color parseColor(String name)
	{
		return SyntaxUtilities.parseColor(name, Color.black);

FUNC_DECL RETURN PARAM PARAM PARAM PARAM CALL

FUNC_DECL RETURN IF VAR_DECL IF IF VAR_DECL PARAM CALL CALL BINARY_OP BINARY_OP IF IF CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL CALL CALL

FUNC_DECL RETURN PARAM PARAM CALL LITERAL_ANCHOR

	public static void loadGeometry(Window win, String name)
	{
		loadGeometry(win, win.getParent(), name);

	public static void saveGeometry(Window win, String name)
	{
		saveGeometry (win, win.getParent(), name);

	public static void hideSplashScreen()
	{
		if(splash != null)
		{
			splash.dispose();
			splash = null;

FUNC_DECL PARAM PARAM CALL CALL FUNC_DECL PARAM CALL CALL CALL FUNC_DECL CALL

	public static boolean isRightButton(int modifiers)
	{
		return TextAreaMouseHandler.isRightButton(modifiers);

FUNC_DECL RETURN IF VAR_DECL VAR_DECL BINARY_OP LOOP LITERAL_ANCHOR CALL CALL CALL CALL LOOP ASSIGN CALL CALL CALL

FUNC_DECL PARAM PARAM PARAM PARAM CALL LITERAL_ANCHOR

FUNC_DECL LOOP PARAM PARAM CALL IF CALL BINARY_OP CALL CALL

	public static View getView(Component comp)
	{
		return (View)getComponentParent(comp,View.class);

	public static void addSizeSaver(Frame frame, String name)
	{
		addSizeSaver(frame,frame.getParent(),name);

FUNC_DECL VAR_DECL PARAM PARAM PARAM CALL CALL CALL

	static void showSplashScreen()
	{
		splash = new SplashScreen();

	static void advanceSplashProgress()
	{
		if(splash != null)
			splash.advance();

	static void advanceSplashProgress(String label)
	{
		if(splash != null)
			splash.advance(label);


org.gjt.sp.jedit.menu.DirectoryProvider

public class DirectoryProvider implements DynamicMenuProvider
{
	//{{{ DirectoryProvider constructor
	public DirectoryProvider(String dir)
	{
		this.dir = dir;
	} //}}}

	//{{{ updateEveryTime() method
	public boolean updateEveryTime()
	{
		return true;
	} //}}}

	//{{{ update() method
	public void update(JMenu menu)
	{
		final View view = GUIUtilities.getView(menu);

		String path;
		if(dir == null)
		{
			path = view.getBuffer().getDirectory();
		}
		else
			path = dir;

		JMenuItem mi = new JMenuItem(path + ':');
		mi.setActionCommand(path);
		mi.setIcon(FileCellRenderer.openDirIcon);

		//{{{ ActionListeners
		ActionListener fileListener = new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				jEdit.openFile(view,evt.getActionCommand());
			}
		};

		ActionListener dirListener = new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				VFSBrowser.browseDirectory(view,
					evt.getActionCommand());
			}
		}; //}}}

		mi.addActionListener(dirListener);

		menu.add(mi);
		menu.addSeparator();

		if(dir == null && !(view.getBuffer().getVFS() instanceof FileVFS))
		{
			mi = new JMenuItem(jEdit.getProperty(
				"directory.not-local"));
			mi.setEnabled(false);
			menu.add(mi);
			return;
		}

		File directory = new File(path);

		JMenu current = menu;

		// for filtering out backups
		String backupPrefix = jEdit.getProperty("backup.prefix");
		String backupSuffix = jEdit.getProperty("backup.suffix");

		File[] list = directory.listFiles();
		if(list == null || list.length == 0)
		{
			mi = new JMenuItem(jEdit.getProperty(
				"directory.no-files"));
			mi.setEnabled(false);
			menu.add(mi);
		}
		else
		{
			int maxItems = jEdit.getIntegerProperty("menu.spillover",20);

			Arrays.sort(list,
				new StandardUtilities.StringCompare<File>(true));
			for(int i = 0; i < list.length; i++)
			{
				File file = list[i];

				String name = file.getName();

				// skip marker files
				if(name.endsWith(".marks"))
					continue;

				// skip autosave files
				if(name.startsWith("#") && name.endsWith("#"))
					continue;

				// skip backup files
				if((backupPrefix.length() != 0
					&& name.startsWith(backupPrefix))
					|| (backupSuffix.length() != 0
					&& name.endsWith(backupSuffix)))
					continue;

				// skip directories
				//if(file.isDirectory())
				//	continue;

				mi = new JMenuItem(name);
				mi.setActionCommand(file.getPath());
				mi.addActionListener(file.isDirectory()
					? dirListener
					: fileListener);
				mi.setIcon(file.isDirectory()
					? FileCellRenderer.dirIcon
					: FileCellRenderer.fileIcon);

				if(current.getItemCount() >= maxItems && i != list.length - 1)
				{
					//current.addSeparator();
					JMenu newCurrent = new JMenu(
						jEdit.getProperty(
						"common.more"));
					current.add(newCurrent);
					current = newCurrent;
				}
				current.add(mi);
			}
		}
	} //}}}

	//{{{ Private members
	private final String dir;


public class ElemExtensionCall extends ElemLiteralResult
{

  /** The Namespace URI for this extension call element.
   *  @serial          */
  String m_extns;

  /** Language used by extension.
   *  @serial          */
  String m_lang;

  /** URL pointing to extension.
   *  @serial          */
  String m_srcURL;

  /** Source for script.
   *  @serial          */
  String m_scriptSrc;

  /** Declaration for Extension element.
   *  @serial          */
  ElemExtensionDecl m_decl = null;

  /**
   * Get an int constant identifying the type of element.
   * @see org.apache.xalan.templates.Constants
   *
   *@return The token ID for this element
   */
  public int getXSLToken()
  {
    return Constants.ELEMNAME_EXTENSIONCALL;
  }

  /**
   * Return the node name.
   *
   * @return The element's name
   */

  /**
   * This function is called after everything else has been
   * recomposed, and allows the template to set remaining
   * values that may be based on some other property that
   * depends on recomposition.
   */
  public void compose(StylesheetRoot sroot) throws TransformerException
  {
    super.compose(sroot);
    m_extns = this.getNamespace();
    m_decl = getElemExtensionDecl(sroot, m_extns);
    if (m_decl == null)
      sroot.getExtensionNamespacesManager().registerExtension(m_extns);
  }

  /**
   * Return the ElemExtensionDecl for this extension element
   *
   *
   * @param stylesheet Stylesheet root associated with this extension element
   * @param namespace Namespace associated with this extension element
   *
   * @return the ElemExtensionDecl for this extension element.
   */
  private ElemExtensionDecl getElemExtensionDecl(StylesheetRoot stylesheet,
          String namespace)
  {

    ElemExtensionDecl decl = null;
    int n = stylesheet.getGlobalImportCount();

    for (int i = 0; i < n; i++)
    {
      Stylesheet imported = stylesheet.getGlobalImport(i);

      for (ElemTemplateElement child = imported.getFirstChildElem();
              child != null; child = child.getNextSiblingElem())
      {
        if (Constants.ELEMNAME_EXTENSIONDECL == child.getXSLToken())
        {
          decl = (ElemExtensionDecl) child;

          String prefix = decl.getPrefix();
          String declNamespace = child.getNamespaceForPrefix(prefix);

          if (namespace.equals(declNamespace))
          {
            return decl;
          }
        }
      }
    }

    return decl;
  }

  /**
   * Execute the fallbacks when an extension is not available.
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
  public void executeFallbacks(
          TransformerImpl transformer)
            throws TransformerException
  {
    for (ElemTemplateElement child = m_firstChild; child != null;
             child = child.m_nextSibling)
    {
      if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK)
      {
        try
        {
          transformer.pushElemTemplateElement(child);
          ((ElemFallback) child).executeFallback(transformer);
        }
        finally
        {
          transformer.popElemTemplateElement();
        }
      }
    }

  }

  /**
   * Execute an extension.
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
  public void execute(
          TransformerImpl transformer)
            throws TransformerException
  {

    try
    {
      transformer.getResultTreeHandler().flushPending();

      ExtensionsTable etable = transformer.getExtensionsTable();
      ExtensionHandler nsh = etable.get(m_extns);

      if (null == nsh)
      {
        executeFallbacks(transformer);
        return;
      }

      try
      {
        nsh.processElement(this.getLocalName(), this, transformer,
                           getStylesheet(), this);
      }
      catch (Exception e)
      {

        String msg = e.getMessage();

        TransformerException te;
        if(e instanceof TransformerException)
        {
          te = (TransformerException)e;
        }
        else
        {
          if(null != msg)
            te = new TransformerException(e);

        }
        if(null == te.getLocator())
          te.setLocator(this);

        if (null != msg)
        {
          if (msg.indexOf("fatal") >= 0)
          {
            transformer.getErrorListener().fatalError(te);
          }
          else if(e instanceof RuntimeException){}
          else{
            transformer.getErrorListener().warning(te);
		  }
        }

        executeFallbacks(
          transformer);
      }
    }
    catch(org.xml.sax.SAXException se)
    {
      transformer.getErrorListener().fatalError(new TransformerException(se));
    }
  }

  /**
   * Return the raw value of the attribute.
   *
   * @param rawName Raw name of the attribute to get
   *
   * @return the raw value of the attribute or null if not found
   */
  public String getAttribute(String rawName)
  {

    AVT avt = getLiteralResultAttribute(rawName);

    if ((null != avt) && avt.getRawName().equals(rawName))
    {
      return avt.getSimpleString();
    }

    return null;
  }

  /**
   * Return the value of the attribute interpreted as an Attribute
   * Value Template (in other words, you can use curly expressions
   *
   * @param rawName Raw name of the attribute to get
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @return the value of the attribute
   *
   * @throws TransformerException
   */
  public String getAttribute(
          String rawName, org.w3c.dom.Node sourceNode, TransformerImpl transformer)
            throws TransformerException
  {

    AVT avt = getLiteralResultAttribute(rawName);

    if ((null != avt) && avt.getRawName().equals(rawName))
    {
      XPathContext xctxt = transformer.getXPathContext();

      return avt.evaluate(xctxt,
            xctxt.getDTMHandleFromNode(sourceNode),
            this);
    }

    return null;
  }

  /**
   * Accept a visitor and call the appropriate method
   * for this class.
   *
   * @param visitor The visitor whose appropriate method will be called.
   * @return true if the children of the object should be visited.
   */
  protected boolean accept(XSLTVisitor visitor)
  {
  	return visitor.visitExtensionElement(this);

FUNC_DECL IF PARAM BINARY_OP ASSIGN ASSIGN CALL LITERAL_ANCHOR CALL CALL CALL

FUNC_DECL LOOP PARAM ASSIGN BINARY_OP IF LITERAL_ANCHOR BINARY_OP TRY CALL CALL CALL

FUNC_DECL TRY PARAM CATCH TRY IF VAR_DECL VAR_DECL CATCH BINARY_OP CALL CALL IF IF IF VAR_DECL VAR_DECL CALL RETURN LITERAL_ANCHOR CALL CALL CALL CALL CALL BINARY_OP BINARY_OP BINARY_OP CALL CALL CALL IF LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR IF CALL CALL IF BINARY_OP BINARY_OP ASSIGN BINARY_OP LITERAL_ANCHOR CALL ASSIGN LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL CALL CALL


public class UnrecognizedExtraField implements ZipExtraField {

    /**
     * The Header-ID.
     *
     * @since 1.1
     */
    private ZipShort headerId;

    public void setHeaderId(ZipShort headerId) {
        this.headerId = headerId;
    }

    public ZipShort getHeaderId() {
        return headerId;
    }

    /**
     * Extra field data in local file data - without
     * Header-ID or length specifier.
     *
     * @since 1.1
     */
    private byte[] localData;

    public void setLocalFileDataData(byte[] data) {
        localData = data;
    }

    public ZipShort getLocalFileDataLength() {
        return new ZipShort(localData.length);
    }

    public byte[] getLocalFileDataData() {
        return localData;
    }

    /**
     * Extra field data in central directory - without
     * Header-ID or length specifier.
     *
     * @since 1.1
     */
    private byte[] centralData;

    public void setCentralDirectoryData(byte[] data) {
        centralData = data;
    }

    public ZipShort getCentralDirectoryLength() {
        if (centralData != null) {
            return new ZipShort(centralData.length);
        }
        return getLocalFileDataLength();
    }

    public byte[] getCentralDirectoryData() {
        if (centralData != null) {
            return centralData;
        }
        return getLocalFileDataData();
    }

    public void parseFromLocalFileData(byte[] data, int offset, int length) {
        byte[] tmp = new byte[length];
        System.arraycopy(data, offset, tmp, 0, length);
        setLocalFileDataData(tmp);


public abstract class BinaryPredicateSupport<E extends Exchange> implements Predicate<E> {

    private final Expression<E> left;
    private final Expression<E> right;

    protected BinaryPredicateSupport(Expression<E> left, Expression<E> right) {
        notNull(left, "left");
        notNull(right, "right");

        this.left = left;
        this.right = right;
    }

    @Override
    public String toString() {
        return left + " " + getOperationText() + " " + right;
    }

    public boolean matches(E exchange) {
        Object leftValue = left.evaluate(exchange);
        Object rightValue = right.evaluate(exchange);
        return matches(exchange, leftValue, rightValue);
    }

    public void assertMatches(String text, E exchange) {
        Object leftValue = left.evaluate(exchange);
        Object rightValue = right.evaluate(exchange);
        if (!matches(exchange, leftValue, rightValue)) {
            throw new AssertionError(text + assertionFailureMessage(exchange, leftValue, rightValue));
        }
    }

    protected abstract boolean matches(E exchange, Object leftValue, Object rightValue);

    protected abstract String getOperationText();

    protected String assertionFailureMessage(E exchange, Object leftValue, Object rightValue) {
        return this + " failed on " + exchange + " with left value <" + leftValue + "> right value <"
               + rightValue + ">";

FUNC_DECL PARAM PARAM ASSIGN ASSIGN CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR


public class MRIDTransformationRule implements NamespaceTransformer {
    private static class MridRuleMatcher {
        private static final String[] TYPES = new String[] {"o", "m", "b", "r"};

        private Matcher[] matchers = new Matcher[TYPES.length];

        public boolean match(MRIDRule src, ModuleRevisionId mrid) {
            //CheckStyle:MagicNumber| OFF
            matchers[0] = Pattern.compile(getPattern(src.getOrg()))
                    .matcher(mrid.getOrganisation());
            if (!matchers[0].matches()) {
                return false;
            }
            matchers[1] = Pattern.compile(getPattern(src.getModule())).matcher(mrid.getName());
            if (!matchers[1].matches()) {
                return false;
            }
            if (mrid.getBranch() == null) {
                matchers[2] = null;
            } else {
                matchers[2] = Pattern.compile(getPattern(src.getBranch())).matcher(
                    mrid.getBranch());
                if (!matchers[2].matches()) {
                    return false;
                }
            }
            matchers[3] = Pattern.compile(getPattern(src.getRev())).matcher(mrid.getRevision());
            if (!matchers[3].matches()) {
                return false;
            }

            return true;
            //CheckStyle:MagicNumber| ON
        }

        public ModuleRevisionId apply(MRIDRule dest, ModuleRevisionId mrid) {
            String org = applyRules(dest.getOrg(), "o");
            String mod = applyRules(dest.getModule(), "m");
            String branch = applyRules(dest.getBranch(), "b");
            String rev = applyRules(dest.getRev(), "r");

            return ModuleRevisionId.newInstance(org, mod, branch, rev,
                                                mrid.getQualifiedExtraAttributes());
        }

        private String applyRules(String str, String type) {
            for (int i = 0; i < TYPES.length; i++) {
                str = applyTypeRule(str, TYPES[i], type, matchers[i]);
            }
            return str;
        }

        private String applyTypeRule(String rule, String type, String ruleType, Matcher m) {
            if (m == null) {
                return rule;
            }
            String res = rule == null ? "$" + ruleType + "0" : rule;
            for (int i = 0; i < TYPES.length; i++) {
                if (TYPES[i].equals(type)) {
                    res = res.replaceAll("([^\\\\])\\$" + type, "$1\\$");
                    res = res.replaceAll("^\\$" + type, "\\$");
                } else {
                    res = res.replaceAll("([^\\\\])\\$" + TYPES[i], "$1\\\\\\$" + TYPES[i]);
                    res = res.replaceAll("^\\$" + TYPES[i], "\\\\\\$" + TYPES[i]);
                }
            }

            StringBuffer sb = new StringBuffer();
            m.reset();
            m.find();
            m.appendReplacement(sb, res);

            String str = sb.toString();
            // null rule not replaced, let it be null
            if (rule == null && ("$" + ruleType + "0").equals(str)) {
                return null;
            }

            return str;
        }

        private String getPattern(String p) {
            return p == null ? ".*" : p;
        }
    }

    private List src = new ArrayList();

    private MRIDRule dest;

    public void addSrc(MRIDRule src) {
        this.src.add(src);
    }

    public void addDest(MRIDRule dest) {
        if (this.dest != null) {
            throw new IllegalArgumentException("only one dest is allowed per mapping");
        }
        this.dest = dest;
    }

    public ModuleRevisionId transform(ModuleRevisionId mrid) {
        MridRuleMatcher matcher = new MridRuleMatcher();
        for (Iterator iter = src.iterator(); iter.hasNext();) {
            MRIDRule rule = (MRIDRule) iter.next();
            if (matcher.match(rule, mrid)) {
                ModuleRevisionId destMrid = matcher.apply(dest, mrid);
                Message.debug("found matching namespace rule: " + rule + ". Applied " + dest
                        + " on " + mrid + ". Transformed to " + destMrid);
                return destMrid;
            }
        }
        return mrid;
    }

    public boolean isIdentity() {
        return false;


org.apache.xalan.xsltc.compiler.TestSeq

final class TestSeq {

    /**
     * Integer code for the kernel type of this test sequence
     */
    private int _kernelType;

    /**
     * Vector of all patterns in the test sequence. May include
     * patterns with "*", "@*" or "node()" kernel.
     */
    private Vector _patterns = null;

    /**
     * A reference to the Mode object.
     */
    private Mode _mode = null;

    /**
     * Default template for this test sequence
     */
    private Template _default = null;

    /**
     * Instruction list representing this test sequence.
     */
    private InstructionList _instructionList;

    /**
     * Cached handle to avoid compiling more than once.
     */
    private InstructionHandle _start = null;

    /**
     * Creates a new test sequence given a set of patterns and a mode.
     */
    public TestSeq(Vector patterns, Mode mode) {
	this(patterns, -2, mode);
    }

    public TestSeq(Vector patterns, int kernelType, Mode mode) {
	_patterns = patterns;
	_kernelType = kernelType;
	_mode = mode;
    }

    /**
     * Returns a string representation of this test sequence. Notice
     * that test sequences are mutable, so the value returned by this
     * method is different before and after calling reduce().
     */
    public String toString() {
	final int count = _patterns.size();
	final StringBuffer result = new StringBuffer();

	for (int i = 0; i < count; i++) {
	    final LocationPathPattern pattern =
		(LocationPathPattern) _patterns.elementAt(i);

	    if (i == 0) {
		result.append("Testseq for kernel " + _kernelType)
		      .append('\n');
	    }
	    result.append("   pattern " + i + ": ")
	          .append(pattern.toString())
		  .append('\n');
	}
	return result.toString();
    }

    /**
     * Returns the instruction list for this test sequence
     */
    public InstructionList getInstructionList() {
	return _instructionList;
    }

    /**
     * Return the highest priority for a pattern in this test
     * sequence. This is either the priority of the first or
     * of the default pattern.
     */
    public double getPriority() {
	final Template template = (_patterns.size() == 0) ? _default
	    : ((Pattern) _patterns.elementAt(0)).getTemplate();
	return template.getPriority();
    }

    /**
     * Returns the position of the highest priority pattern in
     * this test sequence.
     */
    public int getPosition() {
	final Template template = (_patterns.size() == 0) ? _default
	    : ((Pattern) _patterns.elementAt(0)).getTemplate();
	return template.getPosition();
    }

    /**
     * Reduce the patterns in this test sequence. Creates a new
     * vector of patterns and sets the default pattern if it
     * finds a patterns that is fully reduced.
     */
    public void reduce() {
	final Vector newPatterns = new Vector();

	final int count = _patterns.size();
	for (int i = 0; i < count; i++) {
	    final LocationPathPattern pattern =
		(LocationPathPattern)_patterns.elementAt(i);

	    pattern.reduceKernelPattern();

	    if (pattern.isWildcard()) {
		_default = pattern.getTemplate();
	    }
	    else {
		newPatterns.addElement(pattern);
	    }
	}
	_patterns = newPatterns;
    }

    /**
     * Returns, by reference, the templates that are included in
     * this test sequence. Note that a single template can occur
     * in several test sequences if its pattern is a union.
     */
    public void findTemplates(Dictionary templates) {
	if (_default != null) {
	    templates.put(_default, this);
	}
	for (int i = 0; i < _patterns.size(); i++) {
	    final LocationPathPattern pattern =
		(LocationPathPattern)_patterns.elementAt(i);
	    templates.put(pattern.getTemplate(), this);
	}
    }

    /**
     * Get the instruction handle to a template's code. This is
     * used when a single template occurs in several test
     * sequences; that is, if its pattern is a union of patterns
     * (e.g. match="A/B | A/C").
     */
    private InstructionHandle getTemplateHandle(Template template) {
	return (InstructionHandle)_mode.getTemplateInstructionHandle(template);
    }

    /**
     * Returns pattern n in this test sequence
     */
    private LocationPathPattern getPattern(int n) {
	return (LocationPathPattern)_patterns.elementAt(n);
    }

    /**
     * Compile the code for this test sequence. Compile patterns
     * from highest to lowest priority. Note that since patterns
     * can be share by multiple test sequences, instruction lists
     * must be copied before backpatching.
     */
    public InstructionHandle compile(ClassGenerator classGen,
				     MethodGenerator methodGen,
				     InstructionHandle continuation)
    {
	if (_start != null) {
	    return _start;
	}

	final int count = _patterns.size();
	if (count == 0) {
	    return (_start = getTemplateHandle(_default));
	}

	InstructionHandle fail = (_default == null) ? continuation
	    : getTemplateHandle(_default);

	for (int n = count - 1; n >= 0; n--) {
	    final LocationPathPattern pattern = getPattern(n);
	    final Template template = pattern.getTemplate();
	    final InstructionList il = new InstructionList();

	    il.append(methodGen.loadCurrentNode());

	    InstructionList ilist = _mode.getInstructionList(pattern);
	    if (ilist == null) {
		ilist = pattern.compile(classGen, methodGen);
		_mode.addInstructionList(pattern, ilist);
	    }

	    InstructionList copyOfilist = ilist.copy();

	    FlowList trueList = pattern.getTrueList();
	    if (trueList != null) {
		trueList = trueList.copyAndRedirect(ilist, copyOfilist);
	    }
	    FlowList falseList = pattern.getFalseList();
	    if (falseList != null) {
		falseList = falseList.copyAndRedirect(ilist, copyOfilist);
	    }

	    il.append(copyOfilist);

	    final InstructionHandle gtmpl = getTemplateHandle(template);
	    final InstructionHandle success = il.append(new GOTO_W(gtmpl));

	    if (trueList != null) {
		trueList.backPatch(success);
	    }
	    if (falseList != null) {
		falseList.backPatch(fail);
	    }

	    fail = il.getStart();

	    if (_instructionList != null) {
		il.append(_instructionList);
	    }

	    _instructionList = il;
	}
	return (_start = fail);

FUNC_DECL PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN


org.apache.xalan.trace.TracerEvent

public class TracerEvent implements java.util.EventListener
{

  /**
   * The node in the style tree where the event occurs.
   */
  public final ElemTemplateElement m_styleNode;

  /**
   * The XSLT processor instance.
   */
  public final TransformerImpl m_processor;

  /**
   * The current context node.
   */
  public final Node m_sourceNode;

  /**
   * The current mode.
   */
  public final QName m_mode;

  /**
   * Create an event originating at the given node of the style tree.
   * @param processor The XSLT TransformerFactory.
   * @param sourceNode The current context node.
   * @param mode The current mode.
   * @param m_styleNode node in the style tree reference for the event.
   * Should not be null.  That is not enforced.
   * @param styleNode The stylesheet element that is executing.
   */
  public TracerEvent(TransformerImpl processor, Node sourceNode, QName mode,
                     ElemTemplateElement styleNode)
  {

    this.m_processor = processor;
    this.m_sourceNode = sourceNode;
    this.m_mode = mode;
    this.m_styleNode = styleNode;
  }

  /**
   * Returns a string representation of the node.
   * The string returned for elements will contain the element name
   * and any attributes enclosed in angle brackets.
   * The string returned for attributes will be of form, "name=value."
   *
   * @param n any DOM node. Must not be null.
   *
   * @return a string representation of the given node.
   */
  public static String printNode(Node n)
  {

    String r = n.hashCode() + " ";

    if (n instanceof Element)
    {
      r += "<" + n.getNodeName();

      Node c = n.getFirstChild();

      while (null != c)
      {
        if (c instanceof Attr)
        {
          r += printNode(c) + " ";
        }

        c = c.getNextSibling();
      }

      r += ">";
    }
    else
    {
      if (n instanceof Attr)
      {
        r += n.getNodeName() + "=" + n.getNodeValue();
      }
      else
      {
        r += n.getNodeName();
      }
    }

    return r;
  }

  /**
   * Returns a string representation of the node list.
   * The string will contain the list of nodes inside square braces.
   * Elements will contain the element name
   * and any attributes enclosed in angle brackets.
   * Attributes will be of form, "name=value."
   *
   * @param l any DOM node list. Must not be null.
   *
   * @return a string representation of the given node list.
   */
  public static String printNodeList(NodeList l)
  {

    String r = l.hashCode() + "[";
    int len = l.getLength() - 1;
    int i = 0;

    while (i < len)
    {
      Node n = l.item(i);

      if (null != n)
      {
        r += printNode(n) + ", ";
      }

      ++i;
    }

    if (i == len)
    {
      Node n = l.item(len);

      if (null != n)
      {
        r += printNode(n);
      }
    }

    return r + "]";

FUNC_DECL PARAM PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN ASSIGN


org.apache.xpath.objects.XNull

public class XNull extends XNodeSet
{

  /**
   * Create an XObject.
   */
  public XNull()
  {
    super();
  }

  /**
   * Tell what kind of class this is.
   *
   * @return type CLASS_NULL
   */
  public int getType()
  {
    return CLASS_NULL;
  }

  /**
   * Given a request type, return the equivalent string.
   * For diagnostic purposes.
   *
   * @return type string "#CLASS_NULL"
   */
  public String getTypeString()
  {
    return "#CLASS_NULL";
  }

  /**
   * Cast result object to a number.
   *
   * @return 0.0
   */

  public double num()
  {
    return 0.0;
  }

  /**
   * Cast result object to a boolean.
   *
   * @return false
   */
  public boolean bool()
  {
    return false;
  }

  /**
   * Cast result object to a string.
   *
   * @return empty string ""
   */
  public String str()
  {
    return "";
  }

  /**
   * Cast result object to a result tree fragment.
   *
   * @param support XPath context to use for the conversion
   *
   * @return The object as a result tree fragment.
   */
  public int rtf(XPathContext support)
  {
    return DTM.NULL;
  }

  /**
   * Tell if two objects are functionally equal.
   *
   * @param obj2 Object to compare this to
   *
   * @return True if the given object is of type CLASS_NULL
   */
  public boolean equals(XObject obj2)
  {
    return obj2.getType() == CLASS_NULL;

  public double num()
  {
    return 0.0;

  public boolean bool()
  {
    return false;

  public String str()
  {
    return "";


public abstract class AbstractSimpleLanguage implements Language {

    public Predicate<Exchange> createPredicate(String expression) {
        return PredicateBuilder.toPredicate(createExpression(expression));
    }

    public Expression<Exchange> createExpression(String expression) {
        if (expression.indexOf("${") >= 0) {
            return createComplexExpression(expression);
        }
        return createSimpleExpression(expression);
    }

    protected Expression<Exchange> createComplexExpression(String expression) {
        List<Expression> results = new ArrayList<Expression>();

        int pivot = 0;
        int size = expression.length();
        while (pivot < size) {
            int idx = expression.indexOf("${", pivot);
            if (idx < 0) {
                results.add(createConstantExpression(expression, pivot, size));
                break;
            } else {
                if (pivot < idx) {
                    results.add(createConstantExpression(expression, pivot, idx));
                }
                pivot = idx + 2;
                int endIdx = expression.indexOf("}", pivot);
                if (endIdx < 0) {
                    throw new IllegalArgumentException("Expecting } but found end of string for simple expression: " + expression);
                }
                String simpleText = expression.substring(pivot, endIdx);

                Expression simpleExpression = createSimpleExpression(simpleText);
                results.add(simpleExpression);
                pivot = endIdx + 1;
            }
        }
        return ExpressionBuilder.concatExpression(results, expression);
    }

    protected Expression createConstantExpression(String expression, int start, int end) {
        return ExpressionBuilder.constantExpression(expression.substring(start, end));
    }

    /**
     * Creates the simple expression based on the extracted content from the ${ } place holders
     *
     * @param expression  the content between ${ and }
     * @return the expression
     */
    protected abstract <E extends Exchange> Expression<Exchange> createSimpleExpression(String expression);

    protected String ifStartsWithReturnRemainder(String prefix, String text) {
        if (text.startsWith(prefix)) {
            String remainder = text.substring(prefix.length());
            if (remainder.length() > 0) {
                return remainder;
            }
        }
        return null;

FUNC_DECL RETURN PARAM PARAM PARAM CALL CALL

FUNC_DECL RETURN IF PARAM PARAM LITERAL_ANCHOR CALL IF VAR_DECL BINARY_OP RETURN LITERAL_ANCHOR CALL CALL CALL