/*
 * Copyright 1995-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.applet;

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
import javax.print.attribute.*;
import java.applet.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.SocketPermission;
import sun.misc.Ref;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import sun.awt.SunToolkit;
import sun.awt.AppContext;
import java.lang.ref.WeakReference;

/**
 * A frame to show the applet tag in.
 */
class TextFrame extends Frame {

    /**
     * Create the tag frame.
     */
    TextFrame(int x, int y, String title, String text) {
        setTitle(title);
        TextArea txt = new TextArea(20, 60);
        txt.setText(text);
        txt.setEditable(false);

        add("Center", txt);

        Panel p = new Panel();
        add("South", p);
        Button b = new Button(amh.getMessage("button.dismiss", "Dismiss"));
        p.add(b);

        class ActionEventListener implements ActionListener {
            public void actionPerformed(ActionEvent evt) {
                dispose();
            }
        }
        b.addActionListener(new ActionEventListener());

        pack();
        move(x, y);
        setVisible(true);

        WindowListener windowEventListener = new WindowAdapter() {

            public void windowClosing(WindowEvent evt) {
                dispose();
            }
        };

        addWindowListener(windowEventListener);
    }
    private static AppletMessageHandler amh = new AppletMessageHandler("textframe");

}

/**
 * Lets us construct one using unix-style one shot behaviors
 */

class StdAppletViewerFactory implements AppletViewerFactory
{
    public AppletViewer createAppletViewer(int x, int y,
                                           URL doc, Hashtable atts) {
        return new AppletViewer(x, y, doc, atts, System.out, this);
    }

    public MenuBar getBaseMenuBar() {
        return new MenuBar();
    }

    public boolean isStandalone() {
        return true;
    }
}

/**
 * The applet viewer makes it possible to run a Java applet without using a browser.
 * For details on the syntax that <B>appletviewer</B> supports, see
 * <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.
 * (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
 *  once the JDK docs have been installed.)
 */
