[comp.sources.x] v03i078: Xcu -- widget set from Cornell University, Part02/12

argv@island.uu.net (Dan Heller) (04/25/89)

Submitted-by: Gene Dykes <gdykes@tcgould.tn.cornell.edu>
Posting-number: Volume 3, Issue 78
Archive-name: xcu/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 2 (of 12)."
# Contents:  src/CuTbl.c.ab src/CuWlm.c.ab wlmCompiler/wlc.l
# Wrapped by argv@island on Mon Apr 24 15:41:26 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/CuTbl.c.ab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/CuTbl.c.ab'\"
else
echo shar: Extracting \"'src/CuTbl.c.ab'\" \(27239 characters\)
sed "s/^X//" >'src/CuTbl.c.ab' <<'END_OF_FILE'
X
X    arbs = (int *) XtMalloc (cols[i] * sizeof(int)) ;
X    for (j=0;  j < cols[i];  j++)
X	{
X	CuTblConstraints constraint =
X	    (CuTblConstraints) (item[i][j].pw->core.constraints) ;
X	if (constraint->tbl.fill_column)
X		{
X		arbs[n_arbs++] = j ;
X		}
X	}
X
X    if (n_arbs && !tw->tbl.equal_cols[i])
X	{
X	Cardinal i_arb ;
X	int arb_adjustment ;
X
X	arb_adjustment = (int) ((float) (needed_width - r_width[i]) /
X					n_arbs + 0.5) ;
X	/*
X	 * adjust each one by its proportion of the slack, except for the
X	 * last, which must take up enough to make up for round-off errors
X	 */
X	for (i_arb=0;  i_arb < n_arbs-1;  i_arb++)
X	    {
X	    item[i][arbs[i_arb]].width += arb_adjustment ;
X	    }
X	item[i][arbs[n_arbs-1]].width += (needed_width - r_width[i] -
X						  (n_arbs-1)*arb_adjustment) ;
X	XtFree ((char *)arbs) ;
X	continue ;
X	}
X
X    XtFree ((char *)arbs) ;
X
X    /* else everybody has to adjust */
X
X    if (tw->tbl.equal_cols[i])
X	{
X	/* Doesn't include the two outermost children borders */
X	slack = needed_width - (cols[i] - 1) * (tw->tbl.inter_width +
X		2 * tw->tbl.typical_border) ;
X	portions = (int *) XtMalloc (cols[i] * sizeof(int)) ;
X
X	e_apportion_slack (slack, cols[i], portions) ;
X
X	for (j=0;  j < cols[i];  j++)
X	    {
X	    if (item[i][j].primary == TBL_ITEM ||
X		item[i][j].primary == TBL_HSPAN)
X		{
X		if (item[i][j].primary == TBL_ITEM)
X		    {
X		    last_item = j ;
X		    item[i][last_item].width = 0 ;
X		    }
X		else
X		    {
X		    item[i][last_item].width +=
X			(tw->tbl.inter_width + 2 * tw->tbl.typical_border) ;
X		    }
X		item[i][last_item].width += portions[j] ;
X		}
X	    }
X	XtFree ((char *) portions) ;
X	}
X    else
X	{
X	int last_child = -1 ;
X	int padding = (tw->tbl.r_item[i] - 1) *
X	    (tw->tbl.inter_width + 2 * tw->tbl.typical_border) ;
X
X	for (j=0;  j < cols[i];  j++)
X	    {
X	    last_child = j ;
X	    /* each item is expanded by its proportion of width */
X	    item[i][j].width = (int)((float) (needed_width - padding) /
X		  (r_width[i] - padding) * item[i][j].width + 0.5) ;
X	    }
X
X	if (!tw->tbl.equal_cols[i] && last_child >= 0)
X	    {
X	    /* need to adjust the last item in this row to take up any slack */
X	    int adj ;
X	    int wide = 0 ;
X
X	    for (j=0;  j < cols[i];  j++)
X		{
X		if (j == 0 || item[i][j].pw != item[i][j-1].pw)
X		    {
X		    wide += item[item[i][j].pi][item[i][j].pj].width ;
X		    }
X		}
X	    adj = needed_width - wide -
X		(tw->tbl.r_item[i] - 1) *
X		(tw->tbl.inter_width + 2 * tw->tbl.typical_border) ;
X	    item[i][last_child].width += adj ;
X	    }
X	}
X    }
X
X/*
X * Now, do the same thing for row equalization 
X * The process for the rows is somewhat simpler since there can not be a
X * variable number of rows per column (except that caused by spanning).
X */
X
X/* Step 1 : find the min height needed for each row */
X
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    Cardinal j ;
X    r_height[i] = 0 ;
X    for (j=0;  j < cols[i];  j++)
X	{
X	if (item[i][j].primary == TBL_ITEM)
X	    {
X	    int child_height ;
X	    CuTblConstraints constraint ;
X	    child = item[i][j].pw ;
X	    constraint = (CuTblConstraints)child->core.constraints;
X
X	    /* height of a row is its largest child */
X	    child_height = item[i][j].height / constraint->tbl.span_height ;
X	    if (child_height > r_height[i])
X		r_height[i] = child_height ;
X	    }
X	else
X	if (item[i][j].primary == TBL_VSPAN)
X	    {
X	    /*
X	     * Need to include proper fraction of vertically spanned items
X	     * Simple because it is illegal to have a variable number of columns
X	     * during vertical spanning
X	     */
X	    int child_height ;
X	    CuTblConstraints constraint =
X		(CuTblConstraints)item[i][j].pw->core.constraints;
X
X	    child_height = item[i][j].height / constraint->tbl.span_height ;
X	    if (tw->tbl.equal_rows == True)
X		child_height = item[i][j].height ;
X	    if (child_height > r_height[i])
X		r_height[i] = child_height ;
X	    }
X	}
X    if (r_height[i] > max_r_height)
X	max_r_height = r_height[i] ;
X    }
X
X/* if keyword "equal_row_key", all rows changed to maximum row height */
Xif (tw->tbl.equal_rows == True)
X    {
X    for (i=0;  i < tw->tbl.rows;  i++)
X	{
X	r_height[i] = max_r_height ;
X	}
X    }
X
X/* Now adjust each row to fit within its specified height */
X
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    Cardinal j ;
X    for (j=0;  j < cols[i];  j++)
X	{
X	if (item[i][j].primary == TBL_ITEM)
X	    {
X	    int ii ;
X	    int sum_height = 0 ;
X	    CuTblConstraints constraint ;
X	    child = item[i][j].pw ;
X	    constraint = (CuTblConstraints)child->core.constraints;
X
X	    for (ii=0;  ii < constraint->tbl.span_height;  ii++)
X		{
X		sum_height += r_height[i+ii] ;
X		}
X	    sum_height += 
X		(constraint->tbl.span_height - 1) *
X		(tw->tbl.inter_height + 2 * tw->tbl.typical_border) ;
X	    if (XtIsManaged(child))
X		{
X		item[i][j].height = sum_height ;
X		}
X	    }
X	}
X    }
X
Xtw->tbl.standalone_width = needed_width +
X	       2 * tw->tbl.typical_border +
X	       2 * tw->tbl.internal_width  ;
X
X/* Now one final pass to add in allowances for borders and padding */
X
Xtw->tbl.standalone_height = 0 ;
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    Widget last_pw = NULL ;
X    Cardinal j ;
X
X    tw->tbl.standalone_height += r_height[i] ;
X    for (j=0;  j < cols[i];  j++)
X	{
X	if (item[i][j].primary == TBL_ITEM)
X	    {
X	    if (XtIsManaged(item[i][j].pw))
X		{
X		CuTblConstraints constraint =
X			(CuTblConstraints) item[i][j].pw->core.constraints ;
X		constraint->tbl.sts_width = item[i][j].width ;
X		constraint->tbl.sts_height = item[i][j].height ;
X		}
X	    }
X	if (item[i][j].pw != last_pw)
X	    {
X	    last_pw = item[i][j].pw ;
X	    }
X	}
X    }
X
Xtw->tbl.standalone_height += (tw->tbl.rows-1) * tw->tbl.inter_height +
X		 2 * tw->tbl.internal_height +
X		 2 * tw->tbl.rows * tw->tbl.typical_border ;
X
X/*
X * cleanup
X */
X
XXtFree ((char *)r_width) ;
X
Xreturn ;
X}
X
X/***** **** *** ** * Trial_ETS * ** *** **** *****/
X
Xstatic void
XTrial_ETS (tw)
X    CuTblWidget tw ;
X{
XCardinal i ;
Xint c_slack ;  /* Can't be "Dimension" */
Xint r_slack ;
Xint *p_r_slack = (int *) XtMalloc (tw->tbl.rows * sizeof(int)) ;
Xint *r_height = tw->tbl.r_height ;
Xfloat c_expansion ;
Xfloat r_expansion ;
Xint internal_width = tw->tbl.internal_width ;
Xint internal_height = tw->tbl.internal_height ;
Xint inter_width = tw->tbl.inter_width ;
Xint inter_height = tw->tbl.inter_height ;
Xint inter_width_delta ;
Xint inter_height_delta ;
X
X/*
X * Given an enclosing box, figure out how to parcel the additional
X * padding among the children.   If there is instead a loss of padding,
X * things would look awful, so things are laid out in the smallest way that
X * I would like, and the parent will have to settle for us being clipped.
X *
X * Theoretically, I could reduce the padding to zero, and that might be
X * a good idea.
X * If more space is needed, make the children's fonts smaller, but that is
X *  carrying things just a bit too far.
X */
X
X/*
X * What are the possibilities for the proper effect of fitting within
X * a window that is larger than needed?
X *  1) Expand the children to take up the excess
X *  2) Expand the internalWidth,Height (centers the tbl)
X *  3) Expand the interWidgetWidth,Height (spreads them out)
X *
X *  This code allows any combination of the above possibilities.
X *  (If no bits are set, the default is to expand the widgets)
X */
X
X/*
X * Compute how much bigger/smaller (the slack) than the minimum we are.
X */
X
X/* height */
X
Xif (tw->core.height == 0)
X    tw->core.height = tw->tbl.standalone_height ;
X
Xif (tw->core.height < tw->tbl.standalone_height && tw->tbl.clip_on_shrink)
X    tw->tbl.new_height = tw->tbl.standalone_height ;
Xelse
X    tw->tbl.new_height = tw->core.height ;
X
Xr_expansion = (float) tw->tbl.new_height / tw->tbl.standalone_height ;
Xr_slack = tw->tbl.new_height - tw->tbl.standalone_height ;
X
X/* width */
X
Xif (tw->core.width == 0)
X    tw->core.width = tw->tbl.standalone_width ;
X
Xif (tw->core.width < tw->tbl.standalone_width && tw->tbl.clip_on_shrink)
X    tw->tbl.new_width = tw->tbl.standalone_width ;
Xelse
X    tw->tbl.new_width = tw->core.width ;
X
Xc_expansion = (float) tw->tbl.new_width / tw->tbl.standalone_width ;
Xc_slack = tw->tbl.new_width - tw->tbl.standalone_width ;
X
X/*
X * Depending on what is allowed to change,
X * compute new padding parameters
X */
X
Xif ((int)tw->tbl.resize_participants & (int)CuResizeInternals)
X     {
X     if (((int)tw->tbl.resize_participants & (int)CuResizeInters) &&
X         ((int)tw->tbl.resize_participants & (int)CuResizeChildren))
X	 {
X	 /* internal padding and inter-widget just expand proportionately */
X	 internal_height = tw->tbl.internal_height * r_expansion ;
X	 inter_height = tw->tbl.inter_height * r_expansion ;
X	 r_slack -= 2 * (internal_height - tw->tbl.internal_height) ;
X	 r_slack -= (tw->tbl.rows - 1) *
X		    (inter_height - tw->tbl.inter_height) ;
X
X	 internal_width = tw->tbl.internal_width * c_expansion ;
X	 inter_width = tw->tbl.inter_width * c_expansion ;
X	 c_slack -= 2 * (internal_width - tw->tbl.internal_width) ;
X	 c_slack -= (tw->tbl.max_cols - 1) *
X		    (inter_width - tw->tbl.inter_width) ;
X	 }
X     else
X     if (!((int)tw->tbl.resize_participants & (int)CuResizeInters) &&
X          ((int)tw->tbl.resize_participants & (int)CuResizeChildren))
X	 {
X	 /*
X	  * For now, internal padding just expands proportionately.
X	  * That means widgets will have to expand just a bit more than
X	  * their fair share (also expanding for all of inters' share)
X	  * This should be quite an adequate approximation
X	  */
X	 internal_height = tw->tbl.internal_height * r_expansion ;
X	 r_slack -= 2 * (internal_height - tw->tbl.internal_height) ;
X
X	 internal_width = tw->tbl.internal_width * c_expansion ;
X	 c_slack -= 2 * (internal_width - tw->tbl.internal_width) ;
X	 }
X     else
X     if ( ((int)tw->tbl.resize_participants & (int)CuResizeInters) &&
X         !((int)tw->tbl.resize_participants & (int)CuResizeChildren))
X	 {
X	 /* split up the slack between inter widget and internals */
X	 int row_num_participants = (tw->tbl.rows - 1) + 2 ;
X	 int col_num_participants = (tw->tbl.max_cols - 1) + 2 ;
X	 inter_height = tw->tbl.inter_height +
X				   r_slack / row_num_participants ;
X	 internal_height =
X		tw->tbl.internal_height +
X		(r_slack -
X		(inter_height - tw->tbl.inter_height) *
X		(row_num_participants - 2)) / 2 ;
X	 r_slack -= (2 * (internal_height - tw->tbl.internal_height) +
X		     (row_num_participants - 2) *
X		     (inter_height - tw->tbl.inter_height)) ;
X
X	 inter_width = tw->tbl.inter_width +
X				   c_slack / col_num_participants ;
X	 internal_width =
X		tw->tbl.internal_width +
X		(c_slack -
X		(inter_width - tw->tbl.inter_width) *
X		(col_num_participants - 2)) / 2 ;
X	 c_slack -= (2 * (internal_width - tw->tbl.internal_width) +
X		     (col_num_participants - 2) *
X		     (inter_width - tw->tbl.inter_width)) ;
X	 }
X     else
X	 {
X	 /* internal padding takes up all the slack */
X	 internal_height = tw->tbl.internal_height + r_slack/2 ;
X	 r_slack -= 2 * (internal_height - tw->tbl.internal_height) ;
X
X	 internal_width = tw->tbl.internal_width + c_slack/2 ;
X	 c_slack -= 2 * (internal_width - tw->tbl.internal_width) ;
X	 }
X     }
Xelse
Xif ((int)tw->tbl.resize_participants & (int)CuResizeInters)
X    {
X    if ((int)tw->tbl.resize_participants & (int)CuResizeChildren)
X	{
X	 /*
X	  * For now, inter widget padding just expands proportionately.
X	  * That means widgets will have to expand just a bit more than
X	  * their fair share (also expanding for all of internals' share)
X	  * This should be quite an adequate approximation
X	  */
X	 if (tw->tbl.inter_height > 0)
X	     inter_height = tw->tbl.inter_height * r_expansion ;
X	 r_slack -= (tw->tbl.max_cols - 1) *
X		    (inter_height - tw->tbl.inter_height) ;
X
X	 if (tw->tbl.inter_width > 0)
X	     inter_width = tw->tbl.inter_width * c_expansion ;
X	 c_slack -= (tw->tbl.max_cols - 1) *
X		    (inter_width - tw->tbl.inter_width) ;
X	}
X    else
X	 {
X	 /* inter widget padding takes up all the slack */
X	 if (tw->tbl.rows > 1)
X	     inter_height = tw->tbl.inter_height + r_slack /
X				    (int) (tw->tbl.rows - 1) ;
X	 r_slack -= (tw->tbl.rows - 1) *
X		    (inter_height - tw->tbl.inter_height) ;
X
X	 if (tw->tbl.max_cols > 1)
X	     {
X	     inter_width = tw->tbl.inter_width + c_slack /
X				    (int) (tw->tbl.max_cols - 1) ;
X	     }
X	 c_slack -= (tw->tbl.max_cols - 1) *
X		    (inter_width - tw->tbl.inter_width) ;
X	 }
X    }
X
Xinter_width_delta = inter_width - tw->tbl.inter_width ;
Xinter_height_delta = inter_height - tw->tbl.inter_height ;
X
X/*
X * else widgets take up all the slack
X */
X
Xv_apportion_slack (r_slack, tw->tbl.rows, p_r_slack, r_height) ;
X
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    int *p_c_slack = (int *)XtMalloc(tw->tbl.cols[i] * sizeof (int)) ;
X    Cardinal j ;
X    Cardinal slack_ptr = 0 ;
X    int this_c_slack ;
X
X    /*
X     * we need to apportion the slack evenly over the widgets in the row
X     * ( if the columns were supposed to be even, I suppose a one pixel
X     *   difference won't be too bad. E.g., adding a slack of two pixels
X     *   to 3 even columns will result in the last column being one short.
X     *   Insisting on rounding up the slack is conceivable but would probably
X     *   result in more extensive negotiations in the hierarchy.  I'll yield
X     *   unilaterally.)
X     */
X
X    this_c_slack = c_slack +
X		   inter_width_delta * (tw->tbl.max_cols - tw->tbl.cols[i]) ;
X    /*
X     * If the items in the row are of variable lengths we want to apportion
X     * the slack in proportion to the width of each item, but
X     * if the row has "equal_cols" then we want to allocate the space equally
X     * for each column.
X     */
X    if (tw->tbl.equal_cols[i])
X	{
X	e_apportion_slack (this_c_slack, tw->tbl.cols[i], p_c_slack) ;
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X	    {
X	    if (tw->tbl.item[i][j].primary == TBL_ITEM)
X		{
X		if (XtIsManaged(tw->tbl.item[i][j].pw))
X		    {
X		    Cardinal k ;
X		    CuTblConstraints constraint =
X			(CuTblConstraints) tw->tbl.item[i][j].pw->core.constraints ;
X		    constraint->tbl.ets_width = constraint->tbl.sts_width ;
X		    for (k=0;  k < constraint->tbl.span_width;  k++)
X			{
X			/*
X			 * Add in the appropriate slack for each column entry
X			 * that it spans
X			 */
X			constraint->tbl.ets_width += p_c_slack[slack_ptr++] ;
X			if (k != 0)
X			    {
X			    /*
X			     * Also add in the amount of space between entries
X			     */
X			    constraint->tbl.ets_width += inter_width_delta ;
X			    }
X			}
X
X		    /* similar computation for rows */
X
X		    constraint->tbl.ets_height = constraint->tbl.sts_height ;
X		    for (k=0;  k < constraint->tbl.span_height;  k++)
X			{
X			constraint->tbl.ets_height += p_r_slack[i+k] ;
X			if (k != 0)
X			    {
X			    constraint->tbl.ets_height += inter_height_delta ;
X			    }
X			}
X		    }
X		}
X	    }
X	}
X    else
X	{
X	int n_widths = 0 ;
X	int *r_widths = (int *) XtMalloc (tw->tbl.cols[i] * sizeof(int)) ;
X
X	/* Find the widths of the true items in this row */
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X	    {
X	    if (tw->tbl.item[i][j].primary == TBL_ITEM)
X		{
X		if (XtIsManaged(tw->tbl.item[i][j].pw))
X		    {
X		    CuTblConstraints constraint =
X			(CuTblConstraints)tw->tbl.item[i][j].pw->core.constraints;
X		    r_widths[n_widths++] = constraint->tbl.sts_width ;
X		    }
X		}
X	    }
X
X	v_apportion_slack (this_c_slack, n_widths, p_c_slack, r_widths) ;
X
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X	    {
X	    if (tw->tbl.item[i][j].primary == TBL_ITEM)
X		{
X		if (XtIsManaged(tw->tbl.item[i][j].pw))
X		    {
X		    Cardinal k ;
X		    CuTblConstraints constraint =
X			(CuTblConstraints) tw->tbl.item[i][j].pw->core.constraints ;
X		    constraint->tbl.ets_width = constraint->tbl.sts_width ;
X		    constraint->tbl.ets_width += p_c_slack[slack_ptr++] ;
X
X		    /* similar computation for rows */
X
X		    constraint->tbl.ets_height = constraint->tbl.sts_height ;
X		    for (k=0;  k < constraint->tbl.span_height;  k++)
X			{
X			constraint->tbl.ets_height += p_r_slack[i+k] ;
X			if (k != 0)
X			    {
X			    constraint->tbl.ets_height += inter_height_delta ;
X			    }
X			}
X		    }
X		}
X	    }
X	}
X
X    XtFree ((char *) p_c_slack) ;
X    }
XXtFree ((char *) p_r_slack) ;
X
X/*
X * Now to actually configure the children...
X */
X
X {
X Position current_y = internal_height ;
X Position *e_current_y = NULL ;
X Boolean vspan_current = False ;
X
X for (i=0;  i < tw->tbl.rows;  i++)
X    {
X    Widget last_pw = NULL ;
X    Position current_x = internal_width ;
X    Cardinal j ;
X    CuTblConstraints constraint =
X	    (CuTblConstraints) tw->tbl.item[i][0].pw->core.constraints ;
X
X    /*
X     * If this is the first row of a series of rows with equal columns...
X     */
X
X    if (!vspan_current &&
X       (tw->tbl.vspan_status[i] && (i == 0 || !tw->tbl.vspan_status[i-1])))
X	{
X	vspan_current = True ;
X	e_current_y = (Position *)
X	  	      XtMalloc (tw->tbl.cols[i] * sizeof (Position)) ;
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X		e_current_y[j] = current_y ;
X	}
X
X    /*
X     * else if this is the first row of a series of rows with unequal columns...
X     */
X
X    else
X    if (vspan_current &&
X        (!tw->tbl.vspan_status[i] && (i == 0 || tw->tbl.vspan_status[i-1])))
X	{
X	vspan_current = False ;
X	if (e_current_y)
X	    {
X	    current_y = e_current_y[0] ; /* all should be the same */
X	    XtFree ((char *) e_current_y) ;
X	    e_current_y = NULL ;
X	    }
X	}
X
X    /*
X     * if vspan_current and a new number of columns...
X     */
X
X    if (vspan_current &&
X	i != 0 &&
X	tw->tbl.cols[i] != tw->tbl.cols[i-1] &&
X	tw->tbl.vspan_status[i-1])
X	{
X	current_y = e_current_y[0] ;
X	XtFree ((char *) e_current_y) ;
X	e_current_y = (Position *)
X	  	      XtMalloc (tw->tbl.cols[i] * sizeof (Position)) ;
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X		e_current_y[j] = current_y ;
X	}
X
X    for (j=0;  j < tw->tbl.cols[i];  j++)
X	{
X	CuTblConstraints constraint =
X		(CuTblConstraints) tw->tbl.item[i][j].pw->core.constraints ;
X	if (tw->tbl.item[i][j].primary == TBL_ITEM)
X	    {
X	    if (XtIsManaged(tw->tbl.item[i][j].pw))
X		{
X		Position this_y ;
X		this_y = vspan_current ? e_current_y[j] : current_y ;
X		constraint->tbl.ets_x = current_x ;
X		constraint->tbl.ets_y = this_y ;
X		}
X	    }
X
X	if (vspan_current && (tw->tbl.item[i][j].primary == TBL_ITEM ||
X			      tw->tbl.item[i][j].primary == TBL_HSPAN))
X	    {
X	    e_current_y[j] += constraint->tbl.ets_height +
X			      inter_height + 2*tw->tbl.typical_border ;
X	    }
X	if (tw->tbl.item[i][j].pw != last_pw)
X	    {
X	    current_x += constraint->tbl.ets_width + inter_width +
X			 2*tw->tbl.typical_border ;
X	    last_pw = tw->tbl.item[i][j].pw ;
X	    }
X	}
X
X    if (!vspan_current)
X	{
X	current_y += constraint->tbl.ets_height +
X		     inter_height + 2*tw->tbl.typical_border ;
X	}
X    }
X if (e_current_y)
X    {
X    XtFree ((char *) e_current_y) ;
X    }
X }
X
Xreturn ;
X}
X
X/***** **** *** ** * DoLayout * ** *** **** *****/
X
Xstatic void
XDoLayout (tw, requesting_widget)
X    CuTblWidget tw ;
X    Widget requesting_widget ;
X{
Xint num_children = tw->composite.num_children;
XWidgetList children = tw->composite.children;
XWidget *childP;
X
X/* Use ConfigureWidget on siblings, modify requester directly */
X
Xfor (childP = children; childP - children < num_children; childP++)
X    {
X    CuTblConstraints twc = (CuTblConstraints)(*childP)->core.constraints;
X
X    if (!XtIsManaged(*childP))
X	continue ;
X
X    if (*childP != requesting_widget)
X	{
X	XtConfigureWidget (*childP, twc->tbl.ets_x, twc->tbl.ets_y,
X				    (Dimension) twc->tbl.ets_width,
X				    (Dimension) twc->tbl.ets_height,
X				    (Dimension) tw->tbl.typical_border) ;
X	}
X    else
X	{
X	requesting_widget->core.x = twc->tbl.ets_x ;
X	requesting_widget->core.y = twc->tbl.ets_y ;
X	requesting_widget->core.width = twc->tbl.ets_width ;
X	requesting_widget->core.height = twc->tbl.ets_height ;
X	requesting_widget->core.border_width = tw->tbl.typical_border ;
X	/*
X	 * Well, this (XtConfigureWidget) isn't supposed to be here, but
X	 * without it, the child's x & y never seem to be paid attention
X	 * to.  Width and height change, but the widget stays right where
X	 * it was...
X	 */
X	/***
X	XtConfigureWidget (*childP, twc->tbl.ets_x, twc->tbl.ets_y,
X				    (Dimension) twc->tbl.ets_width,
X				    (Dimension) twc->tbl.ets_height,
X				    (Dimension) tw->tbl.typical_border) ;
X	***/
X	}
X    }
X
Xtw->core.width = tw->tbl.new_width ;
Xtw->core.height = tw->tbl.new_height ;
X
Xreturn ;
X}
X
X/***** **** *** ** * adjust_aligned_columns * ** *** **** *****/
X
Xstatic Boolean
Xadjust_aligned_columns (tw)
X    CuTblWidget tw ;
X{
X/*
X * All items in a column need to be the same width if aligned_columns is True
X * Therefore, find biggest member in each column,
X *  and set all items of the column to that width.
X */
XCardinal i, j ;
XBoolean change_value = False ;
X
Xif (!tw->tbl.aligned_columns)
X    return False ;
X
Xfor (j=0;  j < tw->tbl.cols[0];  j++)
X    {
X    int max_width = 0 ;
X    int max_adj_width = 0 ;
X    for (i=0;  i < tw->tbl.rows;  i++)
X	{
X	if (tw->tbl.item[i][j].adj_width > max_adj_width)
X	    {
X	    max_width = tw->tbl.item[i][j].width ;
X	    max_adj_width = tw->tbl.item[i][j].adj_width ;
X	    }
X	}
X
X    for (i=0;  i < tw->tbl.rows;  i++)
X	{
X	if (tw->tbl.item[i][j].adj_width < max_adj_width)
X	    {
X	    change_value = True ;
X	    tw->tbl.item[i][j].adj_width = max_adj_width ;
X	    tw->tbl.item[i][j].width = max_width ;
X	    }
X	}
X    }
Xreturn change_value ;
X}
X
X/***** **** *** ** * adjust_equal_columns * ** *** **** *****/
X
Xstatic Boolean
Xadjust_equal_columns (tw)
X    CuTblWidget tw ;
X{
X/*
X * All columns in a row marked with an 'e', need to be same width.
X * Therefore, find biggest member, and set all members of the set to that width.
X */
XCardinal i, j ;
XBoolean change_value = False ;
X
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    int max_width = 0 ;
X    int max_adj_width = 0 ;
X    for (j=0;  j < tw->tbl.cols[i];  j++)
X	{
X	if (tw->tbl.item[i][j].e && tw->tbl.item[i][j].adj_width >max_adj_width)
X	    {
X	    max_width = tw->tbl.item[i][j].width ;
X	    max_adj_width = tw->tbl.item[i][j].adj_width ;
X	    }
X	}
X
X    /* Only need to adjust if some columns were marked */
X    if (max_width > 0)
X	{
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X	    {
X	    if (tw->tbl.item[i][j].e && tw->tbl.item[i][j].adj_width <
X					max_adj_width)
X		{
X		change_value = True ;
X		tw->tbl.item[i][j].adj_width = max_adj_width ;
X		tw->tbl.item[i][j].width = max_width ;
X		}
X	    }
X	}
X    }
Xreturn change_value ;
X}
X
X/***** **** *** ** * adjust_spanned_columns * ** *** **** *****/
X
Xstatic Boolean
Xadjust_spanned_columns (tw)
X    CuTblWidget tw ;
X{
X/*
X * All corresponding columns in spanned rows need to be same width.
X * Therefore, find biggest member, and set all members of the set to that width.
X */
XCardinal i, j ;
XBoolean change_value = False ;
X
Xfor (i=0;  i < tw->tbl.rows;  i++)
X    {
X    Cardinal ii = i ;
X    /*
X     * Look for the start of a spanning run
X     */
X    if (tw->tbl.vspan_status[i] && (i == 0 || !tw->tbl.vspan_status[i-1]))
X	{
X	/*
X	 * For each column, search down through the spans
X	 */
X	for (j=0;  j < tw->tbl.cols[i];  j++)
X	    {
X	    int max_width = 0 ;
X	    int max_adj_width = 0 ;
X	    int filled_columns = 0 ;
X	    for (ii=i;  ii < tw->tbl.rows && tw->tbl.vspan_status[ii];  ii++)
X		{
X		CuTblConstraints constraint =
X		   (CuTblConstraints)tw->tbl.item[ii][j].pw->core.constraints ;
X		if (constraint->tbl.fill_column)
X		    filled_columns++ ;
X		if (tw->tbl.item[ii][j].primary == TBL_ITEM &&
X		    tw->tbl.item[ii][j].adj_width > max_adj_width)
X		    {
X		    max_adj_width = tw->tbl.item[ii][j].adj_width ;
X		    max_width = tw->tbl.item[ii][j].width ;
X		    }
X		}
X	    /*
X	     * If some, but not all, of the entries in this column's spanning
X	     * run were set to take up slack, then they must all be so set...
X	     */
X	    if (filled_columns > 0 && filled_columns < ii - i)
X		{
X		for (ii=i; ii < tw->tbl.rows && tw->tbl.vspan_status[ii];  ii++)
X		    {
X		    CuTblConstraints constraint =
X		       (CuTblConstraints)tw->tbl.item[ii][j].pw->core.constraints;
X		    constraint->tbl.fill_column = True ;
X		    }
X		}
X	    /* Only need to adjust if some columns were marked */
X	    if (max_adj_width > 0)
X		{
X		for (ii=i; ii < tw->tbl.rows && tw->tbl.vspan_status[ii]; ii++)
X		    {
X		    if (tw->tbl.item[ii][j].primary != TBL_HSPAN &&
X			tw->tbl.item[ii][j].adj_width < max_adj_width)
X			{
X			change_value = True ;
X			tw->tbl.item[ii][j].adj_width = max_adj_width ;
X			tw->tbl.item[ii][j].width = max_width ;
X			}
X		    }
X		}
X	    }
X	}
X    i = ii ; /* bump past the spanning run */
X    }
Xreturn change_value ;
X}
X
X/***** **** *** ** * v_apportion_slack * ** *** **** *****/
X
Xstatic void
Xv_apportion_slack (slack, n, portions, widths)
X    int slack ;
X    int n ;
X    int *portions ;
X    int *widths ;
X{
XCardinal i ;
Xfloat exact_portion ;
Xfloat running_exact_portion = 0.0 ;
Xint apportioned = 0 ;
Xint total_width = 0 ;
X
Xfor (i=0;  i < n;  i++)
X    total_width += widths[i] ;
X
Xfor (i=0;  i < n-1;  i++)
X    {
X    exact_portion = (float) widths[i] / total_width * slack ;
X    running_exact_portion += exact_portion ;
X    portions[i] = running_exact_portion - apportioned ;
X    apportioned += portions[i] ;
X    }
X
Xportions[n-1] = slack - apportioned ;
Xreturn ;
X}
X
X/***** **** *** ** * e_apportion_slack * ** *** **** *****/
X
Xstatic void
Xe_apportion_slack (slack, n, portions)
X    int slack ;
X    int n ;
X    int *portions ;
X{
XCardinal i ;
Xfloat exact_portion = ((float) slack + 0.999) / n ;
Xfloat running_exact_portion = 0.0 ;
Xint apportioned = 0 ;
X
Xfor (i=0;  i < n;  i++)
X    {
X    running_exact_portion += exact_portion ;
X    portions[i] = running_exact_portion - apportioned ;
X    apportioned += portions[i] ;
X    }
X
Xreturn ;
X}
X
X/***** **** *** ** * SetupLayout * ** *** **** *****/
X
Xstatic void
XSetupLayout (tw)
X    CuTblWidget tw ;
X{
X/*
X * Don't want to count children that have:
X *	core/mappedWhenManaged "False"
X *                  and
X *	constraint/layoutWhenUnmapped "False"
X */
X
Xif (tw->tbl.format_file != NULL) 
X    {
X    /*
X     * Layout is contained in a file.
X     * We'll read the file as one big string.
X     */
X    FILE *fd ;
X    struct stat buf ;
X
X    tw->tbl.format_mode = TBL_STRING_FORMAT ;
X    fd = fopen (tw->tbl.format_file, "r") ;
X    if (fd <= 0)
X	{
X	char *my_text = "CuTbl: Couldn't open (%s) for reading\n" ;
X	char *etext = XtMalloc (strlen(my_text) + strlen(tw->tbl.format_file)) ;
X	sprintf (etext, my_text, tw->tbl.format_file) ;
X	XtError (etext) ;
X	}
X    fstat (fileno(fd), &buf) ;
X    layout_input->input_buffer = XtMalloc (buf.st_size + 1) ;
X    fread (layout_input->input_buffer, (int)buf.st_size, 1, fd) ;
X    layout_input->input_buffer[buf.st_size] = '\0' ;
X    layout_input->string_file = (int) TBL_FILE_FORMAT ;
X
X    Cu_copy_ds (&layout_input->cur_file, tw->tbl.format_file) ;
X    XtFree (tw->tbl.format_file) ;
X    tw->tbl.format_file = NULL ;
X
X    fclose (fd) ;
X    }
Xelse
Xif (tw->tbl.format_string != NULL)
X    {
X    /*
X     * Layout is contained in a string.
X     */
X    tw->tbl.format_mode = TBL_STRING_FORMAT ;
X    Cu_copy_ds (&layout_input->cur_file, "(String Resource)") ;
X    layout_input->input_buffer = tw->tbl.format_string ;
X    layout_input->string_file = (int) TBL_STRING_FORMAT ;
X    }
Xelse
Xif (tw->tbl.format_mode == TBL_FIRST_PASS)
X    {
X    /* default to a row of widgets */
X    Cardinal i ;
X    tw->tbl.format_mode = TBL_STRING_FORMAT ;
X    Cu_copy_ds (&layout_input->cur_file, "(Default Resource)") ;
X    tw->tbl.format_string = XtCalloc (tw->composite.num_children * 2 + 2,
X				  sizeof(char)) ;
X    layout_input->input_buffer = tw->tbl.format_string ;

END_OF_FILE
echo shar: NEWLINE appended to \"'src/CuTbl.c.ab'\"
if test 27240 -ne `wc -c <'src/CuTbl.c.ab'`; then
    echo shar: \"'src/CuTbl.c.ab'\" unpacked with wrong size!
fi
# end of 'src/CuTbl.c.ab'
fi
if test -f 'src/CuWlm.c.ab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/CuWlm.c.ab'\"
else
echo shar: Extracting \"'src/CuWlm.c.ab'\" \(23487 characters\)
sed "s/^X//" >'src/CuWlm.c.ab' <<'END_OF_FILE'
X    }
Xelse
Xif (not_found_action == CuWlmNullOnNotFound)
X    {
X    return NULL ;
X    }
X/* if here, no list found, so we add one */
X
Xwidget_id_list = (WidgetIdList *) XtMalloc (sizeof (WidgetIdList)) ;
Xwidget_id_list->id = widget_id ;
Xwidget_id_list->next = NULL ;
X*last_ptr = widget_id_list ;
X
Xreturn widget_id_list ;
X}
X
X/***** **** *** ** * bmgr_search * ** *** **** *****/
X
Xstatic void
Xbmgr_search (ww, child)
X    CuWlmWidget ww ;
X    Fetus *child ;
X{
Xint i ; /* must not be Cardinal */
Xif (child->class_name == Bmgr_quark)
X    bmgr_setup (ww, child) ;
X
Xfor (i = child->n_children - 1;  i >=0;  i--)
X    bmgr_search (ww, &child->children[i]) ;
X
Xreturn; 
X}
X
X/***** **** *** ** * directive_search * ** *** **** *****/
X
Xstatic void
Xdirective_search (ww, child)
X    Fetus *child ;
X    CuWlmWidget ww ;
X{
Xint i ; /* must not be Cardinal */
Xif (child->directives)
X    directive_setup (ww, child) ;
X
Xfor (i = child->n_children - 1;  i >=0;  i--)
X    directive_search (ww, &child->children[i]) ;
X
Xreturn; 
X}
X
X/***** **** *** ** * bmgr_setup * ** *** **** *****/
X
Xstatic void
Xbmgr_setup (ww, child)
X    CuWlmWidget ww ;
X    Fetus *child ;
X{
XCuButtonWidget *button_list ;
Xcaddr_t *value_list ;
Xint i ;
X
X/*
X * Look widgets up in a list of name/id pairs.
X */
X
Xif (!child->n_manage_list)
X    {
X    char text[200] ;
X    sprintf (text, "CuWlm: Bmgr (%s) with no children!\n", child->widget_name) ;
X    XtError (text) ;
X    }
Xbutton_list = (CuButtonWidget *) XtMalloc (child->n_manage_list * sizeof (CuButtonWidget)) ;
Xvalue_list = (caddr_t *) XtMalloc (child->n_manage_list * sizeof (caddr_t)) ;
X
Xfor (i=0;  i < child->n_manage_list;  i++)
X    {
X    Arg arg ;
X    button_list[i] = (CuButtonWidget)
X	get_widget_id(ww, "CuButton", child->manage_list[i].widget);
X    if (child->manage_list[i].type != NULL)
X	{
X	convert_string_to_arg (ww, child->manage_list[i].type, "",
X			       child->manage_list[i].value, &arg) ;
X	value_list[i] = (caddr_t) arg.value ;
X	}
X    else
X	{
X	value_list[i] = NULL ;
X	}
X    }
X
XCuBmgrManage ((CuBmgrWidget)child->id, button_list, value_list,
X		child->n_manage_list) ;
Xreturn ;
X}
X
X/***** **** *** ** * directive_setup * ** *** **** *****/
X
Xstatic void
Xdirective_setup (ww, child)
X    CuWlmWidget ww ;
X    Fetus *child ;
X{
XCardinal i, j ;
X
Xfor (i=0;  i < child->n_directives;  i++)
X    {
X    Directive *directive = &child->directives[i] ;
X    /*
X     * for each unique callback in the directives, add a callback
X     */
X    for (j=0;  j < i;  j++)
X	{
X	if (strcmp (child->directives[i].callback_name,
X		    child->directives[j].callback_name) == 0)
X	    break ;
X	}
X    if (j == i)
X	{
X	directive->client_data[0] = (long) ww ;
X	directive->client_data[1] =
X	    (long) directive->callback_name ;
X	directive->client_data[2] = (long) child ;
X	XtAddCallback (child->id, directive->callback_name,
X		       wlm_central, (caddr_t) directive->client_data) ; 
X	add_to_sample_list (ww, XrmQuarkToString(child->class_name), child->id);
X	}
X    }
Xreturn ;
X}
X
X/***** **** *** ** * wlm_central * ** *** **** *****/
X
Xstatic void
Xwlm_central (w, client, call)
X    Widget w ;
X    caddr_t client ; /* [0] is the wlm widget,
X		      * [1] is the callback_name,
X		      * [2] is the child
X		      */
X    caddr_t call ;
X{
XCardinal i ;
Xlong *long_client = (long *) client ;
XCuWlmWidget ww =		  (CuWlmWidget) long_client[0] ;
XString    call_callback = (String)    long_client[1] ;
XFetus     *child =	  (Fetus *)   long_client[2] ;
XWidget	   id ;
X
X/*
X * Check for directive actions
X */
X
Xfor (i=0;  i < child->n_directives;  i++)
X    {
X    Cardinal j ;
X    Directive *directive = &child->directives[i] ;
X    if (strcmp(directive->callback_name, call_callback) != 0)
X	continue ; /* not the callback for this directive */
X
X    /*
X     * We need to check each comparison -- all must be true to trigger action
X     */
X    for (j=0;  j < directive->n_call_comparisons;  j++)
X	{
X	Boolean comparison ;
X	int k ; /* Must not be Cardinal */
X	CuWlmArgType case_number ;
X	caddr_t **ptr ;
X	Arg arg ;
X	/*
X	 * 1) convert call_data to real data via call_data_converter
X	 * 2) find data in caller
X	 * 3) compare using call_data_operator
X	 */
X	case_number = convert_string_to_arg
X				(ww, directive->call_data_converter[j],
X			             "", directive->call_data[j], &arg) ;
X	/*
X	 * For each index except the last, do a dereference
X	 * WARNING: This code assumes that all pointers are created equal...
X	 */
X	ptr = (caddr_t **) call ;
X	for (k=0;  k < (int)directive->n_call_indices[j] - 1;  k++)
X	    {
X	    ptr = (caddr_t **) *(call + directive->call_data_index[j][k]) ;
X	    }
X
X	/*
X	 * For the last dereference, we absolutely must branch according
X	 * to type...
X	 * TODO: For now,
X	 * these are hardwired, but eventually they will be generated
X	 * by a compile-time preprocessor and included...
X	 */
X
X	switch (case_number)
X	  {
X	  case CuWlmArgValArg :
X	    {
X	    XtArgVal value ;
X	    if (directive->n_call_indices[j] == 0)
X		{
X		union { caddr_t **ptr ; XtArgVal value ; } uni ;
X		uni.ptr = ptr ;
X		value = uni.value ;
X		}
X	    else
X		value = *(((XtArgVal *)ptr) + directive->call_data_index[j][k]);
X	    switch (directive->call_data_operator[j])
X	      {
X	      case CuWlmDirectiveEquivalence :
X		{
X		comparison = (value == arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveNonEquivalence :
X		{
X		comparison = (value != arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThan :
X		{
X		comparison = (value > arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThan :
X		{
X		comparison = (value < arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThanOrEqualTo :
X		{
X		comparison = (value >= arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThanOrEqualTo :
X		{
X		comparison = (value <= arg.value ? True : False) ;
X		break ;
X		}
X	      }
X	    break ;
X	    }
X	  case CuWlmFloatArg :
X	    {
X	    /*
X	     * This seems like a disgusting hack, but...
X	     */
X	    float value ;
X	    float arg_value ;
X	    union { XtArgVal i ; float f ; } i_to_f ;
X
X	    i_to_f.i = arg.value ;
X	    arg_value = i_to_f.f ;
X
X	    if (directive->n_call_indices[j] == 0)
X		{
X		union { caddr_t **ptr ; float value ; } uni ;
X		uni.ptr = ptr ;
X		value = uni.value ;
X		}
X	    else
X		{
X		value = *(((float *) ptr) + directive->call_data_index[j][k]) ;
X		}
X
X	    switch (directive->call_data_operator[j])
X	      {
X	      case CuWlmDirectiveEquivalence :
X		{
X		comparison = (value == arg_value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveNonEquivalence :
X		{
X		comparison = (value != arg_value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThan :
X		{
X		comparison = (value > arg_value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThan :
X		{
X		comparison = (value < arg_value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThanOrEqualTo :
X		{
X		comparison = (value >= arg_value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThanOrEqualTo :
X		{
X		comparison = (value <= arg_value ? True : False) ;
X		break ;
X		}
X	      }
X	    break ;
X	    }
X	  case CuWlmCharArg :
X	    {
X	    char value ;
X	    if (directive->n_call_indices[j] == 0)
X		{
X		union { caddr_t **ptr ; char value ; } uni ;
X		uni.ptr = ptr ;
X		value = uni.value ;
X		}
X	    else
X		value = *(((char *) ptr) + directive->call_data_index[j][k]) ;
X	    switch (directive->call_data_operator[j])
X	      {
X	      case CuWlmDirectiveEquivalence :
X		{
X		comparison = (value == arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveNonEquivalence :
X		{
X		comparison = (value != arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThan :
X		{
X		comparison = (value > arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThan :
X		{
X		comparison = (value < arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveGreaterThanOrEqualTo :
X		{
X		comparison = (value >= arg.value ? True : False) ;
X		break ;
X		}
X	      case CuWlmDirectiveLessThanOrEqualTo :
X		{
X		comparison = (value <= arg.value ? True : False) ;
X		break ;
X		}
X	      }
X	    break ;
X	    }
X	  case CuWlmStringArg :
X	    {
X	    String value ;
X	    if (directive->n_call_indices[j] == 0)
X		{
X		union { caddr_t **ptr ; String value ; } uni ;
X		uni.ptr = ptr ;
X		value = uni.value ;
X		}
X	    else
X		value = *(((String *) ptr) + directive->call_data_index[j][k]) ;
X	    switch (directive->call_data_operator[j])
X	      {
X	      case CuWlmDirectiveEquivalence :
X		{
X		comparison = (strcmp (value,
X				     (String) arg.value) == 0) ?
X				True : False ;
X		break ;
X		}
X	      case CuWlmDirectiveNonEquivalence :
X		{
X		comparison = (strcmp (value,
X				     (String) arg.value) != 0) ?
X				True : False ;
X		break ;
X		}
X	      }
X	    break ;
X	    }
X	  }
X
X
X	if (comparison == False)
X	    break ;
X	}
X
X    if (j < directive->n_call_comparisons)
X	{
X	continue ; /* do nothing, there was something not matched */
X	}
X    /*
X     * Action has been triggered
X     * First find the target widget, then branch on the two possibilities
X     */
X
X    id = get_widget_id (ww, directive->target_class, directive->target_name) ;
X
X    if (directive->resource.name)
X	{
X	/* The directive is to modify a widget's resource */
X	Arg arg ;
X
X	convert_string_to_arg (ww,
X			   get_resource_info (XtClass(id),
X					      directive->resource.name,
X					      CuWlmResourceInfoRepresentation),
X			   directive->resource.name,
X			   directive->resource.value, &arg) ;
X	XtSetValues (id, &arg, ONE) ;
X	}
X    else
X	{
X	XrmValue string_value ;
X	XrmValue converted_value ;
X	Cardinal k ;
X#define MAX_WLM_PROCEDURE_ARGS 10
X	Arg arg[MAX_WLM_PROCEDURE_ARGS] ;
X	/* The directive is to call a widget's public procedure */
X	string_value.addr = (caddr_t) directive->procedure ;
X	string_value.size = strlen (string_value.addr) ;
X
X	ww->wlm.conversion_class = XrmStringToQuark(directive->target_class) ;
X	XtConvert ((Widget)ww,  XtRString, &string_value,
X			 "Procedure", &converted_value) ;
X	for (k=0;  k < directive->n_arguments;  k++)
X	    {
X	    convert_string_to_arg (ww,
X				   directive->argument_converters[k],
X				   "",
X				   directive->argument_strings[k],
X				   &arg[k]) ;
X	    }
X	(*(*((XtProc *) converted_value.addr)))(id, arg[0].value,
X	arg[1].value, arg[2].value, arg[3].value, arg[4].value, arg[5].value,
X	arg[6].value, arg[7].value, arg[8].value, arg[9].value) ;
X	}
X    }
X
Xreturn ;
X}
X
X/***** **** *** ** * get_resource_info * ** *** **** *****/
X
X/*
X * given a widget class and a resource name,
X * this looks up the class of the resource
X */
X
Xstatic String
Xget_resource_info (class, name, info_type)
X    WidgetClass class ;
X    String name ;
X    CuWlmResourceInfoType info_type ;
X{
XCardinal i ;
XXtResourceList t_resource ;
XCardinal nt_resource ;
XString t_info ;
X
X
XXtGetResourceList (class, &t_resource, &nt_resource) ;
X
Xfor (i=0;  i < nt_resource;  i++)
X    {
X    if (strcmp (name, t_resource[i].resource_name) == 0)
X	break ;
X    }
X
Xif (i == nt_resource)
X    {
X    return NULL ;
X    }
X
Xif (info_type == CuWlmResourceInfoClass)
X    {
X    Cu_copy_ds (&t_info, t_resource[i].resource_class) ;
X    }
Xelse
X    {
X    Cu_copy_ds (&t_info, t_resource[i].resource_type) ;
X    }
X
XXtFree (t_resource) ;
X
Xreturn t_info ;
X}
X
X/***** **** *** ** * AddStringToWidgetConverter * ** *** **** *****/
X
Xstatic void
XAddStringToWidgetConverter (ww)
X    CuWlmWidget ww ;
X{
XWidgetClassList *class_list ;
XXtConvertArgRec *widgetConvertArgs ;
X/*
X * for each widget class, add a converter
X */
Xfor (class_list = ww->wlm.widget_class_list;
X     class_list != NULL;
X     class_list = class_list->next)
X    {
X    widgetConvertArgs = (XtConvertArgRec *)
X			XtMalloc (sizeof(XtConvertArgRec)) ;
X    widgetConvertArgs->address_mode = XtAddress ;
X    widgetConvertArgs->address_id = (caddr_t) class_list ;
X    widgetConvertArgs->size = (Cardinal) sizeof(WidgetClassList *) ;
X
X    XtAddConverter (XtRString, XrmQuarkToString (class_list->quark),
X		    CvtStringToWidget,
X		    widgetConvertArgs, ONE) ;
X    }
Xreturn ;
X}
X
X/***** **** *** ** * AddStringToProcedureConverter * ** *** **** *****/
X
Xstatic void
XAddStringToProcedureConverter ()
X{
Xstatic XtConvertArgRec procedureConvertArgs[] =
X    {
X     {
X     XtBaseOffset,
X     (caddr_t) XtOffset (CuWlmWidget, wlm.widget_class_list),
X     sizeof (WidgetClassList *)
X     }
X    ,{
X     XtBaseOffset,
X     (caddr_t) XtOffset (CuWlmWidget, wlm.conversion_class),
X     sizeof (XrmQuark)
X     }
X    } ;
X
XXtAddConverter (XtRString, "Procedure", CvtStringToProcedure,
X		procedureConvertArgs, XtNumber (procedureConvertArgs)) ;
Xreturn ;
X}
X
X/***** **** *** ** * CvtStringToWidget * ** *** **** *****/
X
X/*
X * Convert String To Widget
X *   Given a widget name, 
X *   and the wlm class list of the widget,
X *   It returns the first id in the IdList for the appropriate widget
X *   TODO: How and whether or not to handle multiple id's
X */
X
Xstatic void
XCvtStringToWidget (args, num_args, fromVal, toVal)
X    XrmValuePtr args ;		/* contains the address of the class list */
X    Cardinal	*num_args ;	/* unused */
X    XrmValuePtr fromVal ;
X    XrmValuePtr toVal ;
X{
XString	widget_name = (String) fromVal->addr ;
X
XWidgetClassList *class_list = (WidgetClassList *) args[0].addr ;
XWidgetNameList *name_list ;
X
Xname_list = get_widget_name_list (class_list, widget_name, CuWlmCroakOnNotFound) ;
X
XtoVal->size = sizeof (WidgetIdList *) ;
XtoVal->addr = (caddr_t) &name_list->widget_id_list->id ;
X
Xreturn ;
X}
X
X/***** **** *** ** * CvtStringToProcedure * ** *** **** *****/
X
X/*
X * Convert String To Procedure
X *   Given a procedure name
X *   and the wlm procedure list of the wlm widget that contains the widget,
X *   It returns the address of the appropriate public function
X */
X
Xstatic void
XCvtStringToProcedure (args, num_args, fromVal, toVal)
X    XrmValuePtr args ;		/* contains the address of the proc list */
X    Cardinal	*num_args ;	/* unused */
X    XrmValuePtr fromVal ;
X    XrmValuePtr toVal ;
X{
XString proc_name = (String) fromVal->addr ;
XXrmQuark widget_class = *((XrmQuark *) args[1].addr) ;
XWidgetClassList *initial_class_list = *((WidgetClassList **) args[0].addr) ;
XWidgetClassList *class_list ;
X
Xstatic XtProc procedure ;
X
Xclass_list = get_widget_class_list (&initial_class_list, widget_class,
X				    CuWlmCroakOnNotFound) ;
Xprocedure = get_proc_list (class_list->proc_list, proc_name) ;
X
XtoVal->size = sizeof (WidgetIdList *) ;
XtoVal->addr = (caddr_t) &procedure ;
X
Xreturn ;
X}
X
X/**
X ** The routines to read in the compiled layout
X **/
X
X#define get_pad() *ptr += pad
X#define get_nl() (*ptr)++
X
X/***** **** *** ** * ParseCuWlmLayout * ** *** **** *****/
X
Xstatic void
XParseCuWlmLayout (ww)
X    CuWlmWidget ww ;
X{
XString ptr ;
Xptr = layout_input->input_buffer ;
Xif (*ptr != '#' ||  *(ptr+1) != 'W' || *(ptr+2) != 'L' ||
X		    *(ptr+3) != 'D' || *(ptr+4) != 'L')
X    {
X    String errortext = XtMalloc (strlen(layout_input->file0) + 80) ;
X    sprintf (errortext,
X	     "CuWlm: File specified (%s) is not a compiled layout file!\n",
X	     layout_input->file0) ;
X    XtError (errortext) ;
X    }
Xptr+=6 ;
X
Xww->wlm.max_depth = get_int (&ptr) ;
Xww->wlm.child = (Fetus *) XtCalloc (1, sizeof (Fetus)) ;
Xget_child (ww->wlm.child, &ptr, 0) ;
Xreturn ;
X}
X
X/***** **** *** ** * get_child * ** *** **** *****/
X
Xstatic void
Xget_child (child, ptr, pad)
X    Fetus *child ;
X    String *ptr ;
X    int pad ;
X{
XCardinal i ;
X
Xget_nl() ;
Xget_pad() ;
Xchild->class_name = XrmStringToQuark (get_word(ptr)) ;
X
Xget_pad() ;
Xchild->n_resources = get_int(ptr) ;
X
Xif (child->n_resources)
Xchild->resources = (Resource *)
X		    XtMalloc (child->n_resources * sizeof (Resource)) ;
Xfor (i=0;  i < child->n_resources;  i++)
X    {
X    get_resource (&child->resources[i], ptr, pad) ;
X    }
X
Xget_pad() ;
Xchild->n_directives = get_int(ptr) ;
X
Xif (child->n_directives)
Xchild->directives = (Directive *)
X		    XtMalloc (child->n_directives * sizeof (Directive)) ;
Xfor (i=0;  i < child->n_directives;  i++)
X    get_directive (&child->directives[i], ptr, pad) ;
X
Xget_pad() ;
Xchild->n_manage_list = get_int(ptr) ;
X
Xif (child->n_manage_list)
Xchild->manage_list = (CuWlmManageItem *)
X		    XtMalloc (child->n_manage_list * sizeof (CuWlmManageItem)) ;
Xfor (i=0;  i < child->n_manage_list;  i++)
X    get_manage (&child->manage_list[i], ptr, pad) ;
X
Xget_pad() ;
Xchild->n_children = get_int(ptr) ;
X
Xif (child->n_children)
Xchild->children = (Fetus *) XtCalloc (child->n_children, sizeof (Fetus)) ;
Xpad += 2 ;
Xfor (i=0;  i < child->n_children;  i++)
X    get_child (&child->children[i], ptr, pad) ;
X
Xreturn ;
X}
X
X/***** **** *** ** * get_int * ** *** **** *****/
X
Xstatic int
Xget_int (ptr)
X    String *ptr ;
X{
Xint value ;
XString p = *ptr ;
X/*
X * ptr is now looking at something like: 5
X * Find the end of ascii integer and put a null there; use atoi to convert it.
X * Advance master pointer to point to just past that null,
X * and return the integer.
X */
X
Xwhile (*p != ' ' && *p != '\n')
X    p++ ;
X*p = '\0'; 
Xvalue = atoi(*ptr) ;
X*ptr = p+1 ;
Xreturn value ;
X}
X
X/***** **** *** ** * get_word * ** *** **** *****/
X
Xstatic String
Xget_word (ptr)
X    String *ptr ;
X{
Xint length ;
XString p ;
X/*
X * ptr is now looking at something like: 5 Label
X * Find the end of ascii integer and put a null there; use atoi to convert it.
X * Then put a null at the end of the word to be found.
X * Advance master pointer to point to just past that null,
X * and return a pointer to the word.
X */
X
Xlength = get_int(ptr) ;
Xp = *ptr ;
Xp[length] = '\0' ;
X*ptr = p + length + 1 ;
Xreturn p ;
X}
X
X/***** **** *** ** * get_string * ** *** **** *****/
X
Xstatic String
Xget_string (ptr)
X    String *ptr ;
X{
Xint length ;
XString p ;
X/*
X * Same as get_word, but string is enclosed in parentheses
X */
X
Xlength = get_int(ptr) ;
Xp = *ptr + 1 ;
Xp[length] = '\0' ;
X*ptr = p + length + 2 ;
Xreturn p ;
X}
X
X/***** **** *** ** * get_resource * ** *** **** *****/
X
Xstatic void
Xget_resource (resource, ptr, pad)
X    Resource *resource ;
X    String *ptr ;
X    int pad ;
X{
XString context ;
Xget_pad() ;
Xresource->name = get_word(ptr) ;
Xresource->value = get_string(ptr) ;
Xcontext = get_word(ptr) ;
Xresource->context = (strlen(context)==5) ? CuWlmLocalContext : CuWlmGlobalContext ;
X
Xreturn ;
X}
X
X/***** **** *** ** * get_directive * ** *** **** *****/
X
Xstatic void
Xget_directive (directive, ptr, pad)
X    Directive *directive ;
X    String *ptr ;
X    int pad ;
X{
XCardinal i, j,  n ;
XString dtype ;
X
Xget_pad() ;
Xdirective->callback_name = get_word(ptr) ;
Xdirective->target_class = get_word(ptr) ;
Xdirective->target_name = get_word(ptr) ;
Xn = directive->n_call_comparisons = get_int(ptr) ;
Xdtype = get_word(ptr) ;
X
Xpad++ ;
Xdirective->call_data_converter = (String *) XtMalloc (n * sizeof (String)) ;
Xdirective->call_data = (String *) XtMalloc (n * sizeof (String)) ;
Xdirective->call_data_operator = (CuWlmDirectiveOperator *)
X	XtMalloc (n * sizeof (CuWlmDirectiveOperator)) ;
Xdirective->n_call_indices = (Cardinal *) XtMalloc (n * sizeof (Cardinal)) ;
Xdirective->call_data_index = (int **) XtMalloc (n * sizeof (int *)) ;
X
Xfor (i=0;  i < n;  i++)
X    {
X    String dummy ;
X    get_pad() ;
X    directive->call_data_converter[i] = get_word(ptr) ;
X    directive->call_data[i] = get_string(ptr) ;
X    directive->call_data_operator[i] = (CuWlmDirectiveOperator) get_int(ptr) ;
X    dummy = get_word(ptr) ; /* there only for visualization of operator */
X    directive->n_call_indices[i] = (Cardinal) get_int(ptr) ;
X    (*ptr) += 2 ; /* skip the ": " */
X    directive->call_data_index[i] =
X	(int *) XtMalloc (directive->n_call_indices[i] * sizeof (int)) ;
X    for (j=0;  j < directive->n_call_indices[i];  j++)
X	directive->call_data_index[i][j] = get_int(ptr) ;
X    }
Xpad-- ;
X
Xget_pad() ;
Xif (strcmp(dtype, "XtSetValues") == 0)
X    {
X    directive->target_class = get_word(ptr) ;
X    directive->target_name = get_string(ptr) ;
X    directive->resource.name = get_word(ptr) ;
X    directive->resource.value = get_string(ptr) ;
X    }
Xelse
X    {
X    directive->resource.name = NULL ;
X    directive->procedure = get_word(ptr) ;
X    directive->n_arguments = get_int(ptr) ;
X    directive->argument_converters =
X	(String *) XtMalloc (directive->n_arguments * sizeof(String)) ;
X    directive->argument_strings =
X	(String *) XtMalloc (directive->n_arguments * sizeof(String)) ;
X    for (i=0;  i < directive->n_arguments;  i++)
X	{
X	get_pad() ;
X	directive->argument_converters[i] = get_word(ptr) ;
X	directive->argument_strings[i] = get_string(ptr) ;
X	}
X    }
X
Xreturn ;
X}
X
X/***** **** *** ** * get_manage * ** *** **** *****/
X
Xstatic void
Xget_manage (managed, ptr, pad)
X    CuWlmManageItem *managed ;
X    String *ptr ;
X    int pad ;
X{
Xget_pad() ;
Xmanaged->widget = get_string(ptr) ;
Xmanaged->type = get_word(ptr) ;
Xmanaged->value = get_string(ptr) ;
X
Xreturn ;
X}
X
X/**
X ***
X **** Public Procedures
X ***
X **/
X
X/**
X ** Device Functions
X **/
X
X/***** **** *** ** * CuWlmSample * ** *** **** *****/
X
Xvoid
XCuWlmSample (ww)
X    CuWlmWidget ww ;
X{
XCuWlmSampleList *sample_list ;
X
Xif (!XtIsSubclass ((Widget)ww, (WidgetClass)cuWlmWidgetClass)) {
X    XtError("CuWlmSample requires arg to be subclass of cuWlmWidgetClass");
X    }
X
Xif (ww->wlm.first_device)
X    {
X    ww->wlm.first_device = False ;
X    }
X
Xww->wlm.sampling_active = True ;
X
Xfor (sample_list=ww->wlm.sample_list;
X     sample_list != NULL;
X     sample_list = sample_list->next)
X     {
X     (*sample_list->sample_proc)(sample_list->id) ;
X     }
X
Xww->wlm.sampling_active = False ;
X
Xreturn ;
X}
X
X/***** **** *** ** * CuWlmRequest * ** *** **** *****/
X
Xvoid
XCuWlmRequest (ww)
X    CuWlmWidget ww ;
X{
XCuWlmSreRecord *save ;
X/*
X * if there is a wlmEvent already queued, return it
X * o.w., wait for something to happen
X */
Xif (!XtIsSubclass ((Widget)ww, (WidgetClass)cuWlmWidgetClass)) {
X    XtError("CuWlmRequest requires arg to be subclass of cuWlmWidgetClass");
X    }
Xif (ww->wlm.first_device)
X    {
X    CuWlmSample (ww) ;
X    ww->wlm.first_device = False ;
X    }
X
Xif (ww->wlm.queue_ptr != NULL)
X    {
X    dequeue_event (ww) ;
X    ww->wlm.event_stamp++ ;
X    return ;
X    }
X
X/*
X * Since requests can be recursive, we have to keep a stack of them
X */
X
Xsave = ww->wlm.sre_status ;
Xww->wlm.sre_status = (CuWlmSreRecord *) XtMalloc (sizeof (CuWlmSreRecord)) ;
Xww->wlm.sre_status->status = CuWlmRequestNotSatisfied ;
Xww->wlm.sre_status->next = save ;
X
Xwhile (ww->wlm.sre_status->status == CuWlmRequestNotSatisfied)
X    {
X    XEvent event ;
X
X    XtNextEvent (&event) ;
X    XtDispatchEvent (&event) ;
X    }
Xmy_sync () ;
X
Xww->wlm.event_stamp++ ;
Xsave = ww->wlm.sre_status ;
Xww->wlm.sre_status = ww->wlm.sre_status->next ;
XXtFree (save) ;
X
Xreturn ;
X}
X
X/***** **** *** ** * CuWlmEvent * ** *** **** *****/
X
XBoolean
XCuWlmEvent (ww)
X    CuWlmWidget ww ;
X{
XCuWlmSreRecord *save ;
XBoolean return_status ;
X/*
X * if there is a wlmEvent already queued, return it
X * o.w., wait for something to happen
X */
Xif (!XtIsSubclass ((Widget)ww, (WidgetClass)cuWlmWidgetClass)) {
X    XtError("CuWlmEvent requires arg to be subclass of cuWlmWidgetClass");
X    }
Xif (ww->wlm.first_device)
X    {
X    CuWlmSample (ww) ;
X    ww->wlm.first_device = False ;
X    }
X
Xif (ww->wlm.queue_ptr != NULL)
X    {
X    dequeue_event (ww) ;
X    return True ;
X    }
X
Xsave = ww->wlm.sre_status ;
Xww->wlm.sre_status = (CuWlmSreRecord *) XtMalloc (sizeof (CuWlmSreRecord)) ;
Xww->wlm.sre_status->status = CuWlmRequestNotSatisfied ;
Xww->wlm.sre_status->next = save ;
X
Xif (XtPending())
X    {
X    /***
X    XEvent event ;
X
X    XtNextEvent (&event) ;
X    XtDispatchEvent (&event) ;
X    ***/
X    my_sync () ;
X    }
X
Xreturn_status = (ww->wlm.sre_status->status == CuWlmRequestSatisfied) ;
Xsave = ww->wlm.sre_status ;
Xww->wlm.sre_status = ww->wlm.sre_status->next ;
XXtFree (save) ;
X

END_OF_FILE
echo shar: NEWLINE appended to \"'src/CuWlm.c.ab'\"
if test 23488 -ne `wc -c <'src/CuWlm.c.ab'`; then
    echo shar: \"'src/CuWlm.c.ab'\" unpacked with wrong size!
fi
# end of 'src/CuWlm.c.ab'
fi
if test -f 'wlmCompiler/wlc.l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wlmCompiler/wlc.l'\"
else
echo shar: Extracting \"'wlmCompiler/wlc.l'\" \(1946 characters\)
sed "s/^X//" >'wlmCompiler/wlc.l' <<'END_OF_FILE'
X%{
X#define ManageContext 1
X#define DirectiveContext 2
Xstatic int oops_context ;
X
Xstatic	void convert_nl () ;
X
Xstatic Boolean	first_time = True ; /* recognizes the first time for yylex()*/
Xstatic Boolean	nested_args = False ; 
X
Xextern int lex_bug ;
X
Xstatic char *ttt ;
X
X#undef input
X#undef unput
X
X/***
X#include "y.tab.h"
X***/
X%}
X
X%START	string
X
X%%
X
X"/*"  /* look for start of comment */
X    {
X    char c ;
X    for (;;)
X	{
X	while ((c = input()) != '*')
X	    ;
X	if ((c = input()) == '/')
X	    break ;
X	unput (c) ;
X	}
X    }
X
X["]  /* look for start of string */
X    {
X    BEGIN string ;
X    }
X
X<string>[^"]*\"  /* anything but another quote */
X    {
X    yytext[yyleng-1] = '\0' ; /* trash the trailing quote */
X    Cu_copy_ds (&ttt, yytext) ;
X    convert_nl (ttt) ;	/* convert '\' 'n' to '\n' and remove '\' '\n' */
X    yylval.s_val = ttt ;
X
X    BEGIN 0 ;
X    return STRING ;
X    }
X
Xif		/* if keyword */
X	{
X	return IF_KEY ;
X	}
X
XXtSetValues	/* set_values keyword */
X	{
X	return SET_VALUES_KEY ;
X	}
X
Xinclude		/* include keyword */
X	{
X	return INCL_KEY ;
X	}
X
Xmanage		/* manage keyword */
X	{
X	return MANAGE_KEY ;
X	}
X
X[^ \t\n\{\}\:\(\)\[\]\"\,\=\&\!\<\>\*]*	/* item (anything but punctuation) */
X	{
X	Cu_copy_ds (&ttt, yytext) ;
X	yylval.s_val = ttt ;
X	return WORD ;
X	}
X
X[\{\}\<\>\(\)\[\]\:\,\=\&\!\*]				/* punctuation */
X	{
X	return (yytext[0]) ;
X	}
X
X[ \n\t]		/* white space	*/
X	{
X	;
X	}
X
X.	{
X	sprintf (error_text, "LEX returning ERROR on char (%c)\n", *yytext) ;
X	XtWarning (error_text) ;
X	return ERROR ;
X	}
X%%
X
Xstatic void
Xconvert_nl (text)
X    char *text ;
X{
XCardinal i ;
Xfor (i=0;  i < strlen (text);  i++)
X	{
X	if (text[i] == '\\' && text[i+1] == 'n')
X		{
X		Cardinal j ;
X		text[i] = '\n' ;
X		j = i+1 ;
X		while (text[j] != 0)
X			{
X			text[j] = text[j+1] ;
X			j++ ;
X			}
X		}
X	else
X	if (text[i] == '\\' && text[i+1] == '\n')
X		{
X		Cardinal j = i ;
X		while (1)
X			{
X			text[j] = text[j+2] ;
X			if (text[j] == '\0')
X				break ;
X			j++ ;
X			}
X		}
X	}
Xreturn ;
X}
X

END_OF_FILE
echo shar: NEWLINE appended to \"'wlmCompiler/wlc.l'\"
if test 1947 -ne `wc -c <'wlmCompiler/wlc.l'`; then
    echo shar: \"'wlmCompiler/wlc.l'\" unpacked with wrong size!
fi
# end of 'wlmCompiler/wlc.l'
fi
echo shar: End of archive 2 \(of 12\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0