/***********************************************************************
 *
 * TITLE:
 *	event.c
 *
 * AUTHOR:
 *	Cassie Mulnix
 *
 * DESCRIPTION:
 *	This module is part of the OPPS editor, xopps.  It contains
 *	routines to handle event objects.
 *
 *                              CHANGE HISTORY
 *
 * $Log: event.c,v $
 * Revision 1.63  1994/12/31  03:46:18  kevin
 * fixed memory allocation problem after DialogTextGet
 *
 * Revision 1.62  1994/08/10  22:02:18  cassie
 * fixed DialogFlagSet calls
 *
 * Revision 1.61  1994/07/20  19:06:35  clm
 * updated TRUE, ERROR etc in cancel & ok_button functions
 * to DIALOG_ constants
 *
 * Revision 1.60  1994/06/16  21:55:48  clm
 * updated to new dialog routines - extra parameter to DialogTextCreate
 *
 * Revision 1.59  1994/06/16  16:56:35  clm
 * updated to new gr_ routines using GR_ for font names
 *
 * Revision 1.58  1994/06/08  18:47:59  clm
 * removed Xm library includes since they are in dialog
 *
 * Revision 1.57  1994/06/07  16:36:03  clm
 * fixed order of hpos_list
 *
 * Revision 1.56  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.55  1994/05/20  23:31:43  clm
 * updated with HP, SGI changes
 *
 * Revision 1.54  1994/05/04  23:34:36  clm
 * ported to ANSI C
 *
 * Revision 1.53  1993/11/11  18:12:10  clm
 * adjusted vertical position of text
 *
 * Revision 1.52  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.51  1993/05/21  15:01:09  clm
 * fixed buffer length for sav function
 *
 * Revision 1.50  1993/05/18  22:39:41  clm
 * added meaningful error messages for check_num and check_day
 *
 * Revision 1.49  1993/05/18  20:58:30  clm
 * added new message.c function
 *
 * Revision 1.48  1993/03/25  18:56:30  clm
 * fixed placement of date and text items
 *
 * Revision 1.47  1993/02/26  17:35:47  clm
 * fixed locate for edate == end of chart
 *
 * Revision 1.46  1993/02/20  00:03:47  clm
 * added Slip Precedence Objects to edit popup
 * added Slip Successors on Line to edit popup
 *
 * Revision 1.45  1993/02/08  16:03:11  clm
 * fixed mov coordinate of line position
 * fixed loc_function for y2
 * fixed dsp_marker size to match symbol object
 * centered symbol in date
 * added Slip Successors on Line to popup
 *
 * Revision 1.44  1992/12/22  16:35:18  clm
 * fixed mov routine
 *
 * Revision 1.43  1992/12/22  16:00:38  clm
 * fixed lim and load so objects cannot be loaded or moved outside chart lines
 *
 * Revision 1.42  1992/12/15  20:40:12  clm
 * changed strlen to sizeof when assigning symbols
 *
 * Revision 1.41  1992/12/10  21:45:40  clm
 * fixed new_index so chart is always object 0
 *
 * Revision 1.40  1992/11/30  21:05:37  clm
 * fixed locate function
 *
 * Revision 1.39  1992/11/25  16:02:10  clm
 * get rid of unused variables
 *
 * Revision 1.38  1992/11/24  16:28:27  clm
 * fixed rem functions - setting of ip array
 *
 * Revision 1.37  1992/11/20  15:59:58  clm
 * fixed number of elements in load event
 *
 * Revision 1.36  1992/11/12  18:56:22  clm
 * added display date option
 *
 * Revision 1.35  1992/11/09  16:28:17  clm
 * added precedence lines
 * fixed layout of popup
 *
 * Revision 1.34  1992/10/13  18:13:18  clm
 * fixed copy of text items
 *
 * Revision 1.33  1992/10/12  21:18:03  clm
 * fixed locate routine
 *
 * Revision 1.32  1992/10/09  21:17:43  clm
 * fixed move routine
 *
 * Revision 1.31  1992/10/06  16:45:22  clm
 * fixed error checking of line to cover all pages
 *
 * Revision 1.30  1992/10/02  20:06:32  clm
 * housekeeping
 *
 * Revision 1.29  1992/09/30  22:14:03  clm
 * fixed placement of s_char
 * changed locate and display to have only one rectangle
 *
 * Revision 1.28  1992/09/28  20:45:34  clm
 * added id toggle and text
 *
 * Revision 1.27  1992/09/24  15:42:19  clm
 * fixed load of event
 *
 * Revision 1.26  1992/09/16  14:55:14  clm
 * fixed load function so doesn't add object if error in load
 *
 * Revision 1.25  1992/09/14  14:12:24  clm
 * fixed error checking of font in load_event
 *
 * Revision 1.24  1992/09/02  15:49:00  clm
 * fixed display of symbol character
 *
 * Revision 1.23  1992/08/31  21:49:56  clm
 * added color optionmenu to edit popup
 *
 * Revision 1.22  1992/08/27  21:53:52  clm
 * fixed sized of marker in locate
 *
 * Revision 1.21  1992/08/27  20:12:24  clm
 * took loc out of load function (since pg_lines and num_pages
 * are also loaded, page_end and begin have not yet been
 * reset until load is done, loc after all is loaded)
 *
 * Revision 1.20  1992/08/26  18:13:43  clm
 * fixed location of marker
 *
 * Revision 1.19  1992/08/26  17:13:42  clm
 * fixed color in display
 *
 * Revision 1.18  1992/08/25  17:45:21  clm
 * fixed loc function so that text rectangles get refreshed
 *
 * Revision 1.17  1992/08/13  18:08:56  clm
 * fixed error checking for load_event
 *
 * Revision 1.15  1992/08/10  17:41:56  clm
 * fixed loc and dsp so that object appears when pages displayed changes
 *
 * Revision 1.14  1992/08/04  17:01:10  clm
 * changed malloc and free to XtMalloc and XtFree
 *
 * Revision 1.13  1992/08/04  15:51:26  clm
 * fixed display to only occur if line is on current page
 *
 * Revision 1.12  1992/08/03  21:31:10  clm
 * changed save and load functions to time values
 *
 * Revision 1.11  1992/07/22  22:16:16  clm
 * changed mov function to reflect change in mover.c
 *
 * Revision 1.9  1992/07/15  19:41:28  clm
 * added s_char to display
 *
 * Revision 1.8  1992/07/10  16:28:47  clm
 * all of event.c is functional
 *
 * Revision 1.7  1992/05/21  21:32:47  clm
 * incorporated rectangle function
 *
 * Revision 1.5  1992/05/20  20:50:00  clm
 * fixed gr_text function call
 *
 * Revision 1.4  1992/05/20  19:50:57  clm
 * cleaned up file and help format
 *
 * Revision 1.3  1992/05/11  22:38:30  kevin
 * renamed project include file to xopps.h
 *
 * Revision 1.1  1991/09/19  00:54:00  tommy
 * Initial revision
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: event.c,v 1.63 1994/12/31 03:46:18 kevin OEL $";
#endif

/*
    event.c - an xopps module containing routines for event objects

    local functions:
        dsp_event(i) - display event object
        REM_event(i) - remove event object
        mov_event(i) - move event object
        edt_event(i) - change contents of event field
        msg_event(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 event_ok_button(void);		/* Callback for ok button */
