 /*
  * Khoros: $Id: dlg.c,v 1.2 1991/12/18 09:49:29 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: dlg.c,v 1.2 1991/12/18 09:49:29 dkhoros Exp $";
#endif

 /*
  * $Log: dlg.c,v $
 * Revision 1.2  1991/12/18  09:49:29  dkhoros
 * HellPatch3
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>> File Name:  dlg.c
 >>>>
 >>>>  Routines: readdlg
 >>>>            readhead
 >>>>            readnode
 >>>>            readline
 >>>>            readarea
 >>>>            readfixed
 >>>>
 >>>>      Date: 10/7/90
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

#include "vinclude.h"
#include "file_formats/dlg.h"

struct dlgimage *readdlg();
static int readhead();
static int readcontrol();
static int readcats();
static struct dlgnode *readnode();
static struct dlgline *readline();
static struct dlgarea *readarea();
void dlg_convert_coords();
 
/****************************************************************
*
* Routine: readdlg
*
* Purpose: This routine reads a dlg file into a dlgimage structure.
*
*   Input: The name of a dlg file.
*
*  Output: A pointer to a dlgimage structure.  This routine returns
*          NULL on failure.
*
*  Author: Per Lysne  10/7/90
*
****************************************************************/
struct dlgimage *
readdlg(filename)
char *filename;
{
    int category, node, area, line;
    struct dlgimage *image;
    FILE *file, *fopen();
    struct dlgcategory *categoryptr;
    struct dlgnode **nodesptr;
    struct dlgline **linesptr;
    struct dlgarea **areasptr;

    /* Test for a bad input file name. */
    if (filename == NULL) {
        fprintf (stderr, "error in readdlg - bad input file name\n");
        return (NULL);
    }

    /* Open the file to read the DLG image from. */
    file = fopen (filename, "r");
    if (file == NULL) {
        fprintf (stderr, "error in readdlg - could not access %s\n", filename);
        return(NULL);
    }

    /* Allocate the struct type dlgimage. */
    image = (struct dlgimage *)kmalloc (sizeof(struct dlgimage));
    if (image == NULL) {
        fprintf (stderr, "error in readdlg - could not malloc image\n");
        return (NULL);
    }

    /* Read header records from the DLG file. */
    if (readhead(file, image) != 1) {
        fprintf (stderr, "error in readdlg - could not read header records\n");
        free (image);
        return (NULL);
    }

    /* Read control records from the DLG file. */
    if (readcontrol(file, image) != 1) {
        fprintf (stderr, "error in readdlg - could not read control records\n");
        free (image);
        return (NULL);
    }

    /* Read category records from DLG file. */
    if (readcats(file, image) != 1) {
        fprintf (stderr,"error in readdlg - could not read category records\n");
        free (image);
        return (NULL);
    }

    /*
     * Read all of the nodes, areas, and lines for each category of data
     * in this DLG file.
     */
    for (category=0; category<image->num_categories; category++) {

        /*
         * Categoryptr points to the current category structure in the array
         * of category structures which is in the dlgimage structure.
         */
        categoryptr = &(image->categories[category]);

        /*
         * Allocate the array of dlgnode structures that is accessed through
         * the current category.
         */
        nodesptr = (struct dlgnode **) kcalloc (categoryptr->num_nodes, 
                   sizeof (struct dlgnode *));
        if (nodesptr == NULL) {
            fprintf (stderr,
              "error in readdlg - could not allocate nodes #%d\n",
               category);
            free (image);
            return (NULL);
        }
        categoryptr->nodes = nodesptr;

        /*
         * Allocate the array of dlgarea structures that is accessed through
         * the current category.
         */
        areasptr = (struct dlgarea **) kcalloc (categoryptr->num_areas,
                    sizeof (struct dlgarea *));
        if (areasptr == NULL) {
            fprintf (stderr,
              "error in readdlg - could not allocate areas #%d\n",
               category);
            free (image);
            return (NULL);
        }
        categoryptr->areas = areasptr;
        
        /*
         * Allocate the array of dlgline structures that is accessed through
         * the current category.
         */
        linesptr = (struct dlgline **) kcalloc (categoryptr->num_lines,
                    sizeof (struct dlgline *));
        if (linesptr == NULL) {
            fprintf (stderr,
              "error in readdlg - could not allocate lines #%d\n",
               category);
            free (image);
            return (NULL);
        }
        categoryptr->lines = linesptr;

        /* Read all of the node records for this category. */
        for (node=0; node<categoryptr->act_nodes; node++) {
            categoryptr->nodes[node] = readnode (file);
            if (categoryptr->nodes[node] == NULL) {
                fprintf (stderr,
                  "warning in readdlg: could not read node no. %d in cat. %s\n",
                  node, categoryptr->name);
                free (image);
                return (NULL);
            }
        }

        /* Read all of the area records for this category. */
        for (area=0; area<categoryptr->act_areas; area++) {
            categoryptr->areas[area] = readarea (file);
            if (categoryptr->areas[area] == NULL) {
                fprintf (stderr,
                  "warning in readdlg: could not read area no. %d\n", area);
                free (image);
                return (NULL);
            }
        }

        /* Read all of the line records for this category. */
        for (line=0; line<categoryptr->act_lines; line++) {
            categoryptr->lines[line] = readline (file);
            if (categoryptr->lines[line] == NULL) {
                fprintf (stderr,
                  "warning in readdlg: could not read line no. %d\n", line);
                free (image);
                return (NULL);
            }
        }

    }

    return (image);
}



