home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / browser / hotjava.java < prev    next >
Text File  |  1995-08-11  |  57KB  |  2,257 lines

  1. /*
  2.  * @(#)hotjava.java    1.184 95/08/04 Jonathan Payne and Patrick Naughton
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package browser;
  21.  
  22. import awt.*;
  23. import net.*;
  24. import java.lang.*;
  25. import java.io.*;
  26. import java.util.*;
  27. import net.www.html.URL;
  28. import net.www.html.MeteredStream;
  29. import net.www.html.ProgressReport;
  30. import net.www.http.HttpClient;
  31. import net.ftp.FtpClient;
  32. import browser.tools.JavaSearch.SearchWindow;
  33.  
  34. /**
  35.  * Class hotjava is really an awt.Frame, with code to create and
  36.  * manage all the UI components of hotjava.
  37.  * @version 1.184, 04 Aug 1995
  38.  * @author Jonathan Payne
  39.  * @author Sami Shaio
  40.  * @author Arthur van Hoff
  41.  */
  42. public class hotjava extends Frame {
  43.     static private boolean    securityConfigured = false;
  44.     static WRAccessHandler    handler = null;
  45.     static WServer    server = null;
  46.     static Font        labelFont;
  47.     static Font        inputFont;
  48.     static Font        dialogFont;
  49.     static Color    blue = null;
  50.     static SecurityDialog    sDialog = null;
  51.     static ProgressDialog    pDialog = null;
  52.     public static Color    anchorColor = null;
  53.     public static Color    visitedAnchorColor = null;
  54.     public static Properties    props;
  55.     static int        copiesRunning;
  56.     public static String home;
  57.     public static String dochome;
  58.     public static String version = "1.0 alpha3";
  59.     public static String programName = "HotJava";
  60.     public static String untitledTitle = "Untitled";
  61.     public static URLHistory    history;
  62.  
  63.     public static int windowWidth  = 641;
  64.     public static int windowHeight = 729;
  65.     
  66.     StatusWindow    statusWindow;
  67.     ToolBar        toolBar;
  68.     InfoWindow        infoWindow;
  69.     SearchWindow        searchWindow;
  70.     HistoryWindow    histWindow;
  71.     StringDialog        findDialog;
  72.  
  73.     MenuBar        mbar;
  74.     public FileMenu    fileMenu;
  75.     GoToMenu        gotoMenu;
  76.     protected WRWindow    doc;
  77.     HotList        hlist;
  78.     String        urlSpec;
  79.     String              pageTitle;
  80.     Image        icon;
  81.  
  82.     static {
  83.     home = System.getenv("WWW_HOME");
  84.     if (home == null) {
  85.         home = "doc:index.html";
  86.     }
  87.  
  88.     dochome = "doc:/doc/";
  89.  
  90.     initHistory();
  91.     }
  92.  
  93.     static void initHistory() {
  94.     history = new URLHistory();
  95.  
  96.     if (false) {
  97.         FileInputStream    is = null;
  98.         String    home = System.getenv("HOME");
  99.         String    hotjavaName;
  100.  
  101.         hotjavaName = home + File.separator + ".hotjava"
  102.             + File.separator + ".hotjava-global-history";
  103.         try {
  104.         is = new FileInputStream(hotjavaName);
  105.         history.parseStream(is);
  106.         } catch (IOException e) {
  107.         } catch (Exception e) {
  108.         System.err.println("Error " + e + " while reading your global history file!");
  109.         System.err.println("Therefore, your global history will not be updated in this session.");
  110.         return;
  111.         }
  112.         history.openOutputStream(hotjavaName);
  113.     }
  114.     }
  115.  
  116.     public static GifImage fetchGIF(String fromURL) {
  117.     try {
  118.         URL imgUrl = new URL(null, fromURL);
  119.         InputStream iStream = imgUrl.openStream();
  120.         return new GifImage(iStream, null);
  121.     } catch (Exception e) {
  122.         return null;
  123.     }
  124.     }
  125.  
  126.     public void go(String u) {
  127.     doc.pushURL(new URL(null, u));
  128.     }
  129.  
  130.     public void goHome() {
  131.     doc.pushURL(new URL(null, home));
  132.     }
  133.  
  134.     public void setTitle(String t) {
  135.     if (t == null || t.equals("")) {
  136.         super.setTitle(programName + " " + version);
  137.         pageTitle = "";
  138.     } else {
  139.         super.setTitle(programName+": "+t);
  140.         pageTitle = t;
  141.     }
  142.     }
  143.  
  144.     public void setURL(String u) {
  145.     infoWindow.urlField.setText(u);
  146.     }
  147.  
  148.     /**
  149.      * Call this to say that this document has HTML source.  Can be used
  150.      * to turn on/off various commands, etc.
  151.      */
  152.     public void pageHasSource(boolean source) {
  153.     if (source) {
  154.         fileMenu.viewSourceItem.enable();
  155.     } else {
  156.         fileMenu.viewSourceItem.disable();
  157.     }
  158.     }    
  159.  
  160.     public void handleQuit() {
  161.     if (--hotjava.copiesRunning > 0) {
  162.         // XXX: should actually be destroying the window and
  163.         // recovering resources...
  164.         unMap();
  165.     } else {
  166.         System.exit(0);
  167.     }
  168.     }
  169.  
  170.     public void setMessage(String msg) {
  171.         if (statusWindow.message != null) {
  172.         statusWindow.message.setText(msg);
  173.         } else {
  174.         setStatusMessage(msg);
  175.         }
  176.     }
  177.  
  178.  
  179.     public void readProperties() {
  180.     props = new Properties(System.getenv("HOME") + File.separator + ".hotjava" + File.separator + "properties");
  181.  
  182.     WRWindow.delayImageLoading = "true".equals(props.get("delayImageLoading"));
  183.     WRWindow.delayAppletLoading = "true".equals(props.get("delayAppletLoading"));
  184.     WRTextItem.underlineAnchors = ! "plain".equals(props.get("anchorStyle"));
  185.  
  186.     if (!version.equals(props.get("version"))) {
  187.         urlSpec = "doc:copyright.html";
  188.         props.put("version", version);
  189.         props.save();
  190.     }
  191.  
  192.     Object pval;
  193.  
  194.     if ((pval = props.get("firewallSet")) != null) {
  195.         HttpClient.useProxyForFirewall = "true".equals(pval);
  196.     }
  197.     pval = props.get("firewallHost");
  198.  
  199.     if (pval != null) {
  200.         HttpClient.firewallProxyHost = (String)pval;
  201.     }
  202.     pval = props.get("firewallPort");
  203.  
  204.     if (pval != null) {
  205.         try {
  206.         HttpClient.firewallProxyPort = Integer.parseInt((String)pval);
  207.         } catch (NumberFormatException e) {
  208.         System.out.println("Error parsing firewallProxyPort: "
  209.                    + (String)pval);
  210.         HttpClient.useProxyForFirewall = false;
  211.         }
  212.     }
  213.  
  214.     if ((pval = props.get("proxySet")) != null) {
  215.         HttpClient.useProxyForCaching = "true".equals(pval);
  216.     }
  217.     if ((pval = props.get("proxyHost")) != null) {
  218.         HttpClient.cachingProxyHost = (String)pval;
  219.     }
  220.     if ((pval = props.get("proxyPort")) != null) {
  221.         try {
  222.         HttpClient.cachingProxyPort = Integer.parseInt((String)pval);
  223.         } catch (NumberFormatException e) {
  224.         System.out.println("Error parsing cachingProxyPort: "
  225.                    + (String)pval);
  226.         HttpClient.useProxyForCaching = false;
  227.         }
  228.     }
  229.  
  230.     if ((pval = props.get("useFtpProxy")) != null) {
  231.         FtpClient.useFtpProxy = "true".equals(pval);
  232.     }
  233.     if ((pval = props.get("ftpProxyHost")) != null) {
  234.         FtpClient.ftpProxyHost = (String)pval;
  235.     }
  236.     if ((pval = props.get("ftpProxyPort")) != null) {
  237.         try {
  238.         FtpClient.ftpProxyPort = Integer.parseInt((String)pval);
  239.         } catch (NumberFormatException e) {
  240.         System.out.println("Error parsing ftpProxyPort: "
  241.                    + (String)pval);
  242.         FtpClient.useFtpProxy = false;
  243.         }
  244.     }
  245.     }
  246.  
  247.     public hotjava(WServer serv, String args[]) {
  248.     super(serv, true, null, windowWidth, windowHeight, Color.lightGray);
  249.     setInsets(4,0,4,0);
  250.     copiesRunning++;
  251.     super.setTitle(programName);
  252.     urlSpec = args.length > 0 ? args[0] : home;
  253.  
  254.  
  255.     // Read properties and set defaults
  256.     readProperties();
  257.   
  258.     if (blue == null) {
  259.         blue = Color.black;
  260.         anchorColor = new Color(serv, 0, 0, 192);
  261.         visitedAnchorColor = new Color(serv, 96, 32, 128);
  262.         labelFont = serv.fonts.getFont("Helvetica", Font.BOLD, 14);
  263.         inputFont = serv.fonts.getFont("DialogInput", Font.BOLD, 12);
  264.     }
  265.  
  266.     dialogFont = serv.fonts.getFont("Dialog", Font.BOLD, 12);
  267.     setDefaultFont(dialogFont);
  268.     doc = new WRWindow(this, "Center");
  269.     infoWindow = new InfoWindow(this);
  270.     doc.setScrollbar(new Scrollbar(doc, "sbar", Scrollbar.VERTICAL, true));
  271.     statusWindow = new StatusWindow(this);
  272.     toolBar = statusWindow.getToolBar();
  273.  
  274.     mbar = new MenuBar(this);
  275.     fileMenu = new FileMenu(mbar, this);
  276.     new OptionsMenu(mbar, this);
  277.     new NavigateMenu(mbar, this);
  278.     gotoMenu = new GoToMenu(mbar, this);
  279.     new HelpMenu(mbar, this);
  280.  
  281.     hlist = new HotList(serv, this);
  282.     histWindow = new HistoryWindow(serv, this, doc.docHistory);
  283.     findDialog = new StringDialog(this, hotjava.dialogFont,
  284.                       "Find", "Find what:",
  285.                       false, false, "Find", "Cancel",
  286.                       "Help", "", null);
  287.  
  288.     // Set the HotJava icon
  289.     // XXX: Note that this needs to be done before the frame is
  290.     // mapped for it to take effect.
  291.     //
  292.     serv.sync();
  293.  
  294.     try {
  295.         GifImage gif = hotjava.fetchGIF("doc:demo/images/wricon.gif");
  296.         icon = doc.createImage(gif, 32, 32);
  297.         setIconImage(icon);
  298.     } catch (Exception e) {
  299.         System.out.println("Couldn't set icon image");
  300.     }
  301.  
  302.     if (sDialog == null) {
  303.         sDialog = new SecurityDialog(this);
  304.     }
  305.     if (pDialog == null) {
  306.         pDialog = new ProgressDialog(this);
  307.     }
  308.  
  309.     map();
  310.  
  311.     if (! securityConfigured) {
  312.         sDialog.map();
  313.         sDialog.resize();
  314.     }
  315.  
  316.     URL current_url = null;
  317.     try {
  318.         current_url = new URL(current_url, urlSpec);
  319.         doc.pushURL(current_url);
  320.     } catch(Exception e) {
  321.         System.out.println("Ignoring error " + e);
  322.     }
  323.     }
  324.  
  325.     public static void main(String args[]) {
  326.     try {
  327.         File.setReadACL(System.getenv("HOTJAVA_READ_PATH"));
  328.         File.setWriteACL(System.getenv("HOTJAVA_WRITE_PATH"));
  329.     } catch (IOException e) {
  330.         System.out.println("Couldn't initialize security ACLs.");
  331.         return;
  332.     }
  333.     Firewall.readFirewallHosts();
  334.     if (!Firewall.readAccessMode()) {
  335.         securityConfigured = false;
  336.     } else {
  337.         securityConfigured = true;
  338.     }
  339.     try {
  340.         server = new WServer();
  341.     } catch(Exception e) {
  342.         System.out.println("Couldn't open connection to window server");
  343.         return;
  344.     }
  345.     server.start();
  346.     hotjava wr = new hotjava(server, args);
  347.     handler = new WRAccessHandler(wr);
  348.     File.setAccessErrorHandler(handler);
  349.     Firewall.setHandler(new WRSecurityHandler(wr));
  350.     }
  351.  
  352. }
  353.  
  354. class WRAccessHandler extends AccessErrorHandler {
  355.     MessageDialog    diag;
  356.  
  357.     WRAccessHandler(hotjava w) {
  358.     diag = new MessageDialog(w,
  359.                  "Access Exception",
  360.                  "",
  361.                  MessageDialog.ERROR_TYPE,
  362.                  2,
  363.                  true,
  364.                  "Deny Access",
  365.                  "Allow This Access",
  366.                  null,
  367.                  null);
  368.     }
  369.  
  370.     public int readException(String path) {
  371.     diag.setMessage("An applet has attempted to read " + path);
  372.     switch (diag.show()) {
  373.       case 2:
  374.         return AccessErrorHandler.ALLOW_THIS_ACCESS;
  375.       case 1:
  376.       default:
  377.         return AccessErrorHandler.DENY_ACCESS;
  378.     }
  379.     }
  380.  
  381.     public int writeException(String path) {
  382.     diag.setMessage("An applet has attempted to write " + path);
  383.     switch (diag.show()) {
  384.       case 2:
  385.         return AccessErrorHandler.ALLOW_THIS_ACCESS;
  386.       case 1:
  387.       default:
  388.         return AccessErrorHandler.DENY_ACCESS;
  389.     }    
  390.     }
  391. }
  392.  
  393.  
  394. class WRSecurityHandler extends AccessErrorHandler {
  395.     MessageDialog    diag;
  396.  
  397.     WRSecurityHandler(hotjava w) {
  398.     diag = new MessageDialog(w,
  399.                  "Security Exception",
  400.                  "",
  401.                  MessageDialog.ERROR_TYPE,
  402.                  1,
  403.                  true,
  404.                  "Ok",
  405.                  null,
  406.                  null,
  407.                  null);
  408.     }
  409.  
  410.     public int readException(String msg) {
  411.     diag.setMessage(msg);
  412.     diag.show();
  413.     return AccessErrorHandler.DENY_ACCESS;
  414.     }
  415. }
  416.  
  417.  
  418. class ClearButton extends Button {
  419.     hotjava target;
  420.  
  421.     public ClearButton(Container w, hotjava hj) {
  422.     super("Document URL:", null, w);
  423.     target = hj;
  424.     }
  425.     
  426.     public ClearButton(Image i, Image iP, Container w,
  427.                hotjava hj) {
  428.     super(i, iP, null, w);
  429.     target = hj;
  430.     }
  431.     
  432.     public void selected(Component c, int pos) {
  433.     target.setURL("");
  434.     }
  435. }
  436.  
  437.  
  438. class BackButton extends Button {
  439.     hotjava target;
  440.  
  441.     public BackButton(Container w, hotjava mw) {
  442.     super("Back", null, w);
  443.     target = mw;
  444.     }
  445.     
  446.     public BackButton(Image i, Image iP, Image dis, Container w,
  447.               hotjava mw) {
  448.     super(i, iP, dis, null, w);
  449.     target = mw;
  450.     }
  451.     
  452.     public void selected(Component c, int pos) {
  453.     target.doc.backup();
  454.     }
  455. }
  456.  
  457.  
  458. class FwdButton extends Button {
  459.     hotjava target;
  460.  
  461.     public FwdButton(Container w, hotjava mw) {
  462.     super("Forward", null, w);
  463.     target = mw;
  464.     }
  465.  
  466.     public FwdButton(Image i, Image iP, Image dis, Container w,
  467.              hotjava mw) {
  468.     super(i, iP, dis, null, w);
  469.     target = mw;
  470.     }
  471.     
  472.     public void selected(Component c, int pos) {
  473.     target.doc.forward();
  474.     }
  475. }
  476.  
  477. class HomeButton extends Button {
  478.     hotjava target;
  479.  
  480.     public HomeButton(Container w, hotjava mw) {
  481.     super("Home", null, w);
  482.     target = mw;
  483.     }
  484.     
  485.     public HomeButton(Image i, Image iP, Container w,
  486.               hotjava mw) {
  487.     super(i, iP, null, w);
  488.     target = mw;
  489.     }
  490.     
  491.     public void selected(Component c, int pos) {
  492.     target.goHome();
  493.     }
  494. }
  495.  
  496.  
  497. class ReloadButton extends Button {
  498.     hotjava target;
  499.  
  500.     public ReloadButton(Container w, hotjava mw) {
  501.     super("Reload", null, w);
  502.     target = mw;
  503.     }
  504.     
  505.     public ReloadButton(Image i, Image iP, Container w,
  506.             hotjava mw) {
  507.     super(i, iP, null, w);
  508.     target = mw;
  509.     }
  510.     
  511.     public void selected(Component c, int pos) {
  512.     target.doc.reload();
  513.     }
  514. }
  515.  
  516.  
  517. class StopButton extends Button {
  518.     hotjava target;
  519.  
  520.     public StopButton(Container w, hotjava mw) {
  521.     super("Stop", null, w);
  522.     target = mw;
  523.     }
  524.     
  525.     public StopButton(Image i, Image iP, Image dis, Container w,
  526.               hotjava mw) {
  527.     super(i, iP, dis, null, w);
  528.     target = mw;
  529.     }
  530.     
  531.     public void selected(Component c, int pos) {
  532.     target.doc.stopFetch();
  533.     }
  534. }
  535.  
  536.  
  537.  
  538. /*
  539.  * This class displays control buttons and status messages for
  540.  * hotjava.  It is an observer of the MeteredStream class, which
  541.  * notifies it of progress while reading HTTP streams.
  542.  */
  543. class StatusWindow extends Window implements Runnable {
  544.     Color    fg;
  545.     Label    message;
  546.     hotjava     hj;
  547.     ToolBar     toolBar;
  548.  
  549.     final int sepBarHeight = 2;
  550.  
  551.     public StatusWindow(hotjava mw) {
  552.     super(mw, "South", mw.background, 500, 30);
  553.     setLayout(new ColumnLayout(true));
  554.  
  555.         hj = mw;
  556.     toolBar = new ToolBar(this, this, hj);
  557.     new Space(this, null, 0, sepBarHeight + 2, true, false);
  558.  
  559.     fg = Color.black;
  560.  
  561.     InputStream iStream;
  562.     URL        imgUrl;
  563.  
  564.     if (mw.hasStatusBar()) {
  565.             mw.showStatusBar(true);
  566.         } else {
  567.         message=new Label("", "status", this,hotjava.labelFont);
  568.         message.setColor(hotjava.blue);
  569.         message.setHFill(true);
  570.         }
  571.  
  572.         // Finally, fork a thread to execute the run() method defined below.
  573.      new Thread(this, "Progress Reporter").start();
  574.     }
  575.  
  576.     public ToolBar getToolBar() {
  577.     return toolBar;
  578.     }
  579.  
  580.     public void paint() {
  581.     paint3DRect(0, 0, width, sepBarHeight, false, true);
  582.     }
  583.  
  584.     public void setMessage(String msg) {
  585.         if (message != null) {
  586.         message.setText(msg);
  587.         } else {
  588.             hj.setStatusMessage(msg);
  589.         }
  590.     }
  591.  
  592.     private String plural(int n) {
  593.     return (n == 1) ? "" : "s";
  594.     }
  595.  
  596.     /*
  597.      * Notify any observers that the amount expected or the amount
  598.      * read has changed.  The notification only happens if the total
  599.      * number of bytes (read and expected) has changed by more than
  600.      * 3% of the last amount reported.  Make sure that this method
  601.      * is only called from synchronized static methods.
  602.      */
  603.     public void run() {
  604.     ProgressReport pr = new ProgressReport();
  605.     int lastReport = 0;
  606.     int connections = 0;
  607.  
  608.     Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
  609.     while (true) {
  610.         Thread.sleep(500);
  611.         MeteredStream.checkProgress(pr);
  612.         int total = pr.recvd + pr.expected;
  613.  
  614.         if (connections != pr.connections || total != lastReport) {
  615.         int diff = pr.expected - pr.recvd;
  616.         int percent = (int) (((float)pr.recvd/pr.expected) * 100);
  617.             
  618.         if (pr.connections == 0 && diff == 0) {
  619.                     String msg = hj.statusMessage;
  620.                     if (message != null) 
  621.                         msg = message.label;
  622.             if (msg.endsWith("% completed)]"))
  623.             setMessage("");
  624.         } else {
  625.             setMessage("[" + pr.connections + " connection"
  626.             + plural(pr.connections) + ": " + diff
  627.                    + " bytes remaining (" + percent + "% completed)]");
  628.         }
  629.         lastReport = total;
  630.         connections = pr.connections;
  631.         }
  632.     }
  633.     }
  634. }
  635.  
  636. /**
  637.  * This class displays control buttons for hotjava.
  638.  */
  639.  
  640. class ToolBar extends Row {
  641.  
  642.     Button backButton;
  643.     Button fwdButton;
  644.     Button stopButton;
  645.     
  646.     public ToolBar(Container cont, Window win, hotjava hj) {
  647.     super(cont, null, true);
  648.  
  649.     try {
  650.         final String base = "doc:demo/images/";
  651.         
  652.         GifImage bbm = hotjava.fetchGIF(base + "back.gif");
  653.         GifImage bbPm = hotjava.fetchGIF(base + "backP.gif");
  654.         GifImage bdbm = hotjava.fetchGIF(base + "backD.gif");
  655.         GifImage fbm = hotjava.fetchGIF(base + "fwd.gif");
  656.         GifImage fbPm = hotjava.fetchGIF(base + "fwdP.gif");
  657.         GifImage fdbm = hotjava.fetchGIF(base + "fwdD.gif");
  658.         GifImage hbm = hotjava.fetchGIF(base + "home.gif");
  659.         GifImage hbPm = hotjava.fetchGIF(base + "homeP.gif");
  660.         GifImage rbm = hotjava.fetchGIF(base + "reload.gif");
  661.         GifImage rbPm = hotjava.fetchGIF(base + "reloadP.gif");
  662.         GifImage stopbm = hotjava.fetchGIF(base + "stop.gif");
  663.         GifImage stopPbm = hotjava.fetchGIF(base + "stopP.gif");
  664.         GifImage stopDbm = hotjava.fetchGIF(base + "stopD.gif");
  665.         
  666.         if (bbm==null) {
  667.         backButton = new BackButton(this, hj);
  668.         } else {
  669.         Image bimg = win.createImage(bbm);
  670.         Image bPimg = win.createImage(bbPm);
  671.         Image bDisImg = win.createImage(bdbm);
  672.         backButton = new BackButton(bimg, bPimg, bDisImg, this, hj);
  673.         }
  674.         
  675.         if (fbm==null) {
  676.         fwdButton = new FwdButton(this, hj);
  677.         } else {
  678.         Image fimg = win.createImage(fbm);
  679.         Image fPimg = win.createImage(fbPm);
  680.         Image fDisImg = win.createImage(fdbm);
  681.         fwdButton = new FwdButton(fimg, fPimg, fDisImg, this, hj);
  682.         }
  683.         
  684.         if (hbm==null) {
  685.         new HomeButton(this, hj);
  686.         } else {
  687.         Image himg = win.createImage(hbm);
  688.         Image hPimg = win.createImage(hbPm);
  689.         new HomeButton(himg, hPimg, this, hj);
  690.         }
  691.         
  692.         if (rbm==null) {
  693.         new ReloadButton(this, hj);
  694.         } else {
  695.         Image rimg = win.createImage(rbm);
  696.         Image rPimg = win.createImage(rbPm);
  697.         new ReloadButton(rimg, rPimg, this, hj);
  698.         }
  699.         
  700.         if (stopbm==null) {
  701.         new StopButton(this, hj);
  702.         } else {
  703.         Image stopImg = win.createImage(stopbm);
  704.         Image stopPImg = win.createImage(stopPbm);
  705.         Image stopDImg = win.createImage(stopDbm);
  706.         
  707.         stopButton = new StopButton(stopImg, stopPImg, stopDImg,
  708.                         this, hj);
  709.         }
  710.     } catch (Exception e) {
  711.         System.err.println("Unable to read one or more button "+
  712.                    "images - using text labels instead");
  713.         backButton = new BackButton(this, hj);
  714.         fwdButton = new FwdButton(this, hj);
  715.         new HomeButton(this, hj);
  716.         new ReloadButton(this, hj);
  717.         stopButton = new StopButton(this, hj);
  718.     }
  719.  
  720.     backButton.disable();
  721.     fwdButton.disable();
  722.     stopButton.disable();
  723.     }
  724.  
  725.     public void setButtonStates(int stkIndex, Stack docStack) {
  726.     fwdButton.enable();
  727.     backButton.enable();
  728.  
  729.     if (docStack.size() == 1) {
  730.         backButton.disable();
  731.         fwdButton.disable();
  732.     } else if (stkIndex >= docStack.size()) {
  733.         fwdButton.disable();
  734.     } else if (stkIndex == 1) {
  735.         backButton.disable();
  736.     }
  737.     }
  738.  
  739.     public void allowStop(boolean yes) {
  740.     if (yes) {
  741.         stopButton.enable();
  742.     } else {
  743.         stopButton.disable();
  744.     }
  745.     }
  746.  
  747. }
  748.  
  749.  
  750. class FileMenu extends Menu {
  751.  
  752.     OpenDialog    openDialog;
  753.     PrintDialog    printDialog;
  754.  
  755.     public MenuItem viewSourceItem;
  756.     
  757.     public FileMenu(MenuBar mbar, hotjava w) {
  758.     super("File", mbar);
  759.  
  760.     mw = w;
  761.  
  762.     MenuItem    item;
  763.  
  764.     item = new MenuItem("New", this);
  765.     item.disable();
  766.     item = new MenuItem("Open...", this);
  767.     item = new MenuItem("Reload", this);
  768.     item = new MenuItem("Save", this);
  769.     item.disable();
  770.     item = new MenuItem("Save As...", this);
  771.     item.disable();
  772.     item = new MenuItem("Print...", this);
  773.     item.disable();
  774.     viewSourceItem = new MenuItem("View Source...", this);
  775.     viewSourceItem.disable();
  776.     item = new MenuItem("Close", this);
  777.     item.disable();
  778.     new MenuItem("Quit", this);
  779.     enabled = true;
  780.     }
  781.     
  782.     public void selected(int index) {
  783.     int    height;
  784.     int    width;
  785.     String  args[];
  786.  
  787.     switch (index) {
  788.       case 0: // New
  789.         args = new String[1];
  790.         args[0] = mw.urlSpec;
  791.         new hotjava(hotjava.server, args);
  792.         break;
  793.       case 1: // Open
  794.         if (openDialog == null) {
  795.         openDialog = new OpenDialog(hotjava.server, mw);
  796.         }
  797.         openDialog.map();
  798.         break;
  799.       case 2: // Reload
  800.         mw.doc.reload();
  801.         break;
  802.       case 3: // Save
  803.         break;
  804.       case 4: // Save As
  805.         break;
  806.       case 5: // Print...
  807.         if (printDialog == null) {
  808.         printDialog = new PrintDialog(mw, mw.doc.document());
  809.         }
  810.         printDialog.map();
  811.         break;
  812.       case 6: // View Source...
  813.         new SourceViewer(mw, mw.doc.document().thisURL);
  814.         break;
  815.       case 7: // Close Window
  816.         hotjava.copiesRunning--;
  817.         if (hotjava.copiesRunning > 0) {
  818.         // XXX: should actually be destroying the window and
  819.         // recovering resources...
  820.         mw.unMap();
  821.         break;
  822.         }
  823.         // else fall into quit case
  824.       case 8: // Quit
  825.         System.exit(0);
  826.         break;
  827.       default:
  828.         break;
  829.     }
  830.     }
  831.  
  832.     hotjava        mw;
  833.     private boolean    enabled;
  834. }
  835.  
  836. class OptionsMenu extends Menu {
  837.     hotjava         mw;
  838.     MenuItem        showToggle;
  839.     PropertySheet    propSheet = null;
  840.  
  841.     public OptionsMenu(MenuBar mbar, hotjava w) {
  842.     super("Options", mbar);
  843.  
  844.     mw = w;
  845.  
  846.     MenuItem    item;
  847.  
  848.     item = new MenuItem("Font", this);
  849.     item.disable();
  850.     item = new MenuItem("Color", this);
  851.     item.disable();
  852.     new MenuItem("Security...", this);
  853.     new MenuItem("Properties...", this);
  854.     new MenuItem("Flush Cache", this);
  855.     new MenuItem("Progress Monitor", this);
  856.     }
  857.     public void selected(int index) {
  858.     boolean    st;
  859.  
  860.     switch (index) {
  861.       case 2: // Security...
  862.         hotjava.sDialog.map();
  863.         hotjava.sDialog.resize();
  864.         break;
  865.       case 3: // Properties...
  866.         if (propSheet == null) {
  867.         propSheet = new PropertySheet(mw);
  868.         }
  869.         propSheet.show();
  870.         break;
  871.       case 4: // Flush Cache
  872.         ImageCache.flush();
  873.         browser.audio.AudioData.flushCache();
  874.         break;
  875.       case 5: // Progress
  876.         hotjava.pDialog.map();
  877.         hotjava.pDialog.resize();
  878.         break;
  879.       default:
  880.         break;
  881.     }
  882.     }
  883. }
  884.  
  885. class HotlistMenuItem extends MenuItem {
  886.     String url;
  887.     hotjava mw;
  888.  
  889.     public HotlistMenuItem(String title, String url, Menu parent,
  890.                hotjava mw) {
  891.     super(title, parent);
  892.     this.url = url;
  893.     this.mw = mw;
  894.     }
  895.     public void selected() {
  896.     mw.doc.pushURL(new URL(null, url));
  897.     }
  898. }
  899.  
  900. class GoToMenu extends Menu {
  901.     hotjava mw;
  902.  
  903.     public GoToMenu(MenuBar mbar, hotjava w) {
  904.     super("Goto", mbar);
  905.     mw = w;
  906.     new MenuItem("Add Current", this);
  907.     addSeparator();    
  908.     }
  909.  
  910.     public void selected(int index) {
  911.     switch (index) {
  912.       case 0:
  913.         mw.hlist.addItem(mw.pageTitle,
  914.                  mw.infoWindow.urlField.getText(),
  915.                  true,
  916.                  true);
  917.         break;
  918.       default:
  919.         break;
  920.     }
  921.     }
  922.  
  923.     public HotlistMenuItem addHotItem(String title, String url) {
  924.     if ((title == null) || (title.length() == 0)) {
  925.         title = hotjava.untitledTitle+" (" + url + ")";
  926.     }
  927.     return new HotlistMenuItem(title, url, this, mw);
  928.     }
  929. }
  930.  
  931.  
  932. class NavigateMenu extends Menu {
  933.     hotjava    mw;
  934.     boolean    addedSeparator = false;
  935.  
  936.     public NavigateMenu(MenuBar mbar, hotjava w) {
  937.     super("Navigate", mbar);
  938.  
  939.     mw = w;
  940.     MenuItem    item;
  941.  
  942.     new MenuItem("Forward", this);
  943.     new MenuItem("Back", this);
  944.     new MenuItem("Home", this);
  945.     addSeparator();
  946.     new MenuItem("Show History...", this);
  947.     addSeparator();
  948.     new MenuItem("Add Current to Hotlist", this);
  949.     new MenuItem("Show Hotlist...", this);
  950.     addSeparator();
  951.     (new MenuItem("Find...", this)).disable();
  952.     }
  953.  
  954.     public void selected(int index) {
  955.     String urlstring;
  956.  
  957.     switch (index) {
  958.       case 0:
  959.         // Forward
  960.         mw.doc.forward();
  961.         break;
  962.       case 1:
  963.         // Back
  964.         mw.doc.backup();
  965.         break;
  966.       case 2:
  967.         // Home
  968.         mw.goHome();
  969.         break;
  970.       case 3:
  971.         // History
  972.         mw.histWindow.showWindow();
  973.         break;
  974.       case 4:
  975.         // Add Current to HotList
  976.         mw.hlist.addItem(mw.pageTitle,
  977.                  mw.infoWindow.urlField.getText(),
  978.                  false,
  979.                  false);
  980.         break;
  981.       case 5:
  982.         // Show HotList
  983.         mw.hlist.map();
  984.         mw.hlist.resize();
  985.         mw.hlist.wServer.sync();
  986.         break;
  987.       case 6:
  988.         mw.findDialog.setHandler(new FindHandler(mw));
  989.         mw.findDialog.show();
  990.       default:
  991.         break;
  992.     }
  993.     }
  994. }
  995.  
  996. class HotlistGotoButton extends Button {
  997.     public HotlistGotoButton(Container w, HotList hl) {
  998.     super("Visit","", w);
  999.     hlist = hl;
  1000.     }
  1001.     public void selected(Component c, int pos) {
  1002.     HotListItem    hItem = (HotListItem)hlist.urlList.elementAt(hlist.selectedItem);
  1003.  
  1004.     hlist.mw.doc.pushURL(new URL(null, hItem.url));
  1005.     }
  1006.  
  1007.     HotList    hlist;
  1008. }
  1009.  
  1010. class DismissButton extends Button {
  1011.  
  1012.     public DismissButton(Container w, Frame f) {
  1013.     this(w, f, "Cancel");
  1014.     }
  1015.     
  1016.     public DismissButton(Container w, Frame f, String label) {
  1017.     super(label, null, w);
  1018.  
  1019.     frame = f;
  1020.     }
  1021.     
  1022.     public void selected(Component c, int pos) {
  1023.     frame.unMap();
  1024.     }
  1025.  
  1026.     Frame    frame;
  1027. }
  1028.  
  1029. class PropertiesDismissButton extends Button {
  1030.     hotjava      wr;
  1031.     PropertySheet props;
  1032.  
  1033.     public PropertiesDismissButton(Container w,
  1034.                    PropertySheet f,
  1035.                    hotjava wr) {
  1036.     super("Cancel", null, w);
  1037.     this.wr = wr;
  1038.     this.props = f;
  1039.     }
  1040.     
  1041.     public void selected(Component c, int pos) {
  1042.     wr.readProperties();
  1043.     props.setAllValues();
  1044.     props.unMap();
  1045.     }
  1046. }
  1047.  
  1048. class DeleteButton extends Button {
  1049.     public DeleteButton(Container w, HotList hl) {
  1050.     super("Delete",null,w);
  1051.     hlist = hl;
  1052.     }
  1053.     public void selected(Component c, int pos) {
  1054.     hlist.delete(hlist.selectedItem);
  1055.     }
  1056.  
  1057.     HotList    hlist;
  1058. }
  1059.  
  1060. class ApplyButton extends Button {
  1061.     public ApplyButton(Container w, PropertySheet f) {
  1062.     super("Apply",null, w);
  1063.  
  1064.     propSheet = f;
  1065.     }
  1066.  
  1067.     private void portError(String wouldBeNumber, String portName) {
  1068.     MessageDialog error = propSheet.errorDialog;
  1069.     
  1070.     error.setMessage("'"+wouldBeNumber+"' is not a valid "+portName+
  1071.                  " port number.  Try again.");
  1072.     error.show();
  1073.     }
  1074.  
  1075.     private void hostError(String wouldBeHost, String hostName) {
  1076.     MessageDialog error = propSheet.errorDialog;
  1077.     
  1078.     error.setMessage("'"+wouldBeHost+"' is not a valid "+hostName+
  1079.                  " host name.  Try again.");
  1080.     error.show();
  1081.     }
  1082.     
  1083.     public void selected(Component c, int pos) {
  1084.     boolean wasError = false;
  1085.  
  1086.     // Try to parse port numbers.  If we fail, pitch an error dialog,
  1087.     // and don't store any values.
  1088.     String firewallPort = propSheet.fProxyPort.getText();
  1089.     try {
  1090.         HttpClient.firewallProxyPort = Integer.parseInt(firewallPort);
  1091.     } catch (NumberFormatException e) {
  1092.         portError(firewallPort, "Firewall Proxy");
  1093.         propSheet.fProxyPort.setText(HttpClient.firewallProxyPort+"");
  1094.         wasError = true;
  1095.     }
  1096.  
  1097.     String proxyPort = propSheet.cProxyPort.getText();
  1098.     try {
  1099.         HttpClient.cachingProxyPort = Integer.parseInt(proxyPort);
  1100.     } catch (NumberFormatException e) {
  1101.         portError(proxyPort, "Caching Proxy");
  1102.         propSheet.cProxyPort.setText(HttpClient.cachingProxyPort+"");
  1103.         wasError = true;
  1104.     }
  1105.  
  1106.     String ftpProxyPort = propSheet.ftpProxyPort.getText();
  1107.     try {
  1108.         FtpClient.ftpProxyPort = Integer.parseInt(ftpProxyPort);
  1109.     } catch (NumberFormatException e) {
  1110.         portError(ftpProxyPort, "FTP Proxy");
  1111.         propSheet.ftpProxyPort.setText(FtpClient.ftpProxyPort+"");
  1112.         wasError = true;
  1113.     }
  1114.  
  1115.     String firewallProxy = propSheet.fProxyField.getText();
  1116.     try {
  1117.         if (propSheet.fProxyToggle.getState()) {
  1118.         InetAddress    iaddr = InetAddress.getByName(firewallProxy);
  1119.         }
  1120.         HttpClient.firewallProxyHost = firewallProxy;
  1121.     } catch (UnknownHostException e) {
  1122.         hostError(firewallProxy, "Firewall Proxy");
  1123.         propSheet.fProxyField.setText(HttpClient.firewallProxyHost);
  1124.         wasError = true;
  1125.     }
  1126.  
  1127.     String cachingProxy = propSheet.cProxyField.getText();
  1128.     try {
  1129.         if (propSheet.cProxyToggle.getState()) {
  1130.         InetAddress    iaddr = InetAddress.getByName(cachingProxy);
  1131.         }
  1132.         HttpClient.cachingProxyHost = cachingProxy;
  1133.     } catch (UnknownHostException e) {
  1134.         hostError(cachingProxy, "Caching Proxy");
  1135.         propSheet.cProxyField.setText(HttpClient.cachingProxyHost);
  1136.         wasError = true;
  1137.     }
  1138.  
  1139.     String ftpProxy = propSheet.ftpProxyField.getText();
  1140.     try {
  1141.         if (propSheet.ftpProxyToggle.getState()) {
  1142.         InetAddress    iaddr = InetAddress.getByName(ftpProxy);
  1143.         }
  1144.         FtpClient.ftpProxyHost = ftpProxy;
  1145.     } catch (UnknownHostException e) {
  1146.         hostError(ftpProxy, "FTP Proxy");
  1147.         propSheet.ftpProxyField.setText(FtpClient.ftpProxyHost);
  1148.         wasError = true;
  1149.     }
  1150.     
  1151.  
  1152.     if (! wasError) {
  1153.         if (WRTextItem.underlineAnchors != propSheet.ulField.getState()) {
  1154.         WRTextItem.underlineAnchors = propSheet.ulField.getState();
  1155.         propSheet.mw.doc.paint();
  1156.         }
  1157.         propSheet.mw.doc.setDelayImageLoading(propSheet.dilField.getState());
  1158.         propSheet.mw.doc.setDelayAppletLoading(propSheet.dalField.getState());
  1159.         
  1160.         HttpClient.useProxyForFirewall = propSheet.fProxyToggle.getState();
  1161.         HttpClient.useProxyForCaching = propSheet.cProxyToggle.getState();
  1162.         FtpClient.useFtpProxy = propSheet.ftpProxyToggle.getState();
  1163.  
  1164.         propSheet.unMap();
  1165.         
  1166.         // set and save properties
  1167.         propSheet.mw.props.put("anchorStyle",
  1168.                    WRTextItem.underlineAnchors ?
  1169.                    "underline" : "plain");
  1170.         propSheet.mw.props.put("delayAppletLoading",
  1171.                    WRWindow.delayAppletLoading ?
  1172.                    "true" : "false");
  1173.         propSheet.mw.props.put("delayImageLoading",
  1174.                    WRWindow.delayImageLoading ?
  1175.                    "true" : "false");
  1176.         propSheet.mw.props.put("firewallSet",
  1177.                    HttpClient.useProxyForFirewall ?
  1178.                    "true":"false");
  1179.         propSheet.mw.props.put("firewallHost",
  1180.                    HttpClient.firewallProxyHost);
  1181.         propSheet.mw.props.put("firewallPort", firewallPort);
  1182.         
  1183.         propSheet.mw.props.put("proxySet",
  1184.                    HttpClient.useProxyForCaching ?
  1185.                    "true": "false");
  1186.         propSheet.mw.props.put("proxyHost", HttpClient.cachingProxyHost);
  1187.         propSheet.mw.props.put("proxyPort", proxyPort);
  1188.  
  1189.         propSheet.mw.props.put("useFtpProxy",
  1190.                    FtpClient.useFtpProxy ?
  1191.                    "true": "false");
  1192.         propSheet.mw.props.put("ftpProxyHost", FtpClient.ftpProxyHost);
  1193.         propSheet.mw.props.put("ftpProxyPort", ftpProxyPort);
  1194.         
  1195.         propSheet.mw.props.save();
  1196.     }
  1197.     }
  1198.  
  1199.    PropertySheet    propSheet;
  1200. }
  1201.  
  1202.  
  1203. class SaveButton extends Button {
  1204.     public SaveButton(Container w,  SourceViewer f) {
  1205.     super("Save...",null, w);
  1206.     sViewer = f;
  1207.     }
  1208.     public void selected(Component c, int pos) {
  1209.     if (fdialog == null) {
  1210.         fdialog = new FileDialog("Save HTML Source...", sViewer);
  1211.     }
  1212.     String path = fdialog.chooseFile(null);
  1213.  
  1214.     if (path != null) {
  1215.         try {
  1216.         File fpath = new File(path);
  1217.         PrintStream pStr = new PrintStream(new FileOutputStream(fpath));
  1218.         pStr.print(sViewer.t.getText());
  1219.         pStr.close();
  1220.         } catch (Exception e) {
  1221.         sViewer.status.setText("Error writing to " + path);
  1222.         return;
  1223.         }
  1224.         sViewer.status.setText("Wrote " + path);
  1225.     }
  1226.     }
  1227.  
  1228.     SourceViewer sViewer;
  1229.     FileDialog    fdialog = null;
  1230. }
  1231.  
  1232. class SourceViewer extends Frame implements Runnable {
  1233.     URL doc;
  1234.     TextArea t;
  1235.     Label    status;
  1236.     
  1237.     SourceViewer(hotjava wr, URL doc) {
  1238.     super(hotjava.server, true, wr, 725, 500, Color.lightGray);
  1239.  
  1240.     this.doc = doc;
  1241.     Font defaultFont = wServer.fonts.getFont("Courier", Font.PLAIN, 14);
  1242.     setDefaultFont(hotjava.dialogFont);
  1243.     setTitle("Source Viewer " + doc.toExternalForm());
  1244.     Window w = new Window(this, "Center", background, 700, 300);
  1245.     w.setLayout(new ColumnLayout(true));
  1246.     t = new TextArea(w, "Center", defaultFont, 80, 24);
  1247.     t.setHFill(true);
  1248.     t.setVFill(true);
  1249.     t.setEditable(false);
  1250.     w = new Window(this,"South",background,700,200);
  1251.     w.setLayout(new ColumnLayout(true));
  1252.     Row row = new Row(w,null,true);
  1253.     new SaveButton(row, this);
  1254.     new DismissButton(row, this);
  1255.     status = new Label("",null, w, defaultFont);
  1256.     status.setHFill(true);
  1257.     map();
  1258.     resize();
  1259.     new Thread(this, "SourceViewer").start();
  1260.     }
  1261.  
  1262.     public void run() {
  1263.     InputStream in = null;
  1264.     try {
  1265.         in = doc.openStream();
  1266.     } catch (FileNotFoundException e) {
  1267.         t.setText("");    // can you say HACK?
  1268.         return;
  1269.     }
  1270.     OutputStreamBuffer out = new OutputStreamBuffer();
  1271.     byte buffer[] = new byte[1024];
  1272.     while (true) {
  1273.         int n = in.read(buffer, 0, buffer.length);
  1274.         if (n < 0) {
  1275.         break;
  1276.         }
  1277.         out.write(buffer, 0, n);
  1278.     }
  1279.     in.close();
  1280.     t.setText(out.toString());
  1281.     }
  1282. }
  1283.  
  1284. class PrintButton extends Button implements Runnable {
  1285.     PrintDialog printDialog;
  1286.  
  1287.     public PrintButton(Container w, PrintDialog f) {
  1288.     super("Print",null, w);
  1289.  
  1290.     printDialog = f;
  1291.     }
  1292.  
  1293.     public void selected(Component c, int pos) {
  1294.     new Thread(this, "Print Dialog").start();
  1295.     }
  1296.  
  1297.     public void run() {
  1298.     OutputStream os;
  1299.     Dimension paper = null;
  1300.     Properties props = printDialog.theWR.props;
  1301.     Object prop;
  1302.     String destType = null;
  1303.     String paperType = null;
  1304.  
  1305.     printDialog.theWR.setMessage("Printing...");
  1306.     prop = props.get("printerName");
  1307.     if (prop == null || !(prop instanceof String)
  1308.         || !((String) prop).equals(printDialog.printerName.getText()))
  1309.         props.put("printerName", printDialog.printerName.getText());
  1310.     prop = props.get("printCommand");
  1311.     if (prop == null || !(prop instanceof String)
  1312.         || !((String) prop).equals(printDialog.commandName.getText()))
  1313.         props.put("printCommand", printDialog.commandName.getText());
  1314.     prop = props.get("printFile");
  1315.     if (prop == null || !(prop instanceof String)
  1316.         || !((String) prop).equals(printDialog.fileName.getText()))
  1317.         props.put("printFile", printDialog.fileName.getText());
  1318.     if (printDialog.useFile.getState()){
  1319.         destType = "file";
  1320.         String file = printDialog.fileName.getText();
  1321.         try {
  1322.         os = (OutputStream) new FileOutputStream(file);
  1323.         } catch (Exception e) {
  1324.         printDialog.unMap();
  1325.         printDialog.theWR.setMessage("Printing: Bad File...Cancelled");
  1326.         return;
  1327.         }
  1328.     } else if (printDialog.useCommand.getState()){
  1329.         destType = "command";
  1330.         String command = printDialog.commandName.getText();
  1331.         os = System.execout(command);
  1332.     } else {
  1333.         String printer;
  1334.         if (printDialog.usePrinter.getState()) {
  1335.         destType = "printer";
  1336.         printer = printDialog.printerName.getText();
  1337.         if (!printer.equals(""))
  1338.             printer = " -d " + printer;
  1339.         } else {
  1340.         // assert(printDialog.useDefault.getState())
  1341.         destType = "default";
  1342.         printer = "";
  1343.         }
  1344.         os = System.execout("lp" + printer);
  1345.     }
  1346.     if (destType != null) {
  1347.         prop = props.get("printDestination");
  1348.         if (prop == null || !(prop instanceof String)
  1349.         || !((String) prop).equals(destType))
  1350.         props.put("printDestination", destType);
  1351.     }
  1352.     if (printDialog.letterSheets.getState()) {
  1353.         paperType = "letter";
  1354.         paper = PSGraphics.Letter;
  1355.     } else if (printDialog.legalSheets.getState()) {
  1356.         paperType = "legal";
  1357.         paper = PSGraphics.Legal;
  1358.     } else if (printDialog.executiveSheets.getState()) {
  1359.         paperType = "executive";
  1360.         paper = PSGraphics.Executive;
  1361.     } else if (printDialog.A4Sheets.getState()) {
  1362.         paperType = "A4";
  1363.         paper = PSGraphics.A4;
  1364.     }
  1365.     if (paperType != null) {
  1366.         prop = props.get("paperType");
  1367.         if (prop == null || !(prop instanceof String)
  1368.         || !((String) prop).equals(paperType))
  1369.         props.put("paperType", paperType);
  1370.     }
  1371.     if (props.changed)
  1372.         props.save();
  1373.  
  1374.     Dimension layout = new Dimension(printDialog.theWin.width,
  1375.                      printDialog.theWin.height);
  1376.     BufferedOutputStream bos = new BufferedOutputStream(os);
  1377.     PSGraphics pg = new PSGraphics(printDialog.theWin, bos,
  1378.                        printDialog.theDoc.getTitle(),
  1379.                        layout, paper);
  1380.     String finalmsg = "Printing...Done";
  1381.     try {
  1382.         printDialog.theWin.print(pg);
  1383.     } catch (Exception e) {
  1384.         e.printStackTrace();
  1385.         finalmsg = "Printing: I/O Error...Cancelled";
  1386.     }
  1387.     try {
  1388.         pg.close();
  1389.     } catch (Exception e) {
  1390.         finalmsg = "Printing: I/O Error...Cancelled";
  1391.     }
  1392.     printDialog.unMap();
  1393.     printDialog.theWR.setMessage(finalmsg);
  1394.     // REMIND: dispose is broken
  1395.     // printDialog.dispose();
  1396.     }
  1397. }
  1398.  
  1399. class DisposeButton extends Button {
  1400.     Frame    theFrame;
  1401.  
  1402.     public DisposeButton(Container w, Frame f) {
  1403.     this(w, f, "Cancel");
  1404.     }
  1405.  
  1406.     public DisposeButton(Container w, Frame f, String label) {
  1407.     super(label, null, w);
  1408.  
  1409.     theFrame = f;
  1410.     }
  1411.  
  1412.     public void selected(Component c, int pos) {
  1413.     theFrame.unMap();
  1414.     // REMIND: dispose is broken
  1415.     // theFrame.dispose();
  1416.     }
  1417. }
  1418.  
  1419. class PrintDialog extends Frame {
  1420.     hotjava theWR;
  1421.     Document theDoc;
  1422.     WRWindow theWin;
  1423.  
  1424.     RadioGroup paperSize = new RadioGroup();
  1425.     Toggle letterSheets;
  1426.     Toggle legalSheets;
  1427.     Toggle executiveSheets;
  1428.     Toggle A4Sheets;
  1429.  
  1430.     RadioGroup destType = new RadioGroup();
  1431.     Toggle useDefault;
  1432.     Toggle usePrinter;
  1433.     Toggle useFile;
  1434.     Toggle useCommand;
  1435.     TextField printerName;
  1436.     TextField fileName;
  1437.     TextField commandName;
  1438.  
  1439.     public PrintDialog(hotjava wr, Document doc) {
  1440.         super(hotjava.server, true, wr, 400, 270, Color.lightGray);
  1441.     setDefaultFont(hotjava.dialogFont);
  1442.     setTitle("Print HotJava Document");
  1443.     theWR = wr;
  1444.     theWin = wr.doc;
  1445.     theDoc = doc;
  1446.  
  1447.         Window w;
  1448.     RowColLayout r;
  1449.     Properties props = theWR.props;
  1450.     Object prop;
  1451.     String propStr;
  1452.  
  1453.     prop = props.get("paperType");
  1454.     if (prop != null && (prop instanceof String))
  1455.         propStr = (String) prop;
  1456.     else
  1457.         propStr = "";
  1458.  
  1459.     w = new Window(this, "Page Sizes", background, 400, 40);
  1460.     r = new RowColLayout(0, 7, true);
  1461.     r.setGaps(0,0,0,0);
  1462.     w.setLayout(r);
  1463.     new Label("Paper Size:", null, w);
  1464.     new Label("", null, w);    // Extra label provides gap before choices.
  1465.     letterSheets = new Toggle("Letter", null, w, paperSize,
  1466.                   propStr.equals("letter"));
  1467.     legalSheets = new Toggle("Legal", null, w, paperSize,
  1468.                  propStr.equals("legal"));
  1469.     executiveSheets = new Toggle("Executive", null, w, paperSize,
  1470.                      propStr.equals("executive"));
  1471.     A4Sheets = new Toggle("A4", null, w, paperSize,
  1472.                   propStr.equals("A4"));
  1473.     if (paperSize.getCurrent() == null)
  1474.         letterSheets.setState(true);
  1475.     w.move(0, 0);
  1476.  
  1477.     prop = props.get("printDestination");
  1478.     if (prop != null && (prop instanceof String))
  1479.         propStr = (String) prop;
  1480.     else
  1481.         propStr = "default";
  1482.     String defPrinter = System.getenv("PRINTER");
  1483.     if (defPrinter == null)
  1484.         defPrinter = "";
  1485.  
  1486.     w = new Window(this, "Destinations Title", background, 400, 30);
  1487.     new Label("Print Destinations", null, w);
  1488.     w.move(0, 40);
  1489.  
  1490.     w = new Window(this, "Default Destination", background, 400, 40);
  1491.     r = new RowColLayout(0, 2, true);
  1492.     r.setGaps(0,0,0,0);
  1493.     w.setLayout(r);
  1494.     useDefault = new Toggle(" System Default Printer:  " + defPrinter,
  1495.                 null, w, destType, propStr.equals("default"));
  1496.     w.move(0, 70);
  1497.  
  1498.     w = new Window(this, "Other Destinations", background, 400, 120);
  1499.     r = new RowColLayout(0, 2, true);
  1500.     r.setGaps(0,0,0,4);
  1501.     w.setLayout(r);
  1502.  
  1503.     usePrinter = new Toggle("Printer:", null, w, destType,
  1504.                 propStr.equals("printer"));
  1505.     prop = props.get("printerName");
  1506.     if (prop == null || !(prop instanceof String))
  1507.         prop = defPrinter;
  1508.     printerName = new TextField((String) prop, null, w, true);
  1509.  
  1510.     useFile = new Toggle("File:", null, w, destType,
  1511.                  propStr.equals("file"));
  1512.     prop = props.get("printFile");
  1513.     if (prop == null || !(prop instanceof String))
  1514.         prop = (Object) "/tmp/";
  1515.     fileName = new TextField((String) prop, null, w, true);
  1516.  
  1517.     useCommand = new Toggle(" Command:", null, w, destType,
  1518.                 propStr.equals("command"));
  1519.     prop = props.get("printCommand");
  1520.     if (prop == null || !(prop instanceof String))
  1521.         prop = (Object) "lp";
  1522.     commandName = new TextField((String) prop, null, w, true);
  1523.  
  1524.     if (destType.getCurrent() == null)
  1525.         useDefault.setState(true);
  1526.     w.move(0, 110);
  1527.  
  1528.     w = new Window(this, "Buttons", background, 400, 40);
  1529.     new PrintButton(w, this);
  1530.     new DisposeButton(w, this);
  1531.     w.move(0, 230);
  1532.  
  1533.     resize();
  1534.     }
  1535. }
  1536.  
  1537. class PropertySheet extends Frame {
  1538.     public PropertySheet(hotjava wr) {
  1539.     super(hotjava.server, true, wr, 500, 446, Color.lightGray);
  1540.     setDefaultFont(hotjava.dialogFont);
  1541.     setTitle("HotJava Properties");
  1542.     mw = wr;
  1543.  
  1544.     RowColLayout    r;
  1545.     Window        w;
  1546.     int        h;
  1547.     String        acl;
  1548.     String path = System.getenv("HOME") + File.separator +
  1549.         ".hotjava" + File.separator + "properties";
  1550.     File wpath = new File(System.getenv("HOME") +
  1551.                   File.separator + ".hotjava");
  1552.  
  1553.  
  1554.     wpath.mkdir();
  1555.     propFile = new File(path);
  1556.     w = new Window(this,"Center", background, 300, 130);
  1557.     r = new RowColLayout(0, 2, true);
  1558.     r.setGaps(0,0,0,0);
  1559.     w.setLayout(r);
  1560.  
  1561.     // XXX: this layout needs fixing...
  1562.  
  1563.     fProxyToggle = new Toggle("Firewall Proxy","proxy",w,
  1564.                   HttpClient.useProxyForFirewall);
  1565.     new Label("Port",null, w);
  1566.     fProxyField = new TextField(HttpClient.firewallProxyHost,
  1567.                     null,w,true);
  1568.     fProxyPort = new TextField("" + HttpClient.firewallProxyPort,
  1569.                    null,w,true);
  1570.  
  1571.     ftpProxyToggle = new Toggle("FTP Proxy",
  1572.                     null,w,FtpClient.useFtpProxy);
  1573.     new Label("Port",null, w);
  1574.     
  1575.     ftpProxyField = new TextField(FtpClient.ftpProxyHost,
  1576.                     null,w,true);
  1577.     ftpProxyPort = new TextField("" + FtpClient.ftpProxyPort,
  1578.                      null,w,true);
  1579.  
  1580.     cProxyToggle = new Toggle("Caching Proxy",null,w,
  1581.                   HttpClient.useProxyForCaching);
  1582.     new Label("Port",null, w);
  1583.     cProxyField = new TextField(HttpClient.cachingProxyHost,
  1584.                     null,w,true);
  1585.     cProxyPort = new TextField("" + HttpClient.cachingProxyPort,
  1586.                    null,w,true);
  1587.  
  1588.  
  1589.     new Label("Read Path:",null,w);
  1590.     acl = File.getReadACL();
  1591.     new TextField(acl,null,w,false);
  1592.     new Label("Write Path:",null,w);
  1593.     acl = File.getWriteACL();
  1594.     new TextField(acl,null,w,false);
  1595.     //new Label("Delay Image loading:","dil",w);
  1596.     new Label("Underline anchors:",null,w);
  1597.     ulField = new Toggle("", null,w,WRTextItem.underlineAnchors);
  1598.     new Label("Delay image loading:",null,w);
  1599.     dilField = new Toggle("", null,w,WRWindow.delayImageLoading);
  1600.     new Label("Delay applet loading:",null,w);
  1601.     dalField = new Toggle("", null,w,WRWindow.delayAppletLoading);
  1602.     w = new Window(this,"South",background,300,50);
  1603.     new ApplyButton(w, this);
  1604.     new PropertiesDismissButton(w, this, wr);
  1605.  
  1606.     errorDialog = new MessageDialog(this, "Error", null,
  1607.                     MessageDialog.ERROR_TYPE, 1, true,
  1608.                     null, null, null, null);
  1609.     }
  1610.  
  1611.     void setAllValues() {
  1612.     ulField.setState(WRTextItem.underlineAnchors);
  1613.     dilField.setState(mw.doc.delayImageLoading);
  1614.     dalField.setState(mw.doc.delayAppletLoading);
  1615.         
  1616.     fProxyToggle.setState(HttpClient.useProxyForFirewall);
  1617.     fProxyField.setText(HttpClient.firewallProxyHost);
  1618.     fProxyPort.setText(HttpClient.firewallProxyPort+"");
  1619.     
  1620.     cProxyToggle.setState(HttpClient.useProxyForCaching);
  1621.     cProxyField.setText(HttpClient.cachingProxyHost);
  1622.     cProxyPort.setText(HttpClient.cachingProxyPort+"");
  1623.  
  1624.     ftpProxyToggle.setState(FtpClient.useFtpProxy);
  1625.     ftpProxyField.setText(FtpClient.ftpProxyHost);
  1626.     ftpProxyPort.setText(FtpClient.ftpProxyPort+"");
  1627.     }
  1628.     
  1629.     void show() {
  1630.     setAllValues();
  1631.     map();
  1632.     resize();
  1633.     }
  1634.     
  1635.     hotjava        mw;
  1636.  
  1637.     TextField        fProxyField;
  1638.     TextField        fProxyPort;
  1639.     Toggle        fProxyToggle;
  1640.  
  1641.     TextField        cProxyField;
  1642.     TextField        cProxyPort;
  1643.     Toggle        cProxyToggle;
  1644.  
  1645.     Toggle        ftpProxyToggle;    
  1646.     TextField        ftpProxyField;
  1647.     TextField        ftpProxyPort;
  1648.  
  1649.     File        propFile;
  1650.     Toggle        ulField;
  1651.     Toggle        dilField;
  1652.     Toggle        dalField;
  1653.  
  1654.     MessageDialog    errorDialog;
  1655. }
  1656.  
  1657. class OpenButton extends Button {
  1658.     public OpenButton(Container w,  OpenDialog d, hotjava mw) {
  1659.     super("Open",null, w);
  1660.     target = mw;
  1661.     dialog = d;
  1662.     }
  1663.     public void selected(Component c, int pos) {
  1664.     dialog.unMap();
  1665.     target.doc.pushURL(new URL(null, dialog.urlField.getText()));
  1666.     }
  1667.  
  1668.     hotjava target;
  1669.     OpenDialog    dialog;
  1670. }
  1671.  
  1672. class OpenTextField extends TextField {
  1673.     hotjava target;
  1674.  
  1675.     OpenTextField(Window w, hotjava mw) {
  1676.     super("",null,w,true);
  1677.     target = mw;
  1678.     }
  1679.  
  1680.     public void selected() {
  1681.     target.doc.pushURL(new URL(null, getText()));
  1682.     }
  1683. }
  1684.  
  1685. class OpenDialog extends Frame {
  1686.     TextField    urlField;
  1687.  
  1688.     public OpenDialog(WServer server, hotjava w) {
  1689.     super(server, true, w, 400, 120, Color.lightGray);
  1690.     setTitle("Open URL...");
  1691.     setDefaultFont(hotjava.dialogFont);
  1692.     Window cw = new Window(this, "Center", background, 300, 100);
  1693.     urlField = new OpenTextField(cw,w);
  1694.     urlField.setHFill(true);
  1695.     new OpenButton(cw, this, w);
  1696.     new DismissButton(cw, this);
  1697.     }
  1698. }
  1699.  
  1700. class HotListItem {
  1701.     public String    url;
  1702.     public boolean    inMenu;
  1703.     public MenuItem    menuItem;
  1704.  
  1705.     public HotListItem(String url, boolean inMenu) {
  1706.     this.url = url;
  1707.     this.inMenu = inMenu;
  1708.     }
  1709.  
  1710.     public String toString() {
  1711.     String m;
  1712.  
  1713.     if (menuItem != null) {
  1714.         m = "<menuitem>";
  1715.     } else {
  1716.         m = null;
  1717.     }
  1718.         
  1719.     return "HotListItem[" + url + ", " + inMenu + ", " + m + "]";
  1720.     }
  1721. }
  1722.  
  1723. class MenuToggle extends Toggle {
  1724.     HotList target;
  1725.  
  1726.     public MenuToggle(Container parent, HotList target) {
  1727.     super("In Goto Menu",null,parent, false);
  1728.     this.target = target;
  1729.     }
  1730.  
  1731.     public void selected() {
  1732.     target.changeMenuStatus(getState(), target.selectedItem);
  1733.     }
  1734. }
  1735.  
  1736. class HotList extends Frame implements ChoiceHandler {
  1737.     String        hName;
  1738.     String        home;
  1739.     File        hotlist;
  1740.     Window        cw;
  1741.     int            selectedItem;
  1742.     HotlistGotoButton    gotoButton;
  1743.     List        slist;
  1744.     Vector        urlList;
  1745.     Vector        inMenuList;
  1746.     hotjava        mw;
  1747.     TextField        urlValue;
  1748.     Toggle        inMenuToggle;
  1749.  
  1750.     public HotList(WServer server, hotjava w) {
  1751.     super(server, true, w, 300, 400, Color.lightGray);
  1752.     setTitle("HotJava Hotlist");
  1753.     setDefaultFont(hotjava.dialogFont);
  1754.  
  1755.     Label l;
  1756.  
  1757.     mw = w;
  1758.     cw = new Window(this, "Center", background, 300, 200);
  1759.     cw.setLayout(new ColumnLayout(true));
  1760.     slist = new List(cw,this,null, 10, false);
  1761.     slist.setHFill(true);
  1762.     slist.setVFill(true);
  1763.     urlList = new Vector();
  1764.     inMenuList = new Vector();
  1765.     readHotList("default");
  1766.     cw = new Window(this, "South", background, 300, 100);
  1767.     cw.setLayout(new ColumnLayout(true));
  1768.  
  1769.     new Label("URL:", null, cw);
  1770.     urlValue = new TextField("",null,cw, false);
  1771.     urlValue.setHFill(true);
  1772.  
  1773.     Row row = new Row(cw, null, true);
  1774.     inMenuToggle = new MenuToggle(row,this);
  1775.  
  1776.     row = new Row(cw, null, true);
  1777.     gotoButton = new HotlistGotoButton(row, this);
  1778.     new DeleteButton(row, this);
  1779.     new DismissButton(row, this);
  1780.     selectedItem = 0;
  1781.     }
  1782.  
  1783.     /**
  1784.      * Change whether the given item is in the Goto menu or not.
  1785.      */
  1786.     public void changeMenuStatus(boolean inMenu, int index) {
  1787.     HotListItem hItem = (HotListItem)urlList.elementAt(index);
  1788.     String        title = slist.itemAt(index);
  1789.  
  1790.     if (hItem.inMenu == inMenu) {
  1791.         return;
  1792.     }
  1793.     if (inMenu) {
  1794.         hItem.menuItem = mw.gotoMenu.addHotItem(title, hItem.url);
  1795.     } else {
  1796.         if (hItem.menuItem != null) {
  1797.         hItem.menuItem.dispose();
  1798.         }
  1799.     }
  1800.     hItem.inMenu = inMenu;
  1801.     if (index == selectedItem && inMenu != inMenuToggle.getState()) {
  1802.         inMenuToggle.setState(inMenu);
  1803.     }
  1804.     write();
  1805.     }
  1806.  
  1807.     /**
  1808.      * Add an item to the hotlist
  1809.      */
  1810.     public void addItem(String title,
  1811.             String url,
  1812.             boolean inMenu,
  1813.             boolean checkMenu) {
  1814.     HotListItem    prev;
  1815.     int        i;
  1816.     int        nitems = urlList.size();
  1817.  
  1818.     for (i=0; i < nitems; i++) {
  1819.         prev = (HotListItem)urlList.elementAt(i);
  1820.         if (prev.url.equals(url)) {
  1821.         if (checkMenu) {
  1822.             changeMenuStatus(inMenu, i);
  1823.         }
  1824.         return;
  1825.         }
  1826.     }
  1827.     
  1828.     if (title.length() == 0) {
  1829.         title = "Untitled (" + url + ")";
  1830.     }
  1831.     slist.addItem(title);
  1832.     urlList.addElement(prev = new HotListItem(url, false));
  1833.     if (checkMenu && inMenu) {
  1834.         prev.inMenu = inMenu;
  1835.         prev.menuItem = mw.gotoMenu.addHotItem(title, url);
  1836.     }
  1837.     write();
  1838.     }
  1839.  
  1840.     /**
  1841.      * write out this hotlist.
  1842.      */
  1843.     public void write() {
  1844.     FileOutputStream    outStr;
  1845.     PrintStream        pStr;
  1846.     int i;
  1847.     int nitems = urlList.size();
  1848.     File    hfile;
  1849.     HotListItem    hItem;
  1850.  
  1851.     hfile = new File(hotlist.getParent());
  1852.     hfile.mkdir();
  1853.     outStr = new FileOutputStream(hotlist);
  1854.     pStr = new PrintStream(outStr);
  1855.     pStr.println("hotjava-hotlist-version-1");
  1856.     pStr.println(hName);
  1857.     for (i = 0; i < nitems; i++) {
  1858.         hItem = (HotListItem)urlList.elementAt(i);
  1859.  
  1860.         if (hItem.inMenu) {
  1861.         pStr.println(hItem.url + " inMenu");
  1862.         } else {
  1863.         pStr.println(hItem.url);
  1864.         }
  1865.         pStr.println(slist.itemAt(i));
  1866.     }
  1867.     outStr.close();
  1868.     }
  1869.  
  1870.     /**
  1871.      * Delete the given item from the hotlist.  Assumes item is the
  1872.      * current one selected, so clears the URL value.
  1873.      */
  1874.     public void delete(int item) {
  1875.     HotListItem    hItem = (HotListItem)urlList.elementAt(item);
  1876.     slist.delItem(item);
  1877.     
  1878.     if (hItem.inMenu && hItem.menuItem != null) {
  1879.         hItem.menuItem.dispose();
  1880.     }
  1881.     urlList.removeElementAt(item);
  1882.     urlValue.setText("");
  1883.     write();
  1884.     }
  1885.  
  1886.     public void readHotList(String name) {
  1887.     FileInputStream    fstream;
  1888.     String        hlPath;
  1889.   
  1890.     hlPath = System.getenv("HOME") + File.separator + ".hotjava" +
  1891.         File.separator + "hotlist-" + name;
  1892.     hName = name;
  1893.     try {
  1894.         hotlist = new File(hlPath);
  1895.         fstream = new FileInputStream(hotlist);
  1896.     } catch (Exception e) {
  1897.         try {
  1898.         hotlist = new File(System.getenv("HOME") + File.separator + ".mosaic-hotlist-default");
  1899.         fstream = new FileInputStream(hotlist);
  1900.         } catch (Exception ee) {
  1901.         return;
  1902.         }
  1903.     }
  1904.     DataInputStream    dis = new DataInputStream(fstream);
  1905.     String    url;
  1906.     String    title;
  1907.  
  1908.     /* read version number and stupid line after it */
  1909.     dis.readLine();
  1910.     dis.readLine();
  1911.  
  1912.     try {
  1913.         while (true) {
  1914.         url = dis.readLine();
  1915.         title = dis.readLine();
  1916.         if (url == null || title == null) {
  1917.             break;
  1918.         }
  1919.         int    separator = url.indexOf(' ');
  1920.         boolean putInMenu = false;
  1921.  
  1922.         if (separator != -1) {
  1923.             if (url.substring(separator).startsWith(" inMenu")) {
  1924.             putInMenu = true;
  1925.             }
  1926.             url = url.substring(0, separator);
  1927.         }
  1928.  
  1929.         HotListItem    item = new HotListItem(url, putInMenu);
  1930.  
  1931.         urlList.addElement(item);
  1932.         slist.addItem(title);
  1933.         if (putInMenu) {
  1934.             item.menuItem = mw.gotoMenu.addHotItem(title, item.url);
  1935.         }
  1936.         }
  1937.     } finally {
  1938.         fstream.close();
  1939.     }
  1940.     hotlist = new File(hlPath);
  1941.     }
  1942.     
  1943.     public void selected(Component c, int pos) {
  1944.     HotListItem hItem;
  1945.     selectedItem = pos;
  1946.     hItem = (HotListItem)urlList.elementAt(pos);
  1947.     inMenuToggle.setState(hItem.inMenu);
  1948.     urlValue.setText(hItem.url);
  1949.     }
  1950.  
  1951.     public void doubleClick(Component c, int pos) {
  1952.     selectedItem = pos;
  1953.     gotoButton.selected(c, pos);
  1954.     }
  1955. }
  1956.  
  1957.  
  1958. class HelpMenu extends Menu {
  1959.     hotjava mw;
  1960.  
  1961.     static String topics[] = {
  1962.     "doc:readme.html",
  1963.     "doc:copyright.html",
  1964.  
  1965.     "doc:index.html",
  1966.     "doc:/doc/misc/using.html",
  1967.     "http://java.sun.com/",
  1968.     "doc:demo/index.html",
  1969.     "doc:/doc/misc/people.html",
  1970.     "doc:/doc/misc/BugReport.html",
  1971.     "doc:/doc/misc/Register.html",
  1972.  
  1973.     "doc:/doc/",
  1974.     "doc:/doc/misc/JavaSearchHelp.html"
  1975.     };
  1976.     
  1977.     public HelpMenu(MenuBar mbar, hotjava w) {
  1978.     super("Help", mbar);
  1979.  
  1980.     mw = w;
  1981.     MenuItem    item;
  1982.  
  1983.     new MenuItem("README!", this);
  1984.     new MenuItem("Copyright and License", this);
  1985.  
  1986.     addSeparator();
  1987.     new MenuItem("About HotJava", this);
  1988.     new MenuItem("Using HotJava", this);
  1989.     new MenuItem("Latest HotJava Info", this);
  1990.     new MenuItem("HotJava Demos", this);
  1991.     new MenuItem("Meet the People", this);
  1992.     addSeparator();
  1993.     new MenuItem("Submit a Bug Report", this);
  1994.     new MenuItem("Register", this);
  1995.  
  1996.     addSeparator();
  1997.     new MenuItem("HotJava Documentation", this);
  1998.     new MenuItem("How to Search the Documentation", this);
  1999.     new MenuItem("Search HotJava Documentation...", this);
  2000.     }
  2001.     
  2002.     public void selected(int index) {
  2003.         if (index >= topics.length) {
  2004.             if (mw.searchWindow == null) {
  2005.         mw.searchWindow = new SearchWindow(mw, mw.server);
  2006.             } 
  2007.         mw.searchWindow.map();
  2008.             mw.searchWindow.resize();
  2009.         } else {
  2010.             mw.doc.pushURL(new URL(null, topics[index]));
  2011.         }
  2012.     }
  2013. }
  2014.  
  2015. class UrlField extends TextField {
  2016.     public UrlField(String value, Container parent, hotjava w) {
  2017.     super(value, null, parent, true);
  2018.     setColor(Color.black);    
  2019.     setFont(hotjava.inputFont);
  2020.     mw = w;
  2021.     }
  2022.     public void selected() {
  2023.     mw.doc.pushURL(new URL(null, getText()));
  2024.     }
  2025.  
  2026.     hotjava mw;
  2027. }
  2028.  
  2029. class InfoWindow extends Window {
  2030.  
  2031.     Label    urlTitle;
  2032.     TextField    urlField;
  2033.  
  2034.     final int sepBarHeight = 2;
  2035.  
  2036.     public InfoWindow(hotjava hj) {
  2037.     super(hj, "North", hj.background, 100, 10);
  2038.     setLayout(new RowLayout(true));
  2039.     
  2040.     Column col = new Column(this, null, false);
  2041.     new Space(col, null, 10, 3, false, false);
  2042.     urlTitle = new Label("Document URL:", null, col, hotjava.labelFont);
  2043.     urlTitle.setColor(hotjava.blue);
  2044.     urlField = new UrlField("", this, hj);
  2045.     urlField.setHFill(true);
  2046.  
  2047.     }
  2048.  
  2049.     public void paint() {
  2050.     paint3DRect(0, height - sepBarHeight, width, sepBarHeight, false, true);
  2051.     }
  2052. }
  2053.  
  2054.  
  2055. class FindHandler implements DialogHandler {
  2056.  
  2057.     /** The HotJava in which we reside. */
  2058.     hotjava wr;
  2059.     
  2060.     /** The document window we're leaching off of. */
  2061.     WRWindow docWin;
  2062.  
  2063.     /** Where we should start (or resume) searching from. */
  2064.     int fromPos = 0;
  2065.  
  2066.     FindHandler(hotjava runner) {
  2067.     wr = runner;
  2068.     docWin = runner.doc;
  2069.     }
  2070.     
  2071.     public void okCallback(Dialog m) {
  2072.     String text = ""; //docWin.document().getText();
  2073.     StringDialog sd = (StringDialog)m;
  2074.     String lookFor = sd.getText();
  2075.  
  2076.     int index = text.indexOf(lookFor, fromPos);
  2077.     if (index != -1) {
  2078.         docWin.scrollToTextPosition(index);
  2079.         wr.setMessage("Found '"+lookFor+"' at character "+index+".");
  2080.         fromPos = index + 1;
  2081.     } else {
  2082.         String msg = "Not found.  Start again from beginning?";
  2083.         MessageDialog md = new MessageDialog(sd, "Not found", msg,
  2084.                          MessageDialog.QUESTION_TYPE,
  2085.                          2, true, null, null, null,
  2086.                          null);
  2087.         boolean startOver = (md.show() == 1); // user pressed OK button
  2088.         if (startOver) {
  2089.         fromPos = 0;
  2090.         docWin.scrollToTextPosition(0);
  2091.         // do some sort of highlighting here, when possible.
  2092.         } else {
  2093.         sd.hide();
  2094.         }
  2095.     }
  2096.  
  2097.     // now change message to "find again" and let user do it again
  2098.     sd.setTitle("Find again");
  2099.     }
  2100.     
  2101.     /** Invoked when the user presses the "Cancel" button. */
  2102.     public void cancelCallback(Dialog m) {
  2103.     m.hide();
  2104.     }
  2105.  
  2106.     /** Invoked when the user presses the "Help" button. */
  2107.     public void helpCallback(Dialog m) {
  2108.     }
  2109. }
  2110.  
  2111.  
  2112. class HistoryItem {
  2113.     URL url;
  2114.     String title;
  2115.  
  2116.     HistoryItem(URL url, String title) {
  2117.     this.url = url;
  2118.     this.title = title;
  2119.     }
  2120. }
  2121.  
  2122.  
  2123. class HistoryWindow extends Frame implements ChoiceHandler, Runnable {
  2124.  
  2125.     hotjava       wRunner;
  2126.     TextField      urlValue;
  2127.     HistoryVector historyVec;
  2128.     int           lastUpdated;
  2129.  
  2130.     int          selectedItem;
  2131.  
  2132.     List      scrollingList;
  2133.     Vector      urlList;
  2134.  
  2135.     public synchronized void newElement() {
  2136.     notify();
  2137.     }
  2138.     
  2139.     public synchronized void run() {
  2140.     while (true) {
  2141.         wait();
  2142.  
  2143.         int time = historyVec.getTimeStamp();
  2144.         if (mapped && (lastUpdated != time)) {
  2145.         stickHistoryOnList();
  2146.         lastUpdated = time;
  2147.         }
  2148.     }
  2149.     }
  2150.  
  2151.     public HistoryWindow(WServer server, hotjava w, HistoryVector history) {
  2152.     super(server, true, w, 300, 400, Color.lightGray);
  2153.     setTitle(hotjava.programName+" History");
  2154.     setDefaultFont(hotjava.dialogFont);
  2155.     
  2156.     historyVec = history;
  2157.     urlList = new Vector();
  2158.  
  2159.     Label l;
  2160.     Window cw;
  2161.  
  2162.     cw = new Window(this, "Center", background, 300, 350);
  2163.     cw.setLayout(new ColumnLayout(true));
  2164.     scrollingList = new List(cw, this, "", 14, false, false);
  2165.     scrollingList.setHFill(true);
  2166.     scrollingList.setVFill(true);
  2167.  
  2168.     cw = new Window(this, "South", background, 300, 50);
  2169.     cw.setLayout(new ColumnLayout(true));
  2170.  
  2171.     urlValue = new TextField("destination URL", "urlValue", cw, false);
  2172.     urlValue.setHFill(true);
  2173.  
  2174.     Row row = new Row(cw, null, true);
  2175.     new HistoryGotoButton(row, this);
  2176.     new DismissButton(row, this);
  2177.  
  2178.     selectedItem = 0;
  2179.     wRunner = w;
  2180.  
  2181.     Thread th = new Thread(this);
  2182.     th.setName("History Updater");
  2183.     th.start();
  2184.     }
  2185.  
  2186.     private void showURL(int pos) {
  2187.     URL url = (URL)urlList.elementAt(pos);
  2188.     urlValue.setText(url.toExternalForm());
  2189.     }    
  2190.  
  2191.     public void selected(Component c, int pos) {
  2192.     selectedItem = pos;
  2193.     showURL(selectedItem);
  2194.     }
  2195.  
  2196.     public void doubleClick(Component c, int pos) {
  2197.     selectedItem = pos;
  2198.     gotoDocument();
  2199.     }
  2200.  
  2201.     public void showWindow() {
  2202.     map();
  2203.     resize();
  2204.     wServer.sync();
  2205.     int time = historyVec.getTimeStamp();
  2206.     if (lastUpdated != time) {
  2207.         stickHistoryOnList();
  2208.         lastUpdated = time;
  2209.     }
  2210.     }
  2211.  
  2212.  
  2213.     public void gotoDocument() {
  2214.     wRunner.doc.pushURL((URL)urlList.elementAt(selectedItem));
  2215.     }
  2216.     
  2217.     public void stickHistoryOnList() {
  2218.     scrollingList.clear();
  2219.     urlList.removeAllElements();
  2220.  
  2221.     for (int i = 0; i < historyVec.size(); i++) {
  2222.         HistoryItem dInfo = (HistoryItem)historyVec.elementAt(i);
  2223.         URL url = dInfo.url;
  2224.         String title = dInfo.title;
  2225.         
  2226.         if (title == null || title.length() == 0) {
  2227.         title = hotjava.untitledTitle+" ("+url.toExternalForm()+")";
  2228.         }
  2229.         
  2230.         scrollingList.addItem(title);
  2231.         urlList.addElement(url);
  2232.     }
  2233.  
  2234.     if (historyVec.size() > 0) {
  2235.         int showItem = historyVec.getCurrent();
  2236.         scrollingList.makeVisible(showItem);
  2237.         scrollingList.select(showItem);
  2238.         showURL(showItem);
  2239.     }
  2240.     }
  2241. }
  2242.  
  2243.  
  2244. class HistoryGotoButton extends Button {
  2245.  
  2246.     public HistoryGotoButton(Container w, HistoryWindow hw) {
  2247.     super("Visit", null, w);
  2248.     histWin = hw;
  2249.     }
  2250.     
  2251.     public void selected(Component c, int pos) {
  2252.     histWin.gotoDocument();
  2253.     }
  2254.  
  2255.     HistoryWindow    histWin;
  2256. }
  2257.