/***********************************************************************
 *
 * TITLE:
 *	activity.c
 *
 * AUTHOR:
 *	Cassie Mulnix
 *
 * DESCRIPTION:	
 *	This module is part of the OPPS editor, xopps.  It contains
 *	routines to handle activity objects.
 *
 *                              CHANGE HISTORY
 *
 * $Log: activity.c,v $
 * Revision 1.51  1994/12/31  03:34:52  kevin
 * fixed memory allocation problem after DialogTextGet
 *
 * Revision 1.50  1994/11/01  15:43:38  cassie
 * fixed % complete and loa callbacks to work with edited values and
 * not stored values only
 *
 * Revision 1.49  1994/10/12  18:14:51  cassie
 * set change to DIALOG_NO_CHANGE in ok_button
 *
 * Revision 1.48  1994/08/10  22:02:18  cassie
 * fixed DialogFlagSet calls
 *
 * Revision 1.47  1994/07/20  19:06:35  clm
 * updated TRUE, ERROR etc in cancel & ok_button functions
 * to DIALOG_ constants
 *
 * Revision 1.46  1994/06/16  21:55:48  clm
 * updated to new dialog routines - extra parameter to DialogTextCreate
 *
 * Revision 1.45  1994/06/16  16:56:35  clm
 * updated to new gr_ routines using GR_ for font names
 *
 * Revision 1.44  1994/06/08  18:47:59  clm
 * removed Xm library includes since they are in dialog
 *
 * Revision 1.43  1994/06/07  17:05:55  clm
 * initialize edate_diff to 0 for hp warning
 *
 * Revision 1.42  1994/06/07  16:39:58  clm
 * fixed loc function
 *
 * Revision 1.41  1994/06/01  22:27:07  clm
 * rewrote init functions to use dialog oellib functions
 * also don't initialize popups until object called
 *
 * Revision 1.40  1994/05/20  23:31:43  clm
 * updated with HP, SGI changes
 *
 * Revision 1.39  1994/05/04  23:34:36  clm
 * ported to ANSI C
 *
 * Revision 1.38  1994/02/10  20:36:57  clm
 * fixed location and placement of text
 *
 * Revision 1.37  1994/02/09  20:57:09  clm
 * added UTC_ONE_DAY/2 to pctdate for correct filling
 *
 * Revision 1.36  1993/11/11  18:12:10  clm
 * adjusted vertical position of text
 *
 * Revision 1.35  1993/10/13  21:04:19  clm
 * changed dsp routine so empty box does not become filled box for symbol
 * if auto reset of symbols is ON
 *
 * Revision 1.34  1993/10/12  16:37:52  clm
 * fixed gr_rect_clear to be based on y_gap
 *
 * Revision 1.33  1993/10/11  15:44:07  clm
 * added clear rectangle larger than object so stands out from vertical lines
 *
 * Revision 1.32  1993/09/10  18:01:52  clm
 * offset rectangle to left 1 position
 *
 * Revision 1.31  1993/05/27  16:43:42  clm
 *  change symbols to filled with status date
 *
 * Revision 1.30  1993/05/21  16:01:58  clm
 * fixed buffer size for sav function
 *
 * Revision 1.29  1993/05/18  22:39:41  clm
 * added meaningful error messages for check_num and check_day
 *
 * Revision 1.28  1993/05/18  20:58:30  clm
 * added new message.c function
 *
 * Revision 1.27  1993/03/29  15:57:34  clm
 * fixed date_handle so it is called after start date is set
 * and if dates are edited, percent complete is updated
 *
 * Revision 1.26  1993/03/25  18:33:39  clm
 * fixed fill pattern to end at beginning of day instead of middle of day
 *
 * Revision 1.25  1993/02/23  18:22:28  clm
 * fixed locate function for xs < start_date
 *
 * Revision 1.24  1993/02/20  00:03:30  clm
 * added Slip Precedence Objects to edit popup
 *
 * Revision 1.23  1993/02/08  15:51:08  clm
 *  centered symbol on date
 *
 * Revision 1.23  1993/01/25  23:39:14  clm
 * fixed fill_pattern gap
 * fixed dsp_marker size to match symbol object
 *
 * Revision 1.22  1993/01/21  16:48:27  clm
 * fixed loc_function for y2
 *
 * Revision 1.21  1992/12/15  20:39:25  clm
 * changed strlen to sizeof when assigning symbols
 *
 * Revision 1.20  1992/12/14  18:54:39  clm
 * really fixed dsp and loc bug
 *
 * Revision 1.19  1992/12/11  22:47:39  clm
 * fixed dsp error checking of page bounds
 *
 * Revision 1.18  1992/12/11  22:10:48  clm
 * fixed loc and dsp for completely offpage objects
 *
 * Revision 1.17  1992/12/10  21:45:40  clm
 * fixed new_index so chart is always object 0
 *
 * Revision 1.16  1992/11/30  22:27:43  clm
 * fixed locate function
 *
 * Revision 1.15  1992/11/24  16:28:27  clm
 * fixed rem functions - setting of ip array
 *
 * Revision 1.14  1992/11/12  18:57:35  clm
 * fixed layer setting in ok_button
 *
 * Revision 1.13  1992/11/09  21:44:02  clm
 * removed unused variable
 *
 * Revision 1.12  1992/11/09  16:26:41  clm
 * added precedence lines
 * fixed layout of popup
 *
 * Revision 1.11  1992/10/12  18:02:19  clm
 * fixed mov to not reset x coordinate since x cannot change
 *
 * Revision 1.10  1992/10/09  21:17:43  clm
 * fixed move routine
 *
 * Revision 1.9  1992/10/02  19:15:00  clm
 * housekeeping
 *
 * Revision 1.8  1992/10/01  21:27:16  clm
 * added actloaCB and actpctCB for editing dates while popup is managed
 *
 * Revision 1.7  1992/09/30  22:34:57  clm
 * fixed locate routine for r.x and r.y for two text items
 *
 * Revision 1.6  1992/09/30  15:01:32  clm
 * cleaned up dsp routine
 * fixed display so it is layered on top of chart
 *
 * Revision 1.5  1992/09/29  16:24:39  clm
 * added id text and toggle
 *
 * Revision 1.4  1992/09/29  15:51:45  clm
 * added  id text and toggle
 *
 * Revision 1.3  1992/09/25  20:31:53  clm
 * error checking to make sure end date is after start date
 *
 * Revision 1.2  1992/09/22  21:45:18  clm
 * fixed fill_patterns to work with ramps
 *
 * Revision 1.1  1992/09/22  17:18:27  clm
 * Initial revision
 *
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: activity.c,v 1.51 1994/12/31 03:34:52 kevin OEL $";
#endif

/*
    activity.c - an xopps module for activity objects

    local functions:
        dsp_act(i) - display act object
        rem_act(i) - remove act object
        mov_act(i) - move act object
        edt_act(i) - change contents of act field
        msg_act(i) - display message on screen
*/

#include "xopps.h"

static int font_values[] = {
    GR_COURIER, GR_COURIER_BOLD, GR_HELVETICA, GR_HELVETICA_BOLD, GR_TIMES, 
    GR_TIMES_BOLD
};

static int font_sizes[] = {
    8, 10, 12, 14, 18, 24
};

static int symbol_nums[MAX_MARKER];

	/* local functions */
static void activity_ok_button(void);		/* Callback for ok button */
static void cancel_button(void);		/* Callback for cancel button */
static void change_color(Widget, XtPointer, XtPointer);
static void change_disp(Widget, XtPointer, XtPointer);
static void change_drawlyr(Widget, XtPointer, XtPointer);
static void change_smark(Widget, XtPointer, XtPointer);
static void change_emark(Widget, XtPointer, XtPointer);
static void change_hpos(Widget, XtPointer, XtPointer);
static void change_vpos(Widget, XtPointer, XtPointer);
static void change_fillpatt(Widget, XtPointer, XtPointer);
static void change_point(Widget, XtPointer, XtPointer);
static void change_font(Widget, XtPointer, XtPointer);
static void change_loa(Widget, XtPointer, XtPointer);
static void change_idhpos(Widget, XtPointer, XtPointer);
static void change_idvpos(Widget, XtPointer, XtPointer);
static void change_idtog(Widget, XtPointer, XtPointer);
static void change_pline(Widget, XtPointer, XtPointer);
static void set_pline(utc_val, utc_val);	/* Executes pline slips */
static void dsp_act(int);
static void edt_act(int, int);
static void rem_act(int, int);
static void lim_act(int, int *, int *, int *, int *, int);
static void loc_act(int, int);
static void mov_act(int, int, int, int);
static void cpy_act(struct obj *, struct obj *);
static void msg_act(int, int);
static void sav_act(int, FILE *, int);
static int load_act(char *);
static void set_percent_done(void);		/* sets percent done value */
static void set_pct_date(int);			/* sets percent complete date */
static int set_loa(int, int);			/* sets length of event */
static void set_loa_date(int);			/* sets end date value */
static int date_handle(utc_val, utc_val);	/* part of ok_button */
static void actloaCB(Widget, XtPointer, XmAnyCallbackStruct *);
	/* Callback for loa change */
static void actpctCB(Widget, XtPointer, XmAnyCallbackStruct *);
	/* Callback for pct change */
static void verify_fun(Widget, XtPointer, XtPointer);
static void create_dialog(void);

static struct ops act_ops = {
    dsp_act, edt_act, rem_act, lim_act, loc_act, mov_act,
    cpy_act, msg_act, sav_act
};
                                              /* function pointer */

static DialogDate *sdate, *edate;
static DialogDate *rudate, *rddate;
static DialogDate *bsdate, *bedate;
static DialogDate *pctdate;
static DialogOption *fillw;
static DialogText *pct;
static DialogText *textw, *idw;
static DialogOption *hposw, *vposw;
static DialogOption *dspidw;
static DialogOption *idhposw, *idvposw;
static DialogOption *fontw, *pointw;
static DialogOption *dispw, *drawlyrw;
static DialogText *linew, *lengthw;
static DialogOption *lenmenuw, *colorw;
static DialogOption *plinew;
static DialogOption *smark, *emark;