/****************************************************************
*
* Routine: readhead
*
* Purpose: Reads the header records from a dlg file.
*
*   Input: A file pointer to a dlg file and a pointer to a dlgimage struct.
*
*  Output: The header info is placed in the dlgimage.  Returns 1 on
*          success and 0 on failure.
*
*  Author: Per Lysne  10/7/90
*
****************************************************************/
static int readhead (file, image)
FILE *file;
struct dlgimage *image;
{
    char dummy[128];
    int readfixed();
    void nextline();

    /* 1st line. */
    readfixed (file, 72, "%s", image->name);
    nextline (file);

    /* 2nd line. */
    readfixed (file, 40, "%s", image->cart_unit);
    readfixed (file,  1, "%s", dummy);
    readfixed (file, 10, "%s", image->source_date);
    readfixed (file,  1, "%s", image->date_qual);
    readfixed (file,  8, "%d", &(image->orig_scale));
    readfixed (file,  3, "%s", dummy);
    readfixed (file,  1, "%s", image->sect_ind);
    nextline (file);

    /* 3rd line. */
    readfixed (file, 80, "%s", image->line_3);
    nextline (file);

    /* 4th line. */
    readfixed (file,  6, "%d", &(image->level_code));
    readfixed (file,  6, "%d", &(image->plani_code));
    readfixed (file,  6, "%d", &(image->plani_zone));
    readfixed (file,  6, "%d", &(image->plani_units));
    readfixed (file, 18, "%lf", &(image->resolution));
    readfixed (file,  6, "%d", &(image->trans_param));
    readfixed (file,  6, "%d", &(image->misc_records));
    readfixed (file,  6, "%d", &(image->num_sides));
    readfixed (file,  6, "%d", &(image->num_categories));
    nextline (file);

    /* 5th line */
    readfixed (file, 24, "%lf", &(image->projection[0]));
    readfixed (file, 24, "%lf", &(image->projection[1]));
    readfixed (file, 24, "%lf", &(image->projection[2]));
    nextline (file);

    /* 6th line */
    readfixed (file, 24, "%lf", &(image->projection[3]));
    readfixed (file, 24, "%lf", &(image->projection[4]));
    readfixed (file, 24, "%lf", &(image->projection[5]));
    nextline (file);

