/***********************************************************************
 *
 * TITLE:
 *	drawing.c
 *
 * AUTHOR:
 *	Cassie Mulnix
 *	
 * DESCRIPTION:
 *	This module is part of the OPPS editor, xopps.  It contains
 *	drawing area plotting routines.
 *
 *                              CHANGE HISTORY
 *
 * $Log: drawing.c,v $
 * Revision 1.69  1994/10/12  23:23:54  cassie
 * made text popup have maximum of 100 characters
 *
 * Revision 1.68  1994/06/01  23:48:36  clm
 * fixed background color so hline text popups show on HP
 *
 * Revision 1.67  1994/06/01  22:28:37  clm
 * changed color from structure to 3 arrays
 *
 * 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  1993/05/18  20:58:30  clm
 * added new message.c function
 *
 * Revision 1.63  1993/03/03  23:00:32  clm
 * fixed item_off for EVT2SLP in all if cases
 *
 * Revision 1.62  1993/02/20  00:05:10  clm
 * added precedence lines
 *
 * Revision 1.61  1993/01/13  23:32:20  clm
 * if object2 is not found, set obj2 to 0 for finish_object
 *
 * Revision 1.61  1993/01/12  16:15:03  clm
 * if object2 is not found, set obj2 to 0 for finish_object
 *
 * Revision 1.60  1993/01/04  21:15:05  clm
 * added item_on for ADD in chart area
 *
 * Revision 1.59  1992/12/17  23:56:02  clm
 * fixed menu so no objects could be added outside chart lines
 *
 * Revision 1.58  1992/12/17  18:21:44  clm
 * fixed new_pline so it won't exit when pline array is filled
 *
 * Revision 1.57  1992/12/14  21:51:22  clm
 * fixed messages when adding pline
 *
 * Revision 1.56  1992/12/14  20:55:50  clm
 * find_pline only if x and y in chart area
 *
 * Revision 1.55  1992/12/09  18:32:23  clm
 * finish_pline if 2nd object is not right type so rubberbanding
 * gets reexposed
 *
 * Revision 1.54  1992/12/04  17:04:32  clm
 * fixed precedence lines
 *
 * Revision 1.53  1992/12/01  18:05:47  clm
 * added expose event if no call to finish_pline is made
 * l
 *
 * Revision 1.52  1992/11/24  21:13:58  clm
 * added DELETE_PLINE to menu if pline is there, even if object is found also
 *
 * Revision 1.51  1992/11/24  16:29:28  clm
 * added remove of pline obj1 if obj2 is not an object
 *
 * Revision 1.50  1992/11/09  21:44:50  clm
 * removed unused variable
 *
 * Revision 1.49  1992/11/09  16:27:53  clm
 * added precedence lines to action
 *
 * Revision 1.48  1992/10/13  21:01:16  clm
 * fixed pointer warning for compiling V.18
 *
 * Revision 1.47  1992/10/02  20:16:06  clm
 * housekeeping
 *
 * Revision 1.46  1992/10/01  21:33:01  clm
 * added activateCallback for processEditField so popup would be
 * unmanaged when return was hit
 *
 * Revision 1.45  1992/09/22  17:18:42  clm
 * added activity object
 *
 * Revision 1.44  1992/09/14  23:02:53  clm
 * widened the popup to match extended drawing area
 *
 * Revision 1.43  1992/09/11  22:59:27  clm
 * changed to GR_EXPAND mode and changed margin size
 *
 * Revision 1.42  1992/09/10  19:27:23  clm
 * fixed action routine
 *
 * Revision 1.40  1992/09/10  14:45:17  clm
 * moved issue_date text below bottom margin
 * fixed Button2 action to find chart lines first
 *
 * Revision 1.39  1992/09/08  22:49:29  clm
 * added Edit Field for hline text
 *
 * Revision 1.38  1992/08/31  17:01:55  clm
 * added highlight definition
 *
 * Revision 1.37  1992/08/27  21:54:12  clm
 * added for loops for xlnary and ylnary to draw_outline
 *
 * Revision 1.36  1992/08/26  18:15:58  clm
 * changed message to warning
 *
 * Revision 1.35  1992/08/26  17:24:13  clm
 * moved issue date down
 *
 * Revision 1.34  1992/08/25  20:06:43  clm
 * added beware messages and modified values
 *
 * Revision 1.33  1992/08/25  17:07:22  clm
 * grayed out undo option for now
 *
 * Revision 1.32  1992/08/25  15:34:40  clm
 * added xlnary and ylnary to action function
 *
 * Revision 1.31  1992/08/13  18:08:33  clm
 * fixed hlnmenu area
 *
 * Revision 1.30  1992/08/03  21:30:01  clm
 * added status, page, chart date, symbol, level, and slip objects
 *
 * Revision 1.29  1992/07/13  20:52:31  clm
 * got move working for all objects
 *
 * Revision 1.27  1992/07/06  17:48:30  clm
 * fixed format of comments
 *
 * Revision 1.26  1992/06/24  17:11:35  clm
 * added horizontal line menu
 * functions for horizontal limes
 *
 * Revision 1.25  1992/05/26  15:30:11  clm
 * updated for use with rectangle routines
 *
 * Revision 1.24  1992/05/22  16:25:33  clm
 * added horizontal lines to draw_outline
 *
 * Revision 1.21  1992/05/20  19:50:57  clm
 * cleaned up file and help format
 *
 * Revision 1.20  1992/05/11  22:38:28  kevin
 * renamed project include file to xopps.h
 *
 * Revision 1.1  90/12/05  08:11:42  ana
 * Initial revision
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: drawing.c,v 1.69 1994/10/12 23:23:54 cassie OEL $";
#endif

#include "xopps.h"

#include <Xm/ScrolledW.h>
#include <Xm/RowColumn.h>
#include <Xm/DrawingA.h>
#include <Xm/Text.h>

static Region clip_region = NULL;

#define item_on(x)  XtSetSensitive(menu_item[x], TRUE)
#define item_off(x) XtSetSensitive(menu_item[x], FALSE)

static void action(Widget, XtPointer, XmDrawingAreaCallbackStruct *);
static void redraw(Widget, XtPointer, XmDrawingAreaCallbackStruct *);
static void processEditField(Widget, XtPointer, XtPointer); 

static Widget drawing_area;
static Widget singleEditField;
static struct hln *old_hln;
static struct hln *new_hln;
static int obj1, obj2;			/* objects for pline */
static Pixel bc, fc;

