cee04683c11e2e2e55039b883fb315d7c4089383
[navit-package] / navit / map / mg / town.c
1 /**
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 <stdio.h>
21 #include <string.h>
22 #include "debug.h"
23 #include "mg.h"
24
25
26
27 static void
28 town_coord_rewind(void *priv_data)
29 {
30         struct town_priv *twn=priv_data;
31
32         twn->cidx=0;
33 }
34
35 static int
36 town_coord_get(void *priv_data, struct coord *c, int count)
37 {
38         struct town_priv *twn=priv_data;
39
40         if (twn->cidx || count <= 0)
41                 return 0;
42         twn->cidx=1;
43         *c=twn->c;
44         return 1;
45 }
46
47 static void
48 town_attr_rewind(void *priv_data)
49 {
50         struct town_priv *twn=priv_data;
51
52         twn->aidx=0;
53         twn->attr_next=attr_label;
54 }
55
56 static int
57 town_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
58 {
59         struct town_priv *twn=priv_data;
60         int len;
61
62         attr->type=attr_type;
63         switch (attr_type) {
64         case attr_any:
65                 while (twn->attr_next != attr_none) {
66                         if (town_attr_get(twn, twn->attr_next, attr))
67                                 return 1;
68                 }
69                 return 0;
70         case attr_label:
71                 attr->u.str=twn->district;
72                 twn->attr_next=attr_town_name;
73                 if (attr->u.str[0])
74                         return 1;
75                 attr->u.str=twn->name;
76                 return ((attr->u.str && attr->u.str[0]) ? 1:0);
77         case attr_town_name:
78                 attr->u.str=twn->name;
79                 twn->attr_next=attr_town_postal;
80                 return ((attr->u.str && attr->u.str[0]) ? 1:0);
81         case attr_town_postal:
82         case attr_postal:
83                 strncpy(twn->postal, twn->postal_code1, 32);
84                 attr->u.str=twn->postal;
85                 len=mg_country_postal_len(twn->country);
86                 if (!len)
87                         len=31;
88                 twn->postal[len]='\0';
89                 twn->attr_next=attr_district_name;
90                 return ((attr->u.str && attr->u.str[0]) ? 1:0);
91         case attr_district_name:
92                 attr->u.str=twn->district;
93                 twn->attr_next=attr_debug;
94                 return ((attr->u.str && attr->u.str[0]) ? 1:0);
95         case attr_town_streets_item:
96                 twn->town_attr_item.type=type_town_streets;
97                 twn->town_attr_item.id_hi=twn->country | (file_town_twn << 16) | 0x10000000;
98                 twn->town_attr_item.id_lo=twn->street_assoc;
99                 attr->u.item=&twn->town_attr_item;
100                 twn->attr_next=attr_debug;
101                 return 1;
102         case attr_debug:
103                 sprintf(twn->debug, "order %d\nsize %d\nstreet_assoc 0x%x", twn->order, twn->size, twn->street_assoc);
104                 attr->u.str=twn->debug;
105                 twn->attr_next=attr_none;
106                 return 1;
107         default:
108                 dbg_assert(1==0);
109                 return 0;
110         }
111         return 1;
112 }
113
114 static struct item_methods town_meth = {
115         town_coord_rewind,
116         town_coord_get,
117         town_attr_rewind,
118         town_attr_get,
119 };
120
121 static void
122 town_get_data(struct town_priv *twn, unsigned char **p)
123 {
124         twn->id=get_u32_unal(p);
125         twn->c.x=get_u32_unal(p);
126         twn->c.y=get_u32_unal(p);
127         twn->name=get_string(p);
128         twn->district=get_string(p);
129         twn->postal_code1=get_string(p);
130         twn->order=get_u8(p);                   /* 1-15 (19) */
131         twn->country=get_u16_unal(p);
132         twn->type=get_u8(p);
133         twn->unknown2=get_u32_unal(p);
134         twn->size=get_u8(p);
135         twn->street_assoc=get_u32_unal(p);
136         twn->unknown3=get_u8(p);
137         twn->postal_code2=get_string(p);
138         twn->unknown4=get_u32_unal(p);
139 #if 0
140                 printf("%s\t%s\t%s\t%d\t%d\t%d\n",twn->name,twn->district,twn->postal_code1,twn->order, twn->country, twn->type);
141 #endif
142 }
143                             /*0 1 2 3 4 5 6 7  8  9  10 11 12 13 14 15 16 17 18 */
144 static unsigned char limit[]={0,1,2,2,4,6,8,10,11,13,14,14,14,20,20,20,20,20,20};
145
146 static enum item_type town_item[]={type_town_label_5e1, type_town_label_1e2, type_town_label_2e2, type_town_label_5e2, type_town_label_1e3, type_town_label_1e3, type_town_label_2e3, type_town_label_5e3, type_town_label_1e4, type_town_label_2e4, type_town_label_5e4, type_town_label_1e5, type_town_label_1e5, type_town_label_2e5, type_town_label_5e5, type_town_label_1e6, type_town_label_2e6};
147 static enum item_type district_item[]={type_district_label_5e1, type_district_label_1e2, type_district_label_2e2, type_district_label_5e2, type_district_label_1e3, type_district_label_1e3, type_district_label_2e3, type_district_label_5e3, type_district_label_1e4, type_district_label_2e4, type_district_label_5e4, type_district_label_1e5, type_district_label_1e5, type_district_label_2e5, type_district_label_5e5, type_district_label_1e6, type_district_label_2e6};
148 int
149 town_get(struct map_rect_priv *mr, struct town_priv *twn, struct item *item)
150 {
151         int size;
152         for (;;) {
153                 if (mr->b.p >= mr->b.end)
154                         return 0;
155                 town_get_data(twn, &mr->b.p);
156                 twn->cidx=0;
157                 twn->aidx=0;
158                 twn->attr_next=attr_label;
159                 if (! mr->cur_sel || (twn->order <= limit[mr->cur_sel->order] && coord_rect_contains(&mr->cur_sel->u.c_rect,&twn->c))) {
160                         switch(twn->type) {
161                         case 1:
162                                 size=twn->size;
163                                 if (size >= sizeof(town_item)/sizeof(enum item_type)) 
164                                         size=sizeof(town_item)/sizeof(enum item_type)-1;
165                                 item->type=town_item[size];
166                                 break;
167                         case 3:
168                                 size=twn->size;
169                                 if (size == 6 && twn->order < 14)
170                                         size++;
171                                 if (size == 5 && twn->order < 14)
172                                         size+=2;
173                                 if (size >= sizeof(district_item)/sizeof(enum item_type)) 
174                                         size=sizeof(district_item)/sizeof(enum item_type)-1;
175                                 item->type=district_item[size];
176                                 break;
177                         case 4:
178                                 item->type=type_port_label;
179                                 break;
180                         case 9:
181                                 item->type=type_highway_exit_label;
182                                 break;
183                         default:
184                                 printf("unknown town type 0x%x '%s' '%s' 0x%x,0x%x\n", twn->type, twn->name, twn->district, twn->c.x, twn->c.y);
185                                 item->type=type_town_label;
186                         }
187                         if (map_selection_contains_item(mr->cur_sel, 0, item->type)) {
188                                 item->id_hi=twn->country | (mr->current_file << 16);
189                                 item->id_lo=twn->id;
190                                 item->priv_data=twn;
191                                 item->meth=&town_meth;
192                                 return 1;
193                         }
194                 }
195         }
196 }
197
198 int
199 town_get_byid(struct map_rect_priv *mr, struct town_priv *twn, int id_hi, int id_lo, struct item *item)
200 {
201         int country=id_hi & 0xffff;
202         int res;
203         if (!tree_search_hv(mr->m->dirname, "town", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res))
204                 return 0;
205         block_get_byindex(mr->m->file[mr->current_file], res >> 16, &mr->b);
206         mr->b.p=mr->b.block_start+(res & 0xffff);
207         return town_get(mr, twn, item);
208 }
209
210 static int
211 town_search_compare(unsigned char **p, struct map_rect_priv *mr)
212 {
213         int country, d;
214         char *name;
215
216         if (mr->search_type == attr_town_postal) {
217                 mr->search_blk_count=1;
218                 mr->search_blk_off=(struct block_offset *)(*p);
219                 *p+=4;
220                 name=get_string(p);
221                 d=0;
222         } else {
223                 country=get_u16_unal(p);
224                 dbg(1,"country 0x%x ", country);
225                 name=get_string(p);
226                 dbg(1,"name '%s' ",name);
227                 mr->search_blk_count=get_u32_unal(p);
228                 mr->search_blk_off=(struct block_offset *)(*p);
229                 dbg(1,"len %d ", mr->search_blk_count);
230                 (*p)+=mr->search_blk_count*4;
231                 d=mr->search_country-country;
232         }
233         if (!d) {
234                 if (mr->search_partial)
235                         d=strncasecmp(mr->search_str, name, strlen(mr->search_str));
236                 else
237                         d=strcasecmp(mr->search_str, name);
238         }
239         dbg(1,"%d \n",d);
240         return d;
241
242 }
243
244
245
246 struct item *
247 town_search_get_item(struct map_rect_priv *mr)
248 {
249         int dir=1,leaf;
250
251         if (! mr->search_blk_count) {
252                 dbg(1,"partial %d 0x%x '%s' ***\n", mr->search_partial, mr->search_country, mr->search_str);
253                 if (! mr->search_linear) {
254                         while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) {
255                                 dir=town_search_compare(&mr->search_p, mr);
256                                 if (! dir) {
257                                         mr->search_linear=1;
258                                         mr->search_p=NULL;
259                                         break;
260                                 }
261                         }
262                         if (! mr->search_linear) {
263                                 dbg(1,"not found\n");
264                                 return NULL;
265                         }
266                 }
267                 if (! tree_search_next_lin(&mr->ts, &mr->search_p)) {
268                         dbg(1,"linear not found\n");
269                         return NULL;
270                 }
271                 if (town_search_compare(&mr->search_p, mr)) {
272                         dbg(1,"no match\n");
273                         return NULL;
274                 }
275                 dbg(1,"found %d blocks\n",mr->search_blk_count);
276         }
277         if (! mr->search_blk_count)
278                 return NULL;
279         dbg(1,"block 0x%x offset 0x%x\n", block_offset_get_block(mr->search_blk_off), block_offset_get_offset(mr->search_blk_off));
280         block_get_byindex(mr->m->file[mr->current_file], block_offset_get_block(mr->search_blk_off), &mr->b);
281         mr->b.p=mr->b.block_start+block_offset_get_offset(mr->search_blk_off);
282         town_get(mr, &mr->town, &mr->item);
283         mr->search_blk_off++;
284         mr->search_blk_count--;
285         return &mr->item;
286 }