static Widget act_dialog;			/* dialog shell for popup */
static int nmarks;				/* number symbols */
static int new_color;				/* new color value */
static int new_smark;				/* new value for start symbol */
static int new_emark;				/* new value for end symbol */
static int new_disp;				/* new value for display date */
static int new_drawlyr;				/* new value for layer */
static int new_fillpatt;			/* new value for fill pattern */
static int new_point;                           /* new point id */
static int new_font;                            /* new font id */
static int new_loa;				/* new loa id */
static int new_hpos;				/* new hpos id */
static int new_vpos;				/* new vpos id */
static int new_idhpos;				/* new hpos for id */
static int new_idvpos;				/* new vpos for id text */
static int new_idtog;				/* new id toggle */
static int loa;					/* current loa value */
static int loa_type;				/* current loa toggle value */
static int change = DIALOG_NO_CHANGE;		/* a change was made */
static int pline_flag = FALSE;			/* slip plines flag */
static Widget parent_shell;

/***********************************************************************
 *
 * FUNCTION:
 *	init_activity_object()
 *
 * INPUTS:
 *	parent	(Widget)
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	none
 *
 * DESCRIPTION:
 *	sets up widgets for activity
 */

void 
init_activity_object(Widget parent)
{
    register_io_obj('O', load_act);			/* register object */
    parent_shell = parent;
}

/***********************************************************************
 *
 * FUNCTION:
 *	create_dialog()
 *
 * INPUTS:
 *	none
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	none
 *
 * DESCRIPTION:
 *	sets up widgets for activity
 */

static void 
create_dialog(void)
{
    Pixmap marks[16];                       /* symbol images */
    Cardinal n;				    /* temp indices */

    static char *patts[] = { "Open", "Solid", "Left Diagonals",
	"Right Diagonals", "Horizontal Lines", "Vertical Lines",
	"Cross Hatched" };
    static char *hpos_list[] = { "Left", "Center", "Right" };
    static char *vpos_list[] = { "Above", "Below", "Center" };
    static char *disps[] = { "None", "Display" };
    static char *fonts[] = { "Courier", "Courier Bold", "Helvetica",
	"Helvetica Bold", "Times", "Times Bold" };
    static char *points[] = { "8", "10", "12", "14", "18", "24" };
    static char *dates[] = { "None", "DOY", "Month/Day" };
    static char *drawlyrs[] = { "0", "1", "2", "3" };
    static char *loas[] = { "Calendar Days", "Week Days" };
    static char *plines[] = { "No", "Yes" };

    get_markers(marks, &nmarks);
    for (n = 0; n < nmarks; n++) {
        symbol_nums[n] = n;
    }

    act_dialog = DialogInit(parent_shell, "Activity Object", "activity",
	verify_fun, (XtPointer)DIALOG_CANCEL);

    DialogAddRow(2);
    sdate = DialogDateCreate("Start Date ");
    edate = DialogDateCreate("End Date ");

    DialogAddRow(2);
    rudate = DialogDateCreate("Ramp Up Date ");
    rddate = DialogDateCreate("Ramp Down Date ");

    DialogAddRow(2);
    bsdate = DialogDateCreate("Baseline Start Date ");
    bedate = DialogDateCreate("Baseline End Date ");

    DialogAddRow(2);
    pctdate = DialogDateCreate("Percent Done Date ");
    pct = DialogTextCreate("Percent Complete ", 3, 3);
    XtAddCallback(pct->text, XmNactivateCallback, (XtCallbackProc)actpctCB,
	NULL);

    DialogAddRow(3);
    fillw = DialogOptionCreate("Fill Pattern ", 7, 1, change_fillpatt,
	DIALOG_OPT_STR_ARY, patts, NULL);	
    smark = DialogOptionCreate("Start Symbol ", nmarks, 0, change_smark,
	DIALOG_OPT_PIX_ARY, marks, NULL);
    emark = DialogOptionCreate("End Symbol ", nmarks, 0, change_emark,
	DIALOG_OPT_PIX_ARY, marks, NULL);

    textw = DialogTextCreate("Text ", 30, 100);

    DialogAddRow(2);
    hposw = DialogOptionCreate("Horizontal Text Position ", 3, 0, change_hpos,
	DIALOG_OPT_STR_ARY, hpos_list, NULL);
    vposw = DialogOptionCreate("Vertical Text Position ", 3, 0, change_vpos,
	DIALOG_OPT_STR_ARY, vpos_list, NULL);

    DialogAddRow(2);
    idw = DialogTextCreate("Id ", 30, 100);
    dspidw = DialogOptionCreate("Display Id ", 2, 0, change_idtog, 
	DIALOG_OPT_STR_ARY, disps, NULL);

    DialogAddRow(2);
    idhposw = DialogOptionCreate("Horizontal Id Position ", 3, 0, change_idhpos,
	DIALOG_OPT_STR_ARY, hpos_list, NULL);
    idvposw = DialogOptionCreate("Vertical Id Position ", 3, 0, change_idvpos,
	DIALOG_OPT_STR_ARY, vpos_list, NULL);

    DialogAddRow(2);
    fontw = DialogOptionCreate("Font ", 6, 5, change_font, 
	DIALOG_OPT_STR_ARY, fonts, font_values);
    pointw = DialogOptionCreate("Point ", 6, 10, change_point, 
	DIALOG_OPT_STR_ARY, points, font_sizes);

    DialogAddRow(3);
    dispw = DialogOptionCreate("Display Date", 3, 1, change_disp, 
	DIALOG_OPT_STR_ARY, dates, NULL);
    drawlyrw = DialogOptionCreate("Draw Layer ", 4, 0, change_drawlyr, 
	DIALOG_OPT_STR_ARY, drawlyrs, NULL);
    colorw = DialogOptionCreate("Color ", ncolor, 0, change_color,
	DIALOG_OPT_STR_ARY, color_name, color_index);

    DialogAddRow(3);
    linew = DialogTextCreate("Line Position ", 2, 2);
    lengthw = DialogTextCreate("Length of Activity ", 4, 4);
    XtAddCallback(lengthw->text, XmNactivateCallback, (XtCallbackProc)actloaCB,
	NULL);
    lenmenuw = DialogOptionCreate(" ", 2, 0, change_loa, DIALOG_OPT_STR_ARY,
	loas, NULL);

    plinew = DialogOptionCreate("Slip Precedence Objects ", 2, 0, change_pline,
	DIALOG_OPT_STR_ARY, plines, NULL);

    DialogStdButtons(verify_fun, (XtPointer)DIALOG_UPDATE, verify_fun,
	(XtPointer)DIALOG_CANCEL, (XtCallbackProc)ShowHelp, "activity");

}

/***********************************************************************
 *
 * FUNCTION:
 *	add_activity()
 *
 * INPUTS:
 *	st_date, e_date, up_date, dn_date,pd_date, bs_date, be_date   (utc_val)
 *	line, strtsym, endsym, done_pct, layer, hpos, vpos, font
 *	    point, color		(int)
 *	fill_pattern 			(enum pattern)
 *	disp				(enum tds)
 *	text, idtext			(char *)		
 *	idtog, idhpos, idvpos		(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *	i	the index of the new object
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	adds an activity object
 */