static void cancel_button(void);	/* Callback for cancel button */
static void change_point(Widget, XtPointer, XtPointer);
static void change_font(Widget, XtPointer, XtPointer);
static void change_mark(Widget, XtPointer, XtPointer);
static void change_drawlyr(Widget, XtPointer, XtPointer);
static void change_hpos(Widget, XtPointer, XtPointer);
static void change_hpos2(Widget, XtPointer, XtPointer);
static void change_vpos(Widget, XtPointer, XtPointer);
static void change_vpos2(Widget, XtPointer, XtPointer);
static void change_color(Widget, XtPointer, XtPointer);
static void change_idvpos(Widget, XtPointer, XtPointer);
static void change_idhpos(Widget, XtPointer, XtPointer);
static void change_idtog(Widget, XtPointer, XtPointer);
static void change_disp(Widget, XtPointer, XtPointer);
static void change_slip(Widget, XtPointer, XtPointer);
static void change_pline(Widget, XtPointer, XtPointer);
static void set_pline(utc_val);			/* executes pline slips */
static void dsp_event(int);
static void edt_event(int, int);
static void rem_event(int, int);
static void lim_event(int, int *, int *, int *, int *, int);
static void loc_event(int, int);
static void mov_event(int, int, int, int);
static void cpy_event(struct obj *, struct obj *);
static void msg_event(int, int);
static void sav_event(int, FILE *, int);
static int load_event(char *);
static void verify_fun(Widget, XtPointer, XtPointer);

                                              /* function pointer */
static struct ops evt_ops = {
    dsp_event, edt_event, rem_event, lim_event, loc_event, mov_event,
    cpy_event, msg_event, sav_event
};

static DialogDate *date;
static DialogText *linew, *labelc;
static DialogText *text1, *text2, *id;
static DialogOption *marker;
static DialogOption *hpos, *vpos;
static DialogOption *hpos2, *vpos2;
static DialogOption *idhpos, *idvpos;
static DialogOption *idtog, *font, *point;
static DialogOption *color;
static DialogOption *drawlyr, *disp;
static DialogOption *slip_evts, *slip_pobjs;

                                              /* function pointer */

static Widget event_dialog;			/* dialog shell for popup */
static int nmarks;				/* number of markers */
static int new_point;                           /* new point id */
static int new_font;                            /* new font id */
static int new_marker;				/* new marker id */
static int new_drawlyr;				/* new draw layer id */
static int new_vpos;				/* new vertical pos id */
static int new_hpos;				/* new horizontal pos id */
static int new_vpos2;				/* new vertical pos id */
static int new_hpos2;				/* new horizontal pos id */
static int new_idhpos;				/* new horiz. pos for id */
static int new_idvpos;				/* new vertical pos for id */
static int new_idtog;				/* new toggle value for id */
static int new_color;				/* new color id */
static int new_disp;				/* new date display */

static int pline_flag = FALSE;			/* slip plines flag */
static int days_flag = FALSE;
static Widget parent_shell;

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

void 
init_event_object(Widget parent)
{
    register_io_obj('E', load_event);		/* register object */
    parent_shell = parent;

}

