home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / lib / PEX / ws / wsb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  68.8 KB  |  2,484 lines

  1. /* $XConsortium: wsb.c,v 5.8 93/01/27 16:07:36 mor Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1989, 1990, 1991 by Sun Microsystems, Inc. and the X Consortium.
  5.  
  6.                         All Rights Reserved
  7.  
  8. Permission to use, copy, modify, and distribute this software and its 
  9. documentation for any purpose and without fee is hereby granted, 
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in 
  12. supporting documentation, and that the names of Sun Microsystems,
  13. the X Consortium, and MIT not be used in advertising or publicity 
  14. pertaining to distribution of the software without specific, written 
  15. prior permission.  
  16.  
  17. SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
  18. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT 
  19. SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
  20. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. /* PEX/PHIGS workstation utility functions for the B model (client side
  28.  * workstations and structure storage).
  29.  */
  30.  
  31. #include "phg.h"
  32. #include "cp.h"
  33. #include "ws.h"
  34. #include "css.h"
  35. #include "alloc.h"
  36. #include "PEX.h"
  37. #include "PEXproto.h"
  38. #include "PEXmacs.h"
  39. #include "PEXfuncs.h"
  40. #include "phigspex.h"
  41.  
  42.  
  43. static void
  44. wsb_load_funcs( ws )
  45.     Ws         *ws;
  46. {
  47.     ws->close = phg_wsb_close_ws;
  48.     ws->redraw_all = phg_wsb_redraw_all;
  49.     ws->conditional_redraw = phg_wsb_conditional_redraw;
  50.     ws->repaint_all = phg_wsb_repaint_all;
  51.     ws->make_requested_current = phg_wsb_make_requested_current;
  52.     ws->update = phg_wsb_update;
  53.     ws->set_disp_update_state = phg_wsb_set_disp_update_state;
  54.     ws->set_rep = phg_wsb_set_rep;
  55.     ws->set_filter = phg_wsb_set_filter;
  56.     ws->set_colour_model = (void(*)())NULL;    /* state set by CP */
  57.     ws->set_hlhsr_mode = phg_wsb_set_hlhsr_mode;
  58.     ws->set_view_input_priority = phg_wsb_set_view_input_priority;
  59.     ws->set_ws_window = phg_wsb_set_ws_window;
  60.     ws->set_ws_vp = phg_wsb_set_ws_vp;
  61.     ws->delete_el_for_repl = (void(*)())NULL;    /* not used */
  62.     ws->add_el = phg_wsb_add_el;
  63.     ws->copy_struct = phg_wsb_copy_struct;
  64.     ws->close_struct = phg_wsb_close_struct;
  65.     ws->move_ep = (void(*)())NULL;    /* not used */
  66.     ws->delete_el = phg_wsb_delete_el;
  67.     ws->delete_struct = phg_wsb_delete_struct;
  68.     ws->delete_struct_net = phg_wsb_delete_struct_net;
  69.     ws->delete_all_structs = phg_wsb_delete_all_structs;
  70.     ws->post = phg_wsb_post;
  71.     ws->unpost = phg_wsb_unpost;
  72.     ws->unpost_all = phg_wsb_unpost_all;
  73.     ws->change_posting = phg_wsb_change_posting;
  74.     ws->drawable_pick = phg_wsb_drawable_pick;
  75.     ws->map_points = phg_wsb_map_points;
  76.     ws->redraw_regions = phg_wsb_redraw_regions;
  77.  
  78.     ws->inq_view_indices = phg_wsb_inq_view_indices;
  79.     ws->inq_bundle_indices = phg_wsx_inq_LUT_indices;
  80.     ws->inq_posted = phg_wsb_inq_posted;
  81.     ws->inq_representation = phg_wsb_inq_rep;
  82.     ws->inq_view_rep = phg_wsb_inq_view_rep;
  83.     ws->inq_ws_xform = phg_wsb_inq_ws_xform;
  84.     ws->inq_disp_update_state = phg_wsb_inq_disp_update_state;
  85.     ws->inq_filter = phg_wsb_inq_filter;
  86.     ws->inq_hlhsr_mode = phg_wsb_inq_hlhsr_mode;
  87.     ws->inq_colour_model = (void(*)())NULL;    /* have CP return it */
  88. }
  89.  
  90. /* 
  91.  * Tables that determine what update action is valid at a give point
  92.  * in time.  The table has 3 axes:
  93.  *    [Time] [Modification Mode] [Deferral Mode].
  94.  */
  95.  
  96. static  Ws_action_table default_action_table =
  97. {
  98.     {   /* PHG_TIME_NOW */  
  99.     {   /* NIVE */   
  100.         PHG_UPDATE_ACCURATE,         /* ASAP */
  101.         PHG_UPDATE_IF_IG,             /* BNIG */
  102.         PHG_UPDATE_IF_IL,             /* BNIL */
  103.         PHG_UPDATE_NOTHING,         /* ASTI */
  104.         PHG_UPDATE_NOTHING            /* WAIT */
  105.     },
  106.     {   /* UWOR */
  107.         PHG_UPDATE_ACCURATE,         /* ASAP */
  108.         PHG_UPDATE_IF_IG,             /* BNIG */
  109.         PHG_UPDATE_IF_IL,             /* BNIL */
  110.         PHG_UPDATE_UWOR,             /* ASTI */
  111.         PHG_UPDATE_UWOR            /* WAIT */
  112.     },
  113.     {   /* UQUM */
  114.         PHG_UPDATE_ACCURATE,         /* ASAP */
  115.         PHG_UPDATE_IF_IG,             /* BNIG */
  116.         PHG_UPDATE_IF_IL,             /* BNIL */
  117.         PHG_UPDATE_UQUM,             /* ASTI */
  118.         PHG_UPDATE_UQUM            /* WAIT */
  119.     }, 
  120.     }, 
  121.  
  122.     {   /* PHG_TIME_BIG */  
  123.     {   /* NIVE */   
  124.         ASSURE_CORRECT,             /* ASAP */
  125.         PHG_UPDATE_ACCURATE,         /* BNIG */
  126.         PHG_UPDATE_NOTHING,         /* BNIL */
  127.         PHG_UPDATE_NOTHING,         /* ASTI */
  128.         PHG_UPDATE_NOTHING            /* WAIT */
  129.     }, 
  130.     {   /* UWOR */ 
  131.         ASSURE_CORRECT,             /* ASAP */
  132.         PHG_UPDATE_ACCURATE,         /* BNIG */
  133.         PHG_UPDATE_NOTHING,         /* BNIL */
  134.         PHG_UPDATE_NOTHING,         /* ASTI */
  135.         PHG_UPDATE_NOTHING            /* WAIT */
  136.     }, 
  137.     {   /* UQUM */   
  138.         ASSURE_CORRECT,             /* ASAP */
  139.         PHG_UPDATE_ACCURATE,         /* BNIG */
  140.         PHG_UPDATE_NOTHING,         /* BNIL */
  141.         PHG_UPDATE_NOTHING,         /* ASTI */
  142.         PHG_UPDATE_NOTHING            /* WAIT */
  143.     }, 
  144.     },         
  145.     {   /* PHG_TIME_BIL */  
  146.     {   /* NIVE */   
  147.         ASSURE_CORRECT,             /* ASAP */
  148.         PHG_UPDATE_ACCURATE,         /* BNIG */
  149.         PHG_UPDATE_ACCURATE,         /* BNIL */
  150.         PHG_UPDATE_NOTHING,         /* ASTI */
  151.         PHG_UPDATE_NOTHING            /* WAIT */
  152.     }, 
  153.     {   /* UWOR */ 
  154.         ASSURE_CORRECT,             /* ASAP */
  155.         PHG_UPDATE_ACCURATE,         /* BNIG */
  156.         PHG_UPDATE_ACCURATE,         /* BNIL */
  157.         PHG_UPDATE_NOTHING,         /* ASTI */
  158.         PHG_UPDATE_NOTHING            /* WAIT */
  159.     }, 
  160.     {   /* UQUM */   
  161.         ASSURE_CORRECT,             /* ASAP */
  162.         PHG_UPDATE_ACCURATE,         /* BNIG */
  163.         PHG_UPDATE_ACCURATE,         /* BNIL */
  164.         PHG_UPDATE_NOTHING,         /* ASTI */
  165.         PHG_UPDATE_NOTHING            /* WAIT */
  166.     }, 
  167.     }, 
  168.     {   /* PHG_TIME_ATI */  
  169.     {   /* NIVE */   
  170.         ASSURE_CORRECT,             /* ASAP */
  171.         PHG_UPDATE_IF_INCORRECT,         /* BNIG */
  172.         PHG_UPDATE_IF_INCORRECT,         /* BNIL */
  173.         PHG_UPDATE_ACCURATE,         /* ASTI */
  174.         PHG_UPDATE_NOTHING            /* WAIT */
  175.     }, 
  176.     {   /* UWOR */ 
  177.         ASSURE_CORRECT,             /* ASAP */
  178.         PHG_UPDATE_IF_INCORRECT,         /* BNIG */
  179.         PHG_UPDATE_IF_INCORRECT,         /* BNIL */
  180.         PHG_UPDATE_ACCURATE,         /* ASTI */
  181.         PHG_UPDATE_NOTHING            /* WAIT */
  182.     },
  183.     {   /* UQUM */   
  184.         ASSURE_CORRECT,             /* ASAP */
  185.         PHG_UPDATE_IF_INCORRECT,         /* BNIG */
  186.         PHG_UPDATE_IF_INCORRECT,         /* BNIL */
  187.         PHG_UPDATE_ACCURATE,         /* ASTI */
  188.         PHG_UPDATE_NOTHING            /* WAIT */
  189.     },
  190.     }
  191. };
  192.  
  193.  
  194. static
  195. void
  196. init_update_state( ws, wst )
  197.     Ws    *ws;
  198.     Wst    *wst;
  199. {   
  200.     register Ws_output_ws    *ows = &ws->out_ws;
  201.     register Wsb_output_ws    *owsb = &ows->model.b;
  202.  
  203.     ows->def_mode = ws->type->desc_tbl.phigs_dt.out_dt.deferral_mode;
  204.     ows->mod_mode = ws->type->desc_tbl.phigs_dt.out_dt.modification_mode;
  205.  
  206.     owsb->update_action_table = (Ws_action_table_ptr)default_action_table;
  207.  
  208.     /* cache action for time "NOW" */
  209.     owsb->now_action = (*owsb->update_action_table)
  210.     [(int)PHG_TIME_NOW][(int)ows->mod_mode][(int)ows->def_mode];
  211.  
  212.     owsb->vis_rep = PVISUAL_ST_CORRECT;
  213.     owsb->surf_state = PSURF_EMPTY;
  214. }
  215.  
  216.  
  217. static int
  218. init_view_table( ws, wst )
  219.     Ws    *ws;
  220.     Wst    *wst;
  221. {   
  222.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  223.  
  224.     register Ws_view_entry    *view;
  225.     register Pview_rep3        *predef_view;
  226.     register int        i, max_pd_view;
  227.  
  228.     ALLOC_DECLARE(5);
  229.  
  230.     /* Allocate and initiailize the view table to correspond to the
  231.      * predefined views in the PEX view LUT.  This code puts a limit on the
  232.      * number of view entries that can be defined.  This limit may
  233.      * be less than the server's limit.
  234.      */
  235.     owsb->num_views = ws->type->desc_tbl.phigs_dt.num_view_indices;
  236.  
  237.     if ( !ALLOCATED( owsb->views = (Ws_view_entry *)
  238.         malloc((unsigned)(owsb->num_views * sizeof(Ws_view_entry)))) ) {
  239.     ERR_BUF( ws->erh, ERR900 );
  240.     return 0;
  241.     }
  242.  
  243.     owsb->top_view = 0;
  244.     if ( !ALLOCATED( owsb->view_priorities = (Ws_view_priority *)
  245.         malloc((unsigned)(owsb->num_views * sizeof(Ws_view_priority)))) ) {
  246.     ERR_BUF( ws->erh, ERR900 );
  247.     ALLOC_FREE;
  248.     return 0;
  249.     }
  250.  
  251.     owsb->num_pending_views = 0;
  252.     if ( !ALLOCATED( owsb->pending_views = (Ws_pending_view *)
  253.         malloc((unsigned)(owsb->num_views * sizeof(Ws_pending_view)))) ) {
  254.     ERR_BUF( ws->erh, ERR900 );
  255.     ALLOC_FREE;
  256.     return 0;
  257.     }
  258.  
  259.     max_pd_view = wst->desc_tbl.phigs_dt.num_predefined_views - 1;
  260.     predef_view = wst->desc_tbl.phigs_dt.default_views;
  261.     view = owsb->views;
  262.     /* Load the predefined views. */
  263.     for ( i = 0; i <= max_pd_view; i++, predef_view++, view++ ) {
  264.     view->pending = PUPD_NOT_PEND;
  265.     bcopy( (char *)predef_view->ori_matrix,(char *) view->vom,
  266.         sizeof(Pmatrix3) );
  267.     bcopy( (char *)predef_view->map_matrix, (char *)view->vmm,
  268.         sizeof(Pmatrix3) );
  269.     view->clip_limit = predef_view->clip_limit;
  270.     view->xy_clip = predef_view->xy_clip;
  271.     view->back_clip = predef_view->back_clip;
  272.     view->front_clip = predef_view->front_clip;
  273.     /* view->npc_to_wc not computed until needed in input code. */
  274.     view->npc_to_wc_state = WS_INV_NOT_CURRENT;
  275.     }
  276.  
  277.     /* Load the available but not predefined views. */
  278.     for ( /* use existing index */ ; i < owsb->num_views; i++, view++ )
  279.     *view = owsb->views[0];
  280.     
  281.     /* Initialize the view transformation priorities.  The list is
  282.      * terminated at top and bottom by -1.
  283.      */
  284.     for ( i = 0; i < owsb->num_views; i++ ) {
  285.     owsb->view_priorities[i].higher = i - 1;
  286.     owsb->view_priorities[i].lower = i + 1;
  287.     }
  288.     owsb->view_priorities[owsb->num_views - 1].lower = -1;
  289.     
  290.     return 1;
  291. }
  292.  
  293.  
  294. static int
  295. init_output_state( ws )
  296.     Ws        *ws;
  297. {
  298.     Wst        *wst = ws->type;
  299.  
  300.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  301.  
  302.     if ( !init_view_table( ws, wst ) )
  303.     return 0;
  304.  
  305.     /* Initialize the workstation transform. */
  306.     owsb->req_ws_window.x_min = 0.0;
  307.     owsb->req_ws_window.x_max = 1.0;
  308.     owsb->req_ws_window.y_min = 0.0;
  309.     owsb->req_ws_window.y_max = 1.0;
  310.     owsb->req_ws_window.z_min = 0.0;
  311.     owsb->req_ws_window.z_max = 1.0;
  312.     owsb->ws_window = owsb->req_ws_window;
  313.     owsb->ws_window_pending = PUPD_NOT_PEND;
  314.  
  315.     owsb->req_ws_viewport.x_min = 0.0;
  316.     owsb->req_ws_viewport.x_max = ws->ws_rect.width;
  317.     owsb->req_ws_viewport.y_min = 0.0;
  318.     owsb->req_ws_viewport.y_max = ws->ws_rect.height;
  319.     owsb->req_ws_viewport.z_min = 0.0;
  320.     owsb->req_ws_viewport.z_max = 1.0;
  321.     owsb->ws_viewport = owsb->req_ws_viewport;
  322.     owsb->ws_viewport_pending = PUPD_NOT_PEND;
  323.  
  324.     phg_wsx_compute_ws_transform( &owsb->ws_window, &owsb->ws_viewport,
  325.     &owsb->ws_xform );
  326.  
  327.     /* Initialize the list of posted structs. */
  328.     owsb->posted.lowest.higher = &owsb->posted.highest;
  329.     owsb->posted.lowest.lower = NULL;
  330.     owsb->posted.highest.higher = NULL;
  331.     owsb->posted.highest.lower = &owsb->posted.lowest;
  332.  
  333.     /* Initialize other miscellaneous output state. */
  334.     owsb->cur_hlhsr_mode = PHIGS_HLHSR_MODE_NONE;
  335.     owsb->req_hlhsr_mode = PHIGS_HLHSR_MODE_NONE;
  336.     owsb->hlhsr_mode_pending = PUPD_NOT_PEND;
  337.  
  338.     return 1;
  339. }
  340.  
  341. static int
  342. wsb_init_resources( ws )
  343.     Ws        *ws;
  344. {
  345.     CARD16        count;
  346.     CARD32        size, *rid_list;
  347.     pexTableIndex    start;
  348.     pexBitmask        pmask[PEXMSPipeline], rmask;
  349.     CARD32        *card32_p;
  350.     pexReflectionAttr    *refl_attr, *bf_refl_attr;
  351.     pexFloatColour    *spec_colr, *bf_spec_colr;
  352.     pexViewport        *vp;
  353.  
  354.     register int        i;
  355.     register Ws_view_entry    *view;
  356.     register pexViewEntry    *pex_view;
  357.  
  358.     /* Initialize all the predefined table entries from the WDT. */
  359.     if ( !phg_wsx_init_LUTs( ws, 1 ) )
  360.     return 0;
  361.  
  362.     /* Initialize the Pipeline Context.  Since PEX and PHIGS defaults
  363.      * are different for reflection attrs and culling mode, set those in
  364.      * PEX when creating the context.
  365.      */
  366.     size = 0;
  367.     bzero((char *)pmask, sizeof(pmask));
  368.     PEX_BITSET(pmask,PEXPCSurfaceReflAttr);
  369.     size += sizeof(*refl_attr) + sizeof(*spec_colr);
  370.     refl_attr = (pexReflectionAttr *)ws->scratch.buf;
  371.     spec_colr = (pexFloatColour *)(refl_attr + 1);
  372.     refl_attr->ambient = 1.0;
  373.     refl_attr->diffuse = 1.0;
  374.     refl_attr->specular = 1.0;
  375.     refl_attr->specularConc = 0.0;
  376.     refl_attr->transmission = 0.0;
  377.     refl_attr->specularColour.colourType = PEXRgbFloatColour;
  378.     spec_colr->first = spec_colr->second = spec_colr->third = 1.0;
  379.     PEX_BITSET(pmask,PEXPCBfSurfaceReflAttr);
  380.     size += sizeof(*bf_refl_attr) + sizeof(*bf_spec_colr);
  381.     bf_refl_attr = (pexReflectionAttr *)(spec_colr + 1);
  382.     *bf_refl_attr = *refl_attr;
  383.     bf_spec_colr = (pexFloatColour *)(bf_refl_attr + 1);
  384.     *bf_spec_colr = *spec_colr;
  385.     PEX_BITSET(pmask,PEXPCCullingMode); size += sizeof(CARD32);
  386.     card32_p = (CARD32 *)(bf_spec_colr + 1);
  387.     *card32_p = 0;
  388.     (void)PEXChangePipelineContext( ws->display, ws->out_ws.model.b.pipeline,
  389.     pmask, size, (char *)ws->scratch.buf );
  390.  
  391.     /* Initialize the renderer. */
  392.     size = 0;
  393.     bzero((char *)&rmask, sizeof(rmask));
  394.     rid_list = (XID *)ws->scratch.buf;
  395.     /* The way the bits are defined in PEX.h doesn't allow the use of
  396.      * PEX_BITSET().
  397.      */
  398.     rmask |= PEXRDPipelineContext; size += sizeof(CARD32);
  399.     *rid_list++ = ws->out_ws.model.b.pipeline;
  400.     rmask |= PEXRDMarkerBundle; size += sizeof(CARD32);
  401.     *rid_list++ = ws->out_ws.lut.marker;
  402.     rmask |= PEXRDTextBundle; size += sizeof(CARD32);
  403.     *rid_list++ = ws->out_ws.lut.text;
  404.     rmask |= PEXRDLineBundle; size += sizeof(CARD32);
  405.     *rid_list++ = ws->out_ws.lut.line;
  406.     rmask |= PEXRDInteriorBundle; size += sizeof(CARD32);
  407.     *rid_list++ = ws->out_ws.lut.interior;
  408.     rmask |= PEXRDEdgeBundle; size += sizeof(CARD32);
  409.     *rid_list++ = ws->out_ws.lut.edge;
  410.     rmask |= PEXRDViewTable; size += sizeof(CARD32);
  411.     *rid_list++ = ws->out_ws.lut.view;
  412.     rmask |= PEXRDColourTable; size += sizeof(CARD32);
  413.     *rid_list++ = ws->out_ws.lut.colour;
  414.     rmask |= PEXRDDepthCueTable; size += sizeof(CARD32);
  415.     *rid_list++ = ws->out_ws.lut.depth_cue;
  416.     rmask |= PEXRDLightTable; size += sizeof(CARD32);
  417.     *rid_list++ = ws->out_ws.lut.light_source;
  418.     rmask |= PEXRDColourApproxTable; size += sizeof(CARD32);
  419.     *rid_list++ = ws->out_ws.lut.colour_approx;
  420.     rmask |= PEXRDPatternTable; size += sizeof(CARD32);
  421.     *rid_list++ = ws->out_ws.lut.pattern;
  422.     rmask |= PEXRDTextFontTable; size += sizeof(CARD32);
  423.     *rid_list++ = ws->out_ws.lut.font;
  424.     rmask |= PEXRDHighlightIncl; size += sizeof(CARD32);
  425.     *rid_list++ = ws->out_ws.nset.hlt_incl;
  426.     rmask |= PEXRDHighlightExcl; size += sizeof(CARD32);
  427.     *rid_list++ = ws->out_ws.nset.hlt_excl;
  428.     rmask |= PEXRDInvisibilityIncl; size += sizeof(CARD32);
  429.     *rid_list++ = ws->out_ws.nset.invis_incl;
  430.     rmask |= PEXRDInvisibilityExcl; size += sizeof(CARD32);
  431.     *rid_list++ = ws->out_ws.nset.invis_excl;
  432.     rmask |= PEXRDHlhsrMode; size += sizeof(CARD32);
  433.     *rid_list++ = (CARD32)PEX_CONV_PHIGS_HLHSR_MODE(PHIGS_HLHSR_MODE_NONE);
  434.     rmask |= PEXRDViewport; size += sizeof(pexViewport);
  435.     vp = (pexViewport *)rid_list++;
  436.     vp->minval.x = ws->out_ws.model.b.req_ws_viewport.x_min;
  437.     vp->minval.y = ws->out_ws.model.b.req_ws_viewport.y_min;
  438.     vp->minval.z = ws->out_ws.model.b.req_ws_viewport.z_min;
  439.     vp->maxval.x = ws->out_ws.model.b.req_ws_viewport.x_max;
  440.     vp->maxval.y = ws->out_ws.model.b.req_ws_viewport.y_max;
  441.     vp->maxval.z = ws->out_ws.model.b.req_ws_viewport.z_max;
  442.     vp->useDrawable = 0;
  443.     /* No need to set the NPC volume since the PEX default is correct. */
  444.     (void)PEXChangeRenderer( ws->display, ws->rid, rmask, size,
  445.     (char *)ws->scratch.buf );
  446.  
  447.     return 1;
  448. }
  449.  
  450. static int
  451. wsb_create_resources( ws )
  452.     Ws        *ws;
  453. {
  454.     pexBitmask        pmask[PEXMSPipeline];
  455.     pexBitmask        dyn_tbls, dyn_nsets, dyn_attrs;
  456.     Pint        err;
  457.     CARD16        *card16_p;
  458.     Drawable            draw;
  459.     int                 numbufs, mbuf_event_base, mbuf_error_base;;
  460.  
  461.  
  462.     /* Create the LUTs, renderer and pipeline context. */
  463.     if ( !phg_wsx_create_LUTs( ws, 1, &err ) ) {
  464.     ERR_BUF( ws->erh, err );
  465.     return 0;
  466.     }
  467.  
  468.     /* Create the pipeline context. */
  469.     ws->out_ws.model.b.pipeline = XAllocID(ws->display);
  470.     (void)PEXCreatePipelineContext( ws->display, ws->out_ws.model.b.pipeline,
  471.     (pexBitmask *)NULL, (CARD32)0, (char *)NULL );
  472.  
  473.     /* Make an inquiry to see if the create worked. */
  474.     /* TODO: Remove when GetPipeline fixed.
  475.     bzero((char *)pmask, sizeof(pmask));
  476.     PEX_BITSET(pmask,PEXPCCullingMode);
  477.     if ( !PEXGetPipelineContext( ws->display, ws->out_ws.model.b.pipeline,
  478.         pmask, (char **)&card16_p ) ) {
  479.     ERR_BUF( ws->erh, ERRN202 );
  480.     return 0;
  481.     }
  482.     */
  483.  
  484.     /* Check the Workstation buffer mode and do the double buffer
  485.        create here if necessary This is simpler than on the workstation
  486.        since this PHIGS implementation only lets the Double Buffers
  487.        be created when the workstation is created, so no change action
  488.        need be done
  489.     */
  490.  
  491.     /* initialize the local drawable variable */
  492.     draw = ws->drawable_id;
  493.     ws->out_ws.model.b.has_double_buffer = FALSE;
  494.  
  495.     if (ws->type->desc_tbl.xwin_dt.buffer_mode == PHIGS_BUF_DOUBLE) {
  496.       if (XmbufQueryExtension(ws->display, &mbuf_event_base, &mbuf_error_base)){
  497.  
  498.         /* the Multi-Buffer extension is there */
  499.         numbufs = XmbufCreateBuffers(ws->display, ws->drawable_id, 2,
  500.                      MultibufferUpdateActionBackground,
  501.                      MultibufferUpdateHintFrequent,
  502.                      &ws->out_ws.model.b.double_drawable[0]);
  503.         if  (numbufs == 2) {
  504.           /* got the buffers OK */
  505.           ws->out_ws.model.b.front = 0;
  506.           ws->out_ws.model.b.back = 1;
  507.           ws->out_ws.model.b.has_double_buffer = TRUE;
  508.           draw = ws->out_ws.model.b.double_drawable[1];
  509.           /* this isn't implemented yet
  510.             XmbufClearBufferArea(ws->display, draw, 0, 0, 0, 0, False);
  511.           */
  512.         } else
  513.           /* buffers didn't get created correctly, bag them  */
  514.           XmbufDestroyBuffers(ws->display, ws->drawable_id);
  515.       }
  516.     }
  517.  
  518.  
  519.     /* Create the renderer, initializing the necessary attributes. */
  520.     ws->rid = XAllocID(ws->display);
  521.     (void)PEXCreateRenderer( ws->display, ws->rid, draw,
  522.     (pexBitmask)0, (CARD32)0, (char *)NULL );
  523.  
  524.     /* Make an inquiry to see if the create worked. */
  525.     if ( !PEXGetRendererDynamics( ws->display, ws->rid, &dyn_tbls,
  526.         &dyn_nsets, &dyn_attrs ) ) {
  527.     ERR_BUF( ws->erh, ERRN202 );
  528.     return 0;
  529.     }
  530.  
  531.     return 1;
  532. }
  533.  
  534.  
  535. static void
  536. wsb_update_wdt( ws )
  537.     Ws        *ws;
  538. {
  539.     /* Update the dynamics flags -- everything IRG for client-side WSs. */
  540.     ws->type->desc_tbl.phigs_dt.out_dt.view_rep = PDYN_IRG;
  541.     ws->type->desc_tbl.phigs_dt.out_dt.polyline_bundle_rep = PDYN_IRG;
  542.     ws->type->desc_tbl.phigs_dt.out_dt.polymarker_bundle_rep = PDYN_IRG;
  543.     ws->type->desc_tbl.phigs_dt.out_dt.text_bundle_rep = PDYN_IRG;
  544.     ws->type->desc_tbl.phigs_dt.out_dt.interior_bundle_rep = PDYN_IRG;
  545.     ws->type->desc_tbl.phigs_dt.out_dt.edge_bundle_rep = PDYN_IRG;
  546.     ws->type->desc_tbl.phigs_dt.out_dt.pattern_rep = PDYN_IRG;
  547.     ws->type->desc_tbl.phigs_dt.out_dt.colour_rep = PDYN_IRG;
  548.     ws->type->desc_tbl.phigs_dt.out_dt.ws_xform = PDYN_IRG;
  549.     ws->type->desc_tbl.phigs_dt.out_dt.highlight_filter = PDYN_IRG;
  550.     ws->type->desc_tbl.phigs_dt.out_dt.invis_filter = PDYN_IRG;
  551.     ws->type->desc_tbl.phigs_dt.out_dt.hlhsr_mode = PDYN_IRG;
  552.     ws->type->desc_tbl.phigs_dt.out_dt.struct_content_mod = PDYN_IRG;
  553.     ws->type->desc_tbl.phigs_dt.out_dt.post = PDYN_IRG;
  554.     ws->type->desc_tbl.phigs_dt.out_dt.unpost = PDYN_IRG;
  555.     ws->type->desc_tbl.phigs_dt.out_dt.struct_delete = PDYN_IRG;
  556.     ws->type->desc_tbl.phigs_dt.out_dt.ref_mod = PDYN_IRG;
  557. }
  558.  
  559.  
  560. Ws*
  561. phg_wsb_open_ws( cph, cp_args, ret, css_srvr )
  562.     Cp_handle        cph;
  563.     Phg_args        *cp_args;
  564.     Phg_ret        *ret;
  565.     Cpx_css_srvr    *css_srvr;
  566. {
  567.     void        wsb_destroy_ws();
  568.     Phg_args_open_ws    *args = &cp_args->data.open_ws;
  569.     char        *avlist[4];
  570.     Ws            *ws;
  571.     XWindowAttributes    wattr;
  572.     Phg_pex_ext_info    pex_info;
  573.  
  574.     ret->err = -1;
  575.     if ( !(ws = phg_wsx_create( cph, args, css_srvr )) )
  576.     return ws;
  577.  
  578.     switch ( args->type->base_type ) {
  579.     case WST_BASE_TYPE_X_DRAWABLE:
  580.         ws->display = args->conn_info.display;
  581.         ws->drawable_id = args->conn_info.drawable_id;
  582.         phg_cpx_instance_connection( cph, ws->display, 0 );
  583.         break;
  584.  
  585.     case WST_BASE_TYPE_X_TOOL:
  586.         /* Get a display connection for it. */
  587.         if ( (ws->display = phg_cpx_connection_exists( cph, CPX_BY_NAME,
  588.             args->conn_info.display_name )) ) {
  589.         /* We know PEX is supported on this display because it's in
  590.          * the CPs connection list.
  591.          */
  592.         phg_cpx_instance_connection( cph, ws->display, 0 );
  593.         } else if ( ws->display = phg_utx_open_pex_display(
  594.             args->conn_info.display_name, &pex_info, &ret->err ) ) {
  595.         phg_cpx_instance_connection( cph, ws->display, 1 );
  596.         } else {
  597.         ERR_BUF( ws->erh, ret->err );
  598.         goto abort;
  599.         }
  600.  
  601.         /* Create the window. */
  602.         if ( !phg_wsx_setup_tool( ws, &args->conn_info, args->type ) )
  603.         goto abort;
  604.         break;
  605.     }
  606.  
  607.     (void)XGetWindowAttributes( ws->display, ws->drawable_id, &wattr );
  608.     WS_SET_WS_RECT( ws, &wattr )
  609.  
  610.     /* Build an accurate WDT after the window is open. */
  611.     avlist[0] = PHIGS_X_DISPLAY_WINDOW;
  612.     avlist[1] = (char *)ws->display;
  613.     avlist[2] = (char *)ws->drawable_id;
  614.     avlist[3] = (char *)0;
  615.     if ( ws->type = phg_wst_create( cph->erh, args->type, avlist ) ) {
  616.     ws->type->wsid = ws->id;
  617.     ws->type->bound_status = WST_BOUND;
  618.     wsb_update_wdt( ws );
  619.     } else
  620.     goto abort;
  621.  
  622.     ws->current_colour_model =
  623.     ws->type->desc_tbl.phigs_dt.out_dt.default_colour_model;
  624.     ws->category = ws->type->desc_tbl.phigs_dt.ws_category;
  625.     ws->out_ws.model.b.cssh = css_srvr->model.b.cssh;
  626.     if ( !init_output_state( ws ) )
  627.     goto abort;
  628.     init_update_state( ws, ws->type );
  629.  
  630.     /* Create and initialize all the PEX resources. */
  631.     if ( !wsb_create_resources( ws ) )
  632.     goto abort;
  633.     if ( !wsb_init_resources( ws ) )
  634.     goto abort;
  635.  
  636.     if ( !phg_wsx_setup_colormap( ws, &ret->err ) ) {
  637.     ERR_BUF(ws->erh, ret->err);
  638.     goto abort;
  639.     }
  640.  
  641.     wsb_load_funcs( ws );
  642.  
  643.     /* Fill in the WDT fields that depend on an open workstaton. */
  644.     ws->type->desc_tbl.phigs_dt.out_dt.num_display_priorities = 0;
  645.     ws->type->desc_tbl.phigs_dt.dev_coords[0] = ws->ws_rect.width;
  646.     ws->type->desc_tbl.phigs_dt.dev_coords[1] = ws->ws_rect.height;
  647.     ws->type->desc_tbl.phigs_dt.dev_addrs_units[0] = ws->ws_rect.width;
  648.     ws->type->desc_tbl.phigs_dt.dev_addrs_units[1] = ws->ws_rect.height;
  649.  
  650.     /* Fill in the return data. */
  651.     ret->err = 0;
  652.     ret->data.open_ws.wstype = ws->type;
  653.     ret->data.open_ws.wst_buffer = ws->type->buffer;
  654.     ret->data.open_ws.wst_buffer_size = ws->type->buffer_size;
  655.     ret->data.open_ws.drawable_id = ws->drawable_id;
  656.     ret->data.open_ws.overlay_id = ws->input_overlay_window;
  657.  
  658.     return ws;
  659.  
  660. abort:
  661.     wsb_destroy_ws( ws );
  662.     return (Ws *)NULL;
  663. }
  664.  
  665.  
  666. void
  667. wsb_free_all_posted( owsb )
  668.     Wsb_output_ws    *owsb;
  669. {
  670.     register    Ws_post_str    *cur, *end;
  671.  
  672.     cur = owsb->posted.lowest.higher;
  673.     end = &owsb->posted.highest;
  674.     while ( cur != end ) {
  675.     cur = cur->higher;
  676.     free( (char *)cur->lower );
  677.     }
  678.     owsb->posted.lowest.higher = end;
  679.     end->lower = &owsb->posted.lowest;
  680. }
  681.  
  682.  
  683. void
  684. wsb_destroy_ws( ws )
  685.     Ws        *ws;
  686. {
  687.     if ( ws ) {
  688.     if ( ws->out_ws.model.b.views )
  689.         free( (char *)ws->out_ws.model.b.views );
  690.     if ( ws->out_ws.model.b.pending_views )
  691.         free( (char *)ws->out_ws.model.b.pending_views );
  692.     if ( ws->out_ws.model.b.view_priorities )
  693.         free( (char *)ws->out_ws.model.b.view_priorities );
  694.     if ( ws->display ) {
  695.         if ( ws->drawable_id )
  696.         phg_wsx_release_window( ws );
  697.         if ( ws->out_ws.model.b.pipeline )
  698.         PEXFreePipelineContext( ws->display,
  699.             ws->out_ws.model.b.pipeline );
  700.         if ( ws->rid )
  701.         PEXFreeRenderer( ws->display, ws->rid );
  702.         phg_wsx_destroy_LUTs( ws );
  703.         XFlush( ws->display );
  704.         phg_cpx_release_connection( ws->cph, ws->display );
  705.     }
  706.     phg_wsx_destroy( ws );
  707.     }
  708. }
  709.  
  710.  
  711. void
  712. phg_wsb_close_ws( ws )
  713.     Ws        *ws;
  714. {
  715.     if ( ws ) {
  716.     wsb_free_all_posted( &ws->out_ws.model.b );
  717.     wsb_destroy_ws( ws );
  718.     }
  719. }
  720.  
  721.  
  722. void
  723. phg_wsb_redraw_all( ws, clear_control )
  724.     Ws        *ws;
  725.     Pctrl_flag    clear_control;
  726. {
  727.     (*ws->make_requested_current)( ws );
  728.     (*ws->repaint_all)( ws, clear_control, 0, (XRectangle *)NULL );
  729.     ws->out_ws.model.b.vis_rep = PVISUAL_ST_CORRECT;
  730. }
  731.  
  732.  
  733.  
  734. /* Make all "requested" and pending data current. */
  735. void
  736. phg_wsb_make_requested_current( ws )
  737.     Ws        *ws;
  738. {
  739.     Ws_view_entry    *view;
  740.     Ws_pending_view    *req_view;
  741.     pexViewEntry    pex_view;
  742.     pexViewport        vp;
  743.     pexNpcSubvolume    win;
  744.  
  745.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  746.  
  747.     /* WS transform */
  748.     if ( owsb->ws_window_pending == PUPD_PEND
  749.         || owsb->ws_viewport_pending == PUPD_PEND ) {
  750.     if ( owsb->ws_window_pending == PUPD_PEND ) {
  751.         owsb->ws_window = owsb->req_ws_window;
  752.         owsb->ws_window_pending = PUPD_NOT_PEND;
  753.         win.minval.x = owsb->ws_window.x_min;
  754.         win.minval.y = owsb->ws_window.y_min;
  755.         win.minval.z = owsb->ws_window.z_min;
  756.         win.maxval.x = owsb->ws_window.x_max;
  757.         win.maxval.y = owsb->ws_window.y_max;
  758.         win.maxval.z = owsb->ws_window.z_max;
  759.         (void)PEXChangeRenderer( ws->display, ws->rid,
  760.         (pexBitmask)PEXRDNpcSubvolume,
  761.         (CARD32)sizeof(pexNpcSubvolume), (char *)&win );
  762.     }
  763.  
  764.     if ( owsb->ws_viewport_pending == PUPD_PEND ) {
  765.         owsb->ws_viewport = owsb->req_ws_viewport;
  766.         owsb->ws_viewport_pending = PUPD_NOT_PEND;
  767.         vp.minval.x = owsb->ws_viewport.x_min;
  768.         vp.minval.y = owsb->ws_viewport.y_min;
  769.         vp.minval.z = owsb->ws_viewport.z_min;
  770.         vp.maxval.x = owsb->ws_viewport.x_max;
  771.         vp.maxval.y = owsb->ws_viewport.y_max;
  772.         vp.maxval.z = owsb->ws_viewport.z_max;
  773.         vp.useDrawable = 0;
  774.         (void)PEXChangeRenderer( ws->display, ws->rid,
  775.         (pexBitmask)PEXRDViewport,
  776.         (CARD32)sizeof(pexViewport), (char *)&vp );
  777.     }
  778.  
  779.     phg_wsx_compute_ws_transform( &owsb->ws_window, &owsb->ws_viewport,
  780.         &owsb->ws_xform );
  781.     }
  782.  
  783.     /* View table */
  784.     if ( owsb->num_pending_views > 0 ) {
  785.     req_view = owsb->pending_views;
  786.     while ( owsb->num_pending_views > 0 ) {
  787.         view = &owsb->views[req_view->id];
  788.         /*Set it locally. */
  789.         view->pending = PUPD_NOT_PEND;
  790.         bcopy( (char *)req_view->view.ori_matrix, (char *)view->vom,
  791.         sizeof(Pmatrix3) );
  792.         bcopy( (char *)req_view->view.map_matrix, (char *)view->vmm,
  793.         sizeof(Pmatrix3) );
  794.         view->clip_limit = req_view->view.clip_limit;
  795.         view->xy_clip = req_view->view.xy_clip;
  796.         view->back_clip = req_view->view.back_clip;
  797.         view->front_clip = req_view->view.front_clip;
  798.         view->npc_to_wc_state = WS_INV_NOT_CURRENT;
  799.  
  800.         /* Set it in the server.  Can't set them all as a block with one
  801.          * request because the pending views may not be contiguous.
  802.          */
  803.         (void)phg_utx_view_entry_to_pex( &req_view->view, &pex_view );
  804.         (void)PEXSetTableEntries( ws->display, ws->out_ws.lut.view,
  805.         (pexTableIndex)req_view->id, (CARD16)1,
  806.         (CARD32)sizeof(pex_view), (char *)&pex_view );
  807.         ++req_view;
  808.         --owsb->num_pending_views;
  809.     }
  810.     }
  811.  
  812.     /* Other pending data */
  813.     if ( owsb->hlhsr_mode_pending == PUPD_PEND) {
  814.      CARD32     new_mode;
  815.  
  816.      owsb->cur_hlhsr_mode = owsb->req_hlhsr_mode;
  817.      owsb->hlhsr_mode_pending = PUPD_NOT_PEND;
  818.  
  819.      new_mode = (CARD32)PEX_CONV_PHIGS_HLHSR_MODE(owsb->cur_hlhsr_mode);
  820.          (void)PEXChangeRenderer( ws->display, ws->rid,
  821.                                  (pexBitmask)PEXRDHlhsrMode,
  822.                                  (CARD32)sizeof(CARD32), (char *)&new_mode);
  823.  
  824.     }
  825.  
  826.     /* Make it all take effect. */
  827.     XFlush( ws->display );
  828. }
  829.  
  830.  
  831. void
  832. phg_wsb_repaint_all( ws, clear_control, num_rects, exposure_rects )
  833.     Ws        *ws;
  834.     Pctrl_flag    clear_control;
  835.     int        num_rects;        /* may be 0 */
  836.     XRectangle    *exposure_rects;    /* may be NULL */
  837. {
  838.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  839.     int                 tmp;
  840.     Drawable            draw;
  841.  
  842.     register int    i;
  843.  
  844.     /* assuming this stuff does clear then don't do it when using Double Buff
  845.        since the swap will take care of that
  846.     */
  847.     if ((clear_control == PFLAG_ALWAYS || owsb->surf_state == PSURF_NOT_EMPTY)
  848.        && !ws->out_ws.model.b.has_double_buffer) {
  849.     /* TODO: Need a way to "clear" the window that uses the zero-th
  850.      * entry in the WS colour table and runs it through colour mapping.
  851.      */
  852.     if ( num_rects > 0 ) {
  853.         for ( i = 0; i < num_rects; i++ )
  854.         XClearArea( ws->display, ws->drawable_id,
  855.             exposure_rects[i].x, exposure_rects[i].x,
  856.             exposure_rects[i].width, exposure_rects[i].height,
  857.             False );
  858.     } else
  859.         XClearWindow( ws->display, ws->drawable_id );
  860.     }
  861.     owsb->surf_state = PSURF_EMPTY;
  862.  
  863.     /* set the drawable correctly */
  864.     if (ws->out_ws.model.b.has_double_buffer)
  865.         draw = ws->out_ws.model.b.double_drawable[ws->out_ws.model.b.back];
  866.     else  /* single buffer */
  867.         draw = ws->drawable_id;
  868.  
  869.     phg_wsb_traverse_all_postings( ws, draw );
  870.  
  871.     /* now swap the buffers and update the drawable indices */
  872.     if (ws->out_ws.model.b.has_double_buffer) {
  873.           XmbufDisplayBuffers(ws->display, 1, &draw, 0, 0);
  874.           tmp = ws->out_ws.model.b.front;
  875.           ws->out_ws.model.b.front  = ws->out_ws.model.b.back;
  876.           ws->out_ws.model.b.back = tmp;
  877.     }
  878.  
  879.     /* Redraw input prompts & echos of any active input devices. */
  880.     if ( ws->input_repaint && WS_ANY_INP_DEV_ACTIVE(ws) )
  881.     (ws->input_repaint)( ws, num_rects, exposure_rects );
  882.  
  883.     XFlush( ws->display );
  884. }
  885.  
  886.  
  887. void
  888. phg_wsb_traverse_all_postings( ws, draw )
  889.     Ws        *ws;
  890.     Drawable            draw;
  891. {
  892.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  893.     register Ws_post_str    *post_str, *end;
  894.  
  895.     WSB_CHECK_POSTED(&owsb->posted)
  896.     if( WSB_SOME_POSTED(&owsb->posted) ) {
  897.     /* Set up for complete traversal. */
  898.     post_str = owsb->posted.lowest.higher;
  899.     end = &(owsb->posted.highest);
  900.     PEXBeginRendering( ws->display, ws->rid, draw);
  901.     while ( post_str != end ) {
  902.         phg_wsb_traverse_net( ws, post_str->structh );
  903.         post_str = post_str->higher;
  904.     }
  905.     PEXEndRendering( ws->display, ws->rid, PEXOn );
  906.     XFlush( ws->display );
  907.     owsb->surf_state = PSURF_NOT_EMPTY;
  908.     }
  909. }
  910.  
  911.  
  912. void
  913. phg_wsb_traverse_net( ws, structp )
  914.     Ws_handle        ws;
  915.     Struct_handle    structp;
  916. {
  917.     register    El_handle    el;
  918.  
  919.     PEXBeginStructure( ws->display, ws->rid, (CARD32)structp->struct_id );
  920.     el = structp->first_el;
  921.     while ( 1 ) {    /* termination test is at the bottom */
  922.     switch ( el->eltype ) {
  923.         case PELEM_NIL:
  924.         break;
  925.         case PELEM_EXEC_STRUCT:
  926.         phg_wsb_traverse_net( ws, (Struct_handle)el->eldata.ptr );
  927.         break;
  928.         default:
  929.         PEXRenderOutputCommands( ws->display, ws->rid, (CARD32)1,
  930.             (CARD32)(((pexElementInfo *)el->eldata.ptr)->length
  931.             * sizeof(CARD32)),
  932.             (char *)el->eldata.ptr );
  933.         break;
  934.     }
  935.  
  936.     if ( el == structp->last_el )
  937.         break;  /* out of the while over all elements in struct */
  938.     el = el->next;
  939.     }
  940.     PEXEndStructure( ws->display, ws->rid );
  941. }
  942.  
  943.  
  944. static int
  945. wsb_visible_element_type( el )
  946.     El_handle    el;
  947. {
  948.     int        status = 1;    /* almost all are */
  949.  
  950.     switch ( el->eltype ) {
  951.     case PELEM_APPL_DATA:
  952.     case PELEM_LABEL:
  953.     case PELEM_PICK_ID:
  954.         status = 0;
  955.         break;
  956.     }
  957.  
  958.     return status;
  959. }
  960.  
  961. void
  962. phg_wsb_add_el( ws )
  963.     Ws    *ws;
  964. {
  965.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  966.     El_handle        cur_el = CSS_CUR_ELP(owsb->cssh);
  967.  
  968.     assure(CSS_CUR_STRUCTP(owsb->cssh)); /* A structure must be open */
  969.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  970.     switch ( owsb->now_action ) {
  971.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  972.     default:
  973.         if ( wsb_visible_element_type( cur_el ) )
  974.         (*ws->redraw_all)( ws, PFLAG_COND );
  975.         break;
  976.  
  977.     case PHG_UPDATE_UWOR:
  978.     case PHG_UPDATE_NOTHING:
  979.     case PHG_UPDATE_UQUM:
  980.         owsb->vis_rep = PVISUAL_ST_DEFER;
  981.         break;
  982.     }
  983. }
  984.  
  985.  
  986. int
  987. phg_wsb_asti_update( ws, clear_control )
  988.     Ws        *ws;
  989.     Pctrl_flag    clear_control;
  990. {
  991.     /* Returns non-zero if redraw occurred. */
  992.  
  993.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  994.  
  995.     switch ( (*owsb->update_action_table)
  996.         [(int)PHG_TIME_ATI]
  997.         [(int)ws->out_ws.mod_mode]
  998.         [(int)ws->out_ws.def_mode] ) {
  999.     case PHG_UPDATE_IF_INCORRECT:
  1000.     case PHG_UPDATE_IF_IL:
  1001.     case PHG_UPDATE_IF_IG:
  1002.         if ( owsb->vis_rep == PVISUAL_ST_CORRECT )
  1003.         break;
  1004.         /* else fall through to PHG_UPDATE_ACCURATE case */
  1005.     case PHG_UPDATE_ACCURATE:
  1006.         (*ws->redraw_all)( ws, clear_control );
  1007.         return 1;
  1008.  
  1009.     case PHG_UPDATE_UQUM:
  1010.     case PHG_UPDATE_UWOR:
  1011.     case PHG_UPDATE_NOTHING:
  1012.         break;
  1013.     }
  1014.  
  1015.     return 0;
  1016. }
  1017.  
  1018. void
  1019. phg_wsb_close_struct( ws, structh )
  1020.     Ws            *ws;
  1021.     Struct_handle    structh;
  1022. {
  1023.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1024.  
  1025.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1026.     /* First, do processing that is independent of screen output */
  1027.     switch ( owsb->now_action ) {
  1028.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1029.     case PHG_UPDATE_UWOR:
  1030.     case PHG_UPDATE_NOTHING:
  1031.     case PHG_UPDATE_UQUM:
  1032.     default:
  1033.         break;
  1034.     }
  1035.  
  1036.     /* Updates are implementation dependent in ASTI mode.  This is one
  1037.      * of the cases where we do an ASTI update;  we're hopefully doing the
  1038.      * application a favor.
  1039.      */
  1040.     (void)phg_wsb_asti_update( ws, PFLAG_COND );
  1041. }
  1042.  
  1043.  
  1044. static void
  1045. wsb_update_a_posting( ws, posting )
  1046.     Ws            *ws;
  1047.     Ws_post_str     *posting;
  1048. {
  1049.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1050.  
  1051.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1052.     switch ( owsb->now_action ) {
  1053.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1054.         (*ws->redraw_all)( ws, PFLAG_COND );
  1055.         break;
  1056.  
  1057.     case PHG_UPDATE_UWOR:
  1058.     case PHG_UPDATE_NOTHING:
  1059.     case PHG_UPDATE_UQUM:
  1060.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1061.         break;
  1062.     }
  1063. }
  1064.  
  1065.  
  1066. void
  1067. phg_wsb_post( ws, structh, priority, first_posting )
  1068.     Ws            *ws;
  1069.     Struct_handle    structh;
  1070.     Pfloat        priority;
  1071.     int            first_posting;    /* 0 if already posted */
  1072. {
  1073.     Ws_post_str     *start;
  1074.  
  1075.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1076.     register     Ws_post_str     *cur, *end;
  1077.     register     Ws_post_str     *new;
  1078.  
  1079.  
  1080.     if ( !first_posting ) {
  1081.     /* Check to see if structure is already posted. */
  1082.     cur = owsb->posted.lowest.higher;
  1083.     end = &owsb->posted.highest;
  1084.     while ( cur != end && cur->structh != structh )
  1085.         cur = cur->higher;
  1086.     }
  1087.  
  1088.     /* The structure is already_posted if (cur != end). */
  1089.     if ( !first_posting && cur != end ) {
  1090.     if( cur->higher != end && priority >= cur->higher->disp_pri ) {
  1091.         start = end->lower;
  1092.         assure(start == owsb->posted.highest.lower);
  1093.         end = cur->higher;    /* insert betw. cur->higher & posted.highest */
  1094.     } else if ( cur->lower != &owsb->posted.lowest
  1095.         && priority < cur->lower->disp_pri ) {
  1096.         /* Will insert between start and cur->lower. */
  1097.         start = cur->lower;
  1098.         end = &owsb->posted.lowest;
  1099.     } else {
  1100.         /* This is a reposting with the same *relative* prio. */
  1101.         cur->disp_pri = priority;
  1102.         return;
  1103.     }
  1104.  
  1105.     /* Struct is posted.  Remove it, but re-use its Ws_post_str entry */
  1106.     cur->lower->higher = cur->higher;
  1107.     cur->higher->lower = cur->lower;
  1108.     new = cur;
  1109.  
  1110.     } else {
  1111.     /* Struct is not currently posted, malloc an element. */
  1112.     if ( !(new = (Ws_post_str *)malloc(sizeof(Ws_post_str))) ) {
  1113.         ERR_BUF( ws->erh, ERR900);
  1114.         return;
  1115.     }
  1116.     start = owsb->posted.highest.lower;
  1117.     end = &owsb->posted.lowest;
  1118.     }
  1119.  
  1120.     /* Now figure out where to insert it, working backwards from start
  1121.      * to end
  1122.      */
  1123.     cur = start;
  1124.     while ( cur != end && cur->disp_pri > priority )
  1125.     cur = cur->lower;    /* if priorities equal, new after cur */
  1126.     /* insert new element w/prio >= than cur's, so cur->higher will be new */
  1127.     new->lower = cur;
  1128.     new->higher = cur->higher;
  1129.     cur->higher = new;
  1130.     new->higher->lower = new;
  1131.     new->structh = structh;
  1132.     new->disp_pri = priority;
  1133.  
  1134.     if ( structh->num_el != 0 )
  1135.     wsb_update_a_posting( ws, new );
  1136. }
  1137.  
  1138.  
  1139. /* This function only called from the css for change struct ids/refs -
  1140.  * it is used to change the structure pointers referencing a given
  1141.  * structure, because the way the change struct ids/refs functions work
  1142.  * is by changing struct_id fields rather than copying whole structures,
  1143.  * so any lists using structure pointers to reference specific structures
  1144.  * have to be changed to use the correct pointers.
  1145.  */
  1146.  
  1147. void
  1148. phg_wsb_change_posting( ws, unpost, post )
  1149.     Ws            *ws;
  1150.     Struct_handle    unpost, post;
  1151. {
  1152.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1153.     register     Ws_post_str     *cur, *end;
  1154.  
  1155.     cur = owsb->posted.lowest.higher;
  1156.     end = &owsb->posted.highest;
  1157.     while ( cur != end && cur->structh != unpost )
  1158.     cur = cur->higher;
  1159.  
  1160.     if ( cur != end ) {
  1161.     if ( post ) {
  1162.         /* if the structure to be "posted" is already posted, remove it */
  1163.         phg_wsb_change_posting( ws, post, (Struct_handle)NULL );
  1164.         /* Change posted structure from "unpost" to "post", same priority*/
  1165.         cur->structh = post;
  1166.     } else {
  1167.         /* Post is NULL - just remove Ws_post_str entry for unpost. */
  1168.         cur->lower->higher = cur->higher;
  1169.         cur->higher->lower = cur->lower;
  1170.         free( (char *)cur );
  1171.     }
  1172.     }
  1173. }
  1174.  
  1175.  
  1176. /* Search the list of posted structures for this one.
  1177.  * If found, return pointer to next-higher-priority posted structure element.
  1178.  * (Remember that that could be the dummy element owsb->posted.highest)
  1179.  * If not, return NULL.
  1180.  */
  1181. static Ws_post_str*
  1182. wsb_unpost_struct_if_found( owsb, structh )
  1183.     Wsb_output_ws    *owsb;
  1184.     Struct_handle     structh;
  1185. {
  1186.     register     Ws_post_str    *cur, *end;
  1187.  
  1188.     cur = owsb->posted.lowest.higher;
  1189.     end = &owsb->posted.highest;
  1190.     while ( cur != end && cur->structh != structh )
  1191.     cur = cur->higher;
  1192.     if ( cur != end ) {
  1193.     /* Found it -- now delete it */
  1194.     cur->lower->higher = cur->higher;
  1195.     cur->higher->lower = cur->lower;
  1196.     end = cur->higher;    /* Save this around the free */
  1197.     free( (char *)cur );
  1198.     return end;
  1199.     } else
  1200.     return (Ws_post_str*)NULL;
  1201. }
  1202.  
  1203.  
  1204. void
  1205. phg_wsb_unpost( ws, structh )
  1206.     Ws            *ws;
  1207.     Struct_handle    structh;
  1208. {
  1209.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1210.  
  1211.     if ( !wsb_unpost_struct_if_found( owsb, structh ) )
  1212.     /* Tried to unpost structure that wasn't there; but that's okay. */
  1213.     return;
  1214.  
  1215.     if ( structh->num_el != 0 ) {
  1216.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1217.     switch ( owsb->now_action ) {
  1218.         case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1219.         (*ws->redraw_all)( ws, PFLAG_COND );
  1220.         break;
  1221.  
  1222.         case PHG_UPDATE_UWOR:
  1223.         case PHG_UPDATE_NOTHING:
  1224.         case PHG_UPDATE_UQUM:
  1225.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1226.         break;
  1227.     }
  1228.     }
  1229. }
  1230.  
  1231.  
  1232. void
  1233. phg_wsb_unpost_all( ws )
  1234.     Ws    *ws;
  1235. {
  1236.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1237.  
  1238.     wsb_free_all_posted( owsb );
  1239.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1240.     switch ( owsb->now_action ) {
  1241.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1242.         (*ws->redraw_all)( ws, PFLAG_COND );
  1243.         break;
  1244.  
  1245.     case PHG_UPDATE_UWOR:
  1246.     case PHG_UPDATE_NOTHING:
  1247.     case PHG_UPDATE_UQUM:
  1248.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1249.         break;
  1250.     }
  1251. }
  1252.  
  1253.  
  1254. void
  1255. phg_wsb_delete_all_structs( ws )
  1256.     Ws        *ws;
  1257. {
  1258.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1259.  
  1260.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1261.     phg_wsb_unpost_all( ws );
  1262. }
  1263.  
  1264.  
  1265. int
  1266. phg_wsb_delete_struct( ws, structh, flag )
  1267.     Ws            *ws;
  1268.     Struct_handle    structh;
  1269.     Ws_delete_flag    flag;
  1270. {
  1271.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1272.     int            call_again = 0;
  1273.  
  1274.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1275.     switch ( owsb->now_action ) {
  1276.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1277.         if ( flag == WS_PRE_CSS_DELETE ) {
  1278.         (void)wsb_unpost_struct_if_found( owsb, structh );
  1279.         call_again = 1;
  1280.         } else
  1281.         (*ws->redraw_all)( ws, PFLAG_COND );
  1282.         break;
  1283.  
  1284.     case PHG_UPDATE_UWOR:
  1285.     case PHG_UPDATE_NOTHING:
  1286.     case PHG_UPDATE_UQUM:
  1287.         (void)wsb_unpost_struct_if_found( owsb, structh );
  1288.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1289.         break;
  1290.     }
  1291.  
  1292.     return call_again;
  1293. }
  1294.  
  1295.  
  1296. int
  1297. phg_wsb_delete_struct_net( ws, structh, reff, flag )
  1298.     Ws            *ws;
  1299.     Struct_handle     structh;
  1300.     Pref_flag         reff;
  1301.     Ws_delete_flag     flag;
  1302. {
  1303.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1304.     int            call_again = 0;
  1305.  
  1306.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1307.     switch ( owsb->now_action ) {
  1308.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1309.         if ( flag == WS_PRE_CSS_DELETE ) {
  1310.         (void)wsb_unpost_struct_if_found( owsb, structh );
  1311.         call_again = 1;
  1312.         } else
  1313.         (*ws->redraw_all)( ws, PFLAG_COND );
  1314.         break;
  1315.  
  1316.     case PHG_UPDATE_UWOR:
  1317.     case PHG_UPDATE_NOTHING:
  1318.     case PHG_UPDATE_UQUM:
  1319.     default:
  1320.         (void)wsb_unpost_struct_if_found( owsb, structh );
  1321.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1322.         break;
  1323.     }
  1324.     return call_again;
  1325. }
  1326.  
  1327.  
  1328. void
  1329. phg_wsb_copy_struct( ws, first_el )
  1330.     Ws        *ws;
  1331.     El_handle    first_el;
  1332. {
  1333.     (*ws->conditional_redraw)( ws );
  1334. }
  1335.  
  1336.  
  1337. /* Delete elements elh1 through elh2, inclusive, in structure structh */
  1338. int
  1339. phg_wsb_delete_el( ws, structh, elh1, elh2, flag )
  1340.     Ws            *ws;
  1341.     Struct_handle    structh;
  1342.     El_handle        elh1, elh2;
  1343.     Ws_delete_flag    flag;
  1344. {
  1345.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1346.     int            call_again = 0;
  1347.  
  1348.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1349.     switch ( owsb->now_action ) {
  1350.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1351.     default:
  1352.         if ( flag == WS_PRE_CSS_DELETE ) {
  1353.         if ( elh1 == elh2 && !wsb_visible_element_type( elh1 ) )
  1354.             call_again = 0; /* avoid second call. */
  1355.         else
  1356.             call_again = 1;
  1357.         } else        /* POST_CSS_DELETE */
  1358.         (*ws->redraw_all)(ws, PFLAG_COND);
  1359.         break;
  1360.  
  1361.     case PHG_UPDATE_UWOR:
  1362.     case PHG_UPDATE_NOTHING:
  1363.     case PHG_UPDATE_UQUM:
  1364.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1365.         break;
  1366.     }
  1367.  
  1368.     return call_again;
  1369. }
  1370.  
  1371.  
  1372. /* Called by CP after difficult operations like change struct refs/ids.
  1373.  * Redraws workstation, if that is permitted, else DEFERs.
  1374.  */
  1375. void
  1376. phg_wsb_conditional_redraw( ws )
  1377. Ws        *ws;
  1378. {
  1379.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1380.  
  1381.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1382.     switch ( owsb->now_action ) {
  1383.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1384.         (*ws->redraw_all)( ws, PFLAG_ALWAYS );
  1385.         break;
  1386.  
  1387.     case PHG_UPDATE_UQUM:
  1388.     case PHG_UPDATE_UWOR:
  1389.     case PHG_UPDATE_NOTHING:
  1390.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1391.         break;
  1392.     }
  1393. }
  1394.  
  1395.  
  1396. /* Resolves PHG_UPDATE_IF_Ix to the ASTI now_action, if no input device active.
  1397.  *
  1398.  * Check this function before every (out_ws->now_action) use.
  1399.  * Then use case_PHG_UPDATE_ACCURATE_or_IF_Ix in switch (out_ws->now_action),
  1400.  * so that PHG_UPDATE_IF_Ix acts as PHG_UPDATE_ACCURATE (i.e., ASAP)
  1401.  * while appicable input devices are (still) active.
  1402.  */
  1403. void
  1404. phg_wsb_resolve_now_action( ws, now_action_ptr )
  1405.     Ws            *ws;
  1406.     Ws_update_action    *now_action_ptr;
  1407. {
  1408.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1409.  
  1410.     switch ( *now_action_ptr ) {
  1411.       case PHG_UPDATE_IF_IL:
  1412.     /* If none active, treat like ASTI until next bnig_update(ws,ws) */
  1413.     if ( !WS_ANY_INP_DEV_ACTIVE(ws) ) {
  1414.         *now_action_ptr = (*owsb->update_action_table)
  1415.         [(int)PHG_TIME_NOW][(int)ws->out_ws.mod_mode][(int)PDEFER_ASTI];
  1416.     }
  1417.     break;
  1418.  
  1419.       case PHG_UPDATE_IF_IG:
  1420.     /* If none active, treat like ASTI until next bnig_update(ws,*) */
  1421.     if ( !phg_cp_any_inp_device_active( ws->cph ) ) {
  1422.         *now_action_ptr = (*owsb->update_action_table)
  1423.         [(int)PHG_TIME_NOW][(int)ws->out_ws.mod_mode][(int)PDEFER_ASTI];
  1424.     }
  1425.     break;
  1426.     }
  1427. }
  1428.  
  1429.  
  1430. void
  1431. phg_wsb_update( ws, flag )
  1432.     Ws        *ws;
  1433.     Pregen_flag    flag;
  1434. {
  1435.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1436.  
  1437.     if ( flag != PFLAG_POSTPONE && owsb->vis_rep != PVISUAL_ST_CORRECT ) 
  1438.     (*ws->redraw_all)( ws, PFLAG_COND );
  1439.     else
  1440.     (*ws->make_requested_current)( ws );
  1441. }
  1442.  
  1443.  
  1444. void
  1445. phg_wsb_set_disp_update_state( ws, def_mode, mod_mode )
  1446.     Ws        *ws;
  1447.     Pdefer_mode    def_mode;
  1448.     Pmod_mode    mod_mode;
  1449. {
  1450.     Ws_update_action    previous_now_action;
  1451.  
  1452.     register    Ws_output_ws    *out_ws = &ws->out_ws;
  1453.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1454.  
  1455.     out_ws->def_mode = def_mode;
  1456.     out_ws->mod_mode = mod_mode;
  1457.  
  1458.     previous_now_action = owsb->now_action;
  1459.     owsb->now_action = (*owsb->update_action_table)
  1460.     [(int)PHG_TIME_NOW][(int)out_ws->mod_mode][(int)out_ws->def_mode];
  1461.     assure(owsb->now_action != PHG_UPDATE_IF_INCORRECT);
  1462.  
  1463.     if ( owsb->now_action != previous_now_action ) {
  1464.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1465.     switch ( owsb->now_action ) {
  1466.         case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1467.         if( owsb->vis_rep != PVISUAL_ST_CORRECT )
  1468.             (*ws->redraw_all)( ws, PFLAG_COND );
  1469.         break;
  1470.     }
  1471.     }
  1472. }
  1473.  
  1474.  
  1475. void
  1476. phg_wsb_set_hlhsr_mode( ws, mode )
  1477.     Ws        *ws;
  1478.     Pint    mode;
  1479. {
  1480.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1481.  
  1482.     if( ws->type->desc_tbl.phigs_dt.num_hlhsr_modes == 1 )
  1483.     return; /* No need to update if the user asks for what he has! */
  1484.  
  1485.     owsb->req_hlhsr_mode = mode;
  1486.     owsb->hlhsr_mode_pending = PUPD_PEND;
  1487.  
  1488.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1489.     switch ( owsb->now_action ) {
  1490.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1491.         (*ws->redraw_all)( ws, PFLAG_COND );
  1492.         break;
  1493.  
  1494.     case PHG_UPDATE_UWOR:
  1495.     case PHG_UPDATE_UQUM:
  1496.     case PHG_UPDATE_NOTHING:
  1497.     default:
  1498.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1499.         break;
  1500.     }
  1501. }
  1502.  
  1503.  
  1504. void
  1505. phg_wsb_set_ws_window( ws, two_d, limits )
  1506.     Ws        *ws;
  1507.     int        two_d;
  1508.     Plimit3    *limits;
  1509. {
  1510.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1511.  
  1512.     owsb->ws_window_pending = PUPD_PEND;
  1513.     if ( two_d ) {    /* leave the z values as they are */
  1514.     owsb->req_ws_window.x_min = limits->x_min;
  1515.     owsb->req_ws_window.x_max = limits->x_max;
  1516.     owsb->req_ws_window.y_min = limits->y_min;
  1517.     owsb->req_ws_window.y_max = limits->y_max;
  1518.     } else
  1519.     owsb->req_ws_window = *limits;
  1520.  
  1521.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1522.     switch ( owsb->now_action ) {
  1523.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1524.         (*ws->redraw_all)( ws, PFLAG_COND );
  1525.         break;
  1526.  
  1527.     case PHG_UPDATE_UQUM:
  1528.     case PHG_UPDATE_UWOR:
  1529.     case PHG_UPDATE_NOTHING:
  1530.     default:
  1531.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1532.         break;
  1533.     }
  1534. }
  1535.  
  1536.  
  1537. void
  1538. phg_wsb_set_ws_vp( ws, two_d, limits )
  1539.     Ws        *ws;
  1540.     int        two_d;
  1541.     Plimit3    *limits;
  1542. {
  1543.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1544.  
  1545.     owsb->ws_viewport_pending = PUPD_PEND;
  1546.     if ( two_d ) {    /* leave the z values as they are */
  1547.     owsb->req_ws_viewport.x_min = limits->x_min;
  1548.     owsb->req_ws_viewport.x_max = limits->x_max;
  1549.     owsb->req_ws_viewport.y_min = limits->y_min;
  1550.     owsb->req_ws_viewport.y_max = limits->y_max;
  1551.     } else
  1552.     owsb->req_ws_viewport = *limits;
  1553.  
  1554.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1555.     switch ( owsb->now_action ) {
  1556.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1557.         (*ws->redraw_all)( ws, PFLAG_COND );
  1558.         break;
  1559.  
  1560.     case PHG_UPDATE_UQUM:
  1561.     case PHG_UPDATE_UWOR:
  1562.     case PHG_UPDATE_NOTHING:
  1563.     default:
  1564.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1565.         break;
  1566.     }
  1567. }
  1568.  
  1569.  
  1570. void
  1571. phg_wsb_set_view_input_priority( ws, index, ref_index, priority )
  1572.     Ws            *ws;
  1573.     register Pint    index;
  1574.     Pint        ref_index;
  1575.     Prel_pri        priority;
  1576. {
  1577.     Pint            old;
  1578.  
  1579.     register    Ws_view_priority    *ref, *idx;
  1580.     register    Pint            *highest;
  1581.     register    Ws_view_priority    *vp;
  1582.  
  1583.     vp = ws->out_ws.model.b.view_priorities;
  1584.     highest = &ws->out_ws.model.b.top_view;
  1585.     idx = &vp[index];
  1586.     ref = &vp[ref_index];
  1587.  
  1588.     if ( priority == PPRI_LOWER ) {
  1589.     if ( ref->lower != index ) {
  1590.         if ( index == *highest)
  1591.         *highest = idx->lower;
  1592.  
  1593.         old = ref->lower;
  1594.         if ( ref->lower != -1 )    /* if ref not lowest priority */
  1595.         vp[ref->lower].higher = index;
  1596.         ref->lower = index;
  1597.  
  1598.         if ( idx->higher != -1 )     /* if idx not highest priority */
  1599.         vp[idx->higher].lower = idx->lower;
  1600.         if ( idx->lower != -1 )     /* if idx not lowest priority */
  1601.         vp[idx->lower].higher = idx->higher;
  1602.         idx->higher = ref_index;
  1603.         idx->lower = old;
  1604.     }
  1605.     /* Don't need to do anything if priority is already as desired. */
  1606.  
  1607.     } else if ( ref->higher != index ) {    /* PPRI_HIGHER */
  1608.     if ( ref_index == *highest )
  1609.         *highest = index;
  1610.     else if ( index == *highest )
  1611.         *highest = idx->lower;
  1612.  
  1613.     old = ref->higher;
  1614.     if ( ref->higher != -1 )
  1615.         vp[ref->higher].lower = index;
  1616.     ref->higher = index;
  1617.  
  1618.     if ( idx->higher != -1 )
  1619.         vp[idx->higher].lower = idx->lower;
  1620.     if ( idx->lower != -1 )
  1621.         vp[idx->lower].higher = idx->higher;
  1622.     idx->lower = ref_index;
  1623.     idx->higher = old;
  1624.     }
  1625.  
  1626.     /* Has no effect on the screen */
  1627. }
  1628.  
  1629.  
  1630. void
  1631. phg_wsb_set_rep( ws, type, rep )
  1632.     Ws            *ws;
  1633.     Phg_args_rep_type    type;
  1634.     Phg_args_rep_data    *rep;
  1635. {
  1636.     register    Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1637.     register    int        i;
  1638.  
  1639.     switch ( type ) {
  1640.     case PHG_ARGS_LNREP:
  1641.     case PHG_ARGS_EXTLNREP:
  1642.     case PHG_ARGS_MKREP:
  1643.     case PHG_ARGS_EXTMKREP:
  1644.     case PHG_ARGS_TXREP:
  1645.     case PHG_ARGS_EXTTXREP:
  1646.     case PHG_ARGS_INTERREP:
  1647.     case PHG_ARGS_EXTINTERREP:
  1648.     case PHG_ARGS_EDGEREP:
  1649.     case PHG_ARGS_EXTEDGEREP:
  1650.     case PHG_ARGS_PTREP:
  1651.     case PHG_ARGS_EXTPTREP:
  1652.     case PHG_ARGS_DCUEREP:
  1653.     case PHG_ARGS_LIGHTSRCREP:
  1654.     case PHG_ARGS_COLRMAPREP:
  1655.         phg_wsx_set_LUT_entry( ws, type, rep, (Pgcolr*)NULL );
  1656.         break;
  1657.  
  1658.     case PHG_ARGS_VIEWREP:
  1659.         /* Add it to the list of pending views. */
  1660.         if ( owsb->views[rep->index].pending == PUPD_NOT_PEND )
  1661.         i = owsb->num_pending_views++;
  1662.         else {
  1663.         /* Find the existing pending entry so it can be replaced. */
  1664.         for ( i = 0; i < owsb->num_pending_views; i++ )
  1665.             if ( owsb->pending_views[i].id == rep->index )
  1666.             break;
  1667.         }
  1668.         owsb->pending_views[i].id = rep->index;
  1669.         owsb->pending_views[i].view = rep->bundl.viewrep;
  1670.         owsb->views[rep->index].pending = PUPD_PEND;
  1671.         break;
  1672.  
  1673.     case PHG_ARGS_COREP: {
  1674.         Pgcolr    gcolr;
  1675.  
  1676.         /* Store in current colour model. */
  1677.         gcolr.type = ws->current_colour_model;
  1678.         gcolr.val.general.x = rep->bundl.corep.rgb.red;
  1679.         gcolr.val.general.y = rep->bundl.corep.rgb.green;
  1680.         gcolr.val.general.z = rep->bundl.corep.rgb.blue;
  1681.         phg_wsx_set_LUT_entry( ws, type, rep, &gcolr );
  1682.         } break;
  1683.     }
  1684.  
  1685.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1686.     switch ( owsb->now_action ) {
  1687.     case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1688.         (*ws->redraw_all)( ws, PFLAG_COND );
  1689.         break;
  1690.  
  1691.     default:
  1692.     case PHG_UPDATE_UQUM:
  1693.     case PHG_UPDATE_UWOR:
  1694.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1695.         break;
  1696.  
  1697.     case PHG_UPDATE_NOTHING:
  1698.         /* Defer if rep has PENDING flag, or if screen could be affected. */
  1699.         if ( WSB_SOME_POSTED(&owsb->posted) || (type == PHG_ARGS_VIEWREP) )
  1700.          owsb->vis_rep = PVISUAL_ST_DEFER;
  1701.         break;
  1702.     }
  1703. }
  1704.  
  1705. void
  1706. phg_wsb_set_filter( ws, type, devid, inc_set, exc_set )
  1707.     Ws            *ws;
  1708.     Phg_args_flt_type    type;
  1709.     Pint        devid;
  1710.     Pint_list        *inc_set;
  1711.     Pint_list        *exc_set;
  1712. {
  1713.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1714.  
  1715.     phg_wsx_set_name_set( ws, type, devid, inc_set, exc_set );
  1716.  
  1717.     if ( (type == PHG_ARGS_FLT_HIGH || type == PHG_ARGS_FLT_INVIS)
  1718.         && WSB_SOME_POSTED(&owsb->posted) ) {
  1719.     WSB_CHECK_FOR_INTERACTION_UNDERWAY(ws, &owsb->now_action)
  1720.     switch ( owsb->now_action ) {
  1721.         case_PHG_UPDATE_ACCURATE_or_IF_Ix:
  1722.         (*ws->redraw_all)( ws, PFLAG_COND );
  1723.         break;
  1724.  
  1725.         case PHG_UPDATE_UQUM:
  1726.         case PHG_UPDATE_UWOR:
  1727.         case PHG_UPDATE_NOTHING:
  1728.         default:
  1729.         owsb->vis_rep = PVISUAL_ST_DEFER;
  1730.         break;
  1731.     }
  1732.     }
  1733. }
  1734.  
  1735.  
  1736. void
  1737. phg_wsb_inq_view_indices( ws, ret )
  1738.     Ws        *ws;
  1739.     Phg_ret    *ret;
  1740. {
  1741.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1742.  
  1743.     register    Pint            *list, view;
  1744.     register    int            i;
  1745.     register    Ws_view_priority    *prio = owsb->view_priorities;
  1746.  
  1747.     if ( !PHG_SCRATCH_SPACE( &ws->scratch, owsb->num_views * sizeof(Pint))) {
  1748.     ret->err = ERR900;
  1749.  
  1750.     } else {
  1751.     ret->err = 0;
  1752.     ret->data.int_list.num_ints = owsb->num_views;
  1753.     ret->data.int_list.ints = list = (Pint *)ws->scratch.buf;
  1754.     view = owsb->top_view;
  1755.     i = 0;
  1756.     while ( view != -1 ) {
  1757.         list[i++] = view;
  1758.         view = prio[view].lower;
  1759.     }
  1760.     }
  1761. }
  1762.  
  1763.  
  1764. void
  1765. phg_wsb_inq_posted( ws, ret )
  1766.     Ws        *ws;
  1767.     Phg_ret    *ret;
  1768. {
  1769.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1770.  
  1771.     register    Ws_post_str    *cur, *end;
  1772.     register    int        cnt;
  1773.     register    Pposted_struct    *list;
  1774.  
  1775.     cur = owsb->posted.lowest.higher;
  1776.     end = &owsb->posted.highest;
  1777.  
  1778.     /* Count them */
  1779.     cnt = 0;
  1780.     while ( cur != end ) {
  1781.     ++cnt;
  1782.     cur = cur->higher;
  1783.     }
  1784.  
  1785.     ret->err = 0;
  1786.     ret->data.postlist.num_postings = cnt;
  1787.     if ( cnt > 0 ) {
  1788.     if ( PHG_SCRATCH_SPACE(&ws->scratch, cnt * sizeof(Pposted_struct)) ) {
  1789.         ret->data.postlist.postings = list =
  1790.         (Pposted_struct *)ws->scratch.buf;
  1791.         cur = owsb->posted.lowest.higher;
  1792.         while ( cur != end ) {
  1793.         list->id = cur->structh->struct_id;
  1794.         list++->disp_pri = cur->disp_pri;
  1795.         cur = cur->higher;
  1796.         }
  1797.  
  1798.     } else {
  1799.         ret->err = ERR900;
  1800.         ret->data.postlist.num_postings = 0;
  1801.     }
  1802.     }
  1803. }
  1804.  
  1805.  
  1806. void
  1807. phg_wsb_inq_view_rep( ws, index, ret )
  1808.     Ws        *ws;
  1809.     Pint    index;
  1810.     Phg_ret    *ret;
  1811. {
  1812.     register int        i;
  1813.     register Pview_rep3        *cr;
  1814.     register Ws_view_entry    *cv;
  1815.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1816.     register Phg_ret_view_rep    *vr = &ret->data.view_rep;
  1817.  
  1818.     ret->err = 0;
  1819.     vr->update_state = owsb->views[index].pending;
  1820.     /* Load the "current" view. */
  1821.     if ( !PHG_SCRATCH_SPACE( &ws->scratch, sizeof(Pview_rep3) ) ) {
  1822.     ret->err = ERR900;
  1823.     return;
  1824.     } else {
  1825.     vr->cur_rep = cr = (Pview_rep3 *)ws->scratch.buf;
  1826.     cv = &owsb->views[index];
  1827.     cr->clip_limit = cv->clip_limit;
  1828.     cr->xy_clip = cv->xy_clip;
  1829.     cr->back_clip = cv->back_clip;
  1830.     cr->front_clip = cv->front_clip;
  1831.     bcopy( (char *)cv->vom, (char *)cr->ori_matrix, sizeof(Pmatrix3) );
  1832.     bcopy( (char *)cv->vmm, (char *)cr->map_matrix, sizeof(Pmatrix3) );
  1833.     }
  1834.  
  1835.     /* Load the "requested" view. */
  1836.     if ( vr->update_state == PUPD_NOT_PEND )    /* save some time */
  1837.     vr->req_rep = vr->cur_rep;
  1838.     else {
  1839.     /* Find the requested entry in the pending view list. */
  1840.     for ( i = 0; i < owsb->num_pending_views; i++ ) {
  1841.         if ( owsb->pending_views[i].id == index ) {
  1842.         cr = &owsb->pending_views[i].view;
  1843.         break;    /* we've found it, no need to keep searching */
  1844.         }
  1845.     }
  1846.     vr->req_rep = cr;
  1847.     }
  1848. }
  1849.  
  1850.  
  1851. void
  1852. phg_wsb_inq_ws_xform( ws, ret )
  1853.     Ws        *ws;
  1854.     Phg_ret    *ret;
  1855. {
  1856.     register Phg_ret_ws_tran3    *wsxf = &ret->data.ws_xform;
  1857.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1858.  
  1859.     ret->err = 0;
  1860.     wsxf->state =
  1861.        owsb->ws_window_pending == PUPD_PEND
  1862.     || owsb->ws_viewport_pending == PUPD_PEND
  1863.         ? PUPD_PEND : PUPD_NOT_PEND;
  1864.     wsxf->req_window = owsb->req_ws_window;
  1865.     wsxf->req_viewport = owsb->req_ws_viewport;
  1866.     wsxf->cur_window = owsb->ws_window;
  1867.     wsxf->cur_viewport = owsb->ws_viewport;
  1868. }
  1869.  
  1870.  
  1871. void
  1872. phg_wsb_inq_disp_update_state( ws, ret)
  1873.     Ws            *ws;
  1874.     Phg_ret        *ret;
  1875. {
  1876.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1877.  
  1878.     ret->err = 0;
  1879.     ret->data.update_state.def_mode = ws->out_ws.def_mode;
  1880.     ret->data.update_state.mod_mode = ws->out_ws.mod_mode;
  1881.     ret->data.update_state.display_surf = owsb->surf_state;
  1882.     ret->data.update_state.state = owsb->vis_rep;
  1883. }
  1884.  
  1885.  
  1886. void
  1887. phg_wsb_inq_hlhsr_mode( ws, ret )
  1888.     Ws            *ws;
  1889.     Phg_ret        *ret;
  1890. {
  1891.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  1892.  
  1893.     ret->err = 0;
  1894.     ret->data.hlhsr_mode.state =  owsb->hlhsr_mode_pending;
  1895.     ret->data.hlhsr_mode.cur_mode = owsb->cur_hlhsr_mode;
  1896.     ret->data.hlhsr_mode.req_mode = owsb->req_hlhsr_mode;
  1897. }
  1898.  
  1899.  
  1900. void
  1901. phg_wsb_inq_rep( ws, index, how, rep_type, ret )
  1902.     Ws            *ws;
  1903.     Pint        index;
  1904.     Pinq_type        how;        /* set or realized */
  1905.     Phg_args_rep_type    rep_type;
  1906.     Phg_ret        *ret;
  1907. {
  1908.     ret->err = 0;
  1909.     switch ( rep_type ) {
  1910.     case PHG_ARGS_LNREP:
  1911.     case PHG_ARGS_EXTLNREP:
  1912.     case PHG_ARGS_MKREP:
  1913.     case PHG_ARGS_EXTMKREP:
  1914.     case PHG_ARGS_TXREP:
  1915.     case PHG_ARGS_EXTTXREP:
  1916.     case PHG_ARGS_INTERREP:
  1917.     case PHG_ARGS_EXTINTERREP:
  1918.     case PHG_ARGS_EDGEREP:
  1919.     case PHG_ARGS_EXTEDGEREP:
  1920.     case PHG_ARGS_PTREP:
  1921.     case PHG_ARGS_EXTPTREP:
  1922.     case PHG_ARGS_DCUEREP:
  1923.     case PHG_ARGS_LIGHTSRCREP:
  1924.     case PHG_ARGS_COLRMAPREP:
  1925.     /* View rep is done elsewhere. */
  1926.         phg_wsx_inq_LUT_entry( ws, index, how, rep_type, ret,
  1927.         (Pgcolr *)NULL, (Pview_rep3 *)NULL );
  1928.         break;
  1929.  
  1930.     case PHG_ARGS_COREP: {
  1931.         Pgcolr        src_gcolr, gcolr;
  1932.         Pcolr_rep    *cb = &ret->data.rep.corep;
  1933.  
  1934.         /* Need to convert to current colour model. */
  1935.         phg_wsx_inq_LUT_entry( ws, index, how, rep_type, ret,
  1936.         &src_gcolr, (Pview_rep3 *)NULL );
  1937.         gcolr.type = ws->current_colour_model;
  1938.         (void)phg_utx_convert_colour( &src_gcolr, &gcolr,
  1939.         &ws->type->desc_tbl.phigs_dt.out_dt.chroma_info );
  1940.         cb->rgb.red = gcolr.val.general.x;
  1941.         cb->rgb.green = gcolr.val.general.y;
  1942.         cb->rgb.blue = gcolr.val.general.z;
  1943.         } break;
  1944.     }
  1945. }
  1946.  
  1947.  
  1948. static void
  1949. update_inv_view_xform( view )
  1950.     Ws_view_entry    *view;
  1951. {
  1952.      /* Calculate the inverse xform, if necessary. */
  1953.     if ( view->npc_to_wc_state == WS_INV_NOT_CURRENT ) {
  1954.     phg_mat_mul( view->npc_to_wc, view->vmm, view->vom );
  1955.     phg_mat_inv( view->npc_to_wc );
  1956.     view->npc_to_wc_state = WS_INV_CURRENT;
  1957.     }
  1958. }
  1959.  
  1960.  
  1961. int
  1962. phg_wsb_map_initial_points( ws, view_index, num_pts, wc_pts, dwbl_pts )
  1963.     Ws        *ws;
  1964.     Pint    view_index;
  1965.     Pint    *num_pts;
  1966.     Ppoint3    *wc_pts;
  1967.     XPoint    *dwbl_pts;
  1968. {
  1969.     Ppoint3    scratch[20];    /* enough for most cases */
  1970.     Pmatrix3    wc_to_npc;
  1971.     Ppoint3    dc_pt;
  1972.  
  1973.     register    Ppoint3        *npc_pts = (Ppoint3 *)NULL;
  1974.     register    int        i;
  1975.     register    Ws_view_entry    *view;
  1976.     register    Ws_xform    *wsxf = &ws->out_ws.model.b.ws_xform;
  1977.  
  1978.     /* Transform the initial points to NPC and check that they all fit
  1979.      * in the clip limits of the specified view.  Then transform and map
  1980.      * them to drawable coordinates.
  1981.      */
  1982.     if ( *num_pts <= 0 )
  1983.     return 0;
  1984.     if ( *num_pts <= sizeof(scratch)/sizeof(scratch[0]) )
  1985.     npc_pts = scratch;
  1986.     else if ( *num_pts > sizeof(scratch)/sizeof(scratch[0]) ) {
  1987.     if ( !(npc_pts = (Ppoint3 *)malloc( (unsigned)(*num_pts *
  1988.         sizeof(Ppoint3)) )) ) {
  1989.         *num_pts = 0;
  1990.         ERR_BUF( ws->erh, ERR900 );
  1991.         return 0;
  1992.     }
  1993.     }
  1994.  
  1995.     view = &ws->out_ws.model.b.views[view_index];
  1996.     phg_mat_mul( wc_to_npc, view->vmm, view->vom );
  1997.     if ( !phg_tranpts3( wc_to_npc, *num_pts, wc_pts, npc_pts ) ) {
  1998.     *num_pts = 0;
  1999.     return 0;
  2000.     }
  2001.  
  2002.     for ( i = 0; i < *num_pts; i++ ) {
  2003.     if ( !WS_PT_IN_LIMIT( &view->clip_limit, &npc_pts[i] ) ) {
  2004.         *num_pts = 0;
  2005.         break;
  2006.     } else {
  2007.         WS_NPC_TO_DC( wsxf, &npc_pts[i], &dc_pt )
  2008.         WS_DC_TO_DRWBL2( ws, &dc_pt, &dwbl_pts[i] );
  2009.     }
  2010.     }
  2011.  
  2012.     if ( npc_pts && npc_pts != scratch )
  2013.     free( (char *)npc_pts );
  2014.  
  2015.     return ( *num_pts > 0 ? 1 : 0 );
  2016. }
  2017.  
  2018.  
  2019. int
  2020. phg_wsb_resolve_locator( ws, dc_pt, determine_z, view_index, wc_pt )
  2021.     Ws            *ws;
  2022.     pexDeviceCoord      *dc_pt;
  2023.     int            determine_z;    /* ignored */
  2024.     Pint        *view_index;
  2025.     Ppoint3        *wc_pt;
  2026. {
  2027.     Ppoint3        npc_pt;
  2028.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  2029.     Ws_view_priority    *priorities = owsb->view_priorities;
  2030.     Ws_xform        *wsxf = &owsb->ws_xform;
  2031.     Plimit3        *ws_win = &owsb->ws_window;
  2032.     int            status = 0;
  2033.  
  2034.     register Ws_view_entry    *view;
  2035.  
  2036.     /* Apply the inverse WS transform and see if it's in the ws window.
  2037.      * Can't just check against the viewport boundaries because the
  2038.      * window may be smaller if the aspect ratios are different.
  2039.      */
  2040.     WS_DC_TO_NPC2(wsxf, dc_pt, &npc_pt)
  2041.     if ( npc_pt.x >= ws_win->x_min && npc_pt.x <= ws_win->x_max
  2042.     && npc_pt.y >= ws_win->y_min && npc_pt.y <= ws_win->y_max ) {
  2043.  
  2044.     /* Find the highest priority view that contains the point. */
  2045.     for ( *view_index = owsb->top_view; *view_index != -1;
  2046.         *view_index = priorities[*view_index].lower ) {
  2047.         view = &owsb->views[*view_index];
  2048.         if ( WS_PT_IN_LIMIT2(&view->clip_limit, &npc_pt) ) {
  2049.         /* Assign the clip window minimum to Z. */
  2050.         npc_pt.z = view->clip_limit.z_min;
  2051.  
  2052.         /* Calculate the inverse xform if necessary. */
  2053.         if ( view->npc_to_wc_state == WS_INV_NOT_CURRENT )
  2054.             update_inv_view_xform( view );
  2055.   
  2056.         /* Map point to WC if xform invertible. */
  2057.         if ( view->npc_to_wc_state == WS_INV_CURRENT ) {
  2058.             if ( phg_tranpt3( &npc_pt, view->npc_to_wc, wc_pt ) ) {
  2059.             status = 1;
  2060.             break;    /* out of the for on view index */
  2061.             }
  2062.         }
  2063.         }
  2064.     }
  2065.     }
  2066.     return status;
  2067. }
  2068.  
  2069.  
  2070. static int
  2071. wsb_resolve_stroke( ws, two_d, dc_ll, dc_ur, view_index )
  2072.     Ws            *ws;
  2073.     int            two_d;    /* input points are 2D */
  2074.     pexDeviceCoord    *dc_ll, *dc_ur;
  2075.     Pint        *view_index;    /* resolved view index */
  2076.  
  2077.     /* Returns 1 if stroke resolvable, else 0 */
  2078. {
  2079.     Ppoint3        npc_ll, npc_ur;
  2080.     Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  2081.     Ws_view_priority    *priorities = owsb->view_priorities;
  2082.     Ws_xform        *wsxf = &owsb->ws_xform;
  2083.     Plimit3        *ws_win = &owsb->ws_window;
  2084.     int            status = 0, in_limit;
  2085.  
  2086.     register Ws_view_entry    *view;
  2087.  
  2088.     /* Apply the inverse WS transform and see if the bounding box is in
  2089.      * the ws window.  Can't just check against the viewport boundaries
  2090.      * because the window may be smaller if the aspect ratios are different.
  2091.      */
  2092.     in_limit = 0;
  2093.     if ( two_d ) {
  2094.     WS_DC_TO_NPC2(wsxf, dc_ll, &npc_ll)
  2095.     WS_DC_TO_NPC2(wsxf, dc_ur, &npc_ur)
  2096.     in_limit = WS_PT_IN_LIMIT2(ws_win, &npc_ll)
  2097.         && WS_PT_IN_LIMIT2(ws_win, &npc_ur);
  2098.     } else {
  2099.     WS_DC_TO_NPC(wsxf, dc_ll, &npc_ll)
  2100.     WS_DC_TO_NPC(wsxf, dc_ur, &npc_ur)
  2101.     in_limit = WS_PT_IN_LIMIT(ws_win, &npc_ll)
  2102.         && WS_PT_IN_LIMIT(ws_win, &npc_ur);
  2103.     }
  2104.  
  2105.     if ( in_limit ) {
  2106.     /* Find the highest priority view that contains the bounding box. */
  2107.     for ( *view_index = owsb->top_view; *view_index != -1;
  2108.         *view_index = priorities[*view_index].lower ) {
  2109.         view = &owsb->views[*view_index];
  2110.         in_limit = 0;
  2111.         if ( two_d )
  2112.         in_limit = WS_PT_IN_LIMIT2(&view->clip_limit, &npc_ll)
  2113.             && WS_PT_IN_LIMIT2(&view->clip_limit, &npc_ur);
  2114.         else
  2115.         in_limit = WS_PT_IN_LIMIT(&view->clip_limit, &npc_ll)
  2116.             && WS_PT_IN_LIMIT(&view->clip_limit, &npc_ur);
  2117.  
  2118.         if ( in_limit ) {
  2119.         /* Found the view.  Calculate its inverse transform if
  2120.          * necessary.
  2121.          */
  2122.         if ( view->npc_to_wc_state == WS_INV_NOT_CURRENT )
  2123.             update_inv_view_xform( view );
  2124.  
  2125.         if ( view->npc_to_wc_state == WS_INV_CURRENT ) {
  2126.             status = 1;
  2127.             break;  /* break out of the view loop when view found */
  2128.         }
  2129.         }
  2130.     }
  2131.     }
  2132.     return status;
  2133. }
  2134.  
  2135.  
  2136. static void
  2137. wsb_transform_stroke( ws, view_index, two_d, num_pts, dc_pts, wc_pts )
  2138.         Ws        *ws;
  2139.         Pint        view_index;
  2140.         int        two_d;
  2141.     register    int        num_pts;
  2142.     register    pexDeviceCoord    *dc_pts;
  2143.         Ppoint_list3    *wc_pts;
  2144. {
  2145.     register int        i;
  2146.     register Ppoint3        *npc_pts;
  2147.     register Ws_xform        *wsxf = &ws->out_ws.model.b.ws_xform;
  2148.     register Ws_view_entry    *view = &ws->out_ws.model.b.views[view_index];
  2149.  
  2150.     /* Shouldn't call this function with num_pts == 0. */
  2151.     if ( !(npc_pts = (Ppoint3 *)
  2152.         malloc( (unsigned)(num_pts * sizeof(Ppoint3)) )) ) {
  2153.     wc_pts->num_points = 0;
  2154.     ERR_BUF( ws->erh, ERR900 );
  2155.     return;
  2156.     }
  2157.  
  2158.     /* Transform the points to npc and add the z value. */
  2159.     for ( i = 0; i < num_pts; i++ ) {
  2160.     if ( two_d ) {
  2161.         WS_DC_TO_NPC2(wsxf, &dc_pts[i], &npc_pts[i])
  2162.         /* Assign the back clip limit. */
  2163.         npc_pts[i].z = view->clip_limit.z_min;
  2164.     } else {
  2165.         WS_DC_TO_NPC(wsxf, &dc_pts[i], &npc_pts[i])
  2166.     }
  2167.     }
  2168.  
  2169.     /* Transform the points to wc. */
  2170.     if ( !phg_tranpts3( view->npc_to_wc, num_pts, npc_pts, wc_pts->points ) )
  2171.     wc_pts->num_points = 0;
  2172.  
  2173.     free( (char *)npc_pts );
  2174. }
  2175.  
  2176.  
  2177. int
  2178. phg_wsb_resolve_stroke( ws, num_pts, dc_pts, determine_z, view_index, wc_pts )
  2179.         Ws        *ws;
  2180.     register    int        num_pts;
  2181.         pexDeviceCoord    *dc_pts;
  2182.         int        determine_z;    /* ignored */
  2183.         Pint        *view_index;
  2184.         Ppoint_list3    *wc_pts;
  2185. {
  2186.     pexDeviceCoord    ll, ur;
  2187.     int            status = 0, two_d = determine_z;
  2188.  
  2189.     register pexDeviceCoord    *dp;
  2190.     register int        i, xmin, xmax, ymin, ymax, zmin, zmax;
  2191.  
  2192.     /* Get the bounding box of all the points. */
  2193.     xmin = dc_pts->x; xmax = dc_pts->x;
  2194.     ymin = dc_pts->y; ymax = dc_pts->y;
  2195.     if ( !two_d )
  2196.     zmin = dc_pts->z, zmax = dc_pts->z;
  2197.     for ( i = 1, dp = &dc_pts[1]; i < num_pts; i++, dp++ ) {
  2198.     if ( dp->x < xmin )
  2199.         xmin = dp->x;
  2200.     else if ( dp->x > xmax )
  2201.         xmax = dp->x;
  2202.  
  2203.     if ( dp->y < ymin )
  2204.         ymin = dp->y;
  2205.     else if ( dp->y > ymax )
  2206.         ymax = dp->y;
  2207.     
  2208.     if ( !two_d ) {
  2209.         /* The incoming points have Z values. */
  2210.         if ( dp->z < zmin )
  2211.         zmin = dp->z;
  2212.         else if ( dp->z > zmax )
  2213.         zmax = dp->z;
  2214.     }
  2215.     }
  2216.     ll.x = xmin; ll.y = ymax;
  2217.     ur.x = xmax; ur.y = ymin;
  2218.     if ( !two_d )
  2219.     ur.x = xmax, ur.y = ymin;
  2220.  
  2221.     /* Resolve and transform the points.  Don't change the current
  2222.      * measure if the points can't be resolved.
  2223.      */
  2224.     if ( wsb_resolve_stroke( ws, two_d, &ll, &ur, view_index ) ) {
  2225.     wc_pts->num_points = num_pts;
  2226.     wsb_transform_stroke( ws, *view_index, two_d, num_pts, dc_pts, wc_pts );
  2227.     status = 1;
  2228.     }
  2229.  
  2230.     return status;
  2231. }
  2232.  
  2233.  
  2234. int
  2235. phg_wsb_resolve_pick( ws, dev, echo, dc_pt, pick )
  2236.     Ws            *ws;
  2237.     Ws_inp_pick        *dev;
  2238.     int            echo;
  2239.     pexDeviceCoord      *dc_pt;
  2240.     Ppick        *pick;
  2241. {
  2242.     register Wsb_output_ws    *owsb = &ws->out_ws.model.b;
  2243.     register Ws_post_str    *post_str, *end;
  2244.     pexDeviceCoord2D        dc_vol[2];
  2245.     Ppoint            npc_pt[2];
  2246.     pexPickElementRef        *pickPath;
  2247.     int                pickDepth;
  2248.     int                betterPick, i;
  2249.  
  2250.     CARD32            pickDataBytes;
  2251.  
  2252.     struct {
  2253.     pexEnumTypeIndex pickType;
  2254.     CARD16         unused;
  2255.     union {
  2256.         pexPD_DC_HitBox    dcHitBox;
  2257.         pexPD_NPC_HitVolume npcHitVolume;
  2258.     } pickRec;
  2259.     } pickData;
  2260.     
  2261.     WSB_CHECK_POSTED (&owsb->posted)
  2262.  
  2263.     if (WSB_SOME_POSTED (&owsb->posted)) {
  2264.  
  2265.     /*
  2266.      * Use pick rendering to get the pick results.  Call BeginPickOne, do
  2267.      * a complete traversal (starting with highest priority structure,
  2268.      * then call EndPickOne to get the pick results.
  2269.      */
  2270.  
  2271.     if (dev->dev_type == PEXPickDeviceDC_HitBox) {
  2272.  
  2273.         pickData.pickType = PEXPickDeviceDC_HitBox;
  2274.  
  2275.         pickData.pickRec.dcHitBox.position.x = dc_pt->x;
  2276.         pickData.pickRec.dcHitBox.position.y = dc_pt->y;
  2277.         pickData.pickRec.dcHitBox.distance = dev->ap_size;
  2278.  
  2279.         pickDataBytes = 4 + sizeof (pexPD_DC_HitBox);
  2280.  
  2281.     } else {
  2282.  
  2283.         pickData.pickType = PEXPickDeviceNPC_HitVolume;
  2284.  
  2285.         dc_vol[0].x = dc_pt->x - dev->ap_size;
  2286.         dc_vol[0].y = dc_pt->y - dev->ap_size;
  2287.         dc_vol[1].x = dc_pt->x + dev->ap_size;
  2288.         dc_vol[1].y = dc_pt->y + dev->ap_size;
  2289.  
  2290.         WS_DC_TO_NPC2 (&owsb->ws_xform, &dc_vol[0], &npc_pt[0])
  2291.         WS_DC_TO_NPC2 (&owsb->ws_xform, &dc_vol[1], &npc_pt[1])
  2292.  
  2293.         pickData.pickRec.npcHitVolume.minval.x = npc_pt[0].x;
  2294.         pickData.pickRec.npcHitVolume.minval.y = npc_pt[0].y;
  2295.         pickData.pickRec.npcHitVolume.maxval.x = npc_pt[1].x;
  2296.         pickData.pickRec.npcHitVolume.maxval.y = npc_pt[1].y;
  2297.         pickData.pickRec.npcHitVolume.minval.z = owsb->ws_window.z_min;
  2298.         pickData.pickRec.npcHitVolume.maxval.z = owsb->ws_window.z_max;
  2299.  
  2300.         pickDataBytes = 4 + sizeof (pexPD_NPC_HitVolume);
  2301.     }
  2302.  
  2303.     PEXChangeRenderer (ws->display, ws->rid,
  2304.         (pexBitmask) PEXRDPickInclusion, (CARD32) sizeof (pexNameSet),
  2305.         (char *) &(dev->filter.incl));
  2306.  
  2307.     PEXChangeRenderer (ws->display, ws->rid,
  2308.         (pexBitmask) PEXRDPickExclusion, (CARD32) sizeof (pexNameSet),
  2309.         (char *) &(dev->filter.excl));
  2310.  
  2311.  
  2312.     PEXBeginPickOne (ws->display, ws->rid, ws->drawable_id, -1,
  2313.         PEXLast, pickDataBytes, &pickData);
  2314.  
  2315.     post_str = owsb->posted.highest.lower;
  2316.     end = &(owsb->posted.lowest);
  2317.  
  2318.     while (post_str != end) {
  2319.         phg_wsb_traverse_net (ws, post_str->structh);
  2320.         post_str = post_str->lower;
  2321.     }
  2322.  
  2323.     PEXEndPickOne (ws->display, ws->rid, &betterPick,
  2324.         &pickPath, &pickDepth);
  2325.     }
  2326.  
  2327.  
  2328.     if (!pickDepth) {
  2329.  
  2330.         pick->status = PIN_STATUS_NONE;
  2331.         pick->pick_path.depth = 0;
  2332.         pick->pick_path.path_list = (Ppick_path_elem *) NULL;
  2333.  
  2334.     } else {
  2335.  
  2336.     /*
  2337.      * The protocol pick element ref data structure has its fields
  2338.      * layed out in a different order than the PHIGS data structure.
  2339.      * We must repack the data into PHIGS format.
  2340.      */
  2341.  
  2342.     for (i = 1; i < pickDepth; i++) {
  2343.         Ppick_path_elem *dst = (Ppick_path_elem *) &pickPath[i];
  2344.         pexPickElementRef src;
  2345.  
  2346.         src = pickPath[i];
  2347.         dst->struct_id = src.sid;
  2348.         dst->pick_id = src.pickid;
  2349.         dst->elem_pos = src.offset;
  2350.     }
  2351.  
  2352.     /*
  2353.      * order = bottom first?
  2354.      */
  2355.  
  2356.     if (dev->order == PORDER_BOTTOM_FIRST) {
  2357.         int            head, tail;
  2358.         pexPickElementRef     temp;
  2359.  
  2360.         head = 1;
  2361.         tail = pickDepth - 1;
  2362.  
  2363.         for (i = 0; i < (pickDepth - 1) / 2; i++) {
  2364.         temp = pickPath[head];
  2365.         pickPath[head] = pickPath[tail];
  2366.         pickPath[tail] = temp;
  2367.         head++;
  2368.         tail--;
  2369.         }
  2370.     }
  2371.  
  2372.     /*
  2373.      * return status and pick path
  2374.      */
  2375.  
  2376.     pick->status = PIN_STATUS_OK;
  2377.     pick->pick_path.depth = pickDepth - 1;
  2378.     pick->pick_path.path_list = (Ppick_path_elem *) &(pickPath[1]);
  2379.     }
  2380.  
  2381.     return 1;
  2382. }
  2383.  
  2384. void
  2385. phg_wsb_inq_filter( ws, type, ret )
  2386.     Ws            *ws;
  2387.     Phg_args_flt_type    type;
  2388.     Phg_ret        *ret;
  2389. {
  2390.     phg_wsx_inq_name_set( ws, type, (Pint)0, ret );
  2391. }
  2392.  
  2393.  
  2394. void
  2395. phg_wsb_drawable_pick( ws, args, ret )
  2396.     Ws                *ws;
  2397.     Phg_args_drawable_pick    *args;
  2398.     Phg_ret            *ret;
  2399. {
  2400.     ret->err = ERRN500;
  2401.     ERR_BUF( ws->erh, ret->err );
  2402.     ret->data.drawable_pick.status = PIN_STATUS_NO_IN;
  2403.     ret->data.drawable_pick.pick.depth = 0;
  2404.     ret->data.drawable_pick.pick.path_list = (Ppick_path_elem *)NULL;
  2405. }
  2406.  
  2407.  
  2408. void
  2409. phg_wsb_map_points( ws, args, ret )
  2410.     Ws                *ws;
  2411.     Phg_args_map_points        *args;
  2412.     Phg_ret            *ret;
  2413. {
  2414.     pexDeviceCoord    *dc_pts;
  2415.  
  2416.     register int    i;
  2417.  
  2418.     ret->err = 0;
  2419.     ret->data.map_points.view_index = 0;
  2420.     ret->data.map_points.points.num_points = 0;
  2421.     ret->data.map_points.points.points = (Ppoint3 *)NULL;
  2422.  
  2423.     /* Allocate space for both the DC and WC points. */
  2424.     if ( !PHG_SCRATCH_SPACE( &ws->scratch,
  2425.         (unsigned)(args->points.num_points
  2426.         * (sizeof(Ppoint) + sizeof(Ppoint3))) ) ) {
  2427.     ERR_BUF( ws->erh, ERR900 );
  2428.     return;
  2429.     }
  2430.     dc_pts = (pexDeviceCoord *)ws->scratch.buf;
  2431.     ret->data.map_points.points.points =
  2432.     (Ppoint3 *)(dc_pts + args->points.num_points);
  2433.  
  2434.     /* Convert the points to DC. */
  2435.     phg_wsx_update_ws_rect( ws );
  2436.     for ( i = 0; i < args->points.num_points; i++ ) {
  2437.     /* Z coord is already in DC. */
  2438.     WS_DRWBL_TO_DC2(ws, &args->points.points[i], &dc_pts[i]);
  2439.     dc_pts[i].z = args->points.points[i].z;
  2440.     }
  2441.  
  2442.     /* Convert the DC points to WC. */
  2443.     if ( !phg_wsb_resolve_stroke( ws, args->points.num_points, dc_pts, 0,
  2444.         &ret->data.map_points.view_index,
  2445.         &ret->data.map_points.points ) ) {
  2446.     ret->data.map_points.points.num_points = 0;
  2447.     }
  2448. }
  2449.  
  2450. void
  2451. phg_wsb_redraw_regions( ws, args )
  2452.     Ws                *ws;
  2453.     Phg_args_redraw_regions    *args;
  2454. {
  2455.     pexDeviceRect    *pex_rects;
  2456.     pexBitmask        rmask;
  2457.     CARD32        *card32_p;
  2458.  
  2459.     if ( args->num_regions <= 0 )
  2460.     return;
  2461.  
  2462.     if ( !(pex_rects = (pexDeviceRect *)PHG_SCRATCH_SPACE( &ws->scratch,
  2463.         sizeof(CARD32) +
  2464.         (unsigned)(args->num_regions * sizeof(*pex_rects)) )) ) {
  2465.     ERR_BUF( ws->erh, ERR900 );
  2466.     return;
  2467.     }
  2468.     card32_p = (CARD32 *)ws->scratch.buf;
  2469.     pex_rects = (pexDeviceRect *)(card32_p + 1);
  2470.  
  2471.     *card32_p = args->num_regions;
  2472.     phg_wsx_convert_rects( ws, args->num_regions, args->regions, pex_rects );
  2473.     rmask = PEXRDClipList;
  2474.     (void)PEXChangeRenderer( ws->display, ws->rid, rmask,
  2475.     (CARD32)(sizeof(CARD32) + args->num_regions * sizeof(pexDeviceRect)),
  2476.     (char *)card32_p );
  2477.     (*ws->repaint_all)( ws, PFLAG_COND, args->num_regions, args->regions );
  2478.  
  2479.     /* Reset the renderer's clip list. */ 
  2480.     *card32_p = 0;
  2481.     (void)PEXChangeRenderer( ws->display, ws->rid, rmask,(CARD32)sizeof(CARD32),
  2482.     (char *)card32_p );
  2483. }
  2484.