    /* 7th line */
    readfixed (file, 24, "%lf", &(image->projection[6]));
    readfixed (file, 24, "%lf", &(image->projection[7]));
    readfixed (file, 24, "%lf", &(image->projection[8]));
    nextline (file);

    /* 8th line */
    readfixed (file, 24, "%lf", &(image->projection[9]));
    readfixed (file, 24, "%lf", &(image->projection[10]));
    readfixed (file, 24, "%lf", &(image->projection[11]));
    nextline (file);

    /* 9th line */
    readfixed (file, 24, "%lf", &(image->projection[12]));
    readfixed (file, 24, "%lf", &(image->projection[13]));
    readfixed (file, 24, "%lf", &(image->projection[14]));
    nextline (file);

    /* 10th line */
    readfixed (file, 18, "%lf", &(image->int_projection[0]));
    readfixed (file, 18, "%lf", &(image->int_projection[1]));
    readfixed (file, 18, "%lf", &(image->int_projection[2]));
    readfixed (file, 18, "%lf", &(image->int_projection[3]));
    nextline (file);

    return (1);
}



/****************************************************************
*
* Routine: readcontrol
*
* Purpose: Reads the control records from a dlg file.
*
*   Input: A file pointer to a dlg file and a pointer to a dlgimage struct.
*
*  Output: The control info is placed in the dlgimage.  Returns 1 on
*          success and 0 on failure.
*
*  Author: Per Lysne  12/24/90
*
****************************************************************/
static int readcontrol (file, image)
FILE *file;
struct dlgimage *image;
{
    int i;
    char whichcorner[7], dummy[7];

    for (i=0; i<4; i++) {
        readfixed (file,  6, "%s", whichcorner);
        if (strncmp(whichcorner, "SW", 2) == 0) {
            readfixed (file, 12, "%lf", &(image->corners[SW][LATITUDE]));
            readfixed (file, 12, "%lf", &(image->corners[SW][LONGITUDE]));
            readfixed (file,  6, "%s", dummy);
            readfixed (file, 12, "%lf", &(image->corners[SW][INTERNAL_X]));
            readfixed (file, 12, "%lf", &(image->corners[SW][INTERNAL_Y]));
            nextline (file);
        }
        else if (strncmp(whichcorner, "NW", 2) == 0) {
            readfixed (file, 12, "%lf", &(image->corners[NW][LATITUDE]));
            readfixed (file, 12, "%lf", &(image->corners[NW][LONGITUDE]));
            readfixed (file,  6, "%s", dummy);
            readfixed (file, 12, "%lf", &(image->corners[NW][INTERNAL_X]));
            readfixed (file, 12, "%lf", &(image->corners[NW][INTERNAL_Y]));
            nextline (file);
        }
        else if (strncmp(whichcorner, "NE", 2) == 0) {
            readfixed (file, 12, "%lf", &(image->corners[NE][LATITUDE]));
            readfixed (file, 12, "%lf", &(image->corners[NE][LONGITUDE]));
            readfixed (file,  6, "%s", dummy);
            readfixed (file, 12, "%lf", &(image->corners[NE][INTERNAL_X]));
            readfixed (file, 12, "%lf", &(image->corners[NE][INTERNAL_Y]));
            nextline (file);
        }
        else if (strncmp(whichcorner, "SE", 2) == 0) {
            readfixed (file, 12, "%lf", &(image->corners[SE][LATITUDE]));
            readfixed (file, 12, "%lf", &(image->corners[SE][LONGITUDE]));
            readfixed (file,  6, "%s", dummy);
            readfixed (file, 12, "%lf", &(image->corners[SE][INTERNAL_X]));
            readfixed (file, 12, "%lf", &(image->corners[SE][INTERNAL_Y]));
            nextline (file);
        }
        else {
            fprintf (stderr, "error in readcontrol: bad control record\n");
            return (0);
        }
    }

    return (1);
}