/***********************************************************************
 *
 * FUNCTION:
 *	create_dialog()
 *
 * INPUTS:
 *	none
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	none
 *
 * DESCRIPTION:
 *	sets the widgets for an event object
 */

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

    static char *hpos_list[] = { "Left", "Right", "Center" };
    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 *opts[] = { "No", "Yes" };

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

    event_dialog = DialogInit(parent_shell, "Event Object", "event", 
	verify_fun, (XtPointer)DIALOG_CANCEL);

    DialogAddRow(2);
    date = DialogDateCreate("Event Date ");
    linew = DialogTextCreate("Line Position ", 2, 2);

    DialogAddRow(2);
    marker = DialogOptionCreate("Event Marker ", nmarks, 0, change_mark, 
	DIALOG_OPT_PIX_ARY, marks, NULL);
    labelc = DialogTextCreate("Label Character ", 1, 1);

    text1 = DialogTextCreate("Text 1 ", 50, 100);

    DialogAddRow(2);
    hpos = DialogOptionCreate("Horiz. Position Text 1 ", 3, 2, change_hpos, 
	DIALOG_OPT_STR_ARY, hpos_list, NULL);
    vpos = DialogOptionCreate("Vert. Position Text 1 ", 3, 0, change_vpos, 
	DIALOG_OPT_STR_ARY, vpos_list, NULL);

    text2 = DialogTextCreate("Text 2 ", 50, 100);

    DialogAddRow(2);
    hpos2 = DialogOptionCreate("Horiz. Position Text 2 ", 3, 2, change_hpos2, 
	DIALOG_OPT_STR_ARY, hpos_list, NULL);
    vpos2 = DialogOptionCreate("Vert. Position Text 2 ", 3, 1, change_vpos2, 
	DIALOG_OPT_STR_ARY, vpos_list, NULL);

    DialogAddRow(2);
    id = DialogTextCreate("Id ", 25, 100);
    idtog = DialogOptionCreate("Display Id ", 2, 0, change_idtog, 
	DIALOG_OPT_STR_ARY, disps, NULL);

    DialogAddRow(2);
    idhpos = DialogOptionCreate("Id Horiz. Position ", 3, 0, change_idhpos, 
	DIALOG_OPT_STR_ARY, hpos_list, NULL);
    idvpos = DialogOptionCreate("Id Vert. Position ", 3, 2, change_idvpos, 
	DIALOG_OPT_STR_ARY, vpos_list, NULL);
    
    DialogAddRow(2);
    font = DialogOptionCreate("Font ", 6, 4, change_font, DIALOG_OPT_STR_ARY,
	fonts, font_values);
    point = DialogOptionCreate("Point ", 6, 10, change_point, 
	DIALOG_OPT_STR_ARY, points, font_sizes);

    DialogAddRow(3);
    color = DialogOptionCreate("Color ", ncolor, 0, change_color, 
	DIALOG_OPT_STR_ARY, color_name, color_index);
    drawlyr = DialogOptionCreate("Draw Layer ", 4, 0, change_drawlyr, 
	DIALOG_OPT_STR_ARY, drawlyrs, NULL);
    disp = DialogOptionCreate("Display Date", 3, 0, change_disp, 
	DIALOG_OPT_STR_ARY, dates, NULL);

    slip_evts = DialogOptionCreate("Slip Successor Events on Line ", 2, 0,
	change_slip, DIALOG_OPT_STR_ARY, opts, NULL);
    
    slip_pobjs = DialogOptionCreate("Slip Precedence Objects ", 2, 0, 
	change_pline, DIALOG_OPT_STR_ARY, opts, NULL);

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

}

/***********************************************************************
 *
 * FUNCTION:
 *	add_event()
 *
 * INPUTS:
 *	edate	(utc_val)
 *	line, sym	(int)
 *	s_char	(char *)
 *	moffset	(int)
 *	text, text2	(char *)
 *	font, hpos1, vpos1, hpos2, vpos2, layer, color 	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	adds an event object
 */

int 
add_event(utc_val edate, int line, int sym, char *s_char, int moffset, char *text, char *text2,	int font, int point, int hpos1, int hpos2, int vpos1, int vpos2, int layer, int color, enum tds disp, char *idtext, int idtog, int idhpos, int idvpos)
{
    int i;              	/* index */

    i = new_index(FALSE);
    objary[i].z.evtptr = (struct evt *)XtMalloc(sizeof(struct evt));
    objary[i].z.evtptr->line = line;
    objary[i].z.evtptr->sym = sym;
    objary[i].z.evtptr->s_char = XtNewString(s_char);
    objary[i].z.evtptr->moffset = moffset;
    objary[i].z.evtptr->font = font;
    objary[i].z.evtptr->point = point;
    objary[i].z.evtptr->hpos1 = hpos1;
    objary[i].z.evtptr->hpos2 = hpos2;
    objary[i].z.evtptr->vpos1 = vpos1;
    objary[i].z.evtptr->vpos2 = vpos2;
    objary[i].z.evtptr->edate = edate;
    objary[i].z.evtptr->color = color;
    objary[i].z.evtptr->disp = disp;
    objary[i].z.evtptr->text = XtNewString(text);
    objary[i].z.evtptr->text2 = XtNewString(text2);
    objary[i].z.evtptr->idhpos = idhpos;
    objary[i].z.evtptr->idvpos = idvpos;
    objary[i].z.evtptr->idtog = idtog;
    objary[i].z.evtptr->idtext = XtNewString(idtext);
    objary[i].type = OBJ_EVT;
    objary[i].layer = layer;
    objary[i].opsptr = &evt_ops;
    return i;
}

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

