/***********************************************************************
 *
 * TITLE:
 *      line.c
 *
 * AUTHOR:
 *      Cassie Mulnix
 *
 * DESCRIPTION:
 *      This module is part of the OPPS editor, xopps.  It contains
 *      object routines to handle chart line objects.
 *
 *                              CHANGE HISTORY
 *
 * $Log: line.c,v $
 * Revision 1.20  1994/06/16  21:55:48  clm
 * updated to new dialog routines - extra parameter to DialogTextCreate
 *
 * Revision 1.19  1994/06/01  22:28:54  clm
 * cleaned up init arguments
 * changed color from structure to 3 arrays
 *
 * Revision 1.18  1994/05/20  23:31:43  clm
 * updated with HP, SGI changes
 *
 * Revision 1.17  1994/05/04  23:34:36  clm
 * ported to ANSI C
 *
 * Revision 1.16  1993/05/18  20:58:30  clm
 * added new message.c function
 *
 * Revision 1.15  1993/03/04  17:49:11  clm
 * line_init in load_line if any lines are missing
 * set default line dir if direction is off
 *
 * Revision 1.14  1993/03/03  18:12:11  clm
 * added error checking of Y_LINE 3 to Y_LINE 2
 *
 * Revision 1.13  1993/02/08  16:08:59  clm
 * check for minimum gap for chart lines
 *
 * Revision 1.12  1992/12/17  18:50:07  clm
 * fixed error checking for mov_line
 *
 * Revision 1.11  1992/10/02  20:44:33  clm
 * `housekeeping
 *
 * Revision 1.10  1992/10/02  18:44:34  clm
 * fixed mov_line routine for y_line 3
 *
 * Revision 1.9  1992/09/14  14:48:55  clm
 * fixed mov function so that text will always fit in chart area
 *
 * Revision 1.8  1992/09/11  22:59:49  clm
 * changed line coordinates to fit in new drawing size
 * changed mode to GR_EXPAND
 *
 * Revision 1.7  1992/09/10  20:56:55  clm
 * fix cord of ylnary[3] to correspond to y_gap value
 *
 * Revision 1.6  1992/09/09  22:55:13  clm
 * added line_init function to hard code line coordinates
 * removing xopps_init file
 *
 * Revision 1.4  1992/08/27  16:19:40  clm
 * took out unused functions
 *
 * Revision 1.3  1992/08/26  15:05:21  clm
 * fixed lim function
 *
 * Revision 1.2  1992/08/25  20:07:24  clm
 * added modified boolean for beware message
 *
 * Revision 1.1  1992/08/25  18:01:21  clm
 * Initial revision
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: line.c,v 1.20 1994/06/16 21:55:48 clm OEL $";
#endif

#include "xopps.h"

#define LINE_SENSE 5     /* line sensitivity: how close the mouse has to be */

static int load_line(char *);
static void edt_line(int, int);
static void rem_line(int, int);
static void lim_line(int, int *, int *, int *, int *, int);
static void loc_line(int, int);
static void mov_line(int, int, int, int);
static void dsp_line(int);
static void cpy_line(struct obj *, struct obj *);
static void msg_line(int, int);
static void sav_line(int, FILE *, int);

static struct ops line_ops = {
    dsp_line, edt_line, rem_line, lim_line, loc_line, mov_line, cpy_line,
    msg_line, sav_line
};

enum dialog_type { DONE_BUTTON, CANCEL_BUTTON, HELP_BUTTON,
                   COORD_LABEL, COORD, S_OFF_LABEL, S_OFF, E_OFF_LABEL, E_OFF,
                   TIMELINE_SEPARATOR, PAGE_INFO,
                   LINE, N_ITEMS
};

/***********************************************************************
 *
 * FUNCTION:
 *      line_init()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	hard code values of xlnary and ylnary
 *
 */

