Merge with modular_map
[navit-package] / src / data / mg / block.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "debug.h"
4 #include "mg.h"
5
6
7 int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem;
8
9 struct block_index_item {
10         unsigned long blocknum;
11         unsigned long blocks;
12 };
13
14 struct block_index {
15         unsigned long blocks;
16         unsigned long size;
17         unsigned long next;      
18         struct block_index_item list[0];
19 };
20
21 static struct block *
22 block_get(unsigned char **p)
23 {
24         struct block *ret=(struct block *)(*p);
25         *p += sizeof(*ret);
26         return ret;
27 }
28
29
30 static struct block *
31 block_get_byid(struct file *file, int id, unsigned char **p_ret)
32 {
33         struct block_index *blk_idx;
34         int blk_num,max;
35
36
37         blk_idx=(struct block_index *)(file->begin+0x1000);
38         max=(blk_idx->size-sizeof(struct block_index))/sizeof(struct block_index_item);
39         block_mem+=24;
40         while (id >= max) {
41                 blk_idx=(struct block_index *)(file->begin+blk_idx->next*512);
42                 id-=max;
43         }
44         blk_num=blk_idx->list[id].blocknum;
45
46         *p_ret=file->begin+blk_num*512;
47         return block_get(p_ret);
48 }
49
50 int
51 block_get_byindex(struct file *file, int idx, struct block_priv *blk)
52 {
53         dbg(1,"idx=%d\n", idx);
54         blk->b=block_get_byid(file, idx, &blk->p);
55         blk->block_start=(unsigned char *)(blk->b);
56         blk->p_start=blk->p;
57         blk->end=blk->block_start+blk->b->size;
58
59         return 1;
60 }
61
62 static void
63 block_setup_tags(struct map_rect_priv *mr)
64 {
65         int len;
66         unsigned char *p,*t;
67         char *str;
68
69         mr->b.binarytree=0;
70
71         p=mr->file->begin+0x0c;
72         while (*p) {
73                 str=get_string(&p);
74                 len=get_u32_unal(&p);
75                 t=p;
76                 /* printf("String '%s' len %d\n", str, len); */
77                 if (! strcmp(str,"FirstBatBlock")) {
78                         /* printf("%ld\n", get_u32_unal(&t)); */
79                 } else if (! strcmp(str,"MaxBlockSize")) {
80                         /* printf("%ld\n", get_u32_unal(&t)); */
81                 } else if (! strcmp(str,"FREE_BLOCK_LIST")) {
82                         /* printf("%ld\n", get_u32_unal(&t)); */
83                 } else if (! strcmp(str,"TotalRect")) {
84                         mr->b.b_rect.lu.x=get_u32_unal(&t);
85                         mr->b.b_rect.lu.y=get_u32_unal(&t);
86                         mr->b.b_rect.rl.x=get_u32_unal(&t);
87                         mr->b.b_rect.rl.y=get_u32_unal(&t);
88                         /* printf("0x%x,0x%x-0x%x,0x%x\n", mr->b.b_rect.lu.x, mr->b.b_rect.lu.y, mr->b.b_rect.rl.x, mr->b.b_rect.rl.y); */
89                 } else if (! strcmp(str,"Version")) {
90                         /* printf("0x%lx\n", get_u32_unal(&t)); */
91                 } else if (! strcmp(str,"Categories")) {
92                         /* printf("0x%x\n", get_u16(&t)); */
93                 } else if (! strcmp(str,"binaryTree")) {
94                         mr->b.binarytree=get_u32_unal(&t);
95                         /* printf("%d\n", mr->b.binarytree); */
96                 } else if (! strcmp(str,"CategorySets")) {
97                         /* printf("0x%x\n", get_u16(&t)); */
98                 } else if (! strcmp(str,"Kommentar")) {
99                         /* printf("%s\n", get_string(&t)); */
100                 }
101                 p+=len;
102         }
103 }
104
105 #if 0
106 static void
107 block_rect_print(struct coord_rect *r)
108 {
109         printf ("0x%x,0x%x-0x%x,0x%x (0x%x,0x%x)", r->lu.x, r->lu.y, r->rl.x, r->rl.y, r->lu.x/2+r->rl.x/2,r->lu.y/2+r->rl.y/2);
110 }
111 #endif
112
113 static void
114 block_rect_same(struct coord_rect *r1, struct coord_rect *r2)
115 {
116         g_assert(r1->lu.x==r2->lu.x);
117         g_assert(r1->lu.y==r2->lu.y);
118         g_assert(r1->rl.x==r2->rl.x);
119         g_assert(r1->rl.y==r2->rl.y);
120 }
121
122 int
123 block_init(struct map_rect_priv *mr)
124 {
125         mr->b.block_num=-1;
126         mr->b.bt.b=NULL;
127         mr->b.bt.next=0;
128         block_setup_tags(mr);
129         if (mr->b.binarytree) {
130                 mr->b.bt.next=mr->b.binarytree;
131                 mr->b.bt.p=NULL;
132                 mr->b.bt.block_count=0;
133         }
134         if (mr->cur_sel && !coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b_rect)) 
135                 return 0;
136         return block_next(mr);
137 }
138
139
140 int
141 block_next_lin(struct map_rect_priv *mr)
142 {
143         for (;;) {
144                 block_lin_count++;
145                 block_mem+=sizeof(struct block *);
146                 mr->b.block_num++;
147                 if (! mr->b.block_num) 
148                         mr->b.p=mr->file->begin+0x2000;
149                 else
150                         mr->b.p=mr->b.block_start+mr->b.b->blocks*512;
151                 if (mr->b.p >= mr->file->end)
152                         return 0;
153                 mr->b.block_start=mr->b.p;
154                 mr->b.b=block_get(&mr->b.p);
155                 mr->b.p_start=mr->b.p;
156                 mr->b.end=mr->b.block_start+mr->b.b->size;
157                 if (mr->b.b->count == -1)
158                         return 0;
159                 if (!mr->cur_sel || coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b->r)) {
160                         block_active_count++;
161                         block_active_mem+=mr->b.b->blocks*512-sizeof(struct block *);
162                         return 1;
163                 }
164         }
165 }
166
167 int
168 block_next(struct map_rect_priv *mr)
169 {
170         int blk_num,coord,r_h,r_w;
171         struct block_bt_priv *bt=&mr->b.bt;
172
173         if (!mr->b.binarytree || ! mr->cur_sel)
174                 return block_next_lin(mr);
175         for (;;) {
176                 if (! bt->p) {
177                         dbg(1,"block 0x%x\n", bt->next);
178                         if (bt->next == -1)
179                                 return 0;
180                         bt->b=block_get_byid(mr->file, bt->next, &bt->p);
181                         bt->end=(unsigned char *)mr->b.bt.b+mr->b.bt.b->size;
182                         bt->next=bt->b->next;
183                         bt->order=0;
184                         dbg(1,"size 0x%x next 0x%x\n", bt->b->size, bt->b->next);
185                         if (! mr->b.bt.block_count) {
186 #if 0
187                                 if (debug) {
188                                         printf("idx rect ");
189                                         block_rect_print(&mr->b.bt.b->r);
190                                 }
191 #endif
192                                 bt->r=bt->b->r;
193                                 bt->r_curr=bt->r;
194                                 coord=get_u32(&mr->b.bt.p);
195                         } else {
196                                 bt->p=(unsigned char *)bt->b+0xc;
197                         }
198                         bt->block_count++;
199                 }
200                 while (mr->b.bt.p < mr->b.bt.end) {
201                         block_idx_count++;
202                         blk_num=get_u32(&mr->b.bt.p);
203                         coord=get_u32(&mr->b.bt.p); 
204                         block_mem+=8;
205                         dbg(1,"%p vs %p coord 0x%x ", mr->b.bt.end, mr->b.bt.p, coord);
206                         dbg(1,"block 0x%x", blk_num);
207                 
208                         r_w=bt->r_curr.rl.x-bt->r_curr.lu.x;
209                         r_h=bt->r_curr.lu.y-bt->r_curr.rl.y;
210 #if 0
211                         if (debug) {
212                                 printf(" rect1 ");
213                                 block_rect_print(&bt->r_curr);
214                                 printf(" %dx%d", r_w, r_h);
215                         }
216 #endif
217                         mr->b.b=NULL;
218                         if (blk_num != -1) {
219                                 block_mem+=8;
220                                 if (coord_rect_overlap(&mr->cur_sel->rect, &bt->r_curr)) {
221                                         mr->b.b=block_get_byid(mr->file, blk_num, &mr->b.p);
222                                         mr->b.block_num=blk_num;
223                                         g_assert(mr->b.b != NULL);
224                                         mr->b.block_start=(unsigned char *)(mr->b.b);
225                                         mr->b.p_start=mr->b.p;
226                                         mr->b.end=mr->b.block_start+mr->b.b->size;
227                                         block_rect_same(&mr->b.b->r, &bt->r_curr);
228                                 }
229                         }
230                         if (coord != -1) {
231                                 bt->stack[bt->stackp]=bt->r_curr;
232                                 if (r_w > r_h) {
233                                         bt->r_curr.rl.x=coord;
234                                         bt->stack[bt->stackp].lu.x=coord+1;
235                                 } else {
236                                         bt->r_curr.lu.y=coord;
237                                         bt->stack[bt->stackp].rl.y=coord+1;
238                                 }
239                                 bt->stackp++;
240                                 g_assert(bt->stackp < BT_STACK_SIZE);
241                         } else {
242                                 if (bt->stackp) {
243                                         bt->stackp--;
244                                         bt->r_curr=bt->stack[bt->stackp];
245                                 } else {
246                                         bt->r_curr=bt->r;
247                                         bt->order++;
248                                         if (bt->order > 100)
249                                                 return 0;
250                                 }
251                         }
252                         if (mr->b.b) {
253                                 block_active_count++;
254                                 block_active_mem+=mr->b.b->blocks*512;
255                                 return 1;
256                         }
257                 }
258                 bt->p=NULL;
259         }       
260         return 0;
261 }