static void 
dsp_event(int i)
{
    struct evt *evtptr;         /* local pointer */
    int sym;                    /* event symbol */
    XRectangle *(*line_rect)[];	/* rectangle */
    enum tog mask;              /* mask for white background */
    int font_height;		/* height of font */
    int font_width;		/* width of font */
    int width;			/* width of text string */
    int x;			/* temp x coordinate */
    int text_x, text_y;		/* x and y coordinates for text */
    int sym_x, sym_y;		/* x and y coordinates for symbol char */
    char buf[6];		/* temp buffer for date */
    int dxtime;			/* length of date */
    int mo, da, yr;		/* parse of date */
    int utc_date;		/* utc doy of date */
    int txwidth;		/* width and of font character */

    evtptr = objary[i].z.evtptr;
    gr_set_color(color_name[evtptr->color], color_gscale[evtptr->color]);
    if (((evtptr->line >= page_begin) && (evtptr->line <= page_end)) &&
	((evtptr->edate >= objary[0].z.chtptr->start_date) && (evtptr->edate
	< objary[0].z.chtptr->end_date))) {
        font_height = gr_txheight(evtptr->font|evtptr->point);
	font_width = gr_strwidth(evtptr->s_char, (evtptr->font|evtptr->point));

       /* 
     	* display marker 
	*/
        if (auto_ereset == TOG_ON) { /* fill appropriate symbols */
            if (st_date >= evtptr->edate) {
            /* objects to left of (and on) status line */
                sym = evtptr->sym;
                if ((sym == 0) || (sym == 2) || (sym == 4) || (sym == 10)) {
                    evtptr->sym = sym + 1;
                }
       	    } else { /* objects to right of status line */
                sym = evtptr->sym;
                if ((sym == 1) || (sym == 3) || (sym == 5) || (sym == 11) ||
	            (sym == 13)) {
                    evtptr->sym = sym - 1;
                }
            }
        }
	x = utc_to_x(evtptr->edate + UTC_ONE_DAY/2) + 1;
    	line_rect = getMoveRect(Hobjary[hln_objary[evtptr->line]].rlist);
  	dsp_marker(evtptr->sym, x - y_gap/2 + 1, (*line_rect)[0]->y + 3, 
	   y_gap - 5, 0);
	if (evtptr->s_char != "") {
	    if (evtptr->sym == 0) {
		sym_x = x - font_width/2;
		sym_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 + 1;
	    } else if (evtptr->sym == 2) {
		sym_x = x - font_width/2;
                sym_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 + 2;
	    } else if (evtptr->sym == 4) {
		sym_x = x - font_width/2;
                sym_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 - 1;
	    } else if (evtptr->sym == 10) {
		sym_x = x - font_width/2 - 1;
                sym_y = (*line_rect)[0]->y + y_gap/2 + font_height/2;
	    } else {
		sym_x = x - font_width/2;
		sym_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 + 1;
	    }
	    gr_text(sym_x, sym_y, evtptr->s_char, GR_LEFT, 
		(evtptr->font|evtptr->point), 0);
        }

	if (objary[i].layer == 0) {
      	    mask = TOG_OFF;
    	} else {
      	    mask = TOG_ON;
        }

	/*
	 * display text 1
	 */
	txwidth = gr_txwidth(evtptr->font|evtptr->point);
	if (evtptr->disp == TDS_DOY) {
	    utc_date = get_doy(evtptr->edate);
	    (void)sprintf(buf, "%03d", utc_date);
	    dxtime = (strlen(buf) + 1) * txwidth;
	} else if (evtptr->disp == TDS_DATE) {
	    get_mdy(&mo, &da, &yr, evtptr->edate);
	    (void)sprintf(buf, "%d/%d", mo, da);
	    dxtime = (strlen(buf) + 1) * txwidth;
	} else {
	   (void)sprintf(buf, "%s", "");
	   dxtime = 0;
	}
	width = gr_strwidth(evtptr->text, evtptr->font|evtptr->point);
	if (evtptr->text != NULL) {
	    switch (evtptr->hpos1) {
	    case TX_LEFT:
		if (evtptr->disp == TDS_NONE) {
		    text_x = x - y_gap/2 - width - 2;
		} else {
		    text_x = x - y_gap - width - 4 - txwidth;  
	 	}
		break;
	    case TX_RIGHT:
		text_x = x + y_gap/2 + 2;
		break;
	    default:
		text_x = x - width/2;
		break;
	    }
	    switch (evtptr->vpos1) {
	    case TX_ABOVE:
	 	text_y = (*line_rect)[0]->y;
		break;
	    case TX_BELOW:
		text_y = (*line_rect)[0]->y + y_gap + font_height + 2;
		break;
	    default:
		text_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 + 1;
		break;
	    }
        }
	gr_text(x - y_gap - txwidth, (*line_rect)[0]->y + y_gap/2 + 
	    font_height/2+1, buf, GR_LEFT, (evtptr->font|evtptr->point), 
	    (int)mask);
	gr_text(text_x, text_y, evtptr->text, GR_LEFT,
	    (evtptr->font|evtptr->point), (int)mask);

	/*
	 * display text 2
	 */
	width = gr_strwidth(evtptr->text2, evtptr->font|evtptr->point);
	if (evtptr->text2 != NULL) {
	    switch (evtptr->hpos2) {
	    case TX_LEFT:
		if (evtptr->disp == TDS_NONE) {
		    text_x = x - y_gap/2 - width - 2;
		} else {
		    text_x = x - y_gap - width - txwidth - 4;
		}
		break;
	    case TX_RIGHT:
		text_x = x + y_gap/2 + 2;
		break;
	    default:
		text_x = x - width/2;
		break;
	    }
	    switch (evtptr->vpos2) {
	    case TX_ABOVE:
	 	text_y = (*line_rect)[0]->y;
		break;
	    case TX_BELOW:
		text_y = (*line_rect)[0]->y + y_gap + font_height + 2;
		break;
	    default:
		text_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 + 1;
		break;
	    }
        }
	gr_text(x - y_gap - txwidth, (*line_rect)[0]->y + y_gap/2 + 
	    font_height/2+1, buf, GR_LEFT, (evtptr->font|evtptr->point), 
	    (int)mask);
	gr_text(text_x, text_y, evtptr->text2, GR_LEFT,
	    (evtptr->font|evtptr->point), (int)mask);

	/*
	 * display id text
	 */
	if (evtptr->idtog == TOG_ON) {
	    if (evtptr->idtext != NULL) {
	        width = gr_strwidth(evtptr->idtext, 
		    evtptr->font|evtptr->point);
	        if (evtptr->text != NULL) {
	            switch (evtptr->idhpos) {
	            case TX_LEFT:
			if (evtptr->disp == TDS_NONE) {
		    	    text_x = x - y_gap/2 - width - 2;
			} else {
		    	    text_x = x - y_gap - width - txwidth - 4;
			}
		        break;
	            case TX_RIGHT:
		        text_x = x + y_gap/2 + 1;
		        break;
	            default:
		        text_x = x - width/2;
		        break;
	            }
	            switch (evtptr->idvpos) {
	            case TX_ABOVE:
	 	        text_y = (*line_rect)[0]->y;
	        	break;
	            case TX_BELOW:
		        text_y = (*line_rect)[0]->y + y_gap + font_height + 2;
		        break;
	            default:
		        text_y = (*line_rect)[0]->y + y_gap/2 + font_height/2 
			    + 1;
		        break;
	            }
                }
	       gr_text(text_x, text_y, evtptr->idtext, GR_LEFT,
		    (evtptr->font|evtptr->point), (int)mask);
	    }
	}
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	msg_event()
 *
 * INPUTS:
 *	i	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	displays the event message for event i
 */

static void 
msg_event(int i, int dir)
{
    char buf[64];				/* temp buffer */
    int mo, da, yr;				/* month, day, and year */

    get_mdy(&mo, &da, &yr, objary[i].z.evtptr->edate);
    (void)sprintf(buf, "Event: %d/%d/%d", mo, da, yr); 
    Message(buf);
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_point()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the selected font point size.
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_font()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module changes the selected font.
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_mark()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the selected mark.
 */

static void 
change_mark(Widget button, XtPointer option, XtPointer any_data)
{
    new_marker = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_drawlyr()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the selected draw layer.
 */

static void 
change_drawlyr(Widget button, XtPointer option, XtPointer any_data)
{
    new_drawlyr = (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_vpos()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the selected vertical label position
 *	with respect to the object.
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_vpos2()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the selected vertical label position
 *	with respect to the object.
 */

static void 
change_vpos2(Widget button, XtPointer option, XtPointer any_data)
{
    new_vpos2 = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_hpos()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the new horizontal position of the label
 *	with respect to the object.
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_hpos2()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module sets the new horizontal position of the label
 *	with respect to the object.
 *
 */

static void 
change_hpos2(Widget button, XtPointer option, XtPointer any_data)
{
    new_hpos2 = (int)option;
}

/***********************************************************************
 *
 * FUNCTION:
 *      change_idhpos()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the new horizontal position of the id
 *      with respect to the object.
 *
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_idvpos()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the new horizontal position of the id
 *      with respect to the object.
 *
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_idtog()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the id display toggle to the input value
 *
 */

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


/***********************************************************************
 *
 * FUNCTION:
 *      change_color()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the new color for the object.
 *
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      change_slip()
 *
 * INPUTS:
 *      button          - (Widget)
 *      option          - (XtPointer)
 *      any_data        - (XtPointer)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      This module sets the slip successor value for events
 *
 */

static void 
change_slip(Widget button, XtPointer option, XtPointer any_data)
{
    days_flag = (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 events
 *
 */

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

/***********************************************************************
 *
 * FUNCTION:
 *      event_ok_button()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module checks input after ok button is pressed.
 */

static void 
event_ok_button(void)
{
    int change = DIALOG_NO_CHANGE;	/* object changed */
    int i;				/* object counter */
    utc_val date_diff;			/* change in date */
    utc_val temp_date;			/* temp date value */
    int line;				/* line of object */
    char *buf;				/* temporary buffer */
    int val;				/* temporary int value */

    date_diff = 0;
    temp_date = DialogDateGet(date);
    if (temp_date != UTC_INVALID) {
        if (temp_date != objtmp.z.evtptr->edate) {
	    change |= DIALOG_UPDATE;
	}
    } else {
	Warning("Improper Event Date");
	change |= DIALOG_ERROR;
    }
    date_diff = temp_date - objtmp.z.evtptr->edate;
    if (days_flag) {		/* reset date for successor events on line */
	line = objtmp.z.evtptr->line;
	if ((int)date_diff > 0) {		/* date slipped forward */
	    for (i = 0; i < nobj; i++) {
		if ((objary[i].type == OBJ_EVT) && 
		    (objary[i].z.evtptr != objtmp.z.evtptr) && 
		    (objary[i].z.evtptr->line == line)) {
		    if (objary[i].z.evtptr->edate >= objtmp.z.evtptr->edate) {
		        objary[i].z.evtptr->edate = objary[i].z.evtptr->edate +
			    date_diff;
			(*(objary[i].opsptr->loc))(i, OBJECT);
		    }
		}
	    }
	}
    }
    /* 
     * reset date for pline objects 
     */
    set_pline(date_diff);

    objtmp.z.evtptr->edate = temp_date;

    val = DialogTextGetInt(linew);
    if ((val < 1) || (val > MAX_LINE)) {
        Warning("Improper Line Position");
        change |= DIALOG_ERROR;
    } else if (val != objtmp.z.evtptr->line) {
	change |= DIALOG_UPDATE;
	objtmp.z.evtptr->line = val;
    }

    if (new_marker != objtmp.z.evtptr->sym) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->sym = DialogOptionGet(marker);

    buf = DialogTextGet(labelc);
    if (strcmp(buf, objtmp.z.evtptr->s_char)) {
	change |= DIALOG_UPDATE;
	XtFree(objtmp.z.evtptr->s_char);
	objtmp.z.evtptr->s_char = buf;
    } else {
	XtFree(buf);
    }

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

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

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

    if (new_font != objtmp.z.evtptr->font) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->font = DialogOptionGet(font);

    if (new_point != objtmp.z.evtptr->point) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->point = DialogOptionGet(point);

    if (new_hpos != objtmp.z.evtptr->hpos1) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->hpos1 = DialogOptionGet(hpos);

    if (new_vpos != objtmp.z.evtptr->vpos1) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->vpos1 = DialogOptionGet(vpos);

    if (new_hpos2 != objtmp.z.evtptr->hpos2) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->hpos2 = DialogOptionGet(hpos2);

    if (new_vpos2 != objtmp.z.evtptr->vpos2) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->vpos2 = DialogOptionGet(vpos2);

    if (new_idhpos != objtmp.z.evtptr->idhpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->idhpos = DialogOptionGet(idhpos);

    if (new_idvpos != objtmp.z.evtptr->idvpos) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->idvpos = DialogOptionGet(idvpos);

    if (new_idtog != objtmp.z.evtptr->idtog) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->idtog = DialogOptionGet(idtog);

    if (new_drawlyr != objtmp.layer) {
	change |= DIALOG_UPDATE;
    }
    objtmp.layer = DialogOptionGet(drawlyr);

    if (new_disp != objtmp.z.evtptr->disp) {
	change |= DIALOG_UPDATE;
    }
    objtmp.z.evtptr->disp = DialogOptionGet(disp);

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

    object_change = change;
    DialogFlagSet(change);
}

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

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

/***********************************************************************
 *
 * FUNCTION:
 *      mov_event()
 *
 * INPUTS:
 *	i, x, y		(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION: 
 *	This module moves the event object when the middle mouse
 * 	button is pressed.
 */
static void 
mov_event(int i, int x, int y, int dir)
{
    utc_val edate;				/* event date */
    struct evt *evtptr;				/* object pointer */
    XRectangle *(*line_r)[];			/* horiz. line rectangle */
 
    evtptr = objary[i].z.evtptr;
    x = utc_to_x(evtptr->edate) + x;
    x_to_utc(x, &edate);

    objary[i].z.evtptr->edate = edate;
    line_r = getMoveRect(Hobjary[hln_objary[evtptr->line]].rlist);
    objary[i].z.evtptr->line = (((*line_r)[0]->y + y + 2 - y_act_bottom) /y_gap)
	+ page_begin;
}

/***********************************************************************
 *
 * FUNCTION:
 *      sav_event()
 *
 * INPUTS:
 *	i		(int)
 *	fp		(FILE *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	This module saves event i to file fp.
 *
 */

static void 
sav_event(int i, FILE *fp, int dir)
{
    struct evt *evtptr;			/* event pointer */
    char buf[1024];			/* temp text buffer */
    
    evtptr = objary[i].z.evtptr;
    buf[0] = 'E';
    buf[1] = ' ';
    record_print(buf+2, "tddqdqqdddddddddqddd", evtptr->edate, evtptr->line, 
	evtptr->sym, evtptr->s_char, evtptr->moffset, evtptr->text,
	evtptr->text2, evtptr->font, evtptr->point, evtptr->hpos1,
	evtptr->hpos2, evtptr->vpos1, evtptr->vpos2, objary[i].layer,
	evtptr->color, evtptr->disp, evtptr->idtext, evtptr->idtog, 
	evtptr->idhpos, evtptr->idvpos); 
    fputs(buf, fp);
}

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

static int 
load_event(char *buf)
{
    utc_val edate;				/* event date */
    int line, sym;				/* line and symbol */
    char s_char[2];				/* character in symbol */
    int moffset; 				/* offset of marker */
    char text[128], text2[128];			/* text buffers */
    int font, point, hpos1, hpos2, vpos1, vpos2;/* event objects */
    int layer,color;
    enum tds disp;
    int idhpos, idvpos, idtog;			/* id placement */
    char idtext[128];				/* id text */
    int i;					/* temp index */

    if (record_scan(buf + 1, "tddqdqqdddddddddqddd", &edate, &line, &sym,s_char,
	&moffset, text, text2, &font, &point, &hpos1, &hpos2, &vpos1,
	&vpos2, &layer, &color, &disp, idtext, &idtog, &idhpos, &idvpos)== 20) {
	if ((line < page_begin) || (line > num_pages * pg_lines)) {
            Warning("Illegal Event line %d", line);
	} else if ((sym < 0) || (sym > 16)) {
	    Warning("Illegal Event symbol %d", sym);
	} else if ((font != GR_COURIER) && (font != GR_COURIER_BOLD) &&
		(font != GR_TIMES) && (font != GR_TIMES_BOLD) && 
		(font != GR_HELVETICA) && (font != GR_HELVETICA_BOLD)) {
            Warning("Illegal Event font %d", font);
        } else if ((point != 8) && (point != 10) && (point != 12) &&
            (point != 14) && (point != 18) && (point != 24)) {
            Warning("Illegal Event point %d", point);
        } else if ((hpos1 < 0) || (hpos1 > 2)) {
	    Warning("Illegal Event horizontal position 1 %d", hpos1);
        } else if ((hpos2 < 0) || (hpos2 > 2)) {
	    Warning("Illegal Event horizontal position 2 %d", hpos2);
        } else if ((vpos1 < 0) || (vpos1 > 2)) {
	    Warning("Illegal Event vertical position 1 %d", vpos1);
        } else if ((vpos2 < 0) || (vpos2 > 2)) {
	    Warning("Illegal Event vertical position 2 %d", vpos2);
	} else if ((layer < 0) || (layer > 3)) {
            Warning("Illegal Event layer %d", layer);
	} else if ((color < 0) || (color > ncolor)) {
	    Warning("Illegal Event color %d", color);
	} else if (((int)disp < TDS_NONE) || ((int)disp > TDS_DATE)) {
	    Warning("Illegal Event display %d", disp);
        } else if ((idhpos < 0) || (idhpos > 2)) {
	    Warning("Illegal Event horizontal ID position %d", idhpos);
        } else if ((idvpos < 0) || (idvpos > 2)) {
	    Warning("Illegal Event Vertical ID position %d", idvpos);
        } else if ((idtog < 0) || (idtog > 2)) {
	    Warning("Illegal Event ID toggle display %d", idtog);
 	} else {
            i = add_event(edate, line, sym, s_char, moffset, text, text2, font,
	        point, hpos1, hpos2, vpos1, vpos2, layer, color, disp, idtext, 
		idtog, idhpos, idvpos);
            return 0;
	}
        return -1;
    } else {
        return -1;
    }
}

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

static void 
cpy_event(struct obj *to, struct obj *from)
{
    if (from->type == OBJ_NUL) {
	 return;
    }

    to->z.evtptr = (struct evt *)XtMalloc(sizeof(struct evt));
    to->z.evtptr->edate = from->z.evtptr->edate;
    to->z.evtptr->line = from->z.evtptr->line;
    to->z.evtptr->sym = from->z.evtptr->sym;
    to->z.evtptr->s_char = from->z.evtptr->s_char;
    to->z.evtptr->moffset = from->z.evtptr->moffset;
    to->z.evtptr->font = from->z.evtptr->font;
    to->z.evtptr->point = from->z.evtptr->point;
    to->z.evtptr->hpos1 = from->z.evtptr->hpos1;
    to->z.evtptr->hpos2 = from->z.evtptr->hpos2;
    to->z.evtptr->vpos1 = from->z.evtptr->vpos1;
    to->z.evtptr->vpos2 = from->z.evtptr->vpos2;
    to->z.evtptr->color = from->z.evtptr->color;
    to->z.evtptr->idhpos = from->z.evtptr->idhpos;
    to->z.evtptr->idvpos = from->z.evtptr->idvpos;
    to->z.evtptr->idtog = from->z.evtptr->idtog;
    to->z.evtptr->disp = from->z.evtptr->disp;
    to->z.evtptr->text = XtNewString(from->z.evtptr->text);
    to->z.evtptr->text2 = XtNewString(from->z.evtptr->text2);
    to->z.evtptr->idtext = XtNewString(from->z.evtptr->idtext);
    to->type = OBJ_EVT;
    to->layer = from->layer;
    to->opsptr = &evt_ops;
    to->precptr = from->precptr;
    to->rlist = copyRectList(from->rlist);
}

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

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

    switch (i) {
    default:
	objptr = &(objary[i]);
	break;
    case BACK:
	objptr = &objbck;
	break;
    case TEMP:
	objptr = &objtmp;
	prec = 1;
	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((char *)objptr->z.evtptr);
    rem_object(objptr);
}

/***********************************************************************
 *
 * FUNCTION:
 *	edt_event()
 *
 * INPUTS:
 *	i, new	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	edits object i
 */

static void 
edt_event(int i, int new)
{
    char buf[3];

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

    (*(objary[i].opsptr->cpy))(&objtmp, &objary[i]);
    new_point = objtmp.z.evtptr->point;
    new_font = objtmp.z.evtptr->font;
    new_hpos = objtmp.z.evtptr->hpos1;
    new_hpos2 = objtmp.z.evtptr->hpos2;
    new_vpos = objtmp.z.evtptr->vpos1;
    new_vpos2 = objtmp.z.evtptr->vpos2;
    new_marker = objtmp.z.evtptr->sym;
    new_color = objtmp.z.evtptr->color;
    new_idhpos = objtmp.z.evtptr->idhpos;
    new_idvpos = objtmp.z.evtptr->idvpos;
    new_idtog = objtmp.z.evtptr->idtog;
    new_disp = objtmp.z.evtptr->disp;
    new_drawlyr = objtmp.layer;
    days_flag = FALSE;
    pline_flag = FALSE;
    if (new) {
    /*
     * only call rem when UNDO option is added
     */
	(*(objary[i].opsptr->rem))(i, OBJECT);
	i = -1;
    }

    DialogDateSet(date, objtmp.z.evtptr->edate);

    sprintf(buf, "%d", objtmp.z.evtptr->line);
    DialogTextSet(linew, buf);

    DialogOptionSet(font, (int)new_font);
    DialogOptionSet(point, (int)new_point);
    DialogOptionSet(hpos, (int)new_hpos);
    DialogOptionSet(hpos2, (int)new_hpos2);
    DialogOptionSet(vpos, (int)new_vpos);
    DialogOptionSet(vpos2, (int)new_vpos2);
    DialogOptionSet(idhpos, (int)new_idhpos);
    DialogOptionSet(idvpos, (int)new_idvpos);
    DialogOptionSet(idtog, (int)new_idtog);
    DialogOptionSet(marker, (int)new_marker);
    DialogOptionSet(color, (int)new_color);
    DialogOptionSet(drawlyr, (int)new_drawlyr);
    DialogOptionSet(disp, (int)new_disp);

    DialogTextSet(labelc, objtmp.z.evtptr->s_char);

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

    DialogOptionSet(slip_evts, (int)days_flag);
    DialogOptionSet(slip_pobjs, (int)pline_flag);

    DialogTextSet(text1, objtmp.z.evtptr->text);
    DialogTextSet(text2, objtmp.z.evtptr->text2);
    DialogTextSet(id, objtmp.z.evtptr->idtext);
    EditObject(i, event_dialog);
}

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

static void 
loc_event(int i, int dir)
{
    struct evt *evtptr;			/* local pointer */
    int height, width;			/* text width and height */
    XRectangle r;			/* rectangles for text and marker */
    XRectangle *(*line_r)[];		/* rectangle for line event is on */
    int ln_pos;				/* line position of event */
    char buf[6];			/* buffer for date */
    int mo, da, yr;			/* parse out date */
    int utc_date;			/* utc doy of date */
    int txwidth;			/* width of font character */
    int dxtime;				/* length of date */

    evtptr = objary[i].z.evtptr;
    height = gr_txheight(evtptr->font|evtptr->point);
    
    if (((evtptr->line < page_begin) || (evtptr->line > page_end)) ||
	((evtptr->edate < objary[0].z.chtptr->start_date) || 
	(evtptr->edate >= objary[0].z.chtptr->end_date))) {
	    setRectList(objary[i].rlist,0);
	    return;
    }

    txwidth = gr_txwidth(evtptr->font|evtptr->point);
    if (evtptr->disp == TDS_DOY) {
        utc_date = get_doy(evtptr->edate);
        (void)sprintf(buf, "%03d", utc_date);
        dxtime = (strlen(buf) + 1) * txwidth;
    } else if (evtptr->disp == TDS_DATE) {
        get_mdy(&mo, &da, &yr, evtptr->edate);
        (void)sprintf(buf, "%d/%d", mo, da);
        dxtime = (strlen(buf) + 1) * txwidth;
    } else {
       (void)sprintf(buf, "%s", "");
       dxtime = 0;
    }

    /*
     * initial rectangle
     */
    if (evtptr->disp == TDS_NONE) {
	r.x = utc_to_x(evtptr->edate + UTC_ONE_DAY/2) - y_gap/2 - 1;
    } else {
        r.x = utc_to_x(evtptr->edate + UTC_ONE_DAY/2) - y_gap - txwidth - 3;
    }
    ln_pos = hln_objary[evtptr->line];
    line_r = getMoveRect(Hobjary[ln_pos].rlist);
    r.y = (*line_r)[0]->y + 1;  
    r.height = y_gap + 2;
    r.width = y_gap-1 + dxtime;

    /*
     * adjust rectangle for text placement 
     */
    width = gr_strwidth(evtptr->text, evtptr->font|evtptr->point);
    if (gr_strwidth(evtptr->text2, evtptr->font|evtptr->point) > width) {
	width = gr_strwidth(evtptr->text2, evtptr->font|evtptr->point);
    }
    if (gr_strwidth(evtptr->idtext, evtptr->font|evtptr->point) > width) {
	width = gr_strwidth(evtptr->idtext, evtptr->font|evtptr->point);
    }
    /*
     * adjust x if text exists
     */
    if (((evtptr->hpos1 == TX_LEFT) && (strcmp(evtptr->text, "") != 0)) || 
	((evtptr->hpos2 == TX_LEFT) && (strcmp(evtptr->text2, "") != 0)) ||
	((evtptr->idhpos == TX_LEFT) && (strcmp(evtptr->idtext, "") != 0))) {
	r.x = r.x - width;
	r.width = r.width + width + 1;
	objary[i].z.evtptr->moffset = r.width; 
    } else if (((evtptr->hpos1 == TX_CENTER) && (strcmp(evtptr->text, "") != 0))
	|| ((evtptr->hpos2 == TX_CENTER) && (strcmp(evtptr->text2, "") != 0)) ||
	((evtptr->idhpos == TX_CENTER) && (strcmp(evtptr->idtext, "") != 0))) {
	r.x = r.x - width/2 - 1;
	r.width = r.width + width/2 + 1;
    }
    /*
     * adjust width only if text exists
     */
    if (((evtptr->hpos1 == TX_CENTER) && (strcmp(evtptr->text, "") != 0)) || 
	((evtptr->hpos2 == TX_CENTER) && (strcmp(evtptr->text2, "") != 0)) ||
	((evtptr->idhpos == TX_CENTER) && (strcmp(evtptr->idtext, "") != 0))) {
	r.width = r.width + width/2 + 1;
	objary[i].z.evtptr->moffset = r.width/2;
    }
    if (((evtptr->hpos1 == TX_RIGHT) && (strcmp(evtptr->text, "") != 0)) || 
	((evtptr->hpos2 == TX_RIGHT) && (strcmp(evtptr->text2, "") != 0)) ||
	((evtptr->idhpos == TX_RIGHT) && (strcmp(evtptr->idtext, "") != 0))) {
	r.width = r.width + width + 1;
	objary[i].z.evtptr->moffset = 0;
    }
    /*
     * adjust y and height if text string is not empty
     */
    if (((evtptr->vpos1 == TX_ABOVE) && (strcmp(evtptr->text, "") != 0)) || 
	((evtptr->vpos2 == TX_ABOVE) && (strcmp(evtptr->text2, "")!= 0)) ||
	((evtptr->idvpos == TX_ABOVE) && (strcmp(evtptr->idtext, "") != 0))) {
	r.y = r.y - 1 - height;
	r.height = r.height + height + 1;
    }
    if (((evtptr->vpos1 == TX_BELOW) && (strcmp(evtptr->text, "") != 0)) || 
	((evtptr->vpos2 == TX_BELOW) && (strcmp(evtptr->text2, "") != 0)) ||
	((evtptr->idvpos == TX_BELOW) && (strcmp(evtptr->idtext, "") != 0))) {
	r.height = r.height + height + 1;
    }

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

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

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

    r = getMoveRect(objary[i].rlist);
    if (snap_evt == TOG_OFF) {
	*x1 = x_time_offset;
	*y1 = y_act_bottom;
	*x2 = xlnary[nxln-1].z.lnptr->cord - (1 + (*r)[0]->width);
	*y2 = y_lines_end - y_gap;
    } else {
	*x1 = (*r)[0]->x;
	*y1 = y_act_bottom;
	*x2 = (*r)[0]->x;
	*y2 = y_lines_end - y_gap;
    }
}

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

static void 
set_pline(utc_val date_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.evtptr->edate !=
                objtmp.z.evtptr->edate) {
                switch (objary[plnary[co].obj1].type) {
                case OBJ_EVT:
                    objary[plnary[co].obj1].z.evtptr->edate += date_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_ACT:
                    objary[plnary[co].obj1].z.actptr->strtdate += date_diff;
                    objary[plnary[co].obj1].z.actptr->endate += date_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SACT:
                    objary[plnary[co].obj1].z.sactptr->strtdate += date_diff;
                    objary[plnary[co].obj1].z.sactptr->endate += date_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SLP:
                    objary[plnary[co].obj1].z.slpptr->strtdate += date_diff;
                    objary[plnary[co].obj1].z.slpptr->endate += date_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                case OBJ_SEQ:
                    objary[plnary[co].obj1].z.seqptr->strtdate += date_diff;
                    objary[plnary[co].obj1].z.seqptr->endate += date_diff;
                    (*(objary[plnary[co].obj1].opsptr->loc))(plnary[co].obj1,
			OBJECT);
                    break;
                default:
                    break;
                }
            }
            if (objary[plnary[co].obj2].z.evtptr->edate !=
                objtmp.z.evtptr->edate) {
                switch (objary[plnary[co].obj2].type) {
                case OBJ_EVT:
                    objary[plnary[co].obj2].z.evtptr->edate += date_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_ACT:
                    objary[plnary[co].obj2].z.actptr->strtdate += date_diff;
                    objary[plnary[co].obj2].z.actptr->endate += date_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SACT:
                    objary[plnary[co].obj2].z.sactptr->strtdate += date_diff;
                    objary[plnary[co].obj2].z.sactptr->endate += date_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SLP:
                    objary[plnary[co].obj2].z.slpptr->strtdate += date_diff;
                    objary[plnary[co].obj2].z.slpptr->endate += date_diff;
                    (*(objary[plnary[co].obj2].opsptr->loc))(plnary[co].obj2,
			OBJECT);
                    break;
                case OBJ_SEQ:
                    objary[plnary[co].obj2].z.seqptr->strtdate += date_diff;
                    objary[plnary[co].obj2].z.seqptr->endate += date_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) {
        event_ok_button();
    }
}