void 
line_init(void)
{
    /* set values of vertical lines */
    add_line(0, 0, 2, 0, 4, 0, 0);
    add_line(1, 0, 264, 1, 3, 0, 0);
    add_line(2, 0, 296, 0, 1, 0, 0);
    add_line(3, 0, 725, 0, 1, 0, 0);
    add_line(4, 0, 997, 0, 4, 0, 0);
    nxln = 5;

    /* set values of horizontal lines */
    add_line(0, 1, 2, 0, 4, 0, 0);
    add_line(1, 1, 70, 0, 4, 0, 0);
    add_line(2, 1, 138, 0, 4, 0, 0);
    add_line(3, 1, 667, 0, 4, 0, 0);
    add_line(4, 1, 736, 0, 4, 0, 0);
    nyln = 5;
}

/***********************************************************************
 *
 * FUNCTION:
 *      init_line_object()
 *
 * INPUTS:
 *	none
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	none
 *
 * DESCRIPTION:
 *	registers the line object
 *
 */

void 
init_line_object(void)
{
    register_io_obj('A', load_line);
}

/***********************************************************************
 *
 * FUNCTION:
 *	load_line()
 *
 * INPUTS:
 *	buf	- (char *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static int 
load_line(char *buf)
{
    static int new_lines = FALSE;
    int num, dir, cord, startln, endln, start_offset, end_offset;

    if (record_scan(buf + 1, "ddddddd", &num, &dir, &cord, &startln,
                    &endln, &start_offset, &end_offset) == 7) {
        if ((dir != 0) && (dir != 1)) {
	    if (nxln != MAX_XLINES) {
                Warning("Error - Illegal direction of line %d, %d used", num,0);
		dir = 0;
	    } else {
                Warning("Error - Illegal direction of line %d, %d used", num,1);
		dir = 1;
	    }
        }
        if (dir == 0) {		/* vertical line */
                if ( (num < 0 ) || (num >= MAX_XLINES) ) {
                    Warning("Error - Illegal Vertical Line Index (%d)", num);
                    return -1;
                }
                if ( (cord < 0) || (cord > page_width) ) {
                    Warning("Page Limit Coordinate (%d) Error", cord);
                    return -1;
                }
            } else if (dir == 1) {	/* horizontal line */
                if ((num < 0 ) || (num >= MAX_YLINES)) {
                    Warning("Error - Illegal Horizontal Line Index (%d)", num);
                    return -1;
                }
                if ( (cord < 0) || (cord > page_height) ) {
                    Warning("Page Limit Coordinate (%d) Error - Line %d",cord);
                    return -1;
                }
            }
            if (!new_lines) {
                new_lines = TRUE;
                nxln = 0;
                nyln = 0;
             }
             add_line(num, dir, cord, startln, endln, start_offset, end_offset);
             return 0;
    } else {
        return -1;
   }
}

