home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 May / PCW596.iso / wtest / clico / sunsoft / java / solaris.lzh / SOLARIS.TAZ / SOLARIS / hotjava / classsrc / browser / hotjava.java < prev    next >
Encoding:
Java Source  |  1995-05-15  |  55.3 KB  |  2,258 lines

  1. /*
  2.  * @(#)hotjava.java    1.181 95/05/15 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.181, 15 May 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);
  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.     new MenuItem("Print...", this);
  773.     viewSourceItem = new MenuItem("View Source...", this);
  774.     viewSourceItem.disable();
  775.     item = new MenuItem("Close", this);
  776.     item.disable();
  777.     new MenuItem("Quit", this);
  778.     enabled = true;
  779.     }
  780.     
  781.     public void selected(int index) {
  782.     int    height;
  783.     int    width;
  784.     String  args[];
  785.  
  786.     switch (index) {
  787.       case 0: // New
  788.         args = new String[1];
  789.         args[0] = mw.urlSpec;
  790.         new hotjava(hotjava.server, args);
  791.         break;
  792.       case 1: // Open
  793.         if (openDialog == null) {
  794.         openDialog = new OpenDialog(hotjava.server, mw);
  795.         }
  796.         openDialog.map();
  797.         break;
  798.       case 2: // Reload
  799.         mw.doc.reload();
  800.         break;
  801.       case 3: // Save
  802.         break;
  803.       case 4: // Save As
  804.         break;
  805.       case 5: // Print...
  806.         if (printDialog == null) {
  807.         printDialog = new PrintDialog(mw, mw.doc.document());
  808.         }
  809.         printDialog.map();
  810.         break;
  811.       case 6: // View Source...
  812.         new SourceViewer(mw, mw.doc.document().thisURL);
  813.         break;
  814.       case 7: // Close Window
  815.         hotjava.copiesRunning--;
  816.         if (hotjava.copiesRunning > 0) {
  817.         // XXX: should actually be destroying the window and
  818.         // recovering resources...
  819.         mw.unMap();
  820.         break;
  821.         }
  822.         // else fall into quit case
  823.       case 8: // Quit
  824.         System.exit(0);
  825.         break;
  826.       default:
  827.         break;
  828.     }
  829.     }
  830.  
  831.     hotjava        mw;
  832.     private boolean    enabled;
  833. }
  834.  
  835. class OptionsMenu extends Menu {
  836.     hotjava         mw;
  837.     MenuItem        showToggle;
  838.     PropertySheet    propSheet = null;
  839.  
  840.     public OptionsMenu(MenuBar mbar, hotjava w) {
  841.     super("Options", mbar);
  842.  
  843.     mw = w;
  844.  
  845.     MenuItem    item;
  846.  
  847.     item = new MenuItem("Font", this);
  848.     item.disable();
  849.     item = new MenuItem("Color", this);
  850.     item.disable();
  851.     new MenuItem("Security...", this);
  852.     new MenuItem("Properties...", this);
  853.     new MenuItem("Flush Cache", this);
  854.     new MenuItem("Progress Monitor", this);
  855.     }
  856.     public void selected(int index) {
  857.     boolean    st;
  858.  
  859.     switch (index) {
  860.       case 2: // Security...
  861.         hotjava.sDialog.map();
  862.         hotjava.sDialog.resize();
  863.         break;
  864.       case 3: // Properties...
  865.         if (propSheet == null) {
  866.         propSheet = new PropertySheet(mw);
  867.         }
  868.         propSheet.show();
  869.         break;
  870.       case 4: // Flush Cache
  871.         ImageCache.flush();
  872.         browser.audio.AudioData.flushCache();
  873.         break;
  874.       case 5: // Progress
  875.         hotjava.pDialog.map();
  876.         hotjava.pDialog.resize();
  877.         break;
  878.       default:
  879.         break;
  880.     }
  881.     }
  882. }
  883.  
  884. class HotlistMenuItem extends MenuItem {
  885.     String url;
  886.     hotjava mw;
  887.  
  888.     public HotlistMenuItem(String title, String url, Menu parent,
  889.                hotjava mw) {
  890.     super(title, parent);
  891.     this.url = url;
  892.     this.mw = mw;
  893.     }
  894.     public void selected() {
  895.     mw.doc.pushURL(new URL(null, url));
  896.     }
  897. }
  898.  
  899. class GoToMenu extends Menu {
  900.     hotjava mw;
  901.  
  902.     public GoToMenu(MenuBar mbar, hotjava w) {
  903.     super("Goto", mbar);
  904.     mw = w;
  905.     new MenuItem("Add Current", this);
  906.     addSeparator();    
  907.     }
  908.  
  909.     public void selected(int index) {
  910.     switch (index) {
  911.       case 0:
  912.         mw.hlist.addItem(mw.pageTitle,
  913.                  mw.infoWindow.urlField.getText(),
  914.                  true,
  915.                  true);
  916.         break;
  917.       default:
  918.         break;
  919.     }
  920.     }
  921.  
  922.     public HotlistMenuItem addHotItem(String title, String url) {
  923.     if ((title == null) || (title.length() == 0)) {
  924.         title = hotjava.untitledTitle+" (" + url + ")";
  925.     }
  926.     return new HotlistMenuItem(title, url, this, mw);
  927.     }
  928. }
  929.  
  930.  
  931. class NavigateMenu extends Menu {
  932.     hotjava    mw;
  933.     boolean    addedSeparator = false;
  934.  
  935.     public NavigateMenu(MenuBar mbar, hotjava w) {
  936.     super("Navigate", mbar);
  937.  
  938.     mw = w;
  939.     MenuItem    item;
  940.  
  941.     new MenuItem("Forward", this);
  942.     new MenuItem("Back", this);
  943.     new MenuItem("Home", this);
  944.     addSeparator();
  945.     new MenuItem("Show History...", this);
  946.     addSeparator();
  947.     new MenuItem("Add Current to Hotlist", this);
  948.     new MenuItem("Show Hotlist...", this);
  949.     addSeparator();
  950.     (new MenuItem("Find...", this)).disable();
  951.     }
  952.  
  953.     public void selected(int index) {
  954.     String urlstring;
  955.  
  956.     switch (index) {
  957.       case 0:
  958.         // Forward
  959.         mw.doc.forward();
  960.         break;
  961.       case 1:
  962.         // Back
  963.         mw.doc.backup();
  964.         break;
  965.       case 2:
  966.         // Home
  967.         mw.goHome();
  968.         break;
  969.       case 3:
  970.         // History
  971.         mw.histWindow.showWindow();
  972.         break;
  973.       case 4:
  974.         // Add Current to HotList
  975.         mw.hlist.addItem(mw.pageTitle,
  976.                  mw.infoWindow.urlField.getText(),
  977.                  false,
  978.                  false);
  979.         break;
  980.       case 5:
  981.         // Show HotList
  982.         mw.hlist.map();
  983.         mw.hlist.resize();
  984.         mw.hlist.wServer.sync();
  985.         break;
  986.       case 6:
  987.         mw.findDialog.setHandler(new FindHandler(mw));
  988.         mw.findDialog.show();
  989.       default:
  990.         break;
  991.     }
  992.     }
  993. }
  994.  
  995. class HotlistGotoButton extends Button {
  996.     public HotlistGotoButton(Container w, HotList hl) {
  997.     super("Visit","", w);
  998.     hlist = hl;
  999.     }
  1000.     public void selected(Component c, int pos) {
  1001.     HotListItem    hItem = (HotListItem)hlist.urlList.elementAt(hlist.selectedItem);
  1002.  
  1003.     hlist.mw.doc.pushURL(new URL(null, hItem.url));
  1004.     }
  1005.  
  1006.     HotList    hlist;
  1007. }
  1008.  
  1009. class DismissButton extends Button {
  1010.  
  1011.     public DismissButton(Container w, Frame f) {
  1012.     this(w, f, "Cancel");
  1013.     }
  1014.     
  1015.     public DismissButton(Container w, Frame f, String label) {
  1016.     super(label, null, w);
  1017.  
  1018.     frame = f;
  1019.     }
  1020.     
  1021.     public void selected(Component c, int pos) {
  1022.     frame.unMap();
  1023.     }
  1024.  
  1025.     Frame    frame;
  1026. }
  1027.  
  1028. class PropertiesDismissButton extends Button {
  1029.     hotjava      wr;
  1030.     PropertySheet props;
  1031.  
  1032.     public PropertiesDismissButton(Container w,
  1033.                    PropertySheet f,
  1034.                    hotjava wr) {
  1035.     super("Cancel", null, w);
  1036.     this.wr = wr;
  1037.     this.props = f;
  1038.     }
  1039.     
  1040.     public void selected(Component c, int pos) {
  1041.     wr.readProperties();
  1042.     props.setAllValues();
  1043.     props.unMap();
  1044.     }
  1045. }
  1046.  
  1047. class DeleteButton extends Button {
  1048.     public DeleteButton(Container w, HotList hl) {
  1049.     super("Delete",null,w);
  1050.     hlist = hl;
  1051.     }
  1052.     public void selected(Component c, int pos) {
  1053.     hlist.delete(hlist.selectedItem);
  1054.     }
  1055.  
  1056.     HotList    hlist;
  1057. }
  1058.  
  1059. class ApplyButton extends Button {
  1060.     public ApplyButton(Container w, PropertySheet f) {
  1061.     super("Apply",null, w);
  1062.  
  1063.     propSheet = f;
  1064.     }
  1065.  
  1066.     private void portError(String wouldBeNumber, String portName) {
  1067.     MessageDialog error = propSheet.errorDialog;
  1068.     
  1069.     error.setMessage("'"+wouldBeNumber+"' is not a valid "+portName+
  1070.                  " port number.  Try again.");
  1071.     error.show();
  1072.     }
  1073.  
  1074.     private void hostError(String wouldBeHost, String hostName) {
  1075.     MessageDialog error = propSheet.errorDialog;
  1076.     
  1077.     error.setMessage("'"+wouldBeHost+"' is not a valid "+hostName+
  1078.                  " host name.  Try again.");
  1079.     error.show();
  1080.     }
  1081.     
  1082.     public void selected(Component c, int pos) {
  1083.     boolean wasError = false;
  1084.  
  1085.     // Try to parse port numbers.  If we fail, pitch an error dialog,
  1086.     // and don't store any values.
  1087.     String firewallPort = propSheet.fProxyPort.getText();
  1088.     try {
  1089.         HttpClient.firewallProxyPort = Integer.parseInt(firewallPort);
  1090.     } catch (NumberFormatException e) {
  1091.         portError(firewallPort, "Firewall Proxy");
  1092.         propSheet.fProxyPort.setText(HttpClient.firewallProxyPort+"");
  1093.         wasError = true;
  1094.     }
  1095.  
  1096.     String proxyPort = propSheet.cProxyPort.getText();
  1097.     try {
  1098.         HttpClient.cachingProxyPort = Integer.parseInt(proxyPort);
  1099.     } catch (NumberFormatException e) {
  1100.         portError(proxyPort, "Caching Proxy");
  1101.         propSheet.cProxyPort.setText(HttpClient.cachingProxyPort+"");
  1102.         wasError = true;
  1103.     }
  1104.  
  1105.     String ftpProxyPort = propSheet.ftpProxyPort.getText();
  1106.     try {
  1107.         FtpClient.ftpProxyPort = Integer.parseInt(ftpProxyPort);
  1108.     } catch (NumberFormatException e) {
  1109.         portError(ftpProxyPort, "FTP Proxy");
  1110.         propSheet.ftpProxyPort.setText(FtpClient.ftpProxyPort+"");
  1111.         wasError = true;
  1112.     }
  1113.  
  1114.     String firewallProxy = propSheet.fProxyField.getText();
  1115.     try {
  1116.         if (propSheet.fProxyToggle.getState()) {
  1117.         InetAddress    iaddr = InetAddress.getByName(firewallProxy);
  1118.         }
  1119.         HttpClient.firewallProxyHost = firewallProxy;
  1120.     } catch (UnknownHostException e) {
  1121.         hostError(firewallProxy, "Firewall Proxy");
  1122.         propSheet.fProxyField.setText(HttpClient.firewallProxyHost);
  1123.         wasError = true;
  1124.     }
  1125.  
  1126.     String cachingProxy = propSheet.cProxyField.getText();
  1127.     try {
  1128.         if (propSheet.cProxyToggle.getState()) {
  1129.         InetAddress    iaddr = InetAddress.getByName(cachingProxy);
  1130.         }
  1131.         HttpClient.cachingProxyHost = cachingProxy;
  1132.     } catch (UnknownHostException e) {
  1133.         hostError(cachingProxy, "Caching Proxy");
  1134.         propSheet.cProxyField.setText(HttpClient.cachingProxyHost);
  1135.         wasError = true;
  1136.     }
  1137.  
  1138.     String ftpProxy = propSheet.ftpProxyField.getText();
  1139.     try {
  1140.         if (propSheet.ftpProxyToggle.getState()) {
  1141.         InetAddress    iaddr = InetAddress.getByName(ftpProxy);
  1142.         }
  1143.         FtpClient.ftpProxyHost = ftpProxy;
  1144.     } catch (UnknownHostException e) {
  1145.         hostError(ftpProxy, "FTP Proxy");
  1146.         propSheet.ftpProxyField.setText(FtpClient.ftpProxyHost);
  1147.         wasError = true;
  1148.     }
  1149.     
  1150.  
  1151.     if (! wasError) {
  1152.         if (WRTextItem.underlineAnchors != propSheet.ulField.getState()) {
  1153.         WRTextItem.underlineAnchors = propSheet.ulField.getState();
  1154.         propSheet.mw.doc.paint();
  1155.         }
  1156.         propSheet.mw.doc.setDelayImageLoading(propSheet.dilField.getState());
  1157.         propSheet.mw.doc.setDelayAppletLoading(propSheet.dalField.getState());
  1158.         
  1159.         HttpClient.useProxyForFirewall = propSheet.fProxyToggle.getState();
  1160.         HttpClient.useProxyForCaching = propSheet.cProxyToggle.getState();
  1161.         FtpClient.useFtpProxy = propSheet.ftpProxyToggle.getState();
  1162.  
  1163.         propSheet.unMap();
  1164.         
  1165.         // set and save properties
  1166.         propSheet.mw.props.put("anchorStyle",
  1167.                    WRTextItem.underlineAnchors ?
  1168.                    "underline" : "plain");
  1169.         propSheet.mw.props.put("delayAppletLoading",
  1170.                    WRWindow.delayAppletLoading ?
  1171.                    "true" : "false");
  1172.         propSheet.mw.props.put("delayImageLoading",
  1173.                    WRWindow.delayImageLoading ?
  1174.                    "true" : "false");
  1175.         propSheet.mw.props.put("firewallSet",
  1176.                    HttpClient.useProxyForFirewall ?
  1177.                    "true":"false");
  1178.         propSheet.mw.props.put("firewallHost",
  1179.                    HttpClient.firewallProxyHost);
  1180.         propSheet.mw.props.put("firewallPort", firewallPort);
  1181.         
  1182.         propSheet.mw.props.put("proxySet",
  1183.                    HttpClient.useProxyForCaching ?
  1184.                    "true": "false");
  1185.         propSheet.mw.props.put("proxyHost", HttpClient.cachingProxyHost);
  1186.         propSheet.mw.props.put("proxyPort", proxyPort);
  1187.  
  1188.         propSheet.mw.props.put("useFtpProxy",
  1189.                    FtpClient.useFtpProxy ?
  1190.                    "true": "false");
  1191.         propSheet.mw.props.put("ftpProxyHost", FtpClient.ftpProxyHost);
  1192.         propSheet.mw.props.put("ftpProxyPort", ftpProxyPort);
  1193.         
  1194.         propSheet.mw.props.save();
  1195.     }
  1196.     }
  1197.  
  1198.    PropertySheet    propSheet;
  1199. }
  1200.  
  1201.  
  1202. class SaveButton extends Button {
  1203.     public SaveButton(Container w,  SourceViewer f) {
  1204.     super("Save...",null, w);
  1205.     sViewer = f;
  1206.     }
  1207.     public void selected(Component c, int pos) {
  1208.     if (fdialog == null) {
  1209.         fdialog = new FileDialog("Save HTML Source...", sViewer);
  1210.     }
  1211.     String path = fdialog.chooseFile(null);
  1212.  
  1213.     if (path != null) {
  1214.         try {
  1215.         File fpath = new File(path);
  1216.         PrintStream pStr = new PrintStream(new FileOutputStream(fpath));
  1217.         pStr.print(sViewer.t.getText());
  1218.         pStr.close();
  1219.         } catch (Exception e) {
  1220.         sViewer.status.setText("Error writing to " + path);
  1221.         return;
  1222.         }
  1223.         sViewer.status.setText("Wrote " + path);
  1224.     }
  1225.     }
  1226.  
  1227.     SourceViewer sViewer;
  1228.     FileDialog    fdialog = null;
  1229. }
  1230.  
  1231. class SourceViewer extends Frame implements Runnable {
  1232.     URL doc;
  1233.     TextArea t;
  1234.     Label    status;
  1235.     
  1236.     SourceViewer(hotjava wr, URL doc) {
  1237.     super(hotjava.server, true, wr, 725, 500, Color.lightGray);
  1238.  
  1239.     this.doc = doc;
  1240.     Font defaultFont = wServer.fonts.getFont("Courier", Font.PLAIN, 14);
  1241.     setDefaultFont(hotjava.dialogFont);
  1242.     setTitle("Source Viewer " + doc.toExternalForm());
  1243.     Window w = new Window(this, "Center", background, 700, 300);
  1244.     w.setLayout(new ColumnLayout(true));
  1245.     t = new TextArea(w, "Center", defaultFont, 80, 24);
  1246.     t.setHFill(true);
  1247.     t.setVFill(true);
  1248.     t.setEditable(false);
  1249.     w = new Window(this,"South",background,700,200);
  1250.     w.setLayout(new ColumnLayout(true));
  1251.     Row row = new Row(w,null,true);
  1252.     new SaveButton(row, this);
  1253.     new DismissButton(row, this);
  1254.     status = new Label("",null, w, defaultFont);
  1255.     status.setHFill(true);
  1256.     map();
  1257.     resize();
  1258.     new Thread(this, "SourceViewer").start();
  1259.     }
  1260.  
  1261.     public void run() {
  1262.     InputStream in = null;
  1263.     try {
  1264.         in = doc.openStream();
  1265.     } catch (FileNotFoundException e) {
  1266.         t.setText("");    // can you say HACK?
  1267.         return;
  1268.     }
  1269.     OutputStreamBuffer out = new OutputStreamBuffer();
  1270.     byte buffer[] = new byte[1024];
  1271.     while (true) {
  1272.         int n = in.read(buffer, 0, buffer.length);
  1273.         if (n < 0) {
  1274.         break;
  1275.         }
  1276.         out.write(buffer, 0, n);
  1277.     }
  1278.     in.close();
  1279.     t.setText(out.toString());
  1280.     }
  1281. }
  1282.  
  1283. class PrintButton extends Button implements Runnable {
  1284.     PrintDialog printDialog;
  1285.  
  1286.     public PrintButton(Container w, PrintDialog f) {
  1287.     super("Print",null, w);
  1288.  
  1289.     printDialog = f;
  1290.     }
  1291.  
  1292.     public void selected(Component c, int pos) {
  1293.     new Thread(this, "Print Dialog").start();
  1294.     }
  1295.  
  1296.     public void run() {
  1297.     OutputStream os;
  1298.     Dimension paper = null;
  1299.     Properties props = printDialog.theWR.props;
  1300.     Object prop;
  1301.     String destType = null;
  1302.     String paperType = null;
  1303.  
  1304.     printDialog.theWR.setMessage("Printing...");
  1305.     prop = props.get("printerName");
  1306.     if (prop == null || !(prop instanceof String)
  1307.         || !((String) prop).equals(printDialog.printerName.getText()))
  1308.         props.put("printerName", printDialog.printerName.getText());
  1309.     prop = props.get("printCommand");
  1310.     if (prop == null || !(prop instanceof String)
  1311.         || !((String) prop).equals(printDialog.commandName.getText()))
  1312.         props.put("printCommand", printDialog.commandName.getText());
  1313.     prop = props.get("printFile");
  1314.     if (prop == null || !(prop instanceof String)
  1315.         || !((String) prop).equals(printDialog.fileName.getText()))
  1316.         props.put("printFile", printDialog.fileName.getText());
  1317.     if (printDialog.useFile.getState()){
  1318.         destType = "file";
  1319.         String file = printDialog.fileName.getText();
  1320.         try {
  1321.         os = (OutputStream) new FileOutputStream(file);
  1322.         } catch (Exception e) {
  1323.         printDialog.unMap();
  1324.         printDialog.theWR.setMessage("Printing: Bad File...Cancelled");
  1325.         return;
  1326.         }
  1327.     } else if (printDialog.useCommand.getState()){
  1328.         destType = "command";
  1329.         String command = printDialog.commandName.getText();
  1330.         os = System.execout(command);
  1331.     } else {
  1332.         String printer;
  1333.         if (printDialog.usePrinter.getState()) {
  1334.         destType = "printer";
  1335.         printer = printDialog.printerName.getText();
  1336.         if (!printer.equals(""))
  1337.             printer = " -d " + printer;
  1338.         } else {
  1339.         // assert(printDialog.useDefault.getState())
  1340.         destType = "default";
  1341.         printer = "";
  1342.         }
  1343.         os = System.execout("lp" + printer);
  1344.     }
  1345.     if (destType != null) {
  1346.         prop = props.get("printDestination");
  1347.         if (prop == null || !(prop instanceof String)
  1348.         || !((String) prop).equals(destType))
  1349.         props.put("printDestination", destType);
  1350.     }
  1351.     if (printDialog.letterSheets.getState()) {
  1352.         paperType = "letter";
  1353.         paper = PSGraphics.Letter;
  1354.     } else if (printDialog.legalSheets.getState()) {
  1355.         paperType = "legal";
  1356.         paper = PSGraphics.Legal;
  1357.     } else if (printDialog.executiveSheets.getState()) {
  1358.         paperType = "executive";
  1359.         paper = PSGraphics.Executive;
  1360.     } else if (printDialog.A4Sheets.getState()) {
  1361.         paperType = "A4";
  1362.         paper = PSGraphics.A4;
  1363.     }
  1364.     if (paperType != null) {
  1365.         prop = props.get("paperType");
  1366.         if (prop == null || !(prop instanceof String)
  1367.         || !((String) prop).equals(paperType))
  1368.         props.put("paperType", paperType);
  1369.     }
  1370.     if (props.changed)
  1371.         props.save();
  1372.  
  1373.     Dimension layout = new Dimension(printDialog.theWin.width,
  1374.                      printDialog.theWin.height);
  1375.     BufferedOutputStream bos = new BufferedOutputStream(os);
  1376.     PSGraphics pg = new PSGraphics(printDialog.theWin, bos,
  1377.                        printDialog.theDoc.getTitle(),
  1378.                        layout, paper);
  1379.     String finalmsg = "Printing...Done";
  1380.     try {
  1381.         printDialog.theWin.print(pg);
  1382.     } catch (Exception e) {
  1383.         e.printStackTrace();
  1384.         finalmsg = "Printing: I/O Error...Cancelled";
  1385.     }
  1386.     try {
  1387.         pg.close();
  1388.     } catch (Exception e) {
  1389.         finalmsg = "Printing: I/O Error...Cancelled";
  1390.     }
  1391.     printDialog.unMap();
  1392.     printDialog.theWR.setMessage(finalmsg);
  1393.     // REMIND: dispose is broken
  1394.     // printDialog.dispose();
  1395.     }
  1396. }
  1397.  
  1398. class DisposeButton extends Button {
  1399.     Frame    theFrame;
  1400.  
  1401.     public DisposeButton(Container w, Frame f) {
  1402.     this(w, f, "Cancel");
  1403.     }
  1404.  
  1405.     public DisposeButton(Container w, Frame f, String label) {
  1406.     super(label, null, w);
  1407.  
  1408.     theFrame = f;
  1409.     }
  1410.  
  1411.     public void selected(Component c, int pos) {
  1412.     theFrame.unMap();
  1413.     // REMIND: dispose is broken
  1414.     // theFrame.dispose();
  1415.     }
  1416. }
  1417.  
  1418. class PrintDialog extends Frame {
  1419.     hotjava theWR;
  1420.     Document theDoc;
  1421.     WRWindow theWin;
  1422.  
  1423.     RadioGroup paperSize = new RadioGroup();
  1424.     Toggle letterSheets;
  1425.     Toggle legalSheets;
  1426.     Toggle executiveSheets;
  1427.     Toggle A4Sheets;
  1428.  
  1429.     RadioGroup destType = new RadioGroup();
  1430.     Toggle useDefault;
  1431.     Toggle usePrinter;
  1432.     Toggle useFile;
  1433.     Toggle useCommand;
  1434.     TextField printerName;
  1435.     TextField fileName;
  1436.     TextField commandName;
  1437.  
  1438.     public PrintDialog(hotjava wr, Document doc) {
  1439.         super(hotjava.server, true, wr, 400, 270, Color.lightGray);
  1440.     setDefaultFont(hotjava.dialogFont);
  1441.     setTitle("Print HotJava Document");
  1442.     theWR = wr;
  1443.     theWin = wr.doc;
  1444.     theDoc = doc;
  1445.  
  1446.         Window w;
  1447.     RowColLayout r;
  1448.     Properties props = theWR.props;
  1449.     Object prop;
  1450.     String propStr;
  1451.  
  1452.     prop = props.get("paperType");
  1453.     if (prop != null && (prop instanceof String))
  1454.         propStr = (String) prop;
  1455.     else
  1456.         propStr = "";
  1457.  
  1458.     w = new Window(this, "Page Sizes", background, 400, 40);
  1459.     r = new RowColLayout(0, 7, true);
  1460.     r.setGaps(0,0,0,0);
  1461.     w.setLayout(r);
  1462.     new Label("Paper Size:", null, w);
  1463.     new Label("", null, w);    // Extra label provides gap before choices.
  1464.     letterSheets = new Toggle("Letter", null, w, paperSize,
  1465.                   propStr.equals("letter"));
  1466.     legalSheets = new Toggle("Legal", null, w, paperSize,
  1467.                  propStr.equals("legal"));
  1468.     executiveSheets = new Toggle("Executive", null, w, paperSize,
  1469.                      propStr.equals("executive"));
  1470.     A4Sheets = new Toggle("A4", null, w, paperSize,
  1471.                   propStr.equals("A4"));
  1472.     if (paperSize.getCurrent() == null)
  1473.         letterSheets.setState(true);
  1474.     w.move(0, 0);
  1475.  
  1476.     prop = props.get("printDestination");
  1477.     if (prop != null && (prop instanceof String))
  1478.         propStr = (String) prop;
  1479.     else
  1480.         propStr = "default";
  1481.     String defPrinter = System.getenv("PRINTER");
  1482.     if (defPrinter == null)
  1483.         defPrinter = "";
  1484.  
  1485.     w = new Window(this, "Destinations Title", background, 400, 30);
  1486.     new Label("Print Destinations", null, w);
  1487.     w.move(0, 40);
  1488.  
  1489.     w = new Window(this, "Default Destination", background, 400, 40);
  1490.     r = new RowColLayout(0, 2, true);
  1491.     r.setGaps(0,0,0,0);
  1492.     w.setLayout(r);
  1493.     useDefault = new Toggle(" System Default Printer:  " + defPrinter,
  1494.                 null, w, destType, propStr.equals("default"));
  1495.     w.move(0, 70);
  1496.  
  1497.     w = new Window(this, "Other Destinations", background, 400, 120);
  1498.     r = new RowColLayout(0, 2, true);
  1499.     r.setGaps(0,0,0,4);
  1500.     w.setLayout(r);
  1501.  
  1502.     usePrinter = new Toggle("Printer:", null, w, destType,
  1503.                 propStr.equals("printer"));
  1504.     prop = props.get("printerName");
  1505.     if (prop == null || !(prop instanceof String))
  1506.         prop = defPrinter;
  1507.     printerName = new TextField((String) prop, null, w, true);
  1508.  
  1509.     useFile = new Toggle("File:", null, w, destType,
  1510.                  propStr.equals("file"));
  1511.     prop = props.get("printFile");
  1512.     if (prop == null || !(prop instanceof String))
  1513.         prop = (Object) "/tmp/";
  1514.     fileName = new TextField((String) prop, null, w, true);
  1515.  
  1516.     useCommand = new Toggle(" Command:", null, w, destType,
  1517.                 propStr.equals("command"));
  1518.     prop = props.get("printCommand");
  1519.     if (prop == null || !(prop instanceof String))
  1520.         prop = (Object) "lp";
  1521.     commandName = new TextField((String) prop, null, w, true);
  1522.  
  1523.     if (destType.getCurrent() == null)
  1524.         useDefault.setState(true);
  1525.     w.move(0, 110);
  1526.  
  1527.     w = new Window(this, "Buttons", background, 400, 40);
  1528.     new PrintButton(w, this);
  1529.     new DisposeButton(w, this);
  1530.     w.move(0, 230);
  1531.  
  1532.     resize();
  1533.     }
  1534. }
  1535.  
  1536. class PropertySheet extends Frame {
  1537.     public PropertySheet(hotjava wr) {
  1538.     super(hotjava.server, true, wr, 500, 446, Color.lightGray);
  1539.     setDefaultFont(hotjava.dialogFont);
  1540.     setTitle("HotJava Properties");
  1541.     mw = wr;
  1542.  
  1543.     RowColLayout    r;
  1544.     Window        w;
  1545.     int        h;
  1546.     String        acl;
  1547.     String path = System.getenv("HOME") + File.separator +
  1548.         ".hotjava" + File.separator + "properties";
  1549.     File wpath = new File(System.getenv("HOME") +
  1550.                   File.separator + ".hotjava");
  1551.  
  1552.  
  1553.     wpath.mkdir();
  1554.     propFile = new File(path);
  1555.     w = new Window(this,"Center", background, 300, 130);
  1556.     r = new RowColLayout(0, 2, true);
  1557.     r.setGaps(0,0,0,0);
  1558.     w.setLayout(r);
  1559.  
  1560.     // XXX: this layout needs fixing...
  1561.  
  1562.     fProxyToggle = new Toggle("Firewall Proxy","proxy",w,
  1563.                   HttpClient.useProxyForFirewall);
  1564.     new Label("Port",null, w);
  1565.     fProxyField = new TextField(HttpClient.firewallProxyHost,
  1566.                     null,w,true);
  1567.     fProxyPort = new TextField("" + HttpClient.firewallProxyPort,
  1568.                    null,w,true);
  1569.  
  1570.     ftpProxyToggle = new Toggle("FTP Proxy",
  1571.                     null,w,FtpClient.useFtpProxy);
  1572.     new Label("Port",null, w);
  1573.     
  1574.     ftpProxyField = new TextField(FtpClient.ftpProxyHost,
  1575.                     null,w,true);
  1576.     ftpProxyPort = new TextField("" + FtpClient.ftpProxyPort,
  1577.                      null,w,true);
  1578.  
  1579.     cProxyToggle = new Toggle("Caching Proxy",null,w,
  1580.                   HttpClient.useProxyForCaching);
  1581.     new Label("Port",null, w);
  1582.     cProxyField = new TextField(HttpClient.cachingProxyHost,
  1583.                     null,w,true);
  1584.     cProxyPort = new TextField("" + HttpClient.cachingProxyPort,
  1585.                    null,w,true);
  1586.  
  1587.  
  1588.     new Label("Read Path:",null,w);
  1589.     acl = File.getReadACL();
  1590.     new TextField(acl,null,w,false);
  1591.     new Label("Write Path:",null,w);
  1592.     acl = File.getWriteACL();
  1593.     new TextField(acl,null,w,false);
  1594.     //new Label("Delay Image loading:","dil",w);
  1595.     new Label("Underline anchors:",null,w);
  1596.     ulField = new Toggle("", null,w,WRTextItem.underlineAnchors);
  1597.     new Label("Delay image loading:",null,w);
  1598.     dilField = new Toggle("", null,w,WRWindow.delayImageLoading);
  1599.     new Label("Delay applet loading:",null,w);
  1600.     dalField = new Toggle("", null,w,WRWindow.delayAppletLoading);
  1601.     w = new Window(this,"South",background,300,50);
  1602.     new ApplyButton(w, this);
  1603.     new PropertiesDismissButton(w, this, wr);
  1604.  
  1605.     errorDialog = new MessageDialog(this, "Error", null,
  1606.                     MessageDialog.ERROR_TYPE, 1, true,
  1607.                     null, null, null, null);
  1608.     }
  1609.  
  1610.     void setAllValues() {
  1611.     ulField.setState(WRTextItem.underlineAnchors);
  1612.     dilField.setState(mw.doc.delayImageLoading);
  1613.     dalField.setState(mw.doc.delayAppletLoading);
  1614.         
  1615.     fProxyToggle.setState(HttpClient.useProxyForFirewall);
  1616.     fProxyField.setText(HttpClient.firewallProxyHost);
  1617.     fProxyPort.setText(HttpClient.firewallProxyPort+"");
  1618.     
  1619.     cProxyToggle.setState(HttpClient.useProxyForCaching);
  1620.     cProxyField.setText(HttpClient.cachingProxyHost);
  1621.     cProxyPort.setText(HttpClient.cachingProxyPort+"");
  1622.  
  1623.     ftpProxyToggle.setState(FtpClient.useFtpProxy);
  1624.     ftpProxyField.setText(FtpClient.ftpProxyHost);
  1625.     ftpProxyPort.setText(FtpClient.ftpProxyPort+"");
  1626.     }
  1627.     
  1628.     void show() {
  1629.     setAllValues();
  1630.     map();
  1631.     resize();
  1632.     }
  1633.     
  1634.     hotjava        mw;
  1635.  
  1636.     TextField        fProxyField;
  1637.     TextField        fProxyPort;
  1638.     Toggle        fProxyToggle;
  1639.  
  1640.     TextField        cProxyField;
  1641.     TextField        cProxyPort;
  1642.     Toggle        cProxyToggle;
  1643.  
  1644.     Toggle        ftpProxyToggle;    
  1645.     TextField        ftpProxyField;
  1646.     TextField        ftpProxyPort;
  1647.  
  1648.     File        propFile;
  1649.     Toggle        ulField;
  1650.     Toggle        dilField;
  1651.     Toggle        dalField;
  1652.  
  1653.     MessageDialog    errorDialog;
  1654. }
  1655.  
  1656. class OpenButton extends Button {
  1657.     public OpenButton(Container w,  OpenDialog d, hotjava mw) {
  1658.     super("Open",null, w);
  1659.     target = mw;
  1660.     dialog = d;
  1661.     }
  1662.     public void selected(Component c, int pos) {
  1663.     dialog.unMap();
  1664.     target.doc.pushURL(new URL(null, dialog.urlField.getText()));
  1665.     }
  1666.  
  1667.     hotjava target;
  1668.     OpenDialog    dialog;
  1669. }
  1670.  
  1671. class OpenTextField extends TextField {
  1672.     hotjava target;
  1673.  
  1674.     OpenTextField(Window w, hotjava mw) {
  1675.     super("",null,w,true);
  1676.     target = mw;
  1677.     }
  1678.  
  1679.     public void selected() {
  1680.     target.doc.pushURL(new URL(null, getText()));
  1681.     }
  1682. }
  1683.  
  1684. class OpenDialog extends Frame {
  1685.     TextField    urlField;
  1686.  
  1687.     public OpenDialog(WServer server, hotjava w) {
  1688.     super(server, true, w, 400, 100, Color.lightGray);
  1689.     setTitle("Open URL...");
  1690.     setDefaultFont(hotjava.dialogFont);
  1691.     Window cw = new Window(this, "Center", background, 300, 100);
  1692.     urlField = new OpenTextField(cw,w);
  1693.     urlField.setHFill(true);
  1694.     new OpenButton(cw, this, w);
  1695.     new DismissButton(cw, this);
  1696.     }
  1697. }
  1698.  
  1699. class HotListItem {
  1700.     public String    url;
  1701.     public boolean    inMenu;
  1702.     public MenuItem    menuItem;
  1703.  
  1704.     public HotListItem(String url, boolean inMenu) {
  1705.     this.url = url;
  1706.     this.inMenu = inMenu;
  1707.     }
  1708.  
  1709.     public String toString() {
  1710.     String m;
  1711.  
  1712.     if (menuItem != null) {
  1713.         m = "<menuitem>";
  1714.     } else {
  1715.         m = null;
  1716.     }
  1717.         
  1718.     return "HotListItem[" + url + ", " + inMenu + ", " + m + "]";
  1719.     }
  1720. }
  1721.  
  1722. class MenuToggle extends Toggle {
  1723.     HotList target;
  1724.  
  1725.     public MenuToggle(Container parent, HotList target) {
  1726.     super("In Goto Menu",null,parent, false);
  1727.     this.target = target;
  1728.     }
  1729.  
  1730.     public void selected() {
  1731.     target.changeMenuStatus(getState(), target.selectedItem);
  1732.     }
  1733. }
  1734.  
  1735. class HotList extends Frame implements ChoiceHandler {
  1736.     String        hName;
  1737.     String        home;
  1738.     File        hotlist;
  1739.     Window        cw;
  1740.     int            selectedItem;
  1741.     HotlistGotoButton    gotoButton;
  1742.     List        slist;
  1743.     Vector        urlList;
  1744.     Vector        inMenuList;
  1745.     hotjava        mw;
  1746.     TextField        urlValue;
  1747.     Toggle        inMenuToggle;
  1748.  
  1749.     public HotList(WServer server, hotjava w) {
  1750.     super(server, true, w, 300, 400, Color.lightGray);
  1751.     setTitle("HotJava Hotlist");
  1752.     setDefaultFont(hotjava.dialogFont);
  1753.  
  1754.     Label l;
  1755.  
  1756.     mw = w;
  1757.     cw = new Window(this, "Center", background, 300, 200);
  1758.     cw.setLayout(new ColumnLayout(true));
  1759.     slist = new List(cw,this,null, 10, false);
  1760.     slist.setHFill(true);
  1761.     slist.setVFill(true);
  1762.     urlList = new Vector();
  1763.     inMenuList = new Vector();
  1764.     readHotList("default");
  1765.     cw = new Window(this, "South", background, 300, 100);
  1766.     cw.setLayout(new ColumnLayout(true));
  1767.  
  1768.     new Label("URL:", null, cw);
  1769.     urlValue = new TextField("",null,cw, false);
  1770.     urlValue.setHFill(true);
  1771.  
  1772.     Row row = new Row(cw, null, true);
  1773.     inMenuToggle = new MenuToggle(row,this);
  1774.  
  1775.     row = new Row(cw, null, true);
  1776.     gotoButton = new HotlistGotoButton(row, this);
  1777.     new DeleteButton(row, this);
  1778.     new DismissButton(row, this);
  1779.     selectedItem = 0;
  1780.     }
  1781.  
  1782.     /**
  1783.      * Change whether the given item is in the Goto menu or not.
  1784.      */
  1785.     public void changeMenuStatus(boolean inMenu, int index) {
  1786.     HotListItem hItem = (HotListItem)urlList.elementAt(index);
  1787.     String        title = slist.itemAt(index);
  1788.  
  1789.     if (hItem.inMenu == inMenu) {
  1790.         return;
  1791.     }
  1792.     if (inMenu) {
  1793.         hItem.menuItem = mw.gotoMenu.addHotItem(title, hItem.url);
  1794.     } else {
  1795.         if (hItem.menuItem != null) {
  1796.         hItem.menuItem.dispose();
  1797.         }
  1798.     }
  1799.     hItem.inMenu = inMenu;
  1800.     if (index == selectedItem && inMenu != inMenuToggle.getState()) {
  1801.         inMenuToggle.setState(inMenu);
  1802.     }
  1803.     write();
  1804.     }
  1805.  
  1806.     /**
  1807.      * Add an item to the hotlist
  1808.      */
  1809.     public void addItem(String title,
  1810.             String url,
  1811.             boolean inMenu,
  1812.             boolean checkMenu) {
  1813.     HotListItem    prev;
  1814.     int        i;
  1815.     int        nitems = urlList.size();
  1816.  
  1817.     for (i=0; i < nitems; i++) {
  1818.         prev = (HotListItem)urlList.elementAt(i);
  1819.         if (prev.url.equals(url)) {
  1820.         if (checkMenu) {
  1821.             changeMenuStatus(inMenu, i);
  1822.         }
  1823.         return;
  1824.         }
  1825.     }
  1826.     
  1827.     if (title.length() == 0) {
  1828.         title = "Untitled (" + url + ")";
  1829.     }
  1830.     slist.addItem(title);
  1831.     urlList.addElement(prev = new HotListItem(url, false));
  1832.     if (checkMenu && inMenu) {
  1833.         prev.inMenu = inMenu;
  1834.         prev.menuItem = mw.gotoMenu.addHotItem(title, url);
  1835.     }
  1836.     write();
  1837.     }
  1838.  
  1839.     /**
  1840.      * write out this hotlist.
  1841.      */
  1842.     public void write() {
  1843.     FileOutputStream    outStr;
  1844.     PrintStream        pStr;
  1845.     int i;
  1846.     int nitems = urlList.size();
  1847.     File    hfile;
  1848.     HotListItem    hItem;
  1849.  
  1850.     hfile = new File(hotlist.getParent());
  1851.     hfile.mkdir();
  1852.     outStr = new FileOutputStream(hotlist);
  1853.     pStr = new PrintStream(outStr);
  1854.     pStr.println("hotjava-hotlist-version-1");
  1855.     pStr.println(hName);
  1856.     for (i = 0; i < nitems; i++) {
  1857.         hItem = (HotListItem)urlList.elementAt(i);
  1858.  
  1859.         if (hItem.inMenu) {
  1860.         pStr.println(hItem.url + " inMenu");
  1861.         } else {
  1862.         pStr.println(hItem.url);
  1863.         }
  1864.         pStr.println(slist.itemAt(i));
  1865.     }
  1866.     outStr.close();
  1867.     }
  1868.  
  1869.     /**
  1870.      * Delete the given item from the hotlist.  Assumes item is the
  1871.      * current one selected, so clears the URL value.
  1872.      */
  1873.     public void delete(int item) {
  1874.     HotListItem    hItem = (HotListItem)urlList.elementAt(item);
  1875.     slist.delItem(item);
  1876.     
  1877.     if (hItem.inMenu && hItem.menuItem != null) {
  1878.         hItem.menuItem.dispose();
  1879.     }
  1880.     urlList.removeElementAt(item);
  1881.     urlValue.setText("");
  1882.     write();
  1883.     }
  1884.  
  1885.     public void readHotList(String name) {
  1886.     FileInputStream    fstream;
  1887.     String        hlPath;
  1888.   
  1889.     hlPath = System.getenv("HOME") + File.separator + ".hotjava" +
  1890.         File.separator + "hotlist-" + name;
  1891.     hName = name;
  1892.     try {
  1893.         hotlist = new File(hlPath);
  1894.         fstream = new FileInputStream(hotlist);
  1895.     } catch (Exception e) {
  1896.         try {
  1897.         hotlist = new File(System.getenv("HOME") + File.separator + ".mosaic-hotlist-default");
  1898.         fstream = new FileInputStream(hotlist);
  1899.         } catch (Exception ee) {
  1900.         return;
  1901.         }
  1902.     }
  1903.     DataInputStream    dis = new DataInputStream(fstream);
  1904.     String    url;
  1905.     String    title;
  1906.  
  1907.     /* read version number and stupid line after it */
  1908.     dis.readLine();
  1909.     dis.readLine();
  1910.  
  1911.     try {
  1912.         while (true) {
  1913.         url = dis.readLine();
  1914.         title = dis.readLine();
  1915.         if (url == null || title == null) {
  1916.             break;
  1917.         }
  1918.         int    separator = url.indexOf(' ');
  1919.         boolean putInMenu = false;
  1920.  
  1921.         if (separator != -1) {
  1922.             if (url.substring(separator).startsWith(" inMenu")) {
  1923.             putInMenu = true;
  1924.             }
  1925.             url = url.substring(0, separator);
  1926.         }
  1927.  
  1928.         HotListItem    item = new HotListItem(url, putInMenu);
  1929.  
  1930.         urlList.addElement(item);
  1931.         slist.addItem(title);
  1932.         if (putInMenu) {
  1933.             item.menuItem = mw.gotoMenu.addHotItem(title, item.url);
  1934.         }
  1935.         }
  1936.     } finally {
  1937.         fstream.close();
  1938.     }
  1939.     hotlist = new File(hlPath);
  1940.     }
  1941.     
  1942.     public void selected(Component c, int pos) {
  1943.     HotListItem hItem;
  1944.     selectedItem = pos;
  1945.     hItem = (HotListItem)urlList.elementAt(pos);
  1946.     inMenuToggle.setState(hItem.inMenu);
  1947.     urlValue.setText(hItem.url);
  1948.     }
  1949.  
  1950.     public void doubleClick(Component c, int pos) {
  1951.     selectedItem = pos;
  1952.     gotoButton.selected(c, pos);
  1953.     }
  1954. }
  1955.  
  1956.  
  1957. class HelpMenu extends Menu {
  1958.     hotjava mw;
  1959.  
  1960.     static String topics[] = {
  1961.     "doc:readme.html",
  1962.     "doc:copyright.html",
  1963.  
  1964.     "doc:index.html",
  1965.     "doc:/doc/misc/using.html",
  1966.     "http://java.sun.com/",
  1967.     "doc:demo/index.html",
  1968.     "doc:/doc/misc/people.html",
  1969.     "doc:/doc/misc/BugReport.html",
  1970.     "doc:/doc/misc/Register.html",
  1971.  
  1972.     "doc:/doc/",
  1973.     "doc:/doc/misc/JavaSearchHelp.html"
  1974.     };
  1975.     
  1976.     public HelpMenu(MenuBar mbar, hotjava w) {
  1977.     super("Help", mbar);
  1978.  
  1979.     mw = w;
  1980.     MenuItem    item;
  1981.  
  1982.     new MenuItem("README!", this);
  1983.     new MenuItem("Copyright and License", this);
  1984.  
  1985.     addSeparator();
  1986.     new MenuItem("About HotJava", this);
  1987.     new MenuItem("Using HotJava", this);
  1988.     new MenuItem("Latest HotJava Info", this);
  1989.     new MenuItem("HotJava Demos", this);
  1990.     new MenuItem("Meet the People", this);
  1991.     addSeparator();
  1992.     new MenuItem("Submit a Bug Report", this);
  1993.     new MenuItem("Register", this);
  1994.  
  1995.     addSeparator();
  1996.     new MenuItem("HotJava Documentation", this);
  1997.     new MenuItem("How to Search the Documentation", this);
  1998.     new MenuItem("Search HotJava Documentation...", this);
  1999.     }
  2000.     
  2001.     public void selected(int index) {
  2002.         if (index >= topics.length) {
  2003.             if (mw.searchWindow == null) {
  2004.         mw.searchWindow = new SearchWindow(mw, mw.server);
  2005.             } 
  2006.         mw.searchWindow.map();
  2007.             mw.searchWindow.resize();
  2008.         } else {
  2009.             mw.doc.pushURL(new URL(null, topics[index]));
  2010.         }
  2011.     }
  2012. }
  2013.  
  2014. class UrlField extends TextField {
  2015.     public UrlField(String value, Container parent, hotjava w) {
  2016.     super(value, null, parent, true);
  2017.     setColor(Color.black);    
  2018.     setFont(hotjava.inputFont);
  2019.     mw = w;
  2020.     }
  2021.     public void selected() {
  2022.     mw.doc.pushURL(new URL(null, getText()));
  2023.     }
  2024.  
  2025.     hotjava mw;
  2026. }
  2027.  
  2028. class InfoWindow extends Window {
  2029.  
  2030.     Label    urlTitle;
  2031.     TextField    urlField;
  2032.  
  2033.     final int sepBarHeight = 2;
  2034.  
  2035.     public InfoWindow(hotjava hj) {
  2036.     super(hj, "North", hj.background, 100, 10);
  2037.     setLayout(new RowLayout(true));
  2038.     
  2039.     Column col = new Column(this, null, false);
  2040.     new Space(col, null, 10,
  2041.           9 + (hotjava.inputFont.ascent - hotjava.labelFont.ascent),
  2042.           false, false);
  2043.     urlTitle = new Label("Document URL:", null, col, hotjava.labelFont);
  2044.     urlTitle.setColor(hotjava.blue);
  2045.     urlField = new UrlField("", this, hj);
  2046.     urlField.setHFill(true);
  2047.  
  2048.     }
  2049.  
  2050.     public void paint() {
  2051.     paint3DRect(0, height - sepBarHeight, width, sepBarHeight, false, true);
  2052.     }
  2053. }
  2054.  
  2055.  
  2056. class FindHandler implements DialogHandler {
  2057.  
  2058.     /** The HotJava in which we reside. */
  2059.     hotjava wr;
  2060.     
  2061.     /** The document window we're leaching off of. */
  2062.     WRWindow docWin;
  2063.  
  2064.     /** Where we should start (or resume) searching from. */
  2065.     int fromPos = 0;
  2066.  
  2067.     FindHandler(hotjava runner) {
  2068.     wr = runner;
  2069.     docWin = runner.doc;
  2070.     }
  2071.     
  2072.     public void okCallback(Dialog m) {
  2073.     String text = ""; //docWin.document().getText();
  2074.     StringDialog sd = (StringDialog)m;
  2075.     String lookFor = sd.getText();
  2076.  
  2077.     int index = text.indexOf(lookFor, fromPos);
  2078.     if (index != -1) {
  2079.         docWin.scrollToTextPosition(index);
  2080.         wr.setMessage("Found '"+lookFor+"' at character "+index+".");
  2081.         fromPos = index + 1;
  2082.     } else {
  2083.         String msg = "Not found.  Start again from beginning?";
  2084.         MessageDialog md = new MessageDialog(sd, "Not found", msg,
  2085.                          MessageDialog.QUESTION_TYPE,
  2086.                          2, true, null, null, null,
  2087.                          null);
  2088.         boolean startOver = (md.show() == 1); // user pressed OK button
  2089.         if (startOver) {
  2090.         fromPos = 0;
  2091.         docWin.scrollToTextPosition(0);
  2092.         // do some sort of highlighting here, when possible.
  2093.         } else {
  2094.         sd.hide();
  2095.         }
  2096.     }
  2097.  
  2098.     // now change message to "find again" and let user do it again
  2099.     sd.setTitle("Find again");
  2100.     }
  2101.     
  2102.     /** Invoked when the user presses the "Cancel" button. */
  2103.     public void cancelCallback(Dialog m) {
  2104.     m.hide();
  2105.     }
  2106.  
  2107.     /** Invoked when the user presses the "Help" button. */
  2108.     public void helpCallback(Dialog m) {
  2109.     }
  2110. }
  2111.  
  2112.  
  2113. class HistoryItem {
  2114.     URL url;
  2115.     String title;
  2116.  
  2117.     HistoryItem(URL url, String title) {
  2118.     this.url = url;
  2119.     this.title = title;
  2120.     }
  2121. }
  2122.  
  2123.  
  2124. class HistoryWindow extends Frame implements ChoiceHandler, Runnable {
  2125.  
  2126.     hotjava       wRunner;
  2127.     TextField      urlValue;
  2128.     HistoryVector historyVec;
  2129.     int           lastUpdated;
  2130.  
  2131.     int          selectedItem;
  2132.  
  2133.     List      scrollingList;
  2134.     Vector      urlList;
  2135.  
  2136.     public synchronized void newElement() {
  2137.     notify();
  2138.     }
  2139.     
  2140.     public synchronized void run() {
  2141.     while (true) {
  2142.         wait();
  2143.  
  2144.         int time = historyVec.getTimeStamp();
  2145.         if (mapped && (lastUpdated != time)) {
  2146.         stickHistoryOnList();
  2147.         lastUpdated = time;
  2148.         }
  2149.     }
  2150.     }
  2151.  
  2152.     public HistoryWindow(WServer server, hotjava w, HistoryVector history) {
  2153.     super(server, true, w, 300, 400, Color.lightGray);
  2154.     setTitle(hotjava.programName+" History");
  2155.     setDefaultFont(hotjava.dialogFont);
  2156.     
  2157.     historyVec = history;
  2158.     urlList = new Vector();
  2159.  
  2160.     Label l;
  2161.     Window cw;
  2162.  
  2163.     cw = new Window(this, "Center", background, 300, 350);
  2164.     cw.setLayout(new ColumnLayout(true));
  2165.     scrollingList = new List(cw, this, "", 14, false, false);
  2166.     scrollingList.setHFill(true);
  2167.     scrollingList.setVFill(true);
  2168.  
  2169.     cw = new Window(this, "South", background, 300, 50);
  2170.     cw.setLayout(new ColumnLayout(true));
  2171.  
  2172.     urlValue = new TextField("destination URL", "urlValue", cw, false);
  2173.     urlValue.setHFill(true);
  2174.  
  2175.     Row row = new Row(cw, null, true);
  2176.     new HistoryGotoButton(row, this);
  2177.     new DismissButton(row, this);
  2178.  
  2179.     selectedItem = 0;
  2180.     wRunner = w;
  2181.  
  2182.     Thread th = new Thread(this);
  2183.     th.setName("History Updater");
  2184.     th.start();
  2185.     }
  2186.  
  2187.     private void showURL(int pos) {
  2188.     URL url = (URL)urlList.elementAt(pos);
  2189.     urlValue.setText(url.toExternalForm());
  2190.     }    
  2191.  
  2192.     public void selected(Component c, int pos) {
  2193.     selectedItem = pos;
  2194.     showURL(selectedItem);
  2195.     }
  2196.  
  2197.     public void doubleClick(Component c, int pos) {
  2198.     selectedItem = pos;
  2199.     gotoDocument();
  2200.     }
  2201.  
  2202.     public void showWindow() {
  2203.     map();
  2204.     resize();
  2205.     wServer.sync();
  2206.     int time = historyVec.getTimeStamp();
  2207.     if (lastUpdated != time) {
  2208.         stickHistoryOnList();
  2209.         lastUpdated = time;
  2210.     }
  2211.     }
  2212.  
  2213.  
  2214.     public void gotoDocument() {
  2215.     wRunner.doc.pushURL((URL)urlList.elementAt(selectedItem));
  2216.     }
  2217.     
  2218.     public void stickHistoryOnList() {
  2219.     scrollingList.clear();
  2220.     urlList.removeAllElements();
  2221.  
  2222.     for (int i = 0; i < historyVec.size(); i++) {
  2223.         HistoryItem dInfo = (HistoryItem)historyVec.elementAt(i);
  2224.         URL url = dInfo.url;
  2225.         String title = dInfo.title;
  2226.         
  2227.         if (title == null || title.length() == 0) {
  2228.         title = hotjava.untitledTitle+" ("+url.toExternalForm()+")";
  2229.         }
  2230.         
  2231.         scrollingList.addItem(title);
  2232.         urlList.addElement(url);
  2233.     }
  2234.  
  2235.     if (historyVec.size() > 0) {
  2236.         int showItem = historyVec.getCurrent();
  2237.         scrollingList.makeVisible(showItem);
  2238.         scrollingList.select(showItem);
  2239.         showURL(showItem);
  2240.     }
  2241.     }
  2242. }
  2243.  
  2244.  
  2245. class HistoryGotoButton extends Button {
  2246.  
  2247.     public HistoryGotoButton(Container w, HistoryWindow hw) {
  2248.     super("Visit", null, w);
  2249.     histWin = hw;
  2250.     }
  2251.     
  2252.     public void selected(Component c, int pos) {
  2253.     histWin.gotoDocument();
  2254.     }
  2255.  
  2256.     HistoryWindow    histWin;
  2257. }
  2258.