static int cp;				/* current pline */
/***********************************************************************
 *
 * FUNCTION:
 *	init_drawing_1
 *
 * INPUTS:
 *	display	(Display *)
 *	parent	(Widget)
 *	mode	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	initialize a scrolling drawing area of fixed size
 */

void 
init_drawing_1(Display *display, Widget parent, int mode)
{

    Widget swindow;
    Arg args[20];
    Cardinal n;
    float dx;
    float dy;

    if (mode & GR_LANDSCAPE) {
        dx = 10.0;
        dy = 7.5;
    } else {
        dx = 7.5;
        dy = 10.0;
    }

    if (mode & GR_EXPAND) {
        page_width = (int)(100.0 * dx);
        page_height = (int)(100.0 * dy);
    } else {
        page_width = (int)(75.0 * dx);
        page_height = (int)(75.0 * dy);
    }


    n = 0;
    XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED); n++;
    XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
    swindow = XmCreateScrolledWindow(parent, "swindow", args, n);
    XtManageChild(swindow);

    n = 0;
    XtSetArg(args[n], XmNwidth, page_width); n++;
    XtSetArg(args[n], XmNheight, page_height); n++;
    XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
    drawing_area = XmCreateDrawingArea(swindow, "drawingarea", args, n);
    XtManageChild(drawing_area);
    XtAddCallback(drawing_area, XmNinputCallback, (XtCallbackProc)action, NULL);
    XtAddCallback(drawing_area, XmNexposeCallback, (XtCallbackProc)redraw, 
	NULL);

    createEditField(drawing_area);
    init_menu(drawing_area);
    init_hln_menu(drawing_area);
    gr_init(page_width, page_height, mode);
}

/***********************************************************************
 *
 * FUNCTION:
 *	init_drawing_2
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	initializes a drawing area's foreground and background colors
 */


void 
init_drawing_2(void)
{
    Cardinal n;
    Arg args[3];
    Pixel background, foreground, highlight;
    XGCValues gcval;

    n = 0;
    XtSetArg(args[n], XmNforeground, &foreground); n++;
    XtSetArg(args[n], XmNbackground, &background); n++;
    XtSetArg(args[n], XmNhighlight, &highlight); n++;
    XtGetValues(drawing_area, args, n);
    gcval.foreground = foreground;
    gcval.background = background;

    dw.win = XtWindow(drawing_area);
    dw.gc = XCreateGC(dw.display, dw.win, GCForeground | GCBackground, &gcval);

    gr_init_colors(background, foreground, highlight);

    gcval.function = GXinvert;
    hilite_gc = XCreateGC(dw.display, dw.win, GCForeground | GCBackground
	| GCFunction, &gcval);
}

