/***********************************************************************
 *
 * TITLE:
 *	sactivity.c
 *
 * AUTHOR:
 *	Cassie Mulnix
 *
 * DESCRIPTION:	
 *	This module is part of the OPPS editor, xopps.  It contains
 *	routines to handle simple activity objects.
 *
 *                              CHANGE HISTORY
 *
 * $Log: sactivity.c,v $
 * Revision 1.77  1994/12/31  04:29:21  kevin
 * fixed memory allocation problem after DialogTextGet
 *
 * Revision 1.76  1994/11/01  15:43:38  cassie
 * fixed % complete and loa callbacks to work with edited values and
 * not stored values only
 *
 * Revision 1.75  1994/10/12  18:14:51  cassie
 * set change to DIALOG_NO_CHANGE in ok_button
 *
 * Revision 1.74  1994/08/10  22:05:48  cassie
 * removed call to DialogFlagSet in verify_fun since
 * it is already set in ok_button
 *
 * Revision 1.73  1994/07/20  19:06:35  clm
 * updated TRUE, ERROR etc in cancel & ok_button functions
 * to DIALOG_ constants
 *
 * Revision 1.72  1994/06/16  21:57:27  clm
 * updated to new dialog routines - extra parameter to DialogTextCreate
 *
 * Revision 1.71  1994/06/16  16:56:35  clm
 * updated to new gr_ routines using GR_ for font names
 *
 * Revision 1.70  1994/06/08  18:48:45  clm
 * removed Xm library includes since they are in dialog
 *
 * Revision 1.69  1994/06/07  17:05:55  clm
 * initialize edate_diff to 0 for hp warning
 *
 * Revision 1.68  1994/06/07  16:39:58  clm
 * fixed loc function
 *
 * Revision 1.67  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.66  1994/05/20  23:31:43  clm
 * updated with HP, SGI changes
 *
 * Revision 1.65  1994/05/04  23:34:36  clm
 * ported to ANSI C
 *
 * Revision 1.64  1994/02/10  20:06:04  clm
 * fixed positioning of text and locate functions
 *
 * Revision 1.63  1994/02/09  20:57:09  clm
 * added UTC_ONE_DAY/2 to pctdate for correct filling
 *
 * Revision 1.62  1993/11/11  18:12:10  clm
 * adjusted vertical position of text
 *
 * Revision 1.61  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.60  1993/10/11  17:00:12  clm
 * fixed gr_rect_clear
 *
 * Revision 1.59  1993/10/11  15:44:43  clm
 * added clear rectangle around object so that it stands out from vertical lines
 *
 * Revision 1.58  1993/09/10  18:01:35  clm
 * offset rectangle to left 1 position
 *
 * Revision 1.57  1993/05/27  16:37:52  clm
 * change symbols to filled with status date
 *
 * Revision 1.56  1993/05/21  16:01:58  clm
 * fixed buffer size for sav function
 *
 * Revision 1.55  1993/05/20  15:27:09  clm
 * fixed ok_button had |= when needed =
 *
 * Revision 1.54  1993/05/19  19:38:27  clm
 * changed Sactivity in messages to Simple Activity
 *
 * Revision 1.53  1993/05/18  22:39:41  clm
 * added meaningful error messages for check_num and check_day
 *
 * Revision 1.52  1993/05/18  20:58:30  clm
 * added new message.c function
 *
 * Revision 1.51  1993/03/29  15:48:35  clm
 * fixed date_handle call so new start date is set before call
 *
 * Revision 1.50  1993/03/25  18:33:39  clm
 * fixed fill pattern to end at beginning of day instead of middle of day
 *
 * Revision 1.49  1993/02/23  18:21:50  clm
 * fixed LOCAte function for xs < start_date
 * l
 *
 * Revision 1.48  1993/02/20  00:04:14  clm
 * added Slip Precedence Objects to edit popup
 *
 * Revision 1.47  1993/02/08  16:21:49  clm
 * centered symbol in date
 *
 * Revision 1.46  1993/02/08  16:18:37  clm
 * fixed loc_function for y2
 * fixed fill_pattern gap
 * fixed dsp_marker size to match symbol object
 *
 * Revision 1.45  1992/12/17  22:54:43  clm
 * fixed size of dspdatebuttons
 *
 * Revision 1.44  1992/12/15  20:39:51  clm
 * changed strlen to sizeof when assigning symbols
 *
 * Revision 1.43  1992/12/14  18:55:08  clm
 *  really fixed dsp and loc bug
 *
 * Revision 1.42  1992/12/11  22:47:55  clm
 * fixed dsp error checking of page bounds
 *
 * Revision 1.41  1992/12/11  22:11:12  clm
 * fixed loc and dsp for completely offpage objects
 *
 * Revision 1.40  1992/12/10  21:45:40  clm
 * fixed new_index so chart is always object 0
 *
 * Revision 1.39  1992/12/01  17:03:36  clm
 * cleaned up code
 *
 * Revision 1.38  1992/11/30  22:36:28  clm
 * fixed locate function
 *
 * Revision 1.37  1992/11/24  16:28:27  clm
 * fixed rem functions - setting of ip array
 *
 * Revision 1.36  1992/11/12  18:57:56  clm
 * fixed layer setting in ok_button
 *
 * Revision 1.35  1992/11/09  16:32:51  clm
 * added precedence lines
 *
 * Revision 1.34  1992/10/12  18:06:17  clm
 * fixed move so that the x coord is not changed, since it can't be moved
 *
 * Revision 1.33  1992/10/09  21:17:43  clm
 * fixed move routine
 *
 * Revision 1.32  1992/10/02  20:41:54  clm
 * housekeeping
 *
 * Revision 1.31  1992/10/01  21:06:00  clm
 * added loaCB and pctCB to change date values while popup is up
 *
 * Revision 1.30  1992/09/30  22:30:14  clm
 * fixed locate routine
 *
 * Revision 1.29  1992/09/29  22:24:54  clm
 * fixed display of auto_areset
 *
 * Revision 1.28  1992/09/29  16:24:22  clm
 * fixed display of id text and toggle
 *
 * Revision 1.27  1992/09/28  22:42:07  clm
 * added id text and toggle
 *
 * Revision 1.26  1992/09/25  20:34:43  clm
 *  error checking to make sure end date is after start date
 *
 * Revision 1.25  1992/09/24  21:12:53  clm
 * fixed fill pattern to be in the entered object color
 *
 * Revision 1.24  1992/09/16  14:55:56  clm
 * fixed load function so doesn't add object if error in load
 *
 * Revision 1.23  1992/09/14  23:26:30  clm
 * fixed auto % reset display
 *
 * Revision 1.22  1992/09/14  22:59:01  clm
 * added vertical text positioning
 * fixed loc and dsp functions to reflect vpos
 *
 * Revision 1.21  1992/09/14  20:41:45  clm
 * added vertical position to object
 * fixed display for vertical position
 *
 * Revision 1.20  1992/09/14  14:20:37  clm
 * fixed error checking of font in load_sactivity
 *
 * Revision 1.19  1992/08/31  15:40:45  clm
 * add rect_clear call so background lines don't show
 * fixed set_loa call so dates are handled correctly
 *
 * Revision 1.18  1992/08/27  20:56:40  clm
 * changed G_SOLID fill option to use gr_rect_fill routine
 *
 * Revision 1.17  1992/08/27  20:14:54  clm
 * took loc out of load since pg_lines is also loaded
 *
 * Revision 1.16  1992/08/27  14:50:38  clm
 * set pctdate to startdate, not st_date
 *
 * Revision 1.15  1992/08/26  17:19:09  clm
 * fixed loc and display so if object is partially off the screen
 * it will still be displayed
 *
 * Revision 1.14  1992/08/20  15:17:59  clm
 * added color to sav routine
 *
 * Revision 1.12  1992/08/13  18:09:21  clm
 * fixed error checking for load module
 *
 * Revision 1.11  1992/08/04  17:01:10  clm
 * changed malloc and free to XtMalloc and XtFree
 *
 * Revision 1.10  1992/08/04  16:31:02  clm
 * changed dsp to handle multiple pages
 *
 * Revision 1.9  1992/08/03  21:52:20  clm
 * edit to status date changes st_date
 *
 * Revision 1.8  1992/08/03  21:35:55  clm
 * changed save and load to time values
 *
 * Revision 1.7  1992/06/03  16:46:54  clm
 * updated dialog shell
 *
 * Revision 1.6  1992/05/21  21:34:20  clm
 * incorporated rectangle routines
 *
 * Revision 1.4  1992/05/20  19:50:57  clm
 * cleaned up file and help format
 *
 * Revision 1.3  1992/05/11  22:39:32  kevin
 * renamed project include file to xopps.h
 *
 * Revision 1.2  1991/10/03  00:00:00  tommy
 * added xopps specifics
 *
 * Revision 1.1  1991/10/01  00:57:44  tommy
 * Initial revision
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: sactivity.c,v 1.77 1994/12/31 04:29:21 kevin OEL $";
#endif

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

    local functions:
        dsp_sact(i) - display sact object
        rem_sact(i) - remove sact object
        mov_sact(i) - move sact object
        edt_sact(i) - change contents of sact field
        msg_sact(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 create_dialog(void);
static void sactivity_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);	/* Execute pline object slips */
static void dsp_sact(int);
static void edt_sact(int, int);
static void rem_sact(int, int);
static void lim_sact(int, int *, int *, int *, int *, int);
static void loc_sact(int, int);
static void mov_sact(int, int, int, int);
static void cpy_sact(struct obj *, struct obj *);
static void msg_sact(int, int);
static void sav_sact(int, FILE *, int);
static int load_sact(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 loaCB(Widget, XtPointer, XmAnyCallbackStruct *);
static void pctCB(Widget, XtPointer, XmAnyCallbackStruct *);
static void verify_fun(Widget, XtPointer, XtPointer);

static struct ops sact_ops = {
    dsp_sact, edt_sact, rem_sact, lim_sact, loc_sact, mov_sact,
    cpy_sact, msg_sact, sav_sact
};
                                              /* function pointer */

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

static Widget sact_dialog;			/* dialog shell for popup */
static Widget parent_shell;
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 id for id text */
static int new_idvpos;				/* new vpos id for id text */
static int new_idtog;				/* new toggle for id display */
static int loa;					/* current loa value */
static int loa_type;				/* current loa toggle value */

static int pline_flag = FALSE;			/* slip plines flag */
static int change = DIALOG_NO_CHANGE;		/* a change occured */

/***********************************************************************
 *
 * FUNCTION:
 *	init_sactivity_object()
 *
 * INPUTS:
 *	parent	(Widget)
 *
 * OUTPUTS:
 * 	none
 *
 * RETURNS:
 * 	none
 *
 * EXTERNALLY READ:
 * 	none
 *
 * EXTERNALLY MODIFIED:
 * 	none
 *
 * DESCRIPTION:
 *	registers sactivity object and sets the parent
 */

void 
init_sactivity_object(Widget parent)
{
    register_io_obj('D', load_sact);			/* 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 sactivity
 */

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

    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;
    }

    sact_dialog = DialogInit(parent_shell, "Simple Activity Object", 
	"sactivity", verify_fun, (XtPointer)DIALOG_CANCEL);

    DialogAddRow(2);
    sdate = DialogDateCreate("Start Date ");
    edate = DialogDateCreate("End Date ");
    DialogAddRow(2);
    pctdate = DialogDateCreate("Percent Done Date ");
    pct = DialogTextCreate("Percent Complete ", 3, 3);
    XtAddCallback(pct->text, XmNactivateCallback, (XtCallbackProc)pctCB,
        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 ", 25, 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 ", 25, 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)loaCB,
        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, "sactivity");

}