/****************************************************************
*
* Routine: readcats
*
* Purpose: To read the category records in a dlg file.
*
*   Input: A pointer to an open dlg data file.
*
*  Output: The category info is placed in the dlgimage.  Returns 1 on
*          success and 0 on failure.
*
*  Author: Per Lysne  12/24/90
*
****************************************************************/
static int readcats (file, image)
FILE *file;
struct dlgimage *image;
{
    int i;
    char dummy[4];

    for (i=0; i<image->num_categories; i++) {
        readfixed (file, 20, "%s", image->categories[i].name); 
        readfixed (file,  4, "%d", &(image->categories[i].form_code)); 
        readfixed (file,  6, "%d", &(image->categories[i].num_nodes)); 
        readfixed (file,  6, "%d", &(image->categories[i].act_nodes)); 
        readfixed (file,  1, "%s", dummy);
        readfixed (file,  1, "%d", &(image->categories[i].nta_link)); 
        readfixed (file,  1, "%d", &(image->categories[i].ntl_link)); 
        readfixed (file,  1, "%s", dummy);
        readfixed (file,  6, "%d", &(image->categories[i].num_areas)); 
        readfixed (file,  6, "%d", &(image->categories[i].act_areas)); 
        readfixed (file,  1, "%s", dummy);
        readfixed (file,  1, "%d", &(image->categories[i].atn_link)); 
        readfixed (file,  1, "%d", &(image->categories[i].atl_link)); 
        readfixed (file,  1, "%d", &(image->categories[i].area_list)); 
        readfixed (file,  6, "%d", &(image->categories[i].num_lines)); 
        readfixed (file,  6, "%d", &(image->categories[i].act_lines)); 
        readfixed (file,  3, "%s", dummy);
        readfixed (file,  1, "%d", &(image->categories[i].line_list)); 
        nextline (file);
    }

    return (1);
}