int 
add_activity(utc_val st_date, utc_val e_date, utc_val up_date, utc_val dn_date, int line, int strtsym, int endsym, utc_val pd_date, int done_pct, utc_val bs_date, utc_val be_date, enum pattern fill_pattern, int layer, enum tds disp, int hpos, int vpos, int font, int point, int color, char *text, char *idtext, int idtog, int idhpos, int idvpos)
{
    int i;              /* index */

    i = new_index(FALSE);
    objary[i].z.actptr = (struct act *)XtMalloc((Cardinal)sizeof(struct act));
    objary[i].z.actptr->strtdate = st_date;
    objary[i].z.actptr->endate = e_date;
    objary[i].z.actptr->update = up_date;
    objary[i].z.actptr->dwndate = dn_date;
    objary[i].z.actptr->line = line;
    objary[i].z.actptr->strtsym = strtsym;
    objary[i].z.actptr->endsym = endsym;
    objary[i].z.actptr->pctdate = pd_date;
    objary[i].z.actptr->done_pct = done_pct;
    objary[i].z.actptr->b_strtdate = bs_date;
    objary[i].z.actptr->b_endate = be_date;
    objary[i].z.actptr->fill_pattern = fill_pattern;
    objary[i].z.actptr->disp = disp;
    objary[i].z.actptr->hpos = hpos;
    objary[i].z.actptr->vpos = vpos;
    objary[i].z.actptr->font = font;
    objary[i].z.actptr->point = point;
    objary[i].z.actptr->color = color;
    objary[i].z.actptr->idtog = idtog;
    objary[i].z.actptr->idhpos = idhpos;
    objary[i].z.actptr->idvpos = idvpos;
    objary[i].z.actptr->text = XtNewString(text);
    objary[i].z.actptr->idtext = XtNewString(idtext);
    loa = (objary[i].z.actptr->endate - objary[i].z.actptr->strtdate)/
	UTC_ONE_DAY;
    objary[i].type = OBJ_ACT;
    objary[i].layer = layer;
    objary[i].opsptr = &act_ops;
    return i;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_color()
 *
 * INPUTS:
 *      button  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets new color for act object
 */

static void 
change_color(Widget button, XtPointer option, XtPointer any_data)
{
    new_color = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *	change_disp()
 *
 * INPUTS:
 *	button		(Widget)
 *	option 		(XtPointer)
 *	anydata		(XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes display date to the input value
 */

static void 
change_disp(Widget button, XtPointer option, XtPointer any_data)
{
    new_disp = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_loa()
 *
 * INPUTS:
 *      button          (Widget)
 *      option          (XtPointer)
 *      anydata         (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      changes length of event to the input value
 */

static void 
change_loa(Widget button, XtPointer option, XtPointer any_data)
{
    new_loa = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *	change_fillpatt()
 *
 * INPUTS:
 *	button			(Widget)
 *	option, any_data	(XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes fill pattern of activity to the input value
 */

static void 
change_fillpatt(Widget button, XtPointer option, XtPointer any_data)
{
    new_fillpatt = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *	change_hpos()
 *
 * INPUTS:
 *	button			(Widget)
 *	option, any_data	(XtPointer)	
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the hpos position of the activity object
 */

static void 
change_hpos(Widget button, XtPointer option, XtPointer any_data)
{
    new_hpos = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_vpos()
 *
 * INPUTS:
 *      button                  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      changes the vpos position of the activity object
 */

static void 
change_vpos(Widget button, XtPointer option, XtPointer any_data)
{
    new_vpos = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_idhpos()
 *
 * INPUTS:
 *      button                  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      changes the id hpos position of the activity object
 */

static void 
change_idhpos(Widget button, XtPointer option, XtPointer any_data)
{
    new_idhpos = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_idvpos()
 *
 * INPUTS:
 *      button                  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      changes the id vpos position of the activity object
 */

static void 
change_idvpos(Widget button, XtPointer option, XtPointer any_data)
{
    new_idvpos = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_idtog()
 *
 * INPUTS:
 *      button                  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      changes the id display toggle position of the activity object
 */

static void 
change_idtog(Widget button, XtPointer option, XtPointer any_data)
{
    new_idtog = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *	change_drawlyr()
 *
 * INPUTS:
 *	button			(Widget)
 *	option, any_data	(XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the draw layer of the activity object
 */

static void 
change_drawlyr(Widget button, XtPointer option, XtPointer any_data)
{
    new_drawlyr = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_smark()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the smark of the activity object
 *
 */

static void 
change_smark(Widget button, XtPointer option, XtPointer any_data)
{
    new_smark = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_emark()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the emark of the activity object
 *
 */

static void 
change_emark(Widget button, XtPointer option, XtPointer any_data)
{
    new_emark = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_font()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the font of the activity object
 *
 */

static void 
change_font(Widget button, XtPointer option, XtPointer any_data)
{
    new_font = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_point()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:	
 *	changes the font point size of the activity object
 *
 */

static void 
change_point(Widget button, XtPointer option, XtPointer any_data)
{
    new_point = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_pline()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the pline object slip value for activities
 *
 */

static void 
change_pline(Widget button, XtPointer option, XtPointer any_data)
{
    pline_flag = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *	dsp_act()
 *
 * INPUTS:
 *	i  (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION: 
 *	displays the object
 */

static void 
dsp_act(int i)
{
    struct act *actptr;       		/* local pointer */
    int mid, xmid, stat;              	/* midpoint for fill pattern */
    int xs, xe, xu, xd, xbs, xbe;       /* x-pos of start/end times */
    int j, x, y2;       		/* temporary variables */
    int diff, done_days;        	/* difference in dates */
    enum tog s_flag, e_flag;   	 	/* flag to draw symbols if off page */
    char lbuf[6];               	/* print start hour buffer */
    char rbuf[6];               	/* print end hour buffer */
    int txwidth, txheight, width;  	/* text height and width */
    enum tog mask;              	/* mask for whiting out background */
    int utc_date;			/* temp day of year of date */
    int syear, sday, smonth;		/* start date values */
    int eyear, eday, emonth;		/* end date values */
    float up_m, dn_m;			/* slipe of up/down ramps */
    int bar_y, bar_height;		/* bar coordinates */
    int height, ht;			/* height of bar and ramp */
    int center_y;			/* center coordinate */
    int text_x, text_y;			/* text coordinate */
    int idtext_x, idtext_y;		/* id text coordinate */
    XRectangle *(*line_rect)[];		/* line rectangle */
    int ln_pos;				/* line position of object */
    int fill_gap;			/* minimum y_gap for fill_pattern */

    actptr = objary[i].z.actptr;
    xs = utc_to_x(actptr->strtdate + UTC_ONE_DAY/2);
    xe = utc_to_x(actptr->endate + UTC_ONE_DAY/2);
    s_flag = TOG_ON;
    e_flag = TOG_ON;

    if (xs == XVAL_EARLY) {
	s_flag = TOG_OFF;
	xs = x_time_offset;
    }
    if (xe == XVAL_LATE) {
	e_flag = TOG_OFF;
	xe = x_right_margin;
    }
    /* add one for correct positioning */
    xs++;
    xe++;
    if (xs > xe) {	/* start position should precede end position */
	xe = xs + 1;
    }

    /* calculate baseline and ramp positions based on dates */
    xbs = utc_to_x(actptr->b_strtdate + UTC_ONE_DAY/2);
    xbe = utc_to_x(actptr->b_endate + UTC_ONE_DAY/2);
    xu = utc_to_x(actptr->update + UTC_ONE_DAY/2);
    xd = utc_to_x(actptr->dwndate + UTC_ONE_DAY/2);
    /* percent done fill based on percent done date */
    mid = utc_to_x(actptr->pctdate + UTC_ONE_DAY/2);
    stat = utc_to_x(st_date);

    if (xbs == XVAL_EARLY) {
	xbs = x_time_offset;
    } else if (xbs == XVAL_LATE) {
	xbs = x_right_margin;
    }
    if (xbe == XVAL_LATE) {
	xbe = x_right_margin;
    } else if (xbe == XVAL_EARLY) {
	xbe = x_time_offset;
    }
    xbs++;
    xbe++;
    if (xbs > xbe) {
	xbe = xbs;
	actptr->b_endate = actptr->b_strtdate;
    }
    if (xu == XVAL_EARLY) {
	xu = x_time_offset;
    } else if (xu == XVAL_LATE) {
	xu = x_right_margin;
    }
    if (xd == XVAL_EARLY) {
	xd = x_time_offset;
    } else if (xd == XVAL_LATE) {
	xu = x_right_margin;
    }
    xu++;
    xd++;
    if (xu > xd) {
	xu = xd;
    }
    height = y_gap/2 - 1;
    ht = height;
    if (xu == xd) {
	xu = xs;
	xd = xe;
	/* no ramps means start and ramp up dates should be the same */
	actptr->update = actptr->strtdate;
	actptr->dwndate = actptr->endate;
    } else if ((xu < xs) || ((xu >= xe) && (xu < x_right_margin))) {
	xu = xs;
	actptr->update = actptr->strtdate;
    }
    if ((xd > xe) || ((xd <= xs) && (xd > x_time_offset))) {
	xd = xe;
	actptr->dwndate = actptr->endate;
    }
    if (auto_areset == TOG_ON) {
	/* find difference between status and start dates */
	/* NOTE: % done date will be reset to status date */
	
	if (st_date < actptr->strtdate) {
	    done_days = 0;
	} else {
	    done_days = (st_date - actptr->strtdate)/UTC_ONE_DAY;
	}
	diff = (actptr->endate - actptr->strtdate)/UTC_ONE_DAY;
	if (done_days <= 0) {
	    /*
	     * status date prior to start date
	     */
	    mid = xs;	
	    actptr->done_pct = 0;
	    actptr->pctdate = actptr->strtdate;
	    /*
             * begin symbol should be empty
             */
            if ((actptr->strtsym == 1) || (actptr->strtsym == 3) ||
                (actptr->strtsym == 5) || (actptr->strtsym == 11) ||
                (actptr->strtsym == 13)) {
                actptr->strtsym -= 1;
            }
            /*
             * end symbol should be empty
             */
            if ((actptr->endsym == 1) || (actptr->endsym == 3) ||
                (actptr->endsym == 5) || (actptr->endsym == 11) ||
                (actptr->endsym == 13)) {
                actptr->endsym -= 1;
            }
	} else if (done_days >= diff) {
	    /*
	     * status date past endate
	     */
	    mid = xe;
	    actptr->done_pct = 100;
	    actptr->pctdate = actptr->endate;
            /*
             * begin symbol should be filled
             */
            if ((actptr->strtsym == 0) || (actptr->strtsym == 2) ||
                (actptr->strtsym == 4) || (actptr->strtsym == 10)) {
                actptr->strtsym += 1;
            }
            /*
             * end symbol should be filled
             */
            if ((actptr->endsym == 0) || (actptr->endsym == 2) ||
                (actptr->endsym == 4) || (actptr->endsym == 10)) {
                actptr->endsym += 1;
            }
        } else if (diff == 0) {
            mid = xs;
            actptr->done_pct = 0;
            actptr->pctdate = actptr->strtdate;
            /*
             * begin symbol should be empty
             */
            if ((actptr->strtsym == 1) || (actptr->strtsym == 3) ||
                (actptr->strtsym == 5) || (actptr->strtsym == 11) ||
                (actptr->strtsym == 13)) {
                actptr->strtsym -= 1;
            }
            /*
             * end symbol should be empty
             */
            if ((actptr->endsym == 1) || (actptr->endsym == 3) ||
                (actptr->endsym == 5) || (actptr->endsym == 11) ||
                (actptr->endsym == 13)) {
                actptr->endsym -= 1;
            }
	} else {
	    /* 
	     * status date between start and end dates
 	     */
	    actptr->done_pct = (done_days * 100) / diff;
	    actptr->pctdate = st_date;
	    mid = stat;
	    /*
             * begin symbol should be filled
             */
            if ((actptr->strtsym == 0) || (actptr->strtsym == 2) ||
                (actptr->strtsym == 4) || (actptr->strtsym == 10)) {
                actptr->strtsym += 1;
            }
            /*
             * end symbol should be empty
             */
            if ((actptr->endsym == 1) || (actptr->endsym == 3) ||
                (actptr->endsym == 5) || (actptr->endsym == 11) ||
                (actptr->endsym == 13)) {
                actptr->endsym -= 1;
            }
	}
    }
    if (mid == XVAL_EARLY) {	
        mid = x_time_offset;
    } else if (mid == XVAL_LATE) {
	mid = x_right_margin;
    }
    if (mid < xs) {
    	    /* possible error condition */
        mid = xs;
        actptr->pctdate = actptr->strtdate;
	actptr->done_pct = 0;
    } else if (mid > xe) {
	mid = xe;
	actptr->pctdate = actptr->endate;
	actptr->done_pct = 100;
    }
    if (((actptr->line >= page_begin) && (actptr->line <= page_end)) &&
	((actptr->strtdate <= objary[0].z.chtptr->end_date) &&
	(actptr->endate >= objary[0].z.chtptr->start_date))) { 
	width = gr_strwidth(actptr->text, actptr->font|actptr->point);
        txheight = gr_txheight(actptr->font|actptr->point);
	/* 
	 * y coord of rectangle was moved up for TX_ABOVE, so the center
	 * must be adjusted
 	 */
  	ln_pos = hln_objary[actptr->line];
	line_rect = getMoveRect(Hobjary[ln_pos].rlist);
        center_y = (*line_rect)[0]->y + 1;
	bar_y = center_y + y_gap/4 + 1;
	bar_height = (y_gap - 1)/2 - 2;
	gr_rect_clear(xs - 2, center_y, xe - xs + 2, y_gap - 2);
        gr_set_color(color_name[actptr->color], color_gscale[actptr->color]);
	if ((xu == xs) && (xd == xe)) {
	    gr_rectangle(xs - 1, bar_y - 1, xe - xs, bar_height + 2);
	}

	if (xbs < xbe) {		/* graph outer rectangle for activity */
	    gr_rect_clear(xbs - 2, bar_y + bar_height - 1 + y_gap/2,
		 xbe - xbs + 2, (bar_height + 6) / 2);
            gr_set_color(color_name[actptr->color], 
		color_gscale[actptr->color]);
	    gr_rectangle(xbs - 1, bar_y + bar_height + y_gap/2, xbe - xbs,
		 (bar_height + 2)/2);
	}
        gr_set_color(color_name[actptr->color], color_gscale[actptr->color]);
	up_m = 1;
	dn_m = 1;

        /* set fill_gap so that spacing of fill patterns is visible */
        if (y_gap < 6) {
            fill_gap = 6;
        } else {
            fill_gap = y_gap;
        }

	switch(actptr->fill_pattern) {
	case OPEN:
	    break;
	case SOLID:
	    /*
	     * find slope of the lines for up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    /*
	     * find height for drawing vertical line
	     */
	    if (mid < xu) {
		ht = up_m * (mid - xs);
	    } else if (mid > xd) {
		ht = dn_m * (xe - mid);
	    }
	    for (j = 0; j <= bar_height; j++) {
		if ((xs < xu) && (up_m > 0)) {
		    x = xs + (height - j) / up_m;
		} else {
		    x = xs + 1;
		}
		xmid = mid;
		if ((mid > xd) && (dn_m > 0)) {
		    xmid = xe - (height - j) / dn_m;
		}
		if (x < xmid) {
		    if (xmid <= mid) {
		    	gr_line(x, bar_y + j, xmid, bar_y + j);
		    } else {
		        gr_line(x, bar_y + j, mid, bar_y + j);
		    }
		}
	    }
	    break;
	case LEFT_DIAG:
	    /*
	     * find slope of the lines for up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    ht = 0;
  	    y2 = bar_y + bar_height;
            for (j = xs; j <= mid; j += fill_gap/2) {
	        /*
	         * find starting height
	         */
	        if (j < xu) {
		    ht = up_m * (j - xs);
	        } else if (j > xd) {
		    ht = dn_m * (xe - j);
	        }
 	        if (j + fill_gap/2 <= mid) {
		    if ((j + fill_gap/2 < xu) || (j + fill_gap/2 > xd)) {
			gr_line(j, y2 - ht, j + fill_gap/2, y2);
		    } else {
	                gr_line(j, bar_y, j + fill_gap/2, y2);
		    }
	        }
	    }
	    break;
        case RIGHT_DIAG:
	    /*
	     * find slope of the lines for up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    ht = 0;
  	    y2 = bar_y + bar_height;
            for (j = xs; j <= mid; j += fill_gap/2) {
	        /*
	         * find starting height
	         */
	        if (j < xu) {
		    ht = up_m * (j - xs);
	        } else if (j > xd) {
		    ht = dn_m * (xe - j);
	        }
 	        if (j + fill_gap/2 <= mid) {
		    if ((j + fill_gap/2 < xu) || (j + fill_gap/2 > xd)) {
			gr_line(j + fill_gap/2, y2 - ht, j, y2);
		    } else {
	                gr_line(j + fill_gap/2, bar_y, j, y2);
		    }
	        }
	    }
	    break;
	case HORIZONTAL:
	    /*
	     * find slope of up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    /*
	     * find height for drawing vertical line at mid
	     */
	    if (mid < xu) {
		ht = up_m * (mid - xs);
	    } else if (mid > xd) {
		ht = dn_m * (xe - mid);
	    }
	    for (j = 3; j <= bar_height; j += 3) {
		if ((xs < xu) && (up_m > 0)) {
		    x = xs + (height - j) / up_m;
		} else {
		    x = xs + 1;
		}
		xmid = mid;
		if ((mid > xd) && (dn_m > 0)) {
		    xmid = xe - (height - j) / dn_m;
		}
		if (x < xmid) {
		    if (xmid <= mid) {
		        gr_line(x, bar_y + j, xmid, bar_y + j);
		    } else {
		        gr_line(x, bar_y + j, mid, bar_y + j);
		    }
		}
	    }
	    break;
	case VERTICAL:
	    /*
	     * find slope of the lines for up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    ht = 0;
	    y2 = bar_y + bar_height;
	    for (j = xs; j < mid; j +=5) {
	        /*
	         * find starting height
	         */
	        if (j < xu) {
		    ht = up_m * (j - xs);
	        } else if (j > xd) {
		    ht = dn_m * (xe - j);
	        }
		if ((j < xu) || (j > xd)) {
		    gr_line(j, y2 - ht, j, y2);
		} else {
	            gr_line(j, bar_y, j, y2);
		}
	    }
	    break;
	case CROS_HATCH:
	    /*
	     * find slope of the lines for up and down ramps
	     */
	    if (xs < xu) {
		up_m = (float)(height) / (float)(xu - xs);
	    }
	    if (xe > xd) {
		dn_m = (float)(height) / (float)(xe - xd);
	    }
	    ht = 0;
  	    y2 = bar_y + bar_height;
            for (j = xs; j <= mid; j += fill_gap/2) {
	        /*
	         * find starting height
	         */
	        if (j < xu) {
		    ht = up_m * (j - xs);
	        } else if (j > xd) {
		    ht = dn_m * (xe - j);
	        }
 	        if (j + fill_gap/2 <= mid) {
		    if ((j + fill_gap/2 < xu) || (j + fill_gap/2 > xd)) {
			gr_line(j, y2 - ht, j + fill_gap/2, y2);
			gr_line(j + fill_gap/2, y2 - ht, j, y2);
	 	    } else {
	                gr_line(j, bar_y, j + fill_gap/2, y2);
	                gr_line(j + fill_gap/2, bar_y, j, y2);
		    }
	        }
	    }
	    break;
        }
	/*
	 * make sure border lines are drawn
	 */
	if ((xs != xu) || (xd != xe)) {
	    gr_line(xu, bar_y, xd, bar_y);
	    gr_line(xs, bar_y + bar_height, xe, bar_y + bar_height);
	}
	if (xs != xu) {
	    gr_line(xs, bar_y + bar_height, xu, bar_y);
	}
	if (xe != xd) {
	    gr_line(xd, bar_y, xe, bar_y + bar_height);
	}
        if ((mid > xs) && (mid <= xe)) {
            gr_line(mid, bar_y + bar_height - ht + 1, mid,bar_y + bar_height);
        }
	/*
	 * display markers
	 */
        if ((s_flag == TOG_ON) && (actptr->strtsym >= 0)) {
            dsp_marker(actptr->strtsym, xs - (y_gap - 1)/2, center_y + 3,
 	        y_gap - 5, 0);
            xs -= 15;
        }
        if ((e_flag == TOG_ON) && (actptr->endsym >= 0)) {
            dsp_marker(actptr->endsym, xe - (y_gap - 1)/2 + 1, center_y + 3,
   	        y_gap - 5, 0);
	    xe += 6;
        }

	/*
	 * display date if display toggle is on
	 */	
        txwidth = gr_txwidth(actptr->font|actptr->point);
        if (actptr->disp == TDS_DOY) {
    	    utc_date = get_doy(actptr->strtdate);
	    (void)sprintf(lbuf, "%03d", utc_date);
	    utc_date = get_doy(actptr->endate);
	    (void)sprintf(rbuf, "%03d", utc_date);
        } else if (actptr->disp == TDS_DATE) {
            get_mdy(&smonth, &sday, &syear, actptr->strtdate);
            get_mdy(&emonth, &eday, &eyear, actptr->endate);
 	    (void)sprintf(lbuf, "%d/%d", smonth, sday);
	    (void)sprintf(rbuf, "%d/%d", emonth, eday);
        } else {
            (void)sprintf(lbuf, "%s", "");
	    (void)sprintf(rbuf, "%s", "");
        }
	/*
	 * find positioning of text
	 */
	line_rect = getMoveRect(Hobjary[ln_pos].rlist);
        switch (actptr->hpos) {
        case GR_LEFT:
	    text_x = xs - y_gap/2 - width - 1;
	    if (!strcmp(lbuf, "")) {
		text_x += 3;
	    }
	    if (actptr->disp != TDS_NONE) {
		text_x -= y_gap;
	    }
    	    break;
        case GR_RIGHT:
	    text_x = xe + y_gap/2 + 1;
	    if (!strcmp(rbuf, "")) {
		text_x -= 2;
	    }
	    if (actptr->disp != TDS_NONE) {
		text_x += y_gap;
	    }
    	    break;
    	default:
    	    text_x = xs - width/2 + (xe - xs)/2;
 	    break;
        }
        switch (actptr->vpos) {
        case TX_ABOVE:
            text_y = (*line_rect)[0]->y - 1;
            break;
        case TX_BELOW:
            text_y = (*line_rect)[0]->y + y_gap + txheight + 3;
            break;
        default:
            text_y = center_y + y_gap/2 + txheight/2;
            break;
        }
        if (objary[i].layer == 0) {
            mask = TOG_OFF;
        } else {
            mask = TOG_ON;
        }

 	if (actptr->idtog == TOG_ON) {
            width = gr_strwidth(actptr->idtext, actptr->font|actptr->point);
            switch (actptr->idhpos) {
            case GR_LEFT:
                idtext_x = xs - y_gap/2 - width - 1;
	        if (actptr->disp != TDS_NONE) {
		    idtext_x -= y_gap;
	        }
                break;
            case GR_RIGHT:
                idtext_x = xe + y_gap/2 + 1;
		if (actptr->disp != TDS_NONE) {
		    idtext_x += y_gap;
		}
                break;
            default:
                idtext_x = xs - width/2 + (xe - xs)/2;
                break;
            }
            switch (actptr->idvpos) {
            case TX_ABOVE:
                idtext_y = (*line_rect)[0]->y - 1;
                break;
            case TX_BELOW:
                idtext_y = (*line_rect)[0]->y + y_gap + txheight + 3;
                break;
            default:
                idtext_y = center_y + y_gap/2 + txheight/2;
                break;
            }
	}

        gr_text(xs - y_gap, center_y + y_gap/4 + txheight,
	    lbuf, GR_LEFT, (actptr->font|actptr->point), (int)mask);
        gr_text(xe + y_gap/2 + 1, center_y + y_gap/4 + txheight,rbuf,GR_LEFT, 
            (actptr->font|actptr->point), (int)mask);
        gr_text(text_x, text_y, actptr->text, GR_LEFT,
	    (actptr->font|actptr->point), (int)mask);
	if (actptr->idtog == TOG_ON) {
            gr_text(idtext_x, idtext_y, actptr->idtext, GR_LEFT,
	        (actptr->font|actptr->point), (int)mask);
	}
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	loc_act()
 *
 * INPUTS:
 *	i  (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION: 
 *	This module locates the position of activity object i
 */

static void 
loc_act(int i, int dir)
{
    struct act *actptr;			/* local pointer */
    XRectangle r1;			/* rectangles for object */
    int xs, xe, xbs, xbe;		/* x coordinates */
    int ln_pos;				/* line position */
    XRectangle *(*line_rect)[];		/* horizontal line rectangle */
    int width, height;			/* width and height of text */
    int txwidth;			/* text width of one character */
    int utc_date;			/* day of year of date */
    char lbuf[6], rbuf[6];		/* temp buffer strings */
    int smonth, sday, syear;		/* start date values */
    int emonth, eday, eyear;		/* end date values */
    int dxltime, dxrtime;		/* length of date buffers */

    actptr = objary[i].z.actptr;
    if (((actptr->line < page_begin) || (actptr->line > page_end)) ||
	((actptr->strtdate < objary[0].z.chtptr->start_date) &&
	(actptr->endate < objary[0].z.chtptr->start_date)) ||
	((actptr->strtdate > objary[0].z.chtptr->end_date) && 
	(actptr->endate > objary[0].z.chtptr->end_date))) { 
    	    setRectList(objary[i].rlist, 0);
	    return;
    }
    xs = utc_to_x(actptr->strtdate + UTC_ONE_DAY/2);
    xe = utc_to_x(actptr->endate + UTC_ONE_DAY/2);
    if ((xe == XVAL_EARLY) || (xs == XVAL_LATE)) {
        setRectList(objary[i].rlist, 0);
	return;
    }
    if (xs == XVAL_EARLY) {
        xs = x_time_offset;
    }
    if (xe == XVAL_LATE) {
        xe = x_right_margin;
    }
    /* add one for correct centering */
    xs++;
    xe++;
    if (xs > xe) {
        xe = xs + 2;
    }
    /* calculate baseline positions to fix all possible error conditions */
    xbs = utc_to_x(actptr->b_strtdate + UTC_ONE_DAY/2);
    xbe = utc_to_x(actptr->b_endate + UTC_ONE_DAY/2);
    if (xbs == XVAL_EARLY) {
        xbs = x_time_offset;
    }
    if (xbs == XVAL_LATE) {
        xbs = x_right_margin;
    }
    if (xbe == XVAL_EARLY) {
        xbe = x_time_offset;
    }
    if (xbe == XVAL_LATE) {
        xbe = x_right_margin;
    }
    xbs++;
    xbe++;
    if (xbs > xbe) {
	xbe = xbs;
	actptr->b_endate = actptr->b_strtdate;
    }
    ln_pos = hln_objary[actptr->line];
    line_rect = getMoveRect(Hobjary[ln_pos].rlist);
    width = gr_strwidth(actptr->text, actptr->font|actptr->point);
    height = gr_txheight(actptr->font|actptr->point);
    txwidth = gr_txwidth(actptr->font|actptr->point);
    /* 
     * if display date is on find text width 
     */
    if (actptr->disp == TDS_DOY) {
        utc_date = get_doy(actptr->strtdate);
        (void)sprintf(lbuf, "%03d", utc_date);
        utc_date = get_doy(actptr->endate);
        (void)sprintf(rbuf, "%03d", utc_date);
	dxltime = (strlen(lbuf) + 1) * txwidth;
	dxrtime = (strlen(rbuf) + 1) * txwidth;
    } else if (actptr->disp == TDS_DATE) {
        get_mdy(&smonth, &sday, &syear, actptr->strtdate);
        get_mdy(&emonth, &eday, &eyear, actptr->endate);
        (void)sprintf(lbuf, "%d/%d", smonth, sday);
        (void)sprintf(rbuf, "%d/%d", emonth, eday);
	dxltime = (strlen(lbuf) + 1) * txwidth;
        dxrtime = (strlen(rbuf) + 1) * txwidth;
    } else {
        (void)sprintf(lbuf, "%s", "");
        (void)sprintf(rbuf, "%s", "");
	dxltime = 0;
        dxrtime = 0;
    }
	
    /*
     * rectangle for object 
     */

    if (gr_strwidth(actptr->idtext, actptr->font|actptr->point) > width) {
	width = gr_strwidth(actptr->idtext, actptr->font|actptr->point);
    }
    if (((actptr->hpos == GR_LEFT) && (strcmp(actptr->text, "") != 0)) || 
	((actptr->idhpos == GR_LEFT) && (strcmp(actptr->idtext, "") != 0))) {
	r1.x = xs - y_gap - dxltime - width - 7;
    } else {
	r1.x = xs - y_gap - dxltime - 1;
    }
    if (actptr->disp != TDS_NONE) {
	r1.x -= y_gap + 1;
    }

    if (xbs < r1.x) {
	/* 
	 * baseline can start before activity
	 */
	r1.x = xbs - 1;
    }
    r1.y = (*line_rect)[0]->y + 1;
    if (((actptr->hpos == GR_RIGHT) && (strcmp(actptr->text, "") != 0)) || 
	((actptr->idhpos == GR_RIGHT) && (strcmp(actptr->idtext, "") != 0))) {
    	r1.width = xe + y_gap + width + dxrtime + 5 - r1.x;
    } else {
	r1.width = xe + y_gap + dxrtime + 2 - r1.x;
    }
    if (actptr->disp != TDS_NONE) {
	r1.width += y_gap;
    }
    if (xbe > xe) {
	/* 
	 * baseline can end after activity
	 */
	r1.width = (xbe + 1 - r1.x);
    }
    if (xbs == xbe) {
	/* 
	 * add height for baseline
	 */
	r1.height = y_gap + 1; 
    } else {
	r1.height = y_gap * 2 + 2;
    }
    /*
     * fix offsets for text position
     */
    if (((actptr->vpos == TX_ABOVE) && (strcmp(actptr->text, "") != 0)) || 
	((actptr->idvpos == TX_ABOVE) && (strcmp(actptr->idtext, "") != 0))) {
	r1.y = r1.y - height - 1;
	r1.height = r1.height + height + 1;
    }
    if (((actptr->vpos == TX_BELOW) && (strcmp(actptr->text, "") != 0)) || 
	((actptr->idvpos == TX_BELOW) && (strcmp(actptr->idtext, "") != 0))) {
	r1.height = r1.height + height + 1;
    }

    setRectList(objary[i].rlist, 1, &r1, RL_PRIMARY);
}

/***********************************************************************
 *
 * FUNCTION:
 *	edit_act()
 *
 * INPUTS:
 *	i, new	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	pops up a edit box for the activity i
 */

static void 
edt_act(int i, int new)
{
    char buf[4];

    if (act_dialog == NULL) {
	create_dialog();
    }

    (*(objary[i].opsptr->cpy))(&objtmp, &objary[i]);
    loa = (objtmp.z.actptr->endate - objtmp.z.actptr->strtdate) / UTC_ONE_DAY;
    new_point = objtmp.z.actptr->point;
    new_font = objtmp.z.actptr->font;
    new_hpos = objtmp.z.actptr->hpos;
    new_vpos = objtmp.z.actptr->vpos;
    new_smark = objtmp.z.actptr->strtsym;
    new_emark = objtmp.z.actptr->endsym;
    new_fillpatt = objtmp.z.actptr->fill_pattern;
    new_disp = objtmp.z.actptr->disp;
    new_drawlyr = objtmp.layer;
    new_color = objtmp.z.actptr->color;
    new_idhpos = objtmp.z.actptr->idhpos;
    new_idvpos = objtmp.z.actptr->idvpos;
    new_idtog = objtmp.z.actptr->idtog;
    new_loa = 0;
    pline_flag = FALSE;
    change = DIALOG_NO_CHANGE;
    if (new) {
	(*(objary[i].opsptr->rem))(i, OBJECT);
	i = -1;
    }

    DialogDateSet(sdate, objtmp.z.actptr->strtdate);
    DialogDateSet(edate, objtmp.z.actptr->endate);
    DialogDateSet(rudate, objtmp.z.actptr->update);
    DialogDateSet(rddate, objtmp.z.actptr->dwndate);
    DialogDateSet(bsdate, objtmp.z.actptr->b_strtdate);
    DialogDateSet(bedate, objtmp.z.actptr->b_endate);
    DialogDateSet(pctdate, objtmp.z.actptr->pctdate);
    sprintf(buf, "%d", objtmp.z.actptr->done_pct);
    DialogTextSet(pct, buf);
    sprintf(buf, "%d", objtmp.z.actptr->line);
    DialogTextSet(linew, buf);
    DialogOptionSet(lenmenuw, 0);
    DialogOptionSet(fontw, (int)new_font);
    DialogOptionSet(pointw, (int)new_point);
    DialogOptionSet(hposw, (int)new_hpos);
    DialogOptionSet(vposw, (int)new_vpos);
    DialogOptionSet(smark, (int)new_smark);
    DialogOptionSet(emark, (int)new_emark);
    DialogOptionSet(dispw, (int)new_disp);
    DialogOptionSet(fillw, (int)new_fillpatt);
    DialogOptionSet(drawlyrw, (int)new_drawlyr);
    DialogOptionSet(colorw, (int)new_color);
    DialogOptionSet(idhposw, (int)new_idhpos);
    DialogOptionSet(idvposw, (int)new_idvpos);
    DialogOptionSet(dspidw, (int)new_idtog);

    if ((objtmp.precptr == NULL) || (new)) {
        XtSetSensitive(plinew->parent, FALSE);
    } else {
        XtSetSensitive(plinew->parent, TRUE);
    }

    DialogOptionSet(plinew, (int)pline_flag);
    DialogTextSet(textw, objtmp.z.actptr->text);
    DialogTextSet(idw, objtmp.z.actptr->idtext);
    sprintf(buf, "%d", loa);
    DialogTextSet(lengthw, buf);
    EditObject(i, act_dialog);
}

/***********************************************************************
 *
 * FUNCTION:
 *	rem_act()
 *
 * INPUTS:
 *	i  (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module removes activity object i from the data base
 */

static void 
rem_act(int i, int dir)
{
    struct obj *objptr;				/* temp object pointer */
    int nip;					/* number of indices */
    int (*ip)[];				/* index of pline array */
    int j;					/* temp loop index */
    int prec = 0;

    switch (i) {
    case BACK:
	objptr = &objbck;
 	break;
    case TEMP:
	objptr = &objtmp;
	prec = 1;
	break;
    default: 
	objptr = &(objary[i]);
	break;
    }

    if (!prec) {
        if (objptr->precptr != NULL) {
            if (objptr->precptr->nelems > 0) {
                nip = objptr->precptr->nelems;
                ip = (int(*)[])XtMalloc((Cardinal)(sizeof(int) * nip));
	        for (j = 0; j < nip; j++) {
                    (*ip)[j] = elemof_dynarray(objptr->precptr, j);
	        }
                for (j = 0; j < nip; j++) {
                    rem_pline((*ip)[j], OBJECT);
                }
                XtFree((char *)ip);
                delete_dynarray(objptr->precptr);
            }
        }
    }
    freeRectList(objptr->rlist);
    XtFree(objptr->z.actptr->text);
    XtFree((char *)objptr->z.actptr);
    rem_object(objptr);
}

/***********************************************************************
 *
 * FUNCTION:   
 *	lim_act()
 *
 * INPUTS:
 *	i  		(int)
 *	x1, y1, x2, y2	(int *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module limits the range of motion of the activity object i
 */

static void 
lim_act(int i, int *x1, int *y1, int *x2, int *y2, int dir)
{
    XRectangle *(*r)[];				/* rectangle */

    r = getMoveRect(objary[i].rlist);

    *x1 = (*r)[0]->x;
    *y1 = y_act_bottom;
    *x2 = (*r)[0]->x;
    *y2 = y_lines_end - y_gap;
}

/***********************************************************************
 *
 * FUNCTION:
 *	mov_act()
 *
 * INPUTS:
 *	i, x, y  	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module moves the activity object when the middle mouse
 *	button is pressed
 */

static void 
mov_act(int i, int x, int y, int dir)
{
    XRectangle *(*r)[];				/* rectangle */
    int txheight;				/* height of font */
    int ycoord;					/* temp y coordinate */
    struct act *actptr;				/* pointer to object */

    actptr = objary[i].z.actptr;
    r = getMoveRect(objary[i].rlist);
    txheight = gr_txheight(actptr->font|actptr->point);
    if (actptr->vpos != TX_ABOVE) {
	ycoord = (*r)[0]->y;
    } else {
	/* 
	 * (*r)[0]->y has changed for TX_ABOVE, so must adjust it back 
	 */
        txheight = gr_txheight(actptr->font|actptr->point);
	ycoord = (*r)[0]->y + 1 + txheight;
    }
    actptr->line =((ycoord + y + 1 - y_act_bottom)/y_gap) + page_begin;
}

/***********************************************************************
 *
 * FUNCTION:
 *	cpy_act()
 *
 * INPUTS:
 *	to, from	(struct obj *) 
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module copies activity from to activity to
 */

static void 
cpy_act(struct obj *to, struct obj *from)
{
    if (from->type == OBJ_NUL) {
	return;
    }
    to->z.actptr = (struct act *)XtMalloc((Cardinal)sizeof(struct act));
    to->z.actptr->strtdate = from->z.actptr->strtdate;
    to->z.actptr->endate = from->z.actptr->endate;
    to->z.actptr->update = from->z.actptr->update;
    to->z.actptr->dwndate = from->z.actptr->dwndate;
    to->z.actptr->line = from->z.actptr->line;
    to->z.actptr->strtsym = from->z.actptr->strtsym;
    to->z.actptr->endsym = from->z.actptr->endsym;
    to->z.actptr->pctdate = from->z.actptr->pctdate;
    to->z.actptr->done_pct = from->z.actptr->done_pct;
    to->z.actptr->b_strtdate = from->z.actptr->b_strtdate;
    to->z.actptr->b_endate = from->z.actptr->b_endate;
    to->z.actptr->fill_pattern = from->z.actptr->fill_pattern;
    to->z.actptr->disp = from->z.actptr->disp;
    to->z.actptr->hpos = from->z.actptr->hpos;
    to->z.actptr->vpos = from->z.actptr->vpos;
    to->z.actptr->font = from->z.actptr->font;
    to->z.actptr->point = from->z.actptr->point;
    to->z.actptr->color = from->z.actptr->color;
    to->z.actptr->idtog = from->z.actptr->idtog;
    to->z.actptr->idhpos = from->z.actptr->idhpos;
    to->z.actptr->idvpos = from->z.actptr->idvpos;
    to->z.actptr->text = XtNewString(from->z.actptr->text);
    to->z.actptr->idtext = XtNewString(from->z.actptr->idtext);
    to->type = OBJ_ACT;
    to->opsptr = &act_ops;
    to->layer = from->layer;
    to->precptr = from->precptr;
    to->rlist = copyRectList(from->rlist);
}

/***********************************************************************
 *
 * FUNCTION:
 *	msg_act()
 *
 * INPUTS:
 *	i  (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	displays the activity message for object i
 */

static void 
msg_act(int i, int dir)
{
    char buf[64];				/* temp buffer */
    int mo, da, yr, mo2, da2, yr2;		/* temp date values */

    get_mdy(&mo, &da, &yr, objary[i].z.actptr->strtdate);
    get_mdy(&mo2, &da2, &yr2, objary[i].z.actptr->endate);
    (void)sprintf(buf, "SActivity: %d/%d/%d - %d/%d/%d, %d Percent Done", mo, 
	da, yr, mo2, da2, yr2, objary[i].z.actptr->done_pct);
    Message(buf);
}

/***********************************************************************
 *
 * FUNCTION:
 *	sav_act()
 *
 * INPUTS:
 *	i  	(int)
 *	fp	(FILE *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	saves the activity object i to fp
 */

static void 
sav_act(int i, FILE *fp, int dir)
{ 
    struct act *actptr;			/*temp object pointer */
    char buf[2056];				/* temp buffer */

    actptr = objary[i].z.actptr;
    buf[0] = 'O';
    buf[1] = ' ';
    (void)record_print(buf+2, "ttttdddtdttddddddddqqddd", actptr->strtdate, 
	actptr->endate, actptr->update, actptr->dwndate, actptr->line,
	actptr->strtsym, actptr->endsym, actptr->pctdate, actptr->done_pct,
	actptr->b_strtdate, actptr->b_endate, actptr->fill_pattern,
	objary[i].layer,actptr->disp, actptr->hpos, actptr->vpos, actptr->font,
	actptr->point, actptr->color, actptr->text, actptr->idtext,
	actptr->idtog, actptr->idhpos, actptr->idvpos);
    fputs(buf, fp);
}

/***********************************************************************
 *
 * FUNCTION:
 *      load_act()
 *
 * INPUTS:
 *      buf     (char *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      loads act object record
 */

static int 
load_act(char *buf)
{
    utc_val st_date, e_date;          /* start and end date */
    utc_val up_date, dn_date;         /* up and down ramp dates */
    int line;                         /* index to hline object */
    int strtsym, endsym;              /* pointer to starting symbol type */
    utc_val pd_date;                  /* percent completed date */
    int done_pct;                     /* percent done */
    utc_val bs_date, be_date;         /* baseline start and end date */
    enum pattern fill_pattern;        /* fill pattern for bar */
    int layer;                        /* drawing layer */
    enum tds disp;                    /* display flag */
    int hpos,vpos;                    /* text position */
    int font;                         /* text font */
    int point;                        /* point for text font */
    char text[64];                    /* comment text */
    int color;			      /* color of act */
    int idhpos, idvpos;               /* id text position */
    char idtext[64];		      /* id text */
    int idtog;			      /* id display toggle */
    int i;			      /* temp index */

    if (record_scan(buf + 1, "ttttdddtdttddddddddqqddd", &st_date, &e_date,
	&up_date, &dn_date, &line, &strtsym, &endsym, &pd_date, &done_pct,
	&bs_date, &be_date, &fill_pattern, &layer, &disp, &hpos, &vpos,
	&font, &point, &color, text, idtext, &idtog, &idhpos, &idvpos) == 24)  {
	if ((line < 0) || (line > num_pages * pg_lines)) {
	    Warning("Illegal Activity line %d", line);
	} else if ((strtsym < 0) || (strtsym > 16)) {
	    Warning("Illegal Activity start symbol %d", strtsym);
	} else if ((endsym < 0) || (endsym > 16)) {
	    Warning("Illegal Activity end symbol %d", endsym);
	} else if ((done_pct < 0) || (done_pct > 100)) {
	    Warning("Illegal Activity percent complete %d", done_pct);
	} else if (((int)fill_pattern < OPEN) || 
	    ((int)fill_pattern > CROS_HATCH)) {
	    Warning("Illegal Activity fill pattern %d", fill_pattern);
	} else if ((layer < 0) || (layer > 3)) {
	    Warning("Illegal Activity layer %d", layer);
	} else if (((int)disp < TDS_NONE) || ((int)disp > TDS_DATE)) {
	    Warning("Illegal Activity display %d", disp);
	} else if ((hpos < 0) || (hpos > 2)) {
	    Warning("Illegal Activity horizontal position %d", hpos);
	} else if ((vpos < 0) || (vpos > 2)) {
	    Warning("Illegal Activity vertical position %d", vpos);
	} else if ((font != GR_COURIER) && (font != GR_COURIER_BOLD) &&
		(font != GR_HELVETICA) && (font != GR_HELVETICA_BOLD) &&
		(font != GR_TIMES) && (font != GR_TIMES_BOLD)) {
	    Warning("Illegal Activity font %d", font);
	} else if ((point != 8) && (point != 10) && (point != 12) && 
	    (point != 14) && (point != 18) && (point != 24)) {
	    Warning("Illegal Activity point %d", point);
	} else if ((color < 0) || (color > ncolor)) {
	    Warning("Illegal Activity color %d", color);
	} else if ((idhpos < 0) || (idhpos > 2)) {
	    Warning("Illegal Activity horizontal id position %d", idhpos);
	} else if ((idvpos < 0) || (idvpos > 2)) {
	    Warning("Illegal Activity vertical id position %d", idvpos);
	} else {
            i = add_activity(st_date, e_date, up_date, dn_date, line, strtsym,
		endsym, pd_date, done_pct, bs_date, be_date, fill_pattern,
		layer, disp, hpos, vpos, font, point, color, text, idtext,
		idtog, idhpos, idvpos);
            return 0;
	}
	return -1;
    } else {
	return -1;
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	activity_ok_button() 
 *
 * INPUTS:    
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	this module checks input after the ok button is pressed
 */

static void 
activity_ok_button(void)
{
    utc_val sdate_diff, edate_diff; 		/* slip in date values */
    utc_val temp_date;
    char *buf;
    int val;
    
    change = DIALOG_NO_CHANGE;
    temp_date = DialogDateGet(sdate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->strtdate) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Start Date");
	change |= DIALOG_ERROR;
    }
    /*
     * slip objects associated by precedence lines
     */
    sdate_diff = temp_date - objtmp.z.actptr->strtdate;
    val = DialogTextGetInt(linew);
    if ((val < 1) || (val > MAX_LINE)) {
	Warning("Improper Line Position");
	change |= DIALOG_ERROR;
    } else if (val != objtmp.z.actptr->line) {
	change |= DIALOG_UPDATE;
	objtmp.z.actptr->line = val;
    }

    edate_diff = 0;
    change |= date_handle(sdate_diff, edate_diff);
    objtmp.z.actptr->strtdate = temp_date;
    if (objtmp.z.actptr->endate <= objtmp.z.actptr->strtdate) {
        Warning("End date must be later than Start date");
        change |= DIALOG_ERROR;
    }

    temp_date = DialogDateGet(rudate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->update) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Ramp Up Date");
	change |= DIALOG_ERROR;
    }
    objtmp.z.actptr->update = temp_date;

    temp_date = DialogDateGet(rddate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->dwndate) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Ramp Down Date");
	change |= DIALOG_ERROR;
    }
    objtmp.z.actptr->dwndate = temp_date;

    temp_date = DialogDateGet(bsdate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->b_strtdate) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Baseline Start Date");
	change |= DIALOG_ERROR;
    }
    objtmp.z.actptr->b_strtdate = temp_date;

    temp_date = DialogDateGet(bedate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->b_endate) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Baseline End Date");
	change |= DIALOG_ERROR;
    }
    objtmp.z.actptr->b_endate = temp_date;

    loa_type = DialogOptionGet(lenmenuw);
    if (new_smark != objtmp.z.actptr->strtsym) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->strtsym = DialogOptionGet(smark);
    if (new_emark != objtmp.z.actptr->endsym) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->endsym = DialogOptionGet(emark);
    if (new_fillpatt != objtmp.z.actptr->fill_pattern) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->fill_pattern = DialogOptionGet(fillw);
    if (new_hpos != objtmp.z.actptr->hpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->hpos = DialogOptionGet(hposw);
    if (new_vpos != objtmp.z.actptr->vpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->vpos = DialogOptionGet(vposw);
    if (new_font != objtmp.z.actptr->font) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->font = DialogOptionGet(fontw);
    if (new_point != objtmp.z.actptr->point) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->point = DialogOptionGet(pointw);
    if (new_disp != objtmp.z.actptr->disp) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->disp = DialogOptionGet(dispw);

    if (new_color != objtmp.z.actptr->color) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->color = DialogOptionGet(colorw);

    if (new_idhpos != objtmp.z.actptr->idhpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->idhpos = DialogOptionGet(idhposw);
    if (new_idvpos != objtmp.z.actptr->idvpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->idvpos = DialogOptionGet(idvposw);
    if (new_idtog != objtmp.z.actptr->idtog) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.actptr->idtog = DialogOptionGet(dspidw);
    if (new_drawlyr != objtmp.layer) {
	change |= DIALOG_UPDATE;
    }
    objtmp.layer = DialogOptionGet(drawlyrw);

    buf = DialogTextGet(textw);
    if (strcmp(buf, objtmp.z.actptr->text)) {
	change |= DIALOG_UPDATE;
	XtFree(objtmp.z.actptr->text);
	objtmp.z.actptr->text = buf;
    } else {
	XtFree(buf);
    }

    buf = DialogTextGet(idw);
    if (strcmp(buf, objtmp.z.actptr->idtext)) {
	change |= DIALOG_UPDATE;
	XtFree(objtmp.z.actptr->idtext);
	objtmp.z.actptr->idtext = buf;
    } else {
	XtFree(buf);
    }

    object_change = change;
    DialogFlagSet(change);
}

/***********************************************************************
 *
 * FUNCTION:
 *	cancel_button()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	discards any edits and closes edit window
 */

/* ARGSUSED */
static void 
cancel_button(void)
{
    object_change = DIALOG_CANCEL;
    DialogFlagSet(DIALOG_CANCEL);
}

/***********************************************************************
 *
 * FUNCTION:
 *	set_percent_done()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets the percent done value if the percent complete date changes
 */

static void 
set_percent_done(void)
{
    int diff, done_days;		/* difference in dates */
    utc_val start_date,end_date,pct_date;
    char buf[50];

/*
    diff = (objtmp.z.actptr->endate - objtmp.z.actptr->strtdate)/UTC_ONE_DAY;
    done_days = (objtmp.z.actptr->pctdate - objtmp.z.actptr->strtdate)/
	UTC_ONE_DAY;
    if (done_days == diff) {
*/
	/* pctdate is same as endate */
/*
	objtmp.z.actptr->done_pct = 100;
    } else if (diff == 0) {
*/
	/* pctdate is same as strtdate */
/*
	objtmp.z.actptr->pctdate = objtmp.z.actptr->strtdate;
	objtmp.z.actptr->done_pct = 0;
    } else {
	objtmp.z.actptr->done_pct = (done_days * 100) / diff;
    }
*/
    start_date = DialogDateGet(sdate);
    end_date = DialogDateGet(edate);
    pct_date = DialogDateGet(pctdate);
    diff = (end_date - start_date)/UTC_ONE_DAY;
    done_days = (pct_date - start_date)/UTC_ONE_DAY;
    if (done_days == diff) {
	(void)sprintf(buf, "%d", 100);
	DialogTextSet(pct, buf);
    } else if (diff == 0) {
	DialogDateSet(pctdate, start_date);
	(void)sprintf(buf, "%d", 0);
	DialogTextSet(pct, buf);
    } else {
	(void)sprintf(buf, "%d", (done_days * 100) / diff);
	DialogTextSet(pct, buf);
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	set_pct_date()
 *
 * INPUTS:
 *	edit_mode		(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets the percent complete date if the percent done value changes
 */

static void 
set_pct_date(int edit_mode)
{
    int pct_diff, diff;			/* difference in dates */
    int pct_val;
    utc_val start_val, end_val, pct_date;

    if (!edit_mode) {
	objtmp.z.actptr->pctdate = objtmp.z.actptr->strtdate;
	if (objtmp.z.actptr->done_pct == 0) {
	    objtmp.z.actptr->pctdate = objtmp.z.actptr->strtdate;
	} else if (objtmp.z.actptr->done_pct == 100) {
	    objtmp.z.actptr->pctdate = objtmp.z.actptr->endate;
	} else {
	    diff = (objtmp.z.actptr->endate - objtmp.z.actptr->strtdate)/
		UTC_ONE_DAY;
	    pct_diff = (objtmp.z.actptr->done_pct * diff)/100 * UTC_ONE_DAY;
	    objtmp.z.actptr->pctdate = objtmp.z.actptr->pctdate + pct_diff;
	}
	DialogDateSet(pctdate, objtmp.z.actptr->pctdate);
    } else {
	pct_val = DialogTextGetInt(pct);
	start_val = DialogDateGet(sdate);
	end_val = DialogDateGet(edate);
	if (pct_val == 0) {
	    DialogDateSet(pctdate, start_val);
	} else if (pct_val == 100) {
	    DialogDateSet(pctdate, end_val);
	} else {
	    diff = (end_val - start_val) / UTC_ONE_DAY;
	    pct_diff = (pct_val * diff) / 100 * UTC_ONE_DAY;
	    pct_date = DialogDateGet(pctdate);
	    pct_date += pct_diff;
	    DialogDateSet(pctdate, pct_date);
	}
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *      set_loa()
 *
 * INPUTS:
 *	direction	(int)
 *	edit_mode	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets the length of event if the value changes
 */

static int 
set_loa(int direction, int edit_mode)
{
    int mo, da, yr, e_yr;		/* month, day, and year */
    int sdoff, edoff;			/* start and end offsets */
    int temp_length;			/* length of activity */
    int sflag, eflag;			/* start and end flags for weekends */
    utc_val start_date;

    if (direction == 1) {
	/*
	 * changes weekday loa value to calendar days loa 
         * by including weekend days
         */
	if (!edit_mode) {
	    get_mdy(&mo, &da, &yr, objtmp.z.actptr->strtdate);
	    sdoff = get_wkday(objtmp.z.actptr->strtdate);
	} else {
	    start_date = DialogDateGet(sdate);
	    get_mdy(&mo, &da, &yr, start_date);
	    sdoff = get_wkday(start_date);
	}
	temp_length = ((int)(loa/5)) * 7;
	temp_length = temp_length + (loa % 5);
	if (sdoff == 6) {
	    temp_length++;
	} else if (sdoff == 5) {
	    temp_length += 2;
	} else if ((sdoff + (loa % 5)) >= 6) {
	    temp_length += 2;
	}
	if (temp_length < 0) {
	    temp_length = 0;
	}
    } else if (direction == 0) {
	/* 
         * changes calendar loa value to weekday days
         * by excluding weekend days
         */
	get_mdy(&mo, &da, &yr, objtmp.z.actptr->strtdate);
	sdoff = get_wkday(objtmp.z.actptr->strtdate);
	if ((sdoff == 5) || (sdoff == 6)) {
	    sflag = TRUE; 			/* starts on weekend */
	} else {
	    sflag = FALSE;
	}
	get_mdy(&mo, &da, &e_yr, objtmp.z.actptr->endate);
	edoff = get_wkday(objtmp.z.actptr->endate);
	if ((edoff == 5) || (edoff == 6)) {
	    eflag = TRUE;			/* ends on weekend */
	} else {
	    eflag = FALSE;
	}
	temp_length = ((int)(loa / 7)) * 5;
	if ((sflag == FALSE) && (eflag == FALSE)) {
	    /*
	     * does not start or end on weekend so subtract weekend days
	     * in the middle 
             */
	    temp_length = temp_length + (loa % 7);
	    if ((edoff - (loa % 7)) < 0) {
		temp_length -= 2;
	    }
	} else if ((sflag == TRUE) && (eflag == TRUE)) {
	    /* 
             * starts and ends on a weekend so subtract weekend days 
	     * for both weekends and those in the middle
             */
	    if ((loa % 7) <= 1) {
		temp_length = temp_length--;
	    } else if ((loa % 7) > 1) {
	  	temp_length = temp_length + 4;
	    }
	} else {
	    /*
  	     * starts or ends on a weekend so subtract weekend days 
	     * for one of them only and those in the middle
             */
	    temp_length = temp_length + (loa % 7);
	    if (edoff == 6) {
		temp_length -= 2;
	    } else if (edoff == 5) {
		temp_length--;
	    } else if (sdoff == 6) {
	   	temp_length --;
	    } else if (sdoff == 5) {
		temp_length -= 2;
	    }
	}
	if (temp_length < 1) {
	    temp_length = 0;
	}
    }
    return temp_length;
}

/***********************************************************************
 *
 * FUNCTION:
 *      set_loa_date()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets the length of event if the date changes
 */

static void 
set_loa_date(int edit_mode)
{
    int diff;				/* difference in dates */
    utc_val start_date, end_date;

    if (!edit_mode) {
	objtmp.z.actptr->endate = objtmp.z.actptr->strtdate;
	if (loa_type == 0) {
            objtmp.z.actptr->endate += (loa * UTC_ONE_DAY);
	} else if (loa_type == 1) {
	    diff = set_loa(1, 0);	/* changes to exclude weekends */
	    objtmp.z.actptr->endate += (diff * UTC_ONE_DAY);
	}
	DialogDateSet(edate, objtmp.z.actptr->endate);
    } else {
	start_date = DialogDateGet(sdate);
	end_date = DialogDateGet(edate);
	if (loa_type == 0) {
	    end_date += (loa * UTC_ONE_DAY);
	} else if (loa_type == 1) {
	    diff = set_loa(1, 1);
	    end_date += (diff * UTC_ONE_DAY);
	}
	DialogDateSet(edate, end_date);
    }	
}

/***********************************************************************
 *
 * FUNCTION:
 *	date_handle()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      checks to see what changes have occured and handles them accordingly
 */

static int 
date_handle(utc_val sdate_diff, utc_val edate_diff)
{
    int change = DIALOG_NO_CHANGE;			/* a change occured */
    int pdchange = DIALOG_NO_CHANGE;
    int endchange = DIALOG_NO_CHANGE;
    int percentchange = DIALOG_NO_CHANGE;
    int loachange = DIALOG_NO_CHANGE; 
    int loatogchange = DIALOG_NO_CHANGE;
    utc_val temp_date;
    int val;

    /*
     * end date change 
     */
    temp_date = DialogDateGet(edate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->endate) {
	    endchange = DIALOG_UPDATE;
	}
    } else {
	Warning("Improper End Date");
	endchange = DIALOG_ERROR;
    }
    change |= endchange;
    edate_diff = temp_date - objtmp.z.actptr->endate;
    set_pline(sdate_diff, edate_diff);
    objtmp.z.actptr->endate = temp_date;

    /*
     * percent date change 
     */
    temp_date = DialogDateGet(pctdate);
    if (temp_date != UTC_INVALID) {
	if (temp_date != objtmp.z.actptr->pctdate) {
	    pdchange = DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Percent Complete Date");
	pdchange = DIALOG_ERROR;
    }
    objtmp.z.actptr->pctdate = temp_date;
    change |= pdchange;
    
    val = DialogTextGetInt(pct);
    if ((val < 0) || (val > 100)) {
	Warning("Improper Percent Complete Value");
	percentchange = DIALOG_ERROR;
	change |= DIALOG_ERROR;
    } else if (val != objtmp.z.actptr->done_pct) {
	percentchange = DIALOG_UPDATE;
	objtmp.z.actptr->done_pct = val;
	change |= DIALOG_ERROR;
    } 

    val = DialogTextGetInt(lengthw);
    if ((val < 0) || (val > 99999)) {
	Warning("Improper Length of Activity Value");
	loachange = DIALOG_ERROR;
    } else if (val != loa) {
	loachange = DIALOG_UPDATE;
    }
    change |= loachange;
    loa = val;

    if (loa_type != new_loa) {
	loatogchange = DIALOG_UPDATE;
    }
    change |= loatogchange;
    loa_type = DialogOptionGet(lenmenuw);

    if ((sdate_diff != 0) || (edate_diff != 0)) {
	set_percent_done();
    }

    if (pdchange) {
        set_percent_done();
    } else if (percentchange) {
        set_pct_date(0);
    } 

    if (((loachange) || (loatogchange)) && (!endchange)) {
        set_loa_date(0);
	set_pct_date(0);
    }
    return change;
}

/***********************************************************************
 *
 * FUNCTION:
 *      actloaCB()
 *
 * INPUTS:
 *      w               - (Widget) button that was pressed
 *      client_data     - (XtPointer)  not used
 *      call_data       - (XmAnyCallbackStruct) not used
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This is the callback for the length of activity text widget
 *      It gets called every time the return key is pressed in that
 *      widget.  The purpose of this function is to check the
 *      validity of the input of the field and set the end date and
 *      percent complete date accordingly.
 */

static void 
actloaCB(Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data)
{
    int val;

    /* extract entered value */
    val = DialogTextGetInt(lengthw);
    if ((val < 0) || (val > 99999)) {
	Warning("Improper Length of Activity");
	return;
    }
    loa = val;

    /* set date values to correspond to new loa value */
    set_loa_date(1);
    set_pct_date(1);
    change |= DIALOG_UPDATE;
}

/***********************************************************************
 *
 * FUNCTION:
 *      actpctCB()
 *
 * INPUTS:
 *      w               - (Widget) button that was pressed
 *      client_data     - (XtPointer)  not used
 *      call_data       - (XmAnyCallbackStruct) not used
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This is the callback for the percent done text widget
 *      It gets called every time the return key is pressed in that
 *      widget.  The purpose of this function is to check the
 *      validity of the input of the field and set the percent
 *      complete date accordingly.
 */

static void 
actpctCB(Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data)
{
    int val;

    /* extract entered value */
    val = DialogTextGetInt(pct);
    if ((val < 0) || (val > 100)) {
	Warning("Improper Percent Done");
	return;
    }
    objtmp.z.actptr->done_pct = val;
	
    /* set date values to correspond to new pct	value */

    set_pct_date(1);
    change |= DIALOG_UPDATE;
}

/***********************************************************************
 *
 * FUNCTION:
 *      set_pline()
 *
 * INPUTS:
 *      date_diff       (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module adjusts the dates of the objects associated by
 *      precedence lines by the slip amount of the activity start date
 */

static void 
set_pline(utc_val sdate_diff, utc_val edate_diff)
{
int i, co;                      /* temp indices */

    if ((pline_flag) && (objtmp.precptr != NULL)) {
        for (i = 0; i < sizeof_dynarray(objtmp.precptr); i++) {
            co = elemof_dynarray(objtmp.precptr, i);
            if ((objary[plnary[co].obj1].z.actptr->strtdate !=
                objtmp.z.actptr->strtdate) || 
		(objary[plnary[co].obj1].z.actptr->endate !=
		objtmp.z.actptr->endate))  {
                switch (objary[plnary[co].obj1].type) {
                case OBJ_EVT:
                    objary[plnary[co].obj1].z.evtptr->edate += sdate_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_ACT:
                    objary[plnary[co].obj1].z.actptr->strtdate += sdate_diff;
                    objary[plnary[co].obj1].z.actptr->endate += edate_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SACT:
                    objary[plnary[co].obj1].z.sactptr->strtdate += sdate_diff;
                    objary[plnary[co].obj1].z.sactptr->endate += edate_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SLP:
                    objary[plnary[co].obj1].z.slpptr->strtdate += sdate_diff;
                    objary[plnary[co].obj1].z.slpptr->endate += edate_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SEQ:
                    objary[plnary[co].obj1].z.seqptr->strtdate += sdate_diff;
                    objary[plnary[co].obj1].z.seqptr->endate += edate_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                default:
                    break;
                }
            }
            if ((objary[plnary[co].obj2].z.actptr->strtdate !=
                objtmp.z.actptr->strtdate) || 
		(objary[plnary[co].obj2].z.actptr->endate != 
		objtmp.z.actptr->endate)) {
                switch (objary[plnary[co].obj2].type) {
                case OBJ_EVT:
                    objary[plnary[co].obj2].z.evtptr->edate += sdate_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_ACT:
                    objary[plnary[co].obj2].z.actptr->strtdate += sdate_diff;
                    objary[plnary[co].obj2].z.actptr->endate += edate_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SACT:
                    objary[plnary[co].obj2].z.sactptr->strtdate += sdate_diff;
                    objary[plnary[co].obj2].z.sactptr->endate += edate_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SLP:
                    objary[plnary[co].obj2].z.slpptr->strtdate += sdate_diff;
                    objary[plnary[co].obj2].z.slpptr->endate += edate_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SEQ:
                    objary[plnary[co].obj2].z.seqptr->strtdate += sdate_diff;
                    objary[plnary[co].obj2].z.seqptr->endate += edate_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                default:
                    break;
                }
            }
        }
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *      verify_fun()
 *
 * INPUTS:
 *      w       (Widget)
 *      x, y    (XtPointer)
 *
 * OUTPUTS:
 *      none
 *
 * RETURNS:
 *      none
 *
 * EXTERNALLY READ:
 *      none
 *
 * EXTERNALLY MODIFIED:
 *      none
 *
 * DESCRIPTION:
 *      validates that the popup dialog can be closed
 */

static void
verify_fun(Widget w, XtPointer x, XtPointer y)
{
    if ((int)x == DIALOG_CANCEL) {
        if (!ShellValidateClose(w)) return;
        cancel_button();
    } else if ((int)x == DIALOG_UPDATE) {
	activity_ok_button();
    }
}