/***********************************************************************
 *
 * FUNCTION:
 *	add_sactivity()
 *
 * INPUTS:
 *	st_date, e_date,pd_date	(utc_val)
 *	line, strtsym, endsym, done_pct, layer, hpos, vpos, font
 *	    point, color	 (int)
 *	fill_pattern 	(enum pattern)
 *	disp	(enum tds)
 *	text	(char *)		
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	adds an sactivity object
 */

int 
add_sactivity(utc_val st_date, utc_val e_date, int line, int strtsym, int endsym, utc_val pd_date, int done_pct, 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.sactptr = (struct sact *)XtMalloc(sizeof(struct sact));
    objary[i].z.sactptr->strtdate = st_date;
    objary[i].z.sactptr->endate = e_date;
    objary[i].z.sactptr->line = line;
    objary[i].z.sactptr->strtsym = strtsym;
    objary[i].z.sactptr->endsym = endsym;
    objary[i].z.sactptr->pctdate = pd_date;
    objary[i].z.sactptr->done_pct = done_pct;
    objary[i].z.sactptr->fill_pattern = fill_pattern;
    objary[i].z.sactptr->disp = disp;
    objary[i].z.sactptr->hpos = hpos;
    objary[i].z.sactptr->vpos = vpos;
    objary[i].z.sactptr->font = font;
    objary[i].z.sactptr->point = point;
    objary[i].z.sactptr->color = color;
    objary[i].z.sactptr->idhpos = idhpos;
    objary[i].z.sactptr->idvpos = idvpos;
    objary[i].z.sactptr->idtog = idtog;
    objary[i].z.sactptr->text = XtNewString(text);
    objary[i].z.sactptr->idtext = XtNewString(idtext);
    loa = (objary[i].z.sactptr->endate - objary[i].z.sactptr->strtdate)/
	UTC_ONE_DAY;
    objary[i].type = OBJ_SACT;
    objary[i].layer = layer;
    objary[i].opsptr = &sact_ops;
    return i;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_color()
 *
 * INPUTS:
 *      button  (Widget)
 *      option, any_data        (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      sets new color for sact 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 sactivity 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 sactivity 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 sactivity 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 sactivity 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 sactivity 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 of the sactivity 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 sactivity 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 sactivity 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 sactivity 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 sactivity 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 sactivity 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_sact()
 *
 * INPUTS:
 *	i  (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION: 
 *	pops up a edit box for the sactivity i
 */

static void 
dsp_sact(int i)
{
    struct sact *sactptr;       	/* local pointer */
    int mid, stat;              	/* midpoint for fill pattern */
    int xs, xe;                		/* x-pos of start/end times */
    int j, y2;          		/* temporary variables */
    int diff, done_days;        	/* difference in dates */
    enum tog s_flag, e_flag;   	 	/* flag to draw symbols if off page */
    int dxltime;                	/* length of start hour string */
    int dxrtime;                	/* length of end hour string */
    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 */
    int bar_y, bar_height;		/* bar coordinates */
    int center_y;			/* center coordinate */
    int text_x, text_y;			/* text coordinate */
    int idtext_x, idtext_y;		/* id text coordinate */
    XRectangle *(*r)[];			/* rectangle for object */
    XRectangle *(*line_rect)[];		/* rectangle for line */
    int ln_pos;				/* line position */
    int fill_gap;			/* minimum y_gap for fill pattern */

    sactptr = objary[i].z.sactptr;
    xs = utc_to_x(sactptr->strtdate + UTC_ONE_DAY/2);
    xe = utc_to_x(sactptr->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 centering */
    xs++;
    xe++;
    if (xs > xe) {		/* start position should precede end position */
	xe = xs + 1;
    }

    /* percent done fill based on percent done date */
    mid = utc_to_x(sactptr->pctdate + UTC_ONE_DAY/2);
    stat = utc_to_x(st_date);

    if (auto_areset == TOG_ON) {
	/* find difference between status and start dates */
	/* NOTE: % done date will be reset to status date */
	
	if (st_date < sactptr->strtdate) {
	    done_days = 0;
	} else {
	    done_days = (st_date - sactptr->strtdate)/UTC_ONE_DAY;
	}
	diff = (sactptr->endate - sactptr->strtdate)/UTC_ONE_DAY;
	if (done_days <= 0) {
	    /*
	     * status date prior to start date
	     */
	    mid = xs;	
	    sactptr->done_pct = 0;
	    sactptr->pctdate = sactptr->strtdate;
	    /*
	     * begin symbol should be empty
	     */
	    if ((sactptr->strtsym == 1) || (sactptr->strtsym == 3) || 
		(sactptr->strtsym == 5) || (sactptr->strtsym == 11) ||
		(sactptr->strtsym == 13)) {
		sactptr->strtsym -= 1;
	    }
	    /*
	     * end symbol should be empty
	     */
	    if ((sactptr->endsym == 1) || (sactptr->endsym == 3) ||
		(sactptr->endsym == 5) || (sactptr->endsym == 11) ||
		(sactptr->endsym == 13)) {
		sactptr->endsym -= 1;
	    }
	} else if (done_days >= diff) {
	    /*
	     * status date past endate
	     */
	    mid = xe;
	    sactptr->done_pct = 100;
	    sactptr->pctdate = sactptr->endate;
	    /*
	     * begin symbol should be filled
	     */
	    if ((sactptr->strtsym == 0) || (sactptr->strtsym == 2) || 
		(sactptr->strtsym == 4) || (sactptr->strtsym == 10)) {
		sactptr->strtsym += 1;
	    }
	    /*
	     * end symbol should be filled
	     */
	    if ((sactptr->endsym == 0) || (sactptr->endsym == 2) || 
		(sactptr->endsym == 4) || (sactptr->endsym == 10)) {
		sactptr->endsym += 1;
	    }
	} else if (diff == 0) {
	    mid = xs;
	    sactptr->done_pct = 0;
	    sactptr->pctdate = sactptr->strtdate;
	    /*
	     * begin symbol should be empty
	     */
	    if ((sactptr->strtsym == 1) || (sactptr->strtsym == 3) || 
		(sactptr->strtsym == 5) || (sactptr->strtsym == 11) ||
		(sactptr->strtsym == 13)) {
		sactptr->strtsym -= 1;
	    }
	    /*
	     * end symbol should be empty
	     */
	    if ((sactptr->endsym == 1) || (sactptr->endsym == 3) ||
		(sactptr->endsym == 5) || (sactptr->endsym == 11) ||
		(sactptr->endsym == 13)) {
		sactptr->endsym -= 1;
	    }
	} else {
	    /* 
	     * status date between start and end dates
 	     */
	    sactptr->done_pct = (done_days * 100) / diff;
	    sactptr->pctdate = st_date;
	    mid = stat;
	    /*
	     * begin symbol should be filled
	     */
	    if ((sactptr->strtsym == 0) || (sactptr->strtsym == 2) || 
		(sactptr->strtsym == 4) || (sactptr->strtsym == 10)) {
		sactptr->strtsym += 1;
	    }
	    /*
	     * end symbol should be empty
	     */
	    if ((sactptr->endsym == 1) || (sactptr->endsym == 3) ||
		(sactptr->endsym == 5) || (sactptr->endsym == 11) ||
		(sactptr->endsym == 13)) {
		sactptr->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;
        sactptr->pctdate = sactptr->strtdate;
	sactptr->done_pct = 0;
    } else if (mid > xe) {
	mid = xe;
	sactptr->pctdate = sactptr->endate;
	sactptr->done_pct = 100;
    }
    if (((sactptr->line >= page_begin) && (sactptr->line <= page_end)) &&
	((sactptr->strtdate <= objary[0].z.chtptr->end_date) &&
	(sactptr->endate >= objary[0].z.chtptr->start_date))) {	
	width = gr_strwidth(sactptr->text, sactptr->font|sactptr->point);
	r = getMoveRect(objary[i].rlist);
        txheight = gr_txheight(sactptr->font|sactptr->point);
	/* 
	 * y coord of rectangle was moved up for TX_ABOVE, so the center
	 * must be adjusted
 	 */
        ln_pos = hln_objary[sactptr->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 - 1, center_y, xe - xs + 1, y_gap - 2);
        gr_set_color(color_name[sactptr->color], color_gscale[sactptr->color]);
	gr_rectangle(xs-1, bar_y - 1, xe - xs, bar_height + 2);

	/* set fill_gap so that spacing of fill patterns is visible */
	if (y_gap < 6) {
	    fill_gap = 6;
	} else {
	    fill_gap = y_gap;
	}
	switch(sactptr->fill_pattern) {
	case OPEN:
	    break;
	case SOLID:
            if (xs < mid) {
		gr_rect_fill(xs, bar_y - 1, mid - xs, bar_height + 2,
		    color_name[sactptr->color], color_gscale[sactptr->color]);
        	gr_set_color(color_name[sactptr->color], 
		    color_gscale[sactptr->color]);
	    }
	    break;
	case LEFT_DIAG:
	    y2 = bar_y + bar_height;
	    for (j = xs; j <= mid; j += fill_gap/2) {
	        if (j + fill_gap/2 <= mid) {
	    	    gr_line(j, bar_y, j + fill_gap/2, y2);
	        }
	    }
	    break;
        case RIGHT_DIAG:
    	    y2 = bar_y + bar_height;
            for (j = xs; j <= mid; j += fill_gap/2) {
	        if (j + fill_gap/2 <= mid) {
	            gr_line(j + fill_gap/2, bar_y, j, y2);
		}
	    }
	    break;
	case HORIZONTAL:
            for (j = 0; j < bar_height; j +=3) {
  	        gr_line(xs, bar_y + j, mid, bar_y + j);
	    }
	    break;
	case VERTICAL:
	    for (j = xs; j < mid; j +=5) {
   	        gr_line(j, bar_y, j, bar_y + bar_height);
	    }
	    break;
	case CROS_HATCH:
  	    y2 = bar_y + bar_height;
            for (j = xs; j <= mid; j += fill_gap/2) {
 	        if (j + fill_gap/2 <= mid) {
	            gr_line(j, bar_y, j + fill_gap/2, y2);
	            gr_line(j + fill_gap/2, bar_y, j, y2);
	        }
	    }
	    break;
        }
        if ((mid > xs) && (mid <= xe)) {
            gr_line(mid, bar_y, mid, bar_y + bar_height);
        }
        if ((s_flag == TOG_ON) && (sactptr->strtsym >= 0)) {
            dsp_marker(sactptr->strtsym, xs - (y_gap - 1)/2, center_y + 3,
 	        y_gap - 5, 0);
            xs -= 15;
        }
        if ((e_flag == TOG_ON) && (sactptr->endsym >= 0)) {
            dsp_marker(sactptr->endsym, xe - (y_gap - 1)/2 + 1, center_y + 3,
   	        y_gap - 5, 0);
	    xe += 6;
        }
	
        	/* display text */
        txwidth = gr_txwidth(sactptr->font|sactptr->point);
        if (sactptr->disp == TDS_DOY) {
    	    utc_date = get_doy(sactptr->strtdate);
	    (void)sprintf(lbuf, "%03d", utc_date);
	    utc_date = get_doy(sactptr->endate);
	    (void)sprintf(rbuf, "%03d", utc_date);
	    dxltime = (strlen(lbuf) + 1) * txwidth;
	    dxrtime = (strlen(rbuf) + 1) * txwidth;
        } else if (sactptr->disp == TDS_DATE) {
            get_mdy(&smonth, &sday, &syear, sactptr->strtdate);
            get_mdy(&emonth, &eday, &eyear, sactptr->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;
        }
        switch (sactptr->hpos) {
        case GR_LEFT:
    	    text_x = xs - y_gap/2 - width - 1;
	    if (sactptr->disp != TDS_NONE) {
		text_x -= y_gap;
	    }
    	    break;
        case GR_RIGHT:
	    text_x = xe + y_gap/2 + 1;
	    if (sactptr->disp != TDS_NONE) {
		text_x += y_gap;
	    }
    	    break;
    	default:
    	    text_x = xs - width/2 + (xe - xs)/2;
 	    break;
        }
	if (sactptr->idtog == TOG_ON) {
	    width = gr_strwidth(sactptr->idtext, sactptr->font|sactptr->point);
            switch (sactptr->idhpos) {
            case GR_LEFT:
                idtext_x = xs - y_gap/2 - width - 1;
		if (sactptr->disp != TDS_NONE) {
                    idtext_x -= y_gap;
		}
                break;
            case GR_RIGHT:
                idtext_x = xe + y_gap + width + 1;
                break;
            default:
                idtext_x = xs - width/2 + (xe - xs)/2;
                break;
            }
	    if (sactptr->idvpos == sactptr->vpos) {
	        switch (sactptr->vpos) {
	        case TX_ABOVE:
	            text_y = (*r)[0]->y;
	            break;
	        case TX_BELOW:
	            text_y = (*r)[0]->y + y_gap + txheight + 2;
	            break;
	        default:
	            text_y = center_y + y_gap/2 + txheight/2;
	            break;
	        }
                switch (sactptr->idvpos) {
                case TX_ABOVE:
                    idtext_y = (*r)[0]->y;
                    break;
                case TX_BELOW:
                    idtext_y = (*r)[0]->y + y_gap + txheight + 2;
                    break;
                default:
                    idtext_y = center_y + y_gap/2 + txheight/2;
                    break;
                }
	    } else {
                switch (sactptr->vpos) {
                case TX_ABOVE:
                    text_y = (*line_rect)[0]->y;
                    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;
                }
                switch (sactptr->idvpos) {
                case TX_ABOVE:
                    idtext_y = (*line_rect)[0]->y;
                    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;
                }
	    }
	} else {
	    switch (sactptr->vpos) {
	    case TX_ABOVE:
	        text_y = (*r)[0]->y;
	        break;
	    case TX_BELOW:
	        text_y = (*r)[0]->y + y_gap + txheight + 2;
	        break;
	    default:
	        text_y = center_y + y_gap/2 + txheight/2;
	        break;
    	    }
	}
        if (objary[i].layer == 0) {
            mask = TOG_OFF;
        } else {
            mask = TOG_ON;
        }
        gr_text(xs - y_gap, center_y + y_gap/4 + txheight, lbuf, GR_LEFT, 
	    (sactptr->font|sactptr->point), (int)mask);
        gr_text(xe + y_gap/2 + 1, center_y + y_gap/4 + txheight, rbuf,GR_LEFT, 
            (sactptr->font|sactptr->point), (int)mask);
        gr_text(text_x, text_y, sactptr->text, GR_LEFT,
	    (sactptr->font|sactptr->point), (int)mask);
	if (sactptr->idtog == TOG_ON) {
	    gr_text(idtext_x, idtext_y, sactptr->idtext, GR_LEFT,
	 	(sactptr->font|sactptr->point), (int)mask);
	}
    }
}

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

static void 
loc_sact(int i, int dir)
{
    struct sact *sactptr;		/* local pointer */
    XRectangle r1;			/* rectangles for parts of object */
    int xs, xe;				/* 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 dxltime, dxrtime;		/* length of buffer strings */
    int smonth, sday, syear;		/* start date values */
    int emonth, eday, eyear;		/* end date values */

    sactptr = objary[i].z.sactptr;
    if (((sactptr->line < page_begin) || (sactptr->line > page_end)) ||
	((sactptr->strtdate < objary[0].z.chtptr->start_date) &&
	(sactptr->endate < objary[0].z.chtptr->start_date)) || 
	((sactptr->strtdate > objary[0].z.chtptr->end_date) &&
	(sactptr->endate > objary[0].z.chtptr->end_date))) { 
    	    setRectList(objary[i].rlist, 0);
	    return;
    }
    xs = utc_to_x(sactptr->strtdate + UTC_ONE_DAY/2);
    xe = utc_to_x(sactptr->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;
    }
    ln_pos = hln_objary[sactptr->line];
    line_rect = getMoveRect(Hobjary[ln_pos].rlist);
    height = gr_txheight(sactptr->font|sactptr->point);

    txwidth = gr_txwidth(sactptr->font|sactptr->point);
    if (sactptr->disp == TDS_DOY) {
        utc_date = get_doy(sactptr->strtdate);
        (void)sprintf(lbuf, "%03d", utc_date);
        utc_date = get_doy(sactptr->endate);
        (void)sprintf(rbuf, "%03d", utc_date);
        dxltime = (strlen(lbuf) + 1) * txwidth;
        dxrtime = (strlen(rbuf) + 1) * txwidth;
    } else if (sactptr->disp == TDS_DATE) {
        get_mdy(&smonth, &sday, &syear, sactptr->strtdate);
        get_mdy(&emonth, &eday, &eyear, sactptr->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 
     */

    width = gr_strwidth(sactptr->text, sactptr->font|sactptr->point);
    if (gr_strwidth(sactptr->idtext, sactptr->font|sactptr->point) > width) {
        width = gr_strwidth(sactptr->idtext, sactptr->font|sactptr->point);
    }
    if (((sactptr->hpos == GR_LEFT) && (strcmp(sactptr->text, "") != 0)) || 
	((sactptr->idhpos == GR_LEFT) && (strcmp(sactptr->idtext, "") != 0))) {
	r1.x = xs - y_gap - width - dxltime - 4;
    } else if (((sactptr->hpos == GR_CENTER) && 
	(strcmp(sactptr->text,"") != 0)) || ((sactptr->idhpos == GR_CENTER)
	&& (strcmp(sactptr->idtext,"") != 0))) {
        r1.x = xs - y_gap - dxltime - 1;
    } else {
	r1.x = xs - y_gap - dxltime - 1;
    }
    if (sactptr->disp != TDS_NONE) {
	r1.x -= y_gap + 1;
    }
    r1.y = (*line_rect)[0]->y + 1;
    if (((sactptr->hpos == GR_RIGHT) && (strcmp(sactptr->text, "") != 0)) ||
	((sactptr->idhpos == GR_RIGHT) && 
	(strcmp(sactptr->idtext, "") != 0))) {
    	r1.width = xe + y_gap + width + dxrtime + 5 - r1.x;
    } else if (((sactptr->hpos == GR_CENTER) && 
	(strcmp(sactptr->text,"") != 0)) || ((sactptr->idhpos == GR_CENTER) 
	&&(strcmp(sactptr->idtext,"")!=0))) {
        r1.width = xe +  y_gap + 1 + dxrtime - r1.x;
    } else {
	r1.width = xe + y_gap + 2 - r1.x;
    }
    if (sactptr->disp != TDS_NONE) {
	r1.width += y_gap;
    }
    r1.height = y_gap + 1; 

    if (((sactptr->vpos == TX_ABOVE) && (strcmp(sactptr->text, "") != 0)) || 
	((sactptr->idvpos == TX_ABOVE) && 
	(strcmp(sactptr->idtext, "") != 0))) {
	r1.y = r1.y - height - 1;
	r1.height = r1.height + height + 1;
    }
    if (((sactptr->vpos == TX_BELOW) && (strcmp(sactptr->text, "") != 0)) || 
	((sactptr->idvpos == TX_BELOW) && 
	(strcmp(sactptr->idtext, "") != 0))) {
	r1.height = r1.height + height + 1;
    }
    setRectList(objary[i].rlist, 1, &r1, RL_PRIMARY);
}

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

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

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

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

    DialogDateSet(sdate, objtmp.z.sactptr->strtdate);
    DialogDateSet(edate, objtmp.z.sactptr->endate);
    DialogDateSet(pctdate, objtmp.z.sactptr->pctdate);

    sprintf(buf, "%d", objtmp.z.sactptr->done_pct);
    DialogTextSet(pct, buf);

    sprintf(buf, "%d", objtmp.z.sactptr->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.sactptr->text);
    DialogTextSet(idw, objtmp.z.sactptr->idtext);
    sprintf(buf, "%d", loa);
    DialogTextSet(lengthw, buf);
    EditObject(i, sact_dialog);

}

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

static void 
rem_sact(int i, int dir)
{
    struct obj *objptr;				/* temp object pointer */
    int (*ip)[];                                /* array of pline indices */
    int nip;                                    /* number of indices */
    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;
    }
    /*
     * only remove precedence lines if object is not temporary
     */
 
    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.sactptr->text);
    XtFree((char *)objptr->z.sactptr);
    rem_object(objptr);
}

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

static void 
lim_sact(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_sact()
 *
 * INPUTS:
 *	i, x, y  	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module moves the sactivity object when the middle mouse
 *	button is pressed
 */

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

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

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

static void 
cpy_sact(struct obj *to, struct obj *from)
{
    if (from->type == OBJ_NUL) {
	return;
    }
    to->z.sactptr = (struct sact *)XtMalloc(sizeof(struct sact));
    to->z.sactptr->strtdate = from->z.sactptr->strtdate;
    to->z.sactptr->endate = from->z.sactptr->endate;
    to->z.sactptr->line = from->z.sactptr->line;
    to->z.sactptr->strtsym = from->z.sactptr->strtsym;
    to->z.sactptr->endsym = from->z.sactptr->endsym;
    to->z.sactptr->pctdate = from->z.sactptr->pctdate;
    to->z.sactptr->done_pct = from->z.sactptr->done_pct;
    to->z.sactptr->fill_pattern = from->z.sactptr->fill_pattern;
    to->z.sactptr->disp = from->z.sactptr->disp;
    to->z.sactptr->hpos = from->z.sactptr->hpos;
    to->z.sactptr->vpos = from->z.sactptr->vpos;
    to->z.sactptr->font = from->z.sactptr->font;
    to->z.sactptr->point = from->z.sactptr->point;
    to->z.sactptr->color = from->z.sactptr->color;
    to->z.sactptr->idhpos = from->z.sactptr->idhpos;
    to->z.sactptr->idvpos = from->z.sactptr->idvpos;
    to->z.sactptr->idtog = from->z.sactptr->idtog;
    to->z.sactptr->text = XtNewString(from->z.sactptr->text);
    to->z.sactptr->idtext = XtNewString(from->z.sactptr->idtext);
    to->type = OBJ_SACT;
    to->opsptr = &sact_ops;
    to->layer = from->layer;
    to->precptr = from->precptr;
    to->rlist = copyRectList(from->rlist);
}

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

static void 
msg_sact(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.sactptr->strtdate);
    get_mdy(&mo2, &da2, &yr2, objary[i].z.sactptr->endate);
    (void)sprintf(buf, "Simple Activity: %d/%d/%d - %d/%d/%d, %d Percent Done", 
	mo, da, yr, mo2, da2, yr2, objary[i].z.sactptr->done_pct);
    Message(buf);
}

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

static void 
sav_sact(int i, FILE *fp, int dir)
{ 
    struct sact *sactptr;			/*temp object pointer */
    char buf[1024];				/* temp buffer */

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

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

static int 
load_sact(char *buf)
{
    utc_val st_date, e_date;          /* start and end date */
    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 */
    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 sact */
    char idtext[64];		      /* id text */
    int idhpos, idvpos;		      /* positioning of id text */
    int idtog;			      /* display toggle for id text */
    int i;			      /* temp index */

    if (record_scan(buf + 1, "ttdddtdddddddddqqddd", &st_date, &e_date, &line,
	&strtsym, &endsym, &pd_date, &done_pct, &fill_pattern, &layer,
	&disp, &hpos, &vpos, &font, &point, &color, text, idtext, &idtog,
	&idhpos, &idvpos) == 20)  {
	if ((line < 0) || (line > num_pages * pg_lines)) {
	    Warning("Illegal Simple Activity line %d", line);
	} else if ((strtsym < 0) || (strtsym > 16)) {
	    Warning("Illegal Simple Activity start symbol %d", strtsym);
	} else if ((endsym < 0) || (endsym > 16)) {
	    Warning("Illegal Simple Activity end symbol %d", endsym);
	} else if ((done_pct < 0) || (done_pct > 100)) {
	    Warning("Illegal Simple Activity percent complete %d", done_pct);
	} else if (((int)fill_pattern < OPEN) || 
	    ((int)fill_pattern > CROS_HATCH)) {
	    Warning("Illegal Simple Activity fill pattern %d", fill_pattern);
	} else if ((layer < 0) || (layer > 3)) {
	    Warning("Illegal Simple Activity layer %d", layer);
	} else if (((int)disp < TDS_NONE) || ((int)disp > TDS_DATE)) {
	    Warning("Illegal Simple Activity display %d", disp);
	} else if ((hpos < 0) || (hpos > 2)) {
	    Warning("Illegal Simple Activity horizontal position %d", hpos);
	} else if ((vpos < 0) || (vpos > 2)) {
	    Warning("Illegal Simple 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 Simple Activity font %d", font);
	} else if ((point != 8) && (point != 10) && (point != 12) && 
	    (point != 14) && (point != 18) && (point != 24)) {
	    Warning("Illegal Simple Activity point %d", point);
	} else if ((color < 0) || (color > ncolor)) {
	    Warning("Illegal Simple Activity color %d", color);
	} else if ((idhpos < 0) || (idhpos > 2)) {
	    Warning("Illegal Simple Activity horizontal Id position %d",idhpos);
	} else if ((idvpos < 0) || (idvpos > 2)) {
	    Warning("Illegal Simple Activity vertical Id position %d", idvpos);
	} else if ((idtog < 0) || (idtog > 1)) {
	    Warning("Illegal Simple Activity Id display %d", idtog);
	} else {
            i = add_sactivity(st_date, e_date, line, strtsym, endsym, pd_date,
	        done_pct, fill_pattern, layer, disp, hpos, vpos, font, point,
	        color, text, idtext, idtog, idhpos, idvpos);
            return 0;
	}
	return -1;
    } else {
	return -1;
    }
}

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

static void 
sactivity_ok_button(void)
{
    utc_val sdate_diff, edate_diff = 0;		/* slip in date values */
    utc_val temp_date;
    char *buf;
    int val;					/* temporary integer */

    change = DIALOG_NO_CHANGE;
    temp_date = DialogDateGet(sdate);
    if (temp_date != UTC_INVALID) {
        if (temp_date != objtmp.z.sactptr->strtdate) {
            change |= DIALOG_UPDATE;
        }
    } else {
        Warning("Improper Start Date");
        change |= DIALOG_ERROR;
    }

    /*
     * slip objects associated by precedence lines
     */
    sdate_diff = temp_date - objtmp.z.sactptr->strtdate;
    val = DialogTextGetInt(linew);
    if ((val < 1) || (val > MAX_LINE)) {
        Warning("Improper Line Position");
        change |= DIALOG_ERROR;
    } else if (val != objtmp.z.sactptr->line) {
        change |= DIALOG_UPDATE;
	objtmp.z.sactptr->line = val;
    }

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

    loa_type = DialogOptionGet(lenmenuw);
    if (new_smark != objtmp.z.sactptr->strtsym) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->strtsym = DialogOptionGet(smark);
    if (new_emark != objtmp.z.sactptr->endsym) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->endsym = DialogOptionGet(emark);

    if (new_fillpatt != objtmp.z.sactptr->fill_pattern) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->fill_pattern = DialogOptionGet(fillw);
    if (new_hpos != objtmp.z.sactptr->hpos) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->hpos = DialogOptionGet(hposw);
    if (new_vpos != objtmp.z.sactptr->vpos) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->vpos = DialogOptionGet(vposw);
    if (new_font != objtmp.z.sactptr->font) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->font = DialogOptionGet(fontw);
    if (new_point != objtmp.z.sactptr->point) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->point = DialogOptionGet(pointw);
    if (new_disp != objtmp.z.sactptr->disp) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->disp = DialogOptionGet(dispw);

    if (new_color != objtmp.z.sactptr->color) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->color = DialogOptionGet(colorw);
    if (new_idhpos != objtmp.z.sactptr->idhpos) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->idhpos = DialogOptionGet(idhposw);
    if (new_idvpos != objtmp.z.sactptr->idvpos) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->idvpos = DialogOptionGet(idvposw);
    if (new_idtog != objtmp.z.sactptr->idtog) {
        change |= DIALOG_UPDATE;
    }
    objtmp.z.sactptr->idtog = DialogOptionGet(dspidw);
    if (new_drawlyr != objtmp.layer) {
        change |= DIALOG_UPDATE;
    }
    objtmp.layer = DialogOptionGet(drawlyrw);
    buf = DialogTextGet(textw);
    if (strcmp(buf, objtmp.z.sactptr->text)) {
        change |= DIALOG_UPDATE;
	XtFree(objtmp.z.sactptr->text);
	objtmp.z.sactptr->text = buf;
    } else {
	XtFree(buf);
    }

    buf = DialogTextGet(idw);
    if (strcmp(buf, objtmp.z.sactptr->idtext)) {
        change |= DIALOG_UPDATE;
	XtFree(objtmp.z.sactptr->idtext);
	objtmp.z.sactptr->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
 */

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 */

    diff = (objtmp.z.sactptr->endate - objtmp.z.sactptr->strtdate)/UTC_ONE_DAY;
    done_days = (objtmp.z.sactptr->pctdate - objtmp.z.sactptr->strtdate)/
	UTC_ONE_DAY;
    if (done_days == diff) {
	/* pctdate is same as endate */
	objtmp.z.sactptr->done_pct = 100;
    } else if (diff == 0) {
	/* pctdate is same as strtdate */
	objtmp.z.sactptr->pctdate = objtmp.z.sactptr->strtdate;
	objtmp.z.sactptr->done_pct = 0;
    } else {
	objtmp.z.sactptr->done_pct = (done_days * 100) / diff;
    }
}

/***********************************************************************
 *
 * 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 */
    utc_val start_date, pct_date, end_date;
    int pct_val;

    if (!edit_mode) {
	objtmp.z.sactptr->pctdate = objtmp.z.sactptr->strtdate;
	if (objtmp.z.sactptr->done_pct == 0) {
	    objtmp.z.sactptr->pctdate = objtmp.z.sactptr->strtdate;
	} else if (objtmp.z.sactptr->done_pct == 100) {
	    objtmp.z.sactptr->pctdate = objtmp.z.sactptr->endate;
	} else {
	    diff = (objtmp.z.sactptr->endate - objtmp.z.sactptr->strtdate)/
		UTC_ONE_DAY;
	    pct_diff = (objtmp.z.sactptr->done_pct * diff)/100 * UTC_ONE_DAY;
	    objtmp.z.sactptr->pctdate = objtmp.z.sactptr->pctdate + pct_diff;
	}
	DialogDateSet(pctdate, objtmp.z.actptr->pctdate);
    } else {
	start_date = DialogDateGet(sdate);
	end_date = DialogDateGet(edate);
	pct_val = DialogTextGetInt(pct);
	if (pct_val == 0) {
	    DialogDateSet(pctdate, start_date);
	} else if (pct_val == 100) {
	    DialogDateSet(pctdate, end_date);
	} else {
	    diff = (end_date - start_date) / 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.sactptr->strtdate);
	    sdoff = get_wkday(objtmp.z.sactptr->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.sactptr->strtdate);
	sdoff = get_wkday(objtmp.z.sactptr->strtdate);
	if ((sdoff == 5) || (sdoff == 6)) {
	    sflag = TRUE; 			/* starts on weekend */
	} else {
	    sflag = FALSE;
	}
	get_mdy(&mo, &da, &e_yr, objtmp.z.sactptr->endate);
	edoff = get_wkday(objtmp.z.sactptr->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:
 *	edit_mode		(int)
 *
 * 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.sactptr->endate = objtmp.z.sactptr->strtdate;
	if (loa_type == 0) {
            objtmp.z.sactptr->endate += (loa * UTC_ONE_DAY);
	} else if (loa_type == 1) {
	    diff = set_loa(1, 0);	/* changes to exclude weekends */
	    objtmp.z.sactptr->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:
 *	sdate_diff, edate_diff
 *
 * 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 = FALSE;				/* a change occured */
    int endchange = FALSE;			/* change in end date */
    int pdchange = FALSE;			/* change in % done date */
    int percentchange = FALSE;			/* change in % complete */
    int loachange = FALSE;			/* change in loa */
    int loatogchange = FALSE;			/* change in loa toggle */
    utc_val temp_date;
    int val;					/* temporary integer */

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

    /*
     * percent date change 
     */
    temp_date = DialogDateGet(pctdate);
    if (temp_date != UTC_INVALID) {
        if (temp_date != objtmp.z.sactptr->pctdate) {
            pdchange = DIALOG_UPDATE;
        }
    } else {
        Warning("Improper Percent Complete Date");
        pdchange = DIALOG_ERROR;
    }
    objtmp.z.sactptr->pctdate = temp_date;
    change |= pdchange;

    /*
     * percent done value change 
     */
    val = DialogTextGetInt(pct);
    if ((val < 0) || (val > 100)) {
        Warning("Improper Percent Complete Value");
        percentchange = DIALOG_ERROR;
    } else if (val != objtmp.z.sactptr->done_pct) {
        percentchange = DIALOG_UPDATE;
    }
    objtmp.z.sactptr->done_pct = val;

    change |= percentchange;

    /*
     * length of event change 
     */
    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;

    /*
     * length of event type change
     */
    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:
 *      loaCB()
 *
 * 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 
loaCB(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_loa_date(1);
    set_pct_date(1); 
    change |= DIALOG_UPDATE;
}

/***********************************************************************
 *
 * FUNCTION:
 *      pctCB()
 *
 * 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 
pctCB(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.sactptr->done_pct = val;

    set_pct_date(1);
    change |= DIALOG_UPDATE;

}

/***********************************************************************
 *
 * FUNCTION:
 *      set_pline()
 *
 * INPUTS:
 *      sdate_diff, edate_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 dates
 */

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.sactptr->strtdate !=
                objtmp.z.sactptr->strtdate) || 
		(objary[plnary[co].obj1].z.sactptr->endate !=
		objtmp.z.sactptr->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.sactptr->strtdate !=
                objtmp.z.sactptr->strtdate) || 
		(objary[plnary[co].obj2].z.sactptr->endate !=
		objtmp.z.sactptr->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) {
        sactivity_ok_button();
    }
}
