home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / LIB / MANAGER.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  70.9 KB  |  1,926 lines

  1. package sub_arctic.lib;
  2.  
  3. /* we import every policy and agent from input so we might as well
  4.  * take the whole works.  */
  5. import sub_arctic.input.*;  
  6.  
  7. import sub_arctic.anim.animation_agent;
  8.  
  9. import sub_arctic.constraints.value_provider;
  10. import sub_arctic.constraints.value_consumer;
  11. import sub_arctic.constraints.provider_part_ref;
  12. import sub_arctic.constraints.consumer_part_ref;
  13.  
  14. import sub_arctic.output.ignore_observer;
  15. import sub_arctic.output.loaded_image;
  16. import sub_arctic.output.drawable;
  17. import sub_arctic.output.color_pair;
  18. import sub_arctic.output.color_scheme;
  19. import sub_arctic.output.style_manager;
  20.  
  21. import java.util.Vector;
  22. import java.util.Hashtable;
  23.  
  24. import java.awt.Toolkit;
  25. import java.awt.Component;
  26. import java.awt.Image;
  27. import java.awt.MediaTracker;
  28. import java.awt.Color;
  29. import java.awt.Event;
  30. import java.awt.Font;
  31. import java.awt.FontMetrics;
  32. import java.awt.image.ImageObserver;
  33. import java.awt.image.ImageProducer;
  34. import java.awt.image.MemoryImageSource;
  35.  
  36. import java.applet.Applet;
  37.  
  38. import java.net.URL;
  39. import java.net.MalformedURLException;
  40.  
  41. import java.io.IOException;
  42. import java.io.PrintStream;
  43.  
  44. /** 
  45.  * This class provides overall coordination and management functions for the
  46.  * toolkit as well as providing a series of utility functions, and functions
  47.  * that isolate the interface to AWT.  This class contains only static 
  48.  * members and methods and is never actually instantiated.
  49.  *
  50.  * @author Scott Hudson
  51.  */
  52. public class manager {
  53.  
  54.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  55.  
  56.   /** 
  57.    * Constructor is private so we get no instances of this class (everything
  58.    * is static).
  59.    */
  60.   private manager() { }
  61.  
  62.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  63.  
  64.   /** Set of all input dispatch policies. */
  65.   protected static Vector _policy_list;
  66.  
  67.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  68.  
  69.   /** Flag indicating something somewhere is damaged. */
  70.   protected static boolean _something_is_damaged = true;
  71.  
  72.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  73.  
  74.   /** Set of all top level interactor objects in the system. */
  75.   protected static Vector _top_level_interactors;  
  76.  
  77.   // this is currently not used, but we may want a redraw_all later
  78.  
  79.   /** Set of all AWT components that top_level interactors are hosted by.
  80.    *  Note: this list is not synchronized with the list of top level 
  81.    * interactors. 
  82.    */
  83.    protected static Vector _all_awt_components;
  84.  
  85.   /** Set of all AWT applets that top_level interactors are hosted by.
  86.    *  Note: this list is not synchronized with the list of top level 
  87.    * interactors or the list of awt components. 
  88.    */
  89.   protected static Vector _all_applets;
  90.  
  91.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  92.  
  93.   /** Reference to a toolkit object that we can use to create things. */
  94.   protected static Toolkit _default_toolkit;
  95.  
  96.   /** 
  97.    * Get a reference the default native toolkit object.  This object is 
  98.    * useful for getting low level access to toolkit capabilities.  However,
  99.    * the manager provides interfaces for most object types of general 
  100.    * interest, so this object will probably be rarely used outside the 
  101.    * manager itself.
  102.    *
  103.    * @return Toolkit the default native toolkit object.
  104.    */
  105.   public static Toolkit default_toolkit() {return _default_toolkit;}
  106.  
  107.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  108.  
  109.   /** 
  110.    * Lookup table for storage of notify lists on behalf of interactors (this
  111.    * is part of the "external" or "heavyweight" constraint system). 
  112.    * This is indexed by provider_part_ref's and contains Vectors of 
  113.    * consumer_part_ref's.
  114.    */
  115.   protected static Hashtable _notify_list_table;
  116.  
  117.   /** 
  118.    * Lookup table for associating external constraints with interactors. 
  119.    * This is indexed by consumer_part_ref's and contains provider_part_ref's.
  120.    */
  121.   protected static Hashtable _extern_constraints_table;
  122.  
  123.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  124.  
  125.   /* Static initialization */
  126.   static
  127.     {
  128.       _something_is_damaged = true;
  129.       _policy_list = new Vector();
  130.       install_standard_policies(); 
  131.       _top_level_interactors = new Vector();
  132.       _all_awt_components = new Vector(); 
  133.       _all_applets = new Vector(); 
  134.       _notify_list_table = new Hashtable();
  135.       _extern_constraints_table = new Hashtable();
  136.       _default_toolkit = Toolkit.getDefaultToolkit();
  137.     }
  138.  
  139.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  140.   /* Policies and Agents */
  141.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  142.  
  143.   /** 
  144.    * Monitor focus input policy.  This policy is focus based (it passes inputs
  145.    * to objects which have established themselves as the focus) but is set
  146.    * up to monitor events only, not consume them.  This is useful for things
  147.    * like creating new kinds of cursors, where we need to know the position
  148.    * of events, but still want them delivered elsewhere.
  149.    */
  150.   public static mon_focus_policy_class monitor_focus_policy;
  151.  
  152.   /** 
  153.    * Event trace dispatch agent.  This agent works under the monitor focus
  154.    * input delivery policy and prints a human readable trace of events as
  155.    * they arrive (for debugging purposes), but does not actually distribute
  156.    * them anywhere.  Trace printing is off by default.  To start tracing 
  157.    * send the message do_trace(true) to this object.
  158.    */
  159.   public static event_trace_agent event_tracer;
  160.  
  161.   /** 
  162.    * Monitor version of raw focus dispatch agent.  This agent works under 
  163.    * the monitor focus policy and delivers raw events to requesting objects.
  164.    * This is here primarily as a hook for implementing unusual actions 
  165.    * (although a lot of things it might be used for are probably better 
  166.    * handled by adding new policies and/or agents, so you might want to 
  167.    * consider that before building something with this).
  168.    */
  169.    public static raw_focus_agent raw_monitor;
  170.  
  171.    /** 
  172.     * Click tracker.  This agent allows an object to monitor mouse button
  173.     * state outside its normal domain (to for example realize that the 
  174.     * release matching a previous press will never arrive since it was 
  175.     * delivered somewhere else).  This agent works with click_tracking 
  176.     * objects and only delivers input resulting from MOUSE_UP, and  
  177.     * MOUSE_DOWN events.  
  178.     */  
  179.    public static click_track_agent click_tracker;
  180.  
  181.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  182.  
  183.   /** 
  184.    * Focus input policy.  This policy delivers inputs to objects which have
  185.    * made themselves the focus of various kinds of inputs (rather than, for
  186.    * example positionally -- based on the mouse position at the time of the
  187.    * event).
  188.    */
  189.    public static focus_policy_class focus_policy;  
  190.  
  191.   /** 
  192.    * Raw input event focus dispatch agent.  This agent works under 
  193.    * the focus policy and delivers raw events to requesting objects.
  194.    * This is here primarily as a hook for implementing unusual actions 
  195.    * (although a lot of things it might be used for are probably better 
  196.    * handled by adding new policies and/or agents, so you might want to 
  197.    * consider that before building something with this).
  198.    */
  199.    public static raw_focus_agent raw_focus;
  200.  
  201.    /** Simple drag focus agent. */
  202.    public static simple_drag_focus_agent simple_drag_focus;
  203.  
  204.    /** Move-drag focus agent. */
  205.    public static move_drag_focus_agent move_drag_focus;
  206.  
  207.    /** Grow-drag focus agent. */
  208.    public static grow_drag_focus_agent grow_drag_focus;
  209.  
  210.    /** Snap-drag focus agent. */
  211.    public static snap_drag_agent snap_drag_focus;
  212.  
  213.    /** Inout drag focus agent. */
  214.    public static inout_drag_focus_agent inout_drag_focus;
  215.  
  216.    /** Text focus agent. */
  217.    public static text_focus_agent text_focus;
  218.  
  219.    /**
  220.     * This is the agent for handling the work procedures set up 
  221.     * for doing multithreaded programming.
  222.     */
  223.    public static work_agent work;
  224.  
  225.    /** 
  226.     * Animation agent.
  227.     * This agent handles the scheduling of animation events (via its
  228.     * 'transitions' notion to interested interactors.  It will deliver
  229.     * these events to any interactor scheduling a transition, independent
  230.     * of other factors such as visibility, being connected to the 
  231.     * tree, etc.
  232.     */
  233.    public static animation_agent animation;
  234.  
  235.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  236.  
  237.   /** 
  238.    * Positional input policy.  This policy delivers inputs to objects which
  239.    * are found under the cursor.
  240.    */
  241.    public static positional_policy_class positional_policy; 
  242.  
  243.   /** 
  244.    * Raw input event positional dispatch agent.  This agent works under 
  245.    * the positional policy and delivers raw events to objects under the 
  246.    * cursor.  This is here primarily as a hook for implementing unusual 
  247.    * actions  (although a lot of things it might be used for are probably 
  248.    * better handled by adding new policies and/or agents, so you might want to 
  249.    * consider that before building something with this).
  250.    */
  251.    public static raw_positional_agent raw_positional;
  252.  
  253.    /** 
  254.     * Agent that combines press and move_drag.  This is a hybrid policy 
  255.     * that accepts press then makes the object it would have been delivered 
  256.     * to the move_drag focus.
  257.     */ 
  258.    public static move_press_drag_agent move_press_drag;
  259.  
  260.    /** 
  261.     * Agent that combines press and grow_drag.  This is a hybrid policy 
  262.     * that accepts press then makes the object it would have been delivered 
  263.     * to the grow_drag focus.
  264.     */ 
  265.    public static grow_press_drag_agent grow_press_drag;
  266.  
  267.    /** 
  268.     * Agent for inout_press_dragging.  This is a hybrid policy that accepts 
  269.     * press then makes the object it would have been delivered to the 
  270.     * inout_drag focus.
  271.     */
  272.    public static inout_press_drag_agent inout_press_drag;
  273.  
  274.    /** 
  275.     * Agent that combines press and simple_drag .  This is a hybrid policy 
  276.     * that accepts press then makes the object it would have been delivered 
  277.     * to the simple_drag focus.
  278.     */ 
  279.    public static simple_press_drag_agent simple_press_drag;
  280.  
  281.    /** Agent for pressable, clickable, and double_clickable. */
  282.    public static click_agent press_click_agent;
  283.  
  284.    /** Agent for maintaining a currently selected set with mouse presses */
  285.    public static selection_agent_class selection_agent;
  286.  
  287.   /**
  288.    * Agent that handles the pointable protocol for telling
  289.    * when objects are entered or exited.
  290.    */
  291.   public static point_agent_class point_agent;
  292.  
  293.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  294.  
  295.   protected static void install_standard_policies() 
  296. {
  297.       /*----------------------*/
  298.       /* monitor focus policy */
  299.       /*----------------------*/
  300.       monitor_focus_policy = new mon_focus_policy_class();
  301.       install_policy_after(monitor_focus_policy, null);
  302.  
  303.       /* monitor agents */
  304.  
  305.       /* event tracer that just prints a debug trace of events */
  306.       event_tracer = new event_trace_agent();
  307.       monitor_focus_policy.add_agent_after(event_tracer, null);
  308.  
  309.       /* agent for tracking mouse state changes anywhere */
  310.       click_tracker = new click_track_agent();
  311.       monitor_focus_policy.add_agent_after(click_tracker, null);
  312.  
  313.       /* raw focus to use as a hook for extensions */
  314.       raw_monitor = new raw_focus_agent();
  315.       monitor_focus_policy.add_agent_after(raw_monitor, null);
  316.  
  317.       /*-----------------------*/
  318.       /* (normal) focus policy */
  319.       /*-----------------------*/ 
  320.       focus_policy = new  focus_policy_class();
  321.       install_policy_after(focus_policy, null);
  322.  
  323.       /* focus agents */
  324.  
  325.       /* raw focus to use as a hook for extensions */
  326.       raw_focus = new raw_focus_agent();
  327.       focus_policy.add_agent_after(raw_focus, null);
  328.  
  329.       /* simple drag focus */
  330.       simple_drag_focus = new simple_drag_focus_agent();
  331.       focus_policy.add_agent_after(simple_drag_focus, null);
  332.  
  333.       /* move-drag focus */
  334.       move_drag_focus = new move_drag_focus_agent();
  335.       focus_policy.add_agent_after(move_drag_focus, null);
  336.  
  337.       /* grow-drag focus */
  338.       grow_drag_focus = new grow_drag_focus_agent();
  339.       focus_policy.add_agent_after(grow_drag_focus, null);
  340.  
  341.       /* snap-drag focus */
  342.       snap_drag_focus = new snap_drag_agent();
  343.       focus_policy.add_agent_after(snap_drag_focus, null);
  344.  
  345.       /* inout drag focus */
  346.       inout_drag_focus = new inout_drag_focus_agent();
  347.       focus_policy.add_agent_after(inout_drag_focus, null);
  348.  
  349.       /* text focus */
  350.       text_focus = new text_focus_agent();
  351.       focus_policy.add_agent_after(text_focus, null);
  352.  
  353.       /* add an animation agent */
  354.       animation = new animation_agent();
  355.       focus_policy.add_agent_after(animation,null);
  356.  
  357.       /* work proc */
  358.       work=new work_agent();
  359.       focus_policy.add_agent_after(work,null);
  360.  
  361.       /*-------------------*/
  362.       /* positional policy */
  363.       /*-------------------*/
  364.       positional_policy = new positional_policy_class();
  365.       install_policy_after(positional_policy, null);
  366.  
  367.       /* positional agents */
  368.  
  369.       /* raw positional to use as a hook for extensions */
  370.       raw_positional = new raw_positional_agent();
  371.       positional_policy.add_agent_after(raw_positional, null);
  372.  
  373.       /* move_press_drag agent */
  374.       move_press_drag = new move_press_drag_agent();
  375.       positional_policy.add_agent_after(move_press_drag, null);
  376.  
  377.       /* grow_press_drag agent */
  378.       grow_press_drag = new grow_press_drag_agent();
  379.       positional_policy.add_agent_after(grow_press_drag, null);
  380.  
  381.       /* inout version of press_drag */
  382.       inout_press_drag = new inout_press_drag_agent();
  383.       positional_policy.add_agent_after(inout_press_drag, null);
  384.  
  385.       /* simple_press_drag agent */
  386.       simple_press_drag = new simple_press_drag_agent();
  387.       positional_policy.add_agent_after(simple_press_drag, null);
  388.  
  389.       /** object that does press, click, and double-click */
  390.       press_click_agent = new click_agent();
  391.       positional_policy.add_agent_after(press_click_agent, null);
  392.  
  393.       /** currently selected set agent */
  394.       selection_agent = new selection_agent_class();
  395.       positional_policy.add_agent_after(selection_agent, null);
  396.  
  397.       /* The agent for handling the pointable interface */
  398.       point_agent=new point_agent_class();
  399.       positional_policy.add_agent_after(point_agent,null);
  400.  
  401.     }
  402.  
  403.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  404.  
  405.   /** 
  406.    * Install a new policy after an existing one (or at the end of the 
  407.    * policy list).
  408.    * @param input_policy add   the policy to add.
  409.    * @param input_policy after the policy to put it after.  If this is null, we
  410.    *                           install at the end of the list.
  411.    */
  412.   public static void install_policy_after(
  413.     input_policy add, 
  414.     input_policy after) 
  415. {
  416.       /* if we have nothing to go after put it at the end */
  417.       if (after == null)
  418.     _policy_list.addElement(add);
  419.       else
  420.     {
  421.       int indx = _policy_list.indexOf(after);
  422.       if (indx < 0) 
  423.         /* no such policy -- throw an exception */
  424.         throw new sub_arctic_error(
  425.           "Attempt to install input policy after uninstalled policy");
  426.       else
  427.          /* put it right after the one given */
  428.         _policy_list.insertElementAt(add, indx+1);
  429.     }
  430.     }
  431.  
  432.    //had:
  433.    //* @exception bad_value if after refers to a policy that's not installed in 
  434.    //*                      the policy list.
  435.  
  436.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  437.  
  438.   /** 
  439.    * Install a new policy before an existing one (or at the beginning of the 
  440.    * policy list).
  441.    * @param input_policy add   the policy to add.
  442.    * @param input_policy after the policy to put it before.  If this is null, we
  443.    *                           install at the beginning of the list.
  444.    */
  445.   public static void install_policy_before(
  446.     input_policy add, 
  447.     input_policy before) 
  448. {
  449.       /* if we have nothing to go before put it at the beginning */
  450.       if (before == null)
  451.     _policy_list.insertElementAt(add,0);
  452.       else
  453.     {
  454.       int indx = _policy_list.indexOf(before);
  455.       if (indx < 0) 
  456.         /* no such policy -- throw an exception */
  457.         throw new sub_arctic_error(
  458.           "Attempt to install input policy before uninstalled policy");
  459.       else
  460.          /* put it right before the one given */
  461.         _policy_list.insertElementAt(add, indx);
  462.     }
  463.     }
  464.  
  465.    //had:
  466.    //*@exception bad_value if before refers to a policy that's not installed in 
  467.    //*                      the policy list.
  468.  
  469.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  470.  
  471.   /** 
  472.    * Add a top_level object to the set of active top_level objects.
  473.    * @param top_level int_obj the top_level interactor to add.
  474.    */
  475.   public static void add_top_level(top_level int_obj)
  476.     {
  477.       /* add it to our list */
  478.       _top_level_interactors.addElement(int_obj);
  479.     }
  480.  
  481.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  482.  
  483.   /** 
  484.    * Remove a top_level object from the set of active top_level objects.
  485.    * @param top_level int_obj the top_level interactor to remove.
  486.    */
  487.   public static void remove_top_level(top_level int_obj)
  488.     {
  489.       _top_level_interactors.removeElement(int_obj);
  490.     }
  491.  
  492.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  493.  
  494.   /** 
  495.    * Indicate that an AWT component that will be hosting a sub_arctic
  496.    * top_level object has been created.
  497.    * @param Component awt_comp the host component.
  498.    */
  499.   public static void register_awt_component(Component awt_comp)
  500.     {
  501.       /* record the component */
  502.       _all_awt_components.addElement(awt_comp);
  503.  
  504.       /* walk up the parent chain to find and record the hosting applet */
  505.       for (Component c = awt_comp; c != null; c = c.getParent())
  506.     if (c instanceof Applet)
  507.       {
  508.         _all_applets.addElement(c);
  509.         break;
  510.       }
  511.     }
  512.  
  513.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  514.  
  515.   /** 
  516.    * Indicate that an AWT component that has been hosting a sub_arctic
  517.    * top_level object is not longer doing so.
  518.    * @param Component awt_comp the component that is no longer a host.
  519.    */
  520.   public static void unregister_awt_component(Component awt_comp)
  521.     {
  522.       _all_awt_components.removeElement(awt_comp);
  523.  
  524.       /* walk up the parent chain to find and remove the hosting applet */
  525.       for (Component c = awt_comp; c != null; c = c.getParent())
  526.     if (c instanceof Applet)
  527.       {
  528.         _all_applets.removeElement(c);
  529.         break;
  530.       }
  531.     }
  532.  
  533.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  534.  
  535.   /** 
  536.    * Indicate whether there is something in the system that is damaged and 
  537.    * needs to be redrawn.
  538.    * @returns boolean true if there is unfixed damage pending.
  539.    */
  540.   public static boolean something_is_damaged() 
  541.     {
  542.       return _something_is_damaged;
  543.     }
  544.  
  545.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  546.  
  547.   /**
  548.    * Report to the system that a top_level object has recorded some damage that
  549.    * requires it to be redrawn.  This report gets passed on to AWT so that 
  550.    * it schedules an update/repaint.
  551.    *
  552.    * @param top_level from_obj the object reporting the damage.
  553.    */
  554.   public static void report_damage(top_level from_obj) 
  555.     {
  556.       _something_is_damaged = true;
  557.       if (from_obj.awt_parent() != null)
  558.         from_obj.awt_parent().repaint();
  559.  
  560.       // look into this again later:
  561.       // we may want to batch up these calls to repaint rather than make them
  562.       // every time we get damage
  563.     }
  564.  
  565.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  566.  
  567.   /**
  568.    * This is a list of dispatch_agents who would like to be informed
  569.    * whenever an event was successfully dispatched. This is important for
  570.    * agents which need to update their state machines on the next 
  571.    * event regardless of who dispatched it
  572.    */
  573.   protected static Vector after_dispatch = new Vector(10);
  574.  
  575.   /**
  576.    * Add an agent to the list of agents interested in the after dispatch hook.  
  577.    *
  578.    * @param dispatch_agent agent the agent to add to the list of interested 
  579.    *                             agents.
  580.    */
  581.   public static void add_to_after_dispatch_list(dispatch_agent agent) {
  582.     /* don't bother adding more than once */
  583.     if (after_dispatch.contains(agent)) return;
  584.     /* put it in */
  585.     after_dispatch.addElement(agent);
  586.   }
  587.  
  588.   /**
  589.    * Remove an agent from the list of dispatch_agents which are 
  590.    * interested in the after dispatch hook. Attempting to remove
  591.    * an agent which is not in the list has no effect.
  592.    * @param dispatch_agent agent the agent to remove.
  593.    */
  594.   public static void remove_from_after_dispatch_list(dispatch_agent agent){
  595.     /* the vector does what we want here */
  596.     after_dispatch.removeElement(agent);
  597.   }
  598.  
  599.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  600.  
  601.   /** 
  602.    * Counter for event sequence numbers.  This is incremented for each 
  603.    * new event.  These sequence numbers are used by some parts of the system 
  604.    * to determine when cached values associated with one event dispatch are 
  605.    * invalid. 
  606.    */
  607.   protected static int _event_seq_num = 0;
  608.  
  609.   /** 
  610.    * Return the sequence number for the current event.  This is used by
  611.    * some parts of the system to determine when cached values associated with
  612.    * one event dispatch are invalid. 
  613.    *
  614.    * @return int the sequence number for the current event.
  615.    */
  616.   public static int event_seq_num() {return _event_seq_num;}
  617.  
  618.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  619.  
  620.   /** 
  621.    * This method dispatches a single event (that occurred "inside of" the
  622.    * given top level object) to the appropriate interactor object(s) in the 
  623.    * interface.  Note: that the event is not necessarily delivered to an 
  624.    * object in the subtree rooted by top_obj -- this depends on the input
  625.    * policy object which ends up dispatching it.  For example, the focus
  626.    * policy will send a key press event to the current text focus object
  627.    * regardless of where the mouse it pointing.<p>
  628.    *
  629.    * Note: this method is synchronized so that only one event dispatch or 
  630.    * redraw can be going on at a time.  This is necessary for maintaining 
  631.    * the integrity of the overall system dispatch-redraw "loop".  However, 
  632.    * this is not sufficient to make the whole system thread-safe.  Access to
  633.    * various interactor trees should always be done through the work_proc 
  634.    * interface.
  635.    *
  636.    * @param Event evt the event to dispatch.
  637.    * @param top_level the top_level object it occured within.
  638.    */
  639.   public static synchronized boolean dispatch_event(Event evt,top_level top_obj)
  640.     {
  641.       event our_event;
  642.       input_policy policy;
  643.       dispatch_agent agent;
  644.       boolean ret_val = false; /* we change this if someone dispatches */
  645.       /* increment the sequence number so caches get invalidated as needed */
  646.       _event_seq_num++;
  647.  
  648.       /* create a sub_arctic event out of the awt event */
  649.       our_event = new event(evt,top_obj);
  650.  
  651.       /* walk down the dispatch policy list */
  652.       for (int i = 0; i < _policy_list.size(); i++)
  653.     {
  654.       /* try to dispatch with the policy.  if it succeeds, we are done. */
  655.        policy = (input_policy)_policy_list.elementAt(i);
  656.        if (policy.dispatch_event(our_event)) {
  657.          ret_val=true;
  658.          break;
  659.        }
  660.     }
  661.       
  662.       /* walk through the list of after_dispatch agents */
  663.       for (int i=0; i<after_dispatch.size(); ++i){
  664.     agent=(dispatch_agent)after_dispatch.elementAt(i);
  665.     agent.after_dispatch_notify(our_event,ret_val);
  666.       }
  667.       /* if nobody wanted it, this will still be false */
  668.       return ret_val;
  669.     }
  670.  
  671.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  672.  
  673.   /** 
  674.    * This method causes a redraw of the given interactor tree (this is 
  675.    * normally called on the basis of a redraw request from AWT).  A redraw
  676.    * request is handled by first laying out the objects in the interactor
  677.    * tree by calling configure() on the root (note: for the most part, this
  678.    * normally results in evaluating all the constraints that size and position
  679.    * objects in the tree).  After all objects have been properly laid out,
  680.    * (which may cause additional areas of the drawable to become damaged)
  681.    * the smallest rectangle enclosing the damaged regions -- that is the
  682.    * regions which might have changed appearance in some way -- are redrawn
  683.    * by calling draw_self on the root of the tree.<p>
  684.    *
  685.    * Note: this method is synchronized so that only one event dispatch or 
  686.    * redraw can be going on at a time.  This is necessary for maintaining 
  687.    * the integrity of the overall system dispatch-redraw "loop".  However, 
  688.    * this is not sufficient to make the whole system thread-safe.  Access  to
  689.    * various interactor trees should always be done through the work_proc
  690.    * interface.
  691.    * 
  692.    * @param top_level top_obj the top_level object to redraw.
  693.    * @param drawable  surface the drawing surface to redraw it on (this
  694.    *                  normally refers directly to the screen).
  695.    */
  696.   public static synchronized void do_redraw(top_level top_obj, drawable surface)
  697.     {
  698.       top_obj.configure();
  699.       top_obj.draw_self(surface);
  700.     }
  701.  
  702.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  703.  
  704.   /** 
  705.    * An ImageObserver object that does nothing.  This is returned by 
  706.    * an_observer() and used internally by the system to provide an 
  707.    * observer object where we don't really need or want to observe. 
  708.    */
  709.   protected static ImageObserver _an_observer = new ignore_observer();
  710.  
  711.   /** 
  712.    * Return an ImageObserver that does nothing.  This is useful in places
  713.    * where an ImageObserver object is needed, but we don't really expect
  714.    * to see any updates (and/or wouldn't know what to do with them if we
  715.    * got them).
  716.    * 
  717.    * @return ImageObserver a non-observing observer object.
  718.    */
  719.   public static ImageObserver an_observer() {return _an_observer;}
  720.  
  721.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  722.  
  723.   /** 
  724.    * Return some active AWT component.  Most code outside the toolkit itself
  725.    * should not need this, but it can be useful in various AWT routines that 
  726.    * require some component to get a piece of information (some of this is now 
  727.    * provided by a toolkit object obtained by default_toolkit() but not 
  728.    * everything).  If a specific component is needed, use 
  729.    * interactor.get_awt_component() instead.
  730.    *
  731.    * @return Component an AWT Component object which is currently hosting a
  732.    *                   subArctic interface (or null if there currently are 
  733.    *                   none).
  734.    */
  735.   public static Component an_awt_component()
  736.     {
  737.       /* just use the first component in the component list */
  738.       if (_all_awt_components.size() > 0)
  739.         return (Component)_all_awt_components.elementAt(0);
  740.       else
  741.         return null;
  742.     }
  743.  
  744.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  745.  
  746.   /** 
  747.    * Return some active AWT applet.  Most code outside the toolkit itself
  748.    * should not need this.
  749.    *
  750.    * @return Applet an applet object which is currently hosting a
  751.    *                subArctic interface (or null if there currently are none).
  752.    */
  753.   public static Applet an_applet()
  754.     {
  755.       /* just use the first applet in the applet list */
  756.       if (_all_applets.size() > 0)
  757.         return (Applet)_all_applets.elementAt(0);
  758.       else
  759.         return null;
  760.     }
  761.  
  762.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  763.  
  764.   /** 
  765.    * Get a FontMetrics object for the given font. 
  766.    * @param Font for_font the font we want the metrics object for.
  767.    * @return FontMetrics the metrics object for that font.
  768.    */
  769.   public static FontMetrics get_metrics(Font for_font)
  770.     {
  771.       /* get it from the AWT native toolkit object */
  772.       return default_toolkit().getFontMetrics(for_font);
  773.     }
  774.  
  775.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  776.  
  777.   /** 
  778.    * An image that we provide when a requested image can't be loaded or 
  779.    * otherwise has a problem.  This will be statically initialized in memory
  780.    * so it will always be there.
  781.    */
  782.   protected static Image        _broken = null;
  783.  
  784.   /** 
  785.    * A loaded_image that we provide when a requested image can't be loaded or 
  786.    * otherwise has a problem.  This will be statically initialized in memory
  787.    * so it will always be there. 
  788.    */
  789.   protected static loaded_image _broken_image_icon = null;
  790.  
  791.   /** 
  792.    * Provide a standard "broken image" icon that can be used to substitute
  793.    * for images that couldn't be loaded for some reason or another. 
  794.    * This gets built from static data on first use.
  795.    */
  796.   public static loaded_image broken_image_icon()
  797.     {
  798.       /* if we haven't done this before, build the image "manually" */
  799.       if (_broken_image_icon == null)
  800.     {
  801.       _broken = build_broken_icon();
  802.  
  803.       /* create the loaded_image object */
  804.       _broken_image_icon = new loaded_image(_broken);
  805.     }
  806.  
  807.       return _broken_image_icon;
  808.     }
  809.  
  810.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  811.  
  812.   /**
  813.    * This is the media id counter.
  814.    */
  815.   static int media_counter=0;
  816.  
  817.   /**
  818.    * This is the media tracker for use with the manager. Note that
  819.    * there can and WILL be concurrent access to the media tracker
  820.    * and to the counter. You better be sure you know what you
  821.    * are doing before you dink with this.
  822.    */
  823.   static private MediaTracker tracker;
  824.  
  825.   /**
  826.    * This object is a lock for the manager's media tracker.
  827.    * We can't lock the media tracker itself, because it
  828.    * can't be created at class load time. Thus we need something
  829.    * to lock on to insure that the tracker is ok, including
  830.    * in the case where it is not yet created.
  831.    */
  832.   static private Integer media_lock=new Integer(0); // who cares
  833.  
  834.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  835.  
  836.   /** 
  837.    * Block until the given image is loaded (or there is an error in loading).
  838.    * Returns false if there was an error in loading.
  839.    * 
  840.    * @param Image img the image to wait for
  841.    * @return boolean true if everything went ok
  842.    */
  843.   public static boolean wait_for_image(Image img)
  844.   {
  845.     int ct=0; // this is a copy of the t
  846.     MediaTracker track;
  847.  
  848.     /* first we want to make sure that we can get things initialized
  849.         ok... we are going to do a "test and set" so that we are
  850.      sure that we got the media tracker initialized and that
  851.       we updated the counter inside the lock 
  852.       */
  853.     synchronized (media_lock) {
  854.       if (tracker==null) {
  855.     tracker=new MediaTracker(an_awt_component());
  856.       }
  857.       track=tracker;
  858.       ct=media_counter++;
  859.     }
  860.  
  861.     //    synchronized (img) {
  862.     //track=new MediaTracker(an_awt_component());
  863.       track.addImage(img, ct);
  864.       try { 
  865.     track.waitForID(ct); 
  866.       } catch(InterruptedException ex) { }
  867.       //    }
  868.  
  869.       /* determine and return status */
  870.       return !track.isErrorID(ct);
  871.   }
  872.  
  873.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  874.  
  875.   /** 
  876.    * Load an image from the given URL.  If or there is an error in loading, 
  877.    * the broken image icon is returned instead.
  878.    *
  879.    * @param URL from_url the location to load the image from.
  880.    * @return loaded_image the resulting image (or the broken image if there was
  881.    *                      a problem).
  882.    */
  883.   public static loaded_image load_image(URL from_url)
  884.     {
  885.       Object fetch_result;
  886.  
  887.       /* URL.getContent is is broken in Netscape (at least at v2.01).  It
  888.        * seems to throw an IOException for pretty much any image you try to
  889.        * load.  Consequently, here we try to load using an stashed applet 
  890.        * first (that works in Netscape).  Only if we don't have an applet
  891.        * (probably never) do we do it the right way.  The use of the applet
  892.        * here should go away should Netscape ever get fixed.
  893.        */
  894.        // this should get put under workaround support
  895.  
  896.       /* if we have an applet to work with load the image with that */
  897.       Applet an_ap = an_applet();
  898.       if (an_ap != null)
  899.     {
  900.       fetch_result = an_ap.getImage(from_url);
  901.     }
  902.       else
  903.     {
  904.       try {
  905.         /* get whatever is out there */
  906.         fetch_result = from_url.getContent();
  907.       } catch (IOException ex) {
  908.         return broken_image_icon();
  909.       }
  910.     }
  911.  
  912.       /* see if we got an image.  note: there is no standard about what gets
  913.        * returned from getContent(), so we have to handle several 
  914.        * possibilities. */
  915.       if (fetch_result instanceof ImageProducer)
  916.     {
  917.       return new loaded_image(
  918.            default_toolkit().createImage((ImageProducer)fetch_result));
  919.     }
  920.       else if (fetch_result instanceof Image)
  921.     {
  922.           return new loaded_image((Image)fetch_result);
  923.     }
  924.       else
  925.     {
  926.       return broken_image_icon();
  927.     }
  928.     }
  929.  
  930.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  931.  
  932.   /** 
  933.    * Load an image from a location named relative to the document that 
  934.    * contains the given applet.  If or there is an error in loading, the 
  935.    * broken image icon is returned instead.
  936.    *
  937.    * @param Applet host_ap         the applet that is within the page we are 
  938.    *                               fetching relative to.
  939.    * @param String image_file_name the name of the image file.
  940.    * @param loaded_image the resulting image (or the broken image if there was
  941.    *                     a problem).
  942.    */
  943.   public static loaded_image load_doc_image(
  944.     Applet host_ap, 
  945.     String image_file_name) throws MalformedURLException 
  946. {
  947.       URL doc_base, image_url;
  948.  
  949.       /* get the base URL for the loaded document */
  950.       doc_base = host_ap.getDocumentBase();
  951.  
  952.       /* append the file name */
  953.       image_url = new URL(doc_base, image_file_name);
  954.  
  955.       /* try to load the image */
  956.       return load_image(image_url);
  957.     }
  958.  
  959.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  960.  
  961.   /** 
  962.    * Load an image from a location named relative to the location of the 
  963.    * code (the .class file) for the given applet.  If or there is an error 
  964.    * in loading, the  broken image icon is returned instead.
  965.    *
  966.    * @param Applet host_ap         the applet whose code we are fetching 
  967.    *                               relative to.
  968.    * @param String image_file_name the name of the image file.
  969.    * @param loaded_image the resulting image (or the broken image if there was
  970.    *                     a problem).
  971.    */
  972.   public static loaded_image load_code_image(
  973.     Applet host_ap, 
  974.     String image_file_name)
  975.     throws MalformedURLException
  976.     {
  977.       URL code_base, image_url;
  978.  
  979.       /* get the base URL for the loaded document */
  980.       code_base = host_ap.getCodeBase();
  981.  
  982.       /* append the file name */
  983.       image_url = new URL(code_base, image_file_name);
  984.  
  985.       /* try to load the image */
  986.       return load_image(image_url);
  987.     }
  988.  
  989.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  990.  
  991.   /** 
  992.    * Debugging routine to print a trace of the current call stack on 
  993.    * on the given PrintStream, then return.  
  994.    *
  995.    * @param PrintStream strm where we print the call stack trace.
  996.    */
  997.   public static void print_stack_trace(PrintStream strm)
  998.     {
  999.       /* throw and immediately catch an exception to get the trace */
  1000.       try {
  1001.     throw new sub_arctic_error();
  1002.       } catch (stack_trace ex) { ex.printStackTrace(strm); }
  1003.  
  1004.       // not clear we have to actually throw the exception, but...
  1005.     }
  1006.     
  1007.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1008.  
  1009.   /** 
  1010.    * Debugging routine to print a trace of the current call stack on 
  1011.    * on System.err, then return.  
  1012.    */
  1013.   public static void print_stack_trace()
  1014.     {
  1015.       /* throw and immediately catch an exception to get the trace */
  1016.       try {
  1017.     throw new sub_arctic_error();
  1018.       } catch (stack_trace ex) { ex.printStackTrace(System.err); }
  1019.     }
  1020.     
  1021.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1022.  
  1023.   /** 
  1024.    * Option flag to handle an unexpected exception by printing a stack trace
  1025.    * on System.error and then exiting.  This is the default.
  1026.    */
  1027.   public static final int EXCEPTION_STACK_CRASH = 0;
  1028.  
  1029.   /** 
  1030.    * Option flag to handle an unexpected exception by printing a stack trace
  1031.    * on System.error and then continuing.
  1032.    */
  1033.   public static final int EXCEPTION_PRINT_STACK = 1;
  1034.  
  1035.   /** 
  1036.    *Option flag to handle an unexpected exception by printing the exception
  1037.    * message to System.err and then exiting.
  1038.    */
  1039.   public static final int EXCEPTION_MESSAGE_CRASH = 2;
  1040.  
  1041.   /** 
  1042.    * Option flag to handle an unexpected exception by printing the exception
  1043.    * message to System.err and then continuing.
  1044.    */
  1045.   public static final int EXCEPTION_PRINT_MESSAGE = 3;
  1046.  
  1047.   /** 
  1048.    * Option flag to handle an unexpected exception by sending the 
  1049.    * "handle_exception()" message to the object previously registered
  1050.    * via "handle_exceptions_with()".  This this object was never registered,
  1051.    * or is null, then the default of printing a stack trace and exiting is
  1052.    * used as a fallback.
  1053.    */
  1054.   public static final int EXCEPTION_CUSTOM = 4;
  1055.  
  1056.   /** 
  1057.    * Option flag to ignore unexpected exceptions -- this is generally a very 
  1058.    * bad idea, think twice before using this.
  1059.    */
  1060.   public static final int EXCEPTION_IGNORE = 5; 
  1061.  
  1062.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1063.  
  1064.   /** 
  1065.    * The current exception handling response.  This must be one of the
  1066.    * EXCEPTION_* option values. 
  1067.    */
  1068.   protected static int _handling_mechanism = EXCEPTION_STACK_CRASH; 
  1069.  
  1070.   /** 
  1071.    * The current exception handling response.  This will be one of the 
  1072.    * EXCEPTION_* option values. 
  1073.    */
  1074.   public static int handling_mechanism() {return _handling_mechanism;}
  1075.  
  1076.   /** 
  1077.    * The current custom exception handling object (if any).  When exception
  1078.    * handling is being done via EXCEPTION_CUSTOM, this object is passed 
  1079.    * exceptions to handle.
  1080.    */
  1081.   protected static exception_handler _handle_object = null;
  1082.  
  1083.   /** 
  1084.    * The current custom exception handling object (if any). When exception
  1085.    * handling is being done via EXCEPTION_CUSTOM, this object is passed
  1086.    * exceptions to handle.
  1087.    */
  1088.   public static exception_handler handle_object() {return _handle_object;}
  1089.  
  1090.   /** 
  1091.    * Establish how unexpected exceptions are handled.  The handling_type 
  1092.    * parameter indicates one of several possible responses (see the 
  1093.    * EXCEPTION_* constants).  The handler parameter indicates an object that 
  1094.    * will handle the exception if  EXCEPTION_CUSTOM is used (it can passed is 
  1095.    * null otherwise). 
  1096.    * 
  1097.    * @param int               handling_type code indicating how to handle an 
  1098.    *                                        unexpected exception.
  1099.    * @param exception_handler handler       the handler object that gets the 
  1100.    *                                        exception if handling_type is 
  1101.    *                                        EXCEPTION_CUSTOM.
  1102.    */
  1103.   public static void handle_exceptions_with(
  1104.     int handling_type, exception_handler handler) 
  1105.     {
  1106.       _handling_mechanism = handling_type;
  1107.       _handle_object = handler;
  1108.     }
  1109.  
  1110.   /** Establish how unexpected exceptions are handled.  The handling_type 
  1111.    *  parameter indicates one of several possible standard responses (see the 
  1112.    *  EXCEPTION_* constants). 
  1113.    *
  1114.    * @param int               handling_type code indicating how to handle an 
  1115.    *                                        unexpected exception.
  1116.    */
  1117.   public static void handle_exceptions_with(int handling_type)
  1118.     {
  1119.       handle_exceptions_with(handling_type, null);
  1120.     }
  1121.  
  1122.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1123.  
  1124.   /** 
  1125.    * Handle an unexpected exception that arrived at some part of the toolkit.
  1126.    * The specific action undertaken is controlled by the last call to 
  1127.    * handle_exceptions_with().
  1128.    * 
  1129.    * @see #handle_exceptions_with()
  1130.    * @param Exception except the unexpected exception.
  1131.    */
  1132.   public static void handle_unexpected_exception(Exception except)
  1133.     {
  1134.       /* Do what we've been told to do */
  1135.       switch (_handling_mechanism)
  1136.     {
  1137.       default:
  1138.           case EXCEPTION_STACK_CRASH:
  1139.         except.printStackTrace(System.err);
  1140.         System.exit(1);
  1141.       break;
  1142.  
  1143.           case EXCEPTION_PRINT_STACK:
  1144.         except.printStackTrace(System.err);
  1145.       break;
  1146.  
  1147.           case EXCEPTION_MESSAGE_CRASH:
  1148.         System.err.println(except.getMessage());
  1149.         System.exit(1);
  1150.       break;
  1151.  
  1152.           case EXCEPTION_PRINT_MESSAGE:
  1153.         System.err.println(except.getMessage());
  1154.       break;
  1155.  
  1156.           case EXCEPTION_CUSTOM:
  1157.         if (_handle_object != null) 
  1158.           _handle_object.handle_exception(except);
  1159.         else
  1160.           {
  1161.             except.printStackTrace(System.err);
  1162.             System.exit(1);
  1163.           }
  1164.       break;
  1165.  
  1166.           case EXCEPTION_IGNORE:
  1167.         /* do nothing... */
  1168.       break;
  1169.     }
  1170.     }
  1171.  
  1172.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1173.  
  1174.   // cycle handling needs its own set of constants...
  1175.  
  1176.   /** 
  1177.    * The current constraint cycle handling response.  This should have
  1178.    * one of the EXCEPTION_* values that designate a response to an
  1179.    * unexpected exception.  Default is to ignore the cycle.
  1180.    */
  1181.   protected static int _cycle_handling_mechanism = EXCEPTION_IGNORE; 
  1182.  
  1183.   /** 
  1184.    * The current constraint cycle handling response.  This should have
  1185.    * one of the EXCEPTION_* values that designate a response to an
  1186.    * unexpected exception.  Default is to ignore the cycle.
  1187.    */
  1188.   public static int cycle_handling_mechanism() {return _handling_mechanism;}
  1189.  
  1190.   /** 
  1191.    * The current custom constraint handling handling object (if any).  When 
  1192.    * cycle handling is being done via EXCEPTION_CUSTOM, this object is passed
  1193.    * cycles to handle.
  1194.    */
  1195.   protected static cycle_handler _cycle_handle_object = null;
  1196.  
  1197.   /** 
  1198.    * The current custom exception handling object (if any).  When
  1199.    * cycle handling is being done via EXCEPTION_CUSTOM, this object is passed
  1200.    * cycles to handle.
  1201.    */
  1202.   public static cycle_handler cycle_handle_object() 
  1203.     {return _cycle_handle_object;}
  1204.  
  1205.   /** 
  1206.    * Establish how constraint cycles are handled.  The handling_type 
  1207.    * parameter indicates one of several possible responses (see the 
  1208.    * EXCEPTION_* constants).  The handler parameter indicates an object that 
  1209.    * will handle the cycle if  EXCEPTION_CUSTOM is used (it can be passed as 
  1210.    * null otherwise). 
  1211.    * 
  1212.    * @param int           handling_type the code indicating how to handle the 
  1213.    *                                    cycle.
  1214.    * @param cycle_handler handler       the optional handler object used when
  1215.    *                                    handling_type is EXCEPTION_CUSTOM.
  1216.    */
  1217.   public static void handle_cycles_with(
  1218.     int handling_type, cycle_handler handler) 
  1219.     {
  1220.       _cycle_handling_mechanism = handling_type;
  1221.       _cycle_handle_object = handler;
  1222.     }
  1223.  
  1224.   /** 
  1225.    * Establish how constraint cycles are handled.  The handling_type 
  1226.    * parameter indicates one of several possible standard responses (see the 
  1227.    * EXCEPTION_* constants). 
  1228.    *
  1229.    * @param int           handling_type the code indicating how to handle the 
  1230.    *                                    cycle.
  1231.    */
  1232.   public static void handle_cycles_with(int handling_type)
  1233.     {
  1234.       handle_cycles_with(handling_type, null);
  1235.     }
  1236.  
  1237.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1238.  
  1239.   /** 
  1240.    * Handle a cycle.  If normal processing at the point of the cycle 
  1241.    * is to proceed, true is returned.  Otherwise, the caller of this routine
  1242.    * should leave the current value in the attribute marked up-to-date (this 
  1243.    * only happens with custom handlers).
  1244.    * 
  1245.    * @param interactor in_obj    the interactor in which the cycle was first 
  1246.    *                             detected.
  1247.    * @param int        part_code the part within that object where the cycle was
  1248.    *                             first detected.
  1249.    */
  1250.   public static boolean handle_cycle(interactor in_obj, int part_code)
  1251.     {
  1252.       /* Do what we've been told to do */
  1253.       switch (_cycle_handling_mechanism)
  1254.     {
  1255.       default:
  1256.           case EXCEPTION_STACK_CRASH:
  1257.         System.err.println("Cycle detected in " + in_obj.tag_str() + 
  1258.                    " (part_code=" + part_code + ")");
  1259.         print_stack_trace();
  1260.         System.exit(1);
  1261.       break;
  1262.  
  1263.           case EXCEPTION_PRINT_STACK:
  1264.         System.err.println("Cycle detected in " + in_obj.tag_str() + 
  1265.                    " (part_code=" + part_code + ")");
  1266.         print_stack_trace();
  1267.       break;
  1268.  
  1269.           case EXCEPTION_MESSAGE_CRASH:  
  1270.         System.err.println("Cycle detected in " + in_obj.tag_str() + 
  1271.                    " (part_code=" + part_code + ")");
  1272.         System.exit(1);
  1273.       break;
  1274.  
  1275.           case EXCEPTION_PRINT_MESSAGE:
  1276.         System.err.println("Cycle detected in " + in_obj.tag_str() + 
  1277.                    " (part_code=" + part_code + ")");
  1278.       break;
  1279.  
  1280.           case EXCEPTION_CUSTOM:
  1281.         if (_cycle_handle_object != null) 
  1282.           return _cycle_handle_object.handle_cycle(in_obj, part_code);
  1283.         else
  1284.           {
  1285.         print_stack_trace();
  1286.             System.exit(1);
  1287.           }
  1288.       break;
  1289.  
  1290.           case EXCEPTION_IGNORE:
  1291.         /* do nothing... */
  1292.       break;
  1293.     }
  1294.  
  1295.       /* unless the custom handler returned something we just proceed with 
  1296.        * evaluation */
  1297.       return true;
  1298.     }
  1299.  
  1300.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1301.  
  1302.   /** 
  1303.    * Establish an associative link between the given part of a value_consumer 
  1304.    * (usually an interactor) and part of a value_provider (usually an 
  1305.    * external_constraint) that gives it a value.  (This is part of the 
  1306.    * "external" or "heavyweight" constraint system.)
  1307.    *
  1308.    * @param value_consumer cons_obj  the object being constrained.
  1309.    * @param int            cons_part the part within that object being 
  1310.    *                                 constrained.
  1311.    * @param value_provider prov_obj  the object (often a constraint) providing
  1312.    *                                 the value.
  1313.    * @param int            prov_part the part of that object that provides the 
  1314.    *                                 value.
  1315.    */
  1316.   public static void establish_extern_constraint(
  1317.     value_consumer cons_obj, 
  1318.     int            cons_part,
  1319.     value_provider prov_obj,
  1320.     int            prov_part)
  1321.     {
  1322.       consumer_part_ref key =   new consumer_part_ref(cons_obj, cons_part);
  1323.       provider_part_ref entry = new provider_part_ref(prov_obj, prov_part);
  1324.  
  1325.       /* put the provider part in the table under the consumer part */
  1326.       _extern_constraints_table.put(key,entry);
  1327.  
  1328.       /* tell tell the provider its attached */
  1329.       prov_obj.attach_dependent(prov_part, cons_obj, cons_part);
  1330.     }
  1331.  
  1332.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1333.  
  1334.   /** 
  1335.    * Remove any association between the given part of a value_consumer and
  1336.    * a value_producer.  (This is part of the "external" or "heavyweight" 
  1337.    * constraint system.)
  1338.    *
  1339.    * @param value_consumer cons_obj  the object that was being constrained.
  1340.    * @param int            cons_part the part within that object that was being 
  1341.    *                                 constrained.
  1342.    * @param value_provider prov_obj  the object (often a constraint) that was 
  1343.    *                                 providing the value.
  1344.    * @param int            prov_part the part of that object that was providing
  1345.    *                                 the value.
  1346.    */
  1347.   public static void drop_extern_constraint( 
  1348.     value_consumer cons_obj, 
  1349.     int            cons_part)
  1350.     {
  1351.       provider_part_ref entry;
  1352.       consumer_part_ref key =   new consumer_part_ref(cons_obj, cons_part);
  1353.  
  1354.       /* take it out of the table */
  1355.       entry = (provider_part_ref)_extern_constraints_table.remove(key);
  1356.  
  1357.       /* let it know that its been detached */
  1358.       if (entry != null && entry.obj != null)
  1359.     entry.obj.detach_dependent(entry.part_num, cons_obj, cons_part);
  1360.     }
  1361.  
  1362.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1363.  
  1364.   /** 
  1365.    * Get the value_provider and part associated with the given value_consumer
  1366.    * part.  Returns null if no such association has been stored. (This is part 
  1367.    * of the "external" or "heavyweight" constraint system.)
  1368.    *
  1369.    * @param value_consumer cons_obj  the consumer object we determining the 
  1370.    *                                 provider (typically constraint) for.
  1371.    * @param int            cons_part the part of that object we are asking 
  1372.    *                                 about.
  1373.    * @return provider_part_ref a reference to the object and part providing the
  1374.    *                           inquired about value, or null if there is none.
  1375.    */
  1376.   public static provider_part_ref find_extern_constraint(
  1377.     value_consumer cons_obj,
  1378.     int            cons_part)
  1379.     {
  1380.       consumer_part_ref key =   new consumer_part_ref(cons_obj, cons_part);
  1381.  
  1382.       /* look it up in the table */
  1383.       return (provider_part_ref)_extern_constraints_table.get(key);
  1384.     }
  1385.  
  1386.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1387.  
  1388.   /** 
  1389.    * Add an element to the notify list being maintained for the given 
  1390.    * value_provider part.  This list represents the set of things that need
  1391.    * to be informed when the provider part changes value (or might have changed
  1392.    * value).
  1393.    *
  1394.    * @param value_provider for_prov    the object (providing a value) which 
  1395.    *                                   needs to inform others of changes.
  1396.    * @param int            for_part    the part of that object we are concerned 
  1397.    *                                   with.
  1398.    * @param value_consumer notify_obj  the object we are to notify.
  1399.    * @param int            notify_part the part of that object we are to notify.
  1400.    */
  1401.   public static void add_to_ood_notify(
  1402.     value_provider for_prov, 
  1403.     int            for_part,
  1404.     value_consumer notify_obj,
  1405.     int            notify_part)
  1406.     {
  1407.       Vector notify_list;
  1408.       provider_part_ref key   = new provider_part_ref(for_prov, for_part);
  1409.       consumer_part_ref entry = new consumer_part_ref(notify_obj, notify_part);
  1410.  
  1411.       /* get the list entry for our provider */
  1412.       notify_list = (Vector)_notify_list_table.get(key);
  1413.  
  1414.       /* if we don't have a list, make one and put it in the table */
  1415.       if (notify_list == null)
  1416.     {
  1417.       notify_list = new Vector(1);
  1418.       _notify_list_table.put(key,notify_list);
  1419.     }
  1420.  
  1421.       /* add to the end of the list */
  1422.       notify_list.addElement(entry);
  1423.     }
  1424.  
  1425.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1426.  
  1427.   /** 
  1428.    * Remove an element from the notify list being maintained for the given
  1429.    * value_provider part.  Return true if the list is then empty.
  1430.    * 
  1431.    * @param value_provider for_prov    the object (providing a value) which 
  1432.    *                                   had been notifying.
  1433.    * @param int            for_part    the part of that object we are concerned 
  1434.    *                                   with.
  1435.    * @param value_consumer notify_obj  the object we were to notify.
  1436.    * @param int            notify_part the part of that object we were to 
  1437.    *                                   notify.
  1438.    */
  1439.   public static boolean remove_ood_notify(
  1440.     value_provider for_prov, 
  1441.     int            for_part,
  1442.     value_consumer notify_obj,
  1443.     int            notify_part)
  1444.     {
  1445.       Vector notify_list;
  1446.       provider_part_ref key   = new provider_part_ref(for_prov, for_part);
  1447.       consumer_part_ref entry = new consumer_part_ref(notify_obj, notify_part);
  1448.  
  1449.       /* get the list entry for our provider */
  1450.       notify_list = (Vector)_notify_list_table.get(key);
  1451.  
  1452.       /* if we don't have a list, we are done */
  1453.       if (notify_list == null) return true;
  1454.  
  1455.       /* otherwise remove the element in question */
  1456.       notify_list.removeElement(entry);
  1457.  
  1458.       return notify_list.isEmpty();
  1459.     }
  1460.  
  1461.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1462.  
  1463.   /** 
  1464.    * Get the notify list being maintained for the given value_provider part. 
  1465.    * Returns null if no list items has been stored for the provider.
  1466.    *
  1467.    * @param value_provider for_prov the object we are asking about.
  1468.    * @param int            for_part the part of that object whose notify list 
  1469.    *                                we want.
  1470.    * @return Vector a vector of consumer_part_ref objects that the given 
  1471.    *                object/part is to notify should it change (or null if no
  1472.    *                notify list has been stored for that object).
  1473.    */
  1474.   public static Vector get_ood_notify(value_provider for_prov, int for_part)
  1475.     {
  1476.       provider_part_ref key   = new provider_part_ref(for_prov, for_part);
  1477.       return (Vector)_notify_list_table.get(key);
  1478.     }
  1479.  
  1480.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1481.  
  1482.   /** 
  1483.    * Build the "broken image" icon from static data.
  1484.    * @return Image the broken image icon.
  1485.    */
  1486.   protected static Image build_broken_icon()
  1487.     {
  1488.       int w = 33; 
  1489.       int h = 32;
  1490.       int data[] = new int[w*h];
  1491.  
  1492.       /* compose the RGB pixels for the gray value */
  1493.       for (int i=0; i<w*h; i++)
  1494.     data[i] = (255 << 24)                 | (broken_icon_data[i] << 16) | 
  1495.               (broken_icon_data[i] << 8) | broken_icon_data[i];
  1496.  
  1497.       /* build a memory image source and turn that into an image */
  1498.       return default_toolkit().createImage(
  1499.                      new MemoryImageSource(w,h, data, 0, w));
  1500.     }
  1501.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1502.  
  1503.   /** 
  1504.    * Data for icon representing a "broken" image.  This is a 33x32 icon.  The
  1505.    * data is 0..255 grayscale.
  1506.    */
  1507.   static int[] broken_icon_data = {
  1508.   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  1509.   255,255,255,255,255,255,255,255,255,255,255,255,255,255,226,255,255,
  1510.   255,209,209,209,209,209,209,209,209,209,209,209,214,223,255,229,229,
  1511.   229,229,229,229,229,229,229,229,229,229,229,229,225,209,255,255,229,
  1512.   255,229,229,229,229,229,229,229,229,229,229, 61,236,204,179,179,179,
  1513.   179,179,179,179,179,179,179,179,179,179,179, 93,209,255,255,229,179,
  1514.   131,131,131,131,131,131,131,131,131, 78,122,242,131,131,131,131,131,
  1515.   131,131,131,131,131,131,131,131,131,131, 65,209,255,255,229,179,131,
  1516.   131,131,131,131,131,131,131,131,139,176,215, 81, 89,140,131,131,131,
  1517.   131,131,131,131,131,131,131,131,131, 65,209,255,255,229,179,131,131,
  1518.   131,131,131,131,131,115, 35, 81,200,255,209,206,167,125,142,142,131,
  1519.   131,131,131,131,131,131,131,131, 65,209,255,255,229,179,131,131,131,
  1520.   131,131,131,115,  1,192,255,255,255,255,255,239,255,151,193,156,131,
  1521.   131,131,131,131,131,131,131, 65,209,255,255,229,179,131,131,131,131,
  1522.   131,131, 26,195,255,255,142,106,142,204,159,162,255,236,198,134,131,
  1523.   131,131,131,131,131,131, 65,209,255,255,229,179,131,131,131,131,131,
  1524.   115, 61,255,255, 43,206,251,132,255,225,111,255,255,173,187,131,131,
  1525.   131,131,131,131,131, 65,209,255,255,229,179,131,131,131,131,131, 82,
  1526.   162,255,209,178,162, 56,143,242,131, 65,255,255,140,239,131,131,131,
  1527.   131,131,131,131, 65,209,255,255,229,179,131,131,131,131,131, 84,203,
  1528.   255,131,236, 87, 73,255,131,131, 29,255,255,128,255,131,131,131,131,
  1529.   131,131,131, 65,209,255,255,229,179,131,131,131,131,131,140,125, 71,
  1530.    89,244,101,208,209,131, 62, 98,255,255, 64,236,131,131,131,131,131,
  1531.   131,131, 65,209,255,255,229,179,131,131,131,131,131,132,190,229,217,
  1532.   143,125,178,228, 64, 59,255,255,198,132,176,131,131,131,131,131,131,
  1533.   131, 65,209,255,255,229,179,131,131,131,131,131,131,131,131,131,131,
  1534.   131,140,229,112,255,255,226, 73,255,131,131,131,131,131,131,131,131,
  1535.    65,209,255,255,229,179,131,131,131,131,131,131,131,131,131,131, 95,
  1536.    43,255,255,255,226, 70,223, 57, 95,143,126,142,131,131,131,131, 65,
  1537.   209,255,255,208,145,128,150,154,131,131,131,109, 92, 87,158, 17,240,
  1538.   255,255,234, 17,123, 87,220,251,255,200,167,158,139,131,131, 65,214,
  1539.   255,255,255,255,255,211,153,150,100, 17,120,225,250,197,206,255,255,
  1540.   255, 96,142,255,192,131,131,140,211,215,226,159,148,103,122,255,255,
  1541.   255,179,131,132,206,215,209,203,251,242,192,183,176,255,255,255,255,
  1542.   255,222,131,131,131,131,131,131,158,222,255,255,237,222,255,255,255,
  1543.   179,131,131,131,184,229,229,142,131,131,131, 40,255,255,255,129,247,
  1544.   131,131,131,131,131,131,131,131,131,131,131,139,212,255,255,255,179,
  1545.   131,131,131,131,131,131,131,131,131,131, 81,255,255,242, 84,233,131,
  1546.   131,131,131,131,131,131,131,131,131,131, 61,156,255,255,255,179,131,
  1547.   131,131,131,131,131,131,131,131,131,120,189,217,183,228,181,131,131,
  1548.   131,131,131,131,131,131,131,131,131, 61,156,255,255,255,179,131,131,
  1549.   131,131,131,131,131,131,131,131, 59,147,222, 86,154,147,131,131,131,
  1550.   131,131,131,131,131,131,131,131, 61,156,255,255,255,179,131,131,131,
  1551.   131,131,131,131,131,131,131, 31,255,255,255,245,179,131,131,131,131,
  1552.   131,131,131,131,131,131,131, 61,156,255,255,255,179,131,131,131,131,
  1553.   131,131,131,131,131,131, 31,255,255,255,222,179,131,131,131,131,131,
  1554.   131,131,131,131,131,131, 61,156,255,255,255,179,131,131,131,131,131,
  1555.   131,131,131,131,131,131,217,184,253, 75,204,131,131,131,131,131,131,
  1556.   131,131,131,131,131, 61,156,255,255,255,179,131,131,131,131,131,131,
  1557.   131,131,131,131,134,165,150,255,226,159,131,131,131,131,131,131,131,
  1558.   131,131,131,131, 61,156,255,255,255,179,131,131,131,131,131,131,131,
  1559.   131,131,131,131,131,118,255,131,131,131,131,131,131,131,131,131,131,
  1560.   131,131,131, 61,156,255,255,255,179,131,131,131,131,131,131,131,131,
  1561.   131,131,131,131, 87,255,131,131,131,131,131,131,131,131,131,131,131,
  1562.   131,131, 61,156,255,255,255,179,131,131,131,131,131,131,131,131,131,
  1563.   131,131, 79,161,242,131,131,131,131,131,131,131,131,131,131,131,131,
  1564.   131, 61,156,255,255,255,179,131,131,131,131,131,131,131,131,131,131,
  1565.   131, 61,255,147,111,111,111,111,111,111,111,111,111,111,111,111,111,
  1566.    46,159,255,255,255,126, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
  1567.   107,255, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 84,
  1568.   179,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  1569.   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  1570.   255,255 };
  1571.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1572.  
  1573.   /**
  1574.    * This holds the system's default color pair
  1575.    */
  1576.   protected static color_pair _default_color_pair=null;
  1577.  
  1578.   /**
  1579.    * This function returns the default color pair for the system.<p>
  1580.    * 
  1581.    * <b>Note</b>: This is now obsolete -- use the style system instead. 
  1582.    *
  1583.    * @return color_pair the system's default color pair
  1584.    */
  1585.   public static color_pair default_color_pair() {
  1586.     if (_default_color_pair==null) {
  1587.       color_scheme cs=style_manager.default_color_scheme();
  1588.       _default_color_pair=new color_pair(cs.foreground(),
  1589.                      cs.base());
  1590.     }
  1591.     return _default_color_pair;
  1592.   }
  1593.  
  1594.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1595.  
  1596.   /** 
  1597.    * Private counter for allocating unique positive integer values (we
  1598.    * ignore the fact that this will eventually wrap-around, so if you need
  1599.    * one every micro-second, do it yourself with a long).
  1600.    */
  1601.   private static int _unique_int = 0;
  1602.  
  1603.   /** 
  1604.    * Return a positive integer value that is unique among results from this
  1605.    * routine (we ignore the fact that this will eventually wrap-around, so 
  1606.    * if you need one every micro-second, do it yourself with a long).
  1607.    */
  1608.   public static int unique_int() {return _unique_int++; }
  1609.  
  1610.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1611.   /* STUFF FOR THE WORK AGENT AND MULTITHREADING */
  1612.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1613.  
  1614.   /**
  1615.    * You can call this method from another thread and it will perform
  1616.    * the work represented by the work_proc with the system in a safe 
  1617.    * synchronization state.
  1618.    *
  1619.    * @param work_proc wp  an object representing what code to run with the 
  1620.    *                      system in a safe state (its really a closure, in 
  1621.    *                      some sense).
  1622.    * @param Object    arg the argument to pass to the work_proc when the 
  1623.    *                      system reaches a safe state.
  1624.    */
  1625.   static public void perform_work(work_proc wp, Object arg) {
  1626.  
  1627.     /* create the pair to hold the two objects */
  1628.     work_pair pair=new work_pair(wp,arg);
  1629.  
  1630.     /* get a component to send the event to */
  1631.     Component c=an_awt_component();
  1632.  
  1633.     /* make the awt event */
  1634.     Event evt=new Event(an_awt_component(),work_agent.WORK_EVENT,
  1635.             pair);
  1636.  
  1637.     /* post that event */
  1638.     c.postEvent(evt);
  1639.   }
  1640.   
  1641.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1642.   /* Work around identification infrastructure */ 
  1643.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1644.  
  1645.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1646.   /* Platform identifiers and associated workaround ids.  Each platform is
  1647.    * limited to 32 workarounds (1<<0 .. 1<<31).  If you run out of space for
  1648.    * ids under a given platform, just start a new one.   When you add
  1649.    * a new platform be sure to fix WA_MAX_PLATFORM_ID as well.  
  1650.    */
  1651.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1652.  
  1653.   /** 
  1654.    * Special platform id to support dynamically added workarounds.  This 
  1655.    * allows people to temporarily put in a platform specific fix even 
  1656.    * if they can't modify identify_platform_workarounds().  In general,
  1657.    * these id's should be avoided in favor of an "official" id.  Note: 
  1658.    * there are only 32 workaround id's available under this "platform"
  1659.    * and its up to you to avoid conflicts. 
  1660.    */ 
  1661.   public static int WA_DYNAMIC = 0;
  1662.  
  1663.     public static int WA_USER1  = 1<<0; public static int WA_USER2  = 1<<1;
  1664.     public static int WA_USER3  = 1<<2; public static int WA_USER4  = 1<<3;
  1665.     public static int WA_USER5  = 1<<4; public static int WA_USER6  = 1<<5;
  1666.     public static int WA_USER7  = 1<<6; public static int WA_USER8  = 1<<7;
  1667.     public static int WA_USER9  = 1<<8; public static int WA_USER10 = 1<<9;
  1668.  
  1669.     public static int WA_USER11 = 1<<10; public static int WA_USER12 = 1<<11;
  1670.     public static int WA_USER13 = 1<<12; public static int WA_USER14 = 1<<13;
  1671.     public static int WA_USER15 = 1<<14; public static int WA_USER16 = 1<<15;
  1672.     public static int WA_USER17 = 1<<16; public static int WA_USER18 = 1<<17;
  1673.     public static int WA_USER19 = 1<<18; public static int WA_USER20 = 1<<19;
  1674.  
  1675.     public static int WA_USER21 = 1<<20; public static int WA_USER22 = 1<<21;
  1676.     public static int WA_USER23 = 1<<22; public static int WA_USER24 = 1<<23;
  1677.     public static int WA_USER25 = 1<<24; public static int WA_USER26 = 1<<25;
  1678.     public static int WA_USER27 = 1<<26; public static int WA_USER28 = 1<<27;
  1679.     public static int WA_USER29 = 1<<28; public static int WA_USER30 = 1<<29;
  1680.  
  1681.     public static int WA_USER31 = 1<<30; public static int WA_USER32 = 1<<31;
  1682.  
  1683.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1684.  
  1685.   /** Platform id for workarounds related to Netscape 3.x on all machines. */
  1686.   public static int WA_NS3_ALL = 1;
  1687.     
  1688.     /* no workarounds yet */
  1689.  
  1690.   /** Platform id for workarounds related to Netscape 3.x on Suns */
  1691.   public static int WA_NS3_SUN = 2;
  1692.  
  1693.     /* no workarounds yet */
  1694.  
  1695.   /** Platform id for workarounds related to Netscape 3.x on Wintel machines. */
  1696.   public static int WA_NS3_PC = 3;
  1697.  
  1698.     /* no workarounds yet */
  1699.  
  1700.   /** Platform id for workarounds related to Netscape 3.x on the Mac */
  1701.   public static int WA_NS3_MAC = 4;
  1702.  
  1703.     public static int WA_TRACKER_HANGS   = 1<<0;
  1704.     public static int WA_REDUNDANT_MOVES = 1<<1;
  1705.  
  1706.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1707.  
  1708.   /** Platform id for workarounds related to JDK 1.0.x on all machines. */
  1709.   public static int WA_JDK1_ALL = 5;
  1710.  
  1711.     /* no workarounds yet */
  1712.  
  1713.   /** Platform id for workarounds related to JDK 1.0.x on Sun machines.*/
  1714.   public static int WA_JDK1_SUN = 6;
  1715.  
  1716.     /* no workarounds yet */
  1717.  
  1718.   /** Platform id for workarounds related to JDK 1.0.x on Wintel machines. */
  1719.   public static int WA_JDK1_PC = 7;
  1720.  
  1721.     /* no workarounds yet */
  1722.  
  1723.   /** Platform id for workarounds related to JDK 1.0.x on the Mac.*/
  1724.   public static int WA_JDK1_MAC = 8;
  1725.  
  1726.     /* no workarounds yet */
  1727.  
  1728.   /** Platform id for workarounds related to MS Internet Explorer 3.x. */
  1729.   public static int WA_IE3 = 9;
  1730.  
  1731.     /* no workarounds yet */
  1732.  
  1733.   /** Largest platform id in use */
  1734.   public static int WA_MAX_PLATFORM_ID = WA_IE3;
  1735.  
  1736.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1737.  
  1738.   /** 
  1739.    * Table of workaround sets.  Workarounds are named by a pair of integers.
  1740.    * The first integer is a platform id, the second is a workaround id 
  1741.    * associated with that platform.  Each index in the table represents a 
  1742.    * particular platform (this is the platform that a particular bug or 
  1743.    * workaround was first identified on, it does not necessarily mean it
  1744.    * is limited to that platform).  The integer at each index represents
  1745.    * a set of at most 32 different workarounds associated with that platform.
  1746.    * This table is initialized at run-time by identify_platform_workarounds() 
  1747.    * (which is invoked early by a static initializer) based on some detective 
  1748.    * work to determine which platform we are actually running on.
  1749.    */
  1750.   protected static int[] _workaround_table;
  1751.  
  1752.   /* static init for the above table */
  1753.   static {
  1754.     identify_platform_workarounds();
  1755.   };
  1756.  
  1757.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1758.  
  1759.   /** 
  1760.    * Helper routine to dump useful system properties to System.out.  You can
  1761.    * use this to determine at least part of the "signature" of a new platform
  1762.    * that you need to incorporate into identify_platform_workarounds(). 
  1763.    */
  1764.   public static void dump_platform_properties()
  1765.    {
  1766.      System.out.println("System Properties for this Platform Include:");
  1767.      System.out.println("--------------------------------------------");
  1768.      System.out.println("os.arch=\"" + System.getProperty("os.arch") + "\"");
  1769.      System.out.println("os.name=\"" + System.getProperty("os.name") + "\"");
  1770.      System.out.println("os.version=\"" + 
  1771.                     System.getProperty("os.version") + "\"");
  1772.      System.out.println("java.version=\"" + 
  1773.                     System.getProperty("java.version") + "\"");
  1774.      System.out.println("java.vendor=\"" + 
  1775.                     System.getProperty("java.vendor") + "\"");
  1776.      System.out.println("java.class.version=\"" + 
  1777.                  System.getProperty("java.class.version") + "\"");
  1778.    }
  1779.  
  1780.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1781.  
  1782.   /**  
  1783.    * Do the detective work to determine which platform we are on and hence
  1784.    * which set of platform specific work arounds should be enabled. This 
  1785.    * will be called once by a static initializer here in the manager.  It 
  1786.    * sets up the _workaround_table array used by need_workaround() to 
  1787.    * determine which platform specific workarounds are needed and which are 
  1788.    * not.<p>
  1789.    *  
  1790.    * <b>Editorial Comment</b>:
  1791.    * The need for this routine is a very clear indication that Java, and in 
  1792.    * particular AWT, has as of yet utterly and completely failed to deliver 
  1793.    * on the promise of "write once run everywhere".  
  1794.    */
  1795.   protected static void identify_platform_workarounds()
  1796.     {
  1797.       String os_name;
  1798.       String os_arch;
  1799.       String os_version;
  1800.       String java_version;
  1801.       String vendor;
  1802.       String java_class_version;
  1803.  
  1804.       /* start with an empty set of active workarounds */
  1805.       _workaround_table = new int[WA_MAX_PLATFORM_ID];
  1806.       for (int i = 0; i < WA_MAX_PLATFORM_ID; i++)
  1807.     _workaround_table[i] = 0;
  1808.  
  1809.       /* Get identifying properties */
  1810.       os_name      = System.getProperty("os.name");
  1811.       os_arch      = System.getProperty("os.arch");
  1812.       os_version   = System.getProperty("os.version");
  1813.       java_version = System.getProperty("java.version");
  1814.       vendor       = System.getProperty("java.vendor");
  1815.       java_class_version = System.getProperty("java.class.version");
  1816.  
  1817.       /* do platform specific setup of _workaround_table */
  1818.  
  1819.       /* -------- JDK --------*/
  1820.       if (vendor.startsWith("Sun Microsystems"))
  1821.     {
  1822.       /* so far, no JDK workarounds... */
  1823.     }
  1824.  
  1825.       /* -------- Netscape --------*/
  1826.       else if (vendor.startsWith("Netscape"))
  1827.     {
  1828.       /* look at java.version to decide between 2.x and 3.x */
  1829.       if (java_version.equals("1.021"))
  1830.         {
  1831.           /* this is 2.02 -- don't know about earlier 2.x's yet*/
  1832.         }
  1833.       else if (java_version.equals("1.02"))
  1834.         {
  1835.           /* this is 3.0 -- separate out HW/SW platforms of interest */
  1836.  
  1837.           /* Macintosh */
  1838.           if (os_name.equals("Mac OS"))
  1839.         {
  1840.           _workaround_table[WA_NS3_MAC] |= 
  1841.                (WA_TRACKER_HANGS | WA_REDUNDANT_MOVES);
  1842.         }
  1843.         }
  1844.     }
  1845.       /* -------- need the other here... --------*/
  1846.     }
  1847.  
  1848.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1849.  
  1850.   /** 
  1851.    * Determine if a given platform specific workaround (identified by a 
  1852.    * platform id and workaround id pair) is needed on the platform we are 
  1853.    * currently running on.  Note: workarounds are not necessarily limited 
  1854.    * to the platform whose id they are associated with -- this is just the 
  1855.    * first platform for which the workaround was identified and helps 
  1856.    * segregate the workaround id name space and make it more extensible.<p>
  1857.    *
  1858.    * <b>Editorial Comment</b>:
  1859.    * The need for this routine is a very clear indication that Java, and in 
  1860.    * particular AWT, has as of yet utterly and completely failed to deliver 
  1861.    * on the promise of "write once run everywhere".  
  1862.    *
  1863.    * @param int platform_id   First part of identification of a particular 
  1864.    *                          workaround (this identifies the platform that the 
  1865.    *                          workaround was first associated with).
  1866.    *
  1867.    * @param int workaround_id Second part of identification of a particular 
  1868.    *                          workaround (this uniquely identifies it within
  1869.    *                          the group associated with a platform).
  1870.    * @return boolean indicating whether the given workaround is needed on the
  1871.    *                 platform we are currently running on.
  1872.    *                        
  1873.    */
  1874.   public static boolean need_workaround(int platform_id, int workaround_id)
  1875.     {
  1876.       return (_workaround_table[platform_id] & workaround_id) != 0;
  1877.     }
  1878.   
  1879.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1880.  
  1881.   /** Activate a specific platform specific workaround.  This is here to allow
  1882.    *  activation of known workarounds on the basis of new circumstances (or
  1883.    *  circumstances that can only be determined dynamically).  This can also
  1884.    *  be used with the WA_DYNAMIC platform id for indicating temporary platform
  1885.    *  specific fixes without updating identify_platform_workarounds().  
  1886.    *  (Such usage should be only temporary, however, because there are only
  1887.    *  32 such workaround id's available and no conflict resolution scheme is
  1888.    *  provided.)<p>
  1889.    *
  1890.    * @param int platform_id   First part of identification of the particular 
  1891.    *                          workaround to the activated (this identifies the 
  1892.    *                          platform that the workaround was first associated 
  1893.    *                          with).
  1894.    *
  1895.    * @param int workaround_id Second part of identification of the particular 
  1896.    *                          workaround to be activated (this uniquely 
  1897.    *                          identifies it within the group associated with a 
  1898.    *                          platform).
  1899.    */
  1900.   public static void activate_workaround(int platform_id, int workaround_id)
  1901.     {
  1902.       /* make sure we are in range */
  1903.       if (platform_id > WA_MAX_PLATFORM_ID) return;
  1904.  
  1905.       _workaround_table[platform_id] |= workaround_id;
  1906.     }
  1907.  
  1908.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1909. /*=========================== COPYRIGHT NOTICE ===========================
  1910.  
  1911. This file is part of the subArctic user interface toolkit.
  1912.  
  1913. Copyright (c) 1996 Scott Hudson and Ian Smith
  1914. All rights reserved.
  1915.  
  1916. The subArctic system is freely available for most uses under the terms
  1917. and conditions described in 
  1918.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  1919. and appearing in full in the lib/interactor.java source file.
  1920.  
  1921. The current release and additional information about this software can be 
  1922. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  1923.  
  1924. ========================================================================*/
  1925.