/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
 * $Id: map_gnis.c,v 1.41 2012/08/25 16:38:29 tvrusso Exp $
 *
 * XASTIR, Amateur Station Tracking and Information Reporting
 * Copyright (C) 1999,2000  Frank Giannandrea
 * Copyright (C) 2000-2012  The Xastir Group
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Look at the README for more information on the program.
 */


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif  // HAVE_CONFIG_H

#include "snprintf.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>

// Needed for Solaris
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif  // HAVE_STRINGS_H

#include <dirent.h>
#include <netinet/in.h>
#include <Xm/XmAll.h>

#ifdef HAVE_X11_XPM_H
#include <X11/xpm.h>
#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
#undef HAVE_XM_XPMI_H
#endif // HAVE_LIBXPM
#endif // HAVE_X11_XPM_H

#ifdef HAVE_XM_XPMI_H
#include <Xm/XpmI.h>
#endif // HAVE_XM_XPMI_H

#include <X11/Xlib.h>

#include <math.h>

#include "xastir.h"
#include "maps.h"
#include "alert.h"
#include "util.h"
#include "main.h"
#include "datum.h"
#include "draw_symbols.h"
#include "rotated.h"
#include "color.h"
#include "xa_config.h"

// Must be last include file
#include "leak_detection.h"



#define CHECKMALLOC(m)  if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }

//NOTE:  This function has a problem if a non-gnis file is labeled
//with a ".gnis" extension.  It causes a segfault in Xastir.  More
//error checking needs to be done in order to prevent this.

// draw_gnis_map()
//
// Allows drawing a background map of labels for the viewport.
// Example format (old):
// "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East"
//
// Example format (new):
// 376016|ID|12th Ave Drain|stream|Canyon|16|027|433107N|1163348W|43.51861|-116.56333||||||||Nampa
//
// These types of files are available from http://geonames.usgs.gov/
// under "Download State Gazetteer Data - Available Via Anonymous FTP".
// A typical filename would be: "WA_Features_20090401.zip".   Do not get the other
// types of files which are columnar.  The files that we parse are
// pipe-delimited.
//
void draw_gnis_map (Widget w,
		    char *dir,
		    char *filenm,
		    alert_entry *alert,
		    u_char alert_color,
		    int destination_pixmap,
		    map_draw_flags *mdf)
{
    char file[MAX_FILENAME];        // Complete path/name of GNIS file
    char short_filenm[MAX_FILENAME];
    FILE *f;                        // Filehandle of GNIS file
    char line[MAX_FILENAME];        // One line of text from file
    char *i, *j;
    char state[50];
    char name[200];
    char type[100];
    char county[100];
    char latitude[15];
    char longitude[15];
    char population[15];
    char lat_dd[3];
    char lat_mm[3];
    char lat_ss[3];
    char lat_dir[2];
    char long_dd[4];
    char long_mm[3];
    char long_ss[3];
    char long_dir[2];
    char lat_str[15];
    char long_str[15];
    int temp1;
    long coord_lon, coord_lat;
    long min_lat, min_lon, max_lat, max_lon;
    int ok;
    long x,y;
    char symbol_table, symbol_id, symbol_over;
    unsigned long bottom_extent = 0l;
    unsigned long top_extent = 0l;
    unsigned long left_extent = 0l;
    unsigned long right_extent = 0l;
    char status_text[MAX_FILENAME];
    int count = 0;


    //fprintf(stderr,"draw_gnis_map starting: %s/%s\n",dir,filenm);

    xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);

    // Create a shorter filename for display (one that fits the
    // status line more closely).  Subtract the length of the
    // "Indexing " and/or "Loading " strings as well.
    if (strlen(filenm) > (41 - 9)) {
        int avail = 41 - 11;
        int new_len = strlen(filenm) - avail;

        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "..%s",
            &filenm[new_len]);
    }
    else {
        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "%s",
            filenm);
    }

    // Screen view
    min_lat = SE_corner_latitude;
    max_lat = NW_corner_latitude;
    min_lon = NW_corner_longitude;
    max_lon = SE_corner_longitude;


    // The map extents in the map index are checked in draw_map to
    // see whether we should draw the map at all.


    // Update the statusline for this map name
    // Check whether we're indexing or drawing the map
    if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
            || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
        xastir_snprintf(status_text,
            sizeof(status_text),
            langcode ("BBARSTA039"),
            short_filenm);
    }
    else {
        xastir_snprintf(status_text,
            sizeof(status_text),
            langcode ("BBARSTA028"),
            short_filenm);
    }
    statusline(status_text,0);       // Loading/Indexing ...


    HandlePendingEvents(app_context);
    if (interrupt_drawing_now) {
        // Update to screen
        (void)XCopyArea(XtDisplay(da),
            pixmap,
            XtWindow(da),
            gc,
            0,
            0,
            (unsigned int)screen_width,
            (unsigned int)screen_height,
            0,
            0);
        return;
    }