/****************************************************************
*
* Routine: readnode
*
* Purpose: Reads a node record from a dlg file.
*
*   Input: A file pointer to a dlg file.
*
*  Output: A pointer to a structure dlgnode.  NULL if the routine fails.
*
*  Author: Per Lysne  10/7/90
*
****************************************************************/
static struct dlgnode *readnode (file)
FILE *file;
{
    int i, dummyi;
    char dummys[7];
    struct dlgnode *nodeptr;


    /* Allocate the new dlgnode structure. */
    nodeptr = (struct dlgnode *) kmalloc (sizeof(struct dlgnode));
    if (nodeptr == NULL) {
       fprintf(stderr,
         "error in readnode - could not allocate structure\n");
       return (NULL);
    }

    /* Read the first line of the node. */
    readfixed (file,  1, "%s", dummys);
    readfixed (file,  5, "%d", &dummyi);
    readfixed (file, 12, "%lf", &(nodeptr->x_coordinate));
    readfixed (file, 12, "%lf", &(nodeptr->y_coordinate));
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%d", &(nodeptr->numsegments));
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%d", &(nodeptr->numattributes));
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%s", dummys);
    nextline (file);

    /* Allocate the array for the line segments. */
    nodeptr->segments = (int *) kcalloc (nodeptr->numsegments, sizeof(int));
    if (nodeptr->segments == NULL) {
        fprintf (stderr, "error in readnode - could not malloc segments\n");
        free (nodeptr);
        return (NULL);
    }

    /* Read the list of line segments. */
    for (i=0; i<nodeptr->numsegments; i++) {
        if (fscanf(file, "%d\n", &(nodeptr->segments[i])) <= 0) {
            fprintf (stderr, 
                     "warning in readnode - could not read segment\n");
            free (nodeptr->segments);
            free (nodeptr);
            return (NULL);
        }
    }

    /* Allocate the arrays for the attributes. */
    nodeptr->majorattributes = (int *) kcalloc
     (nodeptr->numattributes, sizeof(int));
    if (nodeptr->majorattributes == NULL) {
        fprintf(stderr,"error in readnode - could not malloc attributes\n");
        free (nodeptr->segments);
        free (nodeptr);
        return (NULL);
    }
    nodeptr->minorattributes = (int *) kcalloc
     (nodeptr->numattributes, sizeof(int));
    if (nodeptr->minorattributes == NULL) {
        fprintf(stderr,"error in readnode - could not malloc attributes\n");
        free (nodeptr->segments);
        free (nodeptr);
        return (NULL);
    }

    /* Read the list of line attributes. */
    for (i=0; i<nodeptr->numattributes; i++) {
        if (fscanf(file, "%d\n", &(nodeptr->majorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readnode: could not read major attrib. no. %d\n",
             i);
            free (nodeptr->majorattributes);
            free (nodeptr->minorattributes);
            free (nodeptr->segments);
            free (nodeptr);
            return (NULL);
        }

        if (fscanf(file, "%d\n", &(nodeptr->minorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readnode: could not read minor attrib. no. %d\n",
             i);
            free (nodeptr->majorattributes);
            free (nodeptr->minorattributes);
            free (nodeptr->segments);
            free (nodeptr);
            return (NULL);
        }
    }

    return (nodeptr);
}



/****************************************************************
*
* Routine: readline
*
* Purpose: Reads a line record from a dlg file.
*
*   Input: A pointer to a dlg file.
*
*  Output: A pointer to a new struct dlgline.
*
*  Author: Per Lysne  10/7/90
*
****************************************************************/
static struct dlgline *
readline (file)
FILE *file;
{
    int i, dummyi;
    char dummys[13];
    struct dlgline *lineptr;

    /* Check for a bad input file. */
    if (file == NULL) {
        fprintf (stderr, "error in readline - bad file input\n");
        return (NULL);
    }

    /* Allocate the new dlgline structure. */
    lineptr = (struct dlgline *) kmalloc (sizeof(struct dlgline));
    if (lineptr == NULL) {
       fprintf(stderr,"error in readline - could not allocate structure\n");
       return (NULL);
    }

    /* Read the first line of the node. */
    readfixed (file,  1, "%s", dummys);
    readfixed (file,  5, "%d", &dummyi);
    readfixed (file,  6, "%d", &(lineptr->startnode));
    readfixed (file,  6, "%d", &(lineptr->endnode));
    readfixed (file,  6, "%d", &(lineptr->leftarea));
    readfixed (file,  6, "%d", &(lineptr->rightarea));
    readfixed (file, 12, "%s", dummys);
    readfixed (file,  6, "%d", &(lineptr->numcoordinates));
    readfixed (file,  6, "%d", &(lineptr->numattributes));
    readfixed (file,  6, "%d", &dummyi);
    nextline (file);

    /* Allocate the arrays for the coordinate pairs. */
    lineptr->x_coordinates = (double *) kcalloc (lineptr->numcoordinates,
                                               sizeof (double));
    if (lineptr->x_coordinates == NULL) {
        fprintf (stderr,"error in readline - could not malloc x_coords.\n");
        free (lineptr);
        return (NULL);
    }
    lineptr->y_coordinates = (double *) kcalloc (lineptr->numcoordinates,
                                               sizeof (double));
    if (lineptr->y_coordinates == NULL) {
        fprintf (stderr,"error in readline - could not malloc y_coords.\n");
        free (lineptr->x_coordinates);
        free (lineptr);
        return (NULL);
    }
        
    /* Read the pairs of x and y coordinates that define the line. */
    for (i=0; i<lineptr->numcoordinates; i++) {
        if (fscanf (file, "%lf\n", &(lineptr->x_coordinates[i])) <= 0) {
            fprintf (stderr, "warning in readline: ");
            fprintf (stderr, "could not read x_coord. no. %d\n", i);
            free (lineptr->x_coordinates);
            free (lineptr->y_coordinates);
            free (lineptr);
            return (NULL);
        }

        if (fscanf (file, "%lf\n", &(lineptr->y_coordinates[i])) <= 0) {
            fprintf (stderr, "warning in readline: ");
            fprintf (stderr, "could not read y_coord. no. %d\n", i);
            free (lineptr->x_coordinates);
            free (lineptr->y_coordinates);
            free (lineptr);
            return (NULL);
        }
    }

    /* Allocate the arrays to hold the attributes of this line. */
    lineptr->majorattributes = (int *) kcalloc 
      (lineptr->numattributes, sizeof (int));
    if (lineptr->majorattributes == NULL) {
        fprintf (stderr, "error in readline - could not malloc attribs.\n");
        free (lineptr->x_coordinates);
        free (lineptr->y_coordinates);
        free (lineptr);
    }
    lineptr->minorattributes = (int *) kcalloc 
      (lineptr->numattributes, sizeof (int));
    if (lineptr->minorattributes == NULL) {
        fprintf (stderr, "error in readline - could not malloc attribs.\n");
        free (lineptr->x_coordinates);
        free (lineptr->y_coordinates);
        free (lineptr);
    }

    /* Read the attributes to describe this line. */
    for (i=0; i<lineptr->numattributes; i++) {
        if (fscanf (file, "%d\n", &(lineptr->majorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readline: could not read major attrib. no. %d\n",
             i);
            free (lineptr->x_coordinates);
            free (lineptr->y_coordinates);
            free (lineptr->majorattributes);
            free (lineptr->minorattributes);
            free (lineptr);
            return (NULL);
        }

        if (fscanf (file, "%d\n", &(lineptr->minorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readline: could not read minor attrib. no. %d\n",
             i);
            free (lineptr->x_coordinates);
            free (lineptr->y_coordinates);
            free (lineptr->majorattributes);
            free (lineptr->minorattributes);
            free (lineptr);
            return (NULL);
        }
    }

    return (lineptr);
}



/****************************************************************
*
* Routine: readarea
*
* Purpose: Reads an area record from a dlg file.
*
*   Input: A pointer to a dlg file.
*
*  Output: A pointer to a new dlgarea structure.
*
*  Author: Per Lysne  10/7/90
*
****************************************************************/
static struct dlgarea *
readarea (file)
FILE *file;
{
    int i, dummyi;
    char dummys[7];

    struct dlgarea *areaptr;

    /* Check for a bad input file. */
    if (file == NULL) {
        fprintf (stderr, "error in readarea - bad file input\n");
        return (NULL);
    }

    /* Allocate the new dlgarea structure. */
    areaptr = (struct dlgarea *) kmalloc (sizeof(struct dlgarea));
    if (areaptr == NULL) {
       fprintf(stderr,"error in readarea - could not allocate structure\n");
       return (NULL);
    }

    /* Read the first line of the area. */
    readfixed (file,  1, "%s", dummys);
    readfixed (file,  5, "%d", &dummyi);
    readfixed (file, 12, "%lf", &(areaptr->x_coordinate));
    readfixed (file, 12, "%lf", &(areaptr->y_coordinate));
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%d", &(areaptr->numsegments));
    readfixed (file,  6, "%d", &(dummyi));
    readfixed (file,  6, "%d", &(areaptr->numattributes));
    readfixed (file,  6, "%d", &dummyi);
    readfixed (file,  6, "%d", &(areaptr->numislands));
    readfixed (file,  6, "%s", dummys);
    nextline (file);

    /* Allocate the array for the line segments. */
    areaptr->segments = (int *) kcalloc (areaptr->numsegments, sizeof(int));
    if (areaptr->segments == NULL) {
        fprintf (stderr, "error in readarea - could not malloc segments\n");
        free (areaptr);
        return (NULL);
    }

    /* Read the list of line segments. */
    for (i=0; i<areaptr->numsegments; i++) {
        if (fscanf(file, "%d\n", &(areaptr->segments[i])) <= 0) {
            fprintf (stderr, 
                     "warning in readarea - could not read segment\n");
            free (areaptr->segments);
            free (areaptr);
            return (NULL);
        }
    }

    /* Allocate the arrays for the attributes. */
    areaptr->majorattributes = (int *) kcalloc 
     (areaptr->numattributes, sizeof(int));
    if (areaptr->majorattributes == NULL) {
        fprintf(stderr,"error in readarea - could not malloc attributes\n");
        free (areaptr->segments);
        free (areaptr);
        return (NULL);
    }
    areaptr->minorattributes = (int *) kcalloc 
     (areaptr->numattributes, sizeof(int));
    if (areaptr->minorattributes == NULL) {
        fprintf(stderr,"error in readarea - could not malloc attributes\n");
        free (areaptr->segments);
        free (areaptr);
        return (NULL);
    }

    /* Read the list of line attributes. */
    for (i=0; i<areaptr->numattributes; i++) {
        if (fscanf (file, "%d\n", &(areaptr->majorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readarea could not read major attrib. no. %d\n",
             i);
            free (areaptr->majorattributes);
            free (areaptr->minorattributes);
            free (areaptr->segments);
            free (areaptr);
            return (NULL);
        }

        if (fscanf (file, "%d\n", &(areaptr->minorattributes[i])) <= 0) {
            fprintf (stderr, 
             "warning in readarea could not read minor attrib. no. %d\n",
             i);
            free (areaptr->majorattributes);
            free (areaptr->minorattributes);
            free (areaptr->segments);
            free (areaptr);
            return (NULL);
        }
    }

    return (areaptr);
}



/****************************************************************
*
* Routine: dlg_convert_coords
*
* Purpose: To use the conversion parameters in the dlg header to
*          convert the location values in the dlg data.  For more on
*          this, see Appendix E, "Coordinate Conversions" in the
*          dlg user's guides for more information.
*
*   Input: A dlgimage structure.
*    
*  Output: All of the utm coordinates in the dlg image are convereted to
*          the appropriate ground coordinates using the conversion
*          paramters in the dlg header.
*    
*  Author: Per Lysne  12/26/90
*    
****************************************************************/
void dlg_convert_coords (image)
struct dlgimage *image;
{
    int i, cat, node, line, area;
    double A1, A2, A3, A4, x, y, newx, newy;
    struct dlgcategory *catptr;
    struct dlgnode *nodeptr;
    struct dlgline *lineptr;
    struct dlgarea *areaptr;

    A1=image->int_projection[0];
    A2=image->int_projection[1];
    A3=image->int_projection[2];
    A4=image->int_projection[3];

    for (cat=0; cat<image->num_categories; cat++) {
        catptr = &(image->categories[cat]);

        for (node=0; node < catptr->act_nodes; node++) {
            nodeptr = catptr->nodes[node];

            x = nodeptr->x_coordinate;
            y = nodeptr->y_coordinate;

            newx = x*A1 + y*A2 + A3;
            newy = y*A1 - x*A2 + A4;

            nodeptr->x_coordinate = newx;
            nodeptr->y_coordinate = newy;
        }

        for (area=0; area<catptr->act_areas; area++) {
            areaptr = catptr->areas[area];

            x = areaptr->x_coordinate;
            y = areaptr->y_coordinate;
  
            newx = x*A1 + y*A2 + A3;
            newy = y*A1 - x*A2 + A4;

            areaptr->x_coordinate = newx;
            areaptr->y_coordinate = newy;
        }

        for (line=0; line<catptr->act_lines; line++) {
            lineptr = catptr->lines[line];

            for (i=0; i<lineptr->numcoordinates; i++) {
                x = lineptr->x_coordinates[i];
                y = lineptr->y_coordinates[i];

                newx = x*A1 + y*A2 + A3;
                newy = y*A1 - x*A2 + A4;

                lineptr->x_coordinates[i] = newx;
                lineptr->y_coordinates[i] = newy;
            }
        }
    }

    return;
}
