1 /*
2 *
3 * XASTIR, Amateur Station Tracking and Information Reporting
4 * Copyright (C) 1999,2000 Frank Giannandrea
5 * Copyright (C) 2000-2019 The Xastir Group
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * Look at the README for more information on the program.
22 */
23
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif // HAVE_CONFIG_H
28
29 #include "snprintf.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <pwd.h>
38 #include <errno.h>
39
40 // Needed for Solaris
41 #ifdef HAVE_STRINGS_H
42 #include <strings.h>
43 #endif // HAVE_STRINGS_H
44
45 #include <dirent.h>
46 #include <netinet/in.h>
47 #include <Xm/XmAll.h>
48
49 #ifdef HAVE_X11_XPM_H
50 #include <X11/xpm.h>
51 #ifdef HAVE_LIBXPM // if we have both, prefer the extra library
52 #undef HAVE_XM_XPMI_H
53 #endif // HAVE_LIBXPM
54 #endif // HAVE_X11_XPM_H
55
56 #ifdef HAVE_XM_XPMI_H
57 #include <Xm/XpmI.h>
58 #endif // HAVE_XM_XPMI_H
59
60 #include <X11/Xlib.h>
61
62 #include <math.h>
63
64 #include "xastir.h"
65 #include "maps.h"
66 #include "alert.h"
67 #include "util.h"
68 #include "main.h"
69 #include "datum.h"
70 #include "draw_symbols.h"
71 #include "rotated.h"
72 #include "color.h"
73 #include "xa_config.h"
74
75 // Must be last include file
76 #include "leak_detection.h"
77
78
79
80 #define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
81
82 //NOTE: This function has a problem if a non-pop file is labeled
83 //with a ".pop" extension. It causes a segfault in Xastir. More
84 //error checking needs to be done in order to prevent this.
85
86 // draw_pop_map()
87 //
88 // Allows drawing a background map of labels for the viewport.
89 // Example format (old):
90 // "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East"
91 //
92 // Example format (new):
93 // 376016|ID|12th Ave Drain|stream|Canyon|16|027|433107N|1163348W|43.51861|-116.56333||||||||Nampa
94 //
95 // These types of files are available from ftp://aprs.tamu.edu/
96 // A typical filename would be: "WA_deci.gz". Do not get the other
97 // types of files which are columnar. The files that we parse are
98 // pipe-delimited.
99 // These files were originally from geonames.usgs.gov but the format changed
100 // on that site from population to elevation and the display of populated sites
101 // was severly broken by the new format. The population information should be
102 // gathered from census.gov or other locations concerned with population mapping.
103 //
draw_pop_map(Widget w,char * dir,char * filenm,alert_entry * UNUSED (alert),u_char UNUSED (alert_color),int destination_pixmap,map_draw_flags * UNUSED (mdf))104 void draw_pop_map (Widget w,
105 char *dir,
106 char *filenm,
107 alert_entry * UNUSED(alert),
108 u_char UNUSED(alert_color),
109 int destination_pixmap,
110 map_draw_flags * UNUSED(mdf) )
111 {
112 char file[MAX_FILENAME]; // Complete path/name of pop file
113 char short_filenm[MAX_FILENAME];
114 FILE *f; // Filehandle of pop file
115 char line[MAX_FILENAME]; // One line of text from file
116 char *i, *j;
117 char state[50];
118 char name[200];
119 char type[100];
120 char county[100];
121 char latitude[15];
122 char longitude[15];
123 char population[15];
124 char lat_dd[3];
125 char lat_mm[3];
126 char lat_ss[3];
127 char lat_dir[2];
128 char long_dd[4];
129 char long_mm[3];
130 char long_ss[3];
131 char long_dir[2];
132 char lat_str[15];
133 char long_str[15];
134 int temp1;
135 long coord_lon, coord_lat;
136 long min_lat, min_lon, max_lat, max_lon;
137 int ok;
138 long x,y;
139 char symbol_table, symbol_id, symbol_over;
140 unsigned long bottom_extent = 0l;
141 unsigned long top_extent = 0l;
142 unsigned long left_extent = 0l;
143 unsigned long right_extent = 0l;
144 char status_text[MAX_FILENAME];
145 int count = 0;
146
147
148 //fprintf(stderr,"draw_pop_map starting: %s/%s\n",dir,filenm);
149
150 xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
151
152 // Create a shorter filename for display (one that fits the
153 // status line more closely). Subtract the length of the
154 // "Indexing " and/or "Loading " strings as well.
155 if (strlen(filenm) > (41 - 9))
156 {
157 int avail = 41 - 11;
158 int new_len = strlen(filenm) - avail;
159
160 xastir_snprintf(short_filenm,
161 sizeof(short_filenm),
162 "..%s",
163 &filenm[new_len]);
164 }
165 else
166 {
167 xastir_snprintf(short_filenm,
168 sizeof(short_filenm),
169 "%s",
170 filenm);
171 }
172
173 // Screen view
174 min_lat = SE_corner_latitude;
175 max_lat = NW_corner_latitude;
176 min_lon = NW_corner_longitude;
177 max_lon = SE_corner_longitude;
178
179
180 // The map extents in the map index are checked in draw_map to
181 // see whether we should draw the map at all.
182
183
184 // Update the statusline for this map name
185 // Check whether we're indexing or drawing the map
186 if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
187 || (destination_pixmap == INDEX_NO_TIMESTAMPS) )
188 {
189 xastir_snprintf(status_text,
190 sizeof(status_text),
191 langcode ("BBARSTA039"),
192 short_filenm);
193 }
194 else
195 {
196 xastir_snprintf(status_text,
197 sizeof(status_text),
198 langcode ("BBARSTA028"),
199 short_filenm);
200 }
201 statusline(status_text,0); // Loading/Indexing ...
202
203
204 HandlePendingEvents(app_context);
205 if (interrupt_drawing_now)
206 {
207 // Update to screen
208 (void)XCopyArea(XtDisplay(da),
209 pixmap,
210 XtWindow(da),
211 gc,
212 0,
213 0,
214 (unsigned int)screen_width,
215 (unsigned int)screen_height,
216 0,
217 0);
218 return;
219 }
220
221
222 /*
223 Latest pipe-delimited format from USGS (as of 08/12/2004):
224 ----------------------------------------------------------
225 Feature ID Number (FID)
226 State Alpha Code
227 Feature Name
228 Feature Type
229 County Name
230 State Number Code (FIPS Code)
231 County Number Code (FIPS Code)
232 Primary Latitude (DMS)
233 Primary Longitude (DMS)
234 Primary Latitude (decimal degrees)
235 Primary Longitude (decimal degrees)
236 Source Latitude (DMS)
237 Source Longitude (DMS)
238 Source Latitude (decimal degrees)
239 Source Longitude (decimal degrees)
240 Elevation
241 Estimated Population
242 Federal Status
243 Cell Name
244 */
245
246
247 // Attempt to open the file
248 f = fopen (file, "r");
249 if (f != NULL)
250 {
251 while (!feof (f)) // Loop through entire file
252 {
253 int lat_in_view = 0;
254
255 count++;
256 if ((count % 16) == 0)
257 {
258
259 // Check whether map drawing should be interrupted.
260 // Check every 16 lines.
261 //
262 HandlePendingEvents(app_context);
263 if (interrupt_drawing_now)
264 {
265 (void)fclose (f);
266 // Update to screen
267 (void)XCopyArea(XtDisplay(da),
268 pixmap,
269 XtWindow(da),
270 gc,
271 0,
272 0,
273 (unsigned int)screen_width,
274 (unsigned int)screen_height,
275 0,
276 0);
277 return;
278 }
279 }
280
281 if ( get_line (f, line, MAX_FILENAME) ) // Snag one line of data
282 {
283
284 // It is common for these lines to have incredible
285 // numbers of spaces at the end, so trim them here.
286 (void)remove_trailing_spaces(line);
287
288 if (strlen(line) > 0)
289 {
290
291 // Default population, in case the field isn't
292 // present in the file.
293 xastir_snprintf(population,sizeof(population),"0");
294
295 // Examples of old/new format:
296 // 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
297 // 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
298
299 //NOTE: We handle running off the end of "line"
300 //via the "continue" statement. Skip the line
301 //if we don't find enough parameters while
302 //parsing.
303
304 // Find end of Feature ID Number field
305 j = index(line,'|');
306
307 if (j == NULL) // Pipe not found
308 {
309 continue; // Skip this line
310 }
311
312 // Find end of State field
313 i = index(j+1, '|');
314
315 if (i == NULL) // Pipe not found
316 {
317 continue; // Skip this line
318 }
319
320 i[0] = '\0';
321 xastir_snprintf(state,sizeof(state),"%s",j+1);
322
323 //NOTE: It'd be nice to take the part after the comma and put it before the rest
324 // of the text someday, i.e. "Cassidy, Lake".
325
326 // Find end of Feature Name field
327 j = index(i+1, '|');
328
329 if (j == NULL) // Pipe not found
330 {
331 continue; // Skip this line
332 }
333
334 j[0] = '\0';
335 xastir_snprintf(name,sizeof(name),"%s",i+1);
336
337 // Find end of Feature Type field
338 i = index(j+1, '|');
339
340 if (i == NULL) // Pipe not found
341 {
342 continue; // Skip this line
343 }
344
345 i[0] = '\0';
346 xastir_snprintf(type,sizeof(type),"%s",j+1);
347
348 // Find end of County Name field
349 j = index(i+1, '|');
350
351 if (j == NULL) // Pipe not found
352 {
353 continue; // Skip this line
354 }
355
356 j[0] = '\0';
357 xastir_snprintf(county,sizeof(county),"%s",i+1);
358
359 // Find end of State Number Code field
360 i = index(j+1, '|');
361
362 if (i == NULL) // Pipe not found
363 {
364 continue; // Skip this line
365 }
366
367 i[0] = '\0';
368
369 // Find end of County Number Code field
370 j = index(i+1, '|');
371
372 if (j == NULL) // Pipe not found
373 {
374 continue; // Skip this line
375 }
376
377 j[0] = '\0';
378
379 // Examples of old/new format:
380 // 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
381 // 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
382
383 // Find end of Primary Latitude field (DDMMSSN)
384 i = index(j+1, '|');
385
386 if (i == NULL) // Pipe not found
387 {
388 continue; // Skip this line
389 }
390
391 i[0] = '\0';
392 xastir_snprintf(latitude,sizeof(latitude),"%s",j+1);
393 if (!isdigit((int)latitude[0])) // skip record if not
394 {
395 continue; // numeric! (e.g. "UNKNOWN")
396 }
397
398 //WE7U
399 clean_string(latitude);
400
401 // Find end of Primary Longitude field (DDDMMSSW)
402 j = index(i+1, '|');
403
404 if (j == NULL) // Pipe not found
405 {
406 continue; // Skip this line
407 }
408
409 j[0] = '\0';
410 xastir_snprintf(longitude,sizeof(longitude),"%s",i+1);
411 if (!isdigit((int)longitude[0])) // skip record if not
412 {
413 continue; // numeric (e.g. UNKNOWN)
414 }
415
416 //WE7U
417 clean_string(longitude);
418
419 // Find end of Primary Latitude field (decimal
420 // degrees)
421 i = index(j+1, '|');
422
423 if (i == NULL) // Pipe not found
424 {
425 goto FINISH; // We have enough to process now
426 }
427
428 i[0] = '\0';
429
430 // Find end of Primary Longitude field (decimal
431 // degrees)
432 j = index(i+1, '|');
433
434 if (j == NULL) // Pipe not found
435 {
436 goto FINISH; // We have enough to process now
437 }
438
439 j[0] = '\0';
440
441 // Examples of old/new format:
442 // 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
443 // 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
444
445 // Find end of Source Latitude field (DMS) (old
446 // format) or elevation (new format)
447 i = index(j+1, '|');
448
449 if (i == NULL) // Pipe not found
450 {
451 goto FINISH; // We have enough to process now
452 }
453
454 i[0] = '\0';
455
456 // Find end of Source Longitude field (DMS) (old
457 // format) or
458 j = index(i+1, '|');
459
460 if (j == NULL) // Pipe not found
461 {
462 goto FINISH; // We have enough to process now
463 }
464
465 j[0] = '\0';
466
467 // Find end of Source Latitude field (decimal
468 // degrees)
469 i = index(j+1, '|');
470
471 if (i == NULL) // Pipe not found
472 {
473 goto FINISH; // We have enough to process now
474 }
475
476 i[0] = '\0';
477
478 // Find end of Source Longitude field (decimal
479 // degrees)
480 j = index(i+1, '|');
481
482 if (j == NULL) // Pipe not found
483 {
484 goto FINISH; // We have enough to process now
485 }
486
487 j[0] = '\0';
488
489 // Find end of Elevation field
490 i = index(j+1, '|');
491
492 if (i == NULL) // Pipe not found
493 {
494 goto FINISH; // We have enough to process now
495 }
496
497 i[0] = '\0';
498
499 // Find end of Estimated Population field
500 j = index(i+1, '|');
501
502 if (j == NULL) // Pipe not found
503 {
504 goto FINISH; // We have enough to process now
505 }
506
507 if ( j != NULL )
508 {
509 j[0] = '\0';
510 xastir_snprintf(population,sizeof(population),"%s",i+1);
511 }
512
513 FINISH:
514 // There are two more fields (old format),
515 // "Federal Status" and "Cell Name". We ignore
516 // those for now.
517
518 if (strlen(latitude) < 7)
519 {
520 continue; // We really don't have any latitude here!
521 }
522 lat_dd[0] = latitude[0];
523 lat_dd[1] = latitude[1];
524 lat_dd[2] = '\0';
525
526 lat_mm[0] = latitude[2];
527 lat_mm[1] = latitude[3];
528 lat_mm[2] = '\0';
529
530 lat_ss[0] = latitude[4];
531 lat_ss[1] = latitude[5];
532 lat_ss[2] = '\0';
533
534 lat_dir[0] = latitude[6];
535 lat_dir[1] = '\0';
536
537 // Now must convert from DD MM SS format to DD MM.MM format so that we
538 // can run it through our conversion routine to Xastir coordinates.
539 if (1 != sscanf(lat_ss, "%d", &temp1))
540 {
541 fprintf(stderr,"draw_pop_map:sscanf parsing error\n");
542 }
543
544 temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
545 xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
546 lat_mm, temp1, lat_dir);
547 coord_lat = convert_lat_s2l(lat_str);
548
549 // Quick test of latitude to see if it's within
550 // our view. If not and we're not doing
551 // indexing, skip this line and go on to the
552 // next.
553 if (coord_lat <= min_lat && coord_lat >= max_lat)
554 {
555 // Latitude is ok
556 lat_in_view++;
557 }
558 else // Latitude not in current view
559 {
560
561 // Check whether we're indexing the map
562 if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
563 || (destination_pixmap == INDEX_NO_TIMESTAMPS) )
564 {
565 // Process the line 'cuz we're indexing
566 }
567 else // Not indexing so skip to the next
568 {
569 // line in the file
570 continue;
571 }
572 }
573
574 if (strlen(longitude) < 8)
575 {
576 continue; // We really don't have any latitude here!
577 }
578 long_dd[0] = longitude[0];
579 long_dd[1] = longitude[1];
580 long_dd[2] = longitude[2];
581 long_dd[3] = '\0';
582
583 long_mm[0] = longitude[3];
584 long_mm[1] = longitude[4];
585 long_mm[2] = '\0';
586
587 long_ss[0] = longitude[5];
588 long_ss[1] = longitude[6];
589 long_ss[2] = '\0';
590
591 long_dir[0] = longitude[7];
592 long_dir[1] = '\0';
593
594 if (1 != sscanf(long_ss, "%d", &temp1))
595 {
596 fprintf(stderr,"draw_pop_map:sscanf parsing error\n");
597 }
598
599 temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
600 xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
601 long_mm, temp1, long_dir);
602 coord_lon = convert_lon_s2l(long_str);
603
604
605 // Check whether we're indexing the map
606 if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
607 || (destination_pixmap == INDEX_NO_TIMESTAMPS) )
608 {
609
610 // Save the min/max extents of the file. We
611 // should really initially set the extents
612 // to the min/max for the Xastir coordinate
613 // system, but in practice zeroes should
614 // work just as well.
615 //
616 if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l))
617 {
618 bottom_extent = coord_lat;
619 }
620 if ((coord_lat < (long)top_extent) || (top_extent == 0l))
621 {
622 top_extent = coord_lat;
623 }
624 if ((coord_lon < (long)left_extent) || (left_extent == 0l))
625 {
626 left_extent = coord_lon;
627 }
628 if ((coord_lon > (long)right_extent) || (right_extent == 0l))
629 {
630 right_extent = coord_lon;
631 }
632 }
633 // Now check whether this lat/lon is within our viewport. If it
634 // is, draw a text label at that location.
635 else if (coord_lon >= min_lon && coord_lon <= max_lon
636 && lat_in_view)
637 {
638
639 clean_string(state);
640 clean_string(name);
641 clean_string(type);
642 clean_string(county);
643 clean_string(population);
644
645 if (debug_level & 16)
646 {
647 fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t",
648 state, name, type, county, latitude, longitude);
649 fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t",
650 lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir);
651 fprintf(stderr,"%s\t%s\n", lat_str, long_str);
652 }
653
654 // Convert to screen coordinates. Careful
655 // here! The format conversions you'll need
656 // if you try to compress this into two
657 // lines will get you into trouble.
658 x = coord_lon - NW_corner_longitude;
659 y = coord_lat - NW_corner_latitude;
660 x /= scale_x;
661 y /= scale_y;
662
663 ok = 1;
664
665 /* set default symbol */
666 symbol_table = '/';
667 symbol_id = '.'; /* small x */
668 symbol_over = ' ';
669
670 if (strcasecmp(type,"airport") == 0)
671 {
672 symbol_id = '^';
673 if (scale_y > 100)
674 {
675 ok = 0;
676 }
677 }
678 else if (strcasecmp(type,"arch") == 0)
679 {
680 if (scale_y > 50)
681 {
682 ok = 0;
683 }
684 }
685 else if (strcasecmp(type,"area") == 0)
686 {
687 if (scale_y > 50)
688 {
689 ok = 0;
690 }
691 }
692 else if (strcasecmp(type,"arroyo") == 0)
693 {
694 if (scale_y > 50)
695 {
696 ok = 0;
697 }
698 }
699 else if (strcasecmp(type,"bar") == 0)
700 {
701 if (scale_y > 50)
702 {
703 ok = 0;
704 }
705 }
706 else if (strcasecmp(type,"basin") == 0)
707 {
708 if (scale_y > 50)
709 {
710 ok = 0;
711 }
712 }
713 else if (strcasecmp(type,"bay") == 0)
714 {
715 if (scale_y > 50)
716 {
717 ok = 0;
718 }
719 }
720 else if (strcasecmp(type,"beach") == 0)
721 {
722 if (scale_y > 50)
723 {
724 ok = 0;
725 }
726 }
727 else if (strcasecmp(type,"bench") == 0)
728 {
729 if (scale_y > 50)
730 {
731 ok = 0;
732 }
733 }
734 else if (strcasecmp(type,"bend") == 0)
735 {
736 if (scale_y > 50)
737 {
738 ok = 0;
739 }
740 }
741 else if (strcasecmp(type,"bridge") == 0)
742 {
743 if (scale_y > 50)
744 {
745 ok = 0;
746 }
747 }
748 else if (strcasecmp(type,"building") == 0)
749 {
750 if (scale_y > 50)
751 {
752 ok = 0;
753 }
754 }
755 else if (strcasecmp(type,"canal") == 0)
756 {
757 if (scale_y > 50)
758 {
759 ok = 0;
760 }
761 }
762 else if (strcasecmp(type,"cape") == 0)
763 {
764 if (scale_y > 50)
765 {
766 ok = 0;
767 }
768 }
769 else if (strcasecmp(type,"cave") == 0)
770 {
771 if (scale_y > 50)
772 {
773 ok = 0;
774 }
775 }
776 else if (strcasecmp(type,"cemetery") == 0)
777 {
778 symbol_table = '\\';
779 symbol_id = '+';
780 if (scale_y > 50)
781 {
782 ok = 0;
783 }
784 }
785 else if (strcasecmp(type,"census") == 0)
786 {
787 /* if (scale_y > 50)*/ /* Census divisions */
788 ok = 0;
789 }
790 else if (strcasecmp(type,"channel") == 0)
791 {
792 if (scale_y > 50)
793 {
794 ok = 0;
795 }
796 }
797 else if (strcasecmp(type,"church") == 0)
798 {
799 symbol_table = '\\';
800 symbol_id = '+';
801 if (scale_y > 50)
802 {
803 ok = 0;
804 }
805 }
806 else if (strcasecmp(type,"civil") == 0)
807 {
808 if (scale_y > 50)
809 {
810 ok = 0;
811 }
812 }
813 else if (strcasecmp(type,"cliff") == 0)
814 {
815 if (scale_y > 50)
816 {
817 ok = 0;
818 }
819 }
820 else if (strcasecmp(type,"crater") == 0)
821 {
822 if (scale_y > 50)
823 {
824 ok = 0;
825 }
826 }
827 else if (strcasecmp(type,"crossing") == 0)
828 {
829 if (scale_y > 50)
830 {
831 ok = 0;
832 }
833 }
834 else if (strcasecmp(type,"dam") == 0)
835 {
836 if (scale_y > 50)
837 {
838 ok = 0;
839 }
840 }
841 else if (strcasecmp(type,"falls") == 0)
842 {
843 if (scale_y > 50)
844 {
845 ok = 0;
846 }
847 }
848 else if (strcasecmp(type,"flat") == 0)
849 {
850 if (scale_y > 50)
851 {
852 ok = 0;
853 }
854 }
855 else if (strcasecmp(type,"forest") == 0)
856 {
857 if (scale_y > 50)
858 {
859 ok = 0;
860 }
861 }
862 else if (strcasecmp(type,"gap") == 0)
863 {
864 if (scale_y > 50)
865 {
866 ok = 0;
867 }
868 }
869 else if (strcasecmp(type,"geyser") == 0)
870 {
871 if (scale_y > 50)
872 {
873 ok = 0;
874 }
875 }
876 else if (strcasecmp(type,"glacier") == 0)
877 {
878 if (scale_y > 50)
879 {
880 ok = 0;
881 }
882 }
883 else if (strcasecmp(type,"gut") == 0)
884 {
885 if (scale_y > 50)
886 {
887 ok = 0;
888 }
889 }
890 else if (strcasecmp(type,"harbor") == 0)
891 {
892 if (scale_y > 50)
893 {
894 ok = 0;
895 }
896 }
897 else if (strcasecmp(type,"hospital") == 0)
898 {
899 symbol_id = 'h';
900 if (scale_y > 50)
901 {
902 ok = 0;
903 }
904 }
905 else if (strcasecmp(type,"island") == 0)
906 {
907 if (scale_y > 50)
908 {
909 ok = 0;
910 }
911 }
912 else if (strcasecmp(type,"isthmus") == 0)
913 {
914 if (scale_y > 50)
915 {
916 ok = 0;
917 }
918 }
919 else if (strcasecmp(type,"lake") == 0)
920 {
921 if (scale_y > 50)
922 {
923 ok = 0;
924 }
925 }
926 else if (strcasecmp(type,"lava") == 0)
927 {
928 if (scale_y > 50)
929 {
930 ok = 0;
931 }
932 }
933 else if (strcasecmp(type,"levee") == 0)
934 {
935 if (scale_y > 50)
936 {
937 ok = 0;
938 }
939 }
940 else if (strcasecmp(type,"locale") == 0)
941 {
942 if (scale_y > 50)
943 {
944 ok = 0;
945 }
946 }
947 else if (strcasecmp(type,"military") == 0)
948 {
949 if (scale_y > 50)
950 {
951 ok = 0;
952 }
953 }
954 else if (strcasecmp(type,"mine") == 0)
955 {
956 if (scale_y > 50)
957 {
958 ok = 0;
959 }
960 }
961 else if (strcasecmp(type,"oilfield") == 0)
962 {
963 if (scale_y > 50)
964 {
965 ok = 0;
966 }
967 }
968 else if (strcasecmp(type,"other") == 0)
969 {
970 if (scale_y > 50)
971 {
972 ok = 0;
973 }
974 }
975 else if (strcasecmp(type,"park") == 0)
976 {
977 symbol_table = '\\';
978 symbol_id = ';';
979 if (scale_y > 50)
980 {
981 ok = 0;
982 }
983 }
984 else if (strcasecmp(type,"pillar") == 0)
985 {
986 if (scale_y > 50)
987 {
988 ok = 0;
989 }
990 }
991 else if (strcasecmp(type,"plain") == 0)
992 {
993 if (scale_y > 50)
994 {
995 ok = 0;
996 }
997 }
998 else if (strcasecmp(type,"po") == 0)
999 {
1000 symbol_id = ']';
1001 if (scale_y > 50)
1002 {
1003 ok = 0;
1004 }
1005 }
1006 else if (strcasecmp(type,"ppl") == 0)
1007 {
1008 symbol_id = '/';
1009 if (scale_y > 20000) // Don't draw cities at zoom higher than 20,000
1010 {
1011 ok = 0;
1012 }
1013 else if (scale_y > 4000) // Don't draw cities of less than 20,000
1014 {
1015 if (atoi(population) < 50000)
1016 {
1017 ok = 0;
1018 }
1019 }
1020 else if (scale_y > 1500) // Don't draw cities of less than 10,000
1021 {
1022 if (atoi(population) < 20000)
1023 {
1024 ok = 0;
1025 }
1026 }
1027 else if (scale_y > 750) // Don't draw cities of less than 5,000
1028 {
1029 if (atoi(population) < 10000)
1030 {
1031 ok = 0;
1032 }
1033 }
1034 else if (scale_y > 200) // Don't draw cities
1035 {
1036 // of less than 1,000
1037 if (atoi(population) < 1000)
1038 {
1039 ok = 0;
1040 //fprintf(stderr,
1041 // "Name: %s\tPopulation: %s\n",name,
1042 // population);
1043 }
1044 }
1045 }
1046 else if (strcasecmp(type,"range") == 0)
1047 {
1048 if (scale_y > 50)
1049 {
1050 ok = 0;
1051 }
1052 }
1053 else if (strcasecmp(type,"rapids") == 0)
1054 {
1055 if (scale_y > 50)
1056 {
1057 ok = 0;
1058 }
1059 }
1060 else if (strcasecmp(type,"reserve") == 0)
1061 {
1062 if (scale_y > 50)
1063 {
1064 ok = 0;
1065 }
1066 }
1067 else if (strcasecmp(type,"reservoir") == 0)
1068 {
1069 if (scale_y > 50)
1070 {
1071 ok = 0;
1072 }
1073 }
1074 else if (strcasecmp(type,"ridge") == 0)
1075 {
1076 if (scale_y > 50)
1077 {
1078 ok = 0;
1079 }
1080 }
1081 else if (strcasecmp(type,"school") == 0)
1082 {
1083 symbol_id = 'K';
1084 if (scale_y > 50)
1085 {
1086 ok = 0;
1087 }
1088 }
1089 else if (strcasecmp(type,"sea") == 0)
1090 {
1091 if (scale_y > 50)
1092 {
1093 ok = 0;
1094 }
1095 }
1096 else if (strcasecmp(type,"slope") == 0)
1097 {
1098 if (scale_y > 50)
1099 {
1100 ok = 0;
1101 }
1102 }
1103 else if (strcasecmp(type,"spring") == 0)
1104 {
1105 if (scale_y > 50)
1106 {
1107 ok = 0;
1108 }
1109 }
1110 else if (strcasecmp(type,"stream") == 0)
1111 {
1112 if (scale_y > 50)
1113 {
1114 ok = 0;
1115 }
1116 }
1117 else if (strcasecmp(type,"summit") == 0)
1118 {
1119 if (scale_y > 100)
1120 {
1121 ok = 0;
1122 }
1123 }
1124 else if (strcasecmp(type,"swamp") == 0)
1125 {
1126 if (scale_y > 50)
1127 {
1128 ok = 0;
1129 }
1130 }
1131 else if (strcasecmp(type,"trail") == 0)
1132 {
1133 if (scale_y > 50)
1134 {
1135 ok = 0;
1136 }
1137 }
1138 else if (strcasecmp(type,"tower") == 0)
1139 {
1140 symbol_id = 'r';
1141 if (scale_y > 50)
1142 {
1143 ok = 0;
1144 }
1145 }
1146 else if (strcasecmp(type,"tunnel") == 0)
1147 {
1148 if (scale_y > 50)
1149 {
1150 ok = 0;
1151 }
1152 }
1153 else if (strcasecmp(type,"valley") == 0)
1154 {
1155 if (scale_y > 50)
1156 {
1157 ok = 0;
1158 }
1159 }
1160 else if (strcasecmp(type,"well") == 0)
1161 {
1162 if (scale_y > 50)
1163 {
1164 ok = 0;
1165 }
1166 }
1167 else if (strcasecmp(type,"woods") == 0)
1168 {
1169 if (scale_y > 50)
1170 {
1171 ok = 0;
1172 }
1173 }
1174 else if (strcasecmp(type,"ruin") == 0)
1175 {
1176 if (scale_y > 50)
1177 {
1178 ok = 0;
1179 }
1180 }
1181 else
1182 {
1183 fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n",
1184 type,state,county,name);
1185 }
1186
1187 if (ok == 1) // If ok to draw it
1188 {
1189 symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
1190 draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name));
1191 }
1192
1193 }
1194 else
1195 {
1196 //fprintf(stderr,"Not in viewport. Coordinates: %ld %ld\n",coord_lat,coord_lon);
1197 //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat);
1198 //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon);
1199 }
1200 }
1201 }
1202 } // End of while
1203 (void)fclose (f);
1204
1205
1206 // Check whether we're indexing the map
1207 if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
1208 || (destination_pixmap == INDEX_NO_TIMESTAMPS) )
1209 {
1210
1211 // We're indexing only. Save the extents in the index.
1212 index_update_xastir(filenm, // Filename only
1213 bottom_extent, // Bottom
1214 top_extent, // Top
1215 left_extent, // Left
1216 right_extent, // Right
1217 99999); // Default Map Level
1218 }
1219 }
1220 else
1221 {
1222 fprintf(stderr,"Couldn't open file: %s\n", file);
1223 return;
1224 }
1225 if (debug_level & 16)
1226 {
1227 fprintf(stderr,"Exiting draw_pop_map\n");
1228 }
1229 }
1230
1231
1232
1233
1234
1235 // Search for a placename among pop files
1236 //
1237 // We need to search a file in the map directory that has the filename
1238 // STATE.gis, where STATE is from the "state" variable passed to us.
1239 // Search for the placename/county/state/type that the user requested.
1240 // Once found, center the map on that location or bring up a response
1241 // dialog that asks whether one wants to go there, and that dialog
1242 // provides info about the place found, with a possible selection
1243 // out of a list of matches.
1244 // Might also need to place a label at that position on the map in
1245 // case that pop file isn't currently selected.
1246 //
pop_locate_place(Widget UNUSED (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])1247 int pop_locate_place( Widget UNUSED(w),
1248 char *name_in,
1249 char *state_in,
1250 char *county_in,
1251 char *quad_in,
1252 char *type_in,
1253 char *filename_in,
1254 int follow_case,
1255 int get_match,
1256 char match_array_name[50][200],
1257 long match_array_lat[50],
1258 long match_array_long[50] )
1259 {
1260
1261 char file[MAX_FILENAME]; // Complete path/name of pop file
1262 FILE *f; // Filehandle of pop file
1263 char line[MAX_FILENAME]; // One line of text from file
1264 char *i, *j;
1265 char state[50];
1266 char state_in2[50];
1267 char name[200];
1268 char name_in2[50];
1269 char type[100];
1270 char type_in2[50];
1271 char county[100];
1272 char county_in2[50];
1273 char quad[100];
1274 char quad_in2[100];
1275 char latitude[15];
1276 char longitude[15];
1277 char population[15];
1278 char lat_dd[3];
1279 char lat_mm[3];
1280 char lat_ss[3];
1281 char lat_dir[2];
1282 char long_dd[4];
1283 char long_mm[3];
1284 char long_ss[3];
1285 char long_dir[2];
1286 char lat_str[15];
1287 char long_str[15];
1288 int temp1;
1289 long coord_lon, coord_lat;
1290 int ok;
1291 struct stat file_status;
1292 int my_count = 0;
1293
1294
1295 xastir_snprintf(file,sizeof(file),"%s",filename_in);
1296
1297 if (debug_level & 16)
1298 {
1299 fprintf(stderr,"File: %s\n",file);
1300 }
1301
1302
1303 xastir_snprintf(name_in2,sizeof(name_in2),"%s",name_in);
1304 xastir_snprintf(state_in2,sizeof(state_in2),"%s",state_in);
1305 xastir_snprintf(county_in2,sizeof(county_in2),"%s",county_in);
1306 xastir_snprintf(quad_in2,sizeof(quad_in2),"%s",quad_in);
1307 xastir_snprintf(type_in2,sizeof(type_in2),"%s",type_in);
1308
1309
1310 // Convert State/Province to upper-case always (they're
1311 // always upper-case in the pop files from USGS.
1312 to_upper(state_in2);
1313
1314
1315 if (debug_level & 16)
1316 fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n",
1317 name_in,state_in2,county_in,quad_in,type_in);
1318
1319
1320 // If "Match Case" togglebutton is not set, convert the
1321 // rest of the keys to upper-case.
1322 if (!follow_case)
1323 {
1324 to_upper(name_in2);
1325 to_upper(county_in2);
1326 to_upper(quad_in2);
1327 to_upper(type_in2);
1328 }
1329
1330
1331 // Check status of the file
1332 if (stat(file, &file_status) < 0)
1333 {
1334 // "Can't open file"
1335 popup_message( langcode("POPEM00028"), filename_in );
1336 return(0);
1337 }
1338 // Check for regular file
1339 if (!S_ISREG(file_status.st_mode))
1340 {
1341 // "Can't open file"
1342 popup_message( langcode("POPEM00028"), filename_in );
1343 return(0);
1344 }
1345 // Attempt to open the file
1346 f = fopen (file, "r");
1347 if (f == NULL)
1348 {
1349 // "Can't open file"
1350 popup_message_always( langcode("POPEM00028"), filename_in );
1351 return(0);
1352 }
1353
1354 while (!feof (f)) // Loop through entire file
1355 {
1356 if ( get_line (f, line, MAX_FILENAME) ) // Snag one line of data
1357 {
1358 if (strlen(line) > 0)
1359 {
1360
1361
1362 //NOTE: How do we handle running off the end of "line" while using "index"?
1363 // Short lines here can cause segfaults.
1364
1365 // Find end of Feature ID Number field
1366 j = index(line,'|');
1367
1368 if (j == NULL) // Pipe not found
1369 {
1370 continue; // Skip this line
1371 }
1372
1373 // Find end of State field
1374 i = index(++j,'|');
1375
1376 if (i == NULL) // Pipe not found
1377 {
1378 continue; // Skip line
1379 }
1380
1381 i[0] = '\0';
1382 xastir_snprintf(state,sizeof(state),"%s",j);
1383 clean_string(state);
1384
1385 //NOTE: It'd be nice to take the part after the comma and put it before the rest
1386 // of the text someday, i.e. "Cassidy, Lake".
1387
1388 // Find end of Feature Name field
1389 j = index(++i, '|');
1390
1391 if (j == NULL) // Pipe not found
1392 {
1393 continue; // Skip line
1394 }
1395
1396 j[0] = '\0';
1397 xastir_snprintf(name,sizeof(name),"%s",i);
1398 clean_string(name);
1399
1400 // Find end of Feature Type field
1401 i = index(++j, '|');
1402
1403 if (i == NULL) // Pipe not found
1404 {
1405 continue; // Skip line
1406 }
1407
1408 i[0] = '\0';
1409 xastir_snprintf(type,sizeof(type),"%s",j);
1410 clean_string(type);
1411
1412 // Find end of County Name field
1413 j = index(++i, '|');
1414
1415 if (j == NULL) // Pipe not found
1416 {
1417 continue; // Skip line
1418 }
1419
1420 j[0] = '\0';
1421 xastir_snprintf(county,sizeof(county),"%s",i);
1422 clean_string(county);
1423
1424 // Find end of State Number Code field
1425 i = index(++j, '|');
1426
1427 if (i == NULL) // Pipe not found
1428 {
1429 continue; // Skip line
1430 }
1431
1432 i[0] = '\0';
1433
1434 // Find end of County Number Code field
1435 j = index(++i, '|');
1436
1437 if (j == NULL) // Pipe not found
1438 {
1439 continue; // Skip line
1440 }
1441
1442 j[0] = '\0';
1443
1444 // Find end of Primary Latitude field (DDMMSSN)
1445 i = index(++j, '|');
1446
1447 if (i == NULL) // Pipe not found
1448 {
1449 continue; // Skip line
1450 }
1451
1452 i[0] = '\0';
1453 xastir_snprintf(latitude,sizeof(latitude),"%s",j);
1454 clean_string(latitude);
1455
1456 // Find end of Primary Longitude field (DDDMMSSW)
1457 j = index(++i, '|');
1458
1459 if (j == NULL) // Pipe not found
1460 {
1461 continue; // Skip line
1462 }
1463
1464 j[0] = '\0';
1465 xastir_snprintf(longitude,sizeof(longitude),"%s",i);
1466 clean_string(longitude);
1467
1468 // Find end of Primary Latitude field (decimal
1469 // degrees)
1470 i = index(++j, '|');
1471
1472 if (i == NULL) // Pipe not found
1473 {
1474 continue; // Skip line
1475 }
1476
1477 i[0] = '\0';
1478
1479 // Find end of Primary Longitude field (decimal
1480 // degrees)
1481 j = index(++i, '|');
1482
1483 if (j == NULL) // Pipe not found
1484 {
1485 continue; // Skip line
1486 }
1487
1488 j[0] = '\0';
1489
1490 // Find end of Source Latitude field (DMS)
1491 i = index(++j, '|');
1492
1493 if (i == NULL) // Pipe not found
1494 {
1495 continue; // Skip line
1496 }
1497
1498 i[0] = '\0';
1499
1500 // Find end of Source Longitude (DMS)
1501 j = index(++i, '|');
1502
1503 if (j == NULL) // Pipe not found
1504 {
1505 continue; // Skip line
1506 }
1507
1508 j[0] = '\0';
1509
1510 // Find end of Source Latitude field (decimal
1511 // degrees)
1512 i = index(++j, '|');
1513
1514 if (i == NULL) // Pipe not found
1515 {
1516 continue; // Skip line
1517 }
1518
1519 i[0] = '\0';
1520
1521 // Find end of Source Longitude field (decimal
1522 // degrees)
1523 j = index(++i, '|');
1524
1525 if (j == NULL) // Pipe not found
1526 {
1527 continue; // Skip line
1528 }
1529
1530 j[0] = '\0';
1531
1532 // Find end of Elevation field
1533 i = index(++j, '|');
1534
1535 if (i == NULL) // Pipe not found
1536 {
1537 continue; // Skip line
1538 }
1539
1540 i[0] = '\0';
1541
1542 // Find end of Estimated Population field
1543 j = index(++i, '|');
1544
1545 if (j == NULL) // Pipe not found
1546 {
1547 continue; // Skip line
1548 }
1549
1550 j[0] = '\0';
1551 xastir_snprintf(population,sizeof(population),"%s",i);
1552 clean_string(population);
1553
1554 // Snag Cell Name field (Quad name, last field)
1555 xastir_snprintf(quad,sizeof(quad),"%s",j+1);
1556 clean_string(quad);
1557
1558 // If "Match Case" togglebutton is not set, convert
1559 // the data to upper-case before we do our compare.
1560 if (!follow_case)
1561 {
1562 to_upper(name);
1563 to_upper(state);
1564 to_upper(county);
1565 to_upper(quad);
1566 to_upper(type);
1567 }
1568
1569 // Still need to code for the "Match Exact" togglebutton.
1570
1571
1572 // Now compare the input variables with those we've
1573 // parsed. If a match, bring up a list of items which
1574 // match.
1575 //
1576 ok = 1;
1577 if (get_match) // Looking for exact match
1578 {
1579 if (name_in2[0] != '\0')
1580 if (strcmp(name,name_in2) != 0)
1581 {
1582 ok = 0;
1583 }
1584 if (state_in2[0] != '\0')
1585 if (strcmp(state,state_in2) != 0)
1586 {
1587 ok = 0;
1588 }
1589 if (county_in2[0] != '\0')
1590 if (strcmp(county,county_in2) != 0)
1591 {
1592 ok = 0;
1593 }
1594 if (quad_in2[0] != '\0')
1595 if (strcmp(quad,quad_in2) != 0)
1596 {
1597 ok = 0;
1598 }
1599 if (type_in2[0] != '\0')
1600 if (strcmp(type,type_in2) != 0)
1601 {
1602 ok = 0;
1603 }
1604 }
1605 else // Look for substring in file, not exact match
1606 {
1607 if (name_in2[0] != '\0')
1608 if (strstr(name,name_in2) == NULL)
1609 {
1610 ok = 0;
1611 }
1612 if (state_in2[0] != '\0')
1613 if (strstr(state,state_in2) == NULL)
1614 {
1615 ok = 0;
1616 }
1617 if (county_in2[0] != '\0')
1618 if (strstr(county,county_in2) == NULL)
1619 {
1620 ok = 0;
1621 }
1622 if (quad_in2[0] != '\0')
1623 if (strstr(quad,quad_in2) == NULL)
1624 {
1625 ok = 0;
1626 }
1627 if (type_in2[0] != '\0')
1628 if (strstr(type,type_in2) == NULL)
1629 {
1630 ok = 0;
1631 }
1632 }
1633
1634
1635 if (ok)
1636 {
1637 if (debug_level & 16)
1638 {
1639 fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type);
1640 }
1641
1642 // This one pops up the names of whatever we found.
1643 // "Found It!"
1644 //popup_message_always( langcode("POPEM00029"), name );
1645
1646 if (strlen(latitude) < 7)
1647 {
1648 continue; // We really don't have any latitude here!
1649 }
1650 lat_dd[0] = latitude[0];
1651 lat_dd[1] = latitude[1];
1652 lat_dd[2] = '\0';
1653
1654 lat_mm[0] = latitude[2];
1655 lat_mm[1] = latitude[3];
1656 lat_mm[2] = '\0';
1657
1658 lat_ss[0] = latitude[4];
1659 lat_ss[1] = latitude[5];
1660 lat_ss[2] = '\0';
1661
1662 lat_dir[0] = latitude[6];
1663 lat_dir[1] = '\0';
1664
1665 if (strlen(longitude) < 8)
1666 {
1667 continue; // We really don't have any longitude here!
1668 }
1669 long_dd[0] = longitude[0];
1670 long_dd[1] = longitude[1];
1671 long_dd[2] = longitude[2];
1672 long_dd[3] = '\0';
1673
1674 long_mm[0] = longitude[3];
1675 long_mm[1] = longitude[4];
1676 long_mm[2] = '\0';
1677
1678 long_ss[0] = longitude[5];
1679 long_ss[1] = longitude[6];
1680 long_ss[2] = '\0';
1681
1682 long_dir[0] = longitude[7];
1683 long_dir[1] = '\0';
1684
1685 // Now must convert from DD MM SS format to DD MM.MM format so that we
1686 // can run it through our conversion routine to Xastir coordinates.
1687 if (1 != sscanf(lat_ss, "%d", &temp1))
1688 {
1689 fprintf(stderr,"locate_place:sscanf parsing error\n");
1690 }
1691
1692 temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
1693 xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
1694 lat_mm, temp1, lat_dir);
1695 coord_lat = convert_lat_s2l(lat_str);
1696
1697 if (1 != sscanf(long_ss, "%d", &temp1))
1698 {
1699 fprintf(stderr,"locate_place:sscanf parsing error\n");
1700 }
1701
1702 temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
1703 xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
1704 long_mm, temp1, long_dir);
1705 coord_lon = convert_lon_s2l(long_str);
1706
1707
1708 //set_map_position(w, coord_lat, coord_lon);
1709
1710 // Fill in the array values with what we just
1711 // found, increment the counter.
1712 xastir_snprintf(match_array_name[my_count],200,"%s",name);
1713 match_array_lat[my_count] = coord_lat;
1714 match_array_long[my_count] = coord_lon;
1715 my_count++;
1716
1717 // Check for a max array. Return if it is full.
1718 if (my_count > 50)
1719 {
1720 return(50);
1721 }
1722 }
1723 }
1724 }
1725 }
1726
1727 return(my_count);
1728 }
1729
1730
1731