/***********************************************************************
 *
 * FUNCTION:
 *	action()
 *
 * INPUTS:
 *	w	(Widget)
 *	client_data	(XtPointer)
 *	call_data	(XmAnyCallbackStruct *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	determines the action for each button
 */

static void 
action(Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data)
{
    int co, tempco;             /* index of object under cursor */
    int x, y;                   /* return values */
    char buf[64];               /* temporary text buffer */
    static int moving = FALSE;	/* TRUE when moving an object */
    static int edt_hline = FALSE; /* TRUE when hline edit popup is up */
    static enum typ type;	/* temp variable for type of obj found */
    static int movtype = NOTHING; /* temp variable for type of obj found */
    int PLN = 0;

    x = call_data->event->xbutton.x;
    y = call_data->event->xbutton.y;
    data.x = x;
    data.y = y;

    if ((!moving) && (call_data->event->type == ButtonPress)) {
	switch (call_data->event->xbutton.button) {
	case Button1:
	    co = find_H_object(x, y);
	    if ((co >= 0) && (x < x_time_offset)) {
		(void)sprintf(buf, "Edit Horizontal Line");
                Message(buf);
		manageEditField(co);
		edt_hline = TRUE;
	    } else if ((co = find_object(x, y)) >= 0) {
		obj1 = co;
	 	switch (objary[co].type) {
		case OBJ_EVT:
		case OBJ_SACT:
		case OBJ_ACT:
		case OBJ_SEQ:
		case OBJ_SLP:
		    cp = new_pline();
		    if (cp != -1) {
			begin_pline(w, cp, x, y);
		    	pline = TRUE;
		    }
		    break;
		default:
		    Warning("This object cannot have precedence lines");
                    (void)sprintf(buf, "Position: X = %3d, Y = %3d", x, y);
                    Message(buf);
		    break;
  		}
	    } else {	
                (void)sprintf(buf, "Position: X = %3d, Y = %3d", x, y);
                Message(buf);
	    }
            break;
	case Button2:
	    /* 
	     * check to see what type of object it is
	     * and hold on to its type
	     * if it is a horizontal line it is treated
	     * differently than other objects 
	     */
	    co = find_line(x, y, &movtype);
	    if (co >= 0) {
		if (movtype == LINE_X) {
		    (*(xlnary[co].opsptr->msg))(co, LINE_X);
		} else {
		    (*(ylnary[co].opsptr->msg))(co, OBJECT);
		}
		type = OBJECT;
		begin_move(w, co, x, y, movtype);
		moving = TRUE;
	    } else {
		co = find_object(x,y);
		type = objary[co].type;
		if (co < 0) {
	   	    if ((co = find_H_object(x, y)) >= 0) {;
	                (*(Hobjary[co].opsptr->msg))(co, OBJECT);
			type = OBJ_HLN;
		        begin_H_move(w, co, x, y);
		        moving = TRUE;
	    	    } else {
	        	Warning("Nothing to move");
	        	break;
 	    	    }	
	        } else if (type == OBJ_CHT) {
	            Message("Chart Object cannot be moved");
	        } else if (type != OBJ_HLN) {
	            movtype = OBJECT;
	            (*(objary[co].opsptr->msg))(co, OBJECT);
	     	    if (type != OBJ_NUL) {
		        begin_move(w, co, x, y, movtype);
		        moving = TRUE;
		    }
	        }
	    }
            break;
	case Button3:
            co = find_H_object(x, y);
	    if ((co < 0) || (x >= x_time_offset)) {
	        co = find_object(x,y);
		type = objary[co].type;
		if (y > y_act_bottom) {
		    tempco = find_pline(x, y);
		    if (tempco >= 0) {
		        PLN = 1;
		    }
		    if ((co < 0) && (PLN)) {
		        type = OBJ_PLN;
		    }
		}	
	    } else {
	        type = OBJ_HLN;
	    }
            if (type == OBJ_HLN) {
	  	/* show horizontal line menu */
	    	data.co = co;
		XmMenuPosition(hln_menu, 
		    (XButtonPressedEvent *)call_data->event);
		XtManageChild(hln_menu);
		break;
	    } else if (type != OBJ_PLN) {
	        if ((x >= x_left_margin) && (x <= x_right_margin) && 
		    (y >= y_top_margin) && (y <= y_bottom_margin)) {
	    	    data.co = co;
		    if (type == OBJ_EVT) {
			item_on((int)EVT2SLP);
		    } else {	
			item_off((int)EVT2SLP);
		    }
 		    item_on((int)ADD);
            	    item_on((int)ADD_TEXT);	/* can add these everywhere */
            	    item_on((int)ADD_IMAGE);
		    item_on((int)ADD_STATUS);
 		    item_on((int)ADD_PAGE);
		    item_on((int)ADD_CHDATE);
		    item_on((int)ADD_SYM);
		    item_on((int)ADD_LEVEL);
		    if ((x >= x_time_offset) && (x <= x_right_margin) && 
		        (y >= y_act_bottom) && (y <= y_lines_end)) {
		        item_on((int)ADD_SACT);
		        item_on((int)ADD_ACT);
		        item_on((int)ADD_EVENT);
		        item_on((int)ADD_SLIP);
		        item_on((int)ADD_SEQ);
		    } else {
                        item_off((int)ADD_ACT);
                        item_off((int)ADD_SACT);
                        item_off((int)ADD_EVENT);
                        item_off((int)ADD_SLIP);
		        item_off((int)ADD_SEQ);
	    	    }	
/*            	    if (sbck != BACK_NONE) {
		        item_on((int)UNDO);
            	    } else {
		        item_off((int)UNDO);
            	    }
*/
		    if (PLN) {
		        item_on((int)DELETE_PLINE);
		    } else {
		        item_off((int)DELETE_PLINE);
		    }
		    item_off((int)UNDO);
                    if (co >= 0) { 
                     /* on object */
		        (*(objary[co].opsptr->msg))(co, OBJECT);
		        if ((objary[co].type == OBJ_EVT) || (objary[co].type ==
			     OBJ_SACT) || (objary[co].type == OBJ_ACT) ||
			     (objary[co].type == OBJ_SLP) || (objary[co].type ==
			     OBJ_SEQ)) {
			    item_on((int)COPY);
		        } else {
			    item_off((int)COPY);
		        }
		        item_on((int)EDIT);
		        if (objary[co].type != OBJ_CHT) {
		    	    item_on((int)DELETE);
		        } else {
		 	    item_off((int)DELETE);
		        }
                    } else {
		        item_off((int)COPY);
		        item_off((int)EDIT);
		        item_off((int)DELETE);
                    }
                    XmMenuPosition(menu,(XButtonPressedEvent*)call_data->event);
                    XtManageChild(menu);
                    break;
	        } else {
		    Warning("Menu Outside Chart");
		    item_off((int)ADD);
		    item_off((int)UNDO);
                    item_off((int)COPY);
                    item_off((int)DELETE);
                    item_off((int)EDIT);
                    item_off((int)DELETE_PLINE);
		    item_off((int)EVT2SLP);
                    XmMenuPosition(menu,(XButtonPressedEvent*)call_data->event);
                    XtManageChild(menu);
	        }
	    } else if (type == OBJ_PLN) {
	        if ((x >= x_left_margin) && (x <= x_right_margin) && 
		    (y >= y_top_margin) && (y <= y_bottom_margin)) {
		    data.co = tempco;
                    item_on((int)ADD_TEXT);
                    item_on((int)ADD_IMAGE);
                    item_on((int)ADD_STATUS);
                    item_on((int)ADD_PAGE);
                    item_on((int)ADD_CHDATE);
                    item_on((int)ADD_SYM);
                    item_on((int)ADD_LEVEL);
                    if ((x >= x_time_offset) && (x <= x_right_margin) &&
                        (y >= y_act_bottom) && (y <= y_lines_end)) {
                        item_on((int)ADD_SACT);
                        item_on((int)ADD_ACT);
                        item_on((int)ADD_EVENT);
                        item_on((int)ADD_SLIP);
                        item_on((int)ADD_SEQ);
                    } else {
                        item_off((int)ADD_ACT);
                        item_off((int)ADD_SACT);
                        item_off((int)ADD_EVENT);
                        item_off((int)ADD_SLIP);
                        item_off((int)ADD_SEQ);
                    }
                    item_off((int)UNDO);
                    item_off((int)COPY);
                    item_off((int)DELETE);
                    item_off((int)EDIT);
		    item_on((int)DELETE_PLINE);
		    item_off((int)EVT2SLP);
                    XmMenuPosition(menu,(XButtonPressedEvent*)call_data->event);
                    XtManageChild(menu);
                    break;
	        } else {
		    Warning("Menu Outside Chart");
		    item_off((int)ADD);
		    item_off((int)UNDO);
                    item_off((int)COPY);
                    item_off((int)DELETE);
                    item_off((int)EDIT);
                    item_off((int)DELETE_PLINE);
		    item_off((int)EVT2SLP);
                    XmMenuPosition(menu,(XButtonPressedEvent*)call_data->event);
                    XtManageChild(menu);
	        }
	    }
	}
    } else if ((moving) && (call_data->event->type == ButtonRelease) &&
	(call_data->event->xbutton.button == Button2)) {
	if (type == OBJ_HLN) {
	    finish_H_move(w);
	    moving = FALSE;
	} else {
	    finish_move(w, movtype);
	    moving = FALSE;
	    modified = TRUE;
        }
    } else if ((pline) && (call_data->event->type == ButtonRelease) &&
	(call_data->event->xbutton.button == Button1)) {
        x = call_data->event->xbutton.x;
        y = call_data->event->xbutton.y;
	if ((co = find_object(x, y)) > 0) {
	    obj2 = co;
	    finish_pline(w, cp, obj1, obj2);
	    pline = FALSE;
	    modified = TRUE;
	} else {
	    /*
	     * must finish pline so that rubberbanding gets cleared
	     */
	    obj2 = 0;
	    finish_pline(w, cp, obj1, obj2);
	    pline = FALSE;
	}
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	redraw()
 *
 * INPUTS:
 *	w	(Widget)
 *	client_data	(XtPointer)
 *	call_data	(XmAnyCallbackStruct *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	reexposes a region
 */

static void 
redraw(Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data)
{
    XRectangle rectangle;

    rectangle.x = call_data->event->xexpose.x;
    rectangle.y = call_data->event->xexpose.y;
    rectangle.width = call_data->event->xexpose.width;
    rectangle.height = call_data->event->xexpose.height;
    if (clip_region == NULL) clip_region = XCreateRegion();
    XUnionRectWithRegion(&rectangle, clip_region, clip_region);
    if (!(call_data->event->xexpose.count)) {
	gr_screen_on(&dw);
	XSetRegion(dw.display, dw.gc, clip_region);
#ifdef BOZO
	printf("Expose: %d\n", nrect);
	for (i = 0; i < nrect; ++i) {
	    printf("%4hd %4hd %4hu %4hu\n", rectangle[i].x, rectangle[i].y,
		rectangle[i].width, rectangle[i].height);
	}
#endif
	draw_outline(FALSE);	/* use clipping (because it's to screen) */
	gr_screen_off();
	XSetClipMask(dw.display, dw.gc, None);
	XDestroyRegion(clip_region);
	clip_region = NULL;
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	draw_outline()
 *
 * INPUTS:
 *	noclip	(int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	draws the rectangle outline
 */

void 
draw_outline(int noclip)
{
    int i, j;                      /* general index */

    /* display chart lines */
    for (i = 0; i < nxln; i++) {
	(*(xlnary[i].opsptr->dsp))(i);
    }

    for (i = 0; i < nyln; i++) {
	(*(ylnary[i].opsptr->dsp))(i);
    }
    if (issue_disp == TOG_ON) {
	gr_set_color(color_name[0], color_gscale[0]);
        gr_text(x_left_margin + 2, y_bottom_margin + 13, issue_dt, 0,
            (0|10), 0);
    }

    /* display horizontal lines */
    for (i = 0; i < Hnobj; i++) {
 	if (noclip || cliptestRectList(clip_region, Hobjary[i].rlist)) {
	    (*(Hobjary[i].opsptr->dsp))(i);
     	}
    } 
    /* display objects */
    for (j = 0; j < 4; j++) {
        for (i = 0; i < nobj; i++) {
            if ((objary[i].type != OBJ_NUL) && (noclip || cliptestRectList( 
	    	clip_region, objary[i].rlist)) && (objary[i].layer == j)) {
            	(*(objary[i].opsptr->dsp))(i);
	    }
        }
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	AddExposeEvent()	
 *
 * INPUTS:
 *	count	(int)
 *	r	(XRectangle *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	adds expose so that whole screen doesn't refresh
 */

void 
AddExposeEvent(int count, XRectangle *r)
{
    XEvent event;

    XClearArea(dw.display, dw.win, r->x, r->y, (unsigned int)r->width, 
	(unsigned int)r->height, FALSE);
    event.type = Expose;
    event.xexpose.serial = 0;		/* why? - why not! */
    event.xexpose.send_event = FALSE;
    event.xexpose.display = dw.display;
    event.xexpose.window = dw.win;
    event.xexpose.x = r->x;
    event.xexpose.y = r->y;
    event.xexpose.width = r->width;
    event.xexpose.height = r->height;
    event.xexpose.count = count;
    XtDispatchEvent(&event);
}

/***********************************************************************
 *
 * FUNCTION:
 *      manageEditField()
 *
 * INPUTS:
 *      co		(int)
 *
 * OUTPUTS:
 *      none
 *
 * RETURNS:
 *      none
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      manages the text widget for the horizontal line text
 */

void 
manageEditField(int co)
{
    char buf[256];				/* temp text buffer */
    XRectangle *(*r)[];				/* rectangle */
    Arg args[25];				/* widget arguments */
    Cardinal n;					/* temp index */
  
    r = getMoveRect(Hobjary[co].rlist);

    old_hln = Hobjary[co].z.hlnptr;
    new_hln = old_hln;
    (void)sprintf(buf, "%s", Hobjary[co].z.hlnptr->text);
    n = 0;
    XtSetArg(args[n], XmNmaxLength, 100); n++;
    XtSetArg(args[n], XmNvalue, buf); n++;
    XtSetValues(singleEditField, args, n);
    n = 0;
    XtSetArg(args[n], XmNy, (*r)[0]->y - 5); n++;
    XtSetArg(args[n], XmNx, (*r)[0]->x + 28); n++;
    XtSetArg(args[n], XmNbackground, bc); n++;
    XtSetValues(singleEditField, args, n);
    XtManageChild(singleEditField);
    XmProcessTraversal(singleEditField, XmTRAVERSE_CURRENT);
}

/***********************************************************************
 *
 * FUNCTION:
 *      createEditField()
 *
 * INPUTS:
 *      w	(Widget)
 *
 * OUTPUTS:
 *      none
 *
 * RETURNS:
 *      none
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *      creates the text widget popup for editing horizontal line text
 */

void 
createEditField(Widget w)
{
    Cardinal n;
    Arg args[20];

    n = 0;
    XtSetArg(args[n], XmNbackground, &bc); n++;
    XtSetArg(args[n], XmNforeground, &fc); n++;
    XtGetValues(w, args, n);

    n = 0;
    XtSetArg(args[n], XmNbackground, bc); n++;
    XtSetArg(args[n], XmNforeground, fc); n++;
    XtSetArg(args[n], XmNresizeWidth, False); n++;
    XtSetArg(args[n], XmNcolumns, 35); n++;
    XtSetArg(args[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); n++;
    singleEditField = XmCreateText(w, "singleEditField", args, n);
    XtAddCallback(singleEditField, XmNlosingFocusCallback,
	(XtCallbackProc)processEditField, NULL);
    XtAddCallback(singleEditField, XmNactivateCallback, 
	(XtCallbackProc)processEditField, NULL);
    XtAddCallback(singleEditField, XmNhelpCallback, (XtCallbackProc)ShowHelp, 
	"EditField");

}

/***********************************************************************
 *
 * FUNCTION:
 *      processEditField()
 *
 * INPUTS:
 *      w: The widget ID.
 *      client_data: The data passed by the process.
 *      call_data: The data passed by the widget.
 *
 * OUTPUTS:
 *      none
 *
 * RETURNS:
 *      none
 *
 * EXTERNALLY READ:
 *      old_hln, new_hln;
 *
 * EXTERNALLY MODIFIED:
 *      new_hln:   A copy of the old item record with the modified
 *                     information copied to it.
 *
 * DESCRIPTION:
 *      This function takes the information changed in the
 *      editField text box and modifies a new item record. 
 */

static void 
processEditField(Widget w, XtPointer client_data, XtPointer call_data)
{
    int     item_changed = 0;
    char    *ptr;
    char    *new_line_ptr;
    Arg     args[2];

    XtSetArg(args[0],XmNvalue,&ptr);
    XtGetValues(w,args,1);
    if (new_hln->text != ptr) {
	new_hln->text = ptr;
        item_changed = 1;
    }
    XtUnmanageChild(w);
    if(item_changed)
    {
        new_line_ptr = ptr;
        while((new_line_ptr = strchr(new_line_ptr,'\n')) != NULL)
        {
	    new_hln->text = ptr;
            *new_line_ptr = ' ';
            new_line_ptr++;
        }
    }
}