/***********************************************************************
 *
 * FUNCTION:
 *	add_line()
 *
 * INPUTS:
 *	num	- (int)
 *	dir	- (int)
 *	coord	- (int)
 *	sline	- (int)
 *	eline	- (int)
 *	soff	- (int)
 *	eoff	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

void 
add_line(int num, int dir, int cord, int sline, int eline, int soff, int eoff)
{
    if (dir) {
        ylnary[num].rlist = newRectList(0);
        ylnary[num].z.lnptr = (struct line *)XtMalloc(sizeof(struct line));
        ylnary[num].z.lnptr->dir = dir;
        ylnary[num].z.lnptr->cord = cord;
        ylnary[num].z.lnptr->startln = sline;
        ylnary[num].z.lnptr->endln = eline;
        ylnary[num].z.lnptr->start_offset = soff;
        ylnary[num].z.lnptr->end_offset = eoff;
        ylnary[num].type = OBJ_LNY;
        ylnary[num].opsptr = &line_ops;
        nyln++;
    } else {
        xlnary[num].rlist = newRectList(0);
        xlnary[num].z.lnptr = (struct line *)XtMalloc(sizeof(struct line));
        xlnary[num].z.lnptr->dir = dir;
        xlnary[num].z.lnptr->cord = cord;
        xlnary[num].z.lnptr->startln = sline;
        xlnary[num].z.lnptr->endln = eline;
        xlnary[num].z.lnptr->start_offset = soff;
        xlnary[num].z.lnptr->end_offset = eoff;
        xlnary[num].type = OBJ_LNX;
        xlnary[num].opsptr = &line_ops;
        nxln++;
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	cpy_line()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

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

    to->z.lnptr = (struct line *)XtMalloc(sizeof(struct line));
    to->z.lnptr->dir = from->z.lnptr->dir;
    to->z.lnptr->cord = from->z.lnptr->cord;
    to->z.lnptr->startln = from->z.lnptr->startln;
    to->z.lnptr->endln = from->z.lnptr->endln;
    to->z.lnptr->start_offset = from->z.lnptr->start_offset;
    to->z.lnptr->end_offset = from->z.lnptr->end_offset;
    to->type = from->type;
    to->opsptr = &line_ops;
    to->rlist = copyRectList(from->rlist);

}

/***********************************************************************
 *
 * FUNCTION:
 *	rem_line()
 *
 * INPUTS:
 *	num	- (int)
 *	dir	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
rem_line(int num, int dir)
{
    struct obj *objptr;

    switch (num) {
    case BACK:
        objptr = &objbck;
        break;
    case TEMP:
        objptr = &objtmp;
        break;
    default:
        if (dir == LINE_X) {
            objptr = &(xlnary[num]);
        } else {
            objptr = &(ylnary[num]);
        }
        break;
    }
    freeRectList(objptr->rlist);
    XtFree((char *)objptr->z.lnptr);
    rem_object(objptr);
}

/***********************************************************************
 *
 * FUNCTION:
 *	lim_line()
 *
 * INPUTS:
 *	num		- (int)
 *	start_horz	- (int *)
 *	start_vert	- (int *)
 *	end_horz	- (int *)
 *	end_vert	- (int *)
 *	lndir		- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
lim_line(int co, int *x1, int *y1, int *x2, int *y2, int lndir)
{
    XRectangle *(*r)[];         /* move Rectangle */

    switch (lndir) {
    case LINE_X:                  /* vertical line */
        r = getMoveRect(xlnary[co].rlist);
        (*x1) = 0;
        (*y1) = (*r)[0]->y;
	(*x2) = page_width - 1;
        (*y2) = (*r)[0]->y;
        break;
    case LINE_Y:                  /* horizontal line */
        r = getMoveRect(ylnary[co].rlist);
        (*x1) = (*r)[0]->x;
        (*y1) = 0;
        (*x2) = (*r)[0]->x;
        (*y2) = page_height - 1;
        break;
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	loc_line()
 *
 * INPUTS:
 *	i	- (int)
 *	dir	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
loc_line(int i, int dir)
{
    struct line *lineptr;
    XRectangle rpri;				/* Rectangles */

    switch (dir) {
    case LINE_X:
        lineptr = xlnary[i].z.lnptr;
        rpri.x = lineptr->cord;
        rpri.y = ylnary[lineptr->startln].z.lnptr->cord;
        rpri.width = 1;
        rpri.height = ylnary[lineptr->endln].z.lnptr->cord -
                       ylnary[lineptr->startln].z.lnptr->cord;
        setRectList(xlnary[i].rlist, 1, &rpri, RL_PRIMARY);
        break;
    case LINE_Y:
        lineptr = ylnary[i].z.lnptr;
        rpri.x = xlnary[lineptr->startln].z.lnptr->cord;
        rpri.y = lineptr->cord;
        rpri.width = xlnary[lineptr->endln].z.lnptr->cord -
                      xlnary[lineptr->startln].z.lnptr->cord;
        rpri.height = 1;
        setRectList(ylnary[i].rlist, 1, &rpri, RL_PRIMARY);
        break;
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	mov_line()
 *
 * INPUTS:
 *	i	- (int)
 *	x	- (int)
 *	y	- (int)
 *	lndir	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
mov_line(int i, int x, int y, int lndir)
{
   int temp_y_gap;

   switch (lndir) {
   case LINE_X:
	/*
	 * check new coordinate with limit value on right
  	 */
	if ((i == 1) || (i == 3)) {
	    if (xlnary[i].z.lnptr->cord+x > xlnary[nxln-1].z.lnptr->cord) {
		Warning("Can't pass border lines");
		break;
	    }
	} else if (i == 0) {
	    /* header vertical line may be left of horizontal line area
		vertical line, so need to check against furthest left
		vertical line
	     */
	    if (xlnary[1].z.lnptr->cord > xlnary[2].z.lnptr->cord) {
		if (xlnary[i].z.lnptr->cord+x > xlnary[2].z.lnptr->cord) {
		    Warning("Can't pass next line");
		    break;
		}
	    } else {
		if (xlnary[i].z.lnptr->cord+x > xlnary[i+1].z.lnptr->cord) {
		    Warning("Can't pass next line");
		    break;
		}
	    }
	} else if (i == 2) {
	    if (xlnary[i].z.lnptr->cord+x > xlnary[i+1].z.lnptr->cord) {
		Warning("Can't pass next line");
		break;
	    }
	}
	/*
	 * check new coordinate with limit value on left
  	 */
	if ((i == 1) || (i == 3)) {
	    if (xlnary[i].z.lnptr->cord+x < xlnary[i-1].z.lnptr->cord) {	
		Warning("Can't pass previous line");
		break;
	    }
	} else if (i == nxln - 1) {
	    /* header vertical line may be right of horizontal line area
		vertical line, so need to check against furthest right
		vertical line
	     */
	    if (xlnary[i-1].z.lnptr->cord > xlnary[1].z.lnptr->cord) {
		if (xlnary[i].z.lnptr->cord+x < xlnary[i-1].z.lnptr->cord) {
		    Warning("Can't pass previous line");
		    break;
		}
	    } else if (xlnary[i].z.lnptr->cord+x < xlnary[1].z.lnptr->cord) {
		Warning("Can't pass chart line");
		break;
	    }
	} else if (i == 2) {
	    if (xlnary[i].z.lnptr->cord+x < xlnary[0].z.lnptr->cord) {
		Warning("Can't pass border lines");
		break;
	    }
	}
      	xlnary[i].z.lnptr->cord += x;
      	break;
   case LINE_Y:
	if (i != 0) {
	    if (ylnary[i].z.lnptr->cord+y <= ylnary[i-1].z.lnptr->cord) {
		Warning("Can`t pass previous line");
		break;
	    } 
 	}
	if (i != nyln-1) {
	    if (ylnary[i].z.lnptr->cord+y >= ylnary[i+1].z.lnptr->cord) {
	 	Warning("Can't pass next line");
		break;
	    }
	}
	if (i == 1) {
	    if ((ylnary[2].z.lnptr->cord - (ylnary[1].z.lnptr->cord + y))< 45) {
		Warning("Must have width of 45 for chart dates");
		break;
	    }
	}
	if (i == 2) {
	    temp_y_gap = (int)((ylnary[2].z.lnptr->cord + y - y_act_bottom) / 
		pg_lines);
	    if (((ylnary[2].z.lnptr->cord + y) - ylnary[1].z.lnptr->cord)< 45) {
		Warning("Must have width of 45 for chart dates");
		break;
	    }
	    if (((ylnary[3].z.lnptr->cord - (ylnary[2].z.lnptr->cord + y)) <
                pg_lines) || ((temp_y_gap * pg_lines + y_act_bottom) 
		< pg_lines)) {
                Warning("Must have width of at least 1 for each line on chart");
                break;
            }
	}
	if (i == 3) {
	    temp_y_gap = (int)((ylnary[3].z.lnptr->cord + y - y_act_bottom) / 
		pg_lines);
	    if ((((ylnary[3].z.lnptr->cord + y) - ylnary[2].z.lnptr->cord) < 
		pg_lines) || ((temp_y_gap * pg_lines + y_act_bottom) 
		< pg_lines)) {
		Warning("Must have width of at least 1 for each line on chart");
		break;
	    }
	}
	ylnary[i].z.lnptr->cord += y;
      	break;
   }
}

/***********************************************************************
 *
 * FUNCTION:
 *	dsp_line()
 *
 * INPUTS:
 *	i	- (int)
 *	lndir	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */
static void 
dsp_line(int i)
{
#ifdef BOZO
    struct line *lptr;
    int x1, y1, x2, y2;

    switch (lndir) {
    case LINE_X:
        lptr = xlnary[i].z.lnptr;
        gr_set_color(color_name[objary[0].z.chtptr->color],
	     color_gscale[objary[0].z.chtptr->color]);
        x1 = lptr->cord;
        y1 = ylnary[lptr->startln].z.lnptr->cord + lptr->start_offset;
        x2 = lptr->cord;
        y2 = ylnary[lptr->endln].z.lnptr->cord + lptr->end_offset;
        gr_line(x1, y1, x2, y2);
	break;
    case LINE_Y:
        lptr = ylnary[i].z.lnptr;
        gr_set_color(color_name[objary[0].z.chtptr->color],
	     color_gscale[objary[0].z.chtptr->color]);
        x1 = xlnary[lptr->startln].z.lnptr->cord + lptr->start_offset;
        y1 = lptr->cord;
        x2 = xlnary[lptr->endln].z.lnptr->cord + lptr->end_offset;
        y2 = lptr->cord;
        gr_line(x1, y1, x2, y2);
	break;
    }
#endif
}
/***********************************************************************
 *
 * FUNCTION:
 *	msg_line()
 *
 * INPUTS:
 *	i	- (int)
 *	lndir	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
msg_line(int i, int lndir)
{
    switch (lndir) {
    case LINE_X:
        Message("Vertical Line at %d", xlnary[i].z.lnptr->cord);
        break;
    case LINE_Y:
        Message("Horizontal Line at %d", ylnary[i].z.lnptr->cord);
        break;
   }
}

/***********************************************************************
 *
 * FUNCTION:
 *	sav_line()
 *
 * INPUTS:
 *	i	- (int)
 *	dir	- (int)
 *	fp	- (FILE *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
sav_line(int i, FILE *fp, int dir)
{
     struct line *lnptr;
     char buf[256];

    if (dir == LINE_X) {
        lnptr = xlnary[i].z.lnptr;
    } else if (dir == LINE_Y) {
        lnptr = ylnary[i].z.lnptr;
    }
    buf[0] = 'A';
    buf[1] = ' ';
    (void)record_print(buf + 2, "ddddddd", i, lnptr->dir, lnptr->cord,
	lnptr->startln, lnptr->endln, lnptr->start_offset, lnptr->end_offset);
    (void)fputs(buf, fp);
}

/***********************************************************************
 *
 * FUNCTION:
 *	edt_line()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

static void 
edt_line(int i, int ltype)
{
	/* can't edit the line, only move it */
}

/***********************************************************************
 *
 * FUNCTION:
 *	locate_lines()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	locate the lines on screen usually after a file has been loaded.
 *
 */

void 
locate_lines(void)
{
    int i;

    for (i = 0; i < nxln; i++) {
        (*(xlnary[i].opsptr->loc))(i, LINE_X);
    }
    for (i = 0; i < nyln; i++) {
        (*(ylnary[i].opsptr->loc))(i, LINE_Y);
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	clear_all_lines()
 *
 * INPUTS:
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

void 
clear_all_lines(void)
{
    int i;				/* temp index */

    for (i = 0; i < nxln; i++) {
        (*(xlnary[i].opsptr->rem))(i, LINE_X);
    }
    for (i = 0; i < nyln; i++) {
        (*(ylnary[i].opsptr->rem))(i, LINE_Y);
    }
    nxln = 0;
    nyln = 0;
}

/***********************************************************************
 *
 * FUNCTION:
 *	find_line()
 *
 * INPUTS:
 *	x	- (int)
 *	y	- (int)
 *	lndir	- (int *)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

int 
find_line(int x, int y, int *lndir)
{
    int i;                        /* index */
    static int lastln = -1;       /* array index of line array */

    i = 0;
    if ( ((*lndir) == LINE_X) || ((*lndir) == LINE_Y) ){
        i = lastln + 1;
    }

    if ((*lndir) != LINE_Y) {
        /*
         * Rotate between a vertical line to a horizontal line and back
         * to a vertical line.
         */
        if ( (lastln = find_line2(i, x, y, xlnary, ylnary, nxln)) >= 0) {
            (*lndir) = LINE_X;
        } else if ( (lastln = find_line2(0, y, x, ylnary, xlnary, nyln)) >= 0) {
            (*lndir) = LINE_Y;
        } else if (i > 0) {
            if ( (lastln = find_line2(0, x, y, xlnary, ylnary, nxln)) >= 0) {
                (*lndir) = LINE_X;
            }
        }
    } else {
        /*
         * Rotate between a horizontal line to a vertical line and back
         * to a horizontal line.
         */
        if ( (lastln = find_line2(i, y, x, ylnary, xlnary, nyln)) >= 0) {
            (*lndir) = LINE_Y;
        } else if ( (lastln = find_line2(0, x, y, xlnary, ylnary, nxln)) >= 0) {
            (*lndir) = LINE_X;
        } else if (i > 0) {
            if ( (lastln = find_line2(0, y, x, ylnary, xlnary, nyln)) >= 0) {
                (*lndir) = LINE_Y;
            }
        }
    }
    return (lastln);
}

/***********************************************************************
 *
 * FUNCTION:
 *	find_line2()
 *
 * INPUTS:
 *	curr	- (int)
 *	cord	- (int)
 *	pt2	- (int)
 *	ln1	- (struct obj *)
 *	ln2	- (struct obj *)
 *	nlines	- (int)
 *
 * OUTPUTS:
 *
 * RETURNS:
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *
 */

int 
find_line2(int curr, int cord, int pt2, struct obj *ln1, struct obj *ln2, int nlines)
{
    int lastline = -1;   /* return -1 if no line is found */
    int i;
    int ln_start;
    int ln_end;

    /*
     * With the assumption that the lines are placed in sequential order,
     * this function will check the following line(s) in the line array to
     * determine out if another line falls under the mouse's sphere of influence
     * If there is one, it will return the index of that line, otherwise it will
     * return a -1.
     */
    for (i = 0; i < nlines; i++) {
        if ( (curr + i) >= nlines ) {
            break;
        }
        ln_start = ln2[ln1[curr+i].z.lnptr->startln].z.lnptr->cord +
                       ln1[curr+i].z.lnptr->start_offset;
        ln_end = ln2[ln1[curr+i].z.lnptr->endln].z.lnptr->cord +
                       ln1[curr+i].z.lnptr->end_offset;
        if ( (abs(cord - ln1[curr+i].z.lnptr->cord) < LINE_SENSE) &&
             (ln_start < pt2) && (pt2 < ln_end) ) {
            lastline = curr + i;
            return (lastline);
        }
    }
    return (lastline);
}

void 
check_lines(void)
{
    if ((nxln != MAX_XLINES) || (nyln != MAX_YLINES)) {
	Warning("Error in chart lines - default lines being loaded");
	line_init();
    }
}