/*
Latest pipe-delimited format from USGS (as of 08/12/2004):
----------------------------------------------------------
Feature ID Number (FID)
State Alpha Code
Feature Name
Feature Type
County Name
State Number Code (FIPS Code)
County Number Code (FIPS Code)
Primary Latitude (DMS)
Primary Longitude (DMS)
Primary Latitude (decimal degrees)
Primary Longitude (decimal degrees)
Source Latitude (DMS)
Source Longitude (DMS)
Source Latitude (decimal degrees)
Source Longitude (decimal degrees)
Elevation
Estimated Population
Federal Status
Cell Name
*/


    // Attempt to open the file
    f = fopen (file, "r");
    if (f != NULL) {
        while (!feof (f)) {     // Loop through entire file
            int lat_in_view = 0;

            count++;
            if ((count % 16) == 0) {

                // Check whether map drawing should be interrupted.
                // Check every 16 lines.
                //
                HandlePendingEvents(app_context);
                if (interrupt_drawing_now) {
                    (void)fclose (f);
                    // Update to screen
                    (void)XCopyArea(XtDisplay(da),
                        pixmap,
                        XtWindow(da),
                        gc,
                        0,
                        0,
                        (unsigned int)screen_width,
                        (unsigned int)screen_height,
                        0,
                        0);
                    return;
                }
            }

            if ( get_line (f, line, MAX_FILENAME) ) {  // Snag one line of data

                // It is common for these lines to have incredible
                // numbers of spaces at the end, so trim them here.
                (void)remove_trailing_spaces(line);

                if (strlen(line) > 0) {

                    // Default population, in case the field isn't
                    // present in the file.
                    xastir_snprintf(population,sizeof(population),"0");
 
// Examples of old/new format:
// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
// 2008 Format follows
//FEATURE_ID|FEATURE_NAME|FEATURE_CLASS|STATE_ALPHA|STATE_NUMERIC|COUNTY_NAME|COUNTY_NUMERIC|PRIMARY_LAT_DMS|PRIM_LONG_DMS|PRIM_LAT_DEC|PRIM_LONG_DEC|SOURCE_LAT_DMS|SOURCE_LONG_DMS|SOURCE_LAT_DEC|SOURCE_LONG_DEC|ELEVATION|MAP_NAME|DATE_CREATED|DATE_EDITED
//205110|Appalachian National Scenic Trail|Trail|PA|42|Perry|099|401920N|0770439W|40.3221113|-77.0775473|||||201|Wertzville|09/12/1979|05/19/2008

                    //NOTE:  We handle running off the end of "line"
                    //via the "continue" statement.  Skip the line
                    //if we don't find enough parameters while
                    //parsing.

                    // Find end of Feature ID Number field
                    j = index(line,'|');

                    if (j == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

//NOTE:  It'd be nice to take the part after the comma and put it before the rest
// of the text someday, i.e. "Cassidy, Lake".

                    // Find end of Feature Name field
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    i[0] = '\0';
                    xastir_snprintf(name,sizeof(name),"%s",j);

                    // Find end of Feature Type field
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    j[0] = '\0';
                    xastir_snprintf(type,sizeof(type),"%s",i);

                    // Find end of State field
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    i[0] = '\0';
                    xastir_snprintf(state,sizeof(state),"%s",j);

                    // Find end of State Number Code field
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    j[0] = '\0';

                    // Find end of County Name field
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    i[0] = '\0';
                    xastir_snprintf(county,sizeof(county),"%s",j);

                    // Find end of County Number Code field
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    j[0] = '\0';

// Examples of old/new format:
// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria

                    // Find end of Primary Latitude field (DDMMSSN)
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    i[0] = '\0';
                    xastir_snprintf(latitude,sizeof(latitude),"%s",j);
                    if (!isdigit((int)latitude[0])) { // skip record if not
                        continue;                // numeric! (e.g. "UNKNOWN")
                    }

//WE7U
                    clean_string(latitude);
                    
                    // Find end of Primary Longitude field (DDDMMSSW)
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        continue;   // Skip this line
                    }

                    j[0] = '\0';
                    xastir_snprintf(longitude,sizeof(longitude),"%s",i);
                    if (!isdigit((int)longitude[0])) { // skip record if not
                        continue;                 // numeric (e.g. UNKNOWN)
                    }

//WE7U
                    clean_string(longitude);

                    // Find end of Primary Latitude field (decimal
                    // degrees)
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    i[0] = '\0';

                    // Find end of Primary Longitude field (decimal
                    // degrees)
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    j[0] = '\0';

// Examples of old/new format:
// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
 
                    // Find end of Source Latitude field (DMS) (old
                    // format) or elevation (new format)
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    i[0] = '\0';

                    // Find end of Source Longitude field (DMS) (old
                    // format) or 
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    j[0] = '\0';

                    // Find end of Source Latitude field (decimal
                    // degrees)
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    i[0] = '\0';

                    // Find end of Source Longitude field (decimal
                    // degrees)
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    j[0] = '\0';

                    // Find end of Elevation field
                    i = index(++j, '|');

                    if (i == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    i[0] = '\0';

                    // Find end of Estimated Population field
                    j = index(++i, '|');

                    if (j == NULL) {    // Pipe not found
                        goto FINISH;    // We have enough to process now
                    }

                    if ( j != NULL ) {
                        j[0] = '\0';
                        xastir_snprintf(population,sizeof(population),"%s",i);
                    }

FINISH:
                    // There are two more fields (old format),
                    // "Federal Status" and "Cell Name".  We ignore
                    // those for now.
 
		    if (strlen(latitude) < 7) 
			continue;	// We really don't have any latitude here.
                    lat_dd[0] = latitude[0];
                    lat_dd[1] = latitude[1];
                    lat_dd[2] = '\0';
 
                    lat_mm[0] = latitude[2];
                    lat_mm[1] = latitude[3];
                    lat_mm[2] = '\0';

                    lat_ss[0] = latitude[4];
                    lat_ss[1] = latitude[5];
                    lat_ss[2] = '\0';

                    lat_dir[0] = latitude[6];
                    lat_dir[1] = '\0';

                    // Now must convert from DD MM SS format to DD MM.MM format so that we
                    // can run it through our conversion routine to Xastir coordinates.
                    if (1 != sscanf(lat_ss, "%d", &temp1)) {
                        fprintf(stderr,"draw_gnis_map:sscanf parsing error\n");
                    }

                    temp1 = (int)((temp1 / 60.0) * 100 + 0.5);  // Poor man's rounding
                    xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
                            lat_mm, temp1, lat_dir);
                    coord_lat = convert_lat_s2l(lat_str);

                    // Quick test of latitude to see if it's within
                    // our view.  If not and we're not doing
                    // indexing, skip this line and go on to the
                    // next.
                    if (coord_lat <= min_lat && coord_lat >= max_lat) {
                        // Latitude is ok
                        lat_in_view++;
                    }
                    else {  // Latitude not in current view

                        // Check whether we're indexing the map
                        if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
                                || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
                            // Process the line 'cuz we're indexing
                        }
                        else {  // Not indexing so skip to the next
                                // line in the file
                            continue;
                        }
                    }

		    if (strlen(longitude) < 8) 
			continue;	// We really don't have any longitude here.
                    long_dd[0] = longitude[0];
                    long_dd[1] = longitude[1];
                    long_dd[2] = longitude[2];
                    long_dd[3] = '\0';
 
                    long_mm[0] = longitude[3];
                    long_mm[1] = longitude[4];
                    long_mm[2] = '\0';
 
                    long_ss[0] = longitude[5];
                    long_ss[1] = longitude[6];
                    long_ss[2] = '\0';
 
                    long_dir[0] = longitude[7];
                    long_dir[1] = '\0';

                    if (1 != sscanf(long_ss, "%d", &temp1)) {
                        fprintf(stderr,"draw_gnis_map:sscanf parsing error\n");
                    }

                    temp1 = (int)((temp1 / 60.0) * 100 + 0.5);  // Poor man's rounding
                    xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
                            long_mm, temp1, long_dir);
                    coord_lon = convert_lon_s2l(long_str);


                    // Check whether we're indexing the map
                    if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
                            || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {

                        // Save the min/max extents of the file.  We
                        // should really initially set the extents
                        // to the min/max for the Xastir coordinate
                        // system, but in practice zeroes should
                        // work just as well.
                        //
                        if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l))
                            bottom_extent = coord_lat;
                        if ((coord_lat < (long)top_extent) || (top_extent == 0l))
                            top_extent = coord_lat;
                        if ((coord_lon < (long)left_extent) || (left_extent == 0l))
                            left_extent = coord_lon;
                        if ((coord_lon > (long)right_extent) || (right_extent == 0l))
                            right_extent = coord_lon;
                    }
                    // Now check whether this lat/lon is within our viewport.  If it
                    // is, draw a text label at that location.
                    else if (coord_lon >= min_lon && coord_lon <= max_lon
                            && lat_in_view) {

                        clean_string(state);
                        clean_string(name);
                        clean_string(type);
                        clean_string(county);
                        clean_string(population);

                        if (debug_level & 16) {
                            fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t",
                                    state, name, type, county, latitude, longitude);
                            fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t",
                                    lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir);
                            fprintf(stderr,"%s\t%s\n", lat_str, long_str);
                        }

                        // Convert to screen coordinates.  Careful
                        // here!  The format conversions you'll need
                        // if you try to compress this into two
                        // lines will get you into trouble.
                        x = coord_lon - NW_corner_longitude;
                        y = coord_lat - NW_corner_latitude;
                        x /= scale_x;
                        y /= scale_y;

                        ok = 1;

                        /* set default symbol */
                        symbol_table = '/';
                        symbol_id = '.'; /* small x */
                        symbol_over = ' ';

                        if (strcasecmp(type,"airport") == 0) {
                            symbol_id = '^';
                            if (scale_y > 100)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"arch") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"area") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"arroyo") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"bar") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"basin") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"bay") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"beach") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"bench") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"bend") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"bridge") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"building") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"canal") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"cape") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"cave") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"cemetery") == 0) {
                            symbol_table = '\\';
                            symbol_id = '+';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"census") == 0) {
                          /* if (scale_y > 50)*/  /* Census divisions */
                                ok = 0;
                        }
                        else if (strcasecmp(type,"channel") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"church") == 0) {
                            symbol_table = '\\';
                            symbol_id = '+';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"civil") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"cliff") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"crater") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"crossing") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"dam") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"falls") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"flat") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"forest") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"gap") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"geyser") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"glacier") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"gut") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"harbor") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"hospital") == 0) {
                            symbol_id = 'h';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"island") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"isthmus") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"lake") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"lava") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"levee") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"locale") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"military") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"mine") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"oilfield") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"other") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"park") == 0) {
                            symbol_table = '\\';
                            symbol_id = ';';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"pillar") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"plain") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"po") == 0) {
                            symbol_id = ']';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"ppl") == 0) {
                            symbol_id = '/';
                            if (scale_y > 20000)    // Don't draw cities at zoom higher than 20,000
                                ok = 0;
                            else if (scale_y > 4000) {  // Don't draw cities of less than 20,000
                                if (atoi(population) < 50000) {
                                    ok = 0;
                                }
                            }
                            else if (scale_y > 1500) {  // Don't draw cities of less than 10,000
                                if (atoi(population) < 20000) {
                                    ok = 0;
                                }
                            }
                            else if (scale_y > 750) {  // Don't draw cities of less than 5,000
                                if (atoi(population) < 10000) {
                                    ok = 0;
                                }
                            }
                            else if (scale_y > 200) {   // Don't draw cities 
                                                        // of less than 1,000
                                if (atoi(population) < 1000) {
                                    ok = 0;
                                    //fprintf(stderr,
                                    // "Name: %s\tPopulation: %s\n",name,
                                    // population);
                                }
                            }
                        }
                        else if (strcasecmp(type,"range") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"rapids") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"reserve") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"reservoir") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"ridge") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"school") == 0) {
                            symbol_id = 'K';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"sea") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"slope") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"spring") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"stream") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"summit") == 0) {
                            if (scale_y > 100)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"swamp") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"trail") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"tower") == 0) {
                            symbol_id = 'r';
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"tunnel") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"valley") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"well") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"woods") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else if (strcasecmp(type,"ruin") == 0) {
                            if (scale_y > 50)
                                ok = 0;
                        }
                        else {
                            fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n",
                                type,state,county,name);
                        }

                        if (ok == 1) {  // If ok to draw it
                            symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
                            draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name));
                        }

                    }
                    else {
                        //fprintf(stderr,"Not in viewport.  Coordinates: %ld %ld\n",coord_lat,coord_lon);
                        //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat);
                        //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon);
                    }
                }
            }
        }   // End of while
        (void)fclose (f);


        // Check whether we're indexing the map
        if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
                || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {

            // We're indexing only.  Save the extents in the index.
            index_update_xastir(filenm, // Filename only
                bottom_extent,  // Bottom
                top_extent,     // Top
                left_extent,    // Left
                right_extent,   // Right
                99999);         // Default Map Level
        }
    }
    else {
        fprintf(stderr,"Couldn't open file: %s\n", file);
        return;
    }
    if (debug_level & 16)
        fprintf(stderr,"Exiting draw_gnis_map\n");
}





