/[zanavi_public1]/navit/navit/map/garmin_img/garmin_img.c
ZANavi

Contents of /navit/navit/map/garmin_img/garmin_img.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 34693 byte(s)
import files
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2008 Navit Team
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     #include <glib.h>
21     #include <stdlib.h>
22     #include <stdio.h>
23     #include <string.h>
24     #include <math.h>
25     #include "config.h"
26     #include "plugin.h"
27     #include "data.h"
28     #include "projection.h"
29     #include "map.h"
30     #include "maptype.h"
31     #include "item.h"
32     #include "attr.h"
33     #include "coord.h"
34     #include "transform.h"
35     #include <stdio.h>
36     #include "attr.h"
37     #include "coord.h"
38    
39     struct file {
40     FILE *f;
41     int offset;
42     };
43    
44    
45     int shift=5;
46     int subdiv_next=0x10;
47    
48    
49     static void *
50     file_read(struct file *f, int offset, int size)
51     {
52     void *ptr;
53     int ret;
54    
55     ptr=calloc(size, 1);
56     if (! ptr)
57     return ptr;
58     fseek(f->f, f->offset+offset, SEEK_SET);
59     ret=fread(ptr, size, 1, f->f);
60     if (ret != 1) {
61     printf("fread %d vs %d offset %d+%d(0x%x)\n", ret, size, f->offset, offset,offset);
62     g_assert(1==0);
63     }
64     return ptr;
65     }
66    
67     static void
68     file_free(void *ptr)
69     {
70     free(ptr);
71     }
72    
73     struct offset_len {
74     int offset;
75     int length;
76     } __attribute ((packed));
77    
78     static void
79     dump_offset_len(struct offset_len *off_len)
80     {
81     printf("offset: 0x%x(%d) length 0x%x(%d)\n", off_len->offset, off_len->offset, off_len->length, off_len->length);
82     }
83    
84     struct timestamp {
85     short creation_year;
86     char creation_month;
87     char creation_day;
88     char creation_hour;
89     char creation_minute;
90     char creation_second;
91     } __attribute__((packed));
92    
93     struct img_header {
94     char xor;
95     char zero1[9];
96     char update_month;
97     char update_year;
98     char zero2[3];
99     char checksum[1];
100     char signature[7];
101     char unknown1[1];
102     char unknown2[2];
103     char unknown3[2];
104     char unknown4[2];
105     char unknown5[2];
106     char zero3[25];
107     struct timestamp ts;
108     char unknown6;
109     char map_file_identifier[7];
110     char unknown12;
111     char map_description1[20];
112     short unknown13;
113     short unknown14;
114     char e1;
115     char e2;
116     char other[413];
117     char zero4[512];
118     char unknown7;
119     char unknown8[11];
120     int file_offset;
121     char unknown9;
122     char unknown10[15];
123     char unknown11[480];
124     } __attribute__((packed));
125    
126     static void
127     dump_ts(struct timestamp *ts)
128     {
129     printf("%d-%02d-%02d %02d:%02d:%02d\n", ts->creation_year, ts->creation_month, ts->creation_day, ts->creation_hour, ts->creation_minute, ts->creation_second);
130     }
131    
132     #if 0
133     static void
134     dump_img(struct img_header *img_hdr)
135     {
136     printf("signature: '%s'\n", img_hdr->signature);
137     printf("creation: ");
138     dump_ts(&img_hdr->ts);
139     printf("map_file_identifier: '%s'\n", img_hdr->map_file_identifier);
140     printf("file_offset: 0x%x\n", img_hdr->file_offset);
141     printf("e1: 0x%x(%d)\n", img_hdr->e1, img_hdr->e1);
142     printf("e2: 0x%x(%d)\n", img_hdr->e2, img_hdr->e2);
143     printf("offset 0x%x\n", (int) &img_hdr->e1 - (int) img_hdr);
144     printf("size %d\n", sizeof(*img_hdr));
145     }
146     #endif
147    
148     struct fat_block {
149     char flag;
150     char filename[8];
151     char type[3];
152     int size;
153     char zero1;
154     char part;
155     char zero[14];
156     unsigned short blocks[240];
157     } __attribute__((packed));
158    
159     #if 0
160     static void
161     dump_fat_block(struct fat_block *fat_blk)
162     {
163     int i=0;
164     char name[9];
165     char type[4];
166     printf("flag: 0x%x(%d)\n", fat_blk->flag, fat_blk->flag);
167     strcpy(name, fat_blk->filename);
168     name[8]='\0';
169     strcpy(type, fat_blk->type);
170     type[3]='\0';
171     printf("name: '%s.%s'\n", name, type);
172     printf("size: 0x%x(%d)\n", fat_blk->size, fat_blk->size);
173     printf("part: 0x%x(%d)\n", fat_blk->part, fat_blk->part);
174     printf("blocks: ");
175     while (i < 240) {
176     printf("0x%x(%d) ",fat_blk->blocks[i], fat_blk->blocks[i]);
177     if (fat_blk->blocks[i] == 0xffff)
178     break;
179     i++;
180     }
181     printf("size: %d\n", sizeof(*fat_blk));
182    
183     }
184     #endif
185    
186     struct file_header {
187     short header_len;
188     char type[10];
189     char unknown1;
190     char unknown2;
191     struct timestamp ts;
192     } __attribute__((packed));
193    
194     static void
195     dump_file(struct file_header *fil_hdr)
196     {
197     printf("header_len: %d\n", fil_hdr->header_len);
198     printf("type: '%s'\n", fil_hdr->type);
199     printf("unknown1: 0x%x(%d)\n", fil_hdr->unknown1, fil_hdr->unknown1);
200     printf("unknown2: 0x%x(%d)\n", fil_hdr->unknown2, fil_hdr->unknown2);
201     printf("creation: ");
202     dump_ts(&fil_hdr->ts);
203     printf("size %d\n", sizeof(*fil_hdr));
204     }
205    
206     struct region_header {
207     struct file_header fil_hdr;
208     struct offset_len offset_len;
209     } __attribute__((packed));
210    
211     #if 0
212     static void
213     dump_region(struct region_header *rgn_hdr)
214     {
215     dump_offset_len(&rgn_hdr->offset_len);
216     }
217     #endif
218    
219     struct map_priv {
220     int id;
221     char *filename;
222     };
223    
224     struct map_rect_priv {
225     struct coord_rect r;
226     int limit;
227    
228     struct file tre;
229     struct tree_header *tre_hdr;
230     struct file rgn;
231     struct region_header *rgn_hdr;
232     struct file lbl;
233     struct label_header *lbl_hdr;
234     char *label;
235    
236     int subdiv_level_count;
237     int subdiv_pos;
238     char *subdiv;
239    
240     int rgn_offset;
241     int rgn_end;
242     struct rgn_point *pnt;
243     struct rgn_poly *ply;
244     unsigned char *ply_data;
245     int ply_bitpos;
246     int ply_bitcount;
247     int ply_lngbits;
248     int ply_latbits;
249     int ply_lng;
250     int ply_lat;
251     int ply_lnglimit;
252     int ply_latlimit;
253     int ply_lngsign;
254     int ply_latsign;
255     struct offset_len rgn_items[4];
256     int rgn_type;
257    
258     int count;
259    
260     FILE *f;
261     long pos;
262     char line[256];
263     int attr_pos;
264     enum attr_type attr_last;
265     char attrs[256];
266     char attr[256];
267     double lat,lng;
268     char lat_c,lng_c;
269     int eoc;
270     struct map_priv *m;
271     struct item item;
272     };
273    
274     static int map_id;
275    
276     static int
277     contains_coord(char *line)
278     {
279     return g_ascii_isdigit(line[0]);
280     }
281    
282     static int debug=1;
283    
284     static int
285     get_tag(char *line, char *name, int *pos, char *ret)
286     {
287     int len,quoted;
288     char *p,*e,*n;
289    
290     if (debug)
291     printf("get_tag %s from %s\n", name, line);
292     if (! name)
293     return 0;
294     len=strlen(name);
295     if (pos)
296     p=line+*pos;
297     else
298     p=line;
299     for(;;) {
300     while (*p == ' ') {
301     p++;
302     }
303     if (! *p)
304     return 0;
305     n=p;
306     e=index(p,'=');
307     if (! e)
308     return 0;
309     p=e+1;
310     quoted=0;
311     while (*p) {
312     if (*p == ' ' && !quoted)
313     break;
314     if (*p == '"')
315     quoted=1-quoted;
316     p++;
317     }
318     if (e-n == len && !strncmp(n, name, len)) {
319     e++;
320     len=p-e;
321     if (e[0] == '"') {
322     e++;
323     len-=2;
324     }
325     strncpy(ret, e, len);
326     ret[len]='\0';
327     if (pos)
328     *pos=p-line;
329     return 1;
330     }
331     }
332     return 0;
333     }
334    
335     static void
336     get_line(struct map_rect_priv *mr)
337     {
338     mr->pos=ftell(mr->f);
339     fgets(mr->line, 256, mr->f);
340     }
341    
342     static void
343     map_destroy_garmin_img(struct map_priv *m)
344     {
345     if (debug)
346     printf("map_destroy_garmin_img\n");
347     g_free(m);
348     }
349    
350     static char *
351     map_charset_garmin_img(struct map_priv *m)
352     {
353     return "iso8859-1";
354     }
355    
356     static enum projection
357     map_projection_garmin_img(struct map_priv *m)
358     {
359     return projection_garmin;
360     }
361    
362     struct label_data_offset {
363     struct offset_len offset_len;
364     char multiplier;
365     char data;
366     } __attribute ((packed));
367    
368     #if 0
369     static void
370     dump_label_data_offset(struct label_data_offset *lbl_dat)
371     {
372     dump_offset_len(&lbl_dat->offset_len);
373     printf("multiplier 0x%x(%d)\n", lbl_dat->multiplier, lbl_dat->multiplier);
374     printf("data 0x%x(%d)\n", lbl_dat->data, lbl_dat->data);
375     }
376     #endif
377    
378     struct label_data {
379     struct offset_len offset_len;
380     short size;
381     int zero;
382     } __attribute ((packed));
383    
384     static void
385     dump_label_data(struct label_data *lbl_dat)
386     {
387     dump_offset_len(&lbl_dat->offset_len);
388     printf("size 0x%x(%d)\n", lbl_dat->size, lbl_dat->size);
389     }
390    
391     struct tree_header {
392     struct file_header fil_hdr;
393     char boundary[12];
394     struct offset_len level;
395     struct offset_len subdivision;
396     struct label_data copyright;
397     struct offset_len tre7;
398     short unknown1;
399     char zero1;
400     struct label_data polyline;
401     struct label_data polygon;
402     struct label_data point;
403     int mapid;
404     };
405    
406     static void
407     dump_tree_header(struct tree_header *tre_hdr)
408     {
409     printf("tree_header:\n");
410     dump_file(&tre_hdr->fil_hdr);
411     printf("level: "); dump_offset_len(&tre_hdr->level);
412     printf("subdivision: "); dump_offset_len(&tre_hdr->subdivision);
413     printf("copyright: "); dump_label_data(&tre_hdr->copyright);
414     printf("polyline: "); dump_label_data(&tre_hdr->polyline);
415     printf("polygon: "); dump_label_data(&tre_hdr->polygon);
416     printf("point: "); dump_label_data(&tre_hdr->point);
417     printf("len: 0x%x(%d)\n", sizeof(*tre_hdr), sizeof(*tre_hdr));
418     }
419    
420     struct label_header {
421     struct file_header fil_hdr;
422     struct label_data_offset label;
423     struct label_data country;
424     struct label_data region;
425     struct label_data city;
426     struct label_data poi_index;
427     struct label_data_offset poi_properties;
428     short zero1;
429     char zero2;
430     struct label_data poi_types;
431     struct label_data zip;
432     struct label_data hway;
433     struct label_data exit;
434     struct label_data hway_data;
435     int unknown1;
436     short unknown2;
437     struct offset_len sort_descriptor;
438     struct label_data lbl13;
439     struct label_data lbl14;
440     } __attribute((packed));
441    
442     #if 0
443     static void
444     dump_label(struct label_header *lbl_hdr)
445     {
446     dump_file(&lbl_hdr->fil_hdr);
447     printf("label:\n");
448     dump_label_data_offset(&lbl_hdr->label);
449     printf("country:\n");
450     dump_label_data(&lbl_hdr->country);
451     printf("region:\n");
452     dump_label_data(&lbl_hdr->region);
453     printf("city:\n");
454     dump_label_data(&lbl_hdr->city);
455     printf("poi_index:\n");
456     dump_label_data(&lbl_hdr->poi_index);
457     printf("poi_properties:\n");
458     dump_label_data_offset(&lbl_hdr->poi_properties);
459     printf("poi_types:\n");
460     dump_label_data(&lbl_hdr->poi_types);
461     printf("zip:\n");
462     dump_label_data(&lbl_hdr->zip);
463     printf("hway:\n");
464     dump_label_data(&lbl_hdr->hway);
465     printf("exit:\n");
466     dump_label_data(&lbl_hdr->exit);
467     printf("hway_data:\n");
468     dump_label_data(&lbl_hdr->hway_data);
469     printf("lbl13:\n");
470     dump_label_data(&lbl_hdr->lbl13);
471     printf("lbl14:\n");
472     dump_label_data(&lbl_hdr->lbl14);
473     printf("len: 0x%x(%d)\n", sizeof(*lbl_hdr), sizeof(*lbl_hdr));
474     }
475     #endif
476    
477     struct triple {
478     unsigned char data[3];
479     } __attribute((packed));
480    
481     static unsigned int
482     triple_u(struct triple *t)
483     {
484     return t->data[0] | (t->data[1] << 8) | (t->data[2] << 16);
485     }
486    
487     static int
488     triple(struct triple *t)
489     {
490     int ret=t->data[0] | (t->data[1] << 8) | (t->data[2] << 16);
491     if (ret > 1<<23)
492     ret=ret-(1<<24);
493     return ret;
494     }
495    
496     static void
497     dump_triple_u(struct triple *t)
498     {
499     int val=triple_u(t);
500     printf("0x%x(%d)\n", val, val);
501     }
502    
503     struct tcoord {
504     struct triple lng,lat;
505     } __attribute((packed));
506    
507     static void
508     dump_tcoord(struct tcoord *t)
509     {
510     printf ("0x%x(%d),0x%x(%d)\n", triple_u(&t->lng), triple_u(&t->lng), triple_u(&t->lat), triple_u(&t->lat));
511     }
512    
513     struct level {
514     unsigned char zoom;
515     unsigned char bits_per_coord;
516     unsigned short subdivisions;
517     } __attribute((packed));
518    
519     static void
520     dump_level(struct level *lvl)
521     {
522     printf("level:\n");
523     printf("\tzoom 0x%x(%d)\n", lvl->zoom, lvl->zoom);
524     printf("\tbits_per_coord 0x%x(%d)\n", lvl->bits_per_coord, lvl->bits_per_coord);
525     printf("\tsubdivisions 0x%x(%d)\n", lvl->subdivisions, lvl->subdivisions);
526     }
527    
528     struct subdivision {
529     struct triple rgn_offset;
530     unsigned char types;
531     struct tcoord center;
532     unsigned short width;
533     unsigned short height;
534     unsigned short next;
535     } __attribute((packed));
536    
537     static void
538     dump_subdivision(struct subdivision *sub)
539     {
540     printf("subdivision:\n");
541     printf("\trgn_offset: "); dump_triple_u(&sub->rgn_offset);
542     printf("\ttypes: 0x%x(%d)\n", sub->types, sub->types);
543     printf("\tcenter: "); dump_tcoord(&sub->center);
544     printf("\tsize: 0x%x(%d)x0x%x(%d) %s\n",sub->width & 0x7fff, sub->width & 0x7fff, sub->height, sub->height, sub->width & 0x8000 ? "Terminating" : "");
545     printf("\tnext: 0x%x(%d)\n",sub->next, sub->next);
546    
547     printf("\tlen: 0x%x(%d)\n", sizeof(*sub), sizeof(*sub));
548     }
549    
550     struct rgn_point {
551     unsigned char info;
552     struct triple lbl_offset;
553     short lng_delta;
554     short lat_delta;
555     unsigned char subtype;
556     } __attribute((packed));
557    
558     static void
559     dump_point(struct rgn_point *pnt)
560     {
561     printf("point:\n");
562     printf("\tinfo 0x%x(%d)\n", pnt->info, pnt->info);
563     printf("\tlbl_offset 0x%x(%d)\n", triple_u(&pnt->lbl_offset), triple_u(&pnt->lbl_offset));
564     printf("\tlng_delta 0x%x(%d)\n", pnt->lng_delta, pnt->lng_delta);
565     printf("\tlat_delta 0x%x(%d)\n", pnt->lat_delta, pnt->lat_delta);
566     printf("\tsubtype 0x%x(%d)\n", pnt->subtype, pnt->subtype);
567     printf("\tlen: 0x%x(%d)\n", sizeof(*pnt), sizeof(*pnt));
568     }
569    
570     struct rgn_poly {
571     unsigned char info;
572     struct triple lbl_offset;
573     short lng_delta;
574     short lat_delta;
575     union {
576     struct {
577     unsigned char bitstream_len;
578     unsigned char bitstream_info;
579     } __attribute((packed)) p1;
580     struct {
581     unsigned short bitstream_len;
582     unsigned char bitstream_info;
583     } __attribute((packed)) p2;
584     } __attribute((packed)) u;
585     } __attribute((packed));
586    
587     static void
588     dump_poly(struct rgn_poly *ply)
589     {
590     printf("poly:\n");
591     printf("\tinfo 0x%x(%d)\n", ply->info, ply->info);
592     printf("\tlbl_offset 0x%x(%d)\n", triple_u(&ply->lbl_offset), triple_u(&ply->lbl_offset));
593     printf("\tlng_delta 0x%x(%d)\n", ply->lng_delta, ply->lng_delta);
594     printf("\tlat_delta 0x%x(%d)\n", ply->lat_delta, ply->lat_delta);
595     if (ply->info & 0x80) {
596     printf("\tbitstream_len 0x%x(%d)\n", ply->u.p2.bitstream_len, ply->u.p2.bitstream_len);
597     printf("\tbitstream_info 0x%x(%d)\n", ply->u.p2.bitstream_info, ply->u.p2.bitstream_info);
598     } else {
599     printf("\tbitstream_len 0x%x(%d)\n", ply->u.p1.bitstream_len, ply->u.p1.bitstream_len);
600     printf("\tbitstream_info 0x%x(%d)\n", ply->u.p1.bitstream_info, ply->u.p1.bitstream_info);
601     }
602     printf("\tlen: 0x%x(%d)\n", sizeof(*ply), sizeof(*ply));
603     }
604    
605     static void
606     dump_hex(void *ptr, int len)
607     {
608     unsigned char *c=ptr;
609     while (len--) {
610     printf("%02x ", *c++);
611     }
612     printf("\n");
613     }
614    
615     static void
616     dump_hex_r(void *ptr, int len, int rec)
617     {
618     unsigned char *c=ptr;
619     int l=rec;
620     while (len--) {
621     printf("%02x ", *c++);
622     if (! --l) {
623     printf("\n");
624     l=rec;
625     }
626     }
627     printf("\n");
628     }
629    
630     #if 0
631     static void
632     dump_label_offset(struct map_rect_priv *mr, int offset)
633     {
634     void *p;
635     p=file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128);
636     printf("%s\n", (char *)p);
637     }
638     #endif
639    
640    
641     #if 0
642     static void
643     dump_region_item(struct subdivision *sub, struct file *rgn, struct map_rect_priv *mr)
644     {
645     int offset,item_offset,i,j;
646     unsigned short count=0;
647     unsigned short *offsets[4];
648     unsigned short *file_offsets;
649     struct rgn_point *pnt;
650    
651     offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset;
652     file_offsets=file_read(rgn, offset, 90*sizeof(unsigned short));
653     printf("0x%x ", offset); dump_hex(file_offsets, 90);
654     for (i=0 ; i < 4 ; i++) {
655     printf("i=%d\n", i);
656     if (sub->types & (0x10 << i)) {
657     if (count) {
658     offsets[i]=&file_offsets[count-1];
659     } else
660     offsets[i]=&count;
661     count++;
662     } else
663     offsets[i]=NULL;
664    
665     }
666     count--;
667     count*=2;
668     for (i=0 ; i < 4 ; i++) {
669     printf("i=%d\n", i);
670     if (offsets[i]) {
671     printf("offset[%d]=0x%x(%d)\n", i, *offsets[i], *offsets[i]);
672     switch (i) {
673     case 0:
674     printf("point\n");
675     break;
676     case 1:
677     printf("indexed point\n");
678     break;
679     case 2:
680     printf("polyline\n");
681     break;
682     case 3:
683     printf("polygon\n");
684     break;
685     }
686     item_offset=offset+*offsets[i];
687     switch (i) {
688     case 0:
689     case 1:
690     for (j = 0 ; j < 10 ; j++) {
691     struct coord_geo g;
692     char buffer[1024];
693     double conv=180.0/(1UL<<23);
694     pnt=file_read(rgn, item_offset, sizeof(*pnt)*20);
695     // printf("0x%x ", item_offset); dump_hex(pnt, 32);
696     dump_point(pnt);
697     g.lng=(triple(&sub->center.lng)+(pnt->lng_delta << shift))*conv;
698     g.lat=(triple(&sub->center.lat)+(pnt->lat_delta << shift))*conv;
699     printf("%f %f\n", g.lng, g.lat);
700     coord_format(g.lat,g.lng,DEGREES_MINUTES_SECONDS,
701     buffer,sizeof(buffer));
702     printf("%s\n", buffer);
703     dump_label_offset(mr, triple_u(&pnt->lbl_offset));
704     if (pnt->info & 0x80)
705     item_offset+=sizeof(*pnt);
706     else
707     item_offset+=sizeof(*pnt)-1;
708     }
709     }
710     } else {
711     printf("offset[%d] doesn't exist\n", i);
712     }
713     }
714     file_free(file_offsets);
715     }
716    
717     #endif
718    
719     static void
720     dump_levels(struct map_rect_priv *mr)
721     {
722     int i,offset;
723     struct level *lvl;
724    
725     offset=mr->tre_hdr->level.offset;
726     for (i = 0 ; i < mr->tre_hdr->level.length/sizeof(*lvl) ; i++) {
727     lvl=file_read(&mr->tre, offset, sizeof(*lvl));
728     dump_level(lvl);
729     offset+=sizeof(*lvl);
730     }
731     }
732    
733     #if 0
734     static void
735     dump_tree(struct file *f, struct file *rgn, struct map_rect_priv *mr)
736     {
737     struct tree_header *tre_hdr;
738     struct subdivision *sub;
739     int i,offset;
740    
741     tre_hdr=file_read(f, 0, sizeof(*tre_hdr));
742     dump_tree_header(tre_hdr);
743     offset=tre_hdr->subdivision.offset;
744     sub=file_read(f, offset, sizeof(*sub));
745     dump_subdivision(sub);
746     offset+=sizeof(*sub);
747     for (i = 1 ; i < tre_hdr->subdivision.length/sizeof(*sub) ; i++) {
748     printf("i=%d\n", i);
749     sub=file_read(f, offset, sizeof(*sub));
750     dump_subdivision(sub);
751     dump_region_item(sub, rgn, mr);
752     if (sub->width & 0x8000)
753     break;
754     offset+=sizeof(*sub);
755     }
756     file_free(tre_hdr);
757     }
758     #endif
759    
760     #if 0
761     static void
762     dump_labels(struct file *f)
763     {
764     struct label_header *lbl_hdr;
765    
766     lbl_hdr=file_read(f, 0, sizeof(*lbl_hdr));
767     printf("**labels**\n");
768     dump_label(lbl_hdr);
769     file_free(lbl_hdr);
770     #if 0
771     labels=alloca(lbl_hdr.label_length);
772     file_read(f, lbl_hdr.label_offset, labels, lbl_hdr.label_length);
773     l=labels;
774     while (l < labels+lbl_hdr.label_length) {
775     printf("'%s'(%d)\n", l, strlen(l));
776     l+=strlen(l)+1;
777     }
778     #endif
779    
780     }
781     #endif
782    
783     static void
784     garmin_img_coord_rewind(void *priv_data)
785     {
786     }
787    
788     static void
789     parse_line(struct map_rect_priv *mr)
790     {
791     int pos=0;
792     sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos);
793     if (pos < strlen(mr->line)) {
794     strcpy(mr->attrs, mr->line+pos);
795     }
796     }
797    
798     static int
799     get_bits(struct map_rect_priv *mr, int bits)
800     {
801     unsigned long ret;
802     ret=L(*((unsigned long *)(mr->ply_data+mr->ply_bitpos/8)));
803     ret >>= (mr->ply_bitpos & 7);
804     ret &= (1 << bits)-1;
805     mr->ply_bitpos+=bits;
806     return ret;
807     }
808    
809     static int
810     garmin_img_coord_get(void *priv_data, struct coord *c, int count)
811     {
812     struct map_rect_priv *mr=priv_data;
813     struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos);
814     int ret=0;
815     int debug=0;
816     if (debug)
817     printf("garmin_img_coord_get %d\n",count);
818     if (debug)
819     dump_subdivision(sub);
820     while (count--) {
821     if (mr->rgn_type < 2) {
822     c->x=triple(&sub->center.lng)+(mr->pnt->lng_delta << shift);
823     c->y=triple(&sub->center.lat)+(mr->pnt->lat_delta << shift);
824     } else {
825     if (! mr->ply_bitpos) {
826     if (mr->ply->info & 0x80) {
827     mr->ply_bitcount=mr->ply->u.p2.bitstream_len*8;
828     mr->ply_lngbits=mr->ply->u.p2.bitstream_info & 0xf;
829     mr->ply_latbits=mr->ply->u.p2.bitstream_info >> 4;
830     } else {
831     mr->ply_bitcount=mr->ply->u.p1.bitstream_len*8;
832     mr->ply_lngbits=mr->ply->u.p1.bitstream_info & 0xf;
833     mr->ply_latbits=mr->ply->u.p1.bitstream_info >> 4;
834     }
835     if (mr->ply_lngbits <= 9)
836     mr->ply_lngbits+=2;
837     if (mr->ply_latbits <= 9)
838     mr->ply_latbits+=2;
839     if (! get_bits(mr,1)) {
840     mr->ply_lngbits+=1;
841     mr->ply_lngsign=0;
842     } else
843     if (get_bits(mr, 1))
844     mr->ply_lngsign=-1;
845     else
846     mr->ply_lngsign=1;
847     if (! get_bits(mr,1)) {
848     mr->ply_latbits+=1;
849     mr->ply_latsign=0;
850     } else
851     if (get_bits(mr, 1))
852     mr->ply_latsign=-1;
853     else
854     mr->ply_latsign=1;
855     mr->ply_lnglimit=1 << (mr->ply_lngbits-1);
856     mr->ply_latlimit=1 << (mr->ply_latbits-1);
857     mr->ply_lng=mr->ply->lng_delta;
858     mr->ply_lat=mr->ply->lat_delta;
859     if (debug)
860     printf("lngbits %d latbits %d bitcount %d\n", mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount);
861     c->x=0;
862     c->y=0;
863     } else {
864     if (mr->ply_bitpos + mr->ply_lngbits + mr->ply_latbits > mr->ply_bitcount) {
865     if (debug)
866     printf("out of bits %d + %d + %d >= %d\n", mr->ply_bitpos, mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount);
867     return ret;
868     }
869     c->x=0;
870     c->y=0;
871     int x,y;
872     for (;;) {
873     x=get_bits(mr,mr->ply_lngbits);
874     if (debug)
875     printf("x %d ", x);
876     if (mr->ply_lngsign || x != mr->ply_lnglimit)
877     break;
878     c->x += x-1;
879     }
880     if (mr->ply_lngsign) {
881     c->x=x*mr->ply_lngsign;
882     } else {
883     if (x >= mr->ply_lnglimit)
884     c->x = x - (mr->ply_lnglimit << 1) - c->x;
885     else
886     c->x +=x;
887     }
888     for (;;) {
889     y=get_bits(mr,mr->ply_latbits);
890     if (debug)
891     printf("y %d ", y);
892     if (mr->ply_latsign || y != mr->ply_latlimit)
893     break;
894     c->y += y-1;
895     }
896     if (mr->ply_latsign) {
897     c->y=y*mr->ply_latsign;
898     } else {
899     if (y >= mr->ply_latlimit)
900     c->y = y - (mr->ply_latlimit << 1) - c->y;
901     else
902     c->y +=y;
903     }
904     mr->ply_lng += c->x;
905     mr->ply_lat += c->y;
906     }
907     if (debug)
908     printf(": x %d y %d\n", c->x, c->y);
909    
910     c->x=triple(&sub->center.lng)+(mr->ply_lng << shift);
911     c->y=triple(&sub->center.lat)+(mr->ply_lat << shift);
912     }
913     #if 0
914     c->x-=0x6f160;
915     c->y-=0x181f59;
916     c->x+=0x168ca1;
917     c->y+=0x68d815;
918     #endif
919     c++;
920     ret++;
921     if (mr->rgn_type < 2)
922     return ret;
923     }
924     return ret;
925     }
926    
927     static char *
928     get_label_offset(struct map_rect_priv *mr, int offset)
929     {
930     g_assert(offset < mr->lbl_hdr->label.offset_len.length);
931     return file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128);
932     }
933    
934     static void
935     garmin_img_attr_rewind(void *priv_data)
936     {
937     }
938    
939     static int
940     garmin_img_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
941     {
942     struct map_rect_priv *mr=priv_data;
943     int debug=0;
944    
945     if (debug)
946     printf("garmin_img_attr_get\n");
947     if (attr_type == attr_label) {
948     if (debug)
949     printf("garmin_img_attr_get label\n");
950     attr->type=attr_type;
951     if (mr->rgn_type < 2) {
952     if (mr->label)
953     file_free(mr->label);
954     mr->label=get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff);
955     attr->u.str=mr->label;
956     } else {
957     attr->u.str="";
958     }
959     return 1;
960     }
961     return 0;
962     }
963    
964     static struct item_methods methods_garmin_img = {
965     garmin_img_coord_rewind,
966     garmin_img_coord_get,
967     garmin_img_attr_rewind,
968     garmin_img_attr_get,
969     };
970    
971     static int rgn_next_type(struct map_rect_priv *mr)
972     {
973     while (mr->rgn_type < 3) {
974     mr->rgn_type++;
975     if (mr->rgn_items[mr->rgn_type].offset && mr->rgn_items[mr->rgn_type].length != 0) {
976     mr->rgn_offset=mr->rgn_items[mr->rgn_type].offset;
977     mr->rgn_end=mr->rgn_offset+mr->rgn_items[mr->rgn_type].length;
978     return 0;
979     }
980     }
981     return 1;
982     }
983    
984     static int
985     sub_next(struct map_rect_priv *mr, int next)
986     {
987     int i,offset,first=-1,last=-1,count=-1;
988     int end;
989     unsigned short *offsets;
990     int debug=0;
991    
992     if (mr->subdiv_level_count <= 0)
993     return 1;
994     if (debug)
995     printf("%d left\n", mr->subdiv_level_count);
996     mr->subdiv_level_count--;
997    
998     #if 0
999     if (next && mr->subdiv[mr->subdiv_current].width & 0x8000)
1000     return 1;
1001     #endif
1002     if (debug)
1003     dump_hex_r(mr->subdiv+mr->subdiv_pos, 64, 14);
1004     mr->subdiv_pos+=next;
1005     if (debug)
1006     printf("subdiv_pos 0x%x\n", mr->subdiv_pos);
1007     if (mr->subdiv_pos > mr->tre_hdr->subdivision.length)
1008     return 1;
1009     struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos);
1010     offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset;
1011     if (debug) {
1012     printf("offset=0x%x\n", offset);
1013     dump_subdivision(sub);
1014     }
1015     offsets=file_read(&mr->rgn, offset, 3*sizeof(unsigned short));
1016    
1017     if (! next)
1018     next=subdiv_next;
1019     if (mr->subdiv_pos+next < mr->tre_hdr->subdivision.length)
1020     end=triple_u(&((struct subdivision *)(mr->subdiv+mr->subdiv_pos+next))->rgn_offset)+mr->rgn_hdr->offset_len.offset;
1021     else
1022     end=mr->rgn_hdr->offset_len.offset+mr->rgn_hdr->offset_len.length;
1023     if (debug) {
1024     dump_subdivision(sub);
1025     dump_hex(offsets, 6);
1026     }
1027     for (i=0 ; i < 4 ; i++) {
1028     if (debug)
1029     printf("i=%d ", i);
1030     if (sub->types & (0x10 << i)) {
1031     if (debug)
1032     printf("+ ");
1033     if (first == -1) {
1034     first=i;
1035     mr->rgn_items[i].offset=offset;
1036     if (debug)
1037     printf("\n");
1038     } else {
1039     mr->rgn_items[i].offset=offset+offsets[count];
1040     if (debug)
1041     printf("0x%x\n", offsets[count]);
1042     mr->rgn_items[last].length=mr->rgn_items[i].offset-mr->rgn_items[last].offset;
1043     }
1044     last=i;
1045     count++;
1046     } else {
1047     if (debug)
1048     printf("-\n");
1049     mr->rgn_items[i].offset=0;
1050     mr->rgn_items[i].length=0;
1051     }
1052    
1053     }
1054     if (first != -1) {
1055     mr->rgn_items[first].offset+=count*2;
1056     mr->rgn_items[first].length-=count*2;
1057     mr->rgn_items[last].length=end-mr->rgn_items[last].offset;
1058     }
1059     if (debug) {
1060     for (i=0 ; i < 4 ; i++) {
1061     printf("%d 0x%x 0x%x\n", i, mr->rgn_items[i].offset, mr->rgn_items[i].length);
1062     }
1063     }
1064     mr->rgn_type=-1;
1065     rgn_next_type(mr);
1066     if (debug)
1067     printf("*** offset 0x%x\n", mr->rgn_offset);
1068     file_free(offsets);
1069     return 0;
1070     }
1071    
1072     int item_count;
1073    
1074     static struct map_rect_priv *
1075     map_rect_new_garmin_img(struct map_priv *map, struct coord_rect *r, struct layer *layers, int limit)
1076     {
1077     struct map_rect_priv *mr;
1078     struct img_header img;
1079    
1080     if (debug)
1081     printf("map_rect_new_garmin_img\n");
1082     mr=g_new0(struct map_rect_priv, 1);
1083     mr->m=map;
1084     if (r)
1085     mr->r=*r;
1086     mr->limit=limit;
1087     mr->item.id_hi=0;
1088     mr->item.id_lo=0;
1089     mr->item.meth=&methods_garmin_img;
1090     mr->item.priv_data=mr;
1091     mr->f=fopen(map->filename, "r");
1092    
1093     fread(&img, sizeof(img), 1, mr->f);
1094     #if 0
1095     dump_img(&img);
1096     for (i = 0 ; i < (img.file_offset-sizeof(img))/sizeof(fat_blk) ; i++) {
1097     fread(&fat_blk, sizeof(fat_blk), 1, mr->f);
1098     if (!fat_blk.flag)
1099     break;
1100     dump_fat_block(&fat_blk);
1101     }
1102     #endif
1103     mr->rgn.offset=0xa*2048;
1104     mr->rgn.f=mr->f;
1105     mr->rgn_hdr=file_read(&mr->rgn, 0, sizeof(*mr->rgn_hdr));
1106    
1107     mr->tre.offset=0x62b*2048;
1108     mr->tre.f=mr->f;
1109     mr->tre_hdr=file_read(&mr->tre, 0, sizeof(*mr->tre_hdr));
1110    
1111     mr->lbl.offset=0x64a*2048;
1112     mr->lbl.f=mr->f;
1113     mr->lbl_hdr=file_read(&mr->lbl, 0, sizeof(*mr->lbl_hdr));
1114    
1115     mr->subdiv=file_read(&mr->tre, mr->tre_hdr->subdivision.offset, mr->tre_hdr->subdivision.length);
1116     #if 0
1117     dump_hex_r(mr->subdiv, mr->tre_hdr->subdivision.length, 16);
1118     #endif
1119     dump_tree_header(mr->tre_hdr);
1120    
1121     dump_levels(mr);
1122    
1123    
1124     printf("limit=%d\n", limit);
1125     if (limit < 3) {
1126     mr->subdiv_pos=0;
1127     mr->subdiv_level_count=1;
1128     shift=11;
1129     } else if (limit < 6) {
1130     mr->subdiv_pos=1*sizeof(struct subdivision);
1131     mr->subdiv_level_count=5;
1132     shift=9;
1133     } else if (limit < 8) {
1134     mr->subdiv_pos=6*sizeof(struct subdivision);
1135     mr->subdiv_level_count=9;
1136     shift=7;
1137     } else if (limit < 10) {
1138     mr->subdiv_pos=15*sizeof(struct subdivision);
1139     mr->subdiv_level_count=143;
1140     shift=5;
1141     } else {
1142     mr->subdiv_pos=158*sizeof(struct subdivision);
1143     mr->subdiv_level_count=4190;
1144     shift=2;
1145     subdiv_next=14;
1146     }
1147    
1148     #if 0
1149     mr->rgn_offset=triple_u(&mr->subdiv[mr->subdiv_current].rgn_offset)+mr->rgn_hdr->offset_len.offset+4;
1150     mr->rgn_type=1;
1151     mr->rgn_end=mr->rgn_offset+20*8;
1152     #endif
1153     mr->count=0;
1154     item_count=0;
1155    
1156     #if 0
1157     printf("*** offset 0x%x\n", 0x656c-mr->rgn.offset);
1158     printf("*** offset 0x%x\n", mr->rgn_offset);
1159     #endif
1160     #if 1
1161     sub_next(mr, 0);
1162     #endif
1163     #if 0
1164     {
1165     struct rgn_point *pnt;
1166     int i;
1167     int offset=0x65cc;
1168     for (i = 0 ; i < 26 ; i++) {
1169     pnt=file_read(&mr->rgn, 0x656c+8*i-mr->rgn.offset, sizeof(*pnt));
1170     // dump_hex(pnt, sizeof(*pnt));
1171     dump_point(pnt);
1172     dump_label_offset(mr, triple_u(&pnt->lbl_offset));
1173     }
1174     }
1175     exit(0);
1176     #endif
1177     #if 0
1178     dump_tree(&mr->tre,&mr->rgn,mr);
1179     #endif
1180    
1181     #if 0
1182     f.offset=0x64a*2048;
1183     f.f=mr->f;
1184     dump_labels(&f);
1185     #endif
1186     #if 0
1187     fseek(mr->f, img.file_offset, SEEK_SET);
1188     fread(&fil, sizeof(fil), 1, mr->f);
1189     dump_file(&fil);
1190     fread(&rgn, sizeof(rgn), 1, mr->f);
1191     dump_region(&rgn);
1192     fseek(mr->f, rgn.data_length, SEEK_CUR);
1193     fread(&fil, sizeof(fil), 1, mr->f);
1194     dump_file(&fil);
1195     #endif
1196     return mr;
1197     }
1198    
1199    
1200     static void
1201     map_rect_destroy_garmin_img(struct map_rect_priv *mr)
1202     {
1203     fclose(mr->f);
1204     g_free(mr);
1205     }
1206    
1207    
1208     static struct item *
1209     map_rect_get_item_garmin_img(struct map_rect_priv *mr)
1210     {
1211     char *p,type[256];
1212     int ptype;
1213     int debug=0;
1214    
1215     item_count++;
1216    
1217     if (debug)
1218     printf("map_rect_get_item_garmin_img\n");
1219     for (;;) {
1220     if (mr->rgn_offset < mr->rgn_end) {
1221     if (debug)
1222     printf("data available\n");
1223     if (mr->rgn_type >= 2) {
1224     int len;
1225     if (debug)
1226     printf("polyline %d\n", mr->count);
1227     if (mr->ply)
1228     file_free(mr->ply);
1229     mr->ply=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->ply)*3);
1230     if(triple_u(&mr->ply->lbl_offset) >= mr->lbl_hdr->label.offset_len.length) {
1231     printf("item_count %d\n", item_count);
1232     dump_poly(mr->ply);
1233     dump_hex(mr->ply, 32);
1234     printf("%d vs %d\n", triple_u(&mr->ply->lbl_offset), mr->lbl_hdr->label.offset_len.length);
1235     }
1236     g_assert(triple_u(&mr->ply->lbl_offset) < mr->lbl_hdr->label.offset_len.length);
1237     if (debug) {
1238     dump_hex(mr->ply, 16);
1239     dump_poly(mr->ply);
1240     }
1241     if (mr->ply_data)
1242     file_free(mr->ply_data);
1243     mr->rgn_offset+=10;
1244     if (mr->ply->info & 0x80) {
1245     mr->rgn_offset++;
1246     len=mr->ply->u.p2.bitstream_len;
1247     } else
1248     len=mr->ply->u.p1.bitstream_len;
1249    
1250     mr->ply_data=file_read(&mr->rgn, mr->rgn_offset, len);
1251     mr->rgn_offset += len;
1252     mr->ply_bitpos=0;
1253     // dump_hex(mr->ply_data, 32);
1254     if (mr->rgn_type == 3) {
1255     switch(mr->ply->info & 0x7f) {
1256     case 0x1: /* large urban area (>200k) */
1257     mr->item.type=type_town_poly;
1258     break;
1259     case 0xd: /* reservation */
1260     mr->item.type=type_park_poly;
1261     break;
1262     case 0xe: /* airport runway */
1263     mr->item.type=type_airport_poly;
1264     break;
1265     case 0x14: /* national park */
1266     mr->item.type=type_park_poly;
1267     break;
1268     case 0x32: /* sea */
1269     case 0x3d: /* large lake (77-250km2) */
1270     case 0x4c: /* intermittend water */
1271     mr->item.type=type_water_poly;
1272     break;
1273     case 0x4b: /* background */
1274     continue;
1275     default:
1276     printf("unknown polygon: 0x%x\n", mr->ply->info);
1277     mr->item.type=type_street_3_city;
1278     }
1279     } else {
1280     switch(mr->ply->info & 0x3f) {
1281     case 0x1: /* major highway */
1282     mr->item.type=type_highway_land;
1283     break;
1284     case 0x2: /* principal highway */
1285     mr->item.type=type_street_3_land;
1286     break;
1287     case 0x6: /* residental street */
1288     mr->item.type=type_street_2_land;
1289     break;
1290     case 0x16: /* walkway/trail */
1291     mr->item.type=type_street_1_land;
1292     break;
1293     case 0x1e: /* international boundary */
1294     mr->item.type=type_border_country;
1295     break;
1296     case 0x20: /* minor land contour 1/10 */
1297     mr->item.type=type_height_line_1;
1298     break;
1299     case 0x21: /* major land contour 1/2 */
1300     mr->item.type=type_height_line_2;
1301     break;
1302     default:
1303     printf("unknown polyline: 0x%x\n", mr->ply->info);
1304     mr->item.type=type_street_3_city;
1305     }
1306     }
1307     return &mr->item;
1308     }
1309     if (mr->pnt)
1310     file_free(mr->pnt);
1311     mr->pnt=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->pnt));
1312     mr->item.type=type_none;
1313     int subtype=mr->pnt->subtype;
1314     if (mr->pnt->lbl_offset.data[2] & 0x80)
1315     mr->rgn_offset+=9;
1316     else {
1317     mr->rgn_offset+=8;
1318     subtype=0;
1319     }
1320     switch(mr->pnt->info) {
1321     case 0x3: /* large city 2-5M */
1322     mr->item.type=type_town_label_2e6;
1323     break;
1324     case 0xa: /* small city/town 10-20k */
1325     mr->item.type=type_town_label_1e4;
1326     break;
1327     case 0xd: /* settlement 1-2K */
1328     mr->item.type=type_town_label_1e3;
1329     break;
1330     case 0x11: /* settlement less 100 */
1331     mr->item.type=type_town_label_5e1;
1332     break;
1333     case 0x1c:
1334     switch(subtype) {
1335     case 0x01:
1336     mr->item.type=type_poi_wreck;
1337     break;
1338     }
1339     break;
1340     case 0x20:
1341     mr->item.type=type_highway_exit;
1342     break;
1343     case 0x25:
1344     mr->item.type=type_poi_toll_booth;
1345     break;
1346     case 0x2b:
1347     switch(subtype) {
1348     case 0x01:
1349     mr->item.type=type_poi_hotel;
1350     break;
1351     case 0x03:
1352     mr->item.type=type_poi_camp_rv;
1353     break;
1354     }
1355     break;
1356     case 0x2c:
1357     switch(subtype) {
1358     case 0x00:
1359     mr->item.type=type_poi_attraction;
1360     break;
1361     case 0x02:
1362     mr->item.type=type_poi_museum_history;
1363     break;
1364     }
1365     break;
1366     case 0x2e:
1367     mr->item.type=type_poi_shopping;
1368     break;
1369     case 0x2f:
1370     switch(subtype) {
1371     case 0x01:
1372     mr->item.type=type_poi_fuel;
1373     break;
1374     case 0x07:
1375     mr->item.type=type_poi_car_dealer_parts;
1376     break;
1377     case 0x0b:
1378     mr->item.type=type_poi_car_parking;
1379     break;
1380     case 0x15:
1381     mr->item.type=type_poi_public_utilities;
1382     break;
1383     }
1384     break;
1385     case 0x30:
1386     switch(subtype) {
1387     case 0x02:
1388     mr->item.type=type_poi_hospital;
1389     break;
1390     }
1391     break;
1392     case 0x43:
1393     mr->item.type=type_poi_marina;
1394     break;
1395     case 0x46:
1396     mr->item.type=type_poi_bar;
1397     break;
1398     case 0x48:
1399     mr->item.type=type_poi_camping;
1400     break;
1401     case 0x49:
1402     mr->item.type=type_poi_park;
1403     break;
1404     case 0x4a:
1405     mr->item.type=type_poi_picnic;
1406     break;
1407     case 0x59: /* airport */
1408     mr->item.type=type_poi_airport;
1409     break;
1410     case 0x64:
1411     switch(subtype) {
1412     case 0x1:
1413     mr->item.type=type_poi_bridge;
1414     break;
1415     case 0x2:
1416     mr->item.type=type_poi_building;
1417     break;
1418     case 0x15:
1419     mr->item.type=type_town_ghost;
1420     break;
1421     }
1422     break;
1423     case 0x65:
1424     switch(subtype) {
1425     case 0x0:
1426     mr->item.type=type_poi_water_feature;
1427     break;
1428     case 0xc:
1429     mr->item.type=type_poi_island;
1430     break;
1431     case 0xd:
1432     mr->item.type=type_poi_lake;
1433     break;
1434     }
1435     break;
1436     case 0x66:
1437     switch(subtype) {
1438     case 0x0:
1439     mr->item.type=type_poi_land_feature;
1440     break;
1441     case 0x6:
1442     mr->item.type=type_poi_cape;
1443     break;
1444     case 0x14:
1445     mr->item.type=type_poi_rock;
1446     break;
1447     }
1448     break;
1449     }
1450     if (mr->item.type == type_none) {
1451     printf("unknown point: 0x%x 0x%x\n", mr->pnt->info, mr->pnt->subtype);
1452     dump_point(mr->pnt);
1453     printf("label: %s\n", get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff));
1454     mr->item.type=type_town_label;
1455     }
1456     return &mr->item;
1457     }
1458     if (debug)
1459     printf("out of data for type\n");
1460     if (rgn_next_type(mr)) {
1461     if (debug)
1462     printf("out of data for region\n");
1463     if (sub_next(mr, subdiv_next)) {
1464     if (debug)
1465     printf("out of data for subdivision\n");
1466     return NULL;
1467     }
1468     }
1469     }
1470     }
1471    
1472     static struct item *
1473     map_rect_get_item_byid_garmin_img(struct map_rect_priv *mr, int id_hi, int id_lo)
1474     {
1475     fseek(mr->f, id_lo, SEEK_SET);
1476     get_line(mr);
1477     mr->item.id_hi=id_hi;
1478     return map_rect_get_item_garmin_img(mr);
1479     }
1480    
1481     static struct map_methods map_methods_garmin_img = {
1482     projection_garmin,
1483     "iso8859-1",
1484     map_destroy_garmin_img,
1485     map_charset_garmin_img,
1486     map_projection_garmin_img,
1487     map_rect_new_garmin_img,
1488     map_rect_destroy_garmin_img,
1489     map_rect_get_item_garmin_img,
1490     map_rect_get_item_byid_garmin_img,
1491     };
1492    
1493     static struct map_priv *
1494     map_new_garmin_img(struct map_methods *meth, struct attr **attrs)
1495     {
1496     struct map_priv *m;
1497     struct attr *data=attr_search(attrs, NULL, attr_data);
1498     if (! data)
1499     return NULL;
1500    
1501     *meth=map_methods_garmin_img;
1502     m=g_new(struct map_priv, 1);
1503     m->id=++map_id;
1504     m->filename=g_strdup(data->u.str);
1505     return m;
1506     }
1507    
1508     void
1509     plugin_init(void)
1510     {
1511     plugin_register_map_type("garmin_img", map_new_garmin_img);
1512     }
1513    

   
Visit the ZANavi Wiki