public class AppletViewer extends Frame implements AppletContext,
                                                   Printable {

    /**
     * Some constants...
     */
    private static String defaultSaveFile = "Applet.ser";

    /**
     * The panel in which the applet is being displayed.
     */
    AppletViewerPanel panel;

    /**
     * The status line.
     */
    Label label;

    /**
     * output status messages to this stream
     */

    PrintStream statusMsgStream;

    /**
     * For cloning
     */
    AppletViewerFactory factory;


    private final class UserActionListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
            processUserAction(evt);
        }
    }

    /**
     * Create the applet viewer
     */
    public AppletViewer(int x, int y, URL doc, Hashtable atts,
                        PrintStream statusMsgStream, AppletViewerFactory factory) {
        this.factory = factory;
        this.statusMsgStream = statusMsgStream;
        setTitle(amh.getMessage("tool.title", atts.get("code")));

        MenuBar mb = factory.getBaseMenuBar();

        Menu m = new Menu(amh.getMessage("menu.applet"));

        addMenuItem(m, "menuitem.restart");
        addMenuItem(m, "menuitem.reload");
        addMenuItem(m, "menuitem.stop");
        addMenuItem(m, "menuitem.save");
        addMenuItem(m, "menuitem.start");
        addMenuItem(m, "menuitem.clone");
        m.add(new MenuItem("-"));
        addMenuItem(m, "menuitem.tag");
        addMenuItem(m, "menuitem.info");
        addMenuItem(m, "menuitem.edit").disable();
        addMenuItem(m, "menuitem.encoding");
        m.add(new MenuItem("-"));
        addMenuItem(m, "menuitem.print");
        m.add(new MenuItem("-"));
        addMenuItem(m, "menuitem.props");
        m.add(new MenuItem("-"));
        addMenuItem(m, "menuitem.close");
        if (factory.isStandalone()) {
            addMenuItem(m, "menuitem.quit");
        }

        mb.add(m);

        setMenuBar(mb);

        add("Center", panel = new AppletViewerPanel(doc, atts));
        add("South", label = new Label(amh.getMessage("label.hello")));
        panel.init();
        appletPanels.addElement(panel);

        pack();
        move(x, y);
        setVisible(true);

        WindowListener windowEventListener = new WindowAdapter() {

            public void windowClosing(WindowEvent evt) {
                appletClose();
            }

            public void windowIconified(WindowEvent evt) {
                appletStop();
            }

            public void windowDeiconified(WindowEvent evt) {
                appletStart();
            }
        };

        class AppletEventListener implements AppletListener
        {
            final Frame frame;

            public AppletEventListener(Frame frame)
            {
                this.frame = frame;
            }

            public void appletStateChanged(AppletEvent evt)
            {
                AppletPanel src = (AppletPanel)evt.getSource();

                switch (evt.getID()) {
                    case AppletPanel.APPLET_RESIZE: {
                        if(src != null) {
                            resize(preferredSize());
                            validate();
                        }
                        break;
                    }
                    case AppletPanel.APPLET_LOADING_COMPLETED: {
                        Applet a = src.getApplet(); // sun.applet.AppletPanel

                        // Fixed #4754451: Applet can have methods running on main
                        // thread event queue.
                        //
                        // The cause of this bug is that the frame of the applet
                        // is created in main thread group. Thus, when certain
                        // AWT/Swing events are generated, the events will be
                        // dispatched through the wrong event dispatch thread.
                        //
                        // To fix this, we rearrange the AppContext with the frame,
                        // so the proper event queue will be looked up.
                        //
                        // Swing also maintains a Frame list for the AppContext,
                        // so we will have to rearrange it as well.
                        //
                        if (a != null)
                            AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a));
                        else
                            AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext());

                        break;
                    }
                }
            }
        };

        addWindowListener(windowEventListener);
        panel.addAppletListener(new AppletEventListener(this));

        // Start the applet
        showStatus(amh.getMessage("status.start"));
        initEventQueue();
    }

    // XXX 99/9/10 probably should be "private"
    public MenuItem addMenuItem(Menu m, String s) {
        MenuItem mItem = new MenuItem(amh.getMessage(s));
        mItem.addActionListener(new UserActionListener());
        return m.add(mItem);
    }

    /**
     * Send the initial set of events to the appletviewer event queue.
     * On start-up the current behaviour is to load the applet and call
     * Applet.init() and Applet.start().
     */
    private void initEventQueue() {
        // appletviewer.send.event is an undocumented and unsupported system
        // property which is used exclusively for testing purposes.
        String eventList = System.getProperty("appletviewer.send.event");

        if (eventList == null) {
            // Add the standard events onto the event queue.
            panel.sendEvent(AppletPanel.APPLET_LOAD);
            panel.sendEvent(AppletPanel.APPLET_INIT);
            panel.sendEvent(AppletPanel.APPLET_START);
        } else {
            // We're testing AppletViewer.  Force the specified set of events
            // onto the event queue, wait for the events to be processed, and
            // exit.

            // The list of events that will be executed is provided as a
            // ","-separated list.  No error-checking will be done on the list.
            String [] events = splitSeparator(",", eventList);

            for (int i = 0; i < events.length; i++) {
                System.out.println("Adding event to queue: " + events[i]);
                if (events[i].equals("dispose"))
                    panel.sendEvent(AppletPanel.APPLET_DISPOSE);
                else if (events[i].equals("load"))
                    panel.sendEvent(AppletPanel.APPLET_LOAD);
                else if (events[i].equals("init"))
                    panel.sendEvent(AppletPanel.APPLET_INIT);
                else if (events[i].equals("start"))
                    panel.sendEvent(AppletPanel.APPLET_START);
                else if (events[i].equals("stop"))
                    panel.sendEvent(AppletPanel.APPLET_STOP);
                else if (events[i].equals("destroy"))
                    panel.sendEvent(AppletPanel.APPLET_DESTROY);
                else if (events[i].equals("quit"))
                    panel.sendEvent(AppletPanel.APPLET_QUIT);
                else if (events[i].equals("error"))
                    panel.sendEvent(AppletPanel.APPLET_ERROR);
                else
                    // non-fatal error if we get an unrecognized event
                    System.out.println("Unrecognized event name: " + events[i]);
            }

            while (!panel.emptyEventQueue()) ;
            appletSystemExit();
        }
    }

    /**
     * Split a string based on the presence of a specified separator.  Returns
     * an array of arbitrary length.  The end of each element in the array is
     * indicated by the separator of the end of the string.  If there is a
     * separator immediately before the end of the string, the final element
     * will be empty.  None of the strings will contain the separator.  Useful
     * when separating strings such as "foo/bar/bas" using separator "/".
     *
     * @param sep  The separator.
     * @param s    The string to split.
     * @return     An array of strings.  Each string in the array is determined
     *             by the location of the provided sep in the original string,
     *             s.  Whitespace not stripped.
     */
    private String [] splitSeparator(String sep, String s) {
        Vector v = new Vector();
        int tokenStart = 0;
        int tokenEnd   = 0;

        while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {
            v.addElement(s.substring(tokenStart, tokenEnd));
            tokenStart = tokenEnd+1;
        }
        // Add the final element.
        v.addElement(s.substring(tokenStart));

        String [] retVal = new String[v.size()];
        v.copyInto(retVal);
        return retVal;
    }

    /*
     * Methods for java.applet.AppletContext
     */

    private static Map audioClips = new HashMap();

    /**
     * Get an audio clip.
     */
    public AudioClip getAudioClip(URL url) {
        checkConnect(url);
        synchronized (audioClips) {
            AudioClip clip = (AudioClip)audioClips.get(url);
            if (clip == null) {
                audioClips.put(url, clip = new AppletAudioClip(url));
            }
            return clip;
        }
    }

    private static Map imageRefs = new HashMap();

    /**
     * Get an image.
     */
    public Image getImage(URL url) {
        return getCachedImage(url);
    }

    static Image getCachedImage(URL url) {
        // System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
        return (Image)getCachedImageRef(url).get();
    }

    /**
     * Get an image ref.
     */
    static Ref getCachedImageRef(URL url) {
        synchronized (imageRefs) {
            AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
            if (ref == null) {
                ref = new AppletImageRef(url);
                imageRefs.put(url, ref);
            }
            return ref;
        }
    }

    /**
     * Flush the image cache.
     */
    static void flushImageCache() {
        imageRefs.clear();
    }

    static Vector appletPanels = new Vector();

    /**
     * Get an applet by name.
     */
    public Applet getApplet(String name) {
        AppletSecurity security = (AppletSecurity)System.getSecurityManager();
        name = name.toLowerCase();
        SocketPermission panelSp =
            new SocketPermission(panel.getCodeBase().getHost(), "connect");
        for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
            AppletPanel p = (AppletPanel)e.nextElement();
            String param = p.getParameter("name");
            if (param != null) {
                param = param.toLowerCase();
            }
            if (name.equals(param) &&
                p.getDocumentBase().equals(panel.getDocumentBase())) {

                SocketPermission sp =
                    new SocketPermission(p.getCodeBase().getHost(), "connect");

                if (panelSp.implies(sp)) {
                    return p.applet;
                }
            }
        }
        return null;
    }

    /**
     * Return an enumeration of all the accessible
     * applets on this page.
     */
    public Enumeration getApplets() {
        AppletSecurity security = (AppletSecurity)System.getSecurityManager();
        Vector v = new Vector();
        SocketPermission panelSp =
            new SocketPermission(panel.getCodeBase().getHost(), "connect");

        for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
            AppletPanel p = (AppletPanel)e.nextElement();
            if (p.getDocumentBase().equals(panel.getDocumentBase())) {

                SocketPermission sp =
                    new SocketPermission(p.getCodeBase().getHost(), "connect");
                if (panelSp.implies(sp)) {
                    v.addElement(p.applet);
                }
            }
        }
        return v.elements();
    }

    /**
     * Ignore.
     */
    public void showDocument(URL url) {
    }

    /**
     * Ignore.
     */
    public void showDocument(URL url, String target) {
    }

    /**
     * Show status.
     */
    public void showStatus(String status) {
        label.setText(status);
    }

    public void setStream(String key, InputStream stream)throws IOException{
        // We do nothing.
    }

    public InputStream getStream(String key){
        // We do nothing.
        return null;
    }

    public Iterator getStreamKeys(){
        // We do nothing.
        return null;
    }

    /**
     * System parameters.
     */
    static Hashtable systemParam = new Hashtable();

    static {
        systemParam.put("codebase", "codebase");
        systemParam.put("code", "code");
        systemParam.put("alt", "alt");
        systemParam.put("width", "width");
        systemParam.put("height", "height");
        systemParam.put("align", "align");
        systemParam.put("vspace", "vspace");
        systemParam.put("hspace", "hspace");
    }

    /**
     * Print the HTML tag.
     */
    public static void printTag(PrintStream out, Hashtable atts) {
        out.print("<applet");

        String v = (String)atts.get("codebase");
        if (v != null) {
            out.print(" codebase=\"" + v + "\"");
        }

        v = (String)atts.get("code");
        if (v == null) {
            v = "applet.class";
        }
        out.print(" code=\"" + v + "\"");
        v = (String)atts.get("width");
        if (v == null) {
            v = "150";
        }
        out.print(" width=" + v);

        v = (String)atts.get("height");
        if (v == null) {
            v = "100";
        }
        out.print(" height=" + v);

        v = (String)atts.get("name");
        if (v != null) {
            out.print(" name=\"" + v + "\"");
        }
        out.println(">");

        // A very slow sorting algorithm
        int len = atts.size();
        String params[] = new String[len];
        len = 0;
        for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {
            String param = (String)e.nextElement();
            int i = 0;
            for (; i < len ; i++) {
                if (params[i].compareTo(param) >= 0) {
                    break;
                }
            }
            System.arraycopy(params, i, params, i + 1, len - i);
            params[i] = param;
            len++;
        }

        for (int i = 0 ; i < len ; i++) {
            String param = params[i];
            if (systemParam.get(param) == null) {
                out.println("<param name=" + param +
                            " value=\"" + atts.get(param) + "\">");
            }
        }
        out.println("</applet>");
    }

    /**
     * Make sure the atrributes are uptodate.
     */
    public void updateAtts() {
        Dimension d = panel.size();
        Insets in = panel.insets();
        panel.atts.put("width",
                       new Integer(d.width - (in.left + in.right)).toString());
        panel.atts.put("height",
                       new Integer(d.height - (in.top + in.bottom)).toString());
    }

    /**
     * Restart the applet.
     */
    void appletRestart() {
        panel.sendEvent(AppletPanel.APPLET_STOP);
        panel.sendEvent(AppletPanel.APPLET_DESTROY);
        panel.sendEvent(AppletPanel.APPLET_INIT);
        panel.sendEvent(AppletPanel.APPLET_START);
    }

    /**
     * Reload the applet.
     */
    void appletReload() {
        panel.sendEvent(AppletPanel.APPLET_STOP);
        panel.sendEvent(AppletPanel.APPLET_DESTROY);
        panel.sendEvent(AppletPanel.APPLET_DISPOSE);

        /**
         * Fixed #4501142: Classlaoder sharing policy doesn't
         * take "archive" into account. This will be overridden
         * by Java Plug-in.                     [stanleyh]
         */
        AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey());

        /*
         * Make sure we don't have two threads running through the event queue
         * at the same time.
         */
        try {
            panel.joinAppletThread();
            panel.release();
        } catch (InterruptedException e) {
            return;   // abort the reload
        }

        panel.createAppletThread();
        panel.sendEvent(AppletPanel.APPLET_LOAD);
        panel.sendEvent(AppletPanel.APPLET_INIT);
        panel.sendEvent(AppletPanel.APPLET_START);
    }

    /**
     * Save the applet to a well known file (for now) as a serialized object
     */
    void appletSave() {
        AccessController.doPrivileged(new PrivilegedAction() {

            public Object run() {
                // XXX: this privileged block should be made smaller
                // by initializing a private static variable with "user.dir"

                // Applet needs to be stopped for serialization to succeed.
                // Since panel.sendEvent only queues the event, there is a
                // chance that the event will not be processed before
                // serialization begins.  However, by sending the event before
                // FileDialog is created, enough time is given such that this
                // situation is unlikely to ever occur.

                panel.sendEvent(AppletPanel.APPLET_STOP);
                FileDialog fd = new FileDialog(AppletViewer.this,
                                               amh.getMessage("appletsave.filedialogtitle"),
                                               FileDialog.SAVE);
                // needed for a bug under Solaris...
                fd.setDirectory(System.getProperty("user.dir"));
                fd.setFile(defaultSaveFile);
                fd.show();
                String fname = fd.getFile();
                if (fname == null) {
                    // Restart applet if Save is cancelled.
                    panel.sendEvent(AppletPanel.APPLET_START);
                    return null;                // cancelled
                }
                String dname = fd.getDirectory();
                File file = new File(dname, fname);

                try {
                    BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
                    ObjectOutputStream os = new ObjectOutputStream(s);
                    showStatus(amh.getMessage("appletsave.err1",
                                              panel.applet.toString(), file.toString()));
                    os.writeObject(panel.applet);
                } catch (IOException ex) {
                    System.err.println(amh.getMessage("appletsave.err2", ex));
                } finally {
                    panel.sendEvent(AppletPanel.APPLET_START);
                }
                return null;
            }
        });
    }

    /**
     * Clone the viewer and the applet.
     */
    void appletClone() {
        Point p = location();
        updateAtts();
        factory.createAppletViewer(p.x + XDELTA, p.y + YDELTA,
                                   panel.documentURL, (Hashtable)panel.atts.clone());
    }

    /**
     * Show the applet tag.
     */
    void appletTag() {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        updateAtts();
        printTag(new PrintStream(out), panel.atts);
        showStatus(amh.getMessage("applettag"));

        Point p = location();
        new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("applettag.textframe"), out.toString());
    }

    /**
     * Show the applet info.
     */
    void appletInfo() {
        String str = panel.applet.getAppletInfo();
        if (str == null) {
            str = amh.getMessage("appletinfo.applet");
        }
        str += "\n\n";

        String atts[][] = panel.applet.getParameterInfo();
        if (atts != null) {
            for (int i = 0 ; i < atts.length ; i++) {
                str += atts[i][0] + " -- " + atts[i][1] + " -- " + atts[i][2] + "\n";
            }
        } else {
            str += amh.getMessage("appletinfo.param");
        }

        Point p = location();
        new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("appletinfo.textframe"), str);

    }

    /**
     * Show character encoding type
     */
    void appletCharacterEncoding() {
        showStatus(amh.getMessage("appletencoding", encoding));
    }

    /**
     * Edit the applet.
     */
    void appletEdit() {
    }

    /**
     * Print the applet.
     */
    void appletPrint() {
        PrinterJob pj = PrinterJob.getPrinterJob();

        if (pj != null) {
            PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
            if (pj.printDialog(aset)) {
                pj.setPrintable(this);
                try {
                    pj.print(aset);
                    statusMsgStream.println(amh.getMessage("appletprint.finish"));
                } catch (PrinterException e) {
                   statusMsgStream.println(amh.getMessage("appletprint.fail"));
                }
            } else {
                statusMsgStream.println(amh.getMessage("appletprint.cancel"));
            }
        } else {
            statusMsgStream.println(amh.getMessage("appletprint.fail"));
        }
    }

    public int print(Graphics graphics, PageFormat pf, int pageIndex) {
        if (pageIndex > 0) {
            return Printable.NO_SUCH_PAGE;
        } else {
            Graphics2D g2d = (Graphics2D)graphics;
            g2d.translate(pf.getImageableX(), pf.getImageableY());
            panel.applet.printAll(graphics);
            return Printable.PAGE_EXISTS;
        }
    }

    /**
     * Properties.
     */
    static AppletProps props;
    public static synchronized void networkProperties() {
        if (props == null) {
            props = new AppletProps();
        }
        props.addNotify();
        props.setVisible(true);
    }

    /**
     * Start the applet.
     */
    void appletStart() {
        panel.sendEvent(AppletPanel.APPLET_START);
    }

    /**
     * Stop the applet.
     */
    void appletStop() {
        panel.sendEvent(AppletPanel.APPLET_STOP);
    }

    /**
     * Shutdown a viewer.
     * Stop, Destroy, Dispose and Quit a viewer
     */
    private void appletShutdown(AppletPanel p) {
        p.sendEvent(AppletPanel.APPLET_STOP);
        p.sendEvent(AppletPanel.APPLET_DESTROY);
        p.sendEvent(AppletPanel.APPLET_DISPOSE);
        p.sendEvent(AppletPanel.APPLET_QUIT);
    }

    /**
     * Close this viewer.
     * Stop, Destroy, Dispose and Quit an AppletView, then
     * reclaim resources and exit the program if this is
     * the last applet.
     */
    void appletClose() {

        // The caller thread is event dispatch thread, so
        // spawn a new thread to avoid blocking the event queue
        // when calling appletShutdown.
        //
        final AppletPanel p = panel;

        new Thread(new Runnable()
        {
            public void run()
            {
                appletShutdown(p);
                appletPanels.removeElement(p);
                dispose();

                if (countApplets() == 0) {
                    appletSystemExit();
                }
            }
        }).start();
    }

    /**
     * Exit the program.
     * Exit from the program (if not stand alone) - do no clean-up
     */
    private void appletSystemExit() {
        if (factory.isStandalone())
            System.exit(0);
    }

    /**
     * Quit all viewers.
     * Shutdown all viewers properly then
     * exit from the program (if not stand alone)
     */
    protected void appletQuit()
    {
        // The caller thread is event dispatch thread, so
        // spawn a new thread to avoid blocking the event queue
        // when calling appletShutdown.
        //
        new Thread(new Runnable()
        {
            public void run()
            {
                for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
                    AppletPanel p = (AppletPanel)e.nextElement();
                    appletShutdown(p);
                }
                appletSystemExit();
            }
        }).start();
    }

    /**
     * Handle events.
     */
    public void processUserAction(ActionEvent evt) {

        String label = ((MenuItem)evt.getSource()).getLabel();

        if (amh.getMessage("menuitem.restart").equals(label)) {
            appletRestart();
            return;
        }

        if (amh.getMessage("menuitem.reload").equals(label)) {
            appletReload();
            return;
        }

        if (amh.getMessage("menuitem.clone").equals(label)) {
            appletClone();
            return;
        }

        if (amh.getMessage("menuitem.stop").equals(label)) {
            appletStop();
            return;
        }

        if (amh.getMessage("menuitem.save").equals(label)) {
            appletSave();
            return;
        }

        if (amh.getMessage("menuitem.start").equals(label)) {
            appletStart();
            return;
        }

        if (amh.getMessage("menuitem.tag").equals(label)) {
            appletTag();
            return;
        }

        if (amh.getMessage("menuitem.info").equals(label)) {
            appletInfo();
            return;
        }

        if (amh.getMessage("menuitem.encoding").equals(label)) {
            appletCharacterEncoding();
            return;
        }

        if (amh.getMessage("menuitem.edit").equals(label)) {
            appletEdit();
            return;
        }

        if (amh.getMessage("menuitem.print").equals(label)) {
            appletPrint();
            return;
        }

        if (amh.getMessage("menuitem.props").equals(label)) {
            networkProperties();
            return;
        }

        if (amh.getMessage("menuitem.close").equals(label)) {
            appletClose();
            return;
        }

        if (factory.isStandalone() && amh.getMessage("menuitem.quit").equals(label)) {
            appletQuit();
            return;
        }
        //statusMsgStream.println("evt = " + evt);
    }

    /**
     * How many applets are running?
     */

    public static int countApplets() {
        return appletPanels.size();
    }


    /**
     * The current character.
     */
    static int c;

    /**
     * Scan spaces.
     */
    public static void skipSpace(Reader in) throws IOException {
        while ((c >= 0) &&
               ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {
            c = in.read();
        }
    }

    /**
     * Scan identifier
     */
    public static String scanIdentifier(Reader in) throws IOException {
        StringBuffer buf = new StringBuffer();
        while (true) {
            if (((c >= 'a') && (c <= 'z')) ||
                ((c >= 'A') && (c <= 'Z')) ||
                ((c >= '0') && (c <= '9')) || (c == '_')) {
                buf.append((char)c);
                c = in.read();
            } else {
                return buf.toString();
            }
        }
    }

    /**
     * Scan tag
     */
    public static Hashtable scanTag(Reader in) throws IOException {
        Hashtable atts = new Hashtable();
        skipSpace(in);
        while (c >= 0 && c != '>') {
            String att = scanIdentifier(in);
            String val = "";
            skipSpace(in);
            if (c == '=') {
                int quote = -1;
                c = in.read();
                skipSpace(in);
                if ((c == '\'') || (c == '\"')) {
                    quote = c;
                    c = in.read();
                }
                StringBuffer buf = new StringBuffer();
                while ((c > 0) &&
                       (((quote < 0) && (c != ' ') && (c != '\t') &&
                         (c != '\n') && (c != '\r') && (c != '>'))
                        || ((quote >= 0) && (c != quote)))) {
                    buf.append((char)c);
                    c = in.read();
                }
                if (c == quote) {
                    c = in.read();
                }
                skipSpace(in);
                val = buf.toString();
            }
            //statusMsgStream.println("PUT " + att + " = '" + val + "'");
            if (! val.equals("")) {
                atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
            }
            while (true) {
                if ((c == '>') || (c < 0) ||
                    ((c >= 'a') && (c <= 'z')) ||
                    ((c >= 'A') && (c <= 'Z')) ||
                    ((c >= '0') && (c <= '9')) || (c == '_'))
                    break;
                c = in.read();
            }
            //skipSpace(in);
        }
        return atts;
    }

    /* values used for placement of AppletViewer's frames */
    private static int x = 0;
    private static int y = 0;
    private static final int XDELTA = 30;
    private static final int YDELTA = XDELTA;

    static String encoding = null;

    static private Reader makeReader(InputStream is) {
        if (encoding != null) {
            try {
                return new BufferedReader(new InputStreamReader(is, encoding));
            } catch (IOException x) { }
        }
        InputStreamReader r = new InputStreamReader(is);
        encoding = r.getEncoding();
        return new BufferedReader(r);
    }

    /**
     * Scan an html file for <applet> tags
     */
    public static void parse(URL url, String enc) throws IOException {
        encoding = enc;
        parse(url, System.out, new StdAppletViewerFactory());
    }

    public static void parse(URL url) throws IOException {
        parse(url, System.out, new StdAppletViewerFactory());
    }

    public static void parse(URL url, PrintStream statusMsgStream,
                             AppletViewerFactory factory) throws IOException {
        // <OBJECT> <EMBED> tag flags
        boolean isAppletTag = false;
        boolean isObjectTag = false;
        boolean isEmbedTag = false;

        // warning messages
        String requiresNameWarning = amh.getMessage("parse.warning.requiresname");
        String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
        String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
        String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
        String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
        String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
        String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
        String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
        String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
        String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
        String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
        String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");

        java.net.URLConnection conn = url.openConnection();
        Reader in = makeReader(conn.getInputStream());
        /* The original URL may have been redirected - this
         * sets it to whatever URL/codebase we ended up getting
         */
        url = conn.getURL();

        int ydisp = 1;
        Hashtable atts = null;

        while(true) {
            c = in.read();
            if (c == -1)
                break;

            if (c == '<') {
                c = in.read();
                if (c == '/') {
                    c = in.read();
                    String nm = scanIdentifier(in);
                    if (nm.equalsIgnoreCase("applet") ||
                        nm.equalsIgnoreCase("object") ||
                        nm.equalsIgnoreCase("embed")) {

                        // We can't test for a code tag until </OBJECT>
                        // because it is a parameter, not an attribute.
                        if(isObjectTag) {
                            if (atts.get("code") == null && atts.get("object") == null) {
                                statusMsgStream.println(objectRequiresCodeWarning);
                                atts = null;
                            }
                        }

                        if (atts != null) {
                            // XXX 5/18 In general this code just simply
                            // shouldn't be part of parsing.  It's presence
                            // causes things to be a little too much of a
                            // hack.
                            factory.createAppletViewer(x, y, url, atts);
                            x += XDELTA;
                            y += YDELTA;
                            // make sure we don't go too far!
                            Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
                            if ((x > d.width - 300) || (y > d.height - 300)) {
                                x = 0;
                                y = 2 * ydisp * YDELTA;
                                ydisp++;
                            }
                        }
                        atts = null;
                        isAppletTag = false;
                        isObjectTag = false;
                        isEmbedTag = false;
                    }
                }
                else {
                    String nm = scanIdentifier(in);
                    if (nm.equalsIgnoreCase("param")) {
                        Hashtable t = scanTag(in);
                        String att = (String)t.get("name");
                        if (att == null) {
                            statusMsgStream.println(requiresNameWarning);
                        } else {
                            String val = (String)t.get("value");
                            if (val == null) {
                                statusMsgStream.println(requiresNameWarning);
                            } else if (atts != null) {
                                atts.put(att.toLowerCase(), val);
                            } else {
                                statusMsgStream.println(paramOutsideWarning);
                            }
                        }
                    }
                    else if (nm.equalsIgnoreCase("applet")) {
                        isAppletTag = true;
                        atts = scanTag(in);
                        if (atts.get("code") == null && atts.get("object") == null) {
                            statusMsgStream.println(appletRequiresCodeWarning);
                            atts = null;
                        } else if (atts.get("width") == null) {
                            statusMsgStream.println(appletRequiresWidthWarning);
                            atts = null;
                        } else if (atts.get("height") == null) {
                            statusMsgStream.println(appletRequiresHeightWarning);
                            atts = null;
                        }
                    }
                    else if (nm.equalsIgnoreCase("object")) {
                        isObjectTag = true;
                        atts = scanTag(in);
                        // The <OBJECT> attribute codebase isn't what
                        // we want. If its defined, remove it.
                        if(atts.get("codebase") != null) {
                            atts.remove("codebase");
                        }

                        if (atts.get("width") == null) {
                            statusMsgStream.println(objectRequiresWidthWarning);
                            atts = null;
                        } else if (atts.get("height") == null) {
                            statusMsgStream.println(objectRequiresHeightWarning);
                            atts = null;
                        }
                    }
                    else if (nm.equalsIgnoreCase("embed")) {
                        isEmbedTag = true;
                        atts = scanTag(in);

                        if (atts.get("code") == null && atts.get("object") == null) {
                            statusMsgStream.println(embedRequiresCodeWarning);
                            atts = null;
                        } else if (atts.get("width") == null) {
                            statusMsgStream.println(embedRequiresWidthWarning);
                            atts = null;
                        } else if (atts.get("height") == null) {
                            statusMsgStream.println(embedRequiresHeightWarning);
                            atts = null;
                        }
                    }
                    else if (nm.equalsIgnoreCase("app")) {
                        statusMsgStream.println(appNotLongerSupportedWarning);
                        Hashtable atts2 = scanTag(in);
                        nm = (String)atts2.get("class");
                        if (nm != null) {
                            atts2.remove("class");
                            atts2.put("code", nm + ".class");
                        }
                        nm = (String)atts2.get("src");
                        if (nm != null) {
                            atts2.remove("src");
                            atts2.put("codebase", nm);
                        }
                        if (atts2.get("width") == null) {
                            atts2.put("width", "100");
                        }
                        if (atts2.get("height") == null) {
                            atts2.put("height", "100");
                        }
                        printTag(statusMsgStream, atts2);
                        statusMsgStream.println();
                    }
                }
            }
        }
        in.close();
    }

    /**
     * Old main entry point.
     *
     * @deprecated
     */
    @Deprecated
    public static void main(String argv[]) {
        // re-route everything to the new main entry point
        Main.main(argv);
    }

    private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");

    private static void checkConnect(URL url)
    {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            try {
                java.security.Permission perm =
                    url.openConnection().getPermission();
                if (perm != null)
                    security.checkPermission(perm);
                else
                    security.checkConnect(url.getHost(), url.getPort());
            } catch (java.io.IOException ioe) {
                    security.checkConnect(url.getHost(), url.getPort());
            }
        }
    }
}