// Search for a placename among GNIS files
//
// We need to search a file in the map directory that has the filename
// STATE.gis, where STATE is from the "state" variable passed to us.
// Search for the placename/county/state/type that the user requested.
// Once found, center the map on that location or bring up a response
// dialog that asks whether one wants to go there, and that dialog
// provides info about the place found, with a possible selection
// out of a list of matches.
// Might also need to place a label at that position on the map in
// case that GNIS file isn't currently selected.
//
int gnis_locate_place( Widget w,
        char *name_in,
        char *state_in,
        char *county_in,
        char *quad_in,
        char *type_in,
        char *filename_in,
        int follow_case,
        int get_match,
        char match_array_name[50][200],
        long match_array_lat[50],
        long match_array_long[50] ) {

    char file[MAX_FILENAME];        // Complete path/name of GNIS file
    FILE *f;                        // Filehandle of GNIS file
    char line[MAX_FILENAME];        // One line of text from file
    char *i, *j;
    char state[50];
    char state_in2[50];
    char name[200];
    char name_in2[50];
    char type[100];
    char type_in2[50];
    char county[100];
    char county_in2[50];
    char quad[100];
    char quad_in2[100];
    char latitude[15];
    char longitude[15];
    char population[15];
    char lat_dd[3];
    char lat_mm[3];
    char lat_ss[3];
    char lat_dir[2];
    char long_dd[4];
    char long_mm[3];
    char long_ss[3];
    char long_dir[2];
    char lat_str[15];
    char long_str[15];
    int temp1;
    long coord_lon, coord_lat;
    int ok;
    struct stat file_status;
    int my_count = 0;
 
 
    xastir_snprintf(file,sizeof(file),"%s",filename_in);

    if (debug_level & 16)
        fprintf(stderr,"File: %s\n",file);


    xastir_snprintf(name_in2,sizeof(name_in2),"%s",name_in);
    xastir_snprintf(state_in2,sizeof(state_in2),"%s",state_in);
    xastir_snprintf(county_in2,sizeof(county_in2),"%s",county_in);
    xastir_snprintf(quad_in2,sizeof(quad_in2),"%s",quad_in);
    xastir_snprintf(type_in2,sizeof(type_in2),"%s",type_in);


    // Convert State/Province to upper-case always (they're
    // always upper-case in the GNIS files from USGS.
    to_upper(state_in2);


    if (debug_level & 16)
        fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n",
        name_in,state_in2,county_in,quad_in,type_in);


    // If "Match Case" togglebutton is not set, convert the
    // rest of the keys to upper-case.
    if (!follow_case) {
        to_upper(name_in2);
        to_upper(county_in2);
        to_upper(quad_in2);
        to_upper(type_in2);
    }


    // Check status of the file
    if (stat(file, &file_status) < 0) {
        // "Can't open file"
        popup_message( langcode("POPEM00028"), filename_in );
        return(0);
    }
    // Check for regular file
    if (!S_ISREG(file_status.st_mode)) {
        // "Can't open file"
        popup_message( langcode("POPEM00028"), filename_in );
        return(0);
    }
    // Attempt to open the file
    f = fopen (file, "r");
    if (f == NULL) {
        // "Can't open file"
        popup_message_always( langcode("POPEM00028"), filename_in );
        return(0);
    }
 
    while (!feof (f)) {     // Loop through entire file
        if ( get_line (f, line, MAX_FILENAME) ) {  // Snag one line of data
            if (strlen(line) > 0) {


//NOTE:  How do we handle running off the end of "line" while using "index"?
// Short lines here can cause segfaults.

                // Find end of Feature ID Number field
                j = index(line,'|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip this line
                }

//NOTE:  It'd be nice to take the part after the comma and put it before the rest
// of the text someday, i.e. "Cassidy, Lake".

                // Find end of Feature Name field
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';
                xastir_snprintf(name,sizeof(name),"%s",j);
                clean_string(name);

                // Find end of Feature Type field
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';
                xastir_snprintf(type,sizeof(type),"%s",i);
                clean_string(type);

                // Find end of State field
                i = index(++j,'|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';
                xastir_snprintf(state,sizeof(state),"%s",j);
                clean_string(state);

                // Find end of State Number Code field
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                // Find end of County Name field
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';
                xastir_snprintf(county,sizeof(county),"%s",j);
                clean_string(county);

                // Find end of County Number Code field
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                // Find end of Primary Latitude field (DDMMSSN)
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';
                xastir_snprintf(latitude,sizeof(latitude),"%s",j);
                clean_string(latitude);

                // Find end of Primary Longitude field (DDDMMSSW)
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';
                xastir_snprintf(longitude,sizeof(longitude),"%s",i);
                clean_string(longitude);

                // Find end of Primary Latitude field (decimal
                // degrees)
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';

                // Find end of Primary Longitude field (decimal
                // degrees)
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                // Find end of Source Latitude field (DMS)
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';

                // Find end of Source Longitude (DMS)
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                // Find end of Source Latitude field (decimal
                // degrees)
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';

                // Find end of Source Longitude field (decimal
                // degrees)
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                // Find end of Estimated Population field
                i = index(++j, '|');

                if (i == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                i[0] = '\0';

                xastir_snprintf(population,sizeof(population),"%s",j);
                clean_string(population);

                // Find end of Quad field
                j = index(++i, '|');

                if (j == NULL) {    // Pipe not found
                    continue;   // Skip line
                }

                j[0] = '\0';

                xastir_snprintf(quad,sizeof(quad),"%s",i);
                clean_string(quad);

                // If "Match Case" togglebutton is not set, convert
                // the data to upper-case before we do our compare.
                if (!follow_case) {
                    to_upper(name);
                    to_upper(state);
                    to_upper(county);
                    to_upper(quad);
                    to_upper(type);
                }

// Still need to code for the "Match Exact" togglebutton.


                // Now compare the input variables with those we've
                // parsed.  If a match, bring up a list of items which
                // match.
                //
                ok = 1;
                if (get_match) {    // Looking for exact match
                    if (name_in2[0] != '\0')
                        if (strcmp(name,name_in2) != 0)
                            ok = 0;
                    if (state_in2[0] != '\0')
                        if (strcmp(state,state_in2) != 0)
                            ok = 0;
                    if (county_in2[0] != '\0')
                        if (strcmp(county,county_in2) != 0)
                            ok = 0;
                    if (quad_in2[0] != '\0')
                        if (strcmp(quad,quad_in2) != 0)
                            ok = 0;
                    if (type_in2[0] != '\0')
                        if (strcmp(type,type_in2) != 0)
                            ok = 0;
                }
                else {  // Look for substring in file, not exact match
                    if (name_in2[0] != '\0')
                        if (strstr(name,name_in2) == NULL)
                            ok = 0;
                    if (state_in2[0] != '\0')
                        if (strstr(state,state_in2) == NULL)
                            ok = 0;
                    if (county_in2[0] != '\0')
                        if (strstr(county,county_in2) == NULL)
                            ok = 0;
                    if (quad_in2[0] != '\0')
                        if (strstr(quad,quad_in2) == NULL)
                            ok = 0;
                    if (type_in2[0] != '\0')
                        if (strstr(type,type_in2) == NULL)
                            ok = 0;
                }


                if (ok) {
                    if (debug_level & 16)
                        fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type);

// This one pops up the names of whatever we found.
// "Found It!"
//popup_message_always( langcode("POPEM00029"), name );

		    if (strlen(latitude) < 7) 
			continue;	// We really don't have any latitude here.
                    lat_dd[0] = latitude[0];
                    lat_dd[1] = latitude[1];
                    lat_dd[2] = '\0';
 
                    lat_mm[0] = latitude[2];
                    lat_mm[1] = latitude[3];
                    lat_mm[2] = '\0';

                    lat_ss[0] = latitude[4];
                    lat_ss[1] = latitude[5];
                    lat_ss[2] = '\0';

                    lat_dir[0] = latitude[6];
                    lat_dir[1] = '\0';

		    if (strlen(longitude) < 8) 
			continue;	// We really don't have any longitude here.
                    long_dd[0] = longitude[0];
                    long_dd[1] = longitude[1];
                    long_dd[2] = longitude[2];
                    long_dd[3] = '\0';
 
                    long_mm[0] = longitude[3];
                    long_mm[1] = longitude[4];
                    long_mm[2] = '\0';
 
                    long_ss[0] = longitude[5];
                    long_ss[1] = longitude[6];
                    long_ss[2] = '\0';
 
                    long_dir[0] = longitude[7];
                    long_dir[1] = '\0';

                    // Now must convert from DD MM SS format to DD MM.MM format so that we
                    // can run it through our conversion routine to Xastir coordinates.
                    if (1 != sscanf(lat_ss, "%d", &temp1)) {
                        fprintf(stderr,"locate_place:sscanf parsing error\n");
                    }

                    temp1 = (int)((temp1 / 60.0) * 100 + 0.5);  // Poor man's rounding
                    xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
                        lat_mm, temp1, lat_dir);
                    coord_lat = convert_lat_s2l(lat_str);

                    if (1 != sscanf(long_ss, "%d", &temp1)) {
                        fprintf(stderr,"locate_place:sscanf parsing error\n");
                    }

                    temp1 = (int)((temp1 / 60.0) * 100 + 0.5);  // Poor man's rounding
                    xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
                        long_mm, temp1, long_dir);
                    coord_lon = convert_lon_s2l(long_str);


//set_map_position(w, coord_lat, coord_lon);

                    // Fill in the array values with what we just
                    // found, increment the counter.
                    xastir_snprintf(match_array_name[my_count],200,"%s",name);
                    match_array_lat[my_count] = coord_lat;
                    match_array_long[my_count] = coord_lon;
                    my_count++;

                    // Check for a max array.  Return if it is full.
                    if (my_count > 50) {
                        return(50);
                    }
                }
            }
        }
    }

    return(my_count);
}


