From ba8c7a19f05f6491eb7f191d44a5af8506f619cf Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Dec 2005 10:41:56 +0000 Subject: Reorganisation git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@8 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 209 ++ block.h | 30 + command.c | 143 ++ command.h | 1 + compass.c | 122 + compass.h | 2 + container.h | 69 + coord.c | 9 + coord.h | 21 + country.c | 94 + country.h | 12 + cursor.c | 196 ++ cursor.h | 5 + data.h | 39 + data_window.c | 104 + data_window.h | 8 + data_window_int.h | 7 + destination.c | 622 ++++++ destination.h | 11 + display.c | 266 +++ display.h | 24 + draw_info.h | 5 + fib-1.1/Makefile.in | 116 + fib-1.1/README | 26 + fib-1.1/configure | 1045 +++++++++ fib-1.1/configure.in | 17 + fib-1.1/fh_extractmin.3 | 97 + fib-1.1/fh_makeheap.3 | 17 + fib-1.1/fh_makekeyheap.3 | 84 + fib-1.1/fib.c | 696 ++++++ fib-1.1/fib.h | 64 + fib-1.1/fibpriv.h | 98 + fib-1.1/fibtest.c | 80 + fib-1.1/fibtest.out | 37 + fib-1.1/fibtest2.c | 69 + fib-1.1/fibtest2.out | 37 + fib-1.1/tt.c | 64 + fib-1.1/tt.out | 29 + fib-1.1/use.c | 126 ++ file.c | 124 ++ file.h | 18 + graphics.c | 401 ++++ graphics.h | 48 + .../gtk_drawing_area/graphics_gtk_drawing_area.c | 607 +++++ graphics/gtk_gl_ext/graphics_gtk_gl_ext.c | 333 +++ gtkext.h | 1 + gui/gtk/gtkeyboard.c | 2353 ++++++++++++++++++++ gui/gtk/gtkeyboard.h | 3 + gui/gtk/gui_gtk.h | 4 + gui/gtk/gui_gtk_menu.c | 430 ++++ gui/gtk/gui_gtk_statusbar.c | 115 + gui/gtk/gui_gtk_toolbar.c | 349 +++ gui/gtk/gui_gtk_window.c | 67 + locations.txt | 1 + log.c | 88 + log.h | 2 + main.c | 80 + main.h | 1 + map-common.c | 442 ++++ map-share.h | 2 + map-skelimpl.c | 286 +++ map-skels.c | 184 ++ map-srv.c | 262 +++ map-stubs.c | 135 ++ map.h | 341 +++ map.idl | 25 + map.ior | 1 + map_data.c | 112 + map_data.h | 30 + mapclient.c | 103 + menu.c | 35 + menu.h | 8 + navigation.c | 249 +++ navigation.h | 1 + param.c | 46 + param.h | 9 + phrase.c | 25 + phrase.h | 2 + plugin.c | 21 + plugin.h | 56 + plugins/poi_geodownload/libmdb/backend.c | 301 +++ plugins/poi_geodownload/libmdb/catalog.c | 138 ++ plugins/poi_geodownload/libmdb/data.c | 856 +++++++ plugins/poi_geodownload/libmdb/dump.c | 39 + plugins/poi_geodownload/libmdb/file.c | 376 ++++ plugins/poi_geodownload/libmdb/iconv.c | 63 + plugins/poi_geodownload/libmdb/include/mdbtools.h | 536 +++++ plugins/poi_geodownload/libmdb/index.c | 905 ++++++++ plugins/poi_geodownload/libmdb/kkd.c | 149 ++ plugins/poi_geodownload/libmdb/like.c | 78 + plugins/poi_geodownload/libmdb/map.c | 133 ++ plugins/poi_geodownload/libmdb/mem.c | 50 + plugins/poi_geodownload/libmdb/money.c | 139 ++ plugins/poi_geodownload/libmdb/options.c | 86 + plugins/poi_geodownload/libmdb/props.c | 127 ++ plugins/poi_geodownload/libmdb/sargs.c | 273 +++ plugins/poi_geodownload/libmdb/stats.c | 74 + plugins/poi_geodownload/libmdb/table.c | 368 +++ plugins/poi_geodownload/libmdb/worktable.c | 99 + plugins/poi_geodownload/libmdb/write.c | 878 ++++++++ plugins/poi_geodownload/poi.c | 474 ++++ point.h | 9 + poly.c | 109 + poly.h | 13 + popup.c | 306 +++ popup.h | 22 + profile.c | 18 + route.c | 1053 +++++++++ route.h | 48 + script/get_map | 5 + script/gps_emu | 19 + script/gps_emu2 | 40 + script/gps_emu3 | 12 + search.c | 442 ++++ search.h | 30 + speech.c | 61 + speech.h | 5 + statusbar.h | 10 + street.c | 455 ++++ street.h | 53 + street_data.h | 60 + street_name.c | 260 +++ street_name.h | 51 + toolbar.h | 3 + town.c | 260 +++ town.h | 27 + transform.c | 363 +++ transform.h | 37 + tree.c | 320 +++ tree.h | 13 + tst.c | 15 + util.c | 18 + util.h | 4 + vehicle.c | 216 ++ vehicle.h | 6 + 135 files changed, 22606 insertions(+) create mode 100644 block.c create mode 100644 block.h create mode 100644 command.c create mode 100644 command.h create mode 100644 compass.c create mode 100644 compass.h create mode 100644 container.h create mode 100644 coord.c create mode 100644 coord.h create mode 100644 country.c create mode 100644 country.h create mode 100644 cursor.c create mode 100644 cursor.h create mode 100644 data.h create mode 100644 data_window.c create mode 100644 data_window.h create mode 100644 data_window_int.h create mode 100644 destination.c create mode 100644 destination.h create mode 100644 display.c create mode 100644 display.h create mode 100644 draw_info.h create mode 100644 fib-1.1/Makefile.in create mode 100644 fib-1.1/README create mode 100755 fib-1.1/configure create mode 100644 fib-1.1/configure.in create mode 100644 fib-1.1/fh_extractmin.3 create mode 100644 fib-1.1/fh_makeheap.3 create mode 100644 fib-1.1/fh_makekeyheap.3 create mode 100644 fib-1.1/fib.c create mode 100644 fib-1.1/fib.h create mode 100644 fib-1.1/fibpriv.h create mode 100644 fib-1.1/fibtest.c create mode 100644 fib-1.1/fibtest.out create mode 100644 fib-1.1/fibtest2.c create mode 100644 fib-1.1/fibtest2.out create mode 100644 fib-1.1/tt.c create mode 100644 fib-1.1/tt.out create mode 100644 fib-1.1/use.c create mode 100644 file.c create mode 100644 file.h create mode 100644 graphics.c create mode 100644 graphics.h create mode 100644 graphics/gtk_drawing_area/graphics_gtk_drawing_area.c create mode 100644 graphics/gtk_gl_ext/graphics_gtk_gl_ext.c create mode 100644 gtkext.h create mode 100644 gui/gtk/gtkeyboard.c create mode 100644 gui/gtk/gtkeyboard.h create mode 100644 gui/gtk/gui_gtk.h create mode 100644 gui/gtk/gui_gtk_menu.c create mode 100644 gui/gtk/gui_gtk_statusbar.c create mode 100644 gui/gtk/gui_gtk_toolbar.c create mode 100644 gui/gtk/gui_gtk_window.c create mode 100644 locations.txt create mode 100644 log.c create mode 100644 log.h create mode 100644 main.c create mode 100644 main.h create mode 100644 map-common.c create mode 100644 map-share.h create mode 100644 map-skelimpl.c create mode 100644 map-skels.c create mode 100644 map-srv.c create mode 100644 map-stubs.c create mode 100644 map.h create mode 100644 map.idl create mode 100644 map.ior create mode 100644 map_data.c create mode 100644 map_data.h create mode 100644 mapclient.c create mode 100644 menu.c create mode 100644 menu.h create mode 100644 navigation.c create mode 100644 navigation.h create mode 100644 param.c create mode 100644 param.h create mode 100644 phrase.c create mode 100644 phrase.h create mode 100644 plugin.c create mode 100644 plugin.h create mode 100644 plugins/poi_geodownload/libmdb/backend.c create mode 100644 plugins/poi_geodownload/libmdb/catalog.c create mode 100644 plugins/poi_geodownload/libmdb/data.c create mode 100644 plugins/poi_geodownload/libmdb/dump.c create mode 100644 plugins/poi_geodownload/libmdb/file.c create mode 100644 plugins/poi_geodownload/libmdb/iconv.c create mode 100644 plugins/poi_geodownload/libmdb/include/mdbtools.h create mode 100644 plugins/poi_geodownload/libmdb/index.c create mode 100644 plugins/poi_geodownload/libmdb/kkd.c create mode 100644 plugins/poi_geodownload/libmdb/like.c create mode 100644 plugins/poi_geodownload/libmdb/map.c create mode 100644 plugins/poi_geodownload/libmdb/mem.c create mode 100644 plugins/poi_geodownload/libmdb/money.c create mode 100644 plugins/poi_geodownload/libmdb/options.c create mode 100644 plugins/poi_geodownload/libmdb/props.c create mode 100644 plugins/poi_geodownload/libmdb/sargs.c create mode 100644 plugins/poi_geodownload/libmdb/stats.c create mode 100644 plugins/poi_geodownload/libmdb/table.c create mode 100644 plugins/poi_geodownload/libmdb/worktable.c create mode 100644 plugins/poi_geodownload/libmdb/write.c create mode 100644 plugins/poi_geodownload/poi.c create mode 100644 point.h create mode 100644 poly.c create mode 100644 poly.h create mode 100644 popup.c create mode 100644 popup.h create mode 100644 profile.c create mode 100644 route.c create mode 100644 route.h create mode 100755 script/get_map create mode 100755 script/gps_emu create mode 100755 script/gps_emu2 create mode 100755 script/gps_emu3 create mode 100644 search.c create mode 100644 search.h create mode 100644 speech.c create mode 100644 speech.h create mode 100644 statusbar.h create mode 100644 street.c create mode 100644 street.h create mode 100644 street_data.h create mode 100644 street_name.c create mode 100644 street_name.h create mode 100644 toolbar.h create mode 100644 town.c create mode 100644 town.h create mode 100644 transform.c create mode 100644 transform.h create mode 100644 tree.c create mode 100644 tree.h create mode 100644 tst.c create mode 100644 util.c create mode 100644 util.h create mode 100644 vehicle.c create mode 100644 vehicle.h diff --git a/block.c b/block.c new file mode 100644 index 00000000..c48ea3ff --- /dev/null +++ b/block.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include "file.h" +#include "block.h" +#include "data.h" + + +struct file_private { + int binarytree; +}; + +struct block_index_item { + unsigned long blocknum; + unsigned long blocks; +}; + +struct block_index { + unsigned long blocks; + unsigned long size; + unsigned long next; + struct block_index_item list[0]; +}; + + +struct block * +block_get(unsigned char **p) +{ + struct block *ret=(struct block *)(*p); + *p += sizeof(*ret); + return ret; +} + +struct block * +block_get_byindex(struct file *file, int idx, unsigned char **p_ret) +{ + struct block_index *blk_idx; + int blk_num,max; + + blk_idx=(struct block_index *)(file->begin+0x1000); + max=(blk_idx->size-sizeof(struct block_index))/sizeof(struct block_index_item); + while (idx >= max) { + blk_idx=(struct block_index *)(file->begin+blk_idx->next*512); + idx-=max; + } + blk_num=blk_idx->list[idx].blocknum; + + *p_ret=file->begin+blk_num*512; + return block_get(p_ret); +} + +int +block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, int ign, struct block_info *blk_inf, struct transformation *t, + void *data, void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) +{ + struct coord ca[2],cb[2]; + struct block *blk; + int blk_num,val,dx,dy; + int ret=0; + + ca[0].x=c[0].x; + ca[0].y=c[0].y; + ca[1].x=c[1].x; + ca[1].y=c[1].y; + cb[0].x=c[0].x; + cb[0].y=c[0].y; + cb[1].x=c[1].x; + cb[1].y=c[1].y; + + if (*p >= (unsigned char *)(*block)+(*block)->size) { + *block=block_get_byindex(blk_inf->file, (*block)->next, p); + *p-=20; + } + blk_num=get_long(p); + val=get_long(p); + + if (blk_num != -1) + ret++; + + if (blk_num != -1 && (t == NULL || is_visible(t, c))) { + unsigned char *t,*end; + blk=block_get_byindex(blk_inf->file, blk_num, &t); + if (c[0].x != blk->c[0].x || c[0].y != blk->c[0].y || c[1].x != blk->c[1].x || c[1].y != blk->c[1].y) { + printf("ERROR3\n"); + printf("!= 0x%lx,0x%lx-0x%lx,0x%lx\n", blk->c[0].x,blk->c[0].y,blk->c[1].x,blk->c[1].y); + } + end=(unsigned char *)blk; + end+=blk->size; + blk_inf->block=blk; + blk_inf->block_number=blk_num; + (*func)(blk_inf, t, end, data); + } + + if (val != -1) { + dx=c[1].x-c[0].x; + dy=c[0].y-c[1].y; + if (dy > dx) { + ca[0].y=val; + cb[1].y=val+1; + } else { + ca[1].x=val; + cb[0].x=val+1; + } + ret+=block_binarytree_walk(block, p, ca, ign, blk_inf, t, data, func); + ret+=block_binarytree_walk(block, p, cb, ign, blk_inf, t, data, func); + } + return ret; +} + +void +block_file_private_setup(struct file *file) +{ + int len; + unsigned char *p,*str,*t; + struct file_private *file_priv; + + file_priv=malloc(sizeof(*file_priv)); + file->private=file_priv; + memset(file_priv, 0, sizeof(*file_priv)); + + p=file->begin+0x0c; + while (*p) { + str=get_string(&p); + len=get_long(&p); + t=p; + if (! strcmp(str,"binaryTree")) { + file_priv->binarytree=get_long(&t); + } + p+=len; + } +} + +void +block_foreach_visible_linear(struct block_info *blk_inf, struct transformation *t, void *data, + void(*func)(struct block_info *blk_inf, unsigned char *, unsigned char *, void *)) +{ + unsigned char *p,*start,*end; + struct block *blk; + + blk_inf->block_number=0; + p=blk_inf->file->begin+0x2000; + while (p < blk_inf->file->end) { + blk_inf->block_number++; + start=p; + end=p; + blk=block_get(&p); + end+=blk->size; + if (blk->count == -1) + break; + if (t == NULL || is_visible(t, blk->c)) { + blk_inf->block=blk; + (*func)(blk_inf, p, end, data); + } + p=start+blk->blocks*512; + } +} + +void +block_foreach_visible(struct block_info *blk_inf, struct transformation *t, int limit, void *data, + void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) +{ + struct file_private *file_priv=blk_inf->file->private; + + if (! file_priv) { + block_file_private_setup(blk_inf->file); + file_priv=blk_inf->file->private; + } + if (! file_priv->binarytree) { + block_foreach_visible_linear(blk_inf, t, data, func); + } else { + unsigned char *p,*p2; + int dummy1,dummy2,xy,i,count; + struct block *block=block_get_byindex(blk_inf->file, file_priv->binarytree, &p); + p2=p; + dummy1=get_long(&p2); + if (block->count != -1 || dummy1 != -1) { + printf("ERROR2 0x%x\n", block->count); + } + xy=1; + p=p2; + for (i = 0 ; i < limit ; i++) { + p2=p; + dummy1=get_long(&p2); + dummy2=get_long(&p2); + assert((dummy1 == -1 && dummy2 == -1) || i < 32) ; + count=block_binarytree_walk(&block, &p, block->c, 0, blk_inf, t, data, func); + } + } +} + +int +block_get_param(struct block_info *blk_inf, struct param_list *param, int count) +{ + int i=count; + param_add_hex("Number", blk_inf->block_number, ¶m, &count); + param_add_hex("Addr", (unsigned char *)blk_inf->block-blk_inf->file->begin, ¶m, &count); + param_add_hex("Blocks", blk_inf->block->blocks, ¶m, &count); + param_add_hex("Size", blk_inf->block->size, ¶m, &count); + param_add_hex("Next", blk_inf->block->next, ¶m, &count); + param_add_hex_sig("L", blk_inf->block->c[0].x, ¶m, &count); + param_add_hex_sig("T", blk_inf->block->c[0].y, ¶m, &count); + param_add_hex_sig("R", blk_inf->block->c[1].x, ¶m, &count); + param_add_hex_sig("B", blk_inf->block->c[1].y, ¶m, &count); + param_add_hex("W", blk_inf->block->c[1].x-blk_inf->block->c[0].x, ¶m, &count); + param_add_hex("H", blk_inf->block->c[0].y-blk_inf->block->c[1].y, ¶m, &count); + param_add_hex("Count", blk_inf->block->count, ¶m, &count); + return i-count; +} diff --git a/block.h b/block.h new file mode 100644 index 00000000..a65fe935 --- /dev/null +++ b/block.h @@ -0,0 +1,30 @@ +#include "coord.h" +#include "transform.h" + +struct block { + unsigned long blocks; + unsigned long size; + unsigned long next; + struct coord c[2]; + int count; +}; + +struct block_info { + struct map_data *mdata; + struct file *file; + struct block *block; + int block_number; +}; + +struct segment { + struct block_info blk_inf; + void *data[4]; +}; + +struct param_list; + +struct block * block_get(unsigned char **p); +void block_foreach_visible(struct block_info *blk_inf, struct transformation *t, int limit, void *data, + void(*func)(struct block_info *blk_inf, unsigned char *, unsigned char *, void *)); +int block_get_param(struct block_info *blk_inf, struct param_list *param, int count); +struct block *block_get_byindex(struct file *file, int idx, unsigned char **p_ret); diff --git a/command.c b/command.c new file mode 100644 index 00000000..88d26a36 --- /dev/null +++ b/command.c @@ -0,0 +1,143 @@ +#include +#include +#include "coord.h" +#include "town.h" +#include "street.h" + +/* Phonetisch + "KLEIN " -> CL + (x)(x)->x + EI:AY + E:- + F:V + G:C + H:- + I:Y + J:Y + K:C + T:D + W:V +*/ + +struct tree_hdr { + unsigned int addr; + unsigned int size; + unsigned int low; +}; + +struct tree_leaf { + unsigned int low; + unsigned int data; + unsigned char text[0]; +}; + +int +compare(char *s1, char *s2) +{ + char s1_exp, s2_exp; + for (;;) { + s1_exp=*s1++; + s2_exp=*s2++; + if (! s1_exp && ! s2_exp) + return 0; + if (s1_exp == 'A' && *s1 == 'E') { s1_exp='Ä'; s1++; } + if (s1_exp == 'O' && *s1 == 'E') { s1_exp='Ö'; s1++; } + if (s1_exp == 'U' && *s1 == 'E') { s1_exp='Ü'; s1++; } + if (s2_exp == 'A' && *s2 == 'E') { s2_exp='Ä'; s2++; } + if (s2_exp == 'O' && *s2 == 'E') { s2_exp='Ö'; s2++; } + if (s2_exp == 'U' && *s2 == 'E') { s2_exp='Ü'; s2++; } + if (s1_exp != s2_exp) + return s1_exp-s2_exp; + } +#if 0 + for (;;) { + while (*s1 && *s1 == *s2) { + s1++; + s2++; + } + if (! *s1 && ! *s2) + return 0; + if (! *s1) + return -1; + if (! *s2) + return 1; + if (*s1 < *s2 && *s2 < 0x80) + return -1; + if (*s1 > *s2 && *s1 < 0x80) + return 1; + s1_exp=*s1; + s2_exp=*s2; + if (s1_exp >= 0x80) + s1_exp=' '; + if (s2_exp >= 0x80) + s2_exp=' '; +#if 0 + if (*s1 == (unsigned char)'Ä') s1_exp='A'; + if (*s1 == (unsigned char)'Ö') s1_exp='O'; + if (*s1 == (unsigned char)'Ü') s1_exp='U'; + if (*s1 == (unsigned char)'ä') s1_exp='a'; + if (*s1 == (unsigned char)'ö') s1_exp='o'; + if (*s1 == (unsigned char)'ü') s1_exp='u'; + if (*s1 == (unsigned char)'ß') s1_exp='s'; + if (*s2 == (unsigned char)'Ä') s2_exp='A'; + if (*s2 == (unsigned char)'Ö') s2_exp='O'; + if (*s2 == (unsigned char)'Ü') s2_exp='U'; + if (*s2 == (unsigned char)'ä') s2_exp='a'; + if (*s2 == (unsigned char)'ö') s2_exp='o'; + if (*s2 == (unsigned char)'ü') s2_exp='u'; + if (*s2 == (unsigned char)'ß') s2_exp='s'; +#endif + if (s1_exp < s2_exp) + return -1; + if (s1_exp > s2_exp) + return 1; + printf("Problem %c vs %c\n", *s1, *s2); + exit(1); + } +#endif +} +void +command_goto(struct container *co, const char *arg) +{ +#if 0 + struct container *co=map->container; + struct town_list *list,*curr,*best=NULL; + int order=256; + int argc=0; + unsigned long x,y,scale; + char args[strlen(arg)+1]; + char *argv[strlen(arg)+1]; + char *tok; + + + strcpy(args, arg); + tok=strtok(args, " "); + while (tok) { + argv[argc++]=tok; + tok=strtok(NULL," "); + } + + list=NULL; + town_search_by_name(&list, co->map_data, argv[0], 0, 10000); + town_get_by_index(co->map_data, 0x311d54cb); + curr=list; + while (curr) { + if (curr->town->order < order) { + order=curr->town->order; + best=curr; + } + curr=curr->next; + } + if (best) { + printf("'%s' '%s' '%s' '%s'\n", best->town->name, best->town->district, best->town->postal_code1, best->town->postal_code2); +#if 0 + street_search_by_name(class->map_data, best->town->country, best->town->street_assoc, 0, argv[1]); +#endif + map_get_view(map, &x, &y, &scale); + x=best->town->c->x; + y=best->town->c->y; + map_set_view(map, x, y, scale); + } + town_list_free(list); +#endif +} diff --git a/command.h b/command.h new file mode 100644 index 00000000..5082fa04 --- /dev/null +++ b/command.h @@ -0,0 +1 @@ +void command_goto(struct container *co, const char *arg); diff --git a/compass.c b/compass.c new file mode 100644 index 00000000..cbfc9c68 --- /dev/null +++ b/compass.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include "point.h" +#include "coord.h" +#include "graphics.h" +#include "transform.h" +#include "route.h" +#include "vehicle.h" +#include "container.h" + +struct compass { + struct graphics *gr; + struct graphics_gc *bg; + struct graphics_gc *white; + struct graphics_gc *green; + struct graphics_font *font; +}; + +static void +transform_rotate(struct point *center, int angle, struct point *p, int count) +{ + int i,x,y; + double dx,dy; + for (i = 0 ; i < count ; i++) + { + dx=sin(M_PI*angle/180.0); + dy=cos(M_PI*angle/180.0); + x=dy*p->x-dx*p->y; + y=dx*p->x+dy*p->y; + + p->x=center->x+x; + p->y=center->y+y; + p++; + } +} + +static void +handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r, int dir) +{ + struct point ph[3]; + int l=r*0.4; + + ph[0].x=0; + ph[0].y=r; + ph[1].x=0; + ph[1].y=-r; + transform_rotate(p, dir, ph, 2); + gr->draw_lines(gr, gc, ph, 2); + ph[0].x=-l; + ph[0].y=-r+l; + ph[1].x=0; + ph[1].y=-r; + ph[2].x=l; + ph[2].y=-r+l; + transform_rotate(p, dir, ph, 3); + gr->draw_lines(gr, gc, ph, 3); +} + +void +compass_draw(struct compass *comp, struct container *co) +{ + struct point p; + struct coord *pos, *dest; + double *vehicle_dir,dir,distance; + int dx,dy; + char buffer[16]; + + vehicle_dir=vehicle_dir_get(co->vehicle); + comp->gr->draw_mode(comp->gr, draw_mode_begin); + p.x=0; + p.y=0; + comp->gr->draw_rectangle(comp->gr, comp->bg, &p, 60, 80); + p.x=30; + p.y=30; + comp->gr->draw_circle(comp->gr, comp->white, &p, 50); + handle(comp->gr, comp->white, &p, 20, -*vehicle_dir); + dest=route_get_destination(co->route); + if (dest) { + pos=vehicle_pos_get(co->vehicle); + dx=dest->x-pos->x; + dy=dest->y-pos->y; + dir=atan2(dx,dy)*180.0/M_PI; + printf("dx %d dy %d dir=%f vehicle_dir=%f\n", dx, dy, dir, *vehicle_dir); + dir-=*vehicle_dir; + handle(comp->gr, comp->green, &p, 20, dir); + p.x=8; + p.y=72; + distance=transform_distance(pos, dest)/1000.0; + if (distance >= 100) + sprintf(buffer,"%.0f km", distance); + else if (distance >= 10) + sprintf(buffer,"%.1f km", distance); + else + sprintf(buffer,"%.2f km", distance); + + comp->gr->draw_text(comp->gr, comp->green, NULL, comp->font, buffer, &p, 0x10000, 0); + } + comp->gr->draw_mode(comp->gr, draw_mode_end); +} + +struct compass * +compass_new(struct container *co) +{ + struct compass *this=g_new0(struct compass, 1); + struct point p; + p.x=10; + p.y=10; + this->gr=co->gra->overlay_new(co->gra, &p, 60, 80); + this->bg=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->bg, 0, 0, 0); + this->white=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->white, 0xffff, 0xffff, 0xffff); + this->gr->gc_set_linewidth(this->white, 2); + this->green=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->green, 0x0, 0xffff, 0x0); + this->gr->gc_set_linewidth(this->green, 2); + + this->font=this->gr->font_new(this->gr, 200); + compass_draw(this, co); + return this; +} diff --git a/compass.h b/compass.h new file mode 100644 index 00000000..3bc8ad7b --- /dev/null +++ b/compass.h @@ -0,0 +1,2 @@ +struct compass * compass_new(struct container *co); +void compass_draw(struct compass *comp, struct container *co); diff --git a/container.h b/container.h new file mode 100644 index 00000000..33433e4a --- /dev/null +++ b/container.h @@ -0,0 +1,69 @@ +enum display_index { + display_sea=0, + display_wood, + display_other, + display_other1, + display_other2, + display_other3, + display_water, + display_rail, + display_street, + display_street1, + display_street2, + display_street3, + display_street_no_pass, + display_street_route, + display_street_route_static, + display_town, + display_town1, + display_town2, + display_town3, + display_town4, + display_town5, + display_town6, + display_town7, + display_town8, + display_town9, + display_town10, + display_town11, + display_town12, + display_town13, + display_town14, + display_town15, + display_bti, + display_poi, + display_end +}; + +enum data_window_type { + data_window_type_block=0, + data_window_type_town, + data_window_type_poly, + data_window_type_street, + data_window_type_point, + data_window_type_end +}; + +struct map_flags { + int orient_north; + int track; +}; + +struct container { + struct window *win; + struct transformation *trans; + struct graphics *gra; + struct compass *compass; + struct display_list *disp[display_end]; + struct map_data *map_data; + struct menu *menu; + struct toolbar *toolbar; + struct statusbar *statusbar; + struct route *route; + struct cursor *cursor; + struct speech *speech; + struct vehicle *vehicle; + struct data_window *data_window[data_window_type_end]; + struct map_flags *flags; + struct _GtkMap *map; +}; diff --git a/coord.c b/coord.c new file mode 100644 index 00000000..8e792db8 --- /dev/null +++ b/coord.c @@ -0,0 +1,9 @@ +#include "coord.h" + +struct coord * +coord_get(unsigned char **p) +{ + struct coord *ret=(struct coord *)(*p); + *p += sizeof(*ret); + return ret; +} diff --git a/coord.h b/coord.h new file mode 100644 index 00000000..885c7919 --- /dev/null +++ b/coord.h @@ -0,0 +1,21 @@ +#ifndef COORD_H +#define COORD_H + +struct coord { + long x; + long y; +}; + +struct coord_d { + double x; + double y; +}; + +struct coord_geo { + double lng; + double lat; +}; + +struct coord * coord_get(unsigned char **p); + +#endif diff --git a/country.c b/country.c new file mode 100644 index 00000000..4f3a5d00 --- /dev/null +++ b/country.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include "country.h" + +struct country country[]= { + {16 ,"RUS", "RU", "RUS", "Rußland"}, + {20 ,"ET", "EG", "EGY", "Ägypten"}, + {30 ,"GR", "GR", "GRC", "Griechenland"}, + {31 ,"NL", "NL", "NLD", "Niederlande"}, + {32 ,"B", "BE", "BEL", "Belgien"}, + {33 ,"F", "FR", "FRA", "Frankreich"}, + {34 ,"E", "ES", "ESP", "Spanien"}, + {36 ,"H", "HU", "HUN", "Ungarn"}, + {39 ,"I", "IT", "ITA", "Italien"}, + {40 ,"RO", "RO", "ROM", "Rumänien"}, + {41 ,"CH", "CH", "CHE", "Schweiz"}, + {43 ,"A", "AT", "AUT", "Österreich"}, + {44 ,"GB", "GB", "GBR", "Grossbritannien"}, + {45 ,"DK", "DK", "DNK", "Dänemark"}, + {47 ,"N", "NO", "NOR", "Norwegen"}, + {49 ,"D", "DE", "DEU", "Deutschland"}, + {51 ,"P", "PT", "PRT", "Portugal"}, + {52 ,"L", "LU", "LUX", "Luxemburg"}, + {71 ,"LAR", "LY", "LYB", "Libyen"}, + {76 ,"MA", "MA", "MAR", "Marokko"}, + {78 ,"TN", "TN", "TUN", "Tunesien"}, +}; + +struct country * +country_get_by_id(int id) +{ + int i; + for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { + if (id == country[i].id) { + return &country[i]; + } + } + return NULL; +} + +static int +compare(const char *name1, const char *name2, int len, int partial) +{ + if (partial) + return strncasecmp(name1, name2, len); + else + return strcasecmp(name1, name2); +} + +static int +search(int offset, const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +{ + char *col; + int i,ret,len=strlen(name); + int debug=0; + + for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { + col=G_STRUCT_MEMBER(char *,country+i,offset); + if (debug) + printf("comparing '%s'\n", col); + if (!compare(col, name, len, partial)) { + ret=(*func)(&country[i], data); + if (ret) + return 1; + } + col+=sizeof(struct country); + } + return 0; +} + +int +country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +{ + return search(G_STRUCT_OFFSET(struct country, name), name, partial, func, data); +} + +int +country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +{ + return search(G_STRUCT_OFFSET(struct country, car), name, partial, func, data); +} + +int +country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +{ + return search(G_STRUCT_OFFSET(struct country, iso2), name, partial, func, data); +} + +int +country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +{ + return search(G_STRUCT_OFFSET(struct country, iso3), name, partial, func, data); +} diff --git a/country.h b/country.h new file mode 100644 index 00000000..616a6c26 --- /dev/null +++ b/country.h @@ -0,0 +1,12 @@ +struct country { + int id; + char *car; + char *iso2; + char *iso3; + char *name; +}; +struct country * country_get_by_id(int id); +int country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); +int country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); +int country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); +int country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); diff --git a/cursor.c b/cursor.c new file mode 100644 index 00000000..1f1d99e8 --- /dev/null +++ b/cursor.c @@ -0,0 +1,196 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "coord.h" +#include "transform.h" +#include "graphics.h" +#include "statusbar.h" +#include "menu.h" +#include "vehicle.h" +#include "container.h" + + +#include "route.h" + +struct cursor { + struct container *co; + struct graphics_gc *cursor_gc; + struct point cursor_pnt; +}; + +struct coord * +cursor_pos_get(void *t) +{ + struct cursor *this=t; + return vehicle_pos_get(this->co->vehicle); +} + +static void +cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir) +{ + int x=this->cursor_pnt.x; + int y=this->cursor_pnt.y; + int r=12,lw=2; + double dx,dy; + double fac1,fac2; + int dir_i=*dir-this->co->trans->angle; + struct point cpnt[3]; + struct graphics *gra=this->co->gra; + + if (pnt && x == pnt->x && y == pnt->y) + return; + cpnt[0]=this->cursor_pnt; + cpnt[0].x-=r+lw; + cpnt[0].y-=r+lw; + gra->draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2); + if (pnt) { + gra->draw_mode(gra, draw_mode_cursor); + this->cursor_pnt=*pnt; + x=pnt->x; + y=pnt->y; + cpnt[0].x=x; + cpnt[0].y=y; + gra->draw_circle(gra, this->cursor_gc, &cpnt[0], r*2); + if (*speed > 2.5) { + dx=sin(M_PI*dir_i/180); + dy=-cos(M_PI*dir_i/180); + + fac1=0.7*r; + fac2=0.4*r; + cpnt[0].x=x-dx*fac1+dy*fac2; + cpnt[0].y=y-dy*fac1-dx*fac2; + cpnt[1].x=x+dx*r; + cpnt[1].y=y+dy*r; + cpnt[2].x=x-dx*fac1-dy*fac2; + cpnt[2].y=y-dy*fac1+dx*fac2; + gra->draw_lines(gra, this->cursor_gc, cpnt, 3); + } else { + cpnt[1]=cpnt[0]; + gra->draw_lines(gra, this->cursor_gc, cpnt, 2); + } + gra->draw_mode(gra, draw_mode_end); + } +} + +static void +cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new) +{ + struct coord c_new; + struct transformation tr; + struct point pnt; + unsigned long scale; + long x,y; + int dir_i; + struct container *co=this->co; + + if (dir) + dir_i=*dir; + else + dir_i=0; + + pnt.x=co->trans->width-x_new; + pnt.y=co->trans->height-y_new; + graphics_get_view(co, &x, &y, &scale); + tr=*this->co->trans; + transform_setup(&tr, c->x, c->y, scale, dir_i); + transform_reverse(&tr, &pnt, &c_new); + printf("%lx %lx vs %lx %lx\n", c->x, c->y, c_new.x, c_new.y); + x=c_new.x; + y=c_new.y; + transform_set_angle(co->trans,dir_i); + graphics_set_view(co, &x, &y, &scale); +} + +static void +cursor_map_reposition(struct cursor *this, struct coord *c, double *dir) +{ + unsigned long scale; + long x,y; + + if (this->co->flags->orient_north) { + graphics_set_view(this->co, &c->x, &c->y, NULL); + } else { + cursor_map_reposition_screen(this, c, dir, this->co->trans->width/2, this->co->trans->height*0.8); + } +} + +static int +cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir, struct point *pnt) +{ + struct point pnt_new; + struct transformation *t=this->co->trans; + + pnt_new.x=-1; + if (pnt->x < 0.1*t->width) { + pnt_new.x=0.8*t->width; + pnt_new.y=t->height/2; + } + if (pnt->x > 0.9*t->width) { + pnt_new.x=0.2*t->width; + pnt_new.y=t->height/2; + } + if (pnt->y < (this->co->flags->orient_north ? 0.1 : 0.5)*t->height) { + pnt_new.x=t->width/2; + pnt_new.y=0.8*t->height; + } + if (pnt->y > 0.9*t->height) { + pnt_new.x=t->width/2; + pnt_new.y=0.2*t->height; + } + if (pnt_new.x != -1) { + if (this->co->flags->orient_north) { + cursor_map_reposition_screen(this, c, NULL, pnt_new.x, pnt_new.y); + } else { + cursor_map_reposition(this, c, dir); + } + return 1; + } + return 0; +} + +void +cursor_update(struct cursor *this) +{ + struct point pnt; + struct coord *pos; + struct vehicle *v=this->co->vehicle; + double *dir; + + if (v) { + pos=vehicle_pos_get(v); + dir=vehicle_dir_get(v); + route_set_position(this->co->route, cursor_pos_get(this->co->cursor)); + if (!transform(this->co->trans, pos, &pnt)) { + cursor_map_reposition(this, pos, dir); + transform(this->co->trans, pos, &pnt); + } + if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height) { + cursor_map_reposition(this, pos, dir); + transform(this->co->trans, pos, &pnt); + } + if (cursor_map_reposition_boundary(this, pos, dir, &pnt)) + transform(this->co->trans, pos, &pnt); + cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v)); + } +extern void compass_draw(); + compass_draw(this->co->compass, this->co); +} + +extern void *vehicle; + +struct cursor * +cursor_new(struct container *co) +{ + struct cursor *this=g_new(struct cursor,1); + this->co=co; + this->cursor_gc=co->gra->gc_new(co->gra); + co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff); + co->gra->gc_set_linewidth(this->cursor_gc, 2); + vehicle_callback(cursor_update, this); + return this; +} diff --git a/cursor.h b/cursor.h new file mode 100644 index 00000000..46114875 --- /dev/null +++ b/cursor.h @@ -0,0 +1,5 @@ +struct cursor; +struct container; + +struct coord * cursor_pos_get(struct cursor *this); +struct cursor *cursor_new(struct container *co); diff --git a/data.h b/data.h new file mode 100644 index 00000000..1f054333 --- /dev/null +++ b/data.h @@ -0,0 +1,39 @@ +static inline unsigned char +get_char(unsigned char **p) +{ + return *((*p)++); +} + +static inline unsigned short +get_short(unsigned char **p) { + unsigned long ret; + ret=*((unsigned short *)*p); + *p+=sizeof(unsigned short); + return ret; +} + +static inline unsigned long +get_triple(unsigned char **p) { + unsigned long ret; + ret=get_short(p); + ret|=*((*p)++) << 16; + return ret; +} + + +static inline unsigned long +get_long(unsigned char **p) { + unsigned long ret; + ret=*((unsigned int *)*p); + *p+=sizeof(unsigned int); + return ret; +} + +static inline char * +get_string(unsigned char **p) +{ + char *ret=*p; + while (**p) (*p)++; + (*p)++; + return ret; +} diff --git a/data_window.c b/data_window.c new file mode 100644 index 00000000..dfcddcc2 --- /dev/null +++ b/data_window.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include "param.h" +#include "data_window.h" +#include "data_window_int.h" + +struct data_window * +data_window(char *name, struct window *parent, void(*callback)(struct data_window *, char **cols)) +{ + struct data_window *win; + + win=malloc(sizeof(*win)); + win->window=gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(win->window), 320, 200); + gtk_window_set_title(GTK_WINDOW(win->window), name); + + win->scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win->scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_container_add(GTK_CONTAINER(win->window), win->scrolled_window); + + win->clist=NULL; + win->callback=callback; + if (parent) + gtk_window_set_transient_for(GTK_WINDOW((GtkWidget *)(win->window)), GTK_WINDOW(parent)); + gtk_widget_show_all(win->window); + return win; +} + +void +data_window_begin(struct data_window *win) +{ + if (win && win->clist) { + gtk_clist_clear(GTK_CLIST(win->clist)); + gtk_clist_freeze(GTK_CLIST(win->clist)); + } +} + +static void +click_column(GtkCList *clist, int column) +{ + if (column != clist->sort_column) { + gtk_clist_set_sort_type(clist, GTK_SORT_ASCENDING); + gtk_clist_set_sort_column(clist, column); + } else { + if (clist->sort_type == GTK_SORT_ASCENDING) + gtk_clist_set_sort_type(clist, GTK_SORT_DESCENDING); + else + gtk_clist_set_sort_type(clist, GTK_SORT_ASCENDING); + } + gtk_clist_sort(clist); +} + +static void +select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct data_window *win) +{ + int i; + if (win->callback) { + char *cols[20]; + for (i=0;i<20;i++) { + gtk_clist_get_text(clist, row, i, &cols[i]); + } + win->callback(win, cols); + } +} + +void +data_window_add(struct data_window *win, struct param_list *param, int count) +{ + int i; + char *column[count+1]; + char *utf8; + if (! win->clist) { + for (i = 0 ; i < count ; i++) { + column[i]=param[i].name; + } + win->clist=gtk_clist_new_with_titles(count, column); + gtk_clist_clear(GTK_CLIST(win->clist)); + gtk_container_add(GTK_CONTAINER(win->scrolled_window), win->clist); + gtk_clist_freeze(GTK_CLIST(win->clist)); + gtk_signal_connect(GTK_OBJECT(win->clist), "click-column", GTK_SIGNAL_FUNC(click_column), NULL); + gtk_signal_connect(GTK_OBJECT(win->clist), "select-row", GTK_SIGNAL_FUNC(select_row), win); + gtk_widget_show_all(win->window); + } + for (i = 0 ; i < count ; i++) { + utf8=g_locale_to_utf8(param[i].value,-1,NULL,NULL,NULL); + column[i]=utf8; + } + column[i]=NULL; + gtk_clist_append(GTK_CLIST(win->clist), column); + for (i = 0 ; i < count ; i++) { + g_free(column[i]); + } +} + +void +data_window_end(struct data_window *win) +{ + if (win && win->clist) { + gtk_clist_thaw(GTK_CLIST(win->clist)); + gtk_clist_columns_autosize (GTK_CLIST(win->clist)); + } +} diff --git a/data_window.h b/data_window.h new file mode 100644 index 00000000..86a412bb --- /dev/null +++ b/data_window.h @@ -0,0 +1,8 @@ +struct data_window; +struct param_list; +struct window; + +struct data_window *data_window(char *name, struct window *parent, void(*callback)(struct data_window *, char **cols)); +void data_window_add(struct data_window *win, struct param_list *param, int count); +void data_window_begin(struct data_window *win); +void data_window_end(struct data_window *win); diff --git a/data_window_int.h b/data_window_int.h new file mode 100644 index 00000000..c7922c2d --- /dev/null +++ b/data_window_int.h @@ -0,0 +1,7 @@ + +struct data_window { + GtkWidget *window; + GtkWidget *scrolled_window; + GtkWidget *clist; + void(*callback)(struct data_window *, char **cols); +}; diff --git a/destination.c b/destination.c new file mode 100644 index 00000000..9cced769 --- /dev/null +++ b/destination.c @@ -0,0 +1,622 @@ +#include +#include "coord.h" +#include "transform.h" +#include "block.h" +#include "data_window.h" +#include "country.h" +#include "town.h" +#include "street.h" +#include "street_name.h" +#include "gui/gtk/gtkeyboard.h" +#include "cursor.h" +#include "route.h" +#include "statusbar.h" +#include "unistd.h" +#include "destination.h" +#include "coord.h" +#include "container.h" + +extern gint track_focus(gpointer data); + + + +GtkWidget *entry_country, *entry_postal, *entry_city, *entry_district; +GtkWidget *entry_street, *entry_number; +GtkWidget *listbox; +int row_count=8; + +int selected; + +struct search_param { + struct map_data *map_data; + const char *country; + GHashTable *country_hash; + const char *town; + GHashTable *town_hash; + GHashTable *district_hash; + const char *street; + GHashTable *street_hash; + const char *number; + int number_low, number_high; + GtkWidget *clist; + int count; +} search_param2; + +struct destination { + struct town *town; + struct street_name *street_name; + struct coord *c; +}; + +struct country_list *country_list; + +static void +select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct data_window *win) +{ + selected=row; + printf("Selected %d\n", row); +} + +int +destination_set(struct container *co, enum destination_type type, char *text, struct coord *pos) +{ + route_set_position(co->route, cursor_pos_get(co->cursor)); + route_set_destination(co->route, pos); + graphics_redraw(co); + if (co->statusbar && co->statusbar->statusbar_route_update) + co->statusbar->statusbar_route_update(co->statusbar, co->route); + return 0; +} + +int +get_position(struct search_param *search, struct coord *c) +{ + struct destination *dest; + + if (selected == -1) + selected=0; + dest=gtk_clist_get_row_data (GTK_CLIST(search->clist), selected); + + printf("row %d dest %p dest:0x%lx,0x%lx\n", selected, dest, dest->c->x, dest->c->y); + *c=*dest->c; + return 0; +} + +void button_map(GtkWidget *widget, struct container *co) +{ + unsigned long scale; + struct coord c; + + if (!get_position(&search_param2, &c)) { + graphics_set_view(co, &c.x, &c.y, NULL); + } +} + +void button_destination(GtkWidget *widget, struct container *co) +{ + struct coord c; + + if (!get_position(&search_param2, &c)) { + route_set_position(co->route, cursor_pos_get(co->cursor)); + route_set_destination(co->route, &c); + graphics_redraw(co); + } +} + +struct dest_town { + int country; + int assoc; + char *name; + char postal_code[16]; + struct town town; +}; + +guint +destination_town_hash(gconstpointer key) +{ + const struct dest_town *hash=key; + gconstpointer hashkey=(gconstpointer)(hash->country^hash->assoc); + return g_direct_hash(hashkey); +} + +gboolean +destination_town_equal(gconstpointer a, gconstpointer b) +{ + const struct dest_town *t_a=a; + const struct dest_town *t_b=b; + if (t_a->assoc == t_b->assoc && t_a->country == t_b->country) { + if (t_a->name && t_b->name && strcmp(t_a->name, t_b->name)) + return FALSE; + return TRUE; + } + return FALSE; +} + +GHashTable * +destination_town_new(void) +{ + return g_hash_table_new_full(destination_town_hash, destination_town_equal, NULL, g_free); +} + +void +destination_town_set(const struct dest_town *town, char **rows, int full) +{ + char country[32]; + struct country *cou; + if ((cou=country_get_by_id(town->country))) { + rows[1]=cou->car; + } else { + sprintf(country,"(%d)", town->country); + rows[1]=country; + } + if (full) { + rows[4]=(char *)(town->town.postal_code2); + rows[5]=g_convert(town->town.name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + if (town->town.district[0]) + rows[6]=g_convert(town->town.district,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + else + rows[6]=NULL; + } else { + rows[4]=(char *)(town->postal_code); + rows[5]=g_convert(town->name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + } +} + +void +destination_town_show(gpointer key, gpointer value, gpointer user_data) +{ + struct dest_town *town=value; + struct search_param *search=(struct search_param *)user_data; + char *rows[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + int row; + + if (search->count > 0) { + struct destination *dest=g_new(struct destination, 1); + dest->town=&town->town; + dest->street_name=NULL; + dest->c=town->town.c; + destination_town_set(town, rows, 0); + row=gtk_clist_append(GTK_CLIST(search->clist), rows); + printf("town row %d %p dest:0x%lx,0x%lx\n", row, dest, dest->c->x, dest->c->y); + gtk_clist_set_row_data(GTK_CLIST(search->clist), row, dest); + search->count--; + } +} + +GHashTable * +destination_country_new(void) +{ + return g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + +int +destination_country_add(struct country *cou, void *data) +{ + struct search_param *search=data; + struct country *cou2; + + void *first; + first=g_hash_table_lookup(search->country_hash, (void *)(cou->id)); + if (! first) { + cou2=g_new(struct country, 1); + *cou2=*cou; + g_hash_table_insert(search->country_hash, (void *)(cou->id), cou2); + } + return 0; +} + +void +destination_country_show(gpointer key, gpointer value, gpointer user_data) +{ + struct country *cou=value; + struct search_param *search=(struct search_param *)user_data; + char *rows[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + if (search->count > 0) { + rows[0]=cou->name; + rows[1]=cou->car; + rows[2]=cou->iso2; + rows[3]=cou->iso3; + gtk_clist_append(GTK_CLIST(search->clist), rows); + search->count--; + } +} + +int +destination_town_add(struct town *town, void *data) +{ + struct search_param *search=data; + struct dest_town *first; + + struct dest_town cmp; + char *zip1, *zip2; + + if (town->id == 0x1d546b7e) { + printf("found\n"); + } + cmp.country=town->country; + cmp.assoc=town->street_assoc; + cmp.name=town->name; + first=g_hash_table_lookup(search->town_hash, &cmp); + if (! first) { + first=g_new(struct dest_town, 1); + first->country=cmp.country; + first->assoc=cmp.assoc; + strcpy(first->postal_code, town->postal_code2); + first->name=town->name; + first->town=*town; + g_hash_table_insert(search->town_hash, first, first); + } else { + zip1=town->postal_code2; + zip2=first->postal_code; + while (*zip1 && *zip2) { + if (*zip1 != *zip2) { + while (*zip2) { + *zip2++='.'; + } + break; + } + zip1++; + zip2++; + } + } + cmp.name=NULL; + cmp.assoc=town->id; + first=g_hash_table_lookup(search->district_hash, &cmp); + if (! first) { + first=g_new(struct dest_town, 1); + first->country=cmp.country; + first->assoc=cmp.assoc; + first->name=NULL; + first->town=*town; + g_hash_table_insert(search->district_hash, first, first); + } + return 0; +} + +void +destination_town_search(gpointer key, gpointer value, gpointer user_data) +{ + struct country *cou=value; + struct search_param *search=(struct search_param *)user_data; + town_search_by_name(search->map_data, cou->id, search->town, 1, destination_town_add, search); + +} + +GHashTable * +destination_street_new(void) +{ + return g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + + +int +destination_street_add(struct street_name *name, void *data) +{ + struct search_param *search=data; + struct street_name *name2; + + name2=g_new(struct street_name, 1); + *name2=*name; + g_hash_table_insert(search->street_hash, name2, name2); + return 0; +} + +static int +number_partial(int search, int ref, int ext) +{ + int max=1; + + printf("number_partial(%d,%d,%d)", search, ref, ext); + if (ref >= 10) + max=10; + if (ref >= 100) + max=100; + if (ref >= 1000) + max=1000; + while (search < max) { + search*=10; + search+=ext; + } + printf("max=%d result=%d\n", max, search); + return search; +} + +static int +check_number(int low, int high, int s_low, int s_high) +{ + printf("check_number(%d,%d,%d,%d)\n", low, high, s_low, s_high); + if (low <= s_high && high >= s_low) + return 1; + if (s_low == s_high) { + if (low <= number_partial(s_high, high, 9) && high >= number_partial(s_low, low, 0)) + return 1; + } + printf("return 0\n"); + return 0; +} + +void +destination_street_show_common(gpointer key, gpointer value, gpointer user_data, int number) +{ + struct street_name *name=value; + struct search_param *search=(struct search_param *)user_data; + char *utf8; + struct dest_town cmp; + struct dest_town *town; + int row; + char buffer[32]; + char *rows[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + struct street_name_info info; + struct street_name_number_info num_info; + + name->tmp_len=name->aux_len; + name->tmp_data=name->aux_data; + while (street_name_get_info(&info, name) && search->count > 0) { + struct destination *dest; + cmp.country=info.country; + cmp.assoc=info.dist; + cmp.name=NULL; + town=g_hash_table_lookup(search->district_hash, &cmp); + printf("town=%p\n", town); + if (town) { + destination_town_set(town, rows, 1); + utf8=g_convert(name->name2,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + rows[4]=utf8; + if (number) { + info.tmp_len=info.aux_len; + info.tmp_data=info.aux_data; + while (street_name_get_number_info(&num_info, &info) && search->count > 0) { + dest=g_new(struct destination, 1); + dest->town=&town->town; + dest->street_name=name; + dest->c=num_info.c; + if (check_number(num_info.first, num_info.last, search->number_low, search->number_high)) { + if (num_info.first == num_info.last) + sprintf(buffer,"%d",num_info.first); + else + sprintf(buffer,"%d-%d",num_info.first,num_info.last); + rows[8]=buffer; + printf("'%s','%s','%s','%s','%s','%s'\n", rows[0],rows[1],rows[2],rows[3],rows[4],rows[5]); + row=gtk_clist_append(GTK_CLIST(listbox), rows); + gtk_clist_set_row_data(GTK_CLIST(listbox), row, dest); + search->count--; + } + } + } else { + row=gtk_clist_append(GTK_CLIST(listbox), rows); + dest=g_new(struct destination, 1); + dest->town=&town->town; + dest->street_name=name; + dest->c=info.c; + gtk_clist_set_row_data(GTK_CLIST(listbox), row, dest); + search->count--; + } + g_free(utf8); + } else { + printf("Town for '%s' not found\n", name->name2); + } + } +} + +void +destination_street_show(gpointer key, gpointer value, gpointer user_data) +{ + destination_street_show_common(key, value, user_data, 0); +} + +void +destination_street_show_number(gpointer key, gpointer value, gpointer user_data) +{ + destination_street_show_common(key, value, user_data, 1); +} + +void +destination_street_search(gpointer key, gpointer value, gpointer user_data) +{ + const struct dest_town *town=value; + struct search_param *search=(struct search_param *)user_data; + street_name_search(search->map_data, town->country, town->assoc, search->street, 1, destination_street_add, search); +} + + + +void changed(GtkWidget *widget, struct search_param *search) +{ + const char *str; + char *empty[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + char *dash; + + gtk_clist_freeze(GTK_CLIST(listbox)); + gtk_clist_clear(GTK_CLIST(listbox)); + + selected=-1; + + search->count=row_count; + + str=gtk_entry_get_text(GTK_ENTRY(widget)); + + if (widget == entry_country) { + if (search->country_hash) g_hash_table_destroy(search->country_hash); + search->country_hash=NULL; + } + if (widget == entry_country || widget == entry_city) { + if (search->town_hash) g_hash_table_destroy(search->town_hash); + if (search->district_hash) g_hash_table_destroy(search->district_hash); + search->town_hash=NULL; + search->district_hash=NULL; + } + + if (widget == entry_country || widget == entry_city || widget == entry_street) { + if (search->street_hash) g_hash_table_destroy(search->street_hash); + search->street_hash=NULL; + } + + if (widget == entry_country) { + search->country_hash=destination_country_new(); + search->country=str; + country_search_by_name(str, 1, destination_country_add, search); + country_search_by_car(str, 1, destination_country_add, search); + country_search_by_iso2(str, 1, destination_country_add, search); + country_search_by_iso3(str, 1, destination_country_add, search); + g_hash_table_foreach(search->country_hash, destination_country_show, search); + } + if (widget == entry_city) { + printf("Ort: '%s'\n", str); + if (strlen(str) > 1) { + search->town=str; + search->town_hash=destination_town_new(); + search->district_hash=destination_town_new(); + g_hash_table_foreach(search->country_hash, destination_town_search, search); + g_hash_table_foreach(search->town_hash, destination_town_show, search); + } + } + if (widget == entry_street) { + printf("Street: '%s'\n", str); + search->street=str; + search->street_hash=destination_street_new(); + g_hash_table_foreach(search->town_hash, destination_street_search, search); + g_hash_table_foreach(search->street_hash, destination_street_show, search); + } + if (widget == entry_number) { + char buffer[strlen(str)+1]; + strcpy(buffer, str); + search->number=str; + dash=index(buffer,'-'); + if (dash) { + *dash++=0; + search->number_low=atoi(buffer); + if (strlen(str)) + search->number_high=atoi(dash); + else + search->number_high=10000; + } else { + if (!strlen(str)) { + search->number_low=0; + search->number_high=10000; + } else { + search->number_low=atoi(str); + search->number_high=atoi(str); + } + } + g_hash_table_foreach(search->street_hash, destination_street_show_number, search); + } + while (search->count-- > 0) { + gtk_clist_append(GTK_CLIST(listbox), empty); + } + gtk_clist_columns_autosize (GTK_CLIST(listbox)); + gtk_clist_thaw(GTK_CLIST(listbox)); +} + +int destination_address(struct container *co) +{ + GtkWidget *window2, *keyboard, *vbox, *table; + GtkWidget *label_country; + GtkWidget *label_postal, *label_city, *label_district; + GtkWidget *label_street, *label_number; + GtkWidget *hseparator1,*hseparator2; + GtkWidget *button1,*button2; + init_keyboard_stuff((char *) NULL); + int handlerid; + int i; + gchar *text[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + struct search_param *search=&search_param2; + +#if 0 + if (co->cursor) { + struct coord *c; + struct route_info *rt; + struct street_str *st; + struct block_info *blk; + struct street_name name; + struct town town; + + c=cursor_pos_get(co->cursor); + rt=route_find_nearest_street(co->map_data, c); + st=route_info_get_street(rt); + blk=route_info_get_block(rt); + printf("segid 0x%lx nameid 0x%lx\n", st->segid, st->nameid); + street_name_get_by_id(&name, blk->mdata, st->nameid); + printf("'%s' '%s' %d\n", name.name1, name.name2, name.segment_count); + for (i = 0 ; i < name.segment_count ; i++) { + if (name.segments[i].segid == st->segid) { + printf("found: 0x%x, 0x%x\n", name.segments[i].country, name.segments[i].segid); + town_get_by_id(&town, co->map_data, name.segments[i].country, name.townassoc); + printf("%s/%s\n", town.name, town.district); + } + } + } +#endif + + window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); + keyboard = build_keyboard(NULL, "/usr/local/share/gtkeyboard/DE.key"); + vbox = gtk_vbox_new(FALSE, 0); + table = gtk_table_new(3, 8, FALSE); + + entry_country = gtk_entry_new(); + label_country = gtk_label_new("Land"); + entry_postal = gtk_entry_new(); + label_postal = gtk_label_new("PLZ"); + entry_city = gtk_entry_new(); + label_city = gtk_label_new("Ort"); + entry_district = gtk_entry_new(); + label_district = gtk_label_new("Ortsteil/Gemeinde"); + hseparator1 = gtk_vseparator_new(); + entry_street = gtk_entry_new(); + label_street = gtk_label_new("Strasse"); + entry_number = gtk_entry_new(); + label_number = gtk_label_new("Nummer"); + listbox = gtk_clist_new(9); + for (i=0 ; i < row_count ; i++) { + gtk_clist_append(GTK_CLIST(listbox), text); + } + gtk_clist_thaw(GTK_CLIST(listbox)); + gtk_clist_columns_autosize (GTK_CLIST(listbox)); + + hseparator2 = gtk_vseparator_new(); + button1 = gtk_button_new_with_label("Karte"); + button2 = gtk_button_new_with_label("Ziel"); + + gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_city, 2, 3, 0, 1, 0, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), entry_country, 0, 1, 1, 2, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), entry_postal, 1, 2, 1, 2, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), entry_city, 2, 3, 1, 2, 0, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), label_district, 0, 1, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_street, 1, 2, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_number, 2, 3, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), entry_district, 0, 1, 3, 4, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), entry_street, 1, 2, 3, 4, 0, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), entry_number, 2, 3, 3, 4, 0, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), listbox, 0, 3, 4, 5, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), button1, 0, 1, 5, 6, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + gtk_table_attach(GTK_TABLE(table), button2, 2, 3, 5, 6, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + + search->map_data=co->map_data; + search->clist=listbox; + gtk_signal_connect(GTK_OBJECT(entry_country), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(entry_postal), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(entry_city), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(entry_district), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(entry_street), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(entry_number), "changed", GTK_SIGNAL_FUNC(changed), search); + gtk_signal_connect(GTK_OBJECT(button1), "clicked", GTK_SIGNAL_FUNC(button_map), co); + gtk_signal_connect(GTK_OBJECT(button2), "clicked", GTK_SIGNAL_FUNC(button_destination), co); + gtk_widget_grab_focus(entry_city); + + gtk_container_add(GTK_CONTAINER(vbox), table); + gtk_container_add(GTK_CONTAINER(vbox), keyboard); + gtk_container_add(GTK_CONTAINER(window2), vbox); + handlerid = gtk_timeout_add(256, (GtkFunction) track_focus, NULL); + + gtk_signal_connect(GTK_OBJECT(listbox), "select-row", GTK_SIGNAL_FUNC(select_row), NULL); + + gtk_widget_show_all(window2); + + return 0; +} diff --git a/destination.h b/destination.h new file mode 100644 index 00000000..68530f8f --- /dev/null +++ b/destination.h @@ -0,0 +1,11 @@ +enum destination_type { + destination_type_town=4, + destination_type_poly=6, + destination_type_street=8, + destination_type_house=12, + destination_type_map_point=16, + destination_type_bookmark=128, +}; + +int destination_address(struct container *co); +int destination_set(struct container *co, enum destination_type type, char *text, struct coord *c); diff --git a/display.c b/display.c new file mode 100644 index 00000000..ca1874ae --- /dev/null +++ b/display.c @@ -0,0 +1,266 @@ +#include +#include +#include "display.h" +#include "graphics.h" + +struct graphics_image *icons; + +struct graphics_image * +get_icon(struct graphics *gr, char *name) +{ + struct graphics_image *curr=icons; + while (curr) { + if (! strcmp(curr->name, name) && curr->gr == gr) + return curr; + curr=curr->next; + } + curr=gr->image_new(gr, name); + curr->next=icons; + icons=curr; + return curr; +} + +static int +within_dist_point(struct point *p0, struct point *p1, int dist) +{ + if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) { + return 1; + } + return 0; +} + +static int +within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist) +{ + int vx,vy,wx,wy; + int c1,c2; + struct point line_p; + + vx=line_p1->x-line_p0->x; + vy=line_p1->y-line_p0->y; + wx=p->x-line_p0->x; + wy=p->y-line_p0->y; + + c1=vx*wx+vy*wy; + if ( c1 <= 0 ) + return within_dist_point(p, line_p0, dist); + c2=vx*vx+vy*vy; + if ( c2 <= c1 ) + return within_dist_point(p, line_p1, dist); + + line_p.x=line_p0->x+vx*c1/c2; + line_p.y=line_p0->y+vy*c1/c2; + return within_dist_point(p, &line_p, dist); +} + +static int +within_polygon(struct point *p, struct point *poly_pnt, int count) +{ + int i, j, c = 0; + for (i = 0, j = count-1; i < count; j = i++) { + if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) || + ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) && + (poly_pnt->x < (poly_pnt[j].x - poly_pnt[i].x) * (p->y - poly_pnt[i].y) / (poly_pnt[j].y - poly_pnt[i].y) + poly_pnt[i].x)) { + c = !c; + } + } + return c; +} + +static int +within_dist_lines(struct point *p, struct point *line_pnt, int count, int dist) +{ + int i; + for (i = 0 ; i < count-1 ; i++) { + if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) { + return 1; + } + } + return 0; +} + +void +display_free(struct display_list **list, int count) +{ + struct display_list *curr,*next; + while (count--) { + curr=*list; + while (curr) { + next=curr->next; + g_free(curr); + curr=next; + } + *list++=NULL; + } +} + +void * +display_add(struct display_list **head, int type, int attr, char *label, int count, struct point *p, void (*info)(struct display_list *list, struct popup_item **item),void *data, int data_size) +{ + struct display_list *new; + int label_len=0; + + if (! data) + data_size=0; + + if (label) + label_len=strlen(label)+1; + new=g_malloc(sizeof(*new)+count*sizeof(*p)+label_len+data_size); + new->type=type; + new->attr=attr; + new->info=info; + if (label) { + new->label=(char *)new+sizeof(*new)+count*sizeof(*p); + strcpy(new->label, label); + } else + new->label=NULL; + new->count=count; + memcpy(new->p, p, count*sizeof(*p)); + if (data_size) { + new->data=(char *)new+sizeof(*new)+count*sizeof(*p)+label_len; + memcpy(new->data, data, data_size); + } else + new->data=NULL; + new->next=*head; + *head=new; + return new->data; +} + +void +display_draw(struct display_list *list, struct graphics *gr, struct graphics_gc *gc_fill, struct graphics_gc *gc_line) +{ + struct graphics_image *icon; + int r=3; + struct point p; + while (list) { + switch (list->type) { + case 0: + gr->draw_polygon(gr, gc_fill, list->p, list->count); + if (gc_line) + gr->draw_lines(gr, gc_line, list->p, list->count); + break; + case 1: + case 2: + gr->draw_lines(gr, gc_fill, list->p, list->count); + break; + case 3: + case 4: + gr->draw_circle(gr, gc_fill, list->p, r); + break; + case 5: + icon=get_icon(gr, list->label); + if (icon) { + p.x=list->p[0].x - icon->width/2; + p.y=list->p[0].y - icon->height/2; + gr->draw_image(gr, gc_fill, &p, icon); + } + else + printf("invalid icon '%s'\n", list->label); + break; + } + list=list->next; + } +} + +void +display_find(struct point *p, struct display_list **in, int in_count, int maxdist, struct display_list **out, int out_count) +{ + int i=0; + struct display_list *curr; + + while (in_count--) { + curr=*in++; + while (curr) { + switch (curr->type) { + case 0: + if (within_polygon(p, curr->p, curr->count) || + within_dist_lines(p, curr->p, curr->count, maxdist)) + { + if (i < out_count) + out[i++]=curr; + } + break; + case 1: + case 2: + if (within_dist_lines(p, curr->p, curr->count, maxdist)) + { + if (i < out_count) + out[i++]=curr; + } + break; + case 3: + case 4: + case 5: + if (within_dist_point(p, curr->p, 8)) + { + if (i < out_count) + out[i++]=curr; + } + break; + } + curr=curr->next; + } + } + if (i < out_count) + out[i]=NULL; +} + + +static void +label_line(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label) +{ + int i,x,y,tl; + double dx,dy,l; + struct point p_t; + + tl=strlen(label)*400; + for (i = 0 ; i < count-1 ; i++) { + dx=p[i+1].x-p[i].x; + dx*=100; + dy=p[i+1].y-p[i].y; + dy*=100; + l=(int)sqrt((float)(dx*dx+dy*dy)); + if (l > tl) { + x=p[i].x; + y=p[i].y; + if (dx < 0) { + dx=-dx; + dy=-dy; + x=p[i+1].x; + y=p[i+1].y; + } + x+=(l-tl)*dx/l/200; + y+=(l-tl)*dy/l/200; + x-=dy*45/l/10; + y+=dx*45/l/10; + p_t.x=x; + p_t.y=y; +#if 0 + printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l); +#endif + gr->draw_text(gr, fg, bg, font, label, &p_t, dx*0x10000/l, dy*0x10000/l); + } + } +} + +void +display_labels(struct display_list *list, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font) +{ + struct point p; + while (list) { + if (list->label) { + switch (list->type) { + case 1: + case 2: + label_line(gr, fg, bg, font, list->p, list->count, list->label); + break; + case 3: + p.x=list->p[0].x+3; + p.y=list->p[0].y+10; + gr->draw_text(gr, fg, bg, font, list->label, &p, 0x10000, 0); + break; + } + } + list=list->next; + } +} diff --git a/display.h b/display.h new file mode 100644 index 00000000..952381f2 --- /dev/null +++ b/display.h @@ -0,0 +1,24 @@ +#include "point.h" + +struct popup_item; +struct graphics; +struct graphics_gc; +struct graphics_font; + +struct display_list { + struct display_list *next; + void *data; + int type; + int attr; + char *label; + int count; + void (*info)(struct display_list *list, struct popup_item **popup); + struct point p[0]; +}; +void *display_add(struct display_list **head, int type, int attr, char *label, int count, struct point *p, void (*info)(struct display_list *list, struct popup_item **popup), void *data, int data_size); + +void display_free(struct display_list **list, int count); + +void display_draw(struct display_list *list, struct graphics *gr, struct graphics_gc *gc_fill, struct graphics_gc *gc_line); +void display_find(struct point *pnt, struct display_list **in, int in_count, int maxdist, struct display_list **out, int out_count); +void display_labels(struct display_list *list, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font); diff --git a/draw_info.h b/draw_info.h new file mode 100644 index 00000000..6acee92c --- /dev/null +++ b/draw_info.h @@ -0,0 +1,5 @@ +struct draw_info { + struct container *co; + int display; + int limit; +}; diff --git a/fib-1.1/Makefile.in b/fib-1.1/Makefile.in new file mode 100644 index 00000000..d4829377 --- /dev/null +++ b/fib-1.1/Makefile.in @@ -0,0 +1,116 @@ +# $Id: Makefile.in,v 1.1 2005-12-02 10:41:56 martin-s Exp $ +# + +SHELL = /bin/sh + +LIB = fib + +SRCS = fib.c +OBJS = fib.o +SOBJS = fib.so +POBJS = fib.po + +INCS = fib.h + +TESTPROG = use +TESTSRCS = use.c +TESTOBJS = use.o + +REGRESS_PROG = fibtest fibtest2 tt + +DEBUG = -g -Wall -Werror +#OPT = -O2 +PROFILE = -pg +LIBOPTS = -DFH_STATS # -DNO_FREE + +srcdir = @srcdir@ + +AFLAGS = -Wall -I$(srcdir) $(DEBUG) $(OPT) $(LIBOPTS) $(CFLAGS) + +MAJOR = 1 +ARNAME = lib$(LIB).a +SONAME = lib$(LIB).so.$(MAJOR) +PANAME = lib$(LIB)_p.a + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +LIBDIR = @libdir@ +LIBOWN = 0 +LIBGRP = 0 +LIBMOD = 0444 +INCDIR = @includedir@ +INCOWN = 0 +INCGRP = 0 +INCMOD = 0444 + +all: $(ARNAME) $(SONAME) $(PANAME) + +$(ARNAME): $(OBJS) + $(AR) rc $@ $(OBJS) + +$(SONAME): $(SOBJS) + $(CC) -shared -o $@ $(SOBJS) + +$(PANAME): $(POBJS) + $(AR) rc $@ $(POBJS) + +$(TESTPROG): $(TESTOBJS) $(ARNAME) + $(CC) -static $(CFLAGS) -o $@ $(TESTOBJS) $(ARNAME) $(PROFILE) + +deepclean: clean + rm -f Makefile config.cache config.log config.status configure + +clean: regressclean + rm -f $(ARNAME) $(OBJS) $(SONAME) $(SOBJS) $(PANAME) $(POBJS) \ + $(TESTPROG) $(TESTOBJS) .depend + +install: $(ARNAME) $(SONAME) $(PANAME) + mkdir -p -m 755 $(LIBDIR) + for i in $(ARNAME) $(SONAME) $(PANAME); do \ + cp $$i $(LIBDIR); \ + chown $(LIBOWN):$(LIBGRP) $(LIBDIR)/$$i; \ + chmod $(LIBMOD) $(LIBDIR)/$$i; \ + done + mkdir -p -m 755 $(INCDIR) + for i in $(INCS); do \ + cp $$i $(INCDIR); \ + chown $(INCOWN):$(INCGRP) $(INCDIR)/$$i; \ + chmod $(INCMOD) $(INCDIR)/$$i; \ + done + +depend: + mkdep $(AFLAGS) $(SRCS) + +$(srcdir)/configure: configure.in + cd $(srcdir) && autoconf + +Makefile: Makefile.in config.status + ./config.status + +config.status: configure + ./config.status --recheck + +regress: $(REGRESS_PROG) + @for i in $(REGRESS_PROG); do \ + echo Regression for $$i; \ + ./$$i > regress.new; \ + diff $${i}.out regress.new; \ + done + rm regress.new + +regressclean: + rm -f $(REGRESS_PROG) + +.SUFFIXES: +.SUFFIXES: .so .po .c .o +.c.so: + $(CC) -fpic $(AFLAGS) -c $< -o $@ + +.c.po: + $(CC) $(PROFILE) $(AFLAGS) -c $< -o $@ + +.c.o: + $(CC) $(CPPFLAGS) $(AFLAGS) -c $< -o $@ + +.c: $(ARNAME) + $(CC) $(CPPFLAGS) $(AFLAGS) -o $@ $< $(ARNAME) diff --git a/fib-1.1/README b/fib-1.1/README new file mode 100644 index 00000000..eabcd5f8 --- /dev/null +++ b/fib-1.1/README @@ -0,0 +1,26 @@ +Version 1.1 now supports increasing the key using the fh_replace* +functions. Previously it would simply return NULL when you tried to +increase the key. It also improves performance slightly by only calling +checkcons when we are about to use it, at extract, instead of calling it +on every insert. + +I have now fixed fh_union and it properly updates the minimum. + +Thanks to Ryan Earl for pointing out that in fh_consolidate, it is VERY +time consuming to constantly malloc/free an array of pointers. The array +is small enough that simply reallocating when more pointers are needed +is ok. + +Thanks to Thomas Eschbach and Wolfgang Guenther who have pointed out bugs +with my code. Wolfgang Guenther provided a fix which put in on the correct +track for where the bug was. They have also provided a few test programs +that exhibited other bugs which I have now integrated into my source so +that you can easily regress test the library. + +I have reciently completed a review of the code. I have made a number +of improvements with a few minor interface changes. There is another +improvement to the rh_replace* family of functions to help eliminate +redundant code. + +I'm still planning on writing a type safe memory allocator for use with +the code instead of using malloc to hopefully improve performance slightly. diff --git a/fib-1.1/configure b/fib-1.1/configure new file mode 100755 index 00000000..62eaa3d0 --- /dev/null +++ b/fib-1.1/configure @@ -0,0 +1,1045 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=fib.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:529: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:550: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:567: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:584: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:609: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:622: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in limits.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:716: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:754: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h < confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CPP@%$CPP%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/fib-1.1/configure.in b/fib-1.1/configure.in new file mode 100644 index 00000000..82701527 --- /dev/null +++ b/fib-1.1/configure.in @@ -0,0 +1,17 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(fib.c) + +dnl Checks for programs. + +dnl Checks for libraries. + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(limits.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_INLINE + +dnl Checks for library functions. + +AC_OUTPUT(Makefile) diff --git a/fib-1.1/fh_extractmin.3 b/fib-1.1/fh_extractmin.3 new file mode 100644 index 00000000..e1492b40 --- /dev/null +++ b/fib-1.1/fh_extractmin.3 @@ -0,0 +1,97 @@ +.TH FH_EXTRACTMIN 3 "29 Mar 2000" "libfib" +.SH NAME +fh_extractmin \- extract minimum element from a Fibonacci Heap +.SH SYNOPSIS +#include +.PP +void * +.PD 0 +.HP 8 +.BR fh_extractmin "(struct fibheap *heap)" +.PD +.PP +void * +.PD 0 +.HP 8 +.BR fh_min "(struct fibheap *heap)" +.PD +.PP +void * +.PD 0 +.HP 8 +.BR fh_replacedata "(struct fibheap *heap, struct fibheap_el *elem, void *data)" +.PD +.PP +void * +.PD 0 +.HP 8 +.BR fh_delete "(struct fibheap *heap, struct fibheap_el *elem)" +.PD +.PP +void +.PD 0 +.HP 8 +.BR fh_deleteheap "(struct fibheap *heap)" +.PD +.PP +struct fibheap * +.PD 0 +.HP 8 +.BR fh_union "(struct fibheap *heapa, struct fibheap *heapb)" +.PD +.SH DESCRIPTION +These functions are shared between both key heaps and normal heaps. +.PP +Once a +.B elem +pointer has been passed to +.BR fh_delete (3) +that +.B elem +pointer may be reused to store another datum. +You should make sure that you destroy any copies of the pointer. +.SH RETURN VALUES +The +.B fh_extractmin +function returns the value of +.B data +that is the minimum element and removes it from the heap. +.PP +The +.B fh_min +function returns the current minimum element but does +.I not +remove it from the heap. +.PP +The +.B fh_replacedata +replaces the data in +.B elem +and returns the old data. +.PP +The +.B fh_delete +function removes +.B elem +from the heap, and returns the +.B data +that was stored in the element. +.PP +The +.B fh_deleteheap +complete destroys the heap. It does not free any user supplied +.B data +elements stored in the heap. +.PP +The +.B fh_union +function returns the union of the two heaps +.B heapa +and +.BR heapb . +.SH SEE ALSO +.BR fh_makeheap (3), +.BR fh_makekeyheap (3) +.SH AUTHORS +This library and man page was writen by John-Mark Gurney . +.SH BUGS diff --git a/fib-1.1/fh_makeheap.3 b/fib-1.1/fh_makeheap.3 new file mode 100644 index 00000000..bd867cd0 --- /dev/null +++ b/fib-1.1/fh_makeheap.3 @@ -0,0 +1,17 @@ +.TH FH_MAKEHEAP 3 "29 Mar 2000" "libfib" +.SH NAME +fh_makeheap \- make a Fibonacci Heap +.SH SYNOPSIS +.nf +#include +.PP +struct fibheap * +.BR fh_makeheap (void) +.fi +.SH DESCRIPTION +.SH RETURN VALUES +.SH FILES +.SH SEE ALSO +.SH AUTHORS +This library and man page was writen by John-Mark Gurney . +.SH BUGS diff --git a/fib-1.1/fh_makekeyheap.3 b/fib-1.1/fh_makekeyheap.3 new file mode 100644 index 00000000..f55d4307 --- /dev/null +++ b/fib-1.1/fh_makekeyheap.3 @@ -0,0 +1,84 @@ +.TH FH_MAKEKEYHEAP 3 "29 Mar 2000" "libfib" +.SH NAME +fh_makekeyheap \- make a Fibonacci key Heap +.SH SYNOPSIS +#include +.PP +struct fibheap * +.PD 0 +.HP 8 +.BR fh_makekeyheap (void) +.PD +.PP +struct fibheap_el * +.PD 0 +.HP 8 +.BR fh_insertkey "(struct fibheap *heap, int key, void *data)" +.PD +.PP +int +.PD 0 +.HP 8 +.BR fh_minkey "(struct fibheap *heap)" +.PD +.PP +void * +.PD 0 +.HP 8 +.BR fh_replacekey "(struct fibheap *heap, struct fibheap_el *elem, int key)" +.PD +.PP +void * +.PD 0 +.HP 8 +.BR fh_replacekeydata "(struct fibheap *heap, struct fibheap_el *elem, int key, void *data)" +.PD +.SH DESCRIPTION +The +.B fh_makekeyheap +function makes a Fibonacci heap which does ordering based on an +integer key that is given in addition to the data. +This menthod is useful so that you can eliminate the need to call +a comparision function to order the data in the heap. +.PP +The pointer to the structure +.B fibheap +returned by +.B fh_makekeyheap +is an opaque structure. The the pointer can only be passed to other +functions in the +.B libfib +library. +.PP +The +.B fh_insertkey +function inserts the +.B data +element into the heap with a value of +.BR key . +The pointer returned can be used in calls to functions like +.BR fh_delete (3) +to delete the key from the heap before it gets extracted via +.BR fh_extractmin (3). +.SH RETURN VALUES +The +.B fh_makekeyheap +function returns a pointer to a heap structure used to insert and extract +data elements. +.PP +The +.B fh_insertkey +functions returns a pointer to a heap element structure which can be used +to manimulate that data element in the heap. +.PP +The +.B fh_minkey +function returns the integer key of the data at the top of the heap. If you would like to view the data, see +.BR fh_min (3). +.SH SEE ALSO +.BR fh_extractmin (3) +.SH AUTHORS +This library and man page was writen by John-Mark Gurney . +.SH BUGS +A key heap does not provide a way for handling key collitions and deffering +decission to a user provided function to resolve colissions. diff --git a/fib-1.1/fib.c b/fib-1.1/fib.c new file mode 100644 index 00000000..ace5d129 --- /dev/null +++ b/fib-1.1/fib.c @@ -0,0 +1,696 @@ +/*- + * Copyright 1997-2003 John-Mark Gurney. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: fib.c,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * + */ + +#include +#include + +#include +#include + +#define swap(type, a, b) \ + do { \ + type c; \ + c = a; \ + a = b; \ + b = c; \ + } while (0) \ + +#define INT_BITS (sizeof(int) * 8) +static inline int +ceillog2(unsigned int a) +{ + int oa; + int i; + int b; + + oa = a; + b = INT_BITS / 2; + i = 0; + while (b) { + i = (i << 1); + if (a >= (1 << b)) { + a /= (1 << b); + i = i | 1; + } else + a &= (1 << b) - 1; + b /= 2; + } + if ((1 << i) == oa) + return i; + else + return i + 1; +} + +/* + * Private Heap Functions + */ +static void +fh_deleteel(struct fibheap *h, struct fibheap_el *x) +{ + void *data; + int key; + + data = x->fhe_data; + key = x->fhe_key; + + if (!h->fh_keys) + fh_replacedata(h, x, h->fh_neginf); + else + fh_replacekey(h, x, INT_MIN); + if (fh_extractminel(h) != x) { + /* + * XXX - This should never happen as fh_replace should set it + * to min. + */ + abort(); + } + + x->fhe_data = data; + x->fhe_key = key; +} + +static void +fh_initheap(struct fibheap *new) +{ + new->fh_cmp_fnct = NULL; + new->fh_neginf = NULL; + new->fh_n = 0; + new->fh_Dl = -1; + new->fh_cons = NULL; + new->fh_min = NULL; + new->fh_root = NULL; + new->fh_keys = 0; +#ifdef FH_STATS + new->fh_maxn = 0; + new->fh_ninserts = 0; + new->fh_nextracts = 0; +#endif +} + +static void +fh_destroyheap(struct fibheap *h) +{ + h->fh_cmp_fnct = NULL; + h->fh_neginf = NULL; + if (h->fh_cons != NULL) + free(h->fh_cons); + h->fh_cons = NULL; + free(h); +} + +/* + * Public Heap Functions + */ +struct fibheap * +fh_makekeyheap() +{ + struct fibheap *n; + + if ((n = malloc(sizeof *n)) == NULL) + return NULL; + + fh_initheap(n); + n->fh_keys = 1; + + return n; +} + +struct fibheap * +fh_makeheap() +{ + struct fibheap *n; + + if ((n = malloc(sizeof *n)) == NULL) + return NULL; + + fh_initheap(n); + + return n; +} + +voidcmp +fh_setcmp(struct fibheap *h, voidcmp fnct) +{ + voidcmp oldfnct; + + oldfnct = h->fh_cmp_fnct; + h->fh_cmp_fnct = fnct; + + return oldfnct; +} + +void * +fh_setneginf(struct fibheap *h, void *data) +{ + void *old; + + old = h->fh_neginf; + h->fh_neginf = data; + + return old; +} + +struct fibheap * +fh_union(struct fibheap *ha, struct fibheap *hb) +{ + struct fibheap_el *x; + + if (ha->fh_root == NULL || hb->fh_root == NULL) { + /* either one or both are empty */ + if (ha->fh_root == NULL) { + fh_destroyheap(ha); + return hb; + } else { + fh_destroyheap(hb); + return ha; + } + } + ha->fh_root->fhe_left->fhe_right = hb->fh_root; + hb->fh_root->fhe_left->fhe_right = ha->fh_root; + x = ha->fh_root->fhe_left; + ha->fh_root->fhe_left = hb->fh_root->fhe_left; + hb->fh_root->fhe_left = x; + ha->fh_n += hb->fh_n; + /* + * we probably should also keep stats on number of unions + */ + + /* set fh_min if necessary */ + if (fh_compare(ha, hb->fh_min, ha->fh_min) < 0) + ha->fh_min = hb->fh_min; + + fh_destroyheap(hb); + return ha; +} + +void +fh_deleteheap(struct fibheap *h) +{ + /* + * We could do this even faster by walking each binomial tree, but + * this is simpler to code. + */ + while (h->fh_min != NULL) + fhe_destroy(fh_extractminel(h)); + + fh_destroyheap(h); +} + +/* + * Public Key Heap Functions + */ +struct fibheap_el * +fh_insertkey(struct fibheap *h, int key, void *data) +{ + struct fibheap_el *x; + + if ((x = fhe_newelem()) == NULL) + return NULL; + + /* just insert on root list, and make sure it's not the new min */ + x->fhe_data = data; + x->fhe_key = key; + + fh_insertel(h, x); + + return x; +} + +int +fh_minkey(struct fibheap *h) +{ + if (h->fh_min == NULL) + return INT_MIN; + return h->fh_min->fhe_key; +} + +int +fh_replacekey(struct fibheap *h, struct fibheap_el *x, int key) +{ + int ret; + + ret = x->fhe_key; + (void)fh_replacekeydata(h, x, key, x->fhe_data); + + return ret; +} + +void * +fh_replacekeydata(struct fibheap *h, struct fibheap_el *x, int key, void *data) +{ + void *odata; + int okey; + struct fibheap_el *y; + int r; + + odata = x->fhe_data; + okey = x->fhe_key; + + /* + * we can increase a key by deleting and reinserting, that + * requires O(lgn) time. + */ + if ((r = fh_comparedata(h, key, data, x)) > 0) { + /* XXX - bad code! */ + abort(); + fh_deleteel(h, x); + + x->fhe_data = data; + x->fhe_key = key; + + fh_insertel(h, x); + + return odata; + } + + x->fhe_data = data; + x->fhe_key = key; + + /* because they are equal, we don't have to do anything */ + if (r == 0) + return odata; + + y = x->fhe_p; + + if (h->fh_keys && okey == key) + return odata; + + if (y != NULL && fh_compare(h, x, y) <= 0) { + fh_cut(h, x, y); + fh_cascading_cut(h, y); + } + + /* + * the = is so that the call from fh_delete will delete the proper + * element. + */ + if (fh_compare(h, x, h->fh_min) <= 0) + h->fh_min = x; + + return odata; +} + +/* + * Public void * Heap Functions + */ +/* + * this will return these values: + * NULL failed for some reason + * ptr token to use for manipulation of data + */ +struct fibheap_el * +fh_insert(struct fibheap *h, void *data) +{ + struct fibheap_el *x; + + if ((x = fhe_newelem()) == NULL) + return NULL; + + /* just insert on root list, and make sure it's not the new min */ + x->fhe_data = data; + + fh_insertel(h, x); + + return x; +} + +void * +fh_min(struct fibheap *h) +{ + if (h->fh_min == NULL) + return NULL; + return h->fh_min->fhe_data; +} + +void * +fh_extractmin(struct fibheap *h) +{ + struct fibheap_el *z; + void *ret; + + ret = NULL; + + if (h->fh_min != NULL) { + z = fh_extractminel(h); + ret = z->fhe_data; +#ifndef NO_FREE + fhe_destroy(z); +#endif + + } + + return ret; +} + +void * +fh_replacedata(struct fibheap *h, struct fibheap_el *x, void *data) +{ + return fh_replacekeydata(h, x, x->fhe_key, data); +} + +void * +fh_delete(struct fibheap *h, struct fibheap_el *x) +{ + void *k; + + k = x->fhe_data; + if (!h->fh_keys) + fh_replacedata(h, x, h->fh_neginf); + else + fh_replacekey(h, x, INT_MIN); + fh_extractmin(h); + + return k; +} + +/* + * Statistics Functions + */ +#ifdef FH_STATS +int +fh_maxn(struct fibheap *h) +{ + return h->fh_maxn; +} + +int +fh_ninserts(struct fibheap *h) +{ + return h->fh_ninserts; +} + +int +fh_nextracts(struct fibheap *h) +{ + return h->fh_nextracts; +} +#endif + +/* + * begin of private element fuctions + */ +static struct fibheap_el * +fh_extractminel(struct fibheap *h) +{ + struct fibheap_el *ret; + struct fibheap_el *x, *y, *orig; + + ret = h->fh_min; + + orig = NULL; + /* put all the children on the root list */ + /* for true consistancy, we should use fhe_remove */ + for(x = ret->fhe_child; x != orig && x != NULL;) { + if (orig == NULL) + orig = x; + y = x->fhe_right; + x->fhe_p = NULL; + fh_insertrootlist(h, x); + x = y; + } + /* remove minimum from root list */ + fh_removerootlist(h, ret); + h->fh_n--; + + /* if we aren't empty, consolidate the heap */ + if (h->fh_n == 0) + h->fh_min = NULL; + else { + h->fh_min = ret->fhe_right; + fh_consolidate(h); + } + +#ifdef FH_STATS + h->fh_nextracts++; +#endif + + return ret; +} + +static void +fh_insertrootlist(struct fibheap *h, struct fibheap_el *x) +{ + if (h->fh_root == NULL) { + h->fh_root = x; + x->fhe_left = x; + x->fhe_right = x; + return; + } + + fhe_insertafter(h->fh_root, x); +} + +static void +fh_removerootlist(struct fibheap *h, struct fibheap_el *x) +{ + if (x->fhe_left == x) + h->fh_root = NULL; + else + h->fh_root = fhe_remove(x); +} + +static void +fh_consolidate(struct fibheap *h) +{ + struct fibheap_el **a; + struct fibheap_el *w; + struct fibheap_el *y; + struct fibheap_el *x; + int i; + int d; + int D; + + fh_checkcons(h); + + /* assign a the value of h->fh_cons so I don't have to rewrite code */ + D = h->fh_Dl + 1; + a = h->fh_cons; + + for (i = 0; i < D; i++) + a[i] = NULL; + + while ((w = h->fh_root) != NULL) { + x = w; + fh_removerootlist(h, w); + d = x->fhe_degree; + /* XXX - assert that d < D */ + while(a[d] != NULL) { + y = a[d]; + if (fh_compare(h, x, y) > 0) + swap(struct fibheap_el *, x, y); + fh_heaplink(h, y, x); + a[d] = NULL; + d++; + } + a[d] = x; + } + h->fh_min = NULL; + for (i = 0; i < D; i++) + if (a[i] != NULL) { + fh_insertrootlist(h, a[i]); + if (h->fh_min == NULL || fh_compare(h, a[i], + h->fh_min) < 0) + h->fh_min = a[i]; + } +} + +static void +fh_heaplink(struct fibheap *h, struct fibheap_el *y, struct fibheap_el *x) +{ + /* make y a child of x */ + if (x->fhe_child == NULL) + x->fhe_child = y; + else + fhe_insertbefore(x->fhe_child, y); + y->fhe_p = x; + x->fhe_degree++; + y->fhe_mark = 0; +} + +static void +fh_cut(struct fibheap *h, struct fibheap_el *x, struct fibheap_el *y) +{ + fhe_remove(x); + y->fhe_degree--; + fh_insertrootlist(h, x); + x->fhe_p = NULL; + x->fhe_mark = 0; +} + +static void +fh_cascading_cut(struct fibheap *h, struct fibheap_el *y) +{ + struct fibheap_el *z; + + while ((z = y->fhe_p) != NULL) { + if (y->fhe_mark == 0) { + y->fhe_mark = 1; + return; + } else { + fh_cut(h, y, z); + y = z; + } + } +} + +/* + * begining of handling elements of fibheap + */ +static struct fibheap_el * +fhe_newelem() +{ + struct fibheap_el *e; + + if ((e = malloc(sizeof *e)) == NULL) + return NULL; + + fhe_initelem(e); + + return e; +} + +static void +fhe_initelem(struct fibheap_el *e) +{ + e->fhe_degree = 0; + e->fhe_mark = 0; + e->fhe_p = NULL; + e->fhe_child = NULL; + e->fhe_left = e; + e->fhe_right = e; + e->fhe_data = NULL; +} + +static void +fhe_insertafter(struct fibheap_el *a, struct fibheap_el *b) +{ + if (a == a->fhe_right) { + a->fhe_right = b; + a->fhe_left = b; + b->fhe_right = a; + b->fhe_left = a; + } else { + b->fhe_right = a->fhe_right; + a->fhe_right->fhe_left = b; + a->fhe_right = b; + b->fhe_left = a; + } +} + +static inline void +fhe_insertbefore(struct fibheap_el *a, struct fibheap_el *b) +{ + fhe_insertafter(a->fhe_left, b); +} + +static struct fibheap_el * +fhe_remove(struct fibheap_el *x) +{ + struct fibheap_el *ret; + + if (x == x->fhe_left) + ret = NULL; + else + ret = x->fhe_left; + + /* fix the parent pointer */ + if (x->fhe_p != NULL && x->fhe_p->fhe_child == x) + x->fhe_p->fhe_child = ret; + + x->fhe_right->fhe_left = x->fhe_left; + x->fhe_left->fhe_right = x->fhe_right; + + /* clear out hanging pointers */ + x->fhe_p = NULL; + x->fhe_left = x; + x->fhe_right = x; + + return ret; +} + +static void +fh_checkcons(struct fibheap *h) +{ + int oDl; + + /* make sure we have enough memory allocated to "reorganize" */ + if (h->fh_Dl == -1 || h->fh_n > (1 << h->fh_Dl)) { + oDl = h->fh_Dl; + if ((h->fh_Dl = ceillog2(h->fh_n) + 1) < 8) + h->fh_Dl = 8; + if (oDl != h->fh_Dl) + h->fh_cons = (struct fibheap_el **)realloc(h->fh_cons, + sizeof *h->fh_cons * (h->fh_Dl + 1)); + if (h->fh_cons == NULL) + abort(); + } +} + +static int +fh_compare(struct fibheap *h, struct fibheap_el *a, struct fibheap_el *b) +{ + if (h->fh_keys) { + if (a->fhe_key < b->fhe_key) + return -1; + if (a->fhe_key == b->fhe_key) + return 0; + return 1; + } else + return h->fh_cmp_fnct(a->fhe_data, b->fhe_data); +} + +static int +fh_comparedata(struct fibheap *h, int key, void *data, struct fibheap_el *b) +{ + struct fibheap_el a; + + a.fhe_key = key; + a.fhe_data = data; + + return fh_compare(h, &a, b); +} + +static void +fh_insertel(struct fibheap *h, struct fibheap_el *x) +{ + fh_insertrootlist(h, x); + + if (h->fh_min == NULL || (h->fh_keys ? x->fhe_key < h->fh_min->fhe_key + : h->fh_cmp_fnct(x->fhe_data, h->fh_min->fhe_data) < 0)) + h->fh_min = x; + + h->fh_n++; + +#ifdef FH_STATS + if (h->fh_n > h->fh_maxn) + h->fh_maxn = h->fh_n; + h->fh_ninserts++; +#endif + +} diff --git a/fib-1.1/fib.h b/fib-1.1/fib.h new file mode 100644 index 00000000..d8564d3c --- /dev/null +++ b/fib-1.1/fib.h @@ -0,0 +1,64 @@ +/*- + * Copyright 1997, 1998-2003 John-Mark Gurney. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: fib.h,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * + */ + +#ifndef _FIB_H_ +#define _FIB_H_ + +struct fibheap; +struct fibheap_el; +typedef int (*voidcmp)(void *, void *); + +/* functions for key heaps */ +struct fibheap *fh_makekeyheap(void); +struct fibheap_el *fh_insertkey(struct fibheap *, int, void *); +int fh_minkey(struct fibheap *); +int fh_replacekey(struct fibheap *, struct fibheap_el *, int); +void *fh_replacekeydata(struct fibheap *, struct fibheap_el *, int, void *); + +/* functions for void * heaps */ +struct fibheap *fh_makeheap(void); +voidcmp fh_setcmp(struct fibheap *, voidcmp); +void *fh_setneginf(struct fibheap *, void *); +struct fibheap_el *fh_insert(struct fibheap *, void *); + +/* shared functions */ +void *fh_extractmin(struct fibheap *); +void *fh_min(struct fibheap *); +void *fh_replacedata(struct fibheap *, struct fibheap_el *, void *); +void *fh_delete(struct fibheap *, struct fibheap_el *); +void fh_deleteheap(struct fibheap *); +struct fibheap *fh_union(struct fibheap *, struct fibheap *); + +#ifdef FH_STATS +int fh_maxn(struct fibheap *); +int fh_ninserts(struct fibheap *); +int fh_nextracts(struct fibheap *); +#endif + +#endif /* _FIB_H_ */ diff --git a/fib-1.1/fibpriv.h b/fib-1.1/fibpriv.h new file mode 100644 index 00000000..3984b261 --- /dev/null +++ b/fib-1.1/fibpriv.h @@ -0,0 +1,98 @@ +/*- + * Copyright 1997, 1999-2003 John-Mark Gurney. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: fibpriv.h,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * + */ + +#ifndef _FIBPRIV_H_ +#define _FIBPRIV_H_ + +struct fibheap_el; + +/* + * global heap operations + */ +struct fibheap { + int (*fh_cmp_fnct)(void *, void *); + int fh_n; + int fh_Dl; + struct fibheap_el **fh_cons; + struct fibheap_el *fh_min; + struct fibheap_el *fh_root; + void *fh_neginf; + int fh_keys : 1; +#ifdef FH_STATS + int fh_maxn; + int fh_ninserts; + int fh_nextracts; +#endif +}; + +static void fh_initheap(struct fibheap *); +static void fh_insertrootlist(struct fibheap *, struct fibheap_el *); +static void fh_removerootlist(struct fibheap *, struct fibheap_el *); +static void fh_consolidate(struct fibheap *); +static void fh_heaplink(struct fibheap *h, struct fibheap_el *y, + struct fibheap_el *x); +static void fh_cut(struct fibheap *, struct fibheap_el *, struct fibheap_el *); +static void fh_cascading_cut(struct fibheap *, struct fibheap_el *); +static struct fibheap_el *fh_extractminel(struct fibheap *); +static void fh_checkcons(struct fibheap *h); +static void fh_destroyheap(struct fibheap *h); +static int fh_compare(struct fibheap *h, struct fibheap_el *a, + struct fibheap_el *b); +static int fh_comparedata(struct fibheap *h, int key, void *data, + struct fibheap_el *b); +static void fh_insertel(struct fibheap *h, struct fibheap_el *x); +static void fh_deleteel(struct fibheap *h, struct fibheap_el *x); + +/* + * specific node operations + */ +struct fibheap_el { + int fhe_degree; + int fhe_mark; + struct fibheap_el *fhe_p; + struct fibheap_el *fhe_child; + struct fibheap_el *fhe_left; + struct fibheap_el *fhe_right; + int fhe_key; + void *fhe_data; +}; + +static struct fibheap_el *fhe_newelem(void); +static void fhe_initelem(struct fibheap_el *); +static void fhe_insertafter(struct fibheap_el *a, struct fibheap_el *b); +static inline void fhe_insertbefore(struct fibheap_el *a, struct fibheap_el *b); +static struct fibheap_el *fhe_remove(struct fibheap_el *a); +#define fhe_destroy(x) free((x)) + +/* + * general functions + */ +static inline int ceillog2(unsigned int a); + +#endif /* _FIBPRIV_H_ */ diff --git a/fib-1.1/fibtest.c b/fib-1.1/fibtest.c new file mode 100644 index 00000000..c7be1e9c --- /dev/null +++ b/fib-1.1/fibtest.c @@ -0,0 +1,80 @@ +#include +#include +#include "fib.h" + +int main(void) +{ + struct fibheap *a; + void *arr[10]; + int i; + + a = fh_makekeyheap(); + + for (i=1 ; i < 10 ; i++) + { + arr[i]= fh_insertkey(a,0,(void *)i); + printf("adding: 0 %d \n",i); + } + + printf(" \n"); + fh_replacekey(a, arr[1],-1); + fh_replacekey(a, arr[6],-1); + fh_replacekey(a, arr[4],-1); + fh_replacekey(a, arr[2],-1); + fh_replacekey(a, arr[8],-1); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[7],-33); +/* -> node 7 becomes root node, but is still pointed to by node 6 */ + fh_replacekey(a, arr[4],-36); + fh_replacekey(a, arr[3],-1); + fh_replacekey(a, arr[9],-81); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[6],-68); + fh_replacekey(a, arr[2],-69); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[1],-52); + fh_replacekey(a, arr[3],-2); + fh_replacekey(a, arr[4],-120); + fh_replacekey(a, arr[5],-48); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[3],-3); + fh_replacekey(a, arr[5],-63); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[5],-110); + fh_replacekey(a, arr[7],-115); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[5],-188); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[3],-4); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + printf("value(minkey) %d\n",fh_minkey(a)); + printf("id: %d\n\n", (int)fh_extractmin(a)); + + fh_deleteheap(a); + + return 0; +} diff --git a/fib-1.1/fibtest.out b/fib-1.1/fibtest.out new file mode 100644 index 00000000..285bd26b --- /dev/null +++ b/fib-1.1/fibtest.out @@ -0,0 +1,37 @@ +adding: 0 1 +adding: 0 2 +adding: 0 3 +adding: 0 4 +adding: 0 5 +adding: 0 6 +adding: 0 7 +adding: 0 8 +adding: 0 9 + +value(minkey) -1 +id: 8 + +value(minkey) -81 +id: 9 + +value(minkey) -69 +id: 2 + +value(minkey) -120 +id: 4 + +value(minkey) -68 +id: 6 + +value(minkey) -115 +id: 7 + +value(minkey) -188 +id: 5 + +value(minkey) -52 +id: 1 + +value(minkey) -4 +id: 3 + diff --git a/fib-1.1/fibtest2.c b/fib-1.1/fibtest2.c new file mode 100644 index 00000000..8a623b63 --- /dev/null +++ b/fib-1.1/fibtest2.c @@ -0,0 +1,69 @@ +#include +#include +#include "fib.h" + +int +main(void) { + struct fibheap *a; + void *arr[10]; + int i; + a = fh_makekeyheap(); + + for (i=1 ; i < 10 ; i++) + { + arr[i]= fh_insertkey(a,0,(void *)i); + printf("adding: 0 %d \n",i); + } + + printf(" \n"); + fh_replacekey(a, arr[1],-38); + fh_replacekey(a, arr[7],-34); + + printf("wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + fh_replacekey(a, arr[2],-55); + fh_replacekey(a, arr[5],-56); + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[4],-1); + fh_replacekey(a, arr[2],-102); + fh_replacekey(a, arr[6],-1); + fh_replacekey(a, arr[9],-1); + fh_replacekey(a, arr[8],-4); + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + fh_replacekey(a, arr[3],-74); + fh_replacekey(a, arr[8],-55); + fh_replacekey(a, arr[4],-2); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + fh_replacekey(a, arr[4],-3); + fh_replacekey(a, arr[6],-2); + fh_replacekey(a, arr[7],-99); + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + fh_replacekey(a, arr[6],-3); + fh_replacekey(a, arr[4],-4); + fh_replacekey(a, arr[8],-94); + fh_replacekey(a, arr[9],-2); + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + fh_replacekey(a, arr[6],-4); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + /*fh_replacekey(a, arr[9],-3);*/ + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + /*fh_replacekey(a, arr[9],-49);*/ + + fh_deleteheap(a); + + return 0; +} diff --git a/fib-1.1/fibtest2.out b/fib-1.1/fibtest2.out new file mode 100644 index 00000000..e9d1704f --- /dev/null +++ b/fib-1.1/fibtest2.out @@ -0,0 +1,37 @@ +adding: 0 1 +adding: 0 2 +adding: 0 3 +adding: 0 4 +adding: 0 5 +adding: 0 6 +adding: 0 7 +adding: 0 8 +adding: 0 9 + +wert(minkey) -38 +Knoten: 1 + +Wert(minkey) -56 +Knoten: 5 + +Wert(minkey) -102 +Knoten: 2 + +Wert(minkey) -74 +Knoten: 3 + +Wert(minkey) -99 +Knoten: 7 + +Wert(minkey) -94 +Knoten: 8 + +Wert(minkey) -4 +Knoten: 6 + +Wert(minkey) -4 +Knoten: 4 + +Wert(minkey) -2 +Knoten: 9 + diff --git a/fib-1.1/tt.c b/fib-1.1/tt.c new file mode 100644 index 00000000..26db1d2c --- /dev/null +++ b/fib-1.1/tt.c @@ -0,0 +1,64 @@ +#include +#include +#include "fib.h" + +int main(void) +{ + + struct fibheap *a; + void *arr[10]; + int i; + + a = fh_makekeyheap(); + + for (i=1 ; i < 8 ; i++) + { + arr[i]= fh_insertkey(a,0,(void *)i); + printf("adding: 0 %d \n",i); + } + + printf(" \n"); + + fh_replacekey(a, arr[1],-2); + fh_replacekey(a, arr[4],-3); + fh_replacekey(a, arr[7],-5); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[3],-2); + fh_replacekey(a, arr[6],-1); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[1],-9); + fh_replacekey(a, arr[5],-3); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[2],-4); + fh_replacekey(a, arr[5],-5); + fh_replacekey(a, arr[6],-3); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_replacekey(a, arr[2],-6); + fh_replacekey(a, arr[6],-6); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + printf("Wert(minkey) %d\n",fh_minkey(a)); + printf("Knoten: %d\n\n", (int)fh_extractmin(a)); + + fh_deleteheap(a); + + return 0; +} + diff --git a/fib-1.1/tt.out b/fib-1.1/tt.out new file mode 100644 index 00000000..37a8a47c --- /dev/null +++ b/fib-1.1/tt.out @@ -0,0 +1,29 @@ +adding: 0 1 +adding: 0 2 +adding: 0 3 +adding: 0 4 +adding: 0 5 +adding: 0 6 +adding: 0 7 + +Wert(minkey) -5 +Knoten: 7 + +Wert(minkey) -3 +Knoten: 4 + +Wert(minkey) -9 +Knoten: 1 + +Wert(minkey) -5 +Knoten: 5 + +Wert(minkey) -6 +Knoten: 6 + +Wert(minkey) -6 +Knoten: 2 + +Wert(minkey) -2 +Knoten: 3 + diff --git a/fib-1.1/use.c b/fib-1.1/use.c new file mode 100644 index 00000000..e8db3279 --- /dev/null +++ b/fib-1.1/use.c @@ -0,0 +1,126 @@ +#include +#include +#include + +#include "fib.h" + +#define TESTCASE 1 + +#define COUNT 100000 +#define DIF 1000 +#define MAXEXT 10 +#define VERBOSE 1 + +int cmp(void *, void *); + +int +cmp(void *x, void *y) +{ + int a, b; + a = (int)x; + b = (int)y; + + if (a < b) + return -1; + if (a == b) + return 0; + return 1; +} + +int +main(void) +{ +#if !TESTCASE + struct fibheap_el *w; +#else + int e, j, k; +#endif + struct fibheap *a; + int i, x; + + a = fh_makeheap(); + fh_setcmp(a, cmp); + + srandom(time(NULL)); +#if TESTCASE +#if VERBOSE + printf("inserting: "); +#endif + e = 0; + for (i = 0; i < COUNT; i++) { +#if VERBOSE + if (i) + printf(", "); +#endif + fh_insert(a, (void *)(x = random()/10)); +#if VERBOSE + printf("%d", x); +#endif + if (i - e > DIF) { + k = random() % MAXEXT; + for (j = 0; j < k; j++, e++) + printf("throwing: %d\n", (int)fh_extractmin(a)); + } + } + +#if VERBOSE + printf("\nremaining: %d\n", COUNT - e); + printf("extracting: "); +#endif + for (i = 0; i < COUNT - e; i++) { +#if VERBOSE + if (i) + printf(", "); + printf("%d", (int)fh_extractmin(a)); +#else + fh_extractmin(a); +#endif + } +#if VERBOSE + printf("\n"); +#endif + if ((int)fh_extractmin(a) == 0) + printf("heap empty!\n"); + else { + printf("heap not empty! ERROR!\n"); + exit(1); + } +#else + w = fh_insert(a, (void *)6); + printf("adding: %d\n", 6); + fh_insert(a, (void *)9); + printf("adding: %d\n", 9); + fh_insert(a, (void *)1); + printf("adding: %d\n", 1); + for(i = 0; i < 5; i++) { + x = random()/10000; + printf("adding: %d\n", x); + fh_insert(a, (void *)x); + } + fh_insert(a, (void *)4); + printf("adding: %d\n", 4); + fh_insert(a, (void *)8); + printf("adding: %d\n", 8); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("deleting: %d\n", (int)fh_delete(a, w)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + for(i = 0; i < 5; i++) { + x = random()/10000; + printf("adding: %d\n", x); + fh_insert(a, (void *)x); + } + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); + printf("first: %d\n", (int)fh_extractmin(a)); +#endif + + fh_deleteheap(a); + + return 0; +} diff --git a/file.c b/file.c new file mode 100644 index 00000000..2389d8a7 --- /dev/null +++ b/file.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "file.h" + +struct file * +file_create(char *name) +{ + int fd; + struct stat stat; + struct file *file=malloc(sizeof(*file)+strlen(name)+1); + + if (! file) + return file; + fd=open(name, O_RDONLY); + if (fd < 0) { + free(file); + return NULL; + } + fstat(fd, &stat); + file->size=stat.st_size; + file->name=(char *)file+sizeof(*file); + strcpy(file->name, name); + file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + g_assert(file->begin != NULL); + if (file->begin == (void *)0xffffffff) { + perror("mmap"); + } + g_assert(file->begin != (void *)0xffffffff); + file->end=file->begin+file->size; + file->private=NULL; + close(fd); + + g_assert(file != NULL); + return file; +} + +void +file_set_readonly(struct file *file) +{ + mprotect(file->begin, file->end-file->begin, PROT_READ); +} + +void * +file_opendir(char *dir) +{ + return opendir(dir); +} + +char * +file_readdir(void *hnd) +{ + struct dirent *ent; + + ent=readdir(hnd); + if (! ent) + return NULL; + return ent->d_name; +} + +void +file_closedir(void *hnd) +{ + closedir(hnd); +} + +struct file * +file_create_caseinsensitive(char *name) +{ + char dirname[strlen(name)+1]; + char *filename; + char *p; + void *d; + struct file *ret; + + ret=file_create(name); + if (ret) + return ret; + + strcpy(dirname, name); + p=dirname+strlen(name); + while (p > dirname) { + if (*p == '/') + break; + p--; + } + *p=0; + d=file_opendir(dirname); + if (d) { + *p++='/'; + while ((filename=file_readdir(d))) { + if (!strcasecmp(filename, p)) { + strcpy(p, filename); + ret=file_create(dirname); + if (ret) + break; + } + } + file_closedir(d); + } + return ret; +} + +void +file_destroy(struct file *f) +{ + munmap(f->begin, f->size); + free(f); +} + +int +file_get_param(struct file *file, struct param_list *param, int count) +{ + int i=count; + param_add_string("Filename", file->name, ¶m, &count); + param_add_hex("Size", file->size, ¶m, &count); + return i-count; +} diff --git a/file.h b/file.h new file mode 100644 index 00000000..4dedb894 --- /dev/null +++ b/file.h @@ -0,0 +1,18 @@ +#include "param.h" + +struct file { + unsigned char *begin; + unsigned char *end; + unsigned long size; + char *name; + void *private; +}; + +struct file *file_create(char *name); +void file_set_readonly(struct file *file); +struct file *file_create_caseinsensitive(char *name); +int file_get_param(struct file *file, struct param_list *param, int count); +void file_destroy(struct file *f); +void *file_opendir(char *dir); +char *file_readdir(void *hnd); +void file_closedir(void *hnd); diff --git a/graphics.c b/graphics.c new file mode 100644 index 00000000..8787e05e --- /dev/null +++ b/graphics.c @@ -0,0 +1,401 @@ +#include +#include "string.h" +#include "draw_info.h" +#include "graphics.h" +#include "map_data.h" +#include "coord.h" +#include "param.h" /* FIXME */ +#include "block.h" /* FIXME */ +#include "poly.h" +#include "town.h" +#include "street.h" +#include "transform.h" +#include "container.h" + + +#define GC_BACKGROUND 0 +#define GC_WOOD 1 +#define GC_TOWN_FILL 2 +#define GC_TOWN_LINE 3 +#define GC_WATER_FILL 4 +#define GC_WATER_LINE 5 +#define GC_RAIL 6 +#define GC_TEXT_FG 7 +#define GC_TEXT_BG 8 +#define GC_BLACK 9 +#define GC_STREET_SMALL 10 +#define GC_STREET_SMALL_B 11 +#define GC_PARK 12 +#define GC_BUILDING 13 +#define GC_BUILDING_2 14 +#define GC_STREET_MID 15 +#define GC_STREET_MID_B 16 +#define GC_STREET_BIG 17 +#define GC_STREET_BIG_B 18 +#define GC_STREET_BIG2 19 +#define GC_STREET_BIG2_B 20 +#define GC_STREET_BIG2_L 21 +#define GC_STREET_NO_PASS 22 +#define GC_STREET_ROUTE 23 +#define GC_LAST 24 + + +int color[][3]={ + {0xffff, 0xefef, 0xb7b7}, + {0x8e8e, 0xc7c7, 0x8d8d}, + {0xffff, 0xc8c8, 0x9595}, + {0xebeb, 0xb4b4, 0x8181}, + {0x8282, 0xc8c8, 0xeaea}, + {0x5050, 0x9696, 0xb8b8}, + {0x8080, 0x8080, 0x8080}, + {0x0, 0x0, 0x0}, + {0xffff, 0xffff, 0xffff}, + {0x0, 0x0, 0x0}, + {0xffff, 0xffff, 0xffff}, + {0xe0e0, 0xe0e0, 0xe0e0}, + {0x7c7c, 0xc3c3, 0x3434}, + {0xe6e6, 0xe6e6, 0xe6e6}, + {0xffff, 0x6666, 0x6666}, + {0xffff, 0xffff, 0x0a0a}, + {0xe0e0, 0xe0e0, 0xe0e0}, + {0xffff, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x0000}, + {0xffff, 0xffff, 0x0a0a}, + {0xffff, 0x0000, 0x0000}, + {0xffff, 0x0000, 0x0000}, + {0xe0e0, 0xe0e0, 0xffff}, + {0x0000, 0x0000, 0xa0a0}, +}; + +void +container_init_gra(struct container *co) +{ + struct graphics *gra=co->gra; + int i; + + gra->font=g_new0(struct graphics_font *,3); + gra->font[0]=gra->font_new(gra,140); + gra->font[1]=gra->font_new(gra,200); + gra->font[2]=gra->font_new(gra,300); + gra->gc=g_new0(struct graphics_gc *, GC_LAST); + for (i = 0 ; i < GC_LAST ; i++) { + gra->gc[i]=gra->gc_new(gra); + gra->gc_set_background(gra->gc[i], color[0][0], color[0][1], color[0][2]); + gra->gc_set_foreground(gra->gc[i], color[i][0], color[i][1], color[i][2]); + } + gra->gc_set_background(gra->gc[GC_TEXT_BG], color[7][0], color[7][1], color[7][2]); +} + +void +graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale) +{ + struct transformation *t=co->trans; + if (x) *x=t->center.x; + if (y) *y=t->center.y; + if (scale) *scale=t->scale; +} + +void +graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale) +{ + struct transformation *t=co->trans; + if (x) t->center.x=*x; + if (y) t->center.y=*y; + if (scale) t->scale=*scale; + graphics_redraw(co); +} + +void +graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, + void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) +{ + struct draw_info info; + info.co=co; + info.display=display; + info.limit=limit; + map_data_foreach(mdata, file, co->trans, limit2, func, &info); +} + +void +graphics_redraw(struct container *co) +{ + int scale=transform_get_scale(co->trans); + int i,slimit=255,tlimit=255,plimit=255; + int bw[4],w[4],t[4]; + struct display_list **disp=co->disp; + struct graphics *gra=co->gra; + +#if 0 + printf("scale=%d center=0x%lx,0x%lx mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y)); +#endif + + display_free(co->disp, display_end); + + transform_setup_source_rect(co->trans); + + gra->draw_mode(gra, draw_mode_begin); + for (i = 0 ; i < data_window_type_end; i++) { + data_window_begin(co->data_window[i]); + } + gra->gc_set_linewidth(gra->gc[GC_RAIL], 3); + + bw[0]=0; + bw[1]=0; + bw[2]=0; + bw[3]=0; + w[0]=1; + w[1]=1; + w[2]=1; + w[3]=1; + t[0]=0xf; + t[1]=0xf; + t[2]=0xf; + t[3]=0xf; + if (scale < 2) { + tlimit=0xff; + slimit=0xff; + bw[0]=17; + w[0]=15; + bw[1]=19; + w[1]=17; + bw[2]=19; + w[2]=17; + bw[3]=21; + w[3]=17; + } else if (scale < 4) { + tlimit=0xff; + slimit=0xff; + bw[0]=11; + w[0]=9; + bw[1]=13; + w[1]=11; + bw[2]=13; + w[2]=11; + bw[3]=15; + w[3]=11; + } else if (scale < 8) { + tlimit=0xff; + slimit=0xff; + bw[0]=5; + w[0]=3; + bw[1]=11; + w[1]=9; + bw[2]=11; + w[2]=9; + bw[3]=13; + w[3]=9; + t[0]=0xa; + t[1]=0xf; + } else if (scale < 16) { + tlimit=0xff; + slimit=0xff; + bw[1]=9; + w[1]=7; + bw[2]=9; + w[2]=7; + bw[3]=11; + w[3]=7; + t[0]=0x9; + t[1]=0xe; + } else if (scale < 32) { + tlimit=0xff; + slimit=0xff; + bw[1]=5; + w[1]=3; + bw[2]=5; + w[2]=3; + bw[3]=5; + w[3]=3; + t[0]=0x8; + t[1]=0xb; + } else if (scale < 64) { + tlimit=0xf; + slimit=0x6; + bw[1]=5; + w[1]=3; + bw[2]=5; + w[2]=3; + bw[3]=5; + w[3]=3; + t[0]=0x8; + t[1]=0xa; + } else if (scale < 128) { + tlimit=0xc; + slimit=0x6; + plimit=0x1e; + w[1]=3; + w[2]=3; + bw[3]=5; + w[3]=3; + t[0]=0x7; + t[1]=0xa; + } else if (scale < 256) { + tlimit=0xb; + slimit=0x5; + plimit=0x1a; + w[2]=3; + bw[3]=5; + w[3]=3; + t[0]=0x7; + t[1]=0x8; + } else if (scale < 512) { + tlimit=0x9; + slimit=0x5; + plimit=0x14; + w[1]=0; + w[2]=1; + bw[3]=3; + w[3]=1; + t[0]=0x4; + t[1]=0x7; + } else if (scale < 1024) { + tlimit=0x8; + slimit=0x4; + slimit=0x4; + plimit=0x11; + w[1]=0; + w[2]=1; + bw[3]=3; + w[3]=1; + t[0]=0x3; + t[1]=0x5; + } else if (scale < 2048) { + tlimit=0x5; + slimit=0x3; + plimit=0x10; + bw[3]=3; + w[3]=1; + t[0]=0x2; + t[1]=0x4; + } else if (scale < 4096) { + bw[3]=3; + w[3]=1; + tlimit=0x4; + slimit=0x2; + plimit=0xf; + t[0]=0x2; + t[1]=0x3; + } else if (scale < 8192) { + bw[3]=3; + w[3]=1; + tlimit=0x3; + slimit=0x2; + plimit=0xf; + t[0]=0x1; + t[1]=0x2; + } else { + bw[3]=3; + w[3]=1; + tlimit=0x2; + slimit=0x2; + plimit=0xf; + t[0]=0x1; + t[1]=0x4; + } + gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL], w[0]); + gra->gc_set_linewidth(gra->gc[GC_STREET_NO_PASS], w[0]); + gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL_B], bw[0]); + gra->gc_set_linewidth(gra->gc[GC_STREET_MID], w[1]); + gra->gc_set_linewidth(gra->gc[GC_STREET_MID_B], bw[1]); + gra->gc_set_linewidth(gra->gc[GC_STREET_BIG], w[2]); + gra->gc_set_linewidth(gra->gc[GC_STREET_BIG_B], bw[2]); + gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2], w[3]); + gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2_B], bw[3]); + gra->gc_set_linewidth(gra->gc[GC_STREET_ROUTE], w[3]+7+w[3]/2); + + profile_timer(NULL); + graphics_draw(co->map_data, file_border_ply, co, display_rail, plimit, 48, poly_draw_block); + graphics_draw(co->map_data, file_woodland_ply, co, display_wood, plimit, 48, poly_draw_block); + graphics_draw(co->map_data, file_other_ply, co, display_other, plimit, 48, poly_draw_block); + graphics_draw(co->map_data, file_town_twn, co, display_town, tlimit, 48, town_draw_block); + graphics_draw(co->map_data, file_water_ply, co, display_water, plimit, 48, poly_draw_block); + graphics_draw(co->map_data, file_sea_ply, co, display_sea, plimit, 48, poly_draw_block); + /* todo height, tunnel, bridge, street_bti ??? */ +#if 0 + graphics_draw(co->map_data, file_height_ply, co, display_other1, plimit, 48, poly_draw_block); +#endif + if (scale < 256) { + graphics_draw(co->map_data, file_rail_ply, co, display_rail, plimit, 48, poly_draw_block); + } + profile_timer("map_draw"); + plugin_call_draw(co); + profile_timer("plugin"); +#if 0 + draw_poly(map, &co->d_tunnel_ply, "Tunnel", 0, 11, plimit); +#endif + graphics_draw(co->map_data, file_street_str, co, display_street, slimit, 7, street_draw_block); + + display_draw(disp[display_sea], gra, gra->gc[GC_WATER_FILL], NULL); + display_draw(disp[display_wood], gra, gra->gc[GC_WOOD], NULL); + display_draw(disp[display_other], gra, gra->gc[GC_TOWN_FILL], gra->gc[GC_TOWN_LINE]); + display_draw(disp[display_other1], gra, gra->gc[GC_BUILDING], NULL); + display_draw(disp[display_other2], gra, gra->gc[GC_BUILDING_2], NULL); + display_draw(disp[display_other3], gra, gra->gc[GC_PARK], NULL); + display_draw(disp[display_water], gra, gra->gc[GC_WATER_FILL], gra->gc[GC_WATER_LINE]); + display_draw(disp[display_rail], gra, gra->gc[GC_RAIL], NULL); + street_route_draw(co); + display_draw(disp[display_street_route], gra, gra->gc[GC_STREET_ROUTE], NULL); + if (bw[0]) { + display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_SMALL_B], NULL); + display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL_B], NULL); + } + if (bw[1]) + display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID_B], NULL); + if (bw[2]) + display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG_B], NULL); + if (bw[3]) + display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_B], NULL); + if (w[0]) { + display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_NO_PASS], NULL); + display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL], NULL); + } + if (w[1]) + display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID], gra->gc[GC_BLACK]); + display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG], gra->gc[GC_BLACK]); + display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2], gra->gc[GC_BLACK]); + if (w[3] > 1) + display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_L], NULL); + + display_draw(disp[display_poi], gra, gra->gc[GC_BLACK], NULL); + + + profile_timer("display_draw"); + + if (scale < 2) { + display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); + display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); + } + else { + display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + } + display_labels(disp[display_street2], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + display_labels(disp[display_street3], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + + for (i = display_town+t[1] ; i < display_town+0x10 ; i++) + display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + for (i = display_town+t[0] ; i < display_town+t[1] ; i++) + display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); + for (i = display_town ; i < display_town+t[0] ; i++) + display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[2]); + + for (i = display_town ; i < display_town+0x10 ; i++) + display_draw(disp[i], gra, gra->gc[GC_BLACK], NULL); + display_draw(disp[display_bti], gra, gra->gc[GC_BLACK], NULL); + profile_timer("labels"); + gra->draw_mode(gra, draw_mode_end); + for (i = 0 ; i < data_window_type_end; i++) { + data_window_end(co->data_window[i]); + } +#if 0 + map_scrollbars_update(map); +#endif +} + +void +graphics_resize(struct container *co, int w, int h) +{ + co->trans->width=w; + co->trans->height=h; + graphics_redraw(co); +} diff --git a/graphics.h b/graphics.h new file mode 100644 index 00000000..43d583dd --- /dev/null +++ b/graphics.h @@ -0,0 +1,48 @@ + +struct point; +struct container; +struct graphics_gc; +struct graphics_font; +struct graphics_image_gra; + +struct graphics_image { + struct graphics_image *next; + struct graphics *gr; + char *name; + int height; + int width; + struct graphics_image_gra *gra; +}; + +void graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale); +void graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale); +void graphics_resize(struct container *co, int w, int h); +void graphics_redraw(struct container *co); + +enum draw_mode_num { + draw_mode_begin, draw_mode_end, draw_mode_cursor +}; + +struct graphics +{ + struct graphics_gra *gra; + struct graphics_font **font; + struct graphics_gc **gc; + + void (*draw_mode)(struct graphics *gr, enum draw_mode_num mode); + void (*draw_lines)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); + void (*draw_polygon)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); + void (*draw_rectangle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h); + void (*draw_circle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r); + void (*draw_text)(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, unsigned char *text, struct point *p, int dx, int dy); + void (*draw_image)(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img); + void (*draw_restore)(struct graphics *gr, struct point *p, int w, int h); + + struct graphics_font *(*font_new)(struct graphics *gr, int size); + struct graphics_gc *(*gc_new)(struct graphics *gr); + void (*gc_set_linewidth)(struct graphics_gc *gc, int width); + void (*gc_set_foreground)(struct graphics_gc *gc, int r, int g, int b); + void (*gc_set_background)(struct graphics_gc *gc, int r, int g, int b); + struct graphics_image *(*image_new)(struct graphics *gr, char *path); + struct graphics *(*overlay_new)(struct graphics *gr, struct point *p, int w, int h); +}; diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c new file mode 100644 index 00000000..a730cee5 --- /dev/null +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -0,0 +1,607 @@ +#define GDK_ENABLE_BROKEN +#include +#include +#include FT_FREETYPE_H +#include "point.h" +#include "coord.h" +#include "transform.h" +#include "graphics.h" +#include "statusbar.h" +#include "popup.h" +#include "container.h" + +struct graphics_gra { + GdkEventButton button_event; + int button_timeout; + GtkWidget *widget; + GdkDrawable *drawable; + GdkDrawable *background; + GdkColormap *colormap; + FT_Library library; + struct point p; + int width; + int height; + int library_init; + int visible; + struct graphics_gra *parent; + struct graphics_gra *overlays; + struct graphics_gra *next; + enum draw_mode_num mode; +}; + +struct graphics_font { + FT_Face face; +}; + +struct graphics_gc { + GdkGC *gc; + struct graphics_gra *gra; +}; + +struct graphics_image_gra { + GdkPixbuf *pixbuf; +}; + + +static struct graphics_font *font_new(struct graphics *gr, int size) +{ + char *filename="/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf"; + struct graphics_font *font=g_new(struct graphics_font, 1); + if (!gr->gra->library_init) { + FT_Init_FreeType( &gr->gra->library ); + gr->gra->library_init=1; + } + if (FT_New_Face( gr->gra->library, filename, 0, &font->face )) { + g_warning("Failed to load '%s', no labelling", filename); + g_free(font); + return NULL; + } + FT_Set_Char_Size(font->face, 0, size, 300, 300); + return font; +} + +static struct graphics_gc *gc_new(struct graphics *gr) +{ + struct graphics_gc *gc=g_new(struct graphics_gc, 1); + + gc->gc=gdk_gc_new(gr->gra->widget->window); + gc->gra=gr->gra; + return gc; +} + +static void +gc_set_linewidth(struct graphics_gc *gc, int w) +{ + gdk_gc_set_line_attributes(gc->gc, w, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); +} + +static void +gc_set_color(struct graphics_gc *gc, int r, int g, int b, int fg) +{ + GdkColor c; + c.pixel=0; + c.red=r; + c.green=g; + c.blue=b; + gdk_colormap_alloc_color(gc->gra->colormap, &c, FALSE, TRUE); + if (fg) + gdk_gc_set_foreground(gc->gc, &c); + else + gdk_gc_set_background(gc->gc, &c); +} + +static void +gc_set_foreground(struct graphics_gc *gc, int r, int g, int b) +{ + gc_set_color(gc, r, g, b, 1); +} + +static void +gc_set_background(struct graphics_gc *gc, int r, int g, int b) +{ + gc_set_color(gc, r, g, b, 0); +} + +struct graphics_image * +image_new(struct graphics *gr, char *name) +{ + GdkPixbuf *pixbuf; + struct graphics_image *ret; + + pixbuf=gdk_pixbuf_new_from_file(name, NULL); + if (! pixbuf) + return NULL; + ret=g_new0(struct graphics_image, 1); + ret->gr=gr; + ret->name=strdup(name); + ret->gra=g_new0(struct graphics_image_gra, 1); + ret->gra->pixbuf=pixbuf; + ret->width=gdk_pixbuf_get_width(ret->gra->pixbuf); + ret->height=gdk_pixbuf_get_height(ret->gra->pixbuf); + return ret; +} + +static void +draw_lines(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +{ + if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) + gdk_draw_lines(gr->gra->drawable, gc->gc, (GdkPoint *)p, count); + if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) + gdk_draw_lines(gr->gra->widget->window, gc->gc, (GdkPoint *)p, count); +} + +static void +draw_polygon(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +{ + if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) + gdk_draw_polygon(gr->gra->drawable, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) + gdk_draw_polygon(gr->gra->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); +} + +static void +draw_rectangle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h) +{ + gdk_draw_rectangle(gr->gra->drawable, gc->gc, TRUE, p->x, p->y, w, h); +} + +static void +draw_circle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r) +{ + if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) + gdk_draw_arc(gr->gra->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) + gdk_draw_arc(gr->gra->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); +} + + +struct text_glyph { + int x,y,w,h; + GdkImage *shadow; + unsigned char pixmap[0]; +}; + +struct text_render { + int x1,y1; + int x2,y2; + int x3,y3; + int x4,y4; + int glyph_count; + struct text_glyph *glyph[0]; +}; + +static GdkImage * +display_text_render_shadow(struct text_glyph *g) +{ + int mask0, mask1, mask2, x, y, w=g->w, h=g->h; + int str=(g->w+9)/8; + unsigned char *shadow; + unsigned char *p, *pm=g->pixmap; + GdkImage *ret; + + shadow=malloc(str*(g->h+2)); + memset(shadow, 0, str*(g->h+2)); + for (y = 0 ; y < h ; y++) { + p=shadow+str*y; + mask0=0x4000; + mask1=0xe000; + mask2=0x4000; + for (x = 0 ; x < w ; x++) { + if (pm[x+y*w]) { + p[0]|=(mask0 >> 8); + if (mask0 & 0xff) + p[1]|=mask0; + + p[str]|=(mask1 >> 8); + if (mask1 & 0xff) + p[str+1]|=mask1; + p[str*2]|=(mask2 >> 8); + if (mask2 & 0xff) + p[str*2+1]|=mask2; + } + mask0 >>= 1; + mask1 >>= 1; + mask2 >>= 1; + if (!((mask0 >> 8) | (mask1 >> 8) | (mask2 >> 8))) { + mask0<<=8; + mask1<<=8; + mask2<<=8; + p++; + } + } + } + ret=gdk_image_new_bitmap(gdk_visual_get_system(), shadow, g->w+2, g->h+2); + return ret; +} + +static struct text_render * +display_text_render(unsigned char *text, struct graphics_font *font, int dx, int dy, int x, int y) +{ + FT_GlyphSlot slot = font->face->glyph; // a small shortcut + FT_Matrix matrix; + FT_Vector pen; + FT_UInt glyph_index; + int n,len=strlen(text); + struct text_render *ret=malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); + struct text_glyph *curr; + + ret->glyph_count=len; + + matrix.xx = dx; + matrix.xy = dy; + matrix.yx = -dy; + matrix.yy = dx; + + pen.x = 0 * 64; + pen.y = 0 * 64; + x <<= 6; + y <<= 6; + FT_Set_Transform( font->face, &matrix, &pen ); + + + for ( n = 0; n < len; n++ ) + { + + glyph_index = FT_Get_Char_Index(font->face, text[n]); + FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT ); + FT_Render_Glyph(font->face->glyph, ft_render_mode_normal ); + + curr=malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch); + ret->glyph[n]=curr; + + curr->x=(x>>6)+slot->bitmap_left; + curr->y=(y>>6)-slot->bitmap_top; + curr->w=slot->bitmap.width; + curr->h=slot->bitmap.rows; + if (slot->bitmap.width && slot->bitmap.rows) { + memcpy(curr->pixmap, slot->bitmap.buffer, slot->bitmap.rows*slot->bitmap.pitch); + curr->shadow=display_text_render_shadow(curr); + } + else + curr->shadow=NULL; +#if 0 + printf("height=%d\n", slot->metrics.height); + printf("height2=%d\n", face->height); + printf("bbox %d %d %d %d\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax); +#endif + x += slot->advance.x; + y -= slot->advance.y; + } + return ret; +} + +static void +display_text_draw(struct text_render *text, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg) +{ + int i; + struct text_glyph *g, **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->shadow && bg) + gdk_draw_image(gr->gra->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); + } + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->w && g->h) + gdk_draw_gray_image(gr->gra->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); + } +} + +static void +display_text_free(struct text_render *text) +{ + int i; + struct text_glyph **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) { + if ((*gp)->shadow) { + gdk_image_destroy((*gp)->shadow); +#if 0 + free((*gp)->shadow->mem); +#endif + } + free(*gp++); + } + free(text); +} + +static void +draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, unsigned char *text, struct point *p, int dx, int dy) +{ + struct text_render *t; + + if (! font) + return; + if (bg) { + gdk_gc_set_function(fg->gc, GDK_AND_INVERT); + gdk_gc_set_function(bg->gc, GDK_OR); + } + + t=display_text_render(text, font, dx, dy, p->x, p->y); + display_text_draw(t, gr, fg, bg); + display_text_free(t); + if (bg) { + gdk_gc_set_function(fg->gc, GDK_COPY); + gdk_gc_set_function(bg->gc, GDK_COPY); + } +} + +static void +draw_image(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img) +{ + printf("draw_image1 \n"); + gdk_draw_pixbuf(gr->gra->drawable, fg->gc, img->gra->pixbuf, 0, 0, p->x, p->y, + img->width, img->height, GDK_RGB_DITHER_NONE, 0, 0); + printf("draw_image1 end\n"); +} + +static void +overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int window) +{ + GdkPixbuf *pixbuf,*pixbuf2; + GtkWidget *widget=parent->widget; + guchar *pixels1, *pixels2, *p1, *p2; + int x,y; + int rowstride1,rowstride2; + int n_channels1,n_channels2; + pixbuf=gdk_pixbuf_get_from_drawable(NULL, overlay->drawable, NULL, 0, 0, 0, 0, overlay->width, overlay->height); + pixbuf2=gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pixbuf), TRUE, gdk_pixbuf_get_bits_per_sample(pixbuf), + gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); + + rowstride1 = gdk_pixbuf_get_rowstride (pixbuf); + rowstride2 = gdk_pixbuf_get_rowstride (pixbuf2); + pixels1=gdk_pixbuf_get_pixels (pixbuf); + pixels2=gdk_pixbuf_get_pixels (pixbuf2); + n_channels1 = gdk_pixbuf_get_n_channels (pixbuf); + n_channels2 = gdk_pixbuf_get_n_channels (pixbuf2); + for (y = 0 ; y < overlay->height ; y++) { + for (x = 0 ; x < overlay->width ; x++) { + p1 = pixels1 + y * rowstride1 + x * n_channels1; + p2 = pixels2 + y * rowstride2 + x * n_channels2; + p2[0]=p1[0]; + p2[1]=p1[1]; + p2[2]=p1[2]; + p2[3]=127; + } + } + if (window) + gdk_draw_pixmap(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], overlay->background, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height); + else + gdk_draw_pixmap(overlay->background, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, 0, 0, overlay->width, overlay->height); + gdk_draw_pixbuf(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixbuf2, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height, GDK_RGB_DITHER_NONE, 0, 0); + if (window) + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, overlay->p.x, overlay->p.y, overlay->width, overlay->height); +#if 0 + gdk_draw_pixmap(gr->gra->drawable, + gr->gra->widget->style->fg_gc[GTK_WIDGET_STATE(gr->gra->widget)], + img->gra->drawable, + 0, 0, p->x, p->y, img->gra->width, img->gra->height); +#endif +} + +static void +draw_restore(struct graphics *gr, struct point *p, int w, int h) +{ + struct graphics_gra *gra=gr->gra; + GtkWidget *widget=gra->widget; + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gra->drawable, + p->x, p->y, p->x, p->y, w, h); + +} + +static void +draw_mode(struct graphics *gr, enum draw_mode_num mode) +{ + struct graphics_gra *gra=gr->gra; + struct graphics_gra *overlay; + GtkWidget *widget=gra->widget; + + if (mode == draw_mode_begin) { + if (! gra->parent) + gdk_draw_rectangle(gr->gra->drawable, gr->gc[0]->gc, TRUE, 0, 0, gr->gra->width, gr->gra->height); + } + if (mode == draw_mode_end && gr->gra->mode == draw_mode_begin) { + if (gra->parent) { + overlay_draw(gra->parent, gra, 1); + } else { + overlay=gra->overlays; + while (overlay) { + overlay_draw(gra, overlay, 0); + overlay=overlay->next; + } + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gra->drawable, + 0, 0, 0, 0, gra->width, gra->height); + } + } + gr->gra->mode=mode; +} + +/* Events */ + +static gint +configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) +{ + struct container *co=user_data; + struct graphics_gra *gra=co->gra->gra; + + if (! gra->visible) + return TRUE; + if (gra->drawable != NULL) { + gdk_pixmap_unref(gra->drawable); + } + gra->width=widget->allocation.width; + gra->height=widget->allocation.height; + gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1); + graphics_resize(co, gra->width, gra->height); + return TRUE; +} + +static gint +expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) +{ + struct container *co=user_data; + struct graphics *gr=co->gra; + + gr->gra->visible=1; + if (! gr->gra->drawable) + configure(widget, NULL, user_data); + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gr->gra->drawable, event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + + return FALSE; +} + +static gint +button_timeout(gpointer user_data) +{ + struct container *co=user_data; + int x=co->gra->gra->button_event.x; + int y=co->gra->gra->button_event.y; + int button=co->gra->gra->button_event.button; + + co->gra->gra->button_timeout=0; + popup(co, x, y, button); + + return FALSE; +} + +static gint +button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct container *co=user_data; + int x=event->x; + int y=event->y; + int button=event->button; + int border=16; + long map_x,map_y,scale,x_new,y_new; + + if (button == 3) + popup(co, x, y, button); + if (button == 1) { + graphics_get_view(co, &map_x, &map_y, &scale); + if (x < border) { + x_new=map_x-co->trans->width*scale/32; + graphics_set_view(co, &x_new, NULL, NULL); + } else if (x >= co->trans->width-border) { + x_new=map_x+co->trans->width*scale/32; + graphics_set_view(co, &x_new, NULL, NULL); + } else if (y < border) { + y_new=map_y+co->trans->height*scale/32; + graphics_set_view(co, NULL, &y_new, NULL); + } else if (y >= co->trans->height-border) { + y_new=map_y-co->trans->height*scale/32; + graphics_set_view(co, NULL, &y_new, NULL); + } else { + co->gra->gra->button_event=*event; + co->gra->gra->button_timeout=g_timeout_add(500, button_timeout, co); + } + } + return FALSE; +} + +static gint +button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct container *co=user_data; + if (co->gra->gra->button_timeout) + g_source_remove(co->gra->gra->button_timeout); + return FALSE; +} + +static gint +motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) +{ + struct container *co=user_data; + struct point p; + + if (co->statusbar && co->statusbar->statusbar_mouse_update) { + p.x=event->x; + p.y=event->y; + co->statusbar->statusbar_mouse_update(co->statusbar, co->trans, &p); + } + return FALSE; +} + +static struct graphics *graphics_new(void); + +static struct graphics * +overlay_new(struct graphics *gr, struct point *p, int w, int h) +{ + struct graphics *this=graphics_new(); + this->gra->drawable=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); + this->gra->colormap=gr->gra->colormap; + this->gra->widget=gr->gra->widget; + this->gra->p=*p; + this->gra->width=w; + this->gra->height=h; + this->gra->parent=gr->gra; + this->gra->background=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); + this->gra->next=gr->gra->overlays; + gr->gra->overlays=this->gra; + return this; +} + + + +static struct graphics * +graphics_new(void) +{ + struct graphics *this=g_new0(struct graphics,1); + this->draw_mode=draw_mode; + this->draw_lines=draw_lines; + this->draw_polygon=draw_polygon; + this->draw_rectangle=draw_rectangle; + this->draw_circle=draw_circle; + this->draw_text=draw_text; + this->draw_image=draw_image; + this->draw_restore=draw_restore; + this->gc_new=gc_new; + this->gc_set_linewidth=gc_set_linewidth; + this->gc_set_foreground=gc_set_foreground; + this->gc_set_background=gc_set_background; + this->font_new=font_new; + this->image_new=image_new; + this->overlay_new=overlay_new; + this->gra=g_new0(struct graphics_gra, 1); + + return this; +} + +struct graphics * +graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget) +{ + GtkWidget *draw; + + draw=gtk_drawing_area_new(); + struct graphics *this=graphics_new(); + this->gra->widget=draw; + this->gra->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); + gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); + gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), co); + gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(configure), co); +#if 0 + gtk_signal_connect(GTK_OBJECT(draw), "realize_event", GTK_SIGNAL_FUNC(realize), co); +#endif + gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(button_press), co); + gtk_signal_connect(GTK_OBJECT(draw), "button_release_event", GTK_SIGNAL_FUNC(button_release), co); + gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(motion_notify), co); + *widget=draw; + return this; +} + diff --git a/graphics/gtk_gl_ext/graphics_gtk_gl_ext.c b/graphics/gtk_gl_ext/graphics_gtk_gl_ext.c new file mode 100644 index 00000000..c91e94c6 --- /dev/null +++ b/graphics/gtk_gl_ext/graphics_gtk_gl_ext.c @@ -0,0 +1,333 @@ +#include +#include +#include +#include +#include +#include "point.h" +#include "graphics.h" +#include "container.h" + + +struct graphics_gra { + GtkWidget *widget; + int width; + int height; + int library_init; + int visible; + int buffer; +}; + +struct graphics_font { +}; + +struct graphics_gc { + double fr,fg,fb; + double br,bg,bb; + double width; + struct graphics_gra *gra; +}; + +static struct graphics_font *font_new(struct graphics *gr, int size) +{ + struct graphics_font *font=g_new(struct graphics_font, 1); + return font; +} + +static struct graphics_gc *gc_new(struct graphics *gr) +{ + struct graphics_gc *gc=g_new(struct graphics_gc, 1); + + gc->fr=1; + gc->fg=1; + gc->fb=1; + gc->br=0; + gc->bg=0; + gc->bb=0; + gc->width=1; + gc->gra=gr->gra; + return gc; +} + +static void +gc_set_linewidth(struct graphics_gc *gc, int w) +{ + gc->width=w; +} + +static void +gc_set_foreground(struct graphics_gc *gc, int r, int g, int b) +{ + gc->fr=r/65535.0; + gc->fg=g/65535.0; + gc->fb=b/65535.0; +} + +static void +gc_set_background(struct graphics_gc *gc, int r, int g, int b) +{ + gc->br=r/65535.0; + gc->bg=g/65535.0; + gc->bb=b/65535.0; +} + +static void +vertex(struct point *p) +{ + double x,y; + x=p->x; + y=p->y; + x/=792; + y/=469; + x-=0.5; + y=0.5-y; + glVertex3f(x,y,0); +} + +static void +draw_lines(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +{ + int i; + + glLineWidth(gc->width); + glColor3f(gc->fr, gc->fg, gc->fb); + glBegin(GL_LINE_STRIP); + for (i=0 ; i < count ; i++) + vertex(p++); + glEnd(); +} + +static void +draw_polygon(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +{ + int i; + double x,y; + glColor3f(gc->fr, gc->fg, gc->fb); + glBegin(GL_POLYGON); + for (i=0 ; i < count ; i++) + vertex(p++); + glEnd(); +} + + +static void +draw_circle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r) +{ + +} + +static void +draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, unsigned char *text, int x, int y, int dx, int dy) +{ +} + +static void +draw_begin(struct graphics *gr) +{ + printf("draw_begin\n"); + glClearColor(gr->gc[0]->br, gr->gc[0]->bg, gr->gc[0]->bb, 0); + glNewList(1, GL_COMPILE); + gr->gra->buffer=1; +} + +static void +draw_end(struct graphics *gr) +{ + printf("draw_end\n"); + glEndList(); + gr->gra->buffer=0; +} + +static void realize(GtkWidget * widget, gpointer data) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + + GLUquadricObj *qobj; + static GLfloat light_diffuse[] = { 1.0, 0.0, 0.0, 1.0 }; + static GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; + + /*** OpenGL BEGIN ***/ + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + return; + + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); +#if 0 + glNewList(1, GL_COMPILE); + gluSphere(qobj, 1.0, 20, 20); + glBegin(GL_LINE_STRIP); + glVertex3f(0.0,0.1,0.0); + glVertex3f(0.1,0.1,0.0); + glVertex3f(0.1,0.2,0.0); + glVertex3f(0.2,0.2,0.0); + glEnd(); + glEndList(); +#endif + +#if 0 + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); +#endif + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClearDepth(1.0); + + glViewport(0, 0, + widget->allocation.width, widget->allocation.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(19.0, 1.0, 1.0, 10.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, 0.0); + + gdk_gl_drawable_gl_end(gldrawable); + /*** OpenGL END ***/ +} + +static gboolean +configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + struct container *co=user_data; + struct graphics_gra *gra=co->gra->gra; + + + printf("configure %d %d\n",gra->width, gra->height); + gra->width=widget->allocation.width; + gra->height=widget->allocation.height; + + /*** OpenGL BEGIN ***/ + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + return FALSE; + + glViewport(0, 0, + widget->allocation.width, widget->allocation.height); + + gdk_gl_drawable_gl_end(gldrawable); + /*** OpenGL END ***/ + if (gra->visible) + graphics_resize(co, gra->width, gra->height); + + return TRUE; +} + +static gboolean +expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + struct container *co=user_data; + struct graphics_gra *gra=co->gra->gra; + + printf("expose\n"); + if (! gra->visible) { + gra->visible=1; + configure(widget, NULL, user_data); + } + /*** OpenGL BEGIN ***/ + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + return FALSE; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glCallList(1); + + if (gdk_gl_drawable_is_double_buffered(gldrawable)) + gdk_gl_drawable_swap_buffers(gldrawable); + else + glFlush(); + + gdk_gl_drawable_gl_end(gldrawable); + /*** OpenGL END ***/ + + return TRUE; +} + + +struct graphics * +graphics_gtk_gl_area_new(struct container *co, GtkWidget **widget) +{ + GdkGLConfig *glconfig; + gint major, minor; + GtkWidget *drawing_area; + + struct graphics *this=g_new0(struct graphics,1); + this->draw_lines=draw_lines; + this->draw_polygon=draw_polygon; + this->draw_circle=draw_circle; + this->draw_text=draw_text; +#if 0 + this->draw_begin=draw_begin; + this->draw_end=draw_end; +#endif + this->gc_new=gc_new; + this->gc_set_linewidth=gc_set_linewidth; + this->gc_set_foreground=gc_set_foreground; + this->gc_set_background=gc_set_background; + this->font_new=font_new; + this->gra=g_new0(struct graphics_gra, 1); + + /* + * Init GtkGLExt. + */ + + gtk_gl_init(NULL, NULL); + + /* + * Query OpenGL extension version. + */ + + gdk_gl_query_version(&major, &minor); + g_print("OpenGL extension version - %d.%d\n", major, minor); + + /* + * Configure OpenGL-capable visual. + */ + + /* Try double-buffered visual */ + glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | + GDK_GL_MODE_DEPTH | + GDK_GL_MODE_DOUBLE); + if (glconfig == NULL) { + g_print("*** Cannot find the double-buffered visual.\n"); + g_print("*** Trying single-buffered visual.\n"); + + /* Try single-buffered visual */ + glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | + GDK_GL_MODE_DEPTH); + if (glconfig == NULL) { + g_print + ("*** No appropriate OpenGL-capable visual found.\n"); + exit(1); + } + } + + + drawing_area = gtk_drawing_area_new(); + + /* Set OpenGL-capability to the widget. */ + gtk_widget_set_gl_capability(drawing_area, + glconfig, + NULL, TRUE, GDK_GL_RGBA_TYPE); + + g_signal_connect_after(G_OBJECT(drawing_area), "realize", + G_CALLBACK(realize), NULL); + g_signal_connect(G_OBJECT(drawing_area), "configure_event", + G_CALLBACK(configure), co); + g_signal_connect(G_OBJECT(drawing_area), "expose_event", + G_CALLBACK(expose), co); + + *widget=drawing_area; + this->gra->widget=drawing_area; + return this; +} + + diff --git a/gtkext.h b/gtkext.h new file mode 100644 index 00000000..34059d9b --- /dev/null +++ b/gtkext.h @@ -0,0 +1 @@ +void gdk_gc_set_fill_rule(GdkGC *gc, GdkFillRule fill_rule); diff --git a/gui/gtk/gtkeyboard.c b/gui/gtk/gtkeyboard.c new file mode 100644 index 00000000..1963c839 --- /dev/null +++ b/gui/gtk/gtkeyboard.c @@ -0,0 +1,2353 @@ +/* app.c + * For use with GTKeyboard + * written by David Allen, s2mdalle@titan.vcu.edu + * http://opop.nols.com/ + * + * #define DEBUGGING at compile time for interesting info most people don't + * want to see. + */ +/* GTKeyboard - A Graphical Keyboard For X + * Copyright (C) 1999, 2000 David Allen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The regular non-fun glib calls for distro copies of gtkeyboard. */ +# define g_new0_(t,c) g_new0(t,c) +# define g_free_(mem) g_free(mem) +# define g_new_(t,c) g_new(t,c) +# define g_strdup_(x) g_strdup(x) +# define g_malloc_(x) g_malloc(x) +# define MEM(x) ; /* Don't do anything */ + + +/* modmap.h + * Written by David Allen + * + * Released under the terms of the GNU General Public License + */ + + + + +#define slot_number_to_mask(x) (1< + * http://opop.nols.com/ + * Released under the terms of the GNU General Public License + */ + +#define MAXIMUM_ROWS 6 + +/* Abstract data types */ + +typedef struct { + KeySym lower_case; /* What happens when pressed by itself */ + KeySym upper_case; /* What happens when pressed with Shift/CL */ + KeySym alt_gr; /* Alt GR+ button -- mostly unused */ + KeyCode code; + char *aux_string; /* Cheating string holder for things that aren't + * right with XKeysymToString() -- most notably + * the F keys and the keypad keys + * This should NEVER be used in conjunction + * with foreign windows - only text insertion in + * our editing buffer + */ +} KEY; + +typedef struct { + char *tab; + char *backspace; + char *caps_lock; + char *space; + char *alt; + char *alt_gr; + char *control; + char *shift; +} KeyboardTranslation; + +typedef struct { + int row_values[MAXIMUM_ROWS]; + int keycount; + KeySym *syms; + KeyCode *codes; + KeyboardTranslation *trans; + char *name; + ModmapTable *modmap; +} KEYBOARD; + +/* Macros */ +#define NO_KEYBOARD ((KEYBOARD *)NULL) +#define NO_KEY ((KEY *)NULL) + +/* Function prototypes */ +static KEY *gtkeyboard_key_copy(KEY * key); +static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, int keyno); +static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input); +static KEYBOARD *read_keyboard_template(char *filename); +static KEY *gtkeyboard_destroy_key(KEY * input); +static KEY *gtkeyboard_new_key(const KeySym lower, + const KeySym upper, + const KeySym altgr, const char *alt); + + + +/* rc_file.h - A simple configuration file reader/writer header file + * by Patrick Gallot + * + * This file is part of GTKeyboard and as such is licensed under the terms + * of the GNU General Public License. + */ + + +/* Different types that resource file varaibles can have */ +#define RC_NONE 0x0000 +#define RC_STR 0x0002 /* String */ +#define RC_PARSE_FUNC 0x0006 /* This one means that an external + * parsing function should be used + * and the resource file code + * shouldn't bother with the values + */ +typedef struct config_var { + /* These go together to specify a line in a file that could say something + * like "set foo_variable 10" or "foobar = 20" or even + * "toolbar menubar off" + */ + + gchar *Prefix; /* This could be something like "set" or "toolbar" */ + gchar *Name; /* Element name */ + gint Type; /* Type of the value */ + gpointer Val; /* Pointer to the value to store */ + /* Function pointer for custom handling -- it should have parameters + * of the "prefix" token, (usually "set"), the variable name, the + * varaible value, and the pointer we were supposed to store it in. + * The pointer is usually going to be the same as Val above + */ + int (*func) (char *prefix, char *varname, char *val, gpointer ptr); +} RCVARS; + +static int read_ConfigFile(char *filename, RCVARS * vars, int complain); + +#define CONDFREE(x) if(x){ g_free_(x); x = NULL; } + +#define FLUSH_EVERYTHING fflush(Q); fflush(stdout);\ + fflush(stderr); + +/* Toggling Defines */ +#define ON 1 +#define OFF 0 +/* Whatever the status is, FLIP IT */ +#define ISOFF(x) ( x==OFF ) + +/* In case we ever achieve portability to winblows, we can change this + * to a backslash. :) + */ +#define _DIR "/" + +#define FLUSH fflush(Q) +#define NONE NULL + +#define LEFT_MOUSE_BUTTON 1 +#define RIGHT_MOUSE_BUTTON 3 +#define MIDDLE_MOUSE_BUTTON 2 + +#define Q stderr +#define ABOUT_INFO "about.data" +#define RC_FILENAME ".gtkeyboardrc" +#define PROVIDED_RCFILE "example_configurations/defaults.gtkeyboard" +#define APPNAME "GTKeyboard" +#define CR "\n" + + + +/* adt.h + * For GTKeyboard + * written by David Allen s2mdalle@titan.vcu.edu + * http://opop.nols.com/ + * + * This file is released under the terms of the GNU General Public License. + * Please see COPYING for more details. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum number of custom colors. 10 is a good number, above that is + * really not needed per se. + */ +#define MAX_CUSTOM_COLORS 10 + +/**************************************************************************/ + +/* ADTs */ +/* Program configuration settings */ +typedef struct { + /* Changed to bits in 0.97.3 to save a little space. */ + /* Different program options - initialized in app.c changed in + * file_manip.c and messed with elsewhere. + * + * See app.c and the initialization code for comments on what they + * all mean. + */ + int REDIRECT_POLICY_IMPLICIT; + int STATUS_LOGGING; + int CAPS_LOCK; + int IGNORE_LAYOUT_FILE; + /* int ASK_REMAP_ON_EXIT; -- Deprecated for now... */ + int SHIFT; + int ALT_GR; + int NUMLOCK; + int VERBOSE; + int ALT; + int CONTROL; + int USE_KEYBOARD; + + + char *home; /* Home dir of user running the app. */ + char *tempslot; + char *extrafiles; /* Extra files, docs, default rcfile, lic. */ + char *redirect_window_name; /* Window name of redirection location. */ + char *keyboard_file; + char *cache_file; + Window redirect_window; /* Xlib window structure for redirection. */ + Window other; /* Temporary window structure for Xlib */ + + KEYBOARD *keyboard; + KEYBOARD *old_keyboard; + + /* These memory areas won't be used unless PROD isn't defined. + * When PROD isn't defined, we're not debugging, and they essentially + * keep track of the number of memory calls that I make. See also + * mem_header.h for a full definition of how they're used. + */ +#if defined(GTKEYBOARD_MEMORY_DEBUGGING) || defined(DEBUGGING) + long MEM; /* Number of bytes allocated */ + int gnew; /* Number of gnew() calls (alloc) */ + int gnew0; /* Number of gnew0() calls (alloc) */ + int gmalloc; /* Number of g_malloc() calls (alloc) */ + int gstrdup; /* Number of g_strdup() calls (alloc) */ + int gfree; /* Number of g_free() calls (free) */ +#endif +} GTKeyboardOptions; + +typedef struct { + GtkWidget *keyboard; + gint show_keyboard; +} GTKeyboardKeyboardElements; + +typedef struct { + int keyboard; +} GTKeyboardElements; + +/****************************************************************************/ + +typedef struct { + Window xwindow; /* So we can play with xlib. (our window) */ + GtkWidget *KEYBOARD; /* Container containing all keyb elements */ + + + GTKeyboardKeyboardElements keyboard_elements; + + /* If a field has a comment of "Cleaned" next to it, then it is + * either deallocated or destroyed in + * callbacks.c:gtkeyboard_mem_cleanup() via macro calls. + */ + char *custom_colors[MAX_CUSTOM_COLORS]; /* Cleaned */ + gchar *fontname; /* Cleaned */ + gchar *kfontname; /* Cleaned */ + gchar *colorname; /* Cleaned */ + gdouble saved_colors[4]; + + GtkShadowType SHADOW_TYPE; + GtkPositionType PULLOFFS_SIDE; + + GtkItemFactory *item_factory; /* Cleaned */ + GtkWidget *popup_menu; /* Cleaned */ + GdkCursor *cursor; + GtkStyle *style; + + /* Style referring to the main output text area */ + GtkStyle *textstyle; /* Cleaned */ + + /* The default GTK style */ + GtkStyle *deflt; /* Cleaned */ + + GdkFont *font; /* Cleaned */ + + /* The keyboard widget's style */ + GtkStyle *kstyle; /* Cleaned */ + + /* Keyboard font */ + GdkFont *kfont; /* Cleaned */ + + GtkTooltips *tooltips; +} GTKeyboardGUI; + +/**************************************************************************/ + +typedef struct { + int width; + int height; + int x; + int y; +} window_dimensions; + + +/* file_manip.h + * + * For use with GTKeyboard + * written by David Allen s2mdalle@titan.vcu.edu + * This file is released under the terms of the GNU General Public License + */ + +#include +#include +#include +#include +#include + + +#define MAX_LINE_LENGTH 128 +#define TOKEN_SIZE 50 +#define DEFAULT_RCFILE "# Default .gtkeyboardrc file written by GTKeyboard\nkeyboard main_keyboard on\nkeyboard number_pad on\nkeyboard cursor_keys on\nkeyboard f_keys on\n\nset handlebars off\n\nset word_wrap off\nset info_popups on\nset bump_amount 15\nhide buttonbar\nset random_strlen 10\nset eyecandy off\nset redirect_policy implicit\n" + + + + +#define STAT_AND_RETURN_IF_BAD(fname, someint, statstruct) \ + if(!fname)return(0);\ + someint = stat(fname, &statstruct);\ + if(someint<0) return(0); + +/* List of strings - GTKeyboard is really looking for these when it + * reads the rcfiles. These are the options it recognizes. To the user, + * they aren't case sensitive, but here, they must ALL be specified in all caps + */ +#define OPT_KEYBOARD_FILE "KEYBOARD_FILE" + + +/* Prototypes - creeping evil */ +static void parse_user_resource_file(char *filename); +static void FILE_readline(FILE * fp, char *buffer, const int maxlen); +static int setup_default_rcfile(char *file); + +/* EOF */ + +static const char *active_window_name = "CurrentWindow"; + +static Window root; +static XEvent xev; + +/* fake_timestamp is static in irxevent.c */ +static Window find_window(Window top, char *name); +static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev); + +/* Various keyboards are included only for app.c and build_keyboard.c + * in master.h + */ + +/* Just make them all different - gets passed to build_an_entire_keyboard */ +/* Not used yet.. */ + +/* Local defines for what keys appear as */ + +/* + * Check the notes at the bottom of the page for an ASCII drawing of how the + * keyboard should look + * + * Each button is defined as a character string of two characters. The first + * is what you get when SHIFT || CAPS_LOCK > 0 and the second is the normal + * key function. This function loops through grabbing two characters at a + * time and then calling makekeybutton to set things up and map the + * callback to the key and so on. + * + * SPECIAL CASES WITHIN stuff[]: (Yes it's braindamaged) + * LL is the left cursor key + * RR is the right cursor key + * || is caps lock key + * \\ (or escaped, it's \\\\) is SHIFT key + * CC is control + * AA is alt + * +*/ + +/* PROTOTYPES - Most functions in build_keyboard.c are static and don't need + * prototypes here. + */ +static void keysym_callback(GtkWidget * emitter, gpointer data); +static void capslock_toggle(GtkWidget * w, gpointer data); +static void alt_toggle(GtkWidget * w, gpointer data); +static void alt_gr_toggle(GtkWidget * w, gpointer data); +static void control_toggle(GtkWidget * w, gpointer data); +static void shift_on(GtkWidget * w, gpointer data); + +typedef struct { + GtkStyle *style; + int mask; +} GTKeyboardStyle; + +typedef struct { + GtkWidget *dialog; + GdkColor *color; +} color_info; + +typedef struct { + long code; + char *name; +} binding; + + +/* Main program options - do not declare as static - all global */ +static GTKeyboardOptions options; +static GTKeyboardGUI GUI; +static GTKeyboardElements ELEMENTS; + + +#define NO_HANDLER 666 + +/* Static function prototypes */ +static void setup_default_opts(void); +static void setup_default_opts_other(void); + +#define INSTALL_DOC_DIR "/usr/local/share/gtkeyboard" + +int init_keyboard_stuff(char *input) +{ + char *filename; + char *homeptr; + + /* This sets the values in the structure GUI to default values. + * I'll add things for changing the default in that function later. + */ + setup_default_opts(); /* Handles the stuff in options */ + setup_default_opts_other(); + + /* Allocate the necessary memory to copy location of support files + * into */ + options.extrafiles = g_new0_(char, (strlen(INSTALL_DOC_DIR) + 3)); + sprintf(options.extrafiles, "%s%s", INSTALL_DOC_DIR, _DIR); + + options.keyboard = NO_KEYBOARD; + options.old_keyboard = NO_KEYBOARD; + + /* End if */ + homeptr = getenv("HOME"); + + if (homeptr) { + options.home = g_strdup_(getenv("HOME")); + } /* End if */ + else + options.home = NULL; + + filename = + g_new0_(char, strlen(options.home) + 5 + strlen(RC_FILENAME)); + sprintf(filename, "%s%s%s", (options.home ? options.home : "/tmp"), + _DIR, RC_FILENAME); + + /* This parses ALL user preferences from ~/.gtkeyboardrc into various + * structures - the important parts of this are in rc_file.h and + * file_manip.c + */ + + parse_user_resource_file(filename); + + CONDFREE(filename); + + return (1); +} /* End init_keyboard_stuff */ + +/* This gets called once at setup to initialize all the GUI but + * non-keyboard related opts + * Shouldn't return anything or allocate any memory, it just sets + * things to "reasonable" defaults. + */ +static void setup_default_opts_other(void) +{ + /* Here's where you get to set all of the defaults for GUI structure + * members. + */ + GUI.SHADOW_TYPE = GTK_SHADOW_ETCHED_OUT; + GUI.PULLOFFS_SIDE = GTK_POS_LEFT; + GUI.cursor = (GdkCursor *) NULL; + GUI.fontname = (gchar *) NULL; + GUI.kfontname = (gchar *) NULL; + GUI.colorname = (gchar *) NULL; + GUI.textstyle = (GtkStyle *) NULL; + GUI.style = (GtkStyle *) NULL; + GUI.font = (GdkFont *) NULL; + GUI.kfont = (GdkFont *) NULL; + GUI.deflt = (GtkStyle *) NULL; + GUI.xwindow = (Window) NULL; + GUI.popup_menu = (GtkWidget *) NULL; + GUI.item_factory = (GtkItemFactory *) NULL; + + GUI.keyboard_elements.show_keyboard = ON; + + GUI.keyboard_elements.keyboard = (GtkWidget *) NULL; + + return; +} /* End setup_default_opts_other */ + +/* This gets called once at startup, sets all the initial values for + * options.whatever stuff + */ +static void setup_default_opts(void) +{ + /* All screen ELEMENTS on by default */ + + ELEMENTS.keyboard = 1; + + /* Set up some default values for program parameters + * Can be changed by parse_rcfile later. Hopefully these are reasonable. + */ + options.other = (Window) NULL; + options.redirect_window = (Window) NULL; + options.home = (char *) NULL; + options.redirect_window_name = (char *) NULL; + options.tempslot = (char *) NULL; + options.keyboard_file = (char *) NULL; + + + /* options.ASK_REMAP_ON_EXIT = OFF; *//* Currently deprecated */ + options.STATUS_LOGGING = OFF; /* Save the status window */ + options.CAPS_LOCK = OFF; /* Caps lock starts at OFF */ + options.SHIFT = OFF; /* Shift starts at OFF */ + options.ALT_GR = OFF; /* Alt-GR key status */ + options.CONTROL = OFF; /* Control button at OFF */ + options.NUMLOCK = OFF; /* Numlock starts at OFF */ + options.ALT = OFF; /* Alt key starts at OFF */ + options.VERBOSE = OFF; /* Spew messages */ + options.REDIRECT_POLICY_IMPLICIT = ON; /* Default to implicit redir */ + options.IGNORE_LAYOUT_FILE = OFF; /* Dont ignore layout file */ + +} /* End setup_default_opts */ + + + +#define BUILD_KEYBOARD_C + +static char *string_special_cases(KeySym input); + +static void rotate_keyboard_definitions(KEYBOARD * new_keyboard) +{ + if (!new_keyboard) { + fprintf(stderr, + "rotate_keyboard_definitions Error: Bad keyboard.\n"); + fflush(stderr); + return; + } + + /* End if */ + /* If there is an old definition laying around, destroy it to free + * up the memory. + */ + if (options.old_keyboard) { + options.old_keyboard = + gtkeyboard_destroy_keyboard(options.old_keyboard); +#ifdef REMAPPING_DEBUGGING + fprintf(Q, "Rotated old keyboard out..."); + fflush(Q); +#endif /* REMAPPING_DEBUGGING */ + } + + /* End if */ + /* Copy the current keyboard definition to the 'old' keyboard */ + options.old_keyboard = options.keyboard; + + /* Make the argument to this function the 'current' keyboard */ + options.keyboard = new_keyboard; + +#ifdef REMAPPING_DEBUGGING + fprintf(Q, "Old keyboard is now %s, Current keyboard is now %s\n", + (options.old_keyboard ? "valid" : "dead"), + (options.keyboard ? "valid" : "dead")); + fflush(Q); +#endif /* REMAPPING_DEBUGGING */ + + return; +} /* End rotate_keyboard_definitions() */ + +/* This destroys the key attached as object data to a lot of the buttons + * when they get destroyed + */ +static void destroy_key_widget_data(GtkObject *object, gpointer data) +{ + KEY *key = (KEY *) data; + + if (!key) { + fprintf(stderr, + "GTKeyboard error (destroy_key_widget_data) "); + fprintf(stderr, "data == NULL!\n"); + fflush(stderr); + return; + } + /* End if */ + key = gtkeyboard_destroy_key(key); +} /* End destroy_key_widget_data() */ + +/* Call this for every widget that has a KEY structure as its object data + * this makes sure that when the widget is destroyed, destroy_key_widget_data + * gets called on the object data + */ +static void connect_destroy_signal(GtkWidget * widget, gpointer data) +{ +#if 0 + gtk_signal_connect_full(GTK_OBJECT(widget), + "destroy", + GTK_SIGNAL_FUNC(destroy_key_widget_data), + (GtkCallbackMarshal) + gtk_signal_default_marshaller, data, + (GtkDestroyNotify) destroy_key_widget_data, + FALSE, TRUE); +#endif + gtk_signal_connect(GTK_OBJECT(widget), + "destroy", + GTK_SIGNAL_FUNC(destroy_key_widget_data), + data); +} /* End connect_destroy_signal() */ + +static gint triple_callback(GtkWidget * emitter, GdkEvent * event, + gpointer data) +{ + KEY *k = (KEY *) data; + KEY *key = NO_KEY; + + if (!k) { + fprintf(stderr, + "GTKeyboard internal error: %s: NULL \"KEY\" arg.\n", + "(triple_callback)"); + fflush(stderr); + return TRUE; + } + /* End if */ + if (event->type == GDK_BUTTON_PRESS) { + key = gtkeyboard_key_copy(k); + + if (event->button.button == LEFT_MOUSE_BUTTON) { + /* Regular keypress, deal with it as normal */ + keysym_callback((GtkWidget *) NULL, + (gpointer) key); + key = gtkeyboard_destroy_key(key); + return TRUE; + } /* End if */ + else if (event->button.button == MIDDLE_MOUSE_BUTTON) { + KeySym lower, upper; + + /* Always generate the "Alt-GR" keysym */ + if (!key->alt_gr || key->alt_gr == NoSymbol) { + key->alt_gr = key->lower_case; + } /* End if */ + key->lower_case = key->upper_case = key->alt_gr; + + /* Not sure whether this is upper case or lower case. Try to + * find out by seeing if what XConvertCase returns is the same + * or different. + */ + XConvertCase(key->alt_gr, &lower, &upper); + + /* If upper is the same as alt_gr, then we need shift to be + * on. Otherwise leave it however it is + */ + if (key->alt_gr == upper) + options.SHIFT = ON; + + keysym_callback((GtkWidget *) NULL, + (gpointer) key); + /* Free the memory */ + key = gtkeyboard_destroy_key(key); + return TRUE; + } /* End else if */ + else if (event->button.button == RIGHT_MOUSE_BUTTON) { + /* Always generate the "uppercase" Keysym */ + key->lower_case = key->alt_gr = key->upper_case; + + options.SHIFT = ON; + + keysym_callback((GtkWidget *) NULL, + (gpointer) key); + key = gtkeyboard_destroy_key(key); + return TRUE; + } /* End if */ + else { + key = gtkeyboard_destroy_key(key); + return FALSE; + } /* End else */ + } + + /* End if */ + /* Tell calling code that we have not handled this event; pass it on. */ + return FALSE; +} /* End triple_callback() */ + +static void keysym_callback(GtkWidget * emitter, gpointer data) +{ + KEY *key = (KEY *) data; + KeySym sym; + char *keyname = (char *) NULL; + char *altkeyname = (char *) NULL; + KeySym lower = (KeySym) NULL, upper = (KeySym) NULL; + +#ifdef PARANOID_DEBUGGING + fprintf(Q, "keysym_callback(): Got (%s, %s, %s).\n", + XKeysymToString(key->lower_case), + XKeysymToString(key->upper_case), + XKeysymToString(key->alt_gr)); + fflush(Q); +#endif /* PARANOID_DEBUGGING */ + + /* Determine which of the syms in the KEY * structure to use. */ + keyname = XKeysymToString(key->lower_case); + altkeyname = XKeysymToString(key->alt_gr); + + if (options.ALT_GR) { + sym = key->alt_gr; + /* We have only three symbols, and we have to generate + * the fourth one for cyrillic letters. + */ + if (strstr(altkeyname, "Cyrillic_")) { + XConvertCase(sym, &lower, &upper); + + if (options.SHIFT || options.CAPS_LOCK) { + sym = upper; + } /* End if */ + } /* End if */ + } /* End if */ + else if (strstr(keyname, "KP")) { + if (options.NUMLOCK) + sym = key->upper_case; + else + sym = key->lower_case; + } /* End else if */ + else if (options.SHIFT) + sym = key->upper_case; + else if (options.CAPS_LOCK) { + if (isalpha((char) key->upper_case)) + sym = key->upper_case; + else + sym = key->lower_case; + } /* End else if */ + else + sym = key->lower_case; + + if (options.redirect_window_name) { + send_redirect_a_keysym(sym); + + } + /* End if */ + return; +} /* End keysym_callback() */ + +static int isspecial(KeySym input) +{ + char *ptr = XKeysymToString(input); + + if (input == NoSymbol || !ptr) + return (1); + if (strstr(ptr, "_L") || strstr(ptr, "_R")) + return (1); + if (strstr(ptr, "ontrol") || strstr(ptr, "Alt")) + return (1); + if (strstr(ptr, "ode")) + return (1); + if (strstr(ptr, "Tab") || strstr(ptr, "Lock") + || strstr(ptr, "pace")) + return (1); + + return (0); +} /* End isspecial */ + +GtkWidget *build_keyboard(GtkWidget * input, char *filename) +{ + /* NEW BUILD_KEYBOARD() */ + GtkWidget *mainbox = gtk_vbox_new(FALSE, 0); + GtkWidget *hbox = (GtkWidget *) NULL; + GtkWidget *button = (GtkWidget *) NULL; + char *name = (char *) NULL; + char *altname = (char *) NULL; + GtkWidget *align = (GtkWidget *) NULL; + char label[512]; + char tooltip_label[1024]; + char *errbuf = NULL; + char *utf8, *ptr; + int rowno; + int index; + char letter = '\0'; + char cyrletter = '\0'; + KEY *key; + KeySym s; + KeySym altlower, altupper; + + /* Create the current keyboard in a new place. -- This takes care of + * destroying our old ones for us. + */ + rotate_keyboard_definitions(read_keyboard_template(filename)); + + if (!options.keyboard) { + fprintf(stderr, "Couldn't read keyboard: Bummer.\n"); + fflush(stderr); + + errbuf = g_new0(char, strlen(filename) + 100); + sprintf(errbuf, + "Couldn't create keyboard from file:\n%s!\nCheck the file format!", + filename); + + button = gtk_button_new_with_label(errbuf); + + CONDFREE(errbuf); + + return (button); + } /* End if */ + else if (options.keyboard->keycount <= 0) { + errbuf = g_new0(char, strlen(filename) + 100); + sprintf(errbuf, + "Couldn't create keyboard from file:\n%s!\nCheck the file format!", + filename); + + button = gtk_button_new_with_label(errbuf); + CONDFREE(errbuf); + return (button); + } + /* End else if */ + for (rowno = 0; rowno < MAXIMUM_ROWS; rowno++) { + hbox = gtk_hbox_new(FALSE, 0); + align = gtk_alignment_new(0.5, 0.5, 0, 0); + + for (index = 0; + index < options.keyboard->row_values[rowno]; + index++) { + key = + gtkeyboard_keyboard_get_key(options.keyboard, + rowno, index); + + letter = (int) key->upper_case; + name = XKeysymToString(key->upper_case); + altname = XKeysymToString(key->alt_gr); + + if (key->upper_case == XK_Mode_switch || + key->lower_case == XK_Mode_switch) { + sprintf(label, " Alt Gr"); + } /* End if */ + else if (strstr(altname, "Cyrillic_")) { + /* We have only lower case letter, let us + * ask X to convert it to upper case. + */ + XConvertCase(key->alt_gr, &altlower, + &altupper); + + /* FIXME: Yes, this is totally wrong method to get + * the cyrillic letter. It just happen to to + * yield the right letter in koi8-r encoding. + */ + cyrletter = (char) altupper; + if (!isalpha(letter)) { + sprintf(label, " %c \n %c %c", + (char) key->upper_case, + (char) key->lower_case, + cyrletter); + } /* End if */ + else { + sprintf(label, " %c \n %c", + (char) key->upper_case, + cyrletter); + } /* End else */ + } /* End else if */ + else if ((isalnum(letter) || ispunct(letter)) + && (letter > 0)) { + if (!isalpha(letter)) + sprintf(label, " %c \n %c", + (char) key->upper_case, + (char) key->lower_case); + else + sprintf(label, " %c \n", + (char) key->upper_case); + } /* End if */ + else if (letter != 0) { + if (!iscntrl(letter) + && !isspecial(key->upper_case) + && letter != ' ') + sprintf(label, " %c \n %c", + (char) key->upper_case, + (char) key->lower_case); + else { + ptr = + string_special_cases(key-> + lower_case); + strncpy(label, ptr, 512); + g_free_(ptr); + } /* End else */ + } /* End else if */ + else { + ptr = + string_special_cases(key->lower_case); + strncpy(label, ptr, 512); + g_free_(ptr); + } /* End else */ + + s = key->lower_case; + +#if 0 + utf8 = + g_locale_to_utf8(label, -1, NULL, NULL, NULL); +#else + utf8=g_convert(label,-1,"utf-8","iso8859-1",NULL,NULL,NULL); +#endif + /* Make the correct key, and attach the correct signal + * function to it. Toggle/normal button/function + */ + if (s == XK_Caps_Lock || s == XK_Control_L || + s == XK_Control_R || s == XK_Alt_L || + s == XK_Alt_R || s == XK_Mode_switch) + button = + gtk_toggle_button_new_with_label(utf8); + else + button = gtk_button_new_with_label(utf8); + + g_free(utf8); + GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); + if (key->code != 0) + sprintf(tooltip_label, + "KeyCode %d:\n%s\n%s\n%s", + key->code, + XKeysymToString(key->lower_case), + XKeysymToString(key->upper_case), + XKeysymToString(key->alt_gr)); + else + sprintf(tooltip_label, + "KeyCode unknown:\n%s\n%s\n%s", + XKeysymToString(key->lower_case), + XKeysymToString(key->upper_case), + XKeysymToString(key->alt_gr)); + + switch (key->lower_case) { + case XK_Caps_Lock: + gtk_signal_connect(GTK_OBJECT(button), + "clicked", + GTK_SIGNAL_FUNC + (capslock_toggle), + input); + /* Key unused in signalling */ + key = gtkeyboard_destroy_key(key); + break; + case XK_Alt_L: + case XK_Alt_R: + gtk_signal_connect(GTK_OBJECT(button), + "clicked", + GTK_SIGNAL_FUNC + (alt_toggle), NULL); + /* Key unused in signalling */ + key = gtkeyboard_destroy_key(key); + break; + case XK_Control_L: + case XK_Control_R: + gtk_signal_connect(GTK_OBJECT(button), + "clicked", + GTK_SIGNAL_FUNC + (control_toggle), NULL); + /* Key unused in signalling */ + key = gtkeyboard_destroy_key(key); + break; + case XK_Shift_L: + case XK_Shift_R: + gtk_signal_connect(GTK_OBJECT(button), + "clicked", + GTK_SIGNAL_FUNC + (shift_on), NULL); + /* Key unused in signalling */ + key = gtkeyboard_destroy_key(key); + break; + case XK_Mode_switch: + gtk_signal_connect(GTK_OBJECT(button), + "clicked", + GTK_SIGNAL_FUNC + (alt_gr_toggle), NULL); + /* Key unused in signalling */ + key = gtkeyboard_destroy_key(key); + break; + default: + gtk_signal_connect(GTK_OBJECT(button), + "button_press_event", + GTK_SIGNAL_FUNC + (triple_callback), key); + connect_destroy_signal(button, key); + break; + } /* End switch */ + + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, + FALSE, 0); + } /* End for */ + + gtk_container_add(GTK_CONTAINER(align), hbox); + gtk_box_pack_start(GTK_BOX(mainbox), align, FALSE, FALSE, + 0); + } /* End for */ + + if (filename) { + if (options.keyboard_file) { + /* We just built a complete keyboard with this file, so save its + * name for future use. + */ + /* This weird indirect freeing and copying of the string is + * due to the fact that the filename argument to this function + * may in fact be options.keyboard_file itself, so in that + * case it wouldn't be that bright to try to free it and + * copy something that's pointing to the same location. So + * instead we copy it to an intermediate spot, free the + * original, and copy the new value back. + * + * When the value actually is options.keyboard_file, we do a + * bit of redundant work, but oh well. + */ + char *tptr; + tptr = g_strdup_(filename); + g_free_(options.keyboard_file); + options.keyboard_file = g_strdup_(tptr); + g_free_(tptr); +#if 0 + fprintf(Q, + "options.keyboard_file set to be \"%s\"\n", + options.keyboard_file); + fflush(Q); +#endif + } /* End if */ + else { + /* No need to free it - just copy */ + options.keyboard_file = g_strdup_(filename); + fprintf(Q, + "options.keyboard_file set to be \"%s\"\n", + options.keyboard_file); + fflush(Q); + } /* End else */ + } + + /* End if */ + /* gtk_widget_show_all(mainbox); */ + return (mainbox); +} /* End build_keyboard() */ + +static char *string_special_cases(KeySym input) +{ + char label[1024]; + int len, x; + char *ptr; + + if (input == XK_space) { + sprintf(label, + " \n"); + } /* End if */ + else { + /* Space out the output a bit depending on string target + * length so the buttons will look right. + */ + ptr = XKeysymToString(input); + if (strlen(ptr) > 4) + sprintf(label, " %s \n", ptr); + else + sprintf(label, " %s \n", ptr); + } /* End else */ + + len = strlen(label); + + /* Special cases */ + if (strstr(label, "Control") || strstr(label, "control")) { + strcpy(label, " Ctrl "); + } /* End if */ + else if (input == XK_Mode_switch) + strcpy(label, " Alt Gr"); + else { + /* Remove the sillyness from XK_ names from the string. */ + for (x = 0; x < len; x++) { + /* Make everything uppercase */ + label[x] = toupper(label[x]); + + /* Get rid of the _R or _L that may be there. */ + if (label[x] == '_' && + (label[x + 1] == 'R' || label[x + 1] == 'L')) { + label[x] = '\0'; + } /* End if */ + } /* End for */ + } /* End else */ + + ptr = g_strdup_(label); + + return (ptr); +} /* End string_special_cases() */ + + +#define MODE_WRITE + +/* Do not allow both MODE_WRITE and MODE_APPEND to be defined. If both are + * defined, default to MODE_WRITE. The End Of Earth As We Know It (TM) occurs + * (or maybe just a compile error) MODE_WRITE is spiffier. + */ +#ifdef MODE_APPEND +# ifdef MODE_WRITE +# undef MODE_APPEND +# endif /* MODE_WRITE */ +#endif /* MODE_APPEND */ + +#ifndef __USE_GNU +# define __USE_GNU +#endif /* __USE_GNU */ + + +static void alt_gr_toggle(GtkWidget * w, gpointer data) +{ + if (ISOFF(options.ALT_GR)) { + options.ALT_GR = ON; + } /* End if */ + else { + options.ALT_GR = OFF; + } /* End else */ +} /* End alt_gr_toggle */ + +static void control_toggle(GtkWidget * w, gpointer data) +{ + if (ISOFF(options.CONTROL)) { + options.CONTROL = ON; + } /* End if */ + else { + options.CONTROL = OFF; + } /* End else */ +} /* End control_toggle */ + +static void alt_toggle(GtkWidget * w, gpointer data) +{ + if (ISOFF(options.ALT)) { + options.ALT = ON; + } /* End if */ + else { + options.ALT = OFF; + } /* End else */ +} /* End alt_toggle */ + +static void capslock_toggle(GtkWidget * w, gpointer data) +{ + if (options.redirect_window_name) + send_redirect_a_keysym(XK_Caps_Lock); + + /* Whatever it currently is, swtich it */ + if (ISOFF(options.CAPS_LOCK)) { + options.CAPS_LOCK = ON; + } /* End if */ + else { + options.CAPS_LOCK = OFF; + } /* End else */ +} /* End capslock_toggle */ + +static void shift_on(GtkWidget * w, gpointer data) +{ + /* Turn shift on */ + options.SHIFT = ON; + +} /* End shift_on */ + +/* This parses the user resource file via read_ConfigFile. This function + * doesn't actually do much other than define all of the structures for + * parsing in one place and actually doing the function calls. This is + * where you need to tweak command options. + */ +static void parse_user_resource_file(char *filename) +{ + RCVARS rc_parse_values[] = { + {"set", OPT_KEYBOARD_FILE, RC_STR, &options.keyboard_file, + NULL}, + {NULL, NULL, RC_NONE, NULL, NULL} + }; /* End rc_parse_values */ + + if (!file_exists(filename)) { + fprintf(stderr, + "Your resource file doesn't seem to exist.\n"); + fprintf(stderr, "I'll create one for you at \"%s\"\n", + filename); + fflush(stderr); + setup_default_rcfile(filename); + } + /* End if */ + read_ConfigFile(filename, rc_parse_values, 1); +} /* End parse_user_resource_file() */ + +/* Read one line from the specified file pointer and return it as + * as a pointer to char and so on. + */ +static void FILE_readline(FILE * fp, char *buffer, const int maxlen) +{ + int index = 0; + int x; + char tmp; + + do { + x = fread(&tmp, sizeof(char), 1, fp); + if ((x == 0) || (tmp == '\n')) + buffer[index] = '\0'; /* Terminate the string with a NULL */ + else + buffer[index++] = tmp; /* Add the character */ + if (!(index < maxlen)) { + fprintf(Q, + "Error on FILE_readline: index >= maxlen\n"); + fflush(Q); + return; + } /* End if */ + } while ((x != 0) && (tmp != '\n')); + return; +} /* End FILE_readline */ + +/* Copies a default rcfile from somewhere to the input filename */ +static int setup_default_rcfile(char *file) +{ + FILE *fp; + FILE *dflt; + char buffer[1024]; + char buffer2[1024]; + + if ((fp = fopen(file, "w")) == NULL) { + fprintf(Q, "Couldn't open %s for writing - cannot create ", + file); + fprintf(Q, "default .gtkeyboardrc!\n"); + fflush(Q); + return (0); + } /* End if */ + else { + /* Try to open the distribution-provided rcfile first */ + sprintf(buffer, "%s/%s", options.extrafiles, + PROVIDED_RCFILE); + + if ((dflt = fopen(buffer, "r")) == NULL) { + /* Ok, fine, so we can't open the default one we provided + * with the distribution. We'll just give the user a really + * short and crappy one. + */ + fprintf(Q, "Couldn't open %s: %s.\n", buffer, + g_strerror(errno)); + fprintf(Q, + "Fine then! We'll try something else...\n"); + fflush(Q); + + fprintf(fp, "%s", DEFAULT_RCFILE); + fclose(fp); + fprintf(Q, + "Success writing default .gtkeyboardrc\n"); + fprintf(Q, + "You can edit it to make changes later by editing "); + fprintf(Q, "%s\n", file); + fflush(Q); + return (1); + } /* End if */ + else { + while (!feof(dflt)) { + FILE_readline(dflt, buffer2, 1024); + /* Add a newline because FILE_readline kills them off */ + fprintf(fp, "%s\n", buffer2); + } /* End while */ + + fflush(fp); + fclose(dflt); + fclose(fp); + + fprintf(Q, + "Successfully wrote .gtkeyboardrc from "); + fprintf(Q, + "default. (%s: Distribution provided)\n", + PROVIDED_RCFILE); + } /* End else */ + } /* End else */ + FLUSH_EVERYTHING; + return (1); +} /* End setup_default_rcfile */ + +static int file_exists(const char *filename) +{ + struct stat file_info; + int x; + + STAT_AND_RETURN_IF_BAD(filename, x, file_info); + + return (1); +} /* End file_exists */ + +/* seems that xfree86 computes the timestamps for events like this + * strange but it relies on the *1000-32bit-wrap-around + * if anybody knows exactly how to do it, please contact me + * returns: a timestamp for the + * constructed event + */ +static Time fake_timestamp() +{ + int tint; + struct timeval tv; + struct timezone tz; /* is not used since ages */ + gettimeofday(&tv, &tz); + tint = (int) tv.tv_sec * 1000; + tint = tint / 1000 * 1000; + tint = tint + tv.tv_usec / 1000; + return ((Time) tint); +} /* End fake_timestamp() */ + +/* in: id of the root window name of the target window + * returns: id of the target window + * called by: main + */ +static Window find_window(Window top, char *name) +{ + char *wname, *iname; + XClassHint xch; + Window *children, foo; + int revert_to_return; + unsigned int nc; + + if (!strcmp(active_window_name, name)) { + XGetInputFocus(GDK_DISPLAY(), &foo, &revert_to_return); + return (foo); + } + + /* End if */ + /* First the base case */ + if (XFetchName(GDK_DISPLAY(), top, &wname)) { + if (!strncmp(wname, name, strlen(name))) { + XFree(wname); + return (top); /* found it! */ + } + /* End if */ + XFree(wname); + } + /* End if */ + if (XGetIconName(GDK_DISPLAY(), top, &iname)) { + if (!strncmp(iname, name, strlen(name))) { + XFree(iname); + return (top); /* found it! */ + } /* End if */ + XFree(iname); + } + /* End if */ + if (XGetClassHint(GDK_DISPLAY(), top, &xch)) { + if (!strcmp(xch.res_class, name)) { + XFree(xch.res_name); + XFree(xch.res_class); + return (top); /* found it! */ + } /* End if */ + XFree(xch.res_name); + XFree(xch.res_class); + } + /* End if */ + if (!XQueryTree(GDK_DISPLAY(), top, &foo, &foo, &children, &nc) || + children == NULL) + return (0); /* no more windows here */ + + /* check all the sub windows */ + for (; nc > 0; nc--) { + top = find_window(children[nc - 1], name); + if (top) + break; /* we found it somewhere */ + } /* End for */ + + /* Free that mem! Yeehaw!!! */ + if (children) + XFree(children); + + return (top); +} /* End find_window() */ + +/* This just assigns a bunch of things to certain elements of the pointer + * that are shared no matter what type of signal GTKeyboard is sending. + * Prevents code duplication in ugly places + */ +static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev) +{ + xev->type = KeyPress; + xev->display = GDK_DISPLAY(); + xev->root = root; + xev->subwindow = None; + xev->time = fake_timestamp(); + xev->same_screen = True; + xev->state = 0; + xev->x = xev->y = xev->x_root = xev->y_root = 1; +} /* End gtkeyboard_XEvent_common_setup */ + +static int assign_keycode_from_keysym(KeySym foo, XKeyEvent * xev) +{ + unsigned long mask = 0; + char *keyname = (char *) NULL; + + keyname = XKeysymToString(foo); + xev->keycode = XKeysymToKeycode(GDK_DISPLAY(), foo); + + /* Check and assign masks. */ + if (options.SHIFT) { /* Need ShiftMask? */ + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Shift_L)); + if (!mask) { + /* WTF? Shift_L isn't mapped? OK, try Shift_R */ + mask = + find_modifier_mask(XKeysymToKeycode + (GDK_DISPLAY(), + XK_Shift_R)); + } + /* End if */ + fprintf(Q, "Shift mask: 0x%lx normal mask 0x%lx\n", mask, + (unsigned long) ShiftMask); + + /* Even if mask is actually 0 because we couldn't find the shift + * key mapped, this just won't do anything at all. + * find_modifier_mask issued a warning about not finding it, too + */ + xev->state |= mask; + options.SHIFT = 0; + } + /* End if */ + if (options.CAPS_LOCK) { /* Need LockMask? */ + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Caps_Lock)); + fprintf(Q, "Capslock mask: 0x%lx normal mask 0x%lx\n", + mask, (unsigned long) LockMask); + xev->state |= mask; /* Normally LockMask */ + } + /* End if */ + if (options.CONTROL) { /* Need ControlMask? */ + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Control_L)); + if (!mask) { + mask = + find_modifier_mask(XKeysymToKeycode + (GDK_DISPLAY(), + XK_Control_R)); + } + /* End if */ + fprintf(Q, "Control mask: 0x%lx normal mask 0x%lx\n", + mask, (unsigned long) ControlMask); + xev->state |= mask; + } + /* End if */ + if (options.ALT) { /* Need Mod1Mask? */ + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Alt_L)); + if (!mask) { + mask = + find_modifier_mask(XKeysymToKeycode + (GDK_DISPLAY(), XK_Alt_R)); + } + /* End if */ + fprintf(Q, "Alt mask: 0x%lx normal mask 0x%lx\n", + mask, (unsigned long) Mod1Mask); + xev->state |= mask; + } + /* End if */ + if (options.NUMLOCK) { + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Num_Lock)); + fprintf(Q, "Numlock: Mask 0x%lx\n", mask); + xev->state |= mask; + } + /* End if */ + if (options.ALT_GR) { + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_Mode_switch)); + fprintf(Q, "Alt_GR: Mask 0x%lx\n", mask); + xev->state |= mask; + } + /* End if */ + if (strstr(keyname, "Cyrillic_")) { /* Cyrillic? */ + mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), + XK_ISO_Group_Shift)); + /* FIXME: How do we get this mask and what does it mean? + * Seems to be XKB_Group. Default 0x2000 + */ + + xev->state |= mask; + } + + + /* End if */ + /* xev->state = xev->state | ButtonMotionMask; */ +#if 0 + fprintf(Q, "Final mask on event: %ld 0x%lx\n", + (unsigned long) xev->state, (unsigned long) xev->state); +#endif + + if (xev->keycode != 0) + return 1; + + else + return 0; +} /* End assign_keycode_from_keysym() */ + +static void keysym_sendkey(KeySym somesym, Window w) +{ + gtkeyboard_XEvent_common_setup((XKeyEvent *) & xev); + + /* assign_keycode_from_keysym() will also add in the needed + * masks. WARNING: This may change options.SHIFT and other + * bitflags in options according to whether or not they should + * change. + */ + if (!assign_keycode_from_keysym(somesym, (XKeyEvent *) & xev)) { + return; + } + /* End if */ + xev.xkey.window = w; + + /* This may produce a BadWindow error with Xlib. Bummer. + * This happens most commonly when the window that was selected to + * redirect to doesn't exist on screen anymore. + */ + gdk_error_trap_push(); /* Catch errors, hopefully */ + + XSendEvent(GDK_DISPLAY(), w, True, KeyPressMask, &xev); + + XSync(GDK_DISPLAY(), False); + + xev.type = KeyRelease; /* Start the next Event */ + /* usleep(50000); */ +#if 0 + XFlush(GDK_DISPLAY()); +#endif + xev.xkey.time = fake_timestamp(); + XSendEvent(GDK_DISPLAY(), w, True, KeyReleaseMask, &xev); + XSync(GDK_DISPLAY(), False); + +#if 0 + gdk_flush(); +#endif + + if (gdk_error_trap_pop()) { + } + /* End if */ + return; +} /* End keysym_sendkey() */ + +/* Insert KeyCode code into slot slot in the table structure. + * Returns != 0 on success, 0 on failure. Failure means that + * the table is full, or that the code you're trying to insert is 0 + */ +static int ModmapTable_insert(ModmapTable * table, KeyCode code, int slot) +{ + int x = 0; + + if ((code == (KeyCode) 0) || (slot < 0) || (slot > 8)) + /* This operation makes no sense. Return failure. */ + return 0; + + for (x = 0; x < table->max_keypermod; x++) { + /* Insert in the first available open slot + * but not in taken slots. That would be a bad idea to + * silently overwrite some of the caller's data. :) + */ + if (table->modifiers[slot].codes[x] == 0) { + table->modifiers[slot].codes[x] = code; + return 1; + } /* End if */ + } /* End for */ + + /* Fail - can't find empty slot */ + return (0); +} /* End ModmapTable_insert() */ + +static ModmapTable *ModmapTable_new(void) +{ + XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); + ModmapTable *table; + int mkpm = map->max_keypermod; + int x = 0; + int y = 0; + + XFreeModifiermap(map); + table = g_new0_(ModmapTable, 1); + table->max_keypermod = mkpm; + + for (x = 0; x < 8; x++) { + for (y = 0; y < 4; y++) { + table->modifiers[x].codes[y] = (KeyCode) 0; + } /* End for */ + } /* End for */ + + return table; +} /* End ModmapTable_new() */ + +static void ModmapTable_destroy(ModmapTable * table) +{ + g_free_(table); +} /* End ModmapTable_destroy() */ + +/* Translates a string mask name into a slot number for access to numerous + * modmap data structures. + */ +static int mask_name_to_slot_number(char *maskname) +{ + char *masks[] = { "ShiftMask", "LockMask", + "ControlMask", "Mod1Mask", + "Mod2Mask", "Mod3Mask", + "Mod4Mask", "Mod5Mask" + }; + int maskcount = 8; + int y = 0; + + for (y = 0; y < maskcount; y++) { + if (g_strcasecmp(maskname, masks[y]) == 0) + return y; + } /* End for */ + + return (-1); +} /* End mask_name_to_slot_number() */ + +static unsigned long find_modifier_mask(KeyCode code) +{ + XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); + int x = 0, y = 0; + KeyCode c = (KeyCode) NULL; + unsigned long mask = 0; + + if (code == (KeyCode) 0) { + XFreeModifiermap(map); + fprintf(Q, + "Error finding modifier mask for 0 keycode: Have you\n"); + fprintf(Q, + "actually remapped your keyboard to this layout?\n"); + return 0; + } + /* End if */ + for (x = 0; x < 8; x++) { + for (y = 0; y < map->max_keypermod; y++) { + c = map->modifiermap[x * map->max_keypermod + y]; + if (c == code) { + XFreeModifiermap(map); + mask = slot_number_to_mask(x); + fprintf(Q, + "Found modifier %d in slot (%d,%d) mask %ld 0x%lx\n", + code, x, y, mask, mask); + return mask; + } /* End if */ + } /* End for */ + } /* End for */ + + XFreeModifiermap(map); + + /* Return nothing. This is bad, but better than doing the wrong thing. */ + fprintf(Q, + "***** WARNING: find_modifier_mask failed to locate code %d\n", + code); + fflush(Q); + return 0; +} /* End find_modifier_mask() */ + + +/* Makes a NULL-terminated string that gets passed as input nothing but + * upper case characters. + * + * THIS FUNCTION MODIFIES ITS ARGUMENT + */ +static void str_toupper(char *string) +{ + int x = 0; + + while (string[x]) { /* Stop on NULL */ + string[x] = toupper(string[x]); + x++; + } /* End while */ +} /* End str_toupper() */ + +/* Passed - the filename, the set of variables to look for, (see the header + * file for the definition of that structure) and an integer - if it's 0, + * then "syntax error" messages won't be printed. Otherwise, we'll complain. + */ +static int read_ConfigFile(char *filename, RCVARS * vars, int complain) +{ + gint n = 0; + gpointer N; + FILE *rcFile; + GHashTable *H; + gchar Line[BUFSIZ], varPrefix[BUFSIZ], varName[BUFSIZ], + varVal[BUFSIZ]; + + /* if the RC file doesn't exist, don't bother doing anything else */ + if ((rcFile = fopen(filename, "r")) == NULL) { + if (complain) { + fprintf(Q, "Couldn't open %s for reading: %s\n", + filename, g_strerror(errno)); + fflush(Q); + } /* End if */ + return 1; + } + + /* End if */ + /* Create a hash table of all the variable names and their arrayindex+1 */ + H = g_hash_table_new(g_str_hash, g_str_equal); + + n = 0; + /* Hash in all of the variable names. Later when we read them in, + * we'll hash in what we read to compare it against what was in the + * table passed to us. + */ + while (vars[n].Type != RC_NONE) { + g_hash_table_insert(H, vars[n].Name, + GINT_TO_POINTER(n + 1)); + n++; + } /* End while */ + + /* read each line of the RC file */ + while (fgets(Line, BUFSIZ, rcFile) != NULL) { + /* Strip leading and trailing whitespace from the string */ + strcpy(Line, g_strstrip(Line)); + + /* Skip comments and lines too short to have useful information + * in them. This will include "blank" lines that got g_strstrip'd + * down to 0 or 1 bytes + */ + if ((strlen(Line) < 2) || Line[0] == '#') + continue; + + /* Initialize values so in case of error they will be NULL, not + * the value of the last parse. + */ + varPrefix[0] = varName[0] = varVal[0] = '\0'; + + /* grab each variable and its value (maybe). + * If prefix is specified, it tries to read the + * given prefix. + */ + if (strstr(Line, "=")) + sscanf(Line, " %s = %s\n", varName, varVal); + else + sscanf(Line, " %s %s %s\n", varPrefix, varName, + varVal); + + /* Sometimes prefix *could* be null, but if name or value is + * null, there's really nothing we can do with that string. + */ + if (!varName[0] && !varVal[0]) { + if (complain) { + fprintf(stderr, + "Error parsing line \"%s\": ", + Line); + fprintf(stderr, + "I have no idea what that line means.\n"); + fflush(stderr); + } + /* End if */ + continue; + } + + /* End if */ + /* We want the rc file to be case insensitive, but we're looking for + * all upper-case varaible names, so convert the string to all + * upper-case so it will hash in correctly. + */ + str_toupper(varName); + + /* use the hash table to find the correct array entry */ + if ((N = g_hash_table_lookup(H, varName)) == NULL) { + continue; /* but skip to the next line if can't find it. */ + } + /* End if */ + n = GPOINTER_TO_INT(N) - 1; /* convert back into an array index */ + + /* We can't necessarily match the read prefix to the requested + * prefix since the prefixes may be different and may require + * processing through the function pointer associated with the + * record + */ + + /* + * Did we see a prefix when we didn't want one? + */ + if (!vars[n].Prefix && varPrefix[0]) { + fprintf(stderr, + "Error: Bad syntax. I wasn't expecting to see "); + fprintf(stderr, "a variable prefix on \"%s\".\n", + (varName ? varName : Line)); + fprintf(stderr, "Ignoring line \"%s\"\n", Line); + fflush(stderr); + continue; + } + + /* End if */ + /* Are we supposed to run this one through a function? */ + if (vars[n].Type == RC_PARSE_FUNC) { + /* Use the outside function specified in the structure + * to parse these line elements since their grammar is + * somewhat weird + */ + if (!vars[n]. + func(varPrefix, varName, varVal, + vars[n].Val)) { + fprintf(stderr, + "There was an error parsing \"%s\"\n", + Line); + fflush(stderr); + } + /* End if */ + continue; /* Done with this line */ + } + + /* End if */ + /* We're not supposed to run this through a function -- + * based on the variable's type, set the C variable to its saved + * value + */ + switch (vars[n].Type) { + case (RC_STR): + { + char *tok; + + /* varVal is not trustworthy, find the string + * within the quotes and use that instead. + */ + if (strstr(Line, "\"")) { + tok = strtok(Line, "\""); + if (!tok) { + /* This really shouldn't happen */ + if (complain) { + fprintf(stderr, + "Parse error within \"%s\"\n", + Line); + fflush(stderr); + } /* End if */ + break; + } /* End if */ + tok = strtok(NULL, "\""); + } /* End if */ + else + tok = &varVal[0]; + + /* free the current contents of the variable */ + if (*(gchar **) (vars[n].Val)) + g_free_(*(gchar **) vars[n].Val); + + /* set the variable to its new value. */ + if (tok) { + *(gchar **) (vars[n].Val) = + g_strdup_(tok); + } /* End if */ + else + *(gchar **) (vars[n].Val) = + (char *) NULL; + break; + } /* End block */ + } /* End switch */ + } /* End while */ + + /* clean up and exit */ + g_hash_table_destroy(H); + fclose(rcFile); + return 0; +} /* End read_ConfigFile() */ + +static KEY *gtkeyboard_key_copy(KEY * key) +{ + KEY *newkey; + + if (!key) + return (NO_KEY); + + newkey = gtkeyboard_new_key(key->lower_case, + key->upper_case, + key->alt_gr, key->aux_string); + newkey->code = key->code; + return (newkey); +} /* End gtkeyboard_key_copy() */ + +/* Returns the "keyno"th key in row "row" of keyb + * This is allocated memory which must be g_free()'d later. + * This will ALWAYS return allocated memory - it just might always be + * filled with NoSymbol + */ +static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, + int keyno) +{ + KEY *foobar; + int index; + int x, findex = 0; + + foobar = gtkeyboard_new_key(NoSymbol, NoSymbol, NoSymbol, NULL); + + if (row > MAXIMUM_ROWS) { + fprintf(stderr, + "gtkeyboard_keyboard_get_key: Row out of range.\n"); + fflush(stderr); + return (foobar); + } + /* End if */ + if (!keyb) { + fprintf(stderr, + "gtkeyboard_keyboard_get_key: Null keyb.\n"); + fflush(stderr); + return (foobar); + } + /* End if */ + x = findex = 0; + + while (x < row) { + /* Add up the number of keys on all lines preceeding the one we're + * looking for + */ + findex += keyb->row_values[x]; + x++; + } /* End while */ + + index = (findex * 3) + (keyno * 3); + + if (index > ((keyb->keycount * 3) - 3)) { + fprintf(stderr, "gtkeyboard_keyboard_get_key(): "); + fprintf(stderr, + "Illegal index %d of a total keycount of %d (%d).\n", + index, keyb->keycount, ((keyb->keycount * 3) - 3)); + fflush(stderr); + return (foobar); + } + + /* End if */ + /* Three consecutive KeySyms */ + foobar->lower_case = keyb->syms[index]; + foobar->upper_case = keyb->syms[(index + 1)]; + foobar->alt_gr = keyb->syms[(index + 2)]; + foobar->aux_string = (char *) NULL; /* No auxilliary */ + + if (keyb->codes) + foobar->code = keyb->codes[(findex + keyno)]; + else + foobar->code = 0; + + return (foobar); +} /* End gtkeyboard_keyboard_get_key() */ + +static KEY *gtkeyboard_new_key(const KeySym lower, const KeySym upper, + const KeySym altgr, const char *alt) +{ + KEY *somekey = g_new0_(KEY, 1); + somekey->lower_case = lower; + somekey->upper_case = upper; + somekey->alt_gr = altgr; + somekey->code = 0; + if (alt) { + somekey->aux_string = g_strdup_(alt); + } /* End if */ + else + somekey->aux_string = NULL; + + return (somekey); +} /* End gtkeyboard_new_key() */ + +static KEY *gtkeyboard_destroy_key(KEY * input) +{ + if (!input) { + fprintf(Q, + "Error: gtkeyboard_destroy_key: NULL argument.\n"); + fflush(Q); + return (NO_KEY); + } + /* End if */ + if (input->aux_string) { + g_free_(input->aux_string); + input->aux_string = (char *) NULL; + } + /* End if */ + g_free_(input); + input = NO_KEY; /* Null pointer so it won't be reused */ + + return (NO_KEY); +} /* End gtkeyboard_destroy_key() */ + +static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input) +{ + if (!input) { + fprintf(stderr, + "gtkeyboard_destroy_keyboard: Cannot destroy NULL ptr.\n"); + fflush(stderr); + return (NO_KEYBOARD); + } + /* End if */ + if (input->syms) { + g_free_(input->syms); + input->syms = NULL; + } + /* End if */ + if (input->name) { + g_free_(input->name); + input->name = NULL; + } + /* End if */ + if (input->codes) { + g_free_(input->codes); + input->codes = NULL; + } + /* End if */ + if (input->modmap) { + ModmapTable_destroy(input->modmap); + input->modmap = (ModmapTable *) NULL; + } + /* End if */ + if (input->trans) { + CONDFREE(input->trans->space); + CONDFREE(input->trans->tab); + CONDFREE(input->trans->alt_gr); + CONDFREE(input->trans->alt); + CONDFREE(input->trans->control); + CONDFREE(input->trans->shift); + CONDFREE(input->trans->backspace); + + /* Free the parent pointer */ + CONDFREE(input->trans); + } + /* End if */ + g_free_(input); + input = NO_KEYBOARD; + + return (NO_KEYBOARD); +} /* End gtkeyboard_destroy_keyboard() */ + +static int get_valid_line(FILE * fp, char *mem, const int maxlen) +{ + mem[0] = '\0'; + + while (!feof(fp) && mem[0] == '\0') { + FILE_readline(fp, mem, maxlen); + + if (mem[0] != '\0') { + strcpy(mem, g_strstrip(mem)); + + if ((mem[0] && mem[0] == '#') + || (mem[0] && mem[0] == '!')) + mem[0] = '\0'; + } /* End if */ + } /* End while */ + + if (mem[0] == '\0') + return (0); + + else + return (1); +} /* End get_valid_line() */ + +/* Parses the contents of a keyboard description file and returns + * a corresponding KEYBOARD structure. + */ +static KEYBOARD *read_keyboard_template(char *filename) +{ + KEYBOARD *keyb = NO_KEYBOARD; + FILE *fp; + register int x = 0, y = 0; + int line_size = 1024; + int index = 0; + char linedata[line_size]; + char **tokens; + char **tofree; + char *ptr; + + if (!filename || !file_exists(filename)) { + fprintf(stderr, "Error loading keyboard file \"%s\": ", + (filename ? filename : "NULL")); + fprintf(stderr, "File doesn't exist."); + fflush(stderr); + return (NO_KEYBOARD); + } + /* End if */ + fp = fopen(filename, "r"); + + if (!fp) { + return (NO_KEYBOARD); + } + /* End if */ + linedata[0] = '\0'; + + if (!get_valid_line(fp, linedata, line_size)) { + fclose(fp); + return (NO_KEYBOARD); + } + /* End if */ + keyb = g_new0_(KEYBOARD, 1); + keyb->modmap = ModmapTable_new(); + + tofree = g_strsplit(linedata, " ", -1); + tokens = tofree; + + keyb->keycount = 0; + keyb->trans = g_new_(KeyboardTranslation, 1); + + /* Initialize it's various elements */ + keyb->trans->shift = keyb->trans->backspace = keyb->trans->space = + keyb->trans->caps_lock = keyb->trans->control = + keyb->trans->tab = keyb->trans->alt = keyb->trans->alt_gr = + (char *) NULL; + + for (x = 0; x < MAXIMUM_ROWS; x++) { + if (*tokens) + ptr = *tokens++; + else + ptr = NULL; + + if (ptr) + keyb->row_values[x] = atoi(ptr); + else { + *tokens = NULL; + keyb->row_values[x] = 0; + } /* End else */ + + keyb->keycount += keyb->row_values[x]; + } /* End for */ + + g_strfreev(tofree); + tofree = tokens = NULL; + ptr = NULL; + + /* We now know how many keys we have to allocate, how many lines to read, + * and all that good stuff. + * + * Each key must have 3 syms, (lower case, upper case, and Alt Gr) + * So allocate 3*keyb->keycount items, and read keyb->keycount lines. + */ + keyb->syms = g_new0_(KeySym, (3 * keyb->keycount)); + keyb->codes = g_new0_(KeyCode, keyb->keycount); + keyb->name = g_strdup_(filename); /* Save the name of the keyboard */ + + for (x = 0; x < keyb->keycount; x++) { + keyb->codes[x] = 0; /* Initialize that keycode since we're already + * paying the price of the loop and it needs + * to be done. + */ + + if (!get_valid_line(fp, linedata, line_size)) { + fprintf(stderr, + "Error reading file %s: Bad line %d.\n", + filename, (x + 1)); + fflush(stderr); + fflush(stderr); + keyb = gtkeyboard_destroy_keyboard(keyb); + fclose(fp); + return (NO_KEYBOARD); + } + /* End if */ + tokens = tofree = g_strsplit(linedata, " ", -1); + + for (y = 0; y < 3; y++) { + if (*tokens) + ptr = *tokens++; + else + ptr = NULL; + + index = (x * 3) + y; + + if (ptr) { + /* Translate a string into a KeySym */ + keyb->syms[index] = XStringToKeysym(ptr); + + /* Error check that KeySym */ + if (!keyb->syms[index] + || keyb->syms[index] == NoSymbol) { + keyb->syms[index] = NoSymbol; + keyb = + gtkeyboard_destroy_keyboard + (keyb); + return (NO_KEYBOARD); + } /* End if */ + } /* End if */ + else { + /* This kinda sucks */ + keyb->syms[index] = NoSymbol; + } /* End else */ + } /* End for */ + + if (ptr) { + ptr = *tokens++; + } + + /* End if */ + /* Grab the KeyCode if it's there */ + keyb->codes[x] = atoi(ptr ? ptr : "0"); + + if (ptr) { + ptr = *tokens++; + } + /* End if */ + if (ptr && strcmp(ptr, "") != 0) { +#if 0 + fprintf(Q, "Reading proposed mask \"%s\"\n", ptr); + fflush(Q); +#endif + + if (!ModmapTable_insert + (keyb->modmap, keyb->codes[x], + mask_name_to_slot_number(ptr))) { + fprintf(Q, + "*** Warning: Failed to insert %d into %d\n", + keyb->codes[x], + mask_name_to_slot_number(ptr)); + } + /* End if */ +#if 0 + fprintf(Q, "Inserted code %d in slot %d\n", + keyb->codes[x], + mask_name_to_slot_number(ptr)); + fflush(Q); +#endif + } + /* End if */ + g_strfreev(tofree); + } /* End for */ + + fclose(fp); + + return (keyb); +} /* End read_keyboard_template() */ + +static void send_redirect_a_keysym(KeySym input) +{ + Window window; + int revert_to; + + if (!options.other || options.other == (Window) NULL) { + /* SEND_TO_BOTH_WINDOWS was probably set and there wasn't + * a redirect window to send to. Let's save the time involved + * with doing all this string crap and just jump out here. + */ + return; + } + /* End if */ + if (options.other) { + /* send to window user picked */ + keysym_sendkey(input, options.other); + } /* End if */ + else { + /* default to just send the event to whatever window has the input + * focus + */ + XGetInputFocus(GDK_DISPLAY(), &window, &revert_to); + keysym_sendkey(input, window); + } /* End else */ +} /* End send_redirect_a_keysym() */ + +gint track_focus(gpointer data) +{ + Window winFocus; + Window wfcopy; + int revert_to_return; + char *winName; + + + /* find out which window currently has focus */ + XGetInputFocus(GDK_DISPLAY(), &winFocus, &revert_to_return); + wfcopy = winFocus; + + /* Return if the window is the same or if it's the program + * window or if we can't redirect to that window. + * + * If there was a previous window that was any good, stick to + * that one. + */ + if (winFocus == options.redirect_window || + winFocus == GUI.xwindow || + winFocus == None || winFocus == PointerRoot) { + return TRUE; + } + + + + /* End if */ + /* At this point, we know the window is "good" and that we want + * it's name. We're going to use it as the redirect from now on. + */ + /* set up error trapping, in case we get a BadWindow error */ + gdk_error_trap_push(); + + /* this could generate the error */ + XFetchName(GDK_DISPLAY(), winFocus, &winName); + if (!winName) + winName = "Unknown"; + + gdk_flush(); + + if (gdk_error_trap_pop()) { + /* Oops...error. Probably BadWindow */ + CONDFREE(options.redirect_window_name); + + options.redirect_window = None; /* reset focus window */ + options.other = None; + + printf + ("There was an error finding a valid redirect window.\n"); + return TRUE; /* better luck next time */ + } + + /* End if */ + /* since we made it this far, update the window_name */ + if (winName) { + CONDFREE(options.redirect_window_name); + + /* Grab the window definition */ + options.redirect_window = wfcopy; + options.other = wfcopy; + + options.redirect_window_name = g_strdup_(winName); + } /* End if */ + return TRUE; +} /* End track_focus */ diff --git a/gui/gtk/gtkeyboard.h b/gui/gtk/gtkeyboard.h new file mode 100644 index 00000000..fef9fa7a --- /dev/null +++ b/gui/gtk/gtkeyboard.h @@ -0,0 +1,3 @@ +int init_keyboard_stuff(char *input); +GtkWidget *build_keyboard(GtkWidget * input, char *filename); +gint track_focus(gpointer data); diff --git a/gui/gtk/gui_gtk.h b/gui/gtk/gui_gtk.h new file mode 100644 index 00000000..f231c2fd --- /dev/null +++ b/gui/gtk/gui_gtk.h @@ -0,0 +1,4 @@ + +struct statusbar *gui_gtk_statusbar_new(GtkWidget **widget); +struct toolbar *gui_gtk_toolbar_new(struct container *co, GtkWidget **widget); +struct menu *gui_gtk_menu_new(struct container *co, GtkWidget **widget); diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c new file mode 100644 index 00000000..8ddebf6c --- /dev/null +++ b/gui/gtk/gui_gtk_menu.c @@ -0,0 +1,430 @@ +#define GTK_ENABLE_BROKEN +#include +#include +#include +#include +#include +#include +#include "coord.h" +#include "graphics.h" +#include "data_window.h" +#include "route.h" +#include "cursor.h" +#include "command.h" +#include "transform.h" +#include "block.h" +#include "street.h" +#include "statusbar.h" +#include "destination.h" +#include "main.h" +#include "container.h" + +struct menu_gui { + struct container *co; +}; + +#include "menu.h" + +extern struct coord current_pos; + +extern struct data_window *navigation_window; + +struct destination { + struct container *co; + char *text; + struct coord pos; +}; + +static void +menu_goto_abensberg(struct container *co) +{ + co->trans->center.x=1317000; + co->trans->center.y=6235000; + co->trans->scale=2*16; + graphics_redraw(co); +} + +static void +menu_goto_regensburg(struct container *co) +{ + co->trans->center.x=(1339653+1341853)/2; + co->trans->center.y=(6272179+6269979)/2; + co->trans->scale=4*16; + graphics_redraw(co); +} + +static void +menu_goto_problem(struct container *co) +{ +#if 0 /* Crailsheim */ + map->center_x=0x112e55; + map->center_y=0x60275a; + map->scale=4*16; + map_redraw(map); + route_click(map->route, map, 697, 31); + route_click(map->route, map, 71, 503); +#endif + +#if 1 /* Abensberg */ + co->trans->center.x=1317000; + co->trans->center.y=6235000; + co->trans->scale=2*16; + graphics_redraw(co); + route_click(co->route, co, 196, 449); +#endif + +#if 1 /* Neckarsulm */ + co->trans->center.x=0xfa3ac; + co->trans->center.y=0x60289a; + co->trans->scale=2*16; + graphics_redraw(co); + route_click(co->route, co, 454, 274); + + co->trans->center.x=0x1251ac; + co->trans->center.y=0x5f5eda; + co->trans->scale=512*16; + graphics_redraw(co); +#endif + + +} + +static void +menu_window_clone(struct container *co) +{ +#if 0 + void window(int x, int y, int scale); + window(co->trans->center.x, co->trans->center.y, co->trans->scale); +#endif +} + +gboolean +menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, + GtkWidget *win) +{ + GtkWidget *text; + unsigned const char *t; + struct container *co; + + if (! strcmp(event->string,"\r")) { + text=gtk_object_get_data(GTK_OBJECT(win), "Input"); + co=gtk_object_get_data(GTK_OBJECT(win), "Container"); + t=gtk_entry_get_text(GTK_ENTRY(text)); + if (!strncmp(t,"goto ",5)) { + command_goto(co, t+5); + } + } + return TRUE; +} + + +static void +menu_window_command(struct container *co) +{ + GtkWidget *win,*entry,*text,*box; + win=gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(win), 320, 200); + gtk_window_set_title(GTK_WINDOW(win), "Command"); + entry=gtk_entry_new(); + text=gtk_text_new(NULL, NULL); + box=gtk_vbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), entry, 1, 1, 0); + gtk_box_pack_start(GTK_BOX(box), text, 1, 1, 0); + gtk_container_add(GTK_CONTAINER(win), box); + gtk_object_set_data(GTK_OBJECT(win), "Container", co); + gtk_object_set_data(GTK_OBJECT(win), "Input", entry); + gtk_object_set_data(GTK_OBJECT(win), "Output", text); + gtk_signal_connect(GTK_OBJECT(win), "key-press-event", GTK_SIGNAL_FUNC(menu_window_command_key_press), win); + gtk_widget_show_all(win); +} + +static void +menu_window_visible_blocks(struct container *co) +{ + co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); + graphics_redraw(co); +} + +static void +menu_window_visible_towns(struct container *co) +{ + co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); + graphics_redraw(co); +} + +static void +menu_window_visible_polys(struct container *co) +{ + co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); + graphics_redraw(co); +} + +static void +menu_window_visible_streets(struct container *co) +{ + co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); + graphics_redraw(co); +} + +static void +menu_window_visible_points(struct container *co) +{ + co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); + graphics_redraw(co); +} + +static void +menu_map_compare(struct container *co) +{ + char cmd[256]; + int x_min, x_max, y_min, y_max; + + x_min=co->trans->center.x-co->trans->scale/16*co->trans->width*4/10; + x_max=co->trans->center.x+co->trans->scale/16*co->trans->width*4/10; + y_min=co->trans->center.y-co->trans->scale/16*co->trans->height*4/10; + y_max=co->trans->center.y+co->trans->scale/16*co->trans->height*4/10; + sprintf(cmd, "./get_map %d %d %d %d %d %d ; xv map.xpm &", co->trans->width, co->trans->height, x_min, y_max, x_max, y_min); + system(cmd); +} + +static void +menu_map_distances(struct container *co) +{ + route_display_points(co->route, co); +} + +static void +menu_destination_selected(GtkMenuItem *item, struct destination *dest) +{ + struct container *co =dest->co; + + destination_set(co, destination_type_bookmark, dest->text, &dest->pos); +} + +static void +menu_item(struct menu *me, GtkWidget *menu, char *name, void (*func)(struct container *co)) +{ + GtkWidget *item; + item=gtk_menu_item_new_with_label(name); + gtk_menu_append (GTK_MENU(menu), item); + gtk_signal_connect_object(GTK_OBJECT(item), "activate", + GTK_SIGNAL_FUNC (func), me); +} + +int +menu_clock_update(void *data) +{ + char buffer[16]; + time_t now=time(NULL); + GtkWidget *widget=GTK_WIDGET(data); + struct tm *now_tm=localtime(&now); + + sprintf(buffer,"%02d:%02d", now_tm->tm_hour, now_tm->tm_min); + gtk_label_set_text(GTK_LABEL(widget), buffer); + gtk_timeout_add((60-now_tm->tm_sec)*1000,menu_clock_update,widget); + return FALSE; +} + +struct menu * +gui_gtk_menu_new(struct container *co, GtkWidget **widget) +{ + struct menu *this=g_new0(struct menu, 1); + + this->gui=g_new0(struct menu_gui,1); + this->gui->co=co; + + + GtkWidget *menu,*item,*menu2,*item2,*menu3,*clock; + + menu=gtk_menu_bar_new(); + item=gtk_menu_item_new_with_label("Goto"); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + { + menu2=gtk_menu_new(); + item2=gtk_menu_item_new_with_label("Abensberg"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_goto_abensberg), this); + + item2=gtk_menu_item_new_with_label("Regensburg"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_goto_regensburg), this); + item2=gtk_menu_item_new_with_label("Problem"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_goto_problem), this); + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); + + item=gtk_menu_item_new_with_label("Window"); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + { + menu2=gtk_menu_new(); + + item2=gtk_menu_item_new_with_label("Clone"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_clone), this); + + item2=gtk_menu_item_new_with_label("Command"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_command), this); + + item2=gtk_menu_item_new_with_label("Visible Blocks"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_visible_blocks), co); + + item2=gtk_menu_item_new_with_label("Visible Towns"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_visible_towns), co); + + item2=gtk_menu_item_new_with_label("Visible Polys"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_visible_polys), co); + + + item2=gtk_menu_item_new_with_label("Visible Streets"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_window_visible_streets), co); + + menu_item(this, menu2, "Visible Points", menu_window_visible_points); + + item2=gtk_menu_item_new_with_label("Exit"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (exit), this); + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); + + item=gtk_menu_item_new_with_label("Map"); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + { + menu2=gtk_menu_new(); + + item2=gtk_menu_item_new_with_label("Compare"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_map_compare), this); + + item2=gtk_menu_item_new_with_label("Distances"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_map_distances), this); + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); + + item=gtk_menu_item_new_with_label("Route"); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + { + menu2=gtk_menu_new(); + + item2=gtk_menu_item_new_with_label("Start"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (route_start), co); + + item2=gtk_menu_item_new_with_label("Trace"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (route_trace), co); + + item2=gtk_menu_item_new_with_label("Update"); + gtk_menu_append (GTK_MENU(menu2), item2); + gtk_signal_connect_object(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_route_update), this); + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); + + item=gtk_menu_item_new_with_label("Destinations"); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + menu2=gtk_menu_new(); + + item2=gtk_menu_item_new_with_label("Last Destinations"); + gtk_menu_append (GTK_MENU(menu2), item2); + menu3=gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); + + item2=gtk_menu_item_new_with_label("Address"); + gtk_menu_append (GTK_MENU(menu2), item2); + + { + FILE *file; + char buffer[8192]; + double lat,lng,lat_deg,lng_deg; + char lat_c,lng_c; + struct destination *dest; + int pos,len; + char *utf8,*text,*tok,*label; + GList *list; + + file=fopen("locations.txt","r"); + while (fgets(buffer,8192,file)) { + dest=malloc(sizeof(*dest)); + dest->co=co; + len=strlen(buffer)-1; + while (len >= 0 && buffer[len] == '\n') { + buffer[len]='\0'; + } + sscanf(buffer,"%lf %c %lf %c %n",&lat, &lat_c, &lng, &lng_c, &pos); + + lat_deg=floor(lat/100); + lat-=lat_deg*100; + lat_deg+=lat/60; + + lng_deg=floor(lng/100); + lng-=lng_deg*100; + lng_deg+=lng/60; + + transform_mercator(&lng_deg, &lat_deg, &dest->pos); + + text=buffer+pos; + dest->text=strdup(text); + item2=NULL; + menu3=menu2; + while ((tok=strtok(text,"/"))) { + list=NULL; + if (item2) { + menu3=gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); + } + list=gtk_container_get_children(GTK_CONTAINER(menu3)); + while (list) { + item2=GTK_WIDGET(list->data); + gtk_label_get(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item2))),&label); + if (!strcmp(label, tok)) { + menu3=gtk_menu_item_get_submenu(GTK_MENU_ITEM(item2)); + break; + } + list=list->next; + } + item2=NULL; + if (! list) { + utf8=g_locale_to_utf8(tok,-1,NULL,NULL,NULL); + item2=gtk_menu_item_new_with_label(utf8); + gtk_menu_append (GTK_MENU(menu3), item2); + g_free(utf8); + } + text=NULL; + } + gtk_signal_connect(GTK_OBJECT(item2), "activate", + GTK_SIGNAL_FUNC (menu_destination_selected), dest); + } + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); + + item=gtk_menu_item_new(); + clock=gtk_label_new(NULL); + gtk_menu_item_right_justify(GTK_MENU_ITEM(item)); + gtk_container_add(GTK_CONTAINER(item), clock); + gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + menu_clock_update(clock); + + *widget=menu; + return this; +} diff --git a/gui/gtk/gui_gtk_statusbar.c b/gui/gtk/gui_gtk_statusbar.c new file mode 100644 index 00000000..fa4edfa7 --- /dev/null +++ b/gui/gtk/gui_gtk_statusbar.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include "coord.h" +#include "route.h" +#include "transform.h" +#include "gui_gtk.h" + +#include "statusbar.h" + +struct statusbar_gui { + GtkWidget *hbox; + char mouse_text[128]; + GtkWidget *mouse; + char gps_text[128]; + GtkWidget *gps; + char route_text[128]; + GtkWidget *route; +}; + + +void +statusbar_destroy(struct statusbar *this) +{ + g_free(this->gui); + g_free(this); +} + +void +statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct point *p) +{ + struct coord c; + struct coord_geo g; + char buffer[128]; + + transform_reverse(tr, p, &c); + transform_lng_lat(&c, &g); + transform_geo_text(&g, buffer); + sprintf(this->gui->mouse_text,"M: %s", buffer); + gtk_label_set_text(GTK_LABEL(this->gui->mouse), this->gui->mouse_text); +} + +void +statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) +{ + char lat_c='N'; + char lng_c='E'; + char *dirs[]={"N","NO","O","SO","S","SW","W","NW","N"}; + char *dir; + char *utf8; + int dir_idx; + + if (lng < 0) { + lng=-lng; + lng_c='W'; + } + if (lat < 0) { + lat=-lat; + lat_c='S'; + } + dir_idx=(direction+22.5)/45; + dir=dirs[dir_idx]; + sprintf(this->gui->gps_text,"GPS %2d/%1d %02.0f%07.4f%c %03.0f%07.4f%c %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c, height, direction, dir, speed); + utf8=g_locale_to_utf8(this->gui->gps_text,-1,NULL,NULL,NULL); + gtk_label_set_text(GTK_LABEL(this->gui->gps), utf8); + g_free(utf8); + +} + +void +statusbar_route_update(struct statusbar *this, struct route *route) +{ + struct tm *eta_tm; + double route_len; + + eta_tm=route_get_eta(route); + route_len=route_get_len(route); + + sprintf(this->gui->route_text,"Route %4.0fkm %02d:%02d ETA",route_len/1000, eta_tm->tm_hour, eta_tm->tm_min); + gtk_label_set_text(GTK_LABEL(this->gui->route), this->gui->route_text); +} + +struct statusbar * +gui_gtk_statusbar_new(GtkWidget **widget) +{ + struct statusbar *this=g_new0(struct statusbar, 1); + char *utf8; + + this->gui=g_new0(struct statusbar_gui,1); + this->statusbar_destroy=statusbar_destroy; + this->statusbar_mouse_update=statusbar_mouse_update; + this->statusbar_route_update=statusbar_route_update; + this->statusbar_gps_update=statusbar_gps_update; + + this->gui->hbox=gtk_hbox_new(FALSE, 1); + this->gui->mouse=gtk_label_new("M: 0000.0000N 00000.0000E"); + gtk_label_set_justify(GTK_LABEL(this->gui->mouse), GTK_JUSTIFY_LEFT); + utf8=g_locale_to_utf8("GPS 00/0 0000.0000N 00000.0000E 0000m 000°NO 000km/h",-1,NULL,NULL,NULL); + this->gui->gps=gtk_label_new(utf8); + g_free(utf8); + gtk_label_set_justify(GTK_LABEL(this->gui->gps), GTK_JUSTIFY_LEFT); + this->gui->route=gtk_label_new("Route 0000km 0+00:00 ETA"); + gtk_label_set_justify(GTK_LABEL(this->gui->route), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->mouse, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->gps, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->route, TRUE, TRUE, 2); + + *widget=this->gui->hbox; + return this; +} + diff --git a/gui/gtk/gui_gtk_toolbar.c b/gui/gtk/gui_gtk_toolbar.c new file mode 100644 index 00000000..420c93ba --- /dev/null +++ b/gui/gtk/gui_gtk_toolbar.c @@ -0,0 +1,349 @@ +#include +#include "graphics.h" +#include "gui_gtk.h" +#include "menu.h" +#include "coord.h" +#include "destination.h" +#include "container.h" + +struct toolbar_gui { + struct container *co; +}; + +#include "toolbar.h" + +static void +zoom_in(GtkWidget *w, struct toolbar *tb) +{ + unsigned long scale; + graphics_get_view(tb->gui->co, NULL, NULL, &scale); + scale/=2; + if (scale < 1) + scale=1; + graphics_set_view(tb->gui->co, NULL, NULL, &scale); +} + +static void +zoom_out(GtkWidget *w, struct toolbar *tb) +{ + unsigned long scale; + graphics_get_view(tb->gui->co, NULL, NULL, &scale); + scale*=2; + graphics_set_view(tb->gui->co, NULL, NULL, &scale); +} + +static void +refresh_route(GtkWidget *w, struct toolbar *tb) +{ + menu_route_update(tb->gui->co); +} + +static void +track(GtkWidget *w, struct toolbar *tb) +{ + if (tb->gui->co->flags->track) { + tb->gui->co->flags->track=0; + gtk_widget_set_state(w, GTK_STATE_ACTIVE); + } else { + tb->gui->co->flags->track=1; + gtk_widget_set_state(w, GTK_STATE_ACTIVE); + } +} + +static void +orient_north(GtkWidget *w, struct toolbar *tb) +{ + if (tb->gui->co->flags->orient_north) { + tb->gui->co->flags->orient_north=0; + gtk_widget_set_state(w, GTK_STATE_ACTIVE); + } else { + tb->gui->co->flags->orient_north=1; + gtk_widget_set_state(w, GTK_STATE_ACTIVE); + } +} + +static void +destination(GtkWidget *w, struct toolbar *tb) +{ + destination_address(tb->gui->co); +} + + +/* XPM */ +/* Drawn by Mark Donohoe for the K Desktop Environment */ +/* See http://www.kde.org */ +static char*viewmag_plus_xpm[]={ +"22 22 5 1", +"# c #000000", +"c c #a0a0a4", +"a c #dcdcdc", +"b c #ffffff", +". c None", +"......................", +"......................", +"......................", +"......................", +"......................", +".......####...........", +"......#abba#..........", +".....#abcbba#.........", +".....#bcbbbb#.........", +".....#bbbbbb#.........", +".....#abbbba#.........", +"......#abba##.........", +".......#######........", +"............###.......", +".....#.......###......", +".....#........###.....", +"...#####.......##.....", +".....#................", +".....#................", +"......................", +"......................", +"......................"}; + + +/* XPM */ +/* Drawn by Mark Donohoe for the K Desktop Environment */ +/* See http://www.kde.org */ +static char*viewmag_minus_xpm[]={ +"22 22 5 1", +"# c #000000", +"c c #a0a0a4", +"a c #dcdcdc", +"b c #ffffff", +". c None", +"......................", +"......................", +"......................", +"......................", +"......................", +".......####...........", +"......#abba#..........", +".....#abcbba#.........", +".....#bcbbbb#.........", +".....#bbbbbb#.........", +".....#abbbba#.........", +"......#abba##.........", +".......#######........", +"............###.......", +".............###......", +"..............###.....", +"...#####.......##.....", +"......................", +"......................", +"......................", +"......................", +"......................"}; + + +/* XPM */ +/* Drawn by Mark Donohoe for the K Desktop Environment */ +/* See http://www.kde.org */ +static char*reload_xpm[]={ +"22 22 3 1", +"# c #808080", +"a c #000000", +". c None", +"......................", +"......................", +"......................", +"......................", +"........##aaa#........", +".......#aaaaaaa.......", +"......#aa#....#a......", +"......aa#.............", +".....aaa.......a......", +"...aaaaaaa....aaa.....", +"....aaaaa....aaaaa....", +".....aaa....aaaaaaa...", +"......a.......aaa.....", +".............#aa......", +"......a#....#aa#......", +".......aaaaaaa#.......", +"........#aaa##........", +"......................", +"......................", +"......................", +"......................", +"......................"}; + + +/* XPM */ +static char * cursor_xpm[] = { +"22 22 2 1", +" c None", +". c #0000FF", +" ", +" ", +" ", +" .. ", +" .. .. ", +" .. .. ", +" . . ", +" . . ", +" . ... . ", +" . ... . . ", +" . ... . . ", +" . .. . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" .. .. ", +" .. .. ", +" .. ", +" ", +" ", +" "}; + + +/* XPM */ +static char * north_xpm[] = { +"22 22 2 1", +" c None", +". c #000000", +" ", +" ", +" . ", +" ... ", +" . . . ", +" . . . ", +" . ", +" .... . .... ", +" .... . .... ", +" .... . .. ", +" .. .. .. ", +" .. .. .. ", +" .. .. .. ", +" .. .. .. ", +" .. . .... ", +" .... . .... ", +" .... . .... ", +" . ", +" . ", +" . ", +" ", +" "}; + + +/* XPM */ +static char * flag_xpm[] = { +"22 22 2 1", +" c None", +"+ c #000000", +"+++++++ ", +"+ +++++++++ ", +"+ +++ +++++++++ ", +"+ +++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ + ", +"+ ++++++ +++ + ", +"+ +++ ++++++ + ", +"+ +++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ ", +"++++++++++ +++ + ", +"+ +++++++++ + ", +"+ ++++++ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ "}; + +static GtkWidget * +xpm_to_widget(GtkWidget *draw, gchar **xpm_data) +{ + /* GtkWidget is the storage type for widgets */ + GtkWidget *pixmapwid; + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkStyle *style; + + style = gtk_widget_get_style(draw); + + /* In order for this to not create a warning, window has to be a + * gtk_realize_widget (realized) widget + */ + pixmap = gdk_pixmap_create_from_xpm_d(draw->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **)xpm_data ); + + /* a pixmap widget to contain the pixmap */ + pixmapwid = gtk_pixmap_new(pixmap, mask); + gtk_widget_show(pixmapwid); + + return(pixmapwid); +} + +static void +toolbar_button_leave (GtkButton *button, gpointer status) +{ + int *st=status,new_state=GTK_STATE_NORMAL; + g_return_if_fail (button != NULL); + g_return_if_fail (GTK_IS_BUTTON (button)); + + if (*st) + new_state=GTK_STATE_ACTIVE; + if (GTK_WIDGET_STATE (button) != new_state) + { + gtk_widget_set_state (GTK_WIDGET (button), new_state); + gtk_widget_queue_draw (GTK_WIDGET (button)); + } +} + +int tst_stat=1; + +void +toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data) +{ + GtkWidget *icon; + icon=xpm_to_widget(window, icon_data); + gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, text, NULL, icon, GTK_SIGNAL_FUNC(func), data); +} + +void +toolbar_button_toggle(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data, int *flag) +{ + GtkWidget *icon,*item; + icon=xpm_to_widget(window, icon_data); + item=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, text, NULL, icon, GTK_SIGNAL_FUNC(func), data); + if (*flag) + gtk_widget_set_state(item, GTK_STATE_ACTIVE); + gtk_signal_connect(GTK_OBJECT(item), "leave", GTK_SIGNAL_FUNC(toolbar_button_leave), flag); +} + + +struct toolbar * +gui_gtk_toolbar_new(struct container *co, GtkWidget **widget) +{ + GtkWidget *toolbar,*window; + struct toolbar *this=g_new0(struct toolbar, 1); + + this->gui=g_new0(struct toolbar_gui, 1); + this->gui->co=co; + + toolbar=gtk_toolbar_new(); + gtk_toolbar_prepend_space(GTK_TOOLBAR(toolbar)); + gtk_toolbar_prepend_space(GTK_TOOLBAR(toolbar)); + + window=(GtkWidget *)(co->win); + + co->flags->track=1; + co->flags->orient_north=1; + + toolbar_button(window, toolbar, viewmag_plus_xpm, "Zoom In", zoom_in, this); + toolbar_button(window, toolbar, viewmag_minus_xpm, "Zoom Out", zoom_out, this); + toolbar_button(window, toolbar, reload_xpm, "Refresh Route", refresh_route, this); + toolbar_button_toggle(window, toolbar, cursor_xpm, "Cursor on/off", track, this, &co->flags->track); + toolbar_button_toggle(window, toolbar, north_xpm, "Orientate North on/off", orient_north, this, &co->flags->orient_north); + toolbar_button(window, toolbar, flag_xpm, "Destination", destination, this); + + *widget=toolbar; + + return this; +} diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c new file mode 100644 index 00000000..40ddddb1 --- /dev/null +++ b/gui/gtk/gui_gtk_window.c @@ -0,0 +1,67 @@ +#include +#include +#include "coord.h" +#include "transform.h" +#include "container.h" +#include "gui_gtk.h" + + +extern void container_init_gra(struct container *co); + +struct container * +container_new(GtkWidget **widget) +{ + struct container *co=g_new0(struct container, 1); + extern struct map_data *map_data_default; + struct transformation *t=g_new0(struct transformation, 1); + struct map_flags *flags=g_new0(struct map_flags, 1); + struct graphics *gra; + + co->map_data=map_data_default; +#if 1 + extern struct graphics *graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); + gra=graphics_gtk_drawing_area_new(co, widget); +#else + extern struct graphics *graphics_gtk_gl_area_new(struct container *co, GtkWidget **widget); + gra=graphics_gtk_gl_area_new(co, widget); +#endif + co->gra=gra; + co->trans=t; + co->flags=flags; + + return co; +} + +struct container * +gui_gtk_window(int x, int y, int scale) +{ + GtkWidget *window,*map_widget; + GtkWidget *vbox; + GtkWidget *statusbar,*toolbar,*menu; + struct container *co; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(window), 792, 547); + gtk_window_set_title(GTK_WINDOW(window), "Map"); + gtk_widget_realize(window); + vbox = gtk_vbox_new(FALSE, 0); + co=container_new(&map_widget); + + transform_setup(co->trans, x, y, scale, 0); + + co->win=(struct window *) window; + co->statusbar=gui_gtk_statusbar_new(&statusbar); + co->toolbar=gui_gtk_toolbar_new(co, &toolbar); + co->menu=gui_gtk_menu_new(co, &menu); + gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(vbox), map_widget, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(window), vbox); + + gtk_widget_show_all(window); + container_init_gra(co); + return co; +} + + diff --git a/locations.txt b/locations.txt new file mode 100644 index 00000000..739f93b2 --- /dev/null +++ b/locations.txt @@ -0,0 +1 @@ +5231.3734 N 01324.8633 E Berlin Alexanderplatz diff --git a/log.c b/log.c new file mode 100644 index 00000000..c6995361 --- /dev/null +++ b/log.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "file.h" +#include "map_data.h" +#include "log.h" + +void +log_write(char *message, struct file *file, void *data, int size) +{ + char log[4096]; + unsigned char *l,*p=data; + + int fd=open("log.txt",O_RDWR|O_CREAT|O_APPEND|O_SYNC, 0644); + sprintf(log,"# %s\n",message); + l=log+strlen(log); + sprintf(l, "%s 0x%x ", file->name, p-file->begin); + l=log+strlen(log); + while (size) { + sprintf(l,"%02x ", *p++); + l+=3; + size--; + } + *l++='\n'; + *l='\0'; + write(fd, log, strlen(log)); + close(fd); +} + +void +log_apply(struct map_data *map, int files) +{ + char buffer[4096],*p; + char *filename, *addr; + struct file *file; + unsigned char *data; + unsigned long dataval; + struct map_data *curr; + int j; + + FILE *f=fopen("log.txt","r"); + if (!f) + return; + while (fgets(buffer, 4096, f)) { + if (buffer[0] != '#') { + buffer[strlen(buffer)-1]='\0'; + filename=buffer; + p=buffer; + while (*p && *p != ' ') + p++; + if (! *p) + continue; + *p++=0; + file=NULL; + curr=map; + while (curr) { + for(j = 0 ; j < files ; j++) { + if (curr->file[j] && !strcmp(curr->file[j]->name, filename)) { + file=curr->file[j]; + break; + } + } + if (file) + break; + curr=curr->next; + } + if (file) { + addr=p; + while (*p && *p != ' ') + p++; + if (! *p) + continue; + *p++=0; + data=file->begin+strtoul(addr, NULL, 16); + while (*p) { + dataval=strtoul(p, NULL, 16); + *data++=dataval; + p+=2; + while (*p == ' ') + p++; + } + } + } + } + fclose(f); +} diff --git a/log.h b/log.h new file mode 100644 index 00000000..2bf04429 --- /dev/null +++ b/log.h @@ -0,0 +1,2 @@ +void log_write(char *message, struct file *file, void *data, int size); +void log_apply(struct map_data *map, int files); diff --git a/main.c b/main.c new file mode 100644 index 00000000..e2d23554 --- /dev/null +++ b/main.c @@ -0,0 +1,80 @@ +#include +#include +#include "coord.h" +#include "vehicle.h" +#include "cursor.h" +#include "speech.h" +#include "route.h" +#include "map.h" +#include "map_data.h" +#if 0 +#include "map-share.h" +#endif +#include "transform.h" +#include "popup.h" +#include "plugin.h" +#include "compass.h" +#include "container.h" + + +void *speech_handle; + +struct container *co; + +struct map_data *map_data_default; + +struct container *gui_gtk_window(int x, int y, int scale); + +extern void test(struct map_data *mdat); + +int main(int argc, char **argv) +{ + CORBA_Environment ev; + CORBA_ORB orb; + Map map_client = CORBA_OBJECT_NIL; + char *retval; + FILE *ior; + + setenv("LC_NUMERIC","C",1); + setlocale(LC_ALL,""); + setlocale(LC_NUMERIC,"C"); + gtk_set_locale(); + setlocale(LC_NUMERIC,"C"); + gtk_init(&argc, &argv); + gdk_rgb_init(); + + map_data_default=load_maps(NULL); + plugin_load(); + co=gui_gtk_window(1300000,7000000,8192); + co->vehicle=vehicle_new("/tmp/gpsdata"); + co->cursor=cursor_new(co); + co->speech=speech_new(); + speech_handle=co->speech; + co->route=route_new(); + co->compass=compass_new(co); + route_mapdata_set(co->route, co->map_data); + + +#if 0 + CORBA_exception_init(&ev); + orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); + g_assert(ev._major == CORBA_NO_EXCEPTION); + + map_srv_start_poa(orb, &ev); + g_assert(ev._major == CORBA_NO_EXCEPTION); + map_client = map_srv_start_object(&ev, map); + retval = CORBA_ORB_object_to_string(orb, map_client, &ev); + g_assert(ev._major == CORBA_NO_EXCEPTION); + ior=fopen("map.ior","w"); + if (ior) { + fprintf(ior, "%s\n", retval); + fclose(ior); + } + CORBA_free(retval); +#endif + + gtk_main(); + return 0; +} + + diff --git a/main.h b/main.h new file mode 100644 index 00000000..fbf9d73d --- /dev/null +++ b/main.h @@ -0,0 +1 @@ +extern void *speech_handle; diff --git a/map-common.c b/map-common.c new file mode 100644 index 00000000..91d27199 --- /dev/null +++ b/map-common.c @@ -0,0 +1,442 @@ +/* + * This file was generated by orbit-idl-2 - DO NOT EDIT! + */ + +#include +#define ORBIT2_STUBS_API +#define ORBIT_IDL_C_COMMON +#define map_COMMON +#include "map.h" + +static const CORBA_unsigned_long ORBit_zero_int = 0; + +#ifndef ORBIT_IDL_C_IMODULE_map +void +_ORBIT_skel_small_Mappel_Test(POA_Mappel * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_Test) (PortableServer_Servant + _servant, + CORBA_Environment * ev)) +{ + _impl_Test(_o_servant, _o_ev); +} + +void +_ORBIT_skel_small_Map_mapString(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + Map(*_impl_mapString) (PortableServer_Servant + _servant, + const CORBA_char * + astring, + CORBA_double * anum, + CORBA_Environment * + ev)) +{ + *(Map *) _o_retval = + _impl_mapString(_o_servant, *(const CORBA_char * *) _o_args[0], + *(CORBA_double * *)_o_args[1], _o_ev); +} + +void +_ORBIT_skel_small_Map_doNothing(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_doNothing) + (PortableServer_Servant _servant, + CORBA_Environment * ev)) +{ + _impl_doNothing(_o_servant, _o_ev); +} + +void +_ORBIT_skel_small_Map_doOneWay(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_doOneWay) (PortableServer_Servant + _servant, + const CORBA_char * + ignore, + CORBA_Environment * + ev)) +{ + _impl_doOneWay(_o_servant, *(const CORBA_char * *) _o_args[0], _o_ev); +} + +void +_ORBIT_skel_small_Map_PlaceFlag(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_PlaceFlag) + (PortableServer_Servant _servant, + CORBA_Environment * ev)) +{ + _impl_PlaceFlag(_o_servant, _o_ev); +} + +void +_ORBIT_skel_small_Map_PointFromCoord(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + PointObj(*_impl_PointFromCoord) + (PortableServer_Servant _servant, + const CORBA_char * coord, + CORBA_Environment * ev)) +{ + *(PointObj *) _o_retval = + _impl_PointFromCoord(_o_servant, *(const CORBA_char * *) _o_args[0], + _o_ev); +} + +void +_ORBIT_skel_small_Map_View(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_View) (PortableServer_Servant + _servant, + const PointObj * where, + CORBA_Environment * ev)) +{ + _impl_View(_o_servant, (const PointObj *) _o_args[0], _o_ev); +} + +void +_ORBIT_skel_small_Map_ViewAll(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_ViewAll) (PortableServer_Servant + _servant, + const PointObjSequence * + where, + CORBA_Environment * ev)) +{ + _impl_ViewAll(_o_servant, (const CORBA_sequence_PointObj *) _o_args[0], + _o_ev); +} + +void +_ORBIT_skel_small_Map_Route(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + void (*_impl_Route) (PortableServer_Servant + _servant, + const PointObj * src, + const PointObj * dst, + CORBA_Environment * ev)) +{ + _impl_Route(_o_servant, (const PointObj *) _o_args[0], + (const PointObj *) _o_args[1], _o_ev); +} + +void +_ORBIT_skel_small_Map_Get(POA_Map * _o_servant, gpointer _o_retval, + gpointer * _o_args, CORBA_Context _o_ctx, + CORBA_Environment * _o_ev, + Mappel(*_impl_Get) (PortableServer_Servant _servant, + CORBA_Environment * ev)) +{ + *(Mappel *) _o_retval = _impl_Get(_o_servant, _o_ev); +} + +#endif +#if ( (TC_IMPL_TC_PointObj_0 == 'm') \ +&& (TC_IMPL_TC_PointObj_1 == 'a') \ +&& (TC_IMPL_TC_PointObj_2 == 'p') \ +) && !defined(TC_DEF_TC_PointObj) +#define TC_DEF_TC_PointObj 1 +static const char *anon_subnames_array0[] = { "lng", "lat", "height" }; +static const CORBA_TypeCode anon_subtypes_array1[] = + { (CORBA_TypeCode) & TC_CORBA_float_struct, +(CORBA_TypeCode) & TC_CORBA_float_struct, (CORBA_TypeCode) & TC_CORBA_float_struct }; +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_PointObj_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_struct, + 0, + 0, + ORBIT_ALIGNOF_CORBA_FLOAT, + 0, + 3, + (CORBA_TypeCode *) anon_subtypes_array1, + CORBA_OBJECT_NIL, + "PointObj", + "IDL:PointObj:1.0", + (char **) anon_subnames_array0, + NULL, + -1, + 0, + 0, 0 +}; +#endif +#if ( (TC_IMPL_TC_CORBA_sequence_PointObj_0 == 'm') \ +&& (TC_IMPL_TC_CORBA_sequence_PointObj_1 == 'a') \ +&& (TC_IMPL_TC_CORBA_sequence_PointObj_2 == 'p') \ +) && !defined(TC_DEF_TC_CORBA_sequence_PointObj) +#define TC_DEF_TC_CORBA_sequence_PointObj 1 +static const CORBA_TypeCode anon_subtypes_array4[] = + { (CORBA_TypeCode) & TC_PointObj_struct }; +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_CORBA_sequence_PointObj_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_sequence, + 0, + 0, + MAX(ORBIT_ALIGNOF_CORBA_POINTER, + MAX(ORBIT_ALIGNOF_CORBA_LONG, MAX(ORBIT_ALIGNOF_CORBA_STRUCT, 1))), + 0, + 1, + (CORBA_TypeCode *) anon_subtypes_array4, + CORBA_OBJECT_NIL, + NULL, + NULL, + NULL, + NULL, + -1, + 0, + 0, 0 +}; +#endif +#if ( (TC_IMPL_TC_CORBA_sequence_PointObj_0 == 'm') \ +&& (TC_IMPL_TC_CORBA_sequence_PointObj_1 == 'a') \ +&& (TC_IMPL_TC_CORBA_sequence_PointObj_2 == 'p') \ +) && !defined(TC_DEF_TC_CORBA_sequence_PointObj) +#define TC_DEF_TC_CORBA_sequence_PointObj 1 +static const CORBA_TypeCode anon_subtypes_array11[] = + { (CORBA_TypeCode) & TC_PointObj_struct }; +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_CORBA_sequence_PointObj_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_sequence, + 0, + 0, + MAX(ORBIT_ALIGNOF_CORBA_POINTER, + MAX(ORBIT_ALIGNOF_CORBA_LONG, MAX(ORBIT_ALIGNOF_CORBA_STRUCT, 1))), + 0, + 1, + (CORBA_TypeCode *) anon_subtypes_array11, + CORBA_OBJECT_NIL, + NULL, + NULL, + NULL, + NULL, + -1, + 0, + 0, 0 +}; +#endif +#if ( (TC_IMPL_TC_PointObjSequence_0 == 'm') \ +&& (TC_IMPL_TC_PointObjSequence_1 == 'a') \ +&& (TC_IMPL_TC_PointObjSequence_2 == 'p') \ +) && !defined(TC_DEF_TC_PointObjSequence) +#define TC_DEF_TC_PointObjSequence 1 +static const CORBA_TypeCode anon_subtypes_array14[] = + { (CORBA_TypeCode) & TC_CORBA_sequence_PointObj_struct }; +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_PointObjSequence_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_alias, + 0, + 0, + MAX(ORBIT_ALIGNOF_CORBA_POINTER, + MAX(ORBIT_ALIGNOF_CORBA_LONG, MAX(ORBIT_ALIGNOF_CORBA_STRUCT, 1))), + 0, + 1, + (CORBA_TypeCode *) anon_subtypes_array14, + CORBA_OBJECT_NIL, + "PointObjSequence", + "IDL:PointObjSequence:1.0", + NULL, + NULL, + -1, + 0, + 0, 0 +}; +#endif +#if ( (TC_IMPL_TC_Mappel_0 == 'm') \ +&& (TC_IMPL_TC_Mappel_1 == 'a') \ +&& (TC_IMPL_TC_Mappel_2 == 'p') \ +) && !defined(TC_DEF_TC_Mappel) +#define TC_DEF_TC_Mappel 1 +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_Mappel_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_objref, + 0, + 0, + ORBIT_ALIGNOF_CORBA_POINTER, + 0, + 0, + NULL, + CORBA_OBJECT_NIL, + "Mappel", + "IDL:Mappel:1.0", + NULL, + NULL, + -1, + 0, + 0, 0 +}; +#endif +#if ( (TC_IMPL_TC_Map_0 == 'm') \ +&& (TC_IMPL_TC_Map_1 == 'a') \ +&& (TC_IMPL_TC_Map_2 == 'p') \ +) && !defined(TC_DEF_TC_Map) +#define TC_DEF_TC_Map 1 +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +const struct CORBA_TypeCode_struct TC_Map_struct = { + {&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC}, + CORBA_tk_objref, + 0, + 0, + ORBIT_ALIGNOF_CORBA_POINTER, + 0, + 0, + NULL, + CORBA_OBJECT_NIL, + "Map", + "IDL:Map:1.0", + NULL, + NULL, + -1, + 0, + 0, 0 +}; +#endif + +#ifndef ORBIT_IDL_C_IMODULE_map +CORBA_unsigned_long Mappel__classid = 0; +#endif + +#ifndef ORBIT_IDL_C_IMODULE_map +CORBA_unsigned_long Map__classid = 0; +#endif + +/* Interface type data */ + +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +ORBit_IMethod Mappel__imethods[] = { + { + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "Test", 4, + 0} +}; +static CORBA_string Mappel__base_itypes[] = { + "IDL:omg.org/CORBA/Object:1.0" +}; + +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +ORBit_IInterface Mappel__iinterface = { + TC_Mappel, {1, 1, Mappel__imethods, FALSE}, + {1, 1, Mappel__base_itypes, FALSE} +}; + +static ORBit_IArg Map_mapString__arginfo[] = { + {TC_CORBA_string, ORBit_I_ARG_IN, "astring"}, + {TC_CORBA_double, ORBit_I_ARG_OUT | ORBit_I_COMMON_FIXED_SIZE, "anum"} +}; +static ORBit_IArg Map_doOneWay__arginfo[] = { + {TC_CORBA_string, ORBit_I_ARG_IN, "ignore"} +}; +static ORBit_IArg Map_PointFromCoord__arginfo[] = { + {TC_CORBA_string, ORBit_I_ARG_IN, "coord"} +}; +static ORBit_IArg Map_View__arginfo[] = { + {TC_PointObj, ORBit_I_ARG_IN | ORBit_I_COMMON_FIXED_SIZE, "where"} +}; +static ORBit_IArg Map_ViewAll__arginfo[] = { + {TC_PointObjSequence, ORBit_I_ARG_IN, "where"} +}; +static ORBit_IArg Map_Route__arginfo[] = { + {TC_PointObj, ORBit_I_ARG_IN | ORBit_I_COMMON_FIXED_SIZE, "src"}, + {TC_PointObj, ORBit_I_ARG_IN | ORBit_I_COMMON_FIXED_SIZE, "dst"} +}; + +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +ORBit_IMethod Map__imethods[] = { + { + {2, 2, Map_mapString__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_Map, "mapString", 9, + 0} + , { + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "doNothing", 9, + 0} + , { + {1, 1, Map_doOneWay__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "doOneWay", 8, + 0 | ORBit_I_METHOD_1_WAY} + , { + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "PlaceFlag", 9, + 0} + , { + {1, 1, Map_PointFromCoord__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_PointObj, "PointFromCoord", 14, + 0 | ORBit_I_COMMON_FIXED_SIZE} + , { + {1, 1, Map_View__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "View", 4, + 0} + , { + {1, 1, Map_ViewAll__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "ViewAll", 7, + 0} + , { + {2, 2, Map_Route__arginfo, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_void, "Route", 5, + 0} + , { + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + {0, 0, NULL, FALSE}, + TC_Mappel, "Get", 3, + 0} +}; +static CORBA_string Map__base_itypes[] = { + "IDL:omg.org/CORBA/Object:1.0" +}; + +#ifdef ORBIT_IDL_C_IMODULE_map +static +#endif +ORBit_IInterface Map__iinterface = { + TC_Map, {9, 9, Map__imethods, FALSE}, + {1, 1, Map__base_itypes, FALSE} +}; diff --git a/map-share.h b/map-share.h new file mode 100644 index 00000000..c540f30e --- /dev/null +++ b/map-share.h @@ -0,0 +1,2 @@ +void map_srv_start_poa(CORBA_ORB orb, CORBA_Environment * ev); +CORBA_Object map_srv_start_object(CORBA_Environment * ev, struct container *co); diff --git a/map-skelimpl.c b/map-skelimpl.c new file mode 100644 index 00000000..890df21c --- /dev/null +++ b/map-skelimpl.c @@ -0,0 +1,286 @@ +/* This is a template file generated by command */ +/* orbit-idl-2 --skeleton-impl map.idl */ +/* User must edit this file, inserting servant */ +/* specific code between markers. */ + +#include "map.h" + +/*** App-specific servant structures ***/ + +typedef struct +{ + POA_Mappel servant; + PortableServer_POA poa; + + /* ------ add private attributes here ------ */ + /* ------ ---------- end ------------ ------ */ +} impl_POA_Mappel; + +typedef struct +{ + POA_Map servant; + PortableServer_POA poa; + + /* ------ add private attributes here ------ */ + /* ------ ---------- end ------------ ------ */ +} impl_POA_Map; + +/*** Implementation stub prototypes ***/ + +static void impl_Mappel__destroy(impl_POA_Mappel * servant, + CORBA_Environment * ev); +static void +impl_Mappel_Test(impl_POA_Mappel * servant, CORBA_Environment * ev); + +static void impl_Map__destroy(impl_POA_Map * servant, CORBA_Environment * ev); +static Map +impl_Map_mapString(impl_POA_Map * servant, + const CORBA_char * astring, + CORBA_double * anum, CORBA_Environment * ev); + +static void +impl_Map_doNothing(impl_POA_Map * servant, CORBA_Environment * ev); + +static void +impl_Map_doOneWay(impl_POA_Map * servant, + const CORBA_char * ignore, CORBA_Environment * ev); + +static void +impl_Map_PlaceFlag(impl_POA_Map * servant, CORBA_Environment * ev); + +static PointObj +impl_Map_PointFromCoord(impl_POA_Map * servant, + const CORBA_char * coord, CORBA_Environment * ev); + +static void +impl_Map_View(impl_POA_Map * servant, + const PointObj * where, CORBA_Environment * ev); + +static void +impl_Map_ViewAll(impl_POA_Map * servant, + const PointObjSequence * where, CORBA_Environment * ev); + +static void +impl_Map_Route(impl_POA_Map * servant, + const PointObj * src, + const PointObj * dst, CORBA_Environment * ev); + +static Mappel impl_Map_Get(impl_POA_Map * servant, CORBA_Environment * ev); + +/*** epv structures ***/ + +static PortableServer_ServantBase__epv impl_Mappel_base_epv = { + NULL, /* _private data */ + (gpointer) & impl_Mappel__destroy, /* finalize routine */ + NULL, /* default_POA routine */ +}; +static POA_Mappel__epv impl_Mappel_epv = { + NULL, /* _private */ + (gpointer) & impl_Mappel_Test, + +}; +static PortableServer_ServantBase__epv impl_Map_base_epv = { + NULL, /* _private data */ + (gpointer) & impl_Map__destroy, /* finalize routine */ + NULL, /* default_POA routine */ +}; +static POA_Map__epv impl_Map_epv = { + NULL, /* _private */ + (gpointer) & impl_Map_mapString, + + (gpointer) & impl_Map_doNothing, + + (gpointer) & impl_Map_doOneWay, + + (gpointer) & impl_Map_PlaceFlag, + + (gpointer) & impl_Map_PointFromCoord, + + (gpointer) & impl_Map_View, + + (gpointer) & impl_Map_ViewAll, + + (gpointer) & impl_Map_Route, + + (gpointer) & impl_Map_Get, + +}; + +/*** vepv structures ***/ + +static POA_Mappel__vepv impl_Mappel_vepv = { + &impl_Mappel_base_epv, + &impl_Mappel_epv, +}; +static POA_Map__vepv impl_Map_vepv = { + &impl_Map_base_epv, + &impl_Map_epv, +}; + +/*** Stub implementations ***/ + +static Mappel +impl_Mappel__create(PortableServer_POA poa, CORBA_Environment * ev) +{ + Mappel retval; + impl_POA_Mappel *newservant; + PortableServer_ObjectId *objid; + + newservant = g_new0(impl_POA_Mappel, 1); + newservant->servant.vepv = &impl_Mappel_vepv; + newservant->poa = + (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev); + POA_Mappel__init((PortableServer_Servant) newservant, ev); + /* Before servant is going to be activated all + * private attributes must be initialized. */ + + /* ------ init private attributes here ------ */ + /* ------ ---------- end ------------- ------ */ + + objid = PortableServer_POA_activate_object(poa, newservant, ev); + CORBA_free(objid); + retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); + + return retval; +} + +static void +impl_Mappel__destroy(impl_POA_Mappel * servant, CORBA_Environment * ev) +{ + CORBA_Object_release((CORBA_Object) servant->poa, ev); + + /* No further remote method calls are delegated to + * servant and you may free your private attributes. */ + /* ------ free private attributes here ------ */ + /* ------ ---------- end ------------- ------ */ + + POA_Mappel__fini((PortableServer_Servant) servant, ev); +} + +static void +impl_Mappel_Test(impl_POA_Mappel * servant, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static Map +impl_Map__create(PortableServer_POA poa, CORBA_Environment * ev) +{ + Map retval; + impl_POA_Map *newservant; + PortableServer_ObjectId *objid; + + newservant = g_new0(impl_POA_Map, 1); + newservant->servant.vepv = &impl_Map_vepv; + newservant->poa = + (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev); + POA_Map__init((PortableServer_Servant) newservant, ev); + /* Before servant is going to be activated all + * private attributes must be initialized. */ + + /* ------ init private attributes here ------ */ + /* ------ ---------- end ------------- ------ */ + + objid = PortableServer_POA_activate_object(poa, newservant, ev); + CORBA_free(objid); + retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); + + return retval; +} + +static void +impl_Map__destroy(impl_POA_Map * servant, CORBA_Environment * ev) +{ + CORBA_Object_release((CORBA_Object) servant->poa, ev); + + /* No further remote method calls are delegated to + * servant and you may free your private attributes. */ + /* ------ free private attributes here ------ */ + /* ------ ---------- end ------------- ------ */ + + POA_Map__fini((PortableServer_Servant) servant, ev); +} + +static Map +impl_Map_mapString(impl_POA_Map * servant, + const CORBA_char * astring, + CORBA_double * anum, CORBA_Environment * ev) +{ + Map retval; + + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ + + return retval; +} + +static void +impl_Map_doNothing(impl_POA_Map * servant, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static void +impl_Map_doOneWay(impl_POA_Map * servant, + const CORBA_char * ignore, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static void +impl_Map_PlaceFlag(impl_POA_Map * servant, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static PointObj +impl_Map_PointFromCoord(impl_POA_Map * servant, + const CORBA_char * coord, CORBA_Environment * ev) +{ + PointObj retval; + + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ + + return retval; +} + +static void +impl_Map_View(impl_POA_Map * servant, + const PointObj * where, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static void +impl_Map_ViewAll(impl_POA_Map * servant, + const PointObjSequence * where, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static void +impl_Map_Route(impl_POA_Map * servant, + const PointObj * src, + const PointObj * dst, CORBA_Environment * ev) +{ + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ +} + +static Mappel +impl_Map_Get(impl_POA_Map * servant, CORBA_Environment * ev) +{ + Mappel retval; + + /* ------ insert method code here ------ */ + /* ------ ---------- end ------------ ------ */ + + return retval; +} diff --git a/map-skels.c b/map-skels.c new file mode 100644 index 00000000..bcc99254 --- /dev/null +++ b/map-skels.c @@ -0,0 +1,184 @@ +/* + * This file was generated by orbit-idl-2 - DO NOT EDIT! + */ + +#include +#define ORBIT2_STUBS_API +#include "map.h" + +static ORBitSmallSkeleton +get_skel_small_Mappel(POA_Mappel * servant, + const char *opname, gpointer * m_data, gpointer * impl) +{ + switch (opname[0]) { + case 'T': + if (strcmp((opname + 1), "est")) + break; + *impl = (gpointer) servant->vepv->Mappel_epv->Test; + *m_data = (gpointer) & Mappel__iinterface.methods._buffer[0]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Mappel_Test; + break; + default: + break; + } + return NULL; +} + +void +POA_Mappel__init(PortableServer_Servant servant, CORBA_Environment * env) +{ + static PortableServer_ClassInfo class_info = + { NULL, (ORBit_small_impl_finder) & get_skel_small_Mappel, +"IDL:Mappel:1.0", &Mappel__classid, NULL, &Mappel__iinterface }; + PortableServer_ServantBase__init(((PortableServer_ServantBase *) servant), + env); + ORBit_skel_class_register(&class_info, servant, POA_Mappel__fini, + ORBIT_VEPV_OFFSET(POA_Mappel__vepv, Mappel_epv), + (CORBA_unsigned_long) 0); +} + +void +POA_Mappel__fini(PortableServer_Servant servant, CORBA_Environment * env) +{ + PortableServer_ServantBase__fini(servant, env); +} + +static ORBitSmallSkeleton +get_skel_small_Map(POA_Map * servant, + const char *opname, gpointer * m_data, gpointer * impl) +{ + switch (opname[0]) { + case 'G': + if (strcmp((opname + 1), "et")) + break; + *impl = (gpointer) servant->vepv->Map_epv->Get; + *m_data = (gpointer) & Map__iinterface.methods._buffer[8]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_Get; + break; + case 'P': + switch (opname[1]) { + case 'l': + if (strcmp((opname + 2), "aceFlag")) + break; + *impl = (gpointer) servant->vepv->Map_epv->PlaceFlag; + *m_data = (gpointer) & Map__iinterface.methods._buffer[3]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_PlaceFlag; + break; + case 'o': + if (strcmp((opname + 2), "intFromCoord")) + break; + *impl = (gpointer) servant->vepv->Map_epv->PointFromCoord; + *m_data = (gpointer) & Map__iinterface.methods._buffer[4]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_PointFromCoord; + break; + default: + break; + } + break; + case 'R': + if (strcmp((opname + 1), "oute")) + break; + *impl = (gpointer) servant->vepv->Map_epv->Route; + *m_data = (gpointer) & Map__iinterface.methods._buffer[7]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_Route; + break; + case 'V': + switch (opname[1]) { + case 'i': + switch (opname[2]) { + case 'e': + switch (opname[3]) { + case 'w': + switch (opname[4]) { + case '\0': + *impl = (gpointer) servant->vepv->Map_epv->View; + *m_data = + (gpointer) & Map__iinterface.methods. + _buffer[5]; + return (ORBitSmallSkeleton) + _ORBIT_skel_small_Map_View; + break; + case 'A': + if (strcmp((opname + 5), "ll")) + break; + *impl = + (gpointer) servant->vepv->Map_epv->ViewAll; + *m_data = + (gpointer) & Map__iinterface.methods. + _buffer[6]; + return (ORBitSmallSkeleton) + _ORBIT_skel_small_Map_ViewAll; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + case 'd': + switch (opname[1]) { + case 'o': + switch (opname[2]) { + case 'N': + if (strcmp((opname + 3), "othing")) + break; + *impl = (gpointer) servant->vepv->Map_epv->doNothing; + *m_data = (gpointer) & Map__iinterface.methods._buffer[1]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_doNothing; + break; + case 'O': + if (strcmp((opname + 3), "neWay")) + break; + *impl = (gpointer) servant->vepv->Map_epv->doOneWay; + *m_data = (gpointer) & Map__iinterface.methods._buffer[2]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_doOneWay; + break; + default: + break; + } + break; + default: + break; + } + break; + case 'm': + if (strcmp((opname + 1), "apString")) + break; + *impl = (gpointer) servant->vepv->Map_epv->mapString; + *m_data = (gpointer) & Map__iinterface.methods._buffer[0]; + return (ORBitSmallSkeleton) _ORBIT_skel_small_Map_mapString; + break; + default: + break; + } + return NULL; +} + +void +POA_Map__init(PortableServer_Servant servant, CORBA_Environment * env) +{ + static PortableServer_ClassInfo class_info = + { NULL, (ORBit_small_impl_finder) & get_skel_small_Map, "IDL:Map:1.0", +&Map__classid, NULL, &Map__iinterface }; + PortableServer_ServantBase__init(((PortableServer_ServantBase *) servant), + env); + ORBit_skel_class_register(&class_info, servant, POA_Map__fini, + ORBIT_VEPV_OFFSET(POA_Map__vepv, Map_epv), + (CORBA_unsigned_long) 0); +} + +void +POA_Map__fini(PortableServer_Servant servant, CORBA_Environment * env) +{ + PortableServer_ServantBase__fini(servant, env); +} diff --git a/map-srv.c b/map-srv.c new file mode 100644 index 00000000..6d38db03 --- /dev/null +++ b/map-srv.c @@ -0,0 +1,262 @@ +/* + * CORBA map test + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Elliot Lee + */ + +#include +#include +#include +#include +#include "map.h" +#include "coord.h" +#include "route.h" +#include "transform.h" +#include "statusbar.h" +#include "map-share.h" +#include "main.h" +#include + +/** + This is used by map-server.c and map-local.c + It uses map-skels.c +**/ + +static Map the_map_client; +static CORBA_ORB the_orb; +static PortableServer_POA the_poa; +static PortableServer_ObjectId *the_objid; + +#if 0 +static GtkMap *global_map; +#endif + +static CORBA_Object +do_mapString(PortableServer_Servant servant, + const CORBA_char * astring, + CORBA_double * outnum, CORBA_Environment * ev) +{ + + g_message("[server] %s", astring); + + *outnum = rand() % 100; + + return CORBA_Object_duplicate(the_map_client, ev); +} + +static void +do_PlaceFlag(PortableServer_Servant servant, CORBA_Environment * ev) +{ + + g_message("[server PlaceFlag]"); + +} + + +static void +do_doNothing(PortableServer_Servant servant, CORBA_Environment * ev) +{ +} + +PortableServer_ServantBase__epv base_epv = { + NULL, + NULL, + NULL +}; + +PointObj +do_PointFromCoord(PortableServer_Servant _servant, const CORBA_char * coord, CORBA_Environment * ev) +{ + PointObj ret; + double lat,lng,lat_deg,lng_deg; + char lat_c,lng_c; + + printf("String=%s\n", coord); + sscanf(coord,"%lf %c %lf %c",&lat, &lat_c, &lng, &lng_c); + + printf("lat=%f lng=%f\n", lat, lng); + + lat_deg=floor(lat/100); + lat-=lat_deg*100; + lat_deg+=lat/60; + + lng_deg=floor(lng/100); + lng-=lng_deg*100; + lng_deg+=lng/60; + + ret.lat=lat_deg; + ret.lng=lng_deg; + printf("lat_deg=%f lng_deg=%f\n", lat_deg, lng_deg); + + ret.height=0; + return ret; +} + +static void +PointObj_to_coor(const PointObj *pnt, struct coord *c) +{ + double lng, lat; + lng=pnt->lng; + lat=pnt->lat; + transform_mercator(&lng, &lat, c); +} + +void +do_View(PortableServer_Servant _servant, const PointObj *pnt, CORBA_Environment * ev) +{ + unsigned long scale; + struct coord c; +#if 0 + GtkMap *map=global_map; + + map_get_view(map, NULL, NULL, &scale); + PointObj_to_coor(pnt, &c); + map_set_view(map, c.x, c.y, scale); +#endif +} + + +void +do_Route(PortableServer_Servant _servant, const PointObj *src, const PointObj *dst, CORBA_Environment * ev) +{ +#if 0 + struct coord c_src,c_dst; + GtkMap *map=global_map; + unsigned long scale; + + PointObj_to_coor(src, &c_src); + PointObj_to_coor(dst, &c_dst); + route_set_position(map->container->route, &c_src); + route_set_destination(map->container->route, &c_dst); + + map_get_view(map, NULL, NULL, &scale); + map_set_view(map, c_src.x, c_src.y, scale); + + if (map->container->statusbar && map->container->statusbar->statusbar_route_update) + map->container->statusbar->statusbar_route_update(map->container->statusbar, map->container->route); +#endif +} + +POA_Mappel__epv mappel_epv = { +}; + +Mappel do_Get(PortableServer_Servant _servant, CORBA_Environment * ev) +{ + Mappel retval=NULL; +#if 0 + impl_POA_Mappel *newservant; + PortableServer_ObjectId *objid; + + printf("Do_Get\n"); + newservant = g_new0(impl_POA_Mappel, 1); + newservant->servant.vepv = &mappel_epv; + newservant->poa = poa; + POA_Mappel__init((PortableServer_Servant) newservant, ev); + objid = PortableServer_POA_activate_object(poa, newservant, ev); + CORBA_free(objid); + retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); +#endif + + return retval; +} + +POA_Map__epv map_epv = { + mapString: do_mapString, + doNothing: do_doNothing, + PlaceFlag: do_PlaceFlag, + PointFromCoord: do_PointFromCoord, + View: do_View, + Route: do_Route, + Get: do_Get, + }; +POA_Map__vepv poa_map_vepv = { &base_epv, &map_epv }; +POA_Map poa_map_servant = { NULL, &poa_map_vepv }; + + +void map_srv_start_poa(CORBA_ORB orb, CORBA_Environment * ev) +{ + PortableServer_POAManager mgr; + + the_orb = orb; + the_poa = (PortableServer_POA) + CORBA_ORB_resolve_initial_references(orb, "RootPOA", ev); + + mgr = PortableServer_POA__get_the_POAManager(the_poa, ev); + PortableServer_POAManager_activate(mgr, ev); + CORBA_Object_release((CORBA_Object) mgr, ev); +} + +CORBA_Object map_srv_start_object(CORBA_Environment * ev, struct container *co) +{ + POA_Map__init(&poa_map_servant, ev); + if (ev->_major) { + printf("object__init failed: %d\n", ev->_major); + exit(1); + } + the_objid = PortableServer_POA_activate_object(the_poa, + &poa_map_servant, + ev); + if (ev->_major) { + printf("activate_object failed: %d\n", ev->_major); + exit(1); + } + the_map_client = PortableServer_POA_servant_to_reference(the_poa, + &poa_map_servant, + ev); + if (ev->_major) { + printf("servant_to_reference failed: %d\n", ev->_major); + exit(1); + } +#if 0 + global_map=map; +#endif + return the_map_client; +} + +void map_srv_finish_object(CORBA_Environment * ev) +{ + CORBA_Object_release(the_map_client, ev); + if (ev->_major) { + printf("object_release failed: %d\n", ev->_major); + exit(1); + } + the_map_client = 0; + PortableServer_POA_deactivate_object(the_poa, the_objid, ev); + if (ev->_major) { + printf("deactivate_object failed: %d\n", ev->_major); + exit(1); + } + CORBA_free(the_objid); + the_objid = 0; + POA_Map__fini(&poa_map_servant, ev); + if (ev->_major) { + printf("object__fini failed: %d\n", ev->_major); + exit(1); + } +} + + +void map_srv_finish_poa(CORBA_Environment * ev) +{ + CORBA_Object_release((CORBA_Object) the_poa, ev); + if (ev->_major) { + printf("POA release failed: %d\n", ev->_major); + exit(1); + } + the_poa = 0; +} + diff --git a/map-stubs.c b/map-stubs.c new file mode 100644 index 00000000..fa7d0f34 --- /dev/null +++ b/map-stubs.c @@ -0,0 +1,135 @@ +/* + * This file was generated by orbit-idl-2 - DO NOT EDIT! + */ + +#include +#define ORBIT2_STUBS_API +#include "map.h" + +void +Mappel_Test(Mappel _obj, CORBA_Environment * ev) +{ + ORBit_c_stub_invoke(_obj, &Mappel__iinterface.methods, 0, NULL, NULL, NULL, + ev, Mappel__classid, G_STRUCT_OFFSET(POA_Mappel__epv, + Test), + (ORBitSmallSkeleton) _ORBIT_skel_small_Mappel_Test); + +} + +Map +Map_mapString(Map _obj, const CORBA_char * astring, CORBA_double * anum, + CORBA_Environment * ev) +{ + Map _ORBIT_retval; + gpointer _args[2]; + + _args[0] = (gpointer) & astring; + _args[1] = &anum; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 0, &_ORBIT_retval, + _args, NULL, ev, Map__classid, + G_STRUCT_OFFSET(POA_Map__epv, mapString), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_mapString); + + return _ORBIT_retval; +} + +void +Map_doNothing(Map _obj, CORBA_Environment * ev) +{ + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 1, NULL, NULL, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, + doNothing), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_doNothing); + +} + +void +Map_doOneWay(Map _obj, const CORBA_char * ignore, CORBA_Environment * ev) +{ + gpointer _args[1]; + + _args[0] = (gpointer) & ignore; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 2, NULL, _args, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, + doOneWay), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_doOneWay); + +} + +void +Map_PlaceFlag(Map _obj, CORBA_Environment * ev) +{ + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 3, NULL, NULL, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, + PlaceFlag), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_PlaceFlag); + +} + +PointObj +Map_PointFromCoord(Map _obj, const CORBA_char * coord, CORBA_Environment * ev) +{ + PointObj _ORBIT_retval; + gpointer _args[1]; + + _args[0] = (gpointer) & coord; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 4, &_ORBIT_retval, + _args, NULL, ev, Map__classid, + G_STRUCT_OFFSET(POA_Map__epv, PointFromCoord), + (ORBitSmallSkeleton) + _ORBIT_skel_small_Map_PointFromCoord); + + return _ORBIT_retval; +} + +void +Map_View(Map _obj, const PointObj * where, CORBA_Environment * ev) +{ + gpointer _args[1]; + + _args[0] = (gpointer) where; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 5, NULL, _args, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, View), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_View); + +} + +void +Map_ViewAll(Map _obj, const PointObjSequence * where, CORBA_Environment * ev) +{ + gpointer _args[1]; + + _args[0] = (gpointer) where; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 6, NULL, _args, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, + ViewAll), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_ViewAll); + +} + +void +Map_Route(Map _obj, const PointObj * src, const PointObj * dst, + CORBA_Environment * ev) +{ + gpointer _args[2]; + + _args[0] = (gpointer) src; + _args[1] = (gpointer) dst; + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 7, NULL, _args, NULL, + ev, Map__classid, G_STRUCT_OFFSET(POA_Map__epv, Route), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_Route); + +} + +Mappel +Map_Get(Map _obj, CORBA_Environment * ev) +{ + Mappel _ORBIT_retval; + + ORBit_c_stub_invoke(_obj, &Map__iinterface.methods, 8, &_ORBIT_retval, + NULL, NULL, ev, Map__classid, + G_STRUCT_OFFSET(POA_Map__epv, Get), + (ORBitSmallSkeleton) _ORBIT_skel_small_Map_Get); + + return _ORBIT_retval; +} diff --git a/map.h b/map.h new file mode 100644 index 00000000..2ffa914b --- /dev/null +++ b/map.h @@ -0,0 +1,341 @@ +/* + * This file was generated by orbit-idl-2 - DO NOT EDIT! + */ + +#ifndef map_H +#define map_H 1 +#include +#define ORBIT_IDL_SERIAL 20 +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** typedefs **/ +#if !defined(_PointObj_defined) +#define _PointObj_defined 1 + typedef struct PointObj_type PointObj; + struct PointObj_type + { + CORBA_float lng; + CORBA_float lat; + CORBA_float height; + }; + +#if !defined(TC_IMPL_TC_PointObj_0) +#define TC_IMPL_TC_PointObj_0 'm' +#define TC_IMPL_TC_PointObj_1 'a' +#define TC_IMPL_TC_PointObj_2 'p' +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + const struct CORBA_TypeCode_struct TC_PointObj_struct; +#define TC_PointObj ((CORBA_TypeCode)&TC_PointObj_struct) +#endif +#define PointObj__alloc() ((PointObj *)ORBit_small_alloc (TC_PointObj)) +#define PointObj__freekids(m,d) ORBit_small_freekids (TC_PointObj,(m),(d)) +#endif +#if !defined(ORBIT_DECL_CORBA_sequence_PointObj) +#define ORBIT_DECL_CORBA_sequence_PointObj 1 +#define ORBIT_IMPL_CORBA_sequence_PointObj_0 'm' +#define ORBIT_IMPL_CORBA_sequence_PointObj_1 'a' +#define ORBIT_IMPL_CORBA_sequence_PointObj_2 'p' +#if !defined(_CORBA_sequence_PointObj_defined) +#define _CORBA_sequence_PointObj_defined 1 + typedef struct + { + CORBA_unsigned_long _maximum, + _length; + PointObj *_buffer; + CORBA_boolean _release; + } CORBA_sequence_PointObj; +#endif +#if !defined(TC_IMPL_TC_CORBA_sequence_PointObj_0) +#define TC_IMPL_TC_CORBA_sequence_PointObj_0 'm' +#define TC_IMPL_TC_CORBA_sequence_PointObj_1 'a' +#define TC_IMPL_TC_CORBA_sequence_PointObj_2 'p' +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + const struct CORBA_TypeCode_struct TC_CORBA_sequence_PointObj_struct; +#define TC_CORBA_sequence_PointObj ((CORBA_TypeCode)&TC_CORBA_sequence_PointObj_struct) +#endif +#define CORBA_sequence_PointObj__alloc() ((CORBA_sequence_PointObj *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) +#define CORBA_sequence_PointObj__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) +#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) +#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) +#endif +#if !defined(_PointObjSequence_defined) +#define _PointObjSequence_defined 1 + typedef CORBA_sequence_PointObj PointObjSequence; +#define PointObjSequence_marshal(x,y,z) CORBA_sequence_PointObj_marshal((x),(y),(z)) +#define PointObjSequence_demarshal(x,y,z,i) CORBA_sequence_PointObj_demarshal((x),(y),(z),(i)) +#if !defined(TC_IMPL_TC_PointObjSequence_0) +#define TC_IMPL_TC_PointObjSequence_0 'm' +#define TC_IMPL_TC_PointObjSequence_1 'a' +#define TC_IMPL_TC_PointObjSequence_2 'p' +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + const struct CORBA_TypeCode_struct TC_PointObjSequence_struct; +#define TC_PointObjSequence ((CORBA_TypeCode)&TC_PointObjSequence_struct) +#endif +#define PointObjSequence__alloc() ((PointObjSequence *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) +#define PointObjSequence__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) +#define PointObjSequence_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) +#endif +#if !defined(ORBIT_DECL_Mappel) && !defined(_Mappel_defined) +#define ORBIT_DECL_Mappel 1 +#define _Mappel_defined 1 +#define Mappel__freekids CORBA_Object__freekids + typedef CORBA_Object Mappel; + extern CORBA_unsigned_long Mappel__classid; +#if !defined(TC_IMPL_TC_Mappel_0) +#define TC_IMPL_TC_Mappel_0 'm' +#define TC_IMPL_TC_Mappel_1 'a' +#define TC_IMPL_TC_Mappel_2 'p' +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + const struct CORBA_TypeCode_struct TC_Mappel_struct; +#define TC_Mappel ((CORBA_TypeCode)&TC_Mappel_struct) +#endif +#endif +#if !defined(ORBIT_DECL_Map) && !defined(_Map_defined) +#define ORBIT_DECL_Map 1 +#define _Map_defined 1 +#define Map__freekids CORBA_Object__freekids + typedef CORBA_Object Map; + extern CORBA_unsigned_long Map__classid; +#if !defined(TC_IMPL_TC_Map_0) +#define TC_IMPL_TC_Map_0 'm' +#define TC_IMPL_TC_Map_1 'a' +#define TC_IMPL_TC_Map_2 'p' +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + const struct CORBA_TypeCode_struct TC_Map_struct; +#define TC_Map ((CORBA_TypeCode)&TC_Map_struct) +#endif +#endif + +/** POA structures **/ +#ifndef _defined_POA_Mappel +#define _defined_POA_Mappel 1 + typedef struct + { + void *_private; + void (*Test) (PortableServer_Servant _servant, CORBA_Environment * ev); + } POA_Mappel__epv; + typedef struct + { + PortableServer_ServantBase__epv *_base_epv; + POA_Mappel__epv *Mappel_epv; + } POA_Mappel__vepv; + typedef struct + { + void *_private; + POA_Mappel__vepv *vepv; + } POA_Mappel; + extern void POA_Mappel__init(PortableServer_Servant servant, + CORBA_Environment * ev); + extern void POA_Mappel__fini(PortableServer_Servant servant, + CORBA_Environment * ev); +#endif /* _defined_POA_Mappel */ +#ifndef _defined_POA_Map +#define _defined_POA_Map 1 + typedef struct + { + void *_private; + Map(*mapString) (PortableServer_Servant _servant, + const CORBA_char * astring, CORBA_double * anum, + CORBA_Environment * ev); + void (*doNothing) (PortableServer_Servant _servant, + CORBA_Environment * ev); + void (*doOneWay) (PortableServer_Servant _servant, + const CORBA_char * ignore, CORBA_Environment * ev); + void (*PlaceFlag) (PortableServer_Servant _servant, + CORBA_Environment * ev); + PointObj(*PointFromCoord) (PortableServer_Servant _servant, + const CORBA_char * coord, + CORBA_Environment * ev); + void (*View) (PortableServer_Servant _servant, const PointObj * where, + CORBA_Environment * ev); + void (*ViewAll) (PortableServer_Servant _servant, + const PointObjSequence * where, + CORBA_Environment * ev); + void (*Route) (PortableServer_Servant _servant, const PointObj * src, + const PointObj * dst, CORBA_Environment * ev); + Mappel(*Get) (PortableServer_Servant _servant, CORBA_Environment * ev); + } POA_Map__epv; + typedef struct + { + PortableServer_ServantBase__epv *_base_epv; + POA_Map__epv *Map_epv; + } POA_Map__vepv; + typedef struct + { + void *_private; + POA_Map__vepv *vepv; + } POA_Map; + extern void POA_Map__init(PortableServer_Servant servant, + CORBA_Environment * ev); + extern void POA_Map__fini(PortableServer_Servant servant, + CORBA_Environment * ev); +#endif /* _defined_POA_Map */ + +/** skel prototypes **/ + void _ORBIT_skel_small_Mappel_Test(POA_Mappel * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_Test) + (PortableServer_Servant _servant, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_mapString(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + Map(*_impl_mapString) + (PortableServer_Servant _servant, + const CORBA_char * astring, + CORBA_double * anum, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_doNothing(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_doNothing) + (PortableServer_Servant _servant, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_doOneWay(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_doOneWay) + (PortableServer_Servant _servant, + const CORBA_char * ignore, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_PlaceFlag(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_PlaceFlag) + (PortableServer_Servant _servant, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_PointFromCoord(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + PointObj(*_impl_PointFromCoord) + (PortableServer_Servant _servant, + const CORBA_char * coord, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_View(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_View) (PortableServer_Servant + _servant, + const PointObj * where, + CORBA_Environment * + ev)); + void _ORBIT_skel_small_Map_ViewAll(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, + CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_ViewAll) + (PortableServer_Servant _servant, + const PointObjSequence * where, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_Route(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, CORBA_Context ctx, + CORBA_Environment * ev, + void (*_impl_Route) + (PortableServer_Servant _servant, + const PointObj * src, + const PointObj * dst, + CORBA_Environment * ev)); + void _ORBIT_skel_small_Map_Get(POA_Map * _ORBIT_servant, + gpointer _ORBIT_retval, + gpointer * _ORBIT_args, CORBA_Context ctx, + CORBA_Environment * ev, + Mappel(*_impl_Get) (PortableServer_Servant + _servant, + CORBA_Environment * + ev)); + +/** stub prototypes **/ + void Mappel_Test(Mappel _obj, CORBA_Environment * ev); + Map Map_mapString(Map _obj, const CORBA_char * astring, + CORBA_double * anum, CORBA_Environment * ev); + void Map_doNothing(Map _obj, CORBA_Environment * ev); + void Map_doOneWay(Map _obj, const CORBA_char * ignore, + CORBA_Environment * ev); + void Map_PlaceFlag(Map _obj, CORBA_Environment * ev); + PointObj Map_PointFromCoord(Map _obj, const CORBA_char * coord, + CORBA_Environment * ev); + void Map_View(Map _obj, const PointObj * where, CORBA_Environment * ev); + void Map_ViewAll(Map _obj, const PointObjSequence * where, + CORBA_Environment * ev); + void Map_Route(Map _obj, const PointObj * src, const PointObj * dst, + CORBA_Environment * ev); + Mappel Map_Get(Map _obj, CORBA_Environment * ev); +#include + +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + ORBit_IInterface Mappel__iinterface; +#define Mappel_IMETHODS_LEN 1 +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + ORBit_IMethod Mappel__imethods[Mappel_IMETHODS_LEN]; +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + ORBit_IInterface Map__iinterface; +#define Map_IMETHODS_LEN 9 +#ifdef ORBIT_IDL_C_IMODULE_map + static +#else + extern +#endif + ORBit_IMethod Map__imethods[Map_IMETHODS_LEN]; +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifndef EXCLUDE_ORBIT_H +#include + +#endif /* EXCLUDE_ORBIT_H */ +#endif +#undef ORBIT_IDL_SERIAL diff --git a/map.idl b/map.idl new file mode 100644 index 00000000..a68c7d54 --- /dev/null +++ b/map.idl @@ -0,0 +1,25 @@ +struct PointObj { + float lng; /* degrees */ + float lat; /* degrees */ + float height; /* meters */ +}; + +typedef sequence PointObjSequence; + +interface Mappel { + void Test(); +}; + +interface Map { + Map mapString (in string astring, + out double anum); + void doNothing (); + oneway void doOneWay (in string ignore); + void PlaceFlag(); + PointObj PointFromCoord(in string coord); + void View(in PointObj where); + void ViewAll(in PointObjSequence where); + void Route(in PointObj src, in PointObj dst); + Mappel Get(); +}; + diff --git a/map.ior b/map.ior new file mode 100644 index 00000000..cb892efd --- /dev/null +++ b/map.ior @@ -0,0 +1 @@ +IOR:010f00000c00000049444c3a4d61703a312e3000030000000054424f540000000101020005000000554e495800736f630900000070636d617274696e00005f6d2c0000002f746d702f6f726269742d6d617274696e2f6c696e632d353830642d302d363264393631633861336164360000000000caaedfba58000000010102312c0000002f746d702f6f726269742d6d617274696e2f6c696e632d353830642d302d3632643936316338613361643600000000001c00000000000000ad20380865f02828dd29282828282828010000007c08e43c0100000048000000016c654202000000050000001c00000000000000ad20380865f02828dd29282828282828010000007c08e43c0100000014000000010f000001000105000000000901010000000000 diff --git a/map_data.c b/map_data.c new file mode 100644 index 00000000..cc384f03 --- /dev/null +++ b/map_data.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include "file.h" +#include "block.h" +#include "map_data.h" +#include "log.h" + +static struct map_data *load_map(char *dirname) +{ + int i,len=strlen(dirname); + char *filename[file_end]; + char file[len+16]; + struct map_data *data=g_new0(struct map_data,1); + + memset(filename, 0, sizeof(*filename)); + + filename[file_border_ply]="border.ply"; + filename[file_bridge_ply]="bridge.ply"; + filename[file_height_ply]="height.ply"; + filename[file_other_ply]="other.ply"; + filename[file_rail_ply]="rail.ply"; + filename[file_sea_ply]="sea.ply"; + filename[file_street_bti]="street.bti"; + filename[file_street_str]="street.str"; + filename[file_strname_stn]="strname.stn"; + filename[file_town_twn]="town.twn"; + filename[file_tunnel_ply]="tunnel.ply"; + filename[file_water_ply]="water.ply"; + filename[file_woodland_ply]="woodland.ply"; + + strcpy(file, dirname); + file[len]='/'; + for (i = 0 ; i < file_end ; i++) { + if (filename[i]) { + strcpy(file+len+1, filename[i]); + data->file[i]=file_create_caseinsensitive(file); + if (! data->file[i]) { + g_warning("Failed to load %s", file); + } + } + } + return data; +} + +struct map_data *load_maps(char *map) +{ + char *name; + void *hnd; + struct map_data *last,*ret; + int i; + + if (! map) + map=getenv("MAP_DATA"); + if (! map) + map="/opt/reiseplaner/travel/DE.map"; + + ret=load_map(map); + last=ret; + hnd=file_opendir(map); + if (hnd) { + while ((name=file_readdir(hnd))) { + if (!strcasecmp(name+strlen(name)-4,".smp")) { + char next_name[strlen(map)+strlen(name)+2]; + strcpy(next_name, map); + strcat(next_name, "/"); + strcat(next_name, name); + last->next=load_map(next_name); + last=last->next; + } + } + file_closedir(hnd); + } else { + g_warning("Unable to open Map Directory '%s'\n", map); + } + log_apply(ret, file_end); + +#if 0 + last=ret; + while (last) { + for (i = 0 ; i < file_end ; i++) { + if (last->file[i]) { + file_set_readonly(last->file[i]); + } + } + last=last->next; + } + *((int *)0)=0; +#endif + + return ret; +} + + +void +map_data_foreach(struct map_data *mdata, int file, struct transformation *t, int limit, + void(*func)(struct block_info *, unsigned char *, unsigned char *, void *), void *data) +{ + struct block_info blk_inf; + + memset(&blk_inf, 0, sizeof(blk_inf)); + + while (mdata) { + if (mdata->file[file]) { + blk_inf.mdata=mdata; + blk_inf.file=mdata->file[file]; + block_foreach_visible(&blk_inf, t, limit, data, func); + } + mdata=mdata->next; + } +} diff --git a/map_data.h b/map_data.h new file mode 100644 index 00000000..a38bd085 --- /dev/null +++ b/map_data.h @@ -0,0 +1,30 @@ + +enum file_index { + file_border_ply=0, + file_bridge_ply, + file_height_ply, + file_other_ply, + file_rail_ply, + file_sea_ply, + file_street_bti, + file_street_str, + file_strname_stn, + file_town_twn, + file_tunnel_ply, + file_water_ply, + file_woodland_ply, + file_end +}; + +struct map_data { + struct file *file[file_end]; + struct map_data *next; +}; + +struct map_data *load_maps(char *map); + +struct transformation; +struct block_info; + +void map_data_foreach(struct map_data *mdata, int file, struct transformation *t, int limit, + void(*func)(struct block_info *, unsigned char *, unsigned char *, void *), void *data); diff --git a/mapclient.c b/mapclient.c new file mode 100644 index 00000000..056510fd --- /dev/null +++ b/mapclient.c @@ -0,0 +1,103 @@ +/* + * CORBA map test + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Elliot Lee + */ +#include +#include +#include + +#include "map.h" + + +#define ABORT_IF_EXCEPTION(_ev, _message) \ +if ((_ev)->_major != CORBA_NO_EXCEPTION) { \ + g_error("%s: %s", _message, CORBA_exception_id (_ev)); \ + CORBA_exception_free (_ev); \ + abort(); \ +} + +Map map_client, bec; +Mappel mappel; + +gboolean map_opt_quiet = FALSE; + +int main(int argc, char *argv[]) +{ + CORBA_Environment ev; + CORBA_ORB orb; + char buf[1024]; + FILE *ior; + PointObj pnt,src,dst; + + ior=fopen("map.ior","r"); + if (ior) { + fread(buf,1024,1,ior); + fclose(ior); + } + CORBA_exception_init(&ev); + orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); + + + /* bind to object */ + map_client = CORBA_ORB_string_to_object(orb, buf, &ev); + ABORT_IF_EXCEPTION(&ev, "cannot bind to object"); + g_assert(map_client != NULL); + +#if 0 + /* Method call without any argument, usefull to tell + * lifeness */ + Map_doNothing(map_client, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + + Map_PlaceFlag(map_client, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); +#endif + + if (argc > 0) { + if (!strcmp(argv[1],"--view")) { + pnt=Map_PointFromCoord(map_client, argv[2], &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + Map_View(map_client, &pnt, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + } + if (!strcmp(argv[1],"--route")) { + src=Map_PointFromCoord(map_client, argv[2], &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + dst=Map_PointFromCoord(map_client, argv[3], &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + Map_Route(map_client, &src, &dst, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + } + mappel=Map_Get(map_client, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + } + + /* release initial object reference */ + CORBA_Object_release(map_client, &ev); + ABORT_IF_EXCEPTION(&ev, "service raised exception "); + + /* shutdown ORB, shutdown IO channels */ + CORBA_ORB_shutdown(orb, FALSE, &ev); + ABORT_IF_EXCEPTION(&ev, "ORB shutdown ..."); + + /* destroy local ORB */ + CORBA_ORB_destroy(orb, &ev); + ABORT_IF_EXCEPTION(&ev, "destroying local ORB raised exception"); + + return 0; +} diff --git a/menu.c b/menu.c new file mode 100644 index 00000000..e694f82a --- /dev/null +++ b/menu.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include "coord.h" +#include "data_window.h" +#include "route.h" +#include "cursor.h" +#include "menu.h" +#include "command.h" +#include "transform.h" +#include "street.h" +#include "statusbar.h" +#include "destination.h" +#include "main.h" +#include "container.h" + +void +menu_route_do_update(struct container *co) +{ + if (co->cursor) { + route_set_position(co->route, cursor_pos_get(co->cursor)); + graphics_redraw(co); + if (co->statusbar && co->statusbar->statusbar_route_update) + co->statusbar->statusbar_route_update(co->statusbar, co->route); + } +} + +void +menu_route_update(struct container *co) +{ + menu_route_do_update(co); + graphics_redraw(co); +} diff --git a/menu.h b/menu.h new file mode 100644 index 00000000..51b24729 --- /dev/null +++ b/menu.h @@ -0,0 +1,8 @@ +struct menu { + struct menu_gui *gui; +}; + +struct container; + +void menu_route_do_update(struct container *co); +void menu_route_update(struct container *co); diff --git a/navigation.c b/navigation.c new file mode 100644 index 00000000..feb9e385 --- /dev/null +++ b/navigation.c @@ -0,0 +1,249 @@ +#include +#include +#include "coord.h" +#include "param.h" +#include "block.h" +#include "route.h" +#include "street.h" +#include "street_name.h" +#include "speech.h" +#include "navigation.h" +#include "data_window.h" + +struct data_window *navigation_window; + +static int +road_angle(struct coord *c, int dir) +{ + double angle; + int dx=c[1].x-c[0].x; + int dy=c[1].y-c[0].y; + angle=atan2(dx,dy); + angle*=180/M_PI; + if (dir == -1) + angle=angle-180; + if (angle < 0) + angle+=360; + return angle; +} + +static void +expand_str(char *str) +{ + int len=strlen(str); + if (len > 4 && !strcmp(str+len-4,"str.")) + strcpy(str+len-4,"strasse"); + if (len > 4 && !strcmp(str+len-4,"Str.")) + strcpy(str+len-4,"Strasse"); +} + +struct navigation_item { + char name1[128]; + char name2[128]; + int length; + int time; + int crossings_start; + int crossings_end; + int angle_start; + int angle_end; + int points; + struct coord start; + struct coord end; +}; + +void +navigation_goto(struct data_window *navigation_window, char **cols) +{ + extern struct container *co; + unsigned long scale; + long x,y; + + printf("goto %s\n",cols[8]); + sscanf(cols[8],"%lx,%lx",&x,&y); + graphics_set_view(co, &x, &y, NULL); +} + +int +is_same_street(struct navigation_item *old, struct navigation_item *new) +{ + if (strlen(old->name2) && !strcmp(old->name2, new->name2)) { + strcpy(old->name1, new->name1); + return 1; + } + if (strlen(old->name1) && !strcmp(old->name1, new->name1)) { + strcpy(old->name2, new->name2); + return 1; + } + return 0; +} + +int +maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta) +{ + if (is_same_street(old, new)) + return 0; + if (old->crossings_end == 2) + return 0; + *delta=new->angle_start-old->angle_end; + if (*delta < -180) + *delta+=360; + if (*delta > 180) + *delta-=360; + if (*delta < 20 && *delta >-20) + return 0; + return 1; +} + +int flag; +extern void *speech_handle; + +void +make_maneuver(struct navigation_item *old, struct navigation_item *new) +{ + + int delta; + struct param_list param_list[20]; + + char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30]; + char command[256],*p,*dir; + + param_list[0].name="Name1 Old"; + param_list[0].value=old->name1; + param_list[1].name="Name2 Old"; + param_list[1].value=old->name2; + param_list[2].name="Name1 New"; + param_list[2].value=new->name1; + param_list[3].name="Name2 New"; + param_list[3].value=new->name2; + param_list[4].name="Angle Old"; + param_list[5].name="Angle New"; + param_list[6].name="Delta"; + param_list[7].name="Cross-Roads"; + param_list[8].name="Position"; + param_list[9].name="Command"; + if (old->points) { + if (!maneuver_required(old, new, &delta)) { + old->length+=new->length; + old->time+=new->time; + old->crossings_end=new->crossings_end; + old->angle_end=new->angle_end; + old->points+=new->points; + } else { + sprintf(angle_old,"%d", old->angle_end); + param_list[4].value=angle_old; + sprintf(angle_new,"%d", new->angle_start); + param_list[5].value=angle_new; + sprintf(angle_delta,"%d", delta); + param_list[6].value=angle_delta; + sprintf(cross_roads,"%d", old->crossings_end); + param_list[7].value=cross_roads; + sprintf(position,"0x%lx,0x%lx", new->start.x, new->start.y); + param_list[8].value=position; + sprintf(command,"Dem Strassenverlauf %d Meter folgen, dann ", old->length); + p=command+strlen(command); + dir="rechts"; + if (delta < 0) { + dir="links"; + delta=-delta; + } + if (delta < 45) { + strcpy(p,"leicht "); + } else if (delta < 105) { + } else if (delta < 165) { + strcpy(p,"scharf "); + } + p+=strlen(p); + strcpy(p,dir); + p+=strlen(p); + strcpy(p," abbiegen"); + param_list[9].value=command; + if (flag) { + printf("command='%s'\n", command); +#if 0 + speech_say(speech_handle, command); +#endif + flag=0; + } + data_window_add(navigation_window, param_list, 10); + *old=*new; + } + } else { + *old=*new; + } +} + +void +navigation_path_description(void *route) +{ + int id; + struct route_path_segment *curr=route_path_get_all(route); + struct block_info blk_inf; + struct street_str *str; + struct street_name name; + struct street_coord *coord; + struct map_data *mdata=route_mapdata_get(route); + struct coord *start,*end,*tmp; + int angle_start, angle_end, angle_tmp; + struct route_crossings *crossings_start,*crossings_end; + struct navigation_item item_curr,item_last; + + memset(&item_last,0,sizeof(item_last)); + + if (!navigation_window) + navigation_window=data_window("Navigation",NULL,navigation_goto); + data_window_begin(navigation_window); + flag=1; + while (curr) { + str=NULL; + id=curr->segid; + if (id) { + if (id < 0) + id=-id; + street_get_by_id(mdata, id, &blk_inf, &str); + coord=street_coord_get(&blk_inf, str); + start=coord->c; + end=coord->c+coord->count-1; + angle_start=road_angle(coord->c, curr->dir); + if (coord->count > 2) + angle_end=road_angle(coord->c+coord->count-2,curr->dir); + else + angle_end=angle_start; + if (curr->dir < 0) { + tmp=start; + angle_tmp=angle_start; + start=end; + angle_start=angle_end; + end=tmp; + angle_end=angle_tmp; + } + crossings_start=route_crossings_get(route, start); + crossings_end=route_crossings_get(route, end); + if (str && str->nameid) { + street_name_get_by_id(&name, blk_inf.mdata, str->nameid); + strcpy(item_curr.name1,name.name1); + strcpy(item_curr.name2,name.name2); + expand_str(item_curr.name1); + expand_str(item_curr.name2); + } else { + item_curr.name1[0]='\0'; + item_curr.name2[0]='\0'; + } + item_curr.length=curr->length; + item_curr.time=curr->time; + item_curr.crossings_start=crossings_start->count; + item_curr.crossings_end=crossings_end->count; + item_curr.angle_start=angle_start; + item_curr.angle_end=angle_end; + item_curr.points=coord->count; + item_curr.start=*start; + item_curr.end=*end; + make_maneuver(&item_last,&item_curr); + free(coord); + free(crossings_start); + free(crossings_end); + } + curr=curr->next; + } + data_window_end(navigation_window); +} + diff --git a/navigation.h b/navigation.h new file mode 100644 index 00000000..ae39528f --- /dev/null +++ b/navigation.h @@ -0,0 +1 @@ +void navigation_path_description(void *route); diff --git a/param.c b/param.c new file mode 100644 index 00000000..0b3296e3 --- /dev/null +++ b/param.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include "param.h" + +void +param_add_string(char *name, char *value, struct param_list **param, int *count) +{ + if (*count > 0) { + (*param)->name=malloc(strlen(value)+strlen(name)+2); + (*param)->value=(*param)->name+strlen(name)+1; + strcpy((*param)->name, name); + strcpy((*param)->value, value); + (*count)--; + (*param)++; + } + +} + +void +param_add_dec(char *name, unsigned long value, struct param_list **param, int *count) +{ + char buffer[1024]; + sprintf(buffer, "%ld", value); + param_add_string(name, buffer, param, count); +} + + +void +param_add_hex(char *name, unsigned long value, struct param_list **param, int *count) +{ + char buffer[1024]; + sprintf(buffer, "0x%lx", value); + param_add_string(name, buffer, param, count); +} + +void +param_add_hex_sig(char *name, long value, struct param_list **param, int *count) +{ + char buffer[1024]; + if (value < 0) + sprintf(buffer, "-0x%lx", -value); + else + sprintf(buffer, "0x%lx", value); + param_add_string(name, buffer, param, count); +} diff --git a/param.h b/param.h new file mode 100644 index 00000000..496c0542 --- /dev/null +++ b/param.h @@ -0,0 +1,9 @@ +struct param_list { + char *name; + char *value; +}; + +void param_add_string(char *name, char *value, struct param_list **param, int *count); +void param_add_dec(char *name, unsigned long value, struct param_list **param, int *count); +void param_add_hex(char *name, unsigned long value, struct param_list **param, int *count); +void param_add_hex_sig(char *name, long value, struct param_list **param, int *count); diff --git a/phrase.c b/phrase.c new file mode 100644 index 00000000..92f6e7c3 --- /dev/null +++ b/phrase.c @@ -0,0 +1,25 @@ +#include +#include "coord.h" +#include "route.h" +#include "speech.h" + +void +phrase_route_calc(void *speech) +{ + if (! speech) + return; + speech_say(speech,"Die Route wird berechnet\n"); +} + +void +phrase_route_calculated(void *speech, void *route) +{ + struct tm *eta; + if (! speech) + return; + + eta=route_get_eta(route); + + speech_sayf(speech,"Die Route wurde berechnet. Geschätzte Ankunftszeit %d Uhr %d Entfernung %4.0f Kilometer", eta->tm_hour,eta->tm_min,route_get_len(route)/1000); + +} diff --git a/phrase.h b/phrase.h new file mode 100644 index 00000000..9f357388 --- /dev/null +++ b/phrase.h @@ -0,0 +1,2 @@ +void phrase_route_calc(void *speech); +void phrase_route_calculated(void *speech, void *route); diff --git a/plugin.c b/plugin.c new file mode 100644 index 00000000..d5c182b5 --- /dev/null +++ b/plugin.c @@ -0,0 +1,21 @@ +#include +#include +#include "plugin.h" +#define PLUGIN_C +#include "plugin.h" + +void +plugin_load(void) +{ + char *plugin="plugins/poi_geodownload/plugin_poi_geodownload.so"; + void *h=dlopen(plugin,RTLD_LAZY); + void (*init)(void); + + if (! h) + printf("can't load '%s', Error '%s'\n", plugin, dlerror()); + else { + init=dlsym(h,"plugin_init"); + (*init)(); + } + +} diff --git a/plugin.h b/plugin.h new file mode 100644 index 00000000..84e0845d --- /dev/null +++ b/plugin.h @@ -0,0 +1,56 @@ +void plugin_load(void); +int plugin_init(void); + +struct container; +struct popup; +struct popup_item; +#undef PLUGIN_FUNC1 +#undef PLUGIN_FUNC3 +#undef PLUGIN_FUNC4 +#define PLUGIN_PROTO(name,args...) void name(args) + +#ifdef PLUGIN_C +#define PLUGIN_REGISTER(name,args...) \ +void \ +plugin_register_##name(PLUGIN_PROTO((*func),args)) \ +{ \ + plugin_##name##_func=func; \ +} + +#define PLUGIN_CALL(name,args...) \ +{ \ + if (plugin_##name##_func) \ + (*plugin_##name##_func)(args); \ +} + +#define PLUGIN_FUNC1(name,t1,p1) \ +PLUGIN_PROTO((*plugin_##name##_func),t1 p1); \ +void plugin_call_##name(t1 p1) PLUGIN_CALL(name,p1) \ +PLUGIN_REGISTER(name,t1 p1) + +#define PLUGIN_FUNC3(name,t1,p1,t2,p2,t3,p3) \ +PLUGIN_PROTO((*plugin_##name##_func),t1 p1,t2 p2,t3 p3); \ +void plugin_call_##name(t1 p1,t2 p2, t3 p3) PLUGIN_CALL(name,p1,p2,p3) \ +PLUGIN_REGISTER(name,t1 p1,t2 p2,t3 p3) + +#define PLUGIN_FUNC4(name,t1,p1,t2,p2,t3,p3,t4,p4) \ +PLUGIN_PROTO((*plugin_##name##_func),t1 p1,t2 p2,t3 p3,t4 p4); \ +void plugin_call_##name(t1 p1,t2 p2, t3 p3, t4 p4) PLUGIN_CALL(name,p1,p2,p3,p4) \ +PLUGIN_REGISTER(name,t1 p1,t2 p2,t3 p3,t4 p4) + +#else +#define PLUGIN_FUNC1(name,t1,p1) \ +void plugin_register_##name(void(*func)(t1 p1)); \ +void plugin_call_##name(t1 p1); + +#define PLUGIN_FUNC3(name,t1,p1,t2,p2,t3,p3) \ +void plugin_register_##name(void(*func)(t1 p1,t2 p2,t3 p3)); \ +void plugin_call_##name(t1 p1,t2 p2,t3 p3); + +#define PLUGIN_FUNC4(name,t1,p1,t2,p2,t3,p3,t4,p4) \ +void plugin_register_##name(void(*func)(t1 p1,t2 p2,t3 p3,t4 p4)); \ +void plugin_call_##name(t1 p1,t2 p2,t3 p3,t4 p4); +#endif + +PLUGIN_FUNC1(draw, struct container *, co) +PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) diff --git a/plugins/poi_geodownload/libmdb/backend.c b/plugins/poi_geodownload/libmdb/backend.c new file mode 100644 index 00000000..e90f807b --- /dev/null +++ b/plugins/poi_geodownload/libmdb/backend.c @@ -0,0 +1,301 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* +** functions to deal with different backend database engines +*/ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +static int is_init; +static GHashTable *mdb_backends; + + /* Access data types */ +static MdbBackendType mdb_access_types[] = { + {"Unknown 0x00", 0,0,0 }, + {"Boolean", 0,0,0}, + {"Byte", 0,0,0}, + {"Integer", 0,0,0}, + {"Long Integer", 0,0,0}, + {"Currency", 0,0,0}, + {"Single", 0,0,0}, + {"Double", 0,0,0}, + {"DateTime (Short)", 0,0,1}, + {"Unknown 0x09", 0,0,0}, + {"Text", 1,0,1}, + {"OLE", 1,0,1}, + {"Memo/Hyperlink",1,0,1}, + {"Unknown 0x0d",0,0,0}, + {"Unknown 0x0e",0,0,0}, + {"Replication ID",0,0,0}, + {"Numeric",1,1,0} +}; + +/* Oracle data types */ +static MdbBackendType mdb_oracle_types[] = { + {"Oracle_Unknown 0x00",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"FLOAT",0,0,0}, + {"FLOAT",0,0,0}, + {"DATE",0,0,0}, + {"Oracle_Unknown 0x09",0,0,0}, + {"VARCHAR2",1,0,1}, + {"BLOB",1,0,1}, + {"CLOB",1,0,1}, + {"Oracle_Unknown 0x0d",0,0,0}, + {"Oracle_Unknown 0x0e",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, +}; + +/* Sybase/MSSQL data types */ +static MdbBackendType mdb_sybase_types[] = { + {"Sybase_Unknown 0x00",0,0,0}, + {"bit",0,0,0}, + {"char",1,0,1}, + {"smallint",0,0,0}, + {"int",0,0,0}, + {"money",0,0,0}, + {"real",0,0,0}, + {"float",0,0,0}, + {"smalldatetime",0,0,0}, + {"Sybase_Unknown 0x09",0,0,0}, + {"varchar",1,0,1}, + {"varbinary",1,0,1}, + {"text",1,0,1}, + {"Sybase_Unknown 0x0d",0,0,0}, + {"Sybase_Unknown 0x0e",0,0,0}, + {"Sybase_Replication ID",0,0,0}, + {"numeric",1,1,0}, +}; + +/* Postgres data types */ +static MdbBackendType mdb_postgres_types[] = { + {"Postgres_Unknown 0x00",0,0,0}, + {"Bool",0,0,0}, + {"Int2",0,0,0}, + {"Int4",0,0,0}, + {"Int8",0,0,0}, + {"Money",0,0,0}, + {"Float4",0,0,0}, + {"Float8",0,0,0}, + {"Timestamp",0,0,0}, + {"Postgres_Unknown 0x09",0,0,0}, + {"Char",1,0,1}, + {"Postgres_Unknown 0x0b",0,0,0}, + {"Postgres_Unknown 0x0c",0,0,0}, + {"Postgres_Unknown 0x0d",0,0,0}, + {"Postgres_Unknown 0x0e",0,0,0}, + {"Serial",0,0,0}, + {"Postgres_Unknown 0x10",0,0,0}, +}; +/* MySQL data types */ +static MdbBackendType mdb_mysql_types[] = { + {"Text",1,0,1}, + {"char",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"date",0,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"text",1,0,1}, + {"blob",0,0,0}, + {"text",1,0,1}, + {"numeric",1,1,0}, + {"numeric",1,1,0}, +}; + +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); + +char *mdb_get_coltype_string(MdbBackend *backend, int col_type) +{ + static char buf[16]; + + if (col_type > 0x10 ) { + // return NULL; + snprintf(buf,sizeof(buf), "type %04x", col_type); + return buf; + } else { + return backend->types_table[col_type].name; + } +} + +int mdb_coltype_takes_length(MdbBackend *backend, int col_type) +{ + return backend->types_table[col_type].needs_length; +} + +/** + * mdb_init_backends + * + * Initializes the mdb_backends hash and loads the builtin backends. + * Use mdb_remove_backends() to destroy this hash when done. + */ +void mdb_init_backends() +{ + mdb_backends = g_hash_table_new(g_str_hash, g_str_equal); + + mdb_register_backend(mdb_access_types, "access"); + mdb_register_backend(mdb_sybase_types, "sybase"); + mdb_register_backend(mdb_oracle_types, "oracle"); + mdb_register_backend(mdb_postgres_types, "postgres"); + mdb_register_backend(mdb_mysql_types, "mysql"); +} +void mdb_register_backend(MdbBackendType *backend_type, char *backend_name) +{ + MdbBackend *backend = (MdbBackend *) g_malloc0(sizeof(MdbBackend)); + backend->types_table = backend_type; + g_hash_table_insert(mdb_backends, backend_name, backend); +} + +/** + * mdb_remove_backends + * + * Removes all entries from and destroys the mdb_backends hash. + */ +void mdb_remove_backends() +{ + g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL); + g_hash_table_destroy(mdb_backends); +} +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data) +{ + MdbBackend *backend = (MdbBackend *)value; + g_free (backend); + return TRUE; +} + +/** + * mdb_set_default_backend + * @mdb: Handle to open MDB database file + * @backend_name: Name of the backend to set as default + * + * Sets the default backend of the handle @mdb to @backend_name. + * + * Returns: 1 if successful, 0 if unsuccessful. + */ +int mdb_set_default_backend(MdbHandle *mdb, char *backend_name) +{ + MdbBackend *backend; + + backend = (MdbBackend *) g_hash_table_lookup(mdb_backends, backend_name); + if (backend) { + mdb->default_backend = backend; + mdb->backend_name = (char *) g_strdup(backend_name); + is_init = 0; + return 1; + } else { + return 0; + } +} + +/** + * mdb_get_relationships + * @mdb: Handle to open MDB database file + * + * Generates relationships by reading the MSysRelationships table. + * 'szColumn' contains the column name of the child table. + * 'szObject' contains the table name of the child table. + * 'szReferencedColumn' contains the column name of the parent table. + * 'szReferencedObject' contains the table name of the parent table. + * + * Returns: a string stating that relationships are not supported for the + * selected backend, or a string containing SQL commands for setting up + * the relationship, tailored for the selected backend. The caller is + * responsible for freeing this string. + */ +char *mdb_get_relationships(MdbHandle *mdb) +{ + unsigned int i; + gchar *text = NULL; /* String to be returned */ + static char *bound[4]; /* Bound values */ + static MdbTableDef *table; /* Relationships table */ + int backend = 0; /* Backends: 1=oracle */ + + if (strncmp(mdb->backend_name,"oracle",6) == 0) { + backend = 1; + } else { + if (is_init == 0) { /* the first time through */ + is_init = 1; + return (char *) g_strconcat( + "-- relationships are not supported for ", + mdb->backend_name, NULL); + } else { /* the second time through */ + is_init = 0; + return NULL; + } + } + + if (is_init == 0) { + table = mdb_read_table_by_name(mdb, "MSysRelationships", MDB_TABLE); + if ((!table) || (table->num_rows == 0)) { + return NULL; + } + + mdb_read_columns(table); + for (i=0;i<4;i++) { + bound[i] = (char *) g_malloc0(MDB_BIND_SIZE); + } + mdb_bind_column_by_name(table, "szColumn", bound[0]); + mdb_bind_column_by_name(table, "szObject", bound[1]); + mdb_bind_column_by_name(table, "szReferencedColumn", bound[2]); + mdb_bind_column_by_name(table, "szReferencedObject", bound[3]); + mdb_rewind_table(table); + + is_init = 1; + } + else if (table->cur_row >= table->num_rows) { /* past the last row */ + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + if (!mdb_fetch_row(table)) { + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + switch (backend) { + case 1: /* oracle */ + text = g_strconcat("alter table ", bound[1], + " add constraint ", bound[3], "_", bound[1], + " foreign key (", bound[0], ")" + " references ", bound[3], "(", bound[2], ")", NULL); + break; + } + + return (char *)text; +} + diff --git a/plugins/poi_geodownload/libmdb/catalog.c b/plugins/poi_geodownload/libmdb/catalog.c new file mode 100644 index 00000000..dc08abdd --- /dev/null +++ b/plugins/poi_geodownload/libmdb/catalog.c @@ -0,0 +1,138 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +char * +mdb_get_objtype_string(int obj_type) +{ +static char *type_name[] = {"Form", + "Table", + "Macro", + "System Table", + "Report", + "Query", + "Linked Table", + "Module", + "Relationship", + "Unknown 0x09", + "Unknown 0x0a", + "Database" + }; + + if (obj_type > 11) { + return NULL; + } else { + return type_name[obj_type]; + } +} + +void mdb_free_catalog(MdbHandle *mdb) +{ + unsigned int i; + + if (!mdb->catalog) return; + for (i=0; icatalog->len; i++) + g_free (g_ptr_array_index(mdb->catalog, i)); + g_ptr_array_free(mdb->catalog, TRUE); + mdb->catalog = NULL; +} + +GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype) +{ + MdbCatalogEntry *entry, msysobj; + MdbTableDef *table; + char obj_id[256]; + char obj_name[256]; + char obj_type[256]; + char obj_flags[256]; + int type; + + if (mdb->catalog) mdb_free_catalog(mdb); + mdb->catalog = g_ptr_array_new(); + mdb->num_catalog = 0; + + /* dummy up a catalog entry so we may read the table def */ + memset(&msysobj, 0, sizeof(MdbCatalogEntry)); + msysobj.mdb = mdb; + msysobj.object_type = MDB_TABLE; + msysobj.table_pg = 2; + strcpy(msysobj.object_name, "MSysObjects"); + + /* mdb_table_dump(&msysobj); */ + + table = mdb_read_table(&msysobj); + if (!table) return NULL; + + mdb_read_columns(table); + + mdb_bind_column_by_name(table, "Id", obj_id); + mdb_bind_column_by_name(table, "Name", obj_name); + mdb_bind_column_by_name(table, "Type", obj_type); + mdb_bind_column_by_name(table, "Flags", obj_flags); + + mdb_rewind_table(table); + + while (mdb_fetch_row(table)) { + type = atoi(obj_type); + if (objtype==MDB_ANY || type == objtype) { + // fprintf(stdout, "obj_id: %10ld objtype: %-3d obj_name: %s\n", + // (atol(obj_id) & 0x00FFFFFF), type, obj_name); + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + strcpy(entry->object_name, obj_name); + entry->object_type = (type & 0x7F); + entry->table_pg = atol(obj_id) & 0x00FFFFFF; + entry->flags = atol(obj_flags); + mdb->num_catalog++; + g_ptr_array_add(mdb->catalog, entry); + } + } + //mdb_dump_catalog(mdb, MDB_TABLE); + + mdb_free_tabledef(table); + + return mdb->catalog; +} + +void +mdb_dump_catalog(MdbHandle *mdb, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + if (obj_type==MDB_ANY || entry->object_type==obj_type) { + fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2d\n", + mdb_get_objtype_string(entry->object_type), + entry->object_name, + (unsigned int) entry->table_pg, + (unsigned int) entry->kkd_pg, + entry->kkd_rowid); + } + } + return; +} + diff --git a/plugins/poi_geodownload/libmdb/data.c b/plugins/poi_geodownload/libmdb/data.c new file mode 100644 index 00000000..e50e57db --- /dev/null +++ b/plugins/poi_geodownload/libmdb/data.c @@ -0,0 +1,856 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define OFFSET_MASK 0x1fff + +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s); +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, unsigned char isnull, int offset, int len); +static char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale); +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size); + +static char date_fmt[64] = "%x %X"; + +void mdb_set_date_fmt(const char *fmt) +{ + date_fmt[63] = 0; + strncpy(date_fmt, fmt, 63); +} + +void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr) +{ +MdbColumn *col; + + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter + */ + col=g_ptr_array_index(table->columns, col_num - 1); + col->bind_ptr = bind_ptr; +} +int +mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr) +{ + unsigned int i; + int col_num = -1; + MdbColumn *col; + + for (i=0;inum_cols;i++) { + col=g_ptr_array_index(table->columns,i); + if (!strcmp(col->name,col_name)) { + col_num = col->col_num + 1; + mdb_bind_column(table, col_num, bind_ptr); + break; + } + } + + return col_num; +} +void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr) +{ +MdbColumn *col; + + col=g_ptr_array_index(table->columns, col_num - 1); + col->len_ptr = len_ptr; +} + +/** + * mdb_find_pg_row + * @mdb: Database file handle + * @pg_row: Lower byte contains the row number, the upper three contain page + * @buf: Pointer for returning a pointer to the page + * @off: Pointer for returning an offset to the row + * @len: Pointer for returning the length of the row + * + * Returns: 0 on success. 1 on failure. + */ +int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len) +{ + unsigned int pg = pg_row >> 8; + unsigned int row = pg_row & 0xff; + + if (mdb_read_alt_pg(mdb, pg) != mdb->fmt->pg_size) + return 1; + mdb_swap_pgbuf(mdb); + *off = mdb_pg_get_int16(mdb, mdb->fmt->row_count_offset + 2 + (row*2)); + *len = mdb_find_end_of_row(mdb, row) - *off + 1; + mdb_swap_pgbuf(mdb); + *buf = mdb->alt_pg_buf; + return 0; +} + +int +mdb_find_end_of_row(MdbHandle *mdb, int row) +{ + MdbFormatConstants *fmt = mdb->fmt; + int row_end; + + /* Search the previous "row start" values for the first non-'lookupflag' one. + * If we don't find one, then the end of the page is the correct value. + */ +#if 1 + if (row==0) { + row_end = fmt->pg_size - 1; + } else { + row_end = (mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + (row - 1) * 2)) & OFFSET_MASK) - 1; + } + return row_end; +#else + int i, row_start; + + /* if lookupflag is not set, it's good (deleteflag is ok) */ + for (i = row - 1; i >= 0; i--) { + row_start = mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + i * 2)); + if (!(row_start & 0x8000)) { + break; + } + } + + if (i == -1) { + row_end = fmt->pg_size - 1; + } else { + row_end = (row_start & OFFSET_MASK) - 1; + } + return row_end; +#endif +} +int mdb_is_null(unsigned char *null_mask, int col_num) +{ +int byte_num = (col_num - 1) / 8; +int bit_num = (col_num - 1) % 8; + + if ((1 << bit_num) & null_mask[byte_num]) { + return 0; + } else { + return 1; + } +} +/* bool has to be handled specially because it uses the null bit to store its +** value*/ +static int +mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) +{ + + col->cur_value_len = value; + if (col->bind_ptr) { + strcpy(col->bind_ptr, value ? "0" : "1"); + } + + return 0; +} +static int mdb_xfer_bound_ole(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ + int ret = 0; + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr || col->len_ptr) { + //ret = mdb_copy_ole(mdb, col->bind_ptr, start, len); + memcpy(col->bind_ptr, &mdb->pg_buf[start], MDB_MEMO_OVERHEAD); + } + if (col->len_ptr) { + *col->len_ptr = MDB_MEMO_OVERHEAD; + } + return ret; +} +static int mdb_xfer_bound_data(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ +int ret; + //if (!strcmp("Name",col->name)) { + //printf("start %d %d\n",start, len); + //} + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr) { + if (!len) { + strcpy(col->bind_ptr, ""); + } else if (col->col_type == MDB_NUMERIC) { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_num_to_string(mdb, start, col->col_type, + col->col_prec, col->col_scale); + strcpy(col->bind_ptr, str); + g_free(str); + } else { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_col_to_string(mdb, mdb->pg_buf, start, + col->col_type, len); + strcpy(col->bind_ptr, str); + + } + ret = strlen(col->bind_ptr); + if (col->len_ptr) { + *col->len_ptr = ret; + } + return ret; + } + return 0; +} +int mdb_read_row(MdbTableDef *table, unsigned int row) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *col; + unsigned int i; + int rc; + int row_start, row_end; + int delflag, lookupflag; + MdbField fields[256]; + int num_fields; + + if (table->num_rows <= row) + return 0; + + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2)); + row_end = mdb_find_end_of_row(mdb, row); + + delflag = lookupflag = 0; + if (row_start & 0x8000) lookupflag++; + if (row_start & 0x4000) delflag++; + row_start &= OFFSET_MASK; /* remove flags */ +#if MDB_DEBUG + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + row, row_start, row_end, + lookupflag ? "[lookup]" : "", + delflag ? "[delflag]" : ""); +#endif + + if (!table->noskip_del && delflag) { + row_end = row_start-1; + return 0; + } + + num_fields = mdb_crack_row(table, row_start, row_end, fields); + if (!mdb_test_sargs(table, fields, num_fields)) return 0; + +#if MDB_DEBUG + fprintf(stdout,"sarg test passed row %d \n", row); +#endif + +#if MDB_DEBUG + buffer_dump(mdb->pg_buf, row_start, row_end); +#endif + + /* take advantage of mdb_crack_row() to clean up binding */ + /* use num_cols instead of num_fields -- bsb 03/04/02 */ + for (i = 0; i < table->num_cols; i++) { + col = g_ptr_array_index(table->columns,fields[i].colnum); + rc = _mdb_attempt_bind(mdb, col, fields[i].is_null, + fields[i].start, fields[i].siz); + } + + return 1; +} +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, + int len) +{ + if (col->col_type == MDB_BOOL) { + mdb_xfer_bound_bool(mdb, col, isnull); + } else if (isnull) { + mdb_xfer_bound_data(mdb, 0, col, 0); + } else if (col->col_type == MDB_OLE) { + mdb_xfer_bound_ole(mdb, offset, col, len); + } else { + //if (!mdb_test_sargs(mdb, col, offset, len)) { + //return 0; + //} + mdb_xfer_bound_data(mdb, offset, col, len); + } + return 1; +} +int mdb_read_next_dpg(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int next_pg; + +#ifndef SLOW_READ + next_pg = mdb_map_find_next(mdb, table->usage_map, + table->map_sz, table->cur_phys_pg); + + if (next_pg >= 0) { + if (mdb_read_pg(mdb, next_pg)) { + table->cur_phys_pg = next_pg; + return table->cur_phys_pg; + } else { + return 0; + } + } + fprintf(stderr, "Warning: defaulting to brute force read\n"); +#endif + /* can't do a fast read, go back to the old way */ + do { + if (!mdb_read_pg(mdb, table->cur_phys_pg++)) + return 0; + } while (mdb->pg_buf[0]!=0x01 || mdb_pg_get_int32(mdb, 4)!=entry->table_pg); + /* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */ + return table->cur_phys_pg; +} +int mdb_rewind_table(MdbTableDef *table) +{ + table->cur_pg_num=0; + table->cur_phys_pg=0; + table->cur_row=0; + + return 0; +} +int +mdb_fetch_row(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + unsigned int rows; + int rc; + guint32 pg; + + if (table->num_rows==0) + return 0; + + /* initialize */ + if (!table->cur_pg_num) { + table->cur_pg_num=1; + table->cur_row=0; + if ((!table->is_temp_table)&&(table->strategy!=MDB_INDEX_SCAN)) + if (!mdb_read_next_dpg(table)) return 0; + } + + do { + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + rows = mdb_get_int16( + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->row_count_offset); + if (table->cur_row >= rows) { + table->cur_row = 0; + table->cur_pg_num++; + if (table->cur_pg_num > pages->len) + return 0; + } + memcpy(mdb->pg_buf, + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->pg_size); + } else if (table->strategy==MDB_INDEX_SCAN) { + + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { + mdb_index_scan_free(table); + return 0; + } + mdb_read_pg(mdb, pg); + } else { + rows = mdb_pg_get_int16(mdb,fmt->row_count_offset); + + /* if at end of page, find a new page */ + if (table->cur_row >= rows) { + table->cur_row=0; + + if (!mdb_read_next_dpg(table)) { + return 0; + } + } + } + + /* printf("page %d row %d\n",table->cur_phys_pg, table->cur_row); */ + rc = mdb_read_row(table, table->cur_row); + table->cur_row++; + } while (!rc); + + return 1; +} +void mdb_data_dump(MdbTableDef *table) +{ + unsigned int i; + char *bound_values[MDB_MAX_COLS]; + + for (i=0;inum_cols;i++) { + bound_values[i] = (char *) g_malloc(256); + mdb_bind_column(table, i+1, bound_values[i]); + } + mdb_rewind_table(table); + while (mdb_fetch_row(table)) { + for (i=0;inum_cols;i++) { + fprintf(stdout, "column %d is %s\n", i+1, bound_values[i]); + } + } + for (i=0;inum_cols;i++) { + g_free(bound_values[i]); + } +} + +int mdb_is_fixed_col(MdbColumn *col) +{ + return col->is_fixed; +} +#if 0 +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +{ +int i; + + for (i=start; ipg_buf[i]); + } + text[(i-start)*2]='\0'; + + return text; +} +#endif +int +mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + + if (ole_flags == 0x8000) { + /* inline fields don't have a next */ + return 0; + } else if (ole_flags == 0x4000) { + /* 0x4000 flagged ole's are contained on one page and thus + * should be handled entirely with mdb_ole_read() */ + return 0; + } else if (ole_flags == 0x0000) { + pg_row = (col->cur_blob_pg << 8) & col->cur_blob_row; + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } + return 0; +} +int +mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %08x", + ole_len, ole_flags); + + col->chunk_size = chunk_size; + + if (ole_flags == 0x8000) { + /* inline ole field, if we can satisfy it, then do it */ + len = col->cur_value_len - MDB_MEMO_OVERHEAD; + if (chunk_size >= len) { + if (col->bind_ptr) + memcpy(col->bind_ptr, + &mdb->pg_buf[col->cur_value_start + + MDB_MEMO_OVERHEAD], + len); + return len; + } else { + return 0; + } + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld", + col->cur_blob_row, col->cur_blob_pg); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); + + if (col->bind_ptr) { + memcpy(col->bind_ptr, buf + row_start, len); + if (mdb_get_option(MDB_DEBUG_OLE)) + buffer_dump(col->bind_ptr, 0, 16); + } + return len; + } else if (ole_flags == 0x0000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size) +{ + guint16 ole_len; + guint16 ole_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + return len; + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest, buf + row_start, len); + return len; + } else if (ole_flags == 0x0000) { + int cur = 0; + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return 0; + } + + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest+cur, buf + row_start + 4, len - 4); + cur += len - 4; + + /* find next lval page */ + pg_row = mdb_get_int32(buf, row_start); + } while ((pg_row >> 8)); + return cur; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size) +{ + guint16 memo_len; + static char text[MDB_BIND_SIZE]; + guint16 memo_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf, start, start + 12); +#endif + + /* The 16 bit integer at offset 0 is the length of the memo field. + * The 32 bit integer at offset 4 contains page and row information. + */ + memo_len = mdb_pg_get_int16(mdb, start); + memo_flags = mdb_pg_get_int16(mdb, start+2); + + if (memo_flags & 0x8000) { + /* inline memo field */ + strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + text[size - MDB_MEMO_OVERHEAD]='\0'; + return text; + } else if (memo_flags & 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); + buffer_dump(mdb->pg_buf, row_start, row_start + len); +#endif + if (IS_JET3(mdb)) { + strncpy(text, buf + row_start, len); + text[len]='\0'; + } else { + mdb_unicode2ascii(mdb, buf, row_start, len, text); + } + return text; + } else { /* if (memo_flags == 0x0000) { */ + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + text[0]='\0'; + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); +#endif + strncat(text, buf + row_start + 4, + strlen(text) + len - 4 > MDB_BIND_SIZE ? + MDB_BIND_SIZE - strlen(text) : len - 4); + + /* find next lval page */ + pg_row = mdb_get_int32(mdb->pg_buf, row_start); + } while ((pg_row >> 8)); + return text; +/* + } else { + fprintf(stderr,"Unhandled memo field flags = %04x\n", memo_flags); + return ""; +*/ + } +} +static char * +mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale) +{ + char *text; + gint32 l; + + memcpy(&l, mdb->pg_buf+start+13, 4); + + text = (char *) g_malloc(prec+2); + sprintf(text, "%0*" G_GINT32_FORMAT, prec, GINT32_FROM_LE(l)); + if (scale) { + memmove(text+prec-scale, text+prec-scale+1, scale+1); + text[prec-scale] = '.'; + } + return text; +} + +static int trim_trailing_zeros(char * buff, int n) +{ + char * p = buff + n - 1; + + while (p >= buff && *p == '0') + *p-- = '\0'; + + if (*p == '.') + *p = '\0'; + + return 0; +} + +char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size) +{ + /* FIX ME -- not thread safe */ + static char text[MDB_BIND_SIZE]; + time_t t; + int n; + float tf; + double td; + + switch (datatype) { + case MDB_BOOL: + /* shouldn't happen. bools are handled specially + ** by mdb_xfer_bound_bool() */ + break; + case MDB_BYTE: + sprintf(text,"%d",mdb_get_byte(buf, start)); + return text; + break; + case MDB_INT: + sprintf(text,"%ld",(long)mdb_get_int16(buf, start)); + return text; + break; + case MDB_LONGINT: + sprintf(text,"%ld",mdb_get_int32(buf, start)); + return text; + break; + case MDB_FLOAT: + tf = mdb_get_single(mdb->pg_buf, start); + n = sprintf(text,"%.*f",FLT_DIG - (int)ceil(log10(tf)), tf); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_DOUBLE: + td = mdb_get_double(mdb->pg_buf, start); + n = sprintf(text,"%.*f",DBL_DIG - (int)ceil(log10(td)), td); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_TEXT: + if (size<0) { + return ""; + } + if (IS_JET4(mdb)) { +/* + int i; + for (i=0;ipg_buf[start+i], mdb->pg_buf[start+i]); + } + fprintf(stdout, "\n"); +*/ + mdb_unicode2ascii(mdb, mdb->pg_buf, start, size, text); + } else { + strncpy(text, &buf[start], size); + text[size]='\0'; + } + return text; + break; + case MDB_SDATETIME: + td = mdb_get_double(mdb->pg_buf, start); + if (td > 1) { + t = (long int)((td - 25569.0) * 86400.0); + } else { + t = (long int)(td * 86400.0); + } + strftime(text, MDB_BIND_SIZE, date_fmt, (struct tm*)gmtime(&t)); + return text; + + break; + case MDB_MEMO: + return mdb_memo_to_string(mdb, start, size); + break; + case MDB_MONEY: + mdb_money_to_string(mdb, start, text); + return text; + case MDB_NUMERIC: + break; + default: + return ""; + break; + } + return NULL; +} +int mdb_col_disp_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return 4; + break; + case MDB_INT: + return 6; + break; + case MDB_LONGINT: + return 11; + break; + case MDB_FLOAT: + return 10; + break; + case MDB_DOUBLE: + return 10; + break; + case MDB_TEXT: + return col->col_size; + break; + case MDB_SDATETIME: + return 20; + break; + case MDB_MEMO: + return 255; + break; + case MDB_MONEY: + return 21; + break; + } + return 0; +} +int mdb_col_fixed_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return -1; + break; + case MDB_INT: + return 2; + break; + case MDB_LONGINT: + return 4; + break; + case MDB_FLOAT: + return 4; + break; + case MDB_DOUBLE: + return 8; + break; + case MDB_TEXT: + return -1; + break; + case MDB_SDATETIME: + return 4; + break; + case MDB_MEMO: + return -1; + break; + case MDB_MONEY: + return 8; + break; + } + return 0; +} diff --git a/plugins/poi_geodownload/libmdb/dump.c b/plugins/poi_geodownload/libmdb/dump.c new file mode 100644 index 00000000..7ee17f9a --- /dev/null +++ b/plugins/poi_geodownload/libmdb/dump.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void buffer_dump(const unsigned char* buf, int start, int end) +{ + char asc[20]; + int j, k; + + memset(asc, 0, sizeof(asc)); + k = 0; + for (j=start; j<=end; j++) { + if (k == 0) { + fprintf(stdout, "%04x ", j); + } + fprintf(stdout, "%02x ", buf[j]); + asc[k] = isprint(buf[j]) ? buf[j] : '.'; + k++; + if (k == 8) { + fprintf(stdout, " "); + } + if (k == 16) { + fprintf(stdout, " %s\n", asc); + memset(asc, 0, sizeof(asc)); + k = 0; + } + } + for (j=k; j<16; j++) { + fprintf(stdout, " "); + } + if (k < 8) { + fprintf(stdout, " "); + } + fprintf(stdout, " %s\n", asc); +} diff --git a/plugins/poi_geodownload/libmdb/file.c b/plugins/poi_geodownload/libmdb/file.c new file mode 100644 index 00000000..941830c5 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/file.c @@ -0,0 +1,376 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; +*/ +MdbFormatConstants MdbJet4Constants = { + 4096, 0x0c, 16, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59, 7, 21, 9 +}; +MdbFormatConstants MdbJet3Constants = { + 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39, 3, 14, 5 /* not sure on 5, need to check */ +}; + +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg); + +/** + * mdb_find_file: + * @filename: path to MDB (database) file + * + * Finds and returns the absolute path to an MDB file. Function will first try + * to fstat file as passed, then search through the $MDBPATH if not found. + * + * Return value: gchar pointer to absolute path. Caller is responsible for + * freeing. + **/ + +static gchar *mdb_find_file(char *file_name) +{ + struct stat status; + gchar *mdbpath, **dir, *tmpfname; + unsigned int i = 0; + + /* try the provided file name first */ + if (!stat(file_name, &status)) { + return g_strdup(file_name); + } + + /* Now pull apart $MDBPATH and try those */ + mdbpath = (gchar *) getenv("MDBPATH"); + /* no path, can't find file */ + if (!mdbpath || !strlen(mdbpath)) return NULL; + + dir = g_strsplit(mdbpath, ":", 0); + while (dir[i]) { + if (!strlen(dir[i])) continue; + tmpfname = g_strconcat(dir[i++], "/", file_name, NULL); + if (!stat(tmpfname, &status)) { + g_strfreev(dir); + return tmpfname; + } + g_free(tmpfname); + } + g_strfreev(dir); + return NULL; +} +/** + * mdb_open: + * @filename: path to MDB (database) file + * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write + * + * Opens an MDB file and returns an MdbHandle to it. MDB File may be relative + * to the current directory, a full path to the file, or relative to a + * component of $MDBPATH. + * + * Return value: pointer to MdbHandle structure. + **/ +MdbHandle *mdb_open(char *filename, MdbFileFlags flags) +{ + MdbHandle *mdb; + + mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle)); + mdb_set_default_backend(mdb, "access"); + /* need something to bootstrap with, reassign after page 0 is read */ + mdb->fmt = &MdbJet3Constants; + mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile)); + mdb->f->refs = 1; + mdb->f->fd = -1; + mdb->f->filename = (char *) mdb_find_file(filename); + if (!mdb->f->filename) { + fprintf(stderr, "Can't alloc filename\n"); + mdb_close(mdb); + return NULL; + } + if (flags & MDB_WRITABLE) { + mdb->f->writable = TRUE; + mdb->f->fd = open(mdb->f->filename,O_RDWR); + } else { + mdb->f->fd = open(mdb->f->filename,O_RDONLY); + } + + if (mdb->f->fd==-1) { + fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); + mdb_close(mdb); + return NULL; + } + if (!mdb_read_pg(mdb, 0)) { + fprintf(stderr,"Couldn't read first page.\n"); + mdb_close(mdb); + return NULL; + } + if (mdb->pg_buf[0] != 0) { + mdb_close(mdb); + return NULL; + } + mdb->f->jet_version = mdb_pg_get_int32(mdb, 0x14); + if (IS_JET4(mdb)) { + mdb->fmt = &MdbJet4Constants; + } else if (IS_JET3(mdb)) { + mdb->fmt = &MdbJet3Constants; + } else { + fprintf(stderr,"Unknown Jet version.\n"); + mdb_close(mdb); + return NULL; + } + + return mdb; +} + +/** + * mdb_close: + * @mdb: Handle to open MDB database file + * + * Dereferences MDB file, closes if reference count is 0, and destroys handle. + * + **/ +void +mdb_close(MdbHandle *mdb) +{ + if (!mdb) return; + mdb_free_catalog(mdb); + g_free(mdb->stats); + g_free(mdb->backend_name); + + if (mdb->f) { + if (mdb->f->refs > 1) { + mdb->f->refs--; + } else { + if (mdb->f->fd != -1) close(mdb->f->fd); + g_free(mdb->f->filename); + g_free(mdb->f); + } + } + + g_free(mdb); +} +/** + * mdb_clone_handle: + * @mdb: Handle to open MDB database file + * + * Clones an existing database handle. Cloned handle shares the file descriptor + * but has its own page buffer, page position, and similar internal variables. + * + * Return value: new handle to the database. + */ +MdbHandle *mdb_clone_handle(MdbHandle *mdb) +{ + MdbHandle *newmdb; + MdbCatalogEntry *entry, *data; + unsigned int i; + + newmdb = (MdbHandle *) g_memdup(mdb, sizeof(MdbHandle)); + newmdb->stats = NULL; + newmdb->catalog = g_ptr_array_new(); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + data = g_memdup(entry,sizeof(MdbCatalogEntry)); + g_ptr_array_add(newmdb->catalog, data); + } + mdb->backend_name = NULL; + if (mdb->f) { + mdb->f->refs++; + } + return newmdb; +} + +/* +** mdb_read a wrapper for read that bails if anything is wrong +*/ +ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + if (pg && mdb->cur_pg == pg) return mdb->fmt->pg_size; + + len = _mdb_read_pg(mdb, mdb->pg_buf, pg); + //fprintf(stderr, "read page %d type %02x\n", pg, mdb->pg_buf[0]); + mdb->cur_pg = pg; + /* kan - reset the cur_pos on a new page read */ + mdb->cur_pos = 0; /* kan */ + return len; +} +ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + len = _mdb_read_pg(mdb, mdb->alt_pg_buf, pg); + return len; +} +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + if (status.st_size < offset) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + if (mdb->stats && mdb->stats->collect) + mdb->stats->pg_reads++; + + lseek(mdb->f->fd, offset, SEEK_SET); + len = read(mdb->f->fd,pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("read"); + return 0; + } + else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->fmt->pg_size); */ + return 0; + } + return len; +} +void mdb_swap_pgbuf(MdbHandle *mdb) +{ +char tmpbuf[MDB_PGSIZE]; + + memcpy(tmpbuf,mdb->pg_buf, MDB_PGSIZE); + memcpy(mdb->pg_buf,mdb->alt_pg_buf, MDB_PGSIZE); + memcpy(mdb->alt_pg_buf,tmpbuf,MDB_PGSIZE); +} + + +/* really stupid, just here for consistancy */ +unsigned char mdb_get_byte(unsigned char *buf, int offset) +{ + return buf[offset]; +} +unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+1 > mdb->fmt->pg_size) return -1; + mdb->cur_pos++; + return mdb->pg_buf[offset]; +} + +int mdb_get_int16(unsigned char *buf, int offset) +{ + return buf[offset+1]*256+buf[offset]; +} +int mdb_pg_get_int16(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+2 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=2; + return mdb_get_int16(mdb->pg_buf, offset); +} + +gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset) +{ + gint32 l = 0; + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + memcpy((char *)&l+1, &(mdb->pg_buf[offset]), 3); +#if 0 + printf("l=0x%08x 0x%08x\n",l,GINT32_FROM_BE(l)); +#endif + return GINT32_FROM_BE(l); +} +gint32 mdb_get_int24(unsigned char *buf, int offset) +{ + gint32 l = 0; + memcpy(&l, &buf[offset], 3); + return GINT32_FROM_LE(l); +} +gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + return mdb_get_int24(mdb->pg_buf, offset); +} + +long mdb_get_int32(unsigned char *buf, int offset) +{ + guint32 l; + memcpy(&l, &buf[offset], 4); + return (long)GINT32_FROM_LE(l); +} +long mdb_pg_get_int32(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_int32(mdb->pg_buf, offset); +} + +float mdb_get_single(unsigned char *buf, int offset) +{ + union {guint32 g; float f;} f; + memcpy(&f, &buf[offset], 4); + f.g = GUINT32_FROM_LE(f.g); + return f.f; +} +float mdb_pg_get_single(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_single(mdb->pg_buf, offset); +} + +double mdb_get_double(unsigned char *buf, int offset) +{ + union {guint64 g; double d;} d; + memcpy(&d, &buf[offset], 8); + d.g = GUINT64_FROM_LE(d.g); + return d.d; +} +double mdb_pg_get_double(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=8; + return mdb_get_double(mdb->pg_buf, offset); +} + + +int +mdb_set_pos(MdbHandle *mdb, int pos) +{ + if (pos<0 || pos >= mdb->fmt->pg_size) return 0; + + mdb->cur_pos=pos; + return pos; +} +int mdb_get_pos(MdbHandle *mdb) +{ + return mdb->cur_pos; +} diff --git a/plugins/poi_geodownload/libmdb/iconv.c b/plugins/poi_geodownload/libmdb/iconv.c new file mode 100644 index 00000000..9f41afe3 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/iconv.c @@ -0,0 +1,63 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +int +mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest) +{ + unsigned int i; + + if (buf[offset]==0xff && buf[offset+1]==0xfe) { + strncpy(dest, &buf[offset+2], len-2); + dest[len-2]='\0'; + } else { + /* convert unicode to ascii, rather sloppily */ + for (i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ICONV +#include +#endif + +#define MDB_DEBUG 0 + +#define MDB_PGSIZE 4096 +#define MDB_MAX_OBJ_NAME 256 +#define MDB_MAX_COLS 256 +#define MDB_MAX_IDX_COLS 10 +#define MDB_CATALOG_PG 18 +#define MDB_MEMO_OVERHEAD 12 +#define MDB_BIND_SIZE 16384 + +enum { + MDB_PAGE_DB = 0, + MDB_PAGE_DATA, + MDB_PAGE_TABLE, + MDB_PAGE_INDEX, + MDB_PAGE_LEAF, + MDB_PAGE_MAP +}; +enum { + MDB_VER_JET3 = 0, + MDB_VER_JET4 = 1 +}; +enum { + MDB_FORM = 0, + MDB_TABLE, + MDB_MACRO, + MDB_SYSTEM_TABLE, + MDB_REPORT, + MDB_QUERY, + MDB_LINKED_TABLE, + MDB_MODULE, + MDB_RELATIONSHIP, + MDB_UNKNOWN_09, + MDB_UNKNOWN_0A, + MDB_DATABASE_PROPERTY, + MDB_ANY = -1 +}; +enum { + MDB_BOOL = 0x01, + MDB_BYTE = 0x02, + MDB_INT = 0x03, + MDB_LONGINT = 0x04, + MDB_MONEY = 0x05, + MDB_FLOAT = 0x06, + MDB_DOUBLE = 0x07, + MDB_SDATETIME = 0x08, + MDB_TEXT = 0x0a, + MDB_OLE = 0x0b, + MDB_MEMO = 0x0c, + MDB_REPID = 0x0f, + MDB_NUMERIC = 0x10 +}; + +/* SARG operators */ +enum { + MDB_OR = 1, + MDB_AND, + MDB_NOT, + MDB_EQUAL, + MDB_GT, + MDB_LT, + MDB_GTEQ, + MDB_LTEQ, + MDB_LIKE, + MDB_ISNULL, + MDB_NOTNULL +}; + +typedef enum { + MDB_TABLE_SCAN, + MDB_LEAF_SCAN, + MDB_INDEX_SCAN +} MdbStrategy; + +typedef enum { + MDB_NOFLAGS = 0x00, + MDB_WRITABLE = 0x01 +} MdbFileFlags; + +enum { + MDB_DEBUG_LIKE = 0x0001, + MDB_DEBUG_WRITE = 0x0002, + MDB_DEBUG_USAGE = 0x0004, + MDB_DEBUG_OLE = 0x0008, + MDB_DEBUG_ROW = 0x0010, + MDB_USE_INDEX = 0x0020 +}; + +#define mdb_is_logical_op(x) (x == MDB_OR || \ + x == MDB_AND || \ + x == MDB_NOT ) + +#define mdb_is_relational_op(x) (x == MDB_EQUAL || \ + x == MDB_GT || \ + x == MDB_LT || \ + x == MDB_GTEQ || \ + x == MDB_LTEQ || \ + x == MDB_LIKE || \ + x == MDB_ISNULL || \ + x == MDB_NOTNULL ) + +enum { + MDB_ASC, + MDB_DESC +}; + +enum { + MDB_IDX_UNIQUE = 0x01, + MDB_IDX_IGNORENULLS = 0x02, + MDB_IDX_REQUIRED = 0x08 +}; + +#define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4) +#define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) + +/* hash to store registered backends */ +extern GHashTable *mdb_backends; + +/* forward declarations */ +typedef struct mdbindex MdbIndex; +typedef struct mdbsargtree MdbSargNode; + +typedef struct { + char *name; + unsigned char needs_length; /* or precision */ + unsigned char needs_scale; + unsigned char needs_quotes; +} MdbBackendType; + +typedef struct { + MdbBackendType *types_table; +} MdbBackend; + +typedef struct { + gboolean collect; + unsigned long pg_reads; +} MdbStatistics; + +typedef struct { + int fd; + gboolean writable; + char *filename; + guint32 jet_version; + guint32 db_key; + char db_passwd[14]; + MdbBackend *default_backend; + char *backend_name; + MdbStatistics *stats; + /* free map */ + int map_sz; + unsigned char *free_map; + /* reference count */ + int refs; +} MdbFile; + +/* offset to row count on data pages...version dependant */ +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; + +typedef struct { + MdbFile *f; + guint32 cur_pg; + guint16 row_num; + unsigned int cur_pos; + unsigned char pg_buf[MDB_PGSIZE]; + unsigned char alt_pg_buf[MDB_PGSIZE]; + unsigned int num_catalog; + GPtrArray *catalog; + MdbBackend *default_backend; + char *backend_name; + MdbFormatConstants *fmt; + MdbStatistics *stats; +#ifdef HAVE_ICONV + iconv_t iconv_out; +#endif +} MdbHandle; + +typedef struct { + MdbHandle *mdb; + char object_name[MDB_MAX_OBJ_NAME+1]; + int object_type; + unsigned long table_pg; /* misnomer since object may not be a table */ + unsigned long kkd_pg; + unsigned int kkd_rowid; + int num_props; + GArray *props; + GArray *columns; + int flags; +} MdbCatalogEntry; + +typedef struct { + gchar *name; + GHashTable *hash; +} MdbProperties; + +typedef union { + int i; + double d; + char s[256]; +} MdbAny; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; + int col_type; + int col_size; + void *bind_ptr; + int *len_ptr; + GHashTable *properties; + unsigned int num_sargs; + GPtrArray *sargs; + GPtrArray *idx_sarg_cache; + unsigned char is_fixed; + int query_order; + /* col_num is the current column order, + * does not include deletes */ + int col_num; + int cur_value_start; + int cur_value_len; + /* MEMO/OLE readers */ + guint32 cur_blob_pg; + int cur_blob_row; + int chunk_size; + /* numerics only */ + int col_prec; + int col_scale; + MdbProperties *props; + /* info needed for handling deleted/added columns */ + int fixed_offset; + int var_col_num; + /* row_col_num is the row column number order, + * including deleted columns */ + int row_col_num; +} MdbColumn; + +struct mdbsargtree { + int op; + MdbColumn *col; + MdbAny value; + void *parent; + MdbSargNode *left; + MdbSargNode *right; +}; + +typedef struct { + guint32 pg; + int start_pos; + int offset; + int len; + guint16 idx_starts[2000]; + unsigned char cache_value[256]; +} MdbIndexPage; + +typedef int (*MdbSargTreeFunc)(MdbSargNode *, gpointer *data); + +#define MDB_MAX_INDEX_DEPTH 10 + +typedef struct { + int cur_depth; + guint32 last_leaf_found; + int clean_up_mode; + MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; +} MdbIndexChain; + +typedef struct { + MdbCatalogEntry *entry; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned int num_cols; + GPtrArray *columns; + unsigned int num_rows; + int index_start; + unsigned int num_real_idxs; + unsigned int num_idxs; + GPtrArray *indices; + guint32 first_data_pg; + guint32 cur_pg_num; + guint32 cur_phys_pg; + unsigned int cur_row; + int noskip_del; /* don't skip deleted rows */ + /* object allocation map */ + guint32 map_base_pg; + unsigned int map_sz; + unsigned char *usage_map; + /* pages with free space left */ + guint32 freemap_base_pg; + unsigned int freemap_sz; + unsigned char *free_usage_map; + /* query planner */ + MdbSargNode *sarg_tree; + MdbStrategy strategy; + MdbIndex *scan_idx; + MdbHandle *mdbidx; + MdbIndexChain *chain; + MdbProperties *props; + unsigned int num_var_cols; /* to know if row has variable columns */ + /* temp table */ + unsigned int is_temp_table; + GPtrArray *temp_table_pages; +} MdbTableDef; + +struct mdbindex { + int index_num; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned char index_type; + guint32 first_pg; + int num_rows; /* number rows in index */ + unsigned int num_keys; + short key_col_num[MDB_MAX_IDX_COLS]; + unsigned char key_col_order[MDB_MAX_IDX_COLS]; + unsigned char flags; + MdbTableDef *table; +}; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; +} MdbColumnProp; + +typedef struct { + void *value; + int siz; + int start; + unsigned char is_null; + unsigned char is_fixed; + int colnum; + int offset; +} MdbField; + +typedef struct { + int op; + MdbAny value; +} MdbSarg; + +/* mem.c */ +extern void mdb_init(); +extern void mdb_exit(); + +/* file.c */ +extern ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg); +extern ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg); +extern unsigned char mdb_get_byte(unsigned char *buf, int offset); +extern int mdb_get_int16(unsigned char *buf, int offset); +extern gint32 mdb_get_int24(unsigned char *buf, int offset); +extern long mdb_get_int32(unsigned char *buf, int offset); +extern float mdb_get_single(unsigned char *buf, int offset); +extern double mdb_get_double(unsigned char *buf, int offset); +extern unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset); +extern int mdb_pg_get_int16(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset); +extern long mdb_pg_get_int32(MdbHandle *mdb, int offset); +extern float mdb_pg_get_single(MdbHandle *mdb, int offset); +extern double mdb_pg_get_double(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset); +extern MdbHandle *mdb_open(char *filename, MdbFileFlags flags); +extern void mdb_close(MdbHandle *mdb); +extern MdbHandle *mdb_clone_handle(MdbHandle *mdb); +extern void mdb_swap_pgbuf(MdbHandle *mdb); +extern long _mdb_get_int32(unsigned char *buf, int offset); + +/* catalog.c */ +extern void mdb_free_catalog(MdbHandle *mdb); +extern GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type); +extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type); +extern char *mdb_get_objtype_string(int obj_type); + +/* table.c */ +extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry); +extern void mdb_free_tabledef(MdbTableDef *table); +extern MdbTableDef *mdb_read_table(MdbCatalogEntry *entry); +extern MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type); +extern void mdb_append_column(GPtrArray *columns, MdbColumn *in_col); +extern void mdb_free_columns(GPtrArray *columns); +extern GPtrArray *mdb_read_columns(MdbTableDef *table); +extern void mdb_table_dump(MdbCatalogEntry *entry); +extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos); +extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur_pos); +extern int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset); +extern guint16 read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len); +extern int mdb_is_user_table(MdbCatalogEntry *entry); +extern int mdb_is_system_table(MdbCatalogEntry *entry); + +/* data.c */ +extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr); +extern void mdb_data_dump(MdbTableDef *table); +extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr); +extern int mdb_rewind_table(MdbTableDef *table); +extern int mdb_fetch_row(MdbTableDef *table); +extern int mdb_is_fixed_col(MdbColumn *col); +extern char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size); +extern int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len); +extern int mdb_find_end_of_row(MdbHandle *mdb, int row); +extern int mdb_col_fixed_size(MdbColumn *col); +extern int mdb_col_disp_size(MdbColumn *col); +extern void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr); +extern int mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr); +extern int mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size); +extern void mdb_set_date_fmt(const char *); +extern int mdb_read_row(MdbTableDef *table, unsigned int row); + +/* dump.c */ +extern void buffer_dump(const unsigned char* buf, int start, int end); + +/* backend.c */ +extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); +extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); +extern void mdb_init_backends(); +extern void mdb_register_backend(MdbBackendType *backend, char *backend_name); +extern void mdb_remove_backends(); +extern int mdb_set_default_backend(MdbHandle *mdb, char *backend_name); +extern char *mdb_get_relationships(MdbHandle *mdb); + +/* sargs.c */ +extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields); +extern int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field); +extern void mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data); +extern int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data); +extern int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg); +extern int mdb_test_string(MdbSargNode *node, char *s); +extern int mdb_test_int(MdbSargNode *node, gint32 i); +extern int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg); + + + +/* index.c */ +extern GPtrArray *mdb_read_indices(MdbTableDef *table); +extern void mdb_index_dump(MdbTableDef *table, MdbIndex *idx); +extern void mdb_index_scan_free(MdbTableDef *table); +extern int mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg); +extern int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row); +extern void mdb_index_hash_text(guchar *text, guchar *hash); +extern void mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table); +extern int mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row); +extern void mdb_index_swap_n(unsigned char *src, int sz, unsigned char *dest); +extern void mdb_free_indices(GPtrArray *indices); +void mdb_index_page_reset(MdbIndexPage *ipg); +extern MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern MdbIndexPage *mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern void mdb_index_page_init(MdbIndexPage *ipg); + + +/* stats.c */ +extern void mdb_stats_on(MdbHandle *mdb); +extern void mdb_stats_off(MdbHandle *mdb); +extern void mdb_dump_stats(MdbHandle *mdb); + +/* like.c */ +extern int mdb_like_cmp(char *s, char *r); + +/* write.c */ +extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields); +extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size); +extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum); +extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields); +extern int mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size); +extern int mdb_pg_get_freespace(MdbHandle *mdb); +extern int mdb_update_row(MdbTableDef *table); +extern unsigned char *mdb_new_data_pg(MdbCatalogEntry *entry); + +/* map.c */ +extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size); +guint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg); + +/* props.c */ +extern GPtrArray *mdb_read_props_list(gchar *kkd, int len); +extern void mdb_free_props(MdbProperties *props); +extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len); + +/* worktable.c */ +extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name); +extern void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col); +extern void mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed); +extern void mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int column); +extern void mdb_temp_columns_end(MdbTableDef *table); + +/* options.c */ +extern int mdb_get_option(unsigned long optnum); +extern void mdb_debug(int klass, char *fmt, ...); + +/* iconv.c */ +extern int mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); +extern int mdb_ascii2unicode(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); + +#endif /* _mdbtools_h_ */ diff --git a/plugins/poi_geodownload/libmdb/index.c b/plugins/poi_geodownload/libmdb/index.c new file mode 100644 index 00000000..e840536e --- /dev/null +++ b/plugins/poi_geodownload/libmdb/index.c @@ -0,0 +1,905 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000-2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +MdbIndexPage *mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg); + +char idx_to_text[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0-7 0x00-0x07 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8-15 0x09-0x0f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16-23 0x10-0x17 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24-31 0x19-0x1f */ +' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32-39 0x20-0x27 */ +0x00, 0x00, 0x00, 0x00, 0x00, ' ', ' ', 0x00, /* 40-47 0x29-0x2f */ +'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', /* 48-55 0x30-0x37 */ +'^', '_', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56-63 0x39-0x3f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 64-71 0x40-0x47 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 72-79 0x49-0x4f H */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 80-87 0x50-0x57 P */ +'|', '}', '~', '5', '6', '7', '8', '9', /* 88-95 0x59-0x5f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 96-103 0x60-0x67 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 014-111 0x69-0x6f h */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 112-119 0x70-0x77 p */ +'|', '}', '~', 0x00, 0x00, 0x00, 0x00, 0x00, /* 120-127 0x78-0x7f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128-135 0x80-0x87 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ +0x00, 0x00, 0x00, 0x00, 0x00, '`', 0x00, 0x00, /* 0xc0-0xc7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ +0x00, '`', 0x00, '`', '`', '`', 0x00, 0x00, /* 0xe0-0xe7 */ +'f', 'f', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ +0x00, 0x00, 0x00, 'r', 0x00, 0x00, 'r', 0x00, /* 0xf0-0xf7 */ +0x81, 0x00, 0x00, 0x00, 'x', 0x00, 0x00, 0x00, /* 0xf8-0xff */ +}; + + +GPtrArray * +mdb_read_indices(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbIndex *pidx; + unsigned int i, j; + int idx_num, key_num, col_num; + int cur_pos, name_sz, idx2_sz, type_offset; + int index_start_pg = mdb->cur_pg; + gchar *tmpbuf; + + table->indices = g_ptr_array_new(); + + if (IS_JET4(mdb)) { + cur_pos = table->index_start + 52 * table->num_real_idxs; + idx2_sz = 28; + type_offset = 23; + } else { + cur_pos = table->index_start + 39 * table->num_real_idxs; + idx2_sz = 20; + type_offset = 19; + } + + tmpbuf = (gchar *) g_malloc(idx2_sz); + for (i=0;inum_idxs;i++) { + read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); + cur_pos += idx2_sz; + pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex)); + pidx->table = table; + pidx->index_num = mdb_get_int16(tmpbuf, 4); + pidx->index_type = tmpbuf[type_offset]; + g_ptr_array_add(table->indices, pidx); + } + g_free(tmpbuf); + + for (i=0;inum_idxs;i++) { + pidx = g_ptr_array_index (table->indices, i); + if (IS_JET4(mdb)) { + name_sz=read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmpbuf = g_malloc(name_sz); + read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); + cur_pos += name_sz; + mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); + g_free(tmpbuf); + } else { + read_pg_if(mdb, &cur_pos, 0); + name_sz=mdb->pg_buf[cur_pos++]; + read_pg_if_n(mdb, pidx->name, &cur_pos, name_sz); + cur_pos += name_sz; + pidx->name[name_sz]='\0'; + } + //fprintf(stderr, "index name %s\n", pidx->name); + } + + mdb_read_alt_pg(mdb, entry->table_pg); + mdb_read_pg(mdb, index_start_pg); + cur_pos = table->index_start; + idx_num=0; + for (i=0;inum_real_idxs;i++) { + if (IS_JET4(mdb)) cur_pos += 4; + do { + pidx = g_ptr_array_index (table->indices, idx_num++); + } while (pidx && pidx->index_type==2); + + /* if there are more real indexes than index entries left after + removing type 2's decrement real indexes and continue. Happens + on Northwind Orders table. + */ + if (!pidx) { + table->num_real_idxs--; + continue; + } + + pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, + fmt->tab_cols_start_offset + + (i*fmt->tab_ridx_entry_size)); + + key_num=0; + for (j=0;jkey_col_num[key_num] = col_num + 1; + pidx->key_col_order[key_num] = + (mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC; + key_num++; + } + pidx->num_keys = key_num; + + cur_pos += 4; + pidx->first_pg = read_pg_if_32(mdb, &cur_pos); + cur_pos += 4; + read_pg_if(mdb, &cur_pos, 0); + pidx->flags = mdb->pg_buf[cur_pos++]; + if (IS_JET4(mdb)) cur_pos += 9; + } + return NULL; +} +void +mdb_index_hash_text(guchar *text, guchar *hash) +{ + unsigned int k; + + for (k=0;k 0; i--) { + dest[j++] = src[i]; + } +} +void +mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg) +{ + //guint32 cache_int; + unsigned char *c; + + switch (col->col_type) { + case MDB_TEXT: + mdb_index_hash_text(sarg->value.s, idx_sarg->value.s); + break; + + case MDB_LONGINT: + idx_sarg->value.i = GUINT32_SWAP_LE_BE(sarg->value.i); + //cache_int = sarg->value.i * -1; + c = (unsigned char *) &(idx_sarg->value.i); + c[0] |= 0x80; + //printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[2], c[3]); + break; + + case MDB_INT: + break; + + default: + break; + } +} +#if 0 +int +mdb_index_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len) +{ +char tmpbuf[256]; +int lastchar; + + switch (col->col_type) { + case MDB_BYTE: + return mdb_test_int(sarg, mdb_pg_get_byte(mdb, offset)); + break; + case MDB_INT: + return mdb_test_int(sarg, mdb_pg_get_int16(mdb, offset)); + break; + case MDB_LONGINT: + return mdb_test_int(sarg, mdb_pg_get_int32(mdb, offset)); + break; + case MDB_TEXT: + strncpy(tmpbuf, &mdb->pg_buf[offset],255); + lastchar = len > 255 ? 255 : len; + tmpbuf[lastchar]='\0'; + return mdb_test_string(sarg, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +#endif +int +mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, unsigned char *buf, int len) +{ + unsigned int i, j; + MdbColumn *col; + MdbTableDef *table = idx->table; + MdbSarg *idx_sarg; + MdbSarg *sarg; + MdbField field; + MdbSargNode node; + //int c_offset = 0, + int c_len; + +#if 0 + fprintf(stderr,"mdb_index_test_sargs called on "); + for (i=0;ipg_buf[offset+i]); + fprintf(stderr,"\n"); +#endif + for (i=0;inum_keys;i++) { + //c_offset++; /* the per column null indicator/flags */ + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + /* + * This will go away eventually + */ + if (col->col_type==MDB_TEXT) { + //c_len = strlen(&mdb->pg_buf[offset + c_offset]); + c_len = strlen(buf); + } else { + c_len = col->col_size; + //fprintf(stderr,"Only text types currently supported. How did we get here?\n"); + } + /* + * If we have no cached index values for this column, + * create them. + */ + if (col->num_sargs && !col->idx_sarg_cache) { + col->idx_sarg_cache = g_ptr_array_new(); + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->sargs, j); + idx_sarg = g_memdup(sarg,sizeof(MdbSarg)); + //printf("calling mdb_index_cache_sarg\n"); + mdb_index_cache_sarg(col, sarg, idx_sarg); + g_ptr_array_add(col->idx_sarg_cache, idx_sarg); + } + } + + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->idx_sarg_cache, j); + /* XXX - kludge */ + node.op = sarg->op; + node.value = sarg->value; + //field.value = &mdb->pg_buf[offset + c_offset]; + field.value = buf; + field.siz = c_len; + field.is_null = FALSE; + if (!mdb_test_sarg(mdb, col, &node, &field)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + } + return 1; +} +/* + * pack the pages bitmap + */ +int +mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte = 0; + int elem = 0; + int len, start, i; + + start = ipg->idx_starts[elem++]; + + while (start) { + len = ipg->idx_starts[elem] - start; + fprintf(stdout, "len is %d\n", len); + for (i=0; i < len; i++) { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mdb->pg_buf[mask_pos++] = mask_byte; + mask_byte = 0; + } + /* upon reaching the len, set the bit */ + } + mask_byte = (1 << mask_bit) | mask_byte; + fprintf(stdout, "mask byte is %02x at %d\n", mask_byte, mask_pos); + start = ipg->idx_starts[elem++]; + } + /* flush the last byte if any */ + mdb->pg_buf[mask_pos++] = mask_byte; + /* remember to zero the rest of the bitmap */ + for (i = mask_pos; i < 0xf8; i++) { + mdb->pg_buf[mask_pos++] = 0; + } + return 0; +} +/* + * unpack the pages bitmap + */ +int +mdb_index_unpack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte; + int start = 0xf8; + int elem = 0; + int len = 0; + + ipg->idx_starts[elem++]=start; + +#if 0 + fprintf(stdout, "Unpacking index page %u\n", ipg->pg); +#endif + do { + len = 0; + do { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mask_pos++; + } + mask_byte = mdb->pg_buf[mask_pos]; + len++; + } while (mask_pos <= 0xf8 && !((1 << mask_bit) & mask_byte)); + //fprintf(stdout, "%d %d %d %d\n", mask_pos, mask_bit, mask_byte, len); + + start += len; + if (mask_pos < 0xf8) ipg->idx_starts[elem++]=start; + + } while (mask_pos < 0xf8); + + /* if we zero the next element, so we don't pick up the last pages starts*/ + ipg->idx_starts[elem]=0; + + return elem; +} +/* + * find the next entry on a page (either index or leaf). Uses state information + * stored in the MdbIndexPage across calls. + */ +int +mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg) +{ + if (!ipg->pg) return 0; + + /* if this page has not been unpacked to it */ + if (!ipg->idx_starts[0]){ + //fprintf(stdout, "Unpacking page %d\n", ipg->pg); + mdb_index_unpack_bitmap(mdb, ipg); + } + + + if (ipg->idx_starts[ipg->start_pos + 1]==0) return 0; + ipg->len = ipg->idx_starts[ipg->start_pos+1] - ipg->idx_starts[ipg->start_pos]; + ipg->start_pos++; + //fprintf(stdout, "Start pos %d\n", ipg->start_pos); + + return ipg->len; +} +void mdb_index_page_reset(MdbIndexPage *ipg) +{ + ipg->offset = 0xf8; /* start byte of the index entries */ + ipg->start_pos=0; + ipg->len = 0; + ipg->idx_starts[0]=0; +} +void mdb_index_page_init(MdbIndexPage *ipg) +{ + memset(ipg, 0, sizeof(MdbIndexPage)); + mdb_index_page_reset(ipg); +} +/* + * find the next leaf page if any given a chain. Assumes any exhausted leaf + * pages at the end of the chain have been peeled off before the call. + */ +MdbIndexPage * +mdb_find_next_leaf(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg, *newipg; + guint32 pg; + guint passed = 0; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * If we are at the first page deep and it's not an index page then + * we are simply done. (there is no page to find + */ + + if (mdb->pg_buf[0]==MDB_PAGE_LEAF) { + /* Indexes can have leaves at the end that don't appear + * in the upper tree, stash the last index found so + * we can follow it at the end. */ + chain->last_leaf_found = ipg->pg; + return ipg; + } + + /* + * apply sargs here, currently we don't + */ + do { + ipg->len = 0; + //printf("finding next on pg %lu\n", ipg->pg); + if (!mdb_index_find_next_on_page(mdb, ipg)) { + //printf("find_next_on_page returned 0\n"); + return 0; + } + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 3); + //printf("Looking at pg %lu at %lu %d\n", pg, ipg->offset, ipg->len); + ipg->offset += ipg->len; + + /* + * add to the chain and call this function + * recursively. + */ + newipg = mdb_chain_add_page(mdb, chain, pg); + newipg = mdb_find_next_leaf(mdb, idx, chain); + //printf("returning pg %lu\n",newipg->pg); + return newipg; + } while (!passed); + /* no more pages */ + return NULL; + +} +MdbIndexPage * +mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg) +{ + MdbIndexPage *ipg; + + chain->cur_depth++; + if (chain->cur_depth > MDB_MAX_INDEX_DEPTH) { + fprintf(stderr,"Error! maximum index depth of %d exceeded. This is probably due to a programming bug, If you are confident that your indexes really are this deep, adjust MDB_MAX_INDEX_DEPTH in mdbtools.h and recompile.\n", MDB_MAX_INDEX_DEPTH); + exit(1); + } + ipg = &(chain->pages[chain->cur_depth - 1]); + mdb_index_page_init(ipg); + ipg->pg = pg; + + return ipg; +} +/* + * returns the bottom page of the IndexChain, if IndexChain is empty it + * initializes it by reading idx->first_pg (the root page) + */ +MdbIndexPage * +mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + /* + * if it's new use the root index page (idx->first_pg) + */ + if (!chain->cur_depth) { + ipg = &(chain->pages[0]); + mdb_index_page_init(ipg); + chain->cur_depth = 1; + ipg->pg = idx->first_pg; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + } else { + ipg = &(chain->pages[chain->cur_depth - 1]); + ipg->len = 0; + } + + mdb_read_pg(mdb, ipg->pg); + + return ipg; +} +/* + * unwind the stack and search for new leaf node + */ +MdbIndexPage * +mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + //printf("page %lu finished\n",ipg->pg); + if (chain->cur_depth==1) { + //printf("cur_depth == 1 we're out\n"); + return NULL; + } + /* + * unwind the stack until we find something or reach + * the top. + */ + ipg = NULL; + while (chain->cur_depth>1 && ipg==NULL) { + //printf("chain depth %d\n", chain->cur_depth); + chain->cur_depth--; + ipg = mdb_find_next_leaf(mdb, idx, chain); + if (ipg) mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) { + //printf("last leaf %lu\n", chain->last_leaf_found); + return NULL; + } + return ipg; +} +/* + * the main index function. + * caller provides an index chain which is the current traversal of index + * pages from the root page to the leaf. Initially passed as blank, + * mdb_index_find_next will store it's state information here. Each invocation + * then picks up where the last one left off, allowing us to scroll through + * the index one by one. + * + * Sargs are applied here but also need to be applied on the whole row b/c + * text columns may return false positives due to hashing and non-index + * columns with sarg values can't be tested here. + */ +int +mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row) +{ + MdbIndexPage *ipg; + int passed = 0; + int idx_sz; + int idx_start = 0; + MdbColumn *col; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * loop while the sargs don't match + */ + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + if (!chain->clean_up_mode) { + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) return 0; + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) + return 0; + } + } + *row = mdb->pg_buf[ipg->offset + ipg->len - 1]; +#if 0 + printf("page: "); + buffer_dump(mdb->pg_buf, ipg->offset+ipg->len-4, ipg->offset+ipg->len-2); +#endif + *pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); +#if 0 + printf("row = %d pg = %lu ipg->pg = %lu offset = %lu len = %d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len); +#endif + col=g_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1); + idx_sz = mdb_col_fixed_size(col); + /* handle compressed indexes, single key indexes only? */ + if (idx->num_keys==1 && idx_sz>0 && ipg->len - 4 < idx_sz) { +#if 0 + printf("short index found\n"); + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->offset], ipg->len); +#if 0 + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + } else { + idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz); + } + + //idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + passed = mdb_index_test_sargs(mdb, idx, ipg->cache_value, idx_sz); + +// printf("passed=%d\n", passed); + + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); + ipg->offset += ipg->len; + + } while (!passed); + +#if 0 + fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->len); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + + return ipg->len; +} +/* + * XXX - FIX ME + * This function is grossly inefficient. It scans the entire index building + * an IndexChain to a specific row. We should be checking the index pages + * for matches against the indexed fields to find the proper leaf page, but + * getting it working first and then make it fast! + */ +int +mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row) +{ + MdbIndexPage *ipg; + int passed = 0; + guint32 datapg; + guint16 datarow; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + /* back to top? We're done */ + if (chain->cur_depth==1) + return 0; + + /* + * unwind the stack until we find something or reach + * the top. + */ + while (chain->cur_depth>1) { + chain->cur_depth--; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) + return 0; + } + /* test row and pg */ + datarow = mdb->pg_buf[ipg->offset + ipg->len - 1]; + datapg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + + if (datapg == pg && datarow == row) { + passed = 1; + } + ipg->offset += ipg->len; + } while (!passed); + + /* index chain from root to leaf should now be in "chain" */ + return 1; +} + +void mdb_index_walk(MdbTableDef *table, MdbIndex *idx) +{ +MdbHandle *mdb = table->entry->mdb; +int cur_pos = 0; +unsigned char marker; +MdbColumn *col; +unsigned int i; + + if (idx->num_keys!=1) return; + + mdb_read_pg(mdb, idx->first_pg); + cur_pos = 0xf8; + + for (i=0;inum_keys;i++) { + marker = mdb->pg_buf[cur_pos++]; + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + //printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size); + } +} +void +mdb_index_dump(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + + fprintf(stdout,"index number %d\n", idx->index_num); + fprintf(stdout,"index name %s\n", idx->name); + fprintf(stdout,"index first page %d\n", idx->first_pg); + fprintf(stdout,"index rows %d\n", idx->num_rows); + if (idx->index_type==1) fprintf(stdout,"index is a primary key\n"); + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + fprintf(stdout,"Column %s(%d) Sorted %s Unique: %s\n", + col->name, + idx->key_col_num[i], + idx->key_col_order[i]==MDB_ASC ? "ascending" : "descending", + idx->flags & MDB_IDX_UNIQUE ? "Yes" : "No" + ); + } + mdb_index_walk(table, idx); +} +/* + * compute_cost tries to assign a cost to a given index using the sargs + * available in this query. + * + * Indexes with no matching sargs are assigned 0 + * Unique indexes are preferred over non-uniques + * Operator preference is equal, like, isnull, others + */ +int mdb_index_compute_cost(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + MdbSarg *sarg = NULL; + int not_all_equal = 0; + + if (!idx->num_keys) return 0; + if (idx->num_keys > 1) { + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + if (col->sargs) sarg = g_ptr_array_index (col->sargs, 0); + if (!sarg || sarg->op != MDB_EQUAL) not_all_equal++; + } + } + + col=g_ptr_array_index(table->columns,idx->key_col_num[0]-1); + /* + * if this is the first key column and there are no sargs, + * then this index is useless. + */ + if (!col->num_sargs) return 0; + + sarg = g_ptr_array_index (col->sargs, 0); + + /* + * a like with a wild card first is useless as a sarg */ + if (sarg->op == MDB_LIKE && sarg->value.s[0]=='%') + return 0; + + /* + * this needs a lot of tweaking. + */ + if (idx->flags & MDB_IDX_UNIQUE) { + if (idx->num_keys == 1) { + //printf("op is %d\n", sarg->op); + switch (sarg->op) { + case MDB_EQUAL: + return 1; break; + case MDB_LIKE: + return 4; break; + case MDB_ISNULL: + return 12; break; + default: + return 8; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 2; + else return 1; + break; + case MDB_LIKE: + return 6; break; + case MDB_ISNULL: + return 12; break; + default: + return 9; break; + } + } + } else { + if (idx->num_keys == 1) { + switch (sarg->op) { + case MDB_EQUAL: + return 2; break; + case MDB_LIKE: + return 5; break; + case MDB_ISNULL: + return 12; break; + default: + return 10; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 3; + else return 2; + break; + case MDB_LIKE: + return 7; break; + case MDB_ISNULL: + return 12; break; + default: + return 11; break; + } + } + } + return 0; +} +/* + * choose_index runs mdb_index_compute_cost for each available index and picks + * the best. + * + * Returns strategy to use (table scan, or index scan) + */ +MdbStrategy +mdb_choose_index(MdbTableDef *table, int *choice) +{ + unsigned int i; + MdbIndex *idx; + int cost = 0; + int least = 99; + + *choice = -1; + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + cost = mdb_index_compute_cost(table, idx); + //printf("cost for %s is %d\n", idx->name, cost); + if (cost && cost < least) { + least = cost; + *choice = i; + } + } + /* and the winner is: *choice */ + if (least==99) return MDB_TABLE_SCAN; + return MDB_INDEX_SCAN; +} +void +mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table) +{ + int i; + + if (mdb_get_option(MDB_USE_INDEX) && mdb_choose_index(table, &i) == MDB_INDEX_SCAN) { + table->strategy = MDB_INDEX_SCAN; + table->scan_idx = g_ptr_array_index (table->indices, i); + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + //printf("best index is %s\n",table->scan_idx->name); + } + //printf("TABLE SCAN? %d\n", table->strategy); +} +void +mdb_index_scan_free(MdbTableDef *table) +{ + if (table->chain) { + g_free(table->chain); + table->chain = NULL; + } + if (table->mdbidx) { + mdb_close(table->mdbidx); + table->mdbidx = NULL; + } +} + +void mdb_free_indices(GPtrArray *indices) +{ + unsigned int i; + + if (!indices) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(indices, i)); + g_ptr_array_free(indices, TRUE); +} diff --git a/plugins/poi_geodownload/libmdb/kkd.c b/plugins/poi_geodownload/libmdb/kkd.c new file mode 100644 index 00000000..ea72887c --- /dev/null +++ b/plugins/poi_geodownload/libmdb/kkd.c @@ -0,0 +1,149 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +/* +** Note: This code is mostly garbage right now...just a test to parse out the +** KKD structures. +*/ + +GArray *mdb_get_column_props(MdbCatalogEntry *entry, int start) +{ +int pos, cnt=0; +int len, tmp, cplen; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; + + entry->props = g_array_new(FALSE,FALSE,sizeof(MdbColumnProp)); + len = mdb_pg_get_int16(mdb,start); + pos = start + 6; + while (pos < start+len) { + tmp = mdb_pg_get_int16(mdb,pos); /* length of string */ + pos += 2; + cplen = tmp > MDB_MAX_OBJ_NAME ? MDB_MAX_OBJ_NAME : tmp; + g_memmove(prop.name,&mdb->pg_buf[pos],cplen); + prop.name[cplen]='\0'; + pos += tmp; + g_array_append_val(entry->props, prop.name); + cnt++; + } + entry->num_props = cnt; + return entry->props; +} + +GHashTable *mdb_get_column_def(MdbCatalogEntry *entry, int start) +{ +GHashTable *hash = NULL; +MdbHandle *mdb = entry->mdb; +MdbColumnProp prop; +int tmp, pos, col_num, val_len, i; +int len, col_type; +unsigned char c; +int end; + + fprintf(stdout,"\n data\n"); + fprintf(stdout,"-------\n"); + len = mdb_pg_get_int16(mdb,start); + fprintf(stdout,"length = %3d\n",len); + pos = start + 6; + end = start + len; + while (pos < end) { + fprintf(stdout,"pos = %3d\n",pos); + start = pos; + tmp = mdb_pg_get_int16(mdb,pos); /* length of field */ + pos += 2; + col_type = mdb_pg_get_int16(mdb,pos); /* ??? */ + pos += 2; + col_num = 0; + if (col_type) { + col_num = mdb_pg_get_int16(mdb,pos); + pos += 2; + } + val_len = mdb_pg_get_int16(mdb,pos); + pos += 2; + fprintf(stdout,"length = %3d %04x %2d %2d ",tmp, col_type, col_num, val_len); + for (i=0;ipg_buf[pos+i]; + if (isprint(c)) + fprintf(stdout," %c",c); + else + fprintf(stdout," %02x",c); + + } + pos = start + tmp; + prop = g_array_index(entry->props,MdbColumnProp,col_num); + fprintf(stdout," Property %s",prop.name); + fprintf(stdout,"\n"); + } + return hash; +} +void mdb_kkd_dump(MdbCatalogEntry *entry) +{ +int rows; +int kkd_start, kkd_end; +int i, tmp, pos, row_type, datapos=0; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; +int rowid = entry->kkd_rowid; + + + mdb_read_pg(mdb, entry->kkd_pg); + rows = mdb_pg_get_int16(mdb,8); + fprintf(stdout,"number of rows = %d\n",rows); + kkd_start = mdb_pg_get_int16(mdb,10+rowid*2); + fprintf(stdout,"kkd start = %d %04x\n",kkd_start,kkd_start); + kkd_end = mdb->fmt->pg_size; + for (i=0;ifmt->pg_size && + tmp > kkd_start && + tmp < kkd_end) { + kkd_end = tmp; + } + } + fprintf(stdout,"kkd end = %d %04x\n",kkd_end,kkd_end); + pos = kkd_start + 4; /* 4 = K K D \0 */ + while (pos < kkd_end) { + tmp = mdb_pg_get_int16(mdb,pos); + row_type = mdb_pg_get_int16(mdb,pos+4); + fprintf(stdout,"row size = %3d type = 0x%02x\n",tmp,row_type); + if (row_type==0x80) { + fprintf(stdout,"\nColumn Properties\n"); + fprintf(stdout,"-----------------\n"); + mdb_get_column_props(entry,pos); + for (i=0;inum_props;i++) { + prop = g_array_index(entry->props,MdbColumnProp,i); + fprintf(stdout,"%3d %s\n",i,prop.name); + } + } + if (row_type==0x01) datapos = pos; + pos += tmp; + } + + if (datapos) { + mdb_get_column_def(entry, datapos); + } +} + diff --git a/plugins/poi_geodownload/libmdb/like.c b/plugins/poi_geodownload/libmdb/like.c new file mode 100644 index 00000000..0a23d45c --- /dev/null +++ b/plugins/poi_geodownload/libmdb/like.c @@ -0,0 +1,78 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_like_cmp + * @s: String to search within. + * @r: Search pattern. + * + * Tests the string @s to see if it matches the search pattern @r. In the + * search pattern, a percent sign indicates matching on any number of + * characters, and an underscore indicates matching any single character. + * + * Returns: 1 if the string matches, 0 if the string does not match. + */ +int mdb_like_cmp(char *s, char *r) +{ + unsigned int i; + int ret; + + mdb_debug(MDB_DEBUG_LIKE, "comparing %s and %s", s, r); + switch (r[0]) { + case '\0': + if (s[0]=='\0') { + return 1; + } else { + return 0; + } + case '_': + /* skip one character */ + return mdb_like_cmp(&s[1],&r[1]); + case '%': + /* skip any number of characters */ + /* the strlen(s)+1 is important so the next call can */ + /* if there are trailing characters */ + for(i=0;i= pgnum) ? start_pg-pgnum+1 : 0; + for (; ifmt->pg_size - 4) * 8 pages. + * + * map_ind gives us the starting usage_map entry + * offset gives us a page offset into the bitmap + */ + usage_bitlen = (mdb->fmt->pg_size - 4) * 8; + max_map_pgs = (map_sz - 1) / 4; + map_ind = (start_pg + 1) / usage_bitlen; + offset = (start_pg + 1) % usage_bitlen; + + for (; map_indfmt->pg_size) { + fprintf(stderr, "Oops! didn't get a full page at %d\n", map_pg); + exit(1); + } + + usage_bitmap = mdb->alt_pg_buf + 4; + for (i=offset; ientry; + MdbHandle *mdb = entry->mdb; + guint32 pgnum; + guint32 cur_pg = 0; + int free_space; + + do { + pgnum = mdb_map_find_next(mdb, + table->free_usage_map, + table->freemap_sz, cur_pg); + printf("looking at page %d\n", pgnum); + if (!pgnum) { + /* allocate new page */ + pgnum = mdb_alloc_page(table); + return pgnum; + } + cur_pg = pgnum; + + mdb_read_pg(mdb, pgnum); + free_space = mdb_pg_get_freespace(mdb); + + } while (free_space < row_size); + + printf("page %d has %d bytes left\n", pgnum, free_space); + + return pgnum; +} diff --git a/plugins/poi_geodownload/libmdb/mem.c b/plugins/poi_geodownload/libmdb/mem.c new file mode 100644 index 00000000..9c518321 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/mem.c @@ -0,0 +1,50 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_init: + * + * Initializes the LibMDB library. This function should be called exactly once + * by calling program and prior to any other function. + * + **/ +void mdb_init() +{ + mdb_init_backends(); +} + +/** + * mdb_exit: + * + * Cleans up the LibMDB library. This function should be called exactly once + * by the calling program prior to exiting (or prior to final use of LibMDB + * functions). + * + **/ +void mdb_exit() +{ + mdb_remove_backends(); +} diff --git a/plugins/poi_geodownload/libmdb/money.c b/plugins/poi_geodownload/libmdb/money.c new file mode 100644 index 00000000..7f2cf657 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/money.c @@ -0,0 +1,139 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 1998-1999 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define MAXPRECISION 20 +/* +** these routines are copied from the freetds project which does something +** very similiar +*/ + +static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier); +static int do_carry(unsigned char *product); +static char *array_to_string(unsigned char *array, int unsigned scale, char *s); + +/** + * mdb_money_to_string + * @mdb: Handle to open MDB database file + * @start: Offset of the field within the current page + * @s: String that will receieve the value + * + * Returns: the string that has received the value. + */ +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s) +{ + int num_bytes = 8; + int i; + int neg=0; + unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION]; + unsigned char product[MAXPRECISION]; + unsigned char money[num_bytes]; + + memset(multiplier,0,MAXPRECISION); + memset(product,0,MAXPRECISION); + multiplier[0]=1; + memcpy(money, mdb->pg_buf + start, num_bytes); + + /* Perform two's complement for negative numbers */ + if (money[7] & 0x80) { + neg = 1; + for (i=0;i9) { + product[j+1]+=product[j]/10; + product[j]=product[j]%10; + } + } + if (product[j]>9) { + product[j]=product[j]%10; + } + return 0; +} +static char *array_to_string(unsigned char *array, unsigned int scale, char *s) +{ + unsigned int top, i, j=0; + + for (top=MAXPRECISION;(top>0) && (top-1>scale) && !array[top-1];top--); + + if (top == 0) { + s[j++] = '0'; + } else { + for (i=top; i>0; i--) { + if (j == top-scale) s[j++]='.'; + s[j++]=array[i-1]+'0'; + } + } + s[j]='\0'; + + return s; +} diff --git a/plugins/poi_geodownload/libmdb/options.c b/plugins/poi_geodownload/libmdb/options.c new file mode 100644 index 00000000..cdbbc662 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/options.c @@ -0,0 +1,86 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define DEBUG 1 + +static unsigned long opts; +static int optset; + +static void load_options(); + +void +mdb_debug(int klass, char *fmt, ...) +{ +#ifdef DEBUG + va_list ap; + + if (!optset) load_options(); + if (klass & opts) { + va_start(ap, fmt); + vfprintf (stdout,fmt, ap); + va_end(ap); + fprintf(stdout,"\n"); + } +#endif +} + +static void +load_options() +{ + char *opt; + char *s; + + if (!optset && (s=getenv("MDBOPTS"))) { + opt = strtok(s, ":"); + do { + if (!strcmp(opt, "use_index")) opts |= MDB_USE_INDEX; + if (!strcmp(opt, "debug_like")) opts |= MDB_DEBUG_LIKE; + if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE; + if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE; + if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE; + if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW; + if (!strcmp(opt, "debug_all")) { + opts |= MDB_DEBUG_LIKE; + opts |= MDB_DEBUG_WRITE; + opts |= MDB_DEBUG_USAGE; + opts |= MDB_DEBUG_OLE; + opts |= MDB_DEBUG_ROW; + } + opt = strtok(NULL,":"); + } while (opt); + } + optset = 1; +} +int +mdb_get_option(unsigned long optnum) +{ + if (!optset) load_options(); + return ((opts & optnum) > 0); +} diff --git a/plugins/poi_geodownload/libmdb/props.c b/plugins/poi_geodownload/libmdb/props.c new file mode 100644 index 00000000..61db9f54 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/props.c @@ -0,0 +1,127 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +GPtrArray * +mdb_read_props_list(gchar *kkd, int len) +{ + guint32 record_len; + int pos = 0; + gchar *name; + GPtrArray *names = NULL; + int i = 0; + + names = g_ptr_array_new(); +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + pos += 2; +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos - 2, pos + record_len - 1); +#endif + name = g_malloc(record_len + 1); + strncpy(name, &kkd[pos], record_len); + name[record_len] = '\0'; + pos += record_len; + g_ptr_array_add(names, name); +#ifdef MDB_DEBUG + printf("new len = %d\n", names->len); +#endif + } + return names; +} +void +mdb_free_props(MdbProperties *props) +{ + if (!props) return; + + if (props->name) g_free(props->name); + g_free(props); +} +MdbProperties * +mdb_alloc_props() +{ + MdbProperties *props; + + props = g_malloc0(sizeof(MdbProperties)); + + return props; +} +MdbProperties * +mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len) +{ + guint32 record_len, name_len; + int pos = 0; + int elem, dtype, dsize; + gchar *name, *value; + MdbProperties *props; + int i = 0; + +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + + /* skip the name record */ + record_len = mdb_get_int16(kkd, pos); + pos += 4; + name_len = mdb_get_int16(kkd, pos); + pos += 2; + props = mdb_alloc_props(); + if (name_len) { + props->name = g_malloc(name_len + 1); + strncpy(props->name, &kkd[pos], name_len); + props->name[name_len]='\0'; + } + pos += name_len; + + props->hash = g_hash_table_new(g_str_hash, g_str_equal); + + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + elem = mdb_get_int16(kkd, pos + 4); + dtype = kkd[pos + 3]; + dsize = mdb_get_int16(kkd, pos + 6); + value = g_malloc(dsize + 1); + strncpy(value, &kkd[pos + 8], dsize); + value[dsize] = '\0'; + name = g_ptr_array_index(names,elem); +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos, pos + record_len - 1); + printf("elem %d dsize %d dtype %d\n", elem, dsize, dtype); +#endif + if (dtype == MDB_MEMO) dtype = MDB_TEXT; + if (dtype == MDB_BOOL) { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(kkd[pos + 8] ? "yes" : "no")); + } else { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize))); + } + g_free(value); + pos += record_len; + } + return props; + +} diff --git a/plugins/poi_geodownload/libmdb/sargs.c b/plugins/poi_geodownload/libmdb/sargs.c new file mode 100644 index 00000000..b14aaa94 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/sargs.c @@ -0,0 +1,273 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * code for handling searchable arguments (sargs) used primary by the sql + * engine to support where clause handling. The sargs are configured in + * a tree with AND/OR operators connecting the child nodes. NOT operations + * have only one child on the left side. Logical operators (=,<,>,etc..) + * have no children. + * + * datatype support is a bit weak at this point. To add more types create + * a mdb_test_[type]() function and invoke it from mdb_test_sarg() + */ +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void +mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data) +{ + if (func(node, data)) + return; + if (node->left) mdb_sql_walk_tree(node->left, func, data); + if (node->right) mdb_sql_walk_tree(node->right, func, data); +} +int +mdb_test_string(MdbSargNode *node, char *s) +{ +int rc; + + if (node->op == MDB_LIKE) { + return mdb_like_cmp(s,node->value.s); + } + rc = strncmp(node->value.s, s, 255); + switch (node->op) { + case MDB_EQUAL: + if (rc==0) return 1; + break; + case MDB_GT: + if (rc<0) return 1; + break; + case MDB_LT: + if (rc>0) return 1; + break; + case MDB_GTEQ: + if (rc<=0) return 1; + break; + case MDB_LTEQ: + if (rc>=0) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op); + break; + } + return 0; +} +int mdb_test_int(MdbSargNode *node, gint32 i) +{ + switch (node->op) { + case MDB_EQUAL: + printf("comparing %x and %x %d\n", i, node->value.i, node->value.i == i); + if (node->value.i == i) return 1; + break; + case MDB_GT: + if (node->value.i < i) return 1; + break; + case MDB_LT: + if (node->value.i > i) return 1; + break; + case MDB_GTEQ: + if (node->value.i <= i) return 1; + break; + case MDB_LTEQ: + if (node->value.i >= i) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op); + break; + } + return 0; +} +#if 0 +#endif +int +mdb_find_indexable_sargs(MdbSargNode *node, gpointer data) +{ + MdbSarg sarg; + + if (node->op == MDB_OR || node->op == MDB_NOT) return 1; + + /* + * right now all we do is look for sargs that are anded together from + * the root. Later we may put together OR ops into a range, and then + * range scan the leaf pages. That is col1 = 2 or col1 = 4 becomes + * col1 >= 2 and col1 <= 4 for the purpose of index scans, and then + * extra rows are thrown out when the row is tested against the main + * sarg tree. range scans are generally only a bit better than table + * scanning anyway. + * + * also, later we should support the NOT operator, but it's generally + * a pretty worthless test for indexes, ie NOT col1 = 3, we are + * probably better off table scanning. + */ + if (mdb_is_relational_op(node->op) && node->col) { + //printf("op = %d value = %s\n", node->op, node->value.s); + sarg.op = node->op; + sarg.value = node->value; + mdb_add_sarg(node->col, &sarg); + } + return 0; +} +int +mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field) +{ +char tmpbuf[256]; +int lastchar; + + if (node->op == MDB_ISNULL) { + if (field->is_null) return 0; + else return 1; + } else if (node->op == MDB_NOTNULL) { + if (field->is_null) return 1; + else return 0; + } + switch (col->col_type) { + case MDB_BOOL: + return mdb_test_int(node, !field->is_null); + break; + case MDB_BYTE: + return mdb_test_int(node, (gint32)((char *)field->value)[0]); + break; + case MDB_INT: + return mdb_test_int(node, (gint32)mdb_get_int16(field->value, 0)); + break; + case MDB_LONGINT: + return mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0)); + break; + case MDB_TEXT: + if (IS_JET4(mdb)) { + mdb_unicode2ascii(mdb, field->value, 0, field->siz, tmpbuf); + } else { + strncpy(tmpbuf, field->value, 255); + lastchar = field->siz > 255 ? 255 : field->siz; + tmpbuf[lastchar]='\0'; + } + return mdb_test_string(node, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +int +mdb_find_field(int col_num, MdbField *fields, int num_fields) +{ + int i; + + for (i=0;iop)) { + col = node->col; + /* for const = const expressions */ + if (!col) { + return (node->value.i); + } + elem = mdb_find_field(col->col_num, fields, num_fields); + if (!mdb_test_sarg(mdb, col, node, &fields[elem])) + return 0; + } else { /* logical op */ + switch (node->op) { + case MDB_NOT: + rc = mdb_test_sarg_node(mdb, node->left, fields, num_fields); + return !rc; + break; + case MDB_AND: + if (!mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 0; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + case MDB_OR: + if (mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 1; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + } + } + return 1; +} +int +mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields) +{ + MdbSargNode *node; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + node = table->sarg_tree; + + /* there may not be a sarg tree */ + if (!node) return 1; + + return mdb_test_sarg_node(mdb, node, fields, num_fields); +} +#if 0 +int mdb_test_sargs(MdbHandle *mdb, MdbColumn *col, int offset, int len) +{ +MdbSarg *sarg; +int i; + + for (i=0;inum_sargs;i++) { + sarg = g_ptr_array_index (col->sargs, i); + if (!mdb_test_sarg(mdb, col, sarg, offset, len)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + + return 1; +} +#endif +int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg) +{ +MdbSarg *sarg; + if (!col->sargs) { + col->sargs = g_ptr_array_new(); + } + sarg = g_memdup(in_sarg,sizeof(MdbSarg)); + g_ptr_array_add(col->sargs, sarg); + col->num_sargs++; + + return 1; +} +int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg) +{ + MdbColumn *col; + unsigned int i; + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + if (!strcasecmp(col->name,colname)) { + return mdb_add_sarg(col, in_sarg); + } + } + /* else didn't find the column return 0! */ + return 0; +} diff --git a/plugins/poi_geodownload/libmdb/stats.c b/plugins/poi_geodownload/libmdb/stats.c new file mode 100644 index 00000000..1abf2857 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/stats.c @@ -0,0 +1,74 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_stats_on: + * @mdb: Handle to the (open) MDB file to collect stats on. + * + * Begins collection of statistics on an MDBHandle. + * + * Statistics in LibMDB will track the number of reads from the MDB file. The + * collection of statistics is started and stopped with the mdb_stats_on and + * mdb_stats_off functions. Collected statistics are accessed by reading the + * MdbStatistics structure or calling mdb_dump_stats. + * + */ +void +mdb_stats_on(MdbHandle *mdb) +{ + if (!mdb->stats) + mdb->stats = g_malloc0(sizeof(MdbStatistics)); + + mdb->stats->collect = TRUE; +} +/** + * mdb_stats_off: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Turns off statistics collection. + * + * If mdb_stats_off is not called, statistics will be turned off when handle + * is freed using mdb_close. + **/ +void +mdb_stats_off(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + mdb->stats->collect = FALSE; +} +/** + * mdb_dump_stats: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Dumps current statistics to stdout. + **/ +void +mdb_dump_stats(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + fprintf(stdout, "Physical Page Reads: %lu\n", mdb->stats->pg_reads); +} diff --git a/plugins/poi_geodownload/libmdb/table.c b/plugins/poi_geodownload/libmdb/table.c new file mode 100644 index 00000000..d3afca8c --- /dev/null +++ b/plugins/poi_geodownload/libmdb/table.c @@ -0,0 +1,368 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +static gint mdb_col_comparer(MdbColumn **a, MdbColumn **b) +{ + if ((*a)->col_num > (*b)->col_num) + return 1; + else if ((*a)->col_num < (*b)->col_num) + return -1; + else + return 0; +} + +unsigned char mdb_col_needs_size(int col_type) +{ + if (col_type == MDB_TEXT) { + return TRUE; + } else { + return FALSE; + } +} + +MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + + table = (MdbTableDef *) g_malloc0(sizeof(MdbTableDef)); + table->entry=entry; + strcpy(table->name, entry->object_name); + + return table; +} +void mdb_free_tabledef(MdbTableDef *table) +{ + if (!table) return; + if (table->is_temp_table) { + unsigned int i; + for (i=0; itemp_table_pages->len; i++) + g_free(g_ptr_array_index(table->temp_table_pages,i)); + g_ptr_array_free(table->temp_table_pages, TRUE); + } + mdb_free_columns(table->columns); + mdb_free_indices(table->indices); + g_free(table->usage_map); + g_free(table->free_usage_map); + g_free(table); +} +MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + int len, row_start, pg_row; + char *buf; + + table = mdb_alloc_tabledef(entry); + + mdb_read_pg(mdb, entry->table_pg); + if (mdb->pg_buf[0] != 0x02) return NULL; /* not a valid table def page */ + + len = mdb_pg_get_int16(mdb,8); + + table->num_rows = mdb_pg_get_int32(mdb, fmt->tab_num_rows_offset); + table->num_var_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset-2); + table->num_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset); + table->num_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_idxs_offset); + table->num_real_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_ridxs_offset); + /* grab a copy of the usage map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_usage_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz)); + table->usage_map = g_memdup(buf + row_start, table->map_sz); + if (mdb_get_option(MDB_DEBUG_USAGE)) + buffer_dump(buf, row_start, row_start+table->map_sz-1); + mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d", + pg_row >> 8, pg_row & 0xff, row_start, table->map_sz); + + /* grab a copy of the free space page map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_free_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz)); + table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz); + mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n", + pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz); + + table->first_data_pg = mdb_pg_get_int16(mdb, fmt->tab_first_dpg_offset); + + return table; +} +MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + + for (i=0; inum_catalog; i++) { + entry = g_ptr_array_index(mdb->catalog, i); + if (!strcasecmp(entry->object_name, table_name)) + return mdb_read_table(entry); + } + + return NULL; +} + +/* +** read the next page if offset is > pg_size +** return true if page was read +*/ +int +read_pg_if(MdbHandle *mdb, int *cur_pos, int offset) +{ + if (*cur_pos + offset >= mdb->fmt->pg_size) { + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + *cur_pos = 8 - (mdb->fmt->pg_size - (*cur_pos)); + return 1; + } + return 0; +} +guint32 +read_pg_if_32(MdbHandle *mdb, int *cur_pos) +{ + unsigned char c[4]; + int i, rc = 0; + + for (i=0;i<4;i++) { + rc += read_pg_if(mdb, cur_pos, i); + c[i] = mdb->pg_buf[(*cur_pos) + i]; + } + return mdb_get_int32(c, 0); +} +guint16 +read_pg_if_16(MdbHandle *mdb, int *cur_pos) +{ + unsigned char low_byte, high_byte; + int rc = 0; + + rc += read_pg_if(mdb, cur_pos, 0); + low_byte = mdb->pg_buf[*cur_pos]; + rc += read_pg_if(mdb, cur_pos, 1); + high_byte = mdb->pg_buf[(*cur_pos) + 1]; + + return (high_byte * 256 + low_byte); +} +guint16 +read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len) +{ + if (*cur_pos + len < mdb->fmt->pg_size) { + memcpy(buf, &mdb->pg_buf[*cur_pos], len); + return 0; + } else { + int half = mdb->fmt->pg_size - *cur_pos; + memcpy(buf, &mdb->pg_buf[*cur_pos], half); + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + memcpy(buf + half, &mdb->pg_buf[8], len - half); + *cur_pos = 8 - half; + return 1; + } +} + +void mdb_append_column(GPtrArray *columns, MdbColumn *in_col) +{ + g_ptr_array_add(columns, g_memdup(in_col,sizeof(MdbColumn))); +} +void mdb_free_columns(GPtrArray *columns) +{ + unsigned int i; + + if (!columns) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(columns, i)); + g_ptr_array_free(columns, TRUE); +} +GPtrArray *mdb_read_columns(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *pcol; + unsigned char *col; + unsigned int i; + int cur_pos, name_sz; + + table->columns = g_ptr_array_new(); + + col = (unsigned char *) g_malloc(fmt->tab_col_entry_size); + + cur_pos = fmt->tab_cols_start_offset + + (table->num_real_idxs * fmt->tab_ridx_entry_size); + + /* new code based on patch submitted by Tim Nelson 2000.09.27 */ + + /* + ** column attributes + */ + for (i=0;inum_cols;i++) { +#ifdef MDB_DEBUG + /* printf("column %d\n", i); + buffer_dump(mdb->pg_buf, cur_pos ,cur_pos + 18); */ +#endif + read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size); + cur_pos += fmt->tab_col_entry_size; + pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn)); + + pcol->col_type = col[0]; + + // col_num_offset == 1 or 5 + pcol->col_num = col[fmt->col_num_offset]; + + //fprintf(stdout,"----- column %d -----\n",pcol->col_num); + // col_var == 3 or 7 + pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var); + //fprintf(stdout,"var column pos %d\n",pcol->var_col_num); + + // col_var == 5 or 9 + pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset); + //fprintf(stdout,"row column num %d\n",pcol->row_col_num); + + /* FIXME: can this be right in Jet3 and Jet4? */ + if (pcol->col_type == MDB_NUMERIC) { + pcol->col_prec = col[11]; + pcol->col_scale = col[12]; + } + + // col_fixed_offset == 13 or 15 + pcol->is_fixed = col[fmt->col_fixed_offset] & 0x01 ? 1 : 0; + + // col_fixed_offset == 13 or 15 + pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed); + //fprintf(stdout,"fixed column offset %d\n",pcol->fixed_offset); + //fprintf(stdout,"col type %s\n",pcol->is_fixed ? "fixed" : "variable"); + + if (pcol->col_type != MDB_BOOL) { + // col_size_offset == 16 or 23 + pcol->col_size = mdb_get_int16(col, fmt->col_size_offset); + } else { + pcol->col_size=0; + } + + g_ptr_array_add(table->columns, pcol); + } + + g_free (col); + + /* + ** column names - ordered the same as the column attributes table + */ + for (i=0;inum_cols;i++) { + pcol = g_ptr_array_index(table->columns, i); + + if (IS_JET4(mdb)) { + char *tmp_buf; + name_sz = read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmp_buf = (char *) g_malloc(name_sz); + read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz); + mdb_unicode2ascii(mdb, tmp_buf, 0, name_sz, pcol->name); + g_free(tmp_buf); + cur_pos += name_sz; + } else if (IS_JET3(mdb)) { + read_pg_if(mdb, &cur_pos, 0); + name_sz = mdb->pg_buf[cur_pos]; + cur_pos++; + read_pg_if_n(mdb, pcol->name, &cur_pos, name_sz); + pcol->name[name_sz]='\0'; + cur_pos += name_sz; + } else { + fprintf(stderr,"Unknown MDB version\n"); + } + } + + /* Sort the columns by col_num */ + g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer); + + table->index_start = cur_pos; + return table->columns; +} + +void mdb_table_dump(MdbCatalogEntry *entry) +{ +MdbTableDef *table; +MdbColumn *col; +int coln; +MdbIndex *idx; +MdbHandle *mdb = entry->mdb; +unsigned int i, bitn; +guint32 pgnum; + + table = mdb_read_table(entry); + fprintf(stdout,"definition page = %lu\n",entry->table_pg); + fprintf(stdout,"number of datarows = %d\n",table->num_rows); + fprintf(stdout,"number of columns = %d\n",table->num_cols); + fprintf(stdout,"number of indices = %d\n",table->num_real_idxs); + + mdb_read_columns(table); + mdb_read_indices(table); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + + fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n", + i, col->name, + mdb_get_coltype_string(mdb->default_backend, col->col_type), + col->col_size); + } + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_index_dump(table, idx); + } + if (table->usage_map) { + printf("pages reserved by this object\n"); + printf("usage map pg %" G_GUINT32_FORMAT "\n", + table->map_base_pg); + printf("free map pg %" G_GUINT32_FORMAT "\n", + table->freemap_base_pg); + pgnum = mdb_get_int32(table->usage_map,1); + /* the first 5 bytes of the usage map mean something */ + coln = 0; + for (i=5;imap_sz;i++) { + for (bitn=0;bitn<8;bitn++) { + if (table->usage_map[i] & 1 << bitn) { + coln++; + printf("%6" G_GUINT32_FORMAT, pgnum); + if (coln==10) { + printf("\n"); + coln = 0; + } else { + printf(" "); + } + } + pgnum++; + } + } + printf("\n"); + } +} + +int mdb_is_user_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && !(entry->flags & 0x80000002)) ? 1 : 0; +} +int mdb_is_system_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && (entry->flags & 0x80000002)) ? 1 : 0; +} diff --git a/plugins/poi_geodownload/libmdb/worktable.c b/plugins/poi_geodownload/libmdb/worktable.c new file mode 100644 index 00000000..6f893dcf --- /dev/null +++ b/plugins/poi_geodownload/libmdb/worktable.c @@ -0,0 +1,99 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* + * Temp table routines. These are currently used to generate mock results for + * commands like "list tables" and "describe table" + */ + +void +mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed) +{ + memset(tcol,0,sizeof(MdbColumn)); + strcpy(tcol->name, col_name); + tcol->col_type = col_type; + if ((col_type == MDB_TEXT) || (col_type == MDB_MEMO)) { + tcol->col_size = col_size; + } else { + tcol->col_size = mdb_col_fixed_size(tcol); + } + tcol->is_fixed = is_fixed; +} +void +mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int colnum) +{ + field->value = value; + field->siz = siz; + field->is_fixed = is_fixed; + field->is_null = is_null; + field->start = start; + field->colnum = colnum; +} +MdbTableDef * +mdb_create_temp_table(MdbHandle *mdb, char *name) +{ + MdbCatalogEntry *entry; + MdbTableDef *table; + + /* dummy up a catalog entry */ + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + entry->object_type = MDB_TABLE; + entry->table_pg = 0; + strcpy(entry->object_name, name); + + table = mdb_alloc_tabledef(entry); + table->columns = g_ptr_array_new(); + table->is_temp_table = 1; + table->temp_table_pages = g_ptr_array_new(); + + return table; +} +void +mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col) +{ + col->col_num = table->num_cols; + if (!col->is_fixed) + col->var_col_num = table->num_var_cols++; + g_ptr_array_add(table->columns, g_memdup(col, sizeof(MdbColumn))); + table->num_cols++; +} +/* + * Should be called after setting up all temp table columns + */ +void mdb_temp_columns_end(MdbTableDef *table) +{ + MdbColumn *col; + unsigned int i; + unsigned int start = 0; + + for (i=0; inum_cols; i++) { + col = g_ptr_array_index(table->columns, i); + if (col->is_fixed) { + col->fixed_offset = start; + start += col->col_size; + } + } +} diff --git a/plugins/poi_geodownload/libmdb/write.c b/plugins/poi_geodownload/libmdb/write.c new file mode 100644 index 00000000..1cff96a4 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/write.c @@ -0,0 +1,878 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +//static int mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg); +static int mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields); + +void +_mdb_put_int16(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; +} +void +_mdb_put_int32(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; + value /= 256; + buf[offset+2] = value % 256; + value /= 256; + buf[offset+3] = value % 256; +} +ssize_t +mdb_write_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + /* is page beyond current size + 1 ? */ + if (status.st_size < offset + mdb->fmt->pg_size) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + lseek(mdb->f->fd, offset, SEEK_SET); + len = write(mdb->f->fd,mdb->pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("write"); + return 0; + } else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->pg_size); */ + return 0; + } + mdb->cur_pos = 0; + return len; +} + +static int +mdb_is_col_indexed(MdbTableDef *table, int colnum) +{ + unsigned int i, j; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + for (j=0;jnum_keys;j++) { + if (idx->key_col_num[j]==colnum) return 1; + } + } + return 0; +} +static int +mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols=0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = mdb_pg_get_int16(mdb, row_start); + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = mdb_pg_get_int16(mdb, row_end - bitmask_sz - 1); + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + for (i=0; inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 2; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + /* Use col->var_col_num because a deleted column is still + * present in the variable column offsets table for the row */ + } else if ((!fields[i].is_fixed) + && (col->var_col_num < row_var_cols)) { + col_start = var_col_offsets[col->var_col_num]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[(col->var_col_num)+1] - + col_start; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +static int +mdb_crack_row3(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols = 0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found, var_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + unsigned int num_jumps = 0, jumps_used = 0; + unsigned int col_ptr, row_len; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = pg_buf[row_start]; + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = pg_buf[row_end - bitmask_sz]; + row_len = row_end - row_start + 1; + num_jumps = (row_len - 1) / 256; + col_ptr = row_end - bitmask_sz - num_jumps - 1; + /* If last jump is a dummy value, ignore it */ + if ((col_ptr-row_start-row_var_cols)/256 < num_jumps) + num_jumps--; + + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + jumps_used = 0; + for (i=0; inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 1; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + } else if ((!fields[i].is_fixed) + && (var_cols_found < row_var_cols)) { + col_start = var_col_offsets[var_cols_found]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[var_cols_found+1] - + col_start; + var_cols_found++; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +/** + * mdb_crack_row: + * @table: Table that the row belongs to + * @row_start: offset to start of row on current page + * @row_end: offset to end of row on current page + * @fields: pointer to MdbField array to be popluated by mdb_crack_row + * + * Cracks a row buffer apart into its component fields. + * + * A row buffer is that portion of a data page which contains the values for + * that row. Its beginning and end can be found in the row offset table. + * + * The resulting MdbField array contains pointers into the row for each field + * present. Be aware that by modifying field[]->value, you would be modifying + * the row buffer itself, not a copy. + * + * This routine is mostly used internally by mdb_fetch_row() but may have some + * applicability for advanced application programs. + * + * Return value: number of fields present. + */ +int +mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; + + if (IS_JET4(mdb)) { + return mdb_crack_row4(table, row_start, row_end, fields); + } else { + return mdb_crack_row3(table, row_start, row_end, fields); + } +} + +static int +mdb_pack_null_mask(unsigned char *buffer, int num_fields, MdbField *fields) +{ + int pos = 0, bit = 0, byte = 0; + int i; + + /* 'Not null' bitmap */ + for (i=0; i> 8) & 0xff; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i> 8) & 0xff; + pos += 2; + + /* Offsets of the variable-length columns */ + for (i=num_fields; i>0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + row_buffer[pos++] = (fields[i-1].offset >> 8) & 0xff; + } + } + /* Number of variable-length columns */ + row_buffer[pos++] = var_cols & 0xff; + row_buffer[pos++] = (var_cols >> 8) & 0xff; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} + +static int +mdb_pack_row3(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields) +{ + unsigned int pos = 0; + unsigned int var_cols = 0; + unsigned int i, j; + unsigned char *offset_high; + + row_buffer[pos++] = num_fields; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + offset_high[j++] = (fields[i-1].offset << 8) & 0xff; + } + } + + /* Dummy jump table entry */ + if (offset_high[0] < (pos+(num_fields+7)/8-1)/255) { + row_buffer[pos++] = 0xff; + } + /* Jump table */ + for (i=0; i offset_high[i+1]) { + row_buffer[pos++] = var_cols-i; + } + } + g_free(offset_high); + + row_buffer[pos++] = var_cols; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} +int +mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, int unsigned num_fields, MdbField *fields) +{ + if (table->is_temp_table) { + unsigned int i; + for (i=0; icolumns, i); + fields[i].is_null = (fields[i].value) ? 0 : 1; + fields[i].colnum = i; + fields[i].is_fixed = c->is_fixed; + if ((c->col_type != MDB_TEXT) + && (c->col_type != MDB_MEMO)) { + fields[i].siz = c->col_size; + } + } + } + if (IS_JET4(table->entry->mdb)) { + return mdb_pack_row4(table, row_buffer, num_fields, fields); + } else { + return mdb_pack_row3(table, row_buffer, num_fields, fields); + } +} +int +mdb_pg_get_freespace(MdbHandle *mdb) +{ + int rows, free_start, free_end; + int row_count_offset = mdb->fmt->row_count_offset; + + rows = mdb_pg_get_int16(mdb, row_count_offset); + free_start = row_count_offset + 2 + (rows * 2); + free_end = mdb_pg_get_int16(mdb, row_count_offset + (rows * 2)); + mdb_debug(MDB_DEBUG_WRITE,"free space left on page = %d", free_end - free_start); + return (free_end - free_start); +} +unsigned char * +mdb_new_leaf_pg(MdbCatalogEntry *entry) +{ + MdbHandle *mdb = entry->mdb; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(mdb->fmt->pg_size); + + new_pg[0]=0x04; + new_pg[1]=0x01; + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} +unsigned char * +mdb_new_data_pg(MdbCatalogEntry *entry) +{ + MdbFormatConstants *fmt = entry->mdb->fmt; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(fmt->pg_size); + + new_pg[0]=0x01; + new_pg[1]=0x01; + _mdb_put_int16(new_pg, 2, fmt->pg_size - fmt->row_count_offset - 2); + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} + +int +mdb_update_indexes(MdbTableDef *table, int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + unsigned int i; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_debug(MDB_DEBUG_WRITE,"Updating %s (%d).", idx->name, idx->index_type); + if (idx->index_type==1) { + mdb_update_index(table, idx, num_fields, fields, pgnum, rownum); + } + } + return 1; +} + +int +mdb_init_index_chain(MdbTableDef *table, MdbIndex *idx) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + table->scan_idx = idx; + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + + return 1; +} + +int +mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int idx_xref[16]; + unsigned int i, j; + MdbIndexChain *chain; + MdbField idx_fields[10]; + + for (i = 0; i < idx->num_keys; i++) { + for (j = 0; j < num_fields; j++) { + // key_col_num is 1 based, can't remember why though + if (fields[j].colnum == idx->key_col_num[i]-1) { + idx_xref[i] = j; + idx_fields[i] = fields[j]; + } + } + } + for (i = 0; i < idx->num_keys; i++) { + fprintf(stdout, "key col %d (%d) is mapped to field %d (%d %d)\n", + i, idx->key_col_num[i], idx_xref[i], fields[idx_xref[i]].colnum, + fields[idx_xref[i]].siz); + } + for (i = 0; i < num_fields; i++) { + fprintf(stdout, "%d (%d %d)\n", + i, fields[i].colnum, + fields[i].siz); + } + + chain = g_malloc0(sizeof(MdbIndexChain)); + + mdb_index_find_row(mdb, idx, chain, pgnum, rownum); + printf("chain depth = %d\n", chain->cur_depth); + printf("pg = %" G_GUINT32_FORMAT "\n", + chain->pages[chain->cur_depth-1].pg); + //mdb_copy_index_pg(table, idx, &chain->pages[chain->cur_depth-1]); + mdb_add_row_to_leaf_pg(table, idx, &chain->pages[chain->cur_depth-1], idx_fields); + + return 1; +} + +int +mdb_insert_row(MdbTableDef *table, int num_fields, MdbField *fields) +{ + int new_row_size; + unsigned char row_buffer[4096]; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + guint32 pgnum; + guint16 rownum; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(row_buffer, 0, new_row_size-1); + } + pgnum = mdb_map_find_next_freepage(table, new_row_size); + if (!pgnum) { + fprintf(stderr, "Unable to allocate new page.\n"); + return 0; + } + + rownum = mdb_add_row_to_pg(table, row_buffer, new_row_size); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE, "writing page %d", pgnum); + if (!mdb_write_pg(mdb, pgnum)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + + mdb_update_indexes(table, num_fields, fields, pgnum, rownum); + + return 1; +} +/* + * Assumes caller has verfied space is available on page and adds the new + * row to the current pg_buf. + */ +guint16 +mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size) +{ + unsigned char *new_pg; + int num_rows, i, pos, row_start, row_end, row_size; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + if (pages->len == 0) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } else { + new_pg = g_ptr_array_index(pages, pages->len - 1); + if (mdb_get_int16(new_pg, 2) < new_row_size + 2) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } + } + + num_rows = mdb_get_int16(new_pg, fmt->row_count_offset); + pos = (num_rows == 0) ? fmt->pg_size : + mdb_get_int16(new_pg, fmt->row_count_offset + (num_rows*2)); + } else { /* is not a temp table */ + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + pos = fmt->pg_size; + + /* copy existing rows */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + } + + /* add our new row */ + pos -= new_row_size; + memcpy(&new_pg[pos], row_buffer, new_row_size); + /* add row to the row offset table */ + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); + + /* update number rows on this page */ + num_rows++; + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + /* update the freespace */ + _mdb_put_int16(new_pg,2,pos - fmt->row_count_offset - 2 - (num_rows*2)); + + /* copy new page over old */ + if (!table->is_temp_table) { + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + g_free(new_pg); + } + + return num_rows; +} +int +mdb_update_row(MdbTableDef *table) +{ +int row_start, row_end; +unsigned int i; +MdbColumn *col; +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +MdbField fields[256]; +unsigned char row_buffer[4096]; +int old_row_size, new_row_size, delta; +unsigned int num_fields; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + ((table->cur_row-1)*2)); + row_end = mdb_find_end_of_row(mdb, table->cur_row-1); + old_row_size = row_end - row_start; + + row_start &= 0x0FFF; /* remove flags */ + + mdb_debug(MDB_DEBUG_WRITE,"page %lu row %d start %d end %d", (unsigned long) table->cur_phys_pg, table->cur_row-1, row_start, row_end); + if (mdb_get_option(MDB_DEBUG_LIKE)) + buffer_dump(mdb->pg_buf, row_start, row_end); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr && mdb_is_col_indexed(table,i)) { + fprintf(stderr, "Attempting to update column that is part of an index\n"); + return 0; + } + } + num_fields = mdb_crack_row(table, row_start, row_end, fields); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr) { + printf("yes\n"); + fields[i].value = col->bind_ptr; + fields[i].siz = *(col->len_ptr); + } + } + + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) + buffer_dump(row_buffer, 0, new_row_size-1); + delta = new_row_size - old_row_size; + if ((mdb_pg_get_freespace(mdb) - delta) < 0) { + fprintf(stderr, "No space left on this page, update will not occur\n"); + return 0; + } + /* do it! */ + mdb_replace_row(table, table->cur_row-1, row_buffer, new_row_size); + return 0; +} +int +mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +unsigned char *new_pg; +guint16 num_rows; +int row_start, row_end, row_size; +int i, pos; + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE,"updating row %d on page %lu", row, (unsigned long) table->cur_phys_pg); + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + pos = mdb->fmt->pg_size; + + /* rows before */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* our row */ + pos -= new_row_size; + memcpy(&new_pg[pos], new_row, new_row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (row*2), pos); + + /* rows after */ + for (i=row+1;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* almost done, copy page over current */ + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + + g_free(new_pg); + + _mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + /* drum roll, please */ + if (!mdb_write_pg(mdb, table->cur_phys_pg)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + return 0; +} +static int +mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields) +/*, guint32 pgnum, guint16 rownum) +static int +mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg) +*/ +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + guint32 pg; + guint16 row; + unsigned char *new_pg; + unsigned char key_hash[256]; + unsigned char iflag; + int keycol; + + new_pg = mdb_new_leaf_pg(entry); + + mdb_index_page_reset(ipg); + mdb_read_pg(mdb, ipg->pg); + + /* do we support this index type yet? */ + if (idx->num_keys > 1) { + fprintf(stderr,"multikey indexes not yet supported, aborting\n"); + return 0; + } + keycol = idx->key_col_num[0]; + col = g_ptr_array_index (table->columns, keycol - 1); + printf("keycol = %d (%s)\n", keycol, col->name); + if (!mdb_is_fixed_col(col)) { + fprintf(stderr,"variable length key columns not yet supported, aborting\n"); + return 0; + } + printf("col size = %d\n", col->col_size); + + while (mdb_index_find_next_on_page(mdb, ipg)) { + + /* check for compressed indexes. */ + if (ipg->len < col->col_size + 1) { + fprintf(stderr,"compressed indexes not yet supported, aborting\n"); + return 0; + } + + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + row = mdb->pg_buf[ipg->offset + ipg->len - 1]; + iflag = mdb->pg_buf[ipg->offset]; + mdb_index_swap_n(&mdb->pg_buf[ipg->offset + 1], col->col_size, key_hash); + key_hash[col->col_size - 1] &= 0x7f; + printf("length = %d\n", ipg->len); + printf("iflag = %d pg = %" G_GUINT32_FORMAT + " row = %" G_GUINT16_FORMAT "\n", iflag, pg, row); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset + ipg->len - 1); + buffer_dump(mdb->pg_buf, ipg->offset + 1, ipg->offset + col->col_size); + buffer_dump(key_hash, 0, col->col_size - 1); + ipg->offset += ipg->len; + ipg->len = 0; + row++; + } + g_free(new_pg); + + return ipg->len; +} diff --git a/plugins/poi_geodownload/poi.c b/plugins/poi_geodownload/poi.c new file mode 100644 index 00000000..9b6ef93e --- /dev/null +++ b/plugins/poi_geodownload/poi.c @@ -0,0 +1,474 @@ +#include +#include "display.h" +#include "container.h" +#include "coord.h" +#include "transform.h" +#include "popup.h" +#include "plugin.h" + + +struct index_data { + unsigned char data[15]; +}; +struct poi { + char *filename; + char *icon; + MdbHandle *h; + MdbHandle *h_idx; + MdbTableDef *table; + GPtrArray *table_col; + MdbColumn **cols; + MdbIndex *idx; + int idx_size; + struct index_data index_data; + MdbIndexChain chain; + struct poi *next; +} *poi_list; + +struct poi_data { + struct poi *poi; + int page; + int row; +}; + + +static void +print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) +{ + switch (col->col_type) { + case MDB_BOOL: + strcpy(buffer, mdb_pg_get_byte(h, col->cur_value_start) ? "True" : "False"); + break; + case MDB_BYTE: + sprintf(buffer, "%d", mdb_pg_get_byte(h, col->cur_value_start)); + break; + case MDB_LONGINT: + if (hex) + sprintf(buffer, "0x%lx", mdb_pg_get_int32(h, col->cur_value_start)); + else + sprintf(buffer, "%ld", mdb_pg_get_int32(h, col->cur_value_start)); + break; + case MDB_DOUBLE: + sprintf(buffer, "%f", mdb_pg_get_double(h, col->cur_value_start)); + break; + case MDB_TEXT: + sprintf(buffer, "%s", mdb_col_to_string (h, h->pg_buf, col-> cur_value_start, + col->col_type, col->cur_value_len)); + break; + default: + sprintf(buffer, "unknown (%d)", col->col_type); + } +} + +static void +setup_idx_data(struct index_data *idx, struct coord *c, unsigned int geoflags, int size) +{ + /* 7f 80 1c 91 0a 7f 80 5c f5 41 7f 80 00 00 05 */ + idx->data[0]=0x7f; + idx->data[1]=(c->x >> 24) ^ 0x80; + idx->data[2]=c->x >> 16; + idx->data[3]=c->x >> 8; + idx->data[4]=c->x; + idx->data[5]=0x7f; + idx->data[6]=(c->y >> 24) ^ 0x80; + idx->data[7]=c->y >> 16; + idx->data[8]=c->y >> 8; + idx->data[9]=c->y; + idx->data[10]=0x7f; + if (size > 12) { + idx->data[11]=0x80 | (geoflags >> 24); + idx->data[12]=geoflags >> 16; + idx->data[13]=geoflags >> 8; + idx->data[14]=geoflags; + } else { + idx->data[11]=geoflags; + } +} + +static void +setup_idx_rect(struct coord *rect, struct index_data *idx, int size) +{ + struct coord r[2]; + r[0].x=rect[0].x; + r[0].y=rect[1].y; + r[1].x=rect[1].x; + r[1].y=rect[0].y; +#if 0 + printf("low 0x%x 0%x\n", r[0].x, r[0].y); + printf("high 0x%x 0%x\n", r[1].x, r[1].y); +#endif + setup_idx_data(idx, r, 0, size); + setup_idx_data(idx+1, r+1, 0xffffffff, size); +} + +static int +load_row(struct poi *poi, int pg, int row) +{ + int row_start, row_end, offset; + unsigned int num_fields, i; + MdbField fields[256]; + MdbFormatConstants *fmt; + int debug=0; + + fmt=poi->h->fmt; + mdb_read_pg(poi->h, pg); + if (debug) + printf("Page Type %d row_count_offset %d\n",poi->h->pg_buf[0], fmt->row_count_offset); + if (debug > 1) { + for (i = 0; i <= row; i++) { + offset=(fmt->row_count_offset + 2) + i * 2; + printf("row %d %d 0x%x\n", i, offset, mdb_pg_get_int16(poi->h, offset)); + } + } + row_start = mdb_pg_get_int16(poi->h, (fmt->row_count_offset + 2) + row * 2); + if (row_start & 0x4000) + return 1; + row_end = mdb_find_end_of_row(poi->h, row); + if (debug) { + printf("start=0x%x end=0x%x\n", row_start, row_end); + buffer_dump(poi->h->pg_buf, row_start, row_end); + } + + poi->h->cur_pos=row_start & 0x1fff; + poi->table->cur_row=row+1; + num_fields = mdb_crack_row(poi->table, row_start & 0x1fff, row_end, fields); + if (debug) + printf("num_fields=%d\n", num_fields); + for (i = 0; i < num_fields; i++) { + poi->cols[i]->cur_value_start=fields[i].start; + poi->cols[i]->cur_value_len=fields[i].siz; + } + return 0; +} + +static MdbIndexPage * +index_next_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no next\n"); +#endif + if (!chain->clean_up_mode) { +#if 0 + printf("no cleanup\n"); +#endif + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { +#if 0 + printf("cleanup\n"); +#endif + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) { + printf("no last_leaf_found\n"); + return NULL; + } + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = + mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no find_next_on_page\n"); +#endif + return NULL; + } + } + } + return ipg; +} + +static int +index_next(struct poi *poi, struct index_data *idx) +{ + MdbIndexPage *ipg; + MdbIndexChain *chain = &poi->chain; + int row; + int pg; + int offset; + char *cmp, *low, *high; + int debug=0; + + + for(;;) { + for(;;) { + ipg=index_next_row(poi->h_idx, poi->idx, chain); + if (! ipg) + return 0; + row = poi->h_idx->pg_buf[ipg->offset + ipg->len - 1]; + pg = mdb_pg_get_int24_msb(poi->h_idx, ipg->offset + ipg->len - 4); + + offset=poi->idx_size+4-ipg->len; + memcpy(poi->index_data.data+offset, poi->h_idx->pg_buf+ipg->offset, ipg->len - 4); + cmp=poi->index_data.data; + low=idx[0].data; + high=idx[1].data; + if (debug > 1) { + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } +#if 0 + buffer_dump(poi->h_idx->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + ipg->offset += ipg->len; + if (memcmp(cmp, low, poi->idx_size) >= 0) { + if (memcmp(cmp, high, poi->idx_size) <=0 ) { + if (debug) { + printf("match\n"); + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } + break; + } else { + return 0; + } + } + if (debug > 1) + printf("row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + } + if (debug) + printf("match: row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + if (!load_row(poi, pg, row)) + break; + } + return 1; +} + + +static int +load_poi_table(struct poi *poi, MdbCatalogEntry *entry) +{ + int j; + MdbIndex *idx; + + poi->h_idx=NULL; + poi->table = mdb_read_table(entry); + poi->table_col = mdb_read_columns(poi->table); + mdb_read_indices(poi->table); + poi->cols = (MdbColumn **) (poi->table_col->pdata); + if (poi->table_col->len < 4 || strcasecmp(poi->cols[0]->name, "X") || + strcasecmp(poi->cols[1]->name, "Y") || strcasecmp(poi->cols[3]->name, "GEOFLAGS")) + return 1; + for (j = 0; j < poi->table->num_idxs; j++) { + idx = poi->table->indices->pdata[j]; + if (idx->num_keys == 3 && idx->key_col_num[0] == 1 && + idx->key_col_num[1] == 2 && idx->key_col_num[2] == 4) { + poi->idx = idx; + poi->idx_size=3+poi->cols[0]->col_size+poi->cols[1]->col_size+poi->cols[3]->col_size; + poi->h_idx=mdb_clone_handle(poi->h); + } + } + return 0; +} + +static void +load_poi(char *filename, char *icon) +{ + int i; + MdbCatalogEntry *entry; + GPtrArray *catalog; + struct poi *new = g_new(struct poi, 1); + + new->filename = filename; + new->icon = icon; + + new->h = mdb_open(filename, MDB_NOFLAGS); + catalog = mdb_read_catalog(new->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(new, entry)) { + printf("%s invalid\n", filename); + free(new); + new=NULL; + } + } + } + g_ptr_array_free(catalog, 1); + if (new) { + new->next = poi_list; + poi_list = new; + } +} + +static void +get_coord(struct poi *p, struct coord *c) +{ + c->x=mdb_pg_get_int32(p->h, p->cols[0]->cur_value_start); + c->y=mdb_pg_get_int32(p->h, p->cols[1]->cur_value_start); +} + +static void +poi_info(struct display_list *list, struct popup_item **popup) +{ + struct poi_data *data=list->data; + struct poi *poi=data->poi; + struct popup_item *popup_last, *popup_val_last; + char *text,buffer[4096]; + int j; + MdbColumn *col; + char *v; + + popup_last = *popup; + printf("poi_info pg=%d row=%d\n", data->page, data->row); + load_row(poi, data->page, data->row); + + popup_val_last = NULL; + sprintf(buffer,"File:%s", poi->filename); + popup_item_new_text(&popup_val_last, buffer, 1); + sprintf(buffer,"Icon:%s", poi->icon); + popup_item_new_text(&popup_val_last, buffer, 2); + sprintf(buffer,"Page:%d", data->page); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Row:%d", data->row); + popup_item_new_text(&popup_val_last, buffer, 4); + for (j = 0; j < poi->table_col->len; j++) { + col = poi->table_col->pdata[j]; +#if 0 + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); +#endif + sprintf(buffer, "%s:", col->name); + v = buffer + strlen(buffer); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(poi->h, col, v, 1); + else + print_col(poi->h, col, v, 0); +#if 0 + printf("%s\n", buffer); +#endif + text=g_convert(buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + popup_item_new_text(&popup_val_last, buffer, j+10); + g_free(text); + + } + popup_item_new_text(&popup_last, "POI", 20)->submenu = popup_val_last; + *popup=popup_last; +} + +static void +draw_poi(struct poi *p, struct container *co, struct point *pnt) +{ + struct poi_data data; + data.poi=p; + data.page=p->h->cur_pg; + data.row=p->table->cur_row-1; + display_add(&co->disp[display_poi], 5, 0, p->icon, 1, pnt, poi_info, &data, sizeof(data)); +} + +static void +plugin_draw(struct container *co) +{ + struct coord c; + struct point pnt; + struct poi *p; + struct index_data idx[2]; + int use_index=1; + int debug=0; + + p = poi_list; + + if (co->trans->scale > 256) + return; + if (debug) { + printf("scale=%ld\n", co->trans->scale); + printf("rect 0x%lx,0%lx-0x%lx,0x%lx\n", co->trans->rect[0].x, co->trans->rect[0].y, co->trans->rect[1].x, co->trans->rect[1].y); + } + while (p) { + if (use_index) + setup_idx_rect(co->trans->rect, idx, p->idx_size); + if (! use_index) { + printf("rewind %s %p\n", p->filename, p->table); + mdb_rewind_table(p->table); + while (mdb_fetch_row(p->table)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } else { + memset(&p->chain, 0, sizeof(p->chain)); + while (index_next(p, idx)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } + p = p->next; + } + +} + + +int plugin_init(void) +{ + plugin_register_draw(plugin_draw); + mdb_init(); + load_poi("/home/martin/map/work/data/1/GEO00001.MDB", + "/home/martin/map/work/data/1/_MCDNLDS.BMP"); + load_poi("/home/martin/map/work/data/2/GEO00001.MDB", + "/home/martin/map/work/data/2/_BURKING.BMP"); + load_poi("/home/martin/map/work/data/3/GEO00001.MDB", + "/home/martin/map/work/data/3/_PIZZHUT.BMP"); + load_poi("/home/martin/map/work/data/4/GEO00001.MDB", + "/home/martin/map/work/data/4/_CHICKEN.BMP"); + load_poi("/home/martin/map/work/data/5/GEO00001.MDB", + "/home/martin/map/work/data/5/_WIENERW.BMP"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/bahn.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/bahn.adr/BAHN.BMP"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/cinmus.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/cinmus.adr/_Kinocen.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/fsight.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/fsight.adr/_sehensw.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/erlbns.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/erlbns.adr/_Freizei.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/faehre.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/faehre.adr/_Faehren.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/fenter.adr/GEO00001.MDB", + "/opt/reiseplaner/travel/prog.mov/fenter.adr/_casino.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/vhotel.adr/Geo00001.mdb", + "/opt/reiseplaner/travel/prog.mov/vhotel.adr/Vhotel.bmp"); + load_poi + ("/opt/reiseplaner/travel/prog.mov/vgast.adr/Geo00001.mdb", + "/opt/reiseplaner/travel/prog.mov/vgast.adr/Vgast.BMP"); + load_poi + ("/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.mdb", + "/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.bmp"); + load_poi + ("/opt/reiseplaner/travel/address/p_eeu.adr/p_eeu.mdb", + "/opt/reiseplaner/travel/address/p_eeu.adr/P_eeu.bmp"); + load_poi + ("/opt/reiseplaner/travel/address/p_heu.adr/p_heu.mdb", + "/opt/reiseplaner/travel/address/p_heu.adr/P_heu.bmp"); + load_poi + ("/opt/reiseplaner/travel/address/p_ieu.adr/p_ieu.mdb", + "/opt/reiseplaner/travel/address/p_ieu.adr/P_ieu.bmp"); + return 0; +} diff --git a/point.h b/point.h new file mode 100644 index 00000000..6672f3d5 --- /dev/null +++ b/point.h @@ -0,0 +1,9 @@ +#ifndef POINT_H +#define POINT_H + +struct point { + int x; + int y; +}; + +#endif diff --git a/poly.c b/poly.c new file mode 100644 index 00000000..954e7fb2 --- /dev/null +++ b/poly.c @@ -0,0 +1,109 @@ +#include +#include +#include "coord.h" +#include "map_data.h" +#include "file.h" +#include "block.h" +#include "poly.h" +#include "display.h" +#include "draw_info.h" +#include "data_window.h" +#include "container.h" + +extern struct data_window poly_window; + +int +poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) +{ + poly_hdr->addr=*p; + poly_hdr->c=(struct coord *) (*p); + *p+=3*sizeof(struct coord); + poly_hdr->name=*p; + while (**p) { + (*p)++; + } + (*p)++; + poly_hdr->order=*(*p)++; + poly_hdr->type=*(*p)++; + poly_hdr->polys=*(unsigned long *)(*p); (*p)+=sizeof(unsigned long); + poly_hdr->count=(unsigned long *)(*p); (*p)+=poly_hdr->polys*sizeof(unsigned long); + poly_hdr->count_sum=*(unsigned long *)(*p); (*p)+=sizeof(unsigned long); + return 0; +} + +void +poly_draw_segment(struct container *co, struct segment *seg, int disp, unsigned char **p, int limit) +{ + struct poly_hdr poly_hdr; + struct coord *coord; + unsigned int j,k,o; + struct point pnt; + struct param_list param[100]; + int max=20000; + struct point xpoints[max]; + + seg->data[0]=*p; + poly_get_hdr(p, &poly_hdr); + if (poly_hdr.order < limit && is_visible(co->trans, poly_hdr.c)) { + transform(co->trans,&poly_hdr.c[2],&pnt); + for (k = 0 ; k < poly_hdr.polys ; k++) { + assert(poly_hdr.count[k] < max); + for (j = 0 ; j < poly_hdr.count[k] ; j++) { + transform(co->trans, coord_get(p), &xpoints[j]); + } + if (poly_hdr.type < 0x80) { + o=0; + if (poly_hdr.type == 0x1e) + o=1; + else if (poly_hdr.type == 0x2d) + o=2; + else if (poly_hdr.type == 0x32) + o=3; + display_add(&co->disp[disp+o], 0, 0, poly_hdr.name, poly_hdr.count[k], xpoints, NULL, seg, sizeof(*seg)); + + } else { + display_add(&co->disp[disp], 1, 0, poly_hdr.name, poly_hdr.count[k], xpoints, NULL, seg, sizeof(*seg)); + } + if (co->data_window[data_window_type_poly]) + data_window_add(co->data_window[data_window_type_poly], param, poly_get_param(seg, param, 100)); + } + } else + (*p)+=poly_hdr.count_sum*sizeof(*coord); +} + +void +poly_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + struct draw_info *drw_inf=data; + struct segment seg; + int i; + + seg.blk_inf=*blk_inf; + + for (i = 0 ; i < blk_inf->block->count ; i++) + poly_draw_segment(drw_inf->co, &seg, drw_inf->display, &p, drw_inf->limit); +} + + +int +poly_get_param(struct segment *seg, struct param_list *param, int count) +{ + int i=count; + unsigned char *p=seg->data[0]; + struct poly_hdr poly_hdr; + + + param_add_hex("Addr", p-seg->blk_inf.file->begin, ¶m, &count); + poly_get_hdr(&p, &poly_hdr); + param_add_string("Name", poly_hdr.name, ¶m, &count); + param_add_hex("L", poly_hdr.c[0].x, ¶m, &count); + param_add_hex("T", poly_hdr.c[0].y, ¶m, &count); + param_add_hex("R", poly_hdr.c[1].x, ¶m, &count); + param_add_hex("B", poly_hdr.c[1].y, ¶m, &count); + param_add_hex("X", poly_hdr.c[2].x, ¶m, &count); + param_add_hex("Y", poly_hdr.c[2].y, ¶m, &count); + param_add_hex("Order", poly_hdr.order, ¶m, &count); + param_add_hex("Type", poly_hdr.type, ¶m, &count); + param_add_hex("Polys", poly_hdr.polys, ¶m, &count); + return i-count; +} diff --git a/poly.h b/poly.h new file mode 100644 index 00000000..8d735f5b --- /dev/null +++ b/poly.h @@ -0,0 +1,13 @@ +struct poly_hdr { + unsigned char *addr; + struct coord *c; + char *name; + unsigned char order; + unsigned char type; + unsigned long polys; + unsigned long *count; + unsigned long count_sum; +}; + +void poly_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data); +int poly_get_param(struct segment *seg, struct param_list *param, int count); diff --git a/popup.c b/popup.c new file mode 100644 index 00000000..f0fc5883 --- /dev/null +++ b/popup.c @@ -0,0 +1,306 @@ +#include +#include +#include +#include +#include +#include "coord.h" +#include "param.h" +#include "map_data.h" +#include "block.h" +#include "display.h" +#include "town.h" +#include "street.h" +#include "poly.h" +#include "log.h" +#include "popup.h" +#include "plugin.h" +#include "vehicle.h" +#include "route.h" +#include "cursor.h" +#include "statusbar.h" +#include "container.h" + +void +popup_item_destroy_text(struct popup_item *item) +{ + g_free(item->text); + g_free(item); +} + +struct popup_item * +popup_item_new_text(struct popup_item **last, char *text, int priority) +{ + struct popup_item *curr; + curr=g_new(struct popup_item,1); + memset(curr, 0, sizeof(*curr)); + curr->text=g_strdup(text); + curr->priority=priority; + curr->destroy=popup_item_destroy_text; + if (last) { + curr->next=*last; + *last=curr; + } + return curr; +} + +struct popup_item * +popup_item_new_func(struct popup_item **last, char *text, int priority, void (*func)(struct popup_item *, void *), void *param) +{ + struct popup_item *curr=popup_item_new_text(last, text, priority); + curr->func=func; + curr->param=param; + return curr; +} + +struct popup_item * +param_to_menu_new(char *name,struct param_list *plist, int c, int iso) +{ + struct popup_item *last, *curr, *ret; + int i; + + ret=popup_item_new_text(NULL,name,1); + last=NULL; + for (i = 0 ; i < c ; i++) { + char name_buffer[strlen(plist[i].name)+strlen(plist[i].value)+2]; + char *text=name_buffer; + + sprintf(name_buffer,"%s:%s", plist[i].name, plist[i].value); + if (iso) { + text=g_convert(name_buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + if (! text) { + printf("problem converting '%s'\n", name_buffer); + } + } + curr=popup_item_new_text(&last, text, i); + if (iso) + free(text); + } + ret->submenu=last; + return ret; +} + +void +popup_set_no_passing(struct popup_item *item, void *param) +{ + struct display_list *l=param; + struct segment *seg=(struct segment *)(l->data); + struct street_str *str=(struct street_str *)(seg->data[0]); + char log[256]; + int segid=str->segid; + if (segid < 0) + segid=-segid; + + sprintf(log,"Attributes Street 0x%x updated: limit=0x%x(0x%x)", segid, 0x33, str->limit); + str->limit=0x33; + log_write(log, seg->blk_inf.file, str, sizeof(*str)); +} + +void +popup_set_destination(struct popup_item *item, void *param) +{ + struct popup_item *ref=param; + struct popup *popup=ref->param; + struct container *co=popup->co; + printf("Destination %s\n", ref->text); + route_set_position(co->route, cursor_pos_get(co->cursor)); + route_set_destination(co->route, &popup->c); + graphics_redraw(popup->co); + if (co->statusbar && co->statusbar->statusbar_route_update) + co->statusbar->statusbar_route_update(co->statusbar, co->route); +} + +extern void *vehicle; + +void +popup_set_position(struct popup_item *item, void *param) +{ + struct popup_item *ref=param; + struct popup *popup=ref->param; + printf("Position %s\n", ref->text); + vehicle_set_position(popup->co->vehicle, &popup->c); +} + +void +popup_break_crossing(struct display_list *l) +{ + struct segment *seg=(struct segment *)(l->data); + struct street_str *str=(struct street_str *)(seg->data[0]); + char log[256]; + int segid=str->segid; + if (segid < 0) + segid=-segid; + + sprintf(log,"Coordinates Street 0x%x updated: limit=0x%x(0x%x)", segid, 0x33, str->limit); + str->limit=0x33; + log_write(log, seg->blk_inf.file, str, sizeof(*str)); +} + +void +popup_call_func(GtkObject *obj, void *parm) +{ + struct popup_item *curr=parm; + curr->func(curr, curr->param); +} + +GtkWidget * +popup_menu(struct popup_item *list) +{ + int min_prio,curr_prio; + struct popup_item *curr; + GtkWidget *item,*menu,*submenu; + + curr_prio=0; + menu=gtk_menu_new(); + do { + min_prio=INT_MAX; + curr=list; + while (curr) { + if (curr->priority == curr_prio) { + item=gtk_menu_item_new_with_label(curr->text); + gtk_menu_append(GTK_MENU(menu), item); + if (curr->submenu) { + submenu=popup_menu(curr->submenu); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); + } else if (curr->func) { + gtk_signal_connect(GTK_OBJECT(item), "activate", + GTK_SIGNAL_FUNC (popup_call_func), curr); + } + } + if (curr->priority > curr_prio && curr->priority < min_prio) + min_prio=curr->priority; + curr=curr->next; + } + curr_prio=min_prio; + } while (min_prio != INT_MAX); + return menu; +} + +void +popup_display_list_default(struct display_list *d, struct popup_item **popup_list) +{ + struct segment *seg; + char *desc,*text,*item_text; + struct popup_item *curr_item,*submenu; + struct param_list plist[100]; + + desc=NULL; + if (d->type == 0) desc="Polygon"; + if (d->type == 1) desc="Polyline"; + if (d->type == 2) desc="Street"; + if (d->type == 3) desc="Label"; + if (d->type == 4) desc="Point"; + seg=(struct segment *)(d->data); + if (seg) { + if (d->label && strlen(d->label)) { + item_text=malloc(strlen(desc)+strlen(d->label)+2); + strcpy(item_text, desc); + strcat(item_text," "); + strcat(item_text, d->label); + } else { + item_text=desc; + } + text=g_convert(item_text,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + curr_item=popup_item_new_text(popup_list,text,1); + g_free(text); + + curr_item->submenu=param_to_menu_new("File", plist, file_get_param(seg->blk_inf.file, plist, 100), 1); + submenu=curr_item->submenu; + submenu->next=param_to_menu_new("Block", plist, block_get_param(&seg->blk_inf, plist, 100), 1); + submenu=submenu->next; + + if (d->type == 0 || d->type == 1) { + submenu->next=param_to_menu_new(desc, plist, poly_get_param(seg, plist, 100), 1); + } + if (d->type == 2) { + submenu->next=param_to_menu_new(desc, plist, street_get_param(seg, plist, 100, 1), 1); + popup_item_new_func(&submenu->next,"Set no passing", 1000, popup_set_no_passing, d); + } + if (d->type == 3) { + submenu->next=param_to_menu_new(desc, plist, town_get_param(seg, plist, 100), 1); + } + if (d->type == 4) { + submenu->next=param_to_menu_new(desc, plist, street_bti_get_param(seg, plist, 100), 1); + } + } +} + +void +popup_display_list(struct container *co, struct popup *popup, struct popup_item **popup_list) +{ + GtkWidget *menu, *item; + struct display_list *list[100],**p=list; + + menu=gtk_menu_new(); + item=gtk_menu_item_new_with_label("Selection"); + gtk_menu_append (GTK_MENU(menu), item); + display_find(&popup->pnt, co->disp, display_end, 3, list, 100); + while (*p) { + if (! (*p)->info) + popup_display_list_default(*p, popup_list); + else + (*(*p)->info)(*p, popup_list); + p++; + } +} + +void +popup_destroy_items(struct popup_item *item) +{ + struct popup_item *next; + while (item) { + if (item->active && item->func) + item->func(item, item->param); + if (item->submenu) + popup_destroy_items(item->submenu); + next=item->next; + assert(item->destroy != NULL); + item->destroy(item); + item=next; + } +} + +void +popup_destroy(GtkObject *obj, void *parm) +{ + struct popup *popup=parm; + + popup_destroy_items(popup->items); + g_free(popup); +} + +void +popup(struct container *co, int x, int y, int button) +{ + GtkWidget *menu; + struct popup *popup=g_new(struct popup,1); + struct popup_item *list=NULL; + struct popup_item *descr; + struct coord_geo g; + char buffer[256]; + + popup->co=co; + popup->pnt.x=x; + popup->pnt.y=y; + transform_reverse(co->trans, &popup->pnt, &popup->c); + popup_display_list(co, popup, &list); + plugin_call_popup(co, popup, &list); + transform_lng_lat(&popup->c, &g); + strcpy(buffer,"Map Point "); + transform_geo_text(&g, buffer+strlen(buffer)); + descr=popup_item_new_text(&list,buffer, 0); + descr->param=popup; + + popup_item_new_func(&list,"Set as Position", 1000, popup_set_position, descr); + popup_item_new_func(&list,"Set as Destination", 1001, popup_set_destination, descr); + + popup->items=list; + menu=popup_menu(list); + gtk_widget_show_all(menu); + popup->gui_data=menu; + + + gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time()); + gtk_signal_connect(GTK_OBJECT(menu), "selection-done", GTK_SIGNAL_FUNC (popup_destroy), popup); +} + + diff --git a/popup.h b/popup.h new file mode 100644 index 00000000..989d5155 --- /dev/null +++ b/popup.h @@ -0,0 +1,22 @@ +void popup(struct container *co, int x, int y, int button); +struct popup_item *popup_item_new_text(struct popup_item **last, char *text, int priority); + +struct popup { + struct container *co; + struct point pnt; + struct coord c; + void *gui_data; + struct popup_item *items; + struct popup_item *active; +}; + +struct popup_item { + char *text; + int priority; + void (*func)(struct popup_item *, void *); + void *param; + struct popup_item *submenu; + struct popup_item *next; + void (*destroy)(struct popup_item *); + int active; +}; diff --git a/profile.c b/profile.c new file mode 100644 index 00000000..35a41447 --- /dev/null +++ b/profile.c @@ -0,0 +1,18 @@ +#include +#include + +void +profile_timer(char *where) +{ + static struct timeval last; + struct timeval curr; + int msec; + + if (where) { + gettimeofday(&curr, NULL); + msec=(curr.tv_usec-last.tv_usec)/1000+ + (curr.tv_sec-last.tv_sec)*1000; + printf("%s:%d msec\n", where, msec); + } + gettimeofday(&last, NULL); +} diff --git a/route.c b/route.c new file mode 100644 index 00000000..75de703a --- /dev/null +++ b/route.c @@ -0,0 +1,1053 @@ +#include +#include +#include +#include +#include +#include +#include "coord.h" +#include "param.h" +#include "map_data.h" +#include "block.h" +#include "street.h" +#include "street_data.h" +#include "display.h" +#include "transform.h" +#include "route.h" +#include "phrase.h" +#include "navigation.h" +#include "fib-1.0/fib.h" +#include "time.h" + +/* Node1: 4 */ +/* Node2: 4 */ +/* Segid: 4 */ +/* len: 4 */ +/* type: 1 */ +/* limit/order: 1 */ +/* 18 Bytes */ + +extern void *speech_handle; +static int speed_list[16]={120,120,80,110,90,80,60,90,80,70,60,50,30,10,0,60}; + +int debug_route=0; + +#define GC_TEXT_FG 7 +#define GC_TEXT_BG 8 +#define GC_BLACK 9 +#define GC_RED 21 + +int hx=0x1416bc; /* 447C9E dx=3E18, dxmg=5E09*/ +int hy=0x5f224c; /* 5282B5 dy=5E07, dymg=8F1C*/ +int segid_h=0x20461961; + +int hkx=0x1474c5; /* 44BAB6 */ +int hky=0x5fb168; /* 52E0BC */ + +int lx=0x141ac3; +int ly=0x5f2d7a; + +int trace; +/* 0x141b53, 0x5f2065 */ + +struct coord3d { + struct coord xy; + int h; +}; + + +struct route_point { + struct route_point *next; + struct route_point *hash_next; + struct route_segment *start; + struct route_segment *end; + struct route_segment *seg; +#if 0 + int conn; + int id; +#endif + struct fibheap_el *el; + int value; + struct coord3d c; +}; + + +struct route_segment { + struct route_segment *next; + struct route_segment *start_next; + struct route_segment *end_next; + struct route_point *start; + struct route_point *end; + struct street_str *str; + int limit; + int len; + int offset; +}; + +struct street_info { + struct street_header *hdr; + struct street_type *typ; + struct street_str *str; + unsigned char *p; + int bytes; + int include; +}; + +struct route_info { + int mode; + struct coord3d seg1,seg2,line1,line2,pos,click; + int seg1_len,seg2_len; + int offset; + int dist; + struct block_info blk_inf; + struct street_info str_inf; +}; + +struct route { + struct map_data *map_data; + double route_time_val; + double route_len_val; + struct route_path_segment *path; + struct route_path_segment *path_last; + struct route_info *pos; + struct route_info *dst; + struct route_segment *route_segments; + struct route_point *route_points; + struct block_list *blk_lst; +#define HASH_SIZE 8192 + struct route_point *hash[HASH_SIZE]; +}; + +struct route * +route_new(void) +{ + struct route *this=g_new0(struct route, 1); + return this; +} + +void +route_path_free(struct route *this) +{ + struct route_path_segment *curr, *next; + curr=this->path; + + while (curr) { + next=curr->next; + g_free(curr); + curr=next; + } + this->path=NULL; + this->path_last=NULL; +} + +void +route_mapdata_set(struct route *this, struct map_data *mdata) +{ + this->map_data=mdata; +} + +struct map_data * +route_mapdata_get(struct route *this) +{ + return this->map_data; +} + +static void +route_add_path_segment(struct route *this, int segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) +{ + struct route_path_segment *segment=g_new0(struct route_path_segment,1); + segment->next=NULL; + segment->segid=segid; + segment->offset=offset; + segment->dir=dir; + segment->length=len; + segment->time=time; + if (start) + segment->c[0]=*start; + if (end) + segment->c[1]=*end; + if (!this->path) + this->path=segment; + if (this->path_last) + this->path_last->next=segment; + this->path_last=segment; +} + +void +route_set_position(struct route *this, struct coord *pos) +{ + struct route_info *rt; + + route_path_free(this); + rt=route_find_nearest_street(this->map_data, pos); + route_find_point_on_street(rt); + if (this->pos) + g_free(this->pos); + this->pos=rt; + if (this->dst) { + route_find(this, this->pos, this->dst); + } +} + +struct route_path_segment * +route_path_get_all(struct route *this) +{ + return this->path; +} + +struct route_path_segment * +route_path_get(struct route *this, int segid) +{ + struct route_path_segment *curr=this->path; + + while (curr) { + if (curr->segid == segid) + return curr; + curr=curr->next; + } + return NULL; + +} + +void +route_set_destination(struct route *this, struct coord *dest) +{ + struct route_info *rt; + + rt=route_find_nearest_street(this->map_data, dest); + route_find_point_on_street(rt); + if (this->dst) + g_free(this->dst); + this->dst=rt; + route_do_start(this, this->pos, this->dst); +} + +struct coord * +route_get_destination(struct route *this) +{ + if (! this->dst) + return NULL; + return &this->dst->click.xy; +} + +void +route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data, + void(*func)(struct block_info *, struct street_info *, unsigned char **, unsigned char *, void *)) +{ + struct street_info str_inf; + struct street_str *str,*str_tmp; + + if (blk_inf->block_number == 0x10c6) { + printf("route_street_foreach p=%p\n", p); + } + str_inf.hdr=(struct street_header *)p; + p+=sizeof(struct street_header); + assert(str_inf.hdr->count == blk_inf->block->count); + + str_inf.bytes=street_get_bytes(blk_inf->block); + + str_inf.typ=(struct street_type *)p; + p+=blk_inf->block->count*sizeof(struct street_type); + + str=(struct street_str *)p; + str_tmp=str; + while (str_tmp->segid) + str_tmp++; + + p=(unsigned char *)str_tmp; + p+=4; + + while (str->segid) { + str_inf.include=(str[1].segid > 0); + str_inf.str=str; + str_inf.p=p; + func(blk_inf, &str_inf, &p, end-4, data); + if (str_inf.include) + str_inf.typ++; + str++; + } +} + + +static struct route_point * +route_get_point(struct route *this, struct coord3d *c) +{ + struct route_point *p=this->route_points; + int hashval=(c->xy.x + c->xy.y + c->h) & (HASH_SIZE-1); + p=this->hash[hashval]; + while (p) { + if (p->c.xy.x == c->xy.x && p->c.xy.y == c->xy.y && p->c.h == c->h) + return p; + p=p->hash_next; + } + return NULL; +} + + +struct route_point * +route_point_add(struct route *this, struct coord3d *f, int conn) +{ + int hashval; + struct route_point *p; + + p=route_get_point(this,f); + if (p) { +#if 0 + p->conn+=conn; +#endif + } else { + hashval=(f->xy.x + f->xy.y + f->h) & (HASH_SIZE-1); + if (debug_route) + printf("p (0x%lx,0x%lx,0x%x)\n", f->xy.x, f->xy.y, f->h); + p=g_new(struct route_point,1); + p->hash_next=this->hash[hashval]; + this->hash[hashval]=p; + p->next=this->route_points; +#if 0 + p->conn=conn; + p->id=++id; +#endif + p->el=NULL; + p->start=NULL; + p->end=NULL; + p->seg=NULL; + p->value=INT_MAX; + p->c=*f; + this->route_points=p; + } + return p; +} + +static void +route_points_free(struct route *this) +{ + struct route_point *curr,*next; + curr=this->route_points; + while (curr) { + next=curr->next; + g_free(curr); + curr=next; + } + this->route_points=NULL; + memset(this->hash, 0, sizeof(this->hash)); +} + +void +route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, int offset, int limit) +{ + struct route_segment *s; + s=g_new(struct route_segment,1); + s->start=start; + s->start_next=start->start; + start->start=s; + s->end=end; + s->end_next=end->end; + end->end=s; + s->len=len; + s->str=str; + s->offset=offset; + s->limit=limit; + s->next=this->route_segments; + this->route_segments=s; + if (debug_route) + printf("l (0x%lx,0x%lx0x%x)-(0x%lx,0x%lx,0x%x)\n", start->c.xy.x, start->c.xy.y, start->c.h, end->c.xy.x, end->c.xy.y, end->c.h); + +} + +void +route_segments_free(struct route *this) +{ + struct route_segment *curr,*next; + curr=this->route_segments; + while (curr) { + next=curr->next; + g_free(curr); + curr=next; + } + this->route_segments=NULL; +} + +void +route_display_points(struct route *this, struct container *co) +{ +#if 0 + GtkMap *map=co->map; + struct route_point *p=this->route_points; + int r=5; + struct point pnt; + char text[256]; + + while (p) { + if (transform(co->trans, &p->c.xy, &pnt)) { + gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], FALSE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); + if (p->value != -1) { + sprintf(text,"%d", p->value); +#if 0 + display_text(GTK_WIDGET(map)->window, map->gc[GC_TEXT_FG], map->gc[GC_TEXT_BG], map->face[0], text, pnt.x+6, pnt.y+4, 0x10000, 0); +#endif + } + } + p=p->next; + } +#endif +} + +int +route_time(int type, int len) +{ + return len*36/speed_list[type & 0x3f]; +} + +int +route_value(int type, int len) +{ + return route_time(type, len); +} + +int +route_get_height(int segid, struct coord *c) +{ + if (c->x == 0x141b53 && c->y == 0x5f2065 && (segid == 0x4fad2fa || segid == 0x4fad155)) + return 1; + if (c->x == 0x1477a7 && c->y == 0x5fac38 && (segid == 0x32adac2 || segid == 0x40725c6)) + return 1; + if (c->x == 0x147a4c && c->y == 0x5fb194 && (segid == 0x32adb17 || segid == 0x32adb16)) + return 1; + return 0; +} + +void +route_process_street_graph(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +{ + struct route *this=data; + int limit,flags=0; + double len=0; + struct coord3d f,o,l; + struct route_point *s_pnt,*e_pnt; + + street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); + f.h=route_get_height(str_inf->str->segid, &f.xy); + s_pnt=route_point_add(this,&f, 1); + + l=f; + o=f; + while (*p < end) { + flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); + if (flags && !str_inf->include) + break; + len+=transform_distance(&l.xy, &o.xy); + l=o; + o=f; + if (flags) + break; + } + len+=transform_distance(&l.xy, &o.xy); + o.h=route_get_height(str_inf->str->segid, &o.xy); + e_pnt=route_point_add(this,&o, 1); + + limit=str_inf->str->limit; + if (str_inf->str->limit == 0x30 && (str_inf->str->type & 0x40)) + limit=0x03; + if (str_inf->str->limit == 0x03 && (str_inf->str->type & 0x40)) + limit=0x30; + + if (str_inf->str->limit != 0x33) + route_segment_add(this, s_pnt, e_pnt, len, str_inf->str, 0, limit); + debug_route=0; + *p-=2*str_inf->bytes; +} + +static int +compare(void *v1, void *v2) +{ + struct route_point *p1=v1; + struct route_point *p2=v2; + return p1->value-p2->value; +} + +static void +route_flood(struct route *this, struct route_info *rt_end) +{ + struct route_point *end; + struct route_point *p_min; + struct route_segment *s; + int min,new,old,val; + struct fibheap *heap; + + heap = fh_makeheap(); + + fh_setcmp(heap, compare); + + end=route_get_point(this, &rt_end->pos); + assert(end != 0); + end->value=0; + end->el=fh_insert(heap, end); + for (;;) { + p_min=fh_extractmin(heap); + if (! p_min) + break; + min=p_min->value; + if (debug_route) + printf("min=%d, 0x%lx, 0x%lx\n", min, p_min->c.xy.x, p_min->c.xy.y); + s=p_min->start; + while (s) { + val=route_value(s->str->type, s->len); +#if 0 + val+=val*2*street_route_contained(s->str->segid); +#endif + new=min+val; + if (debug_route) + printf("begin %d (0x%lx,0x%lx) ",new,s->end->c.xy.x, s->end->c.xy.y); + if (new < s->end->value && !(s->limit & 0x30)) { + s->end->value=new; + s->end->seg=s; + if (! s->end->el) { + if (debug_route) + printf("insert"); + s->end->el=fh_insert(heap, s->end); + } + else { + if (debug_route) + printf("replace"); + fh_replacedata(heap, s->end->el, s->end); + } + } + if (debug_route) + printf("\n"); + s=s->start_next; + } + s=p_min->end; + while (s) { + new=min+route_value(s->str->type, s->len); + if (debug_route) + printf("end %d vs %d (0x%lx,0x%lx) ",new,s->start->value,s->start->c.xy.x, s->start->c.xy.y); + if (new < s->start->value && !(s->limit & 0x03)) { + old=s->start->value; + s->start->value=new; + s->start->seg=s; + if (! s->start->el) { + if (debug_route) + printf("insert"); + s->start->el=fh_insert(heap, s->start); + } + else { + if (debug_route) + printf("replace"); + fh_replacedata(heap, s->start->el, s->start); + } + } + if (debug_route) + printf("\n"); + s=s->end_next; + } + } +} + +int +route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +{ + struct route_point *start,*start1,*start2; + struct route_segment *s=NULL; + double len=0,slen; + int ret,hr,min,time=0,seg_time,dir,type; + unsigned int val1=0xffffffff,val2=0xffffffff; + + start1=route_get_point(this, &rt_start->seg1); + start2=route_get_point(this, &rt_start->seg2); + assert(start1 != 0); + assert(start2 != 0); + if (start1->value != -1) + val1=start1->value+route_value(rt_start->str_inf.str->type, rt_start->seg1_len); + if (start2->value != -1) + val2=start2->value+route_value(rt_start->str_inf.str->type, rt_start->seg2_len); + + route_add_path_segment(this, 0, 0, &rt_start->click.xy, &rt_start->pos.xy, 1, 0, 0); + type=rt_start->str_inf.str->type; + if (val1 < val2) { + ret=1; + start=start1; + slen=transform_distance(&rt_start->pos.xy, &rt_start->line1.xy); + route_add_path_segment(this, 0, 0, &rt_start->pos.xy, &rt_start->line1.xy, 1, slen, route_time(type, slen)); + route_add_path_segment(this, rt_start->str_inf.str->segid, rt_start->offset, NULL, NULL, -1, rt_start->seg1_len, route_time(type, rt_start->seg1_len)); + } + else { + ret=2; + start=start2; + slen=transform_distance(&rt_start->pos.xy, &rt_start->line2.xy); + route_add_path_segment(this, 0, 0, &rt_start->pos.xy, &rt_start->line2.xy, 1, slen, route_time(type, slen)); + route_add_path_segment(this, rt_start->str_inf.str->segid, -rt_start->offset, NULL, NULL, 1, rt_start->seg2_len, route_time(type, rt_start->seg2_len)); + } + + while (start->value) { + s=start->seg; + if (! s) { + printf("No Route found\n"); + break; + } + if (s->start == start) { + start=s->end; + dir=1; + } + else { + start=s->start; + dir=-1; + } + len+=s->len; + seg_time=route_time(s->str->type, s->len); + time+=seg_time; + route_add_path_segment(this, s->str->segid, s->offset, NULL, NULL, dir, s->len, seg_time); + } + if (s) { + if (s->start->c.xy.x == rt_end->seg1.xy.x && s->start->c.xy.y == rt_end->seg1.xy.y) + route_add_path_segment(this, 0, 0, &rt_end->pos.xy, &rt_end->line1.xy, -1, 0, 0); + else + route_add_path_segment(this, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); + route_add_path_segment(this, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); + printf("len %5.3f\n", len/1000); + this->route_time_val=time/10; + time/=10; + this->route_len_val=len; + min=time/60; + time-=min*60; + hr=min/60; + min-=hr*60; + printf("time %02d:%02d:%02d\n", hr, min, time); +#if 1 + navigation_path_description(this); +#endif + } + return ret; +} + +struct block_list { + struct block_info blk_inf; + unsigned char *p; + unsigned char *end; + struct block_list *next; +}; + +void +route_process_street_block_graph(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + struct route *this=data; + struct block_list *blk_lst=this->blk_lst; + + while (blk_lst) { + if (blk_lst->blk_inf.block_number == blk_inf->block_number && blk_lst->blk_inf.file == blk_inf->file) + return; + blk_lst=blk_lst->next; + } + blk_lst=g_new(struct block_list,1); + blk_lst->blk_inf=*blk_inf; + blk_lst->p=p; + blk_lst->end=end; + blk_lst->next=this->blk_lst; + this->blk_lst=blk_lst; +#if 0 + route_street_foreach(blk_inf, p, end, data, route_process_street_graph); +#endif +} + +void +route_blocklist_free(struct route *this) +{ + struct block_list *curr,*next; + curr=this->blk_lst; + while (curr) { + next=curr->next; + g_free(curr); + curr=next; + } +} + +void +route_build_graph(struct route *this, struct map_data *mdata, struct coord *c, int coord_count) +{ + struct coord rect[2]; + struct transformation t; + + int i,j,max_dist,max_coord_dist; + int ranges[7]={0,1024000,512000,256000,128000,64000,32000}; + this->blk_lst=NULL; + struct block_list *blk_lst_curr; + + rect[0]=c[0]; + rect[1]=c[0]; + for (i = 1 ; i < coord_count ; i++) { + if (c[i].x < rect[0].x) + rect[0].x=c[i].x; + if (c[i].x > rect[1].x) + rect[1].x=c[i].x; + if (c[i].y > rect[0].y) + rect[0].y=c[i].y; + if (c[i].y < rect[1].y) + rect[1].y=c[i].y; + } + max_coord_dist=rect[1].x-rect[0].x; + if (max_coord_dist < rect[0].y-rect[1].y) + max_coord_dist=rect[0].y-rect[1].y; + max_coord_dist+=10000+max_coord_dist/2; + + printf("Collecting Blocks\n"); + for (i = 0 ; i < coord_count ; i++) { + for (j = 0 ; j < 7 ; j++) { + printf("range %d,%d\n", i, j); + max_dist=ranges[j]; + if (max_dist == 0 || max_dist > max_coord_dist) + max_dist=max_coord_dist; + + transform_setup_source_rect_limit(&t,&c[i],max_dist); + + map_data_foreach(mdata, file_street_str, &t, j+1, route_process_street_block_graph, this); + } + } + blk_lst_curr=this->blk_lst; + i=0; + while (blk_lst_curr) { + i++; + blk_lst_curr=blk_lst_curr->next; + } + printf("Block Count %d\n", i); + blk_lst_curr=this->blk_lst; + + j=0; + while (blk_lst_curr) { + j++; + printf("%d/%d\n", j, i); + route_street_foreach(&blk_lst_curr->blk_inf, blk_lst_curr->p, blk_lst_curr->end, this, route_process_street_graph); + blk_lst_curr=blk_lst_curr->next; + } +} + +void +route_process_street3(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +{ + int flags=0; + int i,ldist; + struct coord3d first,f,o,l; + struct coord3d cret; + int match=0; + double len=0,len_p=0; + struct route_info *rt_inf=(struct route_info *)data; + + street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); + f.h=route_get_height(str_inf->str->segid, &f.xy); + + l=f; + o=f; + first=f; + i=0; + + while (*p < end) { + flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); + f.h=route_get_height(str_inf->str->segid, &f.xy); + if (flags && !str_inf->include) + break; + + if (i++) { + ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); + if (ldist < rt_inf->dist) { + rt_inf->dist=ldist; + rt_inf->seg1=first; + rt_inf->line1=l; + rt_inf->pos=cret; + rt_inf->blk_inf=*blk_inf; + rt_inf->str_inf=*str_inf; + rt_inf->line2=o; + rt_inf->offset=i-1; + len_p=len; + match=1; + } + if (rt_inf->mode == 1) + len+=transform_distance(&l.xy, &o.xy); + } + l=o; + o=f; + if (flags) + break; + } + ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); + if (ldist < rt_inf->dist) { + rt_inf->dist=ldist; + rt_inf->seg1=first; + rt_inf->line1=l; + rt_inf->pos=cret; + rt_inf->blk_inf=*blk_inf; + rt_inf->str_inf=*str_inf; + rt_inf->line2=o; + rt_inf->offset=i; + len_p=len; + match=1; + } + if (match) { + rt_inf->seg2=o; + if (rt_inf->mode == 1) { + len+=transform_distance(&l.xy, &o.xy); + len_p+=transform_distance(&rt_inf->pos.xy, &rt_inf->line1.xy); + rt_inf->seg1_len=len_p; + rt_inf->seg2_len=len-len_p; + } + } + *p-=2*str_inf->bytes; +} + + +void +route_process_street_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + route_street_foreach(blk_inf, p, end, data, route_process_street3); +} + +struct street_str * +route_info_get_street(struct route_info *rt) +{ + return rt->str_inf.str; +} + +struct block_info * +route_info_get_block(struct route_info *rt) +{ + return &rt->blk_inf; +} + +struct route_info * +route_find_nearest_street(struct map_data *mdata, struct coord *c) +{ + struct route_info *ret=g_new0(struct route_info,1); + struct transformation t; + int max_dist=1000; + + transform_setup_source_rect_limit(&t,c,max_dist); + + ret->click.xy=*c; + ret->dist=INT_MAX; + ret->mode=0; + + map_data_foreach(mdata, file_street_str, &t, 48, route_process_street_block, ret); + + return ret; +} + +void +route_find_point_on_street(struct route_info *rt_inf) +{ + unsigned char *p,*end; + + rt_inf->dist=INT_MAX; + rt_inf->mode=1; + + p=rt_inf->str_inf.p; + end=(unsigned char *)rt_inf->blk_inf.block; + end+=rt_inf->blk_inf.block->size; + + route_process_street3(&rt_inf->blk_inf, &rt_inf->str_inf, &p, end, rt_inf); +} + + +struct route_info *start,*end; +int count; + +/* XPM */ +static char * flag_xpm[] = { +"16 16 3 1", +" c None", +"+ c #000000", +"@ c #FFFF00", +"+++ ", +"+@@++ ", +"+@@@@+++ ", +"+@@@@@@@++ ", +"+@@@@@@@@@++ ", +"+@@@@@@@@@@@++ ", +"+@@@@@@@@@++ ", +"+@@@@@@@++ ", +"+@@@@+++ ", +"+@@++ ", +"+++ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ "}; + +void +route_click(struct route *this, struct container *co, int x, int y) +{ +#if 0 + GtkMap *map=co->map; + struct point pnt; + GdkBitmap *flag_mask; + GdkPixmap *flag; + struct coord c; + struct route_info *rt_inf; + GdkGC *gc; + + + pnt.x=x; + pnt.y=y; + transform_reverse(co->trans, &pnt, &c); + transform(co->trans, &c, &pnt); + rt_inf=route_find_nearest_street(co->map_data, &c); + + + route_find_point_on_street(rt_inf); + + flag=gdk_pixmap_create_from_xpm_d(GTK_WIDGET(map)->window, &flag_mask, NULL, flag_xpm); + gc=gdk_gc_new(map->DrawingBuffer); + + gdk_gc_set_clip_origin(gc,pnt.x, pnt.y-15); + gdk_gc_set_clip_mask(gc,flag_mask); + gdk_draw_pixmap(GTK_WIDGET(map)->window, + gc, + flag, + 0, 0, pnt.x, pnt.y-15, 16, 16); + printf("Segment ID 0x%lx\n", rt_inf->str_inf.str->segid); +#if 0 + printf("Segment Begin 0x%lx, 0x%lx, 0x%x\n", route_info.seg1.xy.x, route_info.seg1.xy.y, route_info.seg1.h); + printf("Segment End 0x%lx, 0x%lx, 0x%x\n", route_info.seg2.xy.x, route_info.seg2.xy.y, route_info.seg2.h); +#endif + +#if 0 + transform(map, &route_info.seg1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); + transform(map, &route_info.line1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); + transform(map, &route_info.seg2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); + transform(map, &route_info.line2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); + transform(map, &route_info.pos.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); +#endif + printf("offset=%d\n", rt_inf->offset); + printf("seg1_len=%d\n", rt_inf->seg1_len); + printf("seg2_len=%d\n", rt_inf->seg2_len); + + if (trace) { + start=rt_inf; + count=0; + route_path_free(this); + route_find(this, start, end); + map_redraw(map); + } else { + if (! count) { + start=rt_inf; + count=1; + } + else { + end=rt_inf; + count=0; + } + } +#endif +} + +void +route_start(struct route *this, struct container *co) +{ + route_do_start(this, end, start); +} + +void +route_trace(struct container *co) +{ + trace=1-trace; +} + +void +route_data_free(void *t) +{ + route_blocklist_free(t); + route_path_free(t); + route_points_free(t); + route_segments_free(t); +} + +void +route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +{ + int res; + struct route_point *seg1,*seg2,*pos; + struct coord c[2]; + struct timeval tv[4]; + + phrase_route_calc(speech_handle); + route_data_free(this); + gettimeofday(&tv[0], NULL); + c[0]=rt_start->pos.xy; + c[1]=rt_end->pos.xy; + route_build_graph(this,this->map_data,c,2); + gettimeofday(&tv[1], NULL); + seg1=route_point_add(this, &rt_end->seg1, 1); + pos=route_point_add(this, &rt_end->pos, 2); + seg2=route_point_add(this ,&rt_end->seg2, 1); + route_segment_add(this, seg1, pos, rt_end->seg1_len, rt_end->str_inf.str, rt_end->offset, 0); + route_segment_add(this, seg2, pos, rt_end->seg2_len, rt_end->str_inf.str, -rt_end->offset, 0); + + printf("flood\n"); + route_flood(this, rt_end); + gettimeofday(&tv[2], NULL); + printf("find\n"); + res=route_find(this, rt_start, rt_end); + printf("ok\n"); + gettimeofday(&tv[3], NULL); + + printf("graph time %ld\n", (tv[1].tv_sec-tv[0].tv_sec)*1000+(tv[1].tv_usec-tv[0].tv_usec)/1000); + printf("flood time %ld\n", (tv[2].tv_sec-tv[1].tv_sec)*1000+(tv[2].tv_usec-tv[1].tv_usec)/1000); + printf("find time %ld\n", (tv[3].tv_sec-tv[2].tv_sec)*1000+(tv[3].tv_usec-tv[2].tv_usec)/1000); + phrase_route_calculated(speech_handle, this); + +} + + +int +route_destroy(void *t) +{ + struct route *this=t; + + route_data_free(t); + if (this->pos) + g_free(this->pos); + if (this->dst) + g_free(this->dst); + g_free(this); + return 0; +} + + +struct tm * +route_get_eta(struct route *this) +{ + time_t eta; + + eta=time(NULL)+this->route_time_val; + + return localtime(&eta); +} + +double +route_get_len(struct route *this) +{ + return this->route_len_val; +} + +struct route_crossings * +route_crossings_get(struct route *this, struct coord *c) +{ + struct coord3d c3; + struct route_point *pnt; + struct route_segment *seg; + int crossings=0; + struct route_crossings *ret; + + c3.xy=*c; + c3.h=0; + pnt=route_get_point(this, &c3); + seg=pnt->start; + while (seg) { + crossings++; + seg=seg->start_next; + } + seg=pnt->end; + while (seg) { + crossings++; + seg=seg->end_next; + } + ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing)); + ret->count=crossings; + return ret; +} diff --git a/route.h b/route.h new file mode 100644 index 00000000..0b249129 --- /dev/null +++ b/route.h @@ -0,0 +1,48 @@ +struct route_path_segment { + struct route_path_segment *next; + long segid; + int offset; + int dir; + int time; + int length; + struct coord c[2]; +}; + +struct route_crossing { + long segid; + int dir; +}; + +struct route_crossings { + int count; + struct route_crossing crossing[0]; +}; + +struct route; +struct map_data; +struct container; +struct route_info; + +struct route *route_new(void); +int route_destroy(); +void route_mapdata_set(struct route *this, struct map_data *mdata); +struct map_data* route_mapdata_get(struct route *this); +void route_display_points(struct route *this, struct container *co); +void route_click(struct route *this, struct container *co, int x, int y); +void route_start(struct route *this, struct container *co); +void route_set_position(struct route *this, struct coord *pos); +void route_set_destination(struct route *this, struct coord *dst); +struct coord *route_get_destination(struct route *this); +struct route_path_segment *route_path_get(struct route *, int segid); +struct route_path_segment *route_path_get_all(struct route *this); +void route_trace(struct container *co); +struct street_str *route_info_get_street(struct route_info *rt); +struct block_info *route_info_get_block(struct route_info *rt); +struct route_info *route_find_nearest_street(struct map_data *mdata, struct coord *c); +void route_find_point_on_street(struct route_info *rt_inf); +void route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end); +int route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end); +struct tm *route_get_eta(struct route *this); +double route_get_len(struct route *this); +struct route_crossings *route_crossings_get(struct route *this, struct coord *c); + diff --git a/script/get_map b/script/get_map new file mode 100755 index 00000000..20de37d3 --- /dev/null +++ b/script/get_map @@ -0,0 +1,5 @@ +#! /bin/bash +echo "/* XPM */" >map.xpm +req="" +perl -e 'print (pack("a20",length($ARGV[0]))) ; print $ARGV[0]' "$req" | netcat localhost 10371 | dd bs=20 skip=1 2>/dev/null | tail +2 >>map.xpm + diff --git a/script/gps_emu b/script/gps_emu new file mode 100755 index 00000000..f2eef3e5 --- /dev/null +++ b/script/gps_emu @@ -0,0 +1,19 @@ +#! /bin/bash +function send_data +{ + trap send_data SIGPIPE + while read line + do + case $line in + \$GPVTG*) + echo "$line" + sleep 1 + ;; + *) + echo "$line" + ;; + esac + done /tmp/gpsdata +} + +send_data diff --git a/script/gps_emu2 b/script/gps_emu2 new file mode 100755 index 00000000..8f5d9a61 --- /dev/null +++ b/script/gps_emu2 @@ -0,0 +1,40 @@ +#! /usr/bin/perl + +open(FILE,"<$ARGV[0]"); +read(FILE,$header,64); + +($magic,$version)=unpack("a8l",$header); + +#print "magic=$magic version=$version\n"; + +select STDOUT; $| = 1; + +while (read(FILE,$record,64)) +{ + ($flags,$status,$mode,$hdop,$vdop,$pdop,$sats,$timestampl,$timestamph,$latitude,$longitude,$altitude,$speed,$direction)=unpack("SCCCCCCLLddddd",$record); + + + if ($mode == 3) { + ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($timestampl); + $datestring=sprintf("%02d.%02d.%d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec); + $long_dir="E"; + $lat_dir="N"; + if ($longitude < 0) { + $long_dir="W"; + $logitude=-$longitude; + } + if ($latitude < 0) { + $lat_dir="S"; + $latitude=-$latitude; + } + $long_deg=int($longitude); + $lat_deg=int($latitude); + $long_gps=$long_deg*100+($longitude-$long_deg)*60; + $lat_gps=$lat_deg*100+($latitude-$lat_deg)*60; + $lastpos="$lat_gps $lat_dir $long_gps $long_dir"; + printf("\$GPGGA,%02d%02d%02d,%s,%s,%s,%s,1,%d,%s,%s,M,,,,0000*0C\n",$hour,$min,$sec,$lat_gps,$lat_dir,$long_gps,$long_dir,$sats,$hdop,$altitude); + printf("\$GPVTG,%s,T,,M,,N,%s,K,*6A\n",$direction,$speed*1.852); + printf(STDERR "\$GPGGA,%02d%02d%02d,%s,%s,%s,%s,1,%d,%s,%s,M,,,,0000*0C\n",$hour,$min,$sec,$lat_gps,$lat_dir,$long_gps,$long_dir,$sats,$hdop,$altitude); + sleep(1); + } +} diff --git a/script/gps_emu3 b/script/gps_emu3 new file mode 100755 index 00000000..5c0ecf25 --- /dev/null +++ b/script/gps_emu3 @@ -0,0 +1,12 @@ +#! /bin/bash +while read line +do + if [ -n "$line" ] + then + echo $line + fi + if [ "${line#\$GPVTG}" != "$line" ] + then + sleep 1 + fi +done <$1 diff --git a/search.c b/search.c new file mode 100644 index 00000000..165282ce --- /dev/null +++ b/search.c @@ -0,0 +1,442 @@ +#include +#include +#include +#include +#include "search.h" +#include "coord.h" +#include "country.h" +#include "town.h" +#include "street.h" +#include "street_name.h" + + +struct search { + struct map_data *map_data; + char *country; + GHashTable *country_hash; + char *postal; + char *town; + GHashTable *town_hash; + char *district; + GHashTable *district_hash; + char *street; + GHashTable *street_hash; + char *number; + int number_low, number_high; + int (*func)(struct search_destination *dest, void *user_data); + void *user_data; +}; + +struct dest_town { + int country; + int assoc; + char *name; + char postal_code[16]; + struct town town; +}; + +static GHashTable * +search_country_new(void) +{ + return g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + +static int +search_country_add(struct country *cou, void *data) +{ + struct search *search=data; + struct country *cou2; + + void *first; + first=g_hash_table_lookup(search->country_hash, (void *)(cou->id)); + if (! first) { + cou2=g_new(struct country, 1); + *cou2=*cou; + g_hash_table_insert(search->country_hash, (void *)(cou->id), cou2); + } + return 0; +} + +static void +search_country_show(gpointer key, gpointer value, gpointer user_data) +{ + struct country *cou=value; + struct search *search=(struct search *)user_data; + struct search_destination dest; + + memset(&dest, 0, sizeof(dest)); + dest.country=cou; + dest.country_name=cou->name; + dest.country_car=cou->car; + dest.country_iso2=cou->iso2; + dest.country_iso3=cou->iso3; + (*search->func)(&dest, search->user_data); +} + +static guint +search_town_hash(gconstpointer key) +{ + const struct dest_town *hash=key; + gconstpointer hashkey=(gconstpointer)(hash->country^hash->assoc); + return g_direct_hash(hashkey); +} + +static gboolean +search_town_equal(gconstpointer a, gconstpointer b) +{ + const struct dest_town *t_a=a; + const struct dest_town *t_b=b; + if (t_a->assoc == t_b->assoc && t_a->country == t_b->country) { + if (t_a->name && t_b->name && strcmp(t_a->name, t_b->name)) + return FALSE; + return TRUE; + } + return FALSE; +} + + +static GHashTable * +search_town_new(void) +{ + return g_hash_table_new_full(search_town_hash, search_town_equal, NULL, g_free); +} + + +static int +search_town_add(struct town *town, void *data) +{ + struct search *search=data; + struct dest_town *first; + + struct dest_town cmp; + char *zip1, *zip2; + + if (town->id == 0x1d546b7e) { + printf("found\n"); + } + cmp.country=town->country; + cmp.assoc=town->street_assoc; + cmp.name=town->name; + first=g_hash_table_lookup(search->town_hash, &cmp); + if (! first) { + first=g_new(struct dest_town, 1); + first->country=cmp.country; + first->assoc=cmp.assoc; + strcpy(first->postal_code, town->postal_code2); + first->name=town->name; + first->town=*town; + g_hash_table_insert(search->town_hash, first, first); + } else { + zip1=town->postal_code2; + zip2=first->postal_code; + while (*zip1 && *zip2) { + if (*zip1 != *zip2) { + while (*zip2) { + *zip2++='.'; + } + break; + } + zip1++; + zip2++; + } + } + cmp.name=NULL; + cmp.assoc=town->id; + first=g_hash_table_lookup(search->district_hash, &cmp); + if (! first) { + first=g_new(struct dest_town, 1); + first->country=cmp.country; + first->assoc=cmp.assoc; + first->name=NULL; + first->town=*town; + g_hash_table_insert(search->district_hash, first, first); + } + return 0; +} + +static void +search_town_search(gpointer key, gpointer value, gpointer user_data) +{ + struct country *cou=value; + struct search *search=user_data; + + town_search_by_name(search->map_data, cou->id, search->town, 1, search_town_add, search); +} + +static void +search_town_set(const struct dest_town *town, struct search_destination *dest, int full) +{ + char country[32]; + struct country *cou; + if ((cou=country_get_by_id(town->country))) { + dest->country=cou; + dest->country_name=cou->name; + dest->country_car=cou->car; + dest->country_iso2=cou->iso2; + dest->country_iso3=cou->iso3; + } else { + sprintf(country,"(%d)", town->country); + dest->country=NULL; + dest->country_car=country; + } + if (full) { + dest->town_postal=(char *)(town->town.postal_code2); + dest->town_name=g_convert(town->town.name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + if (town->town.district[0]) + dest->district=g_convert(town->town.district,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + else + dest->district=NULL; + } else { + dest->town_postal=(char *)(town->postal_code); + dest->town_name=g_convert(town->name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + } +} + + +static void +search_town_show(gpointer key, gpointer value, gpointer user_data) +{ + struct dest_town *town=value; + struct search *search=user_data; + struct search_destination dest; + + memset(&dest, 0, sizeof(dest)); + dest.town=&town->town; + dest.street_name=NULL; + dest.c=town->town.c; + search_town_set(town, &dest, 0); + + (*search->func)(&dest, search->user_data); +} + + +GHashTable * +search_street_new(void) +{ + return g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + + +static int +search_street_add(struct street_name *name, void *data) +{ + struct search *search=data; + struct street_name *name2; + + name2=g_new(struct street_name, 1); + *name2=*name; + g_hash_table_insert(search->street_hash, name2, name2); + return 0; +} + +static int +number_partial(int search, int ref, int ext) +{ + int max=1; + + printf("number_partial(%d,%d,%d)", search, ref, ext); + if (ref >= 10) + max=10; + if (ref >= 100) + max=100; + if (ref >= 1000) + max=1000; + while (search < max) { + search*=10; + search+=ext; + } + printf("max=%d result=%d\n", max, search); + return search; +} + +static int +check_number(int low, int high, int s_low, int s_high) +{ + int debug=0; + + if (debug) + printf("check_number(%d,%d,%d,%d)\n", low, high, s_low, s_high); + if (low <= s_high && high >= s_low) + return 1; + if (s_low == s_high) { + if (low <= number_partial(s_high, high, 9) && high >= number_partial(s_low, low, 0)) + return 1; + } + if (debug) + printf("return 0\n"); + return 0; +} + +static void +search_street_show_common(gpointer key, gpointer value, gpointer user_data, int number) +{ + struct street_name *name=value; + struct search *search=user_data; + char *utf8; + struct dest_town cmp; + struct dest_town *town; + char buffer[32]; + struct street_name_info info; + struct street_name_number_info num_info; + struct search_destination dest; + int debug=0; + + memset(&dest, 0, sizeof(dest)); + name->tmp_len=name->aux_len; + name->tmp_data=name->aux_data; + while (street_name_get_info(&info, name)) { + cmp.country=info.country; + cmp.assoc=info.dist; + cmp.name=NULL; + town=g_hash_table_lookup(search->district_hash, &cmp); + if (debug) + printf("town=%p\n", town); + if (town) { + search_town_set(town, &dest, 1); + utf8=g_convert(name->name2,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + dest.street_name=utf8; + if (number) { + info.tmp_len=info.aux_len; + info.tmp_data=info.aux_data; + while (street_name_get_number_info(&num_info, &info)) { + dest.town=&town->town; + dest.street=name; + dest.c=num_info.c; + if (check_number(num_info.first, num_info.last, search->number_low, search->number_high)) { + if (num_info.first == num_info.last) + sprintf(buffer,"%d",num_info.first); + else + sprintf(buffer,"%d-%d",num_info.first,num_info.last); + dest.street_number=buffer; + (*search->func)(&dest, search->user_data); + } + } + } else { + dest.town=&town->town; + dest.street=name; + dest.c=info.c; + (*search->func)(&dest, search->user_data); + } + g_free(utf8); + } else { + printf("Town for '%s' not found\n", name->name2); + } + } +} + +static void +search_street_show(gpointer key, gpointer value, gpointer user_data) +{ + search_street_show_common(key, value, user_data, 0); +} + +static void +search_street_show_number(gpointer key, gpointer value, gpointer user_data) +{ + search_street_show_common(key, value, user_data, 1); +} + +static void +search_street_search(gpointer key, gpointer value, gpointer user_data) +{ + const struct dest_town *town=value; + struct search *search=user_data; + street_name_search(search->map_data, town->country, town->assoc, search->street, 1, search_street_add, search); +} + + + +void search_update(struct search *search, enum search_param what, char *val) +{ + char *dash; + + if (what == search_country) { + if (search->country_hash) g_hash_table_destroy(search->country_hash); + search->country_hash=NULL; + } + if (what == search_country || what == search_town) { + if (search->town_hash) g_hash_table_destroy(search->town_hash); + if (search->district_hash) g_hash_table_destroy(search->district_hash); + search->town_hash=NULL; + search->district_hash=NULL; + } + + if (what == search_country || what == search_town || what == search_street) { + if (search->street_hash) g_hash_table_destroy(search->street_hash); + search->street_hash=NULL; + } + + if (what == search_country) { + g_free(search->country); + search->country=g_strdup(val); + if (val) { + search->country_hash=search_country_new(); + country_search_by_name(val, 1, search_country_add, search); + country_search_by_car(val, 1, search_country_add, search); + country_search_by_iso2(val, 1, search_country_add, search); + country_search_by_iso3(val, 1, search_country_add, search); + g_hash_table_foreach(search->country_hash, search_country_show, search); + } + } + if (what == search_town) { + g_free(search->town); + search->town=g_strdup(val); + if (val) { + search->town_hash=search_town_new(); + search->district_hash=search_town_new(); + g_hash_table_foreach(search->country_hash, search_town_search, search); + g_hash_table_foreach(search->town_hash, search_town_show, search); + } + } + if (what == search_street) { + g_free(search->street); + search->street=g_strdup(val); + if (val) { + search->street_hash=search_street_new(); + g_hash_table_foreach(search->town_hash, search_street_search, search); + g_hash_table_foreach(search->street_hash, search_street_show, search); + } + } + if (what == search_number) { + g_free(search->number); + search->number=g_strdup(val); + if (val) { + char buffer[strlen(val)+1]; + strcpy(buffer, val); + dash=index(buffer,'-'); + if (dash) { + *dash++=0; + search->number_low=atoi(buffer); + if (strlen(val)) + search->number_high=atoi(dash); + else + search->number_high=10000; + } else { + if (!strlen(val)) { + search->number_low=0; + search->number_high=10000; + } else { + search->number_low=atoi(val); + search->number_high=atoi(val); + } + } + g_hash_table_foreach(search->street_hash, search_street_show_number, search); + } + } +} + +struct search * +search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data) +{ + struct search *this=g_new0(struct search,1); + this->map_data=mdat; + this->country=g_strdup(country); + this->postal=g_strdup(postal); + this->town=g_strdup(town); + this->district=g_strdup(district); + this->street=g_strdup(street); + this->number=g_strdup(number); + this->func=func; + this->user_data=user_data; + return this; +} diff --git a/search.h b/search.h new file mode 100644 index 00000000..88f38826 --- /dev/null +++ b/search.h @@ -0,0 +1,30 @@ +enum search_param { + search_country, + search_postal, + search_town, + search_district, + search_street, + search_number +}; + +struct search_destination { + char *country_name; + char *country_car; + char *country_iso2; + char *country_iso3; + char *town_postal; + char *town_name; + char *district; + char *street_name; + char *street_number; + struct country *country; + struct town *town; + struct street_name *street; + struct coord *c; +}; + +struct search; +struct map_data; + +void search_update(struct search *search, enum search_param what, char *val); +struct search *search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data); diff --git a/speech.c b/speech.c new file mode 100644 index 00000000..c913629c --- /dev/null +++ b/speech.c @@ -0,0 +1,61 @@ +/* speechd simple client program + * CVS revision: $Id: speech.c,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * Author: Tomas Cerha */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "speech.h" + +struct speech { + int sockfd; +}; + +struct speech * +speech_new(void) { + struct speech *this; + int sockfd; + + sockfd = spd_init("map","main"); + if (sockfd == 0) + return NULL; + this=g_new(struct speech,1); + if (this) { + this->sockfd=sockfd; + } + return this; +} + +int +speech_say(struct speech *this, char *text) { + int err; + + err = spd_sayf(this->sockfd, 2, text); + if (err != 1) + return 1; + return 0; +} + +int +speech_sayf(struct speech *this, char *format, ...) { + char buffer[8192]; + va_list ap; + va_start(ap,format); + vsnprintf(buffer, 8192, format, ap); + return speech_say(this, buffer); +} + +int +speech_destroy(struct speech *this) { + spd_close(this->sockfd); + g_free(this); + return 0; +} diff --git a/speech.h b/speech.h new file mode 100644 index 00000000..a4038e06 --- /dev/null +++ b/speech.h @@ -0,0 +1,5 @@ +struct speech; +struct speech *speech_new(void); +int speech_say(struct speech *this, char *text); +int speech_sayf(struct speech *this, char *format, ...); +int speech_destroy(struct speech *this); diff --git a/statusbar.h b/statusbar.h new file mode 100644 index 00000000..1b9092c9 --- /dev/null +++ b/statusbar.h @@ -0,0 +1,10 @@ +struct route; +struct statusbar_gui; + +struct statusbar { + void (*statusbar_destroy)(struct statusbar *this); + void (*statusbar_mouse_update)(struct statusbar *this, struct transformation *tr, struct point *p); + void (*statusbar_route_update)(struct statusbar *this, struct route *route); + void (*statusbar_gps_update)(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed); + struct statusbar_gui *gui; +}; diff --git a/street.c b/street.c new file mode 100644 index 00000000..f449f1e1 --- /dev/null +++ b/street.c @@ -0,0 +1,455 @@ +#include +#include +#include +#include +#include +#include "container.h" +#include "coord.h" +#include "map_data.h" +#include "file.h" +#include "block.h" +#include "route.h" +#include "street.h" +#include "street_data.h" +#include "street_name.h" +#include "display.h" +#include "draw_info.h" +#include "data_window.h" +#include "data.h" +#include "tree.h" + + +static void +street_draw_segment(struct container *co, struct segment *seg, unsigned char **pos, unsigned char *end, struct coord *ref, int bytes, int include, int disp) +{ + int j,flags,limit; + struct coord f; + struct coord l[2]; + struct street_str *str=seg->data[0]; + char *label; + struct street_name name; + struct param_list param[100]; + struct route_path_segment *route; + struct display_list **displ=co->disp; + int max=10000; + struct point xpoints[max]; + + flags=0; + j=0; + while (! flags && *pos < end) { + flags=street_get_coord(pos, bytes, ref, &f); + if (! j) { + l[0]=f; + l[1]=f; + } else { + if (include || !flags) { + if (f.x < l[0].x) l[0].x=f.x; + if (f.x > l[1].x) l[1].x=f.x; + if (f.y > l[0].y) l[0].y=f.y; + if (f.y < l[1].y) l[1].y=f.y; + } + } + transform(co->trans, &f, &xpoints[j]); + if (! j) + flags=0; + j++; + assert(j < max); + } + if (! include) + j--; + if (is_visible(co->trans, l) && str->type) { + label=NULL; + if (str->nameid) { + street_name_get_by_id(&name, seg->blk_inf.mdata, str->nameid); + if (name.name2[0]) + label=name.name2; + else + label=name.name1; + } + if (str->nameid && name.townassoc < 0 ) { + char buffer[128]; + sprintf(buffer,"-0x%x", -name.townassoc); + label=g_strdup(buffer); + } + limit=0; + if (str->limit == 0x30) + limit=1; + if (str->limit == 0x03) + limit=-1; + if (str->type & 0x40) + limit=-limit; + display_add(&displ[disp], 2, limit, label, j, xpoints, NULL, seg, sizeof(*seg)); + if (co->route && (route=route_path_get(co->route, str->segid))) { + if (! route->offset) + display_add(&displ[display_street_route], 2, 0, label, j, xpoints, NULL, NULL, 0); + else if (route->offset > 0) + display_add(&displ[display_street_route], 2, 0, label, route->offset, xpoints, NULL, NULL, 0); + else + display_add(&displ[display_street_route], 2, 0, label, j+route->offset, xpoints-route->offset, NULL, NULL, 0); + } + if (co->data_window[data_window_type_street]) + data_window_add(co->data_window[data_window_type_street], param, street_get_param(seg, param, 100, 0)); + } + *pos-=2*bytes; +} + +void +street_safety_check(struct street_str *str) +{ +#if 0 + if (!((str->type & 0xf0) == 0x0 || (str->type & 0xf0) == 0x40)) { + printf("str->type=0x%x\n", str->type); + } + assert((str->type & 0xf0) == 0x0 || (str->type & 0xf0) == 0x40); +#endif + assert(str->type != 0xe && str->type != 0x4e && str->type != 0x40); + assert(str->unknown2 == str->unknown3); + assert(str->unknown2 == 0x40 || str->unknown2 == 0x44); +} + +struct street_header_type { + struct street_header *header; + int type_count; + struct street_type *type; +}; + +static void +street_header_type_get(struct block *blk, unsigned char **p_p, struct street_header_type *ret) +{ + unsigned char *p=*p_p; + ret->header=(struct street_header *)p; + p+=sizeof(struct street_header); + ret->type_count=blk->count; + ret->type=(struct street_type *)p; + p+=ret->type_count*sizeof(struct street_type); + assert(ret->header->count == blk->count); + *p_p=p; +} + +static void +street_coord_get_begin(unsigned char **p_p) +{ + unsigned char *p=*p_p; + struct street_str *str; + + str=(struct street_str *)p; + while (str->segid) { + str++; + } + p=(unsigned char *)str; + p+=4; + *p_p=p; +} + +void +street_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + struct street_str *str; + struct street_header_type header_type; + struct street_type *str_type; + int include,count,ncount,bytes,offset; + struct draw_info *drw_inf=data; + struct segment seg; + + seg.blk_inf=*blk_inf; + + street_header_type_get(blk_inf->block, &p, &header_type); + if (header_type.header->order >= drw_inf->limit) + return; + + str_type=header_type.type; + bytes=street_get_bytes(blk_inf->block); + str=(struct street_str *)p; + count=0; + ncount=0; + street_coord_get_begin(&p); + str_type--; + while (str->segid) { + include=1; + if (str[1].segid < 0) { + include=0; + str_type++; + } + seg.data[0]=str; + seg.data[1]=str_type; + seg.data[2]=p; + seg.data[3]=header_type.header; + street_safety_check(str); + offset=0; + if (header_type.header->order < 0x2) + offset=3; + else if (header_type.header->order < 0x4 && str->type != 0x6 && str->type != 0x46) + offset=2; + else if (header_type.header->order < 0x6) + offset=1; + if (str->limit == 0x33) + offset=4; + street_draw_segment(drw_inf->co, &seg, &p, end-4, blk_inf->block->c, bytes, include, drw_inf->display+offset); + str++; + } +} + +void +street_bti_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + struct draw_info *drw_inf=data; + struct street_bti *str; + struct point pnt; + struct param_list param[100]; + struct segment seg; + + while (p < end) { + str=(struct street_bti *)p; + seg.data[0]=str; + p+=sizeof(*str); + if (transform(drw_inf->co->trans, &str->c, &pnt)) { + display_add(&drw_inf->co->disp[display_bti], 4, 0, NULL, 1, &pnt, NULL, &seg, sizeof(seg)); + if (drw_inf->co->data_window[data_window_type_point]) + data_window_add(drw_inf->co->data_window[data_window_type_point], param, street_bti_get_param(&seg, param, 100)); + } + } +} + +void +street_route_draw(struct container *co) +{ + struct route_path_segment *route=NULL; + struct point xpoints[2]; + + if (co->route) + route=route_path_get_all(co->route); + while (route) { + if (!route->segid) { + transform(co->trans, &route->c[0], &xpoints[0]); + transform(co->trans, &route->c[1], &xpoints[1]); + display_add(&co->disp[display_street_route], 2, 0, NULL, 2, xpoints, NULL, NULL, 0); + } + route=route->next; + } +} + +struct street_coord * +street_coord_get(struct block_info *blk_inf, struct street_str *str) +{ + struct block *blk; + unsigned char *p=(unsigned char *)(blk_inf->block),*end,*p_sav; + struct street_header_type hdr_type; + struct street_str *str_curr; + struct coord f,*c; + struct street_coord *ret; + int bytes,num,points,include; + int debug=0; + + end=p; + blk=block_get(&p); + end+=blk->size; + + street_header_type_get(blk, &p, &hdr_type); + str_curr=(struct street_str *)p; + num=str-str_curr; + street_coord_get_begin(&p); + bytes=street_get_bytes(blk); + if (debug) { + printf("num=%d\n", num); + } + street_get_coord(&p, bytes, blk->c, &f); + while (num && str_curr->segid) { + while (! street_get_coord(&p, bytes, blk->c, &f) && p < end); + str_curr++; + num--; + } + include=(str[1].segid > 0); + p_sav=p-2*bytes; + points=1+include; + while (! street_get_coord(&p, bytes, blk->c, &f) && p < end) + points++; + + if (debug) + printf("p=%p points=%d\n",p_sav, points); + p=p_sav; + ret=malloc(sizeof(struct street_coord)+points*sizeof(struct coord)); + ret->count=points; + c=ret->c; + while (points) { + street_get_coord(&p, bytes, blk->c, c); + c++; + points--; + } + return ret; +} + +#if 0 +struct street_nearest * +street_find_nearest(struct map_data *mdata, struct coord *c) +{ + struct street_nearest *ret=g_new0(struct street_nearest,1); + struct transformation t; + int max_dist=1000; + + transform_setup_source_rect_limit(&t,c,max_dist); + + ret->click.xy=*c; + ret->dist=INT_MAX; + ret->mode=0; + + map_data_foreach(mdata, file_street_str, &t, 48, route_process_street_block, ret); + + ret->mode=1; + ret->dist=INT_MAX; + + return ret; +} + +#endif + +int +street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str) +{ + int debug=0; + int res,block,num; + struct map_data *mdat_res; + struct block *blk; + unsigned char *p; + struct street_header_type hdr_type; + struct street_str *str; + + if (tree_search_hv_map(mdat, file_street_str, (id >> 8) | 0x31000000, id & 0xff, &res, &mdat_res)) { + return 1; + } + + block=res >> 12; + num=res & 0xfff; + if (debug) { + printf("block=0x%x\n", block); + printf("num=0x%x\n", num); + } + blk=block_get_byindex(mdat_res->file[file_street_str], block, &p); + res_blk_inf->mdata=mdat_res; + res_blk_inf->file=mdat_res->file[file_street_str]; + res_blk_inf->block=blk; + if (debug) { + printf("blk->count=0x%x\n", blk->count); + } + street_header_type_get(blk, &p, &hdr_type); + str=(struct street_str *)p; + str+=num; + *res_str=str; + return 0; +} + +int +street_get_param(struct segment *seg, struct param_list *param, int count, int verbose) +{ + char buffer[1024]; + int i=count,j; + struct street_str *str=seg->data[0]; + struct street_type *type=seg->data[1]; + struct street_name name; + struct street_name_info name_info; +#if 0 + struct street_name_number_info name_number_info; +#endif + + param_add_hex("Type-Addr", (unsigned char *)type-seg->blk_inf.file->begin, ¶m, &count); + param_add_hex("Order", type->order, ¶m, &count); + param_add_hex("Country", type->country, ¶m, &count); + + param_add_hex("Addr", (unsigned char *)str-seg->blk_inf.file->begin, ¶m, &count); + param_add_hex_sig("Seg-Id", str->segid, ¶m, &count); + param_add_hex("Limit", str->limit, ¶m, &count); + param_add_hex("Unknown2", str->unknown2, ¶m, &count); + param_add_hex("Unknown3", str->unknown3, ¶m, &count); + param_add_hex("Type", str->type, ¶m, &count); + param_add_hex("Name-Id", str->nameid, ¶m, &count); + if (str->segid) { + street_name_get_by_id(&name, seg->blk_inf.mdata, str->nameid); + + param_add_hex("Len", name.len, ¶m, &count); + param_add_hex("Country", name.country, ¶m, &count); + param_add_hex_sig("TownAssoc", name.townassoc, ¶m, &count); + printf("TownAssoc 0x%lx\n", name.townassoc+str->segid); + param_add_string("Name1", name.name1, ¶m, &count); + param_add_string("Name2", name.name2, ¶m, &count); + param_add_hex("Segments", name.segment_count, ¶m, &count); + if (verbose) { + for (j = 0 ; j < name.segment_count ; j++) { + sprintf(buffer,"0x%x 0x%x", name.segments[j].country, name.segments[j].segid); + param_add_string("Segment", buffer, ¶m, &count); + } + param_add_hex("Len", name.aux_len, ¶m, &count); + while (street_name_get_info(&name_info, &name)) { + param_add_hex("Len", name_info.len, ¶m, &count); + param_add_hex("Tag", name_info.tag, ¶m, &count); + param_add_hex("Dist", name_info.dist, ¶m, &count); + param_add_hex("Country", name_info.country, ¶m, &count); + param_add_hex("X", name_info.c->x, ¶m, &count); + param_add_hex("Y", name_info.c->y, ¶m, &count); + param_add_dec("First", name_info.first, ¶m, &count); + param_add_dec("Last", name_info.last, ¶m, &count); + param_add_hex("Segments", name_info.segment_count, ¶m, &count); + } +#if 0 + int tag; + int k, segs; + printf("\n"); + printf("Len 0x%x\n",get_short(&stn)); + tag=*stn++; + printf("Tag 0x%x\n",tag); + if (tag == 0xc0 || tag == 0xd0 || tag == 0xe0) { + printf("DistAssoc 0x%lx\n",get_long(&stn)); + printf("Country 0x%lx\n",get_long(&stn)); + printf("X 0x%lx\n",get_long(&stn)); + printf("Y 0x%lx\n",get_long(&stn)); + printf("First %ld\n",get_triple(&stn)); + printf("Last %ld\n",get_triple(&stn)); + segs=get_long(&stn); + printf("Segs 0x%x\n",segs); + for (k = 0 ; k < 0 ; k++) { + printf("SegId 0x%lx\n", get_long(&stn)); + printf("Country 0x%lx\n",get_long(&stn)); + } + } else if (tag == 0x8f || tag == 0xaa || tag == 0xab || tag == 0xae || tag == 0xaf || tag == 0x9a || tag == 0x9e || tag == 0x9f) { + printf("X 0x%lx\n",get_long(&stn)); + printf("Y 0x%lx\n",get_long(&stn)); + printf("First %ld\n",get_triple(&stn)); + printf("Last %ld\n",get_triple(&stn)); + printf("SegId 0x%lx\n",get_long(&stn)); + printf("Country 0x%lx\n",get_long(&stn)); + } else { + printf("Unknown tag 0x%x\n", tag); + break; + } + } +#endif + } + } else { + if (!verbose) { + param_add_string("Len", "", ¶m, &count); + param_add_string("Country", "", ¶m, &count); + param_add_string("TownAssoc", "", ¶m, &count); + param_add_string("Name1", "", ¶m, &count); + param_add_string("Name2", "", ¶m, &count); + param_add_string("Segments", "", ¶m, &count); + } + } + return i-count; +} + +int +street_bti_get_param(struct segment *seg, struct param_list *param, int count) +{ + int i=count; + struct street_bti *str=seg->data[0]; + + param_add_hex("Addr", (unsigned char *)str-seg->blk_inf.file->begin, ¶m, &count); + param_add_hex("Unknown1", str->unknown1, ¶m, &count); + param_add_hex("Segid1", str->segid1, ¶m, &count); + param_add_hex("Country1", str->country1, ¶m, &count); + param_add_hex("Segid2", str->segid2, ¶m, &count); + param_add_hex("Country2", str->country2, ¶m, &count); + param_add_hex("Unknown5", str->unknown5, ¶m, &count); + param_add_hex("X", str->c.x, ¶m, &count); + param_add_hex("Y", str->c.y, ¶m, &count); + + return i-count; +} diff --git a/street.h b/street.h new file mode 100644 index 00000000..65d024f1 --- /dev/null +++ b/street.h @@ -0,0 +1,53 @@ +struct container; +struct block_info; +struct segment; + +struct street_header { + unsigned char order; + int count; +} __attribute__((packed)); + +struct street_type { + unsigned char order; + unsigned short country; +} __attribute__((packed)); + +struct street_str { + long segid; + unsigned char limit; /* 0x03,0x30=One Way,0x33=No Passing */ + unsigned char unknown2; + unsigned char unknown3; + unsigned char type; + unsigned long nameid; +}; + +struct street_bti { + unsigned char unknown1; + unsigned long segid1; + unsigned long country1; + unsigned long segid2; + unsigned long country2; + unsigned char unknown5; + struct coord c; +} __attribute__((packed)); + +struct street_route { + struct street_route *next; + long segid; + int offset; + struct coord c[2]; +}; + +struct street_coord { + int count; + struct coord c[0]; +}; + + +void street_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); +struct street_coord *street_coord_get(struct block_info *blk_inf, struct street_str *str); +int street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str); +void street_bti_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); +int street_get_param(struct segment *seg, struct param_list *param, int count, int verbose); +int street_bti_get_param(struct segment *seg, struct param_list *param, int count); +void street_route_draw(struct container *co); diff --git a/street_data.h b/street_data.h new file mode 100644 index 00000000..a7701430 --- /dev/null +++ b/street_data.h @@ -0,0 +1,60 @@ +static inline int street_get_bytes(struct block *blk) +{ + int bytes,dx,dy; + bytes=2; + dx=blk->c[1].x-blk->c[0].x; + dy=blk->c[0].y-blk->c[1].y; + + if (dx > 32767 || dy > 32767) + bytes=3; + if (dx > 8388608 || dy > 8388608) + bytes=4; + + return bytes; +} + +static inline int street_get_coord(unsigned char **pos, int bytes, struct coord *ref, struct coord *f) +{ + unsigned char *p; + int x,y,flags=0; + + p=*pos; + x=*p++; + x|=(*p++) << 8; + if (bytes == 2) { + if ( x > 0x7fff) { + x=0x10000-x; + flags=1; + } + } + else if (bytes == 3) { + x|=(*p++) << 16; + if ( x > 0x7fffff) { + x=0x1000000-x; + flags=1; + } + } else { + x|=(*p++) << 16; + x|=(*p++) << 24; + if (x < 0) { + x=-x; + flags=1; + } + } + y=*p++; + y|=(*p++) << 8; + if (bytes == 3) { + y|=(*p++) << 16; + } else if (bytes == 4) { + y|=(*p++) << 16; + y|=(*p++) << 24; + } + f->x=ref[0].x+x; + f->y=ref[1].y+y; +#if 0 + printf("0x%x,0x%x + 0x%x,0x%x = 0x%x,0x%x", x, y, ref[0].x, ref[1].y, f->x, f->y); +#endif + *pos=p; + return flags; +} + diff --git a/street_name.c b/street_name.c new file mode 100644 index 00000000..202c8ae5 --- /dev/null +++ b/street_name.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include "map_data.h" +#include "street_name.h" +#include "file.h" +#include "block.h" +#include "data.h" +#include "tree.h" + +void +street_name_get_by_id(struct street_name *name, struct map_data *mdat, unsigned long id) +{ + unsigned char *p; + if (id) { + p=mdat->file[file_strname_stn]->begin+id+0x2000; + street_name_get(name, &p); + } +} + +void +street_name_get(struct street_name *name, unsigned char **p) +{ + unsigned char *start=*p; + name->len=get_short(p); + name->country=get_short(p); + name->townassoc=get_long(p); + name->name1=get_string(p); + name->name2=get_string(p); + name->segment_count=get_long(p); + name->segments=(struct street_name_segment *)(*p); + (*p)+=(sizeof (struct street_name_segment))*name->segment_count; + name->aux_len=name->len-(*p-start); + name->aux_data=*p; + name->tmp_len=name->aux_len; + name->tmp_data=name->aux_data; + (*p)+=name->aux_len; +} + + +struct street_name_index { + unsigned short country; + long town_assoc; + char name[0]; +} __attribute__((packed)); + +struct street_search_priv { + struct street_name_index *search; + int partial; + struct block_offset last_leaf; + struct map_data *last_mdat; + int last_res; +}; + +int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) +{ + char c1_u,c2_u; + int ret=0; + int debug=0; + + if (i1->country > i2->country) + ret=2; + if (i1->country < i2->country) + ret=-2; + if (! ret) { + if (debug) + printf("town: %ld vs %ld\n", i1->town_assoc,i2->town_assoc); + if (i1->town_assoc > i2->town_assoc) + ret=2; + if (i1->town_assoc < i2->town_assoc) + ret=-2; + if (! ret) { + char *c1=i1->name; + char *c2=i2->name; + if (debug) + printf("name: '%s' vs '%s'\n", c1, c2); + for (;;) { + c1_u=toupper(*c1); + c2_u=toupper(*c2); + if (c1_u == c2_u && c1) { + c1++; + c2++; + } else { + if (! c1_u && ! c2_u) { + if (debug) + printf("return 0: end of strings\n"); + ret=0; + break; + } + if (c1_u == '\0' && c2_u == '\t') { + if (debug) + printf("return 0: delimiter found\n"); + ret=0; + break; + } + if (c1_u == '\0' && partial) { + ret=-1; + break; + } + if (c1_u > c2_u) { + ret=2; + break; + } + if (c1_u < c2_u) { + ret=-2; + break; + } + } + } + } + } + return ret; +} + +static int +street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_data *mdat, void *data) +{ + int ret; + struct street_search_priv *priv_data=data; + struct block_offset *blk_off; + int debug=0; + + blk_off=(struct block_offset *)(*s2); + if (debug) + printf("0x%lx\n", get_long(s2)); + else + get_long(s2); + struct street_name_index *i1=priv_data->search; + struct street_name_index *i2=(struct street_name_index *)(*s2); + + if (debug) { + printf("Country %d %d\n",i1->country, i2->country); + printf("Town_Assoc 0x%lx 0x%lx\n",i1->town_assoc, i2->town_assoc); + printf("Name '%s' '%s'\n",i1->name, i2->name); + printf("Leaf Data 0x%x 0x%x %d\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); + } + *s2+=sizeof(*i2)+strlen(i2->name)+1; + ret=street_name_compare(i1, i2, priv_data->partial); + if (ret <= 0 && leaf == 1 && i1->country == i2->country && priv_data->last_res > 0) { + if (debug) + printf("street_tree_process: file='%s'\n", mdat->file[file_strname_stn]->name); + priv_data->last_leaf=*blk_off; + priv_data->last_mdat=mdat; + priv_data->last_res=ret; + } + if (debug) + printf("ret=%d\n", ret); + return ret; +} + +int +street_name_search(struct map_data *mdat, int country, int town_assoc, const char *name, int partial, int (*func)(struct street_name *name, void *data), void *data) +{ + struct street_search_priv priv; + unsigned char idx_buffer[strlen(name)+1+sizeof(struct street_name_index)]; + struct street_name_index *idx=(struct street_name_index *)idx_buffer; + struct block *blk; + unsigned char *p,*end; + int blk_num,res; + struct street_name str_name; + char buffer2[4096]; + struct street_name_index *idx2=(struct street_name_index *)buffer2; + int ret,debug=0; + + priv.partial=partial; + idx->country=country; + idx->town_assoc=town_assoc; + strcpy(idx->name, name); + priv.search=idx; + priv.last_res=1; + priv.last_mdat=NULL; + + tree_search_map(mdat, file_strname_stn, "b1", street_name_tree_process, &priv); + +#if 0 + if (debug) + printf("street_search_by_name: name='%s' leaf_data=0x%x priv=%p\n",name,priv.last_leaf.data,&priv); +#endif + if (!priv.last_mdat) + return 0; + blk_num=priv.last_leaf.offset; + if (debug) { + printf("block_num 0x%x\n", blk_num); + printf("file %p\n", priv.last_mdat->file[file_strname_stn]); + } + blk=block_get_byindex(priv.last_mdat->file[file_strname_stn], blk_num, &p); + end=(unsigned char *)blk; + end+=blk->size; + + p=(unsigned char *)blk; + p+=12; + if (debug) + printf("p=%p\n",p); + while (p < end) { + street_name_get(&str_name, &p); + idx2->country=str_name.country; + idx2->town_assoc=str_name.townassoc; + strcpy(idx2->name, str_name.name2); + res=street_name_compare(idx,idx2,partial); + if (res == 0 || res == -1) { + if (debug) + printf("Add res=%d '%s' '%s'\n",res,str_name.name1,str_name.name2); + ret=(*func)(&str_name, data); + if (ret) + return 1; + } + if (res < -1) + break; + } + if (debug) + printf("street_search_by_name: %p vs %p\n", p, end); + return 0; +} + + +int +street_name_get_info(struct street_name_info *inf, struct street_name *name) +{ + unsigned char *p=name->tmp_data; + + if (name->tmp_len <= 0) + return 0; + inf->len=get_short(&p); + inf->tag=*p++; + inf->dist=get_long(&p); + inf->country=get_long(&p); + inf->c=coord_get(&p); + inf->first=get_triple(&p); + inf->last=get_triple(&p); + inf->segment_count=get_long(&p); + inf->segments=(struct street_segment *)p; + p+=sizeof(struct street_name_segment)*inf->segment_count; + inf->aux_len=name->tmp_data+name->tmp_len-p; + inf->aux_data=p; + inf->tmp_len=inf->aux_len; + inf->tmp_data=inf->aux_data; + name->tmp_data+=inf->len; + name->tmp_len-=inf->len; + + return 1; +} + +int +street_name_get_number_info(struct street_name_number_info *num, struct street_name_info *inf) +{ + unsigned char *p=inf->tmp_data; + + if (inf->tmp_len <= 0) + return 0; + num->len=get_short(&p); + num->tag=*p++; + num->c=coord_get(&p); + num->first=get_triple(&p); + num->last=get_triple(&p); + num->segment=(struct street_name_segment *)p; + inf->tmp_data+=num->len; + inf->tmp_len-=num->len; + + return 1; +} diff --git a/street_name.h b/street_name.h new file mode 100644 index 00000000..b6c178b1 --- /dev/null +++ b/street_name.h @@ -0,0 +1,51 @@ +struct street_name_segment { + int segid; + int country; +}; + +struct street_name { + int len; + int country; + int townassoc; + char *name1; + char *name2; + int segment_count; + struct street_name_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + + +struct street_name_info { + int len; + int tag; + int dist; + int country; + struct coord *c; + int first; + int last; + int segment_count; + struct street_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + +struct street_name_number_info { + int len; + int tag; + struct coord *c; + int first; + int last; + struct street_name_segment *segment; +}; + +void street_name_get_by_id(struct street_name *name, struct map_data *mdat, unsigned long id); +void street_name_get(struct street_name *name, unsigned char **p); +int street_name_search(struct map_data *mdat, int country, int town_assoc, const char *name, int partial, int (*func)(struct street_name *name, void *data), void *data); +int street_name_get_info(struct street_name_info *inf, struct street_name *name); +int street_name_get_number_info(struct street_name_number_info *num, struct street_name_info *inf); + diff --git a/toolbar.h b/toolbar.h new file mode 100644 index 00000000..ce2f18d6 --- /dev/null +++ b/toolbar.h @@ -0,0 +1,3 @@ +struct toolbar { + struct toolbar_gui *gui; +}; diff --git a/town.c b/town.c new file mode 100644 index 00000000..2d08427b --- /dev/null +++ b/town.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include "display.h" +#include "coord.h" +#include "data_window.h" +#include "map_data.h" +#include "town.h" +#include "data.h" +#include "tree.h" +#include "block.h" +#include "file.h" +#include "draw_info.h" +#include "container.h" +#include "util.h" + +void +town_get(struct town *town, unsigned char **p) +{ + town->id=get_long(p); + town->c=coord_get(p); + town->name=get_string(p); + town->district=get_string(p); + town->postal_code1=get_string(p); + town->order=get_char(p); + town->country=get_short(p); + town->type=get_char(p); + town->unknown2=get_long(p); + town->size=get_char(p); + town->street_assoc=get_long(p); + town->unknown3=get_char(p); + town->postal_code2=get_string(p); + town->unknown4=get_long(p); +} + +void +town_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data) +{ + unsigned char *p=start; + struct town town; + char *s; + struct point pnt; + struct param_list param[100]; + struct segment seg; + struct draw_info *drw_inf=data; + struct data_window *win=drw_inf->co->data_window[data_window_type_town]; + + seg.blk_inf=*blk_inf; + + p+=4; + while (p < end) { + seg.data[0]=p; + town_get(&town, &p); + if (town.order < drw_inf->limit && transform(drw_inf->co->trans, town.c, &pnt)) { + s=town.name; + if (*town.district) + s=town.district; + display_add(&drw_inf->co->disp[drw_inf->display+town.order], 3, 0, s, 1, &pnt, NULL, &seg, sizeof(seg)); + if (win) + data_window_add(win, param, town_get_param(&seg, param, 100)); + } + } +} + +struct town_search_priv { + int country; + const char *name; + int name_len; + int partial; + int leaf; + int (*func)(struct town *, void *data); + void *data; +}; + +static int +town_tree_process(int version, int leaf, unsigned char **s2, struct map_data *mdat, void *data) +{ + int len, cmp, country; + struct block *blk; + struct town_search_priv *priv_data=data; + struct file *f=mdat->file[file_town_twn]; + struct block_offset *blk_off; + struct town town; + unsigned char *p,*name; + int ret,i,debug=0; + + country=get_short(s2); + name=get_string(s2); + if (debug) { + printf("Country: 0x%x ", country); + printf("Town: '%s' ", name); + } + len=get_long(s2); + + blk_off=(struct block_offset *)(*s2); + *s2+=len*4; + + cmp=priv_data->country-country; + if (! cmp) { + if (leaf == -1) + priv_data->leaf=0; + if (leaf == 1) + priv_data->leaf=1; + + if (debug) { + printf("'%s' vs '%s' version=%d\n", priv_data->name, name, version); + } + if (priv_data->leaf && priv_data->partial) + cmp=strncmp(priv_data->name,name,priv_data->name_len); + else + cmp=strcmp(priv_data->name,name); + } else { + if (debug) { + printf("country mismatch\n"); + } + } + + if (cmp > 0) + return 2; + if (cmp < 0) + return -2; + if (debug) + printf("%s\n", name); + for (i = 0 ; i < len ; i++) { + blk=block_get_byindex(f, blk_off->block, &p); + p=(unsigned char *)blk+blk_off->offset; + town_get(&town, &p); + ret=(*priv_data->func)(&town, priv_data->data); + if (ret) + return 1; + blk_off++; + } + return 0; +} + +int +town_search_by(struct map_data *mdat, char *ext, int country, const char *search, int partial, int (*func)(struct town *, void *data), void *data) +{ + struct town_search_priv priv_data; + priv_data.country=country; + priv_data.name=search; + priv_data.name_len=strlen(search); + priv_data.partial=partial; + priv_data.leaf=0; + priv_data.func=func; + priv_data.data=data; + + tree_search_map(mdat, file_town_twn, ext, town_tree_process, &priv_data); + + return 0; +} + +int +town_search_by_postal_code(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +{ + unsigned char uname[strlen(name)+1]; + + strtoupper(uname, name); + return town_search_by(mdat, "b1", country, uname, partial, func, data); +} + + +int +town_search_by_name(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) +{ + unsigned char uname[strlen(name)+1]; + + strtolower(uname, (char *)name); + return town_search_by(mdat, "b2", country, uname, partial, func, data); +} + +int +town_search_by_district(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +{ + unsigned char uname[strlen(name)+1]; + + strtoupper(uname, name); + return town_search_by(mdat, "b3", country, uname, partial, func, data); +} + +int +town_search_by_name_phon(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +{ + unsigned char uname[strlen(name)+1]; + + strtoupper(uname, name); + return town_search_by(mdat, "b4", country, uname, partial, func, data); +} + +int +town_search_by_district_phon(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +{ + unsigned char uname[strlen(name)+1]; + + strtoupper(uname, name); + return town_search_by(mdat, "b5", country, uname, partial, func, data); +} + + +void +town_get_by_id(struct town *town, struct map_data *mdat, int country, int id) +{ + struct map_data *mdat_res; + struct file *f; + int res,block,offset; + struct block *blk; + unsigned char *p; + int search1,search2; + unsigned long id2=id; + + if (id < 0) + id=-id; + search2 = id2 & 0xff; + search1 = (id2 >> 8) | (country << 24); + printf("country=0x%x id=0x%lx -id=0x%lx search1=0x%x search2=0x%x\n", country, id2, -id2, search1, search2); + return; + tree_search_hv_map(mdat, file_town_twn, search1, search2, &res, &mdat_res); + printf("res=0x%x\n",res); + block=res >> 16; + offset=res & 0xffff; + f=mdat_res->file[file_town_twn]; + printf("file %s block 0x%x offset 0x%x\n", f->name, block, offset); + blk=block_get_byindex(f, block, &p); + p=(unsigned char *)blk+offset; + printf("addr 0x%x\n", p-f->begin); + town_get(town, &p); +} + +int +town_get_param(struct segment *seg, struct param_list *param, int count) +{ + int i=count; + unsigned char *p; + struct town town; + + p=(unsigned char *)(seg->blk_inf.block); + p+=sizeof(*seg->blk_inf.block); + + param_add_hex("Block Unknown", get_long(&p), ¶m, &count); + p=seg->data[0]; + param_add_hex("Address", p-seg->blk_inf.file->begin, ¶m, &count); + town_get(&town, &p); + param_add_hex("ID", town.id, ¶m, &count); + param_add_hex_sig("X", town.c->x, ¶m, &count); + param_add_hex_sig("Y", town.c->y, ¶m, &count); + param_add_string("Name", town.name, ¶m, &count); + param_add_string("District", town.district, ¶m, &count); + param_add_string("PostalCode1", town.postal_code1, ¶m, &count); + param_add_hex("Order", town.order, ¶m, &count); + param_add_hex("Country", town.country, ¶m, &count); + param_add_hex("Type", town.type, ¶m, &count); + param_add_hex("Unknown2", town.unknown2, ¶m, &count); + param_add_hex("Size", town.size, ¶m, &count); + param_add_hex("StreetAssoc", town.street_assoc, ¶m, &count); + param_add_hex("Unknown3", town.unknown3, ¶m, &count); + param_add_string("PostalCode2", town.postal_code2, ¶m, &count); + param_add_hex("Unknown4", town.unknown4, ¶m, &count); + + return i-count; +} diff --git a/town.h b/town.h new file mode 100644 index 00000000..fce4b6b5 --- /dev/null +++ b/town.h @@ -0,0 +1,27 @@ +struct town { + unsigned long id; + struct coord *c; + char *name; + char *district; + char *postal_code1; + unsigned char order; + unsigned char type; + unsigned short country; + unsigned long unknown2; + unsigned char size; + unsigned long street_assoc; + unsigned char unknown3; + char *postal_code2; + unsigned long unknown4; +}; + +struct block_info; +struct segment; +struct container; +struct param_list; +struct map_data; + +void town_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); +int town_get_param(struct segment *seg, struct param_list *param, int count); +int town_search_by_name(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *t, void *data), void *data); +void town_get_by_id(struct town *town, struct map_data *mdat, int country, int id); diff --git a/transform.c b/transform.c new file mode 100644 index 00000000..a0f6fe6a --- /dev/null +++ b/transform.c @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include "coord.h" +#include "transform.h" + +int +transform(struct transformation *t, struct coord *c, struct point *p) +{ + double xc,yc; + int ret=0; + xc=c->x; + yc=c->y; + if (xc >= t->rect[0].x && xc <= t->rect[1].x && yc >= t->rect[1].y && yc <= t->rect[0].y) + ret=1; + xc-=t->center.x; + yc-=t->center.y; + yc=-yc; + if (t->angle) { + int xcn, ycn; + xcn=xc*t->cos_val+yc*t->sin_val; + ycn=-xc*t->sin_val+yc*t->cos_val; + xc=xcn; + yc=ycn; + } + xc=xc*16.0/(double)(t->scale); + yc=yc*16.0/(double)(t->scale); +#if 0 + { + double zc=yc; + if (zc < 10 && zc > 10) + zc=10; + return 0; + yc=300; + xc/=(-zc+1000.0)/1000.0; + yc/=(-zc+1000.0)/1000.0; + xc+=t->width/2; + } +#else + yc+=t->height/2; + xc+=t->width/2; +#endif + if (xc < -0x8000) + xc=-0x8000; + if (xc > 0x7fff) { + xc=0x7fff; + } + if (yc < -0x8000) + yc=-0x8000; + if (yc > 0x7fff) + yc=0x7fff; + p->x=xc; + p->y=yc; + return ret; +} + +void +transform_reverse(struct transformation *t, struct point *p, struct coord *c) +{ + int xc,yc; + xc=p->x; + yc=p->y; + xc-=t->width/2; + yc-=t->height/2; + xc=xc*t->scale/16; + yc=-yc*t->scale/16; + if (t->angle) { + int xcn, ycn; + xcn=xc*t->cos_val+yc*t->sin_val; + ycn=-xc*t->sin_val+yc*t->cos_val; + xc=xcn; + yc=ycn; + } + c->x=t->center.x+xc; + c->y=t->center.y+yc; +} + + +static int +min4(int v1,int v2, int v3, int v4) +{ + int res=v1; + if (v2 < res) + res=v2; + if (v3 < res) + res=v3; + if (v4 < res) + res=v4; + return res; +} + +static int +max4(int v1,int v2, int v3, int v4) +{ + int res=v1; + if (v2 > res) + res=v2; + if (v3 > res) + res=v3; + if (v4 > res) + res=v4; + return res; +} + +void +transform_set_angle(struct transformation *t,int angle) +{ + t->angle=angle; + t->cos_val=cos(M_PI*t->angle/180); + t->sin_val=sin(M_PI*t->angle/180); +} + +void +transform_setup(struct transformation *t, int x, int y, int scale, int angle) +{ + t->center.x=x; + t->center.y=y; + t->scale=scale; + transform_set_angle(t, angle); +} + +void +transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit) +{ + t->center=*center; + t->scale=1; + t->angle=0; + t->rect[0].x=center->x-limit; + t->rect[1].x=center->x+limit; + t->rect[1].y=center->y-limit; + t->rect[0].y=center->y+limit; +} + +void +transform_setup_source_rect(struct transformation *t) +{ + int i; + struct coord screen[4]; + struct point screen_pnt[4]; + + screen_pnt[0].x=0; + screen_pnt[0].y=0; + screen_pnt[1].x=t->width; + screen_pnt[1].y=0; + screen_pnt[2].x=0; + screen_pnt[2].y=t->height; + screen_pnt[3].x=t->width; + screen_pnt[3].y=t->height; + for (i = 0 ; i < 4 ; i++) { + transform_reverse(t, &screen_pnt[i], &screen[i]); + } + t->rect[0].x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->rect[1].x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->rect[1].y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); + t->rect[0].y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); +} + +int +transform_get_scale(struct transformation *t) +{ + return t->scale/16; +} + +void +transform_lng_lat(struct coord *c, struct coord_geo *g) +{ + g->lng=c->x/6371000.0/M_PI*180; + g->lat=atan(exp(c->y/6371000.0))/M_PI*360-90; +#if 0 + printf("y=%d vs %f\n", c->y, log(tan(M_PI_4+*lat*M_PI/360))*6371020.0); +#endif +} + +void +transform_geo_text(struct coord_geo *g, char *buffer) +{ + double lng=g->lng; + double lat=g->lat; + char lng_c='E'; + char lat_c='N'; + + if (lng < 0) { + lng=-lng; + lng_c='W'; + } + if (lat < 0) { + lat=-lat; + lat_c='S'; + } + + sprintf(buffer,"%02.0f%07.4f%c %03.0f%07.4f%c", floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c); + +} + +void +transform_mercator(double *lng, double *lat, struct coord *c) +{ + c->x=*lng*6371000.0*M_PI/180; + c->y=log(tan(M_PI_4+*lat*M_PI/360))*6371000.0; +} + +double +transform_scale(int y) +{ + struct coord c; + struct coord_geo g; + c.x=0; + c.y=y; + transform_lng_lat(&c, &g); + return 1/cos(g.lat/180*M_PI); +} + +double +transform_distance(struct coord *c1, struct coord *c2) +{ + double dx,dy,scale=transform_scale((c1->y+c2->y)/2); + dx=c1->x-c2->x; + dy=c1->y-c2->y; + return sqrt(dx*dx+dy*dy)/scale; +} + +int +transform_distance_sq(struct coord *c1, struct coord *c2) +{ + int dx=c1->x-c2->x; + int dy=c1->y-c2->y; + + if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767) + return INT_MAX; + else + return dx*dx+dy*dy; +} + +int +transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt) +{ + int vx,vy,wx,wy; + int c1,c2; + struct coord l; + + vx=l1->x-l0->x; + vy=l1->y-l0->y; + wx=ref->x-l0->x; + wy=ref->y-l0->y; + + c1=vx*wx+vy*wy; + if ( c1 <= 0 ) { + if (lpnt) + *lpnt=*l0; + return transform_distance_sq(l0, ref); + } + c2=vx*vx+vy*vy; + if ( c2 <= c1 ) { + if (lpnt) + *lpnt=*l1; + return transform_distance_sq(l1, ref); + } + + l.x=l0->x+vx*c1/c2; + l.y=l0->y+vy*c1/c2; + if (lpnt) + *lpnt=l; + return transform_distance_sq(&l, ref); +} + + +void +transform_print_deg(double deg) +{ + printf("%2.0f:%2.0f:%2.4f", floor(deg), fmod(deg*60,60), fmod(deg*3600,60)); +} + +int +is_visible(struct transformation *t, struct coord *c) +{ + struct coord *r=t->rect; + + assert(c[0].x <= c[1].x); + assert(c[0].y >= c[1].y); + assert(r[0].x <= r[1].x); + assert(r[0].y >= r[1].y); + if (c[0].x > r[1].x) + return 0; + if (c[1].x < r[0].x) + return 0; + if (c[0].y < r[1].y) + return 0; + if (c[1].y > r[0].y) + return 0; + return 1; +} + +int +is_point_visible(struct transformation *t, struct coord *c) +{ + struct coord *r=t->rect; + + assert(r[0].x <= r[1].x); + assert(r[0].y >= r[1].y); + if (c->x > r[1].x) + return 0; + if (c->x < r[0].x) + return 0; + if (c->y < r[1].y) + return 0; + if (c->y > r[0].y) + return 0; + return 1; +} + + +int +is_too_small(struct transformation *t, struct coord *c, int limit) +{ + return 0; + if ((c[1].x-c[0].x) < limit*t->scale/16) { + return 1; + } + if ((c[0].y-c[1].y) < limit*t->scale/16) { + return 1; + } + return 0; +} + +/* +Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. + +L = latitude in radians (positive north) +Lo = longitude in radians (positive east) +E = easting (meters) +N = northing (meters) + +For the sphere + +E = r Lo +N = r ln [ tan (pi/4 + L/2) ] + +where + +r = radius of the sphere (meters) +ln() is the natural logarithm + +For the ellipsoid + +E = a Lo +N = a * ln ( tan (pi/4 + L/2) * ( (1 - e * sin (L)) / (1 + e * sin (L))) ** (e/2) ) + + + e + - + pi L 1 - e sin(L) 2 + = a ln( tan( ---- + ---) (--------------) ) + 4 2 1 + e sin(L) + + +where + +a = the length of the semi-major axis of the ellipsoid (meters) +e = the first eccentricity of the ellipsoid + + +*/ diff --git a/transform.h b/transform.h new file mode 100644 index 00000000..fe0a0f23 --- /dev/null +++ b/transform.h @@ -0,0 +1,37 @@ +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "point.h" + +struct transformation { + int width; /* Height of destination rectangle */ + int height; /* Width of destination rectangle */ + long scale; /* Scale factor */ + int angle; /* Rotation angle */ + double cos_val,sin_val; /* cos and sin of rotation angle */ + struct coord rect[2]; /* Source rectangle */ + struct coord center; /* Center of source rectangle */ +}; + +int transform(struct transformation *t, struct coord *c, struct point *p); +int is_visible(struct transformation *t, struct coord *c); +int is_too_small(struct transformation *t, struct coord *c, int limit); +void transform_lng_lat(struct coord *c, struct coord_geo *g); +void transform_reverse(struct transformation *t, struct point *p, struct coord *c); +void transform_print_deg(double deg); +double transform_scale(int y); +double transform_distance(struct coord *c1, struct coord *c2); +int transform_distance_sq(struct coord *c1, struct coord *c2); +int transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt); + +void transform_mercator(double *lng, double *lat, struct coord *c); +int is_point_visible(struct transformation *t, struct coord *c); +int transform_get_scale(struct transformation *t); +void transform_setup_source_rect(struct transformation *t); +void transform_set_angle(struct transformation *t,int angle); +void transform_setup(struct transformation *t, int x, int y, int scale, int angle); +void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); +void transform_geo_text(struct coord_geo *g, char *buffer); + + +#endif diff --git a/tree.c b/tree.c new file mode 100644 index 00000000..9aacfacc --- /dev/null +++ b/tree.c @@ -0,0 +1,320 @@ +#include +#include +#include "file.h" +#include "map_data.h" +#include "data.h" +#include "tree.h" + +struct tree_hdr { + unsigned int addr; + unsigned int size; + unsigned int low; +}; + +struct tree_hdr_h { + unsigned int addr; + unsigned int size; +}; + +struct tree_leaf_h { + unsigned int lower; + unsigned int higher; + unsigned int match; + unsigned int value; +}; + +struct tree_hdr_v { + unsigned int count; + unsigned int next; + unsigned int unknown; +}; + +struct tree_leaf_v { + unsigned char key; + int value; +} __attribute__((packed)); + +int +tree_compare_string(unsigned char *s1, unsigned char **s2_ptr) +{ + unsigned char *s2=*s2_ptr; + char s1_exp, s2_exp; + *s2_ptr+=strlen(s2)+1; + for (;;) { + s1_exp=*s1++; + s2_exp=*s2++; + if (! s1_exp && ! s2_exp) + return 0; + if (s1_exp == 'A' && *s1 == 'E') { s1_exp='Ä'; s1++; } + if (s1_exp == 'O' && *s1 == 'E') { s1_exp='Ö'; s1++; } + if (s1_exp == 'U' && *s1 == 'E') { s1_exp='Ü'; s1++; } + if (s2_exp == 'A' && *s2 == 'E') { s2_exp='Ä'; s2++; } + if (s2_exp == 'O' && *s2 == 'E') { s2_exp='Ö'; s2++; } + if (s2_exp == 'U' && *s2 == 'E') { s2_exp='Ü'; s2++; } + if (s1_exp > s2_exp) + return 2; + if (s1_exp < s2_exp) + return -2; + } +} + +int +tree_compare_string_partial(unsigned char *s1, unsigned char **s2_ptr) +{ + unsigned char *s2=*s2_ptr; + char s1_exp, s2_exp; + *s2_ptr+=strlen(s2)+1; + for (;;) { + s1_exp=*s1++; + s2_exp=*s2++; + if (! s1_exp && ! s2_exp) + return 0; + if (s1_exp == 'A' && *s1 == 'E') { s1_exp='Ä'; s1++; } + if (s1_exp == 'O' && *s1 == 'E') { s1_exp='Ö'; s1++; } + if (s1_exp == 'U' && *s1 == 'E') { s1_exp='Ü'; s1++; } + if (s2_exp == 'A' && *s2 == 'E') { s2_exp='Ä'; s2++; } + if (s2_exp == 'O' && *s2 == 'E') { s2_exp='Ö'; s2++; } + if (s2_exp == 'U' && *s2 == 'E') { s2_exp='Ü'; s2++; } + if (! s1_exp) + return -1; + if (s1_exp > s2_exp) + return 2; + if (s1_exp < s2_exp) + return -2; + } +} + + +int +tree_search_h(struct file *file, unsigned int search) +{ + unsigned char *p=file->begin,*end; + int last,i=0,debug=0; + struct tree_hdr_h *thdr; + struct tree_leaf_h *tleaf; + + if (debug) { + printf("tree_search_h\n"); + } + while (i++ < 1000) { + thdr=(struct tree_hdr_h *)p; + p+=sizeof(*thdr); + end=p+thdr->size; + if (debug) { + printf("@0x%x\n", p-file->begin); + } + last=0; + while (p < end) { + tleaf=(struct tree_leaf_h *)p; + p+=sizeof(*tleaf); + if (debug) { + printf("low:0x%x high:0x%x match:0x%x val:0x%x search:0x%x\n", tleaf->lower, tleaf->higher, tleaf->match, tleaf->value, search); + } + if (tleaf->value == search) + return tleaf->match; + if (tleaf->value > search) { + if (tleaf->lower) + last=tleaf->lower; + break; + } + last=tleaf->higher; + } + if (! last || last == -1) + return 0; + p=file->begin+last; + } + return 0; +} + +int +tree_search_v(struct file *file, int offset, int search) +{ + unsigned char *p=file->begin+offset; + int i=0,count,debug=0; + struct tree_hdr_v *thdr; + struct tree_leaf_v *tleaf; + while (i++ < 1000) { + thdr=(struct tree_hdr_v *)p; + p+=sizeof(*thdr); + count=thdr->count; + while (count--) { + tleaf=(struct tree_leaf_v *)p; + p+=sizeof(*tleaf); + if (debug) + printf("tree_search_v: 0x%x 0x%x\n", tleaf->key, search); + if (tleaf->key == search) + return tleaf->value; + } + if (! thdr->next) + break; + p=file->begin+thdr->next; + } + return 0; + +} + +/* return values */ +/* 0=Next */ +/* -2=Too low */ +/* 1=Abort */ +/* 2=Too high */ + +int +tree_search(int version, struct file *file, unsigned char *p, int (*tree_func)(int version, int leaf, unsigned char **, struct map_data *mdat, void *), struct map_data *mdat, void *data, int higher) +{ + unsigned char *end,*psav; + struct tree_hdr *thdr; + int res=1,low; + int high; + int debug=0; + int leaf=0; + int retry=0; + + if (debug) + printf("version %d\n", version); + + thdr=(struct tree_hdr *)p; + p+=sizeof(*thdr); + low=thdr->low; + end=p+thdr->size; + if (debug) + printf("Header: offset 0x%x size %d low 0x%x\n", thdr->addr, thdr->size, thdr->low); + if (higher == -1) + leaf=-1; + if (higher == 1 && low != -1) { + if (debug) + printf("calling first higher tree 0x%x\n",low); + res=tree_search(version,file,low+file->begin,tree_func,mdat,data,1); + if (debug) + printf("returning from first higher tree res=%d\n", res); + } + while (p < end) { + psav=p; + high=get_long(&p); + if (high == -1) + leaf=1; + res=tree_func(version, leaf, &p, mdat, data); + leaf=0; + if (debug) + printf("result: %d high 0x%x\n", res, high); + if (res == 1) + return res; + if (res < 0) { + if (debug) + printf("calling lower tree 0x%x\n",low); + if (low != -1) { + res=tree_search(version,file,low+file->begin,tree_func,mdat,data,0); + if (debug) + printf("returning from lower tree res=%d\n", res); + if (! res && !retry++ ) { + if (debug) + printf("retrying current leaf\n"); + p=psav; + continue; + } + low=-1; + if (res < 0) + break; + } + else + break; + } + retry=0; + if (! res && high != -1) { + if (debug) + printf("high=0x%x\n", high); + if (debug) + printf("calling higher tree 0x%x\n",high); + res=tree_search(version,file,high+file->begin,tree_func,mdat,data,1); + if (debug) + printf("returning from higer tree res=%d\n", res); + low=-1; + } else { + low=high; + } + } + if (low != -1) + res=tree_search(version,file,low+file->begin,tree_func,mdat,data,0); + + return res; +} + +int +tree_search_map(struct map_data *mdat, int map, char *ext, + int (*tree_func)(int, int, unsigned char **, struct map_data *mdat, void *), void *data) + +{ + struct file *f_dat,*f_idx; + char filename[4096]; + int len, version, ret; + unsigned char *p; + int debug=0; + + while (mdat) { + f_dat=mdat->file[map]; + strcpy(filename, f_dat->name); + len=strlen(filename); + strcpy(filename+len-3,ext); + if (debug) + printf("tree_search_map: filename='%s'\n", filename); + f_idx=file_create(filename); + version=1; + p=f_idx->begin; + if (!strncmp(p+4,"RootBlock",9)) { + p+=0x1000; + version=2; + } + ret=tree_search(version, f_idx, p, tree_func, mdat, data, -1); + if (debug) + printf("tree_search_map: ret=%d\n", ret); + file_destroy(f_idx); + if (ret == 1) + return 1; + mdat=mdat->next; + } + return 0; +} + +struct tree_search_hv { + struct map_data *mdat; + struct file *f_idx_h; + struct file *f_idx_v; + struct tree_search_hv *next; +}; + +int +tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigned int search2, int *result, struct map_data **mdat_result) + +{ + struct file *f_dat,*f_idx_h, *f_idx_v; + char filename[4096]; + int h,len,ret=0; + int debug=0; + + while (mdat && !ret) { + f_dat=mdat->file[map]; + strcpy(filename, f_dat->name); + len=strlen(filename); + strcpy(filename+len-3,"h1"); + f_idx_h=file_create(filename); + strcpy(filename+len-3,"v1"); + f_idx_v=file_create(filename); + h=tree_search_h(f_idx_h, search1); + if (h) { + ret=tree_search_v(f_idx_v, h, search2); + if (ret) { + if (debug) + printf("result 0x%x\n", ret); + *result=ret; + *mdat_result=mdat; + file_destroy(f_idx_v); + file_destroy(f_idx_h); + return 0; + } + } + file_destroy(f_idx_v); + file_destroy(f_idx_h); + mdat=mdat->next; + } + return 1; +} diff --git a/tree.h b/tree.h new file mode 100644 index 00000000..58ff0448 --- /dev/null +++ b/tree.h @@ -0,0 +1,13 @@ +struct block_offset { + unsigned short offset; + unsigned short block; +}; + + +int tree_compare_string(unsigned char *s1, unsigned char **s2); +int tree_compare_string_partial(unsigned char *s1, unsigned char **s2); +#if 0 +int tree_search(struct file *file, unsigned char *search, int (*tree_func)(int, unsigned char *, unsigned char **, struct map_data *, void *), struct map_data *mdat, void *data2); +#endif +int tree_search_map(struct map_data *mdat, int map, char *ext, int (*tree_func)(int, int, unsigned char **, struct map_data *, void *), void *data); +int tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigned int search2, int *result, struct map_data **mdat_result); diff --git a/tst.c b/tst.c new file mode 100644 index 00000000..16cd8834 --- /dev/null +++ b/tst.c @@ -0,0 +1,15 @@ +#include +#include +#include + +int tst(void) +{ + unsigned short t1=20; + unsigned short t2=10; + return t2-t1; +} + +int main(int argc, char **argv) +{ + printf("res=%d\n", tst()); +} diff --git a/util.c b/util.c new file mode 100644 index 00000000..b99dfcbd --- /dev/null +++ b/util.c @@ -0,0 +1,18 @@ +#include + +void +strtoupper(unsigned char *dest, unsigned char *src) +{ + while (*src) + *dest++=toupper(*src++); + *dest='\0'; +} + +void +strtolower(unsigned char *dest, unsigned char *src) +{ + while (*src) + *dest++=tolower(*src++); + *dest='\0'; +} + diff --git a/util.h b/util.h new file mode 100644 index 00000000..5f89adb9 --- /dev/null +++ b/util.h @@ -0,0 +1,4 @@ +#include + +void strtoupper(unsigned char *dest, unsigned char *src); +void strtolower(unsigned char *dest, unsigned char *src); diff --git a/vehicle.c b/vehicle.c new file mode 100644 index 00000000..80eda88c --- /dev/null +++ b/vehicle.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include "coord.h" +#include "transform.h" +#include "statusbar.h" +#include "vehicle.h" + +struct vehicle { + GIOChannel *iochan; + int timer_count; + int qual; + int sats; + double lat,lng; + double height; + double dir,speed; + struct coord current_pos; + struct coord_d curr; + struct coord_d delta; + + double speed_last; +}; + +void (*callback_func)(); +void *callback_data; + +int +vehicle_timer(gpointer t) +{ + struct vehicle *this=t; + if (this->timer_count++ < 10) { + this->curr.x+=this->delta.x; + this->curr.y+=this->delta.y; + this->current_pos.x=this->curr.x; + this->current_pos.y=this->curr.y; + if (callback_func) + (*callback_func)(callback_data); + } + return TRUE; +} + +struct coord * +vehicle_pos_get(void *t) +{ + struct vehicle *this=t; + + return &this->current_pos; +} + +double * +vehicle_speed_get(void *t) +{ + struct vehicle *this=t; + + return &this->speed; +} + +double * +vehicle_dir_get(void *t) +{ + struct vehicle *this=t; + + return &this->dir; +} + +void +vehicle_set_position(void *t, struct coord *pos) +{ + struct vehicle *this=t; + + this->current_pos=*pos; + this->curr.x=this->current_pos.x; + this->curr.y=this->current_pos.y; + this->delta.x=0; + this->delta.y=0; + if (callback_func) + (*callback_func)(callback_data); +} + +void +vehicle_parse_gps(struct vehicle *this, char *buffer) +{ + char *p,*item[16]; + double lat,lng,scale,speed; + int i,debug=0; + + if (debug) { + printf("GPS %s\n", buffer); + } + if (!strncmp(buffer,"$GPGGA",6)) { + /* $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C + UTC of Fix,Latitude,N/S,Longitude,E/W,Quality,Satelites,HDOP,Altitude,"M" + */ + i=0; + p=buffer; + while (i < 16) { + item[i++]=p; + while (*p && *p != ',') + p++; + if (! *p) break; + *p++='\0'; + } + + sscanf(item[2],"%lf",&lat); + this->lat=floor(lat/100); + lat-=this->lat*100; + this->lat+=lat/60; + + sscanf(item[4],"%lf",&lng); + this->lng=floor(lng/100); + lng-=this->lng*100; + this->lng+=lng/60; + + sscanf(item[6],"%d",&this->qual); + sscanf(item[7],"%d",&this->sats); + sscanf(item[9],"%lf",&this->height); + + transform_mercator(&this->lng, &this->lat, &this->current_pos); + + this->curr.x=this->current_pos.x; + this->curr.y=this->current_pos.y; + this->timer_count=0; + if (callback_func) + (*callback_func)(callback_data); + } + if (!strncmp(buffer,"$GPVTG",6)) { + /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A + Course Over Ground Degrees True,"T",Course Over Ground Degrees Magnetic,"M", + Speed in Knots,"N","Speed in KM/H","K",*CHECKSUM */ + + i=0; + p=buffer; + while (i < 16) { + item[i++]=p; + while (*p && *p != ',') + p++; + if (! *p) break; + *p++='\0'; + } + sscanf(item[1],"%lf",&this->dir); + sscanf(item[7],"%lf",&this->speed); + + scale=transform_scale(this->current_pos.y); + speed=this->speed+(this->speed-this->speed_last)/2; + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/36; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/36; + this->speed_last=this->speed; + } +} + +gboolean +vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) +{ + struct vehicle *this=t; + GError *error=NULL; + char buffer[4096]; + char *str,*tok; + int size; + + if (condition == G_IO_IN) { + g_io_channel_read_chars(iochan, buffer, 4096, &size, &error); + buffer[size]='\0'; + str=buffer; + while ((tok=strtok(str, "\n"))) { + str=NULL; + vehicle_parse_gps(this, tok); + } + return TRUE; + } + return FALSE; +} + +void * +vehicle_new(char *file) +{ + struct vehicle *this; + GError *error=NULL; + int fd; + + this=g_new(struct vehicle,1); + fd=open(file,O_RDONLY|O_NDELAY); + this->iochan=g_io_channel_unix_new(fd); + g_io_channel_set_encoding(this->iochan, NULL, &error); + g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); +#if 0 + g_timeout_add(100, vehicle_timer, this); +#endif + this->current_pos.x=0x130000; + this->current_pos.y=0x600000; + + return this; +} + +void +vehicle_callback(void (*func)(), void *data) +{ + callback_func=func; + callback_data=data; +} + +int +vehicle_destroy(void *t) +{ + struct vehicle *this=t; + GError *error=NULL; + + + g_io_channel_shutdown(this->iochan,0,&error); + g_free(this); + + return 0; +} diff --git a/vehicle.h b/vehicle.h new file mode 100644 index 00000000..10101c24 --- /dev/null +++ b/vehicle.h @@ -0,0 +1,6 @@ +struct coord *vehicle_pos_get(void *); +double *vehicle_dir_get(void *); +double *vehicle_speed_get(void *); +void vehicle_callback(void (*func)(),void *data); +void vehicle_set_position(void *, struct coord *); +void *vehicle_new(char *file); -- cgit v1.2.1 From 100e703848d7d4491970333238345ca83619b02a Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Dec 2005 12:32:47 +0000 Subject: Converting to autoconf/automake git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@9 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- speech.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/speech.c b/speech.c index c913629c..8823e155 100644 --- a/speech.c +++ b/speech.c @@ -1,5 +1,5 @@ /* speechd simple client program - * CVS revision: $Id: speech.c,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * CVS revision: $Id: speech.c,v 1.2 2005-12-02 12:32:47 martin-s Exp $ * Author: Tomas Cerha */ #include @@ -11,8 +11,10 @@ #include #include #include - +#include "config.h" +#ifdef HAVE_LIBSPEECHD #include +#endif #include "speech.h" struct speech { @@ -21,6 +23,7 @@ struct speech { struct speech * speech_new(void) { +#ifdef HAVE_LIBSPEECHD struct speech *this; int sockfd; @@ -32,30 +35,41 @@ speech_new(void) { this->sockfd=sockfd; } return this; +#else + return NULL; +#endif } int speech_say(struct speech *this, char *text) { +#ifdef HAVE_LIBSPEECHD int err; err = spd_sayf(this->sockfd, 2, text); if (err != 1) return 1; +#endif return 0; } int speech_sayf(struct speech *this, char *format, ...) { +#ifdef HAVE_LIBSPEECHD char buffer[8192]; va_list ap; va_start(ap,format); vsnprintf(buffer, 8192, format, ap); return speech_say(this, buffer); +#else + return 0; +#endif } int speech_destroy(struct speech *this) { +#ifdef HAVE_LIBSPEECHD spd_close(this->sockfd); g_free(this); +#endif return 0; } -- cgit v1.2.1 From dd38a19342185e525fcd27af75e1bedcf13a6097 Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Dec 2005 12:35:12 +0000 Subject: Add missing files git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@10 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 23 +++++++++++++++++++++++ graphics/Makefile.am | 1 + graphics/gtk_drawing_area/Makefile.am | 11 +++++++++++ gui/Makefile.am | 1 + gui/gtk/Makefile.am | 11 +++++++++++ 5 files changed, 47 insertions(+) create mode 100644 Makefile.am create mode 100644 graphics/Makefile.am create mode 100644 graphics/gtk_drawing_area/Makefile.am create mode 100644 gui/Makefile.am create mode 100644 gui/gtk/Makefile.am diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..c169ff87 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,23 @@ +SUBDIRS=fib-1.0 gui graphics + +fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am + cd fib-1.0 + ./configure + +AM_CPPFLAGS = @PACKAGE_CFLAGS@ + + +bin_PROGRAMS = navit + +navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c destination.c \ + display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ + map-stubs.c map_data.c menu.c navigation.c param.c phrase.c plugin.c poly.c popup.c \ + profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c \ + util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ + cursor.h data.h data_window.h data_window_int.h destination.h display.h draw_info.h \ + file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ + param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ + street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h util.h vehicle.h + +navit_LDADD = @PACKAGE_LIBS@ gui/gtk/gtk.o graphics/gtk_drawing_area/gtk_drawing_area.o -Lfib-1.0 -lfib + diff --git a/graphics/Makefile.am b/graphics/Makefile.am new file mode 100644 index 00000000..b5787ee6 --- /dev/null +++ b/graphics/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=gtk_drawing_area diff --git a/graphics/gtk_drawing_area/Makefile.am b/graphics/gtk_drawing_area/Makefile.am new file mode 100644 index 00000000..e06fa19f --- /dev/null +++ b/graphics/gtk_drawing_area/Makefile.am @@ -0,0 +1,11 @@ +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. + +objdir=$(prefix)/dummy +obj_PROGRAMS=gtk_drawing_area.o +INSTALL_PROGRAM=$(INSTALL_DATA) + +gtk_drawing_area_o_SOURCES=graphics_gtk_drawing_area.c + +gtk_drawing_area.o: $(gtk_drawing_area_o_OBJECTS) + ld -r -o gtk_drawing_area.o $(gtk_drawing_area_o_OBJECTS) diff --git a/gui/Makefile.am b/gui/Makefile.am new file mode 100644 index 00000000..126d10a6 --- /dev/null +++ b/gui/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=gtk diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am new file mode 100644 index 00000000..0c449973 --- /dev/null +++ b/gui/gtk/Makefile.am @@ -0,0 +1,11 @@ +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. + +objdir=$(prefix)/dummy +obj_PROGRAMS=gtk.o +INSTALL_PROGRAM=$(INSTALL_DATA) + +gtk_o_SOURCES=gtkeyboard.c gui_gtk_menu.c gui_gtk_statusbar.c gui_gtk_toolbar.c gui_gtk_window.c + +gtk.o: $(gtk_o_OBJECTS) + ld -r -o gtk.o $(gtk_o_OBJECTS) -- cgit v1.2.1 From b39fc96cd075eb23b532db8125432d09332a7fcc Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Dec 2005 13:15:48 +0000 Subject: Added freetype2 package, cleaned up Makefile.am git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@11 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics/gtk_drawing_area/Makefile.am | 4 ++-- gui/gtk/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/graphics/gtk_drawing_area/Makefile.am b/graphics/gtk_drawing_area/Makefile.am index e06fa19f..376b8884 100644 --- a/graphics/gtk_drawing_area/Makefile.am +++ b/graphics/gtk_drawing_area/Makefile.am @@ -1,9 +1,9 @@ AUTOMAKE_OPTIONS = no-exeext AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. -objdir=$(prefix)/dummy +objdir=$(prefix) obj_PROGRAMS=gtk_drawing_area.o -INSTALL_PROGRAM=$(INSTALL_DATA) +INSTALL_PROGRAM=/bin/true gtk_drawing_area_o_SOURCES=graphics_gtk_drawing_area.c diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am index 0c449973..e6a2edd2 100644 --- a/gui/gtk/Makefile.am +++ b/gui/gtk/Makefile.am @@ -1,9 +1,9 @@ AUTOMAKE_OPTIONS = no-exeext AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. -objdir=$(prefix)/dummy +objdir=$(prefix) obj_PROGRAMS=gtk.o -INSTALL_PROGRAM=$(INSTALL_DATA) +INSTALL_PROGRAM=/bin/true gtk_o_SOURCES=gtkeyboard.c gui_gtk_menu.c gui_gtk_statusbar.c gui_gtk_toolbar.c gui_gtk_window.c -- cgit v1.2.1 From d2367656c2d5b72cf4fd471ffd2d2f0266596472 Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Dec 2005 13:26:31 +0000 Subject: Autodetect API git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@12 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- speech.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/speech.c b/speech.c index 8823e155..0cb39e1b 100644 --- a/speech.c +++ b/speech.c @@ -1,5 +1,5 @@ /* speechd simple client program - * CVS revision: $Id: speech.c,v 1.2 2005-12-02 12:32:47 martin-s Exp $ + * CVS revision: $Id: speech.c,v 1.3 2005-12-02 13:26:31 martin-s Exp $ * Author: Tomas Cerha */ #include @@ -27,7 +27,11 @@ speech_new(void) { struct speech *this; int sockfd; +#ifdef SPD_FATAL + sockfd = spd_open("map","main",NULL); +#else sockfd = spd_init("map","main"); +#endif if (sockfd == 0) return NULL; this=g_new(struct speech,1); -- cgit v1.2.1 From 40b863375ba3352061da0a06a5c2c378e4c69ddd Mon Sep 17 00:00:00 2001 From: horwitz Date: Fri, 9 Dec 2005 08:20:33 +0000 Subject: start an improved destination dialog git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@17 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/destination.c b/destination.c index 9cced769..9f489259 100644 --- a/destination.c +++ b/destination.c @@ -22,7 +22,7 @@ extern gint track_focus(gpointer data); GtkWidget *entry_country, *entry_postal, *entry_city, *entry_district; GtkWidget *entry_street, *entry_number; -GtkWidget *listbox; +GtkWidget *listbox, *current=NULL; int row_count=8; int selected; @@ -54,7 +54,13 @@ static void select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct data_window *win) { selected=row; + gchar *text; printf("Selected %d\n", row); + + if(current==entry_country) { + gtk_clist_get_text(GTK_CLIST(clist),row,0,&text); + gtk_entry_set_text(GTK_ENTRY(entry_country),text); + } } int @@ -426,6 +432,8 @@ void changed(GtkWidget *widget, struct search_param *search) char *empty[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; char *dash; + current=widget; + gtk_clist_freeze(GTK_CLIST(listbox)); gtk_clist_clear(GTK_CLIST(listbox)); @@ -548,7 +556,7 @@ int destination_address(struct container *co) #endif window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); - keyboard = build_keyboard(NULL, "/usr/local/share/gtkeyboard/DE.key"); + keyboard = build_keyboard(NULL, "/usr/share/gtkeyboard/key/DE.key"); vbox = gtk_vbox_new(FALSE, 0); table = gtk_table_new(3, 8, FALSE); -- cgit v1.2.1 From d6339924fe6638987b14dd0239c6335d1708d93a Mon Sep 17 00:00:00 2001 From: horwitz Date: Fri, 9 Dec 2005 08:23:48 +0000 Subject: try to find arial in /usr/share/fonts/truetype/msttcorefonts/arial.ttf, too git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@18 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics/gtk_drawing_area/graphics_gtk_drawing_area.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index a730cee5..81e6777a 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -46,15 +46,18 @@ struct graphics_image_gra { static struct graphics_font *font_new(struct graphics *gr, int size) { char *filename="/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf"; + char *filename2="/usr/share/fonts/truetype/msttcorefonts/arial.ttf"; struct graphics_font *font=g_new(struct graphics_font, 1); if (!gr->gra->library_init) { FT_Init_FreeType( &gr->gra->library ); gr->gra->library_init=1; } if (FT_New_Face( gr->gra->library, filename, 0, &font->face )) { - g_warning("Failed to load '%s', no labelling", filename); - g_free(font); - return NULL; + if (FT_New_Face( gr->gra->library, filename2, 0, &font->face )) { + g_warning("Failed to load '%s', no labelling", filename); + g_free(font); + return NULL; + } } FT_Set_Char_Size(font->face, 0, size, 300, 300); return font; -- cgit v1.2.1 From 1b232a61aa70d24f3ed42e317b3724bfee3617e3 Mon Sep 17 00:00:00 2001 From: horwitz Date: Fri, 9 Dec 2005 09:29:59 +0000 Subject: country,town,street,number are displayed when selected in Clist git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@19 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/destination.c b/destination.c index 9f489259..2a9ccbf0 100644 --- a/destination.c +++ b/destination.c @@ -55,11 +55,23 @@ select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct d { selected=row; gchar *text; - printf("Selected %d\n", row); + printf("Selected row %d, column %d\n", row, column); if(current==entry_country) { gtk_clist_get_text(GTK_CLIST(clist),row,0,&text); - gtk_entry_set_text(GTK_ENTRY(entry_country),text); + gtk_entry_set_text(GTK_ENTRY(entry_country),g_strdup(text)); + } + else if( current==entry_city) { + gtk_clist_get_text(GTK_CLIST(clist),row,5,&text); + gtk_entry_set_text(GTK_ENTRY(entry_city),g_strdup(text)); + } + else if( current==entry_street) { + gtk_clist_get_text(GTK_CLIST(clist),row,4,&text); + gtk_entry_set_text(GTK_ENTRY(entry_street),g_strdup(text)); + } + else if( current==entry_number) { + gtk_clist_get_text(GTK_CLIST(clist),row,8,&text); + gtk_entry_set_text(GTK_ENTRY(entry_number),g_strdup(text)); } } -- cgit v1.2.1 From 13b33253bddd8f310842910235498da6be95e554 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 11 Dec 2005 10:50:33 +0000 Subject: Added support for gpsd git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@22 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- compass.c | 5 +- cursor.c | 4 +- cursor.h | 2 +- main.c | 17 +++++-- vehicle.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- vehicle.h | 14 +++--- 6 files changed, 156 insertions(+), 49 deletions(-) diff --git a/compass.c b/compass.c index cbfc9c68..e0c5b2c0 100644 --- a/compass.c +++ b/compass.c @@ -66,6 +66,9 @@ compass_draw(struct compass *comp, struct container *co) int dx,dy; char buffer[16]; + if (! co->vehicle) + return; + vehicle_dir=vehicle_dir_get(co->vehicle); comp->gr->draw_mode(comp->gr, draw_mode_begin); p.x=0; @@ -80,7 +83,7 @@ compass_draw(struct compass *comp, struct container *co) pos=vehicle_pos_get(co->vehicle); dx=dest->x-pos->x; dy=dest->y-pos->y; - dir=atan2(dx,dy)*180.0/M_PI; + dir=atan2(dx,dy)*180.0/M_PI; printf("dx %d dy %d dir=%f vehicle_dir=%f\n", dx, dy, dir, *vehicle_dir); dir-=*vehicle_dir; handle(comp->gr, comp->green, &p, 20, dir); diff --git a/cursor.c b/cursor.c index 1f1d99e8..1e63249d 100644 --- a/cursor.c +++ b/cursor.c @@ -184,13 +184,13 @@ extern void compass_draw(); extern void *vehicle; struct cursor * -cursor_new(struct container *co) +cursor_new(struct container *co, struct vehicle *v) { struct cursor *this=g_new(struct cursor,1); this->co=co; this->cursor_gc=co->gra->gc_new(co->gra); co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff); co->gra->gc_set_linewidth(this->cursor_gc, 2); - vehicle_callback(cursor_update, this); + vehicle_callback(v, cursor_update, this); return this; } diff --git a/cursor.h b/cursor.h index 46114875..5a71ace2 100644 --- a/cursor.h +++ b/cursor.h @@ -2,4 +2,4 @@ struct cursor; struct container; struct coord * cursor_pos_get(struct cursor *this); -struct cursor *cursor_new(struct container *co); +struct cursor *cursor_new(struct container *co, struct vehicle *v); diff --git a/main.c b/main.c index e2d23554..dd21dc89 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include #include +#include #include "coord.h" #include "vehicle.h" #include "cursor.h" @@ -33,6 +34,7 @@ int main(int argc, char **argv) CORBA_ORB orb; Map map_client = CORBA_OBJECT_NIL; char *retval; + char *gps; FILE *ior; setenv("LC_NUMERIC","C",1); @@ -46,12 +48,21 @@ int main(int argc, char **argv) map_data_default=load_maps(NULL); plugin_load(); co=gui_gtk_window(1300000,7000000,8192); - co->vehicle=vehicle_new("/tmp/gpsdata"); - co->cursor=cursor_new(co); + + gps=getenv("GPSDATA"); + if (gps) { + co->vehicle=vehicle_new(gps); + if (co->vehicle) { + co->cursor=cursor_new(co,co->vehicle); + } + } else { + g_warning("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]"); + } co->speech=speech_new(); speech_handle=co->speech; co->route=route_new(); - co->compass=compass_new(co); + if (co->vehicle) + co->compass=compass_new(co); route_mapdata_set(co->route, co->map_data); diff --git a/vehicle.c b/vehicle.c index 80eda88c..62507179 100644 --- a/vehicle.c +++ b/vehicle.c @@ -1,3 +1,4 @@ +#include "config.h" #include #include #include @@ -5,6 +6,9 @@ #include #include #include +#ifdef HAVE_LIBGPS +#include +#endif #include "coord.h" #include "transform.h" #include "statusbar.h" @@ -23,10 +27,14 @@ struct vehicle { struct coord_d delta; double speed_last; +#ifdef HAVE_LIBGPS + struct gps_data_t *gps; +#endif + void (*callback_func)(); + void *callback_data; }; -void (*callback_func)(); -void *callback_data; +struct vehicle *vehicle_last; int vehicle_timer(gpointer t) @@ -37,48 +45,40 @@ vehicle_timer(gpointer t) this->curr.y+=this->delta.y; this->current_pos.x=this->curr.x; this->current_pos.y=this->curr.y; - if (callback_func) - (*callback_func)(callback_data); + if (this->callback_func) + (*this->callback_func)(this->callback_data); } return TRUE; } struct coord * -vehicle_pos_get(void *t) +vehicle_pos_get(struct vehicle *this) { - struct vehicle *this=t; - return &this->current_pos; } double * -vehicle_speed_get(void *t) +vehicle_speed_get(struct vehicle *this) { - struct vehicle *this=t; - return &this->speed; } double * -vehicle_dir_get(void *t) +vehicle_dir_get(struct vehicle *this) { - struct vehicle *this=t; - return &this->dir; } void -vehicle_set_position(void *t, struct coord *pos) +vehicle_set_position(struct vehicle *this, struct coord *pos) { - struct vehicle *this=t; - this->current_pos=*pos; this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->delta.x=0; this->delta.y=0; - if (callback_func) - (*callback_func)(callback_data); + if (this->callback_func) + (*this->callback_func)(this->callback_data); } void @@ -124,8 +124,8 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; - if (callback_func) - (*callback_func)(callback_data); + if (this->callback_func) + (*this->callback_func)(this->callback_data); } if (!strncmp(buffer,"$GPVTG",6)) { /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A @@ -152,37 +152,125 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) } } -gboolean +static gboolean vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) { struct vehicle *this=t; GError *error=NULL; char buffer[4096]; char *str,*tok; - int size; + gsize size; if (condition == G_IO_IN) { - g_io_channel_read_chars(iochan, buffer, 4096, &size, &error); - buffer[size]='\0'; - str=buffer; - while ((tok=strtok(str, "\n"))) { - str=NULL; - vehicle_parse_gps(this, tok); +#ifdef HAVE_LIBGPS + if (this->gps) { + vehicle_last=this; + gps_poll(this->gps); + } else { +#else + { +#endif + g_io_channel_read_chars(iochan, buffer, 4096, &size, &error); + buffer[size]='\0'; + str=buffer; + while ((tok=strtok(str, "\n"))) { + str=NULL; + vehicle_parse_gps(this, tok); + } } + return TRUE; } return FALSE; } -void * -vehicle_new(char *file) +#ifdef HAVE_LIBGPS +static void +vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) +{ + struct vehicle *this=vehicle_last; + double scale,speed; + if (data->set & SPEED_SET) { + this->speed_last=this->speed; + this->speed=data->fix.speed; + data->set &= ~SPEED_SET; + } + if (data->set & TRACK_SET) { + speed=this->speed+(this->speed-this->speed_last)/2; + this->dir=data->fix.track; + scale=transform_scale(this->current_pos.y); + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/36; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/36; + data->set &= ~TRACK_SET; + } + if (data->set & LATLON_SET) { + this->lat=data->fix.latitude; + this->lng=data->fix.longitude; + transform_mercator(&this->lng, &this->lat, &this->current_pos); + this->curr.x=this->current_pos.x; + this->curr.y=this->current_pos.y; + if (this->callback_func) + (*this->callback_func)(this->callback_data); + data->set &= ~LATLON_SET; + } + if (data->set & ALTITUDE_SET) { + this->height=data->fix.altitude; + data->set &= ~ALTITUDE_SET; + } + if (data->set & SATELLITE_SET) { + this->sats=data->satellites; + data->set &= ~SATELLITE_SET; + } + if (data->set & STATUS_SET) { + this->qual=data->status; + data->set &= ~STATUS_SET; + } +} +#endif + +struct vehicle * +vehicle_new(const char *url) { struct vehicle *this; GError *error=NULL; int fd; + char *url_,*colon; +#ifdef HAVE_LIBGPS + struct gps_data_t *gps=NULL; +#endif + if (! strncmp(url,"file:",5)) { + fd=open(url+5,O_RDONLY|O_NDELAY); + if (fd < 0) { + g_warning("Failed to open %s", url); + return NULL; + } + } else if (! strncmp(url,"gpsd://",7)) { +#ifdef HAVE_LIBGPS + url_=g_strdup(url); + colon=index(url_+7,':'); + if (colon) { + *colon=0; + gps=gps_open(url_+7,colon+1); + } else + gps=gps_open(url+7,NULL); + g_free(url_); + if (! gps) { + g_warning("Failed to connect to %s", url); + return NULL; + } + gps_query(gps, "w+x\n"); + gps_set_raw_hook(gps, vehicle_gps_callback); + fd=gps->gps_fd; +#else + g_warning("No support for gpsd compiled in\n"); + return NULL; +#endif + } this=g_new(struct vehicle,1); - fd=open(file,O_RDONLY|O_NDELAY); +#ifdef HAVE_LIBGPS + this->gps=gps; +#endif this->iochan=g_io_channel_unix_new(fd); g_io_channel_set_encoding(this->iochan, NULL, &error); g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); @@ -196,20 +284,23 @@ vehicle_new(char *file) } void -vehicle_callback(void (*func)(), void *data) +vehicle_callback(struct vehicle *this, void (*func)(), void *data) { - callback_func=func; - callback_data=data; + this->callback_func=func; + this->callback_data=data; } int -vehicle_destroy(void *t) +vehicle_destroy(struct vehicle *this) { - struct vehicle *this=t; GError *error=NULL; g_io_channel_shutdown(this->iochan,0,&error); +#ifdef HAVE_LIBGPS + if (this->gps) + gps_close(this->gps); +#endif g_free(this); return 0; diff --git a/vehicle.h b/vehicle.h index 10101c24..8787e38e 100644 --- a/vehicle.h +++ b/vehicle.h @@ -1,6 +1,8 @@ -struct coord *vehicle_pos_get(void *); -double *vehicle_dir_get(void *); -double *vehicle_speed_get(void *); -void vehicle_callback(void (*func)(),void *data); -void vehicle_set_position(void *, struct coord *); -void *vehicle_new(char *file); +struct vehicle; + +struct coord *vehicle_pos_get(struct vehicle *); +double *vehicle_dir_get(struct vehicle *); +double *vehicle_speed_get(struct vehicle *); +void vehicle_callback(struct vehicle *, void (*func)(),void *data); +void vehicle_set_position(struct vehicle *, struct coord *); +struct vehicle *vehicle_new(const char *url); -- cgit v1.2.1 From cd37f5b7f272f854d9df3132d629a7eebeabeaf7 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 11 Dec 2005 12:21:46 +0000 Subject: Cleanup git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@23 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_menu.c | 68 -------------------------------------------------- street.c | 2 ++ 2 files changed, 2 insertions(+), 68 deletions(-) diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index 8ddebf6c..3de3c1cf 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -35,60 +35,6 @@ struct destination { struct coord pos; }; -static void -menu_goto_abensberg(struct container *co) -{ - co->trans->center.x=1317000; - co->trans->center.y=6235000; - co->trans->scale=2*16; - graphics_redraw(co); -} - -static void -menu_goto_regensburg(struct container *co) -{ - co->trans->center.x=(1339653+1341853)/2; - co->trans->center.y=(6272179+6269979)/2; - co->trans->scale=4*16; - graphics_redraw(co); -} - -static void -menu_goto_problem(struct container *co) -{ -#if 0 /* Crailsheim */ - map->center_x=0x112e55; - map->center_y=0x60275a; - map->scale=4*16; - map_redraw(map); - route_click(map->route, map, 697, 31); - route_click(map->route, map, 71, 503); -#endif - -#if 1 /* Abensberg */ - co->trans->center.x=1317000; - co->trans->center.y=6235000; - co->trans->scale=2*16; - graphics_redraw(co); - route_click(co->route, co, 196, 449); -#endif - -#if 1 /* Neckarsulm */ - co->trans->center.x=0xfa3ac; - co->trans->center.y=0x60289a; - co->trans->scale=2*16; - graphics_redraw(co); - route_click(co->route, co, 454, 274); - - co->trans->center.x=0x1251ac; - co->trans->center.y=0x5f5eda; - co->trans->scale=512*16; - graphics_redraw(co); -#endif - - -} - static void menu_window_clone(struct container *co) { @@ -240,20 +186,6 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) item=gtk_menu_item_new_with_label("Goto"); gtk_menu_bar_append(GTK_MENU_BAR(menu), item); { - menu2=gtk_menu_new(); - item2=gtk_menu_item_new_with_label("Abensberg"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_goto_abensberg), this); - - item2=gtk_menu_item_new_with_label("Regensburg"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_goto_regensburg), this); - item2=gtk_menu_item_new_with_label("Problem"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_goto_problem), this); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); diff --git a/street.c b/street.c index f449f1e1..52e9de30 100644 --- a/street.c +++ b/street.c @@ -66,11 +66,13 @@ street_draw_segment(struct container *co, struct segment *seg, unsigned char **p else label=name.name1; } +#if 0 if (str->nameid && name.townassoc < 0 ) { char buffer[128]; sprintf(buffer,"-0x%x", -name.townassoc); label=g_strdup(buffer); } +#endif limit=0; if (str->limit == 0x30) limit=1; -- cgit v1.2.1 From d98bac23e8073c4b647d27205389ffa12832620a Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 11 Dec 2005 12:33:08 +0000 Subject: Bugfixes git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@24 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.h | 1 + gui/gtk/gui_gtk_menu.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cursor.h b/cursor.h index 5a71ace2..eeb63069 100644 --- a/cursor.h +++ b/cursor.h @@ -1,5 +1,6 @@ struct cursor; struct container; +struct vehicle; struct coord * cursor_pos_get(struct cursor *this); struct cursor *cursor_new(struct container *co, struct vehicle *v); diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index 3de3c1cf..cba1babb 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -186,6 +186,7 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) item=gtk_menu_item_new_with_label("Goto"); gtk_menu_bar_append(GTK_MENU_BAR(menu), item); { + menu2=gtk_menu_new(); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); @@ -296,7 +297,7 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) GList *list; file=fopen("locations.txt","r"); - while (fgets(buffer,8192,file)) { + while (file && fgets(buffer,8192,file)) { dest=malloc(sizeof(*dest)); dest->co=co; len=strlen(buffer)-1; -- cgit v1.2.1 From 5ac825f5bbde3067d1ced565163fc5c21a006574 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 11 Dec 2005 13:41:26 +0000 Subject: Fixed some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@25 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.c | 15 +++--- data.h | 2 +- destination.c | 1 + graphics.h | 2 +- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 39 +++++++++++----- map_data.c | 13 +++--- plugin.c | 3 +- popup.c | 31 +++++++------ route.c | 54 +++++++--------------- route.h | 2 +- town.c | 25 +++++----- town.h | 6 ++- tree.c | 12 ++--- util.c | 5 +- util.h | 4 +- vehicle.c | 16 +++---- vehicle.h | 3 +- 17 files changed, 119 insertions(+), 114 deletions(-) diff --git a/cursor.c b/cursor.c index 1e63249d..9d3aaddb 100644 --- a/cursor.c +++ b/cursor.c @@ -13,6 +13,8 @@ #include "menu.h" #include "vehicle.h" #include "container.h" +#include "cursor.h" +#include "compass.h" #include "route.h" @@ -24,9 +26,8 @@ struct cursor { }; struct coord * -cursor_pos_get(void *t) +cursor_pos_get(struct cursor *this) { - struct cursor *this=t; return vehicle_pos_get(this->co->vehicle); } @@ -109,9 +110,6 @@ cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, static void cursor_map_reposition(struct cursor *this, struct coord *c, double *dir) { - unsigned long scale; - long x,y; - if (this->co->flags->orient_north) { graphics_set_view(this->co, &c->x, &c->y, NULL); } else { @@ -126,6 +124,7 @@ cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir struct transformation *t=this->co->trans; pnt_new.x=-1; + pnt_new.y=-1; if (pnt->x < 0.1*t->width) { pnt_new.x=0.8*t->width; pnt_new.y=t->height/2; @@ -153,9 +152,10 @@ cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir return 0; } -void -cursor_update(struct cursor *this) +static void +cursor_update(void *t) { + struct cursor *this=t; struct point pnt; struct coord *pos; struct vehicle *v=this->co->vehicle; @@ -177,7 +177,6 @@ cursor_update(struct cursor *this) transform(this->co->trans, pos, &pnt); cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v)); } -extern void compass_draw(); compass_draw(this->co->compass, this->co); } diff --git a/data.h b/data.h index 1f054333..075eaa6e 100644 --- a/data.h +++ b/data.h @@ -32,7 +32,7 @@ get_long(unsigned char **p) { static inline char * get_string(unsigned char **p) { - char *ret=*p; + char *ret=(char *)(*p); while (**p) (*p)++; (*p)++; return ret; diff --git a/destination.c b/destination.c index 2a9ccbf0..26207d73 100644 --- a/destination.c +++ b/destination.c @@ -1,3 +1,4 @@ +#include #include #include "coord.h" #include "transform.h" diff --git a/graphics.h b/graphics.h index 43d583dd..d7298749 100644 --- a/graphics.h +++ b/graphics.h @@ -34,7 +34,7 @@ struct graphics void (*draw_polygon)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); void (*draw_rectangle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h); void (*draw_circle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r); - void (*draw_text)(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, unsigned char *text, struct point *p, int dx, int dy); + void (*draw_text)(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy); void (*draw_image)(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img); void (*draw_restore)(struct graphics *gr, struct point *p, int w, int h); diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 81e6777a..5c38140b 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -43,21 +43,31 @@ struct graphics_image_gra { }; +char *fontlist[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", + NULL, +}; + static struct graphics_font *font_new(struct graphics *gr, int size) { - char *filename="/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf"; - char *filename2="/usr/share/fonts/truetype/msttcorefonts/arial.ttf"; + char **filename=fontlist; struct graphics_font *font=g_new(struct graphics_font, 1); if (!gr->gra->library_init) { FT_Init_FreeType( &gr->gra->library ); gr->gra->library_init=1; } - if (FT_New_Face( gr->gra->library, filename, 0, &font->face )) { - if (FT_New_Face( gr->gra->library, filename2, 0, &font->face )) { - g_warning("Failed to load '%s', no labelling", filename); - g_free(font); - return NULL; - } + + while (*filename) { + if (!FT_New_Face( gr->gra->library, *filename, 0, &font->face )) + break; + filename++; + } + if (! *filename) { + g_warning("Failed to load font, no labelling"); + g_free(font); + return NULL; } FT_Set_Char_Size(font->face, 0, size, 300, 300); return font; @@ -105,7 +115,7 @@ gc_set_background(struct graphics_gc *gc, int r, int g, int b) gc_set_color(gc, r, g, b, 0); } -struct graphics_image * +static struct graphics_image * image_new(struct graphics *gr, char *name) { GdkPixbuf *pixbuf; @@ -218,7 +228,7 @@ display_text_render_shadow(struct text_glyph *g) } static struct text_render * -display_text_render(unsigned char *text, struct graphics_font *font, int dx, int dy, int x, int y) +display_text_render(char *text, struct graphics_font *font, int dx, int dy, int x, int y) { FT_GlyphSlot slot = font->face->glyph; // a small shortcut FT_Matrix matrix; @@ -318,7 +328,7 @@ display_text_free(struct text_render *text) } static void -draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, unsigned char *text, struct point *p, int dx, int dy) +draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy) { struct text_render *t; @@ -356,6 +366,10 @@ overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int wind int x,y; int rowstride1,rowstride2; int n_channels1,n_channels2; + + if (! parent->drawable) + return; + pixbuf=gdk_pixbuf_get_from_drawable(NULL, overlay->drawable, NULL, 0, 0, 0, 0, overlay->width, overlay->height); pixbuf2=gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pixbuf), TRUE, gdk_pixbuf_get_bits_per_sample(pixbuf), gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); @@ -492,7 +506,8 @@ button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) int y=event->y; int button=event->button; int border=16; - long map_x,map_y,scale,x_new,y_new; + long map_x,map_y,x_new,y_new; + unsigned long scale; if (button == 3) popup(co, x, y, button); diff --git a/map_data.c b/map_data.c index cc384f03..1770bbd2 100644 --- a/map_data.c +++ b/map_data.c @@ -7,9 +7,9 @@ #include "map_data.h" #include "log.h" -static struct map_data *load_map(char *dirname) +static struct map_data *load_map(char *dirname, int submap) { - int i,len=strlen(dirname); + int i,len=strlen(dirname),maybe_missing; char *filename[file_end]; char file[len+16]; struct map_data *data=g_new0(struct map_data,1); @@ -37,7 +37,9 @@ static struct map_data *load_map(char *dirname) strcpy(file+len+1, filename[i]); data->file[i]=file_create_caseinsensitive(file); if (! data->file[i]) { - g_warning("Failed to load %s", file); + maybe_missing=(i == file_border_ply || i == file_height_ply || i == file_sea_ply); + if (! (submap && maybe_missing)) + g_warning("Failed to load %s", file); } } } @@ -49,14 +51,13 @@ struct map_data *load_maps(char *map) char *name; void *hnd; struct map_data *last,*ret; - int i; if (! map) map=getenv("MAP_DATA"); if (! map) map="/opt/reiseplaner/travel/DE.map"; - ret=load_map(map); + ret=load_map(map, 0); last=ret; hnd=file_opendir(map); if (hnd) { @@ -66,7 +67,7 @@ struct map_data *load_maps(char *map) strcpy(next_name, map); strcat(next_name, "/"); strcat(next_name, name); - last->next=load_map(next_name); + last->next=load_map(next_name, 1); last=last->next; } } diff --git a/plugin.c b/plugin.c index d5c182b5..1ad87e68 100644 --- a/plugin.c +++ b/plugin.c @@ -7,6 +7,7 @@ void plugin_load(void) { +#if 0 char *plugin="plugins/poi_geodownload/plugin_poi_geodownload.so"; void *h=dlopen(plugin,RTLD_LAZY); void (*init)(void); @@ -17,5 +18,5 @@ plugin_load(void) init=dlsym(h,"plugin_init"); (*init)(); } - +#endif } diff --git a/popup.c b/popup.c index f0fc5883..c61c5d34 100644 --- a/popup.c +++ b/popup.c @@ -4,7 +4,7 @@ #include #include #include "coord.h" -#include "param.h" +#include "file.h" #include "map_data.h" #include "block.h" #include "display.h" @@ -19,8 +19,9 @@ #include "cursor.h" #include "statusbar.h" #include "container.h" +#include "graphics.h" -void +static void popup_item_destroy_text(struct popup_item *item) { g_free(item->text); @@ -43,7 +44,7 @@ popup_item_new_text(struct popup_item **last, char *text, int priority) return curr; } -struct popup_item * +static struct popup_item * popup_item_new_func(struct popup_item **last, char *text, int priority, void (*func)(struct popup_item *, void *), void *param) { struct popup_item *curr=popup_item_new_text(last, text, priority); @@ -52,7 +53,7 @@ popup_item_new_func(struct popup_item **last, char *text, int priority, void (*f return curr; } -struct popup_item * +static struct popup_item * param_to_menu_new(char *name,struct param_list *plist, int c, int iso) { struct popup_item *last, *curr, *ret; @@ -79,7 +80,7 @@ param_to_menu_new(char *name,struct param_list *plist, int c, int iso) return ret; } -void +static void popup_set_no_passing(struct popup_item *item, void *param) { struct display_list *l=param; @@ -95,7 +96,7 @@ popup_set_no_passing(struct popup_item *item, void *param) log_write(log, seg->blk_inf.file, str, sizeof(*str)); } -void +static void popup_set_destination(struct popup_item *item, void *param) { struct popup_item *ref=param; @@ -111,7 +112,7 @@ popup_set_destination(struct popup_item *item, void *param) extern void *vehicle; -void +static void popup_set_position(struct popup_item *item, void *param) { struct popup_item *ref=param; @@ -120,7 +121,8 @@ popup_set_position(struct popup_item *item, void *param) vehicle_set_position(popup->co->vehicle, &popup->c); } -void +#if 0 +static void popup_break_crossing(struct display_list *l) { struct segment *seg=(struct segment *)(l->data); @@ -134,15 +136,16 @@ popup_break_crossing(struct display_list *l) str->limit=0x33; log_write(log, seg->blk_inf.file, str, sizeof(*str)); } +#endif -void +static void popup_call_func(GtkObject *obj, void *parm) { struct popup_item *curr=parm; curr->func(curr, curr->param); } -GtkWidget * +static GtkWidget * popup_menu(struct popup_item *list) { int min_prio,curr_prio; @@ -175,7 +178,7 @@ popup_menu(struct popup_item *list) return menu; } -void +static void popup_display_list_default(struct display_list *d, struct popup_item **popup_list) { struct segment *seg; @@ -224,7 +227,7 @@ popup_display_list_default(struct display_list *d, struct popup_item **popup_lis } } -void +static void popup_display_list(struct container *co, struct popup *popup, struct popup_item **popup_list) { GtkWidget *menu, *item; @@ -243,7 +246,7 @@ popup_display_list(struct container *co, struct popup *popup, struct popup_item } } -void +static void popup_destroy_items(struct popup_item *item) { struct popup_item *next; @@ -259,7 +262,7 @@ popup_destroy_items(struct popup_item *item) } } -void +static void popup_destroy(GtkObject *obj, void *parm) { struct popup *popup=parm; diff --git a/route.c b/route.c index 75de703a..966251ae 100644 --- a/route.c +++ b/route.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -124,7 +125,7 @@ route_new(void) return this; } -void +static void route_path_free(struct route *this) { struct route_path_segment *curr, *next; @@ -229,7 +230,7 @@ route_get_destination(struct route *this) return &this->dst->click.xy; } -void +static void route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data, void(*func)(struct block_info *, struct street_info *, unsigned char **, unsigned char *, void *)) { @@ -283,7 +284,7 @@ route_get_point(struct route *this, struct coord3d *c) } -struct route_point * +static struct route_point * route_point_add(struct route *this, struct coord3d *f, int conn) { int hashval; @@ -331,7 +332,7 @@ route_points_free(struct route *this) memset(this->hash, 0, sizeof(this->hash)); } -void +static void route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, int offset, int limit) { struct route_segment *s; @@ -353,7 +354,7 @@ route_segment_add(struct route *this, struct route_point *start, struct route_po } -void +static void route_segments_free(struct route *this) { struct route_segment *curr,*next; @@ -391,19 +392,19 @@ route_display_points(struct route *this, struct container *co) #endif } -int +static int route_time(int type, int len) { return len*36/speed_list[type & 0x3f]; } -int +static int route_value(int type, int len) { return route_time(type, len); } -int +static int route_get_height(int segid, struct coord *c) { if (c->x == 0x141b53 && c->y == 0x5f2065 && (segid == 0x4fad2fa || segid == 0x4fad155)) @@ -415,7 +416,7 @@ route_get_height(int segid, struct coord *c) return 0; } -void +static void route_process_street_graph(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) { struct route *this=data; @@ -625,7 +626,7 @@ struct block_list { struct block_list *next; }; -void +static void route_process_street_block_graph(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) { struct route *this=data; @@ -647,7 +648,7 @@ route_process_street_block_graph(struct block_info *blk_inf, unsigned char *p, u #endif } -void +static void route_blocklist_free(struct route *this) { struct block_list *curr,*next; @@ -659,7 +660,7 @@ route_blocklist_free(struct route *this) } } -void +static void route_build_graph(struct route *this, struct map_data *mdata, struct coord *c, int coord_count) { struct coord rect[2]; @@ -718,7 +719,7 @@ route_build_graph(struct route *this, struct map_data *mdata, struct coord *c, i } } -void +static void route_process_street3(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) { int flags=0; @@ -791,7 +792,7 @@ route_process_street3(struct block_info *blk_inf, struct street_info *str_inf, u } -void +static void route_process_street_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) { route_street_foreach(blk_inf, p, end, data, route_process_street3); @@ -846,29 +847,6 @@ route_find_point_on_street(struct route_info *rt_inf) struct route_info *start,*end; int count; -/* XPM */ -static char * flag_xpm[] = { -"16 16 3 1", -" c None", -"+ c #000000", -"@ c #FFFF00", -"+++ ", -"+@@++ ", -"+@@@@+++ ", -"+@@@@@@@++ ", -"+@@@@@@@@@++ ", -"+@@@@@@@@@@@++ ", -"+@@@@@@@@@++ ", -"+@@@@@@@++ ", -"+@@@@+++ ", -"+@@++ ", -"+++ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ "}; - void route_click(struct route *this, struct container *co, int x, int y) { @@ -948,7 +926,7 @@ route_trace(struct container *co) trace=1-trace; } -void +static void route_data_free(void *t) { route_blocklist_free(t); diff --git a/route.h b/route.h index 0b249129..7149cff4 100644 --- a/route.h +++ b/route.h @@ -24,7 +24,7 @@ struct container; struct route_info; struct route *route_new(void); -int route_destroy(); +int route_destroy(void *t); void route_mapdata_set(struct route *this, struct map_data *mdata); struct map_data* route_mapdata_get(struct route *this); void route_display_points(struct route *this, struct container *co); diff --git a/town.c b/town.c index 2d08427b..c619ef5f 100644 --- a/town.c +++ b/town.c @@ -14,7 +14,7 @@ #include "container.h" #include "util.h" -void +static void town_get(struct town *town, unsigned char **p) { town->id=get_long(p); @@ -81,7 +81,8 @@ town_tree_process(int version, int leaf, unsigned char **s2, struct map_data *md struct file *f=mdat->file[file_town_twn]; struct block_offset *blk_off; struct town town; - unsigned char *p,*name; + unsigned char *p; + char *name; int ret,i,debug=0; country=get_short(s2); @@ -133,7 +134,7 @@ town_tree_process(int version, int leaf, unsigned char **s2, struct map_data *md return 0; } -int +static int town_search_by(struct map_data *mdat, char *ext, int country, const char *search, int partial, int (*func)(struct town *, void *data), void *data) { struct town_search_priv priv_data; @@ -151,9 +152,9 @@ town_search_by(struct map_data *mdat, char *ext, int country, const char *search } int -town_search_by_postal_code(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +town_search_by_postal_code(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) { - unsigned char uname[strlen(name)+1]; + char uname[strlen(name)+1]; strtoupper(uname, name); return town_search_by(mdat, "b1", country, uname, partial, func, data); @@ -163,34 +164,34 @@ town_search_by_postal_code(struct map_data *mdat, int country, unsigned char *na int town_search_by_name(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) { - unsigned char uname[strlen(name)+1]; + char uname[strlen(name)+1]; strtolower(uname, (char *)name); return town_search_by(mdat, "b2", country, uname, partial, func, data); } int -town_search_by_district(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +town_search_by_district(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) { - unsigned char uname[strlen(name)+1]; + char uname[strlen(name)+1]; strtoupper(uname, name); return town_search_by(mdat, "b3", country, uname, partial, func, data); } int -town_search_by_name_phon(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +town_search_by_name_phon(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) { - unsigned char uname[strlen(name)+1]; + char uname[strlen(name)+1]; strtoupper(uname, name); return town_search_by(mdat, "b4", country, uname, partial, func, data); } int -town_search_by_district_phon(struct map_data *mdat, int country, unsigned char *name, int partial, int (*func)(struct town *, void *data), void *data) +town_search_by_district_phon(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data) { - unsigned char uname[strlen(name)+1]; + char uname[strlen(name)+1]; strtoupper(uname, name); return town_search_by(mdat, "b5", country, uname, partial, func, data); diff --git a/town.h b/town.h index fce4b6b5..fd48b5e3 100644 --- a/town.h +++ b/town.h @@ -23,5 +23,9 @@ struct map_data; void town_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); int town_get_param(struct segment *seg, struct param_list *param, int count); -int town_search_by_name(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *t, void *data), void *data); +int town_search_by_postal_code(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data); +int town_search_by_name(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data); +int town_search_by_district(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data); +int town_search_by_name_phon(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data); +int town_search_by_district_phon(struct map_data *mdat, int country, const char *name, int partial, int (*func)(struct town *, void *data), void *data); void town_get_by_id(struct town *town, struct map_data *mdat, int country, int id); diff --git a/tree.c b/tree.c index 9aacfacc..6e55b7f2 100644 --- a/tree.c +++ b/tree.c @@ -39,7 +39,7 @@ tree_compare_string(unsigned char *s1, unsigned char **s2_ptr) { unsigned char *s2=*s2_ptr; char s1_exp, s2_exp; - *s2_ptr+=strlen(s2)+1; + *s2_ptr+=strlen((char *)s2)+1; for (;;) { s1_exp=*s1++; s2_exp=*s2++; @@ -63,7 +63,7 @@ tree_compare_string_partial(unsigned char *s1, unsigned char **s2_ptr) { unsigned char *s2=*s2_ptr; char s1_exp, s2_exp; - *s2_ptr+=strlen(s2)+1; + *s2_ptr+=strlen((char *)s2)+1; for (;;) { s1_exp=*s1++; s2_exp=*s2++; @@ -85,7 +85,7 @@ tree_compare_string_partial(unsigned char *s1, unsigned char **s2_ptr) } -int +static int tree_search_h(struct file *file, unsigned int search) { unsigned char *p=file->begin,*end; @@ -126,7 +126,7 @@ tree_search_h(struct file *file, unsigned int search) return 0; } -int +static int tree_search_v(struct file *file, int offset, int search) { unsigned char *p=file->begin+offset; @@ -159,7 +159,7 @@ tree_search_v(struct file *file, int offset, int search) /* 1=Abort */ /* 2=Too high */ -int +static int tree_search(int version, struct file *file, unsigned char *p, int (*tree_func)(int version, int leaf, unsigned char **, struct map_data *mdat, void *), struct map_data *mdat, void *data, int higher) { unsigned char *end,*psav; @@ -260,7 +260,7 @@ tree_search_map(struct map_data *mdat, int map, char *ext, f_idx=file_create(filename); version=1; p=f_idx->begin; - if (!strncmp(p+4,"RootBlock",9)) { + if (!strncmp((char *)(p+4),"RootBlock",9)) { p+=0x1000; version=2; } diff --git a/util.c b/util.c index b99dfcbd..7f77ca28 100644 --- a/util.c +++ b/util.c @@ -1,7 +1,8 @@ #include +#include "util.h" void -strtoupper(unsigned char *dest, unsigned char *src) +strtoupper(char *dest, const char *src) { while (*src) *dest++=toupper(*src++); @@ -9,7 +10,7 @@ strtoupper(unsigned char *dest, unsigned char *src) } void -strtolower(unsigned char *dest, unsigned char *src) +strtolower(char *dest, const char *src) { while (*src) *dest++=tolower(*src++); diff --git a/util.h b/util.h index 5f89adb9..7a2da623 100644 --- a/util.h +++ b/util.h @@ -1,4 +1,4 @@ #include -void strtoupper(unsigned char *dest, unsigned char *src); -void strtolower(unsigned char *dest, unsigned char *src); +void strtoupper(char *dest, const char *src); +void strtolower(char *dest, const char *src); diff --git a/vehicle.c b/vehicle.c index 62507179..1cc494fa 100644 --- a/vehicle.c +++ b/vehicle.c @@ -30,13 +30,14 @@ struct vehicle { #ifdef HAVE_LIBGPS struct gps_data_t *gps; #endif - void (*callback_func)(); + void (*callback_func)(void *data); void *callback_data; }; struct vehicle *vehicle_last; -int +#if 0 +static int vehicle_timer(gpointer t) { struct vehicle *this=t; @@ -50,6 +51,7 @@ vehicle_timer(gpointer t) } return TRUE; } +#endif struct coord * vehicle_pos_get(struct vehicle *this) @@ -81,7 +83,7 @@ vehicle_set_position(struct vehicle *this, struct coord *pos) (*this->callback_func)(this->callback_data); } -void +static void vehicle_parse_gps(struct vehicle *this, char *buffer) { char *p,*item[16]; @@ -233,7 +235,7 @@ vehicle_new(const char *url) { struct vehicle *this; GError *error=NULL; - int fd; + int fd=-1; char *url_,*colon; #ifdef HAVE_LIBGPS struct gps_data_t *gps=NULL; @@ -284,13 +286,13 @@ vehicle_new(const char *url) } void -vehicle_callback(struct vehicle *this, void (*func)(), void *data) +vehicle_callback(struct vehicle *this, void (*func)(void *data), void *data) { this->callback_func=func; this->callback_data=data; } -int +void vehicle_destroy(struct vehicle *this) { GError *error=NULL; @@ -302,6 +304,4 @@ vehicle_destroy(struct vehicle *this) gps_close(this->gps); #endif g_free(this); - - return 0; } diff --git a/vehicle.h b/vehicle.h index 8787e38e..98f18ec2 100644 --- a/vehicle.h +++ b/vehicle.h @@ -3,6 +3,7 @@ struct vehicle; struct coord *vehicle_pos_get(struct vehicle *); double *vehicle_dir_get(struct vehicle *); double *vehicle_speed_get(struct vehicle *); -void vehicle_callback(struct vehicle *, void (*func)(),void *data); +void vehicle_callback(struct vehicle *, void (*func)(void *data),void *data); void vehicle_set_position(struct vehicle *, struct coord *); struct vehicle *vehicle_new(const char *url); +void vehicle_destroy(struct vehicle *); -- cgit v1.2.1 From 8449323550c72780e586d78c4249ca6f927f1fc3 Mon Sep 17 00:00:00 2001 From: horwitz Date: Mon, 12 Dec 2005 21:11:03 +0000 Subject: Fixed some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@26 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics.c | 1 + graphics.h | 2 ++ gui/gtk/gui_gtk_menu.c | 2 +- navigation.c | 38 +++++++++++++++++++++++--------------- navigation.h | 1 + profile.c | 2 ++ profile.h | 1 + 7 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 profile.h diff --git a/graphics.c b/graphics.c index 8787e05e..bae4ce23 100644 --- a/graphics.c +++ b/graphics.c @@ -11,6 +11,7 @@ #include "street.h" #include "transform.h" #include "container.h" +#include "profile.h" #define GC_BACKGROUND 0 diff --git a/graphics.h b/graphics.h index d7298749..a73f1e1e 100644 --- a/graphics.h +++ b/graphics.h @@ -14,6 +14,8 @@ struct graphics_image { struct graphics_image_gra *gra; }; +void container_init_gra(struct container *co); + void graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale); void graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale); void graphics_resize(struct container *co, int w, int h); diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index cba1babb..088fe9d0 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -49,7 +49,7 @@ menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, GtkWidget *win) { GtkWidget *text; - unsigned const char *t; + const char *t; struct container *co; if (! strcmp(event->string,"\r")) { diff --git a/navigation.c b/navigation.c index feb9e385..b56e7f5b 100644 --- a/navigation.c +++ b/navigation.c @@ -1,6 +1,9 @@ #include +#include #include +#include #include "coord.h" +#include "graphics.h" #include "param.h" #include "block.h" #include "route.h" @@ -12,6 +15,26 @@ struct data_window *navigation_window; + +struct navigation_item { + char name1[128]; + char name2[128]; + int length; + int time; + int crossings_start; + int crossings_end; + int angle_start; + int angle_end; + int points; + struct coord start; + struct coord end; +}; + +void navigation_goto(struct data_window *navigation_window, char **cols); +int is_same_street(struct navigation_item *old, struct navigation_item *new); +int maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta); +void make_maneuver(struct navigation_item *old, struct navigation_item *new); + static int road_angle(struct coord *c, int dir) { @@ -37,25 +60,10 @@ expand_str(char *str) strcpy(str+len-4,"Strasse"); } -struct navigation_item { - char name1[128]; - char name2[128]; - int length; - int time; - int crossings_start; - int crossings_end; - int angle_start; - int angle_end; - int points; - struct coord start; - struct coord end; -}; - void navigation_goto(struct data_window *navigation_window, char **cols) { extern struct container *co; - unsigned long scale; long x,y; printf("goto %s\n",cols[8]); diff --git a/navigation.h b/navigation.h index ae39528f..c8c1c399 100644 --- a/navigation.h +++ b/navigation.h @@ -1 +1,2 @@ void navigation_path_description(void *route); + diff --git a/profile.c b/profile.c index 35a41447..149c4ba5 100644 --- a/profile.c +++ b/profile.c @@ -1,5 +1,7 @@ +#include #include #include +#include "profile.h" void profile_timer(char *where) diff --git a/profile.h b/profile.h new file mode 100644 index 00000000..50280354 --- /dev/null +++ b/profile.h @@ -0,0 +1 @@ +void profile_timer(char *where); -- cgit v1.2.1 From c0277d2053a4a0ac0d45ebb1e153bbcddac1b8fb Mon Sep 17 00:00:00 2001 From: horwitz Date: Mon, 12 Dec 2005 21:36:33 +0000 Subject: Fixed some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@27 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics.c | 7 +++++++ poly.c | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/graphics.c b/graphics.c index bae4ce23..f85c2df1 100644 --- a/graphics.c +++ b/graphics.c @@ -11,6 +11,9 @@ #include "street.h" #include "transform.h" #include "container.h" +#include "plugin.h" +#include "display.h" +#include "data_window.h" #include "profile.h" @@ -68,6 +71,10 @@ int color[][3]={ {0x0000, 0x0000, 0xa0a0}, }; +void graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, + void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)); + + void container_init_gra(struct container *co) { diff --git a/poly.c b/poly.c index 954e7fb2..19f73bd1 100644 --- a/poly.c +++ b/poly.c @@ -12,6 +12,10 @@ extern struct data_window poly_window; + +void poly_draw_segment(struct container *co, struct segment *seg, int disp, unsigned char **p, int limit); +int poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr); + int poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) { -- cgit v1.2.1 From fc8aa5c0da2c0b0263ea438535ce96da1c1c2a6b Mon Sep 17 00:00:00 2001 From: horwitz Date: Mon, 12 Dec 2005 21:51:45 +0000 Subject: Don't add prototypes, but make local funtions static git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@28 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- command.c | 4 +++- graphics.c | 5 +---- navigation.c | 13 ++++--------- poly.c | 7 ++----- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/command.c b/command.c index 88d26a36..99b03fcd 100644 --- a/command.c +++ b/command.c @@ -3,6 +3,7 @@ #include "coord.h" #include "town.h" #include "street.h" +#include "command.h" /* Phonetisch "KLEIN " -> CL @@ -31,7 +32,7 @@ struct tree_leaf { unsigned char text[0]; }; -int +static int compare(char *s1, char *s2) { char s1_exp, s2_exp; @@ -96,6 +97,7 @@ compare(char *s1, char *s2) } #endif } + void command_goto(struct container *co, const char *arg) { diff --git a/graphics.c b/graphics.c index f85c2df1..a989156b 100644 --- a/graphics.c +++ b/graphics.c @@ -71,9 +71,6 @@ int color[][3]={ {0x0000, 0x0000, 0xa0a0}, }; -void graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, - void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)); - void container_init_gra(struct container *co) @@ -113,7 +110,7 @@ graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale) graphics_redraw(co); } -void +static void graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) { diff --git a/navigation.c b/navigation.c index b56e7f5b..b69202b3 100644 --- a/navigation.c +++ b/navigation.c @@ -30,11 +30,6 @@ struct navigation_item { struct coord end; }; -void navigation_goto(struct data_window *navigation_window, char **cols); -int is_same_street(struct navigation_item *old, struct navigation_item *new); -int maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta); -void make_maneuver(struct navigation_item *old, struct navigation_item *new); - static int road_angle(struct coord *c, int dir) { @@ -60,7 +55,7 @@ expand_str(char *str) strcpy(str+len-4,"Strasse"); } -void +static void navigation_goto(struct data_window *navigation_window, char **cols) { extern struct container *co; @@ -71,7 +66,7 @@ navigation_goto(struct data_window *navigation_window, char **cols) graphics_set_view(co, &x, &y, NULL); } -int +static int is_same_street(struct navigation_item *old, struct navigation_item *new) { if (strlen(old->name2) && !strcmp(old->name2, new->name2)) { @@ -85,7 +80,7 @@ is_same_street(struct navigation_item *old, struct navigation_item *new) return 0; } -int +static int maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta) { if (is_same_street(old, new)) @@ -105,7 +100,7 @@ maneuver_required(struct navigation_item *old, struct navigation_item *new, int int flag; extern void *speech_handle; -void +static void make_maneuver(struct navigation_item *old, struct navigation_item *new) { diff --git a/poly.c b/poly.c index 19f73bd1..dd639d0f 100644 --- a/poly.c +++ b/poly.c @@ -13,10 +13,7 @@ extern struct data_window poly_window; -void poly_draw_segment(struct container *co, struct segment *seg, int disp, unsigned char **p, int limit); -int poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr); - -int +static int poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) { poly_hdr->addr=*p; @@ -35,7 +32,7 @@ poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) return 0; } -void +static void poly_draw_segment(struct container *co, struct segment *seg, int disp, unsigned char **p, int limit) { struct poly_hdr poly_hdr; -- cgit v1.2.1 From b8f972ada204e50fc6d6d6c36b9d152b4c9f58c7 Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 12 Dec 2005 21:54:56 +0000 Subject: Fix a compiler warning git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@29 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- poly.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poly.c b/poly.c index dd639d0f..e39ecc5b 100644 --- a/poly.c +++ b/poly.c @@ -19,7 +19,7 @@ poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) poly_hdr->addr=*p; poly_hdr->c=(struct coord *) (*p); *p+=3*sizeof(struct coord); - poly_hdr->name=*p; + poly_hdr->name=(char *)(*p); while (**p) { (*p)++; } -- cgit v1.2.1 From c5647a772a440337b0d486f4565554b2bb3b433f Mon Sep 17 00:00:00 2001 From: horwitz Date: Mon, 12 Dec 2005 23:22:36 +0000 Subject: Fixed some warnings and drop tst.c git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@30 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 6 +-- command.c | 2 + compass.c | 2 + destination.c | 43 +++++++++++----------- display.c | 5 ++- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 3 ++ gui/gtk/gtkeyboard.c | 3 ++ gui/gtk/gui_gtk.h | 1 + gui/gtk/gui_gtk_menu.c | 5 ++- gui/gtk/gui_gtk_statusbar.c | 8 ++-- gui/gtk/gui_gtk_toolbar.c | 4 +- gui/gtk/gui_gtk_window.c | 2 +- main.c | 8 ++-- map-srv.c | 18 +++++---- menu.c | 1 + phrase.c | 1 + search.c | 2 +- street.c | 2 +- street_name.c | 2 +- tst.c | 15 -------- 20 files changed, 71 insertions(+), 62 deletions(-) delete mode 100644 tst.c diff --git a/block.c b/block.c index c48ea3ff..8059df7e 100644 --- a/block.c +++ b/block.c @@ -50,7 +50,7 @@ block_get_byindex(struct file *file, int idx, unsigned char **p_ret) return block_get(p_ret); } -int +static int block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, int ign, struct block_info *blk_inf, struct transformation *t, void *data, void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) { @@ -108,7 +108,7 @@ block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, return ret; } -void +static void block_file_private_setup(struct file *file) { int len; @@ -131,7 +131,7 @@ block_file_private_setup(struct file *file) } } -void +static void block_foreach_visible_linear(struct block_info *blk_inf, struct transformation *t, void *data, void(*func)(struct block_info *blk_inf, unsigned char *, unsigned char *, void *)) { diff --git a/command.c b/command.c index 99b03fcd..ba463168 100644 --- a/command.c +++ b/command.c @@ -32,6 +32,7 @@ struct tree_leaf { unsigned char text[0]; }; +#if 0 static int compare(char *s1, char *s2) { @@ -97,6 +98,7 @@ compare(char *s1, char *s2) } #endif } +#endif void command_goto(struct container *co, const char *arg) diff --git a/compass.c b/compass.c index e0c5b2c0..3d9b2544 100644 --- a/compass.c +++ b/compass.c @@ -8,6 +8,8 @@ #include "route.h" #include "vehicle.h" #include "container.h" +#include "compass.h" +#include "compass.h" struct compass { struct graphics *gr; diff --git a/destination.c b/destination.c index 26207d73..c25fa2cd 100644 --- a/destination.c +++ b/destination.c @@ -1,3 +1,4 @@ +#include #include #include #include "coord.h" @@ -16,6 +17,7 @@ #include "destination.h" #include "coord.h" #include "container.h" +#include "graphics.h" extern gint track_focus(gpointer data); @@ -87,7 +89,7 @@ destination_set(struct container *co, enum destination_type type, char *text, st return 0; } -int +static int get_position(struct search_param *search, struct coord *c) { struct destination *dest; @@ -101,9 +103,8 @@ get_position(struct search_param *search, struct coord *c) return 0; } -void button_map(GtkWidget *widget, struct container *co) +static void button_map(GtkWidget *widget, struct container *co) { - unsigned long scale; struct coord c; if (!get_position(&search_param2, &c)) { @@ -111,7 +112,7 @@ void button_map(GtkWidget *widget, struct container *co) } } -void button_destination(GtkWidget *widget, struct container *co) +static void button_destination(GtkWidget *widget, struct container *co) { struct coord c; @@ -130,7 +131,7 @@ struct dest_town { struct town town; }; -guint +static guint destination_town_hash(gconstpointer key) { const struct dest_town *hash=key; @@ -138,7 +139,7 @@ destination_town_hash(gconstpointer key) return g_direct_hash(hashkey); } -gboolean +static gboolean destination_town_equal(gconstpointer a, gconstpointer b) { const struct dest_town *t_a=a; @@ -151,13 +152,13 @@ destination_town_equal(gconstpointer a, gconstpointer b) return FALSE; } -GHashTable * +static GHashTable * destination_town_new(void) { return g_hash_table_new_full(destination_town_hash, destination_town_equal, NULL, g_free); } -void +static void destination_town_set(const struct dest_town *town, char **rows, int full) { char country[32]; @@ -181,7 +182,7 @@ destination_town_set(const struct dest_town *town, char **rows, int full) } } -void +static void destination_town_show(gpointer key, gpointer value, gpointer user_data) { struct dest_town *town=value; @@ -202,13 +203,13 @@ destination_town_show(gpointer key, gpointer value, gpointer user_data) } } -GHashTable * +static GHashTable * destination_country_new(void) { return g_hash_table_new_full(NULL, NULL, NULL, g_free); } -int +static int destination_country_add(struct country *cou, void *data) { struct search_param *search=data; @@ -224,7 +225,7 @@ destination_country_add(struct country *cou, void *data) return 0; } -void +static void destination_country_show(gpointer key, gpointer value, gpointer user_data) { struct country *cou=value; @@ -240,7 +241,7 @@ destination_country_show(gpointer key, gpointer value, gpointer user_data) } } -int +static int destination_town_add(struct town *town, void *data) { struct search_param *search=data; @@ -292,7 +293,7 @@ destination_town_add(struct town *town, void *data) return 0; } -void +static void destination_town_search(gpointer key, gpointer value, gpointer user_data) { struct country *cou=value; @@ -301,14 +302,14 @@ destination_town_search(gpointer key, gpointer value, gpointer user_data) } -GHashTable * +static GHashTable * destination_street_new(void) { return g_hash_table_new_full(NULL, NULL, NULL, g_free); } -int +static int destination_street_add(struct street_name *name, void *data) { struct search_param *search=data; @@ -354,7 +355,7 @@ check_number(int low, int high, int s_low, int s_high) return 0; } -void +static void destination_street_show_common(gpointer key, gpointer value, gpointer user_data, int number) { struct street_name *name=value; @@ -417,19 +418,19 @@ destination_street_show_common(gpointer key, gpointer value, gpointer user_data, } } -void +static void destination_street_show(gpointer key, gpointer value, gpointer user_data) { destination_street_show_common(key, value, user_data, 0); } -void +static void destination_street_show_number(gpointer key, gpointer value, gpointer user_data) { destination_street_show_common(key, value, user_data, 1); } -void +static void destination_street_search(gpointer key, gpointer value, gpointer user_data) { const struct dest_town *town=value; @@ -439,7 +440,7 @@ destination_street_search(gpointer key, gpointer value, gpointer user_data) -void changed(GtkWidget *widget, struct search_param *search) +static void changed(GtkWidget *widget, struct search_param *search) { const char *str; char *empty[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; diff --git a/display.c b/display.c index ca1874ae..bd534f6c 100644 --- a/display.c +++ b/display.c @@ -1,11 +1,14 @@ +#include +#include #include #include +#include #include "display.h" #include "graphics.h" struct graphics_image *icons; -struct graphics_image * +static struct graphics_image * get_icon(struct graphics *gr, char *name) { struct graphics_image *curr=icons; diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 5c38140b..30987fac 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -50,6 +50,9 @@ char *fontlist[]={ NULL, }; + +struct graphics * graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); + static struct graphics_font *font_new(struct graphics *gr, int size) { char **filename=fontlist; diff --git a/gui/gtk/gtkeyboard.c b/gui/gtk/gtkeyboard.c index 1963c839..ca530042 100644 --- a/gui/gtk/gtkeyboard.c +++ b/gui/gtk/gtkeyboard.c @@ -90,6 +90,7 @@ static ModmapTable *ModmapTable_new(void); static void ModmapTable_destroy(ModmapTable * table); static int ModmapTable_insert(ModmapTable * table, KeyCode code, int slot); static int mask_name_to_slot_number(char *maskname); +GtkWidget *build_keyboard(GtkWidget * input, char *filename); /* templates.h @@ -151,6 +152,7 @@ static KEY *gtkeyboard_destroy_key(KEY * input); static KEY *gtkeyboard_new_key(const KeySym lower, const KeySym upper, const KeySym altgr, const char *alt); +gint track_focus(gpointer data); @@ -448,6 +450,7 @@ static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev); /* PROTOTYPES - Most functions in build_keyboard.c are static and don't need * prototypes here. */ +int init_keyboard_stuff(char *input); static void keysym_callback(GtkWidget * emitter, gpointer data); static void capslock_toggle(GtkWidget * w, gpointer data); static void alt_toggle(GtkWidget * w, gpointer data); diff --git a/gui/gtk/gui_gtk.h b/gui/gtk/gui_gtk.h index f231c2fd..a2f3cf9a 100644 --- a/gui/gtk/gui_gtk.h +++ b/gui/gtk/gui_gtk.h @@ -2,3 +2,4 @@ struct statusbar *gui_gtk_statusbar_new(GtkWidget **widget); struct toolbar *gui_gtk_toolbar_new(struct container *co, GtkWidget **widget); struct menu *gui_gtk_menu_new(struct container *co, GtkWidget **widget); +struct container * gui_gtk_window(int x, int y, int scale); diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index 088fe9d0..beef7e56 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -18,6 +18,7 @@ #include "destination.h" #include "main.h" #include "container.h" +#include "gui_gtk.h" struct menu_gui { struct container *co; @@ -44,7 +45,7 @@ menu_window_clone(struct container *co) #endif } -gboolean +static gboolean menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, GtkWidget *win) { @@ -157,7 +158,7 @@ menu_item(struct menu *me, GtkWidget *menu, char *name, void (*func)(struct cont GTK_SIGNAL_FUNC (func), me); } -int +static int menu_clock_update(void *data) { char buffer[16]; diff --git a/gui/gtk/gui_gtk_statusbar.c b/gui/gtk/gui_gtk_statusbar.c index fa4edfa7..10950298 100644 --- a/gui/gtk/gui_gtk_statusbar.c +++ b/gui/gtk/gui_gtk_statusbar.c @@ -21,14 +21,14 @@ struct statusbar_gui { }; -void +static void statusbar_destroy(struct statusbar *this) { g_free(this->gui); g_free(this); } -void +static void statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct point *p) { struct coord c; @@ -42,7 +42,7 @@ statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct gtk_label_set_text(GTK_LABEL(this->gui->mouse), this->gui->mouse_text); } -void +static void statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) { char lat_c='N'; @@ -69,7 +69,7 @@ statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, dou } -void +static void statusbar_route_update(struct statusbar *this, struct route *route) { struct tm *eta_tm; diff --git a/gui/gtk/gui_gtk_toolbar.c b/gui/gtk/gui_gtk_toolbar.c index 420c93ba..cd32c10d 100644 --- a/gui/gtk/gui_gtk_toolbar.c +++ b/gui/gtk/gui_gtk_toolbar.c @@ -298,7 +298,7 @@ toolbar_button_leave (GtkButton *button, gpointer status) int tst_stat=1; -void +static void toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data) { GtkWidget *icon; @@ -306,7 +306,7 @@ toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *te gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, text, NULL, icon, GTK_SIGNAL_FUNC(func), data); } -void +static void toolbar_button_toggle(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data, int *flag) { GtkWidget *icon,*item; diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index 40ddddb1..fb62280f 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -8,7 +8,7 @@ extern void container_init_gra(struct container *co); -struct container * +static struct container * container_new(GtkWidget **widget) { struct container *co=g_new0(struct container, 1); diff --git a/main.c b/main.c index dd21dc89..e5eea70c 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include "coord.h" #include "vehicle.h" #include "cursor.h" @@ -30,12 +32,12 @@ extern void test(struct map_data *mdat); int main(int argc, char **argv) { +#if 0 CORBA_Environment ev; CORBA_ORB orb; - Map map_client = CORBA_OBJECT_NIL; - char *retval; + Map map_client = CORBA_OBJECT_NIL; +#endif char *gps; - FILE *ior; setenv("LC_NUMERIC","C",1); setlocale(LC_ALL,""); diff --git a/map-srv.c b/map-srv.c index 6d38db03..f46ca88d 100644 --- a/map-srv.c +++ b/map-srv.c @@ -78,7 +78,7 @@ PortableServer_ServantBase__epv base_epv = { NULL }; -PointObj +static PointObj do_PointFromCoord(PortableServer_Servant _servant, const CORBA_char * coord, CORBA_Environment * ev) { PointObj ret; @@ -106,6 +106,7 @@ do_PointFromCoord(PortableServer_Servant _servant, const CORBA_char * coord, COR return ret; } +#if 0 static void PointObj_to_coor(const PointObj *pnt, struct coord *c) { @@ -114,13 +115,14 @@ PointObj_to_coor(const PointObj *pnt, struct coord *c) lat=pnt->lat; transform_mercator(&lng, &lat, c); } +#endif -void +static void do_View(PortableServer_Servant _servant, const PointObj *pnt, CORBA_Environment * ev) { +#if 0 unsigned long scale; struct coord c; -#if 0 GtkMap *map=global_map; map_get_view(map, NULL, NULL, &scale); @@ -130,7 +132,7 @@ do_View(PortableServer_Servant _servant, const PointObj *pnt, CORBA_Environment } -void +static void do_Route(PortableServer_Servant _servant, const PointObj *src, const PointObj *dst, CORBA_Environment * ev) { #if 0 @@ -154,7 +156,7 @@ do_Route(PortableServer_Servant _servant, const PointObj *src, const PointObj *d POA_Mappel__epv mappel_epv = { }; -Mappel do_Get(PortableServer_Servant _servant, CORBA_Environment * ev) +static Mappel do_Get(PortableServer_Servant _servant, CORBA_Environment * ev) { Mappel retval=NULL; #if 0 @@ -227,7 +229,8 @@ CORBA_Object map_srv_start_object(CORBA_Environment * ev, struct container *co) return the_map_client; } -void map_srv_finish_object(CORBA_Environment * ev) +#if 0 +static void map_srv_finish_object(CORBA_Environment * ev) { CORBA_Object_release(the_map_client, ev); if (ev->_major) { @@ -250,7 +253,7 @@ void map_srv_finish_object(CORBA_Environment * ev) } -void map_srv_finish_poa(CORBA_Environment * ev) +static void map_srv_finish_poa(CORBA_Environment * ev) { CORBA_Object_release((CORBA_Object) the_poa, ev); if (ev->_major) { @@ -259,4 +262,5 @@ void map_srv_finish_poa(CORBA_Environment * ev) } the_poa = 0; } +#endif diff --git a/menu.c b/menu.c index e694f82a..5430b007 100644 --- a/menu.c +++ b/menu.c @@ -15,6 +15,7 @@ #include "destination.h" #include "main.h" #include "container.h" +#include "graphics.h" void menu_route_do_update(struct container *co) diff --git a/phrase.c b/phrase.c index 92f6e7c3..f1f18af7 100644 --- a/phrase.c +++ b/phrase.c @@ -2,6 +2,7 @@ #include "coord.h" #include "route.h" #include "speech.h" +#include "phrase.h" void phrase_route_calc(void *speech) diff --git a/search.c b/search.c index 165282ce..0d2f17be 100644 --- a/search.c +++ b/search.c @@ -210,7 +210,7 @@ search_town_show(gpointer key, gpointer value, gpointer user_data) } -GHashTable * +static GHashTable * search_street_new(void) { return g_hash_table_new_full(NULL, NULL, NULL, g_free); diff --git a/street.c b/street.c index 52e9de30..4634cca0 100644 --- a/street.c +++ b/street.c @@ -95,7 +95,7 @@ street_draw_segment(struct container *co, struct segment *seg, unsigned char **p *pos-=2*bytes; } -void +static void street_safety_check(struct street_str *str) { #if 0 diff --git a/street_name.c b/street_name.c index 202c8ae5..23fc3fb0 100644 --- a/street_name.c +++ b/street_name.c @@ -52,7 +52,7 @@ struct street_search_priv { int last_res; }; -int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) +static int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) { char c1_u,c2_u; int ret=0; diff --git a/tst.c b/tst.c deleted file mode 100644 index 16cd8834..00000000 --- a/tst.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -int tst(void) -{ - unsigned short t1=20; - unsigned short t2=10; - return t2-t1; -} - -int main(int argc, char **argv) -{ - printf("res=%d\n", tst()); -} -- cgit v1.2.1 From 37b1a4362f3d849b4033212eeae4c5e86d74f786 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 13 Dec 2005 18:39:44 +0000 Subject: Fix more warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@32 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 3 ++- gui/gtk/gtkeyboard.c | 2 +- log.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index 8059df7e..f9ee2e95 100644 --- a/block.c +++ b/block.c @@ -112,7 +112,8 @@ static void block_file_private_setup(struct file *file) { int len; - unsigned char *p,*str,*t; + unsigned char *p,*t; + char *str; struct file_private *file_priv; file_priv=malloc(sizeof(*file_priv)); diff --git a/gui/gtk/gtkeyboard.c b/gui/gtk/gtkeyboard.c index ca530042..02b9c937 100644 --- a/gui/gtk/gtkeyboard.c +++ b/gui/gtk/gtkeyboard.c @@ -1347,7 +1347,7 @@ static int file_exists(const char *filename) * returns: a timestamp for the * constructed event */ -static Time fake_timestamp() +static Time fake_timestamp(void) { int tint; struct timeval tv; diff --git a/log.c b/log.c index c6995361..59c1fc3d 100644 --- a/log.c +++ b/log.c @@ -11,7 +11,8 @@ void log_write(char *message, struct file *file, void *data, int size) { char log[4096]; - unsigned char *l,*p=data; + char *l; + unsigned char *p=data; int fd=open("log.txt",O_RDWR|O_CREAT|O_APPEND|O_SYNC, 0644); sprintf(log,"# %s\n",message); -- cgit v1.2.1 From c92a8cf4e34c6694e755520408f2397f238fb37b Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 13 Dec 2005 20:51:48 +0000 Subject: Beginning of documentation with Doxygen git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@33 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Doxyfile | 1228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ coord.c | 13 + coord.h | 15 +- town.h | 29 +- 4 files changed, 1265 insertions(+), 20 deletions(-) create mode 100644 Doxyfile diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 00000000..e2167554 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,1228 @@ +# Doxyfile 1.4.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = navit + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is YES. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/coord.c b/coord.c index 8e792db8..7ccc8e2e 100644 --- a/coord.c +++ b/coord.c @@ -1,4 +1,15 @@ #include "coord.h" +/** + * @defgroup coord Coordinate handling functions + * @{ + */ + +/** + * Get a coordinate + * + * @param p Pointer to the coordinate + * @returns the coordinate + */ struct coord * coord_get(unsigned char **p) @@ -7,3 +18,5 @@ coord_get(unsigned char **p) *p += sizeof(*ret); return ret; } + +/** @} */ diff --git a/coord.h b/coord.h index 885c7919..54ba4b7e 100644 --- a/coord.h +++ b/coord.h @@ -1,19 +1,22 @@ #ifndef COORD_H #define COORD_H +/*! A integer mercator coordinate */ struct coord { - long x; - long y; + long x; /*!< X-Value */ + long y; /*!< Y-Value */ }; +//! A double mercator coordinate struct coord_d { - double x; - double y; + double x; /*!< X-Value */ + double y; /*!< Y-Value */ }; +//! A WGS84 coordinate struct coord_geo { - double lng; - double lat; + double lng; /*!< Longitude */ + double lat; /*!< Latitude */ }; struct coord * coord_get(unsigned char **p); diff --git a/town.h b/town.h index fd48b5e3..5b7e8458 100644 --- a/town.h +++ b/town.h @@ -1,18 +1,19 @@ +/*! A town description */ struct town { - unsigned long id; - struct coord *c; - char *name; - char *district; - char *postal_code1; - unsigned char order; - unsigned char type; - unsigned short country; - unsigned long unknown2; - unsigned char size; - unsigned long street_assoc; - unsigned char unknown3; - char *postal_code2; - unsigned long unknown4; + unsigned long id; /*!< Identifier */ + struct coord *c; /*!< Coordinates */ + char *name; /*!< Name */ + char *district; /*!< District */ + char *postal_code1; /*!< Postal code */ + unsigned char order; /*!< Order (Importance) */ + unsigned char type; /*!< Type */ + unsigned short country; /*!< Country */ + unsigned long unknown2; /*!< Unknown */ + unsigned char size; /*!< Size of town */ + unsigned long street_assoc; /*!< Association to streets */ + unsigned char unknown3; /*!< Unknown */ + char *postal_code2; /*!< 2nd postal code */ + unsigned long unknown4; /*!< Unknown */ }; struct block_info; -- cgit v1.2.1 From 47e10fe9ce9033d82472162b32b347e7cb1977ba Mon Sep 17 00:00:00 2001 From: horwitz Date: Thu, 15 Dec 2005 21:18:29 +0000 Subject: remove deprecated gtk stuff git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@34 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 18 ++-- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 12 +-- gui/gtk/gtkeyboard.c | 44 ++++---- gui/gtk/gui_gtk_menu.c | 118 ++++++++++----------- gui/gtk/gui_gtk_toolbar.c | 49 ++++----- popup.c | 6 +- 6 files changed, 116 insertions(+), 131 deletions(-) diff --git a/destination.c b/destination.c index c25fa2cd..d4854670 100644 --- a/destination.c +++ b/destination.c @@ -621,14 +621,14 @@ int destination_address(struct container *co) search->map_data=co->map_data; search->clist=listbox; - gtk_signal_connect(GTK_OBJECT(entry_country), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(entry_postal), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(entry_city), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(entry_district), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(entry_street), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(entry_number), "changed", GTK_SIGNAL_FUNC(changed), search); - gtk_signal_connect(GTK_OBJECT(button1), "clicked", GTK_SIGNAL_FUNC(button_map), co); - gtk_signal_connect(GTK_OBJECT(button2), "clicked", GTK_SIGNAL_FUNC(button_destination), co); + g_signal_connect(G_OBJECT(entry_country), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(entry_postal), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(entry_city), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(entry_district), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(entry_street), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(entry_number), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_map), co); + g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_destination), co); gtk_widget_grab_focus(entry_city); gtk_container_add(GTK_CONTAINER(vbox), table); @@ -636,7 +636,7 @@ int destination_address(struct container *co) gtk_container_add(GTK_CONTAINER(window2), vbox); handlerid = gtk_timeout_add(256, (GtkFunction) track_focus, NULL); - gtk_signal_connect(GTK_OBJECT(listbox), "select-row", GTK_SIGNAL_FUNC(select_row), NULL); + g_signal_connect(G_OBJECT(listbox), "select-row", G_CALLBACK(select_row), NULL); gtk_widget_show_all(window2); diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 30987fac..b5d06474 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -614,14 +614,14 @@ graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget) this->gra->widget=draw; this->gra->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); - gtk_signal_connect(GTK_OBJECT(draw), "expose_event", GTK_SIGNAL_FUNC(expose), co); - gtk_signal_connect(GTK_OBJECT(draw), "configure_event", GTK_SIGNAL_FUNC(configure), co); + g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), co); + g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), co); #if 0 - gtk_signal_connect(GTK_OBJECT(draw), "realize_event", GTK_SIGNAL_FUNC(realize), co); + g_signal_connect(G_OBJECT(draw), "realize_event", G_CALLBACK(realize), co); #endif - gtk_signal_connect(GTK_OBJECT(draw), "button_press_event", GTK_SIGNAL_FUNC(button_press), co); - gtk_signal_connect(GTK_OBJECT(draw), "button_release_event", GTK_SIGNAL_FUNC(button_release), co); - gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event", GTK_SIGNAL_FUNC(motion_notify), co); + g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), co); + g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), co); + g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), co); *widget=draw; return this; } diff --git a/gui/gtk/gtkeyboard.c b/gui/gtk/gtkeyboard.c index 02b9c937..58f929b8 100644 --- a/gui/gtk/gtkeyboard.c +++ b/gui/gtk/gtkeyboard.c @@ -337,7 +337,7 @@ typedef struct { GtkShadowType SHADOW_TYPE; GtkPositionType PULLOFFS_SIDE; - GtkItemFactory *item_factory; /* Cleaned */ + GtkUIManager *uimanager; GtkWidget *popup_menu; /* Cleaned */ GdkCursor *cursor; GtkStyle *style; @@ -556,7 +556,7 @@ static void setup_default_opts_other(void) GUI.deflt = (GtkStyle *) NULL; GUI.xwindow = (Window) NULL; GUI.popup_menu = (GtkWidget *) NULL; - GUI.item_factory = (GtkItemFactory *) NULL; + GUI.uimanager = (GtkUIManager *) NULL; GUI.keyboard_elements.show_keyboard = ON; @@ -669,17 +669,17 @@ static void destroy_key_widget_data(GtkObject *object, gpointer data) static void connect_destroy_signal(GtkWidget * widget, gpointer data) { #if 0 - gtk_signal_connect_full(GTK_OBJECT(widget), + g_signal_connect_data(G_OBJECT(widget), "destroy", - GTK_SIGNAL_FUNC(destroy_key_widget_data), + G_CALLBACK(destroy_key_widget_data), (GtkCallbackMarshal) gtk_signal_default_marshaller, data, (GtkDestroyNotify) destroy_key_widget_data, FALSE, TRUE); #endif - gtk_signal_connect(GTK_OBJECT(widget), + g_signal_connect(G_OBJECT(widget), "destroy", - GTK_SIGNAL_FUNC(destroy_key_widget_data), + G_CALLBACK(destroy_key_widget_data), data); } /* End connect_destroy_signal() */ @@ -997,54 +997,48 @@ GtkWidget *build_keyboard(GtkWidget * input, char *filename) switch (key->lower_case) { case XK_Caps_Lock: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC - (capslock_toggle), + G_CALLBACK(capslock_toggle), input); /* Key unused in signalling */ key = gtkeyboard_destroy_key(key); break; case XK_Alt_L: case XK_Alt_R: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC - (alt_toggle), NULL); + G_CALLBACK(alt_toggle), NULL); /* Key unused in signalling */ key = gtkeyboard_destroy_key(key); break; case XK_Control_L: case XK_Control_R: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC - (control_toggle), NULL); + G_CALLBACK(control_toggle), NULL); /* Key unused in signalling */ key = gtkeyboard_destroy_key(key); break; case XK_Shift_L: case XK_Shift_R: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC - (shift_on), NULL); + G_CALLBACK(shift_on), NULL); /* Key unused in signalling */ key = gtkeyboard_destroy_key(key); break; case XK_Mode_switch: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC - (alt_gr_toggle), NULL); + G_CALLBACK(alt_gr_toggle), NULL); /* Key unused in signalling */ key = gtkeyboard_destroy_key(key); break; default: - gtk_signal_connect(GTK_OBJECT(button), + g_signal_connect(G_OBJECT(button), "button_press_event", - GTK_SIGNAL_FUNC - (triple_callback), key); + G_CALLBACK(triple_callback), key); connect_destroy_signal(button, key); break; } /* End switch */ @@ -1657,7 +1651,7 @@ static int mask_name_to_slot_number(char *maskname) int y = 0; for (y = 0; y < maskcount; y++) { - if (g_strcasecmp(maskname, masks[y]) == 0) + if (g_ascii_strcasecmp(maskname, masks[y]) == 0) return y; } /* End for */ diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index beef7e56..0aa2d3f0 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -54,8 +54,8 @@ menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, struct container *co; if (! strcmp(event->string,"\r")) { - text=gtk_object_get_data(GTK_OBJECT(win), "Input"); - co=gtk_object_get_data(GTK_OBJECT(win), "Container"); + text=g_object_get_data(G_OBJECT(win), "Input"); + co=g_object_get_data(G_OBJECT(win), "Container"); t=gtk_entry_get_text(GTK_ENTRY(text)); if (!strncmp(t,"goto ",5)) { command_goto(co, t+5); @@ -78,10 +78,10 @@ menu_window_command(struct container *co) gtk_box_pack_start(GTK_BOX(box), entry, 1, 1, 0); gtk_box_pack_start(GTK_BOX(box), text, 1, 1, 0); gtk_container_add(GTK_CONTAINER(win), box); - gtk_object_set_data(GTK_OBJECT(win), "Container", co); - gtk_object_set_data(GTK_OBJECT(win), "Input", entry); - gtk_object_set_data(GTK_OBJECT(win), "Output", text); - gtk_signal_connect(GTK_OBJECT(win), "key-press-event", GTK_SIGNAL_FUNC(menu_window_command_key_press), win); + g_object_set_data(G_OBJECT(win), "Container", co); + g_object_set_data(G_OBJECT(win), "Input", entry); + g_object_set_data(G_OBJECT(win), "Output", text); + g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(menu_window_command_key_press), win); gtk_widget_show_all(win); } @@ -153,9 +153,9 @@ menu_item(struct menu *me, GtkWidget *menu, char *name, void (*func)(struct cont { GtkWidget *item; item=gtk_menu_item_new_with_label(name); - gtk_menu_append (GTK_MENU(menu), item); - gtk_signal_connect_object(GTK_OBJECT(item), "activate", - GTK_SIGNAL_FUNC (func), me); + gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); + g_signal_connect_swapped(G_OBJECT(item), "activate", + G_CALLBACK(func), me); } static int @@ -168,7 +168,7 @@ menu_clock_update(void *data) sprintf(buffer,"%02d:%02d", now_tm->tm_hour, now_tm->tm_min); gtk_label_set_text(GTK_LABEL(widget), buffer); - gtk_timeout_add((60-now_tm->tm_sec)*1000,menu_clock_update,widget); + g_timeout_add((60-now_tm->tm_sec)*1000,menu_clock_update,widget); return FALSE; } @@ -185,107 +185,107 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) menu=gtk_menu_bar_new(); item=gtk_menu_item_new_with_label("Goto"); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); { menu2=gtk_menu_new(); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); item=gtk_menu_item_new_with_label("Window"); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); { menu2=gtk_menu_new(); item2=gtk_menu_item_new_with_label("Clone"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_clone), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_clone), this); item2=gtk_menu_item_new_with_label("Command"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_command), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_command), this); item2=gtk_menu_item_new_with_label("Visible Blocks"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_visible_blocks), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_visible_blocks), co); item2=gtk_menu_item_new_with_label("Visible Towns"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_visible_towns), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_visible_towns), co); item2=gtk_menu_item_new_with_label("Visible Polys"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_visible_polys), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_visible_polys), co); item2=gtk_menu_item_new_with_label("Visible Streets"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_window_visible_streets), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_window_visible_streets), co); menu_item(this, menu2, "Visible Points", menu_window_visible_points); item2=gtk_menu_item_new_with_label("Exit"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (exit), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (exit), this); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); item=gtk_menu_item_new_with_label("Map"); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); { menu2=gtk_menu_new(); item2=gtk_menu_item_new_with_label("Compare"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_map_compare), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_map_compare), this); item2=gtk_menu_item_new_with_label("Distances"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_map_distances), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_map_distances), this); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); item=gtk_menu_item_new_with_label("Route"); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); { menu2=gtk_menu_new(); item2=gtk_menu_item_new_with_label("Start"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (route_start), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (route_start), co); item2=gtk_menu_item_new_with_label("Trace"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (route_trace), co); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (route_trace), co); item2=gtk_menu_item_new_with_label("Update"); - gtk_menu_append (GTK_MENU(menu2), item2); - gtk_signal_connect_object(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_route_update), this); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); + g_signal_connect_swapped(G_OBJECT(item2), "activate", + G_CALLBACK (menu_route_update), this); } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); item=gtk_menu_item_new_with_label("Destinations"); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); menu2=gtk_menu_new(); item2=gtk_menu_item_new_with_label("Last Destinations"); - gtk_menu_append (GTK_MENU(menu2), item2); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); menu3=gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); item2=gtk_menu_item_new_with_label("Address"); - gtk_menu_append (GTK_MENU(menu2), item2); + gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); { FILE *file; @@ -330,7 +330,7 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) list=gtk_container_get_children(GTK_CONTAINER(menu3)); while (list) { item2=GTK_WIDGET(list->data); - gtk_label_get(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item2))),&label); + label=g_strdup(gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item2))))); if (!strcmp(label, tok)) { menu3=gtk_menu_item_get_submenu(GTK_MENU_ITEM(item2)); break; @@ -341,22 +341,22 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) if (! list) { utf8=g_locale_to_utf8(tok,-1,NULL,NULL,NULL); item2=gtk_menu_item_new_with_label(utf8); - gtk_menu_append (GTK_MENU(menu3), item2); + gtk_menu_shell_append (GTK_MENU_SHELL(menu3), item2); g_free(utf8); } text=NULL; } - gtk_signal_connect(GTK_OBJECT(item2), "activate", - GTK_SIGNAL_FUNC (menu_destination_selected), dest); + g_signal_connect(G_OBJECT(item2), "activate", + G_CALLBACK (menu_destination_selected), dest); } } gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); item=gtk_menu_item_new(); clock=gtk_label_new(NULL); - gtk_menu_item_right_justify(GTK_MENU_ITEM(item)); + gtk_menu_item_set_right_justified(GTK_MENU_ITEM(item),TRUE); gtk_container_add(GTK_CONTAINER(item), clock); - gtk_menu_bar_append(GTK_MENU_BAR(menu), item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); menu_clock_update(clock); *widget=menu; diff --git a/gui/gtk/gui_gtk_toolbar.c b/gui/gtk/gui_gtk_toolbar.c index cd32c10d..ec27b746 100644 --- a/gui/gtk/gui_gtk_toolbar.c +++ b/gui/gtk/gui_gtk_toolbar.c @@ -259,7 +259,7 @@ static GtkWidget * xpm_to_widget(GtkWidget *draw, gchar **xpm_data) { /* GtkWidget is the storage type for widgets */ - GtkWidget *pixmapwid; + GtkWidget *imagewid; GdkPixmap *pixmap; GdkBitmap *mask; GtkStyle *style; @@ -274,26 +274,10 @@ xpm_to_widget(GtkWidget *draw, gchar **xpm_data) (gchar **)xpm_data ); /* a pixmap widget to contain the pixmap */ - pixmapwid = gtk_pixmap_new(pixmap, mask); - gtk_widget_show(pixmapwid); + imagewid = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(imagewid); - return(pixmapwid); -} - -static void -toolbar_button_leave (GtkButton *button, gpointer status) -{ - int *st=status,new_state=GTK_STATE_NORMAL; - g_return_if_fail (button != NULL); - g_return_if_fail (GTK_IS_BUTTON (button)); - - if (*st) - new_state=GTK_STATE_ACTIVE; - if (GTK_WIDGET_STATE (button) != new_state) - { - gtk_widget_set_state (GTK_WIDGET (button), new_state); - gtk_widget_queue_draw (GTK_WIDGET (button)); - } + return(imagewid); } int tst_stat=1; @@ -302,19 +286,29 @@ static void toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data) { GtkWidget *icon; + GtkToolItem *toolitem; + icon=xpm_to_widget(window, icon_data); - gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, text, NULL, icon, GTK_SIGNAL_FUNC(func), data); + toolitem=gtk_tool_button_new(icon,text); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toolitem,-1); + g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(func), data); } static void toolbar_button_toggle(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data, int *flag) { - GtkWidget *icon,*item; + GtkWidget *icon; + GtkToolItem *toggleitem; + icon=xpm_to_widget(window, icon_data); - item=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, text, NULL, icon, GTK_SIGNAL_FUNC(func), data); - if (*flag) - gtk_widget_set_state(item, GTK_STATE_ACTIVE); - gtk_signal_connect(GTK_OBJECT(item), "leave", GTK_SIGNAL_FUNC(toolbar_button_leave), flag); + toggleitem=gtk_toggle_tool_button_new(); + gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toggleitem),icon); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(toggleitem),text); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toggleitem,-1); + if(*flag) + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toggleitem),TRUE); + + g_signal_connect(G_OBJECT(toggleitem), "clicked", G_CALLBACK(func), data); } @@ -328,9 +322,6 @@ gui_gtk_toolbar_new(struct container *co, GtkWidget **widget) this->gui->co=co; toolbar=gtk_toolbar_new(); - gtk_toolbar_prepend_space(GTK_TOOLBAR(toolbar)); - gtk_toolbar_prepend_space(GTK_TOOLBAR(toolbar)); - window=(GtkWidget *)(co->win); co->flags->track=1; diff --git a/popup.c b/popup.c index c61c5d34..af9c01c0 100644 --- a/popup.c +++ b/popup.c @@ -165,8 +165,8 @@ popup_menu(struct popup_item *list) submenu=popup_menu(curr->submenu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); } else if (curr->func) { - gtk_signal_connect(GTK_OBJECT(item), "activate", - GTK_SIGNAL_FUNC (popup_call_func), curr); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK (popup_call_func), curr); } } if (curr->priority > curr_prio && curr->priority < min_prio) @@ -303,7 +303,7 @@ popup(struct container *co, int x, int y, int button) gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time()); - gtk_signal_connect(GTK_OBJECT(menu), "selection-done", GTK_SIGNAL_FUNC (popup_destroy), popup); + g_signal_connect(G_OBJECT(menu), "selection-done", G_CALLBACK (popup_destroy), popup); } -- cgit v1.2.1 From e6eabe025eca9f0d6f819311ec7538df5e7f2925 Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 20 Dec 2005 00:40:44 +0000 Subject: use GtkAction for menu and toolbar git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@35 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- action.h | 3 + gui/gtk/Makefile.am | 2 +- gui/gtk/gui_gtk.h | 4 +- gui/gtk/gui_gtk_action.c | 321 +++++++++++++++++++++++++++++++++++++++++++++++ gui/gtk/gui_gtk_window.c | 9 +- 5 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 action.h create mode 100644 gui/gtk/gui_gtk_action.c diff --git a/action.h b/action.h new file mode 100644 index 00000000..ed64fd56 --- /dev/null +++ b/action.h @@ -0,0 +1,3 @@ +struct action { + struct action_gui *gui; +}; diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am index e6a2edd2..d5ffe2f7 100644 --- a/gui/gtk/Makefile.am +++ b/gui/gtk/Makefile.am @@ -5,7 +5,7 @@ objdir=$(prefix) obj_PROGRAMS=gtk.o INSTALL_PROGRAM=/bin/true -gtk_o_SOURCES=gtkeyboard.c gui_gtk_menu.c gui_gtk_statusbar.c gui_gtk_toolbar.c gui_gtk_window.c +gtk_o_SOURCES=gtkeyboard.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c gtk.o: $(gtk_o_OBJECTS) ld -r -o gtk.o $(gtk_o_OBJECTS) diff --git a/gui/gtk/gui_gtk.h b/gui/gtk/gui_gtk.h index a2f3cf9a..6c7792f1 100644 --- a/gui/gtk/gui_gtk.h +++ b/gui/gtk/gui_gtk.h @@ -1,5 +1,5 @@ struct statusbar *gui_gtk_statusbar_new(GtkWidget **widget); -struct toolbar *gui_gtk_toolbar_new(struct container *co, GtkWidget **widget); -struct menu *gui_gtk_menu_new(struct container *co, GtkWidget **widget); +void gui_gtk_actions_new(struct container *co, GtkWidget **vbox); struct container * gui_gtk_window(int x, int y, int scale); + diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c new file mode 100644 index 00000000..587ac548 --- /dev/null +++ b/gui/gtk/gui_gtk_action.c @@ -0,0 +1,321 @@ +#include +#include +#include "graphics.h" +#include "gui_gtk.h" +#include "container.h" +#include "menu.h" +#include "coord.h" +#include "destination.h" + +struct action_gui { + struct container *co; +}; + +#include "action.h" + + +/* Create callbacks that implement our Actions */ + +static void +zoom_in_action(GtkWidget *w, struct action *ac) +{ + unsigned long scale; + graphics_get_view(ac->gui->co, NULL, NULL, &scale); + scale/=2; + if (scale < 1) + scale=1; + graphics_set_view(ac->gui->co, NULL, NULL, &scale); +} + +static void +zoom_out_action(GtkWidget *w, struct action *ac) +{ + unsigned long scale; + graphics_get_view(ac->gui->co, NULL, NULL, &scale); + scale*=2; + graphics_set_view(ac->gui->co, NULL, NULL, &scale); +} + +static void +refresh_action(GtkWidget *w, struct action *ac) +{ + menu_route_update(ac->gui->co); +} + +static void +cursor_action(GtkWidget *w, struct action *ac) +{ + if (ac->gui->co->flags->track) { + ac->gui->co->flags->track=0; + } else { + ac->gui->co->flags->track=1; + } +} + +static void +orient_north_action(GtkWidget *w, struct action *ac) +{ + if (ac->gui->co->flags->orient_north) { + ac->gui->co->flags->orient_north=0; + } else { + ac->gui->co->flags->orient_north=1; + } +} + +static void +destination_action(GtkWidget *w, struct action *ac) +{ + destination_address(ac->gui->co); +} + + +static void +quit_action (GtkWidget *w, struct action *ac) +{ + gtk_main_quit(); +} + + +/* Create a list of entries which are passed to the Action constructor. + * This is a huge convenience over building Actions by hand. */ +static GtkActionEntry entries[] = +{ + { "DisplayMenuAction", NULL, "Display" }, + { "RouteMenuAction", NULL, "Route" }, + { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, + { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, + { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, + { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action) }, + { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action) }, + { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, + { "QuitAction", GTK_STOCK_QUIT, "_Quit", "Q",NULL, G_CALLBACK (quit_action) } +}; + +static guint n_entries = G_N_ELEMENTS (entries); + +static GtkToggleActionEntry toggleentries[] = +{ + { "CursorAction", NULL,"Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, + { "OrientationAction", NULL, "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } +}; + +static guint n_toggleentries = G_N_ELEMENTS (toggleentries); + +/* XPM */ +static gchar * cursor_xpm[] = { +"22 22 2 1", +" c None", +". c #0000FF", +" ", +" ", +" ", +" .. ", +" .. .. ", +" .. .. ", +" . . ", +" . . ", +" . ... . ", +" . ... . . ", +" . ... . . ", +" . .. . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" .. .. ", +" .. .. ", +" .. ", +" ", +" ", +" "}; + + +/* XPM */ +static gchar * north_xpm[] = { +"22 22 2 1", +" c None", +". c #000000", +" ", +" ", +" . ", +" ... ", +" . . . ", +" . . . ", +" . ", +" .... . .... ", +" .... . .... ", +" .... . .. ", +" .. .. .. ", +" .. .. .. ", +" .. .. .. ", +" .. .. .. ", +" .. . .... ", +" .... . .... ", +" .... . .... ", +" . ", +" . ", +" . ", +" ", +" "}; + + +/* XPM */ +static gchar * flag_xpm[] = { +"22 22 2 1", +" c None", +"+ c #000000", +"+++++++ ", +"+ +++++++++ ", +"+ +++ +++++++++ ", +"+ +++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ + ", +"+ ++++++ +++ + ", +"+ +++ ++++++ + ", +"+ +++ +++ +++ ", +"++++ +++ +++ ", +"++++ +++ +++ ", +"++++++++++ +++ + ", +"+ +++++++++ + ", +"+ ++++++ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ ", +"+ "}; + + + +static struct { + gchar *stockid; + gchar **icon_xpm; +} stock_icons[] = { + {"cursor_icon", &cursor_xpm }, + {"orientation_icon", &north_xpm }, + {"flag_icon", &flag_xpm } +}; + +static gint n_stock_icons = G_N_ELEMENTS (stock_icons); + + +static void +register_my_stock_icons (void) +{ + GtkIconFactory *icon_factory; + GtkIconSet *icon_set; + GtkIconSource *icon_source; + GdkPixbuf *pixbuf; + gint i; + + icon_factory = gtk_icon_factory_new (); + + for (i = 0; i < n_stock_icons; i++) + { + pixbuf = gdk_pixbuf_new_from_xpm_data(stock_icons[i].icon_xpm); + icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); + gtk_icon_factory_add (icon_factory, stock_icons[i].stockid, icon_set); + gtk_icon_set_unref (icon_set); +#if 0 + icon_set = gtk_icon_set_new(); + icon_source = gtk_icon_source_new(); + gtk_icon_source_set_pixbuf(icon_source,pixbuf); + gtk_icon_set_add_source(icon_set, icon_source); + gtk_icon_source_set_state(icon_source,GTK_STATE_ACTIVE); + gtk_icon_set_add_source(icon_set, icon_source); + gtk_icon_source_free(icon_source); + gtk_icon_factory_add(icon_factory, stock_icons[i].stockid, icon_set); + gtk_icon_set_unref(icon_set); +#endif + } + + gtk_icon_factory_add_default(icon_factory); + + g_object_unref(icon_factory); +} + +/* Implement a handler for GtkUIManager's "add_widget" signal. The UI manager + * will emit this signal whenever it needs you to place a new widget it has. */ +static void +action_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) +{ + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); +} + +static char layout[] = + "\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + "; + + +void +gui_gtk_actions_new(struct container *co, GtkWidget **vbox) +{ + GtkActionGroup *action_group; /* Packing group for our Actions */ + GtkUIManager *menu_manager; /* The magic widget! */ + GError *error; /* For reporting exceptions or errors */ + + struct action *this=g_new0(struct action, 1); + + this->gui=g_new0(struct action_gui, 1); + this->gui->co=co; + + register_my_stock_icons(); + + action_group = gtk_action_group_new ("BaseActions"); + menu_manager = gtk_ui_manager_new (); + + /* Pack up our objects: + * vbox -> window + * actions -> action_group + * action_group -> menu_manager */ + gtk_action_group_add_actions (action_group, entries, n_entries, this); + gtk_action_group_add_toggle_actions (action_group, toggleentries, n_toggleentries, this); + gtk_ui_manager_insert_action_group (menu_manager, action_group, 0); + + /* Read in the UI from our XML file */ + error = NULL; + gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); + + if (error) + { + g_message ("building menus failed: %s", error->message); + g_error_free (error); + } + + /* This signal is necessary in order to place widgets from the UI manager + * into the vbox */ + g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); +} + diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index fb62280f..f080bbda 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -37,7 +37,7 @@ gui_gtk_window(int x, int y, int scale) { GtkWidget *window,*map_widget; GtkWidget *vbox; - GtkWidget *statusbar,*toolbar,*menu; + GtkWidget *statusbar; struct container *co; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -51,10 +51,12 @@ gui_gtk_window(int x, int y, int scale) co->win=(struct window *) window; co->statusbar=gui_gtk_statusbar_new(&statusbar); - co->toolbar=gui_gtk_toolbar_new(co, &toolbar); - co->menu=gui_gtk_menu_new(co, &menu); + gui_gtk_actions_new(co,&vbox); + +/* gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); +*/ gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(vbox), map_widget, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); @@ -64,4 +66,3 @@ gui_gtk_window(int x, int y, int scale) return co; } - -- cgit v1.2.1 From b285006e0624d8f2f3c0d6e4b020de0aa72a849c Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 20 Dec 2005 09:51:37 +0000 Subject: readd actions to display the data_window git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@36 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 86 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 587ac548..442e9bd2 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -4,6 +4,7 @@ #include "gui_gtk.h" #include "container.h" #include "menu.h" +#include "data_window.h" #include "coord.h" #include "destination.h" @@ -75,9 +76,42 @@ quit_action (GtkWidget *w, struct action *ac) gtk_main_quit(); } +static void +visible_blocks_action(GtkWidget *w, struct container *co) +{ + co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); + graphics_redraw(co); +} + +static void +visible_towns_action(GtkWidget *w, struct container *co) +{ + co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); + graphics_redraw(co); +} + +static void +visible_polys_action(GtkWidget *w, struct container *co) +{ + co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); + graphics_redraw(co); +} + +static void +visible_streets_action(GtkWidget *w, struct container *co) +{ + co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); + graphics_redraw(co); +} + +static void +visible_points_action(GtkWidget *w, struct container *co) +{ + co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); + graphics_redraw(co); +} + -/* Create a list of entries which are passed to the Action constructor. - * This is a huge convenience over building Actions by hand. */ static GtkActionEntry entries[] = { { "DisplayMenuAction", NULL, "Display" }, @@ -101,7 +135,19 @@ static GtkToggleActionEntry toggleentries[] = static guint n_toggleentries = G_N_ELEMENTS (toggleentries); -/* XPM */ +static GtkActionEntry debug_entries[] = +{ + { "DataMenuAction", NULL, "Data" }, + { "VisibleBlocksAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_blocks_action) }, + { "VisibleTownsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_towns_action) }, + { "VisiblePolysAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_polys_action) }, + { "VisibleStreetsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_streets_action) }, + { "VisiblePointsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_points_action) } +}; + +static guint n_debug_entries = G_N_ELEMENTS (debug_entries); + + static gchar * cursor_xpm[] = { "22 22 2 1", " c None", @@ -130,7 +176,6 @@ static gchar * cursor_xpm[] = { " "}; -/* XPM */ static gchar * north_xpm[] = { "22 22 2 1", " c None", @@ -159,7 +204,6 @@ static gchar * north_xpm[] = { " "}; -/* XPM */ static gchar * flag_xpm[] = { "22 22 2 1", " c None", @@ -236,8 +280,6 @@ register_my_stock_icons (void) g_object_unref(icon_factory); } -/* Implement a handler for GtkUIManager's "add_widget" signal. The UI manager - * will emit this signal whenever it needs you to place a new widget it has. */ static void action_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) { @@ -256,10 +298,17 @@ static char layout[] = \ \ \ + \ + \ + \ + \ + \ + \ + \ + \ \ \ \ - \ \ \ \ @@ -282,9 +331,9 @@ static char layout[] = void gui_gtk_actions_new(struct container *co, GtkWidget **vbox) { - GtkActionGroup *action_group; /* Packing group for our Actions */ - GtkUIManager *menu_manager; /* The magic widget! */ - GError *error; /* For reporting exceptions or errors */ + GtkActionGroup *base_group,*debug_group; + GtkUIManager *menu_manager; + GError *error; struct action *this=g_new0(struct action, 1); @@ -293,18 +342,21 @@ gui_gtk_actions_new(struct container *co, GtkWidget **vbox) register_my_stock_icons(); - action_group = gtk_action_group_new ("BaseActions"); + base_group = gtk_action_group_new ("BaseActions"); + debug_group = gtk_action_group_new ("DebugActions"); menu_manager = gtk_ui_manager_new (); /* Pack up our objects: * vbox -> window * actions -> action_group * action_group -> menu_manager */ - gtk_action_group_add_actions (action_group, entries, n_entries, this); - gtk_action_group_add_toggle_actions (action_group, toggleentries, n_toggleentries, this); - gtk_ui_manager_insert_action_group (menu_manager, action_group, 0); + gtk_action_group_add_actions (base_group, entries, n_entries, this); + gtk_action_group_add_toggle_actions (base_group, toggleentries, n_toggleentries, this); + gtk_ui_manager_insert_action_group (menu_manager, base_group, 0); - /* Read in the UI from our XML file */ + gtk_action_group_add_actions (debug_group, debug_entries, n_debug_entries, co); + gtk_ui_manager_insert_action_group (menu_manager, debug_group, 0); + error = NULL; gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); @@ -314,8 +366,6 @@ gui_gtk_actions_new(struct container *co, GtkWidget **vbox) g_error_free (error); } - /* This signal is necessary in order to place widgets from the UI manager - * into the vbox */ g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); } -- cgit v1.2.1 From 7062607d1108e9eb79d6f5fcf7a9c49d03d39e12 Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 20 Dec 2005 15:08:03 +0000 Subject: fixed display of icons for toggle actions git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@37 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 442e9bd2..918e59f3 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -119,8 +119,6 @@ static GtkActionEntry entries[] = { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, - { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action) }, - { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action) }, { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, { "QuitAction", GTK_STOCK_QUIT, "_Quit", "Q",NULL, G_CALLBACK (quit_action) } }; @@ -129,8 +127,8 @@ static guint n_entries = G_N_ELEMENTS (entries); static GtkToggleActionEntry toggleentries[] = { - { "CursorAction", NULL,"Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, - { "OrientationAction", NULL, "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } + { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, + { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } }; static guint n_toggleentries = G_N_ELEMENTS (toggleentries); @@ -139,10 +137,10 @@ static GtkActionEntry debug_entries[] = { { "DataMenuAction", NULL, "Data" }, { "VisibleBlocksAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_blocks_action) }, - { "VisibleTownsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_towns_action) }, - { "VisiblePolysAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_polys_action) }, - { "VisibleStreetsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_streets_action) }, - { "VisiblePointsAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_points_action) } + { "VisibleTownsAction", NULL, "VisibleTowns", NULL, NULL, G_CALLBACK(visible_towns_action) }, + { "VisiblePolysAction", NULL, "VisiblePolys", NULL, NULL, G_CALLBACK(visible_polys_action) }, + { "VisibleStreetsAction", NULL, "VisibleStreets", NULL, NULL, G_CALLBACK(visible_streets_action) }, + { "VisiblePointsAction", NULL, "VisiblePoints", NULL, NULL, G_CALLBACK(visible_points_action) } }; static guint n_debug_entries = G_N_ELEMENTS (debug_entries); @@ -260,19 +258,9 @@ register_my_stock_icons (void) { pixbuf = gdk_pixbuf_new_from_xpm_data(stock_icons[i].icon_xpm); icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); + g_object_unref(pixbuf); gtk_icon_factory_add (icon_factory, stock_icons[i].stockid, icon_set); gtk_icon_set_unref (icon_set); -#if 0 - icon_set = gtk_icon_set_new(); - icon_source = gtk_icon_source_new(); - gtk_icon_source_set_pixbuf(icon_source,pixbuf); - gtk_icon_set_add_source(icon_set, icon_source); - gtk_icon_source_set_state(icon_source,GTK_STATE_ACTIVE); - gtk_icon_set_add_source(icon_set, icon_source); - gtk_icon_source_free(icon_source); - gtk_icon_factory_add(icon_factory, stock_icons[i].stockid, icon_set); - gtk_icon_set_unref(icon_set); -#endif } gtk_icon_factory_add_default(icon_factory); -- cgit v1.2.1 From 55c4268ddba4b91d88107adae0ba5e9793b77145 Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 20 Dec 2005 15:50:18 +0000 Subject: fix source indentation git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@38 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 106 +++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 918e59f3..ae252bdf 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -73,7 +73,7 @@ destination_action(GtkWidget *w, struct action *ac) static void quit_action (GtkWidget *w, struct action *ac) { - gtk_main_quit(); + gtk_main_quit(); } static void @@ -114,33 +114,33 @@ visible_points_action(GtkWidget *w, struct container *co) static GtkActionEntry entries[] = { - { "DisplayMenuAction", NULL, "Display" }, - { "RouteMenuAction", NULL, "Route" }, - { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, - { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, - { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, - { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, - { "QuitAction", GTK_STOCK_QUIT, "_Quit", "Q",NULL, G_CALLBACK (quit_action) } + { "DisplayMenuAction", NULL, "Display" }, + { "RouteMenuAction", NULL, "Route" }, + { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, + { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, + { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, + { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, + { "QuitAction", GTK_STOCK_QUIT, "_Quit", "Q",NULL, G_CALLBACK (quit_action) } }; static guint n_entries = G_N_ELEMENTS (entries); static GtkToggleActionEntry toggleentries[] = { - { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, - { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } + { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, + { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } }; static guint n_toggleentries = G_N_ELEMENTS (toggleentries); static GtkActionEntry debug_entries[] = { - { "DataMenuAction", NULL, "Data" }, - { "VisibleBlocksAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_blocks_action) }, - { "VisibleTownsAction", NULL, "VisibleTowns", NULL, NULL, G_CALLBACK(visible_towns_action) }, - { "VisiblePolysAction", NULL, "VisiblePolys", NULL, NULL, G_CALLBACK(visible_polys_action) }, - { "VisibleStreetsAction", NULL, "VisibleStreets", NULL, NULL, G_CALLBACK(visible_streets_action) }, - { "VisiblePointsAction", NULL, "VisiblePoints", NULL, NULL, G_CALLBACK(visible_points_action) } + { "DataMenuAction", NULL, "Data" }, + { "VisibleBlocksAction", NULL, "VisibleBlocks", NULL, NULL, G_CALLBACK(visible_blocks_action) }, + { "VisibleTownsAction", NULL, "VisibleTowns", NULL, NULL, G_CALLBACK(visible_towns_action) }, + { "VisiblePolysAction", NULL, "VisiblePolys", NULL, NULL, G_CALLBACK(visible_polys_action) }, + { "VisibleStreetsAction", NULL, "VisibleStreets", NULL, NULL, G_CALLBACK(visible_streets_action) }, + { "VisiblePointsAction", NULL, "VisiblePoints", NULL, NULL, G_CALLBACK(visible_points_action) } }; static guint n_debug_entries = G_N_ELEMENTS (debug_entries); @@ -248,7 +248,6 @@ register_my_stock_icons (void) { GtkIconFactory *icon_factory; GtkIconSet *icon_set; - GtkIconSource *icon_source; GdkPixbuf *pixbuf; gint i; @@ -271,8 +270,8 @@ register_my_stock_icons (void) static void action_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) { - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); } static char layout[] = @@ -319,41 +318,38 @@ static char layout[] = void gui_gtk_actions_new(struct container *co, GtkWidget **vbox) { - GtkActionGroup *base_group,*debug_group; - GtkUIManager *menu_manager; - GError *error; - - struct action *this=g_new0(struct action, 1); - - this->gui=g_new0(struct action_gui, 1); - this->gui->co=co; - - register_my_stock_icons(); - - base_group = gtk_action_group_new ("BaseActions"); - debug_group = gtk_action_group_new ("DebugActions"); - menu_manager = gtk_ui_manager_new (); - - /* Pack up our objects: - * vbox -> window - * actions -> action_group - * action_group -> menu_manager */ - gtk_action_group_add_actions (base_group, entries, n_entries, this); - gtk_action_group_add_toggle_actions (base_group, toggleentries, n_toggleentries, this); - gtk_ui_manager_insert_action_group (menu_manager, base_group, 0); - - gtk_action_group_add_actions (debug_group, debug_entries, n_debug_entries, co); - gtk_ui_manager_insert_action_group (menu_manager, debug_group, 0); - - error = NULL; - gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); - - if (error) - { - g_message ("building menus failed: %s", error->message); - g_error_free (error); - } - - g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); + GtkActionGroup *base_group,*debug_group; + GtkUIManager *menu_manager; + GError *error; + + GtkWidget *toolbar; + + struct action *this=g_new0(struct action, 1); + + this->gui=g_new0(struct action_gui, 1); + this->gui->co=co; + + register_my_stock_icons(); + + base_group = gtk_action_group_new ("BaseActions"); + debug_group = gtk_action_group_new ("DebugActions"); + menu_manager = gtk_ui_manager_new (); + + gtk_action_group_add_actions (base_group, entries, n_entries, this); + gtk_action_group_add_toggle_actions (base_group, toggleentries, n_toggleentries, this); + gtk_ui_manager_insert_action_group (menu_manager, base_group, 0); + + gtk_action_group_add_actions (debug_group, debug_entries, n_debug_entries, co); + gtk_ui_manager_insert_action_group (menu_manager, debug_group, 0); + + error = NULL; + gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); + + if (error) { + g_message ("building menus failed: %s", error->message); + g_error_free (error); + } + + g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); } -- cgit v1.2.1 From 677d2ea76a4c6d1e9d9b919eaeb060be681853eb Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 20 Dec 2005 23:59:21 +0000 Subject: Fix some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@39 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index ae252bdf..616db31a 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -146,7 +146,7 @@ static GtkActionEntry debug_entries[] = static guint n_debug_entries = G_N_ELEMENTS (debug_entries); -static gchar * cursor_xpm[] = { +static const char * cursor_xpm[] = { "22 22 2 1", " c None", ". c #0000FF", @@ -174,7 +174,7 @@ static gchar * cursor_xpm[] = { " "}; -static gchar * north_xpm[] = { +static const char * north_xpm[] = { "22 22 2 1", " c None", ". c #000000", @@ -202,7 +202,7 @@ static gchar * north_xpm[] = { " "}; -static gchar * flag_xpm[] = { +static const char * flag_xpm[] = { "22 22 2 1", " c None", "+ c #000000", @@ -233,11 +233,11 @@ static gchar * flag_xpm[] = { static struct { gchar *stockid; - gchar **icon_xpm; + const char **icon_xpm; } stock_icons[] = { - {"cursor_icon", &cursor_xpm }, - {"orientation_icon", &north_xpm }, - {"flag_icon", &flag_xpm } + {"cursor_icon", cursor_xpm }, + {"orientation_icon", north_xpm }, + {"flag_icon", flag_xpm } }; static gint n_stock_icons = G_N_ELEMENTS (stock_icons); @@ -322,8 +322,6 @@ gui_gtk_actions_new(struct container *co, GtkWidget **vbox) GtkUIManager *menu_manager; GError *error; - GtkWidget *toolbar; - struct action *this=g_new0(struct action, 1); this->gui=g_new0(struct action_gui, 1); -- cgit v1.2.1 From 669b6d0ab40916b227f36520de409b2a279da646 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 27 Dec 2005 09:36:48 +0000 Subject: Fix gps speed to be in km/h git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@40 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vehicle.c b/vehicle.c index 1cc494fa..4816eb60 100644 --- a/vehicle.c +++ b/vehicle.c @@ -194,7 +194,7 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) double scale,speed; if (data->set & SPEED_SET) { this->speed_last=this->speed; - this->speed=data->fix.speed; + this->speed=data->fix.speed*1.852; data->set &= ~SPEED_SET; } if (data->set & TRACK_SET) { -- cgit v1.2.1 From 37ffcb176aa7448f3273202ecdeac6ee239199eb Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 27 Dec 2005 13:28:59 +0000 Subject: cleanup toggle actions git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@41 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 616db31a..b64d7473 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -46,21 +46,13 @@ refresh_action(GtkWidget *w, struct action *ac) static void cursor_action(GtkWidget *w, struct action *ac) { - if (ac->gui->co->flags->track) { - ac->gui->co->flags->track=0; - } else { - ac->gui->co->flags->track=1; - } + ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); } static void orient_north_action(GtkWidget *w, struct action *ac) { - if (ac->gui->co->flags->orient_north) { - ac->gui->co->flags->orient_north=0; - } else { - ac->gui->co->flags->orient_north=1; - } + ac->gui->co->flags->orient_north=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); } static void -- cgit v1.2.1 From 4426bbe8fc3b2862cb9c7541762ef3da23c76476 Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 28 Dec 2005 16:43:59 +0000 Subject: disable some debug messages git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@42 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- compass.c | 2 ++ navigation.c | 2 +- route.c | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compass.c b/compass.c index 3d9b2544..6dd1b9c6 100644 --- a/compass.c +++ b/compass.c @@ -86,7 +86,9 @@ compass_draw(struct compass *comp, struct container *co) dx=dest->x-pos->x; dy=dest->y-pos->y; dir=atan2(dx,dy)*180.0/M_PI; +#if 0 printf("dx %d dy %d dir=%f vehicle_dir=%f\n", dx, dy, dir, *vehicle_dir); +#endif dir-=*vehicle_dir; handle(comp->gr, comp->green, &p, 20, dir); p.x=8; diff --git a/navigation.c b/navigation.c index b69202b3..3f381244 100644 --- a/navigation.c +++ b/navigation.c @@ -161,8 +161,8 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) strcpy(p," abbiegen"); param_list[9].value=command; if (flag) { - printf("command='%s'\n", command); #if 0 + printf("command='%s'\n", command); speech_say(speech_handle, command); #endif flag=0; diff --git a/route.c b/route.c index 966251ae..c8b88a36 100644 --- a/route.c +++ b/route.c @@ -603,7 +603,9 @@ route_find(struct route *this, struct route_info *rt_start, struct route_info *r else route_add_path_segment(this, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); route_add_path_segment(this, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); +#if 0 printf("len %5.3f\n", len/1000); +#endif this->route_time_val=time/10; time/=10; this->route_len_val=len; @@ -611,7 +613,9 @@ route_find(struct route *this, struct route_info *rt_start, struct route_info *r time-=min*60; hr=min/60; min-=hr*60; +#if 0 printf("time %02d:%02d:%02d\n", hr, min, time); +#endif #if 1 navigation_path_description(this); #endif -- cgit v1.2.1 From 40ba1feba016e8045799a9d73a2820c1fa704ccc Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 28 Dec 2005 17:15:46 +0000 Subject: use GtkTreeView instead of GtkCList git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@43 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data_window.c | 68 +++++++++++++++++++++++++++++++++++-------------------- data_window_int.h | 2 +- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/data_window.c b/data_window.c index dfcddcc2..1eff89dc 100644 --- a/data_window.c +++ b/data_window.c @@ -20,7 +20,7 @@ data_window(char *name, struct window *parent, void(*callback)(struct data_windo GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(win->window), win->scrolled_window); - win->clist=NULL; + win->treeview=NULL; win->callback=callback; if (parent) gtk_window_set_transient_for(GTK_WINDOW((GtkWidget *)(win->window)), GTK_WINDOW(parent)); @@ -31,12 +31,12 @@ data_window(char *name, struct window *parent, void(*callback)(struct data_windo void data_window_begin(struct data_window *win) { - if (win && win->clist) { - gtk_clist_clear(GTK_CLIST(win->clist)); - gtk_clist_freeze(GTK_CLIST(win->clist)); + if (win && win->treeview) { + gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL); } } +#if 0 static void click_column(GtkCList *clist, int column) { @@ -64,41 +64,61 @@ select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct d win->callback(win, cols); } } +#endif void data_window_add(struct data_window *win, struct param_list *param, int count) { int i; - char *column[count+1]; - char *utf8; - if (! win->clist) { - for (i = 0 ; i < count ; i++) { - column[i]=param[i].name; + GtkCellRenderer *cell; + GtkTreeIter iter; + GtkListStore *liststore; + GType types[count]; + gchar *utf8; + + if (! win->treeview) { + win->treeview=gtk_tree_view_new(); + gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(win->scrolled_window),win->treeview); + gtk_widget_show_all(GTK_WIDGET(win->window)); + /* add column names to treeview */ + for(i=0;itreeview),-1,param[i].name, + cell,"text",i, NULL); } - win->clist=gtk_clist_new_with_titles(count, column); - gtk_clist_clear(GTK_CLIST(win->clist)); - gtk_container_add(GTK_CONTAINER(win->scrolled_window), win->clist); - gtk_clist_freeze(GTK_CLIST(win->clist)); - gtk_signal_connect(GTK_OBJECT(win->clist), "click-column", GTK_SIGNAL_FUNC(click_column), NULL); - gtk_signal_connect(GTK_OBJECT(win->clist), "select-row", GTK_SIGNAL_FUNC(select_row), win); - gtk_widget_show_all(win->window); } - for (i = 0 ; i < count ; i++) { - utf8=g_locale_to_utf8(param[i].value,-1,NULL,NULL,NULL); - column[i]=utf8; + + /* find data storage and create a new one if none is there */ + if (gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview)) == NULL) { + for(i=0;itreeview), GTK_TREE_MODEL(liststore)); } - column[i]=NULL; - gtk_clist_append(GTK_CLIST(win->clist), column); - for (i = 0 ; i < count ; i++) { - g_free(column[i]); + else + liststore=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview))); + + gtk_list_store_append(liststore,&iter); + + /* add data to data storage */ + for(i=0;iclist), "click-column", G_CALLBACK(click_column), NULL); + g_signal_connect(G_OBJECT(win->clist), "select-row", G_CALLBACK(select_row), win); +#endif } void data_window_end(struct data_window *win) { - if (win && win->clist) { +#if 0 + if (win && win->treeview) { gtk_clist_thaw(GTK_CLIST(win->clist)); gtk_clist_columns_autosize (GTK_CLIST(win->clist)); } +#endif } diff --git a/data_window_int.h b/data_window_int.h index c7922c2d..fdf33544 100644 --- a/data_window_int.h +++ b/data_window_int.h @@ -2,6 +2,6 @@ struct data_window { GtkWidget *window; GtkWidget *scrolled_window; - GtkWidget *clist; + GtkWidget *treeview; void(*callback)(struct data_window *, char **cols); }; -- cgit v1.2.1 From e43e7b816f50493dfa559b345372faf566b76333 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 16:32:35 +0000 Subject: North orientation off by default git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@44 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index b64d7473..b8386cbb 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -120,7 +120,7 @@ static guint n_entries = G_N_ELEMENTS (entries); static GtkToggleActionEntry toggleentries[] = { { "CursorAction", "cursor_icon","Cursor", NULL, NULL, G_CALLBACK(cursor_action),TRUE }, - { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),TRUE } + { "OrientationAction", "orientation_icon", "Orientation", NULL, NULL, G_CALLBACK(orient_north_action),FALSE } }; static guint n_toggleentries = G_N_ELEMENTS (toggleentries); -- cgit v1.2.1 From 09971fecdc51d82b58d1e4c4fa4702348bb9dc6f Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 16:33:20 +0000 Subject: Also display native coordinates in popup menu git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@45 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- popup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/popup.c b/popup.c index af9c01c0..cec4d601 100644 --- a/popup.c +++ b/popup.c @@ -290,6 +290,7 @@ popup(struct container *co, int x, int y, int button) transform_lng_lat(&popup->c, &g); strcpy(buffer,"Map Point "); transform_geo_text(&g, buffer+strlen(buffer)); + sprintf(buffer+strlen(buffer), " (0x%x,0x%x)", popup->c.x, popup->c.y); descr=popup_item_new_text(&list,buffer, 0); descr->param=popup; -- cgit v1.2.1 From fec2d9eb5828b200103498781c47eea369c2774c Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 16:34:10 +0000 Subject: Fix position interpolation git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@46 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 59 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/vehicle.c b/vehicle.c index 4816eb60..718de13d 100644 --- a/vehicle.c +++ b/vehicle.c @@ -14,6 +14,8 @@ #include "statusbar.h" #include "vehicle.h" +#define INTERPOLATION_TIME 50 + struct vehicle { GIOChannel *iochan; int timer_count; @@ -22,6 +24,7 @@ struct vehicle { double lat,lng; double height; double dir,speed; + double time; struct coord current_pos; struct coord_d curr; struct coord_d delta; @@ -36,20 +39,22 @@ struct vehicle { struct vehicle *vehicle_last; -#if 0 +#if INTERPOLATION_TIME static int vehicle_timer(gpointer t) { struct vehicle *this=t; - if (this->timer_count++ < 10) { - this->curr.x+=this->delta.x; - this->curr.y+=this->delta.y; - this->current_pos.x=this->curr.x; - this->current_pos.y=this->curr.y; - if (this->callback_func) - (*this->callback_func)(this->callback_data); - } - return TRUE; +/* if (this->timer_count++ < 1000/INTERPOLATION_TIME) { */ + if (this->delta.x || this->delta.y) { + this->curr.x+=this->delta.x; + this->curr.y+=this->delta.y; + this->current_pos.x=this->curr.x; + this->current_pos.y=this->curr.y; + if (this->callback_func) + (*this->callback_func)(this->callback_data); + } +/* } */ + return TRUE; } #endif @@ -148,8 +153,10 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) scale=transform_scale(this->current_pos.y); speed=this->speed+(this->speed-this->speed_last)/2; - this->delta.x=sin(M_PI*this->dir/180)*speed*scale/36; - this->delta.y=cos(M_PI*this->dir/180)*speed*scale/36; +#ifdef INTERPOLATION_TIME + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; +#endif this->speed_last=this->speed; } } @@ -192,17 +199,28 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) { struct vehicle *this=vehicle_last; double scale,speed; +#if INTERPOLATION_TIME + if (! (data->set & TIME_SET)) { + return; + } + data->set &= ~TIME_SET; + if (this->time == data->fix.time) + return; + this->time=data->fix.time; +#endif if (data->set & SPEED_SET) { this->speed_last=this->speed; - this->speed=data->fix.speed*1.852; + this->speed=data->fix.speed*3.6; data->set &= ~SPEED_SET; } if (data->set & TRACK_SET) { speed=this->speed+(this->speed-this->speed_last)/2; this->dir=data->fix.track; scale=transform_scale(this->current_pos.y); - this->delta.x=sin(M_PI*this->dir/180)*speed*scale/36; - this->delta.y=cos(M_PI*this->dir/180)*speed*scale/36; +#ifdef INTERPOLATION_TIME + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; +#endif data->set &= ~TRACK_SET; } if (data->set & LATLON_SET) { @@ -211,6 +229,7 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) transform_mercator(&this->lng, &this->lat, &this->current_pos); this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; + this->timer_count=0; if (this->callback_func) (*this->callback_func)(this->callback_data); data->set &= ~LATLON_SET; @@ -276,11 +295,15 @@ vehicle_new(const char *url) this->iochan=g_io_channel_unix_new(fd); g_io_channel_set_encoding(this->iochan, NULL, &error); g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); -#if 0 - g_timeout_add(100, vehicle_timer, this); -#endif this->current_pos.x=0x130000; this->current_pos.y=0x600000; + this->curr.x=this->current_pos.x; + this->curr.y=this->current_pos.y; + this->delta.x=0; + this->delta.y=0; +#if INTERPOLATION_TIME + g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this); +#endif return this; } -- cgit v1.2.1 From 8ff71ac8a09b98471c48095c1c44e2f5dc6ce140 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 16:34:47 +0000 Subject: Make it possible to skip coordinates git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@47 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- street_data.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/street_data.h b/street_data.h index a7701430..7f3a507c 100644 --- a/street_data.h +++ b/street_data.h @@ -49,8 +49,10 @@ static inline int street_get_coord(unsigned char **pos, int bytes, struct coord y|=(*p++) << 16; y|=(*p++) << 24; } - f->x=ref[0].x+x; - f->y=ref[1].y+y; + if (f) { + f->x=ref[0].x+x; + f->y=ref[1].y+y; + } #if 0 printf("0x%x,0x%x + 0x%x,0x%x = 0x%x,0x%x", x, y, ref[0].x, ref[1].y, f->x, f->y); #endif -- cgit v1.2.1 From 1323f4b3af3ae0d4841776a756f88d69c2048036 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 18:54:25 +0000 Subject: disable interpolation for now git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@48 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vehicle.c b/vehicle.c index 718de13d..69faf0c9 100644 --- a/vehicle.c +++ b/vehicle.c @@ -14,7 +14,7 @@ #include "statusbar.h" #include "vehicle.h" -#define INTERPOLATION_TIME 50 +/* #define INTERPOLATION_TIME 50 */ struct vehicle { GIOChannel *iochan; -- cgit v1.2.1 From 1226f5d4a7856cd3aad90fb7e10990669c53847e Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 1 Jan 2006 23:11:16 +0000 Subject: First try on tracking git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@49 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 4 +- container.h | 1 + cursor.c | 4 ++ main.c | 7 +- popup.c | 2 +- profile.c | 10 ++- street.c | 134 +++++++++++++++++++++++++++++++---- street.h | 3 + track.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ track.h | 5 ++ transform.c | 54 +++++++++++++- transform.h | 3 +- 12 files changed, 433 insertions(+), 24 deletions(-) create mode 100644 track.c create mode 100644 track.h diff --git a/Makefile.am b/Makefile.am index c169ff87..d0c586d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,12 +12,12 @@ bin_PROGRAMS = navit navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c destination.c \ display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ map-stubs.c map_data.c menu.c navigation.c param.c phrase.c plugin.c poly.c popup.c \ - profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c \ + profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c track.c \ util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ cursor.h data.h data_window.h data_window_int.h destination.h display.h draw_info.h \ file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ - street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h util.h vehicle.h + street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h track.h util.h vehicle.h navit_LDADD = @PACKAGE_LIBS@ gui/gtk/gtk.o graphics/gtk_drawing_area/gtk_drawing_area.o -Lfib-1.0 -lfib diff --git a/container.h b/container.h index 33433e4a..af6f7a6a 100644 --- a/container.h +++ b/container.h @@ -63,6 +63,7 @@ struct container { struct cursor *cursor; struct speech *speech; struct vehicle *vehicle; + struct track *track; struct data_window *data_window[data_window_type_end]; struct map_flags *flags; struct _GtkMap *map; diff --git a/cursor.c b/cursor.c index 9d3aaddb..951a2b83 100644 --- a/cursor.c +++ b/cursor.c @@ -15,6 +15,7 @@ #include "container.h" #include "cursor.h" #include "compass.h" +#include "track.h" #include "route.h" @@ -164,6 +165,9 @@ cursor_update(void *t) if (v) { pos=vehicle_pos_get(v); dir=vehicle_dir_get(v); + track_update(this->co->track, pos, (int)(*dir)); + if (this->co->flags->orient_north) + dir=0; route_set_position(this->co->route, cursor_pos_get(this->co->cursor)); if (!transform(this->co->trans, pos, &pnt)) { cursor_map_reposition(this, pos, dir); diff --git a/main.c b/main.c index e5eea70c..34ab1f75 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ #include "popup.h" #include "plugin.h" #include "compass.h" +#include "track.h" #include "container.h" @@ -51,6 +52,8 @@ int main(int argc, char **argv) plugin_load(); co=gui_gtk_window(1300000,7000000,8192); + co->route=route_new(); + route_mapdata_set(co->route, co->map_data); gps=getenv("GPSDATA"); if (gps) { co->vehicle=vehicle_new(gps); @@ -62,10 +65,10 @@ int main(int argc, char **argv) } co->speech=speech_new(); speech_handle=co->speech; - co->route=route_new(); if (co->vehicle) co->compass=compass_new(co); - route_mapdata_set(co->route, co->map_data); + if (co->vehicle) + co->track=track_new(co->map_data); #if 0 diff --git a/popup.c b/popup.c index cec4d601..b55ed86a 100644 --- a/popup.c +++ b/popup.c @@ -290,7 +290,7 @@ popup(struct container *co, int x, int y, int button) transform_lng_lat(&popup->c, &g); strcpy(buffer,"Map Point "); transform_geo_text(&g, buffer+strlen(buffer)); - sprintf(buffer+strlen(buffer), " (0x%x,0x%x)", popup->c.x, popup->c.y); + sprintf(buffer+strlen(buffer), " (0x%lx,0x%lx)", popup->c.x, popup->c.y); descr=popup_item_new_text(&list,buffer, 0); descr->param=popup; diff --git a/profile.c b/profile.c index 149c4ba5..e52622a5 100644 --- a/profile.c +++ b/profile.c @@ -8,13 +8,19 @@ profile_timer(char *where) { static struct timeval last; struct timeval curr; - int msec; + int msec,usec; if (where) { gettimeofday(&curr, NULL); msec=(curr.tv_usec-last.tv_usec)/1000+ (curr.tv_sec-last.tv_sec)*1000; - printf("%s:%d msec\n", where, msec); + if (msec >= 100) + printf("%s:%d msec\n", where, msec); + else { + usec=(curr.tv_usec-last.tv_usec)+(curr.tv_sec-last.tv_sec)*1000*1000; + printf("%s:%d usec\n", where, usec); + } + } gettimeofday(&last, NULL); } diff --git a/street.c b/street.c index 4634cca0..690c0649 100644 --- a/street.c +++ b/street.c @@ -143,6 +143,86 @@ street_coord_get_begin(unsigned char **p_p) *p_p=p; } +struct street_coord_handle +{ + unsigned char *p; + unsigned char *p_rewind; + unsigned char *next; + unsigned char *end; + int bytes; + int status; + int status_rewind; + struct coord *ref; +}; + +struct street_coord_handle * +street_coord_handle_new(struct block_info *blk_inf, struct street_str *str) +{ + struct street_coord_handle *ret; + unsigned char *p=(unsigned char *)(blk_inf->block); + struct block *blk; + struct street_header_type hdr_type; + struct street_str *str_curr; + int num; + + ret=g_new(struct street_coord_handle,1); + + ret->end=p; + blk=block_get(&p); + ret->end+=blk->size; + ret->bytes=street_get_bytes(blk); + ret->ref=blk->c; + + street_header_type_get(blk, &p, &hdr_type); + str_curr=(struct street_str *)p; + num=str-str_curr; + street_coord_get_begin(&p); + street_get_coord(&p, ret->bytes, blk->c, NULL); + while (num && str_curr->segid) { + while (! street_get_coord(&p, ret->bytes, blk->c, NULL) && p < ret->end) + ret->p=p; + str_curr++; + num--; + } + ret->status=str[1].segid > 0 ? 0:1; + ret->p_rewind=ret->p; + ret->status_rewind=ret->status; + + return ret; +} + +void +street_coord_handle_rewind(struct street_coord_handle *h) +{ + h->p=h->p_rewind; + h->status=h->status_rewind; +} + +int +street_coord_handle_get(struct street_coord_handle *h, struct coord *c) +{ + unsigned char *n; + + if (h->p >= h->end) + return 1; + if (h->status >= 4) + return 1; + n=h->p; + if (street_get_coord(&h->p, h->bytes, h->ref, c)) { + h->next=n; + h->status+=2; + if (h->status == 5) + return 1; + } + return 0; +} + +void +street_coord_handle_destroy(struct street_coord_handle *handle) +{ + g_free(handle); +} + void street_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) { @@ -280,29 +360,53 @@ street_coord_get(struct block_info *blk_inf, struct street_str *str) return ret; } -#if 0 -struct street_nearest * -street_find_nearest(struct map_data *mdata, struct coord *c) +struct street_get_block_param { - struct street_nearest *ret=g_new0(struct street_nearest,1); - struct transformation t; - int max_dist=1000; + void *data; + int (*callback)(struct street_str *str, struct street_coord_handle *h, void *data); +}; - transform_setup_source_rect_limit(&t,c,max_dist); +static void +street_get_block_process(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +{ + struct street_header_type header_type; + struct street_coord_handle h; + struct street_str *str; + int count; + struct street_get_block_param *param=(struct street_get_block_param *)data; - ret->click.xy=*c; - ret->dist=INT_MAX; - ret->mode=0; + street_header_type_get(blk_inf->block, &p, &header_type); - map_data_foreach(mdata, file_street_str, &t, 48, route_process_street_block, ret); + h.bytes=street_get_bytes(blk_inf->block); + h.end=end; + h.ref=blk_inf->block->c; - ret->mode=1; - ret->dist=INT_MAX; + str=(struct street_str *)p; + count=0; + street_coord_get_begin(&p); + h.p=p; - return ret; + while (str->segid) { + h.status=str[1].segid > 0 ? 0:1; + h.p_rewind=h.p; + h.status_rewind=h.status; + param->callback(str, &h, param->data); + while (! h.next && street_coord_handle_get(&h, NULL)); + h.p=h.next; + str++; + } } -#endif +void +street_get_block(struct map_data *mdata, struct transformation *t, void (*callback)(void *data), void *data) +{ + struct street_get_block_param param; + + param.callback=callback; + param.data=data; + map_data_foreach(mdata, file_street_str, t, 48, street_get_block_process, ¶m); + +} int street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str) diff --git a/street.h b/street.h index 65d024f1..194dbc38 100644 --- a/street.h +++ b/street.h @@ -1,6 +1,7 @@ struct container; struct block_info; struct segment; +struct street_coord_handle; struct street_header { unsigned char order; @@ -51,3 +52,5 @@ void street_bti_draw_block(struct block_info *blk_inf, unsigned char *start, uns int street_get_param(struct segment *seg, struct param_list *param, int count, int verbose); int street_bti_get_param(struct segment *seg, struct param_list *param, int count); void street_route_draw(struct container *co); +int street_coord_handle_get(struct street_coord_handle *h, struct coord *c); + diff --git a/track.c b/track.c new file mode 100644 index 00000000..050fe21b --- /dev/null +++ b/track.c @@ -0,0 +1,230 @@ +#include +#include +#include "coord.h" +#include "block.h" +#include "street.h" +#include "profile.h" +#include "track.h" + + +struct track_line +{ + long segid; + int linenum; + struct coord c[2]; + struct coord lpnt; + int value; + int angle; + int dir; + struct track_line *next; +}; + +struct track { + struct map_data *ma; + struct transformation t; + struct coord last_updated; + struct track_line *lines; + struct track_line **last_ptr; + struct coord curr[2]; + struct coord last_in; + struct coord last_out; +}; + +int angle_factor=5; +int connected_pref=-10; +int nostop_pref=10; + + +struct track_line **last; + +static void +tst_callback(struct street_str *str, void *handle, void *data) +{ + struct coord c[2]; + int visible=0,count=0; + struct track_line *lines; + int debug_segid=0; + int debug=0; + + /* printf("tst_callback id=0x%x ",str->segid < 0 ? -str->segid : str->segid); */ + if (! street_coord_handle_get(handle, &c[0])) { + if (str->segid == debug_segid) + printf("0x%lx,0x%lx ", c->x, c->y); + c[1]=c[0]; + while (! street_coord_handle_get(handle, &c[0])) { + if (is_line_visible(data, c)) { + visible=1; + } + c[1]=c[0]; + count++; + if (str->segid == debug_segid) + printf("0x%lx,0x%lx ", c->x, c->y); + } + } + if (visible) { + lines=g_new(struct track_line, count); + street_coord_handle_rewind(handle); + street_coord_handle_get(handle, &c[0]); + count=0; + while (! street_coord_handle_get(handle, &c[1])) { + *last=lines; + last=&lines->next; + lines->segid=str->segid; + lines->linenum=count; + lines->c[0]=c[0]; + lines->c[1]=c[1]; + lines->angle=transform_get_angle(c,0); + lines->next=NULL; + lines++; + count++; + c[0]=c[1]; + } + if (debug) + printf("%d lines\n", count); + } + /* printf("\n"); */ +} + +static void +track_doupdate_lines(struct track *tr, struct coord *c) +{ + + struct transformation t; + + tr->last_ptr=&tr->lines; + transform_setup_source_rect_limit(&t,c,1000); + transform_setup_source_rect_limit(&tr->t,c,1000); + + + profile_timer(NULL); + street_get_block(tr->ma,&t,tst_callback,tr); + profile_timer("end"); +} + +static void +track_free_lines(struct track *tr) +{ + struct track_line *tl=tr->lines,*next; + printf("track_free_lines(tr=%p)\n", tr); + + while (tl) { + next=tl->next; + if (! tl->linenum) { + g_free(tl); + } + tl=next; + } +} + +static int +track_angle_abs_diff(int a1, int a2, int full) +{ + int ret; + + if (a2 > a1) + ret=(a2-a1)%full; + else + ret=(a1-a2)%full; + if (ret > full/2) + ret=full-ret; + return ret; +} + +static int +track_angle_delta(int a1, int a2, int dir) +{ + if (! dir) + return track_angle_abs_diff(a1, a2, 180); + else + return track_angle_abs_diff(a1, a2, 360); +} + +static int +track_is_connected(struct coord *c1, struct coord *c2) +{ + if (c1[0].x == c2[0].x && c1[0].y == c2[0].y) + return 1; + if (c1[0].x == c2[1].x && c1[0].y == c2[1].y) + return 1; + if (c1[1].x == c2[0].x && c1[1].y == c2[0].y) + return 1; + if (c1[1].x == c2[1].x && c1[1].y == c2[1].y) + return 1; + return 0; +} + +void +track_update(struct track *tr, struct coord *c, int angle) +{ + struct track_line *t,*tm; + int min,dist; + int debug=0; + + if (c->x == tr->last_in.x && c->y == tr->last_in.y) { + *c=tr->last_out; + return; + } + if (transform_distance_sq(&tr->last_updated, c) > 250000 || !tr->lines) { + printf("update\n"); + track_free_lines(tr); + track_doupdate_lines(tr, c); + tr->last_updated=*c; + } + profile_timer(NULL); + + t=tr->lines; + g_assert(t != NULL); + + if (debug) printf("0x%lx,0x%lx (%d deg)\n", c->x, c->y, angle); + while (t) { + if (debug) printf("0x%lx 0x%lx,0x%lx - 0x%lx,0x%lx (%d deg) ", -t->segid, t->c[0].x, t->c[0].y, t->c[1].x, t->c[1].y, t->angle); + t->value=transform_distance_line_sq(&t->c[0], &t->c[1], c, &t->lpnt); + if (t->value < INT_MAX/2) + t->value += track_angle_delta(angle, t->angle, 0)*angle_factor; + if (track_is_connected(tr->curr, t->c)) + t->value += connected_pref; + if (t->lpnt.x == tr->last_out.x && t->lpnt.y == tr->last_out.y) + t->value += nostop_pref; + if (debug) printf(" %d\n", t->value); + t=t->next; + } + t=tr->lines; + tm=t; + min=t->value; + while (t) { + if (t->value < min) { + min=t->value; + tm=t; + } + t=t->next; + } + dist=transform_distance_sq(&tm->lpnt, c); + if (debug) printf("dist=%d id=0x%lx\n", dist, tm->segid); + *c=tm->lpnt; + tr->curr[0]=tm->c[0]; + tr->curr[1]=tm->c[1]; + tr->last_out=tm->lpnt; + + printf("pos 0x%lx,0x%lx value %d dist %d angle %d vs %d (%d)\n", c->x, c->y, tm->value, dist, angle, tm->angle, track_angle_delta(angle, tm->angle, 0)); + g_assert(dist < 10000); +#if 0 + profile_timer("track_update end"); +#endif + +} + +struct track * +track_new(struct map_data *ma) +{ + struct track *this=g_new(struct track, 1); + this->ma=ma; + + return this; +} + +void +track_destroy(struct track *tr) +{ + track_free_lines(tr); + g_free(tr); +} diff --git a/track.h b/track.h new file mode 100644 index 00000000..2b435e0f --- /dev/null +++ b/track.h @@ -0,0 +1,5 @@ +struct track; + +void track_update(struct track *tr, struct coord *c, int angle); +struct track * track_new(struct map_data *ma); +void track_destroy(struct track *tr); diff --git a/transform.c b/transform.c index a0f6fe6a..859e0e5a 100644 --- a/transform.c +++ b/transform.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "coord.h" #include "transform.h" @@ -237,6 +238,7 @@ transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref { int vx,vy,wx,wy; int c1,c2; + int climit=1000000; struct coord l; vx=l1->x-l0->x; @@ -256,7 +258,10 @@ transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref *lpnt=*l1; return transform_distance_sq(l1, ref); } - + while (c1 > climit || c2 > climit) { + c1/=256; + c2/=256; + } l.x=l0->x+vx*c1/c2; l.y=l0->y+vy*c1/c2; if (lpnt) @@ -291,6 +296,24 @@ is_visible(struct transformation *t, struct coord *c) return 1; } +int +is_line_visible(struct transformation *t, struct coord *c) +{ + struct coord *r=t->rect; + + assert(r[0].x <= r[1].x); + assert(r[0].y >= r[1].y); + if (MIN(c[0].x,c[1].x) > r[1].x) + return 0; + if (MAX(c[0].x,c[1].x) < r[0].x) + return 0; + if (MAX(c[0].y,c[1].y) < r[1].y) + return 0; + if (MIN(c[0].y,c[1].y) > r[0].y) + return 0; + return 1; +} + int is_point_visible(struct transformation *t, struct coord *c) { @@ -323,6 +346,32 @@ is_too_small(struct transformation *t, struct coord *c, int limit) return 0; } + +void transform_limit_extend(struct coord *rect, struct coord *c) +{ + if (c->x < rect[0].x) rect[0].x=c->x; + if (c->x > rect[1].x) rect[1].x=c->x; + if (c->y < rect[1].y) rect[1].y=c->y; + if (c->y > rect[0].y) rect[0].y=c->y; +} + + + +int +transform_get_angle(struct coord *c, int dir) +{ + double angle; + int dx=c[1].x-c[0].x; + int dy=c[1].y-c[0].y; + angle=atan2(dx,dy); + angle*=180/M_PI; + if (dir == -1) + angle=angle-180; + if (angle < 0) + angle+=360; + return angle; +} + /* Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. @@ -361,3 +410,6 @@ e = the first eccentricity of the ellipsoid */ + + + diff --git a/transform.h b/transform.h index fe0a0f23..7e509355 100644 --- a/transform.h +++ b/transform.h @@ -15,6 +15,7 @@ struct transformation { int transform(struct transformation *t, struct coord *c, struct point *p); int is_visible(struct transformation *t, struct coord *c); +int is_line_visible(struct transformation *t, struct coord *c); int is_too_small(struct transformation *t, struct coord *c, int limit); void transform_lng_lat(struct coord *c, struct coord_geo *g); void transform_reverse(struct transformation *t, struct point *p, struct coord *c); @@ -32,6 +33,6 @@ void transform_set_angle(struct transformation *t,int angle); void transform_setup(struct transformation *t, int x, int y, int scale, int angle); void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); void transform_geo_text(struct coord_geo *g, char *buffer); - +void transform_limit_extend(struct coord *rect, struct coord *c); #endif -- cgit v1.2.1 From 6c089e78d5b9dd69de0d4db2c1331628776772ab Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 2 Jan 2006 18:43:06 +0000 Subject: Fix for smp4.smp git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@50 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index f9ee2e95..9a755366 100644 --- a/block.c +++ b/block.c @@ -95,15 +95,17 @@ block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, if (val != -1) { dx=c[1].x-c[0].x; dy=c[0].y-c[1].y; - if (dy > dx) { - ca[0].y=val; - cb[1].y=val+1; - } else { - ca[1].x=val; - cb[0].x=val+1; + if (dx > 0 && dy > 0) { + if (dy > dx) { + ca[0].y=val; + cb[1].y=val+1; + } else { + ca[1].x=val; + cb[0].x=val+1; + } + ret+=block_binarytree_walk(block, p, ca, ign, blk_inf, t, data, func); + ret+=block_binarytree_walk(block, p, cb, ign, blk_inf, t, data, func); } - ret+=block_binarytree_walk(block, p, ca, ign, blk_inf, t, data, func); - ret+=block_binarytree_walk(block, p, cb, ign, blk_inf, t, data, func); } return ret; } -- cgit v1.2.1 From 5f3090080b3bb9ff5d67147505f5d0ff2e62869d Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 2 Jan 2006 20:46:14 +0000 Subject: Bugfixes git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@51 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 20 ++++++++++---------- track.c | 7 ++++--- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/block.c b/block.c index 9a755366..83637495 100644 --- a/block.c +++ b/block.c @@ -95,17 +95,15 @@ block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, if (val != -1) { dx=c[1].x-c[0].x; dy=c[0].y-c[1].y; - if (dx > 0 && dy > 0) { - if (dy > dx) { - ca[0].y=val; - cb[1].y=val+1; - } else { - ca[1].x=val; - cb[0].x=val+1; - } - ret+=block_binarytree_walk(block, p, ca, ign, blk_inf, t, data, func); - ret+=block_binarytree_walk(block, p, cb, ign, blk_inf, t, data, func); + if (dy > dx) { + ca[0].y=val; + cb[1].y=val+1; + } else { + ca[1].x=val; + cb[0].x=val+1; } + ret+=block_binarytree_walk(block, p, ca, ign, blk_inf, t, data, func); + ret+=block_binarytree_walk(block, p, cb, ign, blk_inf, t, data, func); } return ret; } @@ -187,6 +185,8 @@ block_foreach_visible(struct block_info *blk_inf, struct transformation *t, int dummy1=get_long(&p2); dummy2=get_long(&p2); assert((dummy1 == -1 && dummy2 == -1) || i < 32) ; + if (block->c[0].x > block->c[1].x || block->c[1].y > block->c[0].y) + break; count=block_binarytree_walk(&block, &p, block->c, 0, blk_inf, t, data, func); } } diff --git a/track.c b/track.c index 050fe21b..1f045671 100644 --- a/track.c +++ b/track.c @@ -42,6 +42,7 @@ tst_callback(struct street_str *str, void *handle, void *data) { struct coord c[2]; int visible=0,count=0; + struct track *tr=data; struct track_line *lines; int debug_segid=0; int debug=0; @@ -52,7 +53,7 @@ tst_callback(struct street_str *str, void *handle, void *data) printf("0x%lx,0x%lx ", c->x, c->y); c[1]=c[0]; while (! street_coord_handle_get(handle, &c[0])) { - if (is_line_visible(data, c)) { + if (is_line_visible(&tr->t, c)) { visible=1; } c[1]=c[0]; @@ -67,8 +68,8 @@ tst_callback(struct street_str *str, void *handle, void *data) street_coord_handle_get(handle, &c[0]); count=0; while (! street_coord_handle_get(handle, &c[1])) { - *last=lines; - last=&lines->next; + *(tr->last_ptr)=lines; + tr->last_ptr=&lines->next; lines->segid=str->segid; lines->linenum=count; lines->c[0]=c[0]; -- cgit v1.2.1 From 43b81c26bc072a6f35d9e4a0780515e0ab21c4ce Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 3 Jan 2006 19:46:11 +0000 Subject: fix segfault git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@52 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- track.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/track.c b/track.c index 1f045671..4ad70962 100644 --- a/track.c +++ b/track.c @@ -115,6 +115,7 @@ track_free_lines(struct track *tr) } tl=next; } + tr->lines=NULL; } static int @@ -217,7 +218,7 @@ track_update(struct track *tr, struct coord *c, int angle) struct track * track_new(struct map_data *ma) { - struct track *this=g_new(struct track, 1); + struct track *this=g_new0(struct track, 1); this->ma=ma; return this; -- cgit v1.2.1 From 5ca46436d55843ed9d808e235e67c9f8c3b50894 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 3 Jan 2006 20:05:42 +0000 Subject: Better debugging support git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@53 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 4 ++-- debug.c | 30 ++++++++++++++++++++++++++++++ debug.h | 1 + file.c | 34 ++++++++++++++++++++++++++-------- file.h | 5 ++++- main.c | 3 ++- 6 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 debug.c create mode 100644 debug.h diff --git a/Makefile.am b/Makefile.am index d0c586d0..84c633af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,12 +9,12 @@ AM_CPPFLAGS = @PACKAGE_CFLAGS@ bin_PROGRAMS = navit -navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c destination.c \ +navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c debug.c destination.c \ display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ map-stubs.c map_data.c menu.c navigation.c param.c phrase.c plugin.c poly.c popup.c \ profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c track.c \ util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ - cursor.h data.h data_window.h data_window_int.h destination.h display.h draw_info.h \ + cursor.h data.h data_window.h data_window_int.h debug.h destination.h display.h draw_info.h \ file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h track.h util.h vehicle.h diff --git a/debug.c b/debug.c new file mode 100644 index 00000000..68edf710 --- /dev/null +++ b/debug.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "file.h" +#include "debug.h" + + + +static int sigsegv(void) +{ + FILE *f; + time_t t; + printf("segmentation fault received\n"); + f=fopen("crash.txt","a"); + setvbuf(f, NULL, _IONBF, 0); + fprintf(f,"segmentation fault received\n"); + t=time(NULL); + fprintf(f,"Time: %s", ctime(&t)); + file_remap_readonly_all(); + fprintf(f,"dumping core\n"); + fclose(f); + abort(); +} + +void +debug_init(void) +{ + signal(SIGSEGV, sigsegv); +} diff --git a/debug.h b/debug.h new file mode 100644 index 00000000..fb9abbc9 --- /dev/null +++ b/debug.h @@ -0,0 +1 @@ +void debug_init(void); diff --git a/file.c b/file.c index 2389d8a7..eb85ea18 100644 --- a/file.c +++ b/file.c @@ -9,25 +9,26 @@ #include #include "file.h" +static struct file *file_list; + struct file * file_create(char *name) { - int fd; struct stat stat; struct file *file=malloc(sizeof(*file)+strlen(name)+1); if (! file) return file; - fd=open(name, O_RDONLY); - if (fd < 0) { + file->fd=open(name, O_RDONLY); + if (file->fd < 0) { free(file); return NULL; } - fstat(fd, &stat); + fstat(file->fd, &stat); file->size=stat.st_size; file->name=(char *)file+sizeof(*file); strcpy(file->name, name); - file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0); g_assert(file->begin != NULL); if (file->begin == (void *)0xffffffff) { perror("mmap"); @@ -35,16 +36,32 @@ file_create(char *name) g_assert(file->begin != (void *)0xffffffff); file->end=file->begin+file->size; file->private=NULL; - close(fd); g_assert(file != NULL); + file->next=file_list; + file_list=file; return file; } void -file_set_readonly(struct file *file) +file_remap_readonly(struct file *f) +{ + void *begin; + munmap(f->begin, f->size); + begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0); + if (f->begin != begin) + printf("remap failed\n"); +} + +void +file_remap_readonly_all(void) { - mprotect(file->begin, file->end-file->begin, PROT_READ); + struct file *f=file_list; + + while (f) { + file_remap_readonly(f); + f=f->next; + } } void * @@ -110,6 +127,7 @@ file_create_caseinsensitive(char *name) void file_destroy(struct file *f) { + close(f->fd); munmap(f->begin, f->size); free(f); } diff --git a/file.h b/file.h index 4dedb894..e8e00cc9 100644 --- a/file.h +++ b/file.h @@ -6,10 +6,13 @@ struct file { unsigned long size; char *name; void *private; + int fd; + struct file *next; }; struct file *file_create(char *name); -void file_set_readonly(struct file *file); +void file_remap_readonly(struct file *file); +void file_remap_readonly_all(void); struct file *file_create_caseinsensitive(char *name); int file_get_param(struct file *file, struct param_list *param, int count); void file_destroy(struct file *f); diff --git a/main.c b/main.c index 34ab1f75..434f244e 100644 --- a/main.c +++ b/main.c @@ -19,7 +19,7 @@ #include "compass.h" #include "track.h" #include "container.h" - +#include "debug.h" void *speech_handle; @@ -45,6 +45,7 @@ int main(int argc, char **argv) setlocale(LC_NUMERIC,"C"); gtk_set_locale(); setlocale(LC_NUMERIC,"C"); + debug_init(); gtk_init(&argc, &argv); gdk_rgb_init(); -- cgit v1.2.1 From d20ddd91dad0fd1ddf8c2c6634ae9fc342ee8a6e Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 3 Jan 2006 20:50:05 +0000 Subject: don't ignore orient_north git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@54 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- compass.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compass.c b/compass.c index 6dd1b9c6..f907ef0a 100644 --- a/compass.c +++ b/compass.c @@ -79,7 +79,10 @@ compass_draw(struct compass *comp, struct container *co) p.x=30; p.y=30; comp->gr->draw_circle(comp->gr, comp->white, &p, 50); - handle(comp->gr, comp->white, &p, 20, -*vehicle_dir); + if (co->flags->orient_north) + handle(comp->gr,comp->white, &p, 20,0); + else + handle(comp->gr, comp->white, &p, 20, -*vehicle_dir); dest=route_get_destination(co->route); if (dest) { pos=vehicle_pos_get(co->vehicle); -- cgit v1.2.1 From 1413848bc67a5bcbfafbd91b103fd5566808e1b6 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 3 Jan 2006 21:37:48 +0000 Subject: Converting speech.c to new speechd api git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@55 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- phrase.c | 2 +- popup.c | 1 + speech.c | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/phrase.c b/phrase.c index f1f18af7..761de5a1 100644 --- a/phrase.c +++ b/phrase.c @@ -21,6 +21,6 @@ phrase_route_calculated(void *speech, void *route) eta=route_get_eta(route); - speech_sayf(speech,"Die Route wurde berechnet. Geschätzte Ankunftszeit %d Uhr %d Entfernung %4.0f Kilometer", eta->tm_hour,eta->tm_min,route_get_len(route)/1000); + speech_sayf(speech,"Die Route wurde berechnet, geschätzte Ankunftszeit %d Uhr %d Entfernung %4.0f Kilometer", eta->tm_hour,eta->tm_min,route_get_len(route)/1000); } diff --git a/popup.c b/popup.c index b55ed86a..6aaaef24 100644 --- a/popup.c +++ b/popup.c @@ -118,6 +118,7 @@ popup_set_position(struct popup_item *item, void *param) struct popup_item *ref=param; struct popup *popup=ref->param; printf("Position %s\n", ref->text); + g_assert(popup->co->vehicle != NULL); vehicle_set_position(popup->co->vehicle, &popup->c); } diff --git a/speech.c b/speech.c index 0cb39e1b..fa9ab333 100644 --- a/speech.c +++ b/speech.c @@ -1,5 +1,5 @@ /* speechd simple client program - * CVS revision: $Id: speech.c,v 1.3 2005-12-02 13:26:31 martin-s Exp $ + * CVS revision: $Id: speech.c,v 1.4 2006-01-03 21:37:48 martin-s Exp $ * Author: Tomas Cerha */ #include @@ -18,25 +18,24 @@ #include "speech.h" struct speech { - int sockfd; +#ifdef HAVE_LIBSPEECHD + SPDConnection *conn; +#endif }; struct speech * speech_new(void) { #ifdef HAVE_LIBSPEECHD struct speech *this; - int sockfd; + SPDConnection *conn; -#ifdef SPD_FATAL - sockfd = spd_open("map","main",NULL); -#else - sockfd = spd_init("map","main"); -#endif - if (sockfd == 0) + conn = spd_open("navit","main",NULL,SPD_MODE_SINGLE); + if (! conn) return NULL; this=g_new(struct speech,1); if (this) { - this->sockfd=sockfd; + this->conn=conn; + spd_set_punctuation(conn, SPD_PUNCT_NONE); } return this; #else @@ -49,7 +48,7 @@ speech_say(struct speech *this, char *text) { #ifdef HAVE_LIBSPEECHD int err; - err = spd_sayf(this->sockfd, 2, text); + err = spd_sayf(this->conn, SPD_MESSAGE, text); if (err != 1) return 1; #endif @@ -72,7 +71,7 @@ speech_sayf(struct speech *this, char *format, ...) { int speech_destroy(struct speech *this) { #ifdef HAVE_LIBSPEECHD - spd_close(this->sockfd); + spd_close(this->conn); g_free(this); #endif return 0; -- cgit v1.2.1 From b3a6b03439eaf37e3eb74d40db72d5cde7ef4eb6 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 3 Jan 2006 22:12:44 +0000 Subject: Speak navigation commands git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@56 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navigation.c | 72 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/navigation.c b/navigation.c index 3f381244..4bb2abd8 100644 --- a/navigation.c +++ b/navigation.c @@ -97,18 +97,18 @@ maneuver_required(struct navigation_item *old, struct navigation_item *new, int return 1; } -int flag; +int flag,old_level; extern void *speech_handle; static void make_maneuver(struct navigation_item *old, struct navigation_item *new) { - int delta; + int delta,navmode=1,add_dir,level; struct param_list param_list[20]; - char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30]; - char command[256],*p,*dir; + char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; + char command[256],*p,*dir,*strength; param_list[0].name="Name1 Old"; param_list[0].value=old->name1; @@ -118,12 +118,13 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) param_list[2].value=new->name1; param_list[3].name="Name2 New"; param_list[3].value=new->name2; - param_list[4].name="Angle Old"; - param_list[5].name="Angle New"; + param_list[4].name="Angle\nOld"; + param_list[5].name="Angle\nNew"; param_list[6].name="Delta"; - param_list[7].name="Cross-Roads"; + param_list[7].name="X-\nRoads"; param_list[8].name="Position"; - param_list[9].name="Command"; + param_list[9].name="Dist"; + param_list[10].name="Command"; if (old->points) { if (!maneuver_required(old, new, &delta)) { old->length+=new->length; @@ -142,32 +143,59 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) param_list[7].value=cross_roads; sprintf(position,"0x%lx,0x%lx", new->start.x, new->start.y); param_list[8].value=position; - sprintf(command,"Dem Strassenverlauf %d Meter folgen, dann ", old->length); - p=command+strlen(command); + sprintf(distance,"%d", old->length); + param_list[9].value=distance; + add_dir=1; dir="rechts"; if (delta < 0) { dir="links"; delta=-delta; } if (delta < 45) { - strcpy(p,"leicht "); + strength="leicht "; } else if (delta < 105) { + strength=""; } else if (delta < 165) { - strcpy(p,"scharf "); + strength="scharf "; } - p+=strlen(p); - strcpy(p,dir); - p+=strlen(p); - strcpy(p," abbiegen"); - param_list[9].value=command; + level=0; + if (navmode) { + if (old->length < 20) { + level=1; + sprintf(command,"Jetzt "); + } else if (old->length <= 200) { + level=2; + sprintf(command,"In %d Metern ", old->length); + } else if (old->length <= 500) { + level=3; + sprintf(command,"In Kürze "); + } else { + level=4; + sprintf(command,"Dem Strassenverlauf %d Meter folgen", old->length); + add_dir=0; + } + } else { + sprintf(command,"Dem Strassenverlauf %d Meter folgen, dann ", old->length); + add_dir=1; + } + if (add_dir) { + p=command+strlen(command); + strcpy(p,strength); + p+=strlen(p); + strcpy(p,dir); + p+=strlen(p); + strcpy(p," abbiegen"); + } + param_list[10].value=command; if (flag) { -#if 0 - printf("command='%s'\n", command); - speech_say(speech_handle, command); -#endif + if (level != old_level) { + printf("command='%s'\n", command); + speech_say(speech_handle, command); + old_level=level; + } flag=0; } - data_window_add(navigation_window, param_list, 10); + data_window_add(navigation_window, param_list, 11); *old=*new; } } else { -- cgit v1.2.1 From c695377efc4881279211c6e19115e09739c503fa Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 3 Jan 2006 22:20:09 +0000 Subject: improve memory allocation und fix some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@57 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- plugins/poi_geodownload/poi.c | 4 ++-- popup.c | 3 +-- route.c | 2 +- street.c | 2 +- street.h | 5 +++++ transform.h | 1 + vehicle.c | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/poi_geodownload/poi.c b/plugins/poi_geodownload/poi.c index 9b6ef93e..26b81a1e 100644 --- a/plugins/poi_geodownload/poi.c +++ b/plugins/poi_geodownload/poi.c @@ -283,7 +283,7 @@ load_poi(char *filename, char *icon) int i; MdbCatalogEntry *entry; GPtrArray *catalog; - struct poi *new = g_new(struct poi, 1); + struct poi *new = g_new0(struct poi, 1); new->filename = filename; new->icon = icon; @@ -295,7 +295,7 @@ load_poi(char *filename, char *icon) if (!strcasecmp(entry->object_name, "_INDEXDATA")) { if (load_poi_table(new, entry)) { printf("%s invalid\n", filename); - free(new); + g_free(new); new=NULL; } } diff --git a/popup.c b/popup.c index 6aaaef24..5c3b8bf9 100644 --- a/popup.c +++ b/popup.c @@ -32,8 +32,7 @@ struct popup_item * popup_item_new_text(struct popup_item **last, char *text, int priority) { struct popup_item *curr; - curr=g_new(struct popup_item,1); - memset(curr, 0, sizeof(*curr)); + curr=g_new0(struct popup_item,1); curr->text=g_strdup(text); curr->priority=priority; curr->destroy=popup_item_destroy_text; diff --git a/route.c b/route.c index c8b88a36..ad7b9c52 100644 --- a/route.c +++ b/route.c @@ -336,7 +336,7 @@ static void route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, int offset, int limit) { struct route_segment *s; - s=g_new(struct route_segment,1); + s=g_new0(struct route_segment,1); s->start=start; s->start_next=start->start; start->start=s; diff --git a/street.c b/street.c index 690c0649..b38e31df 100644 --- a/street.c +++ b/street.c @@ -165,7 +165,7 @@ street_coord_handle_new(struct block_info *blk_inf, struct street_str *str) struct street_str *str_curr; int num; - ret=g_new(struct street_coord_handle,1); + ret=g_new0(struct street_coord_handle,1); ret->end=p; blk=block_get(&p); diff --git a/street.h b/street.h index 194dbc38..4e85f5d3 100644 --- a/street.h +++ b/street.h @@ -47,6 +47,11 @@ struct street_coord { void street_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); struct street_coord *street_coord_get(struct block_info *blk_inf, struct street_str *str); +struct street_coord_handle * street_coord_handle_new(struct block_info *blk_inf, struct street_str *str); +void street_coord_handle_rewind(struct street_coord_handle *h); +int street_coord_handle_get(struct street_coord_handle *h, struct coord *c); +void street_coord_handle_destroy(struct street_coord_handle *handle); +void street_get_block(struct map_data *mdata, struct transformation *t, void (*callback)(void *data), void *data); int street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str); void street_bti_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); int street_get_param(struct segment *seg, struct param_list *param, int count, int verbose); diff --git a/transform.h b/transform.h index 7e509355..f2099d25 100644 --- a/transform.h +++ b/transform.h @@ -34,5 +34,6 @@ void transform_setup(struct transformation *t, int x, int y, int scale, int angl void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); void transform_geo_text(struct coord_geo *g, char *buffer); void transform_limit_extend(struct coord *rect, struct coord *c); +int transform_get_angle(struct coord *c, int dir); #endif diff --git a/vehicle.c b/vehicle.c index 69faf0c9..e62e093f 100644 --- a/vehicle.c +++ b/vehicle.c @@ -288,7 +288,7 @@ vehicle_new(const char *url) return NULL; #endif } - this=g_new(struct vehicle,1); + this=g_new0(struct vehicle,1); #ifdef HAVE_LIBGPS this->gps=gps; #endif -- cgit v1.2.1 From 75b89bd83cb323635dbc9b87060ec0df57d98d86 Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 4 Jan 2006 10:00:50 +0000 Subject: replace some mallocs git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@58 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics/gtk_drawing_area/graphics_gtk_drawing_area.c | 13 +++++-------- gui/gtk/gui_gtk_menu.c | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index b5d06474..5402ee5b 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -238,7 +238,7 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int FT_Vector pen; FT_UInt glyph_index; int n,len=strlen(text); - struct text_render *ret=malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); + struct text_render *ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); struct text_glyph *curr; ret->glyph_count=len; @@ -262,7 +262,7 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT ); FT_Render_Glyph(font->face->glyph, ft_render_mode_normal ); - curr=malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch); + curr=g_malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch); ret->glyph[n]=curr; curr->x=(x>>6)+slot->bitmap_left; @@ -320,14 +320,11 @@ display_text_free(struct text_render *text) i=text->glyph_count; while (i-- > 0) { if ((*gp)->shadow) { - gdk_image_destroy((*gp)->shadow); -#if 0 - free((*gp)->shadow->mem); -#endif + g_object_unref((*gp)->shadow); } - free(*gp++); + g_free(*gp++); } - free(text); + g_free(text); } static void diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c index 0aa2d3f0..6f6b22b2 100644 --- a/gui/gtk/gui_gtk_menu.c +++ b/gui/gtk/gui_gtk_menu.c @@ -299,7 +299,7 @@ gui_gtk_menu_new(struct container *co, GtkWidget **widget) file=fopen("locations.txt","r"); while (file && fgets(buffer,8192,file)) { - dest=malloc(sizeof(*dest)); + dest=g_new0(struct destination,1); dest->co=co; len=strlen(buffer)-1; while (len >= 0 && buffer[len] == '\n') { -- cgit v1.2.1 From 9aa3ba233c9944063fa453fe0b75a90c54ffbf53 Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 4 Jan 2006 11:56:01 +0000 Subject: use orient_north for destination arrow, too git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@59 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- compass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compass.c b/compass.c index f907ef0a..4daa430f 100644 --- a/compass.c +++ b/compass.c @@ -92,7 +92,8 @@ compass_draw(struct compass *comp, struct container *co) #if 0 printf("dx %d dy %d dir=%f vehicle_dir=%f\n", dx, dy, dir, *vehicle_dir); #endif - dir-=*vehicle_dir; + if (! co->flags->orient_north) + dir-=*vehicle_dir; handle(comp->gr, comp->green, &p, 20, dir); p.x=8; p.y=72; -- cgit v1.2.1 From 26c87195a78e0eaf64c61fc49c29eab247975ffb Mon Sep 17 00:00:00 2001 From: horwitz Date: Thu, 5 Jan 2006 00:56:37 +0000 Subject: fix warning git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@60 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- street.h | 1 + 1 file changed, 1 insertion(+) diff --git a/street.h b/street.h index 4e85f5d3..9f9149d3 100644 --- a/street.h +++ b/street.h @@ -1,6 +1,7 @@ struct container; struct block_info; struct segment; +struct transformation; struct street_coord_handle; struct street_header { -- cgit v1.2.1 From b8bfdaae035a95e7fbcccc7782a7a906195b9bc9 Mon Sep 17 00:00:00 2001 From: horwitz Date: Thu, 5 Jan 2006 01:01:45 +0000 Subject: remove more mallocs and frees git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@61 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 5 ++--- file.c | 11 +++++----- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 2 +- popup.c | 25 ++++++++++------------ street.c | 3 +-- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/block.c b/block.c index 83637495..8081e92f 100644 --- a/block.c +++ b/block.c @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include "file.h" #include "block.h" #include "data.h" @@ -116,9 +116,8 @@ block_file_private_setup(struct file *file) char *str; struct file_private *file_priv; - file_priv=malloc(sizeof(*file_priv)); + file_priv=g_malloc0(sizeof(*file_priv)); file->private=file_priv; - memset(file_priv, 0, sizeof(*file_priv)); p=file->begin+0x0c; while (*p) { diff --git a/file.c b/file.c index eb85ea18..cdff8733 100644 --- a/file.c +++ b/file.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -15,19 +14,18 @@ struct file * file_create(char *name) { struct stat stat; - struct file *file=malloc(sizeof(*file)+strlen(name)+1); + struct file *file= g_new0(struct file,1); if (! file) return file; file->fd=open(name, O_RDONLY); if (file->fd < 0) { - free(file); + g_free(file); return NULL; } fstat(file->fd, &stat); file->size=stat.st_size; - file->name=(char *)file+sizeof(*file); - strcpy(file->name, name); + file->name = g_strdup(name); file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0); g_assert(file->begin != NULL); if (file->begin == (void *)0xffffffff) { @@ -129,7 +127,8 @@ file_destroy(struct file *f) { close(f->fd); munmap(f->begin, f->size); - free(f); + g_free(f->name); + g_free(f); } int diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 5402ee5b..903148ca 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -195,7 +195,7 @@ display_text_render_shadow(struct text_glyph *g) unsigned char *p, *pm=g->pixmap; GdkImage *ret; - shadow=malloc(str*(g->h+2)); + shadow=malloc(str*(g->h+2)); /* do not use g_malloc() here */ memset(shadow, 0, str*(g->h+2)); for (y = 0 ; y < h ; y++) { p=shadow+str*y; diff --git a/popup.c b/popup.c index 5c3b8bf9..bf6fea08 100644 --- a/popup.c +++ b/popup.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -61,19 +60,20 @@ param_to_menu_new(char *name,struct param_list *plist, int c, int iso) ret=popup_item_new_text(NULL,name,1); last=NULL; for (i = 0 ; i < c ; i++) { - char name_buffer[strlen(plist[i].name)+strlen(plist[i].value)+2]; - char *text=name_buffer; + char *name_buffer = g_strjoin(":",plist[i].name, plist[i].value,NULL); + char *text = name_buffer; - sprintf(name_buffer,"%s:%s", plist[i].name, plist[i].value); if (iso) { text=g_convert(name_buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); if (! text) { printf("problem converting '%s'\n", name_buffer); } } - curr=popup_item_new_text(&last, text, i); + curr=popup_item_new_text(&last,text,i); if (iso) - free(text); + g_free(text); + g_free(name_buffer); + } ret->submenu=last; return ret; @@ -194,17 +194,14 @@ popup_display_list_default(struct display_list *d, struct popup_item **popup_lis if (d->type == 4) desc="Point"; seg=(struct segment *)(d->data); if (seg) { - if (d->label && strlen(d->label)) { - item_text=malloc(strlen(desc)+strlen(d->label)+2); - strcpy(item_text, desc); - strcat(item_text," "); - strcat(item_text, d->label); - } else { - item_text=desc; - } + if (d->label && strlen(d->label)) + item_text=g_strjoin(" ",desc,d->label,NULL); + else + item_text=g_strdup(desc); text=g_convert(item_text,-1,"utf-8","iso8859-1",NULL,NULL,NULL); curr_item=popup_item_new_text(popup_list,text,1); g_free(text); + g_free(item_text); curr_item->submenu=param_to_menu_new("File", plist, file_get_param(seg->blk_inf.file, plist, 100), 1); submenu=curr_item->submenu; diff --git a/street.c b/street.c index b38e31df..05601358 100644 --- a/street.c +++ b/street.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include "container.h" @@ -349,7 +348,7 @@ street_coord_get(struct block_info *blk_inf, struct street_str *str) if (debug) printf("p=%p points=%d\n",p_sav, points); p=p_sav; - ret=malloc(sizeof(struct street_coord)+points*sizeof(struct coord)); + ret=g_malloc(sizeof(struct street_coord)+points*sizeof(struct coord)); ret->count=points; c=ret->c; while (points) { -- cgit v1.2.1 From aecce4bec7aab3400f3cc16570f53e49525a095d Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jan 2006 16:40:39 +0000 Subject: Bugfix for street popup, unmap map files before core dump git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@62 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- debug.c | 2 +- file.c | 23 ++++++++++++++++++++++- file.h | 2 ++ street.c | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/debug.c b/debug.c index 68edf710..3c19218e 100644 --- a/debug.c +++ b/debug.c @@ -17,7 +17,7 @@ static int sigsegv(void) fprintf(f,"segmentation fault received\n"); t=time(NULL); fprintf(f,"Time: %s", ctime(&t)); - file_remap_readonly_all(); + file_unmap_all(); fprintf(f,"dumping core\n"); fclose(f); abort(); diff --git a/file.c b/file.c index cdff8733..b097261a 100644 --- a/file.c +++ b/file.c @@ -55,13 +55,34 @@ void file_remap_readonly_all(void) { struct file *f=file_list; + int limit=1000; - while (f) { + while (f && limit-- > 0) { file_remap_readonly(f); f=f->next; } } +void +file_unmap(struct file *f) +{ + munmap(f->begin, f->size); +} + +void +file_unmap_all(void) +{ + struct file *f=file_list; + int limit=1000; + + while (f && limit-- > 0) { + file_unmap(f); + f=f->next; + } +} + + + void * file_opendir(char *dir) { diff --git a/file.h b/file.h index e8e00cc9..f020ee47 100644 --- a/file.h +++ b/file.h @@ -13,6 +13,8 @@ struct file { struct file *file_create(char *name); void file_remap_readonly(struct file *file); void file_remap_readonly_all(void); +void file_unmap(struct file *file); +void file_unmap_all(void); struct file *file_create_caseinsensitive(char *name); int file_get_param(struct file *file, struct param_list *param, int count); void file_destroy(struct file *f); diff --git a/street.c b/street.c index 05601358..3fb5e239 100644 --- a/street.c +++ b/street.c @@ -466,7 +466,7 @@ street_get_param(struct segment *seg, struct param_list *param, int count, int v param_add_hex("Unknown3", str->unknown3, ¶m, &count); param_add_hex("Type", str->type, ¶m, &count); param_add_hex("Name-Id", str->nameid, ¶m, &count); - if (str->segid) { + if (str->segid && str->nameid) { street_name_get_by_id(&name, seg->blk_inf.mdata, str->nameid); param_add_hex("Len", name.len, ¶m, &count); -- cgit v1.2.1 From 4bedcd99738f5fec3f6baf32f892407f4084c8ce Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jan 2006 22:35:21 +0000 Subject: Improvements in Navigation git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@63 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navigation.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- script/gps_emu2 | 6 ++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/navigation.c b/navigation.c index 4bb2abd8..d70fc593 100644 --- a/navigation.c +++ b/navigation.c @@ -100,6 +100,51 @@ maneuver_required(struct navigation_item *old, struct navigation_item *new, int int flag,old_level; extern void *speech_handle; +static void +get_distance(char *dst, int dist) +{ + if (dist < 100) { + dist=(dist+5)/10; + dist*=10; + sprintf(dst,"%d meter", dist); + return; + } + if (dist < 250) { + dist=(dist+13)/25; + dist*=25; + sprintf(dst,"%d meter", dist); + return; + } + if (dist < 500) { + dist=(dist+25)/50; + dist*=50; + sprintf(dst,"%d meter", dist); + return; + } + if (dist < 1000) { + dist=(dist+50)/100; + dist*=100; + sprintf(dst,"%d meter", dist); + return; + } + if (dist < 5000) { + dist=(dist+50)/100; + if (dist % 10) + sprintf(dst,"%d,%d kilometer", dist/10,dist%10); + else + sprintf(dst,"%d kilometer", dist/10); + return; + } + if (dist < 100000) { + dist=(dist+500)/1000; + sprintf(dst,"%d kilometer", dist); + return; + } + dist=(dist+5000)/10000; + dist*=10; + sprintf(dst,"%d kilometer", dist); +} + static void make_maneuver(struct navigation_item *old, struct navigation_item *new) { @@ -109,6 +154,7 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; char command[256],*p,*dir,*strength; + char dist[256]; param_list[0].name="Name1 Old"; param_list[0].value=old->name1; @@ -157,6 +203,9 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) strength=""; } else if (delta < 165) { strength="scharf "; + } else { + printf("delta=%d\n", delta); + strength="unbekannt "; } level=0; if (navmode) { @@ -165,13 +214,15 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) sprintf(command,"Jetzt "); } else if (old->length <= 200) { level=2; - sprintf(command,"In %d Metern ", old->length); + get_distance(dist, old->length); + sprintf(command,"In %sn ", dist); } else if (old->length <= 500) { level=3; sprintf(command,"In Kürze "); } else { level=4; - sprintf(command,"Dem Strassenverlauf %d Meter folgen", old->length); + get_distance(dist, old->length); + sprintf(command,"Dem Strassenverlauf %s folgen", dist); add_dir=0; } } else { diff --git a/script/gps_emu2 b/script/gps_emu2 index 8f5d9a61..e9e79b42 100755 --- a/script/gps_emu2 +++ b/script/gps_emu2 @@ -9,6 +9,12 @@ read(FILE,$header,64); select STDOUT; $| = 1; +$count=$ARGV[1]; +while ($count) { + read(FILE,$record,64); + $count--; +} + while (read(FILE,$record,64)) { ($flags,$status,$mode,$hdop,$vdop,$pdop,$sats,$timestampl,$timestamph,$latitude,$longitude,$altitude,$speed,$direction)=unpack("SCCCCCCLLddddd",$record); -- cgit v1.2.1 From 4188fed34dfa95bf0515772bd6fd77bf77dd5a2a Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 6 Jan 2006 10:08:15 +0000 Subject: Minor improvement in API git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@64 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- street.c | 33 +++++++++++++++++++-------------- street.h | 3 +-- track.c | 8 ++++---- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/street.c b/street.c index 3fb5e239..04ecb2b4 100644 --- a/street.c +++ b/street.c @@ -198,22 +198,27 @@ street_coord_handle_rewind(struct street_coord_handle *h) } int -street_coord_handle_get(struct street_coord_handle *h, struct coord *c) +street_coord_handle_get(struct street_coord_handle *h, struct coord *c, int count) { unsigned char *n; - - if (h->p >= h->end) - return 1; - if (h->status >= 4) - return 1; - n=h->p; - if (street_get_coord(&h->p, h->bytes, h->ref, c)) { - h->next=n; - h->status+=2; - if (h->status == 5) - return 1; + int ret=0; + + while (count > 0) { + if (h->p >= h->end) + return ret; + if (h->status >= 4) + return ret; + n=h->p; + if (street_get_coord(&h->p, h->bytes, h->ref, c)) { + h->next=n; + h->status+=2; + if (h->status == 5) + return ret; + } + c++; + ret++; } - return 0; + return ret; } void @@ -390,7 +395,7 @@ street_get_block_process(struct block_info *blk_inf, unsigned char *p, unsigned h.p_rewind=h.p; h.status_rewind=h.status; param->callback(str, &h, param->data); - while (! h.next && street_coord_handle_get(&h, NULL)); + while (! h.next && street_coord_handle_get(&h, NULL, 1)); h.p=h.next; str++; } diff --git a/street.h b/street.h index 9f9149d3..7438acc9 100644 --- a/street.h +++ b/street.h @@ -50,7 +50,7 @@ void street_draw_block(struct block_info *blk_inf, unsigned char *start, unsigne struct street_coord *street_coord_get(struct block_info *blk_inf, struct street_str *str); struct street_coord_handle * street_coord_handle_new(struct block_info *blk_inf, struct street_str *str); void street_coord_handle_rewind(struct street_coord_handle *h); -int street_coord_handle_get(struct street_coord_handle *h, struct coord *c); +int street_coord_handle_get(struct street_coord_handle *h, struct coord *c, int count); void street_coord_handle_destroy(struct street_coord_handle *handle); void street_get_block(struct map_data *mdata, struct transformation *t, void (*callback)(void *data), void *data); int street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str); @@ -58,5 +58,4 @@ void street_bti_draw_block(struct block_info *blk_inf, unsigned char *start, uns int street_get_param(struct segment *seg, struct param_list *param, int count, int verbose); int street_bti_get_param(struct segment *seg, struct param_list *param, int count); void street_route_draw(struct container *co); -int street_coord_handle_get(struct street_coord_handle *h, struct coord *c); diff --git a/track.c b/track.c index 4ad70962..47e68164 100644 --- a/track.c +++ b/track.c @@ -48,11 +48,11 @@ tst_callback(struct street_str *str, void *handle, void *data) int debug=0; /* printf("tst_callback id=0x%x ",str->segid < 0 ? -str->segid : str->segid); */ - if (! street_coord_handle_get(handle, &c[0])) { + if (street_coord_handle_get(handle, &c[0], 1)) { if (str->segid == debug_segid) printf("0x%lx,0x%lx ", c->x, c->y); c[1]=c[0]; - while (! street_coord_handle_get(handle, &c[0])) { + while (street_coord_handle_get(handle, &c[0], 1)) { if (is_line_visible(&tr->t, c)) { visible=1; } @@ -65,9 +65,9 @@ tst_callback(struct street_str *str, void *handle, void *data) if (visible) { lines=g_new(struct track_line, count); street_coord_handle_rewind(handle); - street_coord_handle_get(handle, &c[0]); + street_coord_handle_get(handle, &c[0], 1); count=0; - while (! street_coord_handle_get(handle, &c[1])) { + while (street_coord_handle_get(handle, &c[1], 1)) { *(tr->last_ptr)=lines; tr->last_ptr=&lines->next; lines->segid=str->segid; -- cgit v1.2.1 From d116b11d7e2aec6b4fdf8fcf058a8ba51132cb25 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 7 Jan 2006 13:03:28 +0000 Subject: Bugfix git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@73 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- street.c | 1 + 1 file changed, 1 insertion(+) diff --git a/street.c b/street.c index 04ecb2b4..d97fa5db 100644 --- a/street.c +++ b/street.c @@ -217,6 +217,7 @@ street_coord_handle_get(struct street_coord_handle *h, struct coord *c, int coun } c++; ret++; + count--; } return ret; } -- cgit v1.2.1 From 0cddff020f2045c25efaf1ad4c112568a2ceae18 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 8 Jan 2006 18:43:57 +0000 Subject: Search streets with correct country id git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@74 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navigation.c | 2 +- route.c | 42 +++++++++++++++++++++++------------------- route.h | 1 + street.c | 8 ++++++-- street.h | 2 +- tree.c | 6 ++++++ 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/navigation.c b/navigation.c index d70fc593..8e13b7e9 100644 --- a/navigation.c +++ b/navigation.c @@ -281,7 +281,7 @@ navigation_path_description(void *route) if (id) { if (id < 0) id=-id; - street_get_by_id(mdata, id, &blk_inf, &str); + street_get_by_id(mdata, curr->country, id, &blk_inf, &str); coord=street_coord_get(&blk_inf, str); start=coord->c; end=coord->c+coord->count-1; diff --git a/route.c b/route.c index ad7b9c52..797e46ba 100644 --- a/route.c +++ b/route.c @@ -79,6 +79,7 @@ struct route_segment { struct route_point *start; struct route_point *end; struct street_str *str; + struct street_type *strt; int limit; int len; int offset; @@ -86,7 +87,7 @@ struct route_segment { struct street_info { struct street_header *hdr; - struct street_type *typ; + struct street_type *strt; struct street_str *str; unsigned char *p; int bytes; @@ -153,10 +154,12 @@ route_mapdata_get(struct route *this) } static void -route_add_path_segment(struct route *this, int segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) +route_add_path_segment(struct route *this, int country, int segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) { struct route_path_segment *segment=g_new0(struct route_path_segment,1); + segment->next=NULL; + segment->country=country; segment->segid=segid; segment->offset=offset; segment->dir=dir; @@ -246,7 +249,7 @@ route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char str_inf.bytes=street_get_bytes(blk_inf->block); - str_inf.typ=(struct street_type *)p; + str_inf.strt=(struct street_type *)p; p+=blk_inf->block->count*sizeof(struct street_type); str=(struct street_str *)p; @@ -262,8 +265,8 @@ route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char str_inf.str=str; str_inf.p=p; func(blk_inf, &str_inf, &p, end-4, data); - if (str_inf.include) - str_inf.typ++; + if (!str_inf.include) + str_inf.strt++; str++; } } @@ -333,7 +336,7 @@ route_points_free(struct route *this) } static void -route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, int offset, int limit) +route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, struct street_type *strt, int offset, int limit) { struct route_segment *s; s=g_new0(struct route_segment,1); @@ -345,12 +348,13 @@ route_segment_add(struct route *this, struct route_point *start, struct route_po end->end=s; s->len=len; s->str=str; + s->strt=strt; s->offset=offset; s->limit=limit; s->next=this->route_segments; this->route_segments=s; if (debug_route) - printf("l (0x%lx,0x%lx0x%x)-(0x%lx,0x%lx,0x%x)\n", start->c.xy.x, start->c.xy.y, start->c.h, end->c.xy.x, end->c.xy.y, end->c.h); + printf("l (0x%lx,0x%lx,0x%x)-(0x%lx,0x%lx,0x%x)\n", start->c.xy.x, start->c.xy.y, start->c.h, end->c.xy.x, end->c.xy.y, end->c.h); } @@ -452,7 +456,7 @@ route_process_street_graph(struct block_info *blk_inf, struct street_info *str_i limit=0x30; if (str_inf->str->limit != 0x33) - route_segment_add(this, s_pnt, e_pnt, len, str_inf->str, 0, limit); + route_segment_add(this, s_pnt, e_pnt, len, str_inf->str, str_inf->strt, 0, limit); debug_route=0; *p-=2*str_inf->bytes; } @@ -561,21 +565,21 @@ route_find(struct route *this, struct route_info *rt_start, struct route_info *r if (start2->value != -1) val2=start2->value+route_value(rt_start->str_inf.str->type, rt_start->seg2_len); - route_add_path_segment(this, 0, 0, &rt_start->click.xy, &rt_start->pos.xy, 1, 0, 0); + route_add_path_segment(this, 0, 0, 0, &rt_start->click.xy, &rt_start->pos.xy, 1, 0, 0); type=rt_start->str_inf.str->type; if (val1 < val2) { ret=1; start=start1; slen=transform_distance(&rt_start->pos.xy, &rt_start->line1.xy); - route_add_path_segment(this, 0, 0, &rt_start->pos.xy, &rt_start->line1.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.str->segid, rt_start->offset, NULL, NULL, -1, rt_start->seg1_len, route_time(type, rt_start->seg1_len)); + route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line1.xy, 1, slen, route_time(type, slen)); + route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, rt_start->offset, NULL, NULL, -1, rt_start->seg1_len, route_time(type, rt_start->seg1_len)); } else { ret=2; start=start2; slen=transform_distance(&rt_start->pos.xy, &rt_start->line2.xy); - route_add_path_segment(this, 0, 0, &rt_start->pos.xy, &rt_start->line2.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.str->segid, -rt_start->offset, NULL, NULL, 1, rt_start->seg2_len, route_time(type, rt_start->seg2_len)); + route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line2.xy, 1, slen, route_time(type, slen)); + route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, -rt_start->offset, NULL, NULL, 1, rt_start->seg2_len, route_time(type, rt_start->seg2_len)); } while (start->value) { @@ -595,14 +599,14 @@ route_find(struct route *this, struct route_info *rt_start, struct route_info *r len+=s->len; seg_time=route_time(s->str->type, s->len); time+=seg_time; - route_add_path_segment(this, s->str->segid, s->offset, NULL, NULL, dir, s->len, seg_time); + route_add_path_segment(this, s->strt->country, s->str->segid, s->offset, NULL, NULL, dir, s->len, seg_time); } if (s) { if (s->start->c.xy.x == rt_end->seg1.xy.x && s->start->c.xy.y == rt_end->seg1.xy.y) - route_add_path_segment(this, 0, 0, &rt_end->pos.xy, &rt_end->line1.xy, -1, 0, 0); + route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line1.xy, -1, 0, 0); else - route_add_path_segment(this, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); - route_add_path_segment(this, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); + route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); + route_add_path_segment(this, 0, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); #if 0 printf("len %5.3f\n", len/1000); #endif @@ -957,8 +961,8 @@ route_do_start(struct route *this, struct route_info *rt_start, struct route_inf seg1=route_point_add(this, &rt_end->seg1, 1); pos=route_point_add(this, &rt_end->pos, 2); seg2=route_point_add(this ,&rt_end->seg2, 1); - route_segment_add(this, seg1, pos, rt_end->seg1_len, rt_end->str_inf.str, rt_end->offset, 0); - route_segment_add(this, seg2, pos, rt_end->seg2_len, rt_end->str_inf.str, -rt_end->offset, 0); + route_segment_add(this, seg1, pos, rt_end->seg1_len, rt_end->str_inf.str, rt_end->str_inf.strt, rt_end->offset, 0); + route_segment_add(this, seg2, pos, rt_end->seg2_len, rt_end->str_inf.str, rt_end->str_inf.strt, -rt_end->offset, 0); printf("flood\n"); route_flood(this, rt_end); diff --git a/route.h b/route.h index 7149cff4..c13b6564 100644 --- a/route.h +++ b/route.h @@ -1,5 +1,6 @@ struct route_path_segment { struct route_path_segment *next; + int country; long segid; int offset; int dir; diff --git a/street.c b/street.c index d97fa5db..c695e64a 100644 --- a/street.c +++ b/street.c @@ -414,7 +414,7 @@ street_get_block(struct map_data *mdata, struct transformation *t, void (*callba } int -street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str) +street_get_by_id(struct map_data *mdat, int country, int id, struct block_info *res_blk_inf, struct street_str **res_str) { int debug=0; int res,block,num; @@ -424,7 +424,11 @@ street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_header_type hdr_type; struct street_str *str; - if (tree_search_hv_map(mdat, file_street_str, (id >> 8) | 0x31000000, id & 0xff, &res, &mdat_res)) { + if (debug) + printf("street_get_by_id country 0x%x id %d\n", country, id); + if (tree_search_hv_map(mdat, file_street_str, (id >> 8) | (country << 24), id & 0xff, &res, &mdat_res)) { + if (debug) + printf("not found\n"); return 1; } diff --git a/street.h b/street.h index 7438acc9..472e35ce 100644 --- a/street.h +++ b/street.h @@ -53,7 +53,7 @@ void street_coord_handle_rewind(struct street_coord_handle *h); int street_coord_handle_get(struct street_coord_handle *h, struct coord *c, int count); void street_coord_handle_destroy(struct street_coord_handle *handle); void street_get_block(struct map_data *mdata, struct transformation *t, void (*callback)(void *data), void *data); -int street_get_by_id(struct map_data *mdat, int id, struct block_info *res_blk_inf, struct street_str **res_str); +int street_get_by_id(struct map_data *mdat, int country, int id, struct block_info *res_blk_inf, struct street_str **res_str); void street_bti_draw_block(struct block_info *blk_inf, unsigned char *start, unsigned char *end, void *data); int street_get_param(struct segment *seg, struct param_list *param, int count, int verbose); int street_bti_get_param(struct segment *seg, struct param_list *param, int count); diff --git a/tree.c b/tree.c index 6e55b7f2..8a09bedd 100644 --- a/tree.c +++ b/tree.c @@ -113,6 +113,8 @@ tree_search_h(struct file *file, unsigned int search) if (tleaf->value == search) return tleaf->match; if (tleaf->value > search) { + if (debug) + printf("lower\n"); if (tleaf->lower) last=tleaf->lower; break; @@ -291,6 +293,8 @@ tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigne int h,len,ret=0; int debug=0; + if (debug) + printf("tree_search_hv_map(0x%x 0x%x)\n",search1, search2); while (mdat && !ret) { f_dat=mdat->file[map]; strcpy(filename, f_dat->name); @@ -300,6 +304,8 @@ tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigne strcpy(filename+len-3,"v1"); f_idx_v=file_create(filename); h=tree_search_h(f_idx_h, search1); + if (debug) + printf("h=0x%x\n", h); if (h) { ret=tree_search_v(f_idx_v, h, search2); if (ret) { -- cgit v1.2.1 From c64c6f25305d2a6c4d8c6f2d87db1d5c3802c521 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 8 Jan 2006 20:28:41 +0000 Subject: Fixed labelling with non-ascii chars git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@75 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- display.c | 10 ++++++++-- graphics/gtk_drawing_area/graphics_gtk_drawing_area.c | 11 ++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/display.c b/display.c index bd534f6c..75cb3992 100644 --- a/display.c +++ b/display.c @@ -215,6 +215,7 @@ label_line(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, int i,x,y,tl; double dx,dy,l; struct point p_t; + char *utf8; tl=strlen(label)*400; for (i = 0 ; i < count-1 ; i++) { @@ -241,7 +242,9 @@ label_line(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, #if 0 printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l); #endif - gr->draw_text(gr, fg, bg, font, label, &p_t, dx*0x10000/l, dy*0x10000/l); + utf8=g_convert(label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); + gr->draw_text(gr, fg, bg, font, utf8, &p_t, dx*0x10000/l, dy*0x10000/l); + g_free(utf8); } } } @@ -250,6 +253,7 @@ void display_labels(struct display_list *list, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font) { struct point p; + char *utf8; while (list) { if (list->label) { switch (list->type) { @@ -260,7 +264,9 @@ display_labels(struct display_list *list, struct graphics *gr, struct graphics_g case 3: p.x=list->p[0].x+3; p.y=list->p[0].y+10; - gr->draw_text(gr, fg, bg, font, list->label, &p, 0x10000, 0); + utf8=g_convert(list->label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); + gr->draw_text(gr, fg, bg, font, utf8, &p, 0x10000, 0); + g_free(utf8); break; } } diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 903148ca..55b9f01a 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -73,6 +73,7 @@ static struct graphics_font *font_new(struct graphics *gr, int size) return NULL; } FT_Set_Char_Size(font->face, 0, size, 300, 300); + FT_Select_Charmap(font->face, FT_ENCODING_UNICODE); return font; } @@ -237,10 +238,13 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int FT_Matrix matrix; FT_Vector pen; FT_UInt glyph_index; - int n,len=strlen(text); - struct text_render *ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); + int n,len; + struct text_render *ret; struct text_glyph *curr; + wchar_t wtext[1024]; + len=mbstowcs(wtext, text, 1024); + ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); ret->glyph_count=len; matrix.xx = dx; @@ -253,12 +257,13 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int x <<= 6; y <<= 6; FT_Set_Transform( font->face, &matrix, &pen ); + for ( n = 0; n < len; n++ ) { - glyph_index = FT_Get_Char_Index(font->face, text[n]); + glyph_index = FT_Get_Char_Index(font->face, wtext[n]); FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT ); FT_Render_Glyph(font->face->glyph, ft_render_mode_normal ); -- cgit v1.2.1 From 5ef6b548918dec51c5b127acbdce7755d9c947fc Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 11 Jun 2006 10:15:53 +0000 Subject: Add another font search path git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@93 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics/gtk_drawing_area/graphics_gtk_drawing_area.c | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 55b9f01a..81047e00 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -47,6 +47,7 @@ char *fontlist[]={ "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", + "/usr/share/fonts/ttf/arial.ttf", NULL, }; -- cgit v1.2.1 From 9f785fe647d335f5e8fefb65907a4ec316e14cf2 Mon Sep 17 00:00:00 2001 From: horwitz Date: Sun, 11 Jun 2006 17:43:54 +0000 Subject: Honour umlauts in destination dialog git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@98 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 43 +++++++++++++++++++++++++++++++++++++++---- street_name.c | 2 +- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/destination.c b/destination.c index d4854670..187568d5 100644 --- a/destination.c +++ b/destination.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "coord.h" @@ -43,7 +44,7 @@ struct search_param { int number_low, number_high; GtkWidget *clist; int count; -} search_param2; +} search_param2 = {}; struct destination { struct town *town; @@ -442,7 +443,7 @@ destination_street_search(gpointer key, gpointer value, gpointer user_data) static void changed(GtkWidget *widget, struct search_param *search) { - const char *str; + char *str; char *empty[9]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; char *dash; @@ -455,7 +456,8 @@ static void changed(GtkWidget *widget, struct search_param *search) search->count=row_count; - str=gtk_entry_get_text(GTK_ENTRY(widget)); + str=g_convert(gtk_entry_get_text(GTK_ENTRY(widget)),-1,"iso8859-1","utf-8",NULL,NULL,NULL); + /*FIXME free buffers with g_free() after search or when the dialog gets closed. */ if (widget == entry_country) { if (search->country_hash) g_hash_table_destroy(search->country_hash); @@ -473,9 +475,21 @@ static void changed(GtkWidget *widget, struct search_param *search) search->street_hash=NULL; } + if (widget != entry_number) { + gtk_entry_set_text(GTK_ENTRY(entry_number),""); + if (widget != entry_street) { + gtk_entry_set_text(GTK_ENTRY(entry_street),""); + if (widget != entry_city) { + gtk_entry_set_text(GTK_ENTRY(entry_city),""); + } + } + } + if (widget == entry_country) { search->country_hash=destination_country_new(); - search->country=str; + g_free(str); + if (search->country) g_free(search->country); + search->country = str = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget))); country_search_by_name(str, 1, destination_country_add, search); country_search_by_car(str, 1, destination_country_add, search); country_search_by_iso2(str, 1, destination_country_add, search); @@ -483,8 +497,26 @@ static void changed(GtkWidget *widget, struct search_param *search) g_hash_table_foreach(search->country_hash, destination_country_show, search); } if (widget == entry_city) { + int i; + for(i = 0 ;i < strlen(str); i++) { + char u = toupper(str[i]); + + if (u == 'ä') str[i] = 'a'; + if (u == 'ö') str[i] = 'o'; + if (u == 'ü') str[i] = 'u'; + if (u == 'ß') { + char *tmp; + str[i] = '\0'; + tmp = g_strjoin(NULL, str, "ss", str[i+1], NULL); + g_free(str); + str = tmp; + i++; + } + printf("\"%s\"\n",str); + } printf("Ort: '%s'\n", str); if (strlen(str) > 1) { + if (search->town) g_free(search->town); search->town=str; search->town_hash=destination_town_new(); search->district_hash=destination_town_new(); @@ -494,6 +526,7 @@ static void changed(GtkWidget *widget, struct search_param *search) } if (widget == entry_street) { printf("Street: '%s'\n", str); + if (search->street) g_free(search->street); search->street=str; search->street_hash=destination_street_new(); g_hash_table_foreach(search->town_hash, destination_street_search, search); @@ -640,5 +673,7 @@ int destination_address(struct container *co) gtk_widget_show_all(window2); + gtk_entry_set_text(GTK_ENTRY(entry_country),"Deutschland"); + return 0; } diff --git a/street_name.c b/street_name.c index 23fc3fb0..48fc1eb3 100644 --- a/street_name.c +++ b/street_name.c @@ -54,7 +54,7 @@ struct street_search_priv { static int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) { - char c1_u,c2_u; + unsigned char c1_u,c2_u; int ret=0; int debug=0; -- cgit v1.2.1 From 4c48474f7eb8ae4b279c5cb6bcce4e4eba798f78 Mon Sep 17 00:00:00 2001 From: horwitz Date: Sun, 11 Jun 2006 18:19:44 +0000 Subject: fix town names with sz in destination dialog git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@99 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/destination.c b/destination.c index 187568d5..292e630b 100644 --- a/destination.c +++ b/destination.c @@ -44,7 +44,7 @@ struct search_param { int number_low, number_high; GtkWidget *clist; int count; -} search_param2 = {}; +} search_param2; struct destination { struct town *town; @@ -499,15 +499,15 @@ static void changed(GtkWidget *widget, struct search_param *search) if (widget == entry_city) { int i; for(i = 0 ;i < strlen(str); i++) { - char u = toupper(str[i]); + unsigned char u = str[i]; - if (u == 'ä') str[i] = 'a'; - if (u == 'ö') str[i] = 'o'; - if (u == 'ü') str[i] = 'u'; - if (u == 'ß') { + if (u == 0xc4 || u == 0xe4) str[i] = 'a'; + if (u == 0xd6 || u == 0xf6) str[i] = 'o'; + if (u == 0xdc || u == 0xfc) str[i] = 'u'; + if (u == 0xdf) { char *tmp; str[i] = '\0'; - tmp = g_strjoin(NULL, str, "ss", str[i+1], NULL); + tmp = g_strjoin(NULL, str, "ss", str+i+1, NULL); g_free(str); str = tmp; i++; -- cgit v1.2.1 From eb8505dde980d431c63461baaad68976d376a23b Mon Sep 17 00:00:00 2001 From: horwitz Date: Sun, 11 Jun 2006 22:35:14 +0000 Subject: Fix gtk_critical warnings in destiantion dialog git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@100 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- destination.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/destination.c b/destination.c index 292e630b..0daaec36 100644 --- a/destination.c +++ b/destination.c @@ -33,12 +33,12 @@ int selected; struct search_param { struct map_data *map_data; - const char *country; + char *country; GHashTable *country_hash; - const char *town; + char *town; GHashTable *town_hash; GHashTable *district_hash; - const char *street; + char *street; GHashTable *street_hash; const char *number; int number_low, number_high; @@ -501,7 +501,7 @@ static void changed(GtkWidget *widget, struct search_param *search) for(i = 0 ;i < strlen(str); i++) { unsigned char u = str[i]; - if (u == 0xc4 || u == 0xe4) str[i] = 'a'; + if (u == 0xc4 || u == 0xe4) str[i] = 'a'; if (u == 0xd6 || u == 0xf6) str[i] = 'o'; if (u == 0xdc || u == 0xfc) str[i] = 'u'; if (u == 0xdf) { @@ -514,7 +514,7 @@ static void changed(GtkWidget *widget, struct search_param *search) } printf("\"%s\"\n",str); } - printf("Ort: '%s'\n", str); + printf("Town: '%s'\n", str); if (strlen(str) > 1) { if (search->town) g_free(search->town); search->town=str; @@ -529,8 +529,10 @@ static void changed(GtkWidget *widget, struct search_param *search) if (search->street) g_free(search->street); search->street=str; search->street_hash=destination_street_new(); - g_hash_table_foreach(search->town_hash, destination_street_search, search); - g_hash_table_foreach(search->street_hash, destination_street_show, search); + if (search->town_hash) + g_hash_table_foreach(search->town_hash, destination_street_search, search); + if (search->street_hash) + g_hash_table_foreach(search->street_hash, destination_street_show, search); } if (widget == entry_number) { char buffer[strlen(str)+1]; @@ -553,7 +555,8 @@ static void changed(GtkWidget *widget, struct search_param *search) search->number_high=atoi(str); } } - g_hash_table_foreach(search->street_hash, destination_street_show_number, search); + if (search->street_hash) + g_hash_table_foreach(search->street_hash, destination_street_show_number, search); } while (search->count-- > 0) { gtk_clist_append(GTK_CLIST(listbox), empty); -- cgit v1.2.1 From 65875cc824d368204cc2f714abf9499c960b90f9 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 23 Sep 2006 10:49:43 +0000 Subject: Fix crash when speechd is not available git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@104 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- main.c | 2 ++ navigation.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 434f244e..bec79965 100644 --- a/main.c +++ b/main.c @@ -65,6 +65,8 @@ int main(int argc, char **argv) g_warning("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]"); } co->speech=speech_new(); + if (! co->speech) + g_warning("Can't connect to speechd, no speech output available"); speech_handle=co->speech; if (co->vehicle) co->compass=compass_new(co); diff --git a/navigation.c b/navigation.c index 8e13b7e9..4fddbf80 100644 --- a/navigation.c +++ b/navigation.c @@ -241,7 +241,8 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) if (flag) { if (level != old_level) { printf("command='%s'\n", command); - speech_say(speech_handle, command); + if (speech_handle) + speech_say(speech_handle, command); old_level=level; } flag=0; -- cgit v1.2.1 From 9fd41973b7119fb6d70dbca211b3bcf34f42ae62 Mon Sep 17 00:00:00 2001 From: horwitz Date: Mon, 25 Sep 2006 10:43:54 +0000 Subject: Change get_* to get_u8, get_u16, get_u24, get_u32. Fix some compile warnings. git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@105 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 14 +++++++------- data.h | 14 +++++++------- debug.c | 2 +- street.c | 32 ++++++++++++++++---------------- street_name.c | 30 +++++++++++++++--------------- town.c | 24 ++++++++++++------------ tree.c | 2 +- 7 files changed, 59 insertions(+), 59 deletions(-) diff --git a/block.c b/block.c index 8081e92f..3e77431b 100644 --- a/block.c +++ b/block.c @@ -72,8 +72,8 @@ block_binarytree_walk(struct block **block, unsigned char **p, struct coord *c, *block=block_get_byindex(blk_inf->file, (*block)->next, p); *p-=20; } - blk_num=get_long(p); - val=get_long(p); + blk_num=get_u32(p); + val=get_u32(p); if (blk_num != -1) ret++; @@ -122,10 +122,10 @@ block_file_private_setup(struct file *file) p=file->begin+0x0c; while (*p) { str=get_string(&p); - len=get_long(&p); + len=get_u32(&p); t=p; if (! strcmp(str,"binaryTree")) { - file_priv->binarytree=get_long(&t); + file_priv->binarytree=get_u32(&t); } p+=len; } @@ -173,7 +173,7 @@ block_foreach_visible(struct block_info *blk_inf, struct transformation *t, int int dummy1,dummy2,xy,i,count; struct block *block=block_get_byindex(blk_inf->file, file_priv->binarytree, &p); p2=p; - dummy1=get_long(&p2); + dummy1=get_u32(&p2); if (block->count != -1 || dummy1 != -1) { printf("ERROR2 0x%x\n", block->count); } @@ -181,8 +181,8 @@ block_foreach_visible(struct block_info *blk_inf, struct transformation *t, int p=p2; for (i = 0 ; i < limit ; i++) { p2=p; - dummy1=get_long(&p2); - dummy2=get_long(&p2); + dummy1=get_u32(&p2); + dummy2=get_u32(&p2); assert((dummy1 == -1 && dummy2 == -1) || i < 32) ; if (block->c[0].x > block->c[1].x || block->c[1].y > block->c[0].y) break; diff --git a/data.h b/data.h index 075eaa6e..8d4b1b70 100644 --- a/data.h +++ b/data.h @@ -1,28 +1,28 @@ static inline unsigned char -get_char(unsigned char **p) +get_u8(unsigned char **p) { return *((*p)++); } static inline unsigned short -get_short(unsigned char **p) { +get_u16(unsigned char **p) { unsigned long ret; ret=*((unsigned short *)*p); *p+=sizeof(unsigned short); return ret; } -static inline unsigned long -get_triple(unsigned char **p) { +static inline unsigned int +get_u24(unsigned char **p) { unsigned long ret; - ret=get_short(p); + ret=get_u16(p); ret|=*((*p)++) << 16; return ret; } -static inline unsigned long -get_long(unsigned char **p) { +static inline unsigned int +get_u32(unsigned char **p) { unsigned long ret; ret=*((unsigned int *)*p); *p+=sizeof(unsigned int); diff --git a/debug.c b/debug.c index 3c19218e..5fbe6035 100644 --- a/debug.c +++ b/debug.c @@ -7,7 +7,7 @@ -static int sigsegv(void) +static void sigsegv(int sig) { FILE *f; time_t t; diff --git a/street.c b/street.c index c695e64a..85633d3e 100644 --- a/street.c +++ b/street.c @@ -507,29 +507,29 @@ street_get_param(struct segment *seg, struct param_list *param, int count, int v int tag; int k, segs; printf("\n"); - printf("Len 0x%x\n",get_short(&stn)); + printf("Len 0x%x\n",get_u16(&stn)); tag=*stn++; printf("Tag 0x%x\n",tag); if (tag == 0xc0 || tag == 0xd0 || tag == 0xe0) { - printf("DistAssoc 0x%lx\n",get_long(&stn)); - printf("Country 0x%lx\n",get_long(&stn)); - printf("X 0x%lx\n",get_long(&stn)); - printf("Y 0x%lx\n",get_long(&stn)); - printf("First %ld\n",get_triple(&stn)); - printf("Last %ld\n",get_triple(&stn)); - segs=get_long(&stn); + printf("DistAssoc 0x%lx\n",get_u32(&stn)); + printf("Country 0x%lx\n",get_u32(&stn)); + printf("X 0x%lx\n",get_u32(&stn)); + printf("Y 0x%lx\n",get_u32(&stn)); + printf("First %ld\n",get_u24(&stn)); + printf("Last %ld\n",get_u24(&stn)); + segs=get_u32(&stn); printf("Segs 0x%x\n",segs); for (k = 0 ; k < 0 ; k++) { - printf("SegId 0x%lx\n", get_long(&stn)); - printf("Country 0x%lx\n",get_long(&stn)); + printf("SegId 0x%lx\n", get_u32(&stn)); + printf("Country 0x%lx\n",get_u32(&stn)); } } else if (tag == 0x8f || tag == 0xaa || tag == 0xab || tag == 0xae || tag == 0xaf || tag == 0x9a || tag == 0x9e || tag == 0x9f) { - printf("X 0x%lx\n",get_long(&stn)); - printf("Y 0x%lx\n",get_long(&stn)); - printf("First %ld\n",get_triple(&stn)); - printf("Last %ld\n",get_triple(&stn)); - printf("SegId 0x%lx\n",get_long(&stn)); - printf("Country 0x%lx\n",get_long(&stn)); + printf("X 0x%lx\n",get_u32(&stn)); + printf("Y 0x%lx\n",get_u32(&stn)); + printf("First %ld\n",get_u24(&stn)); + printf("Last %ld\n",get_u24(&stn)); + printf("SegId 0x%lx\n",get_u32(&stn)); + printf("Country 0x%lx\n",get_u32(&stn)); } else { printf("Unknown tag 0x%x\n", tag); break; diff --git a/street_name.c b/street_name.c index 48fc1eb3..4fa1046e 100644 --- a/street_name.c +++ b/street_name.c @@ -22,12 +22,12 @@ void street_name_get(struct street_name *name, unsigned char **p) { unsigned char *start=*p; - name->len=get_short(p); - name->country=get_short(p); - name->townassoc=get_long(p); + name->len=get_u16(p); + name->country=get_u16(p); + name->townassoc=get_u32(p); name->name1=get_string(p); name->name2=get_string(p); - name->segment_count=get_long(p); + name->segment_count=get_u32(p); name->segments=(struct street_name_segment *)(*p); (*p)+=(sizeof (struct street_name_segment))*name->segment_count; name->aux_len=name->len-(*p-start); @@ -122,9 +122,9 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d blk_off=(struct block_offset *)(*s2); if (debug) - printf("0x%lx\n", get_long(s2)); + printf("0x%x\n", get_u32(s2)); else - get_long(s2); + get_u32(s2); struct street_name_index *i1=priv_data->search; struct street_name_index *i2=(struct street_name_index *)(*s2); @@ -220,14 +220,14 @@ street_name_get_info(struct street_name_info *inf, struct street_name *name) if (name->tmp_len <= 0) return 0; - inf->len=get_short(&p); + inf->len=get_u16(&p); inf->tag=*p++; - inf->dist=get_long(&p); - inf->country=get_long(&p); + inf->dist=get_u32(&p); + inf->country=get_u32(&p); inf->c=coord_get(&p); - inf->first=get_triple(&p); - inf->last=get_triple(&p); - inf->segment_count=get_long(&p); + inf->first=get_u24(&p); + inf->last=get_u24(&p); + inf->segment_count=get_u32(&p); inf->segments=(struct street_segment *)p; p+=sizeof(struct street_name_segment)*inf->segment_count; inf->aux_len=name->tmp_data+name->tmp_len-p; @@ -247,11 +247,11 @@ street_name_get_number_info(struct street_name_number_info *num, struct street_n if (inf->tmp_len <= 0) return 0; - num->len=get_short(&p); + num->len=get_u16(&p); num->tag=*p++; num->c=coord_get(&p); - num->first=get_triple(&p); - num->last=get_triple(&p); + num->first=get_u24(&p); + num->last=get_u24(&p); num->segment=(struct street_name_segment *)p; inf->tmp_data+=num->len; inf->tmp_len-=num->len; diff --git a/town.c b/town.c index c619ef5f..d58718bd 100644 --- a/town.c +++ b/town.c @@ -17,20 +17,20 @@ static void town_get(struct town *town, unsigned char **p) { - town->id=get_long(p); + town->id=get_u32(p); town->c=coord_get(p); town->name=get_string(p); town->district=get_string(p); town->postal_code1=get_string(p); - town->order=get_char(p); - town->country=get_short(p); - town->type=get_char(p); - town->unknown2=get_long(p); - town->size=get_char(p); - town->street_assoc=get_long(p); - town->unknown3=get_char(p); + town->order=get_u8(p); + town->country=get_u16(p); + town->type=get_u8(p); + town->unknown2=get_u32(p); + town->size=get_u8(p); + town->street_assoc=get_u32(p); + town->unknown3=get_u8(p); town->postal_code2=get_string(p); - town->unknown4=get_long(p); + town->unknown4=get_u32(p); } void @@ -85,13 +85,13 @@ town_tree_process(int version, int leaf, unsigned char **s2, struct map_data *md char *name; int ret,i,debug=0; - country=get_short(s2); + country=get_u16(s2); name=get_string(s2); if (debug) { printf("Country: 0x%x ", country); printf("Town: '%s' ", name); } - len=get_long(s2); + len=get_u32(s2); blk_off=(struct block_offset *)(*s2); *s2+=len*4; @@ -237,7 +237,7 @@ town_get_param(struct segment *seg, struct param_list *param, int count) p=(unsigned char *)(seg->blk_inf.block); p+=sizeof(*seg->blk_inf.block); - param_add_hex("Block Unknown", get_long(&p), ¶m, &count); + param_add_hex("Block Unknown", get_u32(&p), ¶m, &count); p=seg->data[0]; param_add_hex("Address", p-seg->blk_inf.file->begin, ¶m, &count); town_get(&town, &p); diff --git a/tree.c b/tree.c index 8a09bedd..67274947 100644 --- a/tree.c +++ b/tree.c @@ -192,7 +192,7 @@ tree_search(int version, struct file *file, unsigned char *p, int (*tree_func)(i } while (p < end) { psav=p; - high=get_long(&p); + high=get_u32(&p); if (high == -1) leaf=1; res=tree_func(version, leaf, &p, mdat, data); -- cgit v1.2.1 From 6b6eb66a2bcf14624a81e7d032b9922c63c45826 Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 26 Sep 2006 08:35:14 +0000 Subject: Start to use types.h for data values git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@109 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data.h | 27 +++++++++++++++------------ log.c | 2 +- street.c | 2 +- street.h | 28 +++++++++++++++------------- street_name.c | 2 +- town.c | 2 +- tree.c | 2 +- types.h | 9 +++++++++ 8 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 types.h diff --git a/data.h b/data.h index 8d4b1b70..61a9e007 100644 --- a/data.h +++ b/data.h @@ -1,31 +1,33 @@ -static inline unsigned char +#include "types.h" + +static inline u8 get_u8(unsigned char **p) { return *((*p)++); } -static inline unsigned short +static inline u16 get_u16(unsigned char **p) { - unsigned long ret; - ret=*((unsigned short *)*p); - *p+=sizeof(unsigned short); + u16 ret; + ret=*((u16 *)*p); + *p+=sizeof(u16); return ret; } -static inline unsigned int +static inline u32 get_u24(unsigned char **p) { - unsigned long ret; + u32 ret; ret=get_u16(p); ret|=*((*p)++) << 16; return ret; } -static inline unsigned int +static inline u32 get_u32(unsigned char **p) { - unsigned long ret; - ret=*((unsigned int *)*p); - *p+=sizeof(unsigned int); + u32 ret; + ret=*((u32 *)*p); + *p+=sizeof(u32); return ret; } @@ -36,4 +38,5 @@ get_string(unsigned char **p) while (**p) (*p)++; (*p)++; return ret; -} +} + diff --git a/log.c b/log.c index 59c1fc3d..05054d74 100644 --- a/log.c +++ b/log.c @@ -17,7 +17,7 @@ log_write(char *message, struct file *file, void *data, int size) int fd=open("log.txt",O_RDWR|O_CREAT|O_APPEND|O_SYNC, 0644); sprintf(log,"# %s\n",message); l=log+strlen(log); - sprintf(l, "%s 0x%x ", file->name, p-file->begin); + sprintf(l, "%s 0x%lx ", file->name, p-file->begin); l=log+strlen(log); while (size) { sprintf(l,"%02x ", *p++); diff --git a/street.c b/street.c index 85633d3e..8633224a 100644 --- a/street.c +++ b/street.c @@ -482,7 +482,7 @@ street_get_param(struct segment *seg, struct param_list *param, int count, int v param_add_hex("Len", name.len, ¶m, &count); param_add_hex("Country", name.country, ¶m, &count); param_add_hex_sig("TownAssoc", name.townassoc, ¶m, &count); - printf("TownAssoc 0x%lx\n", name.townassoc+str->segid); + printf("TownAssoc 0x%x\n", name.townassoc+str->segid); param_add_string("Name1", name.name1, ¶m, &count); param_add_string("Name2", name.name2, ¶m, &count); param_add_hex("Segments", name.segment_count, ¶m, &count); diff --git a/street.h b/street.h index 472e35ce..97f59bbb 100644 --- a/street.h +++ b/street.h @@ -1,3 +1,5 @@ +#include "types.h" + struct container; struct block_info; struct segment; @@ -15,27 +17,27 @@ struct street_type { } __attribute__((packed)); struct street_str { - long segid; - unsigned char limit; /* 0x03,0x30=One Way,0x33=No Passing */ - unsigned char unknown2; - unsigned char unknown3; - unsigned char type; - unsigned long nameid; + u32 segid; + u8 limit; /* 0x03,0x30=One Way,0x33=No Passing */ + u8 unknown2; + u8 unknown3; + u8 type; + u32 nameid; }; struct street_bti { - unsigned char unknown1; - unsigned long segid1; - unsigned long country1; - unsigned long segid2; - unsigned long country2; - unsigned char unknown5; + u8 unknown1; + u32 segid1; + u32 country1; + u32 segid2; + u32 country2; + u8 unknown5; struct coord c; } __attribute__((packed)); struct street_route { struct street_route *next; - long segid; + u32 segid; int offset; struct coord c[2]; }; diff --git a/street_name.c b/street_name.c index 4fa1046e..cecc62a6 100644 --- a/street_name.c +++ b/street_name.c @@ -132,7 +132,7 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d printf("Country %d %d\n",i1->country, i2->country); printf("Town_Assoc 0x%lx 0x%lx\n",i1->town_assoc, i2->town_assoc); printf("Name '%s' '%s'\n",i1->name, i2->name); - printf("Leaf Data 0x%x 0x%x %d\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); + printf("Leaf Data 0x%x 0x%x %ld\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); } *s2+=sizeof(*i2)+strlen(i2->name)+1; ret=street_name_compare(i1, i2, priv_data->partial); diff --git a/town.c b/town.c index d58718bd..da5770b8 100644 --- a/town.c +++ b/town.c @@ -223,7 +223,7 @@ town_get_by_id(struct town *town, struct map_data *mdat, int country, int id) printf("file %s block 0x%x offset 0x%x\n", f->name, block, offset); blk=block_get_byindex(f, block, &p); p=(unsigned char *)blk+offset; - printf("addr 0x%x\n", p-f->begin); + printf("addr 0x%lx\n", p-f->begin); town_get(town, &p); } diff --git a/tree.c b/tree.c index 67274947..781a0f1c 100644 --- a/tree.c +++ b/tree.c @@ -101,7 +101,7 @@ tree_search_h(struct file *file, unsigned int search) p+=sizeof(*thdr); end=p+thdr->size; if (debug) { - printf("@0x%x\n", p-file->begin); + printf("@0x%lx\n", p-file->begin); } last=0; while (p < end) { diff --git a/types.h b/types.h new file mode 100644 index 00000000..adfc1e57 --- /dev/null +++ b/types.h @@ -0,0 +1,9 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +#endif -- cgit v1.2.1 From d652df38db249c3c33c41f9e1a5e03300e462c21 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 26 Sep 2006 09:08:55 +0000 Subject: segid is signed git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@110 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- street.h | 2 +- types.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/street.h b/street.h index 97f59bbb..516e6865 100644 --- a/street.h +++ b/street.h @@ -17,7 +17,7 @@ struct street_type { } __attribute__((packed)); struct street_str { - u32 segid; + s32 segid; u8 limit; /* 0x03,0x30=One Way,0x33=No Passing */ u8 unknown2; u8 unknown3; diff --git a/types.h b/types.h index adfc1e57..f9ee6abd 100644 --- a/types.h +++ b/types.h @@ -2,8 +2,11 @@ #define _TYPES_H_ #include +typedef int8_t s8; typedef uint8_t u8; +typedef int16_t s16; typedef uint16_t u16; +typedef int32_t s32; typedef uint32_t u32; #endif -- cgit v1.2.1 From 58d955d136c1a9392f6c18a54293f124c4dd9cc9 Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 27 Sep 2006 07:15:03 +0000 Subject: More usage of types.h git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@111 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- route.c | 6 +++--- route.h | 8 +++++--- street.h | 6 +++--- street_name.h | 27 ++++++++++++++------------- town.h | 20 +++++++++++--------- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/route.c b/route.c index 797e46ba..9fd255d5 100644 --- a/route.c +++ b/route.c @@ -154,7 +154,7 @@ route_mapdata_get(struct route *this) } static void -route_add_path_segment(struct route *this, int country, int segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) +route_add_path_segment(struct route *this, int country, s32 segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) { struct route_path_segment *segment=g_new0(struct route_path_segment,1); @@ -199,7 +199,7 @@ route_path_get_all(struct route *this) } struct route_path_segment * -route_path_get(struct route *this, int segid) +route_path_get(struct route *this, s32 segid) { struct route_path_segment *curr=this->path; @@ -409,7 +409,7 @@ route_value(int type, int len) } static int -route_get_height(int segid, struct coord *c) +route_get_height(s32 segid, struct coord *c) { if (c->x == 0x141b53 && c->y == 0x5f2065 && (segid == 0x4fad2fa || segid == 0x4fad155)) return 1; diff --git a/route.h b/route.h index c13b6564..33fcdb58 100644 --- a/route.h +++ b/route.h @@ -1,7 +1,9 @@ +#include "types.h" + struct route_path_segment { struct route_path_segment *next; int country; - long segid; + s32 segid; int offset; int dir; int time; @@ -10,7 +12,7 @@ struct route_path_segment { }; struct route_crossing { - long segid; + s32 segid; int dir; }; @@ -34,7 +36,7 @@ void route_start(struct route *this, struct container *co); void route_set_position(struct route *this, struct coord *pos); void route_set_destination(struct route *this, struct coord *dst); struct coord *route_get_destination(struct route *this); -struct route_path_segment *route_path_get(struct route *, int segid); +struct route_path_segment *route_path_get(struct route *, s32 segid); struct route_path_segment *route_path_get_all(struct route *this); void route_trace(struct container *co); struct street_str *route_info_get_street(struct route_info *rt); diff --git a/street.h b/street.h index 516e6865..a0b5cdbb 100644 --- a/street.h +++ b/street.h @@ -27,9 +27,9 @@ struct street_str { struct street_bti { u8 unknown1; - u32 segid1; + s32 segid1; u32 country1; - u32 segid2; + s32 segid2; u32 country2; u8 unknown5; struct coord c; @@ -37,7 +37,7 @@ struct street_bti { struct street_route { struct street_route *next; - u32 segid; + s32 segid; int offset; struct coord c[2]; }; diff --git a/street_name.h b/street_name.h index b6c178b1..aca17ebd 100644 --- a/street_name.h +++ b/street_name.h @@ -1,15 +1,16 @@ +#include "types.h" struct street_name_segment { int segid; int country; }; struct street_name { - int len; - int country; - int townassoc; + u16 len; + u16 country; + u32 townassoc; char *name1; char *name2; - int segment_count; + u32 segment_count; struct street_name_segment *segments; int aux_len; unsigned char *aux_data; @@ -19,14 +20,14 @@ struct street_name { struct street_name_info { - int len; + u16 len; int tag; - int dist; - int country; + u32 dist; + u32 country; struct coord *c; - int first; - int last; - int segment_count; + u32 first; + u32 last; + u32 segment_count; struct street_segment *segments; int aux_len; unsigned char *aux_data; @@ -35,11 +36,11 @@ struct street_name_info { }; struct street_name_number_info { - int len; + u16 len; int tag; struct coord *c; - int first; - int last; + u32 first; + u32 last; struct street_name_segment *segment; }; diff --git a/town.h b/town.h index 5b7e8458..46513272 100644 --- a/town.h +++ b/town.h @@ -1,19 +1,21 @@ +#include "types.h" + /*! A town description */ struct town { - unsigned long id; /*!< Identifier */ + u32 id; /*!< Identifier */ struct coord *c; /*!< Coordinates */ char *name; /*!< Name */ char *district; /*!< District */ char *postal_code1; /*!< Postal code */ - unsigned char order; /*!< Order (Importance) */ - unsigned char type; /*!< Type */ - unsigned short country; /*!< Country */ - unsigned long unknown2; /*!< Unknown */ - unsigned char size; /*!< Size of town */ - unsigned long street_assoc; /*!< Association to streets */ - unsigned char unknown3; /*!< Unknown */ + u8 order; /*!< Order (Importance) */ + u8 type; /*!< Type */ + u16 country; /*!< Country */ + u32 unknown2; /*!< Unknown */ + u8 size; /*!< Size of town */ + u32 street_assoc; /*!< Association to streets */ + u8 unknown3; /*!< Unknown */ char *postal_code2; /*!< 2nd postal code */ - unsigned long unknown4; /*!< Unknown */ + u32 unknown4; /*!< Unknown */ }; struct block_info; -- cgit v1.2.1 From 6a982d30f1af78539ab63b4664658f6955128336 Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 27 Sep 2006 21:31:45 +0000 Subject: More amd64 fixes to make it actually work git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@112 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- block.c | 10 +++++----- block.h | 6 +++--- coord.h | 6 ++++-- poly.c | 6 +++--- poly.h | 6 +++--- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/block.c b/block.c index 3e77431b..0c7d0f2c 100644 --- a/block.c +++ b/block.c @@ -12,14 +12,14 @@ struct file_private { }; struct block_index_item { - unsigned long blocknum; - unsigned long blocks; + u32 blocknum; + u32 blocks; }; struct block_index { - unsigned long blocks; - unsigned long size; - unsigned long next; + u32 blocks; + u32 size; + u32 next; struct block_index_item list[0]; }; diff --git a/block.h b/block.h index a65fe935..ddc74266 100644 --- a/block.h +++ b/block.h @@ -2,9 +2,9 @@ #include "transform.h" struct block { - unsigned long blocks; - unsigned long size; - unsigned long next; + u32 blocks; + u32 size; + u32 next; struct coord c[2]; int count; }; diff --git a/coord.h b/coord.h index 54ba4b7e..550c0322 100644 --- a/coord.h +++ b/coord.h @@ -1,10 +1,12 @@ #ifndef COORD_H #define COORD_H +#include "types.h" + /*! A integer mercator coordinate */ struct coord { - long x; /*!< X-Value */ - long y; /*!< Y-Value */ + s32 x; /*!< X-Value */ + s32 y; /*!< Y-Value */ }; //! A double mercator coordinate diff --git a/poly.c b/poly.c index e39ecc5b..4fb8514d 100644 --- a/poly.c +++ b/poly.c @@ -26,9 +26,9 @@ poly_get_hdr(unsigned char **p,struct poly_hdr *poly_hdr) (*p)++; poly_hdr->order=*(*p)++; poly_hdr->type=*(*p)++; - poly_hdr->polys=*(unsigned long *)(*p); (*p)+=sizeof(unsigned long); - poly_hdr->count=(unsigned long *)(*p); (*p)+=poly_hdr->polys*sizeof(unsigned long); - poly_hdr->count_sum=*(unsigned long *)(*p); (*p)+=sizeof(unsigned long); + poly_hdr->polys=*(u32 *)(*p); (*p)+=sizeof(u32); + poly_hdr->count=(u32 *)(*p); (*p)+=poly_hdr->polys*sizeof(u32); + poly_hdr->count_sum=*(u32 *)(*p); (*p)+=sizeof(u32); return 0; } diff --git a/poly.h b/poly.h index 8d735f5b..9d9dcbfc 100644 --- a/poly.h +++ b/poly.h @@ -4,9 +4,9 @@ struct poly_hdr { char *name; unsigned char order; unsigned char type; - unsigned long polys; - unsigned long *count; - unsigned long count_sum; + u32 polys; + u32 *count; + u32 count_sum; }; void poly_draw_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data); -- cgit v1.2.1 From 5385aab2d932f73b92862a220c359d9b4a1115b4 Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 9 Jan 2007 13:21:48 +0000 Subject: Create a vehicles even if there's no gps device connected. This resolves an issues with Set Possition in popup menu. git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@113 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/vehicle.c b/vehicle.c index e62e093f..d76a2c9f 100644 --- a/vehicle.c +++ b/vehicle.c @@ -264,7 +264,6 @@ vehicle_new(const char *url) fd=open(url+5,O_RDONLY|O_NDELAY); if (fd < 0) { g_warning("Failed to open %s", url); - return NULL; } } else if (! strncmp(url,"gpsd://",7)) { #ifdef HAVE_LIBGPS @@ -278,23 +277,25 @@ vehicle_new(const char *url) g_free(url_); if (! gps) { g_warning("Failed to connect to %s", url); - return NULL; + } else { + gps_query(gps, "w+x\n"); + gps_set_raw_hook(gps, vehicle_gps_callback); + fd=gps->gps_fd; } - gps_query(gps, "w+x\n"); - gps_set_raw_hook(gps, vehicle_gps_callback); - fd=gps->gps_fd; #else g_warning("No support for gpsd compiled in\n"); - return NULL; #endif } this=g_new0(struct vehicle,1); #ifdef HAVE_LIBGPS - this->gps=gps; + if(gps) + this->gps=gps; #endif - this->iochan=g_io_channel_unix_new(fd); - g_io_channel_set_encoding(this->iochan, NULL, &error); - g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); + if(fd !=-1) { + this->iochan=g_io_channel_unix_new(fd); + g_io_channel_set_encoding(this->iochan, NULL, &error); + g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); + } this->current_pos.x=0x130000; this->current_pos.y=0x600000; this->curr.x=this->current_pos.x; @@ -312,7 +313,7 @@ void vehicle_callback(struct vehicle *this, void (*func)(void *data), void *data) { this->callback_func=func; - this->callback_data=data; +this->callback_data=data; } void -- cgit v1.2.1 From d61cc777f0cee76a47555149ae540a7bbcdc55f1 Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 5 Feb 2007 16:12:31 +0000 Subject: Integrated Kazers changes git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@114 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 4 +-- container.h | 1 + cursor.c | 1 + destination.c | 20 +++++++------- graphics.c | 12 ++++++++- main.c | 13 ++++++++-- navigation.c | 50 +++++++++++++++++++++-------------- osd.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ osd.h | 2 ++ profile.c | 5 ++-- track.c | 5 ++-- 11 files changed, 156 insertions(+), 40 deletions(-) create mode 100644 osd.c create mode 100644 osd.h diff --git a/Makefile.am b/Makefile.am index 84c633af..404a6198 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,12 +11,12 @@ bin_PROGRAMS = navit navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c debug.c destination.c \ display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ - map-stubs.c map_data.c menu.c navigation.c param.c phrase.c plugin.c poly.c popup.c \ + map-stubs.c map_data.c menu.c navigation.c osd.c param.c phrase.c plugin.c poly.c popup.c \ profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c track.c \ util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ cursor.h data.h data_window.h data_window_int.h debug.h destination.h display.h draw_info.h \ file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ - param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ + osd.h param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h track.h util.h vehicle.h navit_LDADD = @PACKAGE_LIBS@ gui/gtk/gtk.o graphics/gtk_drawing_area/gtk_drawing_area.o -Lfib-1.0 -lfib diff --git a/container.h b/container.h index af6f7a6a..03cf94a8 100644 --- a/container.h +++ b/container.h @@ -54,6 +54,7 @@ struct container { struct transformation *trans; struct graphics *gra; struct compass *compass; + struct osd *osd; struct display_list *disp[display_end]; struct map_data *map_data; struct menu *menu; diff --git a/cursor.c b/cursor.c index 951a2b83..92186538 100644 --- a/cursor.c +++ b/cursor.c @@ -182,6 +182,7 @@ cursor_update(void *t) cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v)); } compass_draw(this->co->compass, this->co); + osd_draw(this->co->osd, this->co); } extern void *vehicle; diff --git a/destination.c b/destination.c index 0daaec36..c8c33cef 100644 --- a/destination.c +++ b/destination.c @@ -606,23 +606,23 @@ int destination_address(struct container *co) #endif window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); - keyboard = build_keyboard(NULL, "/usr/share/gtkeyboard/key/DE.key"); + keyboard = build_keyboard(NULL, gettext("/usr/share/gtkeyboard/key/DE.key")); vbox = gtk_vbox_new(FALSE, 0); table = gtk_table_new(3, 8, FALSE); entry_country = gtk_entry_new(); - label_country = gtk_label_new("Land"); + label_country = gtk_label_new(gettext("Land")); entry_postal = gtk_entry_new(); - label_postal = gtk_label_new("PLZ"); + label_postal = gtk_label_new(gettext("PLZ")); entry_city = gtk_entry_new(); - label_city = gtk_label_new("Ort"); + label_city = gtk_label_new(gettext("Ort")); entry_district = gtk_entry_new(); - label_district = gtk_label_new("Ortsteil/Gemeinde"); + label_district = gtk_label_new(gettext("Ortsteil/Gemeinde")); hseparator1 = gtk_vseparator_new(); entry_street = gtk_entry_new(); - label_street = gtk_label_new("Strasse"); + label_street = gtk_label_new(gettext("Strasse")); entry_number = gtk_entry_new(); - label_number = gtk_label_new("Nummer"); + label_number = gtk_label_new(gettext("Nummer")); listbox = gtk_clist_new(9); for (i=0 ; i < row_count ; i++) { gtk_clist_append(GTK_CLIST(listbox), text); @@ -631,8 +631,8 @@ int destination_address(struct container *co) gtk_clist_columns_autosize (GTK_CLIST(listbox)); hseparator2 = gtk_vseparator_new(); - button1 = gtk_button_new_with_label("Karte"); - button2 = gtk_button_new_with_label("Ziel"); + button1 = gtk_button_new_with_label(gettext("Karte")); + button2 = gtk_button_new_with_label(gettext("Ziel")); gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND, 0, 0); gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND, 0, 0); @@ -676,7 +676,7 @@ int destination_address(struct container *co) gtk_widget_show_all(window2); - gtk_entry_set_text(GTK_ENTRY(entry_country),"Deutschland"); + gtk_entry_set_text(GTK_ENTRY(entry_country),gettext("base_country")); return 0; } diff --git a/graphics.c b/graphics.c index a989156b..ad430c66 100644 --- a/graphics.c +++ b/graphics.c @@ -308,7 +308,9 @@ graphics_redraw(struct container *co) gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2_B], bw[3]); gra->gc_set_linewidth(gra->gc[GC_STREET_ROUTE], w[3]+7+w[3]/2); +#ifdef DEBUG profile_timer(NULL); +#endif graphics_draw(co->map_data, file_border_ply, co, display_rail, plimit, 48, poly_draw_block); graphics_draw(co->map_data, file_woodland_ply, co, display_wood, plimit, 48, poly_draw_block); graphics_draw(co->map_data, file_other_ply, co, display_other, plimit, 48, poly_draw_block); @@ -322,9 +324,14 @@ graphics_redraw(struct container *co) if (scale < 256) { graphics_draw(co->map_data, file_rail_ply, co, display_rail, plimit, 48, poly_draw_block); } +#ifdef DEBUG profile_timer("map_draw"); +#endif plugin_call_draw(co); +#ifdef DEBUG profile_timer("plugin"); +#endif + #if 0 draw_poly(map, &co->d_tunnel_ply, "Tunnel", 0, 11, plimit); #endif @@ -364,8 +371,9 @@ graphics_redraw(struct container *co) display_draw(disp[display_poi], gra, gra->gc[GC_BLACK], NULL); +#ifdef DEBUG profile_timer("display_draw"); - +#endif if (scale < 2) { display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); @@ -387,7 +395,9 @@ graphics_redraw(struct container *co) for (i = display_town ; i < display_town+0x10 ; i++) display_draw(disp[i], gra, gra->gc[GC_BLACK], NULL); display_draw(disp[display_bti], gra, gra->gc[GC_BLACK], NULL); +#ifdef DEBUG profile_timer("labels"); +#endif gra->draw_mode(gra, draw_mode_end); for (i = 0 ; i < data_window_type_end; i++) { data_window_end(co->data_window[i]); diff --git a/main.c b/main.c index bec79965..d68d3119 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,8 @@ #include "container.h" #include "debug.h" +#include "osd.h" + void *speech_handle; struct container *co; @@ -49,6 +51,11 @@ int main(int argc, char **argv) gtk_init(&argc, &argv); gdk_rgb_init(); +// i18n basic support + + bindtextdomain( "navit", "./locale" ); + textdomain( "navit" ); + map_data_default=load_maps(NULL); plugin_load(); co=gui_gtk_window(1300000,7000000,8192); @@ -62,14 +69,16 @@ int main(int argc, char **argv) co->cursor=cursor_new(co,co->vehicle); } } else { - g_warning("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]"); + g_warning(gettext("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]")); } co->speech=speech_new(); if (! co->speech) - g_warning("Can't connect to speechd, no speech output available"); + g_warning(gettext("Can't connect to speechd, no speech output available")); speech_handle=co->speech; if (co->vehicle) co->compass=compass_new(co); + if (co->vehicle) + co->osd=osd_new(co); if (co->vehicle) co->track=track_new(co->map_data); diff --git a/navigation.c b/navigation.c index 4fddbf80..07de8792 100644 --- a/navigation.c +++ b/navigation.c @@ -12,6 +12,7 @@ #include "speech.h" #include "navigation.h" #include "data_window.h" +#include "osd.h" struct data_window *navigation_window; @@ -106,43 +107,43 @@ get_distance(char *dst, int dist) if (dist < 100) { dist=(dist+5)/10; dist*=10; - sprintf(dst,"%d meter", dist); + sprintf(dst,gettext("%d meter"), dist); return; } if (dist < 250) { dist=(dist+13)/25; dist*=25; - sprintf(dst,"%d meter", dist); + sprintf(dst,gettext("%d meter"), dist); return; } if (dist < 500) { dist=(dist+25)/50; dist*=50; - sprintf(dst,"%d meter", dist); + sprintf(dst,gettext("%d meter"), dist); return; } if (dist < 1000) { dist=(dist+50)/100; dist*=100; - sprintf(dst,"%d meter", dist); + sprintf(dst,gettext("%d meter"), dist); return; } if (dist < 5000) { dist=(dist+50)/100; if (dist % 10) - sprintf(dst,"%d,%d kilometer", dist/10,dist%10); + sprintf(dst,gettext("%d,%d kilometer"), dist/10,dist%10); else - sprintf(dst,"%d kilometer", dist/10); + sprintf(dst,gettext("%d kilometer"), dist/10); return; } if (dist < 100000) { dist=(dist+500)/1000; - sprintf(dst,"%d kilometer", dist); + sprintf(dst,gettext("%d kilometer"), dist); return; } dist=(dist+5000)/10000; dist*=10; - sprintf(dst,"%d kilometer", dist); + sprintf(dst,gettext("%d kilometer"), dist); } static void @@ -151,6 +152,9 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) int delta,navmode=1,add_dir,level; struct param_list param_list[20]; + + extern struct container *co; + char roadname[256]; char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; char command[256],*p,*dir,*strength; @@ -192,53 +196,59 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) sprintf(distance,"%d", old->length); param_list[9].value=distance; add_dir=1; - dir="rechts"; + dir=gettext("rechts"); if (delta < 0) { - dir="links"; + dir=gettext("links"); delta=-delta; } if (delta < 45) { - strength="leicht "; + strength=gettext("leicht "); } else if (delta < 105) { strength=""; } else if (delta < 165) { - strength="scharf "; + strength=gettext("scharf "); } else { +#ifdef DEBUG printf("delta=%d\n", delta); - strength="unbekannt "; +#endif + strength=gettext("unbekannt "); } level=0; if (navmode) { if (old->length < 20) { level=1; - sprintf(command,"Jetzt "); + sprintf(command,gettext("Jetzt ")); } else if (old->length <= 200) { level=2; get_distance(dist, old->length); - sprintf(command,"In %sn ", dist); + sprintf(command,gettext("In %sn "), dist); } else if (old->length <= 500) { level=3; - sprintf(command,"In Kürze "); + sprintf(command,gettext("In Kürze ")); } else { level=4; get_distance(dist, old->length); - sprintf(command,"Dem Strassenverlauf %s folgen", dist); + sprintf(command,gettext("Dem Strassenverlauf %s folgen"), dist); add_dir=0; } } else { - sprintf(command,"Dem Strassenverlauf %d Meter folgen, dann ", old->length); + sprintf(command,gettext("Dem Strassenverlauf %d Meter folgen, dann "), old->length); add_dir=1; } if (add_dir) { - p=command+strlen(command); +/* p=command+strlen(command); strcpy(p,strength); p+=strlen(p); strcpy(p,dir); p+=strlen(p); - strcpy(p," abbiegen"); + strcpy(p,gettext(" abbiegen"));*/ + sprintf(command,gettext(" %s %s abbiegen"),strength,dir); + p=command+strlen(command); } param_list[10].value=command; if (flag) { + sprintf(roadname,"%s %s",old->name1,old->name2); + osd_set_next_command(command,roadname); if (level != old_level) { printf("command='%s'\n", command); if (speech_handle) diff --git a/osd.c b/osd.c new file mode 100644 index 00000000..896a7e30 --- /dev/null +++ b/osd.c @@ -0,0 +1,83 @@ +//#include +#include +#include +#include "point.h" +//#include "coord.h" +#include "graphics.h" +//#include "transform.h" +//#include "route.h" +#include "vehicle.h" +#include "container.h" +#include "osd.h" + +struct osd { + struct graphics *gr; + struct graphics_gc *bg; + struct graphics_gc *white; + struct graphics_gc *green; + struct graphics_font *font; + + char command[256]; + char road_name[256]; +}; + +void +osd_set_next_command(char *new_command,char *new_road){ + extern struct container *co; + struct osd *this=co->osd; + strcpy(this->command,new_command); + strcpy(this->road_name,new_road); + osd_draw(this, co); +} + +void +osd_draw(struct osd *osd, struct container *co) +{ + double *speed; + struct point p; + + if (! co->vehicle) + return; + + speed=vehicle_speed_get(co->vehicle); + osd->gr->draw_mode(osd->gr, draw_mode_begin); + p.x=0; + p.y=0; + osd->gr->draw_rectangle(osd->gr, osd->bg, &p, 360, 80); + p.x=10; + p.y=20; +// osd->gr->draw_text(osd->gr, osd->green, NULL, osd->font, osd->command, &p, 0x13000, 0); + char osd_data[256]; + sprintf(osd_data,"%.1f km/h",(*speed)); + osd->gr->draw_text(osd->gr, osd->green, NULL, osd->font, osd_data, &p, 0x13000, 0); + p.x=10; + p.y=40; + osd->gr->draw_text(osd->gr, osd->green, NULL, osd->font, osd->command, &p, 0x13000, 0); +// osd->gr->draw_text(osd->gr, osd->green, NULL, osd->font, "Overlay", &p, 0x10000, 0); +// printf("Text %s should appear\n",osd->command); + osd->gr->draw_mode(osd->gr, draw_mode_end); +} + + +struct osd * +osd_new(struct container *co) +{ + printf("Spawning an OSD\n"); + struct osd *this=g_new0(struct osd, 1); + struct point p; + p.x=100; + p.y=10; + this->gr=co->gra->overlay_new(co->gra, &p, 360, 80); + this->bg=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->bg, 0, 0, 0); + this->white=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->white, 0xffff, 0xffff, 0xffff); + this->gr->gc_set_linewidth(this->white, 10); + this->green=this->gr->gc_new(this->gr); + this->gr->gc_set_foreground(this->green, 0x0, 0xffff, 0x0); + this->gr->gc_set_linewidth(this->green, 10); + + this->font=this->gr->font_new(this->gr, 200); + osd_draw(this, co); + return this; +} diff --git a/osd.h b/osd.h new file mode 100644 index 00000000..815b7a4a --- /dev/null +++ b/osd.h @@ -0,0 +1,2 @@ +struct osd * osd_new(struct container *co); +void osd_draw(struct osd *comp, struct container *co); diff --git a/profile.c b/profile.c index e52622a5..b9417470 100644 --- a/profile.c +++ b/profile.c @@ -14,13 +14,12 @@ profile_timer(char *where) gettimeofday(&curr, NULL); msec=(curr.tv_usec-last.tv_usec)/1000+ (curr.tv_sec-last.tv_sec)*1000; - if (msec >= 100) + if (msec >= 100) { printf("%s:%d msec\n", where, msec); - else { + } else { usec=(curr.tv_usec-last.tv_usec)+(curr.tv_sec-last.tv_sec)*1000*1000; printf("%s:%d usec\n", where, usec); } - } gettimeofday(&last, NULL); } diff --git a/track.c b/track.c index 47e68164..2f861650 100644 --- a/track.c +++ b/track.c @@ -106,8 +106,9 @@ static void track_free_lines(struct track *tr) { struct track_line *tl=tr->lines,*next; +#ifdef DEBUG printf("track_free_lines(tr=%p)\n", tr); - +#endif while (tl) { next=tl->next; if (! tl->linenum) { @@ -207,7 +208,7 @@ track_update(struct track *tr, struct coord *c, int angle) tr->curr[1]=tm->c[1]; tr->last_out=tm->lpnt; - printf("pos 0x%lx,0x%lx value %d dist %d angle %d vs %d (%d)\n", c->x, c->y, tm->value, dist, angle, tm->angle, track_angle_delta(angle, tm->angle, 0)); + // printf("pos 0x%lx,0x%lx value %d dist %d angle %d vs %d (%d)\n", c->x, c->y, tm->value, dist, angle, tm->angle, track_angle_delta(angle, tm->angle, 0)); g_assert(dist < 10000); #if 0 profile_timer("track_update end"); -- cgit v1.2.1 From 6f42af053f75bef5b465e5b3e55a7251515c63e1 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 20 Feb 2007 10:53:15 +0000 Subject: First try to handle UTF-8 maps. git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@115 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- display.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/display.c b/display.c index 75cb3992..6b5c2189 100644 --- a/display.c +++ b/display.c @@ -242,9 +242,13 @@ label_line(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, #if 0 printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l); #endif - utf8=g_convert(label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); - gr->draw_text(gr, fg, bg, font, utf8, &p_t, dx*0x10000/l, dy*0x10000/l); - g_free(utf8); + if(!g_utf8_validate(label,-1,NULL)){ + gr->draw_text(gr, fg, bg, font, label, &p_t, dx*0x10000/l, dy*0x10000/l); + } else { + utf8=g_convert(label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); + gr->draw_text(gr, fg, bg, font, utf8, &p_t, dx*0x10000/l, dy*0x10000/l); + g_free(utf8); + } } } } @@ -264,9 +268,14 @@ display_labels(struct display_list *list, struct graphics *gr, struct graphics_g case 3: p.x=list->p[0].x+3; p.y=list->p[0].y+10; - utf8=g_convert(list->label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); - gr->draw_text(gr, fg, bg, font, utf8, &p, 0x10000, 0); - g_free(utf8); + + if(g_utf8_validate(list->label,-1, NULL)){ + utf8=g_convert(list->label, -1, "utf8", "iso8859-1", NULL, NULL, NULL); + gr->draw_text(gr, fg, bg, font, utf8, &p, 0x10000, 0); + g_free(utf8); + } else { + gr->draw_text(gr, fg, bg, font, list->label, &p, 0x10000, 0); + } break; } } -- cgit v1.2.1 From 440c02c9da9aba13e4ec039a5de530e0b6737547 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 20 Feb 2007 14:19:25 +0000 Subject: Added a gui option for toll-free routing, and another to add a sticky view (FixedPos mode). git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@116 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- container.h | 2 ++ cursor.c | 2 +- navigation.c | 1 - osd.c | 8 ++++---- route.c | 18 ++++++++++++++++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/container.h b/container.h index 03cf94a8..bc1b317b 100644 --- a/container.h +++ b/container.h @@ -46,6 +46,8 @@ enum data_window_type { struct map_flags { int orient_north; + int tollfree; + int fixedpos_mode; int track; }; diff --git a/cursor.c b/cursor.c index 92186538..e57f3ac8 100644 --- a/cursor.c +++ b/cursor.c @@ -173,7 +173,7 @@ cursor_update(void *t) cursor_map_reposition(this, pos, dir); transform(this->co->trans, pos, &pnt); } - if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height) { + if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height || this->co->flags->fixedpos_mode) { cursor_map_reposition(this, pos, dir); transform(this->co->trans, pos, &pnt); } diff --git a/navigation.c b/navigation.c index 07de8792..c6a7e3e0 100644 --- a/navigation.c +++ b/navigation.c @@ -153,7 +153,6 @@ make_maneuver(struct navigation_item *old, struct navigation_item *new) int delta,navmode=1,add_dir,level; struct param_list param_list[20]; - extern struct container *co; char roadname[256]; char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; diff --git a/osd.c b/osd.c index 896a7e30..40703d4c 100644 --- a/osd.c +++ b/osd.c @@ -24,10 +24,10 @@ struct osd { void osd_set_next_command(char *new_command,char *new_road){ extern struct container *co; - struct osd *this=co->osd; - strcpy(this->command,new_command); - strcpy(this->road_name,new_road); - osd_draw(this, co); + // struct osd *this=co->osd; + strcpy(co->osd->command,new_command); + strcpy(co->osd->road_name,new_road); + osd_draw(co->osd, co); } void diff --git a/route.c b/route.c index 9fd255d5..8907a54b 100644 --- a/route.c +++ b/route.c @@ -18,6 +18,7 @@ #include "navigation.h" #include "fib-1.0/fib.h" #include "time.h" +#include "container.h" /* Node1: 4 */ /* Node2: 4 */ @@ -399,6 +400,23 @@ route_display_points(struct route *this, struct container *co) static int route_time(int type, int len) { + // The following is a quick hack to handle + // properly tolled road, at least in France. + extern struct container *co; + if((type==0x21)||(type==0x61)){ + if(co->flags->tollfree){ + // We don't allow tolled roads. We return the highest possible value. + return len*36; + } else { + type=1; + } + } + if(speed_list[type & 0x3f]<1 || speed_list[type & 0x3f]>150){ + // The road here hasn't its speed correctly set up. + // I think it's best to assign it a high cost for the moment. + printf("Road type %x (%i) is unknown (speed %i, key %i), assigning high cost\n",type,type,speed_list[type & 0x3f],(type & 0x3f)); + return len*36; + } return len*36/speed_list[type & 0x3f]; } -- cgit v1.2.1 From da32a32bcc525c4c776758890b3bbd072ff70bd6 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 27 Feb 2007 11:01:33 +0000 Subject: Re-enabled poi_geodownload plugin git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@117 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- plugin.c | 11 +++++------ plugins/Makefile.am | 2 ++ plugins/poi_geodownload/Makefile.am | 14 ++++++++++++++ plugins/poi_geodownload/libmdb/Makefile.am | 13 +++++++++++++ plugins/poi_geodownload/libmdb/include/mdbtools.h | 2 +- 5 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 plugins/Makefile.am create mode 100644 plugins/poi_geodownload/Makefile.am create mode 100644 plugins/poi_geodownload/libmdb/Makefile.am diff --git a/plugin.c b/plugin.c index 1ad87e68..e7edfe40 100644 --- a/plugin.c +++ b/plugin.c @@ -7,16 +7,15 @@ void plugin_load(void) { -#if 0 char *plugin="plugins/poi_geodownload/plugin_poi_geodownload.so"; void *h=dlopen(plugin,RTLD_LAZY); void (*init)(void); - if (! h) - printf("can't load '%s', Error '%s'\n", plugin, dlerror()); - else { + if (! h) { + /* printf("can't load '%s', Error '%s'\n", plugin, dlerror()); */ + } else { init=dlsym(h,"plugin_init"); - (*init)(); + if (init) + (*init)(); } -#endif } diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 00000000..603ca500 --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=poi_geodownload + diff --git a/plugins/poi_geodownload/Makefile.am b/plugins/poi_geodownload/Makefile.am new file mode 100644 index 00000000..0f4d0bc4 --- /dev/null +++ b/plugins/poi_geodownload/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS=libmdb +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. -Ilibmdb/include -shared + +objdir=$(prefix) +obj_PROGRAMS=plugin_poi_geodownload.so +INSTALL_PROGRAM=/bin/true + +plugin_poi_geodownload_so_SOURCES=poi.c + +plugin_poi_geodownload.so: $(plugin_poi_geodownload_so_OBJECTS) + $(CC) $(CFLAGS) -shared -o $@ $(plugin_poi_geodownload_so_OBJECTS) -Llibmdb -lmdb + + diff --git a/plugins/poi_geodownload/libmdb/Makefile.am b/plugins/poi_geodownload/libmdb/Makefile.am new file mode 100644 index 00000000..f67ff135 --- /dev/null +++ b/plugins/poi_geodownload/libmdb/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @PACKAGE_CFLAGS@ -Iinclude + +objdir=$(prefix) +obj_PROGRAMS=libmdb.a +INSTALL_PROGRAM=/bin/true + +libmdb_a_SOURCES=backend.c catalog.c data.c dump.c file.c iconv.c index.c kkd.c like.c map.c mem.c money.c options.c props.c sargs.c stats.c table.c worktable.c write.c + +libmdb.a: $(libmdb_a_OBJECTS) + ar r $@ $(libmdb_a_OBJECTS) + + diff --git a/plugins/poi_geodownload/libmdb/include/mdbtools.h b/plugins/poi_geodownload/libmdb/include/mdbtools.h index 186851bc..7be25a79 100644 --- a/plugins/poi_geodownload/libmdb/include/mdbtools.h +++ b/plugins/poi_geodownload/libmdb/include/mdbtools.h @@ -151,7 +151,7 @@ enum { #define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) /* hash to store registered backends */ -extern GHashTable *mdb_backends; +/* extern GHashTable *mdb_backends; */ /* forward declarations */ typedef struct mdbindex MdbIndex; -- cgit v1.2.1 From 111349728788eca710436769ab9f3158c4da7eec Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 28 Feb 2007 20:54:22 +0000 Subject: Fix plugin loading git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@119 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 404a6198..fb2fad6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am ./configure AM_CPPFLAGS = @PACKAGE_CFLAGS@ +LDFLAGS = -Wl,--export-dynamic bin_PROGRAMS = navit -- cgit v1.2.1 From 0dc94b1e7d6caa359c08088265a43653e9f390ec Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 2 Mar 2007 11:01:07 +0000 Subject: Updated for text file csv git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@120 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- plugins/poi_geodownload/poi.c | 230 ++++++++++++++++++++++++++++-------------- 1 file changed, 156 insertions(+), 74 deletions(-) diff --git a/plugins/poi_geodownload/poi.c b/plugins/poi_geodownload/poi.c index 26b81a1e..5540e7f5 100644 --- a/plugins/poi_geodownload/poi.c +++ b/plugins/poi_geodownload/poi.c @@ -13,6 +13,8 @@ struct index_data { struct poi { char *filename; char *icon; + int type; + long pos; MdbHandle *h; MdbHandle *h_idx; MdbTableDef *table; @@ -31,6 +33,26 @@ struct poi_data { int row; }; +struct text_poi { + double lng; + double lat; + char *name; +}; + +static int +parse_text_poi(char *line, struct text_poi *ret) +{ + int rest; + if (sscanf(line, "\"%lf\";\"%lf\";\"%n",&ret->lng,&ret->lat,&rest) == 2) { + ret->name=line+rest; + if (strlen(ret->name)) { + ret->name[strlen(ret->name)-1]='\0'; + } + printf("%f %f %s\n", ret->lng, ret->lat, ret->name); + return 1; + } + return 0; +} static void print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) @@ -278,7 +300,7 @@ load_poi_table(struct poi *poi, MdbCatalogEntry *entry) } static void -load_poi(char *filename, char *icon) +load_poi(char *filename, char *icon, int type) { int i; MdbCatalogEntry *entry; @@ -287,20 +309,23 @@ load_poi(char *filename, char *icon) new->filename = filename; new->icon = icon; - - new->h = mdb_open(filename, MDB_NOFLAGS); - catalog = mdb_read_catalog(new->h, MDB_TABLE); - for (i = 0; i < catalog->len; i++) { - entry = catalog->pdata[i]; - if (!strcasecmp(entry->object_name, "_INDEXDATA")) { - if (load_poi_table(new, entry)) { - printf("%s invalid\n", filename); - g_free(new); - new=NULL; + new->type = type; + + if (type == 0) { + new->h = mdb_open(filename, MDB_NOFLAGS); + catalog = mdb_read_catalog(new->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(new, entry)) { + printf("%s invalid\n", filename); + g_free(new); + new=NULL; + } } } + g_ptr_array_free(catalog, 1); } - g_ptr_array_free(catalog, 1); if (new) { new->next = poi_list; poi_list = new; @@ -326,36 +351,60 @@ poi_info(struct display_list *list, struct popup_item **popup) char *v; popup_last = *popup; - printf("poi_info pg=%d row=%d\n", data->page, data->row); - load_row(poi, data->page, data->row); popup_val_last = NULL; sprintf(buffer,"File:%s", poi->filename); popup_item_new_text(&popup_val_last, buffer, 1); sprintf(buffer,"Icon:%s", poi->icon); popup_item_new_text(&popup_val_last, buffer, 2); - sprintf(buffer,"Page:%d", data->page); - popup_item_new_text(&popup_val_last, buffer, 3); - sprintf(buffer,"Row:%d", data->row); - popup_item_new_text(&popup_val_last, buffer, 4); - for (j = 0; j < poi->table_col->len; j++) { - col = poi->table_col->pdata[j]; -#if 0 - printf("start: %d type:%d\n", col->cur_value_start, col->col_type); -#endif - sprintf(buffer, "%s:", col->name); - v = buffer + strlen(buffer); - if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) - print_col(poi->h, col, v, 1); - else - print_col(poi->h, col, v, 0); -#if 0 - printf("%s\n", buffer); -#endif - text=g_convert(buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - popup_item_new_text(&popup_val_last, buffer, j+10); - g_free(text); - + if (poi->type == 0) { + printf("poi_info pg=%d row=%d\n", data->page, data->row); + load_row(poi, data->page, data->row); + sprintf(buffer,"Page:%d", data->page); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Row:%d", data->row); + popup_item_new_text(&popup_val_last, buffer, 4); + for (j = 0; j < poi->table_col->len; j++) { + col = poi->table_col->pdata[j]; + #if 0 + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); + #endif + sprintf(buffer, "%s:", col->name); + v = buffer + strlen(buffer); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(poi->h, col, v, 1); + else + print_col(poi->h, col, v, 0); + #if 0 + printf("%s\n", buffer); + #endif + text=g_convert(buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + popup_item_new_text(&popup_val_last, buffer, j+10); + g_free(text); + } + } + if (poi->type == 1) { + FILE *f; + struct text_poi tpoi; + char line[1024]; + + f=fopen(poi->filename,"r"); + fseek(f, data->row, SEEK_SET); + fgets(line, 1024, f); + if (strlen(line)) { + line[strlen(line)-1]='\0'; + } + sprintf(buffer,"Pos:%d", data->row); + popup_item_new_text(&popup_val_last, buffer, 3); + if (parse_text_poi(line, &tpoi)) { + sprintf(buffer,"Name:%s", tpoi.name); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Lat:%f", tpoi.lat); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Lng:%f", tpoi.lng); + popup_item_new_text(&popup_val_last, buffer, 3); + } + fclose(f); } popup_item_new_text(&popup_last, "POI", 20)->submenu = popup_val_last; *popup=popup_last; @@ -366,8 +415,13 @@ draw_poi(struct poi *p, struct container *co, struct point *pnt) { struct poi_data data; data.poi=p; - data.page=p->h->cur_pg; - data.row=p->table->cur_row-1; + if (p->type == 0) { + data.page=p->h->cur_pg; + data.row=p->table->cur_row-1; + } + if (p->type == 1) { + data.row=p->pos; + } display_add(&co->disp[display_poi], 5, 0, p->icon, 1, pnt, poi_info, &data, sizeof(data)); } @@ -390,29 +444,54 @@ plugin_draw(struct container *co) printf("rect 0x%lx,0%lx-0x%lx,0x%lx\n", co->trans->rect[0].x, co->trans->rect[0].y, co->trans->rect[1].x, co->trans->rect[1].y); } while (p) { - if (use_index) - setup_idx_rect(co->trans->rect, idx, p->idx_size); - if (! use_index) { - printf("rewind %s %p\n", p->filename, p->table); - mdb_rewind_table(p->table); - while (mdb_fetch_row(p->table)) { - get_coord(p, &c); - if (transform(co->trans, &c, &pnt)) { - if (debug) - printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); - draw_poi(p, co, &pnt); + if (p->type == 0) { + if (use_index) + setup_idx_rect(co->trans->rect, idx, p->idx_size); + if (! use_index) { + printf("rewind %s %p\n", p->filename, p->table); + mdb_rewind_table(p->table); + while (mdb_fetch_row(p->table)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } else { + memset(&p->chain, 0, sizeof(p->chain)); + while (index_next(p, idx)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } } } - } else { - memset(&p->chain, 0, sizeof(p->chain)); - while (index_next(p, idx)) { - get_coord(p, &c); - if (transform(co->trans, &c, &pnt)) { - if (debug) - printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); - draw_poi(p, co, &pnt); + } + if (p->type == 1) { + FILE *f; + char line[1024]; + struct text_poi tpoi; + f=fopen(p->filename, "r"); + p->pos=ftell(f); + fgets(line, 1024, f); + while (!feof(f)) { + if (strlen(line)) { + line[strlen(line)-1]='\0'; } + if (parse_text_poi(line, &tpoi)) { + transform_mercator(&tpoi.lat,&tpoi.lng,&c); + printf("%ld %ld\n", c.x, c.y); + if (transform(co->trans, &c, &pnt)) { + draw_poi(p, co, &pnt); + } + } + p->pos=ftell(f); + fgets(line, 1024, f); } + fclose(f); } p = p->next; } @@ -425,50 +504,53 @@ int plugin_init(void) plugin_register_draw(plugin_draw); mdb_init(); load_poi("/home/martin/map/work/data/1/GEO00001.MDB", - "/home/martin/map/work/data/1/_MCDNLDS.BMP"); + "/home/martin/map/work/data/1/_MCDNLDS.BMP",0); load_poi("/home/martin/map/work/data/2/GEO00001.MDB", - "/home/martin/map/work/data/2/_BURKING.BMP"); + "/home/martin/map/work/data/2/_BURKING.BMP",0); load_poi("/home/martin/map/work/data/3/GEO00001.MDB", - "/home/martin/map/work/data/3/_PIZZHUT.BMP"); + "/home/martin/map/work/data/3/_PIZZHUT.BMP",0); load_poi("/home/martin/map/work/data/4/GEO00001.MDB", - "/home/martin/map/work/data/4/_CHICKEN.BMP"); + "/home/martin/map/work/data/4/_CHICKEN.BMP",0); load_poi("/home/martin/map/work/data/5/GEO00001.MDB", - "/home/martin/map/work/data/5/_WIENERW.BMP"); + "/home/martin/map/work/data/5/_WIENERW.BMP",0); load_poi ("/opt/reiseplaner/travel/prog.mov/bahn.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/bahn.adr/BAHN.BMP"); + "/opt/reiseplaner/travel/prog.mov/bahn.adr/BAHN.BMP",0); load_poi ("/opt/reiseplaner/travel/prog.mov/cinmus.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/cinmus.adr/_Kinocen.bmp"); + "/opt/reiseplaner/travel/prog.mov/cinmus.adr/_Kinocen.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/fsight.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/fsight.adr/_sehensw.bmp"); + "/opt/reiseplaner/travel/prog.mov/fsight.adr/_sehensw.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/erlbns.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/erlbns.adr/_Freizei.bmp"); + "/opt/reiseplaner/travel/prog.mov/erlbns.adr/_Freizei.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/faehre.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/faehre.adr/_Faehren.bmp"); + "/opt/reiseplaner/travel/prog.mov/faehre.adr/_Faehren.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/fenter.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/fenter.adr/_casino.bmp"); + "/opt/reiseplaner/travel/prog.mov/fenter.adr/_casino.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/vhotel.adr/Geo00001.mdb", - "/opt/reiseplaner/travel/prog.mov/vhotel.adr/Vhotel.bmp"); + "/opt/reiseplaner/travel/prog.mov/vhotel.adr/Vhotel.bmp",0); load_poi ("/opt/reiseplaner/travel/prog.mov/vgast.adr/Geo00001.mdb", - "/opt/reiseplaner/travel/prog.mov/vgast.adr/Vgast.BMP"); + "/opt/reiseplaner/travel/prog.mov/vgast.adr/Vgast.BMP",0); load_poi ("/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.mdb", - "/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.bmp"); + "/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.bmp",0); load_poi ("/opt/reiseplaner/travel/address/p_eeu.adr/p_eeu.mdb", - "/opt/reiseplaner/travel/address/p_eeu.adr/P_eeu.bmp"); + "/opt/reiseplaner/travel/address/p_eeu.adr/P_eeu.bmp",0); load_poi ("/opt/reiseplaner/travel/address/p_heu.adr/p_heu.mdb", - "/opt/reiseplaner/travel/address/p_heu.adr/P_heu.bmp"); + "/opt/reiseplaner/travel/address/p_heu.adr/P_heu.bmp",0); load_poi ("/opt/reiseplaner/travel/address/p_ieu.adr/p_ieu.mdb", - "/opt/reiseplaner/travel/address/p_ieu.adr/P_ieu.bmp"); + "/opt/reiseplaner/travel/address/p_ieu.adr/P_ieu.bmp",0); + + load_poi + ("/tmp/textpoi.csv","/tmp/textpoi.bmp",1); return 0; } -- cgit v1.2.1 From 9e6e8f0a5f934a46b3e447a7a034b2aea673242b Mon Sep 17 00:00:00 2001 From: kazer_ Date: Mon, 12 Mar 2007 17:11:37 +0000 Subject: First support of autoloading from a given directory, and .asc files. git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@121 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- plugins/poi_geodownload/poi.c | 190 ++++++++++++++++++++++++++++-------------- 1 file changed, 129 insertions(+), 61 deletions(-) diff --git a/plugins/poi_geodownload/poi.c b/plugins/poi_geodownload/poi.c index 5540e7f5..5dd9ecc5 100644 --- a/plugins/poi_geodownload/poi.c +++ b/plugins/poi_geodownload/poi.c @@ -7,12 +7,16 @@ #include "plugin.h" +#include +#include +#include + struct index_data { unsigned char data[15]; }; struct poi { - char *filename; - char *icon; + char filename[1024]; + char icon[1024]; int type; long pos; MdbHandle *h; @@ -39,18 +43,36 @@ struct text_poi { char *name; }; + char poipath[256]; + char poibmp[256]; + + static int parse_text_poi(char *line, struct text_poi *ret) { int rest; + // This is for csv like files if (sscanf(line, "\"%lf\";\"%lf\";\"%n",&ret->lng,&ret->lat,&rest) == 2) { ret->name=line+rest; if (strlen(ret->name)) { ret->name[strlen(ret->name)-1]='\0'; } - printf("%f %f %s\n", ret->lng, ret->lat, ret->name); return 1; } + // This is for asc files + if (sscanf(line, "%lf , %lf , \"%n",&ret->lat,&ret->lng,&rest) == 2) { + ret->name=line+rest; + if (strlen(ret->name)) { + ret->name[strlen(ret->name)-1]='\0'; + } + return 1; + } + if(line[0]==';'){ + // + } else if(strlen(line)<2){ + } else { + printf("not matched : [%s]\n",line); + } return 0; } @@ -307,10 +329,30 @@ load_poi(char *filename, char *icon, int type) GPtrArray *catalog; struct poi *new = g_new0(struct poi, 1); - new->filename = filename; - new->icon = icon; + FILE *fp = fopen(filename,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : POI file %s does not exists!\n",filename); + exit(0); + return -1; + } + + + fp = fopen(icon,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : WARNING INCORRECT PICTURE! %s!\n",icon); + exit(0); + return -1; + } + + strcpy(new->filename,filename); + strcpy(new->icon,icon); new->type = type; + if (type == 0) { new->h = mdb_open(filename, MDB_NOFLAGS); catalog = mdb_read_catalog(new->h, MDB_TABLE); @@ -405,6 +447,7 @@ poi_info(struct display_list *list, struct popup_item **popup) popup_item_new_text(&popup_val_last, buffer, 3); } fclose(f); + printf("buffer : %s\n",buffer); } popup_item_new_text(&popup_last, "POI", 20)->submenu = popup_val_last; *popup=popup_last; @@ -432,13 +475,13 @@ plugin_draw(struct container *co) struct point pnt; struct poi *p; struct index_data idx[2]; - int use_index=1; - int debug=0; + int use_index=0; + int debug=1; p = poi_list; - if (co->trans->scale > 256) - return; + if (co->trans->scale > 1024) + return; if (debug) { printf("scale=%ld\n", co->trans->scale); printf("rect 0x%lx,0%lx-0x%lx,0x%lx\n", co->trans->rect[0].x, co->trans->rect[0].y, co->trans->rect[1].x, co->trans->rect[1].y); @@ -474,8 +517,14 @@ plugin_draw(struct container *co) FILE *f; char line[1024]; struct text_poi tpoi; - f=fopen(p->filename, "r"); - p->pos=ftell(f); + if(!(f=fopen(p->filename, "r"))){ + printf("can't open poi file for drawing!\n"); + exit(0); + } +#if 0 + printf("opened poi file %s for drawing!\n",p->filename); +#endif + p->pos=ftell(f); fgets(line, 1024, f); while (!feof(f)) { if (strlen(line)) { @@ -483,7 +532,7 @@ plugin_draw(struct container *co) } if (parse_text_poi(line, &tpoi)) { transform_mercator(&tpoi.lat,&tpoi.lng,&c); - printf("%ld %ld\n", c.x, c.y); +// printf("%ld %ld\n", c.x, c.y); if (transform(co->trans, &c, &pnt)) { draw_poi(p, co, &pnt); } @@ -503,54 +552,73 @@ int plugin_init(void) { plugin_register_draw(plugin_draw); mdb_init(); - load_poi("/home/martin/map/work/data/1/GEO00001.MDB", - "/home/martin/map/work/data/1/_MCDNLDS.BMP",0); - load_poi("/home/martin/map/work/data/2/GEO00001.MDB", - "/home/martin/map/work/data/2/_BURKING.BMP",0); - load_poi("/home/martin/map/work/data/3/GEO00001.MDB", - "/home/martin/map/work/data/3/_PIZZHUT.BMP",0); - load_poi("/home/martin/map/work/data/4/GEO00001.MDB", - "/home/martin/map/work/data/4/_CHICKEN.BMP",0); - load_poi("/home/martin/map/work/data/5/GEO00001.MDB", - "/home/martin/map/work/data/5/_WIENERW.BMP",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/bahn.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/bahn.adr/BAHN.BMP",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/cinmus.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/cinmus.adr/_Kinocen.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/fsight.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/fsight.adr/_sehensw.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/erlbns.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/erlbns.adr/_Freizei.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/faehre.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/faehre.adr/_Faehren.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/fenter.adr/GEO00001.MDB", - "/opt/reiseplaner/travel/prog.mov/fenter.adr/_casino.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/vhotel.adr/Geo00001.mdb", - "/opt/reiseplaner/travel/prog.mov/vhotel.adr/Vhotel.bmp",0); - load_poi - ("/opt/reiseplaner/travel/prog.mov/vgast.adr/Geo00001.mdb", - "/opt/reiseplaner/travel/prog.mov/vgast.adr/Vgast.BMP",0); - load_poi - ("/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.mdb", - "/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.bmp",0); - load_poi - ("/opt/reiseplaner/travel/address/p_eeu.adr/p_eeu.mdb", - "/opt/reiseplaner/travel/address/p_eeu.adr/P_eeu.bmp",0); - load_poi - ("/opt/reiseplaner/travel/address/p_heu.adr/p_heu.mdb", - "/opt/reiseplaner/travel/address/p_heu.adr/P_heu.bmp",0); - load_poi - ("/opt/reiseplaner/travel/address/p_ieu.adr/p_ieu.mdb", - "/opt/reiseplaner/travel/address/p_ieu.adr/P_ieu.bmp",0); - - load_poi - ("/tmp/textpoi.csv","/tmp/textpoi.bmp",1); +// load_poi("/home/martin/map/work/data/1/GEO00001.MDB", +// "/home/martin/map/work/data/1/_MCDNLDS.BMP",0); +// load_poi("/home/martin/map/work/data/2/GEO00001.MDB", +// "/home/martin/map/work/data/2/_BURKING.BMP",0); +// load_poi("/home/martin/map/work/data/3/GEO00001.MDB", +// "/home/martin/map/work/data/3/_PIZZHUT.BMP",0); +// load_poi("/home/martin/map/work/data/4/GEO00001.MDB", +// "/home/martin/map/work/data/4/_CHICKEN.BMP",0); +// load_poi("/home/martin/map/work/data/5/GEO00001.MDB", +// "/home/martin/map/work/data/5/_WIENERW.BMP",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/bahn.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/bahn.adr/BAHN.BMP",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/cinmus.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/cinmus.adr/_Kinocen.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/fsight.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/fsight.adr/_sehensw.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/erlbns.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/erlbns.adr/_Freizei.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/faehre.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/faehre.adr/_Faehren.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/fenter.adr/GEO00001.MDB", +// "/opt/reiseplaner/travel/prog.mov/fenter.adr/_casino.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/vhotel.adr/Geo00001.mdb", +// "/opt/reiseplaner/travel/prog.mov/vhotel.adr/Vhotel.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/prog.mov/vgast.adr/Geo00001.mdb", +// "/opt/reiseplaner/travel/prog.mov/vgast.adr/Vgast.BMP",0); +// load_poi +// ("/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.mdb", +// "/opt/reiseplaner/travel/address/p_ceu.adr/p_ceu.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/address/p_eeu.adr/p_eeu.mdb", +// "/opt/reiseplaner/travel/address/p_eeu.adr/P_eeu.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/address/p_heu.adr/p_heu.mdb", +// "/opt/reiseplaner/travel/address/p_heu.adr/p_heu.bmp",0); +// load_poi +// ("/opt/reiseplaner/travel/address/p_ieu.adr/p_ieu.mdb", +// "/opt/reiseplaner/travel/address/p_ieu.adr/P_ieu.bmp",0); + + + struct dirent *lecture; + DIR *rep; + rep = opendir("./pois"); + char fichier[256]; + char ext[3]; + + printf("\nLoading ASC pois from ./pois..\n"); + while ((lecture = readdir(rep))){ + if (sscanf(lecture->d_name, "%[a-zA-Z_].%[a-zA-Z]",fichier,ext) == 2) { + if(!strcmp(ext,"asc")){ + sprintf(poibmp,"./pois/%s.bmp",fichier); + sprintf(poipath,"./pois/%s.asc",fichier); + printf("Found poi file [%s] using icon [%s]\n",poipath,poibmp); + + load_poi (poipath,poibmp,1); + } + } + } + closedir(rep); + return 0; } -- cgit v1.2.1 From e9711b0272267c5ade3760741d4c97d633edd394 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 13 Mar 2007 11:55:57 +0000 Subject: Added better callback support to vehicle.c git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@122 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.c | 5 ++--- vehicle.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++----------- vehicle.h | 4 +++- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/cursor.c b/cursor.c index e57f3ac8..d126f684 100644 --- a/cursor.c +++ b/cursor.c @@ -154,12 +154,11 @@ cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir } static void -cursor_update(void *t) +cursor_update(struct vehicle *v, void *t) { struct cursor *this=t; struct point pnt; struct coord *pos; - struct vehicle *v=this->co->vehicle; double *dir; if (v) { @@ -195,6 +194,6 @@ cursor_new(struct container *co, struct vehicle *v) this->cursor_gc=co->gra->gc_new(co->gra); co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff); co->gra->gc_set_linewidth(this->cursor_gc, 2); - vehicle_callback(v, cursor_update, this); + vehicle_callback_register(v, cursor_update, this); return this; } diff --git a/vehicle.c b/vehicle.c index d76a2c9f..747ffffa 100644 --- a/vehicle.c +++ b/vehicle.c @@ -16,6 +16,11 @@ /* #define INTERPOLATION_TIME 50 */ +struct callback { + void (*func)(struct vehicle *, void *data); + void *data; +}; + struct vehicle { GIOChannel *iochan; int timer_count; @@ -33,8 +38,7 @@ struct vehicle { #ifdef HAVE_LIBGPS struct gps_data_t *gps; #endif - void (*callback_func)(void *data); - void *callback_data; + GList *callbacks; }; struct vehicle *vehicle_last; @@ -58,6 +62,17 @@ vehicle_timer(gpointer t) } #endif +static void +vehicle_call_callbacks(struct vehicle *this) +{ + GList *item=g_list_first(this->callbacks); + while (item) { + struct callback *cb=item->data; + (*cb->func)(this, cb->data); + item=g_list_next(item); + } +} + struct coord * vehicle_pos_get(struct vehicle *this) { @@ -76,6 +91,12 @@ vehicle_dir_get(struct vehicle *this) return &this->dir; } +double * +vehicle_height_get(struct vehicle *this) +{ + return &this->height; +} + void vehicle_set_position(struct vehicle *this, struct coord *pos) { @@ -84,8 +105,7 @@ vehicle_set_position(struct vehicle *this, struct coord *pos) this->curr.y=this->current_pos.y; this->delta.x=0; this->delta.y=0; - if (this->callback_func) - (*this->callback_func)(this->callback_data); + vehicle_call_callbacks(this); } static void @@ -131,8 +151,7 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; - if (this->callback_func) - (*this->callback_func)(this->callback_data); + vehicle_call_callbacks(this); } if (!strncmp(buffer,"$GPVTG",6)) { /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A @@ -230,8 +249,7 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; - if (this->callback_func) - (*this->callback_func)(this->callback_data); + vehicle_call_callbacks(this); data->set &= ~LATLON_SET; } if (data->set & ALTITUDE_SET) { @@ -309,17 +327,28 @@ vehicle_new(const char *url) return this; } +void * +vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data) +{ + struct callback *cb; + cb=g_new(struct callback, 1); + cb->func=func; + cb->data=data; + this->callbacks=g_list_prepend(this->callbacks, cb); + return cb; +} + void -vehicle_callback(struct vehicle *this, void (*func)(void *data), void *data) +vehicle_callback_unregister(struct vehicle *this, void *handle) { - this->callback_func=func; -this->callback_data=data; + g_list_remove(this->callbacks, handle); } void vehicle_destroy(struct vehicle *this) { GError *error=NULL; + GList *item=g_list_first(this->callbacks),*next; g_io_channel_shutdown(this->iochan,0,&error); @@ -327,5 +356,11 @@ vehicle_destroy(struct vehicle *this) if (this->gps) gps_close(this->gps); #endif + while (item) { + next=g_list_next(item); + vehicle_callback_unregister(this, item->data); + item=next; + } + g_list_free(this->callbacks); g_free(this); } diff --git a/vehicle.h b/vehicle.h index 98f18ec2..aa028c49 100644 --- a/vehicle.h +++ b/vehicle.h @@ -3,7 +3,9 @@ struct vehicle; struct coord *vehicle_pos_get(struct vehicle *); double *vehicle_dir_get(struct vehicle *); double *vehicle_speed_get(struct vehicle *); -void vehicle_callback(struct vehicle *, void (*func)(void *data),void *data); +double *vehicle_height_get(struct vehicle *this); +void * vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); +void vehicle_callback_unregister(struct vehicle *this, void *handle); void vehicle_set_position(struct vehicle *, struct coord *); struct vehicle *vehicle_new(const char *url); void vehicle_destroy(struct vehicle *); -- cgit v1.2.1 From 48ab6ef8925fb65798d1140b7759675b85e2e603 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Mon, 16 Apr 2007 11:53:57 +0000 Subject: Added a font path for arial.ttf. This is the default path under Gentoo for example. Will avoid new users to have the "WARNING **: Failed to load font, no labelling" git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@140 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics/gtk_drawing_area/graphics_gtk_drawing_area.c | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 81047e00..a1d18c31 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -48,6 +48,7 @@ char *fontlist[]={ "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", "/usr/share/fonts/ttf/arial.ttf", + "/usr/share/fonts/corefonts/arial.ttf", NULL, }; -- cgit v1.2.1 From a583a2163abaa058721df3253d779e7921483bb1 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 17 Apr 2007 09:00:35 +0000 Subject: First commit so sdl branch. Changed the return value type from double * to double. git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@143 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vehicle.c b/vehicle.c index 747ffffa..4af5b9da 100644 --- a/vehicle.c +++ b/vehicle.c @@ -79,10 +79,10 @@ vehicle_pos_get(struct vehicle *this) return &this->current_pos; } -double * +double vehicle_speed_get(struct vehicle *this) { - return &this->speed; + return this->speed; } double * @@ -91,10 +91,10 @@ vehicle_dir_get(struct vehicle *this) return &this->dir; } -double * +double vehicle_height_get(struct vehicle *this) { - return &this->height; + return this->height; } void -- cgit v1.2.1 From 17a8019e360078561435b02e9160c4bf888893c7 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 17 Apr 2007 09:10:14 +0000 Subject: Revert accidentially done changes git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@144 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- vehicle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vehicle.c b/vehicle.c index 4af5b9da..747ffffa 100644 --- a/vehicle.c +++ b/vehicle.c @@ -79,10 +79,10 @@ vehicle_pos_get(struct vehicle *this) return &this->current_pos; } -double +double * vehicle_speed_get(struct vehicle *this) { - return this->speed; + return &this->speed; } double * @@ -91,10 +91,10 @@ vehicle_dir_get(struct vehicle *this) return &this->dir; } -double +double * vehicle_height_get(struct vehicle *this) { - return this->height; + return &this->height; } void -- cgit v1.2.1 From d71e49df9261a6968e7ffab33c6306914ac1d1c0 Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 4 Jul 2007 22:44:46 +0000 Subject: Merge with modular_map git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@255 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 31 +- action.h | 3 - attr.c | 40 + attr.h | 24 + attr_def.h | 37 + callback.c | 112 + callback.h | 15 + color.h | 3 + command.c | 147 -- command.h | 1 - compass.c | 7 +- coord.c | 176 ++ coord.h | 22 +- country.c | 204 +- country.h | 19 +- cursor.c | 140 +- cursor.h | 15 +- data.h | 47 +- data/Makefile.am | 1 + data/garmin_img/Makefile.am | 4 + data/garmin_img/garmin_img.c | 1486 +++++++++++++ data/mg/Makefile.am | 4 + data/mg/block.c | 261 +++ data/mg/map.c | 296 +++ data/mg/mg.h | 286 +++ data/mg/poly.c | 196 ++ data/mg/street.c | 702 ++++++ data/mg/town.c | 261 +++ data/mg/tree.c | 232 ++ data/textfile/Makefile.am | 4 + data/textfile/textfile.c | 355 +++ data/textfile/textfile.h | 28 + data_window.c | 35 +- debug.c | 52 + debug.h | 7 + destination.h | 15 +- display.h | 24 - fib-1.1/fib.c | 5 +- file.c | 42 + file.h | 20 +- graphics.c | 996 ++++++--- graphics.h | 151 +- graphics/Makefile.am | 8 +- graphics/gtk_drawing_area/Makefile.am | 15 +- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 524 +++-- graphics/null/Makefile.am | 4 + graphics/null/graphics_null.c | 217 ++ graphics/opengl/Makefile.am | 4 + graphics/opengl/graphics_opengl.c | 927 ++++++++ gui.c | 106 + gui.h | 36 + gui/Makefile.am | 9 +- gui/gtk/Makefile.am | 15 +- gui/gtk/destination.c | 369 +++ gui/gtk/gtkeyboard.c | 2350 -------------------- gui/gtk/gtkeyboard.h | 3 - gui/gtk/gui_gtk.h | 23 +- gui/gtk/gui_gtk_action.c | 289 ++- gui/gtk/gui_gtk_menu.c | 364 --- gui/gtk/gui_gtk_statusbar.c | 80 +- gui/gtk/gui_gtk_toolbar.c | 340 --- gui/gtk/gui_gtk_window.c | 153 +- gui/sdl/Makefile.am | 5 + gui/sdl/gui_sdl.h | 23 + gui/sdl/gui_sdl_window.cpp | 684 ++++++ gui/sdl/sdl_events.cpp | 771 +++++++ gui/sdl/sdl_events.h | 32 + item.c | 132 ++ item.h | 50 + item_def.h | 131 ++ layer.h | 6 + layout.c | 131 ++ layout.h | 59 + main.c | 141 +- map.c | 197 ++ map.h | 385 +--- mapset.c | 116 + mapset.h | 16 + maptype.c | 29 + maptype.h | 15 + menu.c | 50 +- menu.h | 23 +- navigation.c | 574 ++--- navigation.h | 28 +- navit.c | 465 ++++ navit.h | 43 + navit.xml | 477 ++++ phrase.c | 5 + plugin.c | 200 +- plugin.h | 76 +- plugin_def.h | 7 + popup.c | 374 ++-- popup.h | 25 +- profile.c | 36 +- profile.h | 9 +- projection.h | 3 + python.c | 281 +++ python.h | 2 + route.c | 1589 ++++++------- route.h | 78 +- script/get_map | 2 +- search.c | 606 ++--- search.h | 63 +- statusbar.h | 20 +- street.c | 46 + street_name.c | 6 +- track.c | 240 +- track.h | 12 +- transform.c | 391 +++- transform.h | 72 +- tree.h | 13 - util.c | 17 + vehicle.c | 346 ++- vehicle.h | 19 +- xmlconfig.c | 534 +++++ xmlconfig.h | 3 + xpm/Makefile.am | 3 + xpm/camping.xpm | 24 + xpm/car_dealer.xpm | 26 + xpm/fuel.xpm | 26 + xpm/hospital.xpm | 24 + xpm/hotel.xpm | 26 + xpm/parking.xpm | 24 + xpm/restaurant.xpm | 73 + xpm/unknown.xpm | 24 + 125 files changed, 15587 insertions(+), 6663 deletions(-) delete mode 100644 action.h create mode 100644 attr.c create mode 100644 attr.h create mode 100644 attr_def.h create mode 100644 callback.c create mode 100644 callback.h create mode 100644 color.h delete mode 100644 command.c delete mode 100644 command.h create mode 100644 data/Makefile.am create mode 100644 data/garmin_img/Makefile.am create mode 100644 data/garmin_img/garmin_img.c create mode 100644 data/mg/Makefile.am create mode 100644 data/mg/block.c create mode 100644 data/mg/map.c create mode 100644 data/mg/mg.h create mode 100644 data/mg/poly.c create mode 100644 data/mg/street.c create mode 100644 data/mg/town.c create mode 100644 data/mg/tree.c create mode 100644 data/textfile/Makefile.am create mode 100644 data/textfile/textfile.c create mode 100644 data/textfile/textfile.h delete mode 100644 display.h create mode 100644 graphics/null/Makefile.am create mode 100644 graphics/null/graphics_null.c create mode 100644 graphics/opengl/Makefile.am create mode 100644 graphics/opengl/graphics_opengl.c create mode 100644 gui.c create mode 100644 gui.h create mode 100644 gui/gtk/destination.c delete mode 100644 gui/gtk/gtkeyboard.c delete mode 100644 gui/gtk/gtkeyboard.h delete mode 100644 gui/gtk/gui_gtk_menu.c delete mode 100644 gui/gtk/gui_gtk_toolbar.c create mode 100644 gui/sdl/Makefile.am create mode 100644 gui/sdl/gui_sdl.h create mode 100644 gui/sdl/gui_sdl_window.cpp create mode 100644 gui/sdl/sdl_events.cpp create mode 100644 gui/sdl/sdl_events.h create mode 100644 item.c create mode 100644 item.h create mode 100644 item_def.h create mode 100644 layer.h create mode 100644 layout.c create mode 100644 layout.h create mode 100644 map.c create mode 100644 mapset.c create mode 100644 mapset.h create mode 100644 maptype.c create mode 100644 maptype.h create mode 100644 navit.c create mode 100644 navit.h create mode 100644 navit.xml create mode 100644 plugin_def.h create mode 100644 projection.h create mode 100644 python.c create mode 100644 python.h delete mode 100644 tree.h create mode 100644 xmlconfig.c create mode 100644 xmlconfig.h create mode 100644 xpm/Makefile.am create mode 100644 xpm/camping.xpm create mode 100644 xpm/car_dealer.xpm create mode 100644 xpm/fuel.xpm create mode 100644 xpm/hospital.xpm create mode 100644 xpm/hotel.xpm create mode 100644 xpm/parking.xpm create mode 100644 xpm/restaurant.xpm create mode 100644 xpm/unknown.xpm diff --git a/Makefile.am b/Makefile.am index fb2fad6b..f198c092 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,24 +1,27 @@ -SUBDIRS=fib-1.0 gui graphics +SUBDIRS=fib-1.0 data gui graphics xpm fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am cd fib-1.0 ./configure -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -LDFLAGS = -Wl,--export-dynamic +AM_CPPFLAGS = @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ @GTK2_CFLAGS@ -DMODULE=\"navit\" bin_PROGRAMS = navit -navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c debug.c destination.c \ - display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ - map-stubs.c map_data.c menu.c navigation.c osd.c param.c phrase.c plugin.c poly.c popup.c \ - profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c track.c \ - util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ - cursor.h data.h data_window.h data_window_int.h debug.h destination.h display.h draw_info.h \ - file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ - osd.h param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ - street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h track.h util.h vehicle.h - -navit_LDADD = @PACKAGE_LIBS@ gui/gtk/gtk.o graphics/gtk_drawing_area/gtk_drawing_area.o -Lfib-1.0 -lfib +#pkglib_DATA = navit.xml +#EXTRA_DIST = navit.xml + +navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_window.c debug.c \ + file.c graphics.c gui.c item.c layout.c log.c main.c map.c \ + mapset.c maptype.c menu.c navit.c navigation.c param.c phrase.c plugin.c popup.c \ + profile.c python.c route.c search.c speech.c transform.c track.c \ + util.c vehicle.c xmlconfig.c attr.h attr_def.h callback.h color.h compass.h coord.h country.h \ + cursor.h data.h data_window.h data_window_int.h debug.h destination.h draw_info.h \ + file.h graphics.h gtkext.h gui.h item.h item_def.h log.h layout.h main.h map-share.h map.h\ + map_data.h mapset.h maptype.h menu.h navigation.h navit.h \ + param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h search.h speech.h statusbar.h \ + toolbar.h transform.h track.h util.h vehicle.h xmlconfig.h + +navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ @GTK2_LIBS@ -Lfib-1.0 -lfib diff --git a/action.h b/action.h deleted file mode 100644 index ed64fd56..00000000 --- a/action.h +++ /dev/null @@ -1,3 +0,0 @@ -struct action { - struct action_gui *gui; -}; diff --git a/attr.c b/attr.c new file mode 100644 index 00000000..0c6d58ae --- /dev/null +++ b/attr.c @@ -0,0 +1,40 @@ +#include +#include "attr.h" + +struct attr_name { + enum attr_type attr; + char *name; +}; + + +static struct attr_name attr_names[]={ +#define ATTR2(x,y) ATTR(x) +#define ATTR(x) { attr_##x, #x }, +#include "attr_def.h" +#undef ATTR2 +#undef ATTR +}; + +enum attr_type +attr_from_name(char *name) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (! strcmp(attr_names[i].name, name)) + return attr_names[i].attr; + } + return attr_none; +} + +char * +attr_to_name(enum attr_type attr) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (attr_names[i].attr == attr) + return attr_names[i].name; + } + return NULL; +} diff --git a/attr.h b/attr.h new file mode 100644 index 00000000..83a12f5b --- /dev/null +++ b/attr.h @@ -0,0 +1,24 @@ +#ifndef ATTR_H +#define ATTR_H + +enum attr_type { +#define ATTR2(x,y) attr_##x=y, +#define ATTR(x) attr_##x, +#include "attr_def.h" +#undef ATTR2 +#undef ATTR +}; + +struct attr { + enum attr_type type; + union { + char *str; + int num; + struct item *item; + } u; +}; + +enum attr_type attr_from_name(char *name); +char * attr_to_name(enum attr_type attr); + +#endif diff --git a/attr_def.h b/attr_def.h new file mode 100644 index 00000000..1a2d472c --- /dev/null +++ b/attr_def.h @@ -0,0 +1,37 @@ +/* common */ +ATTR2(none,0x00000000) +ATTR(any) +ATTR2(type_item_begin,0x00010000) +ATTR(town_streets_item) +ATTR(street_name_item) +ATTR(street_name_numbers_item) +ATTR(street_item) +ATTR(street_number_item) +ATTR2(type_item_end,0x0001ffff) +ATTR2(type_int_begin,0x00020000) +ATTR(id) +ATTR(limit) +ATTR2(type_int_end,0x0002ffff) +ATTR2(type_string_begin,0x00030000) +ATTR(label) +ATTR(country_all) +ATTR(country_iso3) +ATTR(country_iso2) +ATTR(country_car) +ATTR(country_name) +ATTR(town_name) +ATTR(town_postal) +ATTR(district_name) +ATTR(street_name) +ATTR(street_name_systematic) +ATTR(street_number) +ATTR(debug) +ATTR(address) +ATTR(phone) +ATTR(entry_fee) +ATTR(open_hours) +/* poi */ +ATTR(icon) +ATTR(info_html) +ATTR(price_html) +ATTR2(type_string_end,0x0003ffff) diff --git a/callback.c b/callback.c new file mode 100644 index 00000000..9a4cad92 --- /dev/null +++ b/callback.c @@ -0,0 +1,112 @@ +#include +#include "callback.h" + +struct callback { + void (*func)(); + int pcount; + void *p[0]; + +}; + +struct callback_list { + GList *list; +}; + +struct callback_list * +callback_list_new(void) +{ + struct callback_list *ret=g_new0(struct callback_list, 1); + + return ret; +} + +struct callback * +callback_list_add_new(struct callback_list *l, void (*func)(), int pcount, void **p) +{ + struct callback *ret; + int i; + + ret=g_malloc0(sizeof(struct callback)+pcount*sizeof(void *)); + ret->func=func; + ret->pcount=pcount; + for (i = 0 ; i < pcount ; i++) { + ret->p[i]=p[i]; + } + l->list=g_list_prepend(l->list, ret); + return ret; +} + +void +callback_list_remove_destroy(struct callback_list *l, struct callback *cb) +{ + l->list=g_list_remove(l->list, cb); + g_free(cb); +} + + +void +callback_list_call(struct callback_list *l, int pcount, void **p) +{ + void *pf[8]; + struct callback *cb; + GList *cbi; + int i; + + cbi=l->list; + while (cbi) { + cb=cbi->data; + if (cb->pcount + pcount <= 8) { + for (i = 0 ; i < cb->pcount ; i++) + pf[i]=cb->p[i]; + for (i = 0 ; i < pcount ; i++) + pf[i+cb->pcount]=p[i]; + switch (cb->pcount+pcount) { + case 8: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); + break; + case 7: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5],p[6]); + break; + case 6: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5]); + break; + case 5: + cb->func(p[0],p[1],p[2],p[3],p[4]); + break; + case 4: + cb->func(p[0],p[1],p[2],p[3]); + break; + case 3: + cb->func(p[0],p[1],p[2]); + break; + case 2: + cb->func(p[0],p[1]); + break; + case 1: + cb->func(p[0]); + break; + case 0: + cb->func(); + break; + } + } else { + g_warning("too many parameters for callback\n"); + } + cbi=g_list_next(cbi); + } + +} + + +void +callback_list_destroy(struct callback_list *l) +{ + GList *cbi; + cbi=l->list; + while (cbi) { + g_free(cbi->data); + cbi=g_list_next(cbi); + } + g_list_free(l->list); + g_free(l); +} diff --git a/callback.h b/callback.h new file mode 100644 index 00000000..6719faaf --- /dev/null +++ b/callback.h @@ -0,0 +1,15 @@ +#ifdef __cplusplus +extern "C" { +#endif +/* prototypes */ +struct callback; +struct callback_list; +struct callback_list *callback_list_new(void); +struct callback *callback_list_add_new(struct callback_list *l, void (*func)(void), int pcount, void **p); +void callback_list_remove_destroy(struct callback_list *l, struct callback *cb); +void callback_list_call(struct callback_list *l, int pcount, void **p); +void callback_list_destroy(struct callback_list *l); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/color.h b/color.h new file mode 100644 index 00000000..9fdfd3b7 --- /dev/null +++ b/color.h @@ -0,0 +1,3 @@ +struct color { + int r,g,b; +}; diff --git a/command.c b/command.c deleted file mode 100644 index ba463168..00000000 --- a/command.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include "coord.h" -#include "town.h" -#include "street.h" -#include "command.h" - -/* Phonetisch - "KLEIN " -> CL - (x)(x)->x - EI:AY - E:- - F:V - G:C - H:- - I:Y - J:Y - K:C - T:D - W:V -*/ - -struct tree_hdr { - unsigned int addr; - unsigned int size; - unsigned int low; -}; - -struct tree_leaf { - unsigned int low; - unsigned int data; - unsigned char text[0]; -}; - -#if 0 -static int -compare(char *s1, char *s2) -{ - char s1_exp, s2_exp; - for (;;) { - s1_exp=*s1++; - s2_exp=*s2++; - if (! s1_exp && ! s2_exp) - return 0; - if (s1_exp == 'A' && *s1 == 'E') { s1_exp='Ä'; s1++; } - if (s1_exp == 'O' && *s1 == 'E') { s1_exp='Ö'; s1++; } - if (s1_exp == 'U' && *s1 == 'E') { s1_exp='Ü'; s1++; } - if (s2_exp == 'A' && *s2 == 'E') { s2_exp='Ä'; s2++; } - if (s2_exp == 'O' && *s2 == 'E') { s2_exp='Ö'; s2++; } - if (s2_exp == 'U' && *s2 == 'E') { s2_exp='Ü'; s2++; } - if (s1_exp != s2_exp) - return s1_exp-s2_exp; - } -#if 0 - for (;;) { - while (*s1 && *s1 == *s2) { - s1++; - s2++; - } - if (! *s1 && ! *s2) - return 0; - if (! *s1) - return -1; - if (! *s2) - return 1; - if (*s1 < *s2 && *s2 < 0x80) - return -1; - if (*s1 > *s2 && *s1 < 0x80) - return 1; - s1_exp=*s1; - s2_exp=*s2; - if (s1_exp >= 0x80) - s1_exp=' '; - if (s2_exp >= 0x80) - s2_exp=' '; -#if 0 - if (*s1 == (unsigned char)'Ä') s1_exp='A'; - if (*s1 == (unsigned char)'Ö') s1_exp='O'; - if (*s1 == (unsigned char)'Ü') s1_exp='U'; - if (*s1 == (unsigned char)'ä') s1_exp='a'; - if (*s1 == (unsigned char)'ö') s1_exp='o'; - if (*s1 == (unsigned char)'ü') s1_exp='u'; - if (*s1 == (unsigned char)'ß') s1_exp='s'; - if (*s2 == (unsigned char)'Ä') s2_exp='A'; - if (*s2 == (unsigned char)'Ö') s2_exp='O'; - if (*s2 == (unsigned char)'Ü') s2_exp='U'; - if (*s2 == (unsigned char)'ä') s2_exp='a'; - if (*s2 == (unsigned char)'ö') s2_exp='o'; - if (*s2 == (unsigned char)'ü') s2_exp='u'; - if (*s2 == (unsigned char)'ß') s2_exp='s'; -#endif - if (s1_exp < s2_exp) - return -1; - if (s1_exp > s2_exp) - return 1; - printf("Problem %c vs %c\n", *s1, *s2); - exit(1); - } -#endif -} -#endif - -void -command_goto(struct container *co, const char *arg) -{ -#if 0 - struct container *co=map->container; - struct town_list *list,*curr,*best=NULL; - int order=256; - int argc=0; - unsigned long x,y,scale; - char args[strlen(arg)+1]; - char *argv[strlen(arg)+1]; - char *tok; - - - strcpy(args, arg); - tok=strtok(args, " "); - while (tok) { - argv[argc++]=tok; - tok=strtok(NULL," "); - } - - list=NULL; - town_search_by_name(&list, co->map_data, argv[0], 0, 10000); - town_get_by_index(co->map_data, 0x311d54cb); - curr=list; - while (curr) { - if (curr->town->order < order) { - order=curr->town->order; - best=curr; - } - curr=curr->next; - } - if (best) { - printf("'%s' '%s' '%s' '%s'\n", best->town->name, best->town->district, best->town->postal_code1, best->town->postal_code2); -#if 0 - street_search_by_name(class->map_data, best->town->country, best->town->street_assoc, 0, argv[1]); -#endif - map_get_view(map, &x, &y, &scale); - x=best->town->c->x; - y=best->town->c->y; - map_set_view(map, x, y, scale); - } - town_list_free(list); -#endif -} diff --git a/command.h b/command.h deleted file mode 100644 index 5082fa04..00000000 --- a/command.h +++ /dev/null @@ -1 +0,0 @@ -void command_goto(struct container *co, const char *arg); diff --git a/compass.c b/compass.c index 4daa430f..dff312ec 100644 --- a/compass.c +++ b/compass.c @@ -7,10 +7,10 @@ #include "transform.h" #include "route.h" #include "vehicle.h" -#include "container.h" -#include "compass.h" +#include "navit.h" #include "compass.h" +#if 0 struct compass { struct graphics *gr; struct graphics_gc *bg; @@ -83,6 +83,7 @@ compass_draw(struct compass *comp, struct container *co) handle(comp->gr,comp->white, &p, 20,0); else handle(comp->gr, comp->white, &p, 20, -*vehicle_dir); +#if 0 /* FIXME */ dest=route_get_destination(co->route); if (dest) { pos=vehicle_pos_get(co->vehicle); @@ -107,6 +108,7 @@ compass_draw(struct compass *comp, struct container *co) comp->gr->draw_text(comp->gr, comp->green, NULL, comp->font, buffer, &p, 0x10000, 0); } +#endif comp->gr->draw_mode(comp->gr, draw_mode_end); } @@ -131,3 +133,4 @@ compass_new(struct container *co) compass_draw(this, co); return this; } +#endif diff --git a/coord.c b/coord.c index 7ccc8e2e..6f22a8d8 100644 --- a/coord.c +++ b/coord.c @@ -1,4 +1,12 @@ +#include +#include +#include +#include +#include +#include "debug.h" #include "coord.h" +#include "transform.h" +#include "projection.h" /** * @defgroup coord Coordinate handling functions * @{ @@ -19,4 +27,172 @@ coord_get(unsigned char **p) return ret; } +struct coord * +coord_new(int x, int y) +{ + struct coord *c=g_new(struct coord, 1); + + c->x=x; + c->y=y; + + return c; +} + +void +coord_destroy(struct coord *c) +{ + g_free(c); +} + +struct coord_rect * +coord_rect_new(struct coord *lu, struct coord *rl) +{ + struct coord_rect *r=g_new(struct coord_rect, 1); + + g_assert(lu->x <= rl->x); + g_assert(lu->y >= rl->y); + + r->lu=*lu; + r->rl=*rl; + + return r; + +} + +void +coord_rect_destroy(struct coord_rect *r) +{ + g_free(r); +} + +int +coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2) +{ + g_assert(r1->lu.x <= r1->rl.x); + g_assert(r1->lu.y >= r1->rl.y); + g_assert(r2->lu.x <= r2->rl.x); + g_assert(r2->lu.y >= r2->rl.y); + if (r1->lu.x > r2->rl.x) + return 0; + if (r1->rl.x < r2->lu.x) + return 0; + if (r1->lu.y < r2->rl.y) + return 0; + if (r1->rl.y > r2->lu.y) + return 0; + return 1; +} + +int +coord_rect_contains(struct coord_rect *r, struct coord *c) +{ + g_assert(r->lu.x <= r->rl.x); + g_assert(r->lu.y >= r->rl.y); + if (c->x < r->lu.x) + return 0; + if (c->x > r->rl.x) + return 0; + if (c->y < r->rl.y) + return 0; + if (c->y > r->lu.y) + return 0; + return 1; +} + +void +coord_rect_extend(struct coord_rect *r, struct coord *c) +{ + if (c->x < r->lu.x) + r->lu.x=c->x; + if (c->x > r->rl.x) + r->rl.x=c->x; + if (c->y < r->rl.y) + r->rl.y=c->y; + if (c->y > r->lu.y) + r->lu.y=c->y; +} + + /* [Proj:][Ã]DMM.ss[S][S]... N/S [D][D]DMM.ss[S][S]... E/W */ + /* [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]... */ + /* [Proj:][-]0xX [-]0xX */ + +int +coord_parse(const char *c_str, enum projection pro, struct coord *c_ret) +{ + int debug=0; + char *proj=NULL,*s,*co; + const char *str=c_str; + int args,ret; + struct coord_geo g; + struct coord c; + enum projection str_pro=projection_none; + + dbg(1,"enter('%s',%d,%p)\n", c_str, pro, c_ret); + s=index(str,' '); + co=index(str,':'); + if (co && co < s) { + proj=malloc(co-str+1); + strncpy(proj, str, co-str); + proj[co-str]='\0'; + dbg(1,"projection=%s\n", proj); + str=co+1; + s=index(str,' '); + } + while (*s == ' ') { + s++; + } + if (!strncmp(str, "0x", 2) || !strncmp(str,"-0x", 3)) { + args=sscanf(str, "%i %i%n",&c.x, &c.y, &ret); + if (args < 2) + return 0; + dbg(1,"str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret); + dbg(1,"rest='%s'\n", str+ret); + + if (str_pro == projection_none) + str_pro=projection_mg; + if (str_pro == projection_mg) { + *c_ret=c; + } else { + printf("help\n"); + } + } else if (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's') { + dbg(1,"str='%s'\n", str); + double lng, lat; + char ns, ew; + args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret); + if (args < 4) + return 0; + if (str_pro == projection_none) { + g.lat=floor(lat/100); + lat-=g.lat*100; + g.lat+=lat/60; + g.lng=floor(lng/100); + lng-=g.lng*100; + g.lng+=lng/60; + transform_from_geo(pro, &g, c_ret); + } + if (debug) { + printf("str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns, lat, ew, ret); + printf("rest='%s'\n", str+ret); + } + } else { + double lng, lat; + args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret); + if (args < 2) + return 0; + printf("str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret); + printf("rest='%s'\n", str+ret); + } + if (debug) + printf("rest='%s'\n", str+ret); + ret+=str-c_str; + if (debug) { + printf("args=%d\n", args); + printf("ret=%d delta=%d ret_str='%s'\n", ret, str-c_str, c_str+ret); + } + if (proj) + free(proj); + return ret; +} + /** @} */ diff --git a/coord.h b/coord.h index 550c0322..13491d22 100644 --- a/coord.h +++ b/coord.h @@ -1,12 +1,15 @@ #ifndef COORD_H #define COORD_H -#include "types.h" - /*! A integer mercator coordinate */ struct coord { - s32 x; /*!< X-Value */ - s32 y; /*!< Y-Value */ + int x; /*!< X-Value */ + int y; /*!< Y-Value */ +}; + +struct coord_rect { + struct coord lu; + struct coord rl; }; //! A double mercator coordinate @@ -21,6 +24,17 @@ struct coord_geo { double lat; /*!< Latitude */ }; +enum projection; + struct coord * coord_get(unsigned char **p); +struct coord * coord_new(int x, int y); +void coord_destroy(struct coord *c); +int coord_parse(const char *c_str, enum projection pro, struct coord *c_ret); +struct coord_rect * coord_rect_new(struct coord *lu, struct coord *rl); +void coord_rect_destroy(struct coord_rect *r); +int coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2); +int coord_rect_contains(struct coord_rect *r, struct coord *c); +void coord_rect_extend(struct coord_rect *r, struct coord *c); + #endif diff --git a/country.c b/country.c index 4f3a5d00..9d49ef59 100644 --- a/country.c +++ b/country.c @@ -1,10 +1,32 @@ #include #include #include +#include "debug.h" +#include "attr.h" +#include "item.h" #include "country.h" +#include "search.h" + +struct country { + int id; + char *car; + char *iso2; + char *iso3; + char *name; +}; struct country country[]= { + { 1 ,"CZ", "CZ", "CZE", "Tschechische Republik"}, + { 2 ,"SK", "SK", "SVK", "Slowakei"}, + { 7 ,"RSM", "SM", "SMR", "San Marino"}, + {11 ,"EST", "EE", "EST", "Estland"}, + {12 ,"GE", "GE", "GEO", "Georgien"}, + {13 ,"LV", "LV", "LVA", "Lettland"}, + {14 ,"LT", "LT", "LTU", "Litauen"}, + {15 ,"MD", "MD", "MDA", "Moldawien"}, {16 ,"RUS", "RU", "RUS", "Rußland"}, + {17 ,"UA", "UA", "UKR", "Ukraine"}, + {18 ,"BY", "BY", "BLR", "Weißrussland"}, {20 ,"ET", "EG", "EGY", "Ägypten"}, {30 ,"GR", "GR", "GRC", "Griechenland"}, {31 ,"NL", "NL", "NLD", "Niederlande"}, @@ -18,77 +40,163 @@ struct country country[]= { {43 ,"A", "AT", "AUT", "Österreich"}, {44 ,"GB", "GB", "GBR", "Grossbritannien"}, {45 ,"DK", "DK", "DNK", "Dänemark"}, + {46 ,"S", "SE", "SWE", "Schweden"}, {47 ,"N", "NO", "NOR", "Norwegen"}, + {48 ,"PL", "PL", "POL", "Polen"}, {49 ,"D", "DE", "DEU", "Deutschland"}, + {50 ,"GBZ", "GI", "GIB", "Gibraltar"}, {51 ,"P", "PT", "PRT", "Portugal"}, {52 ,"L", "LU", "LUX", "Luxemburg"}, + {53 ,"IRL", "IE", "IRL", "Irland"}, + {54 ,"IS", "IS", "ISL", "Island"}, + {55 ,"AL", "AL", "ALB", "Albanien"}, + {56 ,"M", "MT", "MLT", "Malta"}, + {57 ,"CY", "CY", "CYP", "Zypern"}, + {58 ,"FIN", "FI", "FIN", "Finnland"}, + {59 ,"BG", "BG", "BGR", "Bulgarien"}, + {61 ,"RL", "LB", "LBN", "Libanon"}, + {62 ,"AND", "AD", "AND", "Andorra"}, + {63 ,"SYR", "SY", "SYR", "Syrien"}, + {66 ,"KSA", "SA", "SAU", "Saudi-Arabien"}, {71 ,"LAR", "LY", "LYB", "Libyen"}, + {72 ,"IL", "IL", "ISR", "Israel"}, + {73 ,"AUT", "PS", "PSE", "Palästinensische Autonomiegebiete"}, + {75 ,"FL", "LI", "LIE", "Liechtenstein"}, {76 ,"MA", "MA", "MAR", "Marokko"}, + {77 ,"DZ", "DZ", "DZA", "Algerien"}, {78 ,"TN", "TN", "TUN", "Tunesien"}, + {81 ,"SRB", "RS", "SRB", "Serbien"}, + {83 ,"HKJ", "JO", "JOR", "Jordanien"}, + {85 ,"NDH", "HR", "HRV", "Kroatien"}, + {86 ,"SLO", "SI", "SVN", "Slowenien"}, + {87 ,"BIH", "BA", "BIH", "Bosnien und Herzegowina"}, + {89 ,"MK", "MK", "MKD", "Mazedonien"}, + {90 ,"TR", "TR", "TUR", "Türkei"}, + {93 ,"MC", "MC", "MCO", "Monaco"}, + {94 ,"AZ", "AZ", "AZE", "Aserbaidschan"}, + {95 ,"ARM", "AM", "ARM", "Armenien"}, + {98 ,"FO", "FO", "FRO", "Färöer"}, + {99 ,"WSA", "EH", "ESH", "Westsahara"}, + {336 ,NULL, "SJ", "SJM", "Svalbard und Jan Mayen"}, }; -struct country * -country_get_by_id(int id) -{ - int i; - for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { - if (id == country[i].id) { - return &country[i]; - } - } - return NULL; -} -static int -compare(const char *name1, const char *name2, int len, int partial) -{ - if (partial) - return strncasecmp(name1, name2, len); - else - return strcasecmp(name1, name2); -} +struct country_search { + struct attr search; + int len; + int partial; + struct item item; + int count; + struct country *country; + enum attr_type attr_next; +}; static int -search(int offset, const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +country_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) { - char *col; - int i,ret,len=strlen(name); - int debug=0; - - for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { - col=G_STRUCT_MEMBER(char *,country+i,offset); - if (debug) - printf("comparing '%s'\n", col); - if (!compare(col, name, len, partial)) { - ret=(*func)(&country[i], data); - if (ret) - return 1; - } - col+=sizeof(struct country); - } - return 0; + struct country_search *this=priv_data; + struct country *country=this->country; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (this->attr_next != attr_none) { + if (country_attr_get(this, this->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=country->name; + this->attr_next=attr_id; + return 1; + case attr_id: + attr->u.num=country->id; + this->attr_next=country->car ? attr_country_car : attr_country_iso2; + return 1; + case attr_country_car: + attr->u.str=country->car; + this->attr_next=attr_country_iso2; + return attr->u.str ? 1 : 0; + case attr_country_iso2: + attr->u.str=country->iso2; + this->attr_next=attr_country_iso3; + return 1; + case attr_country_iso3: + attr->u.str=country->iso3; + this->attr_next=attr_country_name; + return 1; + case attr_country_name: + attr->u.str=country->name; + this->attr_next=attr_none; + return 1; + default: + return 0; + } } -int -country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) + + +struct item_methods country_meth = { + NULL, /* coord_rewind */ + NULL, /* coord_get */ + NULL, /* attr_rewind */ + country_attr_get, /* attr_get */ +}; + +struct country_search * +country_search_new(struct attr *search, int partial) { - return search(G_STRUCT_OFFSET(struct country, name), name, partial, func, data); + struct country_search *ret=g_new(struct country_search, 1); + ret->search=*search; + ret->len=strlen(search->u.str); + ret->partial=partial; + ret->count=0; + + ret->item.type=type_country_label; + ret->item.id_hi=0; + ret->item.map=NULL; + ret->item.meth=&country_meth; + ret->item.priv_data=ret; + + return ret; } -int -country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +static int +match(struct country_search *this, enum attr_type type, const char *name) { - return search(G_STRUCT_OFFSET(struct country, car), name, partial, func, data); + int ret; + if (!name) + return 0; + if (this->search.type != type && this->search.type != attr_country_all) + return 0; + if (this->partial) + ret=(strncasecmp(this->search.u.str, name, this->len) == 0); + else + ret=(strcasecmp(this->search.u.str, name) == 0); + return ret; + } -int -country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) + +struct item * +country_search_get_item(struct country_search *this) { - return search(G_STRUCT_OFFSET(struct country, iso2), name, partial, func, data); + for (;;) { + if (this->count >= sizeof(country)/sizeof(struct country)) + return NULL; + this->country=&country[this->count++]; + if (match(this, attr_country_iso3, this->country->iso3) || + match(this, attr_country_iso2, this->country->iso2) || + match(this, attr_country_car, this->country->car) || + match(this, attr_country_name, this->country->name)) { + this->item.id_lo=this->country->id; + return &this->item; + } + } } -int -country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +void +country_search_destroy(struct country_search *this) { - return search(G_STRUCT_OFFSET(struct country, iso3), name, partial, func, data); + g_free(this); } diff --git a/country.h b/country.h index 616a6c26..83be5b95 100644 --- a/country.h +++ b/country.h @@ -1,12 +1,7 @@ -struct country { - int id; - char *car; - char *iso2; - char *iso3; - char *name; -}; -struct country * country_get_by_id(int id); -int country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); +/* prototypes */ +struct attr; +struct country_search; +struct item; +struct country_search *country_search_new(struct attr *search, int partial); +struct item *country_search_get_item(struct country_search *this); +void country_search_destroy(struct country_search *this); diff --git a/cursor.c b/cursor.c index d126f684..933a8347 100644 --- a/cursor.c +++ b/cursor.c @@ -8,59 +8,87 @@ #include #include "coord.h" #include "transform.h" +#include "projection.h" +#include "point.h" #include "graphics.h" #include "statusbar.h" #include "menu.h" #include "vehicle.h" -#include "container.h" +#include "navit.h" +#include "color.h" #include "cursor.h" #include "compass.h" -#include "track.h" +/* #include "track.h" */ +struct callback { + void (*func)(struct cursor *, void *data); + void *data; +}; -#include "route.h" struct cursor { - struct container *co; + struct graphics *gra; struct graphics_gc *cursor_gc; + struct transformation *trans; struct point cursor_pnt; + struct callback offscreen_callback; + struct callback update_callback; + struct vehicle *v; + int dir; + struct coord pos; + void *vehicle_callback; }; struct coord * cursor_pos_get(struct cursor *this) { - return vehicle_pos_get(this->co->vehicle); + return &this->pos; +#if 0 + return vehicle_pos_get(this->v); +#endif +} + + +struct coord * +cursor_pos_set(struct cursor *this, struct coord *pos) +{ + this->pos=*pos; +#if 0 + return vehicle_pos_get(this->v); +#endif } + static void -cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir) +cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir) { int x=this->cursor_pnt.x; int y=this->cursor_pnt.y; int r=12,lw=2; double dx,dy; double fac1,fac2; - int dir_i=*dir-this->co->trans->angle; struct point cpnt[3]; - struct graphics *gra=this->co->gra; + struct graphics *gra=this->gra; if (pnt && x == pnt->x && y == pnt->y) return; + if (!graphics_ready(gra)) + return; cpnt[0]=this->cursor_pnt; cpnt[0].x-=r+lw; cpnt[0].y-=r+lw; - gra->draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2); + graphics_draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2); if (pnt) { - gra->draw_mode(gra, draw_mode_cursor); + graphics_draw_mode(gra, draw_mode_cursor); this->cursor_pnt=*pnt; x=pnt->x; y=pnt->y; cpnt[0].x=x; cpnt[0].y=y; - gra->draw_circle(gra, this->cursor_gc, &cpnt[0], r*2); - if (*speed > 2.5) { - dx=sin(M_PI*dir_i/180); - dy=-cos(M_PI*dir_i/180); + graphics_draw_circle(gra, this->cursor_gc, &cpnt[0], r*2); + if (draw_dir) { + dx=sin(M_PI*dir/180.0); + dy=-cos(M_PI*dir/180.0); fac1=0.7*r; fac2=0.4*r; @@ -70,15 +98,16 @@ cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir) cpnt[1].y=y+dy*r; cpnt[2].x=x-dx*fac1-dy*fac2; cpnt[2].y=y-dy*fac1+dx*fac2; - gra->draw_lines(gra, this->cursor_gc, cpnt, 3); + graphics_draw_lines(gra, this->cursor_gc, cpnt, 3); } else { cpnt[1]=cpnt[0]; - gra->draw_lines(gra, this->cursor_gc, cpnt, 2); + graphics_draw_lines(gra, this->cursor_gc, cpnt, 2); } - gra->draw_mode(gra, draw_mode_end); + graphics_draw_mode(gra, draw_mode_end); } } +#if 0 static void cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new) { @@ -153,47 +182,74 @@ cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir return 0; } +#endif + +int +cursor_get_dir(struct cursor *this) +{ + return this->dir; +} + static void -cursor_update(struct vehicle *v, void *t) +cursor_update(struct vehicle *v, void *data) { - struct cursor *this=t; + struct cursor *this=data; struct point pnt; struct coord *pos; double *dir; + double *speed; + enum projection pro; + int border=10; if (v) { pos=vehicle_pos_get(v); dir=vehicle_dir_get(v); - track_update(this->co->track, pos, (int)(*dir)); - if (this->co->flags->orient_north) - dir=0; - route_set_position(this->co->route, cursor_pos_get(this->co->cursor)); - if (!transform(this->co->trans, pos, &pnt)) { - cursor_map_reposition(this, pos, dir); - transform(this->co->trans, pos, &pnt); + speed=vehicle_speed_get(v); + pro=vehicle_projection(v); + this->dir=*dir; + this->pos=*pos; + if (this->update_callback.func) + (*this->update_callback.func)(this, this->update_callback.data); + if (!transform(this->trans, pro, &this->pos, &pnt) || !transform_within_border(this->trans, &pnt, border)) { + if (this->offscreen_callback.func) + (*this->offscreen_callback.func)(this, this->offscreen_callback.data); + transform(this->trans, pro, &this->pos, &pnt); } - if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height || this->co->flags->fixedpos_mode) { - cursor_map_reposition(this, pos, dir); - transform(this->co->trans, pos, &pnt); - } - if (cursor_map_reposition_boundary(this, pos, dir, &pnt)) - transform(this->co->trans, pos, &pnt); - cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v)); + cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5); } +#if 0 compass_draw(this->co->compass, this->co); - osd_draw(this->co->osd, this->co); +#endif } -extern void *vehicle; - struct cursor * -cursor_new(struct container *co, struct vehicle *v) +cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t) { + printf("cursor_new v=%p\n", v); struct cursor *this=g_new(struct cursor,1); - this->co=co; - this->cursor_gc=co->gra->gc_new(co->gra); - co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff); - co->gra->gc_set_linewidth(this->cursor_gc, 2); - vehicle_callback_register(v, cursor_update, this); + this->gra=gra; + this->trans=t; + this->cursor_gc=graphics_gc_new(gra); + this->v=v; + graphics_gc_set_foreground(this->cursor_gc, c); + graphics_gc_set_linewidth(this->cursor_gc, 2); + this->vehicle_callback=vehicle_callback_register(v, cursor_update, this); return this; } + +void +cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) +{ + this->offscreen_callback.func=func; + this->offscreen_callback.data=data; +} + + +void +cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) +{ + this->update_callback.func=func; + this->update_callback.data=data; +} + + diff --git a/cursor.h b/cursor.h index eeb63069..df15168a 100644 --- a/cursor.h +++ b/cursor.h @@ -1,6 +1,13 @@ +/* prototypes */ +struct color; +struct coord; struct cursor; -struct container; +struct graphics; +struct transformation; struct vehicle; - -struct coord * cursor_pos_get(struct cursor *this); -struct cursor *cursor_new(struct container *co, struct vehicle *v); +struct coord *cursor_pos_get(struct cursor *this); +struct coord *cursor_pos_set(struct cursor *this, struct coord *pos); +int cursor_get_dir(struct cursor *this); +struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t); +void cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); +void cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); diff --git a/data.h b/data.h index 61a9e007..e2af6f96 100644 --- a/data.h +++ b/data.h @@ -1,33 +1,50 @@ -#include "types.h" - -static inline u8 +static inline unsigned char get_u8(unsigned char **p) { return *((*p)++); } -static inline u16 +static inline unsigned short get_u16(unsigned char **p) { - u16 ret; - ret=*((u16 *)*p); - *p+=sizeof(u16); + unsigned short ret; + ret=*((unsigned short *)*p); + *p+=sizeof(unsigned short); return ret; } -static inline u32 +static inline unsigned short +get_u16_unal(unsigned char **p) { + unsigned short ret; + ret=*(*p)++; + ret|=(*(*p)++) << 8; + return ret; +} + + +static inline unsigned int get_u24(unsigned char **p) { - u32 ret; + unsigned long ret; ret=get_u16(p); ret|=*((*p)++) << 16; return ret; } -static inline u32 +static inline unsigned int get_u32(unsigned char **p) { - u32 ret; - ret=*((u32 *)*p); - *p+=sizeof(u32); + unsigned long ret; + ret=*((unsigned int *)*p); + *p+=sizeof(unsigned int); + return ret; +} + +static inline unsigned int +get_u32_unal(unsigned char **p) { + unsigned long ret; + ret=*(*p)++; + ret|=(*(*p)++) << 8; + ret|=(*(*p)++) << 16; + ret|=(*(*p)++) << 24; return ret; } @@ -38,5 +55,7 @@ get_string(unsigned char **p) while (**p) (*p)++; (*p)++; return ret; -} +} + +#define L(x) ({ unsigned char *t=(unsigned char *)&(x); t[0] | (t[1] << 8) | (t[2] << 16) | (t[3] << 24); }) diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 00000000..35a11357 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=mg textfile garmin_img diff --git a/data/garmin_img/Makefile.am b/data/garmin_img/Makefile.am new file mode 100644 index 00000000..7fb84323 --- /dev/null +++ b/data/garmin_img/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libdata_garmin_img.la +libdata_garmin_img_la_SOURCES = garmin_img.c diff --git a/data/garmin_img/garmin_img.c b/data/garmin_img/garmin_img.c new file mode 100644 index 00000000..86b03ca1 --- /dev/null +++ b/data/garmin_img/garmin_img.c @@ -0,0 +1,1486 @@ +#include +#include +#include +#include +#include +#include "plugin.h" +#include "data.h" +#include "map.h" +#include "maptype.h" +#include "item.h" +#include "attr.h" +#include "coord.h" +#include "transform.h" +#include "projection.h" +#include +#include "attr.h" +#include "coord.h" + +struct file { + FILE *f; + int offset; +}; + + +int shift=5; +int subdiv_next=0x10; + + +static void * +file_read(struct file *f, int offset, int size) +{ + void *ptr; + int ret; + + ptr=calloc(size, 1); + if (! ptr) + return ptr; + fseek(f->f, f->offset+offset, SEEK_SET); + ret=fread(ptr, size, 1, f->f); + if (ret != 1) { + printf("fread %d vs %d offset %d+%d(0x%x)\n", ret, size, f->offset, offset,offset); + g_assert(1==0); + } + return ptr; +} + +static void +file_free(void *ptr) +{ + free(ptr); +} + +struct offset_len { + int offset; + int length; +} __attribute ((packed)); + +static void +dump_offset_len(struct offset_len *off_len) +{ + printf("offset: 0x%x(%d) length 0x%x(%d)\n", off_len->offset, off_len->offset, off_len->length, off_len->length); +} + +struct timestamp { + short creation_year; + char creation_month; + char creation_day; + char creation_hour; + char creation_minute; + char creation_second; +} __attribute__((packed)); + +struct img_header { + char xor; + char zero1[9]; + char update_month; + char update_year; + char zero2[3]; + char checksum[1]; + char signature[7]; + char unknown1[1]; + char unknown2[2]; + char unknown3[2]; + char unknown4[2]; + char unknown5[2]; + char zero3[25]; + struct timestamp ts; + char unknown6; + char map_file_identifier[7]; + char unknown12; + char map_description1[20]; + short unknown13; + short unknown14; + char e1; + char e2; + char other[413]; + char zero4[512]; + char unknown7; + char unknown8[11]; + int file_offset; + char unknown9; + char unknown10[15]; + char unknown11[480]; +} __attribute__((packed)); + +static void +dump_ts(struct timestamp *ts) +{ + 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); +} + +#if 0 +static void +dump_img(struct img_header *img_hdr) +{ + printf("signature: '%s'\n", img_hdr->signature); + printf("creation: "); + dump_ts(&img_hdr->ts); + printf("map_file_identifier: '%s'\n", img_hdr->map_file_identifier); + printf("file_offset: 0x%x\n", img_hdr->file_offset); + printf("e1: 0x%x(%d)\n", img_hdr->e1, img_hdr->e1); + printf("e2: 0x%x(%d)\n", img_hdr->e2, img_hdr->e2); + printf("offset 0x%x\n", (int) &img_hdr->e1 - (int) img_hdr); + printf("size %d\n", sizeof(*img_hdr)); +} +#endif + +struct fat_block { + char flag; + char filename[8]; + char type[3]; + int size; + char zero1; + char part; + char zero[14]; + unsigned short blocks[240]; +} __attribute__((packed)); + +#if 0 +static void +dump_fat_block(struct fat_block *fat_blk) +{ + int i=0; + char name[9]; + char type[4]; + printf("flag: 0x%x(%d)\n", fat_blk->flag, fat_blk->flag); + strcpy(name, fat_blk->filename); + name[8]='\0'; + strcpy(type, fat_blk->type); + type[3]='\0'; + printf("name: '%s.%s'\n", name, type); + printf("size: 0x%x(%d)\n", fat_blk->size, fat_blk->size); + printf("part: 0x%x(%d)\n", fat_blk->part, fat_blk->part); + printf("blocks: "); + while (i < 240) { + printf("0x%x(%d) ",fat_blk->blocks[i], fat_blk->blocks[i]); + if (fat_blk->blocks[i] == 0xffff) + break; + i++; + } + printf("size: %d\n", sizeof(*fat_blk)); + +} +#endif + +struct file_header { + short header_len; + char type[10]; + char unknown1; + char unknown2; + struct timestamp ts; +} __attribute__((packed)); + +static void +dump_file(struct file_header *fil_hdr) +{ + printf("header_len: %d\n", fil_hdr->header_len); + printf("type: '%s'\n", fil_hdr->type); + printf("unknown1: 0x%x(%d)\n", fil_hdr->unknown1, fil_hdr->unknown1); + printf("unknown2: 0x%x(%d)\n", fil_hdr->unknown2, fil_hdr->unknown2); + printf("creation: "); + dump_ts(&fil_hdr->ts); + printf("size %d\n", sizeof(*fil_hdr)); +} + +struct region_header { + struct file_header fil_hdr; + struct offset_len offset_len; +} __attribute__((packed)); + +#if 0 +static void +dump_region(struct region_header *rgn_hdr) +{ + dump_offset_len(&rgn_hdr->offset_len); +} +#endif + +struct map_priv { + int id; + char *filename; +}; + +struct map_rect_priv { + struct coord_rect r; + int limit; + + struct file tre; + struct tree_header *tre_hdr; + struct file rgn; + struct region_header *rgn_hdr; + struct file lbl; + struct label_header *lbl_hdr; + char *label; + + int subdiv_level_count; + int subdiv_pos; + char *subdiv; + + int rgn_offset; + int rgn_end; + struct rgn_point *pnt; + struct rgn_poly *ply; + unsigned char *ply_data; + int ply_bitpos; + int ply_bitcount; + int ply_lngbits; + int ply_latbits; + int ply_lng; + int ply_lat; + int ply_lnglimit; + int ply_latlimit; + int ply_lngsign; + int ply_latsign; + struct offset_len rgn_items[4]; + int rgn_type; + + int count; + + FILE *f; + long pos; + char line[256]; + int attr_pos; + enum attr_type attr_last; + char attrs[256]; + char attr[256]; + double lat,lng; + char lat_c,lng_c; + int eoc; + struct map_priv *m; + struct item item; +}; + +static int map_id; + +static int +contains_coord(char *line) +{ + return g_ascii_isdigit(line[0]); +} + +static int debug=1; + +static int +get_tag(char *line, char *name, int *pos, char *ret) +{ + int len,quoted; + char *p,*e,*n; + + if (debug) + printf("get_tag %s from %s\n", name, line); + if (! name) + return 0; + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=index(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (e-n == len && !strncmp(n, name, len)) { + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(ret, e, len); + ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} + +static void +get_line(struct map_rect_priv *mr) +{ + mr->pos=ftell(mr->f); + fgets(mr->line, 256, mr->f); +} + +static void +map_destroy_garmin_img(struct map_priv *m) +{ + if (debug) + printf("map_destroy_garmin_img\n"); + g_free(m); +} + +static char * +map_charset_garmin_img(struct map_priv *m) +{ + return "iso8859-1"; +} + +static enum projection +map_projection_garmin_img(struct map_priv *m) +{ + return projection_garmin; +} + +struct label_data_offset { + struct offset_len offset_len; + char multiplier; + char data; +} __attribute ((packed)); + +#if 0 +static void +dump_label_data_offset(struct label_data_offset *lbl_dat) +{ + dump_offset_len(&lbl_dat->offset_len); + printf("multiplier 0x%x(%d)\n", lbl_dat->multiplier, lbl_dat->multiplier); + printf("data 0x%x(%d)\n", lbl_dat->data, lbl_dat->data); +} +#endif + +struct label_data { + struct offset_len offset_len; + short size; + int zero; +} __attribute ((packed)); + +static void +dump_label_data(struct label_data *lbl_dat) +{ + dump_offset_len(&lbl_dat->offset_len); + printf("size 0x%x(%d)\n", lbl_dat->size, lbl_dat->size); +} + +struct tree_header { + struct file_header fil_hdr; + char boundary[12]; + struct offset_len level; + struct offset_len subdivision; + struct label_data copyright; + struct offset_len tre7; + short unknown1; + char zero1; + struct label_data polyline; + struct label_data polygon; + struct label_data point; + int mapid; +}; + +static void +dump_tree_header(struct tree_header *tre_hdr) +{ + printf("tree_header:\n"); + dump_file(&tre_hdr->fil_hdr); + printf("level: "); dump_offset_len(&tre_hdr->level); + printf("subdivision: "); dump_offset_len(&tre_hdr->subdivision); + printf("copyright: "); dump_label_data(&tre_hdr->copyright); + printf("polyline: "); dump_label_data(&tre_hdr->polyline); + printf("polygon: "); dump_label_data(&tre_hdr->polygon); + printf("point: "); dump_label_data(&tre_hdr->point); + printf("len: 0x%x(%d)\n", sizeof(*tre_hdr), sizeof(*tre_hdr)); +} + +struct label_header { + struct file_header fil_hdr; + struct label_data_offset label; + struct label_data country; + struct label_data region; + struct label_data city; + struct label_data poi_index; + struct label_data_offset poi_properties; + short zero1; + char zero2; + struct label_data poi_types; + struct label_data zip; + struct label_data hway; + struct label_data exit; + struct label_data hway_data; + int unknown1; + short unknown2; + struct offset_len sort_descriptor; + struct label_data lbl13; + struct label_data lbl14; +} __attribute((packed)); + +#if 0 +static void +dump_label(struct label_header *lbl_hdr) +{ + dump_file(&lbl_hdr->fil_hdr); + printf("label:\n"); + dump_label_data_offset(&lbl_hdr->label); + printf("country:\n"); + dump_label_data(&lbl_hdr->country); + printf("region:\n"); + dump_label_data(&lbl_hdr->region); + printf("city:\n"); + dump_label_data(&lbl_hdr->city); + printf("poi_index:\n"); + dump_label_data(&lbl_hdr->poi_index); + printf("poi_properties:\n"); + dump_label_data_offset(&lbl_hdr->poi_properties); + printf("poi_types:\n"); + dump_label_data(&lbl_hdr->poi_types); + printf("zip:\n"); + dump_label_data(&lbl_hdr->zip); + printf("hway:\n"); + dump_label_data(&lbl_hdr->hway); + printf("exit:\n"); + dump_label_data(&lbl_hdr->exit); + printf("hway_data:\n"); + dump_label_data(&lbl_hdr->hway_data); + printf("lbl13:\n"); + dump_label_data(&lbl_hdr->lbl13); + printf("lbl14:\n"); + dump_label_data(&lbl_hdr->lbl14); + printf("len: 0x%x(%d)\n", sizeof(*lbl_hdr), sizeof(*lbl_hdr)); +} +#endif + +struct triple { + unsigned char data[3]; +} __attribute((packed)); + +static unsigned int +triple_u(struct triple *t) +{ + return t->data[0] | (t->data[1] << 8) | (t->data[2] << 16); +} + +static int +triple(struct triple *t) +{ + int ret=t->data[0] | (t->data[1] << 8) | (t->data[2] << 16); + if (ret > 1<<23) + ret=ret-(1<<24); + return ret; +} + +static void +dump_triple_u(struct triple *t) +{ + int val=triple_u(t); + printf("0x%x(%d)\n", val, val); +} + +struct tcoord { + struct triple lng,lat; +} __attribute((packed)); + +static void +dump_tcoord(struct tcoord *t) +{ + printf ("0x%x(%d),0x%x(%d)\n", triple_u(&t->lng), triple_u(&t->lng), triple_u(&t->lat), triple_u(&t->lat)); +} + +struct level { + unsigned char zoom; + unsigned char bits_per_coord; + unsigned short subdivisions; +} __attribute((packed)); + +static void +dump_level(struct level *lvl) +{ + printf("level:\n"); + printf("\tzoom 0x%x(%d)\n", lvl->zoom, lvl->zoom); + printf("\tbits_per_coord 0x%x(%d)\n", lvl->bits_per_coord, lvl->bits_per_coord); + printf("\tsubdivisions 0x%x(%d)\n", lvl->subdivisions, lvl->subdivisions); +} + +struct subdivision { + struct triple rgn_offset; + unsigned char types; + struct tcoord center; + unsigned short width; + unsigned short height; + unsigned short next; +} __attribute((packed)); + +static void +dump_subdivision(struct subdivision *sub) +{ + printf("subdivision:\n"); + printf("\trgn_offset: "); dump_triple_u(&sub->rgn_offset); + printf("\ttypes: 0x%x(%d)\n", sub->types, sub->types); + printf("\tcenter: "); dump_tcoord(&sub->center); + printf("\tsize: 0x%x(%d)x0x%x(%d) %s\n",sub->width & 0x7fff, sub->width & 0x7fff, sub->height, sub->height, sub->width & 0x8000 ? "Terminating" : ""); + printf("\tnext: 0x%x(%d)\n",sub->next, sub->next); + + printf("\tlen: 0x%x(%d)\n", sizeof(*sub), sizeof(*sub)); +} + +struct rgn_point { + unsigned char info; + struct triple lbl_offset; + short lng_delta; + short lat_delta; + unsigned char subtype; +} __attribute((packed)); + +static void +dump_point(struct rgn_point *pnt) +{ + printf("point:\n"); + printf("\tinfo 0x%x(%d)\n", pnt->info, pnt->info); + printf("\tlbl_offset 0x%x(%d)\n", triple_u(&pnt->lbl_offset), triple_u(&pnt->lbl_offset)); + printf("\tlng_delta 0x%x(%d)\n", pnt->lng_delta, pnt->lng_delta); + printf("\tlat_delta 0x%x(%d)\n", pnt->lat_delta, pnt->lat_delta); + printf("\tsubtype 0x%x(%d)\n", pnt->subtype, pnt->subtype); + printf("\tlen: 0x%x(%d)\n", sizeof(*pnt), sizeof(*pnt)); +} + +struct rgn_poly { + unsigned char info; + struct triple lbl_offset; + short lng_delta; + short lat_delta; + union { + struct { + unsigned char bitstream_len; + unsigned char bitstream_info; + } __attribute((packed)) p1; + struct { + unsigned short bitstream_len; + unsigned char bitstream_info; + } __attribute((packed)) p2; + } __attribute((packed)) u; +} __attribute((packed)); + +static void +dump_poly(struct rgn_poly *ply) +{ + printf("poly:\n"); + printf("\tinfo 0x%x(%d)\n", ply->info, ply->info); + printf("\tlbl_offset 0x%x(%d)\n", triple_u(&ply->lbl_offset), triple_u(&ply->lbl_offset)); + printf("\tlng_delta 0x%x(%d)\n", ply->lng_delta, ply->lng_delta); + printf("\tlat_delta 0x%x(%d)\n", ply->lat_delta, ply->lat_delta); + if (ply->info & 0x80) { + printf("\tbitstream_len 0x%x(%d)\n", ply->u.p2.bitstream_len, ply->u.p2.bitstream_len); + printf("\tbitstream_info 0x%x(%d)\n", ply->u.p2.bitstream_info, ply->u.p2.bitstream_info); + } else { + printf("\tbitstream_len 0x%x(%d)\n", ply->u.p1.bitstream_len, ply->u.p1.bitstream_len); + printf("\tbitstream_info 0x%x(%d)\n", ply->u.p1.bitstream_info, ply->u.p1.bitstream_info); + } + printf("\tlen: 0x%x(%d)\n", sizeof(*ply), sizeof(*ply)); +} + +static void +dump_hex(void *ptr, int len) +{ + unsigned char *c=ptr; + while (len--) { + printf("%02x ", *c++); + } + printf("\n"); +} + +static void +dump_hex_r(void *ptr, int len, int rec) +{ + unsigned char *c=ptr; + int l=rec; + while (len--) { + printf("%02x ", *c++); + if (! --l) { + printf("\n"); + l=rec; + } + } + printf("\n"); +} + +#if 0 +static void +dump_label_offset(struct map_rect_priv *mr, int offset) +{ + void *p; + p=file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128); + printf("%s\n", (char *)p); +} +#endif + + +#if 0 +static void +dump_region_item(struct subdivision *sub, struct file *rgn, struct map_rect_priv *mr) +{ + int offset,item_offset,i,j; + unsigned short count=0; + unsigned short *offsets[4]; + unsigned short *file_offsets; + struct rgn_point *pnt; + + offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset; + file_offsets=file_read(rgn, offset, 90*sizeof(unsigned short)); + printf("0x%x ", offset); dump_hex(file_offsets, 90); + for (i=0 ; i < 4 ; i++) { + printf("i=%d\n", i); + if (sub->types & (0x10 << i)) { + if (count) { + offsets[i]=&file_offsets[count-1]; + } else + offsets[i]=&count; + count++; + } else + offsets[i]=NULL; + + } + count--; + count*=2; + for (i=0 ; i < 4 ; i++) { + printf("i=%d\n", i); + if (offsets[i]) { + printf("offset[%d]=0x%x(%d)\n", i, *offsets[i], *offsets[i]); + switch (i) { + case 0: + printf("point\n"); + break; + case 1: + printf("indexed point\n"); + break; + case 2: + printf("polyline\n"); + break; + case 3: + printf("polygon\n"); + break; + } + item_offset=offset+*offsets[i]; + switch (i) { + case 0: + case 1: + for (j = 0 ; j < 10 ; j++) { + struct coord_geo g; + char buffer[1024]; + double conv=180.0/(1UL<<23); + pnt=file_read(rgn, item_offset, sizeof(*pnt)*20); + // printf("0x%x ", item_offset); dump_hex(pnt, 32); + dump_point(pnt); + g.lng=(triple(&sub->center.lng)+(pnt->lng_delta << shift))*conv; + g.lat=(triple(&sub->center.lat)+(pnt->lat_delta << shift))*conv; + printf("%f %f\n", g.lng, g.lat); + transform_geo_text(&g, buffer); + printf("%s\n", buffer); + dump_label_offset(mr, triple_u(&pnt->lbl_offset)); + if (pnt->info & 0x80) + item_offset+=sizeof(*pnt); + else + item_offset+=sizeof(*pnt)-1; + } + } + } else { + printf("offset[%d] doesn't exist\n", i); + } + } + file_free(file_offsets); +} + +#endif + +static void +dump_levels(struct map_rect_priv *mr) +{ + int i,offset; + struct level *lvl; + + offset=mr->tre_hdr->level.offset; + for (i = 0 ; i < mr->tre_hdr->level.length/sizeof(*lvl) ; i++) { + lvl=file_read(&mr->tre, offset, sizeof(*lvl)); + dump_level(lvl); + offset+=sizeof(*lvl); + } +} + +#if 0 +static void +dump_tree(struct file *f, struct file *rgn, struct map_rect_priv *mr) +{ + struct tree_header *tre_hdr; + struct subdivision *sub; + int i,offset; + + tre_hdr=file_read(f, 0, sizeof(*tre_hdr)); + dump_tree_header(tre_hdr); + offset=tre_hdr->subdivision.offset; + sub=file_read(f, offset, sizeof(*sub)); + dump_subdivision(sub); + offset+=sizeof(*sub); + for (i = 1 ; i < tre_hdr->subdivision.length/sizeof(*sub) ; i++) { + printf("i=%d\n", i); + sub=file_read(f, offset, sizeof(*sub)); + dump_subdivision(sub); + dump_region_item(sub, rgn, mr); + if (sub->width & 0x8000) + break; + offset+=sizeof(*sub); + } + file_free(tre_hdr); +} +#endif + +#if 0 +static void +dump_labels(struct file *f) +{ + struct label_header *lbl_hdr; + + lbl_hdr=file_read(f, 0, sizeof(*lbl_hdr)); + printf("**labels**\n"); + dump_label(lbl_hdr); + file_free(lbl_hdr); +#if 0 + labels=alloca(lbl_hdr.label_length); + file_read(f, lbl_hdr.label_offset, labels, lbl_hdr.label_length); + l=labels; + while (l < labels+lbl_hdr.label_length) { + printf("'%s'(%d)\n", l, strlen(l)); + l+=strlen(l)+1; + } +#endif + +} +#endif + +static void +garmin_img_coord_rewind(void *priv_data) +{ +} + +static void +parse_line(struct map_rect_priv *mr) +{ + int pos=0; + sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos); + if (pos < strlen(mr->line)) { + strcpy(mr->attrs, mr->line+pos); + } +} + +static int +get_bits(struct map_rect_priv *mr, int bits) +{ + unsigned long ret; + ret=L(*((unsigned long *)(mr->ply_data+mr->ply_bitpos/8))); + ret >>= (mr->ply_bitpos & 7); + ret &= (1 << bits)-1; + mr->ply_bitpos+=bits; + return ret; +} + +static int +garmin_img_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos); + int ret=0; + int debug=0; + if (debug) + printf("garmin_img_coord_get %d\n",count); + if (debug) + dump_subdivision(sub); + while (count--) { + if (mr->rgn_type < 2) { + c->x=triple(&sub->center.lng)+(mr->pnt->lng_delta << shift); + c->y=triple(&sub->center.lat)+(mr->pnt->lat_delta << shift); + } else { + if (! mr->ply_bitpos) { + if (mr->ply->info & 0x80) { + mr->ply_bitcount=mr->ply->u.p2.bitstream_len*8; + mr->ply_lngbits=mr->ply->u.p2.bitstream_info & 0xf; + mr->ply_latbits=mr->ply->u.p2.bitstream_info >> 4; + } else { + mr->ply_bitcount=mr->ply->u.p1.bitstream_len*8; + mr->ply_lngbits=mr->ply->u.p1.bitstream_info & 0xf; + mr->ply_latbits=mr->ply->u.p1.bitstream_info >> 4; + } + if (mr->ply_lngbits <= 9) + mr->ply_lngbits+=2; + if (mr->ply_latbits <= 9) + mr->ply_latbits+=2; + if (! get_bits(mr,1)) { + mr->ply_lngbits+=1; + mr->ply_lngsign=0; + } else + if (get_bits(mr, 1)) + mr->ply_lngsign=-1; + else + mr->ply_lngsign=1; + if (! get_bits(mr,1)) { + mr->ply_latbits+=1; + mr->ply_latsign=0; + } else + if (get_bits(mr, 1)) + mr->ply_latsign=-1; + else + mr->ply_latsign=1; + mr->ply_lnglimit=1 << (mr->ply_lngbits-1); + mr->ply_latlimit=1 << (mr->ply_latbits-1); + mr->ply_lng=mr->ply->lng_delta; + mr->ply_lat=mr->ply->lat_delta; + if (debug) + printf("lngbits %d latbits %d bitcount %d\n", mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount); + c->x=0; + c->y=0; + } else { + if (mr->ply_bitpos + mr->ply_lngbits + mr->ply_latbits > mr->ply_bitcount) { + if (debug) + printf("out of bits %d + %d + %d >= %d\n", mr->ply_bitpos, mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount); + return ret; + } + c->x=0; + c->y=0; + int x,y; + for (;;) { + x=get_bits(mr,mr->ply_lngbits); + if (debug) + printf("x %d ", x); + if (mr->ply_lngsign || x != mr->ply_lnglimit) + break; + c->x += x-1; + } + if (mr->ply_lngsign) { + c->x=x*mr->ply_lngsign; + } else { + if (x >= mr->ply_lnglimit) + c->x = x - (mr->ply_lnglimit << 1) - c->x; + else + c->x +=x; + } + for (;;) { + y=get_bits(mr,mr->ply_latbits); + if (debug) + printf("y %d ", y); + if (mr->ply_latsign || y != mr->ply_latlimit) + break; + c->y += y-1; + } + if (mr->ply_latsign) { + c->y=y*mr->ply_latsign; + } else { + if (y >= mr->ply_latlimit) + c->y = y - (mr->ply_latlimit << 1) - c->y; + else + c->y +=y; + } + mr->ply_lng += c->x; + mr->ply_lat += c->y; + } + if (debug) + printf(": x %d y %d\n", c->x, c->y); + + c->x=triple(&sub->center.lng)+(mr->ply_lng << shift); + c->y=triple(&sub->center.lat)+(mr->ply_lat << shift); + } +#if 0 + c->x-=0x6f160; + c->y-=0x181f59; + c->x+=0x168ca1; + c->y+=0x68d815; +#endif + c++; + ret++; + if (mr->rgn_type < 2) + return ret; + } + return ret; +} + +static char * +get_label_offset(struct map_rect_priv *mr, int offset) +{ + g_assert(offset < mr->lbl_hdr->label.offset_len.length); + return file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128); +} + +static void +garmin_img_attr_rewind(void *priv_data) +{ +} + +static int +garmin_img_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + int debug=0; + + if (debug) + printf("garmin_img_attr_get\n"); + if (attr_type == attr_label) { + if (debug) + printf("garmin_img_attr_get label\n"); + attr->type=attr_type; + if (mr->rgn_type < 2) { + if (mr->label) + file_free(mr->label); + mr->label=get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff); + attr->u.str=mr->label; + } else { + attr->u.str=""; + } + return 1; + } + return 0; +} + +static struct item_methods methods_garmin_img = { + garmin_img_coord_rewind, + garmin_img_coord_get, + garmin_img_attr_rewind, + garmin_img_attr_get, +}; + +static int rgn_next_type(struct map_rect_priv *mr) +{ + while (mr->rgn_type < 3) { + mr->rgn_type++; + if (mr->rgn_items[mr->rgn_type].offset && mr->rgn_items[mr->rgn_type].length != 0) { + mr->rgn_offset=mr->rgn_items[mr->rgn_type].offset; + mr->rgn_end=mr->rgn_offset+mr->rgn_items[mr->rgn_type].length; + return 0; + } + } + return 1; +} + +static int +sub_next(struct map_rect_priv *mr, int next) +{ + int i,offset,first=-1,last=-1,count=-1; + int end; + unsigned short *offsets; + int debug=0; + + if (mr->subdiv_level_count <= 0) + return 1; + if (debug) + printf("%d left\n", mr->subdiv_level_count); + mr->subdiv_level_count--; + +#if 0 + if (next && mr->subdiv[mr->subdiv_current].width & 0x8000) + return 1; +#endif + if (debug) + dump_hex_r(mr->subdiv+mr->subdiv_pos, 64, 14); + mr->subdiv_pos+=next; + if (debug) + printf("subdiv_pos 0x%x\n", mr->subdiv_pos); + if (mr->subdiv_pos > mr->tre_hdr->subdivision.length) + return 1; + struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos); + offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset; + if (debug) { + printf("offset=0x%x\n", offset); + dump_subdivision(sub); + } + offsets=file_read(&mr->rgn, offset, 3*sizeof(unsigned short)); + + if (! next) + next=subdiv_next; + if (mr->subdiv_pos+next < mr->tre_hdr->subdivision.length) + end=triple_u(&((struct subdivision *)(mr->subdiv+mr->subdiv_pos+next))->rgn_offset)+mr->rgn_hdr->offset_len.offset; + else + end=mr->rgn_hdr->offset_len.offset+mr->rgn_hdr->offset_len.length; + if (debug) { + dump_subdivision(sub); + dump_hex(offsets, 6); + } + for (i=0 ; i < 4 ; i++) { + if (debug) + printf("i=%d ", i); + if (sub->types & (0x10 << i)) { + if (debug) + printf("+ "); + if (first == -1) { + first=i; + mr->rgn_items[i].offset=offset; + if (debug) + printf("\n"); + } else { + mr->rgn_items[i].offset=offset+offsets[count]; + if (debug) + printf("0x%x\n", offsets[count]); + mr->rgn_items[last].length=mr->rgn_items[i].offset-mr->rgn_items[last].offset; + } + last=i; + count++; + } else { + if (debug) + printf("-\n"); + mr->rgn_items[i].offset=0; + mr->rgn_items[i].length=0; + } + + } + if (first != -1) { + mr->rgn_items[first].offset+=count*2; + mr->rgn_items[first].length-=count*2; + mr->rgn_items[last].length=end-mr->rgn_items[last].offset; + } + if (debug) { + for (i=0 ; i < 4 ; i++) { + printf("%d 0x%x 0x%x\n", i, mr->rgn_items[i].offset, mr->rgn_items[i].length); + } + } + mr->rgn_type=-1; + rgn_next_type(mr); + if (debug) + printf("*** offset 0x%x\n", mr->rgn_offset); + file_free(offsets); + return 0; +} + +int item_count; + +static struct map_rect_priv * +map_rect_new_garmin_img(struct map_priv *map, struct coord_rect *r, struct layer *layers, int limit) +{ + struct map_rect_priv *mr; + struct img_header img; + + if (debug) + printf("map_rect_new_garmin_img\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + if (r) + mr->r=*r; + mr->limit=limit; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.meth=&methods_garmin_img; + mr->item.priv_data=mr; + mr->f=fopen(map->filename, "r"); + + fread(&img, sizeof(img), 1, mr->f); +#if 0 + dump_img(&img); + for (i = 0 ; i < (img.file_offset-sizeof(img))/sizeof(fat_blk) ; i++) { + fread(&fat_blk, sizeof(fat_blk), 1, mr->f); + if (!fat_blk.flag) + break; + dump_fat_block(&fat_blk); + } +#endif + mr->rgn.offset=0xa*2048; + mr->rgn.f=mr->f; + mr->rgn_hdr=file_read(&mr->rgn, 0, sizeof(*mr->rgn_hdr)); + + mr->tre.offset=0x62b*2048; + mr->tre.f=mr->f; + mr->tre_hdr=file_read(&mr->tre, 0, sizeof(*mr->tre_hdr)); + + mr->lbl.offset=0x64a*2048; + mr->lbl.f=mr->f; + mr->lbl_hdr=file_read(&mr->lbl, 0, sizeof(*mr->lbl_hdr)); + + mr->subdiv=file_read(&mr->tre, mr->tre_hdr->subdivision.offset, mr->tre_hdr->subdivision.length); +#if 0 + dump_hex_r(mr->subdiv, mr->tre_hdr->subdivision.length, 16); +#endif + dump_tree_header(mr->tre_hdr); + + dump_levels(mr); + + + printf("limit=%d\n", limit); + if (limit < 3) { + mr->subdiv_pos=0; + mr->subdiv_level_count=1; + shift=11; + } else if (limit < 6) { + mr->subdiv_pos=1*sizeof(struct subdivision); + mr->subdiv_level_count=5; + shift=9; + } else if (limit < 8) { + mr->subdiv_pos=6*sizeof(struct subdivision); + mr->subdiv_level_count=9; + shift=7; + } else if (limit < 10) { + mr->subdiv_pos=15*sizeof(struct subdivision); + mr->subdiv_level_count=143; + shift=5; + } else { + mr->subdiv_pos=158*sizeof(struct subdivision); + mr->subdiv_level_count=4190; + shift=2; + subdiv_next=14; + } + +#if 0 + mr->rgn_offset=triple_u(&mr->subdiv[mr->subdiv_current].rgn_offset)+mr->rgn_hdr->offset_len.offset+4; + mr->rgn_type=1; + mr->rgn_end=mr->rgn_offset+20*8; +#endif + mr->count=0; + item_count=0; + +#if 0 + printf("*** offset 0x%x\n", 0x656c-mr->rgn.offset); + printf("*** offset 0x%x\n", mr->rgn_offset); +#endif +#if 1 + sub_next(mr, 0); +#endif +#if 0 + { + struct rgn_point *pnt; + int i; + int offset=0x65cc; + for (i = 0 ; i < 26 ; i++) { + pnt=file_read(&mr->rgn, 0x656c+8*i-mr->rgn.offset, sizeof(*pnt)); + // dump_hex(pnt, sizeof(*pnt)); + dump_point(pnt); + dump_label_offset(mr, triple_u(&pnt->lbl_offset)); + } + } + exit(0); +#endif +#if 0 + dump_tree(&mr->tre,&mr->rgn,mr); +#endif + +#if 0 + f.offset=0x64a*2048; + f.f=mr->f; + dump_labels(&f); +#endif +#if 0 + fseek(mr->f, img.file_offset, SEEK_SET); + fread(&fil, sizeof(fil), 1, mr->f); + dump_file(&fil); + fread(&rgn, sizeof(rgn), 1, mr->f); + dump_region(&rgn); + fseek(mr->f, rgn.data_length, SEEK_CUR); + fread(&fil, sizeof(fil), 1, mr->f); + dump_file(&fil); +#endif + return mr; +} + + +static void +map_rect_destroy_garmin_img(struct map_rect_priv *mr) +{ + fclose(mr->f); + g_free(mr); +} + + +static struct item * +map_rect_get_item_garmin_img(struct map_rect_priv *mr) +{ + char *p,type[256]; + int ptype; + int debug=0; + + item_count++; + + if (debug) + printf("map_rect_get_item_garmin_img\n"); + for (;;) { + if (mr->rgn_offset < mr->rgn_end) { + if (debug) + printf("data available\n"); + if (mr->rgn_type >= 2) { + int len; + if (debug) + printf("polyline %d\n", mr->count); + if (mr->ply) + file_free(mr->ply); + mr->ply=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->ply)*3); + if(triple_u(&mr->ply->lbl_offset) >= mr->lbl_hdr->label.offset_len.length) { + printf("item_count %d\n", item_count); + dump_poly(mr->ply); + dump_hex(mr->ply, 32); + printf("%d vs %d\n", triple_u(&mr->ply->lbl_offset), mr->lbl_hdr->label.offset_len.length); + } + g_assert(triple_u(&mr->ply->lbl_offset) < mr->lbl_hdr->label.offset_len.length); + if (debug) { + dump_hex(mr->ply, 16); + dump_poly(mr->ply); + } + if (mr->ply_data) + file_free(mr->ply_data); + mr->rgn_offset+=10; + if (mr->ply->info & 0x80) { + mr->rgn_offset++; + len=mr->ply->u.p2.bitstream_len; + } else + len=mr->ply->u.p1.bitstream_len; + + mr->ply_data=file_read(&mr->rgn, mr->rgn_offset, len); + mr->rgn_offset += len; + mr->ply_bitpos=0; + // dump_hex(mr->ply_data, 32); + if (mr->rgn_type == 3) { + switch(mr->ply->info & 0x7f) { + case 0x1: /* large urban area (>200k) */ + mr->item.type=type_town_poly; + break; + case 0xd: /* reservation */ + mr->item.type=type_park_poly; + break; + case 0xe: /* airport runway */ + mr->item.type=type_airport_poly; + break; + case 0x14: /* national park */ + mr->item.type=type_park_poly; + break; + case 0x32: /* sea */ + case 0x3d: /* large lake (77-250km2) */ + case 0x4c: /* intermittend water */ + mr->item.type=type_water_poly; + break; + case 0x4b: /* background */ + continue; + default: + printf("unknown polygon: 0x%x\n", mr->ply->info); + mr->item.type=type_street_3_city; + } + } else { + switch(mr->ply->info & 0x3f) { + case 0x1: /* major highway */ + mr->item.type=type_highway_land; + break; + case 0x2: /* principal highway */ + mr->item.type=type_street_3_land; + break; + case 0x6: /* residental street */ + mr->item.type=type_street_2_land; + break; + case 0x16: /* walkway/trail */ + mr->item.type=type_street_1_land; + break; + case 0x1e: /* international boundary */ + mr->item.type=type_border_country; + break; + case 0x20: /* minor land contour 1/10 */ + mr->item.type=type_height_line_1; + break; + case 0x21: /* major land contour 1/2 */ + mr->item.type=type_height_line_2; + break; + default: + printf("unknown polyline: 0x%x\n", mr->ply->info); + mr->item.type=type_street_3_city; + } + } + return &mr->item; + } + if (mr->pnt) + file_free(mr->pnt); + mr->pnt=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->pnt)); + mr->item.type=type_none; + int subtype=mr->pnt->subtype; + if (mr->pnt->lbl_offset.data[2] & 0x80) + mr->rgn_offset+=9; + else { + mr->rgn_offset+=8; + subtype=0; + } + switch(mr->pnt->info) { + case 0x3: /* large city 2-5M */ + mr->item.type=type_town_label_2e6; + break; + case 0xa: /* small city/town 10-20k */ + mr->item.type=type_town_label_1e4; + break; + case 0xd: /* settlement 1-2K */ + mr->item.type=type_town_label_1e3; + break; + case 0x11: /* settlement less 100 */ + mr->item.type=type_town_label_5e1; + break; + case 0x1c: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_wreck; + break; + } + break; + case 0x20: + mr->item.type=type_highway_exit; + break; + case 0x25: + mr->item.type=type_poi_toll_booth; + break; + case 0x2b: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_hotel; + break; + case 0x03: + mr->item.type=type_poi_camp_rv; + break; + } + break; + case 0x2c: + switch(subtype) { + case 0x00: + mr->item.type=type_poi_attraction; + break; + case 0x02: + mr->item.type=type_poi_museum_history; + break; + } + break; + case 0x2e: + mr->item.type=type_poi_shopping; + break; + case 0x2f: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_fuel; + break; + case 0x07: + mr->item.type=type_poi_car_dealer_parts; + break; + case 0x0b: + mr->item.type=type_poi_car_parking; + break; + case 0x15: + mr->item.type=type_poi_public_utilities; + break; + } + break; + case 0x30: + switch(subtype) { + case 0x02: + mr->item.type=type_poi_hospital; + break; + } + break; + case 0x43: + mr->item.type=type_poi_marina; + break; + case 0x46: + mr->item.type=type_poi_bar; + break; + case 0x48: + mr->item.type=type_poi_camping; + break; + case 0x49: + mr->item.type=type_poi_park; + break; + case 0x4a: + mr->item.type=type_poi_picnic; + break; + case 0x59: /* airport */ + mr->item.type=type_poi_airport; + break; + case 0x64: + switch(subtype) { + case 0x1: + mr->item.type=type_poi_bridge; + break; + case 0x2: + mr->item.type=type_poi_building; + break; + case 0x15: + mr->item.type=type_town_ghost; + break; + } + break; + case 0x65: + switch(subtype) { + case 0x0: + mr->item.type=type_poi_water_feature; + break; + case 0xc: + mr->item.type=type_poi_island; + break; + case 0xd: + mr->item.type=type_poi_lake; + break; + } + break; + case 0x66: + switch(subtype) { + case 0x0: + mr->item.type=type_poi_land_feature; + break; + case 0x6: + mr->item.type=type_poi_cape; + break; + case 0x14: + mr->item.type=type_poi_rock; + break; + } + break; + } + if (mr->item.type == type_none) { + printf("unknown point: 0x%x 0x%x\n", mr->pnt->info, mr->pnt->subtype); + dump_point(mr->pnt); + printf("label: %s\n", get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff)); + mr->item.type=type_town_label; + } + return &mr->item; + } + if (debug) + printf("out of data for type\n"); + if (rgn_next_type(mr)) { + if (debug) + printf("out of data for region\n"); + if (sub_next(mr, subdiv_next)) { + if (debug) + printf("out of data for subdivision\n"); + return NULL; + } + } + } +} + +static struct item * +map_rect_get_item_byid_garmin_img(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + fseek(mr->f, id_lo, SEEK_SET); + get_line(mr); + mr->item.id_hi=id_hi; + return map_rect_get_item_garmin_img(mr); +} + +static struct map_methods map_methods_garmin_img = { + map_destroy_garmin_img, + map_charset_garmin_img, + map_projection_garmin_img, + map_rect_new_garmin_img, + map_rect_destroy_garmin_img, + map_rect_get_item_garmin_img, + map_rect_get_item_byid_garmin_img, +}; + +static struct map_priv * +map_new_garmin_img(struct map_methods *meth, char *filename) +{ + struct map_priv *m; + *meth=map_methods_garmin_img; + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->filename=g_strdup(filename); + return m; +} + +void +plugin_init(void) +{ + plugin_register_map_type("garmin_img", map_new_garmin_img); +} + diff --git a/data/mg/Makefile.am b/data/mg/Makefile.am new file mode 100644 index 00000000..65f0157e --- /dev/null +++ b/data/mg/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. -DMODULE=\"data_mg\" +plugin_LTLIBRARIES = libdata_mg.la +libdata_mg_la_SOURCES = map.c block.c town.c tree.c poly.c street.c mg.h diff --git a/data/mg/block.c b/data/mg/block.c new file mode 100644 index 00000000..93c2fb11 --- /dev/null +++ b/data/mg/block.c @@ -0,0 +1,261 @@ +#include +#include +#include "debug.h" +#include "mg.h" + + +int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem; + +struct block_index_item { + unsigned long blocknum; + unsigned long blocks; +}; + +struct block_index { + unsigned long blocks; + unsigned long size; + unsigned long next; + struct block_index_item list[0]; +}; + +static struct block * +block_get(unsigned char **p) +{ + struct block *ret=(struct block *)(*p); + *p += sizeof(*ret); + return ret; +} + + +static struct block * +block_get_byid(struct file *file, int id, unsigned char **p_ret) +{ + struct block_index *blk_idx; + int blk_num,max; + + + blk_idx=(struct block_index *)(file->begin+0x1000); + max=(blk_idx->size-sizeof(struct block_index))/sizeof(struct block_index_item); + block_mem+=24; + while (id >= max) { + blk_idx=(struct block_index *)(file->begin+blk_idx->next*512); + id-=max; + } + blk_num=blk_idx->list[id].blocknum; + + *p_ret=file->begin+blk_num*512; + return block_get(p_ret); +} + +int +block_get_byindex(struct file *file, int idx, struct block_priv *blk) +{ + dbg(1,"idx=%d\n", idx); + blk->b=block_get_byid(file, idx, &blk->p); + blk->block_start=(unsigned char *)(blk->b); + blk->p_start=blk->p; + blk->end=blk->block_start+blk->b->size; + + return 1; +} + +static void +block_setup_tags(struct map_rect_priv *mr) +{ + int len; + unsigned char *p,*t; + char *str; + + mr->b.binarytree=0; + + p=mr->file->begin+0x0c; + while (*p) { + str=get_string(&p); + len=get_u32_unal(&p); + t=p; + /* printf("String '%s' len %d\n", str, len); */ + if (! strcmp(str,"FirstBatBlock")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"MaxBlockSize")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"FREE_BLOCK_LIST")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"TotalRect")) { + mr->b.b_rect.lu.x=get_u32_unal(&t); + mr->b.b_rect.lu.y=get_u32_unal(&t); + mr->b.b_rect.rl.x=get_u32_unal(&t); + mr->b.b_rect.rl.y=get_u32_unal(&t); + /* 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); */ + } else if (! strcmp(str,"Version")) { + /* printf("0x%lx\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"Categories")) { + /* printf("0x%x\n", get_u16(&t)); */ + } else if (! strcmp(str,"binaryTree")) { + mr->b.binarytree=get_u32_unal(&t); + /* printf("%d\n", mr->b.binarytree); */ + } else if (! strcmp(str,"CategorySets")) { + /* printf("0x%x\n", get_u16(&t)); */ + } else if (! strcmp(str,"Kommentar")) { + /* printf("%s\n", get_string(&t)); */ + } + p+=len; + } +} + +#if 0 +static void +block_rect_print(struct coord_rect *r) +{ + 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); +} +#endif + +static void +block_rect_same(struct coord_rect *r1, struct coord_rect *r2) +{ + g_assert(r1->lu.x==r2->lu.x); + g_assert(r1->lu.y==r2->lu.y); + g_assert(r1->rl.x==r2->rl.x); + g_assert(r1->rl.y==r2->rl.y); +} + +int +block_init(struct map_rect_priv *mr) +{ + mr->b.block_num=-1; + mr->b.bt.b=NULL; + mr->b.bt.next=0; + block_setup_tags(mr); + if (mr->b.binarytree) { + mr->b.bt.next=mr->b.binarytree; + mr->b.bt.p=NULL; + mr->b.bt.block_count=0; + } + if (mr->cur_sel && !coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b_rect)) + return 0; + return block_next(mr); +} + + +int +block_next_lin(struct map_rect_priv *mr) +{ + for (;;) { + block_lin_count++; + block_mem+=sizeof(struct block *); + mr->b.block_num++; + if (! mr->b.block_num) + mr->b.p=mr->file->begin+0x2000; + else + mr->b.p=mr->b.block_start+mr->b.b->blocks*512; + if (mr->b.p >= mr->file->end) + return 0; + mr->b.block_start=mr->b.p; + mr->b.b=block_get(&mr->b.p); + mr->b.p_start=mr->b.p; + mr->b.end=mr->b.block_start+mr->b.b->size; + if (mr->b.b->count == -1) + return 0; + if (!mr->cur_sel || coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b->r)) { + block_active_count++; + block_active_mem+=mr->b.b->blocks*512-sizeof(struct block *); + return 1; + } + } +} + +int +block_next(struct map_rect_priv *mr) +{ + int blk_num,coord,r_h,r_w; + struct block_bt_priv *bt=&mr->b.bt; + + if (!mr->b.binarytree || ! mr->cur_sel) + return block_next_lin(mr); + for (;;) { + if (! bt->p) { + dbg(1,"block 0x%x\n", bt->next); + if (bt->next == -1) + return 0; + bt->b=block_get_byid(mr->file, bt->next, &bt->p); + bt->end=(unsigned char *)mr->b.bt.b+mr->b.bt.b->size; + bt->next=bt->b->next; + bt->order=0; + dbg(1,"size 0x%x next 0x%x\n", bt->b->size, bt->b->next); + if (! mr->b.bt.block_count) { +#if 0 + if (debug) { + printf("idx rect "); + block_rect_print(&mr->b.bt.b->r); + } +#endif + bt->r=bt->b->r; + bt->r_curr=bt->r; + coord=get_u32(&mr->b.bt.p); + } else { + bt->p=(unsigned char *)bt->b+0xc; + } + bt->block_count++; + } + while (mr->b.bt.p < mr->b.bt.end) { + block_idx_count++; + blk_num=get_u32(&mr->b.bt.p); + coord=get_u32(&mr->b.bt.p); + block_mem+=8; + dbg(1,"%p vs %p coord 0x%x ", mr->b.bt.end, mr->b.bt.p, coord); + dbg(1,"block 0x%x", blk_num); + + r_w=bt->r_curr.rl.x-bt->r_curr.lu.x; + r_h=bt->r_curr.lu.y-bt->r_curr.rl.y; +#if 0 + if (debug) { + printf(" rect1 "); + block_rect_print(&bt->r_curr); + printf(" %dx%d", r_w, r_h); + } +#endif + mr->b.b=NULL; + if (blk_num != -1) { + block_mem+=8; + if (coord_rect_overlap(&mr->cur_sel->rect, &bt->r_curr)) { + mr->b.b=block_get_byid(mr->file, blk_num, &mr->b.p); + mr->b.block_num=blk_num; + g_assert(mr->b.b != NULL); + mr->b.block_start=(unsigned char *)(mr->b.b); + mr->b.p_start=mr->b.p; + mr->b.end=mr->b.block_start+mr->b.b->size; + block_rect_same(&mr->b.b->r, &bt->r_curr); + } + } + if (coord != -1) { + bt->stack[bt->stackp]=bt->r_curr; + if (r_w > r_h) { + bt->r_curr.rl.x=coord; + bt->stack[bt->stackp].lu.x=coord+1; + } else { + bt->r_curr.lu.y=coord; + bt->stack[bt->stackp].rl.y=coord+1; + } + bt->stackp++; + g_assert(bt->stackp < BT_STACK_SIZE); + } else { + if (bt->stackp) { + bt->stackp--; + bt->r_curr=bt->stack[bt->stackp]; + } else { + bt->r_curr=bt->r; + bt->order++; + if (bt->order > 100) + return 0; + } + } + if (mr->b.b) { + block_active_count++; + block_active_mem+=mr->b.b->blocks*512; + return 1; + } + } + bt->p=NULL; + } + return 0; +} diff --git a/data/mg/map.c b/data/mg/map.c new file mode 100644 index 00000000..20feb8f1 --- /dev/null +++ b/data/mg/map.c @@ -0,0 +1,296 @@ +#include +#include +#include "debug.h" +#include "plugin.h" +#include "maptype.h" +#include "projection.h" +#include "mg.h" + + +struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro); + +static int map_id; + +static char *file[]={ + [file_border_ply]="border.ply", + [file_bridge_ply]="bridge.ply", + [file_build_ply]="build.ply", + [file_golf_ply]="golf.ply", + [file_height_ply]="height.ply", + [file_natpark_ply]="natpark.ply", + [file_nature_ply]="nature.ply", + [file_other_ply]="other.ply", + [file_rail_ply]="rail.ply", + [file_sea_ply]="sea.ply", + [file_street_bti]="street.bti", + [file_street_str]="street.str", + [file_strname_stn]="strname.stn", + [file_town_twn]="town.twn", + [file_tunnel_ply]="tunnel.ply", + [file_water_ply]="water.ply", + [file_woodland_ply]="woodland.ply", +}; + + +static int +file_next(struct map_rect_priv *mr) +{ + int debug=0; + enum layer_type layer; + + for (;;) { + mr->current_file++; + if (mr->current_file >= file_end) + return 0; + mr->file=mr->m->file[mr->current_file]; + if (! mr->file) + continue; + switch (mr->current_file) { + case file_strname_stn: + continue; + case file_town_twn: + layer=layer_town; + break; + case file_street_str: + layer=layer_street; + break; + default: + layer=layer_poly; + } + if (mr->cur_sel && !mr->cur_sel->order[layer]) + continue; + if (debug) + printf("current file: '%s'\n", file[mr->current_file]); + mr->cur_sel=mr->xsel; + if (block_init(mr)) + return 1; + } +} + +static void +map_destroy_mg(struct map_priv *m) +{ + int i; + + printf("mg_map_destroy\n"); + for (i = 0 ; i < file_end ; i++) { + if (m->file[i]) + file_destroy(m->file[i]); + } +} + +extern int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem; + +static struct map_rect_priv * +map_rect_new_mg(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + int i; + + block_lin_count=0; + block_idx_count=0; + block_active_count=0; + block_mem=0; + block_active_mem=0; + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + mr->xsel=sel; + mr->current_file=-1; + if (sel && sel->next) + for (i=0 ; i < file_end ; i++) + mr->block_hash[i]=g_hash_table_new(g_int_hash,g_int_equal); + + file_next(mr); + return mr; +} + + +static struct item * +map_rect_get_item_mg(struct map_rect_priv *mr) +{ + for (;;) { + switch (mr->current_file) { + case file_town_twn: + if (town_get(mr, &mr->town, &mr->item)) + return &mr->item; + break; + case file_border_ply: + /* case file_bridge_ply: */ + case file_build_ply: + case file_golf_ply: + /* case file_height_ply: */ + case file_natpark_ply: + case file_nature_ply: + case file_other_ply: + case file_rail_ply: + case file_sea_ply: + /* case file_tunnel_ply: */ + case file_water_ply: + case file_woodland_ply: + if (poly_get(mr, &mr->poly, &mr->item)) + return &mr->item; + break; + case file_street_str: + if (street_get(mr, &mr->street, &mr->item)) + return &mr->item; + break; + case file_end: + return NULL; + default: + break; + } + if (block_next(mr)) + continue; + if (mr->cur_sel->next) { + mr->cur_sel=mr->cur_sel->next; + if (block_init(mr)) + continue; + } + if (file_next(mr)) + continue; + dbg(1,"lin_count %d idx_count %d active_count %d %d kB (%d kB)\n", block_lin_count, block_idx_count, block_active_count, (block_mem+block_active_mem)/1024, block_active_mem/1024); + return NULL; + } +} + +static struct item * +map_rect_get_item_byid_mg(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + mr->current_file = id_hi >> 16; + switch (mr->current_file) { + case file_town_twn: + if (town_get_byid(mr, &mr->town, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + case file_street_str: + if (street_get_byid(mr, &mr->street, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + default: + if (poly_get_byid(mr, &mr->poly, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + } + return NULL; +} + + +static void +map_rect_destroy_mg(struct map_rect_priv *mr) +{ + int i; + for (i=0 ; i < file_end ; i++) + if (mr->block_hash[i]) + g_hash_table_destroy(mr->block_hash[i]); + g_free(mr); +} + +static struct map_search_priv * +map_search_new_mg(struct map_priv *map, struct item *item, struct attr *search, int partial) +{ + struct map_rect_priv *mr=g_new0(struct map_rect_priv, 1); + dbg(1,"id_lo=0x%x\n", item->id_lo); + dbg(1,"search=%s\n", search->u.str); + mr->m=map; + mr->search_type=search->type; + switch (search->type) { + case attr_town_name: + if (item->type != type_country_label) + return NULL; + tree_search_init(map->dirname, "town.b2", &mr->ts, 0x1000); + break; + case attr_street_name: + if (item->type != type_town_streets) + return NULL; + dbg(1,"street_assoc=0x%x\n", item->id_lo); + tree_search_init(map->dirname, "strname.b1", &mr->ts, 0); + break; + default: + dbg(0,"unknown search\n"); + g_free(mr); + return NULL; + } + mr->search_item=*item; + mr->search_country=item->id_lo; + mr->search_str=search->u.str; + mr->search_partial=partial; + mr->current_file=file_town_twn-1; + file_next(mr); + return (struct map_search_priv *)mr; +} + +static void +map_search_destroy_mg(struct map_search_priv *ms) +{ + struct map_rect_priv *mr=(struct map_rect_priv *)ms; + + if (! mr) + return; + tree_search_free(&mr->ts); + g_free(mr); +} + +static struct item * +map_search_get_item_mg(struct map_search_priv *ms) +{ + struct map_rect_priv *mr=(struct map_rect_priv *)ms; + + if (! mr) + return NULL; + switch (mr->search_type) { + case attr_town_name: + return town_search_get_item(mr); + case attr_street_name: + return street_search_get_item(mr); + default: + return NULL; + } +} + +static struct map_methods map_methods_mg = { + map_destroy_mg, + map_rect_new_mg, + map_rect_destroy_mg, + map_rect_get_item_mg, + map_rect_get_item_byid_mg, + map_search_new_mg, + map_search_destroy_mg, + map_search_get_item_mg, +}; + +struct map_priv * +map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro) +{ + struct map_priv *m; + int i,maybe_missing,len=strlen(dirname); + char filename[len+16]; + + *meth=map_methods_mg; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->dirname=g_strdup(dirname); + strcpy(filename, dirname); + filename[len]='/'; + for (i = 0 ; i < file_end ; i++) { + if (file[i]) { + strcpy(filename+len+1, file[i]); + m->file[i]=file_create_caseinsensitive(filename); + if (! m->file[i]) { + maybe_missing=(i == file_border_ply || i == file_height_ply || i == file_sea_ply); + if (! maybe_missing) + g_warning("Failed to load %s", filename); + } + } + } + + return m; +} + +void +plugin_init(void) +{ + plugin_register_map_type("mg", map_new_mg); +} diff --git a/data/mg/mg.h b/data/mg/mg.h new file mode 100644 index 00000000..696fd55c --- /dev/null +++ b/data/mg/mg.h @@ -0,0 +1,286 @@ +#include +#include "attr.h" +#include "coord.h" +#include "data.h" +#include "item.h" +#include "map.h" +#include "file.h" + +struct block_data { + struct file *file; +}; + +struct block { + int blocks; + int size; + int next; + struct coord_rect r; + int count; +}; + +struct item_priv { + int cidx; + int aidx; + unsigned char *cstart,*cp,*cend; + unsigned char *astart,*ap,*aend; + enum attr_type attr_last; + enum attr_type attr_next; + struct item item; +}; + +struct town_priv { + unsigned int id; /*!< Identifier */ + struct coord c; /*!< Coordinates */ + char *name; /*!< Name */ + char *district; /*!< District */ + char *postal_code1; /*!< Postal code */ + unsigned char order; /*!< Order (Importance) */ + unsigned char type; /*!< Type */ + unsigned short country; /*!< Country */ + unsigned int unknown2; /*!< Unknown */ + unsigned char size; /*!< Size of town */ + unsigned int street_assoc; /*!< Association to streets */ + unsigned char unknown3; /*!< Unknown */ + char *postal_code2; /*!< 2nd postal code */ + unsigned int unknown4; /*!< Unknown */ + + int cidx; + int aidx; + enum attr_type attr_next; + char debug[256]; + struct item town_attr_item; +}; + +struct poly_priv { + int poly_num; + unsigned char *poly_next; + int subpoly_num; + int subpoly_num_all; + unsigned char *subpoly_next; + unsigned char *subpoly_start; + unsigned char *p; + struct coord c[2]; + char *name; + unsigned char order; + unsigned char type; + unsigned int polys; + unsigned int *count; + unsigned int count_sum; + + int aidx; + enum attr_type attr_next; +}; + +struct street_header { + unsigned char order; + int count; +} __attribute__((packed)); + +struct street_type { + unsigned char order; + unsigned short country; +} __attribute__((packed)); + +struct street_header_type { + struct street_header *header; + int type_count; + struct street_type *type; +}; + +struct street_str { + int segid; + unsigned char limit; /* 0x03,0x30=One Way,0x33=No Passing */ + unsigned char unknown2; + unsigned char unknown3; + unsigned char type; + unsigned int nameid; +}; + +struct street_name_segment { + int segid; + int country; +}; + +struct street_name { + int len; + int country; + int townassoc; + char *name1; + char *name2; + int segment_count; + struct street_name_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + +struct street_name_numbers { + int len; + int tag; + int dist; + int country; + struct coord *c; + int first; + int last; + int segment_count; + struct street_name_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + +struct street_name_number { + int len; + int tag; + struct coord *c; + int first; + int last; + struct street_name_segment *segment; +}; + + + +struct street_priv { + struct file *name_file; + struct street_header *header; + int type_count; + struct street_type *type; + struct street_str *str; + struct street_str *str_start; + unsigned char *coord_begin; + unsigned char *p; + unsigned char *p_rewind; + unsigned char *end; + unsigned char *next; + int status; + int status_rewind; + struct coord *ref; + int bytes; + struct street_name name; + enum attr_type attr_next; + char debug[256]; +}; + +enum file_index { + file_border_ply=0, + file_bridge_ply, + file_build_ply, + file_golf_ply, + file_height_ply, + file_natpark_ply, + file_nature_ply, + file_other_ply, + file_rail_ply, + file_sea_ply, + file_street_bti, + file_street_str, + file_strname_stn, + file_town_twn, + file_tunnel_ply, + file_water_ply, + file_woodland_ply, + file_end +}; + +struct map_priv { + int id; + struct file *file[file_end]; + char *dirname; +}; + +#define BT_STACK_SIZE 32 + +struct block_bt_priv { + struct block *b; + struct coord_rect r, r_curr; + int next; + int block_count; + struct coord_rect stack[BT_STACK_SIZE]; + int stackp; + int order; + unsigned char *p; + unsigned char *end; +}; + +struct block_priv { + int block_num; + struct coord_rect b_rect; + unsigned char *block_start; + struct block *b; + unsigned char *p; + unsigned char *end; + unsigned char *p_start; + int binarytree; + struct block_bt_priv bt; +}; + +struct block_offset { + unsigned short offset; + unsigned short block; +}; + + +struct tree_search_node { + struct tree_hdr *hdr; + unsigned char *p; + unsigned char *last; + unsigned char *end; + int low; + int high; + int last_low; + int last_high; + }; + +struct tree_search { + struct file *f; + int last_node; + int curr_node; + struct tree_search_node nodes[5]; +}; + + +struct map_rect_priv { + struct map_selection *xsel; + struct map_selection *cur_sel; + + struct map_priv *m; + enum file_index current_file; + struct file *file; + struct block_priv b; + struct item item; + struct town_priv town; + struct poly_priv poly; + struct street_priv street; + struct tree_search ts; + int search_country; + struct item search_item; + char *search_str; + int search_partial; + int search_linear; + unsigned char *search_p; + int search_blk_count; + enum attr_type search_type; + struct block_offset *search_blk_off; + int search_block; + GHashTable *block_hash[file_end]; + struct item_priv item3; +}; + +int block_init(struct map_rect_priv *mr); +int block_next(struct map_rect_priv *mr); +int block_get_byindex(struct file *file, int idx, struct block_priv *blk); + +int tree_search_hv(char *dirname, char *filename, unsigned int search1, unsigned int search2, int *result); +int town_get(struct map_rect_priv *mr, struct town_priv *poly, struct item *item); +int town_get_byid(struct map_rect_priv *mr, struct town_priv *twn, int id_hi, int id_lo, struct item *item); +struct item * town_search_get_item(struct map_rect_priv *mr); +int poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item); +int poly_get_byid(struct map_rect_priv *mr, struct poly_priv *poly, int id_hi, int id_lo, struct item *item); +int street_get(struct map_rect_priv *mr, struct street_priv *street, struct item *item); +int street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item); +void tree_search_init(char *dirname, char *filename, struct tree_search *ts, int offset); +void tree_search_free(struct tree_search *ts); +int tree_search_next(struct tree_search *ts, unsigned char **p, int dir); +int tree_search_next_lin(struct tree_search *ts, unsigned char **p); diff --git a/data/mg/poly.c b/data/mg/poly.c new file mode 100644 index 00000000..b19aeed5 --- /dev/null +++ b/data/mg/poly.c @@ -0,0 +1,196 @@ +#include "debug.h" +#include "mg.h" + +static void +poly_coord_rewind(void *priv_data) +{ + struct poly_priv *poly=priv_data; + + poly->p=poly->subpoly_start; + +} + +static int +poly_coord_get(void *priv_data, struct coord *c, int count) +{ + struct poly_priv *poly=priv_data; + int ret=0; + + while (count--) { + if (poly->p >= poly->subpoly_next) + break; + c->x=get_u32_unal(&poly->p); + c->y=get_u32_unal(&poly->p); + c++; + ret++; + } + return ret; +} + +static void +poly_attr_rewind(void *priv_data) +{ + struct poly_priv *poly=priv_data; + + poly->aidx=0; +} + +static int +poly_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct poly_priv *poly=priv_data; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (poly->attr_next != attr_none) { + if (poly_attr_get(poly, poly->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=poly->name; + poly->attr_next=attr_none; + if (attr->u.str[0]) + return 1; + return 0; + default: + return 0; + } + return 1; +} + +static struct item_methods poly_meth = { + poly_coord_rewind, + poly_coord_get, + poly_attr_rewind, + poly_attr_get, +}; + +static void +poly_get_data(struct poly_priv *poly, unsigned char **p) +{ + poly->c[0].x=get_u32_unal(p); + poly->c[0].y=get_u32_unal(p); + poly->c[1].x=get_u32_unal(p); + poly->c[1].y=get_u32_unal(p); + *p+=sizeof(struct coord); + poly->name=(char *)(*p); + while (**p) { + (*p)++; + } + (*p)++; + poly->order=*(*p)++; + poly->type=*(*p)++; + poly->polys=get_u32_unal(p); + poly->count=(unsigned int *)(*p); (*p)+=poly->polys*sizeof(unsigned int); + poly->count_sum=get_u32_unal(p); +} + +int +poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) +{ + struct coord_rect r; + + for (;;) { + if (mr->b.p >= mr->b.end) + return 0; + if (mr->b.p == mr->b.p_start) { + poly->poly_num=0; + poly->subpoly_num=0; + poly->subpoly_num_all=0; + poly->poly_next=mr->b.p; + item->meth=&poly_meth; + } + if (poly->poly_num >= mr->b.b->count) + return 0; + if (!poly->subpoly_num) { + mr->b.p=poly->poly_next; + item->id_lo=mr->b.p-mr->file->begin; + poly_get_data(poly, &mr->b.p); + poly->poly_next=mr->b.p+poly->count_sum*sizeof(struct coord); + poly->poly_num++; + r.lu=poly->c[0]; + r.rl=poly->c[1]; + if (mr->cur_sel && (poly->order > mr->cur_sel->order[layer_poly]*3 || !coord_rect_overlap(&mr->cur_sel->rect, &r))) { + poly->subpoly_num_all+=poly->polys; + mr->b.p=poly->poly_next; + continue; + } + switch(poly->type) { + case 0x13: + item->type=type_wood; + break; + case 0x14: + item->type=type_town_poly; + break; + case 0x15: + item->type=type_cemetery_poly; + break; + case 0x1e: + item->type=type_industry_poly; + break; + case 0x24: + item->type=type_parking_lot_poly; + break; + case 0x28: + item->type=type_airport_poly; + break; + case 0x2d: + item->type=type_hospital_poly; + break; + case 0x32: + item->type=type_park_poly; + break; + case 0x34: + item->type=type_sport_poly; + break; + case 0x3c: + item->type=type_water_poly; + break; + case 0xbc: + item->type=type_water_line; + break; + case 0xc6: + item->type=type_border_country; + break; + case 0xc7: + item->type=type_border_state; + break; + case 0xd0: + item->type=type_rail; + break; + default: + dbg(0,"Unknown poly type 0x%x '%s' 0x%x,0x%x\n", poly->type,poly->name,r.lu.x,r.lu.y); + item->type=type_street_unkn; + } + } else + mr->b.p=poly->subpoly_next; + dbg(1,"%d %d %s\n", poly->subpoly_num_all, mr->b.block_num, poly->name); + item->id_lo=poly->subpoly_num_all | (mr->b.block_num << 16); + item->id_hi=(mr->current_file << 16); + dbg(1,"0x%x 0x%x\n", item->id_lo, item->id_hi); + poly->subpoly_next=mr->b.p+L(poly->count[poly->subpoly_num])*sizeof(struct coord); + poly->subpoly_num++; + poly->subpoly_num_all++; + if (poly->subpoly_num >= poly->polys) + poly->subpoly_num=0; + poly->subpoly_start=poly->p=mr->b.p; + item->priv_data=poly; + poly->attr_next=attr_label; + return 1; + } +} + +int +poly_get_byid(struct map_rect_priv *mr, struct poly_priv *poly, int id_hi, int id_lo, struct item *item) +{ + int count=id_lo & 0xffff; + int ret=0; + block_get_byindex(mr->m->file[mr->current_file], id_lo >> 16, &mr->b); + while (count-- >= 0) { + ret=poly_get(mr, poly, item); + } + return ret; +} + diff --git a/data/mg/street.c b/data/mg/street.c new file mode 100644 index 00000000..550e5006 --- /dev/null +++ b/data/mg/street.c @@ -0,0 +1,702 @@ +#include +#include "debug.h" +#include "mg.h" + +int coord_debug; + +static void +street_name_get(struct street_name *name, unsigned char **p) +{ + unsigned char *start=*p; + name->len=get_u16_unal(p); + name->country=get_u16_unal(p); + name->townassoc=get_u32_unal(p); + name->name1=get_string(p); + name->name2=get_string(p); + name->segment_count=get_u32_unal(p); + name->segments=(struct street_name_segment *)(*p); + (*p)+=(sizeof (struct street_name_segment))*name->segment_count; + name->aux_len=name->len-(*p-start); + name->aux_data=*p; + name->tmp_len=name->aux_len; + name->tmp_data=name->aux_data; + *p=start+name->len; +} + +static void +street_name_numbers_get(struct street_name_numbers *name_numbers, unsigned char **p) +{ + unsigned char *start=*p; + name_numbers->len=get_u16(p); + name_numbers->tag=get_u8(p); + name_numbers->dist=get_u32(p); + name_numbers->country=get_u32(p); + name_numbers->c=coord_get(p); + name_numbers->first=get_u24(p); + name_numbers->last=get_u24(p); + name_numbers->segment_count=get_u32(p); + name_numbers->segments=(struct street_name_segment *)(*p); + (*p)+=sizeof(struct street_name_segment)*name_numbers->segment_count; + name_numbers->aux_len=name_numbers->len-(*p-start); + name_numbers->aux_data=*p; + name_numbers->tmp_len=name_numbers->aux_len; + name_numbers->tmp_data=name_numbers->aux_data; + *p=start+name_numbers->len; +} + +static void +street_name_number_get(struct street_name_number *name_number, unsigned char **p) +{ + unsigned char *start=*p; + name_number->len=get_u16(p); + name_number->tag=get_u8(p); + name_number->c=coord_get(p); + name_number->first=get_u24(p); + name_number->last=get_u24(p); + name_number->segment=(struct street_name_segment *)p; + *p=start+name_number->len; +} + +static void +street_name_get_by_id(struct street_name *name, struct file *file, unsigned long id) +{ + unsigned char *p; + if (id) { + p=file->begin+id+0x2000; + street_name_get(name, &p); + } +} + +static int street_get_bytes(struct coord_rect *r) +{ + int bytes,dx,dy; + bytes=2; + dx=r->rl.x-r->lu.x; + dy=r->lu.y-r->rl.y; + g_assert(dx > 0); + g_assert(dy > 0); + if (dx > 32767 || dy > 32767) + bytes=3; + if (dx > 8388608 || dy > 8388608) + bytes=4; + + return bytes; +} + +static int street_get_coord(unsigned char **pos, int bytes, struct coord *ref, struct coord *f) +{ + unsigned char *p; + int x,y,flags=0; + + p=*pos; + x=*p++; + x|=(*p++) << 8; + if (bytes == 2) { + if ( x > 0x7fff) { + x=0x10000-x; + flags=1; + } + } + else if (bytes == 3) { + x|=(*p++) << 16; + if ( x > 0x7fffff) { + x=0x1000000-x; + flags=1; + } + } else { + x|=(*p++) << 16; + x|=(*p++) << 24; + if (x < 0) { + x=-x; + flags=1; + } + } + y=*p++; + y|=(*p++) << 8; + if (bytes == 3) { + y|=(*p++) << 16; + } else if (bytes == 4) { + y|=(*p++) << 16; + y|=(*p++) << 24; + } + if (f) { + f->x=ref[0].x+x; + f->y=ref[1].y+y; + } + dbg(1,"0x%x,0x%x + 0x%x,0x%x = 0x%x,0x%x\n", x, y, ref[0].x, ref[1].y, f->x, f->y); + *pos=p; + return flags; +} + +static void +street_coord_get_begin(unsigned char **p) +{ + struct street_str *str; + + str=(struct street_str *)(*p); + while (L(str->segid)) { + str++; + } + (*p)=(unsigned char *)str; + (*p)+=4; +} + + +static void +street_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_coord_get_helper(struct street_priv *street, struct coord *c) +{ + unsigned char *n; + if (street->p+street->bytes*2 >= street->end) + return 0; + if (street->status >= 4) + return 0; + n=street->p; + if (street_get_coord(&street->p, street->bytes, street->ref, c)) { + if (street->status) + street->next=n; + street->status+=2; + if (street->status == 5) + return 0; + } + return 1; +} + +static int +street_coord_get(void *priv_data, struct coord *c, int count) +{ + struct street_priv *street=priv_data; + int ret=0,i,scount; + + if (! street->p && count) { + street->p=street->coord_begin; + scount=street->str-street->str_start; + for (i = 0 ; i < scount ; i++) { + street->status=L(street->str[i+1].segid) >= 0 ? 0:1; + while (street_coord_get_helper(street, c)); + street->p=street->next; + } + street->status_rewind=street->status=L(street->str[1].segid) >= 0 ? 0:1; + } + while (count > 0) { + if (street_coord_get_helper(street, c)) { + c++; + ret++; + count--; + } else + return ret; + } + return ret; +} + +static void +street_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct street_priv *street=priv_data; + int nameid; + + dbg(1,"segid 0x%x\n", street->str->segid); + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (street->attr_next != attr_none) { + if (street_attr_get(street, street->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + street->attr_next=attr_street_name; + attr->u.str=street->name.name2; + if (attr->u.str && attr->u.str[0]) + return 1; + attr->u.str=street->name.name1; + if (attr->u.str && attr->u.str[0]) + return 1; + return 0; + case attr_street_name: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + attr->u.str=street->name.name2; + street->attr_next=attr_street_name_systematic; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_systematic: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + attr->u.str=street->name.name1; + street->attr_next=attr_limit; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_limit: + if (street->str->type & 0x40) { + attr->u.num=(street->str->limit & 0x30) ? 2:0; + attr->u.num|=(street->str->limit & 0x03) ? 1:0; + } else { + attr->u.num=(street->str->limit & 0x30) ? 1:0; + attr->u.num|=(street->str->limit & 0x03) ? 2:0; + } + street->attr_next=attr_debug; + return 1; + case attr_debug: + street->attr_next=attr_none; + { + struct street_str *str=street->str; + sprintf(street->debug,"order:0x%x\nsegid:0x%x\nlimit:0x%x\nunknown2:0x%x\nunknown3:0x%x\ntype:0x%x\nnameid:0x%x\ntownassoc:0x%x",street->header->order,str->segid,str->limit,str->unknown2,str->unknown3,str->type,str->nameid, street->name.len ? street->name.townassoc : 0); + attr->u.str=street->debug; + } + return 1; + default: + return 0; + } + return 1; +} + +static struct item_methods street_meth = { + street_coord_rewind, + street_coord_get, + street_attr_rewind, + street_attr_get, +}; + +static void +street_get_data(struct street_priv *street, unsigned char **p) +{ + street->header=(struct street_header *)(*p); + (*p)+=sizeof(struct street_header); + street->type_count=street->header->count; + street->type=(struct street_type *)(*p); + (*p)+=street->type_count*sizeof(struct street_type); +} + + + /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */ +static unsigned char limit[]={0,0,1,1,1,2,2,4,6,6,12,13,14,20,20,20,20,20,20}; + +int +street_get(struct map_rect_priv *mr, struct street_priv *street, struct item *item) +{ + if (mr->b.p == mr->b.p_start) { + street_get_data(street, &mr->b.p); + street->name_file=mr->m->file[file_strname_stn]; + if (mr->cur_sel && street->header->order > limit[mr->cur_sel->order[layer_street]]) + return 0; + street->end=mr->b.end; + street->ref=&mr->b.b->r.lu; + street->bytes=street_get_bytes(&mr->b.b->r); + street->str_start=street->str=(struct street_str *)mr->b.p; + street->coord_begin=mr->b.p; + street_coord_get_begin(&street->coord_begin); + street->p=street->coord_begin; + street->type--; + item->meth=&street_meth; + item->priv_data=street; + } else { + street->str++; + street->p=street->next; + } + if (! L(street->str->segid)) + return 0; + if (L(street->str->segid) < 0) + street->type++; +#if 0 + g_assert(street->p != NULL); +#endif + street->next=NULL; + street->status_rewind=street->status=L(street->str[1].segid) >= 0 ? 0:1; +#if 0 + if (street->type->country != 0x31) { + printf("country=0x%x\n", street->type->country); + } +#endif + item->id_hi=street->type->country | (mr->current_file << 16); + item->id_lo=L(street->str->segid) > 0 ? L(street->str->segid) : -L(street->str->segid); + switch(street->str->type & 0x1f) { + case 0xf: /* very small street */ + if (street->str->limit == 0x33) + item->type=type_street_nopass; + else + item->type=type_street_0; + break; + case 0xd: + item->type=type_ferry; + break; + case 0xc: /* small street */ + item->type=type_street_1_city; + break; + case 0xb: + item->type=type_street_2_city; + break; + case 0xa: + if ((street->str->limit == 0x03 || street->str->limit == 0x30) && street->header->order < 4) + item->type=type_street_4_city; + else + item->type=type_street_3_city; + break; + case 0x9: + if (street->header->order < 5) + item->type=type_street_4_city; + else if (street->header->order < 7) + item->type=type_street_2_city; + else + item->type=type_street_1_city; + break; + case 0x8: + item->type=type_street_2_land; + break; + case 0x7: + if ((street->str->limit == 0x03 || street->str->limit == 0x30) && street->header->order < 4) + item->type=type_street_4_city; + else + item->type=type_street_3_land; + break; + case 0x6: + item->type=type_ramp; + break; + case 0x5: + item->type=type_street_4_land; + break; + case 0x4: + item->type=type_street_4_land; + break; + case 0x3: + item->type=type_street_n_lanes; + break; + case 0x2: + item->type=type_highway_city; + break; + case 0x1: + item->type=type_highway_land; + break; + default: + item->type=type_street_unkn; + dbg(0,"unknown type 0x%x\n",street->str->type); + } +#if 0 + coord_debug=(street->str->unknown2 != 0x40 || street->str->unknown3 != 0x40); + if (coord_debug) { + item->type=type_street_unkn; + printf("%d %02x %02x %02x %02x\n", street->str->segid, street->str->type, street->str->limit, street->str->unknown2, street->str->unknown3); + } +#endif + street->p_rewind=street->p; + street->name.len=0; + street->attr_next=attr_label; + return 1; +} + +int +street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item) +{ + int country=id_hi & 0xffff; + int res; + dbg(1,"enter(%p,%p,0x%x,0x%x,%p)\n", mr, street, id_hi, id_lo, item); + if (! country) + return 0; + tree_search_hv(mr->m->dirname, "street", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res); + dbg(1,"res=0x%x (blk=0x%x)\n", res, res >> 12); + block_get_byindex(mr->m->file[mr->current_file], res >> 12, &mr->b); + street_get_data(street, &mr->b.p); + street->name_file=mr->m->file[file_strname_stn]; + street->end=mr->b.end; + street->ref=&mr->b.b->r.lu; + street->bytes=street_get_bytes(&mr->b.b->r); + street->str_start=street->str=(struct street_str *)mr->b.p; + street->coord_begin=mr->b.p; + street_coord_get_begin(&street->coord_begin); + street->p=street->coord_begin; + street->type--; + item->meth=&street_meth; + item->priv_data=street; + street->str+=(res & 0xfff)-1; + dbg(1,"segid 0x%x\n", street->str[1].segid); + return street_get(mr, street, item); +#if 0 + mr->b.p=mr->b.block_start+(res & 0xffff); + return town_get(mr, twn, item); +#endif + + return 0; +} + + +struct street_name_index { + int block; + unsigned short country; + long town_assoc; + char name[0]; +} __attribute__((packed)); + + +static int +street_search_compare_do(struct map_rect_priv *mr, int country, int town_assoc, char *name) +{ + int d; + + dbg(1,"enter"); + dbg(1,"country 0x%x town_assoc 0x%x name '%s'\n", country, town_assoc, name); + d=(mr->search_item.id_hi & 0xffff)-country; + dbg(1,"country %d\n", d); + if (!d) { + d=mr->search_item.id_lo-town_assoc; + dbg(1,"assoc %d 0x%x-0x%x\n",d, mr->search_item.id_lo, town_assoc); + if (! d) { + if (mr->search_partial) + d=strncasecmp(mr->search_str, name, strlen(mr->search_str)); + else + d=strcasecmp(mr->search_str, name); + dbg(1,"string %d\n", d); + } + } + dbg(1,"d=%d\n", d); + return d; +} + +static int +street_search_compare(unsigned char **p, struct map_rect_priv *mr) +{ + struct street_name_index *i; + + dbg(1,"enter\n"); + i=(struct street_name_index *)(*p); + *p+=sizeof(*i)+strlen(i->name)+1; + mr->search_block=i->block; + + dbg(1,"block 0x%x\n", i->block); + + return street_search_compare_do(mr, i->country, i->town_assoc, i->name); +} + +static void +street_name_numbers_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static void +street_name_numbers_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_name_numbers_coord_get(void *priv_data, struct coord *c, int count) +{ + return 0; +} + +static int +street_name_numbers_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + struct item *item; + + attr->type=attr_type; + switch (attr_type) { + default: + dbg(0,"unknown item\n"); + return 0; + } +} + + + + + +static struct item_methods street_name_numbers_meth = { + street_name_numbers_coord_rewind, + street_name_numbers_coord_get, + street_name_numbers_attr_rewind, + street_name_numbers_attr_get, +}; + + +static void +street_name_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static void +street_name_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_name_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + struct street_name_numbers snns; + unsigned char *p=mr->street.name.aux_data; + + dbg(0,"aux_data=%p\n", p); + if (count) { + street_name_numbers_get(&snns, &p); + *c=*(snns.c); + return 1; + } + + return 0; +} + +static int +street_name_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + struct item *item; + + attr->type=attr_type; + switch (attr_type) { + case attr_street_name: + attr->u.str=mr->street.name.name2; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_systematic: + attr->u.str=mr->street.name.name1; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_numbers_item: + item=&mr->item3.item; + attr->u.item=item; + item->type=type_street_name_numbers; + item->id_hi=0; + item->id_lo=1; + item->meth=&street_name_numbers_meth; + item->map=NULL; + item->priv_data=mr; + { + int i; + struct street_name_numbers nns; + unsigned char *p=mr->street.name.aux_data; + unsigned char *end=p+mr->street.name.aux_len; + printf("len=0x%x\n", mr->street.name.aux_len); + for (i = 0 ; i < mr->street.name.aux_len ; i++) { + printf("%02x ",mr->street.name.aux_data[i]); + } + printf("\n"); + { + while (p < end) { + unsigned char *pn,*pn_end;; + struct street_name_number nn; + street_name_numbers_get(&nns, &p); + printf("name_numbers:\n"); + printf(" len 0x%x\n", nns.len); + printf(" tag 0x%x\n", nns.tag); + printf(" dist 0x%x\n", nns.dist); + printf(" country 0x%x\n", nns.country); + printf(" coord 0x%x,0x%x\n", nns.c->x, nns.c->y); + printf(" first %d\n", nns.first); + printf(" last %d\n", nns.last); + printf(" segment count 0x%x\n", nns.segment_count); + printf(" aux_len 0x%x\n", nns.aux_len); + pn=nns.aux_data; + pn_end=nns.aux_data+nns.aux_len; + while (pn < pn_end) { + printf(" number:\n"); + street_name_number_get(&nn, &pn); + printf(" len 0x%x\n", nn.len); + printf(" tag 0x%x\n", nn.tag); + printf(" coord 0x%x,0x%x\n", nn.c->x, nn.c->y); + printf(" first %d\n", nn.first); + printf(" last %d\n", nn.last); + } + } + } + } + return 1; + default: + dbg(0,"unknown item\n"); + return 0; + } +} + + + + + +static struct item_methods street_name_meth = { + street_name_coord_rewind, + street_name_coord_get, + street_name_attr_rewind, + street_name_attr_get, +}; + + +struct item * +street_search_get_item(struct map_rect_priv *mr) +{ + int dir=1,leaf; + unsigned char *last; + + dbg(1,"enter\n"); + if (! mr->search_blk_count) { + dbg(1,"partial 0x%x '%s' ***\n", mr->town.street_assoc, mr->search_str); + if (mr->search_linear) + return NULL; + dbg(1,"tree_search_next\n"); + mr->search_block=-1; + while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) { + dir=street_search_compare(&mr->search_p, mr); + } + if (mr->search_block == -1) + return NULL; + dbg(1,"mr->search_block=0x%x\n", mr->search_block); + mr->search_blk_count=1; + block_get_byindex(mr->m->file[file_strname_stn], mr->search_block, &mr->b); + mr->b.p=mr->b.block_start+12; + } + dbg(1,"name id 0x%x\n", mr->b.p-mr->m->file[file_strname_stn]->begin); + if (! mr->search_blk_count) + return NULL; + if (mr->b.p >= mr->b.end) { + if (!block_next_lin(mr)) + return NULL; + mr->b.p=mr->b.block_start+12; + } + while (mr->b.p < mr->b.end) { + last=mr->b.p; + street_name_get(&mr->street.name, &mr->b.p); + dir=street_search_compare_do(mr, mr->street.name.country, mr->street.name.townassoc, mr->street.name.name2); + dbg(1,"country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir); + if (dir < 0) { + mr->search_blk_count=0; + return NULL; + } + if (!dir) { + dbg(0,"result country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d aux_data=%p len=0x%x\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir, mr->street.name.aux_data, mr->street.name.aux_len); + mr->item.type = type_street_name; + mr->item.id_hi=mr->street.name.country | (mr->current_file << 16) | 0x10000000; + mr->item.id_lo=last-mr->m->file[mr->current_file]->begin; + mr->item.meth=&street_name_meth; + mr->item.map=NULL; + mr->item.priv_data=mr; + return &mr->item; + } + } + return NULL; +} + diff --git a/data/mg/town.c b/data/mg/town.c new file mode 100644 index 00000000..838bc2cc --- /dev/null +++ b/data/mg/town.c @@ -0,0 +1,261 @@ +#include +#include +#include "debug.h" +#include "mg.h" + + + +static void +town_coord_rewind(void *priv_data) +{ + struct town_priv *twn=priv_data; + + twn->cidx=0; +} + +static int +town_coord_get(void *priv_data, struct coord *c, int count) +{ + struct town_priv *twn=priv_data; + + if (twn->cidx || count <= 0) + return 0; + twn->cidx=1; + *c=twn->c; + return 1; +} + +static void +town_attr_rewind(void *priv_data) +{ + struct town_priv *twn=priv_data; + + twn->aidx=0; + twn->attr_next=attr_label; +} + +static int +town_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct town_priv *twn=priv_data; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (twn->attr_next != attr_none) { + if (town_attr_get(twn, twn->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=twn->district; + twn->attr_next=attr_town_name; + if (attr->u.str[0]) + return 1; + attr->u.str=twn->name; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_name: + attr->u.str=twn->name; + twn->attr_next=attr_town_postal; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_postal: + attr->u.str=twn->postal_code1; + twn->attr_next=attr_district_name; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_district_name: + attr->u.str=twn->district; + twn->attr_next=attr_debug; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_streets_item: + twn->town_attr_item.type=type_town_streets; + twn->town_attr_item.id_hi=twn->country | (file_town_twn << 16) | 0x10000000; + twn->town_attr_item.id_lo=twn->street_assoc; + attr->u.item=&twn->town_attr_item; + twn->attr_next=attr_debug; + return 1; + case attr_debug: + sprintf(twn->debug, "order %d\nsize %d\nstreet_assoc 0x%x", twn->order, twn->size, twn->street_assoc); + attr->u.str=twn->debug; + twn->attr_next=attr_none; + return 1; + default: + g_assert(1==0); + return 0; + } + return 1; +} + +static struct item_methods town_meth = { + town_coord_rewind, + town_coord_get, + town_attr_rewind, + town_attr_get, +}; + +static void +town_get_data(struct town_priv *twn, unsigned char **p) +{ + twn->id=get_u32_unal(p); + twn->c.x=get_u32_unal(p); + twn->c.y=get_u32_unal(p); + twn->name=get_string(p); + twn->district=get_string(p); + twn->postal_code1=get_string(p); + twn->order=get_u8(p); /* 1-15 (19) */ + twn->country=get_u16(p); + twn->type=get_u8(p); + twn->unknown2=get_u32_unal(p); + twn->size=get_u8(p); + twn->street_assoc=get_u32_unal(p); + twn->unknown3=get_u8(p); + twn->postal_code2=get_string(p); + twn->unknown4=get_u32_unal(p); +#if 0 + 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); +#endif +} + /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */ +static unsigned char limit[]={0,1,2,2,4,6,8,10,11,13,14,14,14,20,20,20,20,20,20}; + +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}; +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}; +int +town_get(struct map_rect_priv *mr, struct town_priv *twn, struct item *item) +{ + int size; + for (;;) { + if (mr->b.p >= mr->b.end) + return 0; + town_get_data(twn, &mr->b.p); + twn->cidx=0; + twn->aidx=0; + twn->attr_next=attr_label; + if (! mr->cur_sel || (twn->order <= limit[mr->cur_sel->order[layer_town]] && coord_rect_contains(&mr->cur_sel->rect,&twn->c))) { + switch(twn->type) { + case 1: + size=twn->size; + if (size >= sizeof(town_item)/sizeof(enum item_type)) + size=sizeof(town_item)/sizeof(enum item_type)-1; + item->type=town_item[size]; + break; + case 3: + size=twn->size; + if (size == 6 && twn->order < 14) + size++; + if (size == 5 && twn->order < 14) + size+=2; + if (size >= sizeof(district_item)/sizeof(enum item_type)) + size=sizeof(district_item)/sizeof(enum item_type)-1; + item->type=district_item[size]; + break; + case 4: + item->type=type_port_label; + break; + case 9: + item->type=type_highway_exit_label; + break; + default: + 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); + item->type=type_town_label; + } + item->id_hi=twn->country | (mr->current_file << 16); + item->id_lo=twn->id; + item->priv_data=twn; + item->meth=&town_meth; + return 1; + } + } +} + +int +town_get_byid(struct map_rect_priv *mr, struct town_priv *twn, int id_hi, int id_lo, struct item *item) +{ + int country=id_hi & 0xffff; + int res; + if (!tree_search_hv(mr->m->dirname, "town", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res)) + return 0; + block_get_byindex(mr->m->file[mr->current_file], res >> 16, &mr->b); + mr->b.p=mr->b.block_start+(res & 0xffff); + return town_get(mr, twn, item); +} + +static int +town_search_compare(unsigned char **p, struct map_rect_priv *mr) +{ + int country, d; + char *name; + + country=get_u16(p); + dbg(1,"country 0x%x ", country); + name=get_string(p); + dbg(1,"name '%s' ",name); + mr->search_blk_count=get_u32(p); + mr->search_blk_off=(struct block_offset *)(*p); + dbg(1,"len %d ", mr->search_blk_count); + (*p)+=mr->search_blk_count*4; + d=mr->search_country-country; + if (!d) { + if (mr->search_partial) + d=strncasecmp(mr->search_str, name, strlen(mr->search_str)); + else + d=strcasecmp(mr->search_str, name); + } + dbg(1,"%d \n",d); + return d; + +} + + + +struct item * +town_search_get_item(struct map_rect_priv *mr) +{ + int dir=1,leaf; + + if (! mr->search_blk_count) { + if (mr->search_partial) { + dbg(1,"partial 0x%x '%s' ***\n", mr->search_country, mr->search_str); + if (! mr->search_linear) { + while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) { + dir=town_search_compare(&mr->search_p, mr); + if (! dir && leaf) { + mr->search_linear=1; + mr->search_p=NULL; + break; + } + } + if (! mr->search_linear) + return NULL; + } + if (! tree_search_next_lin(&mr->ts, &mr->search_p)) + return NULL; + if (town_search_compare(&mr->search_p, mr)) + return NULL; + dbg(1,"found %d blocks\n",mr->search_blk_count); + } else { + #if 0 + dbg(1,"full 0x%x '%s' ***\n", country, search); + while (tree_search_next(&ts, &p, dir) != -1) { + ps=p; + printf("0x%x ",p-ts.f->begin); + dir=show_town2(&p, country, search, 0); + if (! dir) { + printf("*** found full: "); + show_town2(&ps, country, search, 0); + break; + } + } + #endif + return NULL; + } + } + if (! mr->search_blk_count) + return NULL; + dbg(1,"block 0x%x offset 0x%x\n", mr->search_blk_off->block, mr->search_blk_off->offset); + block_get_byindex(mr->m->file[mr->current_file], mr->search_blk_off->block, &mr->b); + mr->b.p=mr->b.block_start+mr->search_blk_off->offset; + town_get(mr, &mr->town, &mr->item); + mr->search_blk_off++; + mr->search_blk_count--; + return &mr->item; +} diff --git a/data/mg/tree.c b/data/mg/tree.c new file mode 100644 index 00000000..aedce721 --- /dev/null +++ b/data/mg/tree.c @@ -0,0 +1,232 @@ +#include +#include "debug.h" +#include "mg.h" + +struct tree_hdr { + unsigned int addr; + unsigned int size; + unsigned int low; +}; + +struct tree_hdr_h { + unsigned int addr; + unsigned int size; +}; + +struct tree_leaf_h { + unsigned int lower; + unsigned int higher; + unsigned int match; + unsigned int value; +}; + + +struct tree_hdr_v { + unsigned int count; + unsigned int next; + unsigned int unknown; +}; + +struct tree_leaf_v { + unsigned char key; + int value; +} __attribute__((packed)); + +static int +tree_search_h(struct file *file, unsigned int search) +{ + unsigned char *p=file->begin,*end; + int last,i=0,value,lower; + struct tree_hdr_h *thdr; + struct tree_leaf_h *tleaf; + + dbg(1,"enter\n"); + while (i++ < 1000) { + thdr=(struct tree_hdr_h *)p; + p+=sizeof(*thdr); + end=p+thdr->size; + dbg(1,"@0x%x\n", p-file->begin); + last=0; + while (p < end) { + tleaf=(struct tree_leaf_h *)p; + p+=sizeof(*tleaf); + dbg(1,"low:0x%x high:0x%x match:0x%x val:0x%x search:0x%x\n", tleaf->lower, tleaf->higher, tleaf->match, tleaf->value, search); + value=tleaf->value; + if (value == search) + return tleaf->match; + if (value > search) { + dbg(1,"lower\n"); + lower=tleaf->lower; + if (lower) + last=lower; + break; + } + last=tleaf->higher; + } + if (! last || last == -1) + return 0; + p=file->begin+last; + } + return 0; +} + +static int +tree_search_v(struct file *file, int offset, int search) +{ + unsigned char *p=file->begin+offset; + int i=0,count,next; + struct tree_hdr_v *thdr; + struct tree_leaf_v *tleaf; + while (i++ < 1000) { + thdr=(struct tree_hdr_v *)p; + p+=sizeof(*thdr); + count=L(thdr->count); + dbg(1,"offset=0x%x count=0x%x\n", p-file->begin, count); + while (count--) { + tleaf=(struct tree_leaf_v *)p; + p+=sizeof(*tleaf); + dbg(1,"0x%x 0x%x\n", tleaf->key, search); + if (tleaf->key == search) + return L(tleaf->value); + } + next=L(thdr->next); + if (! next) + break; + p=file->begin+next; + } + return 0; +} + +int +tree_search_hv(char *dirname, char *filename, unsigned int search_h, unsigned int search_v, int *result) +{ + struct file *f_idx_h, *f_idx_v; + char buffer[4096]; + int h,v; + + dbg(1,"enter(%s, %s, 0x%x, 0x%x, %p)\n",dirname, filename, search_h, search_v, result); + sprintf(buffer, "%s/%s.h1", dirname, filename); + f_idx_h=file_create_caseinsensitive(buffer); + sprintf(buffer, "%s/%s.v1", dirname, filename); + f_idx_v=file_create_caseinsensitive(buffer); + dbg(1,"%p %p\n", f_idx_h, f_idx_v); + if ((h=tree_search_h(f_idx_h, search_h))) { + dbg(1,"h=0x%x\n", h); + if ((v=tree_search_v(f_idx_v, h, search_v))) { + dbg(1,"v=0x%x\n", v); + *result=v; + file_destroy(f_idx_v); + file_destroy(f_idx_h); + dbg(1,"return 1\n"); + return 1; + } + } + file_destroy(f_idx_v); + file_destroy(f_idx_h); + dbg(1,"return 0\n"); + return 0; +} + +static struct tree_search_node * +tree_search_enter(struct tree_search *ts, int offset) +{ + struct tree_search_node *tsn=&ts->nodes[++ts->curr_node]; + unsigned char *p; + p=ts->f->begin+offset; + tsn->hdr=(struct tree_hdr *)p; + tsn->p=p+sizeof(struct tree_hdr); + tsn->last=tsn->p; + tsn->end=p+tsn->hdr->size; + tsn->low=tsn->hdr->low; + tsn->high=tsn->hdr->low; + dbg(1,"pos 0x%x addr 0x%x size 0x%x low 0x%x end 0x%x\n", p-ts->f->begin, tsn->hdr->addr, tsn->hdr->size, tsn->hdr->low, tsn->end-ts->f->begin); + return tsn; +} + +int tree_search_next(struct tree_search *ts, unsigned char **p, int dir) +{ + struct tree_search_node *tsn=&ts->nodes[ts->curr_node]; + + if (! *p) + *p=tsn->p; + dbg(1,"next *p=%p dir=%d\n", *p, dir); + dbg(1,"low1=0x%x high1=0x%x\n", tsn->low, tsn->high); + if (dir <= 0) { + dbg(1,"down 0x%x\n", tsn->low); + if (tsn->low != 0xffffffff) { + tsn=tree_search_enter(ts, tsn->low); + *p=tsn->p; + tsn->high=get_u32(p); + ts->last_node=ts->curr_node; + dbg(1,"saving last2 %d 0x%x\n", ts->curr_node, tsn->last-ts->f->begin); + dbg(1,"high2=0x%x\n", tsn->high); + return 0; + } + return -1; + } + tsn->low=tsn->high; + tsn->last=*p; + tsn->high=get_u32(p); + dbg(1,"saving last3 %d %p\n", ts->curr_node, tsn->last); + if (*p < tsn->end) + return (tsn->low == 0xffffffff ? 1 : 0); + dbg(1,"end reached\n"); + if (tsn->low != 0xffffffff) { + dbg(1,"low 0x%x\n", tsn->low); + tsn=tree_search_enter(ts, tsn->low); + *p=tsn->p; + tsn->high=get_u32(p); + ts->last_node=ts->curr_node; + dbg(1,"saving last4 %d 0x%x\n", ts->curr_node, tsn->last-ts->f->begin); + dbg(1,"high4=0x%x\n", tsn->high); + return 0; + } + return -1; +} + +int tree_search_next_lin(struct tree_search *ts, unsigned char **p) +{ + struct tree_search_node *tsn=&ts->nodes[ts->curr_node]; + int high; + + dbg(1,"pos=%d 0x%x\n", ts->curr_node, *p-ts->f->begin); + if (*p) + ts->nodes[ts->last_node].last=*p; + *p=tsn->last; + for (;;) { + high=get_u32(p); + if (*p < tsn->end) { + ts->last_node=ts->curr_node; + while (high != 0xffffffff) { + tsn=tree_search_enter(ts, high); + dbg(1,"reload %d\n",ts->curr_node); + high=tsn->low; + } + return 1; + } + dbg(1,"eon %d 0x%x 0x%x\n", ts->curr_node, *p-ts->f->begin, tsn->end-ts->f->begin); + if (! ts->curr_node) + break; + ts->curr_node--; + tsn=&ts->nodes[ts->curr_node]; + *p=tsn->last; + } + + return 0; +} + +void +tree_search_init(char *dirname, char *filename, struct tree_search *ts, int offset) +{ + char buffer[4096]; + sprintf(buffer, "%s/%s", dirname, filename); + ts->f=file_create_caseinsensitive(buffer); + ts->curr_node=-1; + tree_search_enter(ts, offset); +} + +void +tree_search_free(struct tree_search *ts) +{ + file_destroy(ts->f); +} diff --git a/data/textfile/Makefile.am b/data/textfile/Makefile.am new file mode 100644 index 00000000..92850723 --- /dev/null +++ b/data/textfile/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libdata_textfile.la +libdata_textfile_la_SOURCES = textfile.c textfile.h diff --git a/data/textfile/textfile.c b/data/textfile/textfile.c new file mode 100644 index 00000000..e5c3497a --- /dev/null +++ b/data/textfile/textfile.c @@ -0,0 +1,355 @@ +#include +#include +#include +#include +#include +#include "plugin.h" +#include "map.h" +#include "maptype.h" +#include "item.h" +#include "attr.h" +#include "coord.h" +#include "transform.h" +#include "projection.h" + +#include "textfile.h" + +static int map_id; + +static int +contains_coord(char *line) +{ + return g_ascii_isdigit(line[0]); +} + +static int debug=0; + +static int +get_tag(char *line, char *name, int *pos, char *ret, char *name_ret) +{ + int len=0,quoted; + char *p,*e,*n; + + if (debug) + printf("get_tag %s from %s\n", name, line); + if (name) + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=index(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (name == NULL || (e-n == len && !strncmp(n, name, len))) { + if (name_ret) { + len=e-n; + strncpy(name_ret, n, len); + name_ret[len]='\0'; + } + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(ret, e, len); + ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} + +static void +get_line(struct map_rect_priv *mr) +{ + if(mr->f) { + mr->pos=ftell(mr->f); + fgets(mr->line, SIZE, mr->f); + if (strlen(mr->line) >= SIZE-1) + printf("line too long\n"); + } +} + +static void +map_destroy_textfile(struct map_priv *m) +{ + if (debug) + printf("map_destroy_textfile\n"); + g_free(m); +} + +static void +textfile_coord_rewind(void *priv_data) +{ +} + +static void +parse_line(struct map_rect_priv *mr) +{ + int pos=0; + sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos); + if (pos < strlen(mr->line)) { + strcpy(mr->attrs, mr->line+pos); + } +} + +static int +textfile_coord_get(void *priv_data, struct coord *c, int count) +{ + double lat,lng; + struct coord_geo cg; + struct map_rect_priv *mr=priv_data; + int ret=0; + if (debug) + printf("textfile_coord_get %d\n",count); + while (count--) { + if (contains_coord(mr->line) && mr->f && !feof(mr->f) && (!mr->item.id_hi || !mr->eoc)) { + parse_line(mr); + lat=mr->lat; + lng=mr->lng; + cg.lat=floor(lat/100); + lat-=cg.lat*100; + cg.lat+=lat/60; + + cg.lng=floor(lng/100); + lng-=cg.lng*100; + cg.lng+=lng/60; + + transform_from_geo(projection_mg, &cg, c); + c++; + ret++; + get_line(mr); + if (mr->item.id_hi) + mr->eoc=1; + } else { + break; + } + } + return ret; +} + +static void +textfile_attr_rewind(void *priv_data) +{ +} + +static void +textfile_encode_attr(char *attr_val, enum attr_type attr_type, struct attr *attr) +{ + if (attr_type >= attr_type_int_begin && attr_type <= attr_type_int_end) + attr->u.num=atoi(attr_val); + else + attr->u.str=attr_val; +} + +static int +textfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + char *str=NULL; + if (debug) + printf("textfile_attr_get mr=%p attrs='%s' ", mr, mr->attrs); + if (attr_type != mr->attr_last) { + if (debug) + printf("reset attr_pos\n"); + mr->attr_pos=0; + mr->attr_last=attr_type; + } + if (attr_type == attr_any) { + if (debug) + printf("attr_any"); + if (get_tag(mr->attrs,NULL,&mr->attr_pos,mr->attr, mr->attr_name)) { + attr_type=attr_from_name(mr->attr_name); + if (debug) + printf("found attr '%s' 0x%x\n", mr->attr_name, attr_type); + attr->type=attr_type; + textfile_encode_attr(mr->attr, attr_type, attr); + return 1; + } + } else { + str=attr_to_name(attr_type); + if (debug) + printf("attr='%s' ",str); + if (get_tag(mr->attrs,str,&mr->attr_pos,mr->attr, NULL)) { + textfile_encode_attr(mr->attr, attr_type, attr); + if (debug) + printf("found\n"); + return 1; + } + } + if (debug) + printf("not found\n"); + return 0; +} + +static struct item_methods methods_textfile = { + textfile_coord_rewind, + textfile_coord_get, + textfile_attr_rewind, + textfile_attr_get, +}; + +static struct map_rect_priv * +map_rect_new_textfile(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + + if (debug) + printf("map_rect_new_textfile\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + mr->sel=sel; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.meth=&methods_textfile; + mr->item.priv_data=mr; + mr->f=fopen(map->filename, "r"); + if(!mr->f) { + printf("map_rect_new_textfile unable to open textfile %s\n",map->filename); + } + get_line(mr); + return mr; +} + + +static void +map_rect_destroy_textfile(struct map_rect_priv *mr) +{ + if (mr->f) { + fclose(mr->f); + } + g_free(mr); +} + +static struct item * +map_rect_get_item_textfile(struct map_rect_priv *mr) +{ + char *p,type[SIZE]; + if (debug) + printf("map_rect_get_item_textfile id_hi=%d line=%s", mr->item.id_hi, mr->line); + if (!mr->f) { + return NULL; + } + for(;;) { + if (feof(mr->f)) { + if (debug) + printf("map_rect_get_item_textfile: eof\n"); + if (mr->item.id_hi) { + return NULL; + } + mr->item.id_hi++; + fseek(mr->f, 0, SEEK_SET); + get_line(mr); + } + if (mr->item.id_hi) { + if (!contains_coord(mr->line)) { + get_line(mr); + continue; + } + if ((p=index(mr->line,'\n'))) + *p='\0'; + if (debug) + printf("map_rect_get_item_textfile: point found\n"); + mr->attrs[0]='\0'; + parse_line(mr); + mr->eoc=0; + mr->item.id_lo=mr->pos; + } else { + if (contains_coord(mr->line)) { + get_line(mr); + continue; + } + if ((p=index(mr->line,'\n'))) + *p='\0'; + if (debug) + printf("map_rect_get_item_textfile: line found\n"); + if (! mr->line[0]) { + get_line(mr); + continue; + } + mr->item.id_lo=mr->pos; + strcpy(mr->attrs, mr->line); + get_line(mr); + if (debug) + printf("mr=%p attrs=%s\n", mr, mr->attrs); + } + if (debug) + printf("get_attrs %s\n", mr->attrs); + if (get_tag(mr->attrs,"type",NULL,type,NULL)) { + if (debug) + printf("type='%s'\n", type); + mr->item.type=item_from_name(type); + if (mr->item.type == type_none) + printf("Warning: type '%s' unknown\n", type); + } else { + get_line(mr); + continue; + } + mr->attr_last=attr_none; + if (debug) + printf("return attr='%s'\n", mr->attrs); + return &mr->item; + } +} + +static struct item * +map_rect_get_item_byid_textfile(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + fseek(mr->f, id_lo, SEEK_SET); + get_line(mr); + mr->item.id_hi=id_hi; + return map_rect_get_item_textfile(mr); +} + +static struct map_methods map_methods_textfile = { + map_destroy_textfile, + map_rect_new_textfile, + map_rect_destroy_textfile, + map_rect_get_item_textfile, + map_rect_get_item_byid_textfile, +}; + +static struct map_priv * +map_new_textfile(struct map_methods *meth, char *filename, char **charset, enum projection *pro) +{ + struct map_priv *m; + if (debug) + printf("map_new_textfile %s\n",filename); + *meth=map_methods_textfile; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->filename=g_strdup(filename); + return m; +} + +void +plugin_init(void) +{ + if (debug) + printf("textfile: plugin_init\n"); + plugin_register_map_type("textfile", map_new_textfile); +} + diff --git a/data/textfile/textfile.h b/data/textfile/textfile.h new file mode 100644 index 00000000..980c95d6 --- /dev/null +++ b/data/textfile/textfile.h @@ -0,0 +1,28 @@ +#include +#include "attr.h" +#include "coord.h" +struct map_priv { + int id; + char *filename; +}; + +#define SIZE 512 + +struct map_rect_priv { + struct map_selection *sel; + + FILE *f; + long pos; + char line[SIZE]; + int attr_pos; + enum attr_type attr_last; + char attrs[SIZE]; + char attr[SIZE]; + char attr_name[SIZE]; + double lat,lng; + char lat_c,lng_c; + int eoc; + struct map_priv *m; + struct item item; +}; + diff --git a/data_window.c b/data_window.c index 1eff89dc..99889488 100644 --- a/data_window.c +++ b/data_window.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "param.h" #include "data_window.h" @@ -36,7 +37,6 @@ data_window_begin(struct data_window *win) } } -#if 0 static void click_column(GtkCList *clist, int column) { @@ -52,19 +52,30 @@ click_column(GtkCList *clist, int column) gtk_clist_sort(clist); } + GValue value; static void -select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct data_window *win) +select_row(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, struct data_window *win) { int i; if (win->callback) { + printf("callback\n"); + char *cols[20]; - for (i=0;i<20;i++) { - gtk_clist_get_text(clist, row, i, &cols[i]); + GtkTreeIter iter; + GtkTreeModel *model; + + model=gtk_tree_view_get_model(tree); + gtk_tree_model_get_iter(model, &iter, path); + + for (i=0;icallback(win, cols); } } -#endif void data_window_add(struct data_window *win, struct param_list *param, int count) @@ -87,6 +98,10 @@ data_window_add(struct data_window *win, struct param_list *param, int count) gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (win->treeview),-1,param[i].name, cell,"text",i, NULL); } +#if 0 + g_signal_connect(G_OBJECT(win->treeview), "click-column", G_CALLBACK(click_column), NULL); +#endif + g_signal_connect(G_OBJECT(win->treeview), "row-activated", G_CALLBACK(select_row), win); } /* find data storage and create a new one if none is there */ @@ -106,19 +121,9 @@ data_window_add(struct data_window *win, struct param_list *param, int count) gtk_list_store_set(liststore,&iter,i,utf8,-1); } -#if 0 - g_signal_connect(G_OBJECT(win->clist), "click-column", G_CALLBACK(click_column), NULL); - g_signal_connect(G_OBJECT(win->clist), "select-row", G_CALLBACK(select_row), win); -#endif } void data_window_end(struct data_window *win) { -#if 0 - if (win && win->treeview) { - gtk_clist_thaw(GTK_CLIST(win->clist)); - gtk_clist_columns_autosize (GTK_CLIST(win->clist)); - } -#endif } diff --git a/debug.c b/debug.c index 5fbe6035..62a93350 100644 --- a/debug.c +++ b/debug.c @@ -1,11 +1,16 @@ #include +#include #include #include +#include #include +#include #include "file.h" #include "debug.h" +int debug_level=0; +static GHashTable *debug_hash; static void sigsegv(int sig) { @@ -26,5 +31,52 @@ static void sigsegv(int sig) void debug_init(void) { +#if 0 signal(SIGSEGV, sigsegv); +#endif + debug_hash=g_hash_table_new(g_str_hash, g_str_equal); +} + + +static void +debug_update_level(gpointer key, gpointer value, gpointer user_data) +{ + if (debug_level < (int) value) + debug_level=(int) value; +} + +void +debug_level_set(char *name, int level) +{ + debug_level=0; + g_hash_table_insert(debug_hash, name, (gpointer) level); + g_hash_table_foreach(debug_hash, debug_update_level, NULL); + debug_level_get(name); +} + +int +debug_level_get(const char *name) +{ + return (int)(g_hash_table_lookup(debug_hash, name)); +} + +void +debug_print(int level, const char *module, const char *function, const char *fmt, ...) +{ + va_list ap; + int module_len=strlen(module); + int function_len=strlen(function); + char buffer[module_len+function_len+3]; + + strcpy(buffer, module); + buffer[module_len]=':'; + strcpy(buffer+module_len+1, function); + + if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) { + strcpy(buffer+module_len+function_len+1, ":"); + printf("%s",buffer); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } } diff --git a/debug.h b/debug.h index fb9abbc9..69ced33a 100644 --- a/debug.h +++ b/debug.h @@ -1 +1,8 @@ +int debug_level; +#define dbg(level,fmt...) if (debug_level >= level) debug_print(level,MODULE,__PRETTY_FUNCTION__,fmt) + +/* prototypes */ void debug_init(void); +void debug_level_set(char *name, int level); +int debug_level_get(const char *name); +void debug_print(int level, const char *module, const char *function, const char *fmt, ...); diff --git a/destination.h b/destination.h index 68530f8f..263cc920 100644 --- a/destination.h +++ b/destination.h @@ -1,11 +1,4 @@ -enum destination_type { - destination_type_town=4, - destination_type_poly=6, - destination_type_street=8, - destination_type_house=12, - destination_type_map_point=16, - destination_type_bookmark=128, -}; - -int destination_address(struct container *co); -int destination_set(struct container *co, enum destination_type type, char *text, struct coord *c); +/* prototypes */ +struct navit; +int destination_address(struct navit *nav); +/* end of prototypes */ diff --git a/display.h b/display.h deleted file mode 100644 index 952381f2..00000000 --- a/display.h +++ /dev/null @@ -1,24 +0,0 @@ -#include "point.h" - -struct popup_item; -struct graphics; -struct graphics_gc; -struct graphics_font; - -struct display_list { - struct display_list *next; - void *data; - int type; - int attr; - char *label; - int count; - void (*info)(struct display_list *list, struct popup_item **popup); - struct point p[0]; -}; -void *display_add(struct display_list **head, int type, int attr, char *label, int count, struct point *p, void (*info)(struct display_list *list, struct popup_item **popup), void *data, int data_size); - -void display_free(struct display_list **list, int count); - -void display_draw(struct display_list *list, struct graphics *gr, struct graphics_gc *gc_fill, struct graphics_gc *gc_line); -void display_find(struct point *pnt, struct display_list **in, int in_count, int maxdist, struct display_list **out, int out_count); -void display_labels(struct display_list *list, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font); diff --git a/fib-1.1/fib.c b/fib-1.1/fib.c index ace5d129..276b6bd3 100644 --- a/fib-1.1/fib.c +++ b/fib-1.1/fib.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: fib.c,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * $Id: fib.c,v 1.2 2007-07-04 22:44:39 martin-s Exp $ * */ @@ -261,6 +261,8 @@ fh_replacekey(struct fibheap *h, struct fibheap_el *x, int key) return ret; } +#include + void * fh_replacekeydata(struct fibheap *h, struct fibheap_el *x, int key, void *data) { @@ -277,6 +279,7 @@ fh_replacekeydata(struct fibheap *h, struct fibheap_el *x, int key, void *data) * requires O(lgn) time. */ if ((r = fh_comparedata(h, key, data, x)) > 0) { + printf("fh_comparedata r=%d key=%d data=%p\n", r, key, data); /* XXX - bad code! */ abort(); fh_deleteel(h, x); diff --git a/file.c b/file.c index b097261a..e0ca0c21 100644 --- a/file.c +++ b/file.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "file.h" @@ -41,6 +42,15 @@ file_create(char *name) return file; } +int +file_exists(char *name) +{ + struct stat buf; + if (! stat(name, &buf)) + return 1; + return 0; +} + void file_remap_readonly(struct file *f) { @@ -152,6 +162,38 @@ file_destroy(struct file *f) g_free(f); } +struct file_wordexp { + wordexp_t we; +}; + +struct file_wordexp * +file_wordexp_new(char *pattern) +{ + struct file_wordexp *ret=g_new(struct file_wordexp, 1); + wordexp(pattern, &ret->we, 0); + return ret; +} + +int +file_wordexp_get_count(struct file_wordexp *wexp) +{ + return wexp->we.we_wordc; +} + +char ** +file_wordexp_get_array(struct file_wordexp *wexp) +{ + return wexp->we.we_wordv; +} + +void +file_wordexp_destroy(struct file_wordexp *wexp) +{ + wordfree(&wexp->we); + g_free(wexp); +} + + int file_get_param(struct file *file, struct param_list *param, int count) { diff --git a/file.h b/file.h index f020ee47..615e22b7 100644 --- a/file.h +++ b/file.h @@ -10,14 +10,24 @@ struct file { struct file *next; }; +/* prototypes */ +struct file; +struct file_wordexp; +struct param_list; struct file *file_create(char *name); -void file_remap_readonly(struct file *file); +int file_exists(char *name); +void file_remap_readonly(struct file *f); void file_remap_readonly_all(void); -void file_unmap(struct file *file); +void file_unmap(struct file *f); void file_unmap_all(void); -struct file *file_create_caseinsensitive(char *name); -int file_get_param(struct file *file, struct param_list *param, int count); -void file_destroy(struct file *f); void *file_opendir(char *dir); char *file_readdir(void *hnd); void file_closedir(void *hnd); +struct file *file_create_caseinsensitive(char *name); +void file_destroy(struct file *f); +struct file_wordexp *file_wordexp_new(char *pattern); +int file_wordexp_get_count(struct file_wordexp *wexp); +char **file_wordexp_get_array(struct file_wordexp *wexp); +void file_wordexp_destroy(struct file_wordexp *wexp); +int file_get_param(struct file *file, struct param_list *param, int count); +/* end of prototypes */ diff --git a/graphics.c b/graphics.c index ad430c66..b9222990 100644 --- a/graphics.c +++ b/graphics.c @@ -1,416 +1,694 @@ #include +#include +#include +#include "debug.h" #include "string.h" #include "draw_info.h" #include "graphics.h" -#include "map_data.h" +#include "map.h" #include "coord.h" -#include "param.h" /* FIXME */ -#include "block.h" /* FIXME */ -#include "poly.h" -#include "town.h" -#include "street.h" #include "transform.h" -#include "container.h" +#include "projection.h" +#include "point.h" #include "plugin.h" -#include "display.h" -#include "data_window.h" #include "profile.h" +#include "mapset.h" +#include "route.h" -#define GC_BACKGROUND 0 -#define GC_WOOD 1 -#define GC_TOWN_FILL 2 -#define GC_TOWN_LINE 3 -#define GC_WATER_FILL 4 -#define GC_WATER_LINE 5 -#define GC_RAIL 6 -#define GC_TEXT_FG 7 -#define GC_TEXT_BG 8 -#define GC_BLACK 9 -#define GC_STREET_SMALL 10 -#define GC_STREET_SMALL_B 11 -#define GC_PARK 12 -#define GC_BUILDING 13 -#define GC_BUILDING_2 14 -#define GC_STREET_MID 15 -#define GC_STREET_MID_B 16 -#define GC_STREET_BIG 17 -#define GC_STREET_BIG_B 18 -#define GC_STREET_BIG2 19 -#define GC_STREET_BIG2_B 20 -#define GC_STREET_BIG2_L 21 -#define GC_STREET_NO_PASS 22 -#define GC_STREET_ROUTE 23 -#define GC_LAST 24 - - -int color[][3]={ - {0xffff, 0xefef, 0xb7b7}, - {0x8e8e, 0xc7c7, 0x8d8d}, - {0xffff, 0xc8c8, 0x9595}, - {0xebeb, 0xb4b4, 0x8181}, - {0x8282, 0xc8c8, 0xeaea}, - {0x5050, 0x9696, 0xb8b8}, - {0x8080, 0x8080, 0x8080}, - {0x0, 0x0, 0x0}, - {0xffff, 0xffff, 0xffff}, - {0x0, 0x0, 0x0}, - {0xffff, 0xffff, 0xffff}, - {0xe0e0, 0xe0e0, 0xe0e0}, - {0x7c7c, 0xc3c3, 0x3434}, - {0xe6e6, 0xe6e6, 0xe6e6}, - {0xffff, 0x6666, 0x6666}, - {0xffff, 0xffff, 0x0a0a}, - {0xe0e0, 0xe0e0, 0xe0e0}, - {0xffff, 0x0000, 0x0000}, - {0x0000, 0x0000, 0x0000}, - {0xffff, 0xffff, 0x0a0a}, - {0xffff, 0x0000, 0x0000}, - {0xffff, 0x0000, 0x0000}, - {0xe0e0, 0xe0e0, 0xffff}, - {0x0000, 0x0000, 0xa0a0}, +#include "layout.h" + +struct graphics +{ + struct graphics_priv *priv; + struct graphics_methods meth; + struct graphics_font *font[16]; + struct graphics_gc *gc[3]; + int ready; +}; + +struct displaylist { + GHashTable *dl; }; +struct graphics * +graphics_new(const char *type) +{ + struct graphics *this_; + struct graphics_priv * (*new)(struct graphics_methods *meth); + + new=plugin_get_graphics_type(type); + if (! new) + return NULL; + this_=g_new0(struct graphics, 1); + this_->priv=(*new)(&this_->meth); + return this_; +} + void -container_init_gra(struct container *co) +graphics_init(struct graphics *this_) { - struct graphics *gra=co->gra; - int i; + this_->gc[0]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 }); + graphics_gc_set_foreground(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 }); + this_->gc[1]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[1], &(struct color) { 0x0000, 0x0000, 0x0000 }); + graphics_gc_set_foreground(this_->gc[1], &(struct color) { 0xffff, 0xffff, 0xffff }); + this_->gc[2]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff }); + graphics_gc_set_foreground(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff }); + this_->meth.background_gc(this_->priv, this_->gc[0]->priv); +} - gra->font=g_new0(struct graphics_font *,3); - gra->font[0]=gra->font_new(gra,140); - gra->font[1]=gra->font_new(gra,200); - gra->font[2]=gra->font_new(gra,300); - gra->gc=g_new0(struct graphics_gc *, GC_LAST); - for (i = 0 ; i < GC_LAST ; i++) { - gra->gc[i]=gra->gc_new(gra); - gra->gc_set_background(gra->gc[i], color[0][0], color[0][1], color[0][2]); - gra->gc_set_foreground(gra->gc[i], color[i][0], color[i][1], color[i][2]); - } - gra->gc_set_background(gra->gc[GC_TEXT_BG], color[7][0], color[7][1], color[7][2]); +void * +graphics_get_data(struct graphics *this_, char *type) +{ + return (this_->meth.get_data(this_->priv, type)); } void -graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale) +graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data) { - struct transformation *t=co->trans; - if (x) *x=t->center.x; - if (y) *y=t->center.y; - if (scale) *scale=t->scale; + this_->meth.register_resize_callback(this_->priv, callback, data); } void -graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale) +graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data) { - struct transformation *t=co->trans; - if (x) t->center.x=*x; - if (y) t->center.y=*y; - if (scale) t->scale=*scale; - graphics_redraw(co); + this_->meth.register_button_callback(this_->priv, callback, data); } -static void -graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, - void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) +void +graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data) +{ + this_->meth.register_motion_callback(this_->priv, callback, data); +} + +struct graphics_font * +graphics_font_new(struct graphics *gra, int size) +{ + struct graphics_font *this_; + + this_=g_new0(struct graphics_font,1); + this_->priv=gra->meth.font_new(gra->priv, &this_->meth, size); + return this_; +} + +struct graphics_gc * +graphics_gc_new(struct graphics *gra) +{ + struct graphics_gc *this_; + + this_=g_new0(struct graphics_gc,1); + this_->priv=gra->meth.gc_new(gra->priv, &this_->meth); + return this_; +} + +void +graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c) +{ + gc->meth.gc_set_foreground(gc->priv, c); +} + +void +graphics_gc_set_background(struct graphics_gc *gc, struct color *c) +{ + gc->meth.gc_set_background(gc->priv, c); +} + +void +graphics_gc_set_linewidth(struct graphics_gc *gc, int width) +{ + gc->meth.gc_set_linewidth(gc->priv, width); +} + +struct graphics_image * +graphics_image_new(struct graphics *gra, char *path) +{ + struct graphics_image *this_; + + this_=g_new0(struct graphics_image,1); + this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height); + return this_; +} + +void +graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h) +{ + this_->meth.draw_restore(this_->priv, p, w, h); +} + +void +graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode) +{ + this_->meth.draw_mode(this_->priv, mode); +} + +void +graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count) { - struct draw_info info; - info.co=co; - info.display=display; - info.limit=limit; - map_data_foreach(mdata, file, co->trans, limit2, func, &info); + this_->meth.draw_lines(this_->priv, gc->priv, p, count); } void -graphics_redraw(struct container *co) +graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r) { - int scale=transform_get_scale(co->trans); - int i,slimit=255,tlimit=255,plimit=255; - int bw[4],w[4],t[4]; - struct display_list **disp=co->disp; - struct graphics *gra=co->gra; + this_->meth.draw_circle(this_->priv, gc->priv, p, r); +} + + +#include "attr.h" +#include "popup.h" +#include #if 0 - printf("scale=%d center=0x%lx,0x%lx mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y)); +static void +popup_view_html(struct popup_item *item, char *file) +{ + char command[1024]; + sprintf(command,"firefox %s", file); + system(command); +} + +static void +graphics_popup(struct display_list *list, struct popup_item **popup) +{ + struct item *item; + struct attr attr; + struct map_rect *mr; + struct coord c; + struct popup_item *curr_item,*last=NULL; + item=list->data; + mr=map_rect_new(item->map, NULL, NULL, 0); + printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + if (item) { + if (item_attr_get(item, attr_name, &attr)) { + curr_item=popup_item_new_text(popup,attr.u.str,1); + if (item_attr_get(item, attr_info_html, &attr)) { + popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str)); + } + if (item_attr_get(item, attr_price_html, &attr)) { + popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str)); + } + curr_item->submenu=last; + } + } + map_rect_destroy(mr); +} #endif - - display_free(co->disp, display_end); - transform_setup_source_rect(co->trans); +struct displayitem { + struct item item; + char *label; + int displayed; + int count; + struct point pnt[0]; +}; - gra->draw_mode(gra, draw_mode_begin); - for (i = 0 ; i < data_window_type_end; i++) { - data_window_begin(co->data_window[i]); +static int +xdisplay_free_list(gpointer key, gpointer value, gpointer user_data) +{ + GList *h, *l; + h=value; + l=h; + while (l) { +#if 1 + struct displayitem *di=l->data; + if (! di->displayed && di->item.type < type_line) + dbg(0,"warning: item '%s' not displayed\n", item_to_name(di->item.type)); +#endif + g_free(l->data); + l=g_list_next(l); } - gra->gc_set_linewidth(gra->gc[GC_RAIL], 3); - - bw[0]=0; - bw[1]=0; - bw[2]=0; - bw[3]=0; - w[0]=1; - w[1]=1; - w[2]=1; - w[3]=1; - t[0]=0xf; - t[1]=0xf; - t[2]=0xf; - t[3]=0xf; - if (scale < 2) { - tlimit=0xff; - slimit=0xff; - bw[0]=17; - w[0]=15; - bw[1]=19; - w[1]=17; - bw[2]=19; - w[2]=17; - bw[3]=21; - w[3]=17; - } else if (scale < 4) { - tlimit=0xff; - slimit=0xff; - bw[0]=11; - w[0]=9; - bw[1]=13; - w[1]=11; - bw[2]=13; - w[2]=11; - bw[3]=15; - w[3]=11; - } else if (scale < 8) { - tlimit=0xff; - slimit=0xff; - bw[0]=5; - w[0]=3; - bw[1]=11; - w[1]=9; - bw[2]=11; - w[2]=9; - bw[3]=13; - w[3]=9; - t[0]=0xa; - t[1]=0xf; - } else if (scale < 16) { - tlimit=0xff; - slimit=0xff; - bw[1]=9; - w[1]=7; - bw[2]=9; - w[2]=7; - bw[3]=11; - w[3]=7; - t[0]=0x9; - t[1]=0xe; - } else if (scale < 32) { - tlimit=0xff; - slimit=0xff; - bw[1]=5; - w[1]=3; - bw[2]=5; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x8; - t[1]=0xb; - } else if (scale < 64) { - tlimit=0xf; - slimit=0x6; - bw[1]=5; - w[1]=3; - bw[2]=5; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x8; - t[1]=0xa; - } else if (scale < 128) { - tlimit=0xc; - slimit=0x6; - plimit=0x1e; - w[1]=3; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x7; - t[1]=0xa; - } else if (scale < 256) { - tlimit=0xb; - slimit=0x5; - plimit=0x1a; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x7; - t[1]=0x8; - } else if (scale < 512) { - tlimit=0x9; - slimit=0x5; - plimit=0x14; - w[1]=0; - w[2]=1; - bw[3]=3; - w[3]=1; - t[0]=0x4; - t[1]=0x7; - } else if (scale < 1024) { - tlimit=0x8; - slimit=0x4; - slimit=0x4; - plimit=0x11; - w[1]=0; - w[2]=1; - bw[3]=3; - w[3]=1; - t[0]=0x3; - t[1]=0x5; - } else if (scale < 2048) { - tlimit=0x5; - slimit=0x3; - plimit=0x10; - bw[3]=3; - w[3]=1; - t[0]=0x2; - t[1]=0x4; - } else if (scale < 4096) { - bw[3]=3; - w[3]=1; - tlimit=0x4; - slimit=0x2; - plimit=0xf; - t[0]=0x2; - t[1]=0x3; - } else if (scale < 8192) { - bw[3]=3; - w[3]=1; - tlimit=0x3; - slimit=0x2; - plimit=0xf; - t[0]=0x1; - t[1]=0x2; - } else { - bw[3]=3; - w[3]=1; - tlimit=0x2; - slimit=0x2; - plimit=0xf; - t[0]=0x1; - t[1]=0x4; + g_list_free(h); + return TRUE; +} + +static void +xdisplay_free(GHashTable *display_list) +{ + g_hash_table_foreach_remove(display_list, xdisplay_free_list, NULL); +} + +void +display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label) +{ + struct displayitem *di; + int len; + GList *l; + char *p; + + len=sizeof(*di)+count*sizeof(*pnt); + if (label) + len+=strlen(label)+1; + + p=g_malloc(len); + + di=(struct displayitem *)p; + di->displayed=0; + p+=sizeof(*di)+count*sizeof(*pnt); + di->item=*item; + if (label) { + di->label=p; + strcpy(di->label, label); + } else + di->label=NULL; + di->count=count; + memcpy(di->pnt, pnt, count*sizeof(*pnt)); + + l=g_hash_table_lookup(displaylist->dl, GINT_TO_POINTER(item->type)); + l=g_list_prepend(l, di); + g_hash_table_insert(displaylist->dl, GINT_TO_POINTER(item->type), l); +} + + +static void +label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label) +{ + int i,x,y,tl; + double dx,dy,l; + struct point p_t; + + tl=strlen(label)*400; + for (i = 0 ; i < count-1 ; i++) { + dx=p[i+1].x-p[i].x; + dx*=100; + dy=p[i+1].y-p[i].y; + dy*=100; + l=(int)sqrt((float)(dx*dx+dy*dy)); + if (l > tl) { + x=p[i].x; + y=p[i].y; + if (dx < 0) { + dx=-dx; + dy=-dy; + x=p[i+1].x; + y=p[i+1].y; + } + x+=(l-tl)*dx/l/200; + y+=(l-tl)*dy/l/200; + x-=dy*45/l/10; + y+=dx*45/l/10; + p_t.x=x; + p_t.y=y; + #if 0 + printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l); + #endif + gra->meth.draw_text(gra->priv, fg->priv, bg->priv, font->priv, label, &p_t, dx*0x10000/l, dy*0x10000/l); + } } - gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL], w[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_NO_PASS], w[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL_B], bw[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_MID], w[1]); - gra->gc_set_linewidth(gra->gc[GC_STREET_MID_B], bw[1]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG], w[2]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG_B], bw[2]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2], w[3]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2_B], bw[3]); - gra->gc_set_linewidth(gra->gc[GC_STREET_ROUTE], w[3]+7+w[3]/2); - -#ifdef DEBUG - profile_timer(NULL); -#endif - graphics_draw(co->map_data, file_border_ply, co, display_rail, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_woodland_ply, co, display_wood, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_other_ply, co, display_other, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_town_twn, co, display_town, tlimit, 48, town_draw_block); - graphics_draw(co->map_data, file_water_ply, co, display_water, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_sea_ply, co, display_sea, plimit, 48, poly_draw_block); - /* todo height, tunnel, bridge, street_bti ??? */ -#if 0 - graphics_draw(co->map_data, file_height_ply, co, display_other1, plimit, 48, poly_draw_block); -#endif - if (scale < 256) { - graphics_draw(co->map_data, file_rail_ply, co, display_rail, plimit, 48, poly_draw_block); +} + + +static void +xdisplay_draw_elements(struct graphics *gra, GHashTable *display_list, struct itemtype *itm) +{ + struct element *e; + GList *l,*ls,*es,*types; + enum item_type type; + struct graphics_gc *gc; + struct graphics_image *img; + struct point p; + + es=itm->elements; + while (es) { + e=es->data; + types=itm->type; + while (types) { + type=GPOINTER_TO_INT(types->data); + ls=g_hash_table_lookup(display_list, GINT_TO_POINTER(type)); + l=ls; + gc=NULL; + img=NULL; + while (l) { + struct displayitem *di; + di=l->data; + di->displayed=1; + if (! gc) { + gc=graphics_gc_new(gra); + gc->meth.gc_set_foreground(gc->priv, &e->color); + } + switch (e->type) { + case element_polygon: + gra->meth.draw_polygon(gra->priv, gc->priv, di->pnt, di->count); + break; + case element_polyline: + if (e->u.polyline.width > 1) + gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width); + gra->meth.draw_lines(gra->priv, gc->priv, di->pnt, di->count); + break; + case element_circle: + if (e->u.circle.width > 1) + gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width); + gra->meth.draw_circle(gra->priv, gc->priv, &di->pnt[0], e->u.circle.radius); + p.x=di->pnt[0].x+3; + p.y=di->pnt[0].y+10; + if (! gra->font[e->label_size]) + gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20); + gra->meth.draw_text(gra->priv, gra->gc[2]->priv, gra->gc[1]->priv, gra->font[e->label_size]->priv, di->label, &p, 0x10000, 0); + break; + case element_label: + if (di->label) { + if (! gra->font[e->label_size]) + gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20); + label_line(gra, gra->gc[2], gra->gc[1], gra->font[e->label_size], di->pnt, di->count, di->label); + } + break; + case element_icon: + if (!img) { + img=graphics_image_new(gra, e->u.icon.src); + if (! img) + g_warning("failed to load icon '%s'\n", e->u.icon.src); + } + p.x=di->pnt[0].x - img->width/2; + p.y=di->pnt[0].y - img->height/2; + gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv); + break; + case element_image: + printf("image: '%s'\n", di->label); + gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, di->pnt, di->count, di->label); + break; + default: + printf("Unhandled element type %d\n", e->type); + + } + l=g_list_next(l); + } + types=g_list_next(types); + } + es=g_list_next(es); + } +} + +static void +xdisplay_draw_layer(GHashTable *display_list, struct graphics *gra, struct layer *lay, int order) +{ + GList *itms; + struct itemtype *itm; + + itms=lay->itemtypes; + while (itms) { + itm=itms->data; + if (order >= itm->zoom_min && order <= itm->zoom_max) + xdisplay_draw_elements(gra, display_list, itm); + itms=g_list_next(itms); } -#ifdef DEBUG - profile_timer("map_draw"); -#endif - plugin_call_draw(co); -#ifdef DEBUG - profile_timer("plugin"); -#endif +} -#if 0 - draw_poly(map, &co->d_tunnel_ply, "Tunnel", 0, 11, plimit); -#endif - graphics_draw(co->map_data, file_street_str, co, display_street, slimit, 7, street_draw_block); - - display_draw(disp[display_sea], gra, gra->gc[GC_WATER_FILL], NULL); - display_draw(disp[display_wood], gra, gra->gc[GC_WOOD], NULL); - display_draw(disp[display_other], gra, gra->gc[GC_TOWN_FILL], gra->gc[GC_TOWN_LINE]); - display_draw(disp[display_other1], gra, gra->gc[GC_BUILDING], NULL); - display_draw(disp[display_other2], gra, gra->gc[GC_BUILDING_2], NULL); - display_draw(disp[display_other3], gra, gra->gc[GC_PARK], NULL); - display_draw(disp[display_water], gra, gra->gc[GC_WATER_FILL], gra->gc[GC_WATER_LINE]); - display_draw(disp[display_rail], gra, gra->gc[GC_RAIL], NULL); - street_route_draw(co); - display_draw(disp[display_street_route], gra, gra->gc[GC_STREET_ROUTE], NULL); - if (bw[0]) { - display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_SMALL_B], NULL); - display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL_B], NULL); +static void +xdisplay_draw_layout(GHashTable *display_list, struct graphics *gra, struct layout *l, int order) +{ + GList *lays; + struct layer *lay; + + lays=l->layers; + while (lays) { + lay=lays->data; + xdisplay_draw_layer(display_list, gra, lay, order); + lays=g_list_next(lays); } - if (bw[1]) - display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID_B], NULL); - if (bw[2]) - display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG_B], NULL); - if (bw[3]) - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_B], NULL); - if (w[0]) { - display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_NO_PASS], NULL); - display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL], NULL); +} + +static void +xdisplay_draw(GHashTable *display_list, struct graphics *gra, GList *layouts, int order) +{ + struct layout *l; + + while (layouts) { + l=layouts->data; + xdisplay_draw_layout(display_list, gra, l, order); + return; + layouts=g_list_next(layouts); } - if (w[1]) - display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID], gra->gc[GC_BLACK]); - display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG], gra->gc[GC_BLACK]); - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2], gra->gc[GC_BLACK]); - if (w[3] > 1) - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_L], NULL); +} - display_draw(disp[display_poi], gra, gra->gc[GC_BLACK], NULL); +extern void *route_selection; +static void +do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapsets, int order, struct route *route) +{ + struct map_selection sel; + struct map_rect *mr; + struct item *item; + struct mapset *ms; + struct map *m; + enum projection pro; + struct mapset_handle *h; + struct coord c; + int conv,count,max=16384; + struct point pnt[max]; + struct attr attr; + struct coord_rect r; -#ifdef DEBUG - profile_timer("display_draw"); -#endif - if (scale < 2) { - display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); - display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); + sel.next=NULL; + sel.order[layer_town]=1*order; + sel.order[layer_street]=order; + sel.order[layer_poly]=1*order; + ms=mapsets->data; + h=mapset_open(ms); + while ((m=mapset_next(h, 1))) { + pro=map_projection(m); + conv=map_requires_conversion(m); + transform_rect(t, pro, &sel.rect); + if (route_selection) + mr=map_rect_new(m, route_selection); + else + mr=map_rect_new(m, &sel); + while ((item=map_rect_get_item(mr))) { + if (item->type < type_line) { + item_coord_get(item, &c, 1); + if (!transform(t, pro, &c, &pnt[0])) + continue; + count=1; + } else { + count=0; + while (count < max) { + if (!item_coord_get(item, &c, 1)) + break; + if (! count) { + r.lu=c; + r.rl=c; + } else + coord_rect_extend(&r, &c); + transform(t, pro, &c, &pnt[count]); + if (! count || pnt[count].x != pnt[count-1].x || pnt[count].y != pnt[count-1].y) + count++; + + } + g_assert(count < max); + if (!transform_contains(t, pro, &r)) + continue; + if (route && route_contains(route, item)) { + struct item ritem; + ritem=*item; + ritem.type=type_street_route; + display_add(displaylist, &ritem, count, pnt, NULL); + } + } + if (!item_attr_get(item, attr_label, &attr)) + attr.u.str=NULL; + if (conv && attr.u.str && attr.u.str[0]) { + char *str=map_convert_string(m, attr.u.str); + display_add(displaylist, item, count, pnt, str); + map_convert_free(str); + } else + display_add(displaylist, item, count, pnt, attr.u.str); + } + map_rect_destroy(mr); } - else { - display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + mapset_close(h); +} + +int +graphics_ready(struct graphics *this_) +{ + return this_->ready; +} + +void +graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route) +{ + int order=transform_get_order(trans); + gra->meth.draw_mode(gra->priv, draw_mode_begin); + if (route) + route_draw(route, trans, displaylist); + xdisplay_draw(displaylist->dl, gra, layouts, order); +} + + +void +graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route) +{ + int order=transform_get_order(trans); + + dbg(1,"enter"); + +#if 0 + printf("scale=%d center=0x%x,0x%x mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y)); +#endif + + xdisplay_free(displaylist->dl); + dbg(0,"order=%d\n", order); + + +#if 0 + for (i = 0 ; i < data_window_type_end; i++) { + data_window_begin(co->data_window[i]); } - display_labels(disp[display_street2], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - display_labels(disp[display_street3], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - - for (i = display_town+t[1] ; i < display_town+0x10 ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - for (i = display_town+t[0] ; i < display_town+t[1] ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); - for (i = display_town ; i < display_town+t[0] ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[2]); - - for (i = display_town ; i < display_town+0x10 ; i++) - display_draw(disp[i], gra, gra->gc[GC_BLACK], NULL); - display_draw(disp[display_bti], gra, gra->gc[GC_BLACK], NULL); -#ifdef DEBUG - profile_timer("labels"); #endif - gra->draw_mode(gra, draw_mode_end); + profile(0,NULL); + do_draw(displaylist, trans, mapsets, order, route); + profile(1,"do_draw"); + graphics_displaylist_draw(gra, displaylist, trans, layouts, route); + profile(1,"xdisplay_draw"); + profile(0,"end"); + + gra->meth.draw_mode(gra->priv, draw_mode_end); +#if 0 for (i = 0 ; i < data_window_type_end; i++) { data_window_end(co->data_window[i]); } -#if 0 - map_scrollbars_update(map); #endif + gra->ready=1; +} + + +struct displaylist_handle { + GList *hl_head,*hl,*l; +}; + + +struct displaylist_handle * +graphics_displaylist_open(struct displaylist *displaylist) +{ + struct displaylist_handle *ret; + + ret=g_new0(struct displaylist_handle, 1); + ret->hl_head=ret->hl=g_hash_to_list(displaylist->dl); + + return ret; +} + +struct displayitem * +graphics_displaylist_next(struct displaylist_handle *dlh) +{ + struct displayitem *ret; + if (! dlh->l) { + if (!dlh->hl) + return NULL; + dlh->l=dlh->hl->data; + dlh->hl=g_list_next(dlh->hl); + } + ret=dlh->l->data; + dlh->l=g_list_next(dlh->l); + return ret; } void -graphics_resize(struct container *co, int w, int h) +graphics_displaylist_close(struct displaylist_handle *dlh) +{ + g_list_free(dlh->hl_head); + g_free(dlh); +} + +struct displaylist * +graphics_displaylist_new(void) +{ + struct displaylist *ret=g_new(struct displaylist, 1); + + ret->dl=g_hash_table_new(NULL,NULL); + + return ret; +} + +struct item * +graphics_displayitem_get_item(struct displayitem *di) { - co->trans->width=w; - co->trans->height=h; - graphics_redraw(co); + return &di->item; +} + +char * +graphics_displayitem_get_label(struct displayitem *di) +{ + return di->label; +} + +static int +within_dist_point(struct point *p0, struct point *p1, int dist) +{ + if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767) + return 0; + if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768) + return 0; + if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) { + return 1; + } + return 0; +} + +static int +within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist) +{ + int vx,vy,wx,wy; + int c1,c2; + struct point line_p; + + vx=line_p1->x-line_p0->x; + vy=line_p1->y-line_p0->y; + wx=p->x-line_p0->x; + wy=p->y-line_p0->y; + + c1=vx*wx+vy*wy; + if ( c1 <= 0 ) + return within_dist_point(p, line_p0, dist); + c2=vx*vx+vy*vy; + if ( c2 <= c1 ) + return within_dist_point(p, line_p1, dist); + + line_p.x=line_p0->x+vx*c1/c2; + line_p.y=line_p0->y+vy*c1/c2; + return within_dist_point(p, &line_p, dist); +} + +static int +within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close) +{ + int i; + for (i = 0 ; i < count-1 ; i++) { + if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) { + return 1; + } + } + if (close) + return (within_dist_line(p,line_pnt,line_pnt+count-1,dist)); + return 0; +} + +static int +within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist) +{ + int i, j, c = 0; + for (i = 0, j = count-1; i < count; j = i++) { + if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) || + ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) && + (p->x < (poly_pnt[j].x - poly_pnt[i].x) * (p->y - poly_pnt[i].y) / (poly_pnt[j].y - poly_pnt[i].y) + poly_pnt[i].x)) + c = !c; + } + if (! c) + return within_dist_polyline(p, poly_pnt, count, dist, 1); + return c; +} + +int +graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist) +{ + if (di->item.type < type_line) { + return within_dist_point(p, &di->pnt[0], dist); + } + if (di->item.type < type_area) { + return within_dist_polyline(p, di->pnt, di->count, dist, 0); + } + return within_dist_polygon(p, di->pnt, di->count, dist); } diff --git a/graphics.h b/graphics.h index a73f1e1e..f5145658 100644 --- a/graphics.h +++ b/graphics.h @@ -1,50 +1,125 @@ - +#ifdef __cplusplus +extern "C" { +#endif struct point; struct container; +struct color; +struct graphics; struct graphics_gc; struct graphics_font; -struct graphics_image_gra; +struct graphics_image; +struct transformation; +struct display_list; -struct graphics_image { - struct graphics_image *next; - struct graphics *gr; - char *name; - int height; - int width; - struct graphics_image_gra *gra; +enum draw_mode_num { + draw_mode_begin, draw_mode_end, draw_mode_cursor }; -void container_init_gra(struct container *co); +struct graphics_priv; +struct graphics_font_priv; +struct graphics_image_priv; +struct graphics_gc_priv; +struct graphics_font_methods; +struct graphics_gc_methods; +struct graphics_image_methods; -void graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale); -void graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale); -void graphics_resize(struct container *co, int w, int h); -void graphics_redraw(struct container *co); +struct graphics_methods { + void (*graphics_destroy)(struct graphics_priv *gr); + void (*draw_mode)(struct graphics_priv *gr, enum draw_mode_num mode); + void (*draw_lines)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count); + void (*draw_polygon)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count); + void (*draw_rectangle)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h); + void (*draw_circle)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r); + void (*draw_text)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy); + void (*draw_image)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img); + void (*draw_image_warp)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data); + void (*draw_restore)(struct graphics_priv *gr, struct point *p, int w, int h); + struct graphics_font_priv *(*font_new)(struct graphics_priv *gr, struct graphics_font_methods *meth, int size); + struct graphics_gc_priv *(*gc_new)(struct graphics_priv *gr, struct graphics_gc_methods *meth); + void (*background_gc)(struct graphics_priv *gr, struct graphics_gc_priv *gc); + struct graphics_priv *(*overlay_new)(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h); + struct graphics_image_priv *(*image_new)(struct graphics_priv *gr, struct graphics_image_methods *meth, char *path, int *w, int *h); + void *(*get_data)(struct graphics_priv *gr, char *type); + void (*register_resize_callback)(struct graphics_priv *gr, void (*callback)(void *data, int w, int h), void *data); + void (*register_button_callback)(struct graphics_priv *gr, void (*callback)(void *data, int pressed, int button, struct point *p), void *data); + void (*register_motion_callback)(struct graphics_priv *gr, void (*callback)(void *data, struct point *p), void *data); +}; -enum draw_mode_num { - draw_mode_begin, draw_mode_end, draw_mode_cursor + +struct graphics_font_methods { + void (*font_destroy)(struct graphics_font_priv *font); }; -struct graphics -{ - struct graphics_gra *gra; - struct graphics_font **font; - struct graphics_gc **gc; - - void (*draw_mode)(struct graphics *gr, enum draw_mode_num mode); - void (*draw_lines)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); - void (*draw_polygon)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); - void (*draw_rectangle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h); - void (*draw_circle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r); - void (*draw_text)(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy); - void (*draw_image)(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img); - void (*draw_restore)(struct graphics *gr, struct point *p, int w, int h); - - struct graphics_font *(*font_new)(struct graphics *gr, int size); - struct graphics_gc *(*gc_new)(struct graphics *gr); - void (*gc_set_linewidth)(struct graphics_gc *gc, int width); - void (*gc_set_foreground)(struct graphics_gc *gc, int r, int g, int b); - void (*gc_set_background)(struct graphics_gc *gc, int r, int g, int b); - struct graphics_image *(*image_new)(struct graphics *gr, char *path); - struct graphics *(*overlay_new)(struct graphics *gr, struct point *p, int w, int h); +struct graphics_font { + struct graphics_font_priv *priv; + struct graphics_font_methods meth; }; + +struct graphics_gc_methods { + void (*gc_destroy)(struct graphics_gc_priv *gc); + void (*gc_set_linewidth)(struct graphics_gc_priv *gc, int width); + void (*gc_set_dashes)(struct graphics_gc_priv *gc, unsigned char dash_list[], int n); + void (*gc_set_foreground)(struct graphics_gc_priv *gc, struct color *c); + void (*gc_set_background)(struct graphics_gc_priv *gc, struct color *c); +}; + +struct graphics_gc { + struct graphics_gc_priv *priv; + struct graphics_gc_methods meth; +}; + +struct graphics_image_methods { + void (*image_destroy)(struct graphics_image_priv *img); +}; + +struct graphics_image { + struct graphics_image_priv *priv; + struct graphics_image_methods meth; + int width; + int height; +}; + +/* prototypes */ +enum draw_mode_num; +struct color; +struct displayitem; +struct displaylist; +struct displaylist_handle; +struct graphics; +struct graphics_font; +struct graphics_gc; +struct graphics_image; +struct item; +struct point; +struct route; +struct transformation; +struct graphics *graphics_new(const char *type); +void graphics_init(struct graphics *this_); +void *graphics_get_data(struct graphics *this_, char *type); +void graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data); +void graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data); +void graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data); +struct graphics_font *graphics_font_new(struct graphics *gra, int size); +struct graphics_gc *graphics_gc_new(struct graphics *gra); +void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c); +void graphics_gc_set_background(struct graphics_gc *gc, struct color *c); +void graphics_gc_set_linewidth(struct graphics_gc *gc, int width); +struct graphics_image *graphics_image_new(struct graphics *gra, char *path); +void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h); +void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode); +void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count); +void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r); +void display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label); +int graphics_ready(struct graphics *this_); +void graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route); +struct displaylist_handle *graphics_displaylist_open(struct displaylist *displaylist); +struct displayitem *graphics_displaylist_next(struct displaylist_handle *dlh); +void graphics_displaylist_close(struct displaylist_handle *dlh); +struct displaylist *graphics_displaylist_new(void); +struct item *graphics_displayitem_get_item(struct displayitem *di); +char *graphics_displayitem_get_label(struct displayitem *di); +int graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/graphics/Makefile.am b/graphics/Makefile.am index b5787ee6..87d68de8 100644 --- a/graphics/Makefile.am +++ b/graphics/Makefile.am @@ -1 +1,7 @@ -SUBDIRS=gtk_drawing_area +SUBDIRS=null +if GRAPHICS_GTK_DRAWING_AREA + SUBDIRS+=gtk_drawing_area +endif +if GRAPHICS_OPENGL + SUBDIRS+=opengl +endif diff --git a/graphics/gtk_drawing_area/Makefile.am b/graphics/gtk_drawing_area/Makefile.am index 376b8884..5b8b9448 100644 --- a/graphics/gtk_drawing_area/Makefile.am +++ b/graphics/gtk_drawing_area/Makefile.am @@ -1,11 +1,4 @@ -AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. - -objdir=$(prefix) -obj_PROGRAMS=gtk_drawing_area.o -INSTALL_PROGRAM=/bin/true - -gtk_drawing_area_o_SOURCES=graphics_gtk_drawing_area.c - -gtk_drawing_area.o: $(gtk_drawing_area_o_OBJECTS) - ld -r -o gtk_drawing_area.o $(gtk_drawing_area_o_OBJECTS) +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @GTK2_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_gtk_drawing_area.la +libgraphics_gtk_drawing_area_la_SOURCES = graphics_gtk_drawing_area.c diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index a1d18c31..5fe34d4e 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -1,16 +1,18 @@ #define GDK_ENABLE_BROKEN +#include "config.h" #include #include #include FT_FREETYPE_H +#ifdef HAVE_IMLIB2 +#include +#endif +#include #include "point.h" -#include "coord.h" -#include "transform.h" #include "graphics.h" -#include "statusbar.h" -#include "popup.h" -#include "container.h" +#include "color.h" +#include "plugin.h" -struct graphics_gra { +struct graphics_priv { GdkEventButton button_event; int button_timeout; GtkWidget *widget; @@ -23,27 +25,40 @@ struct graphics_gra { int height; int library_init; int visible; - struct graphics_gra *parent; - struct graphics_gra *overlays; - struct graphics_gra *next; + struct graphics_priv *parent; + struct graphics_priv *overlays; + struct graphics_priv *next; + struct graphics_gc_priv *background_gc; enum draw_mode_num mode; + void (*resize_callback)(void *data, int w, int h); + void *resize_callback_data; + void (*motion_callback)(void *data, struct point *p); + void *motion_callback_data; + void (*button_callback)(void *data, int press, int button, struct point *p); + void *button_callback_data; }; -struct graphics_font { +struct graphics_font_priv { FT_Face face; }; -struct graphics_gc { +struct graphics_gc_priv { GdkGC *gc; - struct graphics_gra *gra; + struct graphics_priv *gr; }; -struct graphics_image_gra { +struct graphics_image_priv { GdkPixbuf *pixbuf; + int w; + int h; }; +static void +graphics_destroy(struct graphics_priv *gr) +{ +} -char *fontlist[]={ +static char *fontlist[]={ "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", @@ -52,20 +67,43 @@ char *fontlist[]={ NULL, }; +#if 0 +static char *fontlist_bd[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arialbd.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arialbd.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf", + "/usr/share/fonts/ttf/arialbd.ttf", + "/usr/share/fonts/corefonts/arialbd.ttf", + NULL, +}; +#endif + + + +static void font_destroy(struct graphics_font_priv *font) +{ + g_free(font); + /* TODO: free font->face */ +} -struct graphics * graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); +static struct graphics_font_methods font_methods = { + font_destroy +}; -static struct graphics_font *font_new(struct graphics *gr, int size) +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) { char **filename=fontlist; - struct graphics_font *font=g_new(struct graphics_font, 1); - if (!gr->gra->library_init) { - FT_Init_FreeType( &gr->gra->library ); - gr->gra->library_init=1; + struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1); + + *meth=font_methods; + + if (!gr->library_init) { + FT_Init_FreeType( &gr->library ); + gr->library_init=1; } while (*filename) { - if (!FT_New_Face( gr->gra->library, *filename, 0, &font->face )) + if (!FT_New_Face( gr->library, *filename, 0, &font->face )) break; filename++; } @@ -79,98 +117,121 @@ static struct graphics_font *font_new(struct graphics *gr, int size) return font; } -static struct graphics_gc *gc_new(struct graphics *gr) +static void +gc_destroy(struct graphics_gc_priv *gc) { - struct graphics_gc *gc=g_new(struct graphics_gc, 1); - - gc->gc=gdk_gc_new(gr->gra->widget->window); - gc->gra=gr->gra; - return gc; + g_object_unref(gc->gc); + g_free(gc); } static void -gc_set_linewidth(struct graphics_gc *gc, int w) +gc_set_linewidth(struct graphics_gc_priv *gc, int w) { gdk_gc_set_line_attributes(gc->gc, w, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); } static void -gc_set_color(struct graphics_gc *gc, int r, int g, int b, int fg) -{ - GdkColor c; - c.pixel=0; - c.red=r; - c.green=g; - c.blue=b; - gdk_colormap_alloc_color(gc->gra->colormap, &c, FALSE, TRUE); +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ + gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n); + gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND); +} + +static void +gc_set_color(struct graphics_gc_priv *gc, struct color *c, int fg) +{ + GdkColor gdkc; + gdkc.pixel=0; + gdkc.red=c->r; + gdkc.green=c->g; + gdkc.blue=c->b; + gdk_colormap_alloc_color(gc->gr->colormap, &gdkc, FALSE, TRUE); if (fg) - gdk_gc_set_foreground(gc->gc, &c); + gdk_gc_set_foreground(gc->gc, &gdkc); else - gdk_gc_set_background(gc->gc, &c); + gdk_gc_set_background(gc->gc, &gdkc); } static void -gc_set_foreground(struct graphics_gc *gc, int r, int g, int b) +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) { - gc_set_color(gc, r, g, b, 1); + gc_set_color(gc, c, 1); } static void -gc_set_background(struct graphics_gc *gc, int r, int g, int b) +gc_set_background(struct graphics_gc_priv *gc, struct color *c) { - gc_set_color(gc, r, g, b, 0); + gc_set_color(gc, c, 0); } -static struct graphics_image * -image_new(struct graphics *gr, char *name) +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1); + + *meth=gc_methods; + gc->gc=gdk_gc_new(gr->widget->window); + gc->gr=gr; + return gc; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) { GdkPixbuf *pixbuf; - struct graphics_image *ret; + struct graphics_image_priv *ret; pixbuf=gdk_pixbuf_new_from_file(name, NULL); if (! pixbuf) return NULL; - ret=g_new0(struct graphics_image, 1); - ret->gr=gr; - ret->name=strdup(name); - ret->gra=g_new0(struct graphics_image_gra, 1); - ret->gra->pixbuf=pixbuf; - ret->width=gdk_pixbuf_get_width(ret->gra->pixbuf); - ret->height=gdk_pixbuf_get_height(ret->gra->pixbuf); + ret=g_new0(struct graphics_image_priv, 1); + ret->pixbuf=pixbuf; + ret->w=gdk_pixbuf_get_width(pixbuf); + ret->h=gdk_pixbuf_get_height(pixbuf); + *w=ret->w; + *h=ret->h; return ret; } static void -draw_lines(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_lines(gr->gra->drawable, gc->gc, (GdkPoint *)p, count); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_lines(gr->gra->widget->window, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_lines(gr->drawable, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_lines(gr->widget->window, gc->gc, (GdkPoint *)p, count); } static void -draw_polygon(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_polygon(gr->gra->drawable, gc->gc, TRUE, (GdkPoint *)p, count); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_polygon(gr->gra->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_polygon(gr->drawable, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_polygon(gr->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); } static void -draw_rectangle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h) +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) { - gdk_draw_rectangle(gr->gra->drawable, gc->gc, TRUE, p->x, p->y, w, h); + gdk_draw_rectangle(gr->drawable, gc->gc, TRUE, p->x, p->y, w, h); } static void -draw_circle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r) +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_arc(gr->gra->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_arc(gr->gra->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_arc(gr->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_arc(gr->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); } @@ -234,7 +295,7 @@ display_text_render_shadow(struct text_glyph *g) } static struct text_render * -display_text_render(char *text, struct graphics_font *font, int dx, int dy, int x, int y) +display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y) { FT_GlyphSlot slot = font->face->glyph; // a small shortcut FT_Matrix matrix; @@ -294,7 +355,7 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int } static void -display_text_draw(struct text_render *text, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg) +display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg) { int i; struct text_glyph *g, **gp; @@ -305,7 +366,7 @@ display_text_draw(struct text_render *text, struct graphics *gr, struct graphics { g=*gp++; if (g->shadow && bg) - gdk_draw_image(gr->gra->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); + gdk_draw_image(gr->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); } gp=text->glyph; i=text->glyph_count; @@ -313,7 +374,7 @@ display_text_draw(struct text_render *text, struct graphics *gr, struct graphics { g=*gp++; if (g->w && g->h) - gdk_draw_gray_image(gr->gra->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); + gdk_draw_gray_image(gr->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); } } @@ -335,7 +396,7 @@ display_text_free(struct text_render *text) } static void -draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy) +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) { struct text_render *t; @@ -356,16 +417,38 @@ draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, s } static void -draw_image(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img) +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) { - printf("draw_image1 \n"); - gdk_draw_pixbuf(gr->gra->drawable, fg->gc, img->gra->pixbuf, 0, 0, p->x, p->y, - img->width, img->height, GDK_RGB_DITHER_NONE, 0, 0); - printf("draw_image1 end\n"); + gdk_draw_pixbuf(gr->drawable, fg->gc, img->pixbuf, 0, 0, p->x, p->y, + img->w, img->h, GDK_RGB_DITHER_NONE, 0, 0); } +#ifdef HAVE_IMLIB2 static void -overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int window) +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ + void *image; + int w,h; + printf("draw_image_warp data=%s\n", data); + image = imlib_load_image(data); + imlib_context_set_display(gdk_x11_drawable_get_xdisplay(gr->widget->window)); + imlib_context_set_colormap(gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(gr->widget))); + imlib_context_set_visual(gdk_x11_visual_get_xvisual(gtk_widget_get_visual(gr->widget))); + imlib_context_set_drawable(gdk_x11_drawable_get_xid(gr->drawable)); + imlib_context_set_image(image); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + if (count == 3) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, p[1].y-p[0].y, p[2].x-p[0].x, p[2].y-p[0].y); + } + if (count == 2) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, 0, 0, p[1].y-p[0].y); + } +} +#endif + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) { GdkPixbuf *pixbuf,*pixbuf2; GtkWidget *widget=parent->widget; @@ -413,44 +496,48 @@ overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int wind } static void -draw_restore(struct graphics *gr, struct point *p, int w, int h) +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) { - struct graphics_gra *gra=gr->gra; - GtkWidget *widget=gra->widget; + GtkWidget *widget=gr->widget; gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gra->drawable, + gr->drawable, p->x, p->y, p->x, p->y, w, h); } static void -draw_mode(struct graphics *gr, enum draw_mode_num mode) +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) { - struct graphics_gra *gra=gr->gra; - struct graphics_gra *overlay; - GtkWidget *widget=gra->widget; + gr->background_gc=gc; +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ + struct graphics_priv *overlay; + GtkWidget *widget=gr->widget; if (mode == draw_mode_begin) { - if (! gra->parent) - gdk_draw_rectangle(gr->gra->drawable, gr->gc[0]->gc, TRUE, 0, 0, gr->gra->width, gr->gra->height); + if (! gr->parent && gr->background_gc) + gdk_draw_rectangle(gr->drawable, gr->background_gc->gc, TRUE, 0, 0, gr->width, gr->height); } - if (mode == draw_mode_end && gr->gra->mode == draw_mode_begin) { - if (gra->parent) { - overlay_draw(gra->parent, gra, 1); + if (mode == draw_mode_end && gr->mode == draw_mode_begin) { + if (gr->parent) { + overlay_draw(gr->parent, gr, 1); } else { - overlay=gra->overlays; + overlay=gr->overlays; while (overlay) { - overlay_draw(gra, overlay, 0); + overlay_draw(gr, overlay, 0); overlay=overlay->next; } gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gra->drawable, - 0, 0, 0, 0, gra->width, gra->height); + gr->drawable, + 0, 0, 0, 0, gr->width, gr->height); } } - gr->gra->mode=mode; + gr->mode=mode; } /* Events */ @@ -458,9 +545,7 @@ draw_mode(struct graphics *gr, enum draw_mode_num mode) static gint configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) { - struct container *co=user_data; - struct graphics_gra *gra=co->gra->gra; - + struct graphics_priv *gra=user_data; if (! gra->visible) return TRUE; if (gra->drawable != NULL) { @@ -469,31 +554,32 @@ configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) gra->width=widget->allocation.width; gra->height=widget->allocation.height; gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1); - graphics_resize(co, gra->width, gra->height); + if (gra->resize_callback) + (*gra->resize_callback)(gra->resize_callback_data, gra->width, gra->height); return TRUE; } static gint expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) { - struct container *co=user_data; - struct graphics *gr=co->gra; + struct graphics_priv *gra=user_data; - gr->gra->visible=1; - if (! gr->gra->drawable) + gra->visible=1; + if (! gra->drawable) configure(widget, NULL, user_data); gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gr->gra->drawable, event->area.x, event->area.y, + gra->drawable, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); - return FALSE; } +#if 0 static gint button_timeout(gpointer user_data) { +#if 0 struct container *co=user_data; int x=co->gra->gra->button_event.x; int y=co->gra->gra->button_event.y; @@ -503,130 +589,186 @@ button_timeout(gpointer user_data) popup(co, x, y, button); return FALSE; +#endif } +#endif static gint button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) { - struct container *co=user_data; - int x=event->x; - int y=event->y; - int button=event->button; - int border=16; - long map_x,map_y,x_new,y_new; - unsigned long scale; - - if (button == 3) - popup(co, x, y, button); - if (button == 1) { - graphics_get_view(co, &map_x, &map_y, &scale); - if (x < border) { - x_new=map_x-co->trans->width*scale/32; - graphics_set_view(co, &x_new, NULL, NULL); - } else if (x >= co->trans->width-border) { - x_new=map_x+co->trans->width*scale/32; - graphics_set_view(co, &x_new, NULL, NULL); - } else if (y < border) { - y_new=map_y+co->trans->height*scale/32; - graphics_set_view(co, NULL, &y_new, NULL); - } else if (y >= co->trans->height-border) { - y_new=map_y-co->trans->height*scale/32; - graphics_set_view(co, NULL, &y_new, NULL); - } else { - co->gra->gra->button_event=*event; - co->gra->gra->button_timeout=g_timeout_add(500, button_timeout, co); - } - } + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 1, event->button, &p); return FALSE; } static gint button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) { - struct container *co=user_data; - if (co->gra->gra->button_timeout) - g_source_remove(co->gra->gra->button_timeout); + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 0, event->button, &p); + return FALSE; +} + +static gint +scroll(GtkWidget * widget, GdkEventScroll * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + int button; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) { + switch (event->direction) { + case GDK_SCROLL_UP: + button=4; + break; + case GDK_SCROLL_DOWN: + button=5; + break; + default: + button=-1; + break; + } + if (button != -1) { + (*this->button_callback)(this->button_callback_data, 1, button, &p); + (*this->button_callback)(this->button_callback_data, 0, button, &p); + } + } return FALSE; } static gint motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) { - struct container *co=user_data; + struct graphics_priv *this=user_data; struct point p; - if (co->statusbar && co->statusbar->statusbar_mouse_update) { - p.x=event->x; - p.y=event->y; - co->statusbar->statusbar_mouse_update(co->statusbar, co->trans, &p); - } + p.x=event->x; + p.y=event->y; + if (this->motion_callback) + (*this->motion_callback)(this->motion_callback_data, &p); return FALSE; } -static struct graphics *graphics_new(void); +static struct graphics_priv *graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth); -static struct graphics * -overlay_new(struct graphics *gr, struct point *p, int w, int h) +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) { - struct graphics *this=graphics_new(); - this->gra->drawable=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); - this->gra->colormap=gr->gra->colormap; - this->gra->widget=gr->gra->widget; - this->gra->p=*p; - this->gra->width=w; - this->gra->height=h; - this->gra->parent=gr->gra; - this->gra->background=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); - this->gra->next=gr->gra->overlays; - gr->gra->overlays=this->gra; + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->drawable=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->colormap=gr->colormap; + this->widget=gr->widget; + this->p=*p; + this->width=w; + this->height=h; + this->parent=gr; + this->background=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->next=gr->overlays; + gr->overlays=this; return this; } +static void * +get_data(struct graphics_priv *this, char *type) +{ + if (strcmp(type,"gtk_widget")) + return NULL; + return this->widget; +} +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ + this->resize_callback=callback; + this->resize_callback_data=data; +} -static struct graphics * -graphics_new(void) +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) { - struct graphics *this=g_new0(struct graphics,1); - this->draw_mode=draw_mode; - this->draw_lines=draw_lines; - this->draw_polygon=draw_polygon; - this->draw_rectangle=draw_rectangle; - this->draw_circle=draw_circle; - this->draw_text=draw_text; - this->draw_image=draw_image; - this->draw_restore=draw_restore; - this->gc_new=gc_new; - this->gc_set_linewidth=gc_set_linewidth; - this->gc_set_foreground=gc_set_foreground; - this->gc_set_background=gc_set_background; - this->font_new=font_new; - this->image_new=image_new; - this->overlay_new=overlay_new; - this->gra=g_new0(struct graphics_gra, 1); + this->motion_callback=callback; + this->motion_callback_data=data; +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ + this->button_callback=callback; + this->button_callback_data=data; +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, +#ifdef HAVE_IMLIB2 + draw_image_warp, +#else + NULL, +#endif + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth) +{ + struct graphics_priv *this=g_new0(struct graphics_priv,1); + *meth=graphics_methods; return this; } -struct graphics * -graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget) +static struct graphics_priv * +graphics_gtk_drawing_area_new(struct graphics_methods *meth) { GtkWidget *draw; draw=gtk_drawing_area_new(); - struct graphics *this=graphics_new(); - this->gra->widget=draw; - this->gra->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); - gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), co); - g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), co); + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->widget=draw; + + this->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); + gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_KEY_PRESS_MASK); + g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), this); + g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), this); #if 0 g_signal_connect(G_OBJECT(draw), "realize_event", G_CALLBACK(realize), co); #endif - g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), co); - g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), co); - g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), co); - *widget=draw; + g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), this); + g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), this); + g_signal_connect(G_OBJECT(draw), "scroll_event", G_CALLBACK(scroll), this); + g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), this); return this; } +void +plugin_init(void) +{ + plugin_register_graphics_type("gtk_drawing_area", graphics_gtk_drawing_area_new); +} diff --git a/graphics/null/Makefile.am b/graphics/null/Makefile.am new file mode 100644 index 00000000..8b22bdbc --- /dev/null +++ b/graphics/null/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_null.la +libgraphics_null_la_SOURCES = graphics_null.c diff --git a/graphics/null/graphics_null.c b/graphics/null/graphics_null.c new file mode 100644 index 00000000..2d8bb308 --- /dev/null +++ b/graphics/null/graphics_null.c @@ -0,0 +1,217 @@ +#include +#include "point.h" +#include "graphics.h" +#include "color.h" +#include "plugin.h" + +static int dummy; +static struct graphics_priv { + int dummy; +} graphics_priv; + +static struct graphics_font_priv { + int dummy; +} graphics_font_priv; + +static struct graphics_gc_priv { + int dummy; +} graphics_gc_priv; + +static struct graphics_image_priv { + int dummy; +} graphics_image_priv; + +static void +graphics_destroy(struct graphics_priv *gr) +{ +} + +static void font_destroy(struct graphics_font_priv *font) +{ + +} + +static struct graphics_font_methods font_methods = { + font_destroy +}; + +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) +{ + *meth=font_methods; + return &graphics_font_priv; +} + +static void +gc_destroy(struct graphics_gc_priv *gc) +{ +} + +static void +gc_set_linewidth(struct graphics_gc_priv *gc, int w) +{ +} + +static void +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ +} + +static void +gc_set_color(struct graphics_gc_priv *gc, struct color *c, int fg) +{ +} + +static void +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) +{ +} + +static void +gc_set_background(struct graphics_gc_priv *gc, struct color *c) +{ +} + +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + *meth=gc_methods; + return &graphics_gc_priv; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) +{ + return &graphics_image_priv; +} + +static void +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ +} + +static void +draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ +} + +static void +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) +{ +} + +static void +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) +{ +} + + +static void +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) +{ +} + +static void +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) +{ +} + +static void +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ +} + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) +{ +} + +static void +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) +{ +} + +static void +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) +{ +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ +} + +static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h); + +static void * +get_data(struct graphics_priv *this, char *type) +{ + return &dummy; +} + + + +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ +} + +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) +{ +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, + draw_image_warp, + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) +{ + *meth=graphics_methods; + return &graphics_priv; +} + + +static struct graphics_priv * +graphics_null_new(struct graphics_methods *meth) +{ + *meth=graphics_methods; + return &graphics_priv; +} + +void +plugin_init(void) +{ + plugin_register_graphics_type("null", graphics_null_new); +} diff --git a/graphics/opengl/Makefile.am b/graphics/opengl/Makefile.am new file mode 100644 index 00000000..99023e34 --- /dev/null +++ b/graphics/opengl/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @OPENGL_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_opengl.la +libgraphics_opengl_la_SOURCES = graphics_opengl.c diff --git a/graphics/opengl/graphics_opengl.c b/graphics/opengl/graphics_opengl.c new file mode 100644 index 00000000..81c8cd4d --- /dev/null +++ b/graphics/opengl/graphics_opengl.c @@ -0,0 +1,927 @@ +#include +#include +#include "config.h" +#if 0 +#include +#include FT_FREETYPE_H +#endif +#include +#include "point.h" +#include "graphics.h" +#include "color.h" +#include "plugin.h" + +struct graphics_priv { +#if 0 + GdkEventButton button_event; +#endif + int button_timeout; +#if 0 + GtkWidget *widget; + GdkDrawable *drawable; + GdkDrawable *background; + GdkColormap *colormap; + FT_Library library; +#endif + struct point p; + int width; + int height; + int library_init; + int visible; + struct graphics_priv *parent; + struct graphics_priv *overlays; + struct graphics_priv *next; + struct graphics_gc_priv *background_gc; + enum draw_mode_num mode; + void (*resize_callback)(void *data, int w, int h); + void *resize_callback_data; + void (*motion_callback)(void *data, struct point *p); + void *motion_callback_data; + void (*button_callback)(void *data, int press, int button, struct point *p); + void *button_callback_data; + GLuint DLid; +}; + +struct graphics_font_priv { +#if 0 + FT_Face face; +#endif +}; + +struct graphics_gc_priv { + struct graphics_priv *gr; + float fr,fg,fb,fa; + float br,bg,bb,ba; + int linewidth; +}; + +struct graphics_image_priv { +#if 0 + GdkPixbuf *pixbuf; +#endif + int w; + int h; +}; + +static void +graphics_destroy(struct graphics_priv *gr) +{ +} + +static char *fontlist[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", + "/usr/share/fonts/ttf/arial.ttf", + "/usr/share/fonts/corefonts/arial.ttf", + NULL, +}; + +#if 0 +static char *fontlist_bd[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arialbd.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arialbd.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf", + "/usr/share/fonts/ttf/arialbd.ttf", + "/usr/share/fonts/corefonts/arialbd.ttf", + NULL, +}; +#endif + + + +static void font_destroy(struct graphics_font_priv *font) +{ + g_free(font); + /* TODO: free font->face */ +} + +static struct graphics_font_methods font_methods = { + font_destroy +}; + +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) +{ +#if 0 + char **filename=fontlist; + struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1); + + *meth=font_methods; + + if (!gr->library_init) { + FT_Init_FreeType( &gr->library ); + gr->library_init=1; + } + + while (*filename) { + if (!FT_New_Face( gr->library, *filename, 0, &font->face )) + break; + filename++; + } + if (! *filename) { + g_warning("Failed to load font, no labelling"); + g_free(font); + return NULL; + } + FT_Set_Char_Size(font->face, 0, size, 300, 300); + FT_Select_Charmap(font->face, FT_ENCODING_UNICODE); + return font; +#endif + return NULL; +} + +static void +gc_destroy(struct graphics_gc_priv *gc) +{ + g_free(gc); +} + +static void +gc_set_linewidth(struct graphics_gc_priv *gc, int w) +{ + gc->linewidth=w; +} + +static void +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ +#if 0 + gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n); + gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND); +#endif +} + +static void +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) +{ + gc->fr=c->r/65535.0; + gc->fg=c->g/65535.0; + gc->fb=c->b/65535.0; + gc->fa=0; +} + +static void +gc_set_background(struct graphics_gc_priv *gc, struct color *c) +{ + gc->br=c->r/65535.0; + gc->bg=c->g/65535.0; + gc->bb=c->b/65535.0; + gc->ba=0; +} + +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1); + + *meth=gc_methods; + gc->gr=gr; + gc->linewidth=1; + return gc; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) +{ +#if 0 + GdkPixbuf *pixbuf; + struct graphics_image_priv *ret; + + pixbuf=gdk_pixbuf_new_from_file(name, NULL); + if (! pixbuf) + return NULL; + ret=g_new0(struct graphics_image_priv, 1); + ret->pixbuf=pixbuf; + ret->w=gdk_pixbuf_get_width(pixbuf); + ret->h=gdk_pixbuf_get_height(pixbuf); + *w=ret->w; + *h=ret->h; + return ret; +#endif + return NULL; +} + +static void +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ + // printf("draw_lines\n"); +// glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + int i; +/* + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_lines(gr->drawable, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_lines(gr->widget->window, gc->gc, (GdkPoint *)p, count); +*/ + /* + if(gr->mode == draw_mode_begin){ + printf("B"); + } else if (gr->mode == draw_mode_end){ + printf("E"); + } else { + printf("x"); + } +*/ + + for (i = 0 ; i < count-1 ; i++) { + +// glEnable( GL_POLYGON_SMOOTH ); +// glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); +// glEnable( GL_BLEND ); + + float dx=p[i+1].x-p[i].x; + float dy=p[i+1].y-p[i].y; + + float cx=(p[i+1].x+p[i].x)/2; + float cy=(p[i+1].y+p[i].y)/2; +// printf("(%lx,%lx) -> (%lx,%lx) : (%lx,%lx)\n",p[i].x,p[i].y,p[i+1].x,p[i+1].y,dx,dy); + + int w=round(sqrt(pow((dx),2)+pow((dy),2))); + + float angle=atan (dy/dx) * 180 / M_PI; + + glPushMatrix(); + glTranslatef(cx,cy,1); + // glColor4f( 0,0,0,1); + // glRasterPos2f( 1,1 ); + glRotatef(angle,0.0,0.0,1.0); + + glColor4f( gc->fr, gc->fg, gc->fb, gc->fa); + + int linewidth=gc->linewidth; + + glBegin( GL_POLYGON ); + glVertex2f( -w/2,-linewidth/2 ); + glVertex2f( -w/2-4,0 ); + glVertex2f( -w/2,+linewidth/2 ); + glVertex2f( +w/2,+linewidth/2 ); + glVertex2f( +w/2+4,0 ); + glVertex2f( +w/2,-linewidth/2 ); + glVertex2f( -w/2,+linewidth/2 ); + glEnd(); + + + // FIXME Roads label can maybe be drawn here, avoid the display_label loop, when playing with Z axis position. + /* + if(attr==1){ + glcRenderStyle(GLC_TEXTURE); + glColor3f(0., 0., 0.); + glScalef(12, 12, 0.); + glcRenderString(">>"); + } else if(attr==-1){ + glcRenderStyle(GLC_TEXTURE); + glColor3f(0., 0., 0.); + glScalef(12, 12, 0.); + glcRenderString("<<"); + } + + */ + glPopMatrix(); + } +// glDisable( GL_BLEND ); +// glDisable( GL_POLYGON_SMOOTH ); + +/* + if(label){ + if((strlen(label)*6)mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_polygon(gr->drawable, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_polygon(gr->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); +#endif + int i; + glColor4f( gc->fr, gc->fg, gc->fb, gc->fa); + glBegin( GL_POLYGON ); + for (i = 0 ; i < count ; i++) { + glVertex2i(p[i].x, p[i].y); + } + glVertex2i(p[0].x, p[0].y); + glEnd(); + +} + +static void +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) +{ +#if 0 + gdk_draw_rectangle(gr->drawable, gc->gc, TRUE, p->x, p->y, w, h); +#endif +} + +static void +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) +{ +#if 0 + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_arc(gr->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_arc(gr->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); +#endif +} + + +#if 0 +struct text_glyph { + int x,y,w,h; + GdkImage *shadow; + unsigned char pixmap[0]; +}; + +struct text_render { + int x1,y1; + int x2,y2; + int x3,y3; + int x4,y4; + int glyph_count; + struct text_glyph *glyph[0]; +}; + +static GdkImage * +display_text_render_shadow(struct text_glyph *g) +{ + int mask0, mask1, mask2, x, y, w=g->w, h=g->h; + int str=(g->w+9)/8; + unsigned char *shadow; + unsigned char *p, *pm=g->pixmap; + GdkImage *ret; + + shadow=malloc(str*(g->h+2)); /* do not use g_malloc() here */ + memset(shadow, 0, str*(g->h+2)); + for (y = 0 ; y < h ; y++) { + p=shadow+str*y; + mask0=0x4000; + mask1=0xe000; + mask2=0x4000; + for (x = 0 ; x < w ; x++) { + if (pm[x+y*w]) { + p[0]|=(mask0 >> 8); + if (mask0 & 0xff) + p[1]|=mask0; + + p[str]|=(mask1 >> 8); + if (mask1 & 0xff) + p[str+1]|=mask1; + p[str*2]|=(mask2 >> 8); + if (mask2 & 0xff) + p[str*2+1]|=mask2; + } + mask0 >>= 1; + mask1 >>= 1; + mask2 >>= 1; + if (!((mask0 >> 8) | (mask1 >> 8) | (mask2 >> 8))) { + mask0<<=8; + mask1<<=8; + mask2<<=8; + p++; + } + } + } + ret=gdk_image_new_bitmap(gdk_visual_get_system(), shadow, g->w+2, g->h+2); + return ret; +} + +static struct text_render * +display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y) +{ + + FT_GlyphSlot slot = font->face->glyph; // a small shortcut + FT_Matrix matrix; + FT_Vector pen; + FT_UInt glyph_index; + int n,len; + struct text_render *ret; + struct text_glyph *curr; + wchar_t wtext[1024]; + + len=mbstowcs(wtext, text, 1024); + ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); + ret->glyph_count=len; + + matrix.xx = dx; + matrix.xy = dy; + matrix.yx = -dy; + matrix.yy = dx; + + pen.x = 0 * 64; + pen.y = 0 * 64; + x <<= 6; + y <<= 6; + FT_Set_Transform( font->face, &matrix, &pen ); + + + + for ( n = 0; n < len; n++ ) + { + + glyph_index = FT_Get_Char_Index(font->face, wtext[n]); + FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT ); + FT_Render_Glyph(font->face->glyph, ft_render_mode_normal ); + + curr=g_malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch); + ret->glyph[n]=curr; + + curr->x=(x>>6)+slot->bitmap_left; + curr->y=(y>>6)-slot->bitmap_top; + curr->w=slot->bitmap.width; + curr->h=slot->bitmap.rows; + if (slot->bitmap.width && slot->bitmap.rows) { + memcpy(curr->pixmap, slot->bitmap.buffer, slot->bitmap.rows*slot->bitmap.pitch); + curr->shadow=display_text_render_shadow(curr); + } + else + curr->shadow=NULL; +#if 0 + printf("height=%d\n", slot->metrics.height); + printf("height2=%d\n", face->height); + printf("bbox %d %d %d %d\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax); +#endif + x += slot->advance.x; + y -= slot->advance.y; + } + return ret; +} + +static void +display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg) +{ +#if 0 + int i; + struct text_glyph *g, **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->shadow && bg) + gdk_draw_image(gr->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); + } + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->w && g->h) + gdk_draw_gray_image(gr->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); + } +#endif +} + +static void +display_text_free(struct text_render *text) +{ + int i; + struct text_glyph **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) { + if ((*gp)->shadow) { + g_object_unref((*gp)->shadow); + } + g_free(*gp++); + } + g_free(text); +} + +#endif + +void SDL_print(char * label,int x, int y, int angle){ + glPushMatrix(); +// glLoadIdentity(); + glcRenderStyle(GLC_TRIANGLE); + glColor3f(0., 0., 0.); + glTranslatef(x, y, -10); + glRotatef(180,1,0,0); + glRotatef(angle,0,0,1); + glScalef(14, 14, 0.); + glcRenderString(label); + glPopMatrix(); + +// glFlush(); + +} + +static void +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) +{ + printf("******************************************* %s\n",text); + SDL_print(text,p->x,p->y,0); + +#if 0 + struct text_render *t; + + if (! font) + return; + if (bg) { + gdk_gc_set_function(fg->gc, GDK_AND_INVERT); + gdk_gc_set_function(bg->gc, GDK_OR); + } + + t=display_text_render(text, font, dx, dy, p->x, p->y); + display_text_draw(t, gr, fg, bg); + display_text_free(t); + if (bg) { + gdk_gc_set_function(fg->gc, GDK_COPY); + gdk_gc_set_function(bg->gc, GDK_COPY); + } +#endif +} + +static void +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) +{ +#if 0 + gdk_draw_pixbuf(gr->drawable, fg->gc, img->pixbuf, 0, 0, p->x, p->y, + img->w, img->h, GDK_RGB_DITHER_NONE, 0, 0); +#endif +} + +#ifdef HAVE_IMLIB2 +static void +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ +#if 0 + void *image; + int w,h; + printf("draw_image_warp data=%s\n", data); + image = imlib_load_image(data); + imlib_context_set_display(gdk_x11_drawable_get_xdisplay(gr->widget->window)); + imlib_context_set_colormap(gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(gr->widget))); + imlib_context_set_visual(gdk_x11_visual_get_xvisual(gtk_widget_get_visual(gr->widget))); + imlib_context_set_drawable(gdk_x11_drawable_get_xid(gr->drawable)); + imlib_context_set_image(image); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + if (count == 3) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, p[1].y-p[0].y, p[2].x-p[0].x, p[2].y-p[0].y); + } + if (count == 2) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, 0, 0, p[1].y-p[0].y); + } +#endif +} +#endif + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) +{ +#if 0 + GdkPixbuf *pixbuf,*pixbuf2; + GtkWidget *widget=parent->widget; + guchar *pixels1, *pixels2, *p1, *p2; + int x,y; + int rowstride1,rowstride2; + int n_channels1,n_channels2; + + if (! parent->drawable) + return; + + pixbuf=gdk_pixbuf_get_from_drawable(NULL, overlay->drawable, NULL, 0, 0, 0, 0, overlay->width, overlay->height); + pixbuf2=gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pixbuf), TRUE, gdk_pixbuf_get_bits_per_sample(pixbuf), + gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); + + rowstride1 = gdk_pixbuf_get_rowstride (pixbuf); + rowstride2 = gdk_pixbuf_get_rowstride (pixbuf2); + pixels1=gdk_pixbuf_get_pixels (pixbuf); + pixels2=gdk_pixbuf_get_pixels (pixbuf2); + n_channels1 = gdk_pixbuf_get_n_channels (pixbuf); + n_channels2 = gdk_pixbuf_get_n_channels (pixbuf2); + for (y = 0 ; y < overlay->height ; y++) { + for (x = 0 ; x < overlay->width ; x++) { + p1 = pixels1 + y * rowstride1 + x * n_channels1; + p2 = pixels2 + y * rowstride2 + x * n_channels2; + p2[0]=p1[0]; + p2[1]=p1[1]; + p2[2]=p1[2]; + p2[3]=127; + } + } + if (window) + gdk_draw_pixmap(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], overlay->background, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height); + else + gdk_draw_pixmap(overlay->background, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, 0, 0, overlay->width, overlay->height); + gdk_draw_pixbuf(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixbuf2, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height, GDK_RGB_DITHER_NONE, 0, 0); + if (window) + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, overlay->p.x, overlay->p.y, overlay->width, overlay->height); +#if 0 + gdk_draw_pixmap(gr->gra->drawable, + gr->gra->widget->style->fg_gc[GTK_WIDGET_STATE(gr->gra->widget)], + img->gra->drawable, + 0, 0, p->x, p->y, img->gra->width, img->gra->height); +#endif +#endif +} + +static void +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) +{ +#if 0 + GtkWidget *widget=gr->widget; + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gr->drawable, + p->x, p->y, p->x, p->y, w, h); +#endif + +} + +static void +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) +{ + gr->background_gc=gc; +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ +#if 0 + if (mode == draw_mode_begin) + glNewList(gr->DLid,GL_COMPILE); + if (mode == draw_mode_end) + glEndList(); +#endif + +#if 0 + struct graphics_priv *overlay; + GtkWidget *widget=gr->widget; + + if (mode == draw_mode_begin) { + if (! gr->parent && gr->background_gc) + gdk_draw_rectangle(gr->drawable, gr->background_gc->gc, TRUE, 0, 0, gr->width, gr->height); + } + if (mode == draw_mode_end && gr->mode == draw_mode_begin) { + if (gr->parent) { + overlay_draw(gr->parent, gr, 1); + } else { + overlay=gr->overlays; + while (overlay) { + overlay_draw(gr, overlay, 0); + overlay=overlay->next; + } + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gr->drawable, + 0, 0, 0, 0, gr->width, gr->height); + } + } + gr->mode=mode; +#endif +} + +#if 0 +/* Events */ + +static gint +configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) +{ + struct graphics_priv *gra=user_data; + if (! gra->visible) + return TRUE; + if (gra->drawable != NULL) { + gdk_pixmap_unref(gra->drawable); + } + gra->width=widget->allocation.width; + gra->height=widget->allocation.height; + gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1); + if (gra->resize_callback) + (*gra->resize_callback)(gra->resize_callback_data, gra->width, gra->height); + return TRUE; +} + +static gint +expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) +{ + struct graphics_priv *gra=user_data; + + gra->visible=1; + if (! gra->drawable) + configure(widget, NULL, user_data); + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gra->drawable, event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +#if 0 +static gint +button_timeout(gpointer user_data) +{ +#if 0 + struct container *co=user_data; + int x=co->gra->gra->button_event.x; + int y=co->gra->gra->button_event.y; + int button=co->gra->gra->button_event.button; + + co->gra->gra->button_timeout=0; + popup(co, x, y, button); + + return FALSE; +#endif +} +#endif + +static gint +button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 1, event->button, &p); + return FALSE; +} + +static gint +button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 0, event->button, &p); + return FALSE; +} + +static gint +scroll(GtkWidget * widget, GdkEventScroll * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + int button; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) { + switch (event->direction) { + case GDK_SCROLL_UP: + button=4; + break; + case GDK_SCROLL_DOWN: + button=5; + break; + default: + button=-1; + break; + } + if (button != -1) { + (*this->button_callback)(this->button_callback_data, 1, button, &p); + (*this->button_callback)(this->button_callback_data, 0, button, &p); + } + } + return FALSE; +} + +static gint +motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->motion_callback) + (*this->motion_callback)(this->motion_callback_data, &p); + return FALSE; +} + +#endif + + +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) +{ +#if 0 + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->drawable=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->colormap=gr->colormap; + this->widget=gr->widget; + this->p=*p; + this->width=w; + this->height=h; + this->parent=gr; + this->background=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->next=gr->overlays; + gr->overlays=this; + return this; +#endif + return NULL; +} + +static void * +get_data(struct graphics_priv *this, char *type) +{ + if (strcmp(type,"opengl_displaylist")) + return NULL; + return &this->DLid; +} + +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ + this->resize_callback=callback; + this->resize_callback_data=data; +} + +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) +{ + this->motion_callback=callback; + this->motion_callback_data=data; +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ + this->button_callback=callback; + this->button_callback_data=data; +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, +#ifdef HAVE_IMLIB2 + draw_image_warp, +#else + NULL, +#endif + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +graphics_opengl_new(struct graphics_methods *meth) +{ + struct graphics_priv *this=g_new0(struct graphics_priv,1); + *meth=graphics_methods; + +// GtkWidget *draw; + +// draw=gtk_drawnig_area_new(); + + printf("Creating the DL from driver\n"); + this->DLid = glGenLists(1); + + +/* + this->widget=draw; + + this->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); + gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_KEY_PRESS_MASK); + g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), this); + g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), this); +#if 0 + g_signal_connect(G_OBJECT(draw), "realize_event", G_CALLBACK(realize), co); +#endif + g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), this); + g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), this); + g_signal_connect(G_OBJECT(draw), "scroll_event", G_CALLBACK(scroll), this); + g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), this); + */ + return this; +} + +void +plugin_init(void) +{ + plugin_register_graphics_type("opengl", graphics_opengl_new); +} diff --git a/gui.c b/gui.c new file mode 100644 index 00000000..f47856ee --- /dev/null +++ b/gui.c @@ -0,0 +1,106 @@ +#include +#include "gui.h" +#include "statusbar.h" +#include "menu.h" +#include "plugin.h" + +struct gui * +gui_new(struct navit *nav, const char *type, int w, int h) +{ + struct gui *this_; + struct gui_priv *(*guitype_new)(struct navit *nav, struct gui_methods *meth, int w, int h); + + guitype_new=plugin_get_gui_type(type); + if (! guitype_new) + return NULL; + + this_=g_new0(struct gui, 1); + this_->priv=guitype_new(nav, &this_->meth, w, h); + return this_; +} + +struct statusbar * +gui_statusbar_new(struct gui *gui) +{ + struct statusbar *this_; + if (! gui->meth.statusbar_new) + return NULL; + this_=g_new0(struct statusbar, 1); + this_->priv=gui->meth.statusbar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +struct menu * +gui_menubar_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.menubar_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.menubar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + + +struct menu * +gui_toolbar_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.toolbar_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.toolbar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +struct menu * +gui_popup_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.popup_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.popup_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +int +gui_set_graphics(struct gui *this_, struct graphics *gra) +{ + if (! this_->meth.set_graphics) + return 1; + return this_->meth.set_graphics(this_->priv, gra); +} + +int +gui_has_main_loop(struct gui *this_) +{ + if (! this_->meth.run_main_loop) + return 0; + return 1; +} + +int +gui_run_main_loop(struct gui *this_) +{ + if (! gui_has_main_loop(this_)) + return 1; + return this_->meth.run_main_loop(this_->priv); +} + diff --git a/gui.h b/gui.h new file mode 100644 index 00000000..11316908 --- /dev/null +++ b/gui.h @@ -0,0 +1,36 @@ +struct navit; +struct gui_priv; +struct menu_methods; +struct statusbar_methods; +struct graphics; + +struct gui_methods { + struct menu_priv *(*menubar_new)(struct gui_priv *priv, struct menu_methods *meth); + struct menu_priv *(*toolbar_new)(struct gui_priv *priv, struct menu_methods *meth); + struct statusbar_priv *(*statusbar_new)(struct gui_priv *priv, struct statusbar_methods *meth); + struct menu_priv *(*popup_new)(struct gui_priv *priv, struct menu_methods *meth); + int (*set_graphics)(struct gui_priv *priv, struct graphics *gra); + int (*run_main_loop)(struct gui_priv *priv); +}; + + +struct gui { + struct gui_methods meth; + struct gui_priv *priv; +}; + +/* prototypes */ +struct graphics; +struct gui; +struct menu; +struct navit; +struct statusbar; +struct gui *gui_new(struct navit *nav, const char *type, int w, int h); +struct statusbar *gui_statusbar_new(struct gui *gui); +struct menu *gui_menubar_new(struct gui *gui); +struct menu *gui_toolbar_new(struct gui *gui); +struct menu *gui_popup_new(struct gui *gui); +int gui_set_graphics(struct gui *this_, struct graphics *gra); +int gui_has_main_loop(struct gui *this_); +int gui_run_main_loop(struct gui *this_); +/* end of prototypes */ diff --git a/gui/Makefile.am b/gui/Makefile.am index 126d10a6..e0e3a225 100644 --- a/gui/Makefile.am +++ b/gui/Makefile.am @@ -1 +1,8 @@ -SUBDIRS=gtk +SUBDIRS= +if GUI_GTK + SUBDIRS += gtk +endif +if GUI_SDL + SUBDIRS += sdl +endif + diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am index d5ffe2f7..9b8d907f 100644 --- a/gui/gtk/Makefile.am +++ b/gui/gtk/Makefile.am @@ -1,11 +1,4 @@ -AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. - -objdir=$(prefix) -obj_PROGRAMS=gtk.o -INSTALL_PROGRAM=/bin/true - -gtk_o_SOURCES=gtkeyboard.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c - -gtk.o: $(gtk_o_OBJECTS) - ld -r -o gtk.o $(gtk_o_OBJECTS) +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @GTK2_CFLAGS@ -I../.. -DMODULE=\"gui_gtk\" +plugin_LTLIBRARIES = libgui_gtk.la +libgui_gtk_la_SOURCES = destination.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c gui_gtk.h diff --git a/gui/gtk/destination.c b/gui/gtk/destination.c new file mode 100644 index 00000000..5ef6e7f5 --- /dev/null +++ b/gui/gtk/destination.c @@ -0,0 +1,369 @@ +#include +#include +#include +#include +#include +#include "debug.h" +#include "destination.h" +#include "navit.h" +#include "attr.h" +#include "coord.h" +#include "item.h" +#include "search.h" + +#define COL_COUNT 8 + +static struct search_param { + struct navit *nav; + struct mapset *ms; + struct search_list *sl; + struct attr attr; + GtkWidget *entry_country, *entry_postal, *entry_city, *entry_district; + GtkWidget *entry_street, *entry_number; + GtkWidget *listbox; + GtkWidget *treeview; + GtkListStore *liststore; + GtkTreeModel *liststore2; +} search_param; + +static void button_map(GtkWidget *widget, struct search_param *search) +{ + struct coord *c=NULL; + GtkTreeIter iter; + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); + if (c) + navit_set_center(search->nav, c); +} + +static void button_destination(GtkWidget *widget, struct search_param *search) +{ + struct coord *c=NULL; + GtkTreeIter iter; + char *desc,*car,*postal,*town,*street; + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); + if (c) { + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 0, &car, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 1, &postal, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 2, &town, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 4, &street, -1); + if (search->attr.type == attr_town_name) + desc=g_strdup_printf("%s-%s %s", car, postal, town); + else + desc=g_strdup_printf("%s-%s %s, %s", car, postal, town, street); + navit_set_destination(search->nav, c, desc); + g_free(desc); + } +} + + +char **columns_text[] = { + (char *[]){"Car","Iso2","Iso3","Country",NULL}, + (char *[]){"Car","Postal","Town","District",NULL}, + (char *[]){"Car","Postal","Town","District","Street",NULL}, + (char *[]){"Car","Postal","Town","District","Street","Number",NULL}, +}; + +static void set_columns(struct search_param *param, int mode) +{ + GList *columns_list,*columns; + char **column_text=columns_text[mode]; + int i=0; + + columns_list=gtk_tree_view_get_columns(GTK_TREE_VIEW(param->treeview)); + columns=columns_list; + while (columns) { + gtk_tree_view_remove_column(GTK_TREE_VIEW(param->treeview), columns->data); + columns=g_list_next(columns); + } + g_list_free(columns_list); + while (*column_text) { + printf("column_text=%p\n", column_text); + printf("*column_text=%s\n", *column_text); + GtkCellRenderer *cell=gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (param->treeview),-1, *column_text, cell, "text", i, NULL); + i++; + column_text++; + } + +} + +static void changed(GtkWidget *widget, struct search_param *search) +{ + struct search_list_result *res; + GtkTreeIter iter; + + search->attr.u.str=(char *)gtk_entry_get_text(GTK_ENTRY(widget)); + printf("changed %s\n", search->attr.u.str); + if (widget == search->entry_country) { + dbg(0,"country\n"); + search->attr.type=attr_country_all; + set_columns(search, 0); + } + if (widget == search->entry_city) { + dbg(0,"town\n"); + search->attr.type=attr_town_name; + if (strlen(search->attr.u.str) < 2) + return; + set_columns(search, 1); + } + if (widget == search->entry_street) { + dbg(0,"street\n"); + search->attr.type=attr_street_name; + set_columns(search, 2); + } + + + search_list_search(search->sl, &search->attr, 1); + gtk_list_store_clear(search->liststore); + while((res=search_list_get_result(search->sl))) { + gtk_list_store_append(search->liststore,&iter); + gtk_list_store_set(search->liststore,&iter,COL_COUNT,res->c,-1); + if (widget == search->entry_country) { + if (res->country) { + gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1); + gtk_list_store_set(search->liststore,&iter,1,res->country->iso3,-1); + gtk_list_store_set(search->liststore,&iter,2,res->country->iso2,-1); + gtk_list_store_set(search->liststore,&iter,3,res->country->name,-1); + } + } else { + if (res->country) + gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1); + else + gtk_list_store_set(search->liststore,&iter,0,"",-1); + if (res->town) { + gtk_list_store_set(search->liststore,&iter,1,res->town->postal,-1); + gtk_list_store_set(search->liststore,&iter,2,res->town->name,-1); + gtk_list_store_set(search->liststore,&iter,3,"",-1); + } else { + gtk_list_store_set(search->liststore,&iter,1,"",-1); + gtk_list_store_set(search->liststore,&iter,2,"",-1); + gtk_list_store_set(search->liststore,&iter,3,"",-1); + } + if (res->street) + gtk_list_store_set(search->liststore,&iter,4,res->street->name,-1); + else + gtk_list_store_set(search->liststore,&iter,4,"",-1); + + } + } +} + +/* borrowed from gpe-login */ + + +#define MAX_ARGS 8 + +static void +parse_xkbd_args (const char *cmd, char **argv) +{ + const char *p = cmd; + char buf[strlen (cmd) + 1], *bufp = buf; + int nargs = 0; + int escape = 0, squote = 0, dquote = 0; + + while (*p) + { + if (escape) + { + *bufp++ = *p; + escape = 0; + } + else + { + switch (*p) + { + case '\\': + escape = 1; + break; + case '"': + if (squote) + *bufp++ = *p; + else + dquote = !dquote; + break; + case '\'': + if (dquote) + *bufp++ = *p; + else + squote = !squote; + break; + case ' ': + if (!squote && !dquote) + { + *bufp = 0; + if (nargs < MAX_ARGS) + argv[nargs++] = strdup (buf); + bufp = buf; + break; + } + default: + *bufp++ = *p; + break; + } + } + p++; + } + + if (bufp != buf) + { + *bufp = 0; + if (nargs < MAX_ARGS) + argv[nargs++] = strdup (buf); + } + argv[nargs] = NULL; +} + +int kbd_pid; + +static int +spawn_xkbd (char *xkbd_path, char *xkbd_str) +{ + char *xkbd_args[MAX_ARGS + 1]; + int fd[2]; + char buf[256]; + char c; + int a = 0; + size_t n; + + pipe (fd); + kbd_pid = fork (); + if (kbd_pid == 0) + { + close (fd[0]); + if (dup2 (fd[1], 1) < 0) + perror ("dup2"); + close (fd[1]); + if (fcntl (1, F_SETFD, 0)) + perror ("fcntl"); + xkbd_args[0] = (char *)xkbd_path; + xkbd_args[1] = "-xid"; + if (xkbd_str) + parse_xkbd_args (xkbd_str, xkbd_args + 2); + else + xkbd_args[2] = NULL; + execvp (xkbd_path, xkbd_args); + perror (xkbd_path); + _exit (1); + } + close (fd[1]); + do { + n = read (fd[0], &c, 1); + if (n) + { + buf[a++] = c; + } + } while (n && (c != 10) && (a < (sizeof (buf) - 1))); + + if (a) + { + buf[a] = 0; + return atoi (buf); + } + return 0; +} + +int destination_address(struct navit *nav) +{ + + GtkWidget *window2, *keyboard, *vbox, *table; + GtkWidget *label_country; + GtkWidget *label_postal, *label_city, *label_district; + GtkWidget *label_street, *label_number; + GtkWidget *hseparator1,*hseparator2; + GtkWidget *button1,*button2; + int i; + struct search_param *search=&search_param; + + + search->nav=nav; + search->ms=navit_get_mapset(nav); + search->sl=search_list_new(search->ms); + + window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); + vbox = gtk_vbox_new(FALSE, 0); + table = gtk_table_new(3, 8, FALSE); + + search->entry_country = gtk_entry_new(); + label_country = gtk_label_new("Land"); + search->entry_postal = gtk_entry_new(); + label_postal = gtk_label_new("PLZ"); + search->entry_city = gtk_entry_new(); + label_city = gtk_label_new("Ort"); + search->entry_district = gtk_entry_new(); + label_district = gtk_label_new("Ortsteil/Gemeinde"); + hseparator1 = gtk_vseparator_new(); + search->entry_street = gtk_entry_new(); + label_street = gtk_label_new("Strasse"); + search->entry_number = gtk_entry_new(); + label_number = gtk_label_new("Nummer"); + search->treeview=gtk_tree_view_new(); + search->listbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (search->listbox), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), NULL); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(search->listbox),search->treeview); + { + GType types[COL_COUNT+1]; + for(i=0;iliststore=gtk_list_store_newv(COL_COUNT+1,types); + search->liststore2=gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(search->liststore)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 0, GTK_SORT_ASCENDING); + gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), GTK_TREE_MODEL(search->liststore2)); + } + + + + + hseparator2 = gtk_vseparator_new(); + button1 = gtk_button_new_with_label("Karte"); + button2 = gtk_button_new_with_label("Ziel"); + + gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_city, 2, 3, 0, 1, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->entry_country, 0, 1, 1, 2, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_postal, 1, 2, 1, 2, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_city, 2, 3, 1, 2, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), label_district, 0, 1, 2, 3, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_street, 1, 2, 2, 3, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_number, 2, 3, 2, 3, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->entry_district, 0, 1, 3, 4, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_street, 1, 2, 3, 4, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_number, 2, 3, 3, 4, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->listbox, 0, 3, 4, 5, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), button1, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), button2, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + + g_signal_connect(G_OBJECT(search->entry_country), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_postal), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_city), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_district), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_street), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_number), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_map), search); + g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_destination), search); + + gtk_widget_grab_focus(search->entry_city); + + gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); + keyboard=gtk_socket_new(); + gtk_box_pack_end(GTK_BOX(vbox), keyboard, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(window2), vbox); +#if 0 + g_signal_connect(G_OBJECT(listbox), "select-row", G_CALLBACK(select_row), NULL); +#endif + gtk_widget_show_all(window2); + gtk_socket_steal(GTK_SOCKET(keyboard), spawn_xkbd("xkbd","-geometry 200x100")); + + return 0; +} diff --git a/gui/gtk/gtkeyboard.c b/gui/gtk/gtkeyboard.c deleted file mode 100644 index 58f929b8..00000000 --- a/gui/gtk/gtkeyboard.c +++ /dev/null @@ -1,2350 +0,0 @@ -/* app.c - * For use with GTKeyboard - * written by David Allen, s2mdalle@titan.vcu.edu - * http://opop.nols.com/ - * - * #define DEBUGGING at compile time for interesting info most people don't - * want to see. - */ -/* GTKeyboard - A Graphical Keyboard For X - * Copyright (C) 1999, 2000 David Allen - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* The regular non-fun glib calls for distro copies of gtkeyboard. */ -# define g_new0_(t,c) g_new0(t,c) -# define g_free_(mem) g_free(mem) -# define g_new_(t,c) g_new(t,c) -# define g_strdup_(x) g_strdup(x) -# define g_malloc_(x) g_malloc(x) -# define MEM(x) ; /* Don't do anything */ - - -/* modmap.h - * Written by David Allen - * - * Released under the terms of the GNU General Public License - */ - - - - -#define slot_number_to_mask(x) (1< - * http://opop.nols.com/ - * Released under the terms of the GNU General Public License - */ - -#define MAXIMUM_ROWS 6 - -/* Abstract data types */ - -typedef struct { - KeySym lower_case; /* What happens when pressed by itself */ - KeySym upper_case; /* What happens when pressed with Shift/CL */ - KeySym alt_gr; /* Alt GR+ button -- mostly unused */ - KeyCode code; - char *aux_string; /* Cheating string holder for things that aren't - * right with XKeysymToString() -- most notably - * the F keys and the keypad keys - * This should NEVER be used in conjunction - * with foreign windows - only text insertion in - * our editing buffer - */ -} KEY; - -typedef struct { - char *tab; - char *backspace; - char *caps_lock; - char *space; - char *alt; - char *alt_gr; - char *control; - char *shift; -} KeyboardTranslation; - -typedef struct { - int row_values[MAXIMUM_ROWS]; - int keycount; - KeySym *syms; - KeyCode *codes; - KeyboardTranslation *trans; - char *name; - ModmapTable *modmap; -} KEYBOARD; - -/* Macros */ -#define NO_KEYBOARD ((KEYBOARD *)NULL) -#define NO_KEY ((KEY *)NULL) - -/* Function prototypes */ -static KEY *gtkeyboard_key_copy(KEY * key); -static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, int keyno); -static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input); -static KEYBOARD *read_keyboard_template(char *filename); -static KEY *gtkeyboard_destroy_key(KEY * input); -static KEY *gtkeyboard_new_key(const KeySym lower, - const KeySym upper, - const KeySym altgr, const char *alt); -gint track_focus(gpointer data); - - - -/* rc_file.h - A simple configuration file reader/writer header file - * by Patrick Gallot - * - * This file is part of GTKeyboard and as such is licensed under the terms - * of the GNU General Public License. - */ - - -/* Different types that resource file varaibles can have */ -#define RC_NONE 0x0000 -#define RC_STR 0x0002 /* String */ -#define RC_PARSE_FUNC 0x0006 /* This one means that an external - * parsing function should be used - * and the resource file code - * shouldn't bother with the values - */ -typedef struct config_var { - /* These go together to specify a line in a file that could say something - * like "set foo_variable 10" or "foobar = 20" or even - * "toolbar menubar off" - */ - - gchar *Prefix; /* This could be something like "set" or "toolbar" */ - gchar *Name; /* Element name */ - gint Type; /* Type of the value */ - gpointer Val; /* Pointer to the value to store */ - /* Function pointer for custom handling -- it should have parameters - * of the "prefix" token, (usually "set"), the variable name, the - * varaible value, and the pointer we were supposed to store it in. - * The pointer is usually going to be the same as Val above - */ - int (*func) (char *prefix, char *varname, char *val, gpointer ptr); -} RCVARS; - -static int read_ConfigFile(char *filename, RCVARS * vars, int complain); - -#define CONDFREE(x) if(x){ g_free_(x); x = NULL; } - -#define FLUSH_EVERYTHING fflush(Q); fflush(stdout);\ - fflush(stderr); - -/* Toggling Defines */ -#define ON 1 -#define OFF 0 -/* Whatever the status is, FLIP IT */ -#define ISOFF(x) ( x==OFF ) - -/* In case we ever achieve portability to winblows, we can change this - * to a backslash. :) - */ -#define _DIR "/" - -#define FLUSH fflush(Q) -#define NONE NULL - -#define LEFT_MOUSE_BUTTON 1 -#define RIGHT_MOUSE_BUTTON 3 -#define MIDDLE_MOUSE_BUTTON 2 - -#define Q stderr -#define ABOUT_INFO "about.data" -#define RC_FILENAME ".gtkeyboardrc" -#define PROVIDED_RCFILE "example_configurations/defaults.gtkeyboard" -#define APPNAME "GTKeyboard" -#define CR "\n" - - - -/* adt.h - * For GTKeyboard - * written by David Allen s2mdalle@titan.vcu.edu - * http://opop.nols.com/ - * - * This file is released under the terms of the GNU General Public License. - * Please see COPYING for more details. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Maximum number of custom colors. 10 is a good number, above that is - * really not needed per se. - */ -#define MAX_CUSTOM_COLORS 10 - -/**************************************************************************/ - -/* ADTs */ -/* Program configuration settings */ -typedef struct { - /* Changed to bits in 0.97.3 to save a little space. */ - /* Different program options - initialized in app.c changed in - * file_manip.c and messed with elsewhere. - * - * See app.c and the initialization code for comments on what they - * all mean. - */ - int REDIRECT_POLICY_IMPLICIT; - int STATUS_LOGGING; - int CAPS_LOCK; - int IGNORE_LAYOUT_FILE; - /* int ASK_REMAP_ON_EXIT; -- Deprecated for now... */ - int SHIFT; - int ALT_GR; - int NUMLOCK; - int VERBOSE; - int ALT; - int CONTROL; - int USE_KEYBOARD; - - - char *home; /* Home dir of user running the app. */ - char *tempslot; - char *extrafiles; /* Extra files, docs, default rcfile, lic. */ - char *redirect_window_name; /* Window name of redirection location. */ - char *keyboard_file; - char *cache_file; - Window redirect_window; /* Xlib window structure for redirection. */ - Window other; /* Temporary window structure for Xlib */ - - KEYBOARD *keyboard; - KEYBOARD *old_keyboard; - - /* These memory areas won't be used unless PROD isn't defined. - * When PROD isn't defined, we're not debugging, and they essentially - * keep track of the number of memory calls that I make. See also - * mem_header.h for a full definition of how they're used. - */ -#if defined(GTKEYBOARD_MEMORY_DEBUGGING) || defined(DEBUGGING) - long MEM; /* Number of bytes allocated */ - int gnew; /* Number of gnew() calls (alloc) */ - int gnew0; /* Number of gnew0() calls (alloc) */ - int gmalloc; /* Number of g_malloc() calls (alloc) */ - int gstrdup; /* Number of g_strdup() calls (alloc) */ - int gfree; /* Number of g_free() calls (free) */ -#endif -} GTKeyboardOptions; - -typedef struct { - GtkWidget *keyboard; - gint show_keyboard; -} GTKeyboardKeyboardElements; - -typedef struct { - int keyboard; -} GTKeyboardElements; - -/****************************************************************************/ - -typedef struct { - Window xwindow; /* So we can play with xlib. (our window) */ - GtkWidget *KEYBOARD; /* Container containing all keyb elements */ - - - GTKeyboardKeyboardElements keyboard_elements; - - /* If a field has a comment of "Cleaned" next to it, then it is - * either deallocated or destroyed in - * callbacks.c:gtkeyboard_mem_cleanup() via macro calls. - */ - char *custom_colors[MAX_CUSTOM_COLORS]; /* Cleaned */ - gchar *fontname; /* Cleaned */ - gchar *kfontname; /* Cleaned */ - gchar *colorname; /* Cleaned */ - gdouble saved_colors[4]; - - GtkShadowType SHADOW_TYPE; - GtkPositionType PULLOFFS_SIDE; - - GtkUIManager *uimanager; - GtkWidget *popup_menu; /* Cleaned */ - GdkCursor *cursor; - GtkStyle *style; - - /* Style referring to the main output text area */ - GtkStyle *textstyle; /* Cleaned */ - - /* The default GTK style */ - GtkStyle *deflt; /* Cleaned */ - - GdkFont *font; /* Cleaned */ - - /* The keyboard widget's style */ - GtkStyle *kstyle; /* Cleaned */ - - /* Keyboard font */ - GdkFont *kfont; /* Cleaned */ - - GtkTooltips *tooltips; -} GTKeyboardGUI; - -/**************************************************************************/ - -typedef struct { - int width; - int height; - int x; - int y; -} window_dimensions; - - -/* file_manip.h - * - * For use with GTKeyboard - * written by David Allen s2mdalle@titan.vcu.edu - * This file is released under the terms of the GNU General Public License - */ - -#include -#include -#include -#include -#include - - -#define MAX_LINE_LENGTH 128 -#define TOKEN_SIZE 50 -#define DEFAULT_RCFILE "# Default .gtkeyboardrc file written by GTKeyboard\nkeyboard main_keyboard on\nkeyboard number_pad on\nkeyboard cursor_keys on\nkeyboard f_keys on\n\nset handlebars off\n\nset word_wrap off\nset info_popups on\nset bump_amount 15\nhide buttonbar\nset random_strlen 10\nset eyecandy off\nset redirect_policy implicit\n" - - - - -#define STAT_AND_RETURN_IF_BAD(fname, someint, statstruct) \ - if(!fname)return(0);\ - someint = stat(fname, &statstruct);\ - if(someint<0) return(0); - -/* List of strings - GTKeyboard is really looking for these when it - * reads the rcfiles. These are the options it recognizes. To the user, - * they aren't case sensitive, but here, they must ALL be specified in all caps - */ -#define OPT_KEYBOARD_FILE "KEYBOARD_FILE" - - -/* Prototypes - creeping evil */ -static void parse_user_resource_file(char *filename); -static void FILE_readline(FILE * fp, char *buffer, const int maxlen); -static int setup_default_rcfile(char *file); - -/* EOF */ - -static const char *active_window_name = "CurrentWindow"; - -static Window root; -static XEvent xev; - -/* fake_timestamp is static in irxevent.c */ -static Window find_window(Window top, char *name); -static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev); - -/* Various keyboards are included only for app.c and build_keyboard.c - * in master.h - */ - -/* Just make them all different - gets passed to build_an_entire_keyboard */ -/* Not used yet.. */ - -/* Local defines for what keys appear as */ - -/* - * Check the notes at the bottom of the page for an ASCII drawing of how the - * keyboard should look - * - * Each button is defined as a character string of two characters. The first - * is what you get when SHIFT || CAPS_LOCK > 0 and the second is the normal - * key function. This function loops through grabbing two characters at a - * time and then calling makekeybutton to set things up and map the - * callback to the key and so on. - * - * SPECIAL CASES WITHIN stuff[]: (Yes it's braindamaged) - * LL is the left cursor key - * RR is the right cursor key - * || is caps lock key - * \\ (or escaped, it's \\\\) is SHIFT key - * CC is control - * AA is alt - * -*/ - -/* PROTOTYPES - Most functions in build_keyboard.c are static and don't need - * prototypes here. - */ -int init_keyboard_stuff(char *input); -static void keysym_callback(GtkWidget * emitter, gpointer data); -static void capslock_toggle(GtkWidget * w, gpointer data); -static void alt_toggle(GtkWidget * w, gpointer data); -static void alt_gr_toggle(GtkWidget * w, gpointer data); -static void control_toggle(GtkWidget * w, gpointer data); -static void shift_on(GtkWidget * w, gpointer data); - -typedef struct { - GtkStyle *style; - int mask; -} GTKeyboardStyle; - -typedef struct { - GtkWidget *dialog; - GdkColor *color; -} color_info; - -typedef struct { - long code; - char *name; -} binding; - - -/* Main program options - do not declare as static - all global */ -static GTKeyboardOptions options; -static GTKeyboardGUI GUI; -static GTKeyboardElements ELEMENTS; - - -#define NO_HANDLER 666 - -/* Static function prototypes */ -static void setup_default_opts(void); -static void setup_default_opts_other(void); - -#define INSTALL_DOC_DIR "/usr/local/share/gtkeyboard" - -int init_keyboard_stuff(char *input) -{ - char *filename; - char *homeptr; - - /* This sets the values in the structure GUI to default values. - * I'll add things for changing the default in that function later. - */ - setup_default_opts(); /* Handles the stuff in options */ - setup_default_opts_other(); - - /* Allocate the necessary memory to copy location of support files - * into */ - options.extrafiles = g_new0_(char, (strlen(INSTALL_DOC_DIR) + 3)); - sprintf(options.extrafiles, "%s%s", INSTALL_DOC_DIR, _DIR); - - options.keyboard = NO_KEYBOARD; - options.old_keyboard = NO_KEYBOARD; - - /* End if */ - homeptr = getenv("HOME"); - - if (homeptr) { - options.home = g_strdup_(getenv("HOME")); - } /* End if */ - else - options.home = NULL; - - filename = - g_new0_(char, strlen(options.home) + 5 + strlen(RC_FILENAME)); - sprintf(filename, "%s%s%s", (options.home ? options.home : "/tmp"), - _DIR, RC_FILENAME); - - /* This parses ALL user preferences from ~/.gtkeyboardrc into various - * structures - the important parts of this are in rc_file.h and - * file_manip.c - */ - - parse_user_resource_file(filename); - - CONDFREE(filename); - - return (1); -} /* End init_keyboard_stuff */ - -/* This gets called once at setup to initialize all the GUI but - * non-keyboard related opts - * Shouldn't return anything or allocate any memory, it just sets - * things to "reasonable" defaults. - */ -static void setup_default_opts_other(void) -{ - /* Here's where you get to set all of the defaults for GUI structure - * members. - */ - GUI.SHADOW_TYPE = GTK_SHADOW_ETCHED_OUT; - GUI.PULLOFFS_SIDE = GTK_POS_LEFT; - GUI.cursor = (GdkCursor *) NULL; - GUI.fontname = (gchar *) NULL; - GUI.kfontname = (gchar *) NULL; - GUI.colorname = (gchar *) NULL; - GUI.textstyle = (GtkStyle *) NULL; - GUI.style = (GtkStyle *) NULL; - GUI.font = (GdkFont *) NULL; - GUI.kfont = (GdkFont *) NULL; - GUI.deflt = (GtkStyle *) NULL; - GUI.xwindow = (Window) NULL; - GUI.popup_menu = (GtkWidget *) NULL; - GUI.uimanager = (GtkUIManager *) NULL; - - GUI.keyboard_elements.show_keyboard = ON; - - GUI.keyboard_elements.keyboard = (GtkWidget *) NULL; - - return; -} /* End setup_default_opts_other */ - -/* This gets called once at startup, sets all the initial values for - * options.whatever stuff - */ -static void setup_default_opts(void) -{ - /* All screen ELEMENTS on by default */ - - ELEMENTS.keyboard = 1; - - /* Set up some default values for program parameters - * Can be changed by parse_rcfile later. Hopefully these are reasonable. - */ - options.other = (Window) NULL; - options.redirect_window = (Window) NULL; - options.home = (char *) NULL; - options.redirect_window_name = (char *) NULL; - options.tempslot = (char *) NULL; - options.keyboard_file = (char *) NULL; - - - /* options.ASK_REMAP_ON_EXIT = OFF; *//* Currently deprecated */ - options.STATUS_LOGGING = OFF; /* Save the status window */ - options.CAPS_LOCK = OFF; /* Caps lock starts at OFF */ - options.SHIFT = OFF; /* Shift starts at OFF */ - options.ALT_GR = OFF; /* Alt-GR key status */ - options.CONTROL = OFF; /* Control button at OFF */ - options.NUMLOCK = OFF; /* Numlock starts at OFF */ - options.ALT = OFF; /* Alt key starts at OFF */ - options.VERBOSE = OFF; /* Spew messages */ - options.REDIRECT_POLICY_IMPLICIT = ON; /* Default to implicit redir */ - options.IGNORE_LAYOUT_FILE = OFF; /* Dont ignore layout file */ - -} /* End setup_default_opts */ - - - -#define BUILD_KEYBOARD_C - -static char *string_special_cases(KeySym input); - -static void rotate_keyboard_definitions(KEYBOARD * new_keyboard) -{ - if (!new_keyboard) { - fprintf(stderr, - "rotate_keyboard_definitions Error: Bad keyboard.\n"); - fflush(stderr); - return; - } - - /* End if */ - /* If there is an old definition laying around, destroy it to free - * up the memory. - */ - if (options.old_keyboard) { - options.old_keyboard = - gtkeyboard_destroy_keyboard(options.old_keyboard); -#ifdef REMAPPING_DEBUGGING - fprintf(Q, "Rotated old keyboard out..."); - fflush(Q); -#endif /* REMAPPING_DEBUGGING */ - } - - /* End if */ - /* Copy the current keyboard definition to the 'old' keyboard */ - options.old_keyboard = options.keyboard; - - /* Make the argument to this function the 'current' keyboard */ - options.keyboard = new_keyboard; - -#ifdef REMAPPING_DEBUGGING - fprintf(Q, "Old keyboard is now %s, Current keyboard is now %s\n", - (options.old_keyboard ? "valid" : "dead"), - (options.keyboard ? "valid" : "dead")); - fflush(Q); -#endif /* REMAPPING_DEBUGGING */ - - return; -} /* End rotate_keyboard_definitions() */ - -/* This destroys the key attached as object data to a lot of the buttons - * when they get destroyed - */ -static void destroy_key_widget_data(GtkObject *object, gpointer data) -{ - KEY *key = (KEY *) data; - - if (!key) { - fprintf(stderr, - "GTKeyboard error (destroy_key_widget_data) "); - fprintf(stderr, "data == NULL!\n"); - fflush(stderr); - return; - } - /* End if */ - key = gtkeyboard_destroy_key(key); -} /* End destroy_key_widget_data() */ - -/* Call this for every widget that has a KEY structure as its object data - * this makes sure that when the widget is destroyed, destroy_key_widget_data - * gets called on the object data - */ -static void connect_destroy_signal(GtkWidget * widget, gpointer data) -{ -#if 0 - g_signal_connect_data(G_OBJECT(widget), - "destroy", - G_CALLBACK(destroy_key_widget_data), - (GtkCallbackMarshal) - gtk_signal_default_marshaller, data, - (GtkDestroyNotify) destroy_key_widget_data, - FALSE, TRUE); -#endif - g_signal_connect(G_OBJECT(widget), - "destroy", - G_CALLBACK(destroy_key_widget_data), - data); -} /* End connect_destroy_signal() */ - -static gint triple_callback(GtkWidget * emitter, GdkEvent * event, - gpointer data) -{ - KEY *k = (KEY *) data; - KEY *key = NO_KEY; - - if (!k) { - fprintf(stderr, - "GTKeyboard internal error: %s: NULL \"KEY\" arg.\n", - "(triple_callback)"); - fflush(stderr); - return TRUE; - } - /* End if */ - if (event->type == GDK_BUTTON_PRESS) { - key = gtkeyboard_key_copy(k); - - if (event->button.button == LEFT_MOUSE_BUTTON) { - /* Regular keypress, deal with it as normal */ - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End if */ - else if (event->button.button == MIDDLE_MOUSE_BUTTON) { - KeySym lower, upper; - - /* Always generate the "Alt-GR" keysym */ - if (!key->alt_gr || key->alt_gr == NoSymbol) { - key->alt_gr = key->lower_case; - } /* End if */ - key->lower_case = key->upper_case = key->alt_gr; - - /* Not sure whether this is upper case or lower case. Try to - * find out by seeing if what XConvertCase returns is the same - * or different. - */ - XConvertCase(key->alt_gr, &lower, &upper); - - /* If upper is the same as alt_gr, then we need shift to be - * on. Otherwise leave it however it is - */ - if (key->alt_gr == upper) - options.SHIFT = ON; - - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - /* Free the memory */ - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End else if */ - else if (event->button.button == RIGHT_MOUSE_BUTTON) { - /* Always generate the "uppercase" Keysym */ - key->lower_case = key->alt_gr = key->upper_case; - - options.SHIFT = ON; - - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End if */ - else { - key = gtkeyboard_destroy_key(key); - return FALSE; - } /* End else */ - } - - /* End if */ - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} /* End triple_callback() */ - -static void keysym_callback(GtkWidget * emitter, gpointer data) -{ - KEY *key = (KEY *) data; - KeySym sym; - char *keyname = (char *) NULL; - char *altkeyname = (char *) NULL; - KeySym lower = (KeySym) NULL, upper = (KeySym) NULL; - -#ifdef PARANOID_DEBUGGING - fprintf(Q, "keysym_callback(): Got (%s, %s, %s).\n", - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - fflush(Q); -#endif /* PARANOID_DEBUGGING */ - - /* Determine which of the syms in the KEY * structure to use. */ - keyname = XKeysymToString(key->lower_case); - altkeyname = XKeysymToString(key->alt_gr); - - if (options.ALT_GR) { - sym = key->alt_gr; - /* We have only three symbols, and we have to generate - * the fourth one for cyrillic letters. - */ - if (strstr(altkeyname, "Cyrillic_")) { - XConvertCase(sym, &lower, &upper); - - if (options.SHIFT || options.CAPS_LOCK) { - sym = upper; - } /* End if */ - } /* End if */ - } /* End if */ - else if (strstr(keyname, "KP")) { - if (options.NUMLOCK) - sym = key->upper_case; - else - sym = key->lower_case; - } /* End else if */ - else if (options.SHIFT) - sym = key->upper_case; - else if (options.CAPS_LOCK) { - if (isalpha((char) key->upper_case)) - sym = key->upper_case; - else - sym = key->lower_case; - } /* End else if */ - else - sym = key->lower_case; - - if (options.redirect_window_name) { - send_redirect_a_keysym(sym); - - } - /* End if */ - return; -} /* End keysym_callback() */ - -static int isspecial(KeySym input) -{ - char *ptr = XKeysymToString(input); - - if (input == NoSymbol || !ptr) - return (1); - if (strstr(ptr, "_L") || strstr(ptr, "_R")) - return (1); - if (strstr(ptr, "ontrol") || strstr(ptr, "Alt")) - return (1); - if (strstr(ptr, "ode")) - return (1); - if (strstr(ptr, "Tab") || strstr(ptr, "Lock") - || strstr(ptr, "pace")) - return (1); - - return (0); -} /* End isspecial */ - -GtkWidget *build_keyboard(GtkWidget * input, char *filename) -{ - /* NEW BUILD_KEYBOARD() */ - GtkWidget *mainbox = gtk_vbox_new(FALSE, 0); - GtkWidget *hbox = (GtkWidget *) NULL; - GtkWidget *button = (GtkWidget *) NULL; - char *name = (char *) NULL; - char *altname = (char *) NULL; - GtkWidget *align = (GtkWidget *) NULL; - char label[512]; - char tooltip_label[1024]; - char *errbuf = NULL; - char *utf8, *ptr; - int rowno; - int index; - char letter = '\0'; - char cyrletter = '\0'; - KEY *key; - KeySym s; - KeySym altlower, altupper; - - /* Create the current keyboard in a new place. -- This takes care of - * destroying our old ones for us. - */ - rotate_keyboard_definitions(read_keyboard_template(filename)); - - if (!options.keyboard) { - fprintf(stderr, "Couldn't read keyboard: Bummer.\n"); - fflush(stderr); - - errbuf = g_new0(char, strlen(filename) + 100); - sprintf(errbuf, - "Couldn't create keyboard from file:\n%s!\nCheck the file format!", - filename); - - button = gtk_button_new_with_label(errbuf); - - CONDFREE(errbuf); - - return (button); - } /* End if */ - else if (options.keyboard->keycount <= 0) { - errbuf = g_new0(char, strlen(filename) + 100); - sprintf(errbuf, - "Couldn't create keyboard from file:\n%s!\nCheck the file format!", - filename); - - button = gtk_button_new_with_label(errbuf); - CONDFREE(errbuf); - return (button); - } - /* End else if */ - for (rowno = 0; rowno < MAXIMUM_ROWS; rowno++) { - hbox = gtk_hbox_new(FALSE, 0); - align = gtk_alignment_new(0.5, 0.5, 0, 0); - - for (index = 0; - index < options.keyboard->row_values[rowno]; - index++) { - key = - gtkeyboard_keyboard_get_key(options.keyboard, - rowno, index); - - letter = (int) key->upper_case; - name = XKeysymToString(key->upper_case); - altname = XKeysymToString(key->alt_gr); - - if (key->upper_case == XK_Mode_switch || - key->lower_case == XK_Mode_switch) { - sprintf(label, " Alt Gr"); - } /* End if */ - else if (strstr(altname, "Cyrillic_")) { - /* We have only lower case letter, let us - * ask X to convert it to upper case. - */ - XConvertCase(key->alt_gr, &altlower, - &altupper); - - /* FIXME: Yes, this is totally wrong method to get - * the cyrillic letter. It just happen to to - * yield the right letter in koi8-r encoding. - */ - cyrletter = (char) altupper; - if (!isalpha(letter)) { - sprintf(label, " %c \n %c %c", - (char) key->upper_case, - (char) key->lower_case, - cyrletter); - } /* End if */ - else { - sprintf(label, " %c \n %c", - (char) key->upper_case, - cyrletter); - } /* End else */ - } /* End else if */ - else if ((isalnum(letter) || ispunct(letter)) - && (letter > 0)) { - if (!isalpha(letter)) - sprintf(label, " %c \n %c", - (char) key->upper_case, - (char) key->lower_case); - else - sprintf(label, " %c \n", - (char) key->upper_case); - } /* End if */ - else if (letter != 0) { - if (!iscntrl(letter) - && !isspecial(key->upper_case) - && letter != ' ') - sprintf(label, " %c \n %c", - (char) key->upper_case, - (char) key->lower_case); - else { - ptr = - string_special_cases(key-> - lower_case); - strncpy(label, ptr, 512); - g_free_(ptr); - } /* End else */ - } /* End else if */ - else { - ptr = - string_special_cases(key->lower_case); - strncpy(label, ptr, 512); - g_free_(ptr); - } /* End else */ - - s = key->lower_case; - -#if 0 - utf8 = - g_locale_to_utf8(label, -1, NULL, NULL, NULL); -#else - utf8=g_convert(label,-1,"utf-8","iso8859-1",NULL,NULL,NULL); -#endif - /* Make the correct key, and attach the correct signal - * function to it. Toggle/normal button/function - */ - if (s == XK_Caps_Lock || s == XK_Control_L || - s == XK_Control_R || s == XK_Alt_L || - s == XK_Alt_R || s == XK_Mode_switch) - button = - gtk_toggle_button_new_with_label(utf8); - else - button = gtk_button_new_with_label(utf8); - - g_free(utf8); - GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); - if (key->code != 0) - sprintf(tooltip_label, - "KeyCode %d:\n%s\n%s\n%s", - key->code, - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - else - sprintf(tooltip_label, - "KeyCode unknown:\n%s\n%s\n%s", - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - - switch (key->lower_case) { - case XK_Caps_Lock: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(capslock_toggle), - input); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Alt_L: - case XK_Alt_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(alt_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Control_L: - case XK_Control_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(control_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Shift_L: - case XK_Shift_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(shift_on), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Mode_switch: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(alt_gr_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - default: - g_signal_connect(G_OBJECT(button), - "button_press_event", - G_CALLBACK(triple_callback), key); - connect_destroy_signal(button, key); - break; - } /* End switch */ - - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, - FALSE, 0); - } /* End for */ - - gtk_container_add(GTK_CONTAINER(align), hbox); - gtk_box_pack_start(GTK_BOX(mainbox), align, FALSE, FALSE, - 0); - } /* End for */ - - if (filename) { - if (options.keyboard_file) { - /* We just built a complete keyboard with this file, so save its - * name for future use. - */ - /* This weird indirect freeing and copying of the string is - * due to the fact that the filename argument to this function - * may in fact be options.keyboard_file itself, so in that - * case it wouldn't be that bright to try to free it and - * copy something that's pointing to the same location. So - * instead we copy it to an intermediate spot, free the - * original, and copy the new value back. - * - * When the value actually is options.keyboard_file, we do a - * bit of redundant work, but oh well. - */ - char *tptr; - tptr = g_strdup_(filename); - g_free_(options.keyboard_file); - options.keyboard_file = g_strdup_(tptr); - g_free_(tptr); -#if 0 - fprintf(Q, - "options.keyboard_file set to be \"%s\"\n", - options.keyboard_file); - fflush(Q); -#endif - } /* End if */ - else { - /* No need to free it - just copy */ - options.keyboard_file = g_strdup_(filename); - fprintf(Q, - "options.keyboard_file set to be \"%s\"\n", - options.keyboard_file); - fflush(Q); - } /* End else */ - } - - /* End if */ - /* gtk_widget_show_all(mainbox); */ - return (mainbox); -} /* End build_keyboard() */ - -static char *string_special_cases(KeySym input) -{ - char label[1024]; - int len, x; - char *ptr; - - if (input == XK_space) { - sprintf(label, - " \n"); - } /* End if */ - else { - /* Space out the output a bit depending on string target - * length so the buttons will look right. - */ - ptr = XKeysymToString(input); - if (strlen(ptr) > 4) - sprintf(label, " %s \n", ptr); - else - sprintf(label, " %s \n", ptr); - } /* End else */ - - len = strlen(label); - - /* Special cases */ - if (strstr(label, "Control") || strstr(label, "control")) { - strcpy(label, " Ctrl "); - } /* End if */ - else if (input == XK_Mode_switch) - strcpy(label, " Alt Gr"); - else { - /* Remove the sillyness from XK_ names from the string. */ - for (x = 0; x < len; x++) { - /* Make everything uppercase */ - label[x] = toupper(label[x]); - - /* Get rid of the _R or _L that may be there. */ - if (label[x] == '_' && - (label[x + 1] == 'R' || label[x + 1] == 'L')) { - label[x] = '\0'; - } /* End if */ - } /* End for */ - } /* End else */ - - ptr = g_strdup_(label); - - return (ptr); -} /* End string_special_cases() */ - - -#define MODE_WRITE - -/* Do not allow both MODE_WRITE and MODE_APPEND to be defined. If both are - * defined, default to MODE_WRITE. The End Of Earth As We Know It (TM) occurs - * (or maybe just a compile error) MODE_WRITE is spiffier. - */ -#ifdef MODE_APPEND -# ifdef MODE_WRITE -# undef MODE_APPEND -# endif /* MODE_WRITE */ -#endif /* MODE_APPEND */ - -#ifndef __USE_GNU -# define __USE_GNU -#endif /* __USE_GNU */ - - -static void alt_gr_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.ALT_GR)) { - options.ALT_GR = ON; - } /* End if */ - else { - options.ALT_GR = OFF; - } /* End else */ -} /* End alt_gr_toggle */ - -static void control_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.CONTROL)) { - options.CONTROL = ON; - } /* End if */ - else { - options.CONTROL = OFF; - } /* End else */ -} /* End control_toggle */ - -static void alt_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.ALT)) { - options.ALT = ON; - } /* End if */ - else { - options.ALT = OFF; - } /* End else */ -} /* End alt_toggle */ - -static void capslock_toggle(GtkWidget * w, gpointer data) -{ - if (options.redirect_window_name) - send_redirect_a_keysym(XK_Caps_Lock); - - /* Whatever it currently is, swtich it */ - if (ISOFF(options.CAPS_LOCK)) { - options.CAPS_LOCK = ON; - } /* End if */ - else { - options.CAPS_LOCK = OFF; - } /* End else */ -} /* End capslock_toggle */ - -static void shift_on(GtkWidget * w, gpointer data) -{ - /* Turn shift on */ - options.SHIFT = ON; - -} /* End shift_on */ - -/* This parses the user resource file via read_ConfigFile. This function - * doesn't actually do much other than define all of the structures for - * parsing in one place and actually doing the function calls. This is - * where you need to tweak command options. - */ -static void parse_user_resource_file(char *filename) -{ - RCVARS rc_parse_values[] = { - {"set", OPT_KEYBOARD_FILE, RC_STR, &options.keyboard_file, - NULL}, - {NULL, NULL, RC_NONE, NULL, NULL} - }; /* End rc_parse_values */ - - if (!file_exists(filename)) { - fprintf(stderr, - "Your resource file doesn't seem to exist.\n"); - fprintf(stderr, "I'll create one for you at \"%s\"\n", - filename); - fflush(stderr); - setup_default_rcfile(filename); - } - /* End if */ - read_ConfigFile(filename, rc_parse_values, 1); -} /* End parse_user_resource_file() */ - -/* Read one line from the specified file pointer and return it as - * as a pointer to char and so on. - */ -static void FILE_readline(FILE * fp, char *buffer, const int maxlen) -{ - int index = 0; - int x; - char tmp; - - do { - x = fread(&tmp, sizeof(char), 1, fp); - if ((x == 0) || (tmp == '\n')) - buffer[index] = '\0'; /* Terminate the string with a NULL */ - else - buffer[index++] = tmp; /* Add the character */ - if (!(index < maxlen)) { - fprintf(Q, - "Error on FILE_readline: index >= maxlen\n"); - fflush(Q); - return; - } /* End if */ - } while ((x != 0) && (tmp != '\n')); - return; -} /* End FILE_readline */ - -/* Copies a default rcfile from somewhere to the input filename */ -static int setup_default_rcfile(char *file) -{ - FILE *fp; - FILE *dflt; - char buffer[1024]; - char buffer2[1024]; - - if ((fp = fopen(file, "w")) == NULL) { - fprintf(Q, "Couldn't open %s for writing - cannot create ", - file); - fprintf(Q, "default .gtkeyboardrc!\n"); - fflush(Q); - return (0); - } /* End if */ - else { - /* Try to open the distribution-provided rcfile first */ - sprintf(buffer, "%s/%s", options.extrafiles, - PROVIDED_RCFILE); - - if ((dflt = fopen(buffer, "r")) == NULL) { - /* Ok, fine, so we can't open the default one we provided - * with the distribution. We'll just give the user a really - * short and crappy one. - */ - fprintf(Q, "Couldn't open %s: %s.\n", buffer, - g_strerror(errno)); - fprintf(Q, - "Fine then! We'll try something else...\n"); - fflush(Q); - - fprintf(fp, "%s", DEFAULT_RCFILE); - fclose(fp); - fprintf(Q, - "Success writing default .gtkeyboardrc\n"); - fprintf(Q, - "You can edit it to make changes later by editing "); - fprintf(Q, "%s\n", file); - fflush(Q); - return (1); - } /* End if */ - else { - while (!feof(dflt)) { - FILE_readline(dflt, buffer2, 1024); - /* Add a newline because FILE_readline kills them off */ - fprintf(fp, "%s\n", buffer2); - } /* End while */ - - fflush(fp); - fclose(dflt); - fclose(fp); - - fprintf(Q, - "Successfully wrote .gtkeyboardrc from "); - fprintf(Q, - "default. (%s: Distribution provided)\n", - PROVIDED_RCFILE); - } /* End else */ - } /* End else */ - FLUSH_EVERYTHING; - return (1); -} /* End setup_default_rcfile */ - -static int file_exists(const char *filename) -{ - struct stat file_info; - int x; - - STAT_AND_RETURN_IF_BAD(filename, x, file_info); - - return (1); -} /* End file_exists */ - -/* seems that xfree86 computes the timestamps for events like this - * strange but it relies on the *1000-32bit-wrap-around - * if anybody knows exactly how to do it, please contact me - * returns: a timestamp for the - * constructed event - */ -static Time fake_timestamp(void) -{ - int tint; - struct timeval tv; - struct timezone tz; /* is not used since ages */ - gettimeofday(&tv, &tz); - tint = (int) tv.tv_sec * 1000; - tint = tint / 1000 * 1000; - tint = tint + tv.tv_usec / 1000; - return ((Time) tint); -} /* End fake_timestamp() */ - -/* in: id of the root window name of the target window - * returns: id of the target window - * called by: main - */ -static Window find_window(Window top, char *name) -{ - char *wname, *iname; - XClassHint xch; - Window *children, foo; - int revert_to_return; - unsigned int nc; - - if (!strcmp(active_window_name, name)) { - XGetInputFocus(GDK_DISPLAY(), &foo, &revert_to_return); - return (foo); - } - - /* End if */ - /* First the base case */ - if (XFetchName(GDK_DISPLAY(), top, &wname)) { - if (!strncmp(wname, name, strlen(name))) { - XFree(wname); - return (top); /* found it! */ - } - /* End if */ - XFree(wname); - } - /* End if */ - if (XGetIconName(GDK_DISPLAY(), top, &iname)) { - if (!strncmp(iname, name, strlen(name))) { - XFree(iname); - return (top); /* found it! */ - } /* End if */ - XFree(iname); - } - /* End if */ - if (XGetClassHint(GDK_DISPLAY(), top, &xch)) { - if (!strcmp(xch.res_class, name)) { - XFree(xch.res_name); - XFree(xch.res_class); - return (top); /* found it! */ - } /* End if */ - XFree(xch.res_name); - XFree(xch.res_class); - } - /* End if */ - if (!XQueryTree(GDK_DISPLAY(), top, &foo, &foo, &children, &nc) || - children == NULL) - return (0); /* no more windows here */ - - /* check all the sub windows */ - for (; nc > 0; nc--) { - top = find_window(children[nc - 1], name); - if (top) - break; /* we found it somewhere */ - } /* End for */ - - /* Free that mem! Yeehaw!!! */ - if (children) - XFree(children); - - return (top); -} /* End find_window() */ - -/* This just assigns a bunch of things to certain elements of the pointer - * that are shared no matter what type of signal GTKeyboard is sending. - * Prevents code duplication in ugly places - */ -static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev) -{ - xev->type = KeyPress; - xev->display = GDK_DISPLAY(); - xev->root = root; - xev->subwindow = None; - xev->time = fake_timestamp(); - xev->same_screen = True; - xev->state = 0; - xev->x = xev->y = xev->x_root = xev->y_root = 1; -} /* End gtkeyboard_XEvent_common_setup */ - -static int assign_keycode_from_keysym(KeySym foo, XKeyEvent * xev) -{ - unsigned long mask = 0; - char *keyname = (char *) NULL; - - keyname = XKeysymToString(foo); - xev->keycode = XKeysymToKeycode(GDK_DISPLAY(), foo); - - /* Check and assign masks. */ - if (options.SHIFT) { /* Need ShiftMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Shift_L)); - if (!mask) { - /* WTF? Shift_L isn't mapped? OK, try Shift_R */ - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), - XK_Shift_R)); - } - /* End if */ - fprintf(Q, "Shift mask: 0x%lx normal mask 0x%lx\n", mask, - (unsigned long) ShiftMask); - - /* Even if mask is actually 0 because we couldn't find the shift - * key mapped, this just won't do anything at all. - * find_modifier_mask issued a warning about not finding it, too - */ - xev->state |= mask; - options.SHIFT = 0; - } - /* End if */ - if (options.CAPS_LOCK) { /* Need LockMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Caps_Lock)); - fprintf(Q, "Capslock mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) LockMask); - xev->state |= mask; /* Normally LockMask */ - } - /* End if */ - if (options.CONTROL) { /* Need ControlMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Control_L)); - if (!mask) { - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), - XK_Control_R)); - } - /* End if */ - fprintf(Q, "Control mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) ControlMask); - xev->state |= mask; - } - /* End if */ - if (options.ALT) { /* Need Mod1Mask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Alt_L)); - if (!mask) { - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), XK_Alt_R)); - } - /* End if */ - fprintf(Q, "Alt mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) Mod1Mask); - xev->state |= mask; - } - /* End if */ - if (options.NUMLOCK) { - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Num_Lock)); - fprintf(Q, "Numlock: Mask 0x%lx\n", mask); - xev->state |= mask; - } - /* End if */ - if (options.ALT_GR) { - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Mode_switch)); - fprintf(Q, "Alt_GR: Mask 0x%lx\n", mask); - xev->state |= mask; - } - /* End if */ - if (strstr(keyname, "Cyrillic_")) { /* Cyrillic? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_ISO_Group_Shift)); - /* FIXME: How do we get this mask and what does it mean? - * Seems to be XKB_Group. Default 0x2000 - */ - - xev->state |= mask; - } - - - /* End if */ - /* xev->state = xev->state | ButtonMotionMask; */ -#if 0 - fprintf(Q, "Final mask on event: %ld 0x%lx\n", - (unsigned long) xev->state, (unsigned long) xev->state); -#endif - - if (xev->keycode != 0) - return 1; - - else - return 0; -} /* End assign_keycode_from_keysym() */ - -static void keysym_sendkey(KeySym somesym, Window w) -{ - gtkeyboard_XEvent_common_setup((XKeyEvent *) & xev); - - /* assign_keycode_from_keysym() will also add in the needed - * masks. WARNING: This may change options.SHIFT and other - * bitflags in options according to whether or not they should - * change. - */ - if (!assign_keycode_from_keysym(somesym, (XKeyEvent *) & xev)) { - return; - } - /* End if */ - xev.xkey.window = w; - - /* This may produce a BadWindow error with Xlib. Bummer. - * This happens most commonly when the window that was selected to - * redirect to doesn't exist on screen anymore. - */ - gdk_error_trap_push(); /* Catch errors, hopefully */ - - XSendEvent(GDK_DISPLAY(), w, True, KeyPressMask, &xev); - - XSync(GDK_DISPLAY(), False); - - xev.type = KeyRelease; /* Start the next Event */ - /* usleep(50000); */ -#if 0 - XFlush(GDK_DISPLAY()); -#endif - xev.xkey.time = fake_timestamp(); - XSendEvent(GDK_DISPLAY(), w, True, KeyReleaseMask, &xev); - XSync(GDK_DISPLAY(), False); - -#if 0 - gdk_flush(); -#endif - - if (gdk_error_trap_pop()) { - } - /* End if */ - return; -} /* End keysym_sendkey() */ - -/* Insert KeyCode code into slot slot in the table structure. - * Returns != 0 on success, 0 on failure. Failure means that - * the table is full, or that the code you're trying to insert is 0 - */ -static int ModmapTable_insert(ModmapTable * table, KeyCode code, int slot) -{ - int x = 0; - - if ((code == (KeyCode) 0) || (slot < 0) || (slot > 8)) - /* This operation makes no sense. Return failure. */ - return 0; - - for (x = 0; x < table->max_keypermod; x++) { - /* Insert in the first available open slot - * but not in taken slots. That would be a bad idea to - * silently overwrite some of the caller's data. :) - */ - if (table->modifiers[slot].codes[x] == 0) { - table->modifiers[slot].codes[x] = code; - return 1; - } /* End if */ - } /* End for */ - - /* Fail - can't find empty slot */ - return (0); -} /* End ModmapTable_insert() */ - -static ModmapTable *ModmapTable_new(void) -{ - XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); - ModmapTable *table; - int mkpm = map->max_keypermod; - int x = 0; - int y = 0; - - XFreeModifiermap(map); - table = g_new0_(ModmapTable, 1); - table->max_keypermod = mkpm; - - for (x = 0; x < 8; x++) { - for (y = 0; y < 4; y++) { - table->modifiers[x].codes[y] = (KeyCode) 0; - } /* End for */ - } /* End for */ - - return table; -} /* End ModmapTable_new() */ - -static void ModmapTable_destroy(ModmapTable * table) -{ - g_free_(table); -} /* End ModmapTable_destroy() */ - -/* Translates a string mask name into a slot number for access to numerous - * modmap data structures. - */ -static int mask_name_to_slot_number(char *maskname) -{ - char *masks[] = { "ShiftMask", "LockMask", - "ControlMask", "Mod1Mask", - "Mod2Mask", "Mod3Mask", - "Mod4Mask", "Mod5Mask" - }; - int maskcount = 8; - int y = 0; - - for (y = 0; y < maskcount; y++) { - if (g_ascii_strcasecmp(maskname, masks[y]) == 0) - return y; - } /* End for */ - - return (-1); -} /* End mask_name_to_slot_number() */ - -static unsigned long find_modifier_mask(KeyCode code) -{ - XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); - int x = 0, y = 0; - KeyCode c = (KeyCode) NULL; - unsigned long mask = 0; - - if (code == (KeyCode) 0) { - XFreeModifiermap(map); - fprintf(Q, - "Error finding modifier mask for 0 keycode: Have you\n"); - fprintf(Q, - "actually remapped your keyboard to this layout?\n"); - return 0; - } - /* End if */ - for (x = 0; x < 8; x++) { - for (y = 0; y < map->max_keypermod; y++) { - c = map->modifiermap[x * map->max_keypermod + y]; - if (c == code) { - XFreeModifiermap(map); - mask = slot_number_to_mask(x); - fprintf(Q, - "Found modifier %d in slot (%d,%d) mask %ld 0x%lx\n", - code, x, y, mask, mask); - return mask; - } /* End if */ - } /* End for */ - } /* End for */ - - XFreeModifiermap(map); - - /* Return nothing. This is bad, but better than doing the wrong thing. */ - fprintf(Q, - "***** WARNING: find_modifier_mask failed to locate code %d\n", - code); - fflush(Q); - return 0; -} /* End find_modifier_mask() */ - - -/* Makes a NULL-terminated string that gets passed as input nothing but - * upper case characters. - * - * THIS FUNCTION MODIFIES ITS ARGUMENT - */ -static void str_toupper(char *string) -{ - int x = 0; - - while (string[x]) { /* Stop on NULL */ - string[x] = toupper(string[x]); - x++; - } /* End while */ -} /* End str_toupper() */ - -/* Passed - the filename, the set of variables to look for, (see the header - * file for the definition of that structure) and an integer - if it's 0, - * then "syntax error" messages won't be printed. Otherwise, we'll complain. - */ -static int read_ConfigFile(char *filename, RCVARS * vars, int complain) -{ - gint n = 0; - gpointer N; - FILE *rcFile; - GHashTable *H; - gchar Line[BUFSIZ], varPrefix[BUFSIZ], varName[BUFSIZ], - varVal[BUFSIZ]; - - /* if the RC file doesn't exist, don't bother doing anything else */ - if ((rcFile = fopen(filename, "r")) == NULL) { - if (complain) { - fprintf(Q, "Couldn't open %s for reading: %s\n", - filename, g_strerror(errno)); - fflush(Q); - } /* End if */ - return 1; - } - - /* End if */ - /* Create a hash table of all the variable names and their arrayindex+1 */ - H = g_hash_table_new(g_str_hash, g_str_equal); - - n = 0; - /* Hash in all of the variable names. Later when we read them in, - * we'll hash in what we read to compare it against what was in the - * table passed to us. - */ - while (vars[n].Type != RC_NONE) { - g_hash_table_insert(H, vars[n].Name, - GINT_TO_POINTER(n + 1)); - n++; - } /* End while */ - - /* read each line of the RC file */ - while (fgets(Line, BUFSIZ, rcFile) != NULL) { - /* Strip leading and trailing whitespace from the string */ - strcpy(Line, g_strstrip(Line)); - - /* Skip comments and lines too short to have useful information - * in them. This will include "blank" lines that got g_strstrip'd - * down to 0 or 1 bytes - */ - if ((strlen(Line) < 2) || Line[0] == '#') - continue; - - /* Initialize values so in case of error they will be NULL, not - * the value of the last parse. - */ - varPrefix[0] = varName[0] = varVal[0] = '\0'; - - /* grab each variable and its value (maybe). - * If prefix is specified, it tries to read the - * given prefix. - */ - if (strstr(Line, "=")) - sscanf(Line, " %s = %s\n", varName, varVal); - else - sscanf(Line, " %s %s %s\n", varPrefix, varName, - varVal); - - /* Sometimes prefix *could* be null, but if name or value is - * null, there's really nothing we can do with that string. - */ - if (!varName[0] && !varVal[0]) { - if (complain) { - fprintf(stderr, - "Error parsing line \"%s\": ", - Line); - fprintf(stderr, - "I have no idea what that line means.\n"); - fflush(stderr); - } - /* End if */ - continue; - } - - /* End if */ - /* We want the rc file to be case insensitive, but we're looking for - * all upper-case varaible names, so convert the string to all - * upper-case so it will hash in correctly. - */ - str_toupper(varName); - - /* use the hash table to find the correct array entry */ - if ((N = g_hash_table_lookup(H, varName)) == NULL) { - continue; /* but skip to the next line if can't find it. */ - } - /* End if */ - n = GPOINTER_TO_INT(N) - 1; /* convert back into an array index */ - - /* We can't necessarily match the read prefix to the requested - * prefix since the prefixes may be different and may require - * processing through the function pointer associated with the - * record - */ - - /* - * Did we see a prefix when we didn't want one? - */ - if (!vars[n].Prefix && varPrefix[0]) { - fprintf(stderr, - "Error: Bad syntax. I wasn't expecting to see "); - fprintf(stderr, "a variable prefix on \"%s\".\n", - (varName ? varName : Line)); - fprintf(stderr, "Ignoring line \"%s\"\n", Line); - fflush(stderr); - continue; - } - - /* End if */ - /* Are we supposed to run this one through a function? */ - if (vars[n].Type == RC_PARSE_FUNC) { - /* Use the outside function specified in the structure - * to parse these line elements since their grammar is - * somewhat weird - */ - if (!vars[n]. - func(varPrefix, varName, varVal, - vars[n].Val)) { - fprintf(stderr, - "There was an error parsing \"%s\"\n", - Line); - fflush(stderr); - } - /* End if */ - continue; /* Done with this line */ - } - - /* End if */ - /* We're not supposed to run this through a function -- - * based on the variable's type, set the C variable to its saved - * value - */ - switch (vars[n].Type) { - case (RC_STR): - { - char *tok; - - /* varVal is not trustworthy, find the string - * within the quotes and use that instead. - */ - if (strstr(Line, "\"")) { - tok = strtok(Line, "\""); - if (!tok) { - /* This really shouldn't happen */ - if (complain) { - fprintf(stderr, - "Parse error within \"%s\"\n", - Line); - fflush(stderr); - } /* End if */ - break; - } /* End if */ - tok = strtok(NULL, "\""); - } /* End if */ - else - tok = &varVal[0]; - - /* free the current contents of the variable */ - if (*(gchar **) (vars[n].Val)) - g_free_(*(gchar **) vars[n].Val); - - /* set the variable to its new value. */ - if (tok) { - *(gchar **) (vars[n].Val) = - g_strdup_(tok); - } /* End if */ - else - *(gchar **) (vars[n].Val) = - (char *) NULL; - break; - } /* End block */ - } /* End switch */ - } /* End while */ - - /* clean up and exit */ - g_hash_table_destroy(H); - fclose(rcFile); - return 0; -} /* End read_ConfigFile() */ - -static KEY *gtkeyboard_key_copy(KEY * key) -{ - KEY *newkey; - - if (!key) - return (NO_KEY); - - newkey = gtkeyboard_new_key(key->lower_case, - key->upper_case, - key->alt_gr, key->aux_string); - newkey->code = key->code; - return (newkey); -} /* End gtkeyboard_key_copy() */ - -/* Returns the "keyno"th key in row "row" of keyb - * This is allocated memory which must be g_free()'d later. - * This will ALWAYS return allocated memory - it just might always be - * filled with NoSymbol - */ -static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, - int keyno) -{ - KEY *foobar; - int index; - int x, findex = 0; - - foobar = gtkeyboard_new_key(NoSymbol, NoSymbol, NoSymbol, NULL); - - if (row > MAXIMUM_ROWS) { - fprintf(stderr, - "gtkeyboard_keyboard_get_key: Row out of range.\n"); - fflush(stderr); - return (foobar); - } - /* End if */ - if (!keyb) { - fprintf(stderr, - "gtkeyboard_keyboard_get_key: Null keyb.\n"); - fflush(stderr); - return (foobar); - } - /* End if */ - x = findex = 0; - - while (x < row) { - /* Add up the number of keys on all lines preceeding the one we're - * looking for - */ - findex += keyb->row_values[x]; - x++; - } /* End while */ - - index = (findex * 3) + (keyno * 3); - - if (index > ((keyb->keycount * 3) - 3)) { - fprintf(stderr, "gtkeyboard_keyboard_get_key(): "); - fprintf(stderr, - "Illegal index %d of a total keycount of %d (%d).\n", - index, keyb->keycount, ((keyb->keycount * 3) - 3)); - fflush(stderr); - return (foobar); - } - - /* End if */ - /* Three consecutive KeySyms */ - foobar->lower_case = keyb->syms[index]; - foobar->upper_case = keyb->syms[(index + 1)]; - foobar->alt_gr = keyb->syms[(index + 2)]; - foobar->aux_string = (char *) NULL; /* No auxilliary */ - - if (keyb->codes) - foobar->code = keyb->codes[(findex + keyno)]; - else - foobar->code = 0; - - return (foobar); -} /* End gtkeyboard_keyboard_get_key() */ - -static KEY *gtkeyboard_new_key(const KeySym lower, const KeySym upper, - const KeySym altgr, const char *alt) -{ - KEY *somekey = g_new0_(KEY, 1); - somekey->lower_case = lower; - somekey->upper_case = upper; - somekey->alt_gr = altgr; - somekey->code = 0; - if (alt) { - somekey->aux_string = g_strdup_(alt); - } /* End if */ - else - somekey->aux_string = NULL; - - return (somekey); -} /* End gtkeyboard_new_key() */ - -static KEY *gtkeyboard_destroy_key(KEY * input) -{ - if (!input) { - fprintf(Q, - "Error: gtkeyboard_destroy_key: NULL argument.\n"); - fflush(Q); - return (NO_KEY); - } - /* End if */ - if (input->aux_string) { - g_free_(input->aux_string); - input->aux_string = (char *) NULL; - } - /* End if */ - g_free_(input); - input = NO_KEY; /* Null pointer so it won't be reused */ - - return (NO_KEY); -} /* End gtkeyboard_destroy_key() */ - -static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input) -{ - if (!input) { - fprintf(stderr, - "gtkeyboard_destroy_keyboard: Cannot destroy NULL ptr.\n"); - fflush(stderr); - return (NO_KEYBOARD); - } - /* End if */ - if (input->syms) { - g_free_(input->syms); - input->syms = NULL; - } - /* End if */ - if (input->name) { - g_free_(input->name); - input->name = NULL; - } - /* End if */ - if (input->codes) { - g_free_(input->codes); - input->codes = NULL; - } - /* End if */ - if (input->modmap) { - ModmapTable_destroy(input->modmap); - input->modmap = (ModmapTable *) NULL; - } - /* End if */ - if (input->trans) { - CONDFREE(input->trans->space); - CONDFREE(input->trans->tab); - CONDFREE(input->trans->alt_gr); - CONDFREE(input->trans->alt); - CONDFREE(input->trans->control); - CONDFREE(input->trans->shift); - CONDFREE(input->trans->backspace); - - /* Free the parent pointer */ - CONDFREE(input->trans); - } - /* End if */ - g_free_(input); - input = NO_KEYBOARD; - - return (NO_KEYBOARD); -} /* End gtkeyboard_destroy_keyboard() */ - -static int get_valid_line(FILE * fp, char *mem, const int maxlen) -{ - mem[0] = '\0'; - - while (!feof(fp) && mem[0] == '\0') { - FILE_readline(fp, mem, maxlen); - - if (mem[0] != '\0') { - strcpy(mem, g_strstrip(mem)); - - if ((mem[0] && mem[0] == '#') - || (mem[0] && mem[0] == '!')) - mem[0] = '\0'; - } /* End if */ - } /* End while */ - - if (mem[0] == '\0') - return (0); - - else - return (1); -} /* End get_valid_line() */ - -/* Parses the contents of a keyboard description file and returns - * a corresponding KEYBOARD structure. - */ -static KEYBOARD *read_keyboard_template(char *filename) -{ - KEYBOARD *keyb = NO_KEYBOARD; - FILE *fp; - register int x = 0, y = 0; - int line_size = 1024; - int index = 0; - char linedata[line_size]; - char **tokens; - char **tofree; - char *ptr; - - if (!filename || !file_exists(filename)) { - fprintf(stderr, "Error loading keyboard file \"%s\": ", - (filename ? filename : "NULL")); - fprintf(stderr, "File doesn't exist."); - fflush(stderr); - return (NO_KEYBOARD); - } - /* End if */ - fp = fopen(filename, "r"); - - if (!fp) { - return (NO_KEYBOARD); - } - /* End if */ - linedata[0] = '\0'; - - if (!get_valid_line(fp, linedata, line_size)) { - fclose(fp); - return (NO_KEYBOARD); - } - /* End if */ - keyb = g_new0_(KEYBOARD, 1); - keyb->modmap = ModmapTable_new(); - - tofree = g_strsplit(linedata, " ", -1); - tokens = tofree; - - keyb->keycount = 0; - keyb->trans = g_new_(KeyboardTranslation, 1); - - /* Initialize it's various elements */ - keyb->trans->shift = keyb->trans->backspace = keyb->trans->space = - keyb->trans->caps_lock = keyb->trans->control = - keyb->trans->tab = keyb->trans->alt = keyb->trans->alt_gr = - (char *) NULL; - - for (x = 0; x < MAXIMUM_ROWS; x++) { - if (*tokens) - ptr = *tokens++; - else - ptr = NULL; - - if (ptr) - keyb->row_values[x] = atoi(ptr); - else { - *tokens = NULL; - keyb->row_values[x] = 0; - } /* End else */ - - keyb->keycount += keyb->row_values[x]; - } /* End for */ - - g_strfreev(tofree); - tofree = tokens = NULL; - ptr = NULL; - - /* We now know how many keys we have to allocate, how many lines to read, - * and all that good stuff. - * - * Each key must have 3 syms, (lower case, upper case, and Alt Gr) - * So allocate 3*keyb->keycount items, and read keyb->keycount lines. - */ - keyb->syms = g_new0_(KeySym, (3 * keyb->keycount)); - keyb->codes = g_new0_(KeyCode, keyb->keycount); - keyb->name = g_strdup_(filename); /* Save the name of the keyboard */ - - for (x = 0; x < keyb->keycount; x++) { - keyb->codes[x] = 0; /* Initialize that keycode since we're already - * paying the price of the loop and it needs - * to be done. - */ - - if (!get_valid_line(fp, linedata, line_size)) { - fprintf(stderr, - "Error reading file %s: Bad line %d.\n", - filename, (x + 1)); - fflush(stderr); - fflush(stderr); - keyb = gtkeyboard_destroy_keyboard(keyb); - fclose(fp); - return (NO_KEYBOARD); - } - /* End if */ - tokens = tofree = g_strsplit(linedata, " ", -1); - - for (y = 0; y < 3; y++) { - if (*tokens) - ptr = *tokens++; - else - ptr = NULL; - - index = (x * 3) + y; - - if (ptr) { - /* Translate a string into a KeySym */ - keyb->syms[index] = XStringToKeysym(ptr); - - /* Error check that KeySym */ - if (!keyb->syms[index] - || keyb->syms[index] == NoSymbol) { - keyb->syms[index] = NoSymbol; - keyb = - gtkeyboard_destroy_keyboard - (keyb); - return (NO_KEYBOARD); - } /* End if */ - } /* End if */ - else { - /* This kinda sucks */ - keyb->syms[index] = NoSymbol; - } /* End else */ - } /* End for */ - - if (ptr) { - ptr = *tokens++; - } - - /* End if */ - /* Grab the KeyCode if it's there */ - keyb->codes[x] = atoi(ptr ? ptr : "0"); - - if (ptr) { - ptr = *tokens++; - } - /* End if */ - if (ptr && strcmp(ptr, "") != 0) { -#if 0 - fprintf(Q, "Reading proposed mask \"%s\"\n", ptr); - fflush(Q); -#endif - - if (!ModmapTable_insert - (keyb->modmap, keyb->codes[x], - mask_name_to_slot_number(ptr))) { - fprintf(Q, - "*** Warning: Failed to insert %d into %d\n", - keyb->codes[x], - mask_name_to_slot_number(ptr)); - } - /* End if */ -#if 0 - fprintf(Q, "Inserted code %d in slot %d\n", - keyb->codes[x], - mask_name_to_slot_number(ptr)); - fflush(Q); -#endif - } - /* End if */ - g_strfreev(tofree); - } /* End for */ - - fclose(fp); - - return (keyb); -} /* End read_keyboard_template() */ - -static void send_redirect_a_keysym(KeySym input) -{ - Window window; - int revert_to; - - if (!options.other || options.other == (Window) NULL) { - /* SEND_TO_BOTH_WINDOWS was probably set and there wasn't - * a redirect window to send to. Let's save the time involved - * with doing all this string crap and just jump out here. - */ - return; - } - /* End if */ - if (options.other) { - /* send to window user picked */ - keysym_sendkey(input, options.other); - } /* End if */ - else { - /* default to just send the event to whatever window has the input - * focus - */ - XGetInputFocus(GDK_DISPLAY(), &window, &revert_to); - keysym_sendkey(input, window); - } /* End else */ -} /* End send_redirect_a_keysym() */ - -gint track_focus(gpointer data) -{ - Window winFocus; - Window wfcopy; - int revert_to_return; - char *winName; - - - /* find out which window currently has focus */ - XGetInputFocus(GDK_DISPLAY(), &winFocus, &revert_to_return); - wfcopy = winFocus; - - /* Return if the window is the same or if it's the program - * window or if we can't redirect to that window. - * - * If there was a previous window that was any good, stick to - * that one. - */ - if (winFocus == options.redirect_window || - winFocus == GUI.xwindow || - winFocus == None || winFocus == PointerRoot) { - return TRUE; - } - - - - /* End if */ - /* At this point, we know the window is "good" and that we want - * it's name. We're going to use it as the redirect from now on. - */ - /* set up error trapping, in case we get a BadWindow error */ - gdk_error_trap_push(); - - /* this could generate the error */ - XFetchName(GDK_DISPLAY(), winFocus, &winName); - if (!winName) - winName = "Unknown"; - - gdk_flush(); - - if (gdk_error_trap_pop()) { - /* Oops...error. Probably BadWindow */ - CONDFREE(options.redirect_window_name); - - options.redirect_window = None; /* reset focus window */ - options.other = None; - - printf - ("There was an error finding a valid redirect window.\n"); - return TRUE; /* better luck next time */ - } - - /* End if */ - /* since we made it this far, update the window_name */ - if (winName) { - CONDFREE(options.redirect_window_name); - - /* Grab the window definition */ - options.redirect_window = wfcopy; - options.other = wfcopy; - - options.redirect_window_name = g_strdup_(winName); - } /* End if */ - return TRUE; -} /* End track_focus */ diff --git a/gui/gtk/gtkeyboard.h b/gui/gtk/gtkeyboard.h deleted file mode 100644 index fef9fa7a..00000000 --- a/gui/gtk/gtkeyboard.h +++ /dev/null @@ -1,3 +0,0 @@ -int init_keyboard_stuff(char *input); -GtkWidget *build_keyboard(GtkWidget * input, char *filename); -gint track_focus(gpointer data); diff --git a/gui/gtk/gui_gtk.h b/gui/gtk/gui_gtk.h index 6c7792f1..1b968ef5 100644 --- a/gui/gtk/gui_gtk.h +++ b/gui/gtk/gui_gtk.h @@ -1,5 +1,22 @@ +struct statusbar_methods; +struct menu_methods; +struct navit; -struct statusbar *gui_gtk_statusbar_new(GtkWidget **widget); -void gui_gtk_actions_new(struct container *co, GtkWidget **vbox); -struct container * gui_gtk_window(int x, int y, int scale); +struct gui_priv { + struct navit *nav; + GtkWidget *win; + GtkWidget *vbox; + GtkWidget *menubar; + GtkActionGroup *base_group; + GtkActionGroup *debug_group; + GtkActionGroup *dyn_group; + GtkUIManager *menu_manager; + void *statusbar; + int dyn_counter; +}; + +struct menu_priv *gui_gtk_menubar_new(struct gui_priv *gui, struct menu_methods *meth); +struct menu_priv *gui_gtk_toolbar_new(struct gui_priv *gui, struct menu_methods *meth); +struct statusbar_priv *gui_gtk_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth); +struct menu_priv *gui_gtk_popup_new(struct gui_priv *gui, struct menu_methods *meth); diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index b8386cbb..d1867be8 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -1,69 +1,101 @@ #include #include +#include "navit.h" #include "graphics.h" #include "gui_gtk.h" -#include "container.h" #include "menu.h" -#include "data_window.h" #include "coord.h" -#include "destination.h" -struct action_gui { - struct container *co; +struct menu_priv { + char *path; + GtkAction *action; + struct gui_priv *gui; + enum menu_type type; + void (*callback)(struct menu *menu, void *data1, void *data2); + struct menu *callback_menu; + void *callback_data1; + void *callback_data2; + struct menu_priv *child; + struct menu_priv *sibling; + gulong handler_id; + guint merge_id; }; -#include "action.h" - - /* Create callbacks that implement our Actions */ static void -zoom_in_action(GtkWidget *w, struct action *ac) +zoom_in_action(GtkWidget *w, struct navit *nav, void *dummy) { - unsigned long scale; - graphics_get_view(ac->gui->co, NULL, NULL, &scale); - scale/=2; - if (scale < 1) - scale=1; - graphics_set_view(ac->gui->co, NULL, NULL, &scale); + navit_zoom_in(nav, 2); } static void -zoom_out_action(GtkWidget *w, struct action *ac) +zoom_out_action(GtkWidget *w, struct navit *nav, void *dummy) { - unsigned long scale; - graphics_get_view(ac->gui->co, NULL, NULL, &scale); - scale*=2; - graphics_set_view(ac->gui->co, NULL, NULL, &scale); + navit_zoom_out(nav, 2); } static void -refresh_action(GtkWidget *w, struct action *ac) +refresh_action(GtkWidget *w, struct navit *nav, void *dummy) { - menu_route_update(ac->gui->co); + navit_draw(nav); } static void -cursor_action(GtkWidget *w, struct action *ac) +cursor_action(GtkWidget *w, struct navit *nav, void *dummy) { + navit_toggle_cursor(nav); +#if 0 ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); +#endif } static void -orient_north_action(GtkWidget *w, struct action *ac) +orient_north_action(GtkWidget *w, struct navit *nav, void *dummy) { +#if 0 ac->gui->co->flags->orient_north=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); +#endif } +#include +#include "point.h" +#include "transform.h" + static void -destination_action(GtkWidget *w, struct action *ac) +info_action(GtkWidget *w, struct navit *nav, void *dummy) { - destination_address(ac->gui->co); + char buffer[512]; + int mw,mh; + struct coord lt, rb; + struct point p; + struct transformation *t; + + t=navit_get_trans(nav); + transform_get_size(t, &mw, &mh); + p.x=0; + p.y=0; + transform_reverse(t, &p, <); + p.x=mw; + p.y=mh; + transform_reverse(t, &p, &rb); + + sprintf(buffer,"./info.sh %d,%d 0x%x,0x%x 0x%x,0x%x", mw, mh, lt.x, lt.y, rb.x, rb.y); + system(buffer); + +} + + + +static void +destination_action(GtkWidget *w, struct navit *nav, void *dummy) +{ + destination_address(nav); } static void -quit_action (GtkWidget *w, struct action *ac) +quit_action (GtkWidget *w, struct navit *nav, void *dummy) { gtk_main_quit(); } @@ -71,36 +103,46 @@ quit_action (GtkWidget *w, struct action *ac) static void visible_blocks_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); graphics_redraw(co); +#endif } static void visible_towns_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); graphics_redraw(co); +#endif } static void visible_polys_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); graphics_redraw(co); +#endif } static void visible_streets_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); graphics_redraw(co); +#endif } static void visible_points_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); graphics_redraw(co); +#endif } @@ -108,10 +150,14 @@ static GtkActionEntry entries[] = { { "DisplayMenuAction", NULL, "Display" }, { "RouteMenuAction", NULL, "Route" }, + { "Map", NULL, "Map" }, + { "LayoutMenuAction", NULL, "Layout" }, { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, + { "InfoAction", GTK_STOCK_INFO, "Info", NULL, NULL, G_CALLBACK(info_action) }, { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, + { "Test", NULL, "Test", NULL, NULL, G_CALLBACK(destination_action) }, { "QuitAction", GTK_STOCK_QUIT, "_Quit", "Q",NULL, G_CALLBACK (quit_action) } }; @@ -232,6 +278,7 @@ static struct { {"flag_icon", flag_xpm } }; + static gint n_stock_icons = G_N_ELEMENTS (stock_icons); @@ -259,17 +306,11 @@ register_my_stock_icons (void) g_object_unref(icon_factory); } -static void -action_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) -{ - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); -} static char layout[] = "\ - \ - \ + \ + \ \ \ \ @@ -277,7 +318,7 @@ static char layout[] = \ \ \ - \ + \ \ \ \ @@ -285,13 +326,13 @@ static char layout[] = \ \ \ - \ + \ \ \ \ \ \ - \ + \ \ \ \ @@ -300,46 +341,170 @@ static char layout[] = \ \ \ + \ \ \ \ \ + \ + \ "; - + + +static void +activate(void *dummy, struct menu_priv *menu) +{ + if (menu->callback) + (*menu->callback)(menu->callback_menu, menu->callback_data1, menu->callback_data2); +} + +static struct menu_methods menu_methods; -void -gui_gtk_actions_new(struct container *co, GtkWidget **vbox) +static struct menu_priv * +add_menu(struct menu_priv *menu, struct menu_methods *meth, char *name, enum menu_type type, void (*callback)(struct menu *data_menu, void *data1, void *data2), struct menu *data_menu, void *data1, void *data2) { - GtkActionGroup *base_group,*debug_group; - GtkUIManager *menu_manager; - GError *error; + struct menu_priv *ret; + char *dynname; + + ret=g_new0(struct menu_priv, 1); + *meth=menu_methods; + if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Route")) { + dynname=g_strdup("Route"); + } else { + dynname=g_strdup_printf("%d", menu->gui->dyn_counter++); + if (type == menu_type_toggle) + ret->action=GTK_ACTION(gtk_toggle_action_new(dynname, name, NULL, NULL)); + else + ret->action=gtk_action_new(dynname, name, NULL, NULL); + if (callback) + ret->handler_id=g_signal_connect(ret->action, "activate", G_CALLBACK(activate), ret); + gtk_action_group_add_action(menu->gui->dyn_group, ret->action); + ret->merge_id=gtk_ui_manager_new_merge_id(menu->gui->menu_manager); + gtk_ui_manager_add_ui( menu->gui->menu_manager, ret->merge_id, menu->path, dynname, dynname, type == menu_type_submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE); + } + ret->gui=menu->gui; + ret->path=g_strdup_printf("%s/%s", menu->path, dynname); + ret->type=type; + ret->callback=callback; + ret->callback_menu=data_menu; + ret->callback_data1=data1; + ret->callback_data2=data2; + ret->sibling=menu->child; + menu->child=ret; + g_free(dynname); + return ret; + +} - struct action *this=g_new0(struct action, 1); +static void +remove_menu(struct menu_priv *item, int recursive) +{ - this->gui=g_new0(struct action_gui, 1); - this->gui->co=co; + if (recursive) { + struct menu_priv *next,*child=item->child; + while (child) { + next=child->sibling; + remove_menu(child, recursive); + child=next; + } + } + if (item->action) { + gtk_ui_manager_remove_ui(item->gui->menu_manager, item->merge_id); + gtk_action_group_remove_action(item->gui->dyn_group, item->action); +#if 0 + if (item->callback) + g_signal_handler_disconnect(item->action, item->handler_id); +#endif + g_object_unref(item->action); + } + g_free(item->path); + g_free(item); +} - register_my_stock_icons(); +static void +set_toggle(struct menu_priv *menu, int active) +{ + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(menu->action), active); +} - base_group = gtk_action_group_new ("BaseActions"); - debug_group = gtk_action_group_new ("DebugActions"); - menu_manager = gtk_ui_manager_new (); +static int +get_toggle(struct menu_priv *menu) +{ + return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(menu->action)); +} - gtk_action_group_add_actions (base_group, entries, n_entries, this); - gtk_action_group_add_toggle_actions (base_group, toggleentries, n_toggleentries, this); - gtk_ui_manager_insert_action_group (menu_manager, base_group, 0); +static struct menu_methods menu_methods = { + add_menu, + set_toggle, + get_toggle, +}; - gtk_action_group_add_actions (debug_group, debug_entries, n_debug_entries, co); - gtk_ui_manager_insert_action_group (menu_manager, debug_group, 0); - error = NULL; - gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); +static void +popup_deactivate(GtkWidget *widget, struct menu_priv *menu) +{ + g_signal_handler_disconnect(widget, menu->handler_id); + remove_menu(menu, 1); +} - if (error) { - g_message ("building menus failed: %s", error->message); - g_error_free (error); +static struct menu_priv * +gui_gtk_ui_new (struct gui_priv *this, struct menu_methods *meth, char *path, int popup, GtkWidget **widget_ret) +{ + struct menu_priv *ret; + GError *error; + GtkWidget *widget; + + *meth=menu_methods; + ret=g_new0(struct menu_priv, 1); + ret->path=g_strdup(path); + ret->gui=this; + if (! this->menu_manager) { + this->base_group = gtk_action_group_new ("BaseActions"); + this->debug_group = gtk_action_group_new ("DebugActions"); + this->dyn_group = gtk_action_group_new ("DynamicActions"); + register_my_stock_icons(); + this->menu_manager = gtk_ui_manager_new (); + gtk_action_group_add_actions (this->base_group, entries, n_entries, this->nav); + gtk_action_group_add_toggle_actions (this->base_group, toggleentries, n_toggleentries, this->nav); + gtk_ui_manager_insert_action_group (this->menu_manager, this->base_group, 0); + gtk_action_group_add_actions (this->debug_group, debug_entries, n_debug_entries, this->nav); + gtk_ui_manager_insert_action_group (this->menu_manager, this->debug_group, 0); + gtk_ui_manager_add_ui_from_string (this->menu_manager, layout, strlen(layout), &error); + gtk_ui_manager_insert_action_group (this->menu_manager, this->dyn_group, 0); + error=NULL; + if (error) { + g_message ("building menus failed: %s", error->message); + g_error_free (error); + } + } + widget=gtk_ui_manager_get_widget(this->menu_manager, path); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); + if (widget_ret) + *widget_ret=widget; + if (! popup) { + gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + } else { + gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); + ret->handler_id=g_signal_connect(widget, "deactivate", G_CALLBACK(popup_deactivate), ret); } + return ret; +} + +struct menu_priv * +gui_gtk_toolbar_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/ToolBar", 0, NULL); +} - g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); +struct menu_priv * +gui_gtk_menubar_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/MenuBar", 0, &this->menubar); } +struct menu_priv * +gui_gtk_popup_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/PopUp", 1, NULL); +} diff --git a/gui/gtk/gui_gtk_menu.c b/gui/gtk/gui_gtk_menu.c deleted file mode 100644 index 6f6b22b2..00000000 --- a/gui/gtk/gui_gtk_menu.c +++ /dev/null @@ -1,364 +0,0 @@ -#define GTK_ENABLE_BROKEN -#include -#include -#include -#include -#include -#include -#include "coord.h" -#include "graphics.h" -#include "data_window.h" -#include "route.h" -#include "cursor.h" -#include "command.h" -#include "transform.h" -#include "block.h" -#include "street.h" -#include "statusbar.h" -#include "destination.h" -#include "main.h" -#include "container.h" -#include "gui_gtk.h" - -struct menu_gui { - struct container *co; -}; - -#include "menu.h" - -extern struct coord current_pos; - -extern struct data_window *navigation_window; - -struct destination { - struct container *co; - char *text; - struct coord pos; -}; - -static void -menu_window_clone(struct container *co) -{ -#if 0 - void window(int x, int y, int scale); - window(co->trans->center.x, co->trans->center.y, co->trans->scale); -#endif -} - -static gboolean -menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, - GtkWidget *win) -{ - GtkWidget *text; - const char *t; - struct container *co; - - if (! strcmp(event->string,"\r")) { - text=g_object_get_data(G_OBJECT(win), "Input"); - co=g_object_get_data(G_OBJECT(win), "Container"); - t=gtk_entry_get_text(GTK_ENTRY(text)); - if (!strncmp(t,"goto ",5)) { - command_goto(co, t+5); - } - } - return TRUE; -} - - -static void -menu_window_command(struct container *co) -{ - GtkWidget *win,*entry,*text,*box; - win=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(win), 320, 200); - gtk_window_set_title(GTK_WINDOW(win), "Command"); - entry=gtk_entry_new(); - text=gtk_text_new(NULL, NULL); - box=gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(box), entry, 1, 1, 0); - gtk_box_pack_start(GTK_BOX(box), text, 1, 1, 0); - gtk_container_add(GTK_CONTAINER(win), box); - g_object_set_data(G_OBJECT(win), "Container", co); - g_object_set_data(G_OBJECT(win), "Input", entry); - g_object_set_data(G_OBJECT(win), "Output", text); - g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(menu_window_command_key_press), win); - gtk_widget_show_all(win); -} - -static void -menu_window_visible_blocks(struct container *co) -{ - co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_towns(struct container *co) -{ - co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_polys(struct container *co) -{ - co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_streets(struct container *co) -{ - co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_points(struct container *co) -{ - co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_map_compare(struct container *co) -{ - char cmd[256]; - int x_min, x_max, y_min, y_max; - - x_min=co->trans->center.x-co->trans->scale/16*co->trans->width*4/10; - x_max=co->trans->center.x+co->trans->scale/16*co->trans->width*4/10; - y_min=co->trans->center.y-co->trans->scale/16*co->trans->height*4/10; - y_max=co->trans->center.y+co->trans->scale/16*co->trans->height*4/10; - sprintf(cmd, "./get_map %d %d %d %d %d %d ; xv map.xpm &", co->trans->width, co->trans->height, x_min, y_max, x_max, y_min); - system(cmd); -} - -static void -menu_map_distances(struct container *co) -{ - route_display_points(co->route, co); -} - -static void -menu_destination_selected(GtkMenuItem *item, struct destination *dest) -{ - struct container *co =dest->co; - - destination_set(co, destination_type_bookmark, dest->text, &dest->pos); -} - -static void -menu_item(struct menu *me, GtkWidget *menu, char *name, void (*func)(struct container *co)) -{ - GtkWidget *item; - item=gtk_menu_item_new_with_label(name); - gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); - g_signal_connect_swapped(G_OBJECT(item), "activate", - G_CALLBACK(func), me); -} - -static int -menu_clock_update(void *data) -{ - char buffer[16]; - time_t now=time(NULL); - GtkWidget *widget=GTK_WIDGET(data); - struct tm *now_tm=localtime(&now); - - sprintf(buffer,"%02d:%02d", now_tm->tm_hour, now_tm->tm_min); - gtk_label_set_text(GTK_LABEL(widget), buffer); - g_timeout_add((60-now_tm->tm_sec)*1000,menu_clock_update,widget); - return FALSE; -} - -struct menu * -gui_gtk_menu_new(struct container *co, GtkWidget **widget) -{ - struct menu *this=g_new0(struct menu, 1); - - this->gui=g_new0(struct menu_gui,1); - this->gui->co=co; - - - GtkWidget *menu,*item,*menu2,*item2,*menu3,*clock; - - menu=gtk_menu_bar_new(); - item=gtk_menu_item_new_with_label("Goto"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Window"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Clone"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_clone), this); - - item2=gtk_menu_item_new_with_label("Command"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_command), this); - - item2=gtk_menu_item_new_with_label("Visible Blocks"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_blocks), co); - - item2=gtk_menu_item_new_with_label("Visible Towns"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_towns), co); - - item2=gtk_menu_item_new_with_label("Visible Polys"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_polys), co); - - - item2=gtk_menu_item_new_with_label("Visible Streets"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_streets), co); - - menu_item(this, menu2, "Visible Points", menu_window_visible_points); - - item2=gtk_menu_item_new_with_label("Exit"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (exit), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Map"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Compare"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_map_compare), this); - - item2=gtk_menu_item_new_with_label("Distances"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_map_distances), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Route"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Start"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (route_start), co); - - item2=gtk_menu_item_new_with_label("Trace"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (route_trace), co); - - item2=gtk_menu_item_new_with_label("Update"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_route_update), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Destinations"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Last Destinations"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - menu3=gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); - - item2=gtk_menu_item_new_with_label("Address"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - - { - FILE *file; - char buffer[8192]; - double lat,lng,lat_deg,lng_deg; - char lat_c,lng_c; - struct destination *dest; - int pos,len; - char *utf8,*text,*tok,*label; - GList *list; - - file=fopen("locations.txt","r"); - while (file && fgets(buffer,8192,file)) { - dest=g_new0(struct destination,1); - dest->co=co; - len=strlen(buffer)-1; - while (len >= 0 && buffer[len] == '\n') { - buffer[len]='\0'; - } - sscanf(buffer,"%lf %c %lf %c %n",&lat, &lat_c, &lng, &lng_c, &pos); - - lat_deg=floor(lat/100); - lat-=lat_deg*100; - lat_deg+=lat/60; - - lng_deg=floor(lng/100); - lng-=lng_deg*100; - lng_deg+=lng/60; - - transform_mercator(&lng_deg, &lat_deg, &dest->pos); - - text=buffer+pos; - dest->text=strdup(text); - item2=NULL; - menu3=menu2; - while ((tok=strtok(text,"/"))) { - list=NULL; - if (item2) { - menu3=gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); - } - list=gtk_container_get_children(GTK_CONTAINER(menu3)); - while (list) { - item2=GTK_WIDGET(list->data); - label=g_strdup(gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item2))))); - if (!strcmp(label, tok)) { - menu3=gtk_menu_item_get_submenu(GTK_MENU_ITEM(item2)); - break; - } - list=list->next; - } - item2=NULL; - if (! list) { - utf8=g_locale_to_utf8(tok,-1,NULL,NULL,NULL); - item2=gtk_menu_item_new_with_label(utf8); - gtk_menu_shell_append (GTK_MENU_SHELL(menu3), item2); - g_free(utf8); - } - text=NULL; - } - g_signal_connect(G_OBJECT(item2), "activate", - G_CALLBACK (menu_destination_selected), dest); - } - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new(); - clock=gtk_label_new(NULL); - gtk_menu_item_set_right_justified(GTK_MENU_ITEM(item),TRUE); - gtk_container_add(GTK_CONTAINER(item), clock); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - menu_clock_update(clock); - - *widget=menu; - return this; -} diff --git a/gui/gtk/gui_gtk_statusbar.c b/gui/gtk/gui_gtk_statusbar.c index 10950298..b31b8dd3 100644 --- a/gui/gtk/gui_gtk_statusbar.c +++ b/gui/gtk/gui_gtk_statusbar.c @@ -10,7 +10,8 @@ #include "statusbar.h" -struct statusbar_gui { +struct statusbar_priv { + struct gui_priv *gui; GtkWidget *hbox; char mouse_text[128]; GtkWidget *mouse; @@ -22,15 +23,15 @@ struct statusbar_gui { static void -statusbar_destroy(struct statusbar *this) +statusbar_destroy(struct statusbar_priv *this) { - g_free(this->gui); g_free(this); } static void -statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct point *p) +statusbar_mouse_update(struct statusbar_priv *this, struct transformation *tr, struct point *p) { +#if 0 struct coord c; struct coord_geo g; char buffer[128]; @@ -38,12 +39,13 @@ statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct transform_reverse(tr, p, &c); transform_lng_lat(&c, &g); transform_geo_text(&g, buffer); - sprintf(this->gui->mouse_text,"M: %s", buffer); - gtk_label_set_text(GTK_LABEL(this->gui->mouse), this->gui->mouse_text); + sprintf(this->mouse_text,"M: %s", buffer); + gtk_label_set_text(GTK_LABEL(this->mouse), this->mouse_text); +#endif } static void -statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) +statusbar_gps_update(struct statusbar_priv *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) { char lat_c='N'; char lng_c='E'; @@ -62,54 +64,66 @@ statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, dou } dir_idx=(direction+22.5)/45; dir=dirs[dir_idx]; - sprintf(this->gui->gps_text,"GPS %2d/%1d %02.0f%07.4f%c %03.0f%07.4f%c %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c, height, direction, dir, speed); - utf8=g_locale_to_utf8(this->gui->gps_text,-1,NULL,NULL,NULL); - gtk_label_set_text(GTK_LABEL(this->gui->gps), utf8); + sprintf(this->gps_text,"GPS %2d/%1d %02.0f%07.4f%c %03.0f%07.4f%c %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c, height, direction, dir, speed); + utf8=g_locale_to_utf8(this->gps_text,-1,NULL,NULL,NULL); + gtk_label_set_text(GTK_LABEL(this->gps), utf8); g_free(utf8); } static void -statusbar_route_update(struct statusbar *this, struct route *route) +statusbar_route_update(struct statusbar_priv *this, struct route *route) { +#if 0 /* FIXME */ struct tm *eta_tm; double route_len; eta_tm=route_get_eta(route); route_len=route_get_len(route); - sprintf(this->gui->route_text,"Route %4.0fkm %02d:%02d ETA",route_len/1000, eta_tm->tm_hour, eta_tm->tm_min); - gtk_label_set_text(GTK_LABEL(this->gui->route), this->gui->route_text); + sprintf(this->route_text,"Route %4.0fkm %02d:%02d ETA",route_len/1000, eta_tm->tm_hour, eta_tm->tm_min); + gtk_label_set_text(GTK_LABEL(this->route), this->route_text); +#endif } -struct statusbar * -gui_gtk_statusbar_new(GtkWidget **widget) +static struct statusbar_methods methods = { + statusbar_destroy, + statusbar_mouse_update, + statusbar_route_update, + statusbar_gps_update, +}; + +struct statusbar_priv * +gui_gtk_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth) { - struct statusbar *this=g_new0(struct statusbar, 1); + struct statusbar_priv *this=g_new0(struct statusbar_priv, 1); char *utf8; - this->gui=g_new0(struct statusbar_gui,1); - this->statusbar_destroy=statusbar_destroy; - this->statusbar_mouse_update=statusbar_mouse_update; - this->statusbar_route_update=statusbar_route_update; - this->statusbar_gps_update=statusbar_gps_update; + this->gui=gui; + *meth=methods; - this->gui->hbox=gtk_hbox_new(FALSE, 1); - this->gui->mouse=gtk_label_new("M: 0000.0000N 00000.0000E"); - gtk_label_set_justify(GTK_LABEL(this->gui->mouse), GTK_JUSTIFY_LEFT); + this->hbox=gtk_hbox_new(FALSE, 1); + this->mouse=gtk_label_new("M: 0000.0000N 00000.0000E"); + gtk_label_set_justify(GTK_LABEL(this->mouse), GTK_JUSTIFY_LEFT); utf8=g_locale_to_utf8("GPS 00/0 0000.0000N 00000.0000E 0000m 000°NO 000km/h",-1,NULL,NULL,NULL); - this->gui->gps=gtk_label_new(utf8); + this->gps=gtk_label_new(utf8); g_free(utf8); - gtk_label_set_justify(GTK_LABEL(this->gui->gps), GTK_JUSTIFY_LEFT); - this->gui->route=gtk_label_new("Route 0000km 0+00:00 ETA"); - gtk_label_set_justify(GTK_LABEL(this->gui->route), GTK_JUSTIFY_LEFT); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->mouse, FALSE, FALSE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->gps, TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->route, TRUE, TRUE, 2); + gtk_label_set_justify(GTK_LABEL(this->gps), GTK_JUSTIFY_LEFT); + this->route=gtk_label_new("Route 0000km 0+00:00 ETA"); + gtk_label_set_justify(GTK_LABEL(this->route), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(this->hbox), this->mouse, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), this->gps, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), this->route, TRUE, TRUE, 2); + GTK_WIDGET_UNSET_FLAGS (this->hbox, GTK_CAN_FOCUS); + + gtk_box_pack_end(GTK_BOX(gui->vbox), this->hbox, FALSE, FALSE, 0); + gtk_widget_show_all(this->hbox); +#if 0 *widget=this->gui->hbox; +#endif return this; } diff --git a/gui/gtk/gui_gtk_toolbar.c b/gui/gtk/gui_gtk_toolbar.c deleted file mode 100644 index ec27b746..00000000 --- a/gui/gtk/gui_gtk_toolbar.c +++ /dev/null @@ -1,340 +0,0 @@ -#include -#include "graphics.h" -#include "gui_gtk.h" -#include "menu.h" -#include "coord.h" -#include "destination.h" -#include "container.h" - -struct toolbar_gui { - struct container *co; -}; - -#include "toolbar.h" - -static void -zoom_in(GtkWidget *w, struct toolbar *tb) -{ - unsigned long scale; - graphics_get_view(tb->gui->co, NULL, NULL, &scale); - scale/=2; - if (scale < 1) - scale=1; - graphics_set_view(tb->gui->co, NULL, NULL, &scale); -} - -static void -zoom_out(GtkWidget *w, struct toolbar *tb) -{ - unsigned long scale; - graphics_get_view(tb->gui->co, NULL, NULL, &scale); - scale*=2; - graphics_set_view(tb->gui->co, NULL, NULL, &scale); -} - -static void -refresh_route(GtkWidget *w, struct toolbar *tb) -{ - menu_route_update(tb->gui->co); -} - -static void -track(GtkWidget *w, struct toolbar *tb) -{ - if (tb->gui->co->flags->track) { - tb->gui->co->flags->track=0; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } else { - tb->gui->co->flags->track=1; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } -} - -static void -orient_north(GtkWidget *w, struct toolbar *tb) -{ - if (tb->gui->co->flags->orient_north) { - tb->gui->co->flags->orient_north=0; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } else { - tb->gui->co->flags->orient_north=1; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } -} - -static void -destination(GtkWidget *w, struct toolbar *tb) -{ - destination_address(tb->gui->co); -} - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*viewmag_plus_xpm[]={ -"22 22 5 1", -"# c #000000", -"c c #a0a0a4", -"a c #dcdcdc", -"b c #ffffff", -". c None", -"......................", -"......................", -"......................", -"......................", -"......................", -".......####...........", -"......#abba#..........", -".....#abcbba#.........", -".....#bcbbbb#.........", -".....#bbbbbb#.........", -".....#abbbba#.........", -"......#abba##.........", -".......#######........", -"............###.......", -".....#.......###......", -".....#........###.....", -"...#####.......##.....", -".....#................", -".....#................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*viewmag_minus_xpm[]={ -"22 22 5 1", -"# c #000000", -"c c #a0a0a4", -"a c #dcdcdc", -"b c #ffffff", -". c None", -"......................", -"......................", -"......................", -"......................", -"......................", -".......####...........", -"......#abba#..........", -".....#abcbba#.........", -".....#bcbbbb#.........", -".....#bbbbbb#.........", -".....#abbbba#.........", -"......#abba##.........", -".......#######........", -"............###.......", -".............###......", -"..............###.....", -"...#####.......##.....", -"......................", -"......................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*reload_xpm[]={ -"22 22 3 1", -"# c #808080", -"a c #000000", -". c None", -"......................", -"......................", -"......................", -"......................", -"........##aaa#........", -".......#aaaaaaa.......", -"......#aa#....#a......", -"......aa#.............", -".....aaa.......a......", -"...aaaaaaa....aaa.....", -"....aaaaa....aaaaa....", -".....aaa....aaaaaaa...", -"......a.......aaa.....", -".............#aa......", -"......a#....#aa#......", -".......aaaaaaa#.......", -"........#aaa##........", -"......................", -"......................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -static char * cursor_xpm[] = { -"22 22 2 1", -" c None", -". c #0000FF", -" ", -" ", -" ", -" .. ", -" .. .. ", -" .. .. ", -" . . ", -" . . ", -" . ... . ", -" . ... . . ", -" . ... . . ", -" . .. . . ", -" . . . ", -" . . . ", -" . . . ", -" . . . ", -" .. .. ", -" .. .. ", -" .. ", -" ", -" ", -" "}; - - -/* XPM */ -static char * north_xpm[] = { -"22 22 2 1", -" c None", -". c #000000", -" ", -" ", -" . ", -" ... ", -" . . . ", -" . . . ", -" . ", -" .... . .... ", -" .... . .... ", -" .... . .. ", -" .. .. .. ", -" .. .. .. ", -" .. .. .. ", -" .. .. .. ", -" .. . .... ", -" .... . .... ", -" .... . .... ", -" . ", -" . ", -" . ", -" ", -" "}; - - -/* XPM */ -static char * flag_xpm[] = { -"22 22 2 1", -" c None", -"+ c #000000", -"+++++++ ", -"+ +++++++++ ", -"+ +++ +++++++++ ", -"+ +++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ + ", -"+ ++++++ +++ + ", -"+ +++ ++++++ + ", -"+ +++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ ", -"++++++++++ +++ + ", -"+ +++++++++ + ", -"+ ++++++ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ "}; - -static GtkWidget * -xpm_to_widget(GtkWidget *draw, gchar **xpm_data) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *imagewid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - style = gtk_widget_get_style(draw); - - /* In order for this to not create a warning, window has to be a - * gtk_realize_widget (realized) widget - */ - pixmap = gdk_pixmap_create_from_xpm_d(draw->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **)xpm_data ); - - /* a pixmap widget to contain the pixmap */ - imagewid = gtk_image_new_from_pixmap(pixmap, mask); - gtk_widget_show(imagewid); - - return(imagewid); -} - -int tst_stat=1; - -static void -toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data) -{ - GtkWidget *icon; - GtkToolItem *toolitem; - - icon=xpm_to_widget(window, icon_data); - toolitem=gtk_tool_button_new(icon,text); - gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toolitem,-1); - g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(func), data); -} - -static void -toolbar_button_toggle(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data, int *flag) -{ - GtkWidget *icon; - GtkToolItem *toggleitem; - - icon=xpm_to_widget(window, icon_data); - toggleitem=gtk_toggle_tool_button_new(); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toggleitem),icon); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(toggleitem),text); - gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toggleitem,-1); - if(*flag) - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toggleitem),TRUE); - - g_signal_connect(G_OBJECT(toggleitem), "clicked", G_CALLBACK(func), data); -} - - -struct toolbar * -gui_gtk_toolbar_new(struct container *co, GtkWidget **widget) -{ - GtkWidget *toolbar,*window; - struct toolbar *this=g_new0(struct toolbar, 1); - - this->gui=g_new0(struct toolbar_gui, 1); - this->gui->co=co; - - toolbar=gtk_toolbar_new(); - window=(GtkWidget *)(co->win); - - co->flags->track=1; - co->flags->orient_north=1; - - toolbar_button(window, toolbar, viewmag_plus_xpm, "Zoom In", zoom_in, this); - toolbar_button(window, toolbar, viewmag_minus_xpm, "Zoom Out", zoom_out, this); - toolbar_button(window, toolbar, reload_xpm, "Refresh Route", refresh_route, this); - toolbar_button_toggle(window, toolbar, cursor_xpm, "Cursor on/off", track, this, &co->flags->track); - toolbar_button_toggle(window, toolbar, north_xpm, "Orientate North on/off", orient_north, this, &co->flags->orient_north); - toolbar_button(window, toolbar, flag_xpm, "Destination", destination, this); - - *widget=toolbar; - - return this; -} diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index f080bbda..663cbcca 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -1,68 +1,119 @@ #include +#include +#if !defined(GDK_Book) || !defined(GDK_Calendar) +#include +#endif #include +#include "navit.h" +#include "debug.h" +#include "gui.h" #include "coord.h" -#include "transform.h" -#include "container.h" +#include "point.h" +#include "plugin.h" +#include "graphics.h" #include "gui_gtk.h" +#ifndef GDK_Book +#define GDK_Book XF86XK_Book +#endif -extern void container_init_gra(struct container *co); +#ifndef GDK_Calendar +#define GDK_Calendar XF86XK_Calendar +#endif -static struct container * -container_new(GtkWidget **widget) +static gboolean +keypress(GtkWidget *widget, GdkEventKey *event, struct gui_priv *this) { - struct container *co=g_new0(struct container, 1); - extern struct map_data *map_data_default; - struct transformation *t=g_new0(struct transformation, 1); - struct map_flags *flags=g_new0(struct map_flags, 1); - struct graphics *gra; + int w,h; + struct point p; + if (event->type != GDK_KEY_PRESS) + return FALSE; + dbg(1,"keypress 0x%x\n", event->keyval); + transform_get_size(navit_get_trans(this->nav), &w, &h); + switch (event->keyval) { + case GDK_KP_Enter: + gtk_menu_shell_select_first(this->menubar, TRUE); + break; + case GDK_Up: + p.x=w/2; + p.y=0; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Down: + p.x=w/2; + p.y=h; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Left: + p.x=0; + p.y=h/2; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Right: + p.x=w; + p.y=h/2; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Book: + navit_zoom_in(this->nav, 2); + break; + case GDK_Calendar: + navit_zoom_out(this->nav, 2); + break; + default: + return FALSE; + } + return TRUE; +} - co->map_data=map_data_default; -#if 1 - extern struct graphics *graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); - gra=graphics_gtk_drawing_area_new(co, widget); -#else - extern struct graphics *graphics_gtk_gl_area_new(struct container *co, GtkWidget **widget); - gra=graphics_gtk_gl_area_new(co, widget); -#endif - co->gra=gra; - co->trans=t; - co->flags=flags; +static int +gui_gtk_set_graphics(struct gui_priv *this, struct graphics *gra) +{ + GtkWidget *graphics; - return co; + graphics=graphics_get_data(gra, "gtk_widget"); + if (! graphics) + return 1; + GTK_WIDGET_SET_FLAGS (graphics, GTK_CAN_FOCUS); + gtk_widget_set_sensitive(graphics, TRUE); + g_signal_connect(G_OBJECT(graphics), "key-press-event", G_CALLBACK(keypress), this); + gtk_box_pack_end(GTK_BOX(this->vbox), graphics, TRUE, TRUE, 0); + gtk_widget_show_all(graphics); + gtk_widget_grab_focus(graphics); + + return 0; } -struct container * -gui_gtk_window(int x, int y, int scale) +struct gui_methods gui_gtk_methods = { + gui_gtk_menubar_new, + gui_gtk_toolbar_new, + gui_gtk_statusbar_new, + gui_gtk_popup_new, + gui_gtk_set_graphics, +}; + +static struct gui_priv * +gui_gtk_new(struct navit *nav, struct gui_methods *meth, int w, int h) { - GtkWidget *window,*map_widget; - GtkWidget *vbox; - GtkWidget *statusbar; - struct container *co; + struct gui_priv *this; + + *meth=gui_gtk_methods; - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(window), 792, 547); - gtk_window_set_title(GTK_WINDOW(window), "Map"); - gtk_widget_realize(window); - vbox = gtk_vbox_new(FALSE, 0); - co=container_new(&map_widget); - - transform_setup(co->trans, x, y, scale, 0); + this=g_new0(struct gui_priv, 1); + this->nav=nav; + this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this->vbox = gtk_vbox_new(FALSE, 0); + gtk_window_set_default_size(GTK_WINDOW(this->win), w, h); + gtk_window_set_title(GTK_WINDOW(this->win), "Navit"); + gtk_widget_realize(this->win); + gtk_container_add(GTK_CONTAINER(this->win), this->vbox); + gtk_widget_show_all(this->win); - co->win=(struct window *) window; - co->statusbar=gui_gtk_statusbar_new(&statusbar); - gui_gtk_actions_new(co,&vbox); - -/* - gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); -*/ - gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(vbox), map_widget, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - - gtk_widget_show_all(window); - container_init_gra(co); - return co; + return this; } +void +plugin_init(void) +{ + plugin_register_gui_type("gtk", gui_gtk_new); +} diff --git a/gui/sdl/Makefile.am b/gui/sdl/Makefile.am new file mode 100644 index 00000000..d8be2a30 --- /dev/null +++ b/gui/sdl/Makefile.am @@ -0,0 +1,5 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @CEGUI_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgui_sdl.la +libgui_sdl_la_SOURCES = gui_sdl_window.cpp sdl_events.cpp +libgui_sdl_la_LIBADD = @SDL_LIBS@ @CEGUI_LIBS@ @OPENGL_LIBS@ diff --git a/gui/sdl/gui_sdl.h b/gui/sdl/gui_sdl.h new file mode 100644 index 00000000..1519084c --- /dev/null +++ b/gui/sdl/gui_sdl.h @@ -0,0 +1,23 @@ +#include "SDL/SDL.h" + +#define XRES 800 +#define YRES 600 + + +struct statusbar_methods; +struct menu_methods; +struct navit; + +struct gui_priv { +/* + GtkWidget *win; + GtkWidget *vbox; + GtkActionGroup *base_group; + GtkActionGroup *debug_group; + GtkActionGroup *dyn_group; + GtkUIManager *menu_manager; + void *statusbar;*/ + struct navit *nav; + int dyn_counter; +}; + diff --git a/gui/sdl/gui_sdl_window.cpp b/gui/sdl/gui_sdl_window.cpp new file mode 100644 index 00000000..818e517e --- /dev/null +++ b/gui/sdl/gui_sdl_window.cpp @@ -0,0 +1,684 @@ +#include "glib.h" +#include +// #include + +// FIXME temporary fix for enum +#include "projection.h" + + +#include "navit.h" +#include "profile.h" +#include "transform.h" +#include "gui.h" +#include "coord.h" +#include "plugin.h" +#include "graphics.h" +#include "gui_sdl.h" + +#include "navigation.h" + +#include "CEGUI.h" + + +// This is for 3d fonts +#include "GL/glc.h" + + +#include "sdl_events.h" + +#define VM_2D 0 +#define VM_3D 1 + +bool VIEW_MODE=VM_3D; + +GLdouble eyeX=400; +GLdouble eyeY=900; +GLdouble eyeZ=-800; +GLdouble centerX=400; +GLdouble centerY=300; +GLdouble centerZ=0; +GLdouble upX=0; +GLdouble upY=-1; +GLdouble upZ=0; + +#include +#include "CEGUIDefaultResourceProvider.h" +CEGUI::OpenGLRenderer* renderer; + +#undef profile +#define profile(x,y) + +CEGUI::Window* myRoot; + +#define MODULE "gui_sdl" +GLuint * DLid; + +struct navit *sdl_gui_navit; + +static int +gui_sdl_set_graphics(struct gui_priv *this_, struct graphics *gra) +{ + printf("setting up the graphics\n"); + + DLid=(GLuint *)graphics_get_data(gra, "opengl_displaylist"); + if (!DLid) + return 1; + return 0; +} + + +void drawCursor() { + printf("Pushing a cursor from GUI\n"); + int x=400; + int y=400; + float cursor_size=15.0f; + glColor4f(0.0f,0.0f,1.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + + } + + +static void +sdl_update_roadbook(struct navigation *nav, void *data) +{ + using namespace CEGUI; + extern Window* myRoot; + + if(! WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->isVisible()){ + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + } + + MultiColumnList* mcl = static_cast(myRoot->getChild("Navit/RoadBook")->getChild("Roadbook")); + mcl->resetList(); + + + struct navigation_list *list; + char *str; + + list=navigation_list_new(nav); + while ((str=navigation_list_get(list, navigation_mode_short))) { + +// printf("SDL : %s\n", str); + + + mcl->addRow(); + /* + char from [256]; + char to [256]; + + sprintf(from,"%s %s",param[0].value,param[1].value); + ListboxTextItem* itemListbox = new ListboxTextItem(from); + sprintf(to,"%s %s",param[2].value,param[3].value); + + itemListbox = new ListboxTextItem(to); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 1, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[9].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 2, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[11].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 3, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[10].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 4, mcl->getRowCount()-1); + + */ + ListboxTextItem* itemListbox = new ListboxTextItem(str); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 0, mcl->getRowCount()-1); + + } + navigation_list_destroy(list); +} + +static int gui_run_main_loop(struct gui_priv *this_) +{ + printf("Entering main loop\n"); + + bool must_quit = false; + + // get "run-time" in seconds + double last_time_pulse = static_cast(SDL_GetTicks()); + + int frames=0; + char fps [12]; + + struct transformation *t; + + + t=navit_get_trans(this_->nav); + transform_set_size(t, 800, 600); + navit_draw(this_->nav); +/* + glNewList(DLid,GL_COMPILE); + int x=400; + int y=400; + float cursor_size=15.0f; + glColor4f(1.0f,0.0f,0.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + glEndList(); +*/ + GLuint cursorDL; + cursorDL=glGenLists(1); + glNewList(cursorDL,GL_COMPILE); + drawCursor(); + glEndList(); + + bool enable_timer=0; + + struct navigation *navig; + navig=navit_get_navigation(sdl_gui_navit); + if(navig){ + printf("navig valid, registering callback\n"); + navigation_register_callback(navig, navigation_mode_long, sdl_update_roadbook, sdl_gui_navit); + } else { + printf("navig unvalid\n"); + } + + + while (!must_quit) + { + if(enable_timer) + profile(0,NULL); + glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if(VIEW_MODE==VM_3D){ + gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); + } + +/* + // FIXME This is to draw a ground. This is ugly and need to be fixed. Without it, we see the color of sky under the roads. + glColor4f(0.0f,0.7f,0.35f,1.0f); + glBegin(GL_POLYGON); + glVertex3f( -800,-600*3, 0.0f); + glVertex3f( -800,600*2, 0.0f); + glVertex3f( 1600,600*2, 0.0f); + glVertex3f( 1600,-600*3, 0.0f); + glEnd(); +*/ + + if(enable_timer) + profile(0,"graphics_redraw"); + g_main_context_iteration (NULL, FALSE); +// profile_timer("main context"); + + // graphics_get_data(this_->gra,DLid); + +#if 0 + glCallList(*DLid); +#endif + navit_draw_displaylist(sdl_gui_navit); + + // glCallList(cursorDL); + inject_input(must_quit); + if(enable_timer) + profile(0,"inputs"); + + // Render the cursor. + int x=400; + int y=480; + float cursor_size=15.0f; + glColor4f(0.0f,1.0f,0.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + if(enable_timer) + profile(0,"cursor"); + + frames++; + if(SDL_GetTicks()-last_time_pulse>1000){ + sprintf(fps,"%i",frames); // /(SDL_GetTicks()/1000)); + frames=0; + last_time_pulse = SDL_GetTicks(); + } + + myRoot->getChild("OSD/SpeedoMeter")->setText(fps); + + /* + glcRenderStyle(GLC_TEXTURE); + glColor3f(1, 0, 0); + glRotatef(180,1,0,0); + glScalef(64, 64, 0); + glcRenderString(fps); + */ + + if(enable_timer) + profile(0,"fps"); + + CEGUI::System::getSingleton().renderGUI(); + if(enable_timer) + profile(0,"GUI"); + + SDL_GL_SwapBuffers(); + } + + +} + + +static struct menu_priv * +gui_sdl_toolbar_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/ToolBar", nav, 0); +} + +static struct statusbar_priv * +gui_sdl_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/ToolBar", nav, 0); +} + +static struct menu_priv * +gui_sdl_menubar_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/MenuBar", nav, 0); +} + +static struct menu_priv * +gui_sdl_popup_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/PopUp", nav, 1); +} + +struct gui_methods gui_sdl_methods = { + gui_sdl_menubar_new, + gui_sdl_toolbar_new, + gui_sdl_statusbar_new, + gui_sdl_popup_new, + gui_sdl_set_graphics, + gui_run_main_loop, +}; + + +int init_GL() { + + printf("init_GL()\n"); +// glClearColor(1.0,0.9,0.7,0); + + // Blue sky + glClearColor(0.3,0.7,1.0,0); + + if(VIEW_MODE==VM_2D){ + printf("Switching to 2D view\n"); +// myRoot->getChild("OSD/ViewMode")->setText("2D"); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glOrtho( 0, XRES, YRES, 0, -1, 1 ); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else { + printf("Switching to 3D view\n"); +// myRoot->getChild("OSD/ViewMode")->setText("3D"); + + // Dimensions de la fenetre de rendu + glViewport(0, 0, XRES, YRES); + // Initialisation de la matrice de projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1.0, 0.1, 2800.0); + // Rendu avec lissage de Gouraud +// glShadeModel(GL_SMOOTH); + // glEnable(GL_DEPTH_TEST); + + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +// gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); + + } + + //Display list code + // GLuint glGenLists(GLsizei numberOfIDsRequired); + // linesDL = glGenLists(1); + + if( glGetError() != GL_NO_ERROR ) { + return 0; + } + return 1; +} + +bool ToggleView(const CEGUI::EventArgs& event) +{ + VIEW_MODE=!VIEW_MODE; + + if(VIEW_MODE==VM_2D){ + myRoot->getChild("OSD/ViewMode")->setText("2D"); + } else { + myRoot->getChild("OSD/ViewMode")->setText("3D"); + } + init_GL(); +} + +bool MoveCamera(const CEGUI::EventArgs& event){ + + CEGUI::Scrollbar * sb = static_cast(myRoot->getChild("OSD/Scrollbar1")); +// printf("moving : %f\n",sb->getScrollPosition()); + eyeZ=-sb->getScrollPosition(); + if (eyeZ>-100){ + eyeZ=-100; + } +} + +bool ShowKeyboard(const CEGUI::EventArgs& event){ + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + myRoot->getChild("Navit/Keyboard")->show(); +} + +void Add_KeyBoard_key(char * key,int x,int y,int w){ + + using namespace CEGUI; + char button_name [5]; + sprintf(button_name,"%s",key); + FrameWindow* wnd = (FrameWindow*)WindowManager::getSingleton().createWindow("TaharezLook/Button", button_name); + myRoot->getChild("Navit/Keyboard")->addChildWindow(wnd); + wnd->setPosition(UVector2(cegui_absdim(x), cegui_absdim( y))); + wnd->setSize(UVector2(cegui_absdim(w), cegui_absdim( 40))); + wnd->setText(key); + wnd->subscribeEvent(PushButton::EventClicked, Event::Subscriber(Handle_Virtual_Key_Down)); + +} + + +void BuildKeyboard(){ + int w=55; + int offset_x=10; + int count_x=0; + + int y=25; + Add_KeyBoard_key("A",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("Z",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("E",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("R",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("T",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("Y",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("U",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("I",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("O",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("P",offset_x+(count_x++)*w,y,w); + count_x++; + Add_KeyBoard_key("7",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("8",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("9",offset_x+(count_x++)*w,y,w); + + y=70; + count_x=0; + Add_KeyBoard_key("Q",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("S",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("D",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("F",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("G",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("H",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("J",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("K",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("L",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("M",offset_x+(count_x++)*w,y,w); + count_x++; + Add_KeyBoard_key("4",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("5",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("6",offset_x+(count_x++)*w,y,w); + + y=115; + count_x=0; + + Add_KeyBoard_key("W",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("X",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("C",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("V",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("B",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("N",offset_x+(count_x++)*w,y,w); + + Add_KeyBoard_key(" ",offset_x+(count_x++)*w,y,w*2); + count_x++; + + Add_KeyBoard_key("BACK",offset_x+(count_x++)*w,y,w*2); + count_x+=2; + + Add_KeyBoard_key("1",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("2",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("3",offset_x+(count_x++)*w,y,w); + + y=160; + count_x=11; + Add_KeyBoard_key("0",offset_x+(count_x++)*w,y,w); + + Add_KeyBoard_key("OK",offset_x+(count_x++)*w,y,w*2); + + +} + +static void init_sdlgui(void) +{ + SDL_Surface * screen; +// atexit (SDL_Quit); + SDL_Init (SDL_INIT_VIDEO); + int videoFlags; + const SDL_VideoInfo *videoInfo; + videoInfo = SDL_GetVideoInfo( ); + + if ( !videoInfo ) + { + fprintf( stderr, "Video query failed: %s\n", + SDL_GetError( ) ); + } + + /* the flags to pass to SDL_SetVideoMode */ + videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ + videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */ + videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */ + videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ + + /* This checks to see if surfaces can be stored in memory */ + if ( videoInfo->hw_available ) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + /* This checks if hardware blits can be done */ + if ( videoInfo->blit_hw ) + videoFlags |= SDL_HWACCEL; + + /* Sets up OpenGL double buffering */ + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + SDL_WM_SetCaption("NavIt - The OpenSource vector based navigation engine", NULL); + + /* get a SDL surface */ + screen = SDL_SetVideoMode( XRES, YRES, 32, + videoFlags ); + + if (screen == NULL) { + fprintf (stderr, "Can't set SDL: %s\n", SDL_GetError ()); + exit (1); + } + + SDL_ShowCursor (SDL_ENABLE); + SDL_EnableUNICODE (1); + SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + init_GL(); + +// sdl_audio_init(); + + try + { + renderer = new CEGUI::OpenGLRenderer(0,XRES,YRES); + new CEGUI::System(renderer); + + using namespace CEGUI; + + SDL_ShowCursor(SDL_ENABLE); + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + CEGUI::DefaultResourceProvider* rp = static_cast + (CEGUI::System::getSingleton().getResourceProvider()); + + rp->setResourceGroupDirectory("schemes", "../datafiles/schemes/"); + rp->setResourceGroupDirectory("imagesets", "../datafiles/imagesets/"); + rp->setResourceGroupDirectory("fonts", "../datafiles/fonts/"); + rp->setResourceGroupDirectory("layouts", "../datafiles/layouts/"); + rp->setResourceGroupDirectory("looknfeels", "../datafiles/looknfeel/"); + rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/"); + + + CEGUI::Imageset::setDefaultResourceGroup("imagesets"); + CEGUI::Font::setDefaultResourceGroup("fonts"); + CEGUI::Scheme::setDefaultResourceGroup("schemes"); + CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels"); + CEGUI::WindowManager::setDefaultResourceGroup("layouts"); + CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts"); + + CEGUI::SchemeManager::getSingleton().loadScheme("TaharezLook.scheme"); + + CEGUI::FontManager::getSingleton().createFont("DejaVuSans-10.font"); + CEGUI::FontManager::getSingleton().createFont("DejaVuSans-14.font"); + + CEGUI::System::getSingleton().setDefaultFont("DejaVuSans-10"); + + CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton(); + + myRoot = CEGUI::WindowManager::getSingleton().loadWindowLayout("navit.layout"); + + CEGUI::System::getSingleton().setGUISheet(myRoot); + + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + + myRoot->getChild("OSD/DestinationButton")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(DialogWindowSwitch)); + + myRoot->getChild("OSD/RoadbookButton")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(RoadBookSwitch)); + myRoot->getChild("Navit/RoadBook")->getChild("OSD/RoadbookButton2")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(RoadBookSwitch)); + myRoot->getChild("OSD/ZoomIn")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ZoomIn)); + myRoot->getChild("OSD/ZoomOut")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ZoomOut)); + myRoot->getChild("OSD/Quit")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ButtonQuit)); + myRoot->getChild("OSD/ViewMode")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ToggleView)); + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/GO")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ButtonGo)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/KB")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ShowKeyboard)); + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Listbox")->subscribeEvent(MultiColumnList::EventSelectionChanged, Event::Subscriber(ItemSelect)); + + myRoot->getChild("OSD/Scrollbar1")->subscribeEvent(Scrollbar::EventScrollPositionChanged, Event::Subscriber(MoveCamera)); + + + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + mcl->setSelectionMode(MultiColumnList::RowSingle) ; + mcl->addColumn("Value", 0, cegui_absdim(200.0)); + mcl->addColumn("ID", 1, cegui_absdim(70.0)); + mcl->addColumn("Assoc", 2, cegui_absdim(70.0)); + mcl->addColumn("x", 3, cegui_absdim(70.0)); + mcl->addColumn("y", 4, cegui_absdim(70.0)); + + MultiColumnList* mcl2 = static_cast(WindowManager::getSingleton().getWindow("Roadbook")); + + mcl2->setSelectionMode(MultiColumnList::RowSingle) ; + mcl2->addColumn("From", 0, cegui_absdim(200.0)); + mcl2->addColumn("To", 1, cegui_absdim(200.0)); + mcl2->addColumn("Dist", 2, cegui_absdim(80.0)); + mcl2->addColumn("ETA", 3, cegui_absdim(80.0)); + mcl2->addColumn("Instruction",4, cegui_absdim(300.0)); + + BuildKeyboard(); + + } + catch (CEGUI::Exception& e) + { + fprintf(stderr,"CEGUI Exception occured: \n%s\n", e.getMessage().c_str()); + printf("quiting...\n"); + exit(1); + } + + char * fontname="/usr/share/fonts/corefonts/verdana.ttf"; + +// printf("Gui initialized. Building fonts\n"); + + + int ctx = 0; + int font = 0; + ctx = glcGenContext(); + glcContext(ctx); + font = glcNewFontFromFamily(glcGenFontID(), "Arial"); + glcFont(font); +// glcFontFace(font, "Italic"); + +// printf("Fonts built. Ready to rock!\n"); + + +} + +static struct gui_priv * +gui_sdl_new(struct navit *nav, struct gui_methods *meth, int w, int h) +{ + printf("Begin SDL init\n"); + struct gui_priv *this_; + sdl_gui_navit=nav; + + if(sdl_gui_navit){ + printf("*** VALID navit instance in gui\n"); + } else { + printf("*** Invalid navit instance in gui\n"); + } + if(nav){ + printf("*** VALID source navit instance in gui\n"); + } else { + printf("*** Invalid source navit instance in gui\n"); + } + + *meth=gui_sdl_methods; + + this_=g_new0(struct gui_priv, 1); + init_sdlgui(); + printf("End SDL init\n"); + + /* + this_->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this_->vbox = gtk_vbox_new(FALSE, 0); + gtk_window_set_default_size(GTK_WINDOW(this_->win), w, h); + gtk_window_set_title(GTK_WINDOW(this_->win), "Navit"); + gtk_widget_realize(this_->win); + gtk_container_add(GTK_CONTAINER(this_->win), this_->vbox); + gtk_widget_show_all(this_->win); + */ + this_->nav=nav; + + + return this_; +} + +void +plugin_init(void) +{ + printf("registering sdl plugin\n"); + plugin_register_gui_type("sdl", gui_sdl_new); +} diff --git a/gui/sdl/sdl_events.cpp b/gui/sdl/sdl_events.cpp new file mode 100644 index 00000000..0d83acff --- /dev/null +++ b/gui/sdl/sdl_events.cpp @@ -0,0 +1,771 @@ +#include "CEGUI.h" +#include "sdl_events.h" + +#include + +// FIXME temporary fix for enum +#include "projection.h" +#include "navit.h" + +#include "../../coord.h" + +// Theses are needed for searches +#include "../../attr.h" +#include "../../item.h" +#include "../../search.h" + +struct sdl_destination{ + int country; + int town; + int town_street_assoc; + int current_search; +} SDL_dest; + + +static struct search_param { + struct navit *nav; + struct mapset *ms; + struct search_list *sl; + struct attr attr; +} search_param; + +// extern "C" struct navit *global_navit; + +void route_to(int x,int y){ + struct coord pos; + pos.x=x; + pos.y=y; + using namespace CEGUI; + extern struct navit *sdl_gui_navit; + + WindowManager::getSingleton().getWindow("DestinationWindow")->hide(); + WindowManager::getSingleton().getWindow("Navit/Routing/Tips")->show(); + WindowManager::getSingleton().getWindow("Navit/ProgressWindow")->show(); +// route_set_destination(co->route, &pos); + // I could have been using search->nav instead of sdl_gui_navit. is it better this way? + + navit_set_destination(sdl_gui_navit, &pos, "FIXME"); + WindowManager::getSingleton().getWindow("Navit/ProgressWindow")->hide(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + WindowManager::getSingleton().getWindow("OSD/ETA")->show(); + +} + + +bool handleItemSelect(int r) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + ListboxItem * item = mcl->getItemAtGridReference(MCLGridRef(r,0)); + ListboxItem * itemid = mcl->getItemAtGridReference(MCLGridRef(r,1)); + ListboxItem * item_assoc = mcl->getItemAtGridReference(MCLGridRef(r,2)); + + + Window* country_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + Window* twn_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + Window* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + if(SDL_dest.current_search==SRCH_COUNTRY){ + country_edit->setText(item->getText()); + // Need to record the country here + twn_edit->activate(); + SDL_dest.current_search=SRCH_TOWN; + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + } else if(SDL_dest.current_search==SRCH_TOWN){ + twn_edit->setText(item->getText()); +// SDL_dest.town_street_assoc=atoi(item_assoc->getText().c_str()); +// SDL_dest.town=atoi(itemid->getText().c_str()); +// printf(" town %s , id=%lx, assoc=%li\n",item->getText().c_str(),SDL_dest.town_street_assoc,SDL_dest.town_street_assoc); + + + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + Window* Dest_x = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(itemx->getText().c_str()); + + Window* Dest_y = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(itemy->getText().c_str()); + + mcl->resetList(); + + SDL_dest.current_search=SRCH_STREET; + street_edit->activate(); + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + } else if(SDL_dest.current_search==SRCH_STREET){ + street_edit->setText(item->getText()); + + myRoot->getChild("Navit/Keyboard")->hide(); + + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + Window* Dest_x = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(itemx->getText().c_str()); + + Window* Dest_y = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(itemy->getText().c_str()); + + mcl->resetList(); + + SDL_dest.current_search=SRCH_STREET; + + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + + /* + ListboxItem * itemid = mcl->getItemAtGridReference(MCLGridRef(r,1)); + int segment_id=atoi(itemid->getText().c_str()); + printf("street seg id : %li\n",segment_id); + + extern struct container *co; + struct block_info res_blk_inf; + struct street_str *res_str; + street_get_by_id(co->map_data, 33, segment_id,&res_blk_inf,&res_str ); + + struct street_coord * streetcoord; + streetcoord=street_coord_get(&res_blk_inf,res_str); + + printf("Street coordinates : %i,%i\n",streetcoord->c->x,streetcoord->c->y); + + char xbuff [256]; + sprintf(xbuff,"%li",streetcoord->c->x); + char ybuff [256]; + sprintf(ybuff,"%li",streetcoord->c->y); + + Window* Dest_x = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(xbuff); + + Window* Dest_y = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(ybuff); + + struct street_name name; +// printf("street_name_get_by_id returns : %i\n",street_name_get_by_id(&name, res_blk_inf.mdata, res_str->nameid)); + street_name_get_by_id(&name, res_blk_inf.mdata, res_str->nameid); +// printf("name1:%s / name2%s\n",name.name1,name.name2); + + struct street_name_number_info num; + struct street_name_info inf; + + SDL_dest.current_search=SRCH_NUMBER; + mcl->resetList(); + + while (street_name_get_info(&inf, &name)) { + while(street_name_get_number_info(&num,&inf)){ +// printf(" House Number : %i -> %i\n",num.first,num.last); + for(int i=num.first;i<=num.last;i+=2){ + add_number_to_list(i,num.c->x,num.c->y); + } + } + } + */ +// route_to(streetcoord->c->x,streetcoord->c->y); + } else if (SDL_dest.current_search==SRCH_NUMBER){ + + struct coord pos; + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + pos.x=atoi(itemx->getText().c_str()); + pos.y=atoi(itemy->getText().c_str()); + + route_to(pos.x,pos.y); + } + + return true; +} + + + +bool ItemSelect(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + ListboxItem * item = mcl->getFirstSelectedItem(); + handleItemSelect(mcl->getItemRowIndex(item)); +} + +bool handleMouseEnters(const CEGUI::EventArgs& event) +{ + // FIXME this whole function could maybe be removed + const CEGUI::WindowEventArgs& we = static_cast(event); + + // FIXME theses variables should be shared + extern CEGUI::OpenGLRenderer* renderer; + extern CEGUI::Window* myRoot; + + using namespace CEGUI; + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + String senderID = we.window->getName(); + + if (senderID == "DestinationWindow/CountryEditbox"){ + // First, clean off the Street and Town Editbox + extern Window* myRoot; + Window* town_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + town_edit->setText(""); + Window* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + SDL_dest.current_search=SRCH_COUNTRY; + + } else if (senderID == "DestinationWindow/TownEditbox"){ + // First, clean off the Street Editbox + extern Window* myRoot; + Window* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + SDL_dest.current_search=SRCH_TOWN; + + } else if (senderID == "DestinationWindow/StreetEditbox"){ + // First, make sure the user selected an entry in the town choice. If he hadn't, select the first for him. + if(SDL_dest.current_search==SRCH_TOWN){ + if (mcl->getRowCount()>0) + { + handleItemSelect(0); + } + } + SDL_dest.current_search=SRCH_STREET; + + } +} + + +void handle_destination_change(){ + printf("Called handle_destination_change\n"); + + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + struct search_param *search=&search_param; + struct search_list_result *res; + + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + + if (SDL_dest.current_search==SRCH_COUNTRY) + { + printf("Starting a country search\n"); + Editbox* country_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + String content=country_edit->getText(); + + mcl->resetList(); + + search->attr.type=attr_country_all; + + // FIXME the following codeblock could be shared between country, town and street search + search->attr.u.str=(char *)content.c_str(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->country->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + } + + } else if (SDL_dest.current_search==SRCH_TOWN) + { + + Editbox* town_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + String content=town_edit->getText(); + + + mcl->resetList(); + + if(strlen(content.c_str())<4){ + + } else { + printf("town searching for %s\n",content.c_str()); + search->attr.type=attr_town_name; + search->attr.u.str=(char *)content.c_str(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->town->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + + char x [256]; + sprintf(x,"%li",res->c->x); + ListboxTextItem* xitem = new ListboxTextItem(x); + + char y [256]; + sprintf(y,"%li",res->c->y); + + ListboxTextItem* yitem = new ListboxTextItem(y); +// item->setSelectionBrushImage(&ImagesetManager::getSingleton().getImageset("TaharezLook")->getImage("MultiListSelectionBrush")); + + try + { + mcl->setItem(xitem, 3, mcl->getRowCount()-1); + mcl->setItem(yitem, 4, mcl->getRowCount()-1); + } + // something went wrong, so cleanup the ListboxTextItem. + catch (InvalidRequestException) + { +// delete item; + } + + } + + } + + + } else if (SDL_dest.current_search==SRCH_STREET) + { + Editbox* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + String content=street_edit->getText(); + if(strlen(content.c_str())<1){ + + } else { + printf("street searching for %s\n",content.c_str()); + search->attr.type=attr_street_name; + search->attr.u.str=(char *)content.c_str(); + + mcl->resetList(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->street->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + + char x [256]; + sprintf(x,"%li",res->c->x); + ListboxTextItem* xitem = new ListboxTextItem(x); + + char y [256]; + sprintf(y,"%li",res->c->y); + + ListboxTextItem* yitem = new ListboxTextItem(y); +// item->setSelectionBrushImage(&ImagesetManager::getSingleton().getImageset("TaharezLook")->getImage("MultiListSelectionBrush")); + + try + { + mcl->setItem(xitem, 3, mcl->getRowCount()-1); + mcl->setItem(yitem, 4, mcl->getRowCount()-1); + } + // something went wrong, so cleanup the ListboxTextItem. + catch (InvalidRequestException) + { +// delete item; + } + + + } + +// street_name_search(search->map_data, 33, SDL_dest.town_street_assoc, content.c_str(), 1, destination_street_add, search); + } + } + +} + + +bool DestinationEntryChange(const CEGUI::EventArgs& event) +{ + handleMouseEnters(event); + handle_destination_change(); + + return true; +} + +bool DialogWindowSwitch(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + + extern CEGUI::Window* myRoot; + + const CEGUI::WindowEventArgs& we = static_cast(event); + if(we.window->getParent()->getChild("DestinationWindow")->isVisible()){ + we.window->getParent()->getChild("DestinationWindow")->hide(); + } else { + Window* town_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + town_edit->setText(""); + Window* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + town_edit->activate(); + SDL_dest.current_search=SRCH_COUNTRY; + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + mcl->resetList(); + we.window->getParent()->getChild("DestinationWindow")->show(); + } + + extern struct navit *sdl_gui_navit; + + if(sdl_gui_navit){ + } else { + printf("*** Invalid navit instance in sdl_events\n"); + } + struct search_param *search=&search_param; + + printf("search->nav=sdl_gui_navit;\n"); + search->nav=sdl_gui_navit; + printf("search->ms=navit_get_mapset(sdl_gui_navit);\n"); + search->ms=navit_get_mapset(sdl_gui_navit); + printf("search->sl=search_list_new(search->ms);\n"); + search->sl=search_list_new(search->ms); + + return true; +} + +bool RoadBookSwitch(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + +// const CEGUI::WindowEventArgs& we = static_cast(event); + if(myRoot->getChild("Navit/RoadBook")->isVisible()){ + myRoot->getChild("Navit/RoadBook")->hide(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + } else { + myRoot->getChild("Navit/RoadBook")->show(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->hide(); + } + return true; +} + +bool ButtonGo(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + MultiColumnList* mcl = static_cast(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + // First, make sure the user selected an entry in the town choice. If he hadn't, select the first for him. + if(SDL_dest.current_search==SRCH_TOWN){ + if (mcl->getRowCount()>0) + { + handleItemSelect(0); + } + } + + + Window* Dest_x = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Window* Dest_y = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + + extern struct navit *sdl_gui_navit; + route_to(atoi(Dest_x->getText().c_str()),atoi(Dest_y->getText().c_str())); + + return true; +} + + +bool ZoomIn(const CEGUI::EventArgs& event) +{ + extern struct navit *sdl_gui_navit; + navit_zoom_in(sdl_gui_navit, 2); + /* + extern struct container *co; + struct transformation *t=co->trans; + if(t->scale>1){ + t->scale/=2; + } + */ + +} + +bool ZoomOut(const CEGUI::EventArgs& event) +{ + extern struct navit *sdl_gui_navit; + navit_zoom_out(sdl_gui_navit, 2); + /* + extern struct container *co; + struct transformation *t=co->trans; + t->scale*=2; + */ +} + +bool ButtonQuit(const CEGUI::EventArgs& event) +{ + exit(0); +} + +bool Handle_Virtual_Key_Down(const CEGUI::EventArgs& event){ + + using namespace CEGUI; + + extern CEGUI::Window* myRoot; + + const CEGUI::WindowEventArgs& we = static_cast(event); + String senderID = we.window->getName(); + + Window* editbox = myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input"); + String content=editbox->getText(); + + + if(senderID=="OK"){ + printf("Validating : %s\n",content.c_str()); + myRoot->getChild("Navit/Keyboard")->hide(); + return 0; + } else if(senderID=="BACK"){ + content=content.substr(0, content.length()-1); + editbox->setText(content); + } else { + content+=senderID; + editbox->setText(content); + } + + Window* country_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + Window* town_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + Window* street_edit = static_cast(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + switch (SDL_dest.current_search) { + case SRCH_COUNTRY: + country_edit->setText(content); + break; + case SRCH_TOWN : + town_edit->setText(content); + break; + case SRCH_STREET : + street_edit->setText(content); + break; + } + handle_destination_change(); +} + + + +// Nothing really interesting below. + +void handle_mouse_down(Uint8 button) +{ + switch ( button ) + { + // handle real mouse buttons + case SDL_BUTTON_LEFT: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton); + break; + case SDL_BUTTON_MIDDLE: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton); + break; + case SDL_BUTTON_RIGHT: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton); + break; + + // handle the mouse wheel + case SDL_BUTTON_WHEELDOWN: + CEGUI::System::getSingleton().injectMouseWheelChange( -1 ); + break; + case SDL_BUTTON_WHEELUP: + CEGUI::System::getSingleton().injectMouseWheelChange( +1 ); + break; + } +} + + +void handle_mouse_up(Uint8 button) +{ + switch ( button ) + { + case SDL_BUTTON_LEFT: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton); + break; + case SDL_BUTTON_MIDDLE: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton); + break; + case SDL_BUTTON_RIGHT: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton); + break; + } +} + +void inject_time_pulse(double& last_time_pulse) +{ + // get current "run-time" in seconds + double t = 0.001*SDL_GetTicks(); + + // inject the time that passed since the last call + CEGUI::System::getSingleton().injectTimePulse( float(t-last_time_pulse) ); + + // store the new time as the last time + last_time_pulse = t; +} + + CEGUI::uint SDLKeyToCEGUIKey(SDLKey key) + { + using namespace CEGUI; + switch (key) + { + case SDLK_BACKSPACE: return Key::Backspace; + case SDLK_TAB: return Key::Tab; + case SDLK_RETURN: return Key::Return; + case SDLK_PAUSE: return Key::Pause; + case SDLK_ESCAPE: return Key::Escape; + case SDLK_SPACE: return Key::Space; + case SDLK_COMMA: return Key::Comma; + case SDLK_MINUS: return Key::Minus; + case SDLK_PERIOD: return Key::Period; + case SDLK_SLASH: return Key::Slash; + case SDLK_0: return Key::Zero; + case SDLK_1: return Key::One; + case SDLK_2: return Key::Two; + case SDLK_3: return Key::Three; + case SDLK_4: return Key::Four; + case SDLK_5: return Key::Five; + case SDLK_6: return Key::Six; + case SDLK_7: return Key::Seven; + case SDLK_8: return Key::Eight; + case SDLK_9: return Key::Nine; + case SDLK_COLON: return Key::Colon; + case SDLK_SEMICOLON: return Key::Semicolon; + case SDLK_EQUALS: return Key::Equals; + case SDLK_LEFTBRACKET: return Key::LeftBracket; + case SDLK_BACKSLASH: return Key::Backslash; + case SDLK_RIGHTBRACKET: return Key::RightBracket; + case SDLK_a: return Key::A; + case SDLK_b: return Key::B; + case SDLK_c: return Key::C; + case SDLK_d: return Key::D; + case SDLK_e: return Key::E; + case SDLK_f: return Key::F; + case SDLK_g: return Key::G; + case SDLK_h: return Key::H; + case SDLK_i: return Key::I; + case SDLK_j: return Key::J; + case SDLK_k: return Key::K; + case SDLK_l: return Key::L; + case SDLK_m: return Key::M; + case SDLK_n: return Key::N; + case SDLK_o: return Key::O; + case SDLK_p: return Key::P; + case SDLK_q: return Key::Q; + case SDLK_r: return Key::R; + case SDLK_s: return Key::S; + case SDLK_t: return Key::T; + case SDLK_u: return Key::U; + case SDLK_v: return Key::V; + case SDLK_w: return Key::W; + case SDLK_x: return Key::X; + case SDLK_y: return Key::Y; + case SDLK_z: return Key::Z; + case SDLK_DELETE: return Key::Delete; + case SDLK_KP0: return Key::Numpad0; + case SDLK_KP1: return Key::Numpad1; + case SDLK_KP2: return Key::Numpad2; + case SDLK_KP3: return Key::Numpad3; + case SDLK_KP4: return Key::Numpad4; + case SDLK_KP5: return Key::Numpad5; + case SDLK_KP6: return Key::Numpad6; + case SDLK_KP7: return Key::Numpad7; + case SDLK_KP8: return Key::Numpad8; + case SDLK_KP9: return Key::Numpad9; + case SDLK_KP_PERIOD: return Key::Decimal; + case SDLK_KP_DIVIDE: return Key::Divide; + case SDLK_KP_MULTIPLY: return Key::Multiply; + case SDLK_KP_MINUS: return Key::Subtract; + case SDLK_KP_PLUS: return Key::Add; + case SDLK_KP_ENTER: return Key::NumpadEnter; + case SDLK_KP_EQUALS: return Key::NumpadEquals; + case SDLK_UP: return Key::ArrowUp; + case SDLK_DOWN: return Key::ArrowDown; + case SDLK_RIGHT: return Key::ArrowRight; + case SDLK_LEFT: return Key::ArrowLeft; + case SDLK_INSERT: return Key::Insert; + case SDLK_HOME: return Key::Home; + case SDLK_END: return Key::End; + case SDLK_PAGEUP: return Key::PageUp; + case SDLK_PAGEDOWN: return Key::PageDown; + case SDLK_F1: return Key::F1; + case SDLK_F2: return Key::F2; + case SDLK_F3: return Key::F3; + case SDLK_F4: return Key::F4; + case SDLK_F5: return Key::F5; + case SDLK_F6: return Key::F6; + case SDLK_F7: return Key::F7; + case SDLK_F8: return Key::F8; + case SDLK_F9: return Key::F9; + case SDLK_F10: return Key::F10; + case SDLK_F11: return Key::F11; + case SDLK_F12: return Key::F12; + case SDLK_F13: return Key::F13; + case SDLK_F14: return Key::F14; + case SDLK_F15: return Key::F15; + case SDLK_NUMLOCK: return Key::NumLock; + case SDLK_SCROLLOCK: return Key::ScrollLock; + case SDLK_RSHIFT: return Key::RightShift; + case SDLK_LSHIFT: return Key::LeftShift; + case SDLK_RCTRL: return Key::RightControl; + case SDLK_LCTRL: return Key::LeftControl; + case SDLK_RALT: return Key::RightAlt; + case SDLK_LALT: return Key::LeftAlt; + case SDLK_LSUPER: return Key::LeftWindows; + case SDLK_RSUPER: return Key::RightWindows; + case SDLK_SYSREQ: return Key::SysRq; + case SDLK_MENU: return Key::AppMenu; + case SDLK_POWER: return Key::Power; + default: return 0; + } + return 0; + } + + +void inject_input(bool& must_quit) +{ + SDL_Event e; + + // go through all available events + while (SDL_PollEvent(&e)) + { + // we use a switch to determine the event type + switch (e.type) + { + // mouse motion handler + case SDL_MOUSEMOTION: + // we inject the mouse position directly. + CEGUI::System::getSingleton().injectMousePosition( + static_cast(e.motion.x), + static_cast(e.motion.y) + ); + break; + + // mouse down handler + case SDL_MOUSEBUTTONDOWN: + // let a special function handle the mouse button down event + handle_mouse_down(e.button.button); + break; + + // mouse up handler + case SDL_MOUSEBUTTONUP: + // let a special function handle the mouse button up event + handle_mouse_up(e.button.button); + break; + + + // key down + case SDL_KEYDOWN: + // to tell CEGUI that a key was pressed, we inject the scancode, translated from SDL + CEGUI::System::getSingleton().injectKeyDown(SDLKeyToCEGUIKey(e.key.keysym.sym)); + + // as for the character it's a litte more complicated. we'll use for translated unicode value. + // this is described in more detail below. + if ((e.key.keysym.unicode & 0xFF80) == 0) + { + CEGUI::System::getSingleton().injectChar(e.key.keysym.unicode & 0x7F); + } + break; + + // key up + case SDL_KEYUP: + // like before we inject the scancode translated from SDL. + CEGUI::System::getSingleton().injectKeyUp(SDLKeyToCEGUIKey(e.key.keysym.sym)); + break; + + + // WM quit event occured + case SDL_QUIT: + must_quit = true; + break; + + } + + } + +} diff --git a/gui/sdl/sdl_events.h b/gui/sdl/sdl_events.h new file mode 100644 index 00000000..1f475f08 --- /dev/null +++ b/gui/sdl/sdl_events.h @@ -0,0 +1,32 @@ +#include "SDL/SDL.h" +#include "CEGUI.h" + + + +#define SRCH_COUNTRY 1 +#define SRCH_TOWN 2 +#define SRCH_STREET 3 +#define SRCH_NUMBER 4 + +bool handleItemSelect(int r); +bool ItemSelect(const CEGUI::EventArgs& event); +bool handleMouseEnters(const CEGUI::EventArgs& event); +void handle_destination_change(); + +bool DestinationEntryChange(const CEGUI::EventArgs& event); +bool DialogWindowSwitch(const CEGUI::EventArgs& event); +bool RoadBookSwitch(const CEGUI::EventArgs& event); +bool ButtonGo(const CEGUI::EventArgs& event); +bool ZoomIn(const CEGUI::EventArgs& event); +bool ZoomOut(const CEGUI::EventArgs& event); +bool ButtonQuit(const CEGUI::EventArgs& event); + +void inject_time_pulse(double& last_time_pulse); + +bool Handle_Virtual_Key_Down(const CEGUI::EventArgs& event); + +CEGUI::uint SDLKeyToCEGUIKey(SDLKey key); + +void inject_input(bool& must_quit); + + diff --git a/item.c b/item.c new file mode 100644 index 00000000..4db0be71 --- /dev/null +++ b/item.c @@ -0,0 +1,132 @@ +#include +#include +#include "attr.h" +#include "coord.h" +#include "item.h" + +struct item_name { + enum item_type item; + char *name; +}; + + +struct item_name item_names[]={ +#define ITEM2(x,y) ITEM(y) +#define ITEM(x) { type_##x, #x }, +#include "item_def.h" +#undef ITEM2 +#undef ITEM +}; + +void +item_coord_rewind(struct item *it) +{ + it->meth->item_coord_rewind(it->priv_data); +} + +int +item_coord_get(struct item *it, struct coord *c, int count) +{ + return it->meth->item_coord_get(it->priv_data, c, count); +} + +void +item_attr_rewind(struct item *it) +{ + it->meth->item_attr_rewind(it->priv_data); +} +int +item_attr_get(struct item *it, enum attr_type attr_type, struct attr *attr) +{ + return it->meth->item_attr_get(it->priv_data, attr_type, attr); +} + +struct item * item_new(char *type, int zoom) +{ + struct item * it; + + it = g_new0(struct item, 1); + + /* FIXME evaluate arguments */ + + return it; +} + +enum item_type +item_from_name(char *name) +{ + int i; + + for (i=0 ; i < sizeof(item_names)/sizeof(struct item_name) ; i++) { + if (! strcmp(item_names[i].name, name)) + return item_names[i].item; + } + return type_none; +} + +char * +item_to_name(enum item_type item) +{ + int i; + + for (i=0 ; i < sizeof(item_names)/sizeof(struct item_name) ; i++) { + if (item_names[i].item == item) + return item_names[i].name; + } + return NULL; +} + +struct item_hash { + GHashTable *h; +}; + +static guint +item_hash_hash(gconstpointer key) +{ + const struct item *itm=key; + gconstpointer hashkey=(gconstpointer)(itm->id_hi^itm->id_lo^((int) itm->map)); + return g_direct_hash(hashkey); +} + +static gboolean +item_hash_equal(gconstpointer a, gconstpointer b) +{ + const struct item *itm_a=a; + const struct item *itm_b=b; + if (item_is_equal(*itm_a, *itm_b)) + return TRUE; + return FALSE; +} + + + +struct item_hash * +item_hash_new(void) +{ + struct item_hash *ret=g_new(struct item_hash, 1); + + ret->h=g_hash_table_new_full(item_hash_hash, item_hash_equal, g_free, NULL); + return ret; +} + +void +item_hash_insert(struct item_hash *h, struct item *item, void *val) +{ + struct item *hitem=g_new(struct item, 1); + *hitem=*item; + g_hash_table_insert(h->h, hitem, val); +} + +void * +item_hash_lookup(struct item_hash *h, struct item *item) +{ + return g_hash_table_lookup(h->h, item); +} + + +void +item_hash_destroy(struct item_hash *h) +{ + g_hash_table_destroy(h->h); + g_free(h); +} diff --git a/item.h b/item.h new file mode 100644 index 00000000..00a8b3a1 --- /dev/null +++ b/item.h @@ -0,0 +1,50 @@ +#include "attr.h" + + +enum item_type { +#define ITEM2(x,y) type_##y=x, +#define ITEM(x) type_##x, +#include "item_def.h" +#undef ITEM2 +#undef ITEM +}; + +#define item_is_equal_id(a,b) ((a).id_hi == (b).id_hi && (a).id_lo == (b).id_lo) +#define item_is_equal(a,b) (item_is_equal_id(a,b) && (a).map == (b).map) + +struct coord; + +struct item_methods { + void (*item_coord_rewind)(void *priv_data); + int (*item_coord_get)(void *priv_data, struct coord *c, int count); + void (*item_attr_rewind)(void *priv_data); + int (*item_attr_get)(void *priv_data, enum attr_type attr_type, struct attr *attr); +}; + +struct item { + enum item_type type; + int id_hi; + int id_lo; + struct map *map; + struct item_methods *meth; + void *priv_data; +}; + +/* prototypes */ +enum attr_type; +enum item_type; +struct attr; +struct coord; +struct item; +struct item_hash; +void item_coord_rewind(struct item *it); +int item_coord_get(struct item *it, struct coord *c, int count); +void item_attr_rewind(struct item *it); +int item_attr_get(struct item *it, enum attr_type attr_type, struct attr *attr); +struct item *item_new(char *type, int zoom); +enum item_type item_from_name(char *name); +char *item_to_name(enum item_type item); +struct item_hash *item_hash_new(void); +void item_hash_insert(struct item_hash *h, struct item *item, void *val); +void *item_hash_lookup(struct item_hash *h, struct item *item); +void item_hash_destroy(struct item_hash *h); diff --git a/item_def.h b/item_def.h new file mode 100644 index 00000000..755497d2 --- /dev/null +++ b/item_def.h @@ -0,0 +1,131 @@ +ITEM2(0x00000000,none) +ITEM2(0x00000001,point_unspecified) +ITEM(town_streets) +ITEM(street_name) +ITEM(street_name_numbers) +ITEM(street_number) +/* Point */ +ITEM2(0x00010000,town_label) +ITEM2(0x00010001,town_label_0e0) +ITEM2(0x00010002,town_label_1e0) +ITEM2(0x00010003,town_label_2e0) +ITEM2(0x00010004,town_label_5e0) +ITEM2(0x00010005,town_label_1e1) +ITEM2(0x00010006,town_label_2e1) +ITEM2(0x00010007,town_label_5e1) +ITEM2(0x00010008,town_label_1e2) +ITEM2(0x00010009,town_label_2e2) +ITEM2(0x0001000a,town_label_5e2) +ITEM2(0x0001000b,town_label_1e3) +ITEM2(0x0001000c,town_label_2e3) +ITEM2(0x0001000d,town_label_5e3) +ITEM2(0x0001000e,town_label_1e4) +ITEM2(0x0001000f,town_label_2e4) +ITEM2(0x00010010,town_label_5e4) +ITEM2(0x00010011,town_label_1e5) +ITEM2(0x00010012,town_label_2e5) +ITEM2(0x00010013,town_label_5e5) +ITEM2(0x00010014,town_label_1e6) +ITEM2(0x00010015,town_label_2e6) +ITEM2(0x00010016,town_label_5e6) +ITEM2(0x00010017,town_label_1e7) +ITEM2(0x00010100,district_label) +ITEM2(0x00010101,district_label_0e0) +ITEM2(0x00010102,district_label_1e0) +ITEM2(0x00010103,district_label_2e0) +ITEM2(0x00010104,district_label_5e0) +ITEM2(0x00010105,district_label_1e1) +ITEM2(0x00010106,district_label_2e1) +ITEM2(0x00010107,district_label_5e1) +ITEM2(0x00010108,district_label_1e2) +ITEM2(0x00010109,district_label_2e2) +ITEM2(0x0001010a,district_label_5e2) +ITEM2(0x0001010b,district_label_1e3) +ITEM2(0x0001010c,district_label_2e3) +ITEM2(0x0001010d,district_label_5e3) +ITEM2(0x0001010e,district_label_1e4) +ITEM2(0x0001010f,district_label_2e4) +ITEM2(0x00010110,district_label_5e4) +ITEM2(0x00010111,district_label_1e5) +ITEM2(0x00010112,district_label_2e5) +ITEM2(0x00010113,district_label_5e5) +ITEM2(0x00010114,district_label_1e6) +ITEM2(0x00010115,district_label_2e6) +ITEM2(0x00010116,district_label_5e6) +ITEM2(0x00010117,district_label_1e7) +ITEM(country_label) +ITEM(town_ghost) +ITEM(highway_exit_label) +ITEM(port_label) +ITEM(label_unkn) +ITEM(highway_exit) +ITEM(poi_lake) +ITEM(poi_island) +ITEM(poi) +ITEM(waypoint) +ITEM(poi_land_feature) +ITEM(poi_cape) +ITEM(poi_rock) +ITEM(poi_airport) +ITEM(poi_toll_booth) +ITEM(poi_fuel) +ITEM(poi_hotel) +ITEM(poi_camp_rv) +ITEM(poi_marina) +ITEM(poi_attraction) +ITEM(poi_museum_history) +ITEM(poi_shopping) +ITEM(poi_car_dealer_parts) +ITEM(poi_car_parking) +ITEM(poi_wreck) +ITEM(poi_building) +ITEM(poi_bridge) +ITEM(poi_park) +ITEM(poi_water_feature) +ITEM(poi_bar) +ITEM(poi_picnic) +ITEM(poi_hospital) +ITEM(poi_camping) +ITEM(poi_public_utilities) +ITEM2(0x80000000,line) +ITEM2(0x80000001,line_unspecified) +/* Line */ +ITEM(border_country) +ITEM(border_state) +ITEM(rail) +ITEM(water_line) +ITEM(street_nopass) +ITEM(street_0) +ITEM(street_1_city) +ITEM(street_2_city) +ITEM(street_3_city) +ITEM(street_4_city) +ITEM(highway_city) +ITEM(street_1_land) +ITEM(street_2_land) +ITEM(street_3_land) +ITEM(street_4_land) +ITEM(street_n_lanes) +ITEM(highway_land) +ITEM(ramp) +ITEM(ferry) +ITEM(roadbook) +ITEM(street_unkn) +ITEM(street_route) +ITEM(height_line_1) +ITEM(height_line_2) +/* Area */ +ITEM2(0xc0000000,area) +ITEM2(0xc0000001,area_unspecified) +ITEM(wood) +ITEM(water_poly) +ITEM(town_poly) +ITEM(cemetery_poly) +ITEM(parking_lot_poly) +ITEM(industry_poly) +ITEM(airport_poly) +ITEM(hospital_poly) +ITEM(park_poly) +ITEM(sport_poly) +ITEM(image) +ITEM(image_path) diff --git a/layer.h b/layer.h new file mode 100644 index 00000000..3415cf94 --- /dev/null +++ b/layer.h @@ -0,0 +1,6 @@ +enum layer_type { + layer_town=0, + layer_street, + layer_poly, + layer_end, +}; diff --git a/layout.c b/layout.c new file mode 100644 index 00000000..0ca33599 --- /dev/null +++ b/layout.c @@ -0,0 +1,131 @@ +#include +#include +#include "layout.h" + +struct layout * layout_new(const char *name) +{ + struct layout *l; + + l = g_new0(struct layout, 1); + l->name = g_strdup(name); + return l; +} + + +struct layer * layer_new(const char *name, int details) +{ + struct layer *l; + + l = g_new0(struct layer, 1); + l->name = g_strdup(name); + l->details = details; + return l; +} + +void layout_add_layer(struct layout *layout, struct layer *layer) +{ + layout->layers = g_list_append(layout->layers, layer); +} + +struct itemtype * itemtype_new(int zoom_min, int zoom_max) +{ + struct itemtype *itm; + + itm = g_new0(struct itemtype, 1); + itm->zoom_min=zoom_min; + itm->zoom_max=zoom_max; + return itm; +} + +void itemtype_add_type(struct itemtype *this, enum item_type type) +{ + this->type = g_list_append(this->type, GINT_TO_POINTER(type)); +} + + +void layer_add_itemtype(struct layer *layer, struct itemtype * itemtype) +{ + layer->itemtypes = g_list_append(layer->itemtypes, itemtype); + +} + +void itemtype_add_element(struct itemtype *itemtype, struct element *element) +{ + itemtype->elements = g_list_append(itemtype->elements, element); +} + +struct element * +polygon_new(struct color *color) +{ + struct element *e; + e = g_new0(struct element, 1); + e->type=element_polygon; + e->color=*color; + + return e; +} + +struct element * +polyline_new(struct color *color, int width) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_polyline; + e->color=*color; + e->u.polyline.width=width; + + return e; +} + +struct element * +circle_new(struct color *color, int radius, int width, int label_size) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_circle; + e->color=*color; + e->label_size=label_size; + e->u.circle.width=width; + e->u.circle.radius=radius; + + return e; +} + +struct element * +label_new(int label_size) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_label; + e->label_size=label_size; + + return e; +} + +struct element * +icon_new(const char *src) +{ + struct element *e; + + e = g_malloc0(sizeof(*e)+strlen(src)+1); + e->type=element_icon; + e->u.icon.src=(char *)(e+1); + strcpy(e->u.icon.src,src); + + return e; +} + +struct element * +image_new(void) +{ + struct element *e; + + e = g_malloc0(sizeof(*e)); + e->type=element_image; + + return e; +} + diff --git a/layout.h b/layout.h new file mode 100644 index 00000000..ed96838e --- /dev/null +++ b/layout.h @@ -0,0 +1,59 @@ +#include "item.h" +#include "color.h" + +struct element_line; +struct element_text; + +struct element { + enum { element_point, element_polyline, element_polygon, element_circle, element_label, element_icon, element_image } type; + struct color color; + int label_size; + union { + struct element_point { + } point; + struct element_polyline { + int width; + } polyline; + struct element_polygon { + } polygon; + struct element_circle { + int width; + int radius; + } circle; + struct element_icon { + char *src; + } icon; + } u; +}; + + +struct itemtype { + int zoom_min, zoom_max; + GList *type; + GList *elements; +}; + +struct layer { char *name; int details; GList *itemtypes; }; + +struct layout { char *name; GList *layers; }; + +/* prototypes */ +enum item_type; +struct color; +struct element; +struct itemtype; +struct layer; +struct layout; +struct layout *layout_new(const char *name); +struct layer *layer_new(const char *name, int details); +void layout_add_layer(struct layout *layout, struct layer *layer); +struct itemtype *itemtype_new(int zoom_min, int zoom_max); +void itemtype_add_type(struct itemtype *this, enum item_type type); +void layer_add_itemtype(struct layer *layer, struct itemtype *itemtype); +void itemtype_add_element(struct itemtype *itemtype, struct element *element); +struct element *polygon_new(struct color *color); +struct element *polyline_new(struct color *color, int width); +struct element *circle_new(struct color *color, int radius, int width, int label_size); +struct element *label_new(int label_size); +struct element *icon_new(const char *src); +struct element *image_new(void); diff --git a/main.c b/main.c index d68d3119..db91ef88 100644 --- a/main.c +++ b/main.c @@ -1,46 +1,59 @@ #include -#include #include #include +#include +#include #include -#include "coord.h" -#include "vehicle.h" -#include "cursor.h" -#include "speech.h" -#include "route.h" -#include "map.h" -#include "map_data.h" -#if 0 -#include "map-share.h" +#include "file.h" +#include "debug.h" +#include "navit.h" +#include "gui.h" +#ifdef HAVE_PYTHON +#include "python.h" #endif -#include "transform.h" -#include "popup.h" #include "plugin.h" -#include "compass.h" -#include "track.h" -#include "container.h" -#include "debug.h" +#include "xmlconfig.h" -#include "osd.h" +struct map_data *map_data_default; -void *speech_handle; +static void sigchld(int sig) +{ + int status; + while (waitpid(-1, &status, WNOHANG) > 0); +} -struct container *co; -struct map_data *map_data_default; +static gchar *get_home_directory(void) +{ + static gchar *homedir = NULL; -struct container *gui_gtk_window(int x, int y, int scale); + if (homedir) return homedir; + homedir = getenv("HOME"); + if (!homedir) + { + struct passwd *p; + +// p = getpwuid(getuid()); +// if (p) homedir = p->pw_dir; + } + if (!homedir) + { + g_warning("Could not find home directory. Using current directory as home directory."); + homedir = "."; + } + return homedir; +} -extern void test(struct map_data *mdat); int main(int argc, char **argv) { + GError *error = NULL; + char *config_file = NULL; #if 0 - CORBA_Environment ev; - CORBA_ORB orb; - Map map_client = CORBA_OBJECT_NIL; + GMainLoop *loop; #endif - char *gps; + + signal(SIGCHLD, sigchld); setenv("LC_NUMERIC","C",1); setlocale(LC_ALL,""); @@ -51,58 +64,38 @@ int main(int argc, char **argv) gtk_init(&argc, &argv); gdk_rgb_init(); -// i18n basic support - - bindtextdomain( "navit", "./locale" ); - textdomain( "navit" ); - - map_data_default=load_maps(NULL); - plugin_load(); - co=gui_gtk_window(1300000,7000000,8192); - - co->route=route_new(); - route_mapdata_set(co->route, co->map_data); - gps=getenv("GPSDATA"); - if (gps) { - co->vehicle=vehicle_new(gps); - if (co->vehicle) { - co->cursor=cursor_new(co,co->vehicle); +#ifdef HAVE_PYTHON + python_init(); +#endif + if (argc > 1) + config_file=argv[1]; + else { + config_file=g_strjoin(NULL,get_home_directory(), "/.navit/navit.xml" , NULL); + if (!file_exists(config_file)) { + if (file_exists("navit.xml.local")) + config_file="navit.xml.local"; + else + config_file="navit.xml"; } - } else { - g_warning(gettext("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]")); } - co->speech=speech_new(); - if (! co->speech) - g_warning(gettext("Can't connect to speechd, no speech output available")); - speech_handle=co->speech; - if (co->vehicle) - co->compass=compass_new(co); - if (co->vehicle) - co->osd=osd_new(co); - if (co->vehicle) - co->track=track_new(co->map_data); - - -#if 0 - CORBA_exception_init(&ev); - orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - - map_srv_start_poa(orb, &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - map_client = map_srv_start_object(&ev, map); - retval = CORBA_ORB_object_to_string(orb, map_client, &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - ior=fopen("map.ior","w"); - if (ior) { - fprintf(ior, "%s\n", retval); - fclose(ior); + if (!config_load(config_file, &error)) { + g_error("Error parsing '%s': %s\n", config_file, error->message); + } else { + printf("Using '%s'\n", config_file); } - CORBA_free(retval); + if (main_loop_gui) { + gui_run_main_loop(main_loop_gui); + } else { +#if 1 + gtk_main(); +#else + loop = g_main_loop_new (NULL, TRUE); + if (g_main_loop_is_running (loop)) + { + g_main_loop_run (loop); + } #endif + } - gtk_main(); return 0; } - - diff --git a/map.c b/map.c new file mode 100644 index 00000000..b5f991e3 --- /dev/null +++ b/map.c @@ -0,0 +1,197 @@ +#include +#include +#include "debug.h" +#include "coord.h" +#include "map.h" +#include "maptype.h" +#include "transform.h" +#include "projection.h" +#include "item.h" +#include "plugin.h" +#include "country.h" + +struct map { + struct map_methods meth; + struct map_priv *priv; + char *filename; + char *type; + char *charset; + int active; + enum projection projection; +}; + +struct map_rect { + struct map *m; + struct map_rect_priv *priv; +}; + +struct map * +map_new(const char *type, const char *filename) +{ + struct map *m; + struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, char **charset, enum projection *pro); + + maptype_new=plugin_get_map_type(type); + if (! maptype_new) + return NULL; + + m=g_new0(struct map, 1); + m->active=1; + m->filename=g_strdup(filename); + m->type=g_strdup(type); + m->priv=maptype_new(&m->meth, filename, &m->charset, &m->projection); + return m; +} + +char * +map_get_filename(struct map *this) +{ + return this->filename; +} + +char * +map_get_type(struct map *this) +{ + return this->type; +} + +int +map_get_active(struct map *this) +{ + return this->active; +} + +void +map_set_active(struct map *this, int active) +{ + this->active=active; +} + +int +map_requires_conversion(struct map *this) +{ + return (this->charset != NULL); +} + +char * +map_convert_string(struct map *this, char *str) +{ + return g_convert(str, -1,"utf-8",this->charset,NULL,NULL,NULL); +} + +void +map_convert_free(char *str) +{ + g_free(str); +} + +enum projection +map_projection(struct map *this) +{ + return this->projection; +} + +void +map_destroy(struct map *m) +{ + m->meth.map_destroy(m->priv); + g_free(m); +} + +struct map_rect * +map_rect_new(struct map *m, struct map_selection *sel) +{ + struct map_rect *mr; + +#if 0 + printf("map_rect_new 0x%x,0x%x-0x%x,0x%x\n", r->lu.x, r->lu.y, r->rl.x, r->rl.y); +#endif + mr=g_new0(struct map_rect, 1); + mr->m=m; + mr->priv=m->meth.map_rect_new(m->priv, sel); + + return mr; +} + +struct item * +map_rect_get_item(struct map_rect *mr) +{ + struct item *ret; + g_assert(mr != NULL); + g_assert(mr->m != NULL); + g_assert(mr->m->meth.map_rect_get_item != NULL); + ret=mr->m->meth.map_rect_get_item(mr->priv); + if (ret) + ret->map=mr->m; + return ret; +} + +struct item * +map_rect_get_item_byid(struct map_rect *mr, int id_hi, int id_lo) +{ + struct item *ret=NULL; + g_assert(mr != NULL); + g_assert(mr->m != NULL); + if (mr->m->meth.map_rect_get_item_byid) + ret=mr->m->meth.map_rect_get_item_byid(mr->priv, id_hi, id_lo); + if (ret) + ret->map=mr->m; + return ret; +} + +void +map_rect_destroy(struct map_rect *mr) +{ + mr->m->meth.map_rect_destroy(mr->priv); + g_free(mr); +} + +struct map_search { + struct map *m; + struct attr search_attr; + void *priv; +}; + +struct map_search * +map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial) +{ + struct map_search *this; + dbg(1,"enter(%p,%p,%p,%d)\n", m, item, search_attr, partial); + dbg(1,"0x%x 0x%x 0x%x\n", attr_country_all, search_attr->type, attr_country_name); + this=g_new0(struct map_search,1); + this->m=m; + this->search_attr=*search_attr; + if (search_attr->type >= attr_country_all && search_attr->type <= attr_country_name) + this->priv=country_search_new(&this->search_attr, partial); + else + this->priv=m->meth.map_search_new(m->priv, item, search_attr, partial); + + return this; +} + +struct item * +map_search_get_item(struct map_search *this) +{ + struct item *ret; + + if (! this) + return NULL; + if (this->search_attr.type >= attr_country_all && this->search_attr.type <= attr_country_name) + return country_search_get_item(this->priv); + ret=this->m->meth.map_search_get_item(this->priv); + if (ret) + ret->map=this->m; + return ret; +} + +void +map_search_destroy(struct map_search *this) +{ + if (! this) + return; + if (this->search_attr.type >= attr_country_all && this->search_attr.type <= attr_country_name) + country_search_destroy(this->priv); + else + this->m->meth.map_search_destroy(this->priv); + g_free(this); +} diff --git a/map.h b/map.h index 2ffa914b..7f330576 100644 --- a/map.h +++ b/map.h @@ -1,341 +1,44 @@ -/* - * This file was generated by orbit-idl-2 - DO NOT EDIT! - */ - -#ifndef map_H -#define map_H 1 -#include -#define ORBIT_IDL_SERIAL 20 -#include - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/** typedefs **/ -#if !defined(_PointObj_defined) -#define _PointObj_defined 1 - typedef struct PointObj_type PointObj; - struct PointObj_type - { - CORBA_float lng; - CORBA_float lat; - CORBA_float height; - }; - -#if !defined(TC_IMPL_TC_PointObj_0) -#define TC_IMPL_TC_PointObj_0 'm' -#define TC_IMPL_TC_PointObj_1 'a' -#define TC_IMPL_TC_PointObj_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_PointObj_struct; -#define TC_PointObj ((CORBA_TypeCode)&TC_PointObj_struct) -#endif -#define PointObj__alloc() ((PointObj *)ORBit_small_alloc (TC_PointObj)) -#define PointObj__freekids(m,d) ORBit_small_freekids (TC_PointObj,(m),(d)) -#endif -#if !defined(ORBIT_DECL_CORBA_sequence_PointObj) -#define ORBIT_DECL_CORBA_sequence_PointObj 1 -#define ORBIT_IMPL_CORBA_sequence_PointObj_0 'm' -#define ORBIT_IMPL_CORBA_sequence_PointObj_1 'a' -#define ORBIT_IMPL_CORBA_sequence_PointObj_2 'p' -#if !defined(_CORBA_sequence_PointObj_defined) -#define _CORBA_sequence_PointObj_defined 1 - typedef struct - { - CORBA_unsigned_long _maximum, - _length; - PointObj *_buffer; - CORBA_boolean _release; - } CORBA_sequence_PointObj; -#endif -#if !defined(TC_IMPL_TC_CORBA_sequence_PointObj_0) -#define TC_IMPL_TC_CORBA_sequence_PointObj_0 'm' -#define TC_IMPL_TC_CORBA_sequence_PointObj_1 'a' -#define TC_IMPL_TC_CORBA_sequence_PointObj_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_CORBA_sequence_PointObj_struct; -#define TC_CORBA_sequence_PointObj ((CORBA_TypeCode)&TC_CORBA_sequence_PointObj_struct) -#endif -#define CORBA_sequence_PointObj__alloc() ((CORBA_sequence_PointObj *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) -#define CORBA_sequence_PointObj__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) -#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#endif -#if !defined(_PointObjSequence_defined) -#define _PointObjSequence_defined 1 - typedef CORBA_sequence_PointObj PointObjSequence; -#define PointObjSequence_marshal(x,y,z) CORBA_sequence_PointObj_marshal((x),(y),(z)) -#define PointObjSequence_demarshal(x,y,z,i) CORBA_sequence_PointObj_demarshal((x),(y),(z),(i)) -#if !defined(TC_IMPL_TC_PointObjSequence_0) -#define TC_IMPL_TC_PointObjSequence_0 'm' -#define TC_IMPL_TC_PointObjSequence_1 'a' -#define TC_IMPL_TC_PointObjSequence_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_PointObjSequence_struct; -#define TC_PointObjSequence ((CORBA_TypeCode)&TC_PointObjSequence_struct) -#endif -#define PointObjSequence__alloc() ((PointObjSequence *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) -#define PointObjSequence__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) -#define PointObjSequence_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#endif -#if !defined(ORBIT_DECL_Mappel) && !defined(_Mappel_defined) -#define ORBIT_DECL_Mappel 1 -#define _Mappel_defined 1 -#define Mappel__freekids CORBA_Object__freekids - typedef CORBA_Object Mappel; - extern CORBA_unsigned_long Mappel__classid; -#if !defined(TC_IMPL_TC_Mappel_0) -#define TC_IMPL_TC_Mappel_0 'm' -#define TC_IMPL_TC_Mappel_1 'a' -#define TC_IMPL_TC_Mappel_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_Mappel_struct; -#define TC_Mappel ((CORBA_TypeCode)&TC_Mappel_struct) -#endif -#endif -#if !defined(ORBIT_DECL_Map) && !defined(_Map_defined) -#define ORBIT_DECL_Map 1 -#define _Map_defined 1 -#define Map__freekids CORBA_Object__freekids - typedef CORBA_Object Map; - extern CORBA_unsigned_long Map__classid; -#if !defined(TC_IMPL_TC_Map_0) -#define TC_IMPL_TC_Map_0 'm' -#define TC_IMPL_TC_Map_1 'a' -#define TC_IMPL_TC_Map_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_Map_struct; -#define TC_Map ((CORBA_TypeCode)&TC_Map_struct) -#endif -#endif - -/** POA structures **/ -#ifndef _defined_POA_Mappel -#define _defined_POA_Mappel 1 - typedef struct - { - void *_private; - void (*Test) (PortableServer_Servant _servant, CORBA_Environment * ev); - } POA_Mappel__epv; - typedef struct - { - PortableServer_ServantBase__epv *_base_epv; - POA_Mappel__epv *Mappel_epv; - } POA_Mappel__vepv; - typedef struct - { - void *_private; - POA_Mappel__vepv *vepv; - } POA_Mappel; - extern void POA_Mappel__init(PortableServer_Servant servant, - CORBA_Environment * ev); - extern void POA_Mappel__fini(PortableServer_Servant servant, - CORBA_Environment * ev); -#endif /* _defined_POA_Mappel */ -#ifndef _defined_POA_Map -#define _defined_POA_Map 1 - typedef struct - { - void *_private; - Map(*mapString) (PortableServer_Servant _servant, - const CORBA_char * astring, CORBA_double * anum, - CORBA_Environment * ev); - void (*doNothing) (PortableServer_Servant _servant, - CORBA_Environment * ev); - void (*doOneWay) (PortableServer_Servant _servant, - const CORBA_char * ignore, CORBA_Environment * ev); - void (*PlaceFlag) (PortableServer_Servant _servant, - CORBA_Environment * ev); - PointObj(*PointFromCoord) (PortableServer_Servant _servant, - const CORBA_char * coord, - CORBA_Environment * ev); - void (*View) (PortableServer_Servant _servant, const PointObj * where, - CORBA_Environment * ev); - void (*ViewAll) (PortableServer_Servant _servant, - const PointObjSequence * where, - CORBA_Environment * ev); - void (*Route) (PortableServer_Servant _servant, const PointObj * src, - const PointObj * dst, CORBA_Environment * ev); - Mappel(*Get) (PortableServer_Servant _servant, CORBA_Environment * ev); - } POA_Map__epv; - typedef struct - { - PortableServer_ServantBase__epv *_base_epv; - POA_Map__epv *Map_epv; - } POA_Map__vepv; - typedef struct - { - void *_private; - POA_Map__vepv *vepv; - } POA_Map; - extern void POA_Map__init(PortableServer_Servant servant, - CORBA_Environment * ev); - extern void POA_Map__fini(PortableServer_Servant servant, - CORBA_Environment * ev); -#endif /* _defined_POA_Map */ - -/** skel prototypes **/ - void _ORBIT_skel_small_Mappel_Test(POA_Mappel * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_Test) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_mapString(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - Map(*_impl_mapString) - (PortableServer_Servant _servant, - const CORBA_char * astring, - CORBA_double * anum, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_doNothing(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_doNothing) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_doOneWay(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_doOneWay) - (PortableServer_Servant _servant, - const CORBA_char * ignore, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_PlaceFlag(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_PlaceFlag) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_PointFromCoord(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - PointObj(*_impl_PointFromCoord) - (PortableServer_Servant _servant, - const CORBA_char * coord, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_View(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_View) (PortableServer_Servant - _servant, - const PointObj * where, - CORBA_Environment * - ev)); - void _ORBIT_skel_small_Map_ViewAll(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_ViewAll) - (PortableServer_Servant _servant, - const PointObjSequence * where, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_Route(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_Route) - (PortableServer_Servant _servant, - const PointObj * src, - const PointObj * dst, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_Get(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - Mappel(*_impl_Get) (PortableServer_Servant - _servant, - CORBA_Environment * - ev)); - -/** stub prototypes **/ - void Mappel_Test(Mappel _obj, CORBA_Environment * ev); - Map Map_mapString(Map _obj, const CORBA_char * astring, - CORBA_double * anum, CORBA_Environment * ev); - void Map_doNothing(Map _obj, CORBA_Environment * ev); - void Map_doOneWay(Map _obj, const CORBA_char * ignore, - CORBA_Environment * ev); - void Map_PlaceFlag(Map _obj, CORBA_Environment * ev); - PointObj Map_PointFromCoord(Map _obj, const CORBA_char * coord, - CORBA_Environment * ev); - void Map_View(Map _obj, const PointObj * where, CORBA_Environment * ev); - void Map_ViewAll(Map _obj, const PointObjSequence * where, - CORBA_Environment * ev); - void Map_Route(Map _obj, const PointObj * src, const PointObj * dst, - CORBA_Environment * ev); - Mappel Map_Get(Map _obj, CORBA_Environment * ev); -#include - -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IInterface Mappel__iinterface; -#define Mappel_IMETHODS_LEN 1 -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IMethod Mappel__imethods[Mappel_IMETHODS_LEN]; -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IInterface Map__iinterface; -#define Map_IMETHODS_LEN 9 -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IMethod Map__imethods[Map_IMETHODS_LEN]; -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#ifndef EXCLUDE_ORBIT_H -#include - -#endif /* EXCLUDE_ORBIT_H */ -#endif -#undef ORBIT_IDL_SERIAL +struct map_priv; +struct attr; +#include "coord.h" +#include "layer.h" + +struct map_selection { + struct map_selection *next; + struct coord_rect rect; + int order[layer_end]; +}; + +struct map_methods { + void (*map_destroy)(struct map_priv *priv); + struct map_rect_priv * (*map_rect_new)(struct map_priv *map, struct map_selection *sel); + void (*map_rect_destroy)(struct map_rect_priv *mr); + struct item * (*map_rect_get_item)(struct map_rect_priv *mr); + struct item * (*map_rect_get_item_byid)(struct map_rect_priv *mr, int id_hi, int id_lo); + struct map_search_priv *(*map_search_new)(struct map_priv *map, struct item *item, struct attr *search, int partial); + void (*map_search_destroy)(struct map_search_priv *ms); + struct item * (*map_search_get_item)(struct map_search_priv *ms); +}; + +/* prototypes */ +enum projection; +struct attr; +struct item; +struct map; +struct map_rect; +struct map_search; +struct map_selection; +struct map *map_new(const char *type, const char *filename); +char *map_get_filename(struct map *this); +char *map_get_type(struct map *this); +int map_get_active(struct map *this); +void map_set_active(struct map *this, int active); +enum projection map_projection(struct map *this); +void map_destroy(struct map *m); +struct map_rect *map_rect_new(struct map *m, struct map_selection *sel); +struct item *map_rect_get_item(struct map_rect *mr); +struct item *map_rect_get_item_byid(struct map_rect *mr, int id_hi, int id_lo); +void map_rect_destroy(struct map_rect *mr); +struct map_search *map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial); +struct item *map_search_get_item(struct map_search *this); +void map_search_destroy(struct map_search *this); diff --git a/mapset.c b/mapset.c new file mode 100644 index 00000000..17fbecf3 --- /dev/null +++ b/mapset.c @@ -0,0 +1,116 @@ +#include +#include +#include "debug.h" +#include "attr.h" +#include "mapset.h" +#include "map.h" + +struct mapset { + GList *maps; +}; + +struct mapset *mapset_new(void) +{ + struct mapset *ms; + + ms=g_new0(struct mapset, 1); + + return ms; +} + +void mapset_add(struct mapset *ms, struct map *m) +{ + ms->maps=g_list_append(ms->maps, m); +} + +#if 0 +static void mapset_maps_free(struct mapset *ms) +{ + /* todo */ +} +#endif + +void mapset_destroy(struct mapset *ms) +{ + g_free(ms); +} + +struct mapset_handle { + GList *l; +}; + +struct mapset_handle * +mapset_open(struct mapset *ms) +{ + struct mapset_handle *ret; + + ret=g_new(struct mapset_handle, 1); + ret->l=ms->maps; + + return ret; +} + +struct map * mapset_next(struct mapset_handle *msh, int active) +{ + struct map *ret; + + for (;;) { + if (!msh->l) + return NULL; + ret=msh->l->data; + msh->l=g_list_next(msh->l); + if (!active || map_get_active(ret)) + return ret; + } +} + +void +mapset_close(struct mapset_handle *msh) +{ + g_free(msh); +} + +struct mapset_search { + GList *map; + struct map_search *ms; + struct item *item; + struct attr *search_attr; + int partial; +}; + +struct mapset_search * +mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial) +{ + struct mapset_search *this; + dbg(1,"enter(%p,%p,%p,%d)\n", ms, item, search_attr, partial); + this=g_new0(struct mapset_search,1); + this->map=ms->maps; + this->item=item; + this->search_attr=search_attr; + this->partial=partial; + this->ms=map_search_new(this->map->data, item, search_attr, partial); + return this; +} + +struct item * +mapset_search_get_item(struct mapset_search *this) +{ + struct item *ret; + while (!(ret=map_search_get_item(this->ms))) { + if (this->search_attr->type >= attr_country_all && this->search_attr->type <= attr_country_name) + break; + this->map=g_list_next(this->map); + if (! this->map) + break; + map_search_destroy(this->ms); + this->ms=map_search_new(this->map->data, this->item, this->search_attr, this->partial); + } + return ret; +} + +void +mapset_search_destroy(struct mapset_search *this) +{ + map_search_destroy(this->ms); + g_free(this); +} diff --git a/mapset.h b/mapset.h new file mode 100644 index 00000000..6998486d --- /dev/null +++ b/mapset.h @@ -0,0 +1,16 @@ +/* prototypes */ +struct attr; +struct item; +struct map; +struct mapset; +struct mapset_handle; +struct mapset_search; +struct mapset *mapset_new(void); +void mapset_add(struct mapset *ms, struct map *m); +void mapset_destroy(struct mapset *ms); +struct mapset_handle *mapset_open(struct mapset *ms); +struct map *mapset_next(struct mapset_handle *msh, int active); +void mapset_close(struct mapset_handle *msh); +struct mapset_search *mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial); +struct item *mapset_search_get_item(struct mapset_search *this); +void mapset_search_destroy(struct mapset_search *this); diff --git a/maptype.c b/maptype.c new file mode 100644 index 00000000..81039613 --- /dev/null +++ b/maptype.c @@ -0,0 +1,29 @@ +#include +#include "map.h" +#include "maptype.h" + +static struct maptype *maptype_root; + +void +maptype_register(char *name, struct map_priv *(*map_new)(struct map_methods *meth, char *data, char **charset, enum projection *pro)) +{ + struct maptype *mt; + mt=g_new(struct maptype, 1); + mt->name=g_strdup(name); + mt->map_new=map_new; + mt->next=maptype_root; + maptype_root=mt; +} + +struct maptype * +maptype_get(const char *name) +{ + struct maptype *mt=maptype_root; + + while (mt) { + if (!g_ascii_strcasecmp(mt->name, name)) + return mt; + mt=mt->next; + } + return NULL; +} diff --git a/maptype.h b/maptype.h new file mode 100644 index 00000000..1a41da53 --- /dev/null +++ b/maptype.h @@ -0,0 +1,15 @@ +struct map_methods; + +struct maptype { + char *name; + struct map_priv *(*map_new)(struct map_methods *meth, char *data); + struct maptype *next; +}; + +/* prototypes */ +enum projection; +struct map_methods; +struct map_priv; +struct maptype; +void maptype_register(char *name, struct map_priv *(*map_new)(struct map_methods *meth, char *data, char **charset, enum projection *pro)); +struct maptype *maptype_get(const char *name); diff --git a/menu.c b/menu.c index 5430b007..d7745751 100644 --- a/menu.c +++ b/menu.c @@ -1,36 +1,52 @@ -#include -#include -#include -#include -#include -#include "coord.h" -#include "data_window.h" -#include "route.h" -#include "cursor.h" +#include #include "menu.h" -#include "command.h" -#include "transform.h" -#include "street.h" -#include "statusbar.h" -#include "destination.h" -#include "main.h" -#include "container.h" -#include "graphics.h" void menu_route_do_update(struct container *co) { +#if 0 if (co->cursor) { +#if 0 /* FIXME */ route_set_position(co->route, cursor_pos_get(co->cursor)); +#endif graphics_redraw(co); if (co->statusbar && co->statusbar->statusbar_route_update) co->statusbar->statusbar_route_update(co->statusbar, co->route); } +#endif } void menu_route_update(struct container *co) { +#if 0 menu_route_do_update(co); graphics_redraw(co); +#endif +} + +struct menu * +menu_add(struct menu *menu, char *name, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2) +{ + struct menu *this; + this=g_new0(struct menu, 1); + this->priv=(*menu->meth.add)(menu->priv, &this->meth, name, type, callback, this, data1, data2); + if (! this->priv) { + g_free(this); + return NULL; + } + + return this; +} + +void +menu_set_toggle(struct menu *menu, int active) +{ + (*menu->meth.set_toggle)(menu->priv, active); +} + +int +menu_get_toggle(struct menu *menu) +{ + return (*menu->meth.get_toggle)(menu->priv); } diff --git a/menu.h b/menu.h index 51b24729..8f40fbc4 100644 --- a/menu.h +++ b/menu.h @@ -1,8 +1,27 @@ +enum menu_type { + menu_type_submenu, + menu_type_menu, + menu_type_toggle, +}; + +struct menu; + +struct menu_methods { + struct menu_priv *(*add)(struct menu_priv *menu, struct menu_methods *meth, char *name, enum menu_type type, void (*callback)(struct menu *data_menu, void *data1, void *data2), struct menu *data_menu, void *data1, void *data2); + void (*set_toggle)(struct menu_priv *menu, int active); + int (*get_toggle)(struct menu_priv *menu); +}; + struct menu { - struct menu_gui *gui; + struct menu_priv *priv; + struct menu_methods meth; }; +/* prototypes */ struct container; - +struct menu; void menu_route_do_update(struct container *co); void menu_route_update(struct container *co); +struct menu *menu_add(struct menu *menu, char *name, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2); +void menu_set_toggle(struct menu *menu, int active); +int menu_get_toggle(struct menu *menu); diff --git a/navigation.c b/navigation.c index c6a7e3e0..20125be6 100644 --- a/navigation.c +++ b/navigation.c @@ -1,341 +1,359 @@ -#include -#include -#include #include +#include +#include +#include +#include +#include "debug.h" +#include "navigation.h" #include "coord.h" -#include "graphics.h" -#include "param.h" -#include "block.h" +#include "item.h" #include "route.h" -#include "street.h" -#include "street_name.h" -#include "speech.h" -#include "navigation.h" -#include "data_window.h" -#include "osd.h" +#include "transform.h" +#include "mapset.h" +#include "map.h" +#include "navit.h" +#include "callback.h" -struct data_window *navigation_window; +struct navigation { + struct mapset *ms; + struct navigation_itm *first; + struct navigation_itm *last; + struct navigation_command *cmd_first; + struct navigation_command *cmd_last; + struct callback_list *callback_speech; + struct callback_list *callback; +}; -struct navigation_item { - char name1[128]; - char name2[128]; - int length; - int time; - int crossings_start; - int crossings_end; +struct navigation_command { + struct navigation_itm *itm; + struct navigation_command *next; + int delta; +}; + +struct navigation_list { + struct navigation *nav; + struct navigation_command *cmd; + struct navigation_itm *itm; + char *str; +}; + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; +}; + + +struct navigation * +navigation_new(struct mapset *ms) +{ + struct navigation *ret=g_new(struct navigation, 1); + ret->ms=ms; + ret->callback=callback_list_new(); + ret->callback_speech=callback_list_new(); + + return ret; +} + +struct navigation_itm { + char *name1; + char *name2; + struct coord start; + struct item item; int angle_start; int angle_end; - int points; - struct coord start; - struct coord end; + int time; + int length; + int dest_time; + int dest_length; + struct navigation_itm *next; + struct navigation_itm *prev; }; +/* 0=N,90=E */ static int -road_angle(struct coord *c, int dir) +road_angle(struct coord *c1, struct coord *c2, int dir) { - double angle; - int dx=c[1].x-c[0].x; - int dy=c[1].y-c[0].y; - angle=atan2(dx,dy); - angle*=180/M_PI; - if (dir == -1) - angle=angle-180; - if (angle < 0) - angle+=360; - return angle; + int ret=transform_get_angle_delta(c1, c2, dir); + dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret); + return ret; } -static void -expand_str(char *str) +static struct navigation_itm * +navigation_itm_new(struct navigation *this_, struct item *item, struct coord *start) { - int len=strlen(str); - if (len > 4 && !strcmp(str+len-4,"str.")) - strcpy(str+len-4,"strasse"); - if (len > 4 && !strcmp(str+len-4,"Str.")) - strcpy(str+len-4,"Strasse"); + struct navigation_itm *ret=g_new0(struct navigation_itm, 1); + int l,i=0,a1,a2,dir=0; + struct map_rect *mr; + struct attr attr; + struct coord c[5]; + + if (item) { + mr=map_rect_new(item->map, NULL); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + if (item_attr_get(item, attr_street_name, &attr)) + ret->name1=g_strdup(attr.u.str); + if (item_attr_get(item, attr_street_name_systematic, &attr)) + ret->name2=g_strdup(attr.u.str); + ret->item=*item; + l=-1; + while (item_coord_get(item, &c[i], 1)) { + dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x ,c[i].y); + l=i; + if (i < 4) + i++; + else { + c[2]=c[3]; + c[3]=c[4]; + } + } + dbg(1,"count=%d\n", l); + if (l == 4) + l=3; + if (start->x != c[0].x || start->y != c[0].y) + dir=-1; + a1=road_angle(&c[0], &c[1], dir); + a2=road_angle(&c[l-1], &c[l], dir); + if (dir >= 0) { + ret->angle_start=a1; + ret->angle_end=a2; + } else { + ret->angle_start=a2; + ret->angle_end=a1; + } + dbg(1,"i=%d a1 %d a2 %d '%s' '%s'\n", i, a1, a2, ret->name1, ret->name2); + map_rect_destroy(mr); + } + if (start) + ret->start=*start; + if (! this_->first) + this_->first=ret; + if (this_->last) { + this_->last->next=ret; + ret->prev=this_->last; + } + this_->last=ret; + return ret; } static void -navigation_goto(struct data_window *navigation_window, char **cols) +calculate_dest_distance(struct navigation *this_) { - extern struct container *co; - long x,y; - - printf("goto %s\n",cols[8]); - sscanf(cols[8],"%lx,%lx",&x,&y); - graphics_set_view(co, &x, &y, NULL); + int len=0, time=0; + struct navigation_itm *itm=this_->last; + while (itm) { + len+=itm->length; + time+=itm->time; + itm->dest_length=len; + itm->dest_time=time; + itm=itm->prev; + } + printf("len %d time %d\n", len, time); } static int -is_same_street(struct navigation_item *old, struct navigation_item *new) +is_same_street2(struct navigation_itm *old, struct navigation_itm *new) { - if (strlen(old->name2) && !strcmp(old->name2, new->name2)) { - strcpy(old->name1, new->name1); + if (old->name1 && new->name1 && !strcmp(old->name1, new->name1)) { + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old->name2, new->name2, old->name1, new->name1); return 1; } - if (strlen(old->name1) && !strcmp(old->name1, new->name1)) { - strcpy(old->name2, new->name2); + if (old->name2 && new->name2 && !strcmp(old->name2, new->name2)) { + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old->name2, new->name2, old->name1, new->name1); return 1; } + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' no\n", old->name2, new->name2, old->name1, new->name1); return 0; } static int -maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta) +maneuver_required2(struct navigation_itm *old, struct navigation_itm *new, int *delta) { - if (is_same_street(old, new)) + dbg(1,"enter %p %p %p\n",old, new, delta); + if (new->item.type == type_ramp && old && (old->item.type == type_highway_land || old->item.type == type_highway_city)) { + dbg(1, "maneuver_required: new is ramp from highway: yes\n"); + return 1; + } + if (is_same_street2(old, new)) { + dbg(1, "maneuver_required: is_same_street: no\n"); return 0; - if (old->crossings_end == 2) + } +#if 0 + if (old->crossings_end == 2) { + dbg(1, "maneuver_required: only 2 connections: no\n"); return 0; + } +#endif *delta=new->angle_start-old->angle_end; if (*delta < -180) *delta+=360; if (*delta > 180) *delta-=360; - if (*delta < 20 && *delta >-20) + if (*delta < 20 && *delta >-20) { + dbg(1, "maneuver_required: delta(%d) < 20: no\n", *delta); return 0; + } + dbg(1, "maneuver_required: delta=%d: yes\n", *delta); return 1; } -int flag,old_level; -extern void *speech_handle; +static struct navigation_command * +command_new(struct navigation *this_, struct navigation_itm *itm, int delta) +{ + struct navigation_command *ret=g_new0(struct navigation_command, 1); + ret->delta=delta; + ret->itm=itm; + if (this_->cmd_last) + this_->cmd_last->next=ret; + this_->cmd_last=ret; + if (!this_->cmd_first) + this_->cmd_first=ret; + return ret; +} static void -get_distance(char *dst, int dist) +make_maneuvers(struct navigation *this_) { - if (dist < 100) { - dist=(dist+5)/10; - dist*=10; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 250) { - dist=(dist+13)/25; - dist*=25; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 500) { - dist=(dist+25)/50; - dist*=50; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 1000) { - dist=(dist+50)/100; - dist*=100; - sprintf(dst,gettext("%d meter"), dist); - return; + struct navigation_itm *itm, *last=NULL, *last_itm=NULL; + itm=this_->first; + int delta; + this_->cmd_last=NULL; + this_->cmd_first=NULL; + while (itm) { + if (last) { + if (maneuver_required2(last_itm, itm, &delta)) { + command_new(this_, itm, delta); + } + } else + last=itm; + last_itm=itm; + itm=itm->next; } - if (dist < 5000) { - dist=(dist+50)/100; - if (dist % 10) - sprintf(dst,gettext("%d,%d kilometer"), dist/10,dist%10); - else - sprintf(dst,gettext("%d kilometer"), dist/10); - return; +} + +static char * +show_maneuver(struct navigation_itm *itm, struct navigation_command *cmd, int mode) +{ + char *dir="rechts",*strength=""; + int distance=itm->dest_length-cmd->itm->dest_length; + int delta=cmd->delta; + if (delta < 0) { + dir="links"; + delta=-delta; } - if (dist < 100000) { - dist=(dist+500)/1000; - sprintf(dst,gettext("%d kilometer"), dist); - return; + if (delta < 45) { + strength="leicht "; + } else if (delta < 105) { + strength=""; + } else if (delta < 165) { + strength="scharf "; + } else { + dbg(0,"delta=%d\n", delta); + strength="unbekannt "; } - dist=(dist+5000)/10000; - dist*=10; - sprintf(dst,gettext("%d kilometer"), dist); + if (cmd->itm->next) + return g_strdup_printf("In %d m %s%s abbiegen", distance, strength, dir); + else + return g_strdup_printf("In %d m haben Sie ihr Ziel erreicht", distance); } -static void -make_maneuver(struct navigation_item *old, struct navigation_item *new) +struct navigation_list * +navigation_list_new(struct navigation *this_) { - - int delta,navmode=1,add_dir,level; - struct param_list param_list[20]; - - char roadname[256]; + struct navigation_list *ret=g_new0(struct navigation_list, 1); + ret->nav=this_; + ret->cmd=this_->cmd_first; + ret->itm=this_->first; + return ret; +} - char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; - char command[256],*p,*dir,*strength; - char dist[256]; +char * +navigation_list_get(struct navigation_list *this_, enum navigation_mode mode) +{ + if (!this_->cmd) + return NULL; + g_free(this_->str); + this_->str=show_maneuver(this_->itm, this_->cmd, mode); + this_->itm=this_->cmd->itm; + this_->cmd=this_->cmd->next; - param_list[0].name="Name1 Old"; - param_list[0].value=old->name1; - param_list[1].name="Name2 Old"; - param_list[1].value=old->name2; - param_list[2].name="Name1 New"; - param_list[2].value=new->name1; - param_list[3].name="Name2 New"; - param_list[3].value=new->name2; - param_list[4].name="Angle\nOld"; - param_list[5].name="Angle\nNew"; - param_list[6].name="Delta"; - param_list[7].name="X-\nRoads"; - param_list[8].name="Position"; - param_list[9].name="Dist"; - param_list[10].name="Command"; - if (old->points) { - if (!maneuver_required(old, new, &delta)) { - old->length+=new->length; - old->time+=new->time; - old->crossings_end=new->crossings_end; - old->angle_end=new->angle_end; - old->points+=new->points; - } else { - sprintf(angle_old,"%d", old->angle_end); - param_list[4].value=angle_old; - sprintf(angle_new,"%d", new->angle_start); - param_list[5].value=angle_new; - sprintf(angle_delta,"%d", delta); - param_list[6].value=angle_delta; - sprintf(cross_roads,"%d", old->crossings_end); - param_list[7].value=cross_roads; - sprintf(position,"0x%lx,0x%lx", new->start.x, new->start.y); - param_list[8].value=position; - sprintf(distance,"%d", old->length); - param_list[9].value=distance; - add_dir=1; - dir=gettext("rechts"); - if (delta < 0) { - dir=gettext("links"); - delta=-delta; - } - if (delta < 45) { - strength=gettext("leicht "); - } else if (delta < 105) { - strength=""; - } else if (delta < 165) { - strength=gettext("scharf "); - } else { -#ifdef DEBUG - printf("delta=%d\n", delta); -#endif - strength=gettext("unbekannt "); - } - level=0; - if (navmode) { - if (old->length < 20) { - level=1; - sprintf(command,gettext("Jetzt ")); - } else if (old->length <= 200) { - level=2; - get_distance(dist, old->length); - sprintf(command,gettext("In %sn "), dist); - } else if (old->length <= 500) { - level=3; - sprintf(command,gettext("In Kürze ")); - } else { - level=4; - get_distance(dist, old->length); - sprintf(command,gettext("Dem Strassenverlauf %s folgen"), dist); - add_dir=0; - } - } else { - sprintf(command,gettext("Dem Strassenverlauf %d Meter folgen, dann "), old->length); - add_dir=1; - } - if (add_dir) { -/* p=command+strlen(command); - strcpy(p,strength); - p+=strlen(p); - strcpy(p,dir); - p+=strlen(p); - strcpy(p,gettext(" abbiegen"));*/ - sprintf(command,gettext(" %s %s abbiegen"),strength,dir); - p=command+strlen(command); - } - param_list[10].value=command; - if (flag) { - sprintf(roadname,"%s %s",old->name1,old->name2); - osd_set_next_command(command,roadname); - if (level != old_level) { - printf("command='%s'\n", command); - if (speech_handle) - speech_say(speech_handle, command); - old_level=level; - } - flag=0; - } - data_window_add(navigation_window, param_list, 11); - *old=*new; - } - } else { - *old=*new; - } + return this_->str; } + void -navigation_path_description(void *route) +navigation_list_destroy(struct navigation_list *this_) { - int id; - struct route_path_segment *curr=route_path_get_all(route); - struct block_info blk_inf; - struct street_str *str; - struct street_name name; - struct street_coord *coord; - struct map_data *mdata=route_mapdata_get(route); - struct coord *start,*end,*tmp; - int angle_start, angle_end, angle_tmp; - struct route_crossings *crossings_start,*crossings_end; - struct navigation_item item_curr,item_last; + g_free(this_->str); + g_free(this_); +} - memset(&item_last,0,sizeof(item_last)); +void +navigation_update(struct navigation *this_, struct route *route) +{ + struct route_path_handle *rph; + struct route_path_segment *s; + struct navigation_itm *itm; + struct route_info *pos,*dst; + struct street_data *sd; + int len,end_flag=0; + void *p; - if (!navigation_window) - navigation_window=data_window("Navigation",NULL,navigation_goto); - data_window_begin(navigation_window); - flag=1; - while (curr) { - str=NULL; - id=curr->segid; - if (id) { - if (id < 0) - id=-id; - street_get_by_id(mdata, curr->country, id, &blk_inf, &str); - coord=street_coord_get(&blk_inf, str); - start=coord->c; - end=coord->c+coord->count-1; - angle_start=road_angle(coord->c, curr->dir); - if (coord->count > 2) - angle_end=road_angle(coord->c+coord->count-2,curr->dir); - else - angle_end=angle_start; - if (curr->dir < 0) { - tmp=start; - angle_tmp=angle_start; - start=end; - angle_start=angle_end; - end=tmp; - angle_end=angle_tmp; - } - crossings_start=route_crossings_get(route, start); - crossings_end=route_crossings_get(route, end); - if (str && str->nameid) { - street_name_get_by_id(&name, blk_inf.mdata, str->nameid); - strcpy(item_curr.name1,name.name1); - strcpy(item_curr.name2,name.name2); - expand_str(item_curr.name1); - expand_str(item_curr.name2); - } else { - item_curr.name1[0]='\0'; - item_curr.name2[0]='\0'; - } - item_curr.length=curr->length; - item_curr.time=curr->time; - item_curr.crossings_start=crossings_start->count; - item_curr.crossings_end=crossings_end->count; - item_curr.angle_start=angle_start; - item_curr.angle_end=angle_end; - item_curr.points=coord->count; - item_curr.start=*start; - item_curr.end=*end; - make_maneuver(&item_last,&item_curr); - free(coord); - free(crossings_start); - free(crossings_end); - } - curr=curr->next; + + pos=route_get_pos(route); + dst=route_get_dst(route); + if (! pos || ! dst) + return; + this_->first=this_->last=NULL; + len=route_info_length(pos, dst, 0); + if (len == -1) { + len=route_info_length(pos, NULL, 0); + end_flag=1; + } + sd=route_info_street(pos); + itm=navigation_itm_new(this_, &sd->item, route_info_point(pos, -1)); + itm->length=len; + itm->time=route_time(&sd->item, len); + rph=route_path_open(route); + while((s=route_path_get_segment(rph))) { + itm=navigation_itm_new(this_, route_path_segment_get_item(s),route_path_segment_get_start(s)); + itm->time=route_path_segment_get_time(s); + itm->length=route_path_segment_get_length(s); } - data_window_end(navigation_window); + if (end_flag) { + len=route_info_length(NULL, dst, 0); + printf("end %d\n", len); + sd=route_info_street(dst); + itm=navigation_itm_new(this_, &sd->item, route_info_point(pos, 2)); + itm->length=len; + itm->time=route_time(&sd->item, len); + } + itm=navigation_itm_new(this_, NULL, NULL); + route_path_close(rph); + calculate_dest_distance(this_); + make_maneuvers(this_); + p=this_; + callback_list_call(this_->callback, 1, &p); +} + +void +navigation_destroy(struct navigation *this_) +{ + callback_list_destroy(this_->callback); + callback_list_destroy(this_->callback_speech); + g_free(this_); } +struct callback * +navigation_register_callback(struct navigation *this_, enum navigation_mode mode, void (*func)(struct navigation *nav, void *data), void *data) +{ + return callback_list_add_new(this_->callback, func, 1, &data); +} + +void +navigation_unregister_callback(struct navigation *this_, struct callback *cb) +{ + callback_list_remove_destroy(this_->callback, cb); +} diff --git a/navigation.h b/navigation.h index c8c1c399..aa80e6c1 100644 --- a/navigation.h +++ b/navigation.h @@ -1,2 +1,28 @@ -void navigation_path_description(void *route); +#ifdef __cplusplus +extern "C" { +#endif +enum navigation_mode { + navigation_mode_long, + navigation_mode_short, + navigation_mode_speech, +}; +/* prototypes */ +enum navigation_mode; +struct callback; +struct mapset; +struct navigation; +struct navigation_list; +struct route; +struct navigation *navigation_new(struct mapset *ms); +struct navigation_list *navigation_list_new(struct navigation *this_); +char *navigation_list_get(struct navigation_list *this_, enum navigation_mode mode); +void navigation_list_destroy(struct navigation_list *this_); +void navigation_update(struct navigation *this_, struct route *route); +void navigation_destroy(struct navigation *this_); +struct callback *navigation_register_callback(struct navigation *this_, enum navigation_mode mode, void (*func)(struct navigation *nav, void *data), void *data); +void navigation_unregister_callback(struct navigation *this_, struct callback *cb); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/navit.c b/navit.c new file mode 100644 index 00000000..04b22eb3 --- /dev/null +++ b/navit.c @@ -0,0 +1,465 @@ +#include +#include +#include +#include "debug.h" +#include "navit.h" +#include "gui.h" +#include "map.h" +#include "mapset.h" +#include "coord.h" +#include "point.h" +#include "transform.h" +#include "projection.h" +#include "menu.h" +#include "graphics.h" +#include "cursor.h" +#include "popup.h" +#include "route.h" +#include "navigation.h" +#include "track.h" + +struct navit { + GList *mapsets; + GList *layouts; + struct gui *gui; + struct layout *layout_current; + struct graphics *gra; + struct action *action; + struct transformation *trans; + struct compass *compass; + struct map_data *map_data; + struct menu *menu; + struct menu *toolbar; + struct statusbar *statusbar; + struct menu *menubar; + struct route *route; + struct navigation *navigation; + struct cursor *cursor; + struct speech *speech; + struct vehicle *vehicle; + struct track *track; + struct map_flags *flags; + int ready; + struct window *win; + struct displaylist *displaylist; + int cursor_flag; + int update; + int follow; + int update_curr; + int follow_curr; +}; + +struct gui * +main_loop_gui; + + +void +navit_add_mapset(struct navit *this_, struct mapset *ms) +{ + this_->mapsets = g_list_append(this_->mapsets, ms); +} + +struct mapset * +navit_get_mapset(struct navit *this_) +{ + return this_->mapsets->data; +} + +void +navit_add_layout(struct navit *this_, struct layout *lay) +{ + this_->layouts = g_list_append(this_->layouts, lay); +} + +void +navit_draw(struct navit *this_) +{ + transform_setup_source_rect(this_->trans); + graphics_draw(this_->gra, this_->displaylist, this_->mapsets, this_->trans, this_->layouts, this_->route); + this_->ready=1; +} + +void +navit_draw_displaylist(struct navit *this_) +{ + if (this_->ready) { + graphics_displaylist_draw(this_->gra, this_->displaylist, this_->trans, this_->layouts, this_->route); + } +} + +static void +navit_resize(void *data, int w, int h) +{ + struct navit *this_=data; + transform_set_size(this_->trans, w, h); + navit_draw(this_); +} + +static void +navit_button(void *data, int pressed, int button, struct point *p) +{ + struct navit *this_=data; + if (pressed && button == 1) { + int border=16; + if (! transform_within_border(this_->trans, p, border)) { + navit_set_center_screen(this_, p); + } else + popup(this_, button, p); + } + if (pressed && button == 2) + navit_set_center_screen(this_, p); + if (pressed && button == 3) + popup(this_, button, p); + if (pressed && button == 4) + navit_zoom_in(this_, 2); + if (pressed && button == 5) + navit_zoom_out(this_, 2); +} + +void +navit_zoom_in(struct navit *this_, int factor) +{ + long scale=transform_get_scale(this_->trans)/factor; + if (scale < 1) + scale=1; + transform_set_scale(this_->trans, scale); + navit_draw(this_); +} + +void +navit_zoom_out(struct navit *this_, int factor) +{ + long scale=transform_get_scale(this_->trans)*factor; + transform_set_scale(this_->trans,scale); + navit_draw(this_); +} + +struct navit * +navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom) +{ + struct navit *this_=g_new0(struct navit, 1); + + this_->cursor_flag=1; + this_->trans=transform_new(); + transform_set_projection(this_->trans, pro); + + transform_setup(this_->trans, center, zoom, 0); + /* this_->flags=g_new0(struct map_flags, 1); */ + this_->displaylist=graphics_displaylist_new(); + this_->gui=gui_new(this_, ui, 792, 547); + if (! this_->gui) { + g_warning("failed to create gui '%s'", ui); + navit_destroy(this_); + return NULL; + } + if (gui_has_main_loop(this_->gui)) { + if (! main_loop_gui) { + main_loop_gui=this_->gui; + } else { + g_warning("gui with main loop already active, ignoring this instance"); + navit_destroy(this_); + return NULL; + } + } + this_->menubar=gui_menubar_new(this_->gui); + this_->toolbar=gui_toolbar_new(this_->gui); + this_->statusbar=gui_statusbar_new(this_->gui); + this_->gra=graphics_new(graphics); + if (! this_->gra) { + g_warning("failed to create graphics '%s'", graphics); + navit_destroy(this_); + return NULL; + } + graphics_register_resize_callback(this_->gra, navit_resize, this_); + graphics_register_button_callback(this_->gra, navit_button, this_); + if (gui_set_graphics(this_->gui, this_->gra)) { + g_warning("failed to connect graphics '%s' to gui '%s'\n", graphics, ui); + navit_destroy(this_); + return NULL; + } + graphics_init(this_->gra); + return this_; +} + +static void +navit_map_toggle(struct menu *menu, void *this__p, void *map_p) +{ + if ((menu_get_toggle(menu) != 0) != (map_get_active(map_p) != 0)) { + map_set_active(map_p, (menu_get_toggle(menu) != 0)); + navit_draw(this__p); + } +} + +static void +navit_projection_set(struct menu *menu, void *this__p, void *pro_p) +{ + struct navit *this_=this__p; + enum projection pro=(enum projection) pro_p; + struct coord_geo g; + struct coord *c; + + c=transform_center(this_->trans); + transform_to_geo(transform_get_projection(this_->trans), c, &g); + transform_set_projection(this_->trans, pro); + transform_from_geo(pro, &g, c); + navit_draw(this_); +} + +static void +navit_set_destination_menu(struct menu *menu, void *this__p, void *c_p) +{ + struct navit *this_=this__p; + struct coord *c=c_p; + if (this_->route) { + route_set_destination(this_->route, c); + navit_draw(this_); + } + +} + +void +navit_set_destination(struct navit *this_, struct coord *c, char *description) +{ + int fd; + char *buffer; + buffer=g_strdup_printf("0x%x 0x%x %s\n", c->x, c->y, description); + fd=open("destination.txt", O_RDWR|O_CREAT|O_APPEND, 0644); + if (fd != -1) + write(fd, buffer, strlen(buffer)); + close(fd); + g_free(buffer); + if (this_->route) { + route_set_destination(this_->route, c); + navit_draw(this_); + } +} + +struct navit *global_navit; + +static void +navit_show_roadbook(struct navigation *nav, void *data) +{ + struct navigation_list *list; + char *str; + + list=navigation_list_new(nav); + while ((str=navigation_list_get(list, navigation_mode_long))) { + printf("%s\n", str); + } + navigation_list_destroy(list); +} + +void +navit_init(struct navit *this_) +{ + struct menu *mapmen,*men,*men2; + struct map *map; + struct mapset_handle *handle; + struct mapset *ms=this_->mapsets->data; + + if (this_->menubar) { + mapmen=menu_add(this_->menubar, "Map", menu_type_submenu, NULL, NULL, NULL); + // menu_add(map, "Test", menu_type_menu, NULL, NULL); + men=menu_add(mapmen, "Layout", menu_type_submenu, NULL, NULL, NULL); + menu_add(men, "Test", menu_type_menu, NULL, NULL, NULL); + men=menu_add(mapmen, "Projection", menu_type_submenu, NULL, NULL, NULL); + menu_add(men, "M&G", menu_type_menu, navit_projection_set, this_, (void *)projection_mg); + menu_add(men, "Garmin", menu_type_menu, navit_projection_set, this_, (void *)projection_garmin); + handle=mapset_open(ms); + while ((map=mapset_next(handle,0))) { + char *s=g_strdup_printf("%s:%s", map_get_type(map), map_get_filename(map)); + men2=menu_add(mapmen, s, menu_type_toggle, navit_map_toggle, this_, map); + menu_set_toggle(men2, map_get_active(map)); + g_free(s); + } + mapset_close(handle); + } + { + struct mapset *ms=this_->mapsets->data; + struct coord c; + int pos,flag=0; + FILE *f; + + char buffer[2048]; + this_->route=route_new(ms); + this_->navigation=navigation_new(ms); + dbg(0,"navigation_register_callback(%p, ... %p)\n", this_->navigation, this_); + navigation_register_callback(this_->navigation, navigation_mode_long, navit_show_roadbook, this_); +#if 1 + this_->track=track_new(ms); +#endif + men=NULL; + if (this_->menubar) { + men=menu_add(this_->menubar, "Route", menu_type_submenu, NULL, NULL, NULL); + men=menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL); + } + f=fopen("destination.txt", "r"); + if (f) { + while (! feof(f) && fgets(buffer, 2048, f)) { + if ((pos=coord_parse(buffer, projection_mg, &c))) { + if (buffer[pos] && buffer[pos] != '\n' ) { + struct coord *cn=g_new(struct coord, 1); + *cn=c; + buffer[strlen(buffer)-1]='\0'; + if (men) + menu_add(men, buffer+pos+1, menu_type_menu, navit_set_destination_menu, this_, cn); + } + flag=1; + } + } + fclose(f); + if (flag) + route_set_destination(this_->route, &c); + } + } + global_navit=this_; +} + +void +navit_set_center(struct navit *this_, struct coord *center) +{ + struct coord *c=transform_center(this_->trans); + *c=*center; + if (this_->ready) + navit_draw(this_); +} + +static void +navit_set_center_cursor(struct navit *this_, struct coord *cursor, int dir, int xpercent, int ypercent) +{ + struct coord *c=transform_center(this_->trans); + int width, height; + struct point p; + struct coord cnew; + + transform_get_size(this_->trans, &width, &height); + *c=*cursor; + transform_set_angle(this_->trans, dir); + p.x=(100-xpercent)*width/100; + p.y=(100-ypercent)*height/100; + transform_reverse(this_->trans, &p, &cnew); + *c=cnew; + if (this_->ready) + navit_draw(this_); + +} + + +void +navit_set_center_screen(struct navit *this_, struct point *p) +{ + struct coord c; + transform_reverse(this_->trans, p, &c); + navit_set_center(this_, &c); +} + +void +navit_toggle_cursor(struct navit *this_) +{ + this_->cursor_flag=1-this_->cursor_flag; +} + +static void +navit_cursor_offscreen(struct cursor *cursor, void *this__p) +{ + struct navit *this_=this__p; + + if (this_->cursor_flag) + navit_set_center(this_, cursor_pos_get(cursor)); +} + +static void +navit_cursor_update(struct cursor *cursor, void *this__p) +{ + struct navit *this_=this__p; + struct coord *cursor_c=cursor_pos_get(cursor); + int dir=cursor_get_dir(cursor); + + if (this_->track) { + struct coord c=*cursor_c; + if (track_update(this_->track, &c, dir)) { + cursor_c=&c; + cursor_pos_set(cursor, cursor_c); + if (this_->route && this_->update_curr == 1) + route_set_position_from_track(this_->route, this_->track); + } + } else { + if (this_->route && this_->update_curr == 1) + route_set_position(this_->route, cursor_c); + } + if (this_->route && this_->update_curr == 1) + navigation_update(this_->navigation, this_->route); + if (this_->cursor_flag) { + if (this_->follow_curr == 1) + navit_set_center_cursor(this_, cursor_c, dir, 50, 80); + } + if (this_->follow_curr > 1) + this_->follow_curr--; + else + this_->follow_curr=this_->follow; + if (this_->update_curr > 1) + this_->update_curr--; + else + this_->update_curr=this_->update; +} + +void +navit_set_position(struct navit *this_, struct coord *c) +{ + if (this_->route) { + route_set_position(this_->route, c); + if (this_->navigation) { + navigation_update(this_->navigation, this_->route); + } + } + navit_draw(this_); +} + +void +navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow) +{ + this_->vehicle=v; + this_->update_curr=this_->update=update; + this_->follow_curr=this_->follow=follow; + this_->cursor=cursor_new(this_->gra, v, c, this_->trans); + cursor_register_offscreen_callback(this_->cursor, navit_cursor_offscreen, this_); + cursor_register_update_callback(this_->cursor, navit_cursor_update, this_); +} + + +struct gui * +navit_get_gui(struct navit *this_) +{ + return this_->gui; +} + +struct transformation * +navit_get_trans(struct navit *this_) +{ + return this_->trans; +} + +struct route * +navit_get_route(struct navit *this_) +{ + return this_->route; +} + +struct navigation * +navit_get_navigation(struct navit *this_) +{ + return this_->navigation; +} + +struct displaylist * +navit_get_displaylist(struct navit *this_) +{ + return this_->displaylist; +} + +void +navit_destroy(struct navit *this_) +{ + g_free(this_); +} + diff --git a/navit.h b/navit.h new file mode 100644 index 00000000..234391b1 --- /dev/null +++ b/navit.h @@ -0,0 +1,43 @@ +#ifdef __cplusplus +extern "C" { +#endif +extern struct gui *main_loop_gui; +/* prototypes */ +enum projection; +struct color; +struct coord; +struct displaylist; +struct gui; +struct layout; +struct mapset; +struct navigation; +struct navit; +struct point; +struct route; +struct transformation; +struct vehicle; +void navit_add_mapset(struct navit *this_, struct mapset *ms); +struct mapset *navit_get_mapset(struct navit *this_); +void navit_add_layout(struct navit *this_, struct layout *lay); +void navit_draw(struct navit *this_); +void navit_draw_displaylist(struct navit *this_); +void navit_zoom_in(struct navit *this_, int factor); +void navit_zoom_out(struct navit *this_, int factor); +struct navit *navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom); +void navit_set_destination(struct navit *this_, struct coord *c, char *description); +void navit_init(struct navit *this_); +void navit_set_center(struct navit *this_, struct coord *center); +void navit_set_center_screen(struct navit *this_, struct point *p); +void navit_toggle_cursor(struct navit *this_); +void navit_set_position(struct navit *this_, struct coord *c); +void navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow); +struct gui *navit_get_gui(struct navit *this_); +struct transformation *navit_get_trans(struct navit *this_); +struct route *navit_get_route(struct navit *this_); +struct navigation *navit_get_navigation(struct navit *this_); +struct displaylist *navit_get_displaylist(struct navit *this_); +void navit_destroy(struct navit *this_); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/navit.xml b/navit.xml new file mode 100644 index 00000000..2339d15f --- /dev/null +++ b/navit.xml @@ -0,0 +1,477 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phrase.c b/phrase.c index 761de5a1..b3fef2a8 100644 --- a/phrase.c +++ b/phrase.c @@ -1,4 +1,5 @@ #include +#include #include "coord.h" #include "route.h" #include "speech.h" @@ -15,12 +16,16 @@ phrase_route_calc(void *speech) void phrase_route_calculated(void *speech, void *route) { +#if 0 struct tm *eta; +#endif if (! speech) return; +#if 0 /* FIXME */ eta=route_get_eta(route); speech_sayf(speech,"Die Route wurde berechnet, geschätzte Ankunftszeit %d Uhr %d Entfernung %4.0f Kilometer", eta->tm_hour,eta->tm_min,route_get_len(route)/1000); +#endif } diff --git a/plugin.c b/plugin.c index e7edfe40..65db7973 100644 --- a/plugin.c +++ b/plugin.c @@ -1,21 +1,197 @@ -#include -#include +#include +#include #include "plugin.h" +#include "file.h" #define PLUGIN_C #include "plugin.h" -void -plugin_load(void) -{ - char *plugin="plugins/poi_geodownload/plugin_poi_geodownload.so"; - void *h=dlopen(plugin,RTLD_LAZY); +struct plugin { + int active; + int lazy; + char *name; + GModule *mod; void (*init)(void); +}; + +struct plugins { + GHashTable *hash; + GList *list; +}; + +struct plugin * +plugin_new(char *plugin) +{ + struct plugin *ret; + if (! g_module_supported()) { + return NULL; + } + ret=g_new0(struct plugin, 1); + ret->name=g_strdup(plugin); + return ret; + +} + +int +plugin_load(struct plugin *pl) +{ + gpointer init; + + GModule *mod; - if (! h) { - /* printf("can't load '%s', Error '%s'\n", plugin, dlerror()); */ + if (pl->mod) { + g_warning("can't load '%s', already loaded\n", pl->name); + return 0; + } + mod=g_module_open(pl->name, pl->lazy ? G_MODULE_BIND_LAZY : 0); + if (! mod) { + g_warning("can't load '%s', Error '%s'\n", pl->name, g_module_error()); + return 0; + } + if (!g_module_symbol(mod, "plugin_init", &init)) { + g_warning("can't load '%s', plugin_init not found\n", pl->name); + g_module_close(mod); + return 0; } else { - init=dlsym(h,"plugin_init"); - if (init) - (*init)(); + pl->mod=mod; + pl->init=init; + } + return 1; +} + +char * +plugin_get_name(struct plugin *pl) +{ + return pl->name; +} + +int +plugin_get_active(struct plugin *pl) +{ + return pl->active; +} + +void +plugin_set_active(struct plugin *pl, int active) +{ + pl->active=active; +} + +void +plugin_set_lazy(struct plugin *pl, int lazy) +{ + pl->lazy=lazy; +} + +void +plugin_call_init(struct plugin *pl) +{ + pl->init(); +} + +void +plugin_unload(struct plugin *pl) +{ + g_module_close(pl->mod); + pl->mod=NULL; +} + +void +plugin_destroy(struct plugin *pl) +{ + g_free(pl); +} + +struct plugins * +plugins_new(void) +{ + struct plugins *ret=g_new0(struct plugins, 1); + ret->hash=g_hash_table_new(g_str_hash, g_str_equal); + return ret; +} + +void +plugins_add_path(struct plugins *pls, char *path, int active, int lazy) +{ + struct file_wordexp *we; + int i, count; + char **array; + char *name; + struct plugin *pl; + + we=file_wordexp_new(path); + count=file_wordexp_get_count(we); + array=file_wordexp_get_array(we); + for (i = 0 ; i < count ; i++) { + name=array[i]; + if (! (pl=g_hash_table_lookup(pls->hash, name))) { + pl=plugin_new(name); + if (! pl) { + g_warning("failed to create plugin '%s'\n", name); + continue; + } + g_hash_table_insert(pls->hash, plugin_get_name(pl), pl); + pls->list=g_list_append(pls->list, pl); + } else { + pls->list=g_list_remove(pls->list, pl); + pls->list=g_list_append(pls->list, pl); + } + plugin_set_active(pl, active); + plugin_set_lazy(pl, lazy); + } + file_wordexp_destroy(we); +} + +void +plugins_init(struct plugins *pls) +{ + struct plugin *pl; + GList *l; + + l=pls->list; + while (l) { + pl=l->data; + if (plugin_get_active(pl)) + if (!plugin_load(pl)) + plugin_set_active(pl, 0); + l=g_list_next(l); + } + l=pls->list; + while (l) { + pl=l->data; + if (plugin_get_active(pl)) + plugin_call_init(pl); + l=g_list_next(l); + } +} + +void +plugins_destroy(struct plugins *pls) +{ + GList *l; + struct plugin *pl; + + l=pls->list; + while (l) { + pl=l->data; + plugin_unload(pl); + plugin_destroy(pl); + } + g_list_free(pls->list); + g_hash_table_destroy(pls->hash); + g_free(pls); +} + +void * +plugin_get_type(enum plugin_type type, const char *name) +{ + GList *l; + struct name_val *nv; + l=plugin_types[type]; + while (l) { + nv=l->data; + if (!g_ascii_strcasecmp(nv->name, name)) + return nv->val; + l=g_list_next(l); } + return NULL; } diff --git a/plugin.h b/plugin.h index 84e0845d..d6e7c17d 100644 --- a/plugin.h +++ b/plugin.h @@ -1,5 +1,18 @@ -void plugin_load(void); -int plugin_init(void); +#ifndef PLUGIN_C + +#ifdef __cplusplus +extern "C" { +#endif + +struct plugin; + +enum plugin_type { + plugin_type_map, + plugin_type_gui, + plugin_type_graphics, + plugin_type_last, +}; +#endif struct container; struct popup; @@ -7,6 +20,7 @@ struct popup_item; #undef PLUGIN_FUNC1 #undef PLUGIN_FUNC3 #undef PLUGIN_FUNC4 +#undef PLUGIN_TYPE #define PLUGIN_PROTO(name,args...) void name(args) #ifdef PLUGIN_C @@ -38,6 +52,32 @@ PLUGIN_PROTO((*plugin_##name##_func),t1 p1,t2 p2,t3 p3,t4 p4); \ void plugin_call_##name(t1 p1,t2 p2, t3 p3, t4 p4) PLUGIN_CALL(name,p1,p2,p3,p4) \ PLUGIN_REGISTER(name,t1 p1,t2 p2,t3 p3,t4 p4) +struct name_val { + char *name; + void *val; +}; + +GList *plugin_types[plugin_type_last]; + +#define PLUGIN_TYPE(type,newargs) \ +struct type##_priv; \ +struct type##_methods; \ +void \ +plugin_register_##type##_type(const char *name, struct type##_priv *(*new_) newargs) \ +{ \ + struct name_val *nv; \ + nv=g_new(struct name_val, 1); \ + nv->name=g_strdup(name); \ + nv->val=new_; \ + plugin_types[plugin_type_##type]=g_list_append(plugin_types[plugin_type_##type], nv); \ +} \ + \ +void * \ +plugin_get_##type##_type(const char *name) \ +{ \ + return plugin_get_type(plugin_type_##type, name); \ +} + #else #define PLUGIN_FUNC1(name,t1,p1) \ void plugin_register_##name(void(*func)(t1 p1)); \ @@ -50,7 +90,35 @@ void plugin_call_##name(t1 p1,t2 p2,t3 p3); #define PLUGIN_FUNC4(name,t1,p1,t2,p2,t3,p3,t4,p4) \ void plugin_register_##name(void(*func)(t1 p1,t2 p2,t3 p3,t4 p4)); \ void plugin_call_##name(t1 p1,t2 p2,t3 p3,t4 p4); + +#define PLUGIN_TYPE(type,newargs) \ +struct type##_priv; \ +struct type##_methods; \ +void plugin_register_##type##_type(const char *name, struct type##_priv *(*new_) newargs); \ +void *plugin_get_##type##_type(const char *name); + #endif -PLUGIN_FUNC1(draw, struct container *, co) -PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) +#include "plugin_def.h" + +void plugin_init(void); +/* prototypes */ +struct plugin *plugin_new(char *plugin); +int plugin_load(struct plugin *pl); +char *plugin_get_name(struct plugin *pl); +int plugin_get_active(struct plugin *pl); +void plugin_set_active(struct plugin *pl, int active); +void plugin_set_lazy(struct plugin *pl, int lazy); +void plugin_call_init(struct plugin *pl); +void plugin_unload(struct plugin *pl); +void plugin_destroy(struct plugin *pl); +struct plugins *plugins_new(void); +void plugins_add_path(struct plugins *pls, char *path, int active, int lazy); +void plugins_init(struct plugins *pls); +void plugins_destroy(struct plugins *pls); +void *plugin_get_type(enum plugin_type type, const char *name); +/* end of prototypes */ + +#ifdef __cplusplus +} +#endif diff --git a/plugin_def.h b/plugin_def.h new file mode 100644 index 00000000..4108a782 --- /dev/null +++ b/plugin_def.h @@ -0,0 +1,7 @@ +enum projection; +PLUGIN_FUNC1(draw, struct container *, co) +PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) +PLUGIN_TYPE(map, (struct map_methods *meth, char *data, char **charset, enum projection *pro)) +struct navit; +PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, int w, int h)) +PLUGIN_TYPE(graphics, (struct graphics_methods *meth)) diff --git a/popup.c b/popup.c index bf6fea08..4d1c812b 100644 --- a/popup.c +++ b/popup.c @@ -1,87 +1,28 @@ -#include +#include #include -#include -#include -#include "coord.h" -#include "file.h" -#include "map_data.h" -#include "block.h" -#include "display.h" -#include "town.h" -#include "street.h" -#include "poly.h" -#include "log.h" +#include +#include +#include +#include #include "popup.h" -#include "plugin.h" -#include "vehicle.h" -#include "route.h" -#include "cursor.h" -#include "statusbar.h" -#include "container.h" +#include "debug.h" +#include "navit.h" +#include "coord.h" +#include "gui.h" +#include "menu.h" +#include "point.h" +#include "transform.h" +#include "projection.h" +#include "map.h" #include "graphics.h" +#include "item.h" +#include "route.h" -static void -popup_item_destroy_text(struct popup_item *item) -{ - g_free(item->text); - g_free(item); -} - -struct popup_item * -popup_item_new_text(struct popup_item **last, char *text, int priority) -{ - struct popup_item *curr; - curr=g_new0(struct popup_item,1); - curr->text=g_strdup(text); - curr->priority=priority; - curr->destroy=popup_item_destroy_text; - if (last) { - curr->next=*last; - *last=curr; - } - return curr; -} - -static struct popup_item * -popup_item_new_func(struct popup_item **last, char *text, int priority, void (*func)(struct popup_item *, void *), void *param) -{ - struct popup_item *curr=popup_item_new_text(last, text, priority); - curr->func=func; - curr->param=param; - return curr; -} - -static struct popup_item * -param_to_menu_new(char *name,struct param_list *plist, int c, int iso) -{ - struct popup_item *last, *curr, *ret; - int i; - - ret=popup_item_new_text(NULL,name,1); - last=NULL; - for (i = 0 ; i < c ; i++) { - char *name_buffer = g_strjoin(":",plist[i].name, plist[i].value,NULL); - char *text = name_buffer; - - if (iso) { - text=g_convert(name_buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - if (! text) { - printf("problem converting '%s'\n", name_buffer); - } - } - curr=popup_item_new_text(&last,text,i); - if (iso) - g_free(text); - g_free(name_buffer); - - } - ret->submenu=last; - return ret; -} - +#if 0 static void popup_set_no_passing(struct popup_item *item, void *param) { +#if 0 struct display_list *l=param; struct segment *seg=(struct segment *)(l->data); struct street_str *str=(struct street_str *)(seg->data[0]); @@ -93,32 +34,36 @@ popup_set_no_passing(struct popup_item *item, void *param) sprintf(log,"Attributes Street 0x%x updated: limit=0x%x(0x%x)", segid, 0x33, str->limit); str->limit=0x33; log_write(log, seg->blk_inf.file, str, sizeof(*str)); +#endif } +#endif + static void -popup_set_destination(struct popup_item *item, void *param) +popup_set_destination(struct menu *menu, void *data1, void *data2) { - struct popup_item *ref=param; - struct popup *popup=ref->param; - struct container *co=popup->co; - printf("Destination %s\n", ref->text); - route_set_position(co->route, cursor_pos_get(co->cursor)); - route_set_destination(co->route, &popup->c); - graphics_redraw(popup->co); - if (co->statusbar && co->statusbar->statusbar_route_update) - co->statusbar->statusbar_route_update(co->statusbar, co->route); + struct navit *nav=data1; + struct coord *c=data2; + struct route *route; + struct coord_geo g; + char buffer[1024]; + char buffer_geo[1024]; + transform_to_geo(transform_get_projection(navit_get_trans(nav)), c, &g); + transform_geo_text(&g, buffer_geo); + sprintf(buffer,"Map Point %s", buffer_geo); + navit_set_destination(nav, c, buffer); } + extern void *vehicle; static void -popup_set_position(struct popup_item *item, void *param) +popup_set_position(struct menu *menu, void *data1, void *data2) { - struct popup_item *ref=param; - struct popup *popup=ref->param; - printf("Position %s\n", ref->text); - g_assert(popup->co->vehicle != NULL); - vehicle_set_position(popup->co->vehicle, &popup->c); + struct navit *nav=data1; + struct coord *c=data2; + dbg(0,"%p %p\n", nav, c); + navit_set_position(nav, c); } #if 0 @@ -138,170 +83,139 @@ popup_break_crossing(struct display_list *l) } #endif -static void -popup_call_func(GtkObject *obj, void *parm) + +#define popup_printf(menu, type, fmt...) popup_printf_cb(menu, type, NULL, NULL, NULL, fmt) + +static void * +popup_printf_cb(void *menu, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2, const char *fmt, ...) { - struct popup_item *curr=parm; - curr->func(curr, curr->param); + gchar *str; + va_list ap; + void *ret; + + va_start(ap, fmt); + str=g_strdup_vprintf(fmt, ap); + dbg(0,"%s\n", str); + ret=menu_add(menu, str, type, callback, data1, data2); + va_end(ap); + g_free(str); + return ret; } -static GtkWidget * -popup_menu(struct popup_item *list) +static void +popup_show_attr_val(void *menu, struct attr *attr) { - int min_prio,curr_prio; - struct popup_item *curr; - GtkWidget *item,*menu,*submenu; + char *attr_name=attr_to_name(attr->type); - curr_prio=0; - menu=gtk_menu_new(); - do { - min_prio=INT_MAX; - curr=list; - while (curr) { - if (curr->priority == curr_prio) { - item=gtk_menu_item_new_with_label(curr->text); - gtk_menu_append(GTK_MENU(menu), item); - if (curr->submenu) { - submenu=popup_menu(curr->submenu); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); - } else if (curr->func) { - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK (popup_call_func), curr); - } - } - if (curr->priority > curr_prio && curr->priority < min_prio) - min_prio=curr->priority; - curr=curr->next; - } - curr_prio=min_prio; - } while (min_prio != INT_MAX); - return menu; + if (attr->type == attr_limit) + popup_printf(menu, menu_type_menu, "%s: %d", attr_name, attr->u.num); + else + popup_printf(menu, menu_type_menu, "%s: %s", attr_name, attr->u.str); } +#if 0 static void -popup_display_list_default(struct display_list *d, struct popup_item **popup_list) +popup_show_attr(void *menu, struct item *item, enum attr_type attr_type) { - struct segment *seg; - char *desc,*text,*item_text; - struct popup_item *curr_item,*submenu; - struct param_list plist[100]; - - desc=NULL; - if (d->type == 0) desc="Polygon"; - if (d->type == 1) desc="Polyline"; - if (d->type == 2) desc="Street"; - if (d->type == 3) desc="Label"; - if (d->type == 4) desc="Point"; - seg=(struct segment *)(d->data); - if (seg) { - if (d->label && strlen(d->label)) - item_text=g_strjoin(" ",desc,d->label,NULL); - else - item_text=g_strdup(desc); - text=g_convert(item_text,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - curr_item=popup_item_new_text(popup_list,text,1); - g_free(text); - g_free(item_text); - - curr_item->submenu=param_to_menu_new("File", plist, file_get_param(seg->blk_inf.file, plist, 100), 1); - submenu=curr_item->submenu; - submenu->next=param_to_menu_new("Block", plist, block_get_param(&seg->blk_inf, plist, 100), 1); - submenu=submenu->next; - - if (d->type == 0 || d->type == 1) { - submenu->next=param_to_menu_new(desc, plist, poly_get_param(seg, plist, 100), 1); - } - if (d->type == 2) { - submenu->next=param_to_menu_new(desc, plist, street_get_param(seg, plist, 100, 1), 1); - popup_item_new_func(&submenu->next,"Set no passing", 1000, popup_set_no_passing, d); - } - if (d->type == 3) { - submenu->next=param_to_menu_new(desc, plist, town_get_param(seg, plist, 100), 1); - } - if (d->type == 4) { - submenu->next=param_to_menu_new(desc, plist, street_bti_get_param(seg, plist, 100), 1); - } - } + struct attr attr; + memset(&attr, 0, sizeof(attr)); + attr.type=attr_type; + if (item_attr_get(item, attr_type, &attr)) + popup_show_attr_val(menu, &attr); } +#endif static void -popup_display_list(struct container *co, struct popup *popup, struct popup_item **popup_list) +popup_show_attrs(void *menu, struct item *item) { - GtkWidget *menu, *item; - struct display_list *list[100],**p=list; - - menu=gtk_menu_new(); - item=gtk_menu_item_new_with_label("Selection"); - gtk_menu_append (GTK_MENU(menu), item); - display_find(&popup->pnt, co->disp, display_end, 3, list, 100); - while (*p) { - if (! (*p)->info) - popup_display_list_default(*p, popup_list); +#if 0 + popup_show_attr(menu, item, attr_debug); + popup_show_attr(menu, item, attr_address); + popup_show_attr(menu, item, attr_phone); + popup_show_attr(menu, item, attr_phone); + popup_show_attr(menu, item, attr_entry_fee); + popup_show_attr(menu, item, attr_open_hours); +#else + struct attr attr; + for (;;) { + memset(&attr, 0, sizeof(attr)); + if (item_attr_get(item, attr_any, &attr)) + popup_show_attr_val(menu, &attr); else - (*(*p)->info)(*p, popup_list); - p++; - } + break; + } + +#endif } static void -popup_destroy_items(struct popup_item *item) +popup_show_item(void *popup, struct displayitem *di) { - struct popup_item *next; - while (item) { - if (item->active && item->func) - item->func(item, item->param); - if (item->submenu) - popup_destroy_items(item->submenu); - next=item->next; - assert(item->destroy != NULL); - item->destroy(item); - item=next; + struct map_rect *mr; + void *menu, *menu_map, *menu_item; + char *label; + struct item *item; + + label=graphics_displayitem_get_label(di); + item=graphics_displayitem_get_item(di); + + if (label) + menu=popup_printf(popup, menu_type_submenu, "%s '%s'", item_to_name(item->type), label); + else + menu=popup_printf(popup, menu_type_submenu, "%s", item_to_name(item->type)); + menu_item=popup_printf(menu, menu_type_submenu, "Item"); + popup_printf(menu_item, menu_type_menu, "type: 0x%x", item->type); + popup_printf(menu_item, menu_type_menu, "id: 0x%x 0x%x", item->id_hi, item->id_lo); + if (item->map) { + mr=map_rect_new(item->map,NULL); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + dbg(1,"item=%p\n", item); + if (item) { + popup_show_attrs(menu_item, item); + } + map_rect_destroy(mr); + menu_map=popup_printf(menu, menu_type_submenu, "Map"); + } else { + popup_printf(menu, menu_type_menu, "(No map)"); } } static void -popup_destroy(GtkObject *obj, void *parm) +popup_display(struct navit *nav, void *popup, struct point *p) { - struct popup *popup=parm; - - popup_destroy_items(popup->items); - g_free(popup); + struct displaylist_handle *dlh; + struct displaylist *display; + struct displayitem *di; + + display=navit_get_displaylist(nav); + dlh=graphics_displaylist_open(display); + while ((di=graphics_displaylist_next(dlh))) { + if (graphics_displayitem_within_dist(di, p, 5)) { + popup_show_item(popup, di); + } + } + graphics_displaylist_close(dlh); } +struct coord c; + void -popup(struct container *co, int x, int y, int button) +popup(struct navit *nav, int button, struct point *p) { - GtkWidget *menu; - struct popup *popup=g_new(struct popup,1); - struct popup_item *list=NULL; - struct popup_item *descr; + void *popup,*men; + char buffer[1024]; struct coord_geo g; - char buffer[256]; - - popup->co=co; - popup->pnt.x=x; - popup->pnt.y=y; - transform_reverse(co->trans, &popup->pnt, &popup->c); - popup_display_list(co, popup, &list); - plugin_call_popup(co, popup, &list); - transform_lng_lat(&popup->c, &g); - strcpy(buffer,"Map Point "); - transform_geo_text(&g, buffer+strlen(buffer)); - sprintf(buffer+strlen(buffer), " (0x%lx,0x%lx)", popup->c.x, popup->c.y); - descr=popup_item_new_text(&list,buffer, 0); - descr->param=popup; - - popup_item_new_func(&list,"Set as Position", 1000, popup_set_position, descr); - popup_item_new_func(&list,"Set as Destination", 1001, popup_set_destination, descr); - - popup->items=list; - menu=popup_menu(list); - gtk_widget_show_all(menu); - popup->gui_data=menu; - - gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time()); - g_signal_connect(G_OBJECT(menu), "selection-done", G_CALLBACK (popup_destroy), popup); + popup=gui_popup_new(navit_get_gui(nav)); + transform_reverse(navit_get_trans(nav), p, &c); + men=popup_printf(popup, menu_type_submenu, "Point 0x%x 0x%x", c.x, c.y); + popup_printf(men, menu_type_menu, "Screen %d %d", p->x, p->y); + transform_to_geo(transform_get_projection(navit_get_trans(nav)), &c, &g); + transform_geo_text(&g, buffer); + popup_printf(men, menu_type_menu, "%s", buffer); + popup_printf(men, menu_type_menu, "%f %f", g.lat, g.lng); + dbg(0,"%p %p\n", nav, &c); + popup_printf_cb(men, menu_type_menu, popup_set_position, nav, &c, "Set as position"); + popup_printf_cb(men, menu_type_menu, popup_set_destination, nav, &c, "Set as destination"); + popup_display(nav, popup, p); } - - diff --git a/popup.h b/popup.h index 989d5155..13be9802 100644 --- a/popup.h +++ b/popup.h @@ -1,22 +1,3 @@ -void popup(struct container *co, int x, int y, int button); -struct popup_item *popup_item_new_text(struct popup_item **last, char *text, int priority); - -struct popup { - struct container *co; - struct point pnt; - struct coord c; - void *gui_data; - struct popup_item *items; - struct popup_item *active; -}; - -struct popup_item { - char *text; - int priority; - void (*func)(struct popup_item *, void *); - void *param; - struct popup_item *submenu; - struct popup_item *next; - void (*destroy)(struct popup_item *); - int active; -}; +struct navit; +struct point; +void popup(struct navit *nav, int button, struct point *p); diff --git a/profile.c b/profile.c index b9417470..c8ea5371 100644 --- a/profile.c +++ b/profile.c @@ -1,25 +1,39 @@ +#include #include #include #include #include "profile.h" void -profile_timer(char *where) +profile_timer(int level, const char *module, const char *function, const char *fmt, ...) { - static struct timeval last; + va_list ap; + static struct timeval last[3]; struct timeval curr; int msec,usec; - if (where) { + if (level < 0) + level=0; + if (level > 2) + level=2; + if (fmt) { gettimeofday(&curr, NULL); - msec=(curr.tv_usec-last.tv_usec)/1000+ - (curr.tv_sec-last.tv_sec)*1000; - if (msec >= 100) { - printf("%s:%d msec\n", where, msec); - } else { - usec=(curr.tv_usec-last.tv_usec)+(curr.tv_sec-last.tv_sec)*1000*1000; - printf("%s:%d usec\n", where, usec); + msec=(curr.tv_usec-last[level].tv_usec)/1000+ + (curr.tv_sec-last[level].tv_sec)*1000; + printf("%s:%s ", module, function); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + if (msec >= 100) + printf(" %d msec\n", msec); + else { + usec=(curr.tv_usec-last[level].tv_usec)+(curr.tv_sec-last[level].tv_sec)*1000*1000; + printf(" %d.%d msec\n", usec/1000, usec%1000); } + gettimeofday(&last[level], NULL); + } else { + gettimeofday(&curr, NULL); + for (level = 0 ; level < 3 ; level++) + last[level]=curr; } - gettimeofday(&last, NULL); } diff --git a/profile.h b/profile.h index 50280354..0a548d6b 100644 --- a/profile.h +++ b/profile.h @@ -1 +1,8 @@ -void profile_timer(char *where); +#ifdef __cplusplus +extern "C" { +#endif +#define profile(level,fmt...) profile_timer(level,MODULE,__PRETTY_FUNCTION__,fmt) +void profile_timer(int level, const char *module, const char *function, const char *fmt, ...); +#ifdef __cplusplus +} +#endif diff --git a/projection.h b/projection.h new file mode 100644 index 00000000..9d73f1b0 --- /dev/null +++ b/projection.h @@ -0,0 +1,3 @@ +enum projection { + projection_none, projection_mg, projection_garmin +}; diff --git a/python.c b/python.c new file mode 100644 index 00000000..4b85bebb --- /dev/null +++ b/python.c @@ -0,0 +1,281 @@ +#include "config.h" +#ifdef HAVE_PYTHON +#include +#include +#include "coord.h" +#include "map.h" +#include "mapset.h" + +#if defined(MS_WINDOWS) || defined(__CYGWIN__) +#define Obj_HEAD PyObject_HEAD_INIT(NULL); +#else +#define Obj_HEAD PyObject_HEAD_INIT(&PyType_Type) +#endif + +/* *** coord *** */ + +typedef struct { + PyObject_HEAD + struct coord *c; +} coordObject; + +static void coord_destroy_py(coordObject *self); + +PyTypeObject coord_Type = { + Obj_HEAD + .tp_name="coord", + .tp_basicsize=sizeof(coordObject), + .tp_dealloc=(destructor)coord_destroy_py, +}; + + +/* *** map *** */ + +typedef struct { + PyObject_HEAD + struct map *m; +} mapObject; + +static void map_destroy_py(mapObject *self); +static PyObject *map_getattr_py(PyObject *self, char *name); + +PyTypeObject map_Type = { + Obj_HEAD + .tp_name="map", + .tp_basicsize=sizeof(mapObject), + .tp_dealloc=(destructor)map_destroy_py, + .tp_getattr=map_getattr_py, +}; + +/* *** IMPLEMENTATIONS *** */ + +/* *** coord *** */ + +static PyObject * +coord_new_py(PyObject *self, PyObject *args) +{ + coordObject *ret; + int x,y; + if (!PyArg_ParseTuple(args, "ii:navit.coord",&x,&y)) + return NULL; + ret=PyObject_NEW(coordObject, &coord_Type); + ret->c=coord_new(x,y); + return (PyObject *)ret; +} + +static void +coord_destroy_py(coordObject *self) +{ + coord_destroy(self->c); +} + +/* *** coord_rect *** */ + +typedef struct { + PyObject_HEAD + struct coord_rect *r; +} coord_rectObject; + + +static void coord_rect_destroy_py(coord_rectObject *self); + +PyTypeObject coord_rect_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="coord_rect", + .tp_basicsize=sizeof(coord_rectObject), + .tp_dealloc=(destructor)coord_rect_destroy_py, +}; + +static PyObject * +coord_rect_new_py(PyObject *self, PyObject *args) +{ + coord_rectObject *ret; + coordObject *lu,*rd; + if (!PyArg_ParseTuple(args, "O!O!:navit.coord_rect_rect",&coord_Type,&lu,&coord_Type,&rd)) + return NULL; + ret=PyObject_NEW(coord_rectObject, &coord_rect_Type); + ret->r=coord_rect_new(lu->c,rd->c); + return (PyObject *)ret; +} + +static void +coord_rect_destroy_py(coord_rectObject *self) +{ + coord_rect_destroy(self->r); +} + +/* *** map_rect *** */ + +typedef struct { + PyObject_HEAD + struct map_rect *mr; +} map_rectObject; + + +static void map_rect_destroy_py(map_rectObject *self); + +PyTypeObject map_rect_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="map_rect", + .tp_basicsize=sizeof(map_rectObject), + .tp_dealloc=(destructor)map_rect_destroy_py, +}; + +static PyObject * +map_rect_new_py(mapObject *self, PyObject *args) +{ + map_rectObject *ret; + coord_rectObject *r; + if (!PyArg_ParseTuple(args, "O!:navit.map_rect_rect",&coord_rect_Type,&r)) + return NULL; + ret=PyObject_NEW(map_rectObject, &map_rect_Type); + ret->mr=map_rect_new(self->m, r->r, NULL, 0); + return (PyObject *)ret; +} + +static void +map_rect_destroy_py(map_rectObject *self) +{ + map_rect_destroy(self->mr); +} + + +/* *** map *** */ + + + +static PyMethodDef map_methods[] = { + {"map_rect_new", (PyCFunction) map_rect_new_py, METH_VARARGS }, + {NULL, NULL }, +}; + +static PyObject * +map_getattr_py(PyObject *self, char *name) +{ + return Py_FindMethod(map_methods, self, name); +} + + +static PyObject * +map_new_py(PyObject *self, PyObject *args) +{ + mapObject *ret; + char *type, *filename; + + if (!PyArg_ParseTuple(args, "ss:navit.map", &type, &filename)) + return NULL; + ret=PyObject_NEW(mapObject, &map_Type); + ret->m=map_new(type,filename); + return (PyObject *)ret; +} + +static void +map_destroy_py(mapObject *self) +{ + map_destroy(self->m); +} + +/* *** mapset *** */ + + +typedef struct { + PyObject_HEAD + struct mapset *ms; +} mapsetObject; + + +static void mapset_destroy_py(mapsetObject *self); +static PyObject *mapset_getattr_py(PyObject *self, char *name); + +PyTypeObject mapset_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="mapset", + .tp_basicsize=sizeof(mapsetObject), + .tp_dealloc=(destructor)mapset_destroy_py, + .tp_getattr=mapset_getattr_py, +}; + +static PyObject * +mapset_add_py(mapsetObject *self, PyObject *args) +{ + mapObject *map; + if (!PyArg_ParseTuple(args, "O:navit.mapset", &map)) + return NULL; + Py_INCREF(map); + mapset_add(self->ms, map->m); + return Py_BuildValue(""); +} + +static PyMethodDef mapset_methods[] = { + {"add", (PyCFunction) mapset_add_py, METH_VARARGS }, + {NULL, NULL }, +}; + +static PyObject * +mapset_getattr_py(PyObject *self, char *name) +{ + return Py_FindMethod(mapset_methods, self, name); +} + +static PyObject * +mapset_new_py(PyObject *self, PyObject *args) +{ + mapsetObject *ret; + if (!PyArg_ParseTuple(args, ":navit.mapset")) + return NULL; + ret=PyObject_NEW(mapsetObject, &mapset_Type); + ret->ms=mapset_new(); + return (PyObject *)ret; +} + +static void +mapset_destroy_py(mapsetObject *self) +{ + mapset_destroy(self->ms); +} + + + +static PyMethodDef navitMethods[]={ + {"coord", coord_new_py, METH_VARARGS, "Create a new coordinate point."}, + {"coord_rect", coord_rect_new_py, METH_VARARGS, "Create a new coordinate rectangle."}, + {"map", map_new_py, METH_VARARGS, "Create a new map."}, + {"mapset", mapset_new_py, METH_VARARGS, "Create a new mapset."}, + {NULL, NULL, 0, NULL} +}; + + +void python_init(void) +{ + int fd,size; + char buffer[65536]; + + return; + + Py_Initialize(); + Py_InitModule("navit", navitMethods); + fd=open("startup.py",O_RDONLY); + if (fd >= 0) { + size=read(fd, buffer, 65535); + if (size > 0) { + buffer[size]='\0'; + PyRun_SimpleString(buffer); + } + } + + Py_Finalize(); + exit(0); +} +#endif diff --git a/python.h b/python.h new file mode 100644 index 00000000..9829b130 --- /dev/null +++ b/python.h @@ -0,0 +1,2 @@ +void python_init(void); + diff --git a/route.c b/route.c index 8907a54b..aa239e75 100644 --- a/route.c +++ b/route.c @@ -1,286 +1,326 @@ #include #include +#if 0 #include #include #include #include +#endif #include +#include "config.h" +#include "debug.h" +#include "profile.h" #include "coord.h" -#include "param.h" -#include "map_data.h" -#include "block.h" -#include "street.h" -#include "street_data.h" -#include "display.h" -#include "transform.h" +#include "map.h" +#include "mapset.h" +#include "item.h" #include "route.h" -#include "phrase.h" -#include "navigation.h" +#include "track.h" +#include "graphics.h" +#include "transform.h" #include "fib-1.0/fib.h" -#include "time.h" -#include "container.h" - -/* Node1: 4 */ -/* Node2: 4 */ -/* Segid: 4 */ -/* len: 4 */ -/* type: 1 */ -/* limit/order: 1 */ -/* 18 Bytes */ -extern void *speech_handle; -static int speed_list[16]={120,120,80,110,90,80,60,90,80,70,60,50,30,10,0,60}; +static int speed_list[]={ + 10, /* street_0 */ + 10, /* street_1_city */ + 30, /* street_2_city */ + 40, /* street_3_city */ + 50, /* street_4_city */ + 80, /* highway_city */ + 60, /* street_1_land */ + 65, /* street_2_land */ + 70, /* street_3_land */ + 80, /* street_4_land */ + 120, /* street_n_lanes */ + 120, /* highway_land */ + 40, /* ramp */ + 30, /* ferry */ +}; int debug_route=0; -#define GC_TEXT_FG 7 -#define GC_TEXT_BG 8 -#define GC_BLACK 9 -#define GC_RED 21 - -int hx=0x1416bc; /* 447C9E dx=3E18, dxmg=5E09*/ -int hy=0x5f224c; /* 5282B5 dy=5E07, dymg=8F1C*/ -int segid_h=0x20461961; - -int hkx=0x1474c5; /* 44BAB6 */ -int hky=0x5fb168; /* 52E0BC */ - -int lx=0x141ac3; -int ly=0x5f2d7a; - -int trace; -/* 0x141b53, 0x5f2065 */ - -struct coord3d { - struct coord xy; - int h; -}; - -struct route_point { - struct route_point *next; - struct route_point *hash_next; - struct route_segment *start; - struct route_segment *end; - struct route_segment *seg; -#if 0 - int conn; - int id; -#endif +struct route_graph_point { + struct route_graph_point *next; + struct route_graph_point *hash_next; + struct route_graph_segment *start; + struct route_graph_segment *end; + struct route_graph_segment *seg; struct fibheap_el *el; int value; - struct coord3d c; + struct coord c; }; -struct route_segment { - struct route_segment *next; - struct route_segment *start_next; - struct route_segment *end_next; - struct route_point *start; - struct route_point *end; - struct street_str *str; - struct street_type *strt; +struct route_graph_segment { + struct route_graph_segment *next; + struct route_graph_segment *start_next; + struct route_graph_segment *end_next; + struct route_graph_point *start; + struct route_graph_point *end; + struct item item; int limit; int len; - int offset; }; -struct street_info { - struct street_header *hdr; - struct street_type *strt; - struct street_str *str; - unsigned char *p; - int bytes; - int include; +struct route_path_segment { + struct item item; + int time; + int length; + struct coord c[2]; + struct route_path_segment *next; +}; + + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; }; struct route_info { - int mode; - struct coord3d seg1,seg2,line1,line2,pos,click; - int seg1_len,seg2_len; - int offset; + struct coord c; + struct coord lp; + int pos; + int dist; - struct block_info blk_inf; - struct street_info str_inf; + int dir; + + struct street_data *street; }; -struct route { - struct map_data *map_data; - double route_time_val; - double route_len_val; +struct route_path { struct route_path_segment *path; struct route_path_segment *path_last; + struct item_hash *path_hash; +}; + + +struct route { + int version; + struct mapset *ms; struct route_info *pos; struct route_info *dst; - struct route_segment *route_segments; - struct route_point *route_points; - struct block_list *blk_lst; + + struct route_graph *graph; + struct route_path *path2; + +}; + +struct route_graph { + struct route_graph_point *route_points; + struct route_graph_segment *route_segments; #define HASH_SIZE 8192 - struct route_point *hash[HASH_SIZE]; + struct route_graph_point *hash[HASH_SIZE]; }; +static struct route_info * route_find_nearest_street(struct mapset *ms, struct coord *c); +static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c); +static void route_graph_update(struct route *this); +static struct route_path *route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst); +static void route_process_street_graph(struct route_graph *this, struct item *item); +static void route_graph_destroy(struct route_graph *this); +static void route_path_update(struct route *this); + + +static void +route_path_destroy(struct route_path *this) +{ + struct route_path_segment *c,*n; + if (! this) + return; + if (this->path_hash) { + item_hash_destroy(this->path_hash); + this->path_hash=NULL; + } + c=this->path; + while (c) { + n=c->next; + g_free(c); + c=n; + } + g_free(this); +} + struct route * -route_new(void) +route_new(struct mapset *ms) { struct route *this=g_new0(struct route, 1); + this->ms=ms; return this; } -static void -route_path_free(struct route *this) +struct mapset * +route_get_mapset(struct route *this) { - struct route_path_segment *curr, *next; - curr=this->path; + return this->ms; +} - while (curr) { - next=curr->next; - g_free(curr); - curr=next; - } - this->path=NULL; - this->path_last=NULL; +struct route_info * +route_get_pos(struct route *this) +{ + return this->pos; } -void -route_mapdata_set(struct route *this, struct map_data *mdata) +struct route_info * +route_get_dst(struct route *this) { - this->map_data=mdata; + return this->dst; } -struct map_data * -route_mapdata_get(struct route *this) +int +route_contains(struct route *this, struct item *item) { - return this->map_data; + if (! this->path2 || !item_hash_lookup(this->path2->path_hash, item)) + return 0; + return 1; } static void -route_add_path_segment(struct route *this, int country, s32 segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) +route_path_update(struct route *this) { - struct route_path_segment *segment=g_new0(struct route_path_segment,1); - - segment->next=NULL; - segment->country=country; - segment->segid=segid; - segment->offset=offset; - segment->dir=dir; - segment->length=len; - segment->time=time; - if (start) - segment->c[0]=*start; - if (end) - segment->c[1]=*end; - if (!this->path) - this->path=segment; - if (this->path_last) - this->path_last->next=segment; - this->path_last=segment; + route_path_destroy(this->path2); + if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst))) { + profile(0,NULL); + route_graph_update(this); + this->path2=route_path_new(this->graph, this->pos, this->dst); + profile(1,"route_path_new"); + profile(0,"end"); + } } void route_set_position(struct route *this, struct coord *pos) { - struct route_info *rt; - - route_path_free(this); - rt=route_find_nearest_street(this->map_data, pos); - route_find_point_on_street(rt); if (this->pos) - g_free(this->pos); - this->pos=rt; - if (this->dst) { - route_find(this, this->pos, this->dst); - } -} - -struct route_path_segment * -route_path_get_all(struct route *this) -{ - return this->path; + route_info_free(this->pos); + this->pos=route_find_nearest_street(this->ms, pos); + dbg(0,"this->pos=%p\n", this->pos); + if (! this->pos) + return; + if (this->dst) + route_path_update(this); } -struct route_path_segment * -route_path_get(struct route *this, s32 segid) +void +route_set_position_from_track(struct route *this, struct track *track) { - struct route_path_segment *curr=this->path; - - while (curr) { - if (curr->segid == segid) - return curr; - curr=curr->next; - } - return NULL; + struct coord *c; + struct route_info *ret; + c=track_get_pos(track); + ret=g_new0(struct route_info, 1); + if (this->pos) + route_info_free(this->pos); + ret->c=*c; + ret->lp=*c; + ret->pos=track_get_segment_pos(track); + ret->dist=0; + ret->dir=0; + ret->street=street_data_dup(track_get_street_data(track)); + this->pos=ret; + if (this->dst) + route_path_update(this); } -void -route_set_destination(struct route *this, struct coord *dest) -{ - struct route_info *rt; +struct map_selection *route_selection; - rt=route_find_nearest_street(this->map_data, dest); - route_find_point_on_street(rt); - if (this->dst) - g_free(this->dst); - this->dst=rt; - route_do_start(this, this->pos, this->dst); +struct map_selection * +route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs) +{ + int dx,dy,sx=1,sy=1,d,m; + struct map_selection *sel=g_new(struct map_selection, 1); + sel->order[layer_town]=0; + sel->order[layer_poly]=0; + sel->order[layer_street]=order; + dbg(1,"%p %p\n", c1, c2); + dx=c1->x-c2->x; + dy=c1->y-c2->y; + if (dx < 0) { + sx=-1; + sel->rect.lu.x=c1->x; + sel->rect.rl.x=c2->x; + } else { + sel->rect.lu.x=c2->x; + sel->rect.rl.x=c1->x; + } + if (dy < 0) { + sy=-1; + sel->rect.lu.y=c2->y; + sel->rect.rl.y=c1->y; + } else { + sel->rect.lu.y=c1->y; + sel->rect.rl.y=c2->y; + } + if (dx*sx > dy*sy) + d=dx*sx; + else + d=dy*sy; + m=d*rel/100+abs; + sel->rect.lu.x-=m; + sel->rect.rl.x+=m; + sel->rect.lu.y+=m; + sel->rect.rl.y-=m; + sel->next=NULL; + return sel; } -struct coord * -route_get_destination(struct route *this) +static struct map_selection * +route_calc_selection(struct coord *c1, struct coord *c2) { - if (! this->dst) - return NULL; - return &this->dst->click.xy; + struct map_selection *ret,*sel; + sel=route_rect(4, c1, c2, 25, 0); + ret=sel; + sel->next=route_rect(8, c1, c1, 0, 40000); + sel=sel->next; + sel->next=route_rect(18, c1, c1, 0, 10000); + sel=sel->next; + sel->next=route_rect(8, c2, c2, 0, 40000); + sel=sel->next; + sel->next=route_rect(18, c2, c2, 0, 10000); + /* route_selection=ret; */ + return ret; } static void -route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data, - void(*func)(struct block_info *, struct street_info *, unsigned char **, unsigned char *, void *)) +route_free_selection(struct map_selection *sel) { - struct street_info str_inf; - struct street_str *str,*str_tmp; - - if (blk_inf->block_number == 0x10c6) { - printf("route_street_foreach p=%p\n", p); + struct map_selection *next; + while (sel) { + next=sel->next; + g_free(sel); + sel=next; } - str_inf.hdr=(struct street_header *)p; - p+=sizeof(struct street_header); - assert(str_inf.hdr->count == blk_inf->block->count); +} - str_inf.bytes=street_get_bytes(blk_inf->block); - - str_inf.strt=(struct street_type *)p; - p+=blk_inf->block->count*sizeof(struct street_type); - str=(struct street_str *)p; - str_tmp=str; - while (str_tmp->segid) - str_tmp++; - p=(unsigned char *)str_tmp; - p+=4; - - while (str->segid) { - str_inf.include=(str[1].segid > 0); - str_inf.str=str; - str_inf.p=p; - func(blk_inf, &str_inf, &p, end-4, data); - if (!str_inf.include) - str_inf.strt++; - str++; - } +void +route_set_destination(struct route *this, struct coord *dst) +{ + profile(0,NULL); + if (this->dst) + route_info_free(this->dst); + this->dst=route_find_nearest_street(this->ms, dst); + if (! this->dst || ! this->pos) + return; + profile(1,"find_nearest_street"); + + route_graph_destroy(this->graph); + this->graph=NULL; + route_path_update(this); + profile(0,"end"); } - -static struct route_point * -route_get_point(struct route *this, struct coord3d *c) +static struct route_graph_point * +route_graph_get_point(struct route_graph *this, struct coord *c) { - struct route_point *p=this->route_points; - int hashval=(c->xy.x + c->xy.y + c->h) & (HASH_SIZE-1); + struct route_graph_point *p=this->route_points; + int hashval=(c->x + c->y) & (HASH_SIZE-1); p=this->hash[hashval]; while (p) { - if (p->c.xy.x == c->xy.x && p->c.xy.y == c->xy.y && p->c.h == c->h) + if (p->c.x == c->x && p->c.y == c->y) return p; p=p->hash_next; } @@ -288,29 +328,21 @@ route_get_point(struct route *this, struct coord3d *c) } -static struct route_point * -route_point_add(struct route *this, struct coord3d *f, int conn) +static struct route_graph_point * +route_graph_add_point(struct route_graph *this, struct coord *f) { int hashval; - struct route_point *p; + struct route_graph_point *p; - p=route_get_point(this,f); - if (p) { -#if 0 - p->conn+=conn; -#endif - } else { - hashval=(f->xy.x + f->xy.y + f->h) & (HASH_SIZE-1); + p=route_graph_get_point(this,f); + if (!p) { + hashval=(f->x + f->y) & (HASH_SIZE-1); if (debug_route) - printf("p (0x%lx,0x%lx,0x%x)\n", f->xy.x, f->xy.y, f->h); - p=g_new(struct route_point,1); + printf("p (0x%x,0x%x)\n", f->x, f->y); + p=g_new(struct route_graph_point,1); p->hash_next=this->hash[hashval]; this->hash[hashval]=p; p->next=this->route_points; -#if 0 - p->conn=conn; - p->id=++id; -#endif p->el=NULL; p->start=NULL; p->end=NULL; @@ -322,10 +354,11 @@ route_point_add(struct route *this, struct coord3d *f, int conn) return p; } + static void -route_points_free(struct route *this) +route_graph_free_points(struct route_graph *this) { - struct route_point *curr,*next; + struct route_graph_point *curr,*next; curr=this->route_points; while (curr) { next=curr->next; @@ -337,32 +370,113 @@ route_points_free(struct route *this) } static void -route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, struct street_type *strt, int offset, int limit) +route_graph_add_segment(struct route_graph *this, struct route_graph_point *start, struct route_graph_point *end, int len, struct item *item, int limit) { - struct route_segment *s; - s=g_new0(struct route_segment,1); + struct route_graph_segment *s; + s=g_new0(struct route_graph_segment,1); s->start=start; s->start_next=start->start; start->start=s; s->end=end; s->end_next=end->end; end->end=s; + g_assert(len >= 0); s->len=len; - s->str=str; - s->strt=strt; - s->offset=offset; + s->item=*item; s->limit=limit; s->next=this->route_segments; this->route_segments=s; if (debug_route) - printf("l (0x%lx,0x%lx,0x%x)-(0x%lx,0x%lx,0x%x)\n", start->c.xy.x, start->c.xy.y, start->c.h, end->c.xy.x, end->c.xy.y, end->c.h); + printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y); } static void -route_segments_free(struct route *this) +route_path_add_item(struct route_path *this, struct item *itm, struct coord *start, struct coord *end, int len, int time) +{ + struct route_path_segment *segment=g_new0(struct route_path_segment,1); + item_hash_insert(this->path_hash, itm, (void *)1); + segment->item=*itm; + segment->next=NULL; + segment->length=len; + segment->time=time; + if (start) + segment->c[0]=*start; + if (end) + segment->c[1]=*end; + if (!this->path) + this->path=segment; + if (this->path_last) + this->path_last->next=segment; + this->path_last=segment; +} + + +struct route_path_handle { + struct route_path_segment *s; +}; + +struct route_path_handle * +route_path_open(struct route *this) +{ + struct route_path_handle *ret=g_new(struct route_path_handle, 1); + + ret->s=this->path2->path; + return ret; +} + +struct route_path_segment * +route_path_get_segment(struct route_path_handle *h) +{ + struct route_path_segment *ret=h->s; + + if (ret) + h->s=ret->next; + + return ret; +} + +struct coord * +route_path_segment_get_start(struct route_path_segment *s) +{ + return &s->c[0]; +} + +struct coord * +route_path_segment_get_end(struct route_path_segment *s) +{ + return &s->c[1]; +} + +struct item * +route_path_segment_get_item(struct route_path_segment *s) +{ + return &s->item; +} + +int +route_path_segment_get_length(struct route_path_segment *s) +{ + return s->length; +} + +int +route_path_segment_get_time(struct route_path_segment *s) +{ + return s->time; +} + +void +route_path_close(struct route_path_handle *h) +{ + g_free(h); +} + + +static void +route_graph_free_segments(struct route_graph *this) { - struct route_segment *curr,*next; + struct route_graph_segment *curr,*next; curr=this->route_segments; while (curr) { next=curr->next; @@ -372,165 +486,156 @@ route_segments_free(struct route *this) this->route_segments=NULL; } -void -route_display_points(struct route *this, struct container *co) +static void +route_graph_destroy(struct route_graph *this) { -#if 0 - GtkMap *map=co->map; - struct route_point *p=this->route_points; - int r=5; - struct point pnt; - char text[256]; - - while (p) { - if (transform(co->trans, &p->c.xy, &pnt)) { - gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], FALSE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - if (p->value != -1) { - sprintf(text,"%d", p->value); -#if 0 - display_text(GTK_WIDGET(map)->window, map->gc[GC_TEXT_FG], map->gc[GC_TEXT_BG], map->face[0], text, pnt.x+6, pnt.y+4, 0x10000, 0); -#endif - } - } - p=p->next; + if (this) { + route_graph_free_points(this); + route_graph_free_segments(this); + g_free(this); } -#endif } -static int -route_time(int type, int len) +int +route_time(struct item *item, int len) { - // The following is a quick hack to handle - // properly tolled road, at least in France. - extern struct container *co; - if((type==0x21)||(type==0x61)){ - if(co->flags->tollfree){ - // We don't allow tolled roads. We return the highest possible value. - return len*36; - } else { - type=1; - } - } - if(speed_list[type & 0x3f]<1 || speed_list[type & 0x3f]>150){ - // The road here hasn't its speed correctly set up. - // I think it's best to assign it a high cost for the moment. - printf("Road type %x (%i) is unknown (speed %i, key %i), assigning high cost\n",type,type,speed_list[type & 0x3f],(type & 0x3f)); + int idx=(item->type-type_street_0); + if (idx >= sizeof(speed_list)/sizeof(int) || idx < 0) { + dbg(0,"street idx(%d) out of range [0,%d[", sizeof(speed_list)/sizeof(int)); return len*36; } - return len*36/speed_list[type & 0x3f]; + return len*36/speed_list[idx]; } -static int -route_value(int type, int len) -{ - return route_time(type, len); -} static int -route_get_height(s32 segid, struct coord *c) +route_value(struct item *item, int len) { - if (c->x == 0x141b53 && c->y == 0x5f2065 && (segid == 0x4fad2fa || segid == 0x4fad155)) - return 1; - if (c->x == 0x1477a7 && c->y == 0x5fac38 && (segid == 0x32adac2 || segid == 0x40725c6)) - return 1; - if (c->x == 0x147a4c && c->y == 0x5fb194 && (segid == 0x32adb17 || segid == 0x32adb16)) - return 1; - return 0; + int ret; + if (len < 0) { + printf("len=%d\n", len); + } + g_assert(len >= 0); + ret=route_time(item, len); + dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret); + return ret; } static void -route_process_street_graph(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +route_process_street_graph(struct route_graph *this, struct item *item) { - struct route *this=data; - int limit,flags=0; +#ifdef AVOID_FLOAT + int len=0; +#else double len=0; - struct coord3d f,o,l; - struct route_point *s_pnt,*e_pnt; - - street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - s_pnt=route_point_add(this,&f, 1); - - l=f; - o=f; - while (*p < end) { - flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - if (flags && !str_inf->include) - break; - len+=transform_distance(&l.xy, &o.xy); - l=o; - o=f; - if (flags) - break; +#endif + struct route_graph_point *s_pnt,*e_pnt; + struct coord c,l; + struct attr attr; + + + if (item_coord_get(item, &l, 1)) { + s_pnt=route_graph_add_point(this,&l); + while (item_coord_get(item, &c, 1)) { + len+=transform_distance(&l, &c); + l=c; + } + e_pnt=route_graph_add_point(this,&l); + g_assert(len >= 0); + if (item_attr_get(item, attr_limit, &attr)) + route_graph_add_segment(this, s_pnt, e_pnt, len, item, attr.u.num); + else + route_graph_add_segment(this, s_pnt, e_pnt, len, item, 0); } - len+=transform_distance(&l.xy, &o.xy); - o.h=route_get_height(str_inf->str->segid, &o.xy); - e_pnt=route_point_add(this,&o, 1); - - limit=str_inf->str->limit; - if (str_inf->str->limit == 0x30 && (str_inf->str->type & 0x40)) - limit=0x03; - if (str_inf->str->limit == 0x03 && (str_inf->str->type & 0x40)) - limit=0x30; - - if (str_inf->str->limit != 0x33) - route_segment_add(this, s_pnt, e_pnt, len, str_inf->str, str_inf->strt, 0, limit); - debug_route=0; - *p-=2*str_inf->bytes; } static int compare(void *v1, void *v2) { - struct route_point *p1=v1; - struct route_point *p2=v2; + struct route_graph_point *p1=v1; + struct route_graph_point *p2=v2; +#if 0 + if (debug_route) + printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2); +#endif return p1->value-p2->value; } +int +route_info_length(struct route_info *pos, struct route_info *dst, int dir) +{ + struct route_info_handle *h; + struct coord *c,*l; + int ret=0; + + h=route_info_open(pos, dst, dir); + if (! h) + return -1; + l=route_info_get(h); + while ((c=route_info_get(h))) { + ret+=transform_distance(c, l); + l=c; + } + return ret; +} + static void -route_flood(struct route *this, struct route_info *rt_end) +route_graph_flood(struct route_graph *this, struct route_info *dst) { - struct route_point *end; - struct route_point *p_min; - struct route_segment *s; + struct route_graph_point *p_min,*end=NULL; + struct route_graph_segment *s; int min,new,old,val; struct fibheap *heap; - - heap = fh_makeheap(); + struct street_data *sd=dst->street; + heap = fh_makeheap(); fh_setcmp(heap, compare); - end=route_get_point(this, &rt_end->pos); - assert(end != 0); - end->value=0; - end->el=fh_insert(heap, end); + if (! (sd->limit & 2)) { + end=route_graph_get_point(this, &sd->c[0]); + g_assert(end != 0); + end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, -1))); + end->el=fh_insert(heap, end); + } + + if (! (sd->limit & 1)) { + end=route_graph_get_point(this, &sd->c[sd->count-1]); + g_assert(end != 0); + end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, 1))); + end->el=fh_insert(heap, end); + } + + dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y); for (;;) { p_min=fh_extractmin(heap); if (! p_min) break; min=p_min->value; if (debug_route) - printf("min=%d, 0x%lx, 0x%lx\n", min, p_min->c.xy.x, p_min->c.xy.y); + printf("extract p=%p free el=%p min=%d, 0x%x, 0x%x\n", p_min, p_min->el, min, p_min->c.x, p_min->c.y); + p_min->el=NULL; s=p_min->start; while (s) { - val=route_value(s->str->type, s->len); + val=route_value(&s->item, s->len); #if 0 val+=val*2*street_route_contained(s->str->segid); #endif new=min+val; if (debug_route) - printf("begin %d (0x%lx,0x%lx) ",new,s->end->c.xy.x, s->end->c.xy.y); - if (new < s->end->value && !(s->limit & 0x30)) { + printf("begin %d len %d vs %d (0x%x,0x%x)\n",new,val,s->end->value, s->end->c.x, s->end->c.y); + if (new < s->end->value && !(s->limit & 1)) { s->end->value=new; s->end->seg=s; if (! s->end->el) { if (debug_route) - printf("insert"); + printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value); s->end->el=fh_insert(heap, s->end); + if (debug_route) + printf("el new=%p\n", s->end->el); } else { if (debug_route) - printf("replace"); + printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value); fh_replacedata(heap, s->end->el, s->end); } } @@ -540,21 +645,24 @@ route_flood(struct route *this, struct route_info *rt_end) } s=p_min->end; while (s) { - new=min+route_value(s->str->type, s->len); + val=route_value(&s->item, s->len); + new=min+val; if (debug_route) - printf("end %d vs %d (0x%lx,0x%lx) ",new,s->start->value,s->start->c.xy.x, s->start->c.xy.y); - if (new < s->start->value && !(s->limit & 0x03)) { + printf("end %d len %d vs %d (0x%x,0x%x)\n",new,val,s->start->value,s->start->c.x, s->start->c.y); + if (new < s->start->value && !(s->limit & 2)) { old=s->start->value; s->start->value=new; s->start->seg=s; if (! s->start->el) { if (debug_route) - printf("insert"); + printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value); s->start->el=fh_insert(heap, s->start); + if (debug_route) + printf("el new=%p\n", s->start->el); } else { if (debug_route) - printf("replace"); + printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value); fh_replacedata(heap, s->start->el, s->start); } } @@ -563,495 +671,478 @@ route_flood(struct route *this, struct route_info *rt_end) s=s->end_next; } } + fh_deleteheap(heap); } -int -route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +static struct route_path * +route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst) { - struct route_point *start,*start1,*start2; - struct route_segment *s=NULL; - double len=0,slen; - int ret,hr,min,time=0,seg_time,dir,type; + struct route_graph_point *start1=NULL,*start2=NULL,*start; + struct route_graph_segment *s=NULL; + int len=0,segs=0; + int ilen,hr,min,sec,time=0,seg_time,seg_len; unsigned int val1=0xffffffff,val2=0xffffffff; - - start1=route_get_point(this, &rt_start->seg1); - start2=route_get_point(this, &rt_start->seg2); - assert(start1 != 0); - assert(start2 != 0); - if (start1->value != -1) - val1=start1->value+route_value(rt_start->str_inf.str->type, rt_start->seg1_len); - if (start2->value != -1) - val2=start2->value+route_value(rt_start->str_inf.str->type, rt_start->seg2_len); - - route_add_path_segment(this, 0, 0, 0, &rt_start->click.xy, &rt_start->pos.xy, 1, 0, 0); - type=rt_start->str_inf.str->type; - if (val1 < val2) { - ret=1; - start=start1; - slen=transform_distance(&rt_start->pos.xy, &rt_start->line1.xy); - route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line1.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, rt_start->offset, NULL, NULL, -1, rt_start->seg1_len, route_time(type, rt_start->seg1_len)); + struct street_data *sd=pos->street; + struct route_path *ret; + + if (! (sd->limit & 1)) { + start1=route_graph_get_point(this, &sd->c[0]); + if (! start1) + return NULL; + val1=start1->value+route_value(&sd->item, route_info_length(pos, NULL, -1)); + dbg(0,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1); } - else { - ret=2; - start=start2; - slen=transform_distance(&rt_start->pos.xy, &rt_start->line2.xy); - route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line2.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, -rt_start->offset, NULL, NULL, 1, rt_start->seg2_len, route_time(type, rt_start->seg2_len)); + if (! (sd->limit & 2)) { + start2=route_graph_get_point(this, &sd->c[sd->count-1]); + if (! start2) + return NULL; + val2=start2->value+route_value(&sd->item, route_info_length(pos, NULL, 1)); + dbg(0,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2); } - - while (start->value) { - s=start->seg; - if (! s) { - printf("No Route found\n"); - break; + if (start1 && (val1 < val2)) { + start=start1; + pos->dir=-1; + } else { + if (start2) { + start=start2; + pos->dir=1; + } else { + printf("no route found, pos blocked\n"); + return NULL; } + } + ret=g_new0(struct route_path, 1); + ret->path_hash=item_hash_new(); + dbg(0,"dir=%d\n", pos->dir); + while ((s=start->seg)) { + segs++; +#if 0 + printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y); +#endif + seg_len=s->len; + seg_time=route_time(&s->item, seg_len); + len+=seg_len; + time+=seg_time; if (s->start == start) { + route_path_add_item(ret, &s->item, &s->start->c, &s->end->c, seg_len, seg_time); start=s->end; - dir=1; - } - else { + } else { + route_path_add_item(ret, &s->item, &s->end->c, &s->start->c, seg_len, seg_time); start=s->start; - dir=-1; } - len+=s->len; - seg_time=route_time(s->str->type, s->len); - time+=seg_time; - route_add_path_segment(this, s->strt->country, s->str->segid, s->offset, NULL, NULL, dir, s->len, seg_time); } - if (s) { - if (s->start->c.xy.x == rt_end->seg1.xy.x && s->start->c.xy.y == rt_end->seg1.xy.y) - route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line1.xy, -1, 0, 0); - else - route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); - route_add_path_segment(this, 0, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); -#if 0 - printf("len %5.3f\n", len/1000); -#endif - this->route_time_val=time/10; - time/=10; - this->route_len_val=len; - min=time/60; - time-=min*60; - hr=min/60; - min-=hr*60; -#if 0 - printf("time %02d:%02d:%02d\n", hr, min, time); -#endif -#if 1 - navigation_path_description(this); -#endif + sd=dst->street; + dbg(0,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y); + dbg(0,"dst sd->limit=%d sd->c[0]=0x%x,0x%x sd->c[sd->count-1]=0x%x,0x%x\n", sd->limit, sd->c[0].x,sd->c[0].y, sd->c[sd->count-1].x, sd->c[sd->count-1].y); + if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) + dst->dir=-1; + else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) + dst->dir=1; + else { + printf("no route found\n"); + route_path_destroy(ret); + return NULL; } + ilen=route_info_length(pos, NULL, 0); + time+=route_time(&pos->street->item, ilen); + len+=ilen; + + ilen=route_info_length(NULL, dst, 0); + time+=route_time(&dst->street->item, ilen); + len+=ilen; + + dbg(0, "%d segments\n", segs); + dbg(0, "len %5.3f\n", len/1000.0); + time/=10; + sec=time; + min=time/60; + time-=min*60; + hr=min/60; + min-=hr*60; + dbg(0, "time %02d:%02d:%02d (%d sec)\n", hr, min, time, sec); + dbg(0, "speed %f km/h\n", len/sec*3.6); return ret; } -struct block_list { - struct block_info blk_inf; - unsigned char *p; - unsigned char *end; - struct block_list *next; -}; - -static void -route_process_street_block_graph(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +static struct route_graph * +route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2) { - struct route *this=data; - struct block_list *blk_lst=this->blk_lst; - - while (blk_lst) { - if (blk_lst->blk_inf.block_number == blk_inf->block_number && blk_lst->blk_inf.file == blk_inf->file) - return; - blk_lst=blk_lst->next; - } - blk_lst=g_new(struct block_list,1); - blk_lst->blk_inf=*blk_inf; - blk_lst->p=p; - blk_lst->end=end; - blk_lst->next=this->blk_lst; - this->blk_lst=blk_lst; -#if 0 - route_street_foreach(blk_inf, p, end, data, route_process_street_graph); -#endif -} + struct route_graph *ret=g_new0(struct route_graph, 1); + struct map_selection *sel; + struct mapset_handle *h; + struct map_rect *mr; + struct map *m; + struct item *item; + struct coord e; + + sel=route_calc_selection(c1, c2); + h=mapset_open(ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + route_process_street_graph(ret, item); + } else + while (item_coord_get(item, &e, 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); + route_free_selection(sel); -static void -route_blocklist_free(struct route *this) -{ - struct block_list *curr,*next; - curr=this->blk_lst; - while (curr) { - next=curr->next; - g_free(curr); - curr=next; - } + return ret; } static void -route_build_graph(struct route *this, struct map_data *mdata, struct coord *c, int coord_count) +route_graph_update(struct route *this) { - struct coord rect[2]; - struct transformation t; - - int i,j,max_dist,max_coord_dist; - int ranges[7]={0,1024000,512000,256000,128000,64000,32000}; - this->blk_lst=NULL; - struct block_list *blk_lst_curr; - - rect[0]=c[0]; - rect[1]=c[0]; - for (i = 1 ; i < coord_count ; i++) { - if (c[i].x < rect[0].x) - rect[0].x=c[i].x; - if (c[i].x > rect[1].x) - rect[1].x=c[i].x; - if (c[i].y > rect[0].y) - rect[0].y=c[i].y; - if (c[i].y < rect[1].y) - rect[1].y=c[i].y; - } - max_coord_dist=rect[1].x-rect[0].x; - if (max_coord_dist < rect[0].y-rect[1].y) - max_coord_dist=rect[0].y-rect[1].y; - max_coord_dist+=10000+max_coord_dist/2; - - printf("Collecting Blocks\n"); - for (i = 0 ; i < coord_count ; i++) { - for (j = 0 ; j < 7 ; j++) { - printf("range %d,%d\n", i, j); - max_dist=ranges[j]; - if (max_dist == 0 || max_dist > max_coord_dist) - max_dist=max_coord_dist; - - transform_setup_source_rect_limit(&t,&c[i],max_dist); - - map_data_foreach(mdata, file_street_str, &t, j+1, route_process_street_block_graph, this); - } - } - blk_lst_curr=this->blk_lst; - i=0; - while (blk_lst_curr) { - i++; - blk_lst_curr=blk_lst_curr->next; - } - printf("Block Count %d\n", i); - blk_lst_curr=this->blk_lst; - - j=0; - while (blk_lst_curr) { - j++; - printf("%d/%d\n", j, i); - route_street_foreach(&blk_lst_curr->blk_inf, blk_lst_curr->p, blk_lst_curr->end, this, route_process_street_graph); - blk_lst_curr=blk_lst_curr->next; - } + route_graph_destroy(this->graph); + profile(1,"graph_free"); + this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c); + profile(1,"route_graph_build"); + route_graph_flood(this->graph, this->dst); + profile(1,"route_graph_flood"); + this->version++; } -static void -route_process_street3(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +struct street_data * +street_get_data (struct item *item) { - int flags=0; - int i,ldist; - struct coord3d first,f,o,l; - struct coord3d cret; - int match=0; - double len=0,len_p=0; - struct route_info *rt_inf=(struct route_info *)data; - - street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - - l=f; - o=f; - first=f; - i=0; - - while (*p < end) { - flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - if (flags && !str_inf->include) - break; - - if (i++) { - ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); - if (ldist < rt_inf->dist) { - rt_inf->dist=ldist; - rt_inf->seg1=first; - rt_inf->line1=l; - rt_inf->pos=cret; - rt_inf->blk_inf=*blk_inf; - rt_inf->str_inf=*str_inf; - rt_inf->line2=o; - rt_inf->offset=i-1; - len_p=len; - match=1; - } - if (rt_inf->mode == 1) - len+=transform_distance(&l.xy, &o.xy); - } - l=o; - o=f; - if (flags) + struct coord c[1000]; + int count=0; + struct street_data *ret; + struct attr attr; + + while (count < 1000) { + if (!item_coord_get(item, &c[count], 1)) break; - } - ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); - if (ldist < rt_inf->dist) { - rt_inf->dist=ldist; - rt_inf->seg1=first; - rt_inf->line1=l; - rt_inf->pos=cret; - rt_inf->blk_inf=*blk_inf; - rt_inf->str_inf=*str_inf; - rt_inf->line2=o; - rt_inf->offset=i; - len_p=len; - match=1; + count++; } - if (match) { - rt_inf->seg2=o; - if (rt_inf->mode == 1) { - len+=transform_distance(&l.xy, &o.xy); - len_p+=transform_distance(&rt_inf->pos.xy, &rt_inf->line1.xy); - rt_inf->seg1_len=len_p; - rt_inf->seg2_len=len-len_p; - } - } - *p-=2*str_inf->bytes; -} + g_assert(count < 1000); + ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord)); + ret->item=*item; + ret->count=count; + if (item_attr_get(item, attr_limit, &attr)) + ret->limit=attr.u.num; + else + ret->limit=0; + memcpy(ret->c, c, count*sizeof(struct coord)); + return ret; + +} -static void -route_process_street_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +struct street_data * +street_data_dup(struct street_data *orig) { - route_street_foreach(blk_inf, p, end, data, route_process_street3); -} + struct street_data *ret; + int size=sizeof(struct street_data)+orig->count*sizeof(struct coord); + + ret=g_malloc(size); + memcpy(ret, orig, size); -struct street_str * -route_info_get_street(struct route_info *rt) -{ - return rt->str_inf.str; + return ret; } -struct block_info * -route_info_get_block(struct route_info *rt) +void +street_data_free(struct street_data *sd) { - return &rt->blk_inf; + g_free(sd); } -struct route_info * -route_find_nearest_street(struct map_data *mdata, struct coord *c) +static struct route_info * +route_find_nearest_street(struct mapset *ms, struct coord *c) { - struct route_info *ret=g_new0(struct route_info,1); - struct transformation t; + struct route_info *ret=NULL; int max_dist=1000; - - transform_setup_source_rect_limit(&t,c,max_dist); + struct map_selection *sel=route_rect(18, c, c, 0, max_dist); + int dist,pos; + struct mapset_handle *h; + struct map *m; + struct map_rect *mr; + struct item *item; + struct coord lp, sc[1000]; + struct street_data *sd; + + h=mapset_open(ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + sd=street_get_data(item); + dist=transform_distance_polyline_sq(sd->c, sd->count, c, &lp, &pos); + if (!ret || dist < ret->dist) { + if (ret) { + street_data_free(ret->street); + g_free(ret); + } + ret=g_new(struct route_info, 1); + ret->c=*c; + ret->lp=lp; + ret->pos=pos; + ret->dist=dist; + ret->dir=0; + ret->street=sd; + dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos); + } else + street_data_free(sd); + } else + while (item_coord_get(item, &sc[0], 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); - ret->click.xy=*c; - ret->dist=INT_MAX; - ret->mode=0; - - map_data_foreach(mdata, file_street_str, &t, 48, route_process_street_block, ret); - return ret; } void -route_find_point_on_street(struct route_info *rt_inf) +route_info_free(struct route_info *inf) { - unsigned char *p,*end; - - rt_inf->dist=INT_MAX; - rt_inf->mode=1; - - p=rt_inf->str_inf.p; - end=(unsigned char *)rt_inf->blk_inf.block; - end+=rt_inf->blk_inf.block->size; - - route_process_street3(&rt_inf->blk_inf, &rt_inf->str_inf, &p, end, rt_inf); + if (inf->street) + street_data_free(inf->street); + g_free(inf); } -struct route_info *start,*end; -int count; +#include "point.h" +#include "projection.h" -void -route_click(struct route *this, struct container *co, int x, int y) +struct street_data * +route_info_street(struct route_info *rinf) { -#if 0 - GtkMap *map=co->map; - struct point pnt; - GdkBitmap *flag_mask; - GdkPixmap *flag; - struct coord c; - struct route_info *rt_inf; - GdkGC *gc; - - - pnt.x=x; - pnt.y=y; - transform_reverse(co->trans, &pnt, &c); - transform(co->trans, &c, &pnt); - rt_inf=route_find_nearest_street(co->map_data, &c); - + return rinf->street; +} - route_find_point_on_street(rt_inf); +struct coord * +route_info_point(struct route_info *rinf, int point) +{ + struct street_data *sd=rinf->street; + int dir; + + switch(point) { + case -1: + case 2: + dir=point == 2 ? rinf->dir : -rinf->dir; + if (dir > 0) + return &sd->c[sd->count-1]; + else + return &sd->c[0]; + case 0: + return &rinf->c; + case 1: + return &rinf->lp; + } + return NULL; - flag=gdk_pixmap_create_from_xpm_d(GTK_WIDGET(map)->window, &flag_mask, NULL, flag_xpm); - gc=gdk_gc_new(map->DrawingBuffer); +} - gdk_gc_set_clip_origin(gc,pnt.x, pnt.y-15); - gdk_gc_set_clip_mask(gc,flag_mask); - gdk_draw_pixmap(GTK_WIDGET(map)->window, - gc, - flag, - 0, 0, pnt.x, pnt.y-15, 16, 16); - printf("Segment ID 0x%lx\n", rt_inf->str_inf.str->segid); -#if 0 - printf("Segment Begin 0x%lx, 0x%lx, 0x%x\n", route_info.seg1.xy.x, route_info.seg1.xy.y, route_info.seg1.h); - printf("Segment End 0x%lx, 0x%lx, 0x%x\n", route_info.seg2.xy.x, route_info.seg2.xy.y, route_info.seg2.h); -#endif +struct route_info_handle { + struct route_info *start; + struct route_info *curr; + struct route_info *end; + struct coord *last; + int count; + int iter; + int pos; + int endpos; + int dir; +}; -#if 0 - transform(map, &route_info.seg1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.line1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.seg2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.line2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.pos.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); -#endif - printf("offset=%d\n", rt_inf->offset); - printf("seg1_len=%d\n", rt_inf->seg1_len); - printf("seg2_len=%d\n", rt_inf->seg2_len); - - if (trace) { - start=rt_inf; - count=0; - route_path_free(this); - route_find(this, start, end); - map_redraw(map); - } else { - if (! count) { - start=rt_inf; - count=1; +struct route_info_handle * +route_info_open(struct route_info *start, struct route_info *end, int dir) +{ + struct route_info_handle *ret=g_new0(struct route_info_handle, 1); + + struct route_info *curr; + dbg(1,"enter\n"); + ret->start=start; + ret->end=end; + if (start) + curr=start; + else + curr=end; + ret->endpos=-2; + if (start && end) { + if (start->street->item.map != end->street->item.map || start->street->item.id_hi != end->street->item.id_hi || start->street->item.id_lo != end->street->item.id_lo) { + dbg(1,"return NULL\n"); + return NULL; + } + printf("trivial start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir); + if (start->pos == end->pos) { + printf("fixme\n"); + start->dir=0; + end->dir=0; + } + if (start->pos > end->pos) { + printf("fixme\n"); + start->dir=-1; + end->dir=1; } - else { - end=rt_inf; - count=0; + if (start->pos < end->pos) { + printf("fixme\n"); + start->dir=1; + end->dir=-1; } + printf("trivial now start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir); + ret->endpos=end->pos; } -#endif -} -void -route_start(struct route *this, struct container *co) -{ - route_do_start(this, end, start); -} - -void -route_trace(struct container *co) -{ - trace=1-trace; + if (!dir) + dir=curr->dir; + ret->dir=dir; + ret->curr=curr; + ret->pos=curr->pos; + if (dir > 0) { + ret->pos++; + ret->endpos++; + } + dbg(1,"return %p\n",ret); + return ret; } -static void -route_data_free(void *t) +struct coord * +route_info_get(struct route_info_handle *h) { - route_blocklist_free(t); - route_path_free(t); - route_points_free(t); - route_segments_free(t); + struct coord *new; + for (;;) { + new=NULL; + dbg(1,"iter=%d\n", h->iter); + switch(h->iter) { + case 0: + if (h->start) { + new=&h->start->c; + h->iter++; + break; + } else { + h->iter=2; + continue; + } + case 1: + new=&h->start->lp; + h->iter++; + break; + case 2: + dbg(1,"h->pos=%d\n", h->pos); + if (h->dir && h->pos >= 0 && h->pos < h->curr->street->count && (h->end == NULL || h->endpos!=h->pos)) { + new=&h->curr->street->c[h->pos]; + h->pos+=h->dir; + } else { + h->iter++; + continue; + } + break; + case 3: + if (h->end) { + new=&h->end->lp; + h->iter++; + break; + } + break; + case 4: + new=&h->end->c; + h->iter++; + break; + + } + if (new) { + dbg(1,"new=%p (0x%x,0x%x) last=%p\n", new, new->x, new->y, h->last); + if (h->last && new->x == h->last->x && new->y == h->last->y) + continue; + h->last=new; + return new; + } + return NULL; + } } void -route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +route_info_close(struct route_info_handle *h) { - int res; - struct route_point *seg1,*seg2,*pos; - struct coord c[2]; - struct timeval tv[4]; - - phrase_route_calc(speech_handle); - route_data_free(this); - gettimeofday(&tv[0], NULL); - c[0]=rt_start->pos.xy; - c[1]=rt_end->pos.xy; - route_build_graph(this,this->map_data,c,2); - gettimeofday(&tv[1], NULL); - seg1=route_point_add(this, &rt_end->seg1, 1); - pos=route_point_add(this, &rt_end->pos, 2); - seg2=route_point_add(this ,&rt_end->seg2, 1); - route_segment_add(this, seg1, pos, rt_end->seg1_len, rt_end->str_inf.str, rt_end->str_inf.strt, rt_end->offset, 0); - route_segment_add(this, seg2, pos, rt_end->seg2_len, rt_end->str_inf.str, rt_end->str_inf.strt, -rt_end->offset, 0); - - printf("flood\n"); - route_flood(this, rt_end); - gettimeofday(&tv[2], NULL); - printf("find\n"); - res=route_find(this, rt_start, rt_end); - printf("ok\n"); - gettimeofday(&tv[3], NULL); - - printf("graph time %ld\n", (tv[1].tv_sec-tv[0].tv_sec)*1000+(tv[1].tv_usec-tv[0].tv_usec)/1000); - printf("flood time %ld\n", (tv[2].tv_sec-tv[1].tv_sec)*1000+(tv[2].tv_usec-tv[1].tv_usec)/1000); - printf("find time %ld\n", (tv[3].tv_sec-tv[2].tv_sec)*1000+(tv[3].tv_usec-tv[2].tv_usec)/1000); - phrase_route_calculated(speech_handle, this); - + g_free(h); } -int -route_destroy(void *t) -{ - struct route *this=t; - - route_data_free(t); - if (this->pos) - g_free(this->pos); - if (this->dst) - g_free(this->dst); - g_free(this); - return 0; -} -struct tm * -route_get_eta(struct route *this) +static int +route_draw_route_info(struct route_info *pos, struct route_info *dst, struct transformation *t, struct displaylist *dsp) { - time_t eta; - - eta=time(NULL)+this->route_time_val; - - return localtime(&eta); + struct route_info_handle *h; + struct coord *c; + struct coord_rect r; + struct item item; + struct point pnt[100]; + int count=0; + + item.id_lo=0; + item.id_hi=0; + item.map=NULL; + item.type=type_street_route; + + dbg(1, "enter\n"); + h=route_info_open(pos, dst, 0); + dbg(1,"h=%p\n", h); + if (! h) { + dbg(1, "return 0\n"); + return 0; + } + if (pos) + dbg(1, "pos=%p pos->dir=%d pos->pos=%d\n", pos, pos->dir, pos->pos); + c=route_info_get(h); + r.lu=*c; + r.rl=*c; + while (c && count < 100) { + dbg(1,"c=%p (0x%x,0x%x)\n", c, c->x, c->y); + transform(t, projection_mg, c, &pnt[count++]); + coord_rect_extend(&r, c); + c=route_info_get(h); + + } + if (count && transform_contains(t, projection_mg, &r)) + display_add(dsp, &item, count, pnt, "Route"); + route_info_close(h); + dbg(1, "return 1\n"); + return 1; } -double -route_get_len(struct route *this) +void +route_draw(struct route *this, struct transformation *t, struct displaylist *dsp) { - return this->route_len_val; + dbg(1,"enter\n"); + if (! this->pos || ! this->dst) + return; + if (! route_draw_route_info(this->pos, this->dst, t, dsp)) { + route_draw_route_info(this->pos, NULL, t, dsp); + route_draw_route_info(NULL, this->dst, t, dsp); + } + dbg(1,"exit\n"); } +#if 0 struct route_crossings * route_crossings_get(struct route *this, struct coord *c) { - struct coord3d c3; - struct route_point *pnt; - struct route_segment *seg; - int crossings=0; - struct route_crossings *ret; - - c3.xy=*c; - c3.h=0; - pnt=route_get_point(this, &c3); - seg=pnt->start; - while (seg) { - crossings++; - seg=seg->start_next; - } - seg=pnt->end; - while (seg) { - crossings++; - seg=seg->end_next; - } - ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing)); - ret->count=crossings; - return ret; + struct route_point *pnt; + struct route_segment *seg; + int crossings=0; + struct route_crossings *ret; + + pnt=route_graph_get_point(this, c); + seg=pnt->start; + while (seg) { + printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo); + crossings++; + seg=seg->start_next; + } + seg=pnt->end; + while (seg) { + printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo); + crossings++; + seg=seg->end_next; + } + ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing)); + ret->count=crossings; + return ret; } +#endif diff --git a/route.h b/route.h index 33fcdb58..6cceae8e 100644 --- a/route.h +++ b/route.h @@ -1,18 +1,5 @@ -#include "types.h" - -struct route_path_segment { - struct route_path_segment *next; - int country; - s32 segid; - int offset; - int dir; - int time; - int length; - struct coord c[2]; -}; - struct route_crossing { - s32 segid; + long segid; int dir; }; @@ -21,31 +8,46 @@ struct route_crossings { struct route_crossing crossing[0]; }; +/* prototypes */ +struct coord; +struct displaylist; +struct item; +struct map_selection; +struct mapset; struct route; -struct map_data; -struct container; struct route_info; - -struct route *route_new(void); -int route_destroy(void *t); -void route_mapdata_set(struct route *this, struct map_data *mdata); -struct map_data* route_mapdata_get(struct route *this); -void route_display_points(struct route *this, struct container *co); -void route_click(struct route *this, struct container *co, int x, int y); -void route_start(struct route *this, struct container *co); +struct route_info_handle; +struct route_path_handle; +struct route_path_segment; +struct street_data; +struct track; +struct transformation; +struct route *route_new(struct mapset *ms); +struct mapset *route_get_mapset(struct route *this); +struct route_info *route_get_pos(struct route *this); +struct route_info *route_get_dst(struct route *this); +int route_contains(struct route *this, struct item *item); void route_set_position(struct route *this, struct coord *pos); +void route_set_position_from_track(struct route *this, struct track *track); +struct map_selection *route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs); void route_set_destination(struct route *this, struct coord *dst); -struct coord *route_get_destination(struct route *this); -struct route_path_segment *route_path_get(struct route *, s32 segid); -struct route_path_segment *route_path_get_all(struct route *this); -void route_trace(struct container *co); -struct street_str *route_info_get_street(struct route_info *rt); -struct block_info *route_info_get_block(struct route_info *rt); -struct route_info *route_find_nearest_street(struct map_data *mdata, struct coord *c); -void route_find_point_on_street(struct route_info *rt_inf); -void route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end); -int route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end); -struct tm *route_get_eta(struct route *this); -double route_get_len(struct route *this); -struct route_crossings *route_crossings_get(struct route *this, struct coord *c); - +struct route_path_handle *route_path_open(struct route *this); +struct route_path_segment *route_path_get_segment(struct route_path_handle *h); +struct coord *route_path_segment_get_start(struct route_path_segment *s); +struct coord *route_path_segment_get_end(struct route_path_segment *s); +struct item *route_path_segment_get_item(struct route_path_segment *s); +int route_path_segment_get_length(struct route_path_segment *s); +int route_path_segment_get_time(struct route_path_segment *s); +void route_path_close(struct route_path_handle *h); +int route_time(struct item *item, int len); +int route_info_length(struct route_info *pos, struct route_info *dst, int dir); +struct street_data *street_get_data(struct item *item); +struct street_data *street_data_dup(struct street_data *orig); +void street_data_free(struct street_data *sd); +void route_info_free(struct route_info *inf); +struct street_data *route_info_street(struct route_info *rinf); +struct coord *route_info_point(struct route_info *rinf, int point); +struct route_info_handle *route_info_open(struct route_info *start, struct route_info *end, int dir); +struct coord *route_info_get(struct route_info_handle *h); +void route_info_close(struct route_info_handle *h); +void route_draw(struct route *this, struct transformation *t, struct displaylist *dsp); diff --git a/script/get_map b/script/get_map index 20de37d3..7c8ef970 100755 --- a/script/get_map +++ b/script/get_map @@ -2,4 +2,4 @@ echo "/* XPM */" >map.xpm req="" perl -e 'print (pack("a20",length($ARGV[0]))) ; print $ARGV[0]' "$req" | netcat localhost 10371 | dd bs=20 skip=1 2>/dev/null | tail +2 >>map.xpm - +xv map.xpm & diff --git a/search.c b/search.c index 0d2f17be..8cb2a8d5 100644 --- a/search.c +++ b/search.c @@ -1,442 +1,300 @@ #include -#include -#include -#include -#include "search.h" +#include "debug.h" +#include "mapset.h" +#include "attr.h" #include "coord.h" -#include "country.h" -#include "town.h" -#include "street.h" -#include "street_name.h" - +#include "item.h" +#include "search.h" -struct search { - struct map_data *map_data; - char *country; - GHashTable *country_hash; - char *postal; - char *town; - GHashTable *town_hash; - char *district; - GHashTable *district_hash; - char *street; - GHashTable *street_hash; - char *number; - int number_low, number_high; - int (*func)(struct search_destination *dest, void *user_data); - void *user_data; +struct search_list_level { + struct mapset *ms; + struct item *parent; + struct attr attr; + int partial; + struct mapset_search *search; + GHashTable *hash; + GList *list,*curr,*last; + int complete; + }; -struct dest_town { - int country; - int assoc; - char *name; - char postal_code[16]; - struct town town; +struct search_list { + struct mapset *ms; + int level; + struct search_list_level levels[4]; + struct search_list_result result; }; -static GHashTable * -search_country_new(void) -{ - return g_hash_table_new_full(NULL, NULL, NULL, g_free); -} - -static int -search_country_add(struct country *cou, void *data) -{ - struct search *search=data; - struct country *cou2; - - void *first; - first=g_hash_table_lookup(search->country_hash, (void *)(cou->id)); - if (! first) { - cou2=g_new(struct country, 1); - *cou2=*cou; - g_hash_table_insert(search->country_hash, (void *)(cou->id), cou2); - } - return 0; -} - -static void -search_country_show(gpointer key, gpointer value, gpointer user_data) -{ - struct country *cou=value; - struct search *search=(struct search *)user_data; - struct search_destination dest; - - memset(&dest, 0, sizeof(dest)); - dest.country=cou; - dest.country_name=cou->name; - dest.country_car=cou->car; - dest.country_iso2=cou->iso2; - dest.country_iso3=cou->iso3; - (*search->func)(&dest, search->user_data); -} - static guint -search_town_hash(gconstpointer key) +search_item_hash_hash(gconstpointer key) { - const struct dest_town *hash=key; - gconstpointer hashkey=(gconstpointer)(hash->country^hash->assoc); - return g_direct_hash(hashkey); + const struct item *itm=key; + gconstpointer hashkey=(gconstpointer)(itm->id_hi^itm->id_lo); + return g_direct_hash(hashkey); } static gboolean -search_town_equal(gconstpointer a, gconstpointer b) +search_item_hash_equal(gconstpointer a, gconstpointer b) { - const struct dest_town *t_a=a; - const struct dest_town *t_b=b; - if (t_a->assoc == t_b->assoc && t_a->country == t_b->country) { - if (t_a->name && t_b->name && strcmp(t_a->name, t_b->name)) - return FALSE; + const struct item *itm_a=a; + const struct item *itm_b=b; + if (item_is_equal_id(*itm_a, *itm_b)) return TRUE; - } return FALSE; } - -static GHashTable * -search_town_new(void) +struct search_list * +search_list_new(struct mapset *ms) { - return g_hash_table_new_full(search_town_hash, search_town_equal, NULL, g_free); -} + struct search_list *ret; + ret=g_new0(struct search_list, 1); + ret->ms=ms; + + return ret; +} -static int -search_town_add(struct town *town, void *data) +static void search_list_search_free(struct search_list *sl, int level); +void +search_list_search(struct search_list *this_, struct attr *search_attr, int partial) { - struct search *search=data; - struct dest_town *first; - - struct dest_town cmp; - char *zip1, *zip2; - - if (town->id == 0x1d546b7e) { - printf("found\n"); + int level=-1; + struct search_list_level *le; + switch(search_attr->type) { + case attr_country_all: + level=0; + break; + case attr_town_name: + level=1; + break; + case attr_street_name: + level=2; + break; + default: + break; } - cmp.country=town->country; - cmp.assoc=town->street_assoc; - cmp.name=town->name; - first=g_hash_table_lookup(search->town_hash, &cmp); - if (! first) { - first=g_new(struct dest_town, 1); - first->country=cmp.country; - first->assoc=cmp.assoc; - strcpy(first->postal_code, town->postal_code2); - first->name=town->name; - first->town=*town; - g_hash_table_insert(search->town_hash, first, first); - } else { - zip1=town->postal_code2; - zip2=first->postal_code; - while (*zip1 && *zip2) { - if (*zip1 != *zip2) { - while (*zip2) { - *zip2++='.'; - } - break; - } - zip1++; - zip2++; + dbg(0,"level=%d\n", level); + if (level != -1) { + this_->level=level; + le=&this_->levels[level]; + le->attr=*search_attr; + le->attr.u.str=g_strdup(search_attr->u.str); + search_list_search_free(this_, level); + le->partial=partial; + if (level > 0) { + le=&this_->levels[level-1]; + le->curr=le->list; } + dbg(1,"le=%p partial=%d\n", le, partial); } - cmp.name=NULL; - cmp.assoc=town->id; - first=g_hash_table_lookup(search->district_hash, &cmp); - if (! first) { - first=g_new(struct dest_town, 1); - first->country=cmp.country; - first->assoc=cmp.assoc; - first->name=NULL; - first->town=*town; - g_hash_table_insert(search->district_hash, first, first); - } - return 0; } -static void -search_town_search(gpointer key, gpointer value, gpointer user_data) +static struct search_list_country * +search_list_country_new(struct item *item) { - struct country *cou=value; - struct search *search=user_data; - - town_search_by_name(search->map_data, cou->id, search->town, 1, search_town_add, search); + struct search_list_country *ret=g_new0(struct search_list_country, 1); + struct attr attr; + + ret->item=*item; + if (item_attr_get(item, attr_country_car, &attr)) + ret->car=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_iso2, &attr)) + ret->iso2=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_iso3, &attr)) + ret->iso3=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_name, &attr)) + ret->name=g_strdup(attr.u.str); + return ret; } static void -search_town_set(const struct dest_town *town, struct search_destination *dest, int full) +search_list_country_destroy(struct search_list_country *this_) { - char country[32]; - struct country *cou; - if ((cou=country_get_by_id(town->country))) { - dest->country=cou; - dest->country_name=cou->name; - dest->country_car=cou->car; - dest->country_iso2=cou->iso2; - dest->country_iso3=cou->iso3; - } else { - sprintf(country,"(%d)", town->country); - dest->country=NULL; - dest->country_car=country; - } - if (full) { - dest->town_postal=(char *)(town->town.postal_code2); - dest->town_name=g_convert(town->town.name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - if (town->town.district[0]) - dest->district=g_convert(town->town.district,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - else - dest->district=NULL; - } else { - dest->town_postal=(char *)(town->postal_code); - dest->town_name=g_convert(town->name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - } + g_free(this_->car); + g_free(this_->iso2); + g_free(this_->iso3); + g_free(this_->name); + g_free(this_); } - -static void -search_town_show(gpointer key, gpointer value, gpointer user_data) +static struct search_list_town * +search_list_town_new(struct item *item) { - struct dest_town *town=value; - struct search *search=user_data; - struct search_destination dest; - - memset(&dest, 0, sizeof(dest)); - dest.town=&town->town; - dest.street_name=NULL; - dest.c=town->town.c; - search_town_set(town, &dest, 0); + struct search_list_town *ret=g_new0(struct search_list_town, 1); + struct attr attr; + struct coord c; - (*search->func)(&dest, search->user_data); -} - - -static GHashTable * -search_street_new(void) -{ - return g_hash_table_new_full(NULL, NULL, NULL, g_free); + ret->itemt=*item; + if (item_attr_get(item, attr_town_streets_item, &attr)) { + dbg(1,"town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo); + ret->item=*attr.u.item; + } + else + ret->item=*item; + if (item_attr_get(item, attr_town_name, &attr)) + ret->name=map_convert_string(item->map,attr.u.str); + if (item_attr_get(item, attr_town_postal, &attr)) + ret->postal=map_convert_string(item->map,attr.u.str); + if (item_coord_get(item, &c, 1)) { + ret->c=g_new(struct coord, 1); + *(ret->c)=c; + } + return ret; } - -static int -search_street_add(struct street_name *name, void *data) +static void +search_list_town_destroy(struct search_list_town *this_) { - struct search *search=data; - struct street_name *name2; - - name2=g_new(struct street_name, 1); - *name2=*name; - g_hash_table_insert(search->street_hash, name2, name2); - return 0; + map_convert_free(this_->name); + map_convert_free(this_->postal); + g_free(this_); } -static int -number_partial(int search, int ref, int ext) +static struct search_list_street * +search_list_street_new(struct item *item) { - int max=1; - - printf("number_partial(%d,%d,%d)", search, ref, ext); - if (ref >= 10) - max=10; - if (ref >= 100) - max=100; - if (ref >= 1000) - max=1000; - while (search < max) { - search*=10; - search+=ext; + struct search_list_street *ret=g_new0(struct search_list_street, 1); + struct attr attr; + struct coord c; + + ret->item=*item; + if (item_attr_get(item, attr_street_name, &attr)) + ret->name=map_convert_string(item->map, attr.u.str); + if (item_coord_get(item, &c, 1)) { + ret->c=g_new(struct coord, 1); + *(ret->c)=c; } - printf("max=%d result=%d\n", max, search); - return search; + return ret; } -static int -check_number(int low, int high, int s_low, int s_high) +static void +search_list_street_destroy(struct search_list_street *this_) { - int debug=0; - - if (debug) - printf("check_number(%d,%d,%d,%d)\n", low, high, s_low, s_high); - if (low <= s_high && high >= s_low) - return 1; - if (s_low == s_high) { - if (low <= number_partial(s_high, high, 9) && high >= number_partial(s_low, low, 0)) - return 1; - } - if (debug) - printf("return 0\n"); - return 0; + map_convert_free(this_->name); + g_free(this_); } + static void -search_street_show_common(gpointer key, gpointer value, gpointer user_data, int number) +search_list_result_destroy(int level, void *p) { - struct street_name *name=value; - struct search *search=user_data; - char *utf8; - struct dest_town cmp; - struct dest_town *town; - char buffer[32]; - struct street_name_info info; - struct street_name_number_info num_info; - struct search_destination dest; - int debug=0; - - memset(&dest, 0, sizeof(dest)); - name->tmp_len=name->aux_len; - name->tmp_data=name->aux_data; - while (street_name_get_info(&info, name)) { - cmp.country=info.country; - cmp.assoc=info.dist; - cmp.name=NULL; - town=g_hash_table_lookup(search->district_hash, &cmp); - if (debug) - printf("town=%p\n", town); - if (town) { - search_town_set(town, &dest, 1); - utf8=g_convert(name->name2,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - dest.street_name=utf8; - if (number) { - info.tmp_len=info.aux_len; - info.tmp_data=info.aux_data; - while (street_name_get_number_info(&num_info, &info)) { - dest.town=&town->town; - dest.street=name; - dest.c=num_info.c; - if (check_number(num_info.first, num_info.last, search->number_low, search->number_high)) { - if (num_info.first == num_info.last) - sprintf(buffer,"%d",num_info.first); - else - sprintf(buffer,"%d-%d",num_info.first,num_info.last); - dest.street_number=buffer; - (*search->func)(&dest, search->user_data); - } - } - } else { - dest.town=&town->town; - dest.street=name; - dest.c=info.c; - (*search->func)(&dest, search->user_data); - } - g_free(utf8); - } else { - printf("Town for '%s' not found\n", name->name2); - } + switch (level) { + case 0: + search_list_country_destroy(p); + break; + case 1: + search_list_town_destroy(p); + break; + case 2: + search_list_street_destroy(p); + break; } } static void -search_street_show(gpointer key, gpointer value, gpointer user_data) +search_list_search_free(struct search_list *sl, int level) { - search_street_show_common(key, value, user_data, 0); -} + struct search_list_level *le=&sl->levels[level]; + GList *next,*curr; + if (le->search) { + mapset_search_destroy(le->search); + le->search=NULL; + } + if (le->search) { + g_hash_table_destroy(le->hash); + } + curr=le->list; + while (curr) { + search_list_result_destroy(level, curr->data); + next=g_list_next(curr); + curr=next; + } + g_list_free(le->list); + le->list=NULL; + le->curr=NULL; + le->last=NULL; + le->complete=0; -static void -search_street_show_number(gpointer key, gpointer value, gpointer user_data) -{ - search_street_show_common(key, value, user_data, 1); } -static void -search_street_search(gpointer key, gpointer value, gpointer user_data) +static int +search_add_result(struct search_list_level *le, void *p) { - const struct dest_town *town=value; - struct search *search=user_data; - street_name_search(search->map_data, town->country, town->assoc, search->street, 1, search_street_add, search); + if (! g_hash_table_lookup(le->hash, p)) { + g_hash_table_insert(le->hash, p, (void *)1); + le->list=g_list_append(le->list, p); + return 1; + } + return 0; } - - -void search_update(struct search *search, enum search_param what, char *val) +struct search_list_result * +search_list_get_result(struct search_list *this_) { - char *dash; - - if (what == search_country) { - if (search->country_hash) g_hash_table_destroy(search->country_hash); - search->country_hash=NULL; - } - if (what == search_country || what == search_town) { - if (search->town_hash) g_hash_table_destroy(search->town_hash); - if (search->district_hash) g_hash_table_destroy(search->district_hash); - search->town_hash=NULL; - search->district_hash=NULL; - } - - if (what == search_country || what == search_town || what == search_street) { - if (search->street_hash) g_hash_table_destroy(search->street_hash); - search->street_hash=NULL; - } - - if (what == search_country) { - g_free(search->country); - search->country=g_strdup(val); - if (val) { - search->country_hash=search_country_new(); - country_search_by_name(val, 1, search_country_add, search); - country_search_by_car(val, 1, search_country_add, search); - country_search_by_iso2(val, 1, search_country_add, search); - country_search_by_iso3(val, 1, search_country_add, search); - g_hash_table_foreach(search->country_hash, search_country_show, search); - } - } - if (what == search_town) { - g_free(search->town); - search->town=g_strdup(val); - if (val) { - search->town_hash=search_town_new(); - search->district_hash=search_town_new(); - g_hash_table_foreach(search->country_hash, search_town_search, search); - g_hash_table_foreach(search->town_hash, search_town_show, search); - } - } - if (what == search_street) { - g_free(search->street); - search->street=g_strdup(val); - if (val) { - search->street_hash=search_street_new(); - g_hash_table_foreach(search->town_hash, search_street_search, search); - g_hash_table_foreach(search->street_hash, search_street_show, search); - } - } - if (what == search_number) { - g_free(search->number); - search->number=g_strdup(val); - if (val) { - char buffer[strlen(val)+1]; - strcpy(buffer, val); - dash=index(buffer,'-'); - if (dash) { - *dash++=0; - search->number_low=atoi(buffer); - if (strlen(val)) - search->number_high=atoi(dash); - else - search->number_high=10000; - } else { - if (!strlen(val)) { - search->number_low=0; - search->number_high=10000; - } else { - search->number_low=atoi(val); - search->number_high=atoi(val); - } + struct search_list_level *le,*leu; + struct item *item; + int level=this_->level; + + dbg(1,"enter\n"); + le=&this_->levels[level]; + dbg(1,"le=%p\n", le); + while(! le->complete) { + dbg(1,"le->search=%p\n", le->search); + if (! le->search) { + dbg(1,"partial=%d\n", le->partial); + if (! level) + le->parent=NULL; + else { + leu=&this_->levels[level-1]; + le->parent=leu->curr->data; + leu->last=leu->curr; + leu->curr=g_list_next(leu->curr); } - g_hash_table_foreach(search->street_hash, search_street_show_number, search); + le->search=mapset_search_new(this_->ms, le->parent, &le->attr, le->partial); + le->hash=g_hash_table_new_full(search_item_hash_hash, search_item_hash_equal, g_free, NULL); } + dbg(1,"le->search=%p\n", le->search); + item=mapset_search_get_item(le->search); + dbg(1,"item=%p\n", item); + if (item) { + void *p=NULL; + this_->result.country=NULL; + this_->result.town=NULL; + this_->result.street=NULL; + this_->result.c=NULL; + switch (level) { + case 0: + p=search_list_country_new(item); + this_->result.country=p; + break; + case 1: + p=search_list_town_new(item); + this_->result.country=this_->levels[0].last->data; + this_->result.town=p; + this_->result.c=this_->result.town->c; + break; + case 2: + p=search_list_street_new(item); + this_->result.country=this_->levels[0].last->data; + this_->result.town=this_->levels[1].last->data; + this_->result.street=p; + this_->result.c=this_->result.street->c; + break; + } + if (p) { + if (search_add_result(le, p)) + return &this_->result; + else + search_list_result_destroy(level, p); + } + } else + le->complete=1; } + return NULL; } -struct search * -search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data) +void +search_list_destroy(struct search_list *this_) { - struct search *this=g_new0(struct search,1); - this->map_data=mdat; - this->country=g_strdup(country); - this->postal=g_strdup(postal); - this->town=g_strdup(town); - this->district=g_strdup(district); - this->street=g_strdup(street); - this->number=g_strdup(number); - this->func=func; - this->user_data=user_data; - return this; + g_free(this_); } diff --git a/search.h b/search.h index 88f38826..0a09494e 100644 --- a/search.h +++ b/search.h @@ -1,30 +1,45 @@ -enum search_param { - search_country, - search_postal, - search_town, - search_district, - search_street, - search_number +#ifdef __cplusplus +extern "C" { +#endif +struct search_list_country { + struct item item; + char *car; + char *iso2; + char *iso3; + char *name; }; -struct search_destination { - char *country_name; - char *country_car; - char *country_iso2; - char *country_iso3; - char *town_postal; - char *town_name; - char *district; - char *street_name; - char *street_number; - struct country *country; - struct town *town; - struct street_name *street; +struct search_list_town { + struct item item; + struct item itemt; struct coord *c; + char *postal; + char *name; }; -struct search; -struct map_data; +struct search_list_street { + struct item item; + struct coord *c; + char *name; +}; + +struct search_list_result { + struct coord *c; + struct search_list_country *country; + struct search_list_town *town; + struct search_list_street *street; +}; -void search_update(struct search *search, enum search_param what, char *val); -struct search *search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data); +/* prototypes */ +struct attr; +struct mapset; +struct search_list; +struct search_list_result; +struct search_list *search_list_new(struct mapset *ms); +void search_list_search(struct search_list *this_, struct attr *search_attr, int partial); +struct search_list_result *search_list_get_result(struct search_list *this_); +void search_list_destroy(struct search_list *this_); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/statusbar.h b/statusbar.h index 1b9092c9..1411ef76 100644 --- a/statusbar.h +++ b/statusbar.h @@ -1,10 +1,18 @@ struct route; -struct statusbar_gui; +struct statusbar_priv; +struct point; +struct transformation; + +struct statusbar_methods { + void (*statusbar_destroy)(struct statusbar_priv *this); + void (*statusbar_mouse_update)(struct statusbar_priv *this, struct transformation *tr, struct point *p); + void (*statusbar_route_update)(struct statusbar_priv *this, struct route *route); + void (*statusbar_gps_update)(struct statusbar_priv *this, int sats, int qual, double lng, double lat, double height, double direction, double speed); +}; struct statusbar { - void (*statusbar_destroy)(struct statusbar *this); - void (*statusbar_mouse_update)(struct statusbar *this, struct transformation *tr, struct point *p); - void (*statusbar_route_update)(struct statusbar *this, struct route *route); - void (*statusbar_gps_update)(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed); - struct statusbar_gui *gui; + struct statusbar_methods meth; + struct statusbar_priv *priv; }; + +/* prototypes */ diff --git a/street.c b/street.c index 8633224a..1880e12c 100644 --- a/street.c +++ b/street.c @@ -568,3 +568,49 @@ street_bti_get_param(struct segment *seg, struct param_list *param, int count) return i-count; } + +struct street_data * +street_get_data (struct item *item) +{ + struct coord c[1000]; + int count=0; + struct street_data *ret; + struct attr attr; + + while (count < 1000) { + if (!item_coord_get(item, &c[count], 1)) + break; + count++; + } + g_assert(count < 1000); + ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord)); + ret->item=*item; + ret->count=count; + if (item_attr_get(item, attr_limit, &attr)) + ret->limit=attr.u.num; + else + ret->limit=0; + memcpy(ret->c, c, count*sizeof(struct coord)); + + return ret; + +} + +struct street_data * +street_data_dup(struct street_data *orig) +{ + struct street_data *ret; + int size=sizeof(struct street_data)+orig->count*sizeof(struct coord); + + ret=g_malloc(size); + memcpy(ret, orig, size); + + return ret; +} + +void +street_data_free(struct street_data *sd) +{ + g_free(sd); +} + diff --git a/street_name.c b/street_name.c index cecc62a6..1e8da63a 100644 --- a/street_name.c +++ b/street_name.c @@ -54,7 +54,7 @@ struct street_search_priv { static int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) { - unsigned char c1_u,c2_u; + char c1_u,c2_u; int ret=0; int debug=0; @@ -122,7 +122,7 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d blk_off=(struct block_offset *)(*s2); if (debug) - printf("0x%x\n", get_u32(s2)); + printf("0x%lx\n", get_u32(s2)); else get_u32(s2); struct street_name_index *i1=priv_data->search; @@ -132,7 +132,7 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d printf("Country %d %d\n",i1->country, i2->country); printf("Town_Assoc 0x%lx 0x%lx\n",i1->town_assoc, i2->town_assoc); printf("Name '%s' '%s'\n",i1->name, i2->name); - printf("Leaf Data 0x%x 0x%x %ld\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); + printf("Leaf Data 0x%x 0x%x %d\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); } *s2+=sizeof(*i2)+strlen(i2->name)+1; ret=street_name_compare(i1, i2, priv_data->partial); diff --git a/track.c b/track.c index 2f861650..295e2ab1 100644 --- a/track.c +++ b/track.c @@ -1,3 +1,14 @@ +#include +#include "track.h" +#include "debug.h" +#include "transform.h" +#include "coord.h" +#include "item.h" +#include "route.h" +#include "map.h" +#include "mapset.h" + +#if 0 #include #include #include "coord.h" @@ -6,89 +17,116 @@ #include "profile.h" #include "track.h" +#endif + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; +}; + + struct track_line { + struct street_data *street; +#if 0 long segid; int linenum; struct coord c[2]; struct coord lpnt; int value; - int angle; int dir; +#endif struct track_line *next; + int angle[0]; }; + struct track { - struct map_data *ma; + struct mapset *ms; +#if 0 struct transformation t; +#endif struct coord last_updated; struct track_line *lines; +#if 0 struct track_line **last_ptr; +#endif + struct track_line *curr_line; + int pos; struct coord curr[2]; struct coord last_in; struct coord last_out; }; -int angle_factor=5; + +int angle_factor=10; int connected_pref=-10; int nostop_pref=10; -struct track_line **last; +struct coord * +track_get_pos(struct track *tr) +{ + return &tr->last_out; +} -static void -tst_callback(struct street_str *str, void *handle, void *data) +int +track_get_segment_pos(struct track *tr) { - struct coord c[2]; - int visible=0,count=0; - struct track *tr=data; - struct track_line *lines; - int debug_segid=0; - int debug=0; + return tr->pos; +} - /* printf("tst_callback id=0x%x ",str->segid < 0 ? -str->segid : str->segid); */ - if (street_coord_handle_get(handle, &c[0], 1)) { - if (str->segid == debug_segid) - printf("0x%lx,0x%lx ", c->x, c->y); - c[1]=c[0]; - while (street_coord_handle_get(handle, &c[0], 1)) { - if (is_line_visible(&tr->t, c)) { - visible=1; - } - c[1]=c[0]; - count++; - if (str->segid == debug_segid) - printf("0x%lx,0x%lx ", c->x, c->y); - } - } - if (visible) { - lines=g_new(struct track_line, count); - street_coord_handle_rewind(handle); - street_coord_handle_get(handle, &c[0], 1); - count=0; - while (street_coord_handle_get(handle, &c[1], 1)) { - *(tr->last_ptr)=lines; - tr->last_ptr=&lines->next; - lines->segid=str->segid; - lines->linenum=count; - lines->c[0]=c[0]; - lines->c[1]=c[1]; - lines->angle=transform_get_angle(c,0); - lines->next=NULL; - lines++; - count++; - c[0]=c[1]; - } - if (debug) - printf("%d lines\n", count); - } - /* printf("\n"); */ +struct street_data * +track_get_street_data(struct track *tr) +{ + return tr->curr_line->street; +} + +static void +track_get_angles(struct track_line *tl) +{ + int i; + struct street_data *sd=tl->street; + for (i = 0 ; i < sd->count-1 ; i++) + tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0); } static void -track_doupdate_lines(struct track *tr, struct coord *c) +track_doupdate_lines(struct track *tr, struct coord *cc) { + int max_dist=1000; + struct map_selection *sel=route_rect(18, cc, cc, 0, max_dist); + struct mapset_handle *h; + struct map *m; + struct map_rect *mr; + struct item *item; + struct street_data *street; + struct track_line *tl; + struct coord c; + + dbg(0,"enter\n"); + h=mapset_open(tr->ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + street=street_get_data(item); + tl=g_malloc(sizeof(struct track_line)+(street->count-1)*sizeof(int)); + tl->street=street; + track_get_angles(tl); + tl->next=tr->lines; + tr->lines=tl; + } else + while (item_coord_get(item, &c, 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); + dbg(0, "exit\n"); +#if 0 struct transformation t; @@ -100,20 +138,20 @@ track_doupdate_lines(struct track *tr, struct coord *c) profile_timer(NULL); street_get_block(tr->ma,&t,tst_callback,tr); profile_timer("end"); +#endif } + static void track_free_lines(struct track *tr) { struct track_line *tl=tr->lines,*next; -#ifdef DEBUG - printf("track_free_lines(tr=%p)\n", tr); -#endif + dbg(0,"enter(tr=%p)\n", tr); + while (tl) { next=tl->next; - if (! tl->linenum) { - g_free(tl); - } + street_data_free(tl->street); + g_free(tl); tl=next; } tr->lines=NULL; @@ -156,71 +194,77 @@ track_is_connected(struct coord *c1, struct coord *c2) return 0; } -void +int track_update(struct track *tr, struct coord *c, int angle) { - struct track_line *t,*tm; + struct track_line *t; + int i,value,min=0; + struct coord lpnt; +#if 0 int min,dist; int debug=0; +#endif + dbg(1,"enter(%p,%p,%d)\n", tr, c, angle); + dbg(1,"c=0x%x,0x%x\n", c->x, c->y); if (c->x == tr->last_in.x && c->y == tr->last_in.y) { *c=tr->last_out; - return; + return 0; } - if (transform_distance_sq(&tr->last_updated, c) > 250000 || !tr->lines) { - printf("update\n"); + tr->last_in=*c; + if (!tr->lines || transform_distance_sq(&tr->last_updated, c) > 250000) { + dbg(1, "update\n"); track_free_lines(tr); track_doupdate_lines(tr, c); tr->last_updated=*c; + dbg(1,"update end\n"); } - profile_timer(NULL); t=tr->lines; - g_assert(t != NULL); - - if (debug) printf("0x%lx,0x%lx (%d deg)\n", c->x, c->y, angle); + if (! t) + return 0; + tr->curr_line=NULL; while (t) { - if (debug) printf("0x%lx 0x%lx,0x%lx - 0x%lx,0x%lx (%d deg) ", -t->segid, t->c[0].x, t->c[0].y, t->c[1].x, t->c[1].y, t->angle); - t->value=transform_distance_line_sq(&t->c[0], &t->c[1], c, &t->lpnt); - if (t->value < INT_MAX/2) - t->value += track_angle_delta(angle, t->angle, 0)*angle_factor; - if (track_is_connected(tr->curr, t->c)) - t->value += connected_pref; - if (t->lpnt.x == tr->last_out.x && t->lpnt.y == tr->last_out.y) - t->value += nostop_pref; - if (debug) printf(" %d\n", t->value); - t=t->next; - } - t=tr->lines; - tm=t; - min=t->value; - while (t) { - if (t->value < min) { - min=t->value; - tm=t; + struct street_data *sd=t->street; + for (i = 0; i < sd->count-1 ; i++) { + value=transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt); + if (value < INT_MAX/2) + value += track_angle_delta(angle, t->angle[i], 0)*angle_factor; + if (track_is_connected(tr->curr, &sd->c[i])) + value += connected_pref; + if (lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y) + value += nostop_pref; + if (! tr->curr_line || value < min) { + tr->curr_line=t; + tr->pos=i; + tr->curr[0]=sd->c[i]; + tr->curr[1]=sd->c[i+1]; + dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, + transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt), + track_angle_delta(angle, t->angle[i], 0)*angle_factor, + track_is_connected(tr->curr, &sd->c[i]) ? connected_pref : 0, + lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0, + value + ); + tr->last_out=lpnt; + min=value; + } } t=t->next; } - dist=transform_distance_sq(&tm->lpnt, c); - if (debug) printf("dist=%d id=0x%lx\n", dist, tm->segid); - *c=tm->lpnt; - tr->curr[0]=tm->c[0]; - tr->curr[1]=tm->c[1]; - tr->last_out=tm->lpnt; - - // printf("pos 0x%lx,0x%lx value %d dist %d angle %d vs %d (%d)\n", c->x, c->y, tm->value, dist, angle, tm->angle, track_angle_delta(angle, tm->angle, 0)); - g_assert(dist < 10000); -#if 0 - profile_timer("track_update end"); -#endif - + dbg(0,"tr->curr_line=%p\n", tr->curr_line); + if (!tr->curr_line) + return 0; + dbg(0,"found 0x%x,0x%x\n", tr->last_out.x, tr->last_out.y); + *c=tr->last_out; + return 1; } struct track * -track_new(struct map_data *ma) +track_new(struct mapset *ms) { struct track *this=g_new0(struct track, 1); - this->ma=ma; + this->ms=ms; return this; } diff --git a/track.h b/track.h index 2b435e0f..90073a5c 100644 --- a/track.h +++ b/track.h @@ -1,5 +1,11 @@ +/* prototypes */ +struct coord; +struct mapset; +struct street_data; struct track; - -void track_update(struct track *tr, struct coord *c, int angle); -struct track * track_new(struct map_data *ma); +struct coord *track_get_pos(struct track *tr); +int track_get_segment_pos(struct track *tr); +struct street_data *track_get_street_data(struct track *tr); +int track_update(struct track *tr, struct coord *c, int angle); +struct track *track_new(struct mapset *ms); void track_destroy(struct track *tr); diff --git a/transform.c b/transform.c index 859e0e5a..abf9c35f 100644 --- a/transform.c +++ b/transform.c @@ -3,18 +3,93 @@ #include #include #include +#include "config.h" #include "coord.h" +#include "debug.h" #include "transform.h" +#include "projection.h" +#include "point.h" + +struct transformation { + int width; /* Height of destination rectangle */ + int height; /* Width of destination rectangle */ + long scale; /* Scale factor */ + int angle; /* Rotation angle */ + double cos_val,sin_val; /* cos and sin of rotation angle */ + enum projection pro; + struct coord_rect r; /* Source rectangle */ + struct coord center; /* Center of source rectangle */ +}; + +struct transformation * +transform_new(void) +{ + struct transformation *this_; + + this_=g_new0(struct transformation, 1); + + return this_; +} + +void +transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g) +{ + double f; + + switch (pro) { + case projection_mg: + g->lng=c->x/6371000.0/M_PI*180; + g->lat=atan(exp(c->y/6371000.0))/M_PI*360-90; + break; + case projection_garmin: + f=360.0/(1<<24); + g->lng=c->x*f; + g->lat=c->y*f; + break; + default: + break; + } +} + +void +transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c) +{ + double f; + + switch (pro) { + case projection_mg: + c->x=g->lng*6371000.0*M_PI/180; + c->y=log(tan(M_PI_4+g->lat*M_PI/360))*6371000.0; + break; + case projection_garmin: + f=360.0/(1<<24); + c->x=g->lng/f; + c->y=g->lat/f; + break; + default: + break; + } +} int -transform(struct transformation *t, struct coord *c, struct point *p) +transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p) { + struct coord c1; +#ifdef AVOID_FLOAT + int xc,yc; +#else double xc,yc; - int ret=0; +#endif + int ret; + if (pro != t->pro) { + struct coord_geo g; + transform_to_geo(pro, c, &g); + transform_from_geo(t->pro, &g, &c1); + c=&c1; + } xc=c->x; yc=c->y; - if (xc >= t->rect[0].x && xc <= t->rect[1].x && yc >= t->rect[1].y && yc <= t->rect[0].y) - ret=1; + ret=coord_rect_contains(&t->r, c); xc-=t->center.x; yc-=t->center.y; yc=-yc; @@ -25,8 +100,13 @@ transform(struct transformation *t, struct coord *c, struct point *p) xc=xcn; yc=ycn; } +#ifdef AVOID_FLOAT xc=xc*16.0/(double)(t->scale); yc=yc*16.0/(double)(t->scale); +#else + xc=xc*16/t->scale; + yc=yc*16/t->scale; +#endif #if 0 { double zc=yc; @@ -77,6 +157,17 @@ transform_reverse(struct transformation *t, struct point *p, struct coord *c) c->y=t->center.y+yc; } +enum projection +transform_get_projection(struct transformation *this_) +{ + return this_->pro; +} + +void +transform_set_projection(struct transformation *this_, enum projection pro) +{ + this_->pro=pro; +} static int min4(int v1,int v2, int v3, int v4) @@ -104,6 +195,45 @@ max4(int v1,int v2, int v3, int v4) return res; } +void +transform_rect(struct transformation *this_, enum projection pro, struct coord_rect *r) +{ + struct coord_geo g; + if (0 && this_->pro == pro) { + *r=this_->r; + } else { + transform_to_geo(this_->pro, &this_->r.lu, &g); + transform_from_geo(pro, &g, &r->lu); + dbg(1,"%f,%f", g.lat, g.lng); + transform_to_geo(this_->pro, &this_->r.rl, &g); + dbg(1,": - %f,%f\n", g.lat, g.lng); + transform_from_geo(pro, &g, &r->rl); + } + dbg(1,"transform rect for %d is %d,%d - %d,%d\n", pro, r->lu.x, r->lu.y, r->rl.x, r->rl.y); +} + +struct coord * +transform_center(struct transformation *this_) +{ + return &this_->center; +} + +int +transform_contains(struct transformation *this_, enum projection pro, struct coord_rect *r) +{ + struct coord_geo g; + struct coord_rect r1; + if (this_->pro != pro) { + transform_to_geo(pro, &r->lu, &g); + transform_from_geo(this_->pro, &g, &r1.lu); + transform_to_geo(pro, &r->rl, &g); + transform_from_geo(this_->pro, &g, &r1.rl); + r=&r1; + } + return coord_rect_overlap(&this_->r, r); + +} + void transform_set_angle(struct transformation *t,int angle) { @@ -112,11 +242,30 @@ transform_set_angle(struct transformation *t,int angle) t->sin_val=sin(M_PI*t->angle/180); } +int +transform_get_angle(struct transformation *this_,int angle) +{ + return this_->angle; +} + +void +transform_set_size(struct transformation *t, int width, int height) +{ + t->width=width; + t->height=height; +} + +void +transform_get_size(struct transformation *t, int *width, int *height) +{ + *width=t->width; + *height=t->height; +} + void -transform_setup(struct transformation *t, int x, int y, int scale, int angle) +transform_setup(struct transformation *t, struct coord *c, int scale, int angle) { - t->center.x=x; - t->center.y=y; + t->center=*c; t->scale=scale; transform_set_angle(t, angle); } @@ -127,10 +276,10 @@ transform_setup_source_rect_limit(struct transformation *t, struct coord *center t->center=*center; t->scale=1; t->angle=0; - t->rect[0].x=center->x-limit; - t->rect[1].x=center->x+limit; - t->rect[1].y=center->y-limit; - t->rect[0].y=center->y+limit; + t->r.lu.x=center->x-limit; + t->r.rl.x=center->x+limit; + t->r.rl.y=center->y-limit; + t->r.lu.y=center->y+limit; } void @@ -151,28 +300,41 @@ transform_setup_source_rect(struct transformation *t) for (i = 0 ; i < 4 ; i++) { transform_reverse(t, &screen_pnt[i], &screen[i]); } - t->rect[0].x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); - t->rect[1].x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); - t->rect[1].y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); - t->rect[0].y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); + t->r.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->r.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->r.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); + t->r.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); } -int +long transform_get_scale(struct transformation *t) { - return t->scale/16; + return t->scale; } void -transform_lng_lat(struct coord *c, struct coord_geo *g) +transform_set_scale(struct transformation *t, long scale) { - g->lng=c->x/6371000.0/M_PI*180; - g->lat=atan(exp(c->y/6371000.0))/M_PI*360-90; -#if 0 - printf("y=%d vs %f\n", c->y, log(tan(M_PI_4+*lat*M_PI/360))*6371020.0); -#endif + t->scale=scale; } + +int +transform_get_order(struct transformation *t) +{ + int scale=t->scale; + int order=0; + while (scale > 1) { + order++; + scale>>=1; + } + order=18-order; + if (order < 0) + order=0; + return order; +} + + void transform_geo_text(struct coord_geo *g, char *buffer) { @@ -194,13 +356,6 @@ transform_geo_text(struct coord_geo *g, char *buffer) } -void -transform_mercator(double *lng, double *lat, struct coord *c) -{ - c->x=*lng*6371000.0*M_PI/180; - c->y=log(tan(M_PI_4+*lat*M_PI/360))*6371000.0; -} - double transform_scale(int y) { @@ -208,17 +363,52 @@ transform_scale(int y) struct coord_geo g; c.x=0; c.y=y; - transform_lng_lat(&c, &g); + transform_to_geo(projection_mg, &c, &g); return 1/cos(g.lat/180*M_PI); } +#ifdef AVOID_FLOAT +static int +tab_sqrt[]={14142,13379,12806,12364,12018,11741,11517,11333,11180,11051,10943,10850,10770,10701,10640,10587,10540,10499,10462,10429,10400,10373,10349,10327,10307,10289,10273,10257,10243,10231,10219,10208}; +#endif + double transform_distance(struct coord *c1, struct coord *c2) { +#ifndef AVOID_FLOAT double dx,dy,scale=transform_scale((c1->y+c2->y)/2); dx=c1->x-c2->x; dy=c1->y-c2->y; return sqrt(dx*dx+dy*dy)/scale; +#else + int dx,dy,f,scale=15539; + dx=c1->x-c2->x; + dy=c1->y-c2->y; + if (dx < 0) + dx=-dx; + if (dy < 0) + dy=-dy; + while (dx > 20000 || dy > 20000) { + dx/=10; + dy/=10; + scale/=10; + } + if (! dy) + return dx*10000/scale; + if (! dx) + return dy*10000/scale; + if (dx > dy) { + f=dx*8/dy-8; + if (f >= 32) + return dx*10000/scale; + return dx*tab_sqrt[f]/scale; + } else { + f=dy*8/dx-8; + if (f >= 32) + return dy*10000/scale; + return dy*tab_sqrt[f]/scale; + } +#endif } int @@ -269,6 +459,29 @@ transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref return transform_distance_sq(&l, ref); } +int +transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos) +{ + int i,dist,distn; + struct coord lp; + if (count < 2) + return 0; + if (pos) + *pos=0; + dist=transform_distance_line_sq(&c[0], &c[1], ref, lpnt); + for (i=2 ; i < count ; i++) { + distn=transform_distance_line_sq(&c[i-1], &c[i], ref, &lp); + if (distn < dist) { + dist=distn; + if (lpnt) + *lpnt=lp; + if (pos) + *pos=i-1; + } + } + return dist; +} + void transform_print_deg(double deg) @@ -279,19 +492,19 @@ transform_print_deg(double deg) int is_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; assert(c[0].x <= c[1].x); assert(c[0].y >= c[1].y); - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (c[0].x > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (c[0].x > r->rl.x) return 0; - if (c[1].x < r[0].x) + if (c[1].x < r->lu.x) return 0; - if (c[0].y < r[1].y) + if (c[0].y < r->rl.y) return 0; - if (c[1].y > r[0].y) + if (c[1].y > r->lu.y) return 0; return 1; } @@ -299,17 +512,17 @@ is_visible(struct transformation *t, struct coord *c) int is_line_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (MIN(c[0].x,c[1].x) > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (MIN(c[0].x,c[1].x) > r->rl.x) return 0; - if (MAX(c[0].x,c[1].x) < r[0].x) + if (MAX(c[0].x,c[1].x) < r->lu.x) return 0; - if (MAX(c[0].y,c[1].y) < r[1].y) + if (MAX(c[0].y,c[1].y) < r->rl.y) return 0; - if (MIN(c[0].y,c[1].y) > r[0].y) + if (MIN(c[0].y,c[1].y) > r->lu.y) return 0; return 1; } @@ -317,17 +530,17 @@ is_line_visible(struct transformation *t, struct coord *c) int is_point_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (c->x > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (c->x > r->rl.x) return 0; - if (c->x < r[0].x) + if (c->x < r->lu.x) return 0; - if (c->y < r[1].y) + if (c->y < r->rl.y) return 0; - if (c->y > r[0].y) + if (c->y > r->lu.y) return 0; return 1; } @@ -346,25 +559,72 @@ is_too_small(struct transformation *t, struct coord *c, int limit) return 0; } +#ifdef AVOID_FLOAT +static int tab_atan[]={0,262,524,787,1051,1317,1584,1853,2126,2401,2679,2962,3249,3541,3839,4142,4452,4770,5095,5430,5774,6128,6494,6873,7265,7673,8098,8541,9004,9490,10000,10538}; -void transform_limit_extend(struct coord *rect, struct coord *c) +static int +atan2_int_lookup(int val) { - if (c->x < rect[0].x) rect[0].x=c->x; - if (c->x > rect[1].x) rect[1].x=c->x; - if (c->y < rect[1].y) rect[1].y=c->y; - if (c->y > rect[0].y) rect[0].y=c->y; + int len=sizeof(tab_atan)/sizeof(int); + int i=len/2; + int p=i-1; + for (;;) { + i>>=1; + if (val < tab_atan[p]) + p-=i; + else + if (val < tab_atan[p+1]) + return p+(p>>1); + else + p+=i; + } } - +static int +atan2_int(int dx, int dy) +{ + int f,mul=1,add=0,ret; + if (! dx) { + return dy < 0 ? 180 : 0; + } + if (! dy) { + return dx < 0 ? -90 : 90; + } + if (dx < 0) { + dx=-dx; + mul=-1; + } + if (dy < 0) { + dy=-dy; + add=180*mul; + mul*=-1; + } + while (dx > 20000 || dy > 20000) { + dx/=10; + dy/=10; + } + if (dx > dy) { + ret=90-atan2_int_lookup(dy*10000/dx); + } else { + ret=atan2_int_lookup(dx*10000/dy); + } + return ret*mul+add; +} +#endif int -transform_get_angle(struct coord *c, int dir) +transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir) { + int dx=c2->x-c1->x; + int dy=c2->y-c1->y; +#ifndef AVOID_FLOAT double angle; - int dx=c[1].x-c[0].x; - int dy=c[1].y-c[0].y; angle=atan2(dx,dy); angle*=180/M_PI; +#else + int angle; + angle=atan2_int(dx,dy); +#endif if (dir == -1) angle=angle-180; if (angle < 0) @@ -372,6 +632,14 @@ transform_get_angle(struct coord *c, int dir) return angle; } +int +transform_within_border(struct transformation *this_, struct point *p, int border) +{ + if (p->x < border || p->x > this_->width-border || p->y < border || p->y > this_->height-border) + return 0; + return 1; +} + /* Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. @@ -412,4 +680,3 @@ e = the first eccentricity of the ellipsoid */ - diff --git a/transform.h b/transform.h index f2099d25..6c9059e1 100644 --- a/transform.h +++ b/transform.h @@ -1,39 +1,47 @@ -#ifndef TRANSFORM_H -#define TRANSFORM_H - -#include "point.h" - -struct transformation { - int width; /* Height of destination rectangle */ - int height; /* Width of destination rectangle */ - long scale; /* Scale factor */ - int angle; /* Rotation angle */ - double cos_val,sin_val; /* cos and sin of rotation angle */ - struct coord rect[2]; /* Source rectangle */ - struct coord center; /* Center of source rectangle */ -}; - -int transform(struct transformation *t, struct coord *c, struct point *p); -int is_visible(struct transformation *t, struct coord *c); -int is_line_visible(struct transformation *t, struct coord *c); -int is_too_small(struct transformation *t, struct coord *c, int limit); -void transform_lng_lat(struct coord *c, struct coord_geo *g); +#ifdef __cplusplus +extern "C" { +#endif +/* prototypes */ +enum projection; +struct coord; +struct coord_geo; +struct coord_rect; +struct point; +struct transformation; +struct transformation *transform_new(void); +void transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g); +void transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c); +int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p); void transform_reverse(struct transformation *t, struct point *p, struct coord *c); -void transform_print_deg(double deg); +enum projection transform_get_projection(struct transformation *this_); +void transform_set_projection(struct transformation *this_, enum projection pro); +void transform_rect(struct transformation *this_, enum projection pro, struct coord_rect *r); +struct coord *transform_center(struct transformation *this_); +int transform_contains(struct transformation *this_, enum projection pro, struct coord_rect *r); +void transform_set_angle(struct transformation *t, int angle); +int transform_get_angle(struct transformation *this_, int angle); +void transform_set_size(struct transformation *t, int width, int height); +void transform_get_size(struct transformation *t, int *width, int *height); +void transform_setup(struct transformation *t, struct coord *c, int scale, int angle); +void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); +void transform_setup_source_rect(struct transformation *t); +long transform_get_scale(struct transformation *t); +void transform_set_scale(struct transformation *t, long scale); +int transform_get_order(struct transformation *t); +void transform_geo_text(struct coord_geo *g, char *buffer); double transform_scale(int y); double transform_distance(struct coord *c1, struct coord *c2); int transform_distance_sq(struct coord *c1, struct coord *c2); int transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt); - -void transform_mercator(double *lng, double *lat, struct coord *c); +int transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos); +void transform_print_deg(double deg); +int is_visible(struct transformation *t, struct coord *c); +int is_line_visible(struct transformation *t, struct coord *c); int is_point_visible(struct transformation *t, struct coord *c); -int transform_get_scale(struct transformation *t); -void transform_setup_source_rect(struct transformation *t); -void transform_set_angle(struct transformation *t,int angle); -void transform_setup(struct transformation *t, int x, int y, int scale, int angle); -void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); -void transform_geo_text(struct coord_geo *g, char *buffer); -void transform_limit_extend(struct coord *rect, struct coord *c); -int transform_get_angle(struct coord *c, int dir); - +int is_too_small(struct transformation *t, struct coord *c, int limit); +int transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir); +int transform_within_border(struct transformation *this_, struct point *p, int border); +/* end of prototypes */ +#ifdef __cplusplus +} #endif diff --git a/tree.h b/tree.h deleted file mode 100644 index 58ff0448..00000000 --- a/tree.h +++ /dev/null @@ -1,13 +0,0 @@ -struct block_offset { - unsigned short offset; - unsigned short block; -}; - - -int tree_compare_string(unsigned char *s1, unsigned char **s2); -int tree_compare_string_partial(unsigned char *s1, unsigned char **s2); -#if 0 -int tree_search(struct file *file, unsigned char *search, int (*tree_func)(int, unsigned char *, unsigned char **, struct map_data *, void *), struct map_data *mdat, void *data2); -#endif -int tree_search_map(struct map_data *mdat, int map, char *ext, int (*tree_func)(int, int, unsigned char **, struct map_data *, void *), void *data); -int tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigned int search2, int *result, struct map_data **mdat_result); diff --git a/util.c b/util.c index 7f77ca28..44643d4f 100644 --- a/util.c +++ b/util.c @@ -1,3 +1,4 @@ +#include #include #include "util.h" @@ -17,3 +18,19 @@ strtolower(char *dest, const char *src) *dest='\0'; } + +static void +hash_callback(gpointer key, gpointer value, gpointer user_data) +{ + GList **l=user_data; + *l=g_list_prepend(*l, value); +} + +GList * +g_hash_to_list(GHashTable *h) +{ + GList *ret=NULL; + g_hash_table_foreach(h, hash_callback, &ret); + + return ret; +} diff --git a/vehicle.c b/vehicle.c index 747ffffa..c81f4d43 100644 --- a/vehicle.c +++ b/vehicle.c @@ -2,19 +2,28 @@ #include #include #include +#include #include #include #include +#include #include #ifdef HAVE_LIBGPS #include #endif +#include "debug.h" #include "coord.h" #include "transform.h" +#include "projection.h" #include "statusbar.h" #include "vehicle.h" -/* #define INTERPOLATION_TIME 50 */ +int vfd; + +static void disable_watch(struct vehicle *this); +static void enable_watch(struct vehicle *this); + + /* #define INTERPOLATION_TIME 50 */ struct callback { void (*func)(struct vehicle *, void *data); @@ -22,11 +31,15 @@ struct callback { }; struct vehicle { + char *url; GIOChannel *iochan; + guint watch; + int is_file; + int is_pipe; int timer_count; int qual; int sats; - double lat,lng; + struct coord_geo geo; double height; double dir,speed; double time; @@ -35,9 +48,14 @@ struct vehicle { struct coord_d delta; double speed_last; + int fd; + FILE *file; #ifdef HAVE_LIBGPS struct gps_data_t *gps; #endif +#define BUFFER_SIZE 256 + char buffer[BUFFER_SIZE]; + int buffer_pos; GList *callbacks; }; @@ -55,13 +73,19 @@ vehicle_timer(gpointer t) this->current_pos.x=this->curr.x; this->current_pos.y=this->curr.y; if (this->callback_func) - (*this->callback_func)(this->callback_data); + (*this->callback_func)(this, this->callback_data); } /* } */ return TRUE; } #endif +enum projection +vehicle_projection(struct vehicle *this) +{ + return projection_mg; +} + static void vehicle_call_callbacks(struct vehicle *this) { @@ -91,12 +115,6 @@ vehicle_dir_get(struct vehicle *this) return &this->dir; } -double * -vehicle_height_get(struct vehicle *this) -{ - return &this->height; -} - void vehicle_set_position(struct vehicle *this, struct coord *pos) { @@ -108,16 +126,57 @@ vehicle_set_position(struct vehicle *this, struct coord *pos) vehicle_call_callbacks(this); } +static int +enable_watch_timer(gpointer t) +{ + struct vehicle *this=t; + enable_watch(this); + + return FALSE; +} + static void vehicle_parse_gps(struct vehicle *this, char *buffer) { char *p,*item[16]; double lat,lng,scale,speed; - int i,debug=0; + int i,bcsum; + int len=strlen(buffer); + unsigned char csum=0; - if (debug) { - printf("GPS %s\n", buffer); + dbg(1, "buffer='%s' ", buffer); + write(vfd, buffer, len); + write(vfd, "\n", 1); + for (;;) { + if (len < 4) { + dbg(0, "too short\n"); + return; + } + if (buffer[len-1] == '\r' || buffer[len-1] == '\n') + buffer[--len]='\0'; + else + break; + } + if (buffer[0] != '$') { + dbg(0, "no leading $\n"); + return; } + if (buffer[len-3] != '*') { + dbg(0, "no *XX\n"); + return; + } + for (i = 1 ; i < len-3 ; i++) { + csum ^= (unsigned char)(buffer[i]); + } + if (!sscanf(buffer+len-2, "%x", &bcsum)) { + dbg(0, "no checksum\n"); + return; + } + if (bcsum != csum) { + dbg(0, "wrong checksum\n"); + return; + } + if (!strncmp(buffer,"$GPGGA",6)) { /* $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C UTC of Fix,Latitude,N/S,Longitude,E/W,Quality,Satelites,HDOP,Altitude,"M" @@ -133,25 +192,29 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) } sscanf(item[2],"%lf",&lat); - this->lat=floor(lat/100); - lat-=this->lat*100; - this->lat+=lat/60; + this->geo.lat=floor(lat/100); + lat-=this->geo.lat*100; + this->geo.lat+=lat/60; sscanf(item[4],"%lf",&lng); - this->lng=floor(lng/100); - lng-=this->lng*100; - this->lng+=lng/60; + this->geo.lng=floor(lng/100); + lng-=this->geo.lng*100; + this->geo.lng+=lng/60; sscanf(item[6],"%d",&this->qual); sscanf(item[7],"%d",&this->sats); sscanf(item[9],"%lf",&this->height); - transform_mercator(&this->lng, &this->lat, &this->current_pos); + transform_from_geo(projection_mg, &this->geo, &this->current_pos); this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; vehicle_call_callbacks(this); + if (this->is_file) { + disable_watch(this); + g_timeout_add(1000, enable_watch_timer, this); + } } if (!strncmp(buffer,"$GPVTG",6)) { /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A @@ -178,44 +241,40 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) #endif this->speed_last=this->speed; } -} - -static gboolean -vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) -{ - struct vehicle *this=t; - GError *error=NULL; - char buffer[4096]; - char *str,*tok; - gsize size; - - if (condition == G_IO_IN) { -#ifdef HAVE_LIBGPS - if (this->gps) { - vehicle_last=this; - gps_poll(this->gps); - } else { -#else - { -#endif - g_io_channel_read_chars(iochan, buffer, 4096, &size, &error); - buffer[size]='\0'; - str=buffer; - while ((tok=strtok(str, "\n"))) { - str=NULL; - vehicle_parse_gps(this, tok); - } + if (!strncmp(buffer,"$GPRMC",6)) { + /* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A */ + /* Time,Active/Void,lat,N/S,long,W/E,speed in knots,track angle,date,magnetic variation */ + i=0; + p=buffer; + while (i < 16) { + item[i++]=p; + while (*p && *p != ',') + p++; + if (! *p) break; + *p++='\0'; } - - return TRUE; - } - return FALSE; + sscanf(item[8],"%lf",&this->dir); + sscanf(item[7],"%lf",&this->speed); + this->speed *= 1.852; + scale=transform_scale(this->current_pos.y); + speed=this->speed+(this->speed-this->speed_last)/2; +#ifdef INTERPOLATION_TIME + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; +#endif + this->speed_last=this->speed; + } } #ifdef HAVE_LIBGPS static void vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) { + // If data->fix.speed is NAN, then the drawing gets jumpy. + if(isnan(data->fix.speed)){ + return 0; + } + struct vehicle *this=vehicle_last; double scale,speed; #if INTERPOLATION_TIME @@ -243,9 +302,9 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) data->set &= ~TRACK_SET; } if (data->set & LATLON_SET) { - this->lat=data->fix.latitude; - this->lng=data->fix.longitude; - transform_mercator(&this->lng, &this->lat, &this->current_pos); + this->geo.lat=data->fix.latitude; + this->geo.lng=data->fix.longitude; + transform_from_geo(projection_mg, &this->geo, &this->current_pos); this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; @@ -267,53 +326,166 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) } #endif -struct vehicle * -vehicle_new(const char *url) + +static void +vehicle_close(struct vehicle *this) { - struct vehicle *this; GError *error=NULL; - int fd=-1; - char *url_,*colon; + + + g_io_channel_shutdown(this->iochan,0,&error); #ifdef HAVE_LIBGPS - struct gps_data_t *gps=NULL; + if (this->gps) + gps_close(this->gps); #endif + if (this->file) + pclose(this->file); + if (this->fd != -1) + close(this->fd); +} - if (! strncmp(url,"file:",5)) { - fd=open(url+5,O_RDONLY|O_NDELAY); +static int +vehicle_open(struct vehicle *this) +{ + struct termios tio; + struct stat st; + int fd; + +#ifdef HAVE_LIBGPS + struct gps_data_t *gps=NULL; + char *url_,*colon; +#endif + if (! strncmp(this->url,"file:",5)) { + fd=open(this->url+5,O_RDONLY|O_NDELAY); if (fd < 0) { - g_warning("Failed to open %s", url); + g_warning("Failed to open %s", this->url); + return 0; } - } else if (! strncmp(url,"gpsd://",7)) { + stat(this->url+5, &st); + if (S_ISREG (st.st_mode)) { + this->is_file=1; + } else { + tcgetattr(fd, &tio); + cfmakeraw(&tio); + cfsetispeed(&tio, B4800); + cfsetospeed(&tio, B4800); + tio.c_cc[VMIN]=16; + tio.c_cc[VTIME]=1; + tcsetattr(fd, TCSANOW, &tio); + } + this->fd=fd; + } else if (! strncmp(this->url,"pipe:",5)) { + this->file=popen(this->url+5, "r"); + this->is_pipe=1; + if (! this->file) { + g_warning("Failed to open %s", this->url); + return 0; + } + fd=fileno(this->file); + } else if (! strncmp(this->url,"gpsd://",7)) { #ifdef HAVE_LIBGPS - url_=g_strdup(url); + url_=g_strdup(this->url); colon=index(url_+7,':'); if (colon) { *colon=0; gps=gps_open(url_+7,colon+1); } else - gps=gps_open(url+7,NULL); + gps=gps_open(this->url+7,NULL); g_free(url_); if (! gps) { - g_warning("Failed to connect to %s", url); - } else { - gps_query(gps, "w+x\n"); - gps_set_raw_hook(gps, vehicle_gps_callback); - fd=gps->gps_fd; + g_warning("Failed to connect to %s", this->url); + return 0; } + gps_query(gps, "w+x\n"); + gps_set_raw_hook(gps, vehicle_gps_callback); + fd=gps->gps_fd; + this->gps=gps; #else g_warning("No support for gpsd compiled in\n"); + return 0; #endif } - this=g_new0(struct vehicle,1); + this->iochan=g_io_channel_unix_new(fd); + enable_watch(this); + return 1; +} + + +static gboolean +vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) +{ + struct vehicle *this=t; + GError *error=NULL; + char *str,*tok; + gsize size; + + dbg(1,"enter condition=%d\n", condition); + if (condition == G_IO_IN) { #ifdef HAVE_LIBGPS - if(gps) - this->gps=gps; + if (this->gps) { + vehicle_last=this; + gps_poll(this->gps); + } else { +#else + { #endif - if(fd !=-1) { - this->iochan=g_io_channel_unix_new(fd); - g_io_channel_set_encoding(this->iochan, NULL, &error); - g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); + size=read(g_io_channel_unix_get_fd(iochan), this->buffer+this->buffer_pos, BUFFER_SIZE-this->buffer_pos-1); + if (size <= 0) { + vehicle_close(this); + vehicle_open(this); + return TRUE; + } + this->buffer_pos+=size; + this->buffer[this->buffer_pos]='\0'; + dbg(1,"size=%d pos=%d buffer='%s'\n", size, this->buffer_pos, this->buffer); + str=this->buffer; + while ((tok=index(str, '\n'))) { + *tok++='\0'; + dbg(1,"line='%s'\n", str); + vehicle_parse_gps(this, str); + str=tok; + } + if (str != this->buffer) { + size=this->buffer+this->buffer_pos-str; + memmove(this->buffer, str, size+1); + this->buffer_pos=size; + dbg(1,"now pos=%d buffer='%s'\n", this->buffer_pos, this->buffer); + } else if (this->buffer_pos == BUFFER_SIZE-1) { + dbg(0,"overflow\n"); + this->buffer_pos=0; + } + + } + + return TRUE; + } + return FALSE; +} + +static void +enable_watch(struct vehicle *this) +{ + this->watch=g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); +} + +static void +disable_watch(struct vehicle *this) +{ + g_source_remove(this->watch); +} + +struct vehicle * +vehicle_new(const char *url) +{ + struct vehicle *this; + this=g_new0(struct vehicle,1); + this->url=g_strdup(url); + this->fd=-1; + + if (! vfd) { + vfd=open("vlog.txt", O_RDWR|O_APPEND|O_CREAT, 0644); } + vehicle_open(this); this->current_pos.x=0x130000; this->current_pos.y=0x600000; this->curr.x=this->current_pos.x; @@ -321,7 +493,7 @@ vehicle_new(const char *url) this->delta.x=0; this->delta.y=0; #if INTERPOLATION_TIME - g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this); + g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this); #endif return this; @@ -344,23 +516,11 @@ vehicle_callback_unregister(struct vehicle *this, void *handle) g_list_remove(this->callbacks, handle); } + void vehicle_destroy(struct vehicle *this) { - GError *error=NULL; - GList *item=g_list_first(this->callbacks),*next; - - - g_io_channel_shutdown(this->iochan,0,&error); -#ifdef HAVE_LIBGPS - if (this->gps) - gps_close(this->gps); -#endif - while (item) { - next=g_list_next(item); - vehicle_callback_unregister(this, item->data); - item=next; - } - g_list_free(this->callbacks); + vehicle_close(this); + g_free(this->url); g_free(this); } diff --git a/vehicle.h b/vehicle.h index aa028c49..46cf4304 100644 --- a/vehicle.h +++ b/vehicle.h @@ -1,11 +1,12 @@ +/* prototypes */ +struct coord; struct vehicle; - -struct coord *vehicle_pos_get(struct vehicle *); -double *vehicle_dir_get(struct vehicle *); -double *vehicle_speed_get(struct vehicle *); -double *vehicle_height_get(struct vehicle *this); -void * vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); -void vehicle_callback_unregister(struct vehicle *this, void *handle); -void vehicle_set_position(struct vehicle *, struct coord *); +enum projection vehicle_projection(struct vehicle *this); +struct coord *vehicle_pos_get(struct vehicle *this); +double *vehicle_speed_get(struct vehicle *this); +double *vehicle_dir_get(struct vehicle *this); +void vehicle_set_position(struct vehicle *this, struct coord *pos); struct vehicle *vehicle_new(const char *url); -void vehicle_destroy(struct vehicle *); +void *vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); +void vehicle_callback_unregister(struct vehicle *this, void *handle); +void vehicle_destroy(struct vehicle *this); diff --git a/xmlconfig.c b/xmlconfig.c new file mode 100644 index 00000000..dadbb4d0 --- /dev/null +++ b/xmlconfig.c @@ -0,0 +1,534 @@ +#include +#include +#include +#include "xmlconfig.h" +#include "navit.h" +#include "vehicle.h" +#include "mapset.h" +#include "map.h" +#include "layout.h" +#include "projection.h" +#include "coord.h" +#include "plugin.h" + + +struct xmlstate { + const gchar **attribute_names; + const gchar **attribute_values; + struct xmlstate *parent; + void *element_object; + const gchar *element; + GError **error; + struct element_func *func; +} *xmlstate_root; + + +static const char * find_attribute(struct xmlstate *state, const char *attribute, int required) +{ + const gchar **attribute_name=state->attribute_names; + const gchar **attribute_value=state->attribute_values; + while(*attribute_name) { + if(! g_ascii_strcasecmp(attribute,*attribute_name)) + return *attribute_value; + attribute_name++; + attribute_value++; + } + if (required) + g_set_error(state->error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, "element '%s' is missing attribute '%s'", state->element, attribute); + return NULL; +} + +static int +find_color(struct xmlstate *state, int required, struct color *color) +{ + const char *value; + int r,g,b; + + value=find_attribute(state, "color", required); + if (! value) + return 0; + + sscanf(value,"#%02x%02x%02x", &r, &g, &b); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + return 1; +} + +static int +find_zoom(struct xmlstate *state, int required, int *min, int *max) +{ + const char *value, *pos; + int ret; + + *min=0; + *max=18; + value=find_attribute(state, "zoom", required); + if (! value) + return 0; + pos=index(value, '-'); + if (! pos) { + ret=sscanf(value,"%d",min); + *max=*min; + } else if (pos == value) + ret=sscanf(value,"-%d",max); + else + ret=sscanf(value,"%d-%d", min, max); + return ret; +} + +static int +find_boolean(struct xmlstate *state, const char *attribute, int deflt, int required) +{ + const char *value; + + value=find_attribute(state, attribute, required); + if (! value) + return deflt; + if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false")) + return 1; + return 0; +} + +static int +convert_number(const char *val) +{ + return g_ascii_strtoull(val,NULL,0); +} + +static int +xmlconfig_plugins(struct xmlstate *state) +{ + state->element_object = plugins_new(); + if (! state->element_object) + return 0; + return 1; +} + +static int +xmlconfig_plugin(struct xmlstate *state) +{ + const char *path; + int active,lazy; + + state->element_object=state->parent->element_object; + path=find_attribute(state, "path", 1); + if (! path) + return 0; + active=find_boolean(state, "active", 1, 0); + lazy=find_boolean(state, "lazy", 1, 0); + plugins_add_path(state->parent->element_object, path, active, lazy); + return 1; +} + +static int +xmlconfig_navit(struct xmlstate *state) +{ + const char *value,*gui,*graphics; + int zoom=0; + struct coord c; + enum projection pro=projection_mg; + + value=find_attribute(state, "zoom", 0); + if (value) + zoom=convert_number(value); + if (! zoom) + zoom=256; + value=find_attribute(state, "center", 0); + if (! value || ! coord_parse(value, pro, &c)) { + c.x=1300000; + c.y=7000000; + } + gui=find_attribute(state, "gui", 0); + if (! gui) + gui="gtk"; + graphics=find_attribute(state, "graphics", 0); + if (! graphics) + graphics="gtk_drawing_area"; + state->element_object = navit_new(gui, graphics, &c, pro, zoom); + if (! state->element_object) + return 0; + return 1; +} + +static int +xmlconfig_vehicle(struct xmlstate *state) +{ + const char *s=find_attribute(state, "source", 1); + const char *value; + struct color color; + int update=1, follow=0; + + if (! s) + return 0; + if (! find_color(state, 1, &color)) + return 0; + state->element_object = vehicle_new(s); + if (! state->element_object) + return 0; + if ((value=find_attribute(state, "update", 0))) + update=convert_number(value); + if ((value=find_attribute(state, "follow", 0))) + follow=convert_number(value); + + navit_vehicle_add(state->parent->element_object, state->element_object, &color, update, follow); + return 1; +} + +static int +xmlconfig_mapset(struct xmlstate *state) +{ + state->element_object = mapset_new(); + if (! state->element_object) + return 0; + navit_add_mapset(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_map(struct xmlstate *state) +{ + const char *type=find_attribute(state, "type", 1); + const char *data=find_attribute(state, "data", 1); + if (! type || ! data) + return 0; + state->element_object = map_new(type, data); + if (! state->element_object) + return 0; + if (!find_boolean(state, "active", 1, 0)) + map_set_active(state->element_object, 0); + mapset_add(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_layout(struct xmlstate *state) +{ + const char *name=find_attribute(state, "name", 1); + + if (! name) + return 0; + state->element_object = layout_new(name); + if (! state->element_object) + return 0; + navit_add_layout(state->parent->element_object, state->element_object); + return 1; +} + +static int +xmlconfig_layer(struct xmlstate *state) +{ + const char *name=find_attribute(state, "name", 1); + if (! name) + return 0; + state->element_object = layer_new(name, convert_number(find_attribute(state, "details", 0))); + if (! state->element_object) + return 0; + layout_add_layer(state->parent->element_object, state->element_object); + return 1; +} + +static int +xmlconfig_item(struct xmlstate *state) +{ + const char *type=find_attribute(state, "type", 1); + int min, max; + enum item_type itype; + char *saveptr, *tok, *type_str, *str; + + if (! type) + return 0; + if (! find_zoom(state, 1, &min, &max)) + return 0; + state->element_object=itemtype_new(min, max); + if (! state->element_object) + return 0; + type_str=g_strdup(type); + str=type_str; + layer_add_itemtype(state->parent->element_object, state->element_object); + while ((tok=strtok_r(str, ",", &saveptr))) { + itype=item_from_name(tok); + itemtype_add_type(state->element_object, itype); + str=NULL; + } + g_free(type_str); + + return 1; +} + +static int +xmlconfig_polygon(struct xmlstate *state) +{ + struct color color; + + if (! find_color(state, 1, &color)) + return 0; + state->element_object=polygon_new(&color); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_polyline(struct xmlstate *state) +{ + struct color color; + const char *width; + int w=0; + + if (! find_color(state, 1, &color)) + return 0; + width=find_attribute(state, "width", 0); + if (width) + w=convert_number(width); + state->element_object=polyline_new(&color, w); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_circle(struct xmlstate *state) +{ + struct color color; + const char *width, *radius, *label_size; + int w=0,r=0,ls=0; + + if (! find_color(state, 1, &color)) + return 0; + width=find_attribute(state, "width", 0); + if (width) + w=convert_number(width); + radius=find_attribute(state, "radius", 0); + if (radius) + r=convert_number(radius); + label_size=find_attribute(state, "label_size", 0); + if (label_size) + ls=convert_number(label_size); + state->element_object=circle_new(&color, r, w, ls); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_label(struct xmlstate *state) +{ + const char *label_size; + int ls=0; + + label_size=find_attribute(state, "label_size", 0); + if (label_size) + ls=convert_number(label_size); + state->element_object=label_new(ls); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_icon(struct xmlstate *state) +{ + const char *src=find_attribute(state, "src", 1); + + if (! src) + return 0; + state->element_object=icon_new(src); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_image(struct xmlstate *state) +{ + state->element_object=image_new(); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +struct element_func { + char *name; + char *parent; + int (*func)(struct xmlstate *state); +} elements[] = { + { "plugins", NULL, xmlconfig_plugins}, + { "plugin", "plugins", xmlconfig_plugin}, + { "navit", NULL, xmlconfig_navit}, + { "vehicle", "navit", xmlconfig_vehicle}, + { "mapset", "navit", xmlconfig_mapset}, + { "map", "mapset", xmlconfig_map}, + { "layout", "navit", xmlconfig_layout}, + { "layer", "layout", xmlconfig_layer}, + { "item", "layer", xmlconfig_item}, + { "polygon", "item", xmlconfig_polygon}, + { "polyline", "item", xmlconfig_polyline}, + { "circle", "item", xmlconfig_circle}, + { "label", "item", xmlconfig_label}, + { "icon", "item", xmlconfig_icon}, + { "image", "item", xmlconfig_image}, + {}, +}; + +static void +start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + struct xmlstate *new=NULL, **parent = user_data; + struct element_func *e=elements,*func=NULL; + const char *parent_name=NULL; + while (e->name) { + if (!g_ascii_strcasecmp(element_name, e->name)) { + func=e; + } + e++; + } + if (! func) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element '%s'", element_name); + return; + } + if (*parent) + parent_name=(*parent)->element; + if ((parent_name && func->parent && g_ascii_strcasecmp(parent_name, func->parent)) || + (!parent_name && func->parent) || (parent_name && !func->parent)) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, + "Element '%s' within unexpected context '%s'. Expected '%s'", + element_name, parent_name, func->parent); + return; + } + + new=g_new(struct xmlstate, 1); + new->attribute_names=attribute_names; + new->attribute_values=attribute_values; + new->parent=*parent; + new->element_object=NULL; + new->element=element_name; + new->error=error; + new->func=func; + *parent=new; + if (!find_boolean(new, "enabled", 1, 0)) + return; + if (new->parent && !new->parent->element_object) + return; + if (!func->func(new)) { + return; + } + return; +#if 0 + struct elem_data *data = user_data; + void *elem=NULL; + void *parent_object; + char *parent_token; + parent_object=data->elem_stack ? data->elem_stack->data : NULL; + parent_token=data->token_stack ? data->token_stack->data : NULL; + + /* g_printf("start_element: %s AN: %s AV: %s\n",element_name,*attribute_names,*attribute_values); */ + + + printf("Unknown element '%s'\n", element_name); +#if 0 + data->elem_stack = g_list_prepend(data->elem_stack, elem); + data->token_stack = g_list_prepend(data->token_stack, (gpointer)element_name); +#endif +#endif +} + + +/* Called for close tags */ +static void +end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + struct xmlstate *curr, **state = user_data; + + curr=*state; + if(!g_ascii_strcasecmp("plugins", element_name) && curr->element_object) + plugins_init(curr->element_object); + if(!g_ascii_strcasecmp("navit", element_name) && curr->element_object) + navit_init(curr->element_object); + *state=curr->parent; + g_free(curr); +} + + +/* Called for character data */ +/* text is not nul-terminated */ +static void +text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + struct xmlstate **state = user_data; + + (void) state; +} + + + +static const GMarkupParser parser = { + start_element, + end_element, + text, + NULL, + NULL +}; + + +gboolean config_load(char *filename, GError **error) +{ + GMarkupParseContext *context; + char *contents; + gsize len; + gboolean result; + gint line; + gint chr; + gchar *message; + + struct xmlstate *curr=NULL; + + context = g_markup_parse_context_new (&parser, 0, &curr, NULL); + + if (!g_file_get_contents (filename, &contents, &len, error)) + return FALSE; + + result = g_markup_parse_context_parse (context, contents, len, error); + if (result && curr) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_PARSE, "element '%s' not closed", curr->element); + result=FALSE; + } + if (!result && error && *error) { + g_markup_parse_context_get_position(context, &line, &chr); + message=g_strdup_printf("%s at line %d, char %d\n", (*error)->message, line, chr); + g_free((*error)->message); + (*error)->message=message; + } + g_markup_parse_context_free (context); + g_free (contents); + + return result; +} + diff --git a/xmlconfig.h b/xmlconfig.h new file mode 100644 index 00000000..036eab52 --- /dev/null +++ b/xmlconfig.h @@ -0,0 +1,3 @@ + +struct container; +gboolean config_load(char *filename,GError **error); diff --git a/xpm/Makefile.am b/xpm/Makefile.am new file mode 100644 index 00000000..786803d2 --- /dev/null +++ b/xpm/Makefile.am @@ -0,0 +1,3 @@ +include $(top_srcdir)/Makefile.inc +xpm_DATA = *.xpm +EXTRA_DIST = *.xpm diff --git a/xpm/camping.xpm b/xpm/camping.xpm new file mode 100644 index 00000000..86ff7d46 --- /dev/null +++ b/xpm/camping.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *camping[]={ +"16 16 5 1", +". c None", +"b c #000000", +"a c #0000ff", +"c c #c6c6c6", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aa####bb####aa#", +"#aa###cbbc###aa#", +"#aa###b##b###aa#", +"#aa##cb##bc##aa#", +"#aa##bc##cb##aa#", +"#aa#cb#bb#bc#aa#", +"#aa#bccbbccb#aa#", +"#aacb#bbbb#bcaa#", +"#aabbbbbbbbbbaa#", +"#aa##########aa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/car_dealer.xpm b/xpm/car_dealer.xpm new file mode 100644 index 00000000..892f10b2 --- /dev/null +++ b/xpm/car_dealer.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *car_dealer[]={ +"16 16 7 1", +". c None", +"c c #000000", +"a c #0000ff", +"b c #7f7f7f", +"d c #bfbfbf", +"e c #f6f6fa", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#a############a#", +"#a####bccb####a#", +"#a##dccccccd##a#", +"#a#####cc#####a#", +"#a##dccccccd##a#", +"#a####bccbe###a#", +"#a#####cc#####a#", +"#a####dccd####a#", +"#a####dccd####a#", +"#a####bccb####a#", +"#a####bccb####a#", +"#a############a#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/fuel.xpm b/xpm/fuel.xpm new file mode 100644 index 00000000..7b9f5f84 --- /dev/null +++ b/xpm/fuel.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *fuel[]={ +"16 16 7 1", +". c None", +"d c #000000", +"a c #0000ff", +"c c #7f7f7f", +"e c #d1d2d3", +"b c #fefefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aabbbbbbbbbbaa#", +"#aabbbcdddcbbaa#", +"#aabbed#bbdbbaa#", +"#aabbed#bbdbbaa#", +"#aabbccddddbbaa#", +"#aabbccddddbbaa#", +"#aabeecddddbbaa#", +"#aabcecddddbbaa#", +"#aabccedddcbbaa#", +"#aabbbbbbbbbbaa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/hospital.xpm b/xpm/hospital.xpm new file mode 100644 index 00000000..44ac2740 --- /dev/null +++ b/xpm/hospital.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *hospital[]={ +"16 16 5 1", +". c None", +"a c #0000ff", +"c c #e32b2b", +"b c #fdfefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aabbbb###bbbaa#", +"#aabbb#cc#bbbaa#", +"#aabbb#cc##bbaa#", +"#aa####cc####aa#", +"#aa#cccccccc#aa#", +"#aa#cccccccc#aa#", +"#aa####cc####aa#", +"#aabbb#cc#bbbaa#", +"#aabbb#cc#bbbaa#", +"#aabbb###bbbbaa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/hotel.xpm b/xpm/hotel.xpm new file mode 100644 index 00000000..c371b95a --- /dev/null +++ b/xpm/hotel.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *hotel[]={ +"16 16 7 1", +". c None", +"b c #000000", +"a c #0000ff", +"d c #555566", +"c c #727283", +"e c #ededef", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aa##########aa#", +"#aa#b########aa#", +"#aa#bc#######aa#", +"#aa#bdc####b#aa#", +"#aa#bcdccccb#aa#", +"#aa#bbbbbbbb#aa#", +"#aa#b######b#aa#", +"#aa#e########aa#", +"#aa##########aa#", +"#aa##########aa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/parking.xpm b/xpm/parking.xpm new file mode 100644 index 00000000..505ac681 --- /dev/null +++ b/xpm/parking.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *parking[]={ +"16 16 5 1", +". c None", +"a c #0000ff", +"b c #8080ff", +"c c #f6f6fa", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaa######baaaa#", +"#aaa##cccc#baaa#", +"#aaa##aaaab#baa#", +"#aaa##aaaab#baa#", +"#aaa##aaaab#baa#", +"#aaa######cbaaa#", +"#aaa##cc##baaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/restaurant.xpm b/xpm/restaurant.xpm new file mode 100644 index 00000000..730fcc94 --- /dev/null +++ b/xpm/restaurant.xpm @@ -0,0 +1,73 @@ +/* XPM */ +static char *tst[]={ +"16 16 54 1", +". c None", +"o c #000000", +"a c #0000ff", +"v c #161717", +"X c #181919", +"V c #191a1a", +"S c #1a1b1b", +"M c #1b1c1c", +"T c #1c1d1d", +"F c #1e1f1f", +"Q c #1f2020", +"L c #212222", +"y c #292a2a", +"G c #2b2c2c", +"Z c #3f3f3f", +"g c #3f4040", +"z c #4d4e4e", +"D c #4e4f4f", +"s c #505050", +"n c #606161", +"A c #6b6c6c", +"E c #6d6d6d", +"r c #6f6f6f", +"t c #6f7070", +"l c #737373", +"w c #7b7b7b", +"h c #7e7e7e", +"P c #7f7f7f", +"W c #818181", +"B c #858686", +"k c #888888", +"K c #8f9090", +"H c #909090", +"q c #919292", +"Y c #929393", +"J c #9a9b9b", +"f c #9c9c9c", +"u c #a8a8a8", +"N c #b1b2b2", +"m c #bfbfbf", +"p c #dedede", +"i c #e8e8e8", +"I c #f3f3f3", +"x c #f8f8f8", +"O c #f9f9f9", +"C c #fafafa", +"U c #fcfcfc", +"e c #fcfcfe", +"c c #fcfdfe", +"b c #fcfdff", +"R c #fdfdfd", +"d c #fdfdff", +"j c #fefefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#a#bcddddde#d#a#", +"#a#fghi##jklm#a#", +"#a#nooop#qrst#a#", +"#a#uoovwxyzAB#a#", +"#a#CDovEmFGHj#a#", +"#a##IJKLMNO###a#", +"#a####PQFPR###a#", +"#a##jPSmmTPU##a#", +"#a#RPVP##PMPC#a#", +"#a#WXY####uVP#a#", +"#a#oPj#####Po#a#", +"#a############a#", +"#PZmaaaaaaaaaaa#", +".##############."}; diff --git a/xpm/unknown.xpm b/xpm/unknown.xpm new file mode 100644 index 00000000..8f6835f2 --- /dev/null +++ b/xpm/unknown.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"13 14 3 1", +/* colors */ +" c yellow", +". c blue", +"X c None", +/* pixels */ +" ", +" ........... ", +" ... ... ", +" .. ..... .. ", +" ........ .. ", +" ........ .. ", +" ...... ... ", +" ..... ..... ", +" ..... ..... ", +" ........... ", +" ..... ..... ", +" ........... ", +" ........... ", +" " +}; -- cgit v1.2.1 From c097d6da94cadc4eb204caef89fe1abc5b060f1b Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jul 2007 08:50:07 +0000 Subject: Improved build system git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@256 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 12 ++++++------ data/garmin_img/Makefile.am | 2 +- data/mg/Makefile.am | 2 +- data/textfile/Makefile.am | 2 +- data_window.c | 13 +++++++++++++ graphics/gtk_drawing_area/Makefile.am | 2 +- graphics/null/Makefile.am | 2 +- graphics/opengl/Makefile.am | 2 +- gui/gtk/Makefile.am | 3 ++- gui/gtk/gui_gtk_window.c | 8 ++++++++ gui/sdl/Makefile.am | 4 ++-- main.c | 11 ++++++++--- plugins/poi_geodownload/Makefile.am | 2 +- xpm/Makefile.am | 4 ++-- 14 files changed, 48 insertions(+), 21 deletions(-) diff --git a/Makefile.am b/Makefile.am index f198c092..f5098c9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,13 +4,13 @@ fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am cd fib-1.0 ./configure -AM_CPPFLAGS = @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ @GTK2_CFLAGS@ -DMODULE=\"navit\" +AM_CPPFLAGS = @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ -DMODULE=\"navit\" bin_PROGRAMS = navit -#pkglib_DATA = navit.xml -#EXTRA_DIST = navit.xml +pkglib_DATA = navit.xml +EXTRA_DIST = navit.xml navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_window.c debug.c \ file.c graphics.c gui.c item.c layout.c log.c main.c map.c \ @@ -18,10 +18,10 @@ navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_wind profile.c python.c route.c search.c speech.c transform.c track.c \ util.c vehicle.c xmlconfig.c attr.h attr_def.h callback.h color.h compass.h coord.h country.h \ cursor.h data.h data_window.h data_window_int.h debug.h destination.h draw_info.h \ - file.h graphics.h gtkext.h gui.h item.h item_def.h log.h layout.h main.h map-share.h map.h\ + file.h graphics.h gtkext.h gui.h item.h item_def.h log.h layer.h layout.h main.h map-share.h map.h\ map_data.h mapset.h maptype.h menu.h navigation.h navit.h \ - param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h search.h speech.h statusbar.h \ + param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h profile.h search.h speech.h statusbar.h \ toolbar.h transform.h track.h util.h vehicle.h xmlconfig.h -navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ @GTK2_LIBS@ -Lfib-1.0 -lfib +navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ -Lfib-1.0 -lfib diff --git a/data/garmin_img/Makefile.am b/data/garmin_img/Makefile.am index 7fb84323..dccc1bd2 100644 --- a/data/garmin_img/Makefile.am +++ b/data/garmin_img/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libdata_garmin_img.la libdata_garmin_img_la_SOURCES = garmin_img.c diff --git a/data/mg/Makefile.am b/data/mg/Makefile.am index 65f0157e..ba356607 100644 --- a/data/mg/Makefile.am +++ b/data/mg/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. -DMODULE=\"data_mg\" +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"data_mg\" plugin_LTLIBRARIES = libdata_mg.la libdata_mg_la_SOURCES = map.c block.c town.c tree.c poly.c street.c mg.h diff --git a/data/textfile/Makefile.am b/data/textfile/Makefile.am index 92850723..d32dea60 100644 --- a/data/textfile/Makefile.am +++ b/data/textfile/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libdata_textfile.la libdata_textfile_la_SOURCES = textfile.c textfile.h diff --git a/data_window.c b/data_window.c index 99889488..0002e44e 100644 --- a/data_window.c +++ b/data_window.c @@ -1,14 +1,19 @@ #include #include #include +#if 0 #include +#endif #include "param.h" #include "data_window.h" +#if 0 #include "data_window_int.h" +#endif struct data_window * data_window(char *name, struct window *parent, void(*callback)(struct data_window *, char **cols)) { +#if 0 struct data_window *win; win=malloc(sizeof(*win)); @@ -27,16 +32,21 @@ data_window(char *name, struct window *parent, void(*callback)(struct data_windo gtk_window_set_transient_for(GTK_WINDOW((GtkWidget *)(win->window)), GTK_WINDOW(parent)); gtk_widget_show_all(win->window); return win; +#endif + return NULL; } void data_window_begin(struct data_window *win) { +#if 0 if (win && win->treeview) { gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL); } +#endif } +#if 0 static void click_column(GtkCList *clist, int column) { @@ -76,10 +86,12 @@ select_row(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, stru win->callback(win, cols); } } +#endif void data_window_add(struct data_window *win, struct param_list *param, int count) { +#if 0 int i; GtkCellRenderer *cell; GtkTreeIter iter; @@ -120,6 +132,7 @@ data_window_add(struct data_window *win, struct param_list *param, int count) utf8=g_locale_to_utf8(param[i].value,-1,NULL,NULL,NULL); gtk_list_store_set(liststore,&iter,i,utf8,-1); } +#endif } diff --git a/graphics/gtk_drawing_area/Makefile.am b/graphics/gtk_drawing_area/Makefile.am index 5b8b9448..1a0a210a 100644 --- a/graphics/gtk_drawing_area/Makefile.am +++ b/graphics/gtk_drawing_area/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @GTK2_CFLAGS@ -I../.. +AM_CPPFLAGS = @GTK2_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libgraphics_gtk_drawing_area.la libgraphics_gtk_drawing_area_la_SOURCES = graphics_gtk_drawing_area.c diff --git a/graphics/null/Makefile.am b/graphics/null/Makefile.am index 8b22bdbc..ffb869f0 100644 --- a/graphics/null/Makefile.am +++ b/graphics/null/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libgraphics_null.la libgraphics_null_la_SOURCES = graphics_null.c diff --git a/graphics/opengl/Makefile.am b/graphics/opengl/Makefile.am index 99023e34..50080a5d 100644 --- a/graphics/opengl/Makefile.am +++ b/graphics/opengl/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ @OPENGL_CFLAGS@ -I../.. +AM_CPPFLAGS = @NAVIT_CFLAGS@ @OPENGL_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libgraphics_opengl.la libgraphics_opengl_la_SOURCES = graphics_opengl.c diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am index 9b8d907f..2cb3c284 100644 --- a/gui/gtk/Makefile.am +++ b/gui/gtk/Makefile.am @@ -1,4 +1,5 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ @GTK2_CFLAGS@ -I../.. -DMODULE=\"gui_gtk\" +AM_CPPFLAGS = @NAVIT_CFLAGS@ @GTK2_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"gui_gtk\" plugin_LTLIBRARIES = libgui_gtk.la libgui_gtk_la_SOURCES = destination.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c gui_gtk.h +libgui_gtk_la_LIBADD = @GTK2_LIBS@ diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index 663cbcca..34f2a98e 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -112,8 +112,16 @@ gui_gtk_new(struct navit *nav, struct gui_methods *meth, int w, int h) return this; } +static int gtk_argc; +static char *gtk_argv[]={NULL}; + void plugin_init(void) { + gtk_init(>k_argc, >k_argv); + gdk_rgb_init(); + gtk_set_locale(); + + plugin_register_gui_type("gtk", gui_gtk_new); } diff --git a/gui/sdl/Makefile.am b/gui/sdl/Makefile.am index d8be2a30..030721ed 100644 --- a/gui/sdl/Makefile.am +++ b/gui/sdl/Makefile.am @@ -1,5 +1,5 @@ include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ @CEGUI_CFLAGS@ -I../.. +AM_CPPFLAGS = @NAVIT_CFLAGS@ @CEGUI_CFLAGS@ -I$(top_srcdir)/src plugin_LTLIBRARIES = libgui_sdl.la -libgui_sdl_la_SOURCES = gui_sdl_window.cpp sdl_events.cpp +libgui_sdl_la_SOURCES = gui_sdl_window.cpp sdl_events.cpp gui_sdl.h sdl_events.h libgui_sdl_la_LIBADD = @SDL_LIBS@ @CEGUI_LIBS@ @OPENGL_LIBS@ diff --git a/main.c b/main.c index db91ef88..b0cadcea 100644 --- a/main.c +++ b/main.c @@ -3,7 +3,9 @@ #include #include #include +#ifdef USE_GTK_MAIN_LOOP #include +#endif #include "file.h" #include "debug.h" #include "navit.h" @@ -49,7 +51,7 @@ int main(int argc, char **argv) { GError *error = NULL; char *config_file = NULL; -#if 0 +#ifndef USE_GTK_MAIN_LOOP GMainLoop *loop; #endif @@ -58,11 +60,14 @@ int main(int argc, char **argv) setenv("LC_NUMERIC","C",1); setlocale(LC_ALL,""); setlocale(LC_NUMERIC,"C"); - gtk_set_locale(); setlocale(LC_NUMERIC,"C"); debug_init(); +#if 0 + /* handled in gui/gtk */ + gtk_set_locale(); gtk_init(&argc, &argv); gdk_rgb_init(); +#endif #ifdef HAVE_PYTHON python_init(); @@ -86,7 +91,7 @@ int main(int argc, char **argv) if (main_loop_gui) { gui_run_main_loop(main_loop_gui); } else { -#if 1 +#ifdef USE_GTK_MAIN_LOOP gtk_main(); #else loop = g_main_loop_new (NULL, TRUE); diff --git a/plugins/poi_geodownload/Makefile.am b/plugins/poi_geodownload/Makefile.am index 0f4d0bc4..ee3cc415 100644 --- a/plugins/poi_geodownload/Makefile.am +++ b/plugins/poi_geodownload/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS=libmdb AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. -Ilibmdb/include -shared +AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I$(top_srcdir)/src -Ilibmdb/include -shared objdir=$(prefix) obj_PROGRAMS=plugin_poi_geodownload.so diff --git a/xpm/Makefile.am b/xpm/Makefile.am index 786803d2..2545d046 100644 --- a/xpm/Makefile.am +++ b/xpm/Makefile.am @@ -1,3 +1,3 @@ include $(top_srcdir)/Makefile.inc -xpm_DATA = *.xpm -EXTRA_DIST = *.xpm +xpm_DATA = camping.xpm car_dealer.xpm fuel.xpm hospital.xpm hotel.xpm parking.xpm restaurant.xpm unknown.xpm +EXTRA_DIST = $(xpm_DATA) -- cgit v1.2.1 From e0c9b05ce5a394f0a95c5aebf255e8049e1bf3b1 Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jul 2007 11:04:00 +0000 Subject: Switched to fib-1.1 git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@257 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 10 ++--- fib-1.1/Makefile.in | 116 ---------------------------------------------------- route.c | 2 +- 3 files changed, 4 insertions(+), 124 deletions(-) delete mode 100644 fib-1.1/Makefile.in diff --git a/Makefile.am b/Makefile.am index f5098c9e..3bb6133b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,10 +1,6 @@ -SUBDIRS=fib-1.0 data gui graphics xpm +SUBDIRS=fib-1.1 data gui graphics xpm -fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am - cd fib-1.0 - ./configure - -AM_CPPFLAGS = @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ -DMODULE=\"navit\" +AM_CPPFLAGS = -Ifib-1.1 @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ -DMODULE=\"navit\" bin_PROGRAMS = navit @@ -23,5 +19,5 @@ navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_wind param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h profile.h search.h speech.h statusbar.h \ toolbar.h transform.h track.h util.h vehicle.h xmlconfig.h -navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ -Lfib-1.0 -lfib +navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ -Lfib-1.1 -lfib diff --git a/fib-1.1/Makefile.in b/fib-1.1/Makefile.in deleted file mode 100644 index d4829377..00000000 --- a/fib-1.1/Makefile.in +++ /dev/null @@ -1,116 +0,0 @@ -# $Id: Makefile.in,v 1.1 2005-12-02 10:41:56 martin-s Exp $ -# - -SHELL = /bin/sh - -LIB = fib - -SRCS = fib.c -OBJS = fib.o -SOBJS = fib.so -POBJS = fib.po - -INCS = fib.h - -TESTPROG = use -TESTSRCS = use.c -TESTOBJS = use.o - -REGRESS_PROG = fibtest fibtest2 tt - -DEBUG = -g -Wall -Werror -#OPT = -O2 -PROFILE = -pg -LIBOPTS = -DFH_STATS # -DNO_FREE - -srcdir = @srcdir@ - -AFLAGS = -Wall -I$(srcdir) $(DEBUG) $(OPT) $(LIBOPTS) $(CFLAGS) - -MAJOR = 1 -ARNAME = lib$(LIB).a -SONAME = lib$(LIB).so.$(MAJOR) -PANAME = lib$(LIB)_p.a - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -LIBDIR = @libdir@ -LIBOWN = 0 -LIBGRP = 0 -LIBMOD = 0444 -INCDIR = @includedir@ -INCOWN = 0 -INCGRP = 0 -INCMOD = 0444 - -all: $(ARNAME) $(SONAME) $(PANAME) - -$(ARNAME): $(OBJS) - $(AR) rc $@ $(OBJS) - -$(SONAME): $(SOBJS) - $(CC) -shared -o $@ $(SOBJS) - -$(PANAME): $(POBJS) - $(AR) rc $@ $(POBJS) - -$(TESTPROG): $(TESTOBJS) $(ARNAME) - $(CC) -static $(CFLAGS) -o $@ $(TESTOBJS) $(ARNAME) $(PROFILE) - -deepclean: clean - rm -f Makefile config.cache config.log config.status configure - -clean: regressclean - rm -f $(ARNAME) $(OBJS) $(SONAME) $(SOBJS) $(PANAME) $(POBJS) \ - $(TESTPROG) $(TESTOBJS) .depend - -install: $(ARNAME) $(SONAME) $(PANAME) - mkdir -p -m 755 $(LIBDIR) - for i in $(ARNAME) $(SONAME) $(PANAME); do \ - cp $$i $(LIBDIR); \ - chown $(LIBOWN):$(LIBGRP) $(LIBDIR)/$$i; \ - chmod $(LIBMOD) $(LIBDIR)/$$i; \ - done - mkdir -p -m 755 $(INCDIR) - for i in $(INCS); do \ - cp $$i $(INCDIR); \ - chown $(INCOWN):$(INCGRP) $(INCDIR)/$$i; \ - chmod $(INCMOD) $(INCDIR)/$$i; \ - done - -depend: - mkdep $(AFLAGS) $(SRCS) - -$(srcdir)/configure: configure.in - cd $(srcdir) && autoconf - -Makefile: Makefile.in config.status - ./config.status - -config.status: configure - ./config.status --recheck - -regress: $(REGRESS_PROG) - @for i in $(REGRESS_PROG); do \ - echo Regression for $$i; \ - ./$$i > regress.new; \ - diff $${i}.out regress.new; \ - done - rm regress.new - -regressclean: - rm -f $(REGRESS_PROG) - -.SUFFIXES: -.SUFFIXES: .so .po .c .o -.c.so: - $(CC) -fpic $(AFLAGS) -c $< -o $@ - -.c.po: - $(CC) $(PROFILE) $(AFLAGS) -c $< -o $@ - -.c.o: - $(CC) $(CPPFLAGS) $(AFLAGS) -c $< -o $@ - -.c: $(ARNAME) - $(CC) $(CPPFLAGS) $(AFLAGS) -o $@ $< $(ARNAME) diff --git a/route.c b/route.c index aa239e75..22141e7a 100644 --- a/route.c +++ b/route.c @@ -18,7 +18,7 @@ #include "track.h" #include "graphics.h" #include "transform.h" -#include "fib-1.0/fib.h" +#include "fib.h" static int speed_list[]={ 10, /* street_0 */ -- cgit v1.2.1 From e26fd0a884c25bbc90d06d7a04033356ef77c271 Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jul 2007 15:39:33 +0000 Subject: Added missing file git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@258 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- fib-1.1/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fib-1.1/Makefile.am diff --git a/fib-1.1/Makefile.am b/fib-1.1/Makefile.am new file mode 100644 index 00000000..5f818c8e --- /dev/null +++ b/fib-1.1/Makefile.am @@ -0,0 +1,3 @@ +noinst_LTLIBRARIES = libfib.la +libfib_la_SOURCES = fib.c +libfib_la_LDFLAGS = -static -- cgit v1.2.1 From b274ab3ad375152b88588a17a6ed1964b43b88ee Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 5 Jul 2007 16:15:43 +0000 Subject: Changed zoom to order in layout to avoid confusion git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@259 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- graphics.c | 2 +- layout.c | 6 +- layout.h | 4 +- navit.xml | 240 ++++++++++++++++++++++++++++++------------------------------ xmlconfig.c | 6 +- 5 files changed, 129 insertions(+), 129 deletions(-) diff --git a/graphics.c b/graphics.c index b9222990..ad8a2237 100644 --- a/graphics.c +++ b/graphics.c @@ -391,7 +391,7 @@ xdisplay_draw_layer(GHashTable *display_list, struct graphics *gra, struct layer itms=lay->itemtypes; while (itms) { itm=itms->data; - if (order >= itm->zoom_min && order <= itm->zoom_max) + if (order >= itm->order_min && order <= itm->order_max) xdisplay_draw_elements(gra, display_list, itm); itms=g_list_next(itms); } diff --git a/layout.c b/layout.c index 0ca33599..249989cc 100644 --- a/layout.c +++ b/layout.c @@ -27,13 +27,13 @@ void layout_add_layer(struct layout *layout, struct layer *layer) layout->layers = g_list_append(layout->layers, layer); } -struct itemtype * itemtype_new(int zoom_min, int zoom_max) +struct itemtype * itemtype_new(int order_min, int order_max) { struct itemtype *itm; itm = g_new0(struct itemtype, 1); - itm->zoom_min=zoom_min; - itm->zoom_max=zoom_max; + itm->order_min=order_min; + itm->order_max=order_max; return itm; } diff --git a/layout.h b/layout.h index ed96838e..91bfe27c 100644 --- a/layout.h +++ b/layout.h @@ -28,7 +28,7 @@ struct element { struct itemtype { - int zoom_min, zoom_max; + int order_min, order_max; GList *type; GList *elements; }; @@ -47,7 +47,7 @@ struct layout; struct layout *layout_new(const char *name); struct layer *layer_new(const char *name, int details); void layout_add_layer(struct layout *layout, struct layer *layer); -struct itemtype *itemtype_new(int zoom_min, int zoom_max); +struct itemtype *itemtype_new(int order_min, int order_max); void itemtype_add_type(struct itemtype *this, enum item_type type); void layer_add_itemtype(struct layer *layer, struct itemtype *itemtype); void itemtype_add_element(struct itemtype *itemtype, struct element *element); diff --git a/navit.xml b/navit.xml index 2339d15f..ba1ad414 100644 --- a/navit.xml +++ b/navit.xml @@ -15,446 +15,446 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+ +
+
+ +
+
+
+ + +
+
+
+ +
+ + + + +
+
+
+ +
+ + + + +
+ +
+
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+ +
+
+ +
+
+
+ + +
+
+
+ +
+ + + + +
+
+
+ +
+ + + + +
+ +
+
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + + +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + + + +
+ +
+
+ +
+
+ +
+
+
+ + +
+ + + + +
+ + + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+
+ +
+ + + + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+ + + + +
+
+ +
+ + + + + + diff --git a/gui/sdl/datafiles/schemes/TaharezLook.scheme b/gui/sdl/datafiles/schemes/TaharezLook.scheme new file mode 100755 index 00000000..e48ad4cc --- /dev/null +++ b/gui/sdl/datafiles/schemes/TaharezLook.scheme @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.1 From b9e84a4c7e4a5008b089dc9f728c7d050ba0a968 Mon Sep 17 00:00:00 2001 From: ghenzo Date: Fri, 13 Jul 2007 14:25:33 +0000 Subject: Adding parser files for Xerces git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@336 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/sdl/datafiles/fonts/Font.xsd | 34 +++ gui/sdl/datafiles/imagesets/Imageset.xsd | 28 +++ gui/sdl/datafiles/layouts/GUILayout.xsd | 63 +++++ gui/sdl/datafiles/looknfeel/Falagard.xsd | 399 +++++++++++++++++++++++++++++++ gui/sdl/datafiles/schemes/GUIScheme.xsd | 54 +++++ 5 files changed, 578 insertions(+) create mode 100644 gui/sdl/datafiles/fonts/Font.xsd create mode 100644 gui/sdl/datafiles/imagesets/Imageset.xsd create mode 100644 gui/sdl/datafiles/layouts/GUILayout.xsd create mode 100644 gui/sdl/datafiles/looknfeel/Falagard.xsd create mode 100644 gui/sdl/datafiles/schemes/GUIScheme.xsd diff --git a/gui/sdl/datafiles/fonts/Font.xsd b/gui/sdl/datafiles/fonts/Font.xsd new file mode 100644 index 00000000..5ab529cd --- /dev/null +++ b/gui/sdl/datafiles/fonts/Font.xsd @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/sdl/datafiles/imagesets/Imageset.xsd b/gui/sdl/datafiles/imagesets/Imageset.xsd new file mode 100644 index 00000000..49ced132 --- /dev/null +++ b/gui/sdl/datafiles/imagesets/Imageset.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/sdl/datafiles/layouts/GUILayout.xsd b/gui/sdl/datafiles/layouts/GUILayout.xsd new file mode 100644 index 00000000..0a3a5b9c --- /dev/null +++ b/gui/sdl/datafiles/layouts/GUILayout.xsd @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/sdl/datafiles/looknfeel/Falagard.xsd b/gui/sdl/datafiles/looknfeel/Falagard.xsd new file mode 100644 index 00000000..590de6bc --- /dev/null +++ b/gui/sdl/datafiles/looknfeel/Falagard.xsd @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/sdl/datafiles/schemes/GUIScheme.xsd b/gui/sdl/datafiles/schemes/GUIScheme.xsd new file mode 100644 index 00000000..24dba207 --- /dev/null +++ b/gui/sdl/datafiles/schemes/GUIScheme.xsd @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.1 From a43a59f20cf6eae2f9d32151eb8cf4fc3c3c8386 Mon Sep 17 00:00:00 2001 From: horwitz Date: Fri, 13 Jul 2007 21:45:45 +0000 Subject: fix some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@338 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/garmin_img/garmin_img.c | 1 + gui/gtk/gui_gtk_window.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/data/garmin_img/garmin_img.c b/data/garmin_img/garmin_img.c index 86b03ca1..4238cc44 100644 --- a/data/garmin_img/garmin_img.c +++ b/data/garmin_img/garmin_img.c @@ -9,6 +9,7 @@ #include "maptype.h" #include "item.h" #include "attr.h" +#include "layer.h" #include "coord.h" #include "transform.h" #include "projection.h" diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index 9e9b7a06..9d2f9ec6 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -3,6 +3,7 @@ #if !defined(GDK_Book) || !defined(GDK_Calendar) #include #endif +#include #include #include "navit.h" #include "debug.h" @@ -103,20 +104,20 @@ gui_gtk_add_bookmark(struct gui_priv *gui, struct coord *c, char *description) gui->dialog_win=gtk_window_new(GTK_WINDOW_TOPLEVEL); vbox=gtk_vbox_new(FALSE, 0); gtk_container_add (GTK_CONTAINER (gui->dialog_win), vbox); - gtk_window_set_title(gui->dialog_win,_("Add Bookmark")); + gtk_window_set_title(GTK_WINDOW(gui->dialog_win),_("Add Bookmark")); gtk_window_set_transient_for(GTK_WINDOW(gui->dialog_win), GTK_WINDOW(gui->win)); gtk_window_set_modal(GTK_WINDOW(gui->dialog_win), TRUE); label=gtk_label_new(_("Name")); - gtk_box_pack_start(vbox, label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); gui->dialog_entry=gtk_entry_new(); - gtk_entry_set_text(gui->dialog_entry, description); - gtk_box_pack_start(vbox, gui->dialog_entry, TRUE, TRUE, 0); + gtk_entry_set_text(GTK_ENTRY(gui->dialog_entry), description); + gtk_box_pack_start(GTK_BOX(vbox), gui->dialog_entry, TRUE, TRUE, 0); hbox=gtk_hbox_new(FALSE, 0); button_ok = gtk_button_new_from_stock (GTK_STOCK_OK); - gtk_box_pack_start(hbox, button_ok, TRUE, TRUE, 10); + gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 10); button_cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL); - gtk_box_pack_start(hbox, button_cancel, TRUE, TRUE, 10); - gtk_box_pack_start(vbox, hbox, TRUE, TRUE, 10); + gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 10); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10); gtk_widget_show_all(gui->dialog_win); GTK_WIDGET_SET_FLAGS (button_ok, GTK_CAN_DEFAULT); gtk_widget_grab_default(button_ok); -- cgit v1.2.1 From c705ae0ea9117aa56423e07b005ca297d70445c8 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Mon, 16 Jul 2007 12:20:34 +0000 Subject: Added c++ compliance git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@343 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- debug.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debug.h b/debug.h index aabf8e93..95eebb24 100644 --- a/debug.h +++ b/debug.h @@ -1,3 +1,7 @@ +#ifdef __cplusplus +extern "C" { +#endif + #include int debug_level; #define dbg(level,fmt...) ({ if (debug_level >= level) debug_printf(level,MODULE,__PRETTY_FUNCTION__,1,fmt); }) @@ -9,3 +13,7 @@ int debug_level_get(const char *name); void debug_vprintf(int level, const char *module, const char *function, int prefix, const char *fmt, va_list ap); void debug_printf(int level, const char *module, const char *function, int prefix, const char *fmt, ...); /* end of prototypes */ + +#ifdef __cplusplus +} +#endif \ No newline at end of file -- cgit v1.2.1 From e376f4e5bd81d8ffded88973befdaf6d1f196ce9 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Mon, 16 Jul 2007 12:49:19 +0000 Subject: Some tips and cleanup about SDL git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@344 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit.xml | 67 ++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/navit.xml b/navit.xml index 8a4d5998..85e9b43e 100644 --- a/navit.xml +++ b/navit.xml @@ -6,7 +6,15 @@ + + + + @@ -468,38 +476,27 @@ - - - - - - - - - - - - - - - - - - - - --> - - - - - + + + + + + + + + + + + + + + + + + + + --> + + + + -- cgit v1.2.1 From ef36bebfd4a8b619596758939fa9ed334099bb2f Mon Sep 17 00:00:00 2001 From: kazer_ Date: Mon, 16 Jul 2007 13:27:59 +0000 Subject: Added distance translation git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@345 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navigation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/navigation.c b/navigation.c index d3cf9565..1943078e 100644 --- a/navigation.c +++ b/navigation.c @@ -172,9 +172,9 @@ get_distance(int dist, enum navigation_mode mode, int is_length) { if (mode == navigation_mode_long) { if (is_length) - return g_strdup_printf("%d m", dist); + return g_strdup_printf(_("%d m"), dist); else - return g_strdup_printf("in %d m", dist); + return g_strdup_printf(_("in %d m"), dist); } if (dist < 1000) { if (is_length) -- cgit v1.2.1 From ba2c6b39a791e3f7423d8e42ce956e968b150147 Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 16 Jul 2007 13:46:19 +0000 Subject: Undo last change git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@346 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/garmin_img/garmin_img.c | 1 - 1 file changed, 1 deletion(-) diff --git a/data/garmin_img/garmin_img.c b/data/garmin_img/garmin_img.c index 4238cc44..86b03ca1 100644 --- a/data/garmin_img/garmin_img.c +++ b/data/garmin_img/garmin_img.c @@ -9,7 +9,6 @@ #include "maptype.h" #include "item.h" #include "attr.h" -#include "layer.h" #include "coord.h" #include "transform.h" #include "projection.h" -- cgit v1.2.1 From a0fbbc817e7ebc7b61c83fc90f6abf2662c4f2f8 Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 16 Jul 2007 18:02:14 +0000 Subject: Added intial support for POI-Windows and kind of friendsd git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@350 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.c | 6 +-- navit.c | 76 ++++++++++++++++++++++++++++++++++-- navit.h | 2 +- vehicle.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vehicle.h | 4 ++ xmlconfig.c | 7 ++-- 6 files changed, 210 insertions(+), 10 deletions(-) diff --git a/cursor.c b/cursor.c index 3e226af7..2cc36d42 100644 --- a/cursor.c +++ b/cursor.c @@ -1,4 +1,3 @@ - #include #include #include @@ -6,6 +5,7 @@ #include #include #include +#include "debug.h" #include "coord.h" #include "transform.h" #include "projection.h" @@ -233,7 +233,7 @@ cursor_update(struct vehicle *v, void *data) struct cursor * cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t) { - printf("cursor_new v=%p\n", v); + dbg(2,"enter gra=%p v=%p c=%p t=%p\n", gra, v, c, t); struct cursor *this=g_new(struct cursor,1); this->gra=gra; this->trans=t; @@ -242,6 +242,7 @@ cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct tran graphics_gc_set_foreground(this->cursor_gc, c); graphics_gc_set_linewidth(this->cursor_gc, 2); this->vehicle_callback=vehicle_callback_register(v, cursor_update, this); + dbg(2,"ret=%p\n", this); return this; } @@ -260,4 +261,3 @@ cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor this->update_callback.data=data; } - diff --git a/navit.c b/navit.c index b9f4bf25..a8d134ed 100644 --- a/navit.c +++ b/navit.c @@ -9,6 +9,7 @@ #include "navit.h" #include "callback.h" #include "gui.h" +#include "item.h" #include "map.h" #include "mapset.h" #include "main.h" @@ -64,8 +65,7 @@ struct navit { struct datawindow *roadbook_window; }; -struct gui * -main_loop_gui; +struct gui *main_loop_gui; void @@ -458,6 +458,74 @@ navit_window_roadbook_new(struct navit *this_) this_->roadbook_window=gui_datawindow_new(this_->gui, "Roadbook", NULL, NULL); } +static void +navit_window_items_new(struct navit *this_) +{ + struct datawindow *win; + struct map_selection sel; + struct coord c,*center; + struct mapset_handle *h; + struct map *m; + struct map_rect *mr; + struct item *item; + struct attr attr; + GHashTable *hash; + int idist,dist=100000; + enum item_type type1,type2,type3; + struct param_list param[4]; + char distbuf[32]; + + param[0].name="Distance"; + param[1].name="Direction"; + param[2].name="Type"; + param[3].name="Name"; + sel.next=NULL; + sel.order[layer_town]=18; + sel.order[layer_street]=18; + sel.order[layer_poly]=18; + center=transform_center(this_->trans); + sel.rect.lu.x=center->x-dist; + sel.rect.lu.y=center->y+dist; + sel.rect.rl.x=center->x+dist; + sel.rect.rl.y=center->y-dist; + hash=g_hash_table_new(g_int_hash, g_int_equal); + type1=type_bookmark; + g_hash_table_insert(hash, &type1, 1); + type2=type_poi_camping; + g_hash_table_insert(hash, &type2, 1); + type3=type_roadbook; + g_hash_table_insert(hash, &type3, 1); + dbg(2,"0x%x,0x%x - 0x%x,0x%x\n", sel.rect.lu.x, sel.rect.lu.y, sel.rect.rl.x, sel.rect.rl.y); + win=gui_datawindow_new(this_->gui, "Itemlist", NULL, NULL); + h=mapset_open(navit_get_mapset(this_)); + while ((m=mapset_next(h, 1))) { + dbg(2,"m=%p %s\n", m, map_get_filename(m)); + mr=map_rect_new(m, &sel); + dbg(2,"mr=%p\n", mr); + while ((item=map_rect_get_item(mr))) { + if (item_coord_get(item, &c, 1)) { + if (coord_rect_contains(&sel.rect, &c) && g_hash_table_lookup(hash, &item->type)) { + if (! item_attr_get(item, attr_label, &attr)) + attr.u.str=NULL; + idist=transform_distance(center, &c); + param[0].value=distbuf; + param[1].value=""; + param[2].value=item_to_name(item->type); + sprintf(distbuf,"%d", idist/1000); + param[3].value=attr.u.str; + datawindow_add(win, param, 4); + /* printf("gefunden %s %s %d\n",item_to_name(item->type), attr.u.str, idist/1000); */ + } + if (item->type >= type_line) + while (item_coord_get(item, &c, 1)); + } + } + map_rect_destroy(mr); + } + mapset_close(h); + g_hash_table_destroy(hash); +} + void navit_init(struct navit *this_) @@ -497,6 +565,7 @@ navit_init(struct navit *this_) global_navit=this_; #if 0 navit_window_roadbook_new(this_); + navit_window_items_new(this_); #endif navit_debug(this_); } @@ -562,6 +631,7 @@ navit_cursor_update(struct cursor *cursor, void *this__p) int dir=cursor_get_dir(cursor); int speed=cursor_get_speed(cursor); + if (this_->pid && speed > 2) kill(this_->pid, SIGWINCH); @@ -607,7 +677,7 @@ navit_set_position(struct navit *this_, struct coord *c) } void -navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow) +navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow, int active) { this_->vehicle=v; this_->update_curr=this_->update=update; diff --git a/navit.h b/navit.h index 3e6ed29a..da527ff6 100644 --- a/navit.h +++ b/navit.h @@ -43,7 +43,7 @@ void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); void navit_toggle_cursor(struct navit *this_); void navit_set_position(struct navit *this_, struct coord *c); -void navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow); +void navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow, int active); void navit_tracking_add(struct navit *this_, struct tracking *tracking); void navit_route_add(struct navit *this_, struct route *route); void navit_navigation_add(struct navit *this_, struct navigation *navigation); diff --git a/vehicle.c b/vehicle.c index 78b5d809..c048f139 100644 --- a/vehicle.c +++ b/vehicle.c @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include #include #ifdef HAVE_LIBGPS #include @@ -56,7 +60,13 @@ struct vehicle { #define BUFFER_SIZE 256 char buffer[BUFFER_SIZE]; int buffer_pos; + struct vehicle *child; GList *callbacks; + + int magic; + int is_udp; + int interval; + struct sockaddr_in rem; }; struct vehicle *vehicle_last; @@ -344,6 +354,114 @@ vehicle_close(struct vehicle *this) close(this->fd); } +struct packet { + int magic __attribute__ ((packed)); + unsigned char type; + union { + struct { + int x __attribute__ ((packed)); + int y __attribute__ ((packed)); + unsigned char speed; + unsigned char dir; + } pos; + } u; +} __attribute__ ((packed)) ; + +static void +vehicle_udp_recv(struct vehicle *this) +{ + struct packet pkt; + int size; + + dbg(2,"enter this=%p",this); + size=recv(this->fd, &pkt, sizeof(pkt), 0); + if (pkt.magic == this->magic) { + dbg(3,"magic 0x%x size=%d\n", pkt.magic, size); + this->current_pos.x=pkt.u.pos.x; + this->current_pos.y=pkt.u.pos.y; + this->speed=pkt.u.pos.speed; + this->dir=pkt.u.pos.dir*2; + vehicle_call_callbacks(this); + } +} + +static void +vehicle_udp_update(struct vehicle *child, void *data) +{ + struct vehicle *this=(struct vehicle *)data; + struct coord *pos=&child->current_pos; + struct packet pkt; + int speed=child->speed; + int dir=child->dir/2; + if (speed > 255) + speed=255; + pkt.magic=this->magic; + pkt.type=1; + pkt.u.pos.x=pos->x; + pkt.u.pos.y=pos->y; + pkt.u.pos.speed=speed; + pkt.u.pos.dir=dir; + sendto(this->fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&this->rem, sizeof(this->rem)); + this->current_pos=child->current_pos; + this->speed=child->speed; + this->dir=child->dir; + vehicle_call_callbacks(this); +} + +static int +vehicle_udp_query(void *data) +{ + struct vehicle *this=(struct vehicle *)data; + struct packet pkt; + dbg(2,"enter this=%p\n", this); + pkt.magic=this->magic; + pkt.type=2; + sendto(this->fd, &pkt, 5, 0, (struct sockaddr *)&this->rem, sizeof(this->rem)); + dbg(2,"ret=TRUE\n"); + return TRUE; +} + +static int +vehicle_udp_open(struct vehicle *this) +{ + char *host,*child,*url,*colon; + int port; + url=g_strdup(this->url); + colon=index(url+6,':'); + struct sockaddr_in lcl; + + if (! colon || sscanf(colon+1,"%d/%i/%d", &port, &this->magic, &this->interval) != 3) { + g_warning("Wrong syntax in %s\n", this->url); + return 0; + } + host=url+6; + *colon='\0'; + this->fd=socket(PF_INET, SOCK_DGRAM, 0); + this->is_udp=1; + memset(&lcl, 0, sizeof(lcl)); + lcl.sin_family = AF_INET; + + this->rem.sin_family = AF_INET; + inet_aton(host, &this->rem.sin_addr); + this->rem.sin_port=htons(port); + + bind(this->fd, (struct sockaddr *)&lcl, sizeof(lcl)); + child=index(colon+1,' '); + if (child) { + child++; + if (!this->child) { + dbg(3,"child=%s\n", child); + this->child=vehicle_new(child); + vehicle_callback_register(this->child, vehicle_udp_update, this); + } + } else { + vehicle_udp_query(this); + g_timeout_add(this->interval*1000, vehicle_udp_query, this); + } + g_free(url); + return 0; +} + static int vehicle_open(struct vehicle *this) { @@ -404,6 +522,9 @@ vehicle_open(struct vehicle *this) g_warning("No support for gpsd compiled in\n"); return 0; #endif + } else if (! strncmp(this->url,"udp://",6)) { + vehicle_udp_open(this); + fd=this->fd; } this->iochan=g_io_channel_unix_new(fd); enable_watch(this); @@ -428,6 +549,10 @@ vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) #else { #endif + if (this->is_udp) { + vehicle_udp_recv(this); + return TRUE; + } size=read(g_io_channel_unix_get_fd(iochan), this->buffer+this->buffer_pos, BUFFER_SIZE-this->buffer_pos-1); if (size <= 0) { vehicle_close(this); diff --git a/vehicle.h b/vehicle.h index 46cf4304..cb045a9b 100644 --- a/vehicle.h +++ b/vehicle.h @@ -1,4 +1,5 @@ /* prototypes */ +enum projection; struct coord; struct vehicle; enum projection vehicle_projection(struct vehicle *this); @@ -7,6 +8,9 @@ double *vehicle_speed_get(struct vehicle *this); double *vehicle_dir_get(struct vehicle *this); void vehicle_set_position(struct vehicle *this, struct coord *pos); struct vehicle *vehicle_new(const char *url); +int vehicle_get_active(struct vehicle *this); +void vehicle_set_active(struct vehicle *this, int active); void *vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); void vehicle_callback_unregister(struct vehicle *this, void *handle); void vehicle_destroy(struct vehicle *this); +/* end of prototypes */ diff --git a/xmlconfig.c b/xmlconfig.c index 577cd1cc..944dd868 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -192,7 +192,7 @@ xmlconfig_vehicle(struct xmlstate *state) const char *s=find_attribute(state, "source", 1); const char *value; struct color color; - int update=1, follow=0; + int update=1, follow=0, active; if (! s) return 0; @@ -205,8 +205,9 @@ xmlconfig_vehicle(struct xmlstate *state) update=convert_number(value); if ((value=find_attribute(state, "follow", 0))) follow=convert_number(value); - - navit_vehicle_add(state->parent->element_object, state->element_object, &color, update, follow); + active=find_boolean(state, "active", 1, 0); + + navit_vehicle_add(state->parent->element_object, state->element_object, &color, update, follow, active); return 1; } -- cgit v1.2.1 From 25fe8f00e4496e270e2a58c823581b9676e172bb Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 16 Jul 2007 20:22:41 +0000 Subject: Fixed a few bugs, added one way support to tracking git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@352 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- debug.h | 2 +- track.c | 35 ++++++++++++++++++++++++++++------- vehicle.c | 6 +++--- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/debug.h b/debug.h index 95eebb24..d153e5bd 100644 --- a/debug.h +++ b/debug.h @@ -16,4 +16,4 @@ void debug_printf(int level, const char *module, const char *function, int prefi #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/track.c b/track.c index 884031de..23ec5d3e 100644 --- a/track.c +++ b/track.c @@ -62,7 +62,7 @@ struct tracking { }; -int angle_factor=10; +int angle_factor=4; int connected_pref=-10; int nostop_pref=10; @@ -172,12 +172,18 @@ tracking_angle_abs_diff(int a1, int a2, int full) } static int -tracking_angle_delta(int a1, int a2, int dir) +tracking_angle_delta(int vehicle_angle, int street_angle, int dir) { - if (! dir) - return tracking_angle_abs_diff(a1, a2, 180); - else - return tracking_angle_abs_diff(a1, a2, 360); + int full=180; + int ret; + if (dir) { + full=360; + if (dir < 0) + street_angle=(street_angle+180)%360; + } + ret=tracking_angle_abs_diff(vehicle_angle, street_angle, full); + + return ret*ret; } static int @@ -226,11 +232,26 @@ tracking_update(struct tracking *tr, struct coord *c, int angle) tr->curr_line=NULL; while (t) { struct street_data *sd=t->street; + int dir; + switch(sd->limit & 3) { + case 0: + dir=0; + break; + case 1: + dir=1; + break; + case 2: + dir=-1; + break; + case 3: + t=t->next; + continue; + } for (i = 0; i < sd->count-1 ; i++) { dbg(2, "%d: (0x%x,0x%x)-(0x%x,0x%x)\n", i, sd->c[i].x, sd->c[i].y, sd->c[i+1].x, sd->c[i+1].y); value=transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt); if (value < INT_MAX/2) - value += tracking_angle_delta(angle, t->angle[i], 0)*angle_factor; + value += tracking_angle_delta(angle, t->angle[i], dir)*angle_factor; if (tracking_is_connected(tr->curr, &sd->c[i])) value += connected_pref; if (lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y) diff --git a/vehicle.c b/vehicle.c index c048f139..103d548e 100644 --- a/vehicle.c +++ b/vehicle.c @@ -363,7 +363,7 @@ struct packet { int y __attribute__ ((packed)); unsigned char speed; unsigned char dir; - } pos; + } pos __attribute__ ((packed)) ; } u; } __attribute__ ((packed)) ; @@ -374,7 +374,7 @@ vehicle_udp_recv(struct vehicle *this) int size; dbg(2,"enter this=%p",this); - size=recv(this->fd, &pkt, sizeof(pkt), 0); + size=recv(this->fd, &pkt, 15, 0); if (pkt.magic == this->magic) { dbg(3,"magic 0x%x size=%d\n", pkt.magic, size); this->current_pos.x=pkt.u.pos.x; @@ -401,7 +401,7 @@ vehicle_udp_update(struct vehicle *child, void *data) pkt.u.pos.y=pos->y; pkt.u.pos.speed=speed; pkt.u.pos.dir=dir; - sendto(this->fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&this->rem, sizeof(this->rem)); + sendto(this->fd, &pkt, 15, 0, (struct sockaddr *)&this->rem, sizeof(this->rem)); this->current_pos=child->current_pos; this->speed=child->speed; this->dir=child->dir; -- cgit v1.2.1 From 3b584eb8d1585a1f21c116d06c1dc4388ec37ee4 Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 16 Jul 2007 22:25:39 +0000 Subject: Improved vehicle handling git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@353 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- callback.c | 9 +++-- callback.h | 25 ++++++++++++++ cursor.c | 42 +++++++++-------------- cursor.h | 5 +-- navit.c | 111 +++++++++++++++++++++++++++++++++++++++--------------------- navit.h | 4 ++- vehicle.c | 52 ++++++++++++---------------- vehicle.h | 7 ++-- xmlconfig.c | 6 ++-- 9 files changed, 155 insertions(+), 106 deletions(-) diff --git a/callback.c b/callback.c index cd45c74d..49d2cd04 100644 --- a/callback.c +++ b/callback.c @@ -54,12 +54,17 @@ callback_list_add_new(struct callback_list *l, void (*func)(), int pcount, void } void -callback_list_remove_destroy(struct callback_list *l, struct callback *cb) +callback_list_remove(struct callback_list *l, struct callback *cb) { l->list=g_list_remove(l->list, cb); - g_free(cb); } +void +callback_list_remove_destroy(struct callback_list *l, struct callback *cb) +{ + callback_list_remove(l, cb); + g_free(cb); +} void callback_list_call(struct callback_list *l, int pcount, void **p) diff --git a/callback.h b/callback.h index 1976a11e..769ef7dd 100644 --- a/callback.h +++ b/callback.h @@ -8,9 +8,34 @@ struct callback_list *callback_list_new(void); struct callback *callback_new(void (*func)(void), int pcount, void **p); void callback_list_add(struct callback_list *l, struct callback *cb); struct callback *callback_list_add_new(struct callback_list *l, void (*func)(void), int pcount, void **p); +void callback_list_remove(struct callback_list *l, struct callback *cb); void callback_list_remove_destroy(struct callback_list *l, struct callback *cb); void callback_list_call(struct callback_list *l, int pcount, void **p); void callback_list_destroy(struct callback_list *l); + +static inline struct callback *callback_new_1(void (*func)(void), void *p1) +{ + void *p[1]; + p[0]=p1; + return callback_new(func, 1, p); +} + +static inline void callback_list_call_1(struct callback_list *l, void *p1) +{ + void *p[1]; + p[0]=p; + callback_list_call(l, 1, p); +} + +static inline void callback_list_call_2(struct callback_list *l, void *p1, void *p2) +{ + void *p[2]; + p[0]=p1; + p[1]=p2; + callback_list_call(l, 2, p); +} + +#define callback_cast(x) (void (*)(void))(x) /* end of prototypes */ #ifdef __cplusplus } diff --git a/cursor.c b/cursor.c index 2cc36d42..ee54cb32 100644 --- a/cursor.c +++ b/cursor.c @@ -15,15 +15,12 @@ #include "menu.h" #include "vehicle.h" #include "navit.h" +#include "callback.h" #include "color.h" #include "cursor.h" #include "compass.h" /* #include "track.h" */ -struct callback { - void (*func)(struct cursor *, void *data); - void *data; -}; struct cursor { @@ -31,13 +28,13 @@ struct cursor { struct graphics_gc *cursor_gc; struct transformation *trans; struct point cursor_pnt; - struct callback offscreen_callback; - struct callback update_callback; + struct callback_list *offscreen_cbl; + struct callback_list *update_cbl; struct vehicle *v; + struct callback *vehicle_cb; int dir; int speed; struct coord pos; - void *vehicle_callback; }; struct coord * @@ -198,9 +195,8 @@ cursor_get_speed(struct cursor *this) } static void -cursor_update(struct vehicle *v, void *data) +cursor_update(struct cursor *this, struct vehicle *v) { - struct cursor *this=data; struct point pnt; struct coord *pos; double *dir; @@ -216,11 +212,9 @@ cursor_update(struct vehicle *v, void *data) this->dir=*dir; this->speed=*speed; this->pos=*pos; - if (this->update_callback.func) - (*this->update_callback.func)(this, this->update_callback.data); + callback_list_call_1(this->update_cbl, this); if (!transform(this->trans, pro, &this->pos, &pnt) || !transform_within_border(this->trans, &pnt, border)) { - if (this->offscreen_callback.func) - (*this->offscreen_callback.func)(this, this->offscreen_callback.data); + callback_list_call_1(this->offscreen_cbl, this); transform(this->trans, pro, &this->pos, &pnt); } cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5); @@ -235,29 +229,25 @@ cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct tran { dbg(2,"enter gra=%p v=%p c=%p t=%p\n", gra, v, c, t); struct cursor *this=g_new(struct cursor,1); + this->offscreen_cbl=callback_list_new(); + this->update_cbl=callback_list_new(); this->gra=gra; this->trans=t; this->cursor_gc=graphics_gc_new(gra); this->v=v; graphics_gc_set_foreground(this->cursor_gc, c); graphics_gc_set_linewidth(this->cursor_gc, 2); - this->vehicle_callback=vehicle_callback_register(v, cursor_update, this); + this->vehicle_cb=callback_new_1(callback_cast(cursor_update), this); + vehicle_callback_add(v, this->vehicle_cb); dbg(2,"ret=%p\n", this); return this; } void -cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) -{ - this->offscreen_callback.func=func; - this->offscreen_callback.data=data; -} - - -void -cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) +cursor_add_callback(struct cursor *this, int offscreen, struct callback *cb) { - this->update_callback.func=func; - this->update_callback.data=data; + if (offscreen) + callback_list_add(this->offscreen_cbl, cb); + else + callback_list_add(this->update_cbl, cb); } - diff --git a/cursor.h b/cursor.h index f6d5a5ea..dcd21e65 100644 --- a/cursor.h +++ b/cursor.h @@ -1,4 +1,5 @@ /* prototypes */ +struct callback; struct color; struct coord; struct cursor; @@ -10,5 +11,5 @@ void cursor_pos_set(struct cursor *this, struct coord *pos); int cursor_get_dir(struct cursor *this); int cursor_get_speed(struct cursor *this); struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t); -void cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); -void cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); +void cursor_add_callback(struct cursor *this, int offscreen, struct callback *cb); +/* end of prototypes */ diff --git a/navit.c b/navit.c index a8d134ed..95459a25 100644 --- a/navit.c +++ b/navit.c @@ -30,6 +30,17 @@ #define _(STRING) gettext(STRING) +struct navit_vehicle { + int update; + int update_curr; + int follow; + int follow_curr; + struct cursor *cursor; + struct vehicle *vehicle; + struct callback *offscreen_cb; + struct callback *update_cb; +}; + struct navit { GList *mapsets; GList *layouts; @@ -46,19 +57,16 @@ struct navit { struct menu *menubar; struct route *route; struct navigation *navigation; - struct cursor *cursor; struct speech *speech; - struct vehicle *vehicle; struct tracking *tracking; struct map_flags *flags; int ready; struct window *win; struct displaylist *displaylist; int cursor_flag; - int update; - int follow; - int update_curr; - int follow_curr; + GList *vehicles; + struct navit_vehicle *vehicle; + struct callback_list *vehicle_cbl; int pid; struct callback *nav_speech_cb; struct callback *roadbook_callback; @@ -453,7 +461,7 @@ navit_window_roadbook_update(struct navit *this_) static void navit_window_roadbook_new(struct navit *this_) { - this_->roadbook_callback=callback_new(navit_window_roadbook_update, 1, &this_); + this_->roadbook_callback=callback_new_1(callback_cast(navit_window_roadbook_update), this_); navigation_register_callback(this_->navigation, navigation_mode_long, this_->roadbook_callback); this_->roadbook_window=gui_datawindow_new(this_->gui, "Roadbook", NULL, NULL); } @@ -490,11 +498,11 @@ navit_window_items_new(struct navit *this_) sel.rect.rl.y=center->y-dist; hash=g_hash_table_new(g_int_hash, g_int_equal); type1=type_bookmark; - g_hash_table_insert(hash, &type1, 1); + g_hash_table_insert(hash, &type1, (void *)1); type2=type_poi_camping; - g_hash_table_insert(hash, &type2, 1); + g_hash_table_insert(hash, &type2, (void *)1); type3=type_roadbook; - g_hash_table_insert(hash, &type3, 1); + g_hash_table_insert(hash, &type3, (void *)1); dbg(2,"0x%x,0x%x - 0x%x,0x%x\n", sel.rect.lu.x, sel.rect.lu.y, sel.rect.rl.x, sel.rect.rl.y); win=gui_datawindow_new(this_->gui, "Itemlist", NULL, NULL); h=mapset_open(navit_get_mapset(this_)); @@ -557,7 +565,7 @@ navit_init(struct navit *this_) navit_add_menu_former_destinations(this_, NULL, this_->route); } if (this_->navigation && this_->speech) { - this_->nav_speech_cb=callback_new(navit_speak, 1, &this_); + this_->nav_speech_cb=callback_new_1(callback_cast(navit_speak), this_); navigation_register_callback(this_->navigation, navigation_mode_speech, this_->nav_speech_cb); #if 0 #endif @@ -615,53 +623,56 @@ navit_toggle_cursor(struct navit *this_) } static void -navit_cursor_offscreen(struct cursor *cursor, void *this__p) +navit_cursor_offscreen(struct navit *this_, struct cursor *cursor) { - struct navit *this_=this__p; - - if (this_->cursor_flag) - navit_set_center(this_, cursor_pos_get(cursor)); + if (!this_->cursor_flag || !this_->vehicle || this_->vehicle->cursor != cursor) + return; + navit_set_center(this_, cursor_pos_get(cursor)); } static void -navit_cursor_update(struct cursor *cursor, void *this__p) +navit_cursor_update(struct navit *this_, struct cursor *cursor) { - struct navit *this_=this__p; struct coord *cursor_c=cursor_pos_get(cursor); int dir=cursor_get_dir(cursor); int speed=cursor_get_speed(cursor); + if (!this_->vehicle || this_->vehicle->cursor != cursor) + return; + + cursor_c=cursor_pos_get(cursor); + dir=cursor_get_dir(cursor); + speed=cursor_get_speed(cursor); if (this_->pid && speed > 2) kill(this_->pid, SIGWINCH); - - if (this_->tracking) { struct coord c=*cursor_c; if (tracking_update(this_->tracking, &c, dir)) { cursor_c=&c; cursor_pos_set(cursor, cursor_c); - if (this_->route && this_->update_curr == 1) + if (this_->route && this_->vehicle->update_curr == 1) route_set_position_from_tracking(this_->route, this_->tracking); } } else { - if (this_->route && this_->update_curr == 1) + if (this_->route && this_->vehicle->update_curr == 1) route_set_position(this_->route, cursor_c); } - if (this_->route && this_->update_curr == 1) + if (this_->route && this_->vehicle->update_curr == 1) navigation_update(this_->navigation, this_->route); if (this_->cursor_flag) { - if (this_->follow_curr == 1) + if (this_->vehicle->follow_curr == 1) navit_set_center_cursor(this_, cursor_c, dir, 50, 80); } - if (this_->follow_curr > 1) - this_->follow_curr--; + if (this_->vehicle->follow_curr > 1) + this_->vehicle->follow_curr--; else - this_->follow_curr=this_->follow; - if (this_->update_curr > 1) - this_->update_curr--; + this_->vehicle->follow_curr=this_->vehicle->follow; + if (this_->vehicle->update_curr > 1) + this_->vehicle->update_curr--; else - this_->update_curr=this_->update; + this_->vehicle->update_curr=this_->vehicle->update; + callback_list_call_2(this_->vehicle_cbl, this_, this_->vehicle->vehicle); } void @@ -676,15 +687,39 @@ navit_set_position(struct navit *this_, struct coord *c) navit_draw(this_); } +struct navit_vehicle * +navit_add_vehicle(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow) +{ + struct navit_vehicle *nv=g_new0(struct navit_vehicle, 1); + nv->vehicle=v; + nv->update_curr=nv->update=update; + nv->follow_curr=nv->follow=follow; + nv->cursor=cursor_new(this_->gra, v, c, this_->trans); + nv->offscreen_cb=callback_new_1(callback_cast(navit_cursor_offscreen), this_); + cursor_add_callback(nv->cursor, 1, nv->offscreen_cb); + nv->update_cb=callback_new_1(callback_cast(navit_cursor_update), this_); + cursor_add_callback(nv->cursor, 0, nv->update_cb); + + this_->vehicles=g_list_append(this_->vehicles, nv); + return nv; +} + +void +navit_add_vehicle_cb(struct navit *this_, struct callback *cb) +{ + callback_list_add(this_->vehicle_cbl, cb); +} + +void +navit_remove_vehicle_cb(struct navit *this_, struct callback *cb) +{ + callback_list_remove(this_->vehicle_cbl, cb); +} + void -navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow, int active) -{ - this_->vehicle=v; - this_->update_curr=this_->update=update; - this_->follow_curr=this_->follow=follow; - this_->cursor=cursor_new(this_->gra, v, c, this_->trans); - cursor_register_offscreen_callback(this_->cursor, navit_cursor_offscreen, this_); - cursor_register_update_callback(this_->cursor, navit_cursor_update, this_); +navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv) +{ + this_->vehicle=nv; } void diff --git a/navit.h b/navit.h index da527ff6..6b905af2 100644 --- a/navit.h +++ b/navit.h @@ -13,6 +13,7 @@ struct mapset; struct menu; struct navigation; struct navit; +struct navit_vehicle; struct point; struct route; struct speech; @@ -43,7 +44,8 @@ void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); void navit_toggle_cursor(struct navit *this_); void navit_set_position(struct navit *this_, struct coord *c); -void navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow, int active); +struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow); +void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv); void navit_tracking_add(struct navit *this_, struct tracking *tracking); void navit_route_add(struct navit *this_, struct route *route); void navit_navigation_add(struct navit *this_, struct navigation *navigation); diff --git a/vehicle.c b/vehicle.c index 103d548e..cf3ff248 100644 --- a/vehicle.c +++ b/vehicle.c @@ -17,6 +17,7 @@ #endif #include "debug.h" #include "coord.h" +#include "callback.h" #include "transform.h" #include "projection.h" #include "statusbar.h" @@ -60,8 +61,10 @@ struct vehicle { #define BUFFER_SIZE 256 char buffer[BUFFER_SIZE]; int buffer_pos; + + struct callback_list *cbl; struct vehicle *child; - GList *callbacks; + struct callback *child_cb; int magic; int is_udp; @@ -96,17 +99,6 @@ vehicle_projection(struct vehicle *this) return projection_mg; } -static void -vehicle_call_callbacks(struct vehicle *this) -{ - GList *item=g_list_first(this->callbacks); - while (item) { - struct callback *cb=item->data; - (*cb->func)(this, cb->data); - item=g_list_next(item); - } -} - struct coord * vehicle_pos_get(struct vehicle *this) { @@ -133,7 +125,7 @@ vehicle_set_position(struct vehicle *this, struct coord *pos) this->curr.y=this->current_pos.y; this->delta.x=0; this->delta.y=0; - vehicle_call_callbacks(this); + callback_list_call_1(this->cbl, this); } static int @@ -220,7 +212,7 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; - vehicle_call_callbacks(this); + callback_list_call_1(this->cbl, this); if (this->is_file) { disable_watch(this); g_timeout_add(1000, enable_watch_timer, this); @@ -318,7 +310,7 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; - vehicle_call_callbacks(this); + callback_list_call_1(this->cbl, this); data->set &= ~LATLON_SET; } if (data->set & ALTITUDE_SET) { @@ -363,7 +355,7 @@ struct packet { int y __attribute__ ((packed)); unsigned char speed; unsigned char dir; - } pos __attribute__ ((packed)) ; + } pos; } u; } __attribute__ ((packed)) ; @@ -381,14 +373,13 @@ vehicle_udp_recv(struct vehicle *this) this->current_pos.y=pkt.u.pos.y; this->speed=pkt.u.pos.speed; this->dir=pkt.u.pos.dir*2; - vehicle_call_callbacks(this); + callback_list_call_1(this->cbl, this); } } static void -vehicle_udp_update(struct vehicle *child, void *data) +vehicle_udp_update(struct vehicle *this, struct vehicle *child) { - struct vehicle *this=(struct vehicle *)data; struct coord *pos=&child->current_pos; struct packet pkt; int speed=child->speed; @@ -405,7 +396,7 @@ vehicle_udp_update(struct vehicle *child, void *data) this->current_pos=child->current_pos; this->speed=child->speed; this->dir=child->dir; - vehicle_call_callbacks(this); + callback_list_call_1(this->cbl, this); } static int @@ -452,7 +443,8 @@ vehicle_udp_open(struct vehicle *this) if (!this->child) { dbg(3,"child=%s\n", child); this->child=vehicle_new(child); - vehicle_callback_register(this->child, vehicle_udp_update, this); + this->child_cb=callback_new_1(callback_cast(vehicle_udp_update), this); + vehicle_callback_add(this->child, this->child_cb); } } else { vehicle_udp_query(this); @@ -603,6 +595,8 @@ vehicle_new(const char *url) { struct vehicle *this; this=g_new0(struct vehicle,1); + + this->cbl=callback_list_new(); this->url=g_strdup(url); this->fd=-1; @@ -623,21 +617,16 @@ vehicle_new(const char *url) return this; } -void * -vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data) +void +vehicle_callback_add(struct vehicle *this, struct callback *cb) { - struct callback *cb; - cb=g_new(struct callback, 1); - cb->func=func; - cb->data=data; - this->callbacks=g_list_prepend(this->callbacks, cb); - return cb; + callback_list_add(this->cbl, cb); } void -vehicle_callback_unregister(struct vehicle *this, void *handle) +vehicle_callback_remove(struct vehicle *this, struct callback *cb) { - this->callbacks=g_list_remove(this->callbacks, handle); + callback_list_remove(this->cbl, cb); } @@ -645,6 +634,7 @@ void vehicle_destroy(struct vehicle *this) { vehicle_close(this); + callback_list_destroy(this->cbl); g_free(this->url); g_free(this); } diff --git a/vehicle.h b/vehicle.h index cb045a9b..ccd673a9 100644 --- a/vehicle.h +++ b/vehicle.h @@ -1,5 +1,6 @@ /* prototypes */ enum projection; +struct callback; struct coord; struct vehicle; enum projection vehicle_projection(struct vehicle *this); @@ -8,9 +9,7 @@ double *vehicle_speed_get(struct vehicle *this); double *vehicle_dir_get(struct vehicle *this); void vehicle_set_position(struct vehicle *this, struct coord *pos); struct vehicle *vehicle_new(const char *url); -int vehicle_get_active(struct vehicle *this); -void vehicle_set_active(struct vehicle *this, int active); -void *vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); -void vehicle_callback_unregister(struct vehicle *this, void *handle); +void vehicle_callback_add(struct vehicle *this, struct callback *cb); +void vehicle_callback_remove(struct vehicle *this, struct callback *cb); void vehicle_destroy(struct vehicle *this); /* end of prototypes */ diff --git a/xmlconfig.c b/xmlconfig.c index 944dd868..5513eac8 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -193,6 +193,7 @@ xmlconfig_vehicle(struct xmlstate *state) const char *value; struct color color; int update=1, follow=0, active; + struct navit_vehicle *nv; if (! s) return 0; @@ -206,8 +207,9 @@ xmlconfig_vehicle(struct xmlstate *state) if ((value=find_attribute(state, "follow", 0))) follow=convert_number(value); active=find_boolean(state, "active", 1, 0); - - navit_vehicle_add(state->parent->element_object, state->element_object, &color, update, follow, active); + nv=navit_add_vehicle(state->parent->element_object, state->element_object, &color, update, follow); + if (active) + navit_set_vehicle(state->parent->element_object, nv); return 1; } -- cgit v1.2.1 From dc1914284001cbd8665e05273f04fa261dd3de85 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 17 Jul 2007 08:52:51 +0000 Subject: Again bugfixes, Improvements to gtk datawindow git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@354 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- callback.h | 2 +- gui/gtk/datawindow.c | 31 +++++++++++++++------ navit.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++-- navit.h | 7 ++++- xmlconfig.c | 5 ++-- 5 files changed, 106 insertions(+), 16 deletions(-) diff --git a/callback.h b/callback.h index 769ef7dd..6d788e84 100644 --- a/callback.h +++ b/callback.h @@ -23,7 +23,7 @@ static inline struct callback *callback_new_1(void (*func)(void), void *p1) static inline void callback_list_call_1(struct callback_list *l, void *p1) { void *p[1]; - p[0]=p; + p[0]=p1; callback_list_call(l, 1, p); } diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c index 292caebc..a505675e 100644 --- a/gui/gtk/datawindow.c +++ b/gui/gtk/datawindow.c @@ -11,6 +11,8 @@ struct datawindow_priv { GtkWidget *window; GtkWidget *scrolled_window; GtkWidget *treeview; + GtkListStore *liststore; + GtkTreeModel *sortmodel; struct callback *click, *close; }; @@ -26,7 +28,6 @@ gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, in int i; GtkCellRenderer *cell; GtkTreeIter iter; - GtkListStore *liststore; GType types[count]; gchar *utf8; @@ -49,19 +50,31 @@ gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, in /* find data storage and create a new one if none is there */ if (gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview)) == NULL) { - for(i=0;itreeview), GTK_TREE_MODEL(liststore)); + for(i=0;iliststore=gtk_list_store_newv(count,types); + if (! strcmp(param[0].name, "Distance")) { + win->sortmodel=gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(win->liststore)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (win->sortmodel), 0, GTK_SORT_ASCENDING); + gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), GTK_TREE_MODEL(win->sortmodel)); + } else + gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), GTK_TREE_MODEL(win->liststore)); } - else - liststore=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview))); - gtk_list_store_append(liststore,&iter); + gtk_list_store_append(win->liststore,&iter); /* add data to data storage */ for(i=0;iliststore,&iter,i,atoi(param[i].value),-1); + } else { + utf8=g_locale_to_utf8(param[i].value,-1,NULL,NULL,NULL); + gtk_list_store_set(win->liststore,&iter,i,utf8,-1); + } } } diff --git a/navit.c b/navit.c index 95459a25..57a7aedb 100644 --- a/navit.c +++ b/navit.c @@ -31,10 +31,12 @@ #define _(STRING) gettext(STRING) struct navit_vehicle { + char *name; int update; int update_curr; int follow; int follow_curr; + struct menu *menu; struct cursor *cursor; struct vehicle *vehicle; struct callback *offscreen_cb; @@ -164,6 +166,7 @@ navit_new(const char *ui, const char *graphics, struct coord *center, enum proje FILE *f; main_add_navit(this_); + this_->vehicle_cbl=callback_list_new(); f=popen("pidof /usr/bin/ipaq-sleep","r"); if (f) { @@ -424,6 +427,42 @@ navit_add_menu_bookmarks(struct navit *this_, struct menu *men) navit_add_menu_destinations(this_, "bookmark.txt", men ? menu_add(men, "Bookmarks", menu_type_submenu, NULL, NULL, NULL) : NULL, NULL); } +static void +navit_vehicle_toggle(struct menu *menu, void *this__p, void *nv_p) +{ + struct navit *this_=(struct navit *)this__p; + struct navit_vehicle *nv=(struct navit_vehicle *)nv_p; + if (menu_get_toggle(menu)) { + if (this_->vehicle && this_->vehicle != nv) + menu_set_toggle(this_->vehicle->menu, 0); + this_->vehicle=nv; + } else { + if (this_->vehicle == nv) + this_->vehicle=NULL; + } +} + +void +navit_add_menu_vehicles(struct navit *this_, struct menu *men) +{ + struct navit_vehicle *nv; + GList *l; + l=this_->vehicles; + while (l) { + nv=l->data; + nv->menu=menu_add(men, nv->name, menu_type_toggle, navit_vehicle_toggle, this_, nv); + menu_set_toggle(nv->menu, this_->vehicle == nv); + l=g_list_next(l); + } +} + +void +navit_add_menu_vehicle(struct navit *this_, struct menu *men) +{ + men=menu_add(men, "Vehicle", menu_type_submenu, NULL, NULL, NULL); + navit_add_menu_vehicles(this_, men); +} + void navit_speak(struct navit *this_) { @@ -466,6 +505,34 @@ navit_window_roadbook_new(struct navit *this_) this_->roadbook_window=gui_datawindow_new(this_->gui, "Roadbook", NULL, NULL); } +static void +get_direction(char *buffer, int angle, int mode) +{ + angle=angle%360; + switch (mode) { + case 0: + sprintf(buffer,"%d",angle); + break; + case 1: + if (angle < 69 || angle > 291) + *buffer++='N'; + if (angle > 111 && angle < 249) + *buffer++='S'; + if (angle > 22 && angle < 158) + *buffer++='E'; + if (angle > 202 && angle < 338) + *buffer++='W'; + *buffer++='\0'; + break; + case 2: + angle=(angle+15)/30; + if (! angle) + angle=12; + sprintf(buffer,"%d H", angle); + break; + } +} + static void navit_window_items_new(struct navit *this_) { @@ -482,6 +549,7 @@ navit_window_items_new(struct navit *this_) enum item_type type1,type2,type3; struct param_list param[4]; char distbuf[32]; + char dirbuf[32]; param[0].name="Distance"; param[1].name="Direction"; @@ -516,8 +584,9 @@ navit_window_items_new(struct navit *this_) if (! item_attr_get(item, attr_label, &attr)) attr.u.str=NULL; idist=transform_distance(center, &c); + get_direction(dirbuf, transform_get_angle_delta(center, &c, 0), 2); param[0].value=distbuf; - param[1].value=""; + param[1].value=dirbuf; param[2].value=item_to_name(item->type); sprintf(distbuf,"%d", idist/1000); param[3].value=attr.u.str; @@ -554,6 +623,7 @@ navit_init(struct navit *this_) if (men) { navit_add_menu_layout(this_, men); navit_add_menu_projection(this_, men); + navit_add_menu_vehicle(this_, men); navit_add_menu_maps(this_, ms, men); } men=menu_add(this_->menubar, "Route", menu_type_submenu, NULL, NULL, NULL); @@ -573,8 +643,8 @@ navit_init(struct navit *this_) global_navit=this_; #if 0 navit_window_roadbook_new(this_); - navit_window_items_new(this_); #endif + navit_window_items_new(this_); navit_debug(this_); } @@ -688,10 +758,11 @@ navit_set_position(struct navit *this_, struct coord *c) } struct navit_vehicle * -navit_add_vehicle(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow) +navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow) { struct navit_vehicle *nv=g_new0(struct navit_vehicle, 1); nv->vehicle=v; + nv->name=g_strdup(name); nv->update_curr=nv->update=update; nv->follow_curr=nv->follow=follow; nv->cursor=cursor_new(this_->gra, v, c, this_->trans); diff --git a/navit.h b/navit.h index 6b905af2..0eeb1abd 100644 --- a/navit.h +++ b/navit.h @@ -4,6 +4,7 @@ extern "C" { extern struct gui *main_loop_gui; /* prototypes */ enum projection; +struct callback; struct color; struct coord; struct displaylist; @@ -38,13 +39,17 @@ void navit_add_menu_maps(struct navit *this_, struct mapset *ms, struct menu *me void navit_add_menu_destinations(struct navit *this_, char *file, struct menu *rmen, struct route *route); void navit_add_menu_former_destinations(struct navit *this_, struct menu *men, struct route *route); void navit_add_menu_bookmarks(struct navit *this_, struct menu *men); +void navit_add_menu_vehicles(struct navit *this_, struct menu *men); +void navit_add_menu_vehicle(struct navit *this_, struct menu *men); void navit_speak(struct navit *this_); void navit_init(struct navit *this_); void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); void navit_toggle_cursor(struct navit *this_); void navit_set_position(struct navit *this_, struct coord *c); -struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow); +struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow); +void navit_add_vehicle_cb(struct navit *this_, struct callback *cb); +void navit_remove_vehicle_cb(struct navit *this_, struct callback *cb); void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv); void navit_tracking_add(struct navit *this_, struct tracking *tracking); void navit_route_add(struct navit *this_, struct route *route); diff --git a/xmlconfig.c b/xmlconfig.c index 5513eac8..f102786f 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -190,7 +190,7 @@ static int xmlconfig_vehicle(struct xmlstate *state) { const char *s=find_attribute(state, "source", 1); - const char *value; + const char *value,*name; struct color color; int update=1, follow=0, active; struct navit_vehicle *nv; @@ -207,7 +207,8 @@ xmlconfig_vehicle(struct xmlstate *state) if ((value=find_attribute(state, "follow", 0))) follow=convert_number(value); active=find_boolean(state, "active", 1, 0); - nv=navit_add_vehicle(state->parent->element_object, state->element_object, &color, update, follow); + name=find_attribute(state, "name", 0); + nv=navit_add_vehicle(state->parent->element_object, state->element_object, name, &color, update, follow); if (active) navit_set_vehicle(state->parent->element_object, nv); return 1; -- cgit v1.2.1 From 0332d6aa65883813c50dca630417c6672ea89cfa Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 17 Jul 2007 08:53:20 +0000 Subject: Disable window for now git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@355 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navit.c b/navit.c index 57a7aedb..c5c8b206 100644 --- a/navit.c +++ b/navit.c @@ -643,8 +643,8 @@ navit_init(struct navit *this_) global_navit=this_; #if 0 navit_window_roadbook_new(this_); -#endif navit_window_items_new(this_); +#endif navit_debug(this_); } -- cgit v1.2.1 From 7f283e9841aadc72c6ccb86b5adfb4a6dbeac31b Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 17 Jul 2007 10:37:23 +0000 Subject: Improved callbacks git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@356 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- callback.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/callback.h b/callback.h index 6d788e84..bf38a783 100644 --- a/callback.h +++ b/callback.h @@ -13,6 +13,11 @@ void callback_list_remove_destroy(struct callback_list *l, struct callback *cb); void callback_list_call(struct callback_list *l, int pcount, void **p); void callback_list_destroy(struct callback_list *l); +static inline struct callback *callback_new_0(void (*func)(void)) +{ + return callback_new(func, 0, NULL); +} + static inline struct callback *callback_new_1(void (*func)(void), void *p1) { void *p[1]; -- cgit v1.2.1 From 0f97fb93810242f265b8dcb1824f9cd8c401db4f Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 17 Jul 2007 12:16:22 +0000 Subject: Added commercial center poly git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@357 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/poly.c | 3 +++ item_def.h | 1 + 2 files changed, 4 insertions(+) diff --git a/data/mg/poly.c b/data/mg/poly.c index b19aeed5..b663444f 100644 --- a/data/mg/poly.c +++ b/data/mg/poly.c @@ -127,6 +127,9 @@ poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) case 0x15: item->type=type_cemetery_poly; break; + case 0x1b: + item->type=type_commercial_center; + break; case 0x1e: item->type=type_industry_poly; break; diff --git a/item_def.h b/item_def.h index 770c19e5..bc94e43b 100644 --- a/item_def.h +++ b/item_def.h @@ -131,3 +131,4 @@ ITEM(park_poly) ITEM(sport_poly) ITEM(image) ITEM(image_path) +ITEM(commercial_center) -- cgit v1.2.1 From 05568c8916441741808bcacfa01d3aa3f7ed0cde Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 17 Jul 2007 12:22:47 +0000 Subject: Added golf course poly git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@358 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/poly.c | 3 +++ item_def.h | 1 + 2 files changed, 4 insertions(+) diff --git a/data/mg/poly.c b/data/mg/poly.c index b663444f..d57f65e8 100644 --- a/data/mg/poly.c +++ b/data/mg/poly.c @@ -148,6 +148,9 @@ poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) case 0x34: item->type=type_sport_poly; break; + case 0x3c: + item->type=type_golf_course; + break; case 0x3c: item->type=type_water_poly; break; diff --git a/item_def.h b/item_def.h index bc94e43b..0f771d2e 100644 --- a/item_def.h +++ b/item_def.h @@ -132,3 +132,4 @@ ITEM(sport_poly) ITEM(image) ITEM(image_path) ITEM(commercial_center) +ITEM(golf_course) -- cgit v1.2.1 From cf32c3f2a16f33c16b1f643104abaa6af44a79ae Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 17 Jul 2007 12:24:23 +0000 Subject: Fixed typo git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@359 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/poly.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/mg/poly.c b/data/mg/poly.c index d57f65e8..90f547ee 100644 --- a/data/mg/poly.c +++ b/data/mg/poly.c @@ -148,7 +148,7 @@ poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) case 0x34: item->type=type_sport_poly; break; - case 0x3c: + case 0x37: item->type=type_golf_course; break; case 0x3c: -- cgit v1.2.1 From 47e6fd5d1ece4167a2fb626242ddcc9a370a8978 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Tue, 17 Jul 2007 15:53:37 +0000 Subject: Fixed turn-around git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@363 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navigation.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/navigation.c b/navigation.c index 1943078e..e23ce3f6 100644 --- a/navigation.c +++ b/navigation.c @@ -438,16 +438,16 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat } else if (delta < 165) { strength=_("strongly "); } else { - dbg(0,"delta=%d\n", delta); + dbg(1,"delta=%d\n", delta); strength=_("unknown "); } if (mode != navigation_mode_long_exact) distance=round_distance(distance); if (mode == navigation_mode_speech) { if (nav->turn_around) - return g_strdup(_("When possible, please turn")); + return g_strdup(_("When possible, please turn around")); level=navigation_get_announce_level(nav, itm->item.type, distance); - dbg(0,"distance=%d level=%d type=0x%x\n", distance, level, itm->item.type); + dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->item.type); } switch(level) { case 3: -- cgit v1.2.1 From 4b00784206d5418276265dae5110b511d6b0eca1 Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 18 Jul 2007 22:42:28 +0000 Subject: Added support for bookmarks git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@364 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/destination.c | 54 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/gui/gtk/destination.c b/gui/gtk/destination.c index 485205a1..286da7ac 100644 --- a/gui/gtk/destination.c +++ b/gui/gtk/destination.c @@ -41,27 +41,50 @@ static void button_map(GtkWidget *widget, struct search_param *search) navit_set_center(search->nav, c); } +static char *description(struct search_param *search, GtkTreeIter *iter) +{ + char *desc,*car,*postal,*town,*street; + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 0, &car, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 1, &postal, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 2, &town, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 4, &street, -1); + if (search->attr.type == attr_town_name) + desc=g_strdup_printf("%s-%s %s", car, postal, town); + else + desc=g_strdup_printf("%s-%s %s, %s", car, postal, town, street); + return desc; +} + static void button_destination(GtkWidget *widget, struct search_param *search) { struct coord *c=NULL; GtkTreeIter iter; - char *desc,*car,*postal,*town,*street; + char *desc; + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); if (c) { - gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 0, &car, -1); - gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 1, &postal, -1); - gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 2, &town, -1); - gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 4, &street, -1); - if (search->attr.type == attr_town_name) - desc=g_strdup_printf("%s-%s %s", car, postal, town); - else - desc=g_strdup_printf("%s-%s %s, %s", car, postal, town, street); + desc=description(search, &iter); navit_set_destination(search->nav, c, desc); g_free(desc); } } +static void button_bookmark(GtkWidget *widget, struct search_param *search) +{ + struct coord *c=NULL; + GtkTreeIter iter; + char *desc; + + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); + if (c) { + desc=description(search, &iter); + navit_add_bookmark(search->nav, c, desc); + g_free(desc); + } +} + char **columns_text[] = { (char *[]){"Car","Iso2","Iso3","Country",NULL}, @@ -109,7 +132,7 @@ static void changed(GtkWidget *widget, struct search_param *search) if (widget == search->entry_city) { dbg(0,"town\n"); search->attr.type=attr_town_name; - if (strlen(search->attr.u.str) < 2) + if (strlen(search->attr.u.str) < 3) return; set_columns(search, 1); } @@ -277,7 +300,7 @@ int destination_address(struct navit *nav) GtkWidget *label_postal, *label_city, *label_district; GtkWidget *label_street, *label_number; GtkWidget *hseparator1,*hseparator2; - GtkWidget *button1,*button2; + GtkWidget *button1,*button2,*button3; int i; struct search_param *search=&search_param; @@ -326,7 +349,8 @@ int destination_address(struct navit *nav) hseparator2 = gtk_vseparator_new(); button1 = gtk_button_new_with_label("Karte"); - button2 = gtk_button_new_with_label("Ziel"); + button2 = gtk_button_new_with_label("Bookmark"); + button3 = gtk_button_new_with_label("Ziel"); gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL, 0, 0); @@ -347,7 +371,8 @@ int destination_address(struct navit *nav) gtk_table_attach(GTK_TABLE(table), search->listbox, 0, 3, 4, 5, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); gtk_table_attach(GTK_TABLE(table), button1, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach(GTK_TABLE(table), button2, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), button2, 1, 2, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), button3, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 0, 0); g_signal_connect(G_OBJECT(search->entry_country), "changed", G_CALLBACK(changed), search); g_signal_connect(G_OBJECT(search->entry_postal), "changed", G_CALLBACK(changed), search); @@ -356,7 +381,8 @@ int destination_address(struct navit *nav) g_signal_connect(G_OBJECT(search->entry_street), "changed", G_CALLBACK(changed), search); g_signal_connect(G_OBJECT(search->entry_number), "changed", G_CALLBACK(changed), search); g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_map), search); - g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_destination), search); + g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_bookmark), search); + g_signal_connect(G_OBJECT(button3), "clicked", G_CALLBACK(button_destination), search); gtk_widget_grab_focus(search->entry_city); -- cgit v1.2.1 From f7fc6e4c3501492cdaa6ac22a1c5766a1a12bb23 Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 18 Jul 2007 22:43:09 +0000 Subject: Fixed some alignment errors git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@365 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/street.c | 10 +++++----- data/mg/town.c | 4 ++-- data/mg/tree.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/data/mg/street.c b/data/mg/street.c index 26bfaedb..45dbabc0 100644 --- a/data/mg/street.c +++ b/data/mg/street.c @@ -28,14 +28,14 @@ static void street_name_numbers_get(struct street_name_numbers *name_numbers, unsigned char **p) { unsigned char *start=*p; - name_numbers->len=get_u16(p); + name_numbers->len=get_u16_unal(p); name_numbers->tag=get_u8(p); - name_numbers->dist=get_u32(p); - name_numbers->country=get_u32(p); + name_numbers->dist=get_u32_unal(p); + name_numbers->country=get_u32_unal(p); name_numbers->c=coord_get(p); name_numbers->first=get_u24(p); name_numbers->last=get_u24(p); - name_numbers->segment_count=get_u32(p); + name_numbers->segment_count=get_u32_unal(p); name_numbers->segments=(struct street_name_segment *)(*p); (*p)+=sizeof(struct street_name_segment)*name_numbers->segment_count; name_numbers->aux_len=name_numbers->len-(*p-start); @@ -49,7 +49,7 @@ static void street_name_number_get(struct street_name_number *name_number, unsigned char **p) { unsigned char *start=*p; - name_number->len=get_u16(p); + name_number->len=get_u16_unal(p); name_number->tag=get_u8(p); name_number->c=coord_get(p); name_number->first=get_u24(p); diff --git a/data/mg/town.c b/data/mg/town.c index 838bc2cc..df880b7a 100644 --- a/data/mg/town.c +++ b/data/mg/town.c @@ -185,11 +185,11 @@ town_search_compare(unsigned char **p, struct map_rect_priv *mr) int country, d; char *name; - country=get_u16(p); + country=get_u16_unal(p); dbg(1,"country 0x%x ", country); name=get_string(p); dbg(1,"name '%s' ",name); - mr->search_blk_count=get_u32(p); + mr->search_blk_count=get_u32_unal(p); mr->search_blk_off=(struct block_offset *)(*p); dbg(1,"len %d ", mr->search_blk_count); (*p)+=mr->search_blk_count*4; diff --git a/data/mg/tree.c b/data/mg/tree.c index aedce721..30852d23 100644 --- a/data/mg/tree.c +++ b/data/mg/tree.c @@ -166,7 +166,7 @@ int tree_search_next(struct tree_search *ts, unsigned char **p, int dir) } tsn->low=tsn->high; tsn->last=*p; - tsn->high=get_u32(p); + tsn->high=get_u32_unal(p); dbg(1,"saving last3 %d %p\n", ts->curr_node, tsn->last); if (*p < tsn->end) return (tsn->low == 0xffffffff ? 1 : 0); @@ -175,7 +175,7 @@ int tree_search_next(struct tree_search *ts, unsigned char **p, int dir) dbg(1,"low 0x%x\n", tsn->low); tsn=tree_search_enter(ts, tsn->low); *p=tsn->p; - tsn->high=get_u32(p); + tsn->high=get_u32_unal(p); ts->last_node=ts->curr_node; dbg(1,"saving last4 %d 0x%x\n", ts->curr_node, tsn->last-ts->f->begin); dbg(1,"high4=0x%x\n", tsn->high); @@ -194,7 +194,7 @@ int tree_search_next_lin(struct tree_search *ts, unsigned char **p) ts->nodes[ts->last_node].last=*p; *p=tsn->last; for (;;) { - high=get_u32(p); + high=get_u32_unal(p); if (*p < tsn->end) { ts->last_node=ts->curr_node; while (high != 0xffffffff) { -- cgit v1.2.1 From 80c30d3494a77acc655fa6b269aa28e0f3c104f6 Mon Sep 17 00:00:00 2001 From: kazer_ Date: Thu, 19 Jul 2007 09:20:27 +0000 Subject: Added osm2navit script git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@366 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- script/osm2navit | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100755 script/osm2navit diff --git a/script/osm2navit b/script/osm2navit new file mode 100755 index 00000000..c16dc215 --- /dev/null +++ b/script/osm2navit @@ -0,0 +1,201 @@ +#!/usr/bin/perl +use Data::Dumper; +sub deg +{ + my ($deg, $dir)=(@_); + + my ($in,$degi); + + $in=$deg; + $degi=int($deg); + $deg-=$degi; + $deg*=60; + return sprintf("%d%09.6f %s", $degi, $deg, $dir); +} +sub coord +{ + my ($id)=(@_); + return deg($lat{$id}, "N") . " " . deg($lon{$id}, "E"); +} + +while (<>) { + $line = $_; + chomp($line); + #print "$line\n"; + if ($line =~ / 5) { + #exit(0); + } +} +while (($key,$value)=each(%reference)) { + if ($value != 1) { + print STDERR "$key $value\n"; + } +} + -- cgit v1.2.1 From ed3d4bb86126d0d5fad410b92ebe98af0f4cab4c Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 21 Jul 2007 08:35:06 +0000 Subject: Improvements to bookmarks and cursor handling git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@367 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.c | 12 ++- cursor.h | 1 + gui/gtk/gui_gtk_action.c | 7 ++ navit.c | 200 ++++++++++++++++++++++++++++++++--------------- navit.h | 1 - route.c | 10 ++- vehicle.c | 2 +- 7 files changed, 164 insertions(+), 69 deletions(-) diff --git a/cursor.c b/cursor.c index ee54cb32..3584cd95 100644 --- a/cursor.c +++ b/cursor.c @@ -35,6 +35,7 @@ struct cursor { int dir; int speed; struct coord pos; + enum projection pro; }; struct coord * @@ -105,6 +106,14 @@ cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir) } } +void +cursor_redraw(struct cursor *this) +{ + struct point pnt; + transform(this->trans, this->pro, &this->pos, &pnt); + cursor_draw(this, &pnt, this->dir-transform_get_angle(this->trans, 0), this->speed > 2.5); +} + #if 0 static void cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new) @@ -212,10 +221,11 @@ cursor_update(struct cursor *this, struct vehicle *v) this->dir=*dir; this->speed=*speed; this->pos=*pos; + this->pro=pro; callback_list_call_1(this->update_cbl, this); if (!transform(this->trans, pro, &this->pos, &pnt) || !transform_within_border(this->trans, &pnt, border)) { callback_list_call_1(this->offscreen_cbl, this); - transform(this->trans, pro, &this->pos, &pnt); + transform(this->trans, this->pro, &this->pos, &pnt); } cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5); } diff --git a/cursor.h b/cursor.h index dcd21e65..88b3b388 100644 --- a/cursor.h +++ b/cursor.h @@ -8,6 +8,7 @@ struct transformation; struct vehicle; struct coord *cursor_pos_get(struct cursor *this); void cursor_pos_set(struct cursor *this, struct coord *pos); +void cursor_redraw(struct cursor *this); int cursor_get_dir(struct cursor *this); int cursor_get_speed(struct cursor *this); struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t); diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 29b9daa0..143b3744 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -90,6 +90,11 @@ info_action(GtkWidget *w, struct navit *nav, void *dummy) } +static void +route_clear_action(GtkWidget *w, struct navit *nav, void *dummy) +{ + navit_set_destination(nav, NULL, NULL); +} static void destination_action(GtkWidget *w, struct navit *nav, void *dummy) @@ -162,6 +167,7 @@ static GtkActionEntry entries[] = { "RefreshAction", GTK_STOCK_REFRESH, _n("Refresh"), NULL, NULL, G_CALLBACK(refresh_action) }, { "InfoAction", GTK_STOCK_INFO, _n("Info"), NULL, NULL, G_CALLBACK(info_action) }, { "DestinationAction", "flag_icon", _n("Destination"), NULL, NULL, G_CALLBACK(destination_action) }, + { "RouteClearAction", NULL, _n("Clear"), NULL, NULL, G_CALLBACK(route_clear_action) }, { "Test", NULL, _n("Test"), NULL, NULL, G_CALLBACK(destination_action) }, { "QuitAction", GTK_STOCK_QUIT, _n("_Quit"), "Q",NULL, G_CALLBACK (quit_action) } }; @@ -334,6 +340,7 @@ static char layout[] = \ \ \ + \ \ \ \ diff --git a/navit.c b/navit.c index c5c8b206..8dc59634 100644 --- a/navit.c +++ b/navit.c @@ -73,6 +73,9 @@ struct navit { struct callback *nav_speech_cb; struct callback *roadbook_callback; struct datawindow *roadbook_window; + struct menu *bookmarks; + GHashTable *bookmarks_hash; + struct menu *destinations; }; struct gui *main_loop_gui; @@ -99,8 +102,17 @@ navit_add_layout(struct navit *this_, struct layout *lay) void navit_draw(struct navit *this_) { + GList *l; + struct navit_vehicle *nv; + transform_setup_source_rect(this_->trans); graphics_draw(this_->gra, this_->displaylist, this_->mapsets, this_->trans, this_->layouts, this_->route); + l=this_->vehicles; + while (l) { + nv=l->data; + cursor_redraw(nv->cursor); + l=g_list_next(l); + } this_->ready=1; } @@ -175,6 +187,7 @@ navit_new(const char *ui, const char *graphics, struct coord *center, enum proje pclose(f); } + this_->bookmarks_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); this_->cursor_flag=1; this_->trans=transform_new(); transform_set_projection(this_->trans, pro); @@ -242,44 +255,131 @@ navit_projection_set(struct menu *menu, void *this__p, void *pro_p) } static void -navit_set_destination_menu(struct menu *menu, void *this__p, void *c_p) +navit_add_menu_destinations(struct navit *this_, char *name, int offset, struct menu *rmen, GHashTable *h, void (*callback)(struct menu *menu, void *data1, void *data2)) { - struct navit *this_=this__p; - struct coord *c=c_p; - if (this_->route) { - route_set_destination(this_->route, c); - navit_draw(this_); - } + char buffer2[2048]; + char *i,*n; + struct menu *men,*nmen; + if (rmen) { + i=name; + n=name; + men=rmen; + while (h && (i=index(n, '/'))) { + strcpy(buffer2, name); + buffer2[i-name]='\0'; + if (!(nmen=g_hash_table_lookup(h, buffer2))) { + nmen=menu_add(men, buffer2+(n-name), menu_type_submenu, NULL, NULL, NULL); + g_hash_table_insert(h, g_strdup(buffer2), nmen); + } + n=i+1; + men=nmen; + } + menu_add(men, n, menu_type_menu, callback, this_, (void *)offset); + } } + static void -navit_append_coord(char *file, struct coord *c, char *type, char *description) +navit_append_coord(struct navit *this_, char *file, struct coord *c, char *type, char *description, struct menu *rmen, GHashTable *h, void (*callback)(struct menu *menu, void *data1, void *data2)) { - int fd; + FILE *f; + int offset=0; char *buffer; - buffer=g_strdup_printf("0x%x 0x%x type=%s label=\"%s\"\n", c->x, c->y, type, description); - fd=open(file, O_RDWR|O_CREAT|O_APPEND, 0644); - if (fd != -1) - write(fd, buffer, strlen(buffer)); - close(fd); - g_free(buffer); + + f=fopen(file, "a"); + if (f) { + offset=ftell(f); + if (c) + fprintf(f,"0x%x 0x%x type=%s label=\"%s\"\n", c->x, c->y, type, description); + else + fprintf(f,"\n"); + fclose(f); + } + if (c) { + buffer=g_strdup(description); + navit_add_menu_destinations(this_, buffer, offset, rmen, h, callback); + g_free(buffer); + } +} + +static int +parse_line(FILE *f, char *buffer, char **name, struct coord *c) +{ + int pos; + char *s,*i; + *name=NULL; + if (! fgets(buffer, 2048, f)) + return -3; + pos=coord_parse(buffer, projection_mg, c); + if (! pos) + return -2; + if (!buffer[pos] || buffer[pos] == '\n') + return -1; + buffer[strlen(buffer)-1]='\0'; + s=buffer+pos+1; + if (!strncmp(s,"type=", 5)) { + i=index(s, '"'); + if (i) { + s=i+1; + i=index(s, '"'); + if (i) + *i='\0'; + } + } + *name=s; + return pos; +} + + +static void +navit_set_destination_from_file(struct navit *this_, char *file, int bookmark, int offset) +{ + FILE *f; + char *name, *description, buffer[2048]; + struct coord c; + + f=fopen(file, "r"); + if (! f) + return; + fseek(f, offset, SEEK_SET); + if (parse_line(f, buffer, &name, &c) <= 0) + return; + if (bookmark) { + description=g_strdup_printf("Bookmark %s", name); + navit_set_destination(this_, &c, description); + g_free(description); + } else + navit_set_destination(this_, &c, name); +} + +static void +navit_set_destination_from_destination(struct menu *menu, void *this_p, void *offset_p) +{ + navit_set_destination_from_file((struct navit *)this_p, "destination.txt", 0, (int)offset_p); +} + +static void +navit_set_destination_from_bookmark(struct menu *menu, void *this_p, void *offset_p) +{ + navit_set_destination_from_file((struct navit *)this_p, "bookmark.txt", 1, (int)offset_p); } void navit_set_destination(struct navit *this_, struct coord *c, char *description) { - navit_append_coord("destination.txt", c, "former_destination", description); + navit_append_coord(this_, "destination.txt", c, "former_destination", description, this_->destinations, NULL, navit_set_destination_from_destination); if (this_->route) { route_set_destination(this_->route, c); navit_draw(this_); } } + void navit_add_bookmark(struct navit *this_, struct coord *c, char *description) { - navit_append_coord("bookmark.txt", c, "bookmark", description); + navit_append_coord(this_,"bookmark.txt", c, "bookmark", description, this_->bookmarks, this_->bookmarks_hash, navit_set_destination_from_bookmark); } struct navit *global_navit; @@ -357,74 +457,50 @@ navit_add_menu_maps(struct navit *this_, struct mapset *ms, struct menu *men) mapset_close(handle); } -void -navit_add_menu_destinations(struct navit *this_, char *file, struct menu *rmen, struct route *route) +static void +navit_add_menu_destinations_from_file(struct navit *this_, char *file, struct menu *rmen, GHashTable *h, struct route *route, void (*callback)(struct menu *menu, void *data1, void *data2)) { - struct coord c; int pos,flag=0; FILE *f; char buffer[2048]; - char buffer2[2048]; - char *s,*i,*n; - struct menu *men,*nmen; - GHashTable *h; + struct coord c; + char *name; + int offset=0; - h=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); f=fopen(file, "r"); if (f) { - while (! feof(f) && fgets(buffer, 2048, f)) { - if ((pos=coord_parse(buffer, projection_mg, &c))) { - if (buffer[pos] && buffer[pos] != '\n' ) { - struct coord *cn=g_new(struct coord, 1); - *cn=c; - buffer[strlen(buffer)-1]='\0'; - s=buffer+pos+1; - if (!strncmp(s,"type=", 5)) { - i=index(s, '"'); - if (i) { - s=i+1; - i=index(s, '"'); - if (i) - *i='\0'; - } - } - if (rmen) { - i=s; - n=s; - men=rmen; - while ((i=index(n, '/'))) { - strcpy(buffer2, s); - buffer2[i-s]='\0'; - if (!(nmen=g_hash_table_lookup(h, buffer2))) { - nmen=menu_add(men, buffer2+(n-s), menu_type_submenu, NULL, NULL, NULL); - g_hash_table_insert(h, g_strdup(buffer2), nmen); - } - n=i+1; - men=nmen; - } - menu_add(men, n, menu_type_menu, navit_set_destination_menu, this_, cn); - } - } + while (! feof(f) && (pos=parse_line(f, buffer, &name, &c)) > -3) { + if (pos > 0) { + navit_add_menu_destinations(this_, name, offset, rmen, h, callback); flag=1; - } + } else + flag=0; + offset=ftell(f); } fclose(f); if (route && flag) route_set_destination(route, &c); } - g_hash_table_destroy(h); } void navit_add_menu_former_destinations(struct navit *this_, struct menu *men, struct route *route) { - navit_add_menu_destinations(this_, "destination.txt", men ? menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL) : NULL, route); + if (men) + this_->destinations=menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL); + else + this_->destinations=NULL; + navit_add_menu_destinations_from_file(this_, "destination.txt", this_->destinations, NULL, route, navit_set_destination_from_destination); } void navit_add_menu_bookmarks(struct navit *this_, struct menu *men) { - navit_add_menu_destinations(this_, "bookmark.txt", men ? menu_add(men, "Bookmarks", menu_type_submenu, NULL, NULL, NULL) : NULL, NULL); + if (men) + this_->bookmarks=menu_add(men, "Bookmarks", menu_type_submenu, NULL, NULL, NULL); + else + this_->bookmarks=NULL; + navit_add_menu_destinations_from_file(this_, "bookmark.txt", this_->bookmarks, this_->bookmarks_hash, NULL, navit_set_destination_from_bookmark); } static void diff --git a/navit.h b/navit.h index 0eeb1abd..e1988a1e 100644 --- a/navit.h +++ b/navit.h @@ -36,7 +36,6 @@ void navit_add_menu_layout(struct navit *this_, struct menu *men); void navit_add_menu_projections(struct navit *this_, struct menu *men); void navit_add_menu_projection(struct navit *this_, struct menu *men); void navit_add_menu_maps(struct navit *this_, struct mapset *ms, struct menu *men); -void navit_add_menu_destinations(struct navit *this_, char *file, struct menu *rmen, struct route *route); void navit_add_menu_former_destinations(struct navit *this_, struct menu *men, struct route *route); void navit_add_menu_bookmarks(struct navit *this_, struct menu *men); void navit_add_menu_vehicles(struct navit *this_, struct menu *men); diff --git a/route.c b/route.c index d44dfb6a..ec5ce24b 100644 --- a/route.c +++ b/route.c @@ -198,7 +198,7 @@ route_set_speed(struct route *this, enum item_type type, int value) int route_contains(struct route *this, struct item *item) { - if (! this->path2 || !item_hash_lookup(this->path2->path_hash, item)) + if (! this->path2 || !this->path2->path_hash || !item_hash_lookup(this->path2->path_hash, item)) return 0; return 1; } @@ -207,6 +207,8 @@ static void route_path_update(struct route *this) { route_path_destroy(this->path2); + if (! this->pos || ! this->dst) + return; if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst, this->speedlist))) { profile(0,NULL); route_graph_update(this); @@ -332,9 +334,9 @@ route_set_destination(struct route *this, struct coord *dst) profile(0,NULL); if (this->dst) route_info_free(this->dst); - this->dst=route_find_nearest_street(this->ms, dst); - if (! this->dst || ! this->pos) - return; + this->dst=NULL; + if (dst) + this->dst=route_find_nearest_street(this->ms, dst); profile(1,"find_nearest_street"); route_graph_destroy(this->graph); diff --git a/vehicle.c b/vehicle.c index cf3ff248..9b0c435e 100644 --- a/vehicle.c +++ b/vehicle.c @@ -365,7 +365,7 @@ vehicle_udp_recv(struct vehicle *this) struct packet pkt; int size; - dbg(2,"enter this=%p",this); + dbg(2,"enter this=%p\n",this); size=recv(this->fd, &pkt, 15, 0); if (pkt.magic == this->magic) { dbg(3,"magic 0x%x size=%d\n", pkt.magic, size); -- cgit v1.2.1 From 729103719a5a2a192428dd2474279e691279dd0c Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 22 Jul 2007 15:37:55 +0000 Subject: Added roadbook button git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@369 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- callback.c | 89 ++++++++++++++++++++++++++---------------------- callback.h | 14 +++++++- gui/gtk/datawindow.c | 7 ++++ gui/gtk/gui_gtk_action.c | 20 +++++++++++ navit.c | 14 +++++--- navit.h | 2 ++ route.c | 2 +- 7 files changed, 101 insertions(+), 47 deletions(-) diff --git a/callback.c b/callback.c index 49d2cd04..8985b8d8 100644 --- a/callback.c +++ b/callback.c @@ -67,54 +67,61 @@ callback_list_remove_destroy(struct callback_list *l, struct callback *cb) } void -callback_list_call(struct callback_list *l, int pcount, void **p) +callback_call(struct callback *cb, int pcount, void **p) { + int i; void *pf[8]; - struct callback *cb; + if (cb->pcount + pcount <= 8) { + dbg(1,"cb->pcount=%d %p pcount=%d %p\n", cb->pcount, cb->p[0], pcount, p[0]); + for (i = 0 ; i < cb->pcount ; i++) + pf[i]=cb->p[i]; + for (i = 0 ; i < pcount ; i++) + pf[i+cb->pcount]=p[i]; + switch (cb->pcount+pcount) { + case 8: + cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6],pf[7]); + break; + case 7: + cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6]); + break; + case 6: + cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5]); + break; + case 5: + cb->func(pf[0],pf[1],pf[2],pf[3],pf[4]); + break; + case 4: + cb->func(pf[0],pf[1],pf[2],pf[3]); + break; + case 3: + cb->func(pf[0],pf[1],pf[2]); + break; + case 2: + cb->func(pf[0],pf[1]); + break; + case 1: + cb->func(pf[0]); + break; + case 0: + cb->func(); + break; + } + } else { + g_warning("too many parameters for callback\n"); + } +} + + +void +callback_list_call(struct callback_list *l, int pcount, void **p) +{ GList *cbi; - int i; + struct callback *cb; cbi=l->list; while (cbi) { cb=cbi->data; - if (cb->pcount + pcount <= 8) { - dbg(1,"cb->pcount=%d %p pcount=%d %p\n", cb->pcount, cb->p[0], pcount, p[0]); - for (i = 0 ; i < cb->pcount ; i++) - pf[i]=cb->p[i]; - for (i = 0 ; i < pcount ; i++) - pf[i+cb->pcount]=p[i]; - switch (cb->pcount+pcount) { - case 8: - cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6],pf[7]); - break; - case 7: - cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5],pf[6]); - break; - case 6: - cb->func(pf[0],pf[1],pf[2],pf[3],pf[4],pf[5]); - break; - case 5: - cb->func(pf[0],pf[1],pf[2],pf[3],pf[4]); - break; - case 4: - cb->func(pf[0],pf[1],pf[2],pf[3]); - break; - case 3: - cb->func(pf[0],pf[1],pf[2]); - break; - case 2: - cb->func(pf[0],pf[1]); - break; - case 1: - cb->func(pf[0]); - break; - case 0: - cb->func(); - break; - } - } else { - g_warning("too many parameters for callback\n"); - } + callback_call(cb, pcount, p); cbi=g_list_next(cbi); } diff --git a/callback.h b/callback.h index bf38a783..aad5c4b1 100644 --- a/callback.h +++ b/callback.h @@ -10,8 +10,10 @@ void callback_list_add(struct callback_list *l, struct callback *cb); struct callback *callback_list_add_new(struct callback_list *l, void (*func)(void), int pcount, void **p); void callback_list_remove(struct callback_list *l, struct callback *cb); void callback_list_remove_destroy(struct callback_list *l, struct callback *cb); +void callback_call(struct callback *cb, int pcount, void **p); void callback_list_call(struct callback_list *l, int pcount, void **p); void callback_list_destroy(struct callback_list *l); +/* end of prototypes */ static inline struct callback *callback_new_0(void (*func)(void)) { @@ -25,6 +27,17 @@ static inline struct callback *callback_new_1(void (*func)(void), void *p1) return callback_new(func, 1, p); } +static inline void callback_call_0(struct callback *cb) +{ + callback_call(cb, 0, NULL); +} + +static inline void callback_list_call_0(struct callback_list *l) +{ + callback_list_call(l, 0, NULL); +} + + static inline void callback_list_call_1(struct callback_list *l, void *p1) { void *p[1]; @@ -41,7 +54,6 @@ static inline void callback_list_call_2(struct callback_list *l, void *p1, void } #define callback_cast(x) (void (*)(void))(x) -/* end of prototypes */ #ifdef __cplusplus } #endif diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c index a505675e..ade86df6 100644 --- a/gui/gtk/datawindow.c +++ b/gui/gtk/datawindow.c @@ -88,6 +88,12 @@ gui_gtk_datawindow_mode(struct datawindow_priv *win, int start) } } +static void +gui_gtk_datawindow_delete(GtkWidget *widget, GdkEvent *event, struct datawindow_priv *win) +{ + callback_call_0(win->close); +} + static struct datawindow_methods gui_gtk_datawindow_meth = { gui_gtk_datawindow_destroy, @@ -116,6 +122,7 @@ gui_gtk_datawindow_new(struct gui_priv *gui, char *name, struct callback *click, win->close=close; if (gui) gtk_window_set_transient_for(GTK_WINDOW((GtkWidget *)(win->window)), GTK_WINDOW(gui->win)); + g_signal_connect(G_OBJECT(win->window), "delete-event", G_CALLBACK(gui_gtk_datawindow_delete), win); gtk_widget_show_all(win->window); return win; return NULL; diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 143b3744..6ed61d2c 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -45,6 +45,12 @@ refresh_action(GtkWidget *w, struct navit *nav, void *dummy) navit_draw(nav); } +static void +roadbook_action(GtkWidget *w, struct navit *nav, void *dummy) +{ + navit_window_roadbook_new(nav); +} + static void cursor_action(GtkWidget *w, struct navit *nav, void *dummy) { @@ -54,6 +60,15 @@ cursor_action(GtkWidget *w, struct navit *nav, void *dummy) #endif } +static void +tracking_action(GtkWidget *w, struct navit *nav, void *dummy) +{ + navit_toggle_tracking(nav); +#if 0 + ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); +#endif +} + static void orient_north_action(GtkWidget *w, struct navit *nav, void *dummy) { @@ -165,6 +180,7 @@ static GtkActionEntry entries[] = { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, _n("ZoomOut"), NULL, NULL, G_CALLBACK(zoom_out_action) }, { "ZoomInAction", GTK_STOCK_ZOOM_IN, _n("ZoomIn"), NULL, NULL, G_CALLBACK(zoom_in_action) }, { "RefreshAction", GTK_STOCK_REFRESH, _n("Refresh"), NULL, NULL, G_CALLBACK(refresh_action) }, + { "RoadbookAction", GTK_STOCK_JUSTIFY_FILL, _n("Roadbook"), NULL, NULL, G_CALLBACK(roadbook_action) }, { "InfoAction", GTK_STOCK_INFO, _n("Info"), NULL, NULL, G_CALLBACK(info_action) }, { "DestinationAction", "flag_icon", _n("Destination"), NULL, NULL, G_CALLBACK(destination_action) }, { "RouteClearAction", NULL, _n("Clear"), NULL, NULL, G_CALLBACK(route_clear_action) }, @@ -177,6 +193,7 @@ static guint n_entries = G_N_ELEMENTS (entries); static GtkToggleActionEntry toggleentries[] = { { "CursorAction", "cursor_icon",_n("Cursor"), NULL, NULL, G_CALLBACK(cursor_action),TRUE }, + { "TrackingAction", NULL ,_n("Tracking"), NULL, NULL, G_CALLBACK(tracking_action),TRUE }, { "OrientationAction", "orientation_icon", _n("Orientation"), NULL, NULL, G_CALLBACK(orient_north_action),FALSE } }; @@ -325,7 +342,9 @@ static char layout[] = \ \ \ + \ \ + \ \ \
\ @@ -354,6 +373,7 @@ static char layout[] = \ \ \ + \ \ \ \ diff --git a/navit.c b/navit.c index 8dc59634..dc423065 100644 --- a/navit.c +++ b/navit.c @@ -61,11 +61,11 @@ struct navit { struct navigation *navigation; struct speech *speech; struct tracking *tracking; - struct map_flags *flags; int ready; struct window *win; struct displaylist *displaylist; int cursor_flag; + int tracking_flag; GList *vehicles; struct navit_vehicle *vehicle; struct callback_list *vehicle_cbl; @@ -189,11 +189,11 @@ navit_new(const char *ui, const char *graphics, struct coord *center, enum proje this_->bookmarks_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); this_->cursor_flag=1; + this_->tracking_flag=1; this_->trans=transform_new(); transform_set_projection(this_->trans, pro); transform_setup(this_->trans, center, zoom, 0); - /* this_->flags=g_new0(struct map_flags, 1); */ this_->displaylist=graphics_displaylist_new(); this_->gui=gui_new(this_, ui, 792, 547); if (! this_->gui) { @@ -573,7 +573,7 @@ navit_window_roadbook_update(struct navit *this_) datawindow_mode(this_->roadbook_window, 0); } -static void +void navit_window_roadbook_new(struct navit *this_) { this_->roadbook_callback=callback_new_1(callback_cast(navit_window_roadbook_update), this_); @@ -768,6 +768,12 @@ navit_toggle_cursor(struct navit *this_) this_->cursor_flag=1-this_->cursor_flag; } +void +navit_toggle_tracking(struct navit *this_) +{ + this_->tracking_flag=1-this_->tracking_flag; +} + static void navit_cursor_offscreen(struct navit *this_, struct cursor *cursor) { @@ -792,7 +798,7 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) if (this_->pid && speed > 2) kill(this_->pid, SIGWINCH); - if (this_->tracking) { + if (this_->tracking && this_->tracking_flag) { struct coord c=*cursor_c; if (tracking_update(this_->tracking, &c, dir)) { cursor_c=&c; diff --git a/navit.h b/navit.h index e1988a1e..7e79aa46 100644 --- a/navit.h +++ b/navit.h @@ -41,10 +41,12 @@ void navit_add_menu_bookmarks(struct navit *this_, struct menu *men); void navit_add_menu_vehicles(struct navit *this_, struct menu *men); void navit_add_menu_vehicle(struct navit *this_, struct menu *men); void navit_speak(struct navit *this_); +void navit_window_roadbook_new(struct navit *this_); void navit_init(struct navit *this_); void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); void navit_toggle_cursor(struct navit *this_); +void navit_toggle_tracking(struct navit *this_); void navit_set_position(struct navit *this_, struct coord *c); struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow); void navit_add_vehicle_cb(struct navit *this_, struct callback *cb); diff --git a/route.c b/route.c index ec5ce24b..65dd0c3a 100644 --- a/route.c +++ b/route.c @@ -224,7 +224,7 @@ route_set_position(struct route *this, struct coord *pos) if (this->pos) route_info_free(this->pos); this->pos=route_find_nearest_street(this->ms, pos); - dbg(0,"this->pos=%p\n", this->pos); + dbg(1,"this->pos=%p\n", this->pos); if (! this->pos) return; if (this->dst) -- cgit v1.2.1 From ae22f37ffa8b63cbb34833d9d6a36649cadf5297 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 22 Jul 2007 18:04:31 +0000 Subject: Improved items window git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@373 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- callback.c | 11 +++- callback.h | 15 ++++++ gui/gtk/datawindow.c | 40 +++++++++++--- gui/gtk/gui_gtk_action.c | 4 +- navit.c | 133 ++++++++++++++++++++++++++++++++++++++--------- xmlconfig.c | 30 +++++++++++ 6 files changed, 198 insertions(+), 35 deletions(-) diff --git a/callback.c b/callback.c index 8985b8d8..ea98c508 100644 --- a/callback.c +++ b/callback.c @@ -71,8 +71,15 @@ callback_call(struct callback *cb, int pcount, void **p) { int i; void *pf[8]; + if (! cb) + return; if (cb->pcount + pcount <= 8) { - dbg(1,"cb->pcount=%d %p pcount=%d %p\n", cb->pcount, cb->p[0], pcount, p[0]); + dbg(1,"cb->pcount=%d\n", cb->pcount); + if (cb->pcount && cb->p) + dbg(1,"cb->p[0]=%p\n", cb->p[0]); + dbg(1,"pcount=%d\n", pcount); + if (pcount && p) + dbg(1,"p[0]=%p\n", p[0]); for (i = 0 ; i < cb->pcount ; i++) pf[i]=cb->p[i]; for (i = 0 ; i < pcount ; i++) @@ -107,7 +114,7 @@ callback_call(struct callback *cb, int pcount, void **p) break; } } else { - g_warning("too many parameters for callback\n"); + g_warning("too many parameters for callback (%d+%d)\n", cb->pcount, pcount); } } diff --git a/callback.h b/callback.h index aad5c4b1..c3fe4017 100644 --- a/callback.h +++ b/callback.h @@ -27,11 +27,26 @@ static inline struct callback *callback_new_1(void (*func)(void), void *p1) return callback_new(func, 1, p); } +static inline struct callback *callback_new_2(void (*func)(void), void *p1, void *p2) +{ + void *p[2]; + p[0]=p1; + p[1]=p2; + return callback_new(func, 2, p); +} + static inline void callback_call_0(struct callback *cb) { callback_call(cb, 0, NULL); } +static inline void callback_call_1(struct callback *cb, void *p1) +{ + void *p[1]; + p[0]=p1; + callback_call(cb, 1, p); +} + static inline void callback_list_call_0(struct callback_list *l) { callback_list_call(l, 0, NULL); diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c index ade86df6..f8fc2677 100644 --- a/gui/gtk/datawindow.c +++ b/gui/gtk/datawindow.c @@ -2,6 +2,7 @@ #include #include #include +#include "debug.h" #include "callback.h" #include "param.h" #include "data_window.h" @@ -22,6 +23,29 @@ gui_gtk_datawindow_destroy(struct datawindow_priv *win) return; } +static GValue value; +static void +select_row(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, struct datawindow_priv *win) +{ + char *cols[20]; + GtkTreeIter iter; + GtkTreeModel *model; + int i; + + dbg(0,"win=%p\n", win); + + model=gtk_tree_view_get_model(tree); + gtk_tree_model_get_iter(model, &iter, path); + + for (i=0;iclick, cols); +} + static void gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, int count) { @@ -38,20 +62,22 @@ gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, in gtk_widget_show_all(GTK_WIDGET(win->window)); /* add column names to treeview */ for(i=0;itreeview),-1,param[i].name, + if (param[i].name) { + cell=gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (win->treeview),-1,param[i].name, cell,"text",i, NULL); + } } #if 0 g_signal_connect(G_OBJECT(win->treeview), "click-column", G_CALLBACK(click_column), NULL); - g_signal_connect(G_OBJECT(win->treeview), "row-activated", G_CALLBACK(select_row), win); #endif + g_signal_connect(G_OBJECT(win->treeview), "row-activated", G_CALLBACK(select_row), win); } /* find data storage and create a new one if none is there */ if (gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview)) == NULL) { for(i=0;iliststore,&iter,i,atoi(param[i].value),-1); } else { utf8=g_locale_to_utf8(param[i].value,-1,NULL,NULL,NULL); @@ -88,10 +114,12 @@ gui_gtk_datawindow_mode(struct datawindow_priv *win, int start) } } -static void +static gboolean gui_gtk_datawindow_delete(GtkWidget *widget, GdkEvent *event, struct datawindow_priv *win) { callback_call_0(win->close); + + return FALSE; } diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 6ed61d2c..f84eaeed 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -372,7 +372,7 @@ static char layout[] = \ \ \ - \ + \ \ \ \ @@ -402,6 +402,8 @@ add_menu(struct menu_priv *menu, struct menu_methods *meth, char *name, enum men *meth=menu_methods; if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Route")) { dynname=g_strdup("Route"); + } else if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Data")) { + dynname=g_strdup("Data"); } else { dynname=g_strdup_printf("%d", menu->gui->dyn_counter++); if (type == menu_type_toggle) diff --git a/navit.c b/navit.c index dc423065..9bb1dd25 100644 --- a/navit.c +++ b/navit.c @@ -67,6 +67,7 @@ struct navit { int cursor_flag; int tracking_flag; GList *vehicles; + GList *windows_items; struct navit_vehicle *vehicle; struct callback_list *vehicle_cbl; int pid; @@ -573,12 +574,20 @@ navit_window_roadbook_update(struct navit *this_) datawindow_mode(this_->roadbook_window, 0); } +void +navit_window_roadbook_destroy(struct navit *this_) +{ + dbg(0, "enter\n"); + navigation_unregister_callback(this_->navigation, navigation_mode_long, this_->roadbook_callback); + this_->roadbook_window=NULL; + this_->roadbook_callback=NULL; +} void navit_window_roadbook_new(struct navit *this_) { this_->roadbook_callback=callback_new_1(callback_cast(navit_window_roadbook_update), this_); navigation_register_callback(this_->navigation, navigation_mode_long, this_->roadbook_callback); - this_->roadbook_window=gui_datawindow_new(this_->gui, "Roadbook", NULL, NULL); + this_->roadbook_window=gui_datawindow_new(this_->gui, "Roadbook", NULL, callback_new_1(callback_cast(navit_window_roadbook_destroy), this_)); } static void @@ -609,10 +618,32 @@ get_direction(char *buffer, int angle, int mode) } } +struct navit_window_items { + struct datawindow *win; + struct callback *click; + char *name; + int distance; + GHashTable *hash; + GList *list; +}; + static void -navit_window_items_new(struct navit *this_) +navit_window_items_click(struct navit *this_, struct navit_window_items *nwi, char **col) +{ + struct coord c; + char *description; + + dbg(0,"enter col=%s,%s,%s,%s,%s\n", col[0], col[1], col[2], col[3], col[4]); + sscanf(col[4], "0x%x,0x%x", &c.x, &c.y); + dbg(0,"0x%x,0x%x\n", c.x, c.y); + description=g_strdup_printf("%s %s", nwi->name, col[3]); + navit_set_destination(this_, &c, description); + g_free(description); +} + +static void +navit_window_items_open(struct menu *men, struct navit *this_, struct navit_window_items *nwi) { - struct datawindow *win; struct map_selection sel; struct coord c,*center; struct mapset_handle *h; @@ -620,35 +651,40 @@ navit_window_items_new(struct navit *this_) struct map_rect *mr; struct item *item; struct attr attr; - GHashTable *hash; - int idist,dist=100000; - enum item_type type1,type2,type3; - struct param_list param[4]; + int idist,dist; + struct param_list param[5]; char distbuf[32]; char dirbuf[32]; - + char coordbuf[64]; + + dbg(0, "distance=%d\n", nwi->distance); + if (nwi->distance == -1) + dist=40000000; + else + dist=nwi->distance*1000; param[0].name="Distance"; param[1].name="Direction"; param[2].name="Type"; param[3].name="Name"; + param[4].name=NULL; sel.next=NULL; +#if 0 sel.order[layer_town]=18; sel.order[layer_street]=18; sel.order[layer_poly]=18; +#else + sel.order[layer_town]=0; + sel.order[layer_street]=0; + sel.order[layer_poly]=0; +#endif center=transform_center(this_->trans); sel.rect.lu.x=center->x-dist; sel.rect.lu.y=center->y+dist; sel.rect.rl.x=center->x+dist; sel.rect.rl.y=center->y-dist; - hash=g_hash_table_new(g_int_hash, g_int_equal); - type1=type_bookmark; - g_hash_table_insert(hash, &type1, (void *)1); - type2=type_poi_camping; - g_hash_table_insert(hash, &type2, (void *)1); - type3=type_roadbook; - g_hash_table_insert(hash, &type3, (void *)1); dbg(2,"0x%x,0x%x - 0x%x,0x%x\n", sel.rect.lu.x, sel.rect.lu.y, sel.rect.rl.x, sel.rect.rl.y); - win=gui_datawindow_new(this_->gui, "Itemlist", NULL, NULL); + nwi->click=callback_new_2(navit_window_items_click, this_, nwi); + nwi->win=gui_datawindow_new(this_->gui, nwi->name, nwi->click, NULL); h=mapset_open(navit_get_mapset(this_)); while ((m=mapset_next(h, 1))) { dbg(2,"m=%p %s\n", m, map_get_filename(m)); @@ -656,17 +692,21 @@ navit_window_items_new(struct navit *this_) dbg(2,"mr=%p\n", mr); while ((item=map_rect_get_item(mr))) { if (item_coord_get(item, &c, 1)) { - if (coord_rect_contains(&sel.rect, &c) && g_hash_table_lookup(hash, &item->type)) { + if (coord_rect_contains(&sel.rect, &c) && g_hash_table_lookup(nwi->hash, &item->type)) { if (! item_attr_get(item, attr_label, &attr)) attr.u.str=NULL; - idist=transform_distance(center, &c); - get_direction(dirbuf, transform_get_angle_delta(center, &c, 0), 2); - param[0].value=distbuf; - param[1].value=dirbuf; - param[2].value=item_to_name(item->type); - sprintf(distbuf,"%d", idist/1000); - param[3].value=attr.u.str; - datawindow_add(win, param, 4); + idist=transform_distance(center, &c); + if (idist < dist) { + get_direction(dirbuf, transform_get_angle_delta(center, &c, 0), 1); + param[0].value=distbuf; + param[1].value=dirbuf; + param[2].value=item_to_name(item->type); + sprintf(distbuf,"%d", idist/1000); + param[3].value=attr.u.str; + sprintf(coordbuf, "0x%x,0x%x", c.x, c.y); + param[4].value=coordbuf; + datawindow_add(nwi->win, param, 5); + } /* printf("gefunden %s %s %d\n",item_to_name(item->type), attr.u.str, idist/1000); */ } if (item->type >= type_line) @@ -676,9 +716,44 @@ navit_window_items_new(struct navit *this_) map_rect_destroy(mr); } mapset_close(h); - g_hash_table_destroy(hash); } +struct navit_window_items * +navit_window_items_new(char *name, int distance) +{ + struct navit_window_items *nwi=g_new0(struct navit_window_items, 1); + nwi->name=g_strdup(name); + nwi->distance=distance; + nwi->hash=g_hash_table_new(g_int_hash, g_int_equal); + + return nwi; +} + +void +navit_window_items_add_item(struct navit_window_items *nwi, enum item_type type) +{ + nwi->list=g_list_prepend(nwi->list, (void *)type); + g_hash_table_insert(nwi->hash, &nwi->list->data, (void *)1); +} + +void +navit_add_window_items(struct navit *this_, struct navit_window_items *nwi) +{ + this_->windows_items=g_list_append(this_->windows_items, nwi); +} + +void +navit_add_menu_windows_items(struct navit *this_, struct menu *men) +{ + struct navit_window_items *nwi; + GList *l; + l=this_->windows_items; + while (l) { + nwi=l->data; + menu_add(men, nwi->name, menu_type_menu, navit_window_items_open, this_, nwi); + l=g_list_next(l); + } +} void navit_init(struct navit *this_) @@ -716,6 +791,12 @@ navit_init(struct navit *this_) #if 0 #endif } + if (this_->menubar) { + men=menu_add(this_->menubar, "Data", menu_type_submenu, NULL, NULL, NULL); + if (men) { + navit_add_menu_windows_items(this_, men); + } + } global_navit=this_; #if 0 navit_window_roadbook_new(this_); diff --git a/xmlconfig.c b/xmlconfig.c index f102786f..0eff60ba 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -214,6 +214,35 @@ xmlconfig_vehicle(struct xmlstate *state) return 1; } +static int +xmlconfig_window_items(struct xmlstate *state) +{ + int distance=-1; + enum item_type itype; + const char *name=find_attribute(state, "name", 1); + const char *value=find_attribute(state, "distance", 0); + const char *type=find_attribute(state, "type", 1); + char *tok,*str,*type_str,*saveptr; + if (! name || !type) + return 0; + if (value) + distance=convert_number(value); + state->element_object = navit_window_items_new(name, distance); + type_str=g_strdup(type); + str=type_str; + while ((tok=strtok_r(str, ",", &saveptr))) { + itype=item_from_name(tok); + navit_window_items_add_item(state->element_object, itype); + str=NULL; + } + g_free(type_str); + + navit_add_window_items(state->parent->element_object, state->element_object); + + return 1; +} + + static int xmlconfig_tracking(struct xmlstate *state) { @@ -511,6 +540,7 @@ struct element_func { { "route", "navit", xmlconfig_route}, { "speed", "route", xmlconfig_speed}, { "vehicle", "navit", xmlconfig_vehicle}, + { "window_items", "navit", xmlconfig_window_items}, { "plugins", NULL, xmlconfig_plugins}, { "plugin", "plugins", xmlconfig_plugin}, {}, -- cgit v1.2.1 From ccee69c285bb64841f7ccc1017d1301abe7ea251 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 22 Jul 2007 20:13:21 +0000 Subject: Improved datawindow git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@374 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/datawindow.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c index f8fc2677..7a6cce89 100644 --- a/gui/gtk/datawindow.c +++ b/gui/gtk/datawindow.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "debug.h" #include "callback.h" @@ -58,8 +59,10 @@ gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, in if (! win->treeview) { win->treeview=gtk_tree_view_new(); gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(win->scrolled_window),win->treeview); + gtk_container_add(GTK_CONTAINER(win->scrolled_window), win->treeview); gtk_widget_show_all(GTK_WIDGET(win->window)); + gtk_widget_grab_focus(GTK_WIDGET(win->treeview)); + /* add column names to treeview */ for(i=0;itype != GDK_KEY_PRESS) + return FALSE; + if (event->keyval == GDK_Cancel) { + gui_gtk_datawindow_delete(widget, event, win); + gtk_widget_destroy(win->window); + } + return FALSE; +} + static struct datawindow_methods gui_gtk_datawindow_meth = { gui_gtk_datawindow_destroy, @@ -142,9 +157,9 @@ gui_gtk_datawindow_new(struct gui_priv *gui, char *name, struct callback *click, win->scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win->scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(win->window), win->scrolled_window); - + g_signal_connect(G_OBJECT(win->window), "key-press-event", G_CALLBACK(keypress), win); win->treeview=NULL; win->click=click; win->close=close; -- cgit v1.2.1 From 81621aa4c397e523234a705c65e5df94fe77ec11 Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 9 Aug 2007 15:02:56 +0000 Subject: Fixed 64 bit usage git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@377 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/block.c | 10 +++++----- data/mg/street.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/mg/block.c b/data/mg/block.c index 93c2fb11..e438e575 100644 --- a/data/mg/block.c +++ b/data/mg/block.c @@ -7,14 +7,14 @@ int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem; struct block_index_item { - unsigned long blocknum; - unsigned long blocks; + unsigned int blocknum; + unsigned int blocks; }; struct block_index { - unsigned long blocks; - unsigned long size; - unsigned long next; + unsigned int blocks; + unsigned int size; + unsigned int next; struct block_index_item list[0]; }; diff --git a/data/mg/street.c b/data/mg/street.c index 45dbabc0..94e0b5fe 100644 --- a/data/mg/street.c +++ b/data/mg/street.c @@ -445,7 +445,7 @@ street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, struct street_name_index { int block; unsigned short country; - long town_assoc; + int town_assoc; char name[0]; } __attribute__((packed)); -- cgit v1.2.1 From 8262f42560663f96fad6f148fc76c4f3d8a48a20 Mon Sep 17 00:00:00 2001 From: horwitz Date: Fri, 10 Aug 2007 12:07:13 +0000 Subject: add fullscreen option to display menu of main window git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@378 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 61 ++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index f84eaeed..7932d400 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -28,61 +28,70 @@ struct menu_priv { /* Create callbacks that implement our Actions */ static void -zoom_in_action(GtkWidget *w, struct navit *nav, void *dummy) +zoom_in_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_zoom_in(nav, 2); + navit_zoom_in(gui->nav, 2); } static void -zoom_out_action(GtkWidget *w, struct navit *nav, void *dummy) +zoom_out_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_zoom_out(nav, 2); + navit_zoom_out(gui->nav, 2); } static void -refresh_action(GtkWidget *w, struct navit *nav, void *dummy) +refresh_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_draw(nav); + navit_draw(gui->nav); } static void -roadbook_action(GtkWidget *w, struct navit *nav, void *dummy) +roadbook_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_window_roadbook_new(nav); + navit_window_roadbook_new(gui->nav); } static void -cursor_action(GtkWidget *w, struct navit *nav, void *dummy) +cursor_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_toggle_cursor(nav); + navit_toggle_cursor(gui->nav); #if 0 ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); #endif } static void -tracking_action(GtkWidget *w, struct navit *nav, void *dummy) +tracking_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_toggle_tracking(nav); + navit_toggle_tracking(gui->nav); #if 0 ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); #endif } static void -orient_north_action(GtkWidget *w, struct navit *nav, void *dummy) +orient_north_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { #if 0 ac->gui->co->flags->orient_north=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); #endif } +static void +window_fullscreen_action(GtkWidget *w, struct gui_priv *gui, void *dummy) +{ + if(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w))) + gtk_window_fullscreen(GTK_WINDOW(gui->win)); + else + gtk_window_unfullscreen(GTK_WINDOW(gui->win)); +} + #include #include "point.h" #include "transform.h" static void -info_action(GtkWidget *w, struct navit *nav, void *dummy) +info_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { char buffer[512]; int mw,mh; @@ -90,7 +99,7 @@ info_action(GtkWidget *w, struct navit *nav, void *dummy) struct point p; struct transformation *t; - t=navit_get_trans(nav); + t=navit_get_trans(gui->nav); transform_get_size(t, &mw, &mh); p.x=0; p.y=0; @@ -106,22 +115,22 @@ info_action(GtkWidget *w, struct navit *nav, void *dummy) static void -route_clear_action(GtkWidget *w, struct navit *nav, void *dummy) +route_clear_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_set_destination(nav, NULL, NULL); + navit_set_destination(gui->nav, NULL, NULL); } static void -destination_action(GtkWidget *w, struct navit *nav, void *dummy) +destination_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { - destination_address(nav); + destination_address(gui->nav); } static void -quit_action (GtkWidget *w, struct navit *nav, void *dummy) +quit_action (GtkWidget *w, struct gui_priv *gui, void *dummy) { - navit_destroy(nav); + navit_destroy(gui->nav); } static void @@ -194,7 +203,8 @@ static GtkToggleActionEntry toggleentries[] = { { "CursorAction", "cursor_icon",_n("Cursor"), NULL, NULL, G_CALLBACK(cursor_action),TRUE }, { "TrackingAction", NULL ,_n("Tracking"), NULL, NULL, G_CALLBACK(tracking_action),TRUE }, - { "OrientationAction", "orientation_icon", _n("Orientation"), NULL, NULL, G_CALLBACK(orient_north_action),FALSE } + { "OrientationAction", "orientation_icon", _n("Orientation"), NULL, NULL, G_CALLBACK(orient_north_action),FALSE }, + { "FullscreenAction",GTK_STOCK_FULLSCREEN, _n("Fullscreen"), NULL, NULL, G_CALLBACK(window_fullscreen_action), FALSE } }; static guint n_toggleentries = G_N_ELEMENTS (toggleentries); @@ -345,6 +355,7 @@ static char layout[] = \ \ \ + \ \ \
\ @@ -501,10 +512,10 @@ gui_gtk_ui_new (struct gui_priv *this, struct menu_methods *meth, char *path, in gtk_action_group_set_translation_domain(this->base_group,"navit"); gtk_action_group_set_translation_domain(this->debug_group,"navit"); gtk_action_group_set_translation_domain(this->dyn_group,"navit"); - gtk_action_group_add_actions (this->base_group, entries, n_entries, this->nav); - gtk_action_group_add_toggle_actions (this->base_group, toggleentries, n_toggleentries, this->nav); + gtk_action_group_add_actions (this->base_group, entries, n_entries, this); + gtk_action_group_add_toggle_actions (this->base_group, toggleentries, n_toggleentries, this); gtk_ui_manager_insert_action_group (this->menu_manager, this->base_group, 0); - gtk_action_group_add_actions (this->debug_group, debug_entries, n_debug_entries, this->nav); + gtk_action_group_add_actions (this->debug_group, debug_entries, n_debug_entries, this); gtk_ui_manager_insert_action_group (this->menu_manager, this->debug_group, 0); gtk_ui_manager_add_ui_from_string (this->menu_manager, layout, strlen(layout), &error); gtk_ui_manager_insert_action_group (this->menu_manager, this->dyn_group, 0); -- cgit v1.2.1 From c06a32920a7e8e11c1bd19867c237a9dec917e1c Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 11 Aug 2007 08:02:47 +0000 Subject: Moved poi_geodownload to data and made it working with the new api git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@379 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- attr.c | 46 ++ attr.h | 3 + attr_def.h | 1 + country.c | 1 - data/Makefile.am | 2 +- data/mg/map.c | 4 +- data/mg/mg.h | 2 +- data/poi_geodownload/Makefile.am | 6 + data/poi_geodownload/libmdb/Makefile.am | 13 + data/poi_geodownload/libmdb/backend.c | 301 ++++++++ data/poi_geodownload/libmdb/catalog.c | 138 ++++ data/poi_geodownload/libmdb/data.c | 856 +++++++++++++++++++++++ data/poi_geodownload/libmdb/dump.c | 39 ++ data/poi_geodownload/libmdb/file.c | 376 ++++++++++ data/poi_geodownload/libmdb/iconv.c | 63 ++ data/poi_geodownload/libmdb/include/mdbtools.h | 536 +++++++++++++++ data/poi_geodownload/libmdb/index.c | 905 +++++++++++++++++++++++++ data/poi_geodownload/libmdb/kkd.c | 149 ++++ data/poi_geodownload/libmdb/like.c | 78 +++ data/poi_geodownload/libmdb/map.c | 133 ++++ data/poi_geodownload/libmdb/mem.c | 50 ++ data/poi_geodownload/libmdb/money.c | 139 ++++ data/poi_geodownload/libmdb/options.c | 86 +++ data/poi_geodownload/libmdb/props.c | 127 ++++ data/poi_geodownload/libmdb/sargs.c | 273 ++++++++ data/poi_geodownload/libmdb/stats.c | 74 ++ data/poi_geodownload/libmdb/table.c | 368 ++++++++++ data/poi_geodownload/libmdb/worktable.c | 99 +++ data/poi_geodownload/libmdb/write.c | 878 ++++++++++++++++++++++++ data/poi_geodownload/poi_geodownload.c | 661 ++++++++++++++++++ data/textfile/textfile.c | 2 +- graphics.c | 4 +- gui/gtk/destination.c | 3 +- item.c | 1 - item.h | 3 +- item_def.h | 4 + map.c | 6 +- map.h | 2 +- mapset.c | 2 +- navit.c | 2 +- plugin_def.h | 3 +- search.c | 1 - xmlconfig.c | 31 +- 43 files changed, 6451 insertions(+), 20 deletions(-) create mode 100644 data/poi_geodownload/Makefile.am create mode 100644 data/poi_geodownload/libmdb/Makefile.am create mode 100644 data/poi_geodownload/libmdb/backend.c create mode 100644 data/poi_geodownload/libmdb/catalog.c create mode 100644 data/poi_geodownload/libmdb/data.c create mode 100644 data/poi_geodownload/libmdb/dump.c create mode 100644 data/poi_geodownload/libmdb/file.c create mode 100644 data/poi_geodownload/libmdb/iconv.c create mode 100644 data/poi_geodownload/libmdb/include/mdbtools.h create mode 100644 data/poi_geodownload/libmdb/index.c create mode 100644 data/poi_geodownload/libmdb/kkd.c create mode 100644 data/poi_geodownload/libmdb/like.c create mode 100644 data/poi_geodownload/libmdb/map.c create mode 100644 data/poi_geodownload/libmdb/mem.c create mode 100644 data/poi_geodownload/libmdb/money.c create mode 100644 data/poi_geodownload/libmdb/options.c create mode 100644 data/poi_geodownload/libmdb/props.c create mode 100644 data/poi_geodownload/libmdb/sargs.c create mode 100644 data/poi_geodownload/libmdb/stats.c create mode 100644 data/poi_geodownload/libmdb/table.c create mode 100644 data/poi_geodownload/libmdb/worktable.c create mode 100644 data/poi_geodownload/libmdb/write.c create mode 100644 data/poi_geodownload/poi_geodownload.c diff --git a/attr.c b/attr.c index 0c6d58ae..91d3f5ab 100644 --- a/attr.c +++ b/attr.c @@ -1,4 +1,7 @@ #include +#include +#include "debug.h" +#include "item.h" #include "attr.h" struct attr_name { @@ -38,3 +41,46 @@ attr_to_name(enum attr_type attr) } return NULL; } + +struct attr * +attr_new_from_text(char *name, char *value) +{ + enum attr_type attr; + struct attr *ret; + + ret=g_new0(struct attr, 1); + dbg(0,"enter name='%s' value='%s'\n", name, value); + attr=attr_from_name(name); + ret->type=attr; + switch (attr) { + case attr_item_type: + ret->u.item_type=item_from_name(value); + break; + default: + dbg(0,"default\n"); + g_free(ret); + ret=NULL; + } + return ret; +} + +struct attr * +attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) +{ + dbg(0, "enter attrs=%p\n", attrs); + while (*attrs) { + dbg(0,"*attrs=%p\n", *attrs); + if ((*attrs)->type == attr) { + return *attrs; + } + attrs++; + } + exit(0); + return NULL; +} + +void +attr_free(struct attr *attr) +{ + g_free(attr); +} diff --git a/attr.h b/attr.h index 83a12f5b..356185c8 100644 --- a/attr.h +++ b/attr.h @@ -1,6 +1,8 @@ #ifndef ATTR_H #define ATTR_H +enum item_type; + enum attr_type { #define ATTR2(x,y) attr_##x=y, #define ATTR(x) attr_##x, @@ -15,6 +17,7 @@ struct attr { char *str; int num; struct item *item; + enum item_type item_type; } u; }; diff --git a/attr_def.h b/attr_def.h index 1a2d472c..0f259764 100644 --- a/attr_def.h +++ b/attr_def.h @@ -7,6 +7,7 @@ ATTR(street_name_item) ATTR(street_name_numbers_item) ATTR(street_item) ATTR(street_number_item) +ATTR(item_type) ATTR2(type_item_end,0x0001ffff) ATTR2(type_int_begin,0x00020000) ATTR(id) diff --git a/country.c b/country.c index 42864da9..f7f238f2 100644 --- a/country.c +++ b/country.c @@ -3,7 +3,6 @@ #include #include #include "debug.h" -#include "attr.h" #include "item.h" #include "country.h" #include "search.h" diff --git a/data/Makefile.am b/data/Makefile.am index 35a11357..8f7999b9 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1 +1 @@ -SUBDIRS=mg textfile garmin_img +SUBDIRS=mg textfile garmin_img poi_geodownload diff --git a/data/mg/map.c b/data/mg/map.c index 20feb8f1..6122b98a 100644 --- a/data/mg/map.c +++ b/data/mg/map.c @@ -7,7 +7,7 @@ #include "mg.h" -struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro); +struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro); static int map_id; @@ -259,7 +259,7 @@ static struct map_methods map_methods_mg = { }; struct map_priv * -map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro) +map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro) { struct map_priv *m; int i,maybe_missing,len=strlen(dirname); diff --git a/data/mg/mg.h b/data/mg/mg.h index c94a536b..78f72c04 100644 --- a/data/mg/mg.h +++ b/data/mg/mg.h @@ -1,8 +1,8 @@ #include +#include "item.h" #include "attr.h" #include "coord.h" #include "data.h" -#include "item.h" #include "map.h" #include "file.h" diff --git a/data/poi_geodownload/Makefile.am b/data/poi_geodownload/Makefile.am new file mode 100644 index 00000000..d3412df3 --- /dev/null +++ b/data/poi_geodownload/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS=libmdb +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -Ilibmdb/include -DMODULE=\"data_poi_geodownload\" +moduledata_LTLIBRARIES = libdata_poi_geodownload.la +libdata_poi_geodownload_la_SOURCES = poi_geodownload.c +libdata_poi_geodownload_la_LIBADD = -Llibmdb -lmdb diff --git a/data/poi_geodownload/libmdb/Makefile.am b/data/poi_geodownload/libmdb/Makefile.am new file mode 100644 index 00000000..6ff3fd61 --- /dev/null +++ b/data/poi_geodownload/libmdb/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @NAVIT_CFLAGS@ -Iinclude + +objdir=$(prefix) +obj_PROGRAMS=libmdb.a +INSTALL_PROGRAM=/bin/true + +libmdb_a_SOURCES=backend.c catalog.c data.c dump.c file.c iconv.c index.c kkd.c like.c map.c mem.c money.c options.c props.c sargs.c stats.c table.c worktable.c write.c + +libmdb.a: $(libmdb_a_OBJECTS) + ar r $@ $(libmdb_a_OBJECTS) + + diff --git a/data/poi_geodownload/libmdb/backend.c b/data/poi_geodownload/libmdb/backend.c new file mode 100644 index 00000000..e90f807b --- /dev/null +++ b/data/poi_geodownload/libmdb/backend.c @@ -0,0 +1,301 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* +** functions to deal with different backend database engines +*/ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +static int is_init; +static GHashTable *mdb_backends; + + /* Access data types */ +static MdbBackendType mdb_access_types[] = { + {"Unknown 0x00", 0,0,0 }, + {"Boolean", 0,0,0}, + {"Byte", 0,0,0}, + {"Integer", 0,0,0}, + {"Long Integer", 0,0,0}, + {"Currency", 0,0,0}, + {"Single", 0,0,0}, + {"Double", 0,0,0}, + {"DateTime (Short)", 0,0,1}, + {"Unknown 0x09", 0,0,0}, + {"Text", 1,0,1}, + {"OLE", 1,0,1}, + {"Memo/Hyperlink",1,0,1}, + {"Unknown 0x0d",0,0,0}, + {"Unknown 0x0e",0,0,0}, + {"Replication ID",0,0,0}, + {"Numeric",1,1,0} +}; + +/* Oracle data types */ +static MdbBackendType mdb_oracle_types[] = { + {"Oracle_Unknown 0x00",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"FLOAT",0,0,0}, + {"FLOAT",0,0,0}, + {"DATE",0,0,0}, + {"Oracle_Unknown 0x09",0,0,0}, + {"VARCHAR2",1,0,1}, + {"BLOB",1,0,1}, + {"CLOB",1,0,1}, + {"Oracle_Unknown 0x0d",0,0,0}, + {"Oracle_Unknown 0x0e",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, +}; + +/* Sybase/MSSQL data types */ +static MdbBackendType mdb_sybase_types[] = { + {"Sybase_Unknown 0x00",0,0,0}, + {"bit",0,0,0}, + {"char",1,0,1}, + {"smallint",0,0,0}, + {"int",0,0,0}, + {"money",0,0,0}, + {"real",0,0,0}, + {"float",0,0,0}, + {"smalldatetime",0,0,0}, + {"Sybase_Unknown 0x09",0,0,0}, + {"varchar",1,0,1}, + {"varbinary",1,0,1}, + {"text",1,0,1}, + {"Sybase_Unknown 0x0d",0,0,0}, + {"Sybase_Unknown 0x0e",0,0,0}, + {"Sybase_Replication ID",0,0,0}, + {"numeric",1,1,0}, +}; + +/* Postgres data types */ +static MdbBackendType mdb_postgres_types[] = { + {"Postgres_Unknown 0x00",0,0,0}, + {"Bool",0,0,0}, + {"Int2",0,0,0}, + {"Int4",0,0,0}, + {"Int8",0,0,0}, + {"Money",0,0,0}, + {"Float4",0,0,0}, + {"Float8",0,0,0}, + {"Timestamp",0,0,0}, + {"Postgres_Unknown 0x09",0,0,0}, + {"Char",1,0,1}, + {"Postgres_Unknown 0x0b",0,0,0}, + {"Postgres_Unknown 0x0c",0,0,0}, + {"Postgres_Unknown 0x0d",0,0,0}, + {"Postgres_Unknown 0x0e",0,0,0}, + {"Serial",0,0,0}, + {"Postgres_Unknown 0x10",0,0,0}, +}; +/* MySQL data types */ +static MdbBackendType mdb_mysql_types[] = { + {"Text",1,0,1}, + {"char",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"date",0,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"text",1,0,1}, + {"blob",0,0,0}, + {"text",1,0,1}, + {"numeric",1,1,0}, + {"numeric",1,1,0}, +}; + +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); + +char *mdb_get_coltype_string(MdbBackend *backend, int col_type) +{ + static char buf[16]; + + if (col_type > 0x10 ) { + // return NULL; + snprintf(buf,sizeof(buf), "type %04x", col_type); + return buf; + } else { + return backend->types_table[col_type].name; + } +} + +int mdb_coltype_takes_length(MdbBackend *backend, int col_type) +{ + return backend->types_table[col_type].needs_length; +} + +/** + * mdb_init_backends + * + * Initializes the mdb_backends hash and loads the builtin backends. + * Use mdb_remove_backends() to destroy this hash when done. + */ +void mdb_init_backends() +{ + mdb_backends = g_hash_table_new(g_str_hash, g_str_equal); + + mdb_register_backend(mdb_access_types, "access"); + mdb_register_backend(mdb_sybase_types, "sybase"); + mdb_register_backend(mdb_oracle_types, "oracle"); + mdb_register_backend(mdb_postgres_types, "postgres"); + mdb_register_backend(mdb_mysql_types, "mysql"); +} +void mdb_register_backend(MdbBackendType *backend_type, char *backend_name) +{ + MdbBackend *backend = (MdbBackend *) g_malloc0(sizeof(MdbBackend)); + backend->types_table = backend_type; + g_hash_table_insert(mdb_backends, backend_name, backend); +} + +/** + * mdb_remove_backends + * + * Removes all entries from and destroys the mdb_backends hash. + */ +void mdb_remove_backends() +{ + g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL); + g_hash_table_destroy(mdb_backends); +} +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data) +{ + MdbBackend *backend = (MdbBackend *)value; + g_free (backend); + return TRUE; +} + +/** + * mdb_set_default_backend + * @mdb: Handle to open MDB database file + * @backend_name: Name of the backend to set as default + * + * Sets the default backend of the handle @mdb to @backend_name. + * + * Returns: 1 if successful, 0 if unsuccessful. + */ +int mdb_set_default_backend(MdbHandle *mdb, char *backend_name) +{ + MdbBackend *backend; + + backend = (MdbBackend *) g_hash_table_lookup(mdb_backends, backend_name); + if (backend) { + mdb->default_backend = backend; + mdb->backend_name = (char *) g_strdup(backend_name); + is_init = 0; + return 1; + } else { + return 0; + } +} + +/** + * mdb_get_relationships + * @mdb: Handle to open MDB database file + * + * Generates relationships by reading the MSysRelationships table. + * 'szColumn' contains the column name of the child table. + * 'szObject' contains the table name of the child table. + * 'szReferencedColumn' contains the column name of the parent table. + * 'szReferencedObject' contains the table name of the parent table. + * + * Returns: a string stating that relationships are not supported for the + * selected backend, or a string containing SQL commands for setting up + * the relationship, tailored for the selected backend. The caller is + * responsible for freeing this string. + */ +char *mdb_get_relationships(MdbHandle *mdb) +{ + unsigned int i; + gchar *text = NULL; /* String to be returned */ + static char *bound[4]; /* Bound values */ + static MdbTableDef *table; /* Relationships table */ + int backend = 0; /* Backends: 1=oracle */ + + if (strncmp(mdb->backend_name,"oracle",6) == 0) { + backend = 1; + } else { + if (is_init == 0) { /* the first time through */ + is_init = 1; + return (char *) g_strconcat( + "-- relationships are not supported for ", + mdb->backend_name, NULL); + } else { /* the second time through */ + is_init = 0; + return NULL; + } + } + + if (is_init == 0) { + table = mdb_read_table_by_name(mdb, "MSysRelationships", MDB_TABLE); + if ((!table) || (table->num_rows == 0)) { + return NULL; + } + + mdb_read_columns(table); + for (i=0;i<4;i++) { + bound[i] = (char *) g_malloc0(MDB_BIND_SIZE); + } + mdb_bind_column_by_name(table, "szColumn", bound[0]); + mdb_bind_column_by_name(table, "szObject", bound[1]); + mdb_bind_column_by_name(table, "szReferencedColumn", bound[2]); + mdb_bind_column_by_name(table, "szReferencedObject", bound[3]); + mdb_rewind_table(table); + + is_init = 1; + } + else if (table->cur_row >= table->num_rows) { /* past the last row */ + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + if (!mdb_fetch_row(table)) { + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + switch (backend) { + case 1: /* oracle */ + text = g_strconcat("alter table ", bound[1], + " add constraint ", bound[3], "_", bound[1], + " foreign key (", bound[0], ")" + " references ", bound[3], "(", bound[2], ")", NULL); + break; + } + + return (char *)text; +} + diff --git a/data/poi_geodownload/libmdb/catalog.c b/data/poi_geodownload/libmdb/catalog.c new file mode 100644 index 00000000..dc08abdd --- /dev/null +++ b/data/poi_geodownload/libmdb/catalog.c @@ -0,0 +1,138 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +char * +mdb_get_objtype_string(int obj_type) +{ +static char *type_name[] = {"Form", + "Table", + "Macro", + "System Table", + "Report", + "Query", + "Linked Table", + "Module", + "Relationship", + "Unknown 0x09", + "Unknown 0x0a", + "Database" + }; + + if (obj_type > 11) { + return NULL; + } else { + return type_name[obj_type]; + } +} + +void mdb_free_catalog(MdbHandle *mdb) +{ + unsigned int i; + + if (!mdb->catalog) return; + for (i=0; icatalog->len; i++) + g_free (g_ptr_array_index(mdb->catalog, i)); + g_ptr_array_free(mdb->catalog, TRUE); + mdb->catalog = NULL; +} + +GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype) +{ + MdbCatalogEntry *entry, msysobj; + MdbTableDef *table; + char obj_id[256]; + char obj_name[256]; + char obj_type[256]; + char obj_flags[256]; + int type; + + if (mdb->catalog) mdb_free_catalog(mdb); + mdb->catalog = g_ptr_array_new(); + mdb->num_catalog = 0; + + /* dummy up a catalog entry so we may read the table def */ + memset(&msysobj, 0, sizeof(MdbCatalogEntry)); + msysobj.mdb = mdb; + msysobj.object_type = MDB_TABLE; + msysobj.table_pg = 2; + strcpy(msysobj.object_name, "MSysObjects"); + + /* mdb_table_dump(&msysobj); */ + + table = mdb_read_table(&msysobj); + if (!table) return NULL; + + mdb_read_columns(table); + + mdb_bind_column_by_name(table, "Id", obj_id); + mdb_bind_column_by_name(table, "Name", obj_name); + mdb_bind_column_by_name(table, "Type", obj_type); + mdb_bind_column_by_name(table, "Flags", obj_flags); + + mdb_rewind_table(table); + + while (mdb_fetch_row(table)) { + type = atoi(obj_type); + if (objtype==MDB_ANY || type == objtype) { + // fprintf(stdout, "obj_id: %10ld objtype: %-3d obj_name: %s\n", + // (atol(obj_id) & 0x00FFFFFF), type, obj_name); + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + strcpy(entry->object_name, obj_name); + entry->object_type = (type & 0x7F); + entry->table_pg = atol(obj_id) & 0x00FFFFFF; + entry->flags = atol(obj_flags); + mdb->num_catalog++; + g_ptr_array_add(mdb->catalog, entry); + } + } + //mdb_dump_catalog(mdb, MDB_TABLE); + + mdb_free_tabledef(table); + + return mdb->catalog; +} + +void +mdb_dump_catalog(MdbHandle *mdb, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + if (obj_type==MDB_ANY || entry->object_type==obj_type) { + fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2d\n", + mdb_get_objtype_string(entry->object_type), + entry->object_name, + (unsigned int) entry->table_pg, + (unsigned int) entry->kkd_pg, + entry->kkd_rowid); + } + } + return; +} + diff --git a/data/poi_geodownload/libmdb/data.c b/data/poi_geodownload/libmdb/data.c new file mode 100644 index 00000000..e50e57db --- /dev/null +++ b/data/poi_geodownload/libmdb/data.c @@ -0,0 +1,856 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define OFFSET_MASK 0x1fff + +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s); +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, unsigned char isnull, int offset, int len); +static char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale); +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size); + +static char date_fmt[64] = "%x %X"; + +void mdb_set_date_fmt(const char *fmt) +{ + date_fmt[63] = 0; + strncpy(date_fmt, fmt, 63); +} + +void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr) +{ +MdbColumn *col; + + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter + */ + col=g_ptr_array_index(table->columns, col_num - 1); + col->bind_ptr = bind_ptr; +} +int +mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr) +{ + unsigned int i; + int col_num = -1; + MdbColumn *col; + + for (i=0;inum_cols;i++) { + col=g_ptr_array_index(table->columns,i); + if (!strcmp(col->name,col_name)) { + col_num = col->col_num + 1; + mdb_bind_column(table, col_num, bind_ptr); + break; + } + } + + return col_num; +} +void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr) +{ +MdbColumn *col; + + col=g_ptr_array_index(table->columns, col_num - 1); + col->len_ptr = len_ptr; +} + +/** + * mdb_find_pg_row + * @mdb: Database file handle + * @pg_row: Lower byte contains the row number, the upper three contain page + * @buf: Pointer for returning a pointer to the page + * @off: Pointer for returning an offset to the row + * @len: Pointer for returning the length of the row + * + * Returns: 0 on success. 1 on failure. + */ +int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len) +{ + unsigned int pg = pg_row >> 8; + unsigned int row = pg_row & 0xff; + + if (mdb_read_alt_pg(mdb, pg) != mdb->fmt->pg_size) + return 1; + mdb_swap_pgbuf(mdb); + *off = mdb_pg_get_int16(mdb, mdb->fmt->row_count_offset + 2 + (row*2)); + *len = mdb_find_end_of_row(mdb, row) - *off + 1; + mdb_swap_pgbuf(mdb); + *buf = mdb->alt_pg_buf; + return 0; +} + +int +mdb_find_end_of_row(MdbHandle *mdb, int row) +{ + MdbFormatConstants *fmt = mdb->fmt; + int row_end; + + /* Search the previous "row start" values for the first non-'lookupflag' one. + * If we don't find one, then the end of the page is the correct value. + */ +#if 1 + if (row==0) { + row_end = fmt->pg_size - 1; + } else { + row_end = (mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + (row - 1) * 2)) & OFFSET_MASK) - 1; + } + return row_end; +#else + int i, row_start; + + /* if lookupflag is not set, it's good (deleteflag is ok) */ + for (i = row - 1; i >= 0; i--) { + row_start = mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + i * 2)); + if (!(row_start & 0x8000)) { + break; + } + } + + if (i == -1) { + row_end = fmt->pg_size - 1; + } else { + row_end = (row_start & OFFSET_MASK) - 1; + } + return row_end; +#endif +} +int mdb_is_null(unsigned char *null_mask, int col_num) +{ +int byte_num = (col_num - 1) / 8; +int bit_num = (col_num - 1) % 8; + + if ((1 << bit_num) & null_mask[byte_num]) { + return 0; + } else { + return 1; + } +} +/* bool has to be handled specially because it uses the null bit to store its +** value*/ +static int +mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) +{ + + col->cur_value_len = value; + if (col->bind_ptr) { + strcpy(col->bind_ptr, value ? "0" : "1"); + } + + return 0; +} +static int mdb_xfer_bound_ole(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ + int ret = 0; + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr || col->len_ptr) { + //ret = mdb_copy_ole(mdb, col->bind_ptr, start, len); + memcpy(col->bind_ptr, &mdb->pg_buf[start], MDB_MEMO_OVERHEAD); + } + if (col->len_ptr) { + *col->len_ptr = MDB_MEMO_OVERHEAD; + } + return ret; +} +static int mdb_xfer_bound_data(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ +int ret; + //if (!strcmp("Name",col->name)) { + //printf("start %d %d\n",start, len); + //} + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr) { + if (!len) { + strcpy(col->bind_ptr, ""); + } else if (col->col_type == MDB_NUMERIC) { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_num_to_string(mdb, start, col->col_type, + col->col_prec, col->col_scale); + strcpy(col->bind_ptr, str); + g_free(str); + } else { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_col_to_string(mdb, mdb->pg_buf, start, + col->col_type, len); + strcpy(col->bind_ptr, str); + + } + ret = strlen(col->bind_ptr); + if (col->len_ptr) { + *col->len_ptr = ret; + } + return ret; + } + return 0; +} +int mdb_read_row(MdbTableDef *table, unsigned int row) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *col; + unsigned int i; + int rc; + int row_start, row_end; + int delflag, lookupflag; + MdbField fields[256]; + int num_fields; + + if (table->num_rows <= row) + return 0; + + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2)); + row_end = mdb_find_end_of_row(mdb, row); + + delflag = lookupflag = 0; + if (row_start & 0x8000) lookupflag++; + if (row_start & 0x4000) delflag++; + row_start &= OFFSET_MASK; /* remove flags */ +#if MDB_DEBUG + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + row, row_start, row_end, + lookupflag ? "[lookup]" : "", + delflag ? "[delflag]" : ""); +#endif + + if (!table->noskip_del && delflag) { + row_end = row_start-1; + return 0; + } + + num_fields = mdb_crack_row(table, row_start, row_end, fields); + if (!mdb_test_sargs(table, fields, num_fields)) return 0; + +#if MDB_DEBUG + fprintf(stdout,"sarg test passed row %d \n", row); +#endif + +#if MDB_DEBUG + buffer_dump(mdb->pg_buf, row_start, row_end); +#endif + + /* take advantage of mdb_crack_row() to clean up binding */ + /* use num_cols instead of num_fields -- bsb 03/04/02 */ + for (i = 0; i < table->num_cols; i++) { + col = g_ptr_array_index(table->columns,fields[i].colnum); + rc = _mdb_attempt_bind(mdb, col, fields[i].is_null, + fields[i].start, fields[i].siz); + } + + return 1; +} +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, + int len) +{ + if (col->col_type == MDB_BOOL) { + mdb_xfer_bound_bool(mdb, col, isnull); + } else if (isnull) { + mdb_xfer_bound_data(mdb, 0, col, 0); + } else if (col->col_type == MDB_OLE) { + mdb_xfer_bound_ole(mdb, offset, col, len); + } else { + //if (!mdb_test_sargs(mdb, col, offset, len)) { + //return 0; + //} + mdb_xfer_bound_data(mdb, offset, col, len); + } + return 1; +} +int mdb_read_next_dpg(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int next_pg; + +#ifndef SLOW_READ + next_pg = mdb_map_find_next(mdb, table->usage_map, + table->map_sz, table->cur_phys_pg); + + if (next_pg >= 0) { + if (mdb_read_pg(mdb, next_pg)) { + table->cur_phys_pg = next_pg; + return table->cur_phys_pg; + } else { + return 0; + } + } + fprintf(stderr, "Warning: defaulting to brute force read\n"); +#endif + /* can't do a fast read, go back to the old way */ + do { + if (!mdb_read_pg(mdb, table->cur_phys_pg++)) + return 0; + } while (mdb->pg_buf[0]!=0x01 || mdb_pg_get_int32(mdb, 4)!=entry->table_pg); + /* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */ + return table->cur_phys_pg; +} +int mdb_rewind_table(MdbTableDef *table) +{ + table->cur_pg_num=0; + table->cur_phys_pg=0; + table->cur_row=0; + + return 0; +} +int +mdb_fetch_row(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + unsigned int rows; + int rc; + guint32 pg; + + if (table->num_rows==0) + return 0; + + /* initialize */ + if (!table->cur_pg_num) { + table->cur_pg_num=1; + table->cur_row=0; + if ((!table->is_temp_table)&&(table->strategy!=MDB_INDEX_SCAN)) + if (!mdb_read_next_dpg(table)) return 0; + } + + do { + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + rows = mdb_get_int16( + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->row_count_offset); + if (table->cur_row >= rows) { + table->cur_row = 0; + table->cur_pg_num++; + if (table->cur_pg_num > pages->len) + return 0; + } + memcpy(mdb->pg_buf, + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->pg_size); + } else if (table->strategy==MDB_INDEX_SCAN) { + + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { + mdb_index_scan_free(table); + return 0; + } + mdb_read_pg(mdb, pg); + } else { + rows = mdb_pg_get_int16(mdb,fmt->row_count_offset); + + /* if at end of page, find a new page */ + if (table->cur_row >= rows) { + table->cur_row=0; + + if (!mdb_read_next_dpg(table)) { + return 0; + } + } + } + + /* printf("page %d row %d\n",table->cur_phys_pg, table->cur_row); */ + rc = mdb_read_row(table, table->cur_row); + table->cur_row++; + } while (!rc); + + return 1; +} +void mdb_data_dump(MdbTableDef *table) +{ + unsigned int i; + char *bound_values[MDB_MAX_COLS]; + + for (i=0;inum_cols;i++) { + bound_values[i] = (char *) g_malloc(256); + mdb_bind_column(table, i+1, bound_values[i]); + } + mdb_rewind_table(table); + while (mdb_fetch_row(table)) { + for (i=0;inum_cols;i++) { + fprintf(stdout, "column %d is %s\n", i+1, bound_values[i]); + } + } + for (i=0;inum_cols;i++) { + g_free(bound_values[i]); + } +} + +int mdb_is_fixed_col(MdbColumn *col) +{ + return col->is_fixed; +} +#if 0 +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +{ +int i; + + for (i=start; ipg_buf[i]); + } + text[(i-start)*2]='\0'; + + return text; +} +#endif +int +mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + + if (ole_flags == 0x8000) { + /* inline fields don't have a next */ + return 0; + } else if (ole_flags == 0x4000) { + /* 0x4000 flagged ole's are contained on one page and thus + * should be handled entirely with mdb_ole_read() */ + return 0; + } else if (ole_flags == 0x0000) { + pg_row = (col->cur_blob_pg << 8) & col->cur_blob_row; + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } + return 0; +} +int +mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %08x", + ole_len, ole_flags); + + col->chunk_size = chunk_size; + + if (ole_flags == 0x8000) { + /* inline ole field, if we can satisfy it, then do it */ + len = col->cur_value_len - MDB_MEMO_OVERHEAD; + if (chunk_size >= len) { + if (col->bind_ptr) + memcpy(col->bind_ptr, + &mdb->pg_buf[col->cur_value_start + + MDB_MEMO_OVERHEAD], + len); + return len; + } else { + return 0; + } + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld", + col->cur_blob_row, col->cur_blob_pg); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); + + if (col->bind_ptr) { + memcpy(col->bind_ptr, buf + row_start, len); + if (mdb_get_option(MDB_DEBUG_OLE)) + buffer_dump(col->bind_ptr, 0, 16); + } + return len; + } else if (ole_flags == 0x0000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size) +{ + guint16 ole_len; + guint16 ole_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + return len; + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest, buf + row_start, len); + return len; + } else if (ole_flags == 0x0000) { + int cur = 0; + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return 0; + } + + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest+cur, buf + row_start + 4, len - 4); + cur += len - 4; + + /* find next lval page */ + pg_row = mdb_get_int32(buf, row_start); + } while ((pg_row >> 8)); + return cur; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size) +{ + guint16 memo_len; + static char text[MDB_BIND_SIZE]; + guint16 memo_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf, start, start + 12); +#endif + + /* The 16 bit integer at offset 0 is the length of the memo field. + * The 32 bit integer at offset 4 contains page and row information. + */ + memo_len = mdb_pg_get_int16(mdb, start); + memo_flags = mdb_pg_get_int16(mdb, start+2); + + if (memo_flags & 0x8000) { + /* inline memo field */ + strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + text[size - MDB_MEMO_OVERHEAD]='\0'; + return text; + } else if (memo_flags & 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); + buffer_dump(mdb->pg_buf, row_start, row_start + len); +#endif + if (IS_JET3(mdb)) { + strncpy(text, buf + row_start, len); + text[len]='\0'; + } else { + mdb_unicode2ascii(mdb, buf, row_start, len, text); + } + return text; + } else { /* if (memo_flags == 0x0000) { */ + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + text[0]='\0'; + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); +#endif + strncat(text, buf + row_start + 4, + strlen(text) + len - 4 > MDB_BIND_SIZE ? + MDB_BIND_SIZE - strlen(text) : len - 4); + + /* find next lval page */ + pg_row = mdb_get_int32(mdb->pg_buf, row_start); + } while ((pg_row >> 8)); + return text; +/* + } else { + fprintf(stderr,"Unhandled memo field flags = %04x\n", memo_flags); + return ""; +*/ + } +} +static char * +mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale) +{ + char *text; + gint32 l; + + memcpy(&l, mdb->pg_buf+start+13, 4); + + text = (char *) g_malloc(prec+2); + sprintf(text, "%0*" G_GINT32_FORMAT, prec, GINT32_FROM_LE(l)); + if (scale) { + memmove(text+prec-scale, text+prec-scale+1, scale+1); + text[prec-scale] = '.'; + } + return text; +} + +static int trim_trailing_zeros(char * buff, int n) +{ + char * p = buff + n - 1; + + while (p >= buff && *p == '0') + *p-- = '\0'; + + if (*p == '.') + *p = '\0'; + + return 0; +} + +char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size) +{ + /* FIX ME -- not thread safe */ + static char text[MDB_BIND_SIZE]; + time_t t; + int n; + float tf; + double td; + + switch (datatype) { + case MDB_BOOL: + /* shouldn't happen. bools are handled specially + ** by mdb_xfer_bound_bool() */ + break; + case MDB_BYTE: + sprintf(text,"%d",mdb_get_byte(buf, start)); + return text; + break; + case MDB_INT: + sprintf(text,"%ld",(long)mdb_get_int16(buf, start)); + return text; + break; + case MDB_LONGINT: + sprintf(text,"%ld",mdb_get_int32(buf, start)); + return text; + break; + case MDB_FLOAT: + tf = mdb_get_single(mdb->pg_buf, start); + n = sprintf(text,"%.*f",FLT_DIG - (int)ceil(log10(tf)), tf); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_DOUBLE: + td = mdb_get_double(mdb->pg_buf, start); + n = sprintf(text,"%.*f",DBL_DIG - (int)ceil(log10(td)), td); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_TEXT: + if (size<0) { + return ""; + } + if (IS_JET4(mdb)) { +/* + int i; + for (i=0;ipg_buf[start+i], mdb->pg_buf[start+i]); + } + fprintf(stdout, "\n"); +*/ + mdb_unicode2ascii(mdb, mdb->pg_buf, start, size, text); + } else { + strncpy(text, &buf[start], size); + text[size]='\0'; + } + return text; + break; + case MDB_SDATETIME: + td = mdb_get_double(mdb->pg_buf, start); + if (td > 1) { + t = (long int)((td - 25569.0) * 86400.0); + } else { + t = (long int)(td * 86400.0); + } + strftime(text, MDB_BIND_SIZE, date_fmt, (struct tm*)gmtime(&t)); + return text; + + break; + case MDB_MEMO: + return mdb_memo_to_string(mdb, start, size); + break; + case MDB_MONEY: + mdb_money_to_string(mdb, start, text); + return text; + case MDB_NUMERIC: + break; + default: + return ""; + break; + } + return NULL; +} +int mdb_col_disp_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return 4; + break; + case MDB_INT: + return 6; + break; + case MDB_LONGINT: + return 11; + break; + case MDB_FLOAT: + return 10; + break; + case MDB_DOUBLE: + return 10; + break; + case MDB_TEXT: + return col->col_size; + break; + case MDB_SDATETIME: + return 20; + break; + case MDB_MEMO: + return 255; + break; + case MDB_MONEY: + return 21; + break; + } + return 0; +} +int mdb_col_fixed_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return -1; + break; + case MDB_INT: + return 2; + break; + case MDB_LONGINT: + return 4; + break; + case MDB_FLOAT: + return 4; + break; + case MDB_DOUBLE: + return 8; + break; + case MDB_TEXT: + return -1; + break; + case MDB_SDATETIME: + return 4; + break; + case MDB_MEMO: + return -1; + break; + case MDB_MONEY: + return 8; + break; + } + return 0; +} diff --git a/data/poi_geodownload/libmdb/dump.c b/data/poi_geodownload/libmdb/dump.c new file mode 100644 index 00000000..7ee17f9a --- /dev/null +++ b/data/poi_geodownload/libmdb/dump.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void buffer_dump(const unsigned char* buf, int start, int end) +{ + char asc[20]; + int j, k; + + memset(asc, 0, sizeof(asc)); + k = 0; + for (j=start; j<=end; j++) { + if (k == 0) { + fprintf(stdout, "%04x ", j); + } + fprintf(stdout, "%02x ", buf[j]); + asc[k] = isprint(buf[j]) ? buf[j] : '.'; + k++; + if (k == 8) { + fprintf(stdout, " "); + } + if (k == 16) { + fprintf(stdout, " %s\n", asc); + memset(asc, 0, sizeof(asc)); + k = 0; + } + } + for (j=k; j<16; j++) { + fprintf(stdout, " "); + } + if (k < 8) { + fprintf(stdout, " "); + } + fprintf(stdout, " %s\n", asc); +} diff --git a/data/poi_geodownload/libmdb/file.c b/data/poi_geodownload/libmdb/file.c new file mode 100644 index 00000000..941830c5 --- /dev/null +++ b/data/poi_geodownload/libmdb/file.c @@ -0,0 +1,376 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; +*/ +MdbFormatConstants MdbJet4Constants = { + 4096, 0x0c, 16, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59, 7, 21, 9 +}; +MdbFormatConstants MdbJet3Constants = { + 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39, 3, 14, 5 /* not sure on 5, need to check */ +}; + +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg); + +/** + * mdb_find_file: + * @filename: path to MDB (database) file + * + * Finds and returns the absolute path to an MDB file. Function will first try + * to fstat file as passed, then search through the $MDBPATH if not found. + * + * Return value: gchar pointer to absolute path. Caller is responsible for + * freeing. + **/ + +static gchar *mdb_find_file(char *file_name) +{ + struct stat status; + gchar *mdbpath, **dir, *tmpfname; + unsigned int i = 0; + + /* try the provided file name first */ + if (!stat(file_name, &status)) { + return g_strdup(file_name); + } + + /* Now pull apart $MDBPATH and try those */ + mdbpath = (gchar *) getenv("MDBPATH"); + /* no path, can't find file */ + if (!mdbpath || !strlen(mdbpath)) return NULL; + + dir = g_strsplit(mdbpath, ":", 0); + while (dir[i]) { + if (!strlen(dir[i])) continue; + tmpfname = g_strconcat(dir[i++], "/", file_name, NULL); + if (!stat(tmpfname, &status)) { + g_strfreev(dir); + return tmpfname; + } + g_free(tmpfname); + } + g_strfreev(dir); + return NULL; +} +/** + * mdb_open: + * @filename: path to MDB (database) file + * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write + * + * Opens an MDB file and returns an MdbHandle to it. MDB File may be relative + * to the current directory, a full path to the file, or relative to a + * component of $MDBPATH. + * + * Return value: pointer to MdbHandle structure. + **/ +MdbHandle *mdb_open(char *filename, MdbFileFlags flags) +{ + MdbHandle *mdb; + + mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle)); + mdb_set_default_backend(mdb, "access"); + /* need something to bootstrap with, reassign after page 0 is read */ + mdb->fmt = &MdbJet3Constants; + mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile)); + mdb->f->refs = 1; + mdb->f->fd = -1; + mdb->f->filename = (char *) mdb_find_file(filename); + if (!mdb->f->filename) { + fprintf(stderr, "Can't alloc filename\n"); + mdb_close(mdb); + return NULL; + } + if (flags & MDB_WRITABLE) { + mdb->f->writable = TRUE; + mdb->f->fd = open(mdb->f->filename,O_RDWR); + } else { + mdb->f->fd = open(mdb->f->filename,O_RDONLY); + } + + if (mdb->f->fd==-1) { + fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); + mdb_close(mdb); + return NULL; + } + if (!mdb_read_pg(mdb, 0)) { + fprintf(stderr,"Couldn't read first page.\n"); + mdb_close(mdb); + return NULL; + } + if (mdb->pg_buf[0] != 0) { + mdb_close(mdb); + return NULL; + } + mdb->f->jet_version = mdb_pg_get_int32(mdb, 0x14); + if (IS_JET4(mdb)) { + mdb->fmt = &MdbJet4Constants; + } else if (IS_JET3(mdb)) { + mdb->fmt = &MdbJet3Constants; + } else { + fprintf(stderr,"Unknown Jet version.\n"); + mdb_close(mdb); + return NULL; + } + + return mdb; +} + +/** + * mdb_close: + * @mdb: Handle to open MDB database file + * + * Dereferences MDB file, closes if reference count is 0, and destroys handle. + * + **/ +void +mdb_close(MdbHandle *mdb) +{ + if (!mdb) return; + mdb_free_catalog(mdb); + g_free(mdb->stats); + g_free(mdb->backend_name); + + if (mdb->f) { + if (mdb->f->refs > 1) { + mdb->f->refs--; + } else { + if (mdb->f->fd != -1) close(mdb->f->fd); + g_free(mdb->f->filename); + g_free(mdb->f); + } + } + + g_free(mdb); +} +/** + * mdb_clone_handle: + * @mdb: Handle to open MDB database file + * + * Clones an existing database handle. Cloned handle shares the file descriptor + * but has its own page buffer, page position, and similar internal variables. + * + * Return value: new handle to the database. + */ +MdbHandle *mdb_clone_handle(MdbHandle *mdb) +{ + MdbHandle *newmdb; + MdbCatalogEntry *entry, *data; + unsigned int i; + + newmdb = (MdbHandle *) g_memdup(mdb, sizeof(MdbHandle)); + newmdb->stats = NULL; + newmdb->catalog = g_ptr_array_new(); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + data = g_memdup(entry,sizeof(MdbCatalogEntry)); + g_ptr_array_add(newmdb->catalog, data); + } + mdb->backend_name = NULL; + if (mdb->f) { + mdb->f->refs++; + } + return newmdb; +} + +/* +** mdb_read a wrapper for read that bails if anything is wrong +*/ +ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + if (pg && mdb->cur_pg == pg) return mdb->fmt->pg_size; + + len = _mdb_read_pg(mdb, mdb->pg_buf, pg); + //fprintf(stderr, "read page %d type %02x\n", pg, mdb->pg_buf[0]); + mdb->cur_pg = pg; + /* kan - reset the cur_pos on a new page read */ + mdb->cur_pos = 0; /* kan */ + return len; +} +ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + len = _mdb_read_pg(mdb, mdb->alt_pg_buf, pg); + return len; +} +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + if (status.st_size < offset) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + if (mdb->stats && mdb->stats->collect) + mdb->stats->pg_reads++; + + lseek(mdb->f->fd, offset, SEEK_SET); + len = read(mdb->f->fd,pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("read"); + return 0; + } + else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->fmt->pg_size); */ + return 0; + } + return len; +} +void mdb_swap_pgbuf(MdbHandle *mdb) +{ +char tmpbuf[MDB_PGSIZE]; + + memcpy(tmpbuf,mdb->pg_buf, MDB_PGSIZE); + memcpy(mdb->pg_buf,mdb->alt_pg_buf, MDB_PGSIZE); + memcpy(mdb->alt_pg_buf,tmpbuf,MDB_PGSIZE); +} + + +/* really stupid, just here for consistancy */ +unsigned char mdb_get_byte(unsigned char *buf, int offset) +{ + return buf[offset]; +} +unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+1 > mdb->fmt->pg_size) return -1; + mdb->cur_pos++; + return mdb->pg_buf[offset]; +} + +int mdb_get_int16(unsigned char *buf, int offset) +{ + return buf[offset+1]*256+buf[offset]; +} +int mdb_pg_get_int16(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+2 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=2; + return mdb_get_int16(mdb->pg_buf, offset); +} + +gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset) +{ + gint32 l = 0; + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + memcpy((char *)&l+1, &(mdb->pg_buf[offset]), 3); +#if 0 + printf("l=0x%08x 0x%08x\n",l,GINT32_FROM_BE(l)); +#endif + return GINT32_FROM_BE(l); +} +gint32 mdb_get_int24(unsigned char *buf, int offset) +{ + gint32 l = 0; + memcpy(&l, &buf[offset], 3); + return GINT32_FROM_LE(l); +} +gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + return mdb_get_int24(mdb->pg_buf, offset); +} + +long mdb_get_int32(unsigned char *buf, int offset) +{ + guint32 l; + memcpy(&l, &buf[offset], 4); + return (long)GINT32_FROM_LE(l); +} +long mdb_pg_get_int32(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_int32(mdb->pg_buf, offset); +} + +float mdb_get_single(unsigned char *buf, int offset) +{ + union {guint32 g; float f;} f; + memcpy(&f, &buf[offset], 4); + f.g = GUINT32_FROM_LE(f.g); + return f.f; +} +float mdb_pg_get_single(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_single(mdb->pg_buf, offset); +} + +double mdb_get_double(unsigned char *buf, int offset) +{ + union {guint64 g; double d;} d; + memcpy(&d, &buf[offset], 8); + d.g = GUINT64_FROM_LE(d.g); + return d.d; +} +double mdb_pg_get_double(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=8; + return mdb_get_double(mdb->pg_buf, offset); +} + + +int +mdb_set_pos(MdbHandle *mdb, int pos) +{ + if (pos<0 || pos >= mdb->fmt->pg_size) return 0; + + mdb->cur_pos=pos; + return pos; +} +int mdb_get_pos(MdbHandle *mdb) +{ + return mdb->cur_pos; +} diff --git a/data/poi_geodownload/libmdb/iconv.c b/data/poi_geodownload/libmdb/iconv.c new file mode 100644 index 00000000..9f41afe3 --- /dev/null +++ b/data/poi_geodownload/libmdb/iconv.c @@ -0,0 +1,63 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +int +mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest) +{ + unsigned int i; + + if (buf[offset]==0xff && buf[offset+1]==0xfe) { + strncpy(dest, &buf[offset+2], len-2); + dest[len-2]='\0'; + } else { + /* convert unicode to ascii, rather sloppily */ + for (i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ICONV +#include +#endif + +#define MDB_DEBUG 0 + +#define MDB_PGSIZE 4096 +#define MDB_MAX_OBJ_NAME 256 +#define MDB_MAX_COLS 256 +#define MDB_MAX_IDX_COLS 10 +#define MDB_CATALOG_PG 18 +#define MDB_MEMO_OVERHEAD 12 +#define MDB_BIND_SIZE 16384 + +enum { + MDB_PAGE_DB = 0, + MDB_PAGE_DATA, + MDB_PAGE_TABLE, + MDB_PAGE_INDEX, + MDB_PAGE_LEAF, + MDB_PAGE_MAP +}; +enum { + MDB_VER_JET3 = 0, + MDB_VER_JET4 = 1 +}; +enum { + MDB_FORM = 0, + MDB_TABLE, + MDB_MACRO, + MDB_SYSTEM_TABLE, + MDB_REPORT, + MDB_QUERY, + MDB_LINKED_TABLE, + MDB_MODULE, + MDB_RELATIONSHIP, + MDB_UNKNOWN_09, + MDB_UNKNOWN_0A, + MDB_DATABASE_PROPERTY, + MDB_ANY = -1 +}; +enum { + MDB_BOOL = 0x01, + MDB_BYTE = 0x02, + MDB_INT = 0x03, + MDB_LONGINT = 0x04, + MDB_MONEY = 0x05, + MDB_FLOAT = 0x06, + MDB_DOUBLE = 0x07, + MDB_SDATETIME = 0x08, + MDB_TEXT = 0x0a, + MDB_OLE = 0x0b, + MDB_MEMO = 0x0c, + MDB_REPID = 0x0f, + MDB_NUMERIC = 0x10 +}; + +/* SARG operators */ +enum { + MDB_OR = 1, + MDB_AND, + MDB_NOT, + MDB_EQUAL, + MDB_GT, + MDB_LT, + MDB_GTEQ, + MDB_LTEQ, + MDB_LIKE, + MDB_ISNULL, + MDB_NOTNULL +}; + +typedef enum { + MDB_TABLE_SCAN, + MDB_LEAF_SCAN, + MDB_INDEX_SCAN +} MdbStrategy; + +typedef enum { + MDB_NOFLAGS = 0x00, + MDB_WRITABLE = 0x01 +} MdbFileFlags; + +enum { + MDB_DEBUG_LIKE = 0x0001, + MDB_DEBUG_WRITE = 0x0002, + MDB_DEBUG_USAGE = 0x0004, + MDB_DEBUG_OLE = 0x0008, + MDB_DEBUG_ROW = 0x0010, + MDB_USE_INDEX = 0x0020 +}; + +#define mdb_is_logical_op(x) (x == MDB_OR || \ + x == MDB_AND || \ + x == MDB_NOT ) + +#define mdb_is_relational_op(x) (x == MDB_EQUAL || \ + x == MDB_GT || \ + x == MDB_LT || \ + x == MDB_GTEQ || \ + x == MDB_LTEQ || \ + x == MDB_LIKE || \ + x == MDB_ISNULL || \ + x == MDB_NOTNULL ) + +enum { + MDB_ASC, + MDB_DESC +}; + +enum { + MDB_IDX_UNIQUE = 0x01, + MDB_IDX_IGNORENULLS = 0x02, + MDB_IDX_REQUIRED = 0x08 +}; + +#define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4) +#define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) + +/* hash to store registered backends */ +/* extern GHashTable *mdb_backends; */ + +/* forward declarations */ +typedef struct mdbindex MdbIndex; +typedef struct mdbsargtree MdbSargNode; + +typedef struct { + char *name; + unsigned char needs_length; /* or precision */ + unsigned char needs_scale; + unsigned char needs_quotes; +} MdbBackendType; + +typedef struct { + MdbBackendType *types_table; +} MdbBackend; + +typedef struct { + gboolean collect; + unsigned long pg_reads; +} MdbStatistics; + +typedef struct { + int fd; + gboolean writable; + char *filename; + guint32 jet_version; + guint32 db_key; + char db_passwd[14]; + MdbBackend *default_backend; + char *backend_name; + MdbStatistics *stats; + /* free map */ + int map_sz; + unsigned char *free_map; + /* reference count */ + int refs; +} MdbFile; + +/* offset to row count on data pages...version dependant */ +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; + +typedef struct { + MdbFile *f; + guint32 cur_pg; + guint16 row_num; + unsigned int cur_pos; + unsigned char pg_buf[MDB_PGSIZE]; + unsigned char alt_pg_buf[MDB_PGSIZE]; + unsigned int num_catalog; + GPtrArray *catalog; + MdbBackend *default_backend; + char *backend_name; + MdbFormatConstants *fmt; + MdbStatistics *stats; +#ifdef HAVE_ICONV + iconv_t iconv_out; +#endif +} MdbHandle; + +typedef struct { + MdbHandle *mdb; + char object_name[MDB_MAX_OBJ_NAME+1]; + int object_type; + unsigned long table_pg; /* misnomer since object may not be a table */ + unsigned long kkd_pg; + unsigned int kkd_rowid; + int num_props; + GArray *props; + GArray *columns; + int flags; +} MdbCatalogEntry; + +typedef struct { + gchar *name; + GHashTable *hash; +} MdbProperties; + +typedef union { + int i; + double d; + char s[256]; +} MdbAny; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; + int col_type; + int col_size; + void *bind_ptr; + int *len_ptr; + GHashTable *properties; + unsigned int num_sargs; + GPtrArray *sargs; + GPtrArray *idx_sarg_cache; + unsigned char is_fixed; + int query_order; + /* col_num is the current column order, + * does not include deletes */ + int col_num; + int cur_value_start; + int cur_value_len; + /* MEMO/OLE readers */ + guint32 cur_blob_pg; + int cur_blob_row; + int chunk_size; + /* numerics only */ + int col_prec; + int col_scale; + MdbProperties *props; + /* info needed for handling deleted/added columns */ + int fixed_offset; + int var_col_num; + /* row_col_num is the row column number order, + * including deleted columns */ + int row_col_num; +} MdbColumn; + +struct mdbsargtree { + int op; + MdbColumn *col; + MdbAny value; + void *parent; + MdbSargNode *left; + MdbSargNode *right; +}; + +typedef struct { + guint32 pg; + int start_pos; + int offset; + int len; + guint16 idx_starts[2000]; + unsigned char cache_value[256]; +} MdbIndexPage; + +typedef int (*MdbSargTreeFunc)(MdbSargNode *, gpointer *data); + +#define MDB_MAX_INDEX_DEPTH 10 + +typedef struct { + int cur_depth; + guint32 last_leaf_found; + int clean_up_mode; + MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; +} MdbIndexChain; + +typedef struct { + MdbCatalogEntry *entry; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned int num_cols; + GPtrArray *columns; + unsigned int num_rows; + int index_start; + unsigned int num_real_idxs; + unsigned int num_idxs; + GPtrArray *indices; + guint32 first_data_pg; + guint32 cur_pg_num; + guint32 cur_phys_pg; + unsigned int cur_row; + int noskip_del; /* don't skip deleted rows */ + /* object allocation map */ + guint32 map_base_pg; + unsigned int map_sz; + unsigned char *usage_map; + /* pages with free space left */ + guint32 freemap_base_pg; + unsigned int freemap_sz; + unsigned char *free_usage_map; + /* query planner */ + MdbSargNode *sarg_tree; + MdbStrategy strategy; + MdbIndex *scan_idx; + MdbHandle *mdbidx; + MdbIndexChain *chain; + MdbProperties *props; + unsigned int num_var_cols; /* to know if row has variable columns */ + /* temp table */ + unsigned int is_temp_table; + GPtrArray *temp_table_pages; +} MdbTableDef; + +struct mdbindex { + int index_num; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned char index_type; + guint32 first_pg; + int num_rows; /* number rows in index */ + unsigned int num_keys; + short key_col_num[MDB_MAX_IDX_COLS]; + unsigned char key_col_order[MDB_MAX_IDX_COLS]; + unsigned char flags; + MdbTableDef *table; +}; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; +} MdbColumnProp; + +typedef struct { + void *value; + int siz; + int start; + unsigned char is_null; + unsigned char is_fixed; + int colnum; + int offset; +} MdbField; + +typedef struct { + int op; + MdbAny value; +} MdbSarg; + +/* mem.c */ +extern void mdb_init(); +extern void mdb_exit(); + +/* file.c */ +extern ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg); +extern ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg); +extern unsigned char mdb_get_byte(unsigned char *buf, int offset); +extern int mdb_get_int16(unsigned char *buf, int offset); +extern gint32 mdb_get_int24(unsigned char *buf, int offset); +extern long mdb_get_int32(unsigned char *buf, int offset); +extern float mdb_get_single(unsigned char *buf, int offset); +extern double mdb_get_double(unsigned char *buf, int offset); +extern unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset); +extern int mdb_pg_get_int16(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset); +extern long mdb_pg_get_int32(MdbHandle *mdb, int offset); +extern float mdb_pg_get_single(MdbHandle *mdb, int offset); +extern double mdb_pg_get_double(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset); +extern MdbHandle *mdb_open(char *filename, MdbFileFlags flags); +extern void mdb_close(MdbHandle *mdb); +extern MdbHandle *mdb_clone_handle(MdbHandle *mdb); +extern void mdb_swap_pgbuf(MdbHandle *mdb); +extern long _mdb_get_int32(unsigned char *buf, int offset); + +/* catalog.c */ +extern void mdb_free_catalog(MdbHandle *mdb); +extern GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type); +extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type); +extern char *mdb_get_objtype_string(int obj_type); + +/* table.c */ +extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry); +extern void mdb_free_tabledef(MdbTableDef *table); +extern MdbTableDef *mdb_read_table(MdbCatalogEntry *entry); +extern MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type); +extern void mdb_append_column(GPtrArray *columns, MdbColumn *in_col); +extern void mdb_free_columns(GPtrArray *columns); +extern GPtrArray *mdb_read_columns(MdbTableDef *table); +extern void mdb_table_dump(MdbCatalogEntry *entry); +extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos); +extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur_pos); +extern int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset); +extern guint16 read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len); +extern int mdb_is_user_table(MdbCatalogEntry *entry); +extern int mdb_is_system_table(MdbCatalogEntry *entry); + +/* data.c */ +extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr); +extern void mdb_data_dump(MdbTableDef *table); +extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr); +extern int mdb_rewind_table(MdbTableDef *table); +extern int mdb_fetch_row(MdbTableDef *table); +extern int mdb_is_fixed_col(MdbColumn *col); +extern char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size); +extern int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len); +extern int mdb_find_end_of_row(MdbHandle *mdb, int row); +extern int mdb_col_fixed_size(MdbColumn *col); +extern int mdb_col_disp_size(MdbColumn *col); +extern void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr); +extern int mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr); +extern int mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size); +extern void mdb_set_date_fmt(const char *); +extern int mdb_read_row(MdbTableDef *table, unsigned int row); + +/* dump.c */ +extern void buffer_dump(const unsigned char* buf, int start, int end); + +/* backend.c */ +extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); +extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); +extern void mdb_init_backends(); +extern void mdb_register_backend(MdbBackendType *backend, char *backend_name); +extern void mdb_remove_backends(); +extern int mdb_set_default_backend(MdbHandle *mdb, char *backend_name); +extern char *mdb_get_relationships(MdbHandle *mdb); + +/* sargs.c */ +extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields); +extern int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field); +extern void mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data); +extern int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data); +extern int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg); +extern int mdb_test_string(MdbSargNode *node, char *s); +extern int mdb_test_int(MdbSargNode *node, gint32 i); +extern int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg); + + + +/* index.c */ +extern GPtrArray *mdb_read_indices(MdbTableDef *table); +extern void mdb_index_dump(MdbTableDef *table, MdbIndex *idx); +extern void mdb_index_scan_free(MdbTableDef *table); +extern int mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg); +extern int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row); +extern void mdb_index_hash_text(guchar *text, guchar *hash); +extern void mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table); +extern int mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row); +extern void mdb_index_swap_n(unsigned char *src, int sz, unsigned char *dest); +extern void mdb_free_indices(GPtrArray *indices); +void mdb_index_page_reset(MdbIndexPage *ipg); +extern MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern MdbIndexPage *mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern void mdb_index_page_init(MdbIndexPage *ipg); + + +/* stats.c */ +extern void mdb_stats_on(MdbHandle *mdb); +extern void mdb_stats_off(MdbHandle *mdb); +extern void mdb_dump_stats(MdbHandle *mdb); + +/* like.c */ +extern int mdb_like_cmp(char *s, char *r); + +/* write.c */ +extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields); +extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size); +extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum); +extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields); +extern int mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size); +extern int mdb_pg_get_freespace(MdbHandle *mdb); +extern int mdb_update_row(MdbTableDef *table); +extern unsigned char *mdb_new_data_pg(MdbCatalogEntry *entry); + +/* map.c */ +extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size); +guint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg); + +/* props.c */ +extern GPtrArray *mdb_read_props_list(gchar *kkd, int len); +extern void mdb_free_props(MdbProperties *props); +extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len); + +/* worktable.c */ +extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name); +extern void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col); +extern void mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed); +extern void mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int column); +extern void mdb_temp_columns_end(MdbTableDef *table); + +/* options.c */ +extern int mdb_get_option(unsigned long optnum); +extern void mdb_debug(int klass, char *fmt, ...); + +/* iconv.c */ +extern int mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); +extern int mdb_ascii2unicode(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); + +#endif /* _mdbtools_h_ */ diff --git a/data/poi_geodownload/libmdb/index.c b/data/poi_geodownload/libmdb/index.c new file mode 100644 index 00000000..e840536e --- /dev/null +++ b/data/poi_geodownload/libmdb/index.c @@ -0,0 +1,905 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000-2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +MdbIndexPage *mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg); + +char idx_to_text[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0-7 0x00-0x07 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8-15 0x09-0x0f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16-23 0x10-0x17 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24-31 0x19-0x1f */ +' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32-39 0x20-0x27 */ +0x00, 0x00, 0x00, 0x00, 0x00, ' ', ' ', 0x00, /* 40-47 0x29-0x2f */ +'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', /* 48-55 0x30-0x37 */ +'^', '_', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56-63 0x39-0x3f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 64-71 0x40-0x47 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 72-79 0x49-0x4f H */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 80-87 0x50-0x57 P */ +'|', '}', '~', '5', '6', '7', '8', '9', /* 88-95 0x59-0x5f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 96-103 0x60-0x67 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 014-111 0x69-0x6f h */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 112-119 0x70-0x77 p */ +'|', '}', '~', 0x00, 0x00, 0x00, 0x00, 0x00, /* 120-127 0x78-0x7f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128-135 0x80-0x87 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ +0x00, 0x00, 0x00, 0x00, 0x00, '`', 0x00, 0x00, /* 0xc0-0xc7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ +0x00, '`', 0x00, '`', '`', '`', 0x00, 0x00, /* 0xe0-0xe7 */ +'f', 'f', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ +0x00, 0x00, 0x00, 'r', 0x00, 0x00, 'r', 0x00, /* 0xf0-0xf7 */ +0x81, 0x00, 0x00, 0x00, 'x', 0x00, 0x00, 0x00, /* 0xf8-0xff */ +}; + + +GPtrArray * +mdb_read_indices(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbIndex *pidx; + unsigned int i, j; + int idx_num, key_num, col_num; + int cur_pos, name_sz, idx2_sz, type_offset; + int index_start_pg = mdb->cur_pg; + gchar *tmpbuf; + + table->indices = g_ptr_array_new(); + + if (IS_JET4(mdb)) { + cur_pos = table->index_start + 52 * table->num_real_idxs; + idx2_sz = 28; + type_offset = 23; + } else { + cur_pos = table->index_start + 39 * table->num_real_idxs; + idx2_sz = 20; + type_offset = 19; + } + + tmpbuf = (gchar *) g_malloc(idx2_sz); + for (i=0;inum_idxs;i++) { + read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); + cur_pos += idx2_sz; + pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex)); + pidx->table = table; + pidx->index_num = mdb_get_int16(tmpbuf, 4); + pidx->index_type = tmpbuf[type_offset]; + g_ptr_array_add(table->indices, pidx); + } + g_free(tmpbuf); + + for (i=0;inum_idxs;i++) { + pidx = g_ptr_array_index (table->indices, i); + if (IS_JET4(mdb)) { + name_sz=read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmpbuf = g_malloc(name_sz); + read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); + cur_pos += name_sz; + mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); + g_free(tmpbuf); + } else { + read_pg_if(mdb, &cur_pos, 0); + name_sz=mdb->pg_buf[cur_pos++]; + read_pg_if_n(mdb, pidx->name, &cur_pos, name_sz); + cur_pos += name_sz; + pidx->name[name_sz]='\0'; + } + //fprintf(stderr, "index name %s\n", pidx->name); + } + + mdb_read_alt_pg(mdb, entry->table_pg); + mdb_read_pg(mdb, index_start_pg); + cur_pos = table->index_start; + idx_num=0; + for (i=0;inum_real_idxs;i++) { + if (IS_JET4(mdb)) cur_pos += 4; + do { + pidx = g_ptr_array_index (table->indices, idx_num++); + } while (pidx && pidx->index_type==2); + + /* if there are more real indexes than index entries left after + removing type 2's decrement real indexes and continue. Happens + on Northwind Orders table. + */ + if (!pidx) { + table->num_real_idxs--; + continue; + } + + pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, + fmt->tab_cols_start_offset + + (i*fmt->tab_ridx_entry_size)); + + key_num=0; + for (j=0;jkey_col_num[key_num] = col_num + 1; + pidx->key_col_order[key_num] = + (mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC; + key_num++; + } + pidx->num_keys = key_num; + + cur_pos += 4; + pidx->first_pg = read_pg_if_32(mdb, &cur_pos); + cur_pos += 4; + read_pg_if(mdb, &cur_pos, 0); + pidx->flags = mdb->pg_buf[cur_pos++]; + if (IS_JET4(mdb)) cur_pos += 9; + } + return NULL; +} +void +mdb_index_hash_text(guchar *text, guchar *hash) +{ + unsigned int k; + + for (k=0;k 0; i--) { + dest[j++] = src[i]; + } +} +void +mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg) +{ + //guint32 cache_int; + unsigned char *c; + + switch (col->col_type) { + case MDB_TEXT: + mdb_index_hash_text(sarg->value.s, idx_sarg->value.s); + break; + + case MDB_LONGINT: + idx_sarg->value.i = GUINT32_SWAP_LE_BE(sarg->value.i); + //cache_int = sarg->value.i * -1; + c = (unsigned char *) &(idx_sarg->value.i); + c[0] |= 0x80; + //printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[2], c[3]); + break; + + case MDB_INT: + break; + + default: + break; + } +} +#if 0 +int +mdb_index_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len) +{ +char tmpbuf[256]; +int lastchar; + + switch (col->col_type) { + case MDB_BYTE: + return mdb_test_int(sarg, mdb_pg_get_byte(mdb, offset)); + break; + case MDB_INT: + return mdb_test_int(sarg, mdb_pg_get_int16(mdb, offset)); + break; + case MDB_LONGINT: + return mdb_test_int(sarg, mdb_pg_get_int32(mdb, offset)); + break; + case MDB_TEXT: + strncpy(tmpbuf, &mdb->pg_buf[offset],255); + lastchar = len > 255 ? 255 : len; + tmpbuf[lastchar]='\0'; + return mdb_test_string(sarg, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +#endif +int +mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, unsigned char *buf, int len) +{ + unsigned int i, j; + MdbColumn *col; + MdbTableDef *table = idx->table; + MdbSarg *idx_sarg; + MdbSarg *sarg; + MdbField field; + MdbSargNode node; + //int c_offset = 0, + int c_len; + +#if 0 + fprintf(stderr,"mdb_index_test_sargs called on "); + for (i=0;ipg_buf[offset+i]); + fprintf(stderr,"\n"); +#endif + for (i=0;inum_keys;i++) { + //c_offset++; /* the per column null indicator/flags */ + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + /* + * This will go away eventually + */ + if (col->col_type==MDB_TEXT) { + //c_len = strlen(&mdb->pg_buf[offset + c_offset]); + c_len = strlen(buf); + } else { + c_len = col->col_size; + //fprintf(stderr,"Only text types currently supported. How did we get here?\n"); + } + /* + * If we have no cached index values for this column, + * create them. + */ + if (col->num_sargs && !col->idx_sarg_cache) { + col->idx_sarg_cache = g_ptr_array_new(); + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->sargs, j); + idx_sarg = g_memdup(sarg,sizeof(MdbSarg)); + //printf("calling mdb_index_cache_sarg\n"); + mdb_index_cache_sarg(col, sarg, idx_sarg); + g_ptr_array_add(col->idx_sarg_cache, idx_sarg); + } + } + + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->idx_sarg_cache, j); + /* XXX - kludge */ + node.op = sarg->op; + node.value = sarg->value; + //field.value = &mdb->pg_buf[offset + c_offset]; + field.value = buf; + field.siz = c_len; + field.is_null = FALSE; + if (!mdb_test_sarg(mdb, col, &node, &field)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + } + return 1; +} +/* + * pack the pages bitmap + */ +int +mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte = 0; + int elem = 0; + int len, start, i; + + start = ipg->idx_starts[elem++]; + + while (start) { + len = ipg->idx_starts[elem] - start; + fprintf(stdout, "len is %d\n", len); + for (i=0; i < len; i++) { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mdb->pg_buf[mask_pos++] = mask_byte; + mask_byte = 0; + } + /* upon reaching the len, set the bit */ + } + mask_byte = (1 << mask_bit) | mask_byte; + fprintf(stdout, "mask byte is %02x at %d\n", mask_byte, mask_pos); + start = ipg->idx_starts[elem++]; + } + /* flush the last byte if any */ + mdb->pg_buf[mask_pos++] = mask_byte; + /* remember to zero the rest of the bitmap */ + for (i = mask_pos; i < 0xf8; i++) { + mdb->pg_buf[mask_pos++] = 0; + } + return 0; +} +/* + * unpack the pages bitmap + */ +int +mdb_index_unpack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte; + int start = 0xf8; + int elem = 0; + int len = 0; + + ipg->idx_starts[elem++]=start; + +#if 0 + fprintf(stdout, "Unpacking index page %u\n", ipg->pg); +#endif + do { + len = 0; + do { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mask_pos++; + } + mask_byte = mdb->pg_buf[mask_pos]; + len++; + } while (mask_pos <= 0xf8 && !((1 << mask_bit) & mask_byte)); + //fprintf(stdout, "%d %d %d %d\n", mask_pos, mask_bit, mask_byte, len); + + start += len; + if (mask_pos < 0xf8) ipg->idx_starts[elem++]=start; + + } while (mask_pos < 0xf8); + + /* if we zero the next element, so we don't pick up the last pages starts*/ + ipg->idx_starts[elem]=0; + + return elem; +} +/* + * find the next entry on a page (either index or leaf). Uses state information + * stored in the MdbIndexPage across calls. + */ +int +mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg) +{ + if (!ipg->pg) return 0; + + /* if this page has not been unpacked to it */ + if (!ipg->idx_starts[0]){ + //fprintf(stdout, "Unpacking page %d\n", ipg->pg); + mdb_index_unpack_bitmap(mdb, ipg); + } + + + if (ipg->idx_starts[ipg->start_pos + 1]==0) return 0; + ipg->len = ipg->idx_starts[ipg->start_pos+1] - ipg->idx_starts[ipg->start_pos]; + ipg->start_pos++; + //fprintf(stdout, "Start pos %d\n", ipg->start_pos); + + return ipg->len; +} +void mdb_index_page_reset(MdbIndexPage *ipg) +{ + ipg->offset = 0xf8; /* start byte of the index entries */ + ipg->start_pos=0; + ipg->len = 0; + ipg->idx_starts[0]=0; +} +void mdb_index_page_init(MdbIndexPage *ipg) +{ + memset(ipg, 0, sizeof(MdbIndexPage)); + mdb_index_page_reset(ipg); +} +/* + * find the next leaf page if any given a chain. Assumes any exhausted leaf + * pages at the end of the chain have been peeled off before the call. + */ +MdbIndexPage * +mdb_find_next_leaf(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg, *newipg; + guint32 pg; + guint passed = 0; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * If we are at the first page deep and it's not an index page then + * we are simply done. (there is no page to find + */ + + if (mdb->pg_buf[0]==MDB_PAGE_LEAF) { + /* Indexes can have leaves at the end that don't appear + * in the upper tree, stash the last index found so + * we can follow it at the end. */ + chain->last_leaf_found = ipg->pg; + return ipg; + } + + /* + * apply sargs here, currently we don't + */ + do { + ipg->len = 0; + //printf("finding next on pg %lu\n", ipg->pg); + if (!mdb_index_find_next_on_page(mdb, ipg)) { + //printf("find_next_on_page returned 0\n"); + return 0; + } + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 3); + //printf("Looking at pg %lu at %lu %d\n", pg, ipg->offset, ipg->len); + ipg->offset += ipg->len; + + /* + * add to the chain and call this function + * recursively. + */ + newipg = mdb_chain_add_page(mdb, chain, pg); + newipg = mdb_find_next_leaf(mdb, idx, chain); + //printf("returning pg %lu\n",newipg->pg); + return newipg; + } while (!passed); + /* no more pages */ + return NULL; + +} +MdbIndexPage * +mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg) +{ + MdbIndexPage *ipg; + + chain->cur_depth++; + if (chain->cur_depth > MDB_MAX_INDEX_DEPTH) { + fprintf(stderr,"Error! maximum index depth of %d exceeded. This is probably due to a programming bug, If you are confident that your indexes really are this deep, adjust MDB_MAX_INDEX_DEPTH in mdbtools.h and recompile.\n", MDB_MAX_INDEX_DEPTH); + exit(1); + } + ipg = &(chain->pages[chain->cur_depth - 1]); + mdb_index_page_init(ipg); + ipg->pg = pg; + + return ipg; +} +/* + * returns the bottom page of the IndexChain, if IndexChain is empty it + * initializes it by reading idx->first_pg (the root page) + */ +MdbIndexPage * +mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + /* + * if it's new use the root index page (idx->first_pg) + */ + if (!chain->cur_depth) { + ipg = &(chain->pages[0]); + mdb_index_page_init(ipg); + chain->cur_depth = 1; + ipg->pg = idx->first_pg; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + } else { + ipg = &(chain->pages[chain->cur_depth - 1]); + ipg->len = 0; + } + + mdb_read_pg(mdb, ipg->pg); + + return ipg; +} +/* + * unwind the stack and search for new leaf node + */ +MdbIndexPage * +mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + //printf("page %lu finished\n",ipg->pg); + if (chain->cur_depth==1) { + //printf("cur_depth == 1 we're out\n"); + return NULL; + } + /* + * unwind the stack until we find something or reach + * the top. + */ + ipg = NULL; + while (chain->cur_depth>1 && ipg==NULL) { + //printf("chain depth %d\n", chain->cur_depth); + chain->cur_depth--; + ipg = mdb_find_next_leaf(mdb, idx, chain); + if (ipg) mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) { + //printf("last leaf %lu\n", chain->last_leaf_found); + return NULL; + } + return ipg; +} +/* + * the main index function. + * caller provides an index chain which is the current traversal of index + * pages from the root page to the leaf. Initially passed as blank, + * mdb_index_find_next will store it's state information here. Each invocation + * then picks up where the last one left off, allowing us to scroll through + * the index one by one. + * + * Sargs are applied here but also need to be applied on the whole row b/c + * text columns may return false positives due to hashing and non-index + * columns with sarg values can't be tested here. + */ +int +mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row) +{ + MdbIndexPage *ipg; + int passed = 0; + int idx_sz; + int idx_start = 0; + MdbColumn *col; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * loop while the sargs don't match + */ + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + if (!chain->clean_up_mode) { + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) return 0; + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) + return 0; + } + } + *row = mdb->pg_buf[ipg->offset + ipg->len - 1]; +#if 0 + printf("page: "); + buffer_dump(mdb->pg_buf, ipg->offset+ipg->len-4, ipg->offset+ipg->len-2); +#endif + *pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); +#if 0 + printf("row = %d pg = %lu ipg->pg = %lu offset = %lu len = %d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len); +#endif + col=g_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1); + idx_sz = mdb_col_fixed_size(col); + /* handle compressed indexes, single key indexes only? */ + if (idx->num_keys==1 && idx_sz>0 && ipg->len - 4 < idx_sz) { +#if 0 + printf("short index found\n"); + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->offset], ipg->len); +#if 0 + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + } else { + idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz); + } + + //idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + passed = mdb_index_test_sargs(mdb, idx, ipg->cache_value, idx_sz); + +// printf("passed=%d\n", passed); + + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); + ipg->offset += ipg->len; + + } while (!passed); + +#if 0 + fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->len); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + + return ipg->len; +} +/* + * XXX - FIX ME + * This function is grossly inefficient. It scans the entire index building + * an IndexChain to a specific row. We should be checking the index pages + * for matches against the indexed fields to find the proper leaf page, but + * getting it working first and then make it fast! + */ +int +mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row) +{ + MdbIndexPage *ipg; + int passed = 0; + guint32 datapg; + guint16 datarow; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + /* back to top? We're done */ + if (chain->cur_depth==1) + return 0; + + /* + * unwind the stack until we find something or reach + * the top. + */ + while (chain->cur_depth>1) { + chain->cur_depth--; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) + return 0; + } + /* test row and pg */ + datarow = mdb->pg_buf[ipg->offset + ipg->len - 1]; + datapg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + + if (datapg == pg && datarow == row) { + passed = 1; + } + ipg->offset += ipg->len; + } while (!passed); + + /* index chain from root to leaf should now be in "chain" */ + return 1; +} + +void mdb_index_walk(MdbTableDef *table, MdbIndex *idx) +{ +MdbHandle *mdb = table->entry->mdb; +int cur_pos = 0; +unsigned char marker; +MdbColumn *col; +unsigned int i; + + if (idx->num_keys!=1) return; + + mdb_read_pg(mdb, idx->first_pg); + cur_pos = 0xf8; + + for (i=0;inum_keys;i++) { + marker = mdb->pg_buf[cur_pos++]; + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + //printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size); + } +} +void +mdb_index_dump(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + + fprintf(stdout,"index number %d\n", idx->index_num); + fprintf(stdout,"index name %s\n", idx->name); + fprintf(stdout,"index first page %d\n", idx->first_pg); + fprintf(stdout,"index rows %d\n", idx->num_rows); + if (idx->index_type==1) fprintf(stdout,"index is a primary key\n"); + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + fprintf(stdout,"Column %s(%d) Sorted %s Unique: %s\n", + col->name, + idx->key_col_num[i], + idx->key_col_order[i]==MDB_ASC ? "ascending" : "descending", + idx->flags & MDB_IDX_UNIQUE ? "Yes" : "No" + ); + } + mdb_index_walk(table, idx); +} +/* + * compute_cost tries to assign a cost to a given index using the sargs + * available in this query. + * + * Indexes with no matching sargs are assigned 0 + * Unique indexes are preferred over non-uniques + * Operator preference is equal, like, isnull, others + */ +int mdb_index_compute_cost(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + MdbSarg *sarg = NULL; + int not_all_equal = 0; + + if (!idx->num_keys) return 0; + if (idx->num_keys > 1) { + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + if (col->sargs) sarg = g_ptr_array_index (col->sargs, 0); + if (!sarg || sarg->op != MDB_EQUAL) not_all_equal++; + } + } + + col=g_ptr_array_index(table->columns,idx->key_col_num[0]-1); + /* + * if this is the first key column and there are no sargs, + * then this index is useless. + */ + if (!col->num_sargs) return 0; + + sarg = g_ptr_array_index (col->sargs, 0); + + /* + * a like with a wild card first is useless as a sarg */ + if (sarg->op == MDB_LIKE && sarg->value.s[0]=='%') + return 0; + + /* + * this needs a lot of tweaking. + */ + if (idx->flags & MDB_IDX_UNIQUE) { + if (idx->num_keys == 1) { + //printf("op is %d\n", sarg->op); + switch (sarg->op) { + case MDB_EQUAL: + return 1; break; + case MDB_LIKE: + return 4; break; + case MDB_ISNULL: + return 12; break; + default: + return 8; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 2; + else return 1; + break; + case MDB_LIKE: + return 6; break; + case MDB_ISNULL: + return 12; break; + default: + return 9; break; + } + } + } else { + if (idx->num_keys == 1) { + switch (sarg->op) { + case MDB_EQUAL: + return 2; break; + case MDB_LIKE: + return 5; break; + case MDB_ISNULL: + return 12; break; + default: + return 10; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 3; + else return 2; + break; + case MDB_LIKE: + return 7; break; + case MDB_ISNULL: + return 12; break; + default: + return 11; break; + } + } + } + return 0; +} +/* + * choose_index runs mdb_index_compute_cost for each available index and picks + * the best. + * + * Returns strategy to use (table scan, or index scan) + */ +MdbStrategy +mdb_choose_index(MdbTableDef *table, int *choice) +{ + unsigned int i; + MdbIndex *idx; + int cost = 0; + int least = 99; + + *choice = -1; + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + cost = mdb_index_compute_cost(table, idx); + //printf("cost for %s is %d\n", idx->name, cost); + if (cost && cost < least) { + least = cost; + *choice = i; + } + } + /* and the winner is: *choice */ + if (least==99) return MDB_TABLE_SCAN; + return MDB_INDEX_SCAN; +} +void +mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table) +{ + int i; + + if (mdb_get_option(MDB_USE_INDEX) && mdb_choose_index(table, &i) == MDB_INDEX_SCAN) { + table->strategy = MDB_INDEX_SCAN; + table->scan_idx = g_ptr_array_index (table->indices, i); + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + //printf("best index is %s\n",table->scan_idx->name); + } + //printf("TABLE SCAN? %d\n", table->strategy); +} +void +mdb_index_scan_free(MdbTableDef *table) +{ + if (table->chain) { + g_free(table->chain); + table->chain = NULL; + } + if (table->mdbidx) { + mdb_close(table->mdbidx); + table->mdbidx = NULL; + } +} + +void mdb_free_indices(GPtrArray *indices) +{ + unsigned int i; + + if (!indices) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(indices, i)); + g_ptr_array_free(indices, TRUE); +} diff --git a/data/poi_geodownload/libmdb/kkd.c b/data/poi_geodownload/libmdb/kkd.c new file mode 100644 index 00000000..ea72887c --- /dev/null +++ b/data/poi_geodownload/libmdb/kkd.c @@ -0,0 +1,149 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +/* +** Note: This code is mostly garbage right now...just a test to parse out the +** KKD structures. +*/ + +GArray *mdb_get_column_props(MdbCatalogEntry *entry, int start) +{ +int pos, cnt=0; +int len, tmp, cplen; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; + + entry->props = g_array_new(FALSE,FALSE,sizeof(MdbColumnProp)); + len = mdb_pg_get_int16(mdb,start); + pos = start + 6; + while (pos < start+len) { + tmp = mdb_pg_get_int16(mdb,pos); /* length of string */ + pos += 2; + cplen = tmp > MDB_MAX_OBJ_NAME ? MDB_MAX_OBJ_NAME : tmp; + g_memmove(prop.name,&mdb->pg_buf[pos],cplen); + prop.name[cplen]='\0'; + pos += tmp; + g_array_append_val(entry->props, prop.name); + cnt++; + } + entry->num_props = cnt; + return entry->props; +} + +GHashTable *mdb_get_column_def(MdbCatalogEntry *entry, int start) +{ +GHashTable *hash = NULL; +MdbHandle *mdb = entry->mdb; +MdbColumnProp prop; +int tmp, pos, col_num, val_len, i; +int len, col_type; +unsigned char c; +int end; + + fprintf(stdout,"\n data\n"); + fprintf(stdout,"-------\n"); + len = mdb_pg_get_int16(mdb,start); + fprintf(stdout,"length = %3d\n",len); + pos = start + 6; + end = start + len; + while (pos < end) { + fprintf(stdout,"pos = %3d\n",pos); + start = pos; + tmp = mdb_pg_get_int16(mdb,pos); /* length of field */ + pos += 2; + col_type = mdb_pg_get_int16(mdb,pos); /* ??? */ + pos += 2; + col_num = 0; + if (col_type) { + col_num = mdb_pg_get_int16(mdb,pos); + pos += 2; + } + val_len = mdb_pg_get_int16(mdb,pos); + pos += 2; + fprintf(stdout,"length = %3d %04x %2d %2d ",tmp, col_type, col_num, val_len); + for (i=0;ipg_buf[pos+i]; + if (isprint(c)) + fprintf(stdout," %c",c); + else + fprintf(stdout," %02x",c); + + } + pos = start + tmp; + prop = g_array_index(entry->props,MdbColumnProp,col_num); + fprintf(stdout," Property %s",prop.name); + fprintf(stdout,"\n"); + } + return hash; +} +void mdb_kkd_dump(MdbCatalogEntry *entry) +{ +int rows; +int kkd_start, kkd_end; +int i, tmp, pos, row_type, datapos=0; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; +int rowid = entry->kkd_rowid; + + + mdb_read_pg(mdb, entry->kkd_pg); + rows = mdb_pg_get_int16(mdb,8); + fprintf(stdout,"number of rows = %d\n",rows); + kkd_start = mdb_pg_get_int16(mdb,10+rowid*2); + fprintf(stdout,"kkd start = %d %04x\n",kkd_start,kkd_start); + kkd_end = mdb->fmt->pg_size; + for (i=0;ifmt->pg_size && + tmp > kkd_start && + tmp < kkd_end) { + kkd_end = tmp; + } + } + fprintf(stdout,"kkd end = %d %04x\n",kkd_end,kkd_end); + pos = kkd_start + 4; /* 4 = K K D \0 */ + while (pos < kkd_end) { + tmp = mdb_pg_get_int16(mdb,pos); + row_type = mdb_pg_get_int16(mdb,pos+4); + fprintf(stdout,"row size = %3d type = 0x%02x\n",tmp,row_type); + if (row_type==0x80) { + fprintf(stdout,"\nColumn Properties\n"); + fprintf(stdout,"-----------------\n"); + mdb_get_column_props(entry,pos); + for (i=0;inum_props;i++) { + prop = g_array_index(entry->props,MdbColumnProp,i); + fprintf(stdout,"%3d %s\n",i,prop.name); + } + } + if (row_type==0x01) datapos = pos; + pos += tmp; + } + + if (datapos) { + mdb_get_column_def(entry, datapos); + } +} + diff --git a/data/poi_geodownload/libmdb/like.c b/data/poi_geodownload/libmdb/like.c new file mode 100644 index 00000000..0a23d45c --- /dev/null +++ b/data/poi_geodownload/libmdb/like.c @@ -0,0 +1,78 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_like_cmp + * @s: String to search within. + * @r: Search pattern. + * + * Tests the string @s to see if it matches the search pattern @r. In the + * search pattern, a percent sign indicates matching on any number of + * characters, and an underscore indicates matching any single character. + * + * Returns: 1 if the string matches, 0 if the string does not match. + */ +int mdb_like_cmp(char *s, char *r) +{ + unsigned int i; + int ret; + + mdb_debug(MDB_DEBUG_LIKE, "comparing %s and %s", s, r); + switch (r[0]) { + case '\0': + if (s[0]=='\0') { + return 1; + } else { + return 0; + } + case '_': + /* skip one character */ + return mdb_like_cmp(&s[1],&r[1]); + case '%': + /* skip any number of characters */ + /* the strlen(s)+1 is important so the next call can */ + /* if there are trailing characters */ + for(i=0;i= pgnum) ? start_pg-pgnum+1 : 0; + for (; ifmt->pg_size - 4) * 8 pages. + * + * map_ind gives us the starting usage_map entry + * offset gives us a page offset into the bitmap + */ + usage_bitlen = (mdb->fmt->pg_size - 4) * 8; + max_map_pgs = (map_sz - 1) / 4; + map_ind = (start_pg + 1) / usage_bitlen; + offset = (start_pg + 1) % usage_bitlen; + + for (; map_indfmt->pg_size) { + fprintf(stderr, "Oops! didn't get a full page at %d\n", map_pg); + exit(1); + } + + usage_bitmap = mdb->alt_pg_buf + 4; + for (i=offset; ientry; + MdbHandle *mdb = entry->mdb; + guint32 pgnum; + guint32 cur_pg = 0; + int free_space; + + do { + pgnum = mdb_map_find_next(mdb, + table->free_usage_map, + table->freemap_sz, cur_pg); + printf("looking at page %d\n", pgnum); + if (!pgnum) { + /* allocate new page */ + pgnum = mdb_alloc_page(table); + return pgnum; + } + cur_pg = pgnum; + + mdb_read_pg(mdb, pgnum); + free_space = mdb_pg_get_freespace(mdb); + + } while (free_space < row_size); + + printf("page %d has %d bytes left\n", pgnum, free_space); + + return pgnum; +} diff --git a/data/poi_geodownload/libmdb/mem.c b/data/poi_geodownload/libmdb/mem.c new file mode 100644 index 00000000..9c518321 --- /dev/null +++ b/data/poi_geodownload/libmdb/mem.c @@ -0,0 +1,50 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_init: + * + * Initializes the LibMDB library. This function should be called exactly once + * by calling program and prior to any other function. + * + **/ +void mdb_init() +{ + mdb_init_backends(); +} + +/** + * mdb_exit: + * + * Cleans up the LibMDB library. This function should be called exactly once + * by the calling program prior to exiting (or prior to final use of LibMDB + * functions). + * + **/ +void mdb_exit() +{ + mdb_remove_backends(); +} diff --git a/data/poi_geodownload/libmdb/money.c b/data/poi_geodownload/libmdb/money.c new file mode 100644 index 00000000..7f2cf657 --- /dev/null +++ b/data/poi_geodownload/libmdb/money.c @@ -0,0 +1,139 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 1998-1999 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define MAXPRECISION 20 +/* +** these routines are copied from the freetds project which does something +** very similiar +*/ + +static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier); +static int do_carry(unsigned char *product); +static char *array_to_string(unsigned char *array, int unsigned scale, char *s); + +/** + * mdb_money_to_string + * @mdb: Handle to open MDB database file + * @start: Offset of the field within the current page + * @s: String that will receieve the value + * + * Returns: the string that has received the value. + */ +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s) +{ + int num_bytes = 8; + int i; + int neg=0; + unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION]; + unsigned char product[MAXPRECISION]; + unsigned char money[num_bytes]; + + memset(multiplier,0,MAXPRECISION); + memset(product,0,MAXPRECISION); + multiplier[0]=1; + memcpy(money, mdb->pg_buf + start, num_bytes); + + /* Perform two's complement for negative numbers */ + if (money[7] & 0x80) { + neg = 1; + for (i=0;i9) { + product[j+1]+=product[j]/10; + product[j]=product[j]%10; + } + } + if (product[j]>9) { + product[j]=product[j]%10; + } + return 0; +} +static char *array_to_string(unsigned char *array, unsigned int scale, char *s) +{ + unsigned int top, i, j=0; + + for (top=MAXPRECISION;(top>0) && (top-1>scale) && !array[top-1];top--); + + if (top == 0) { + s[j++] = '0'; + } else { + for (i=top; i>0; i--) { + if (j == top-scale) s[j++]='.'; + s[j++]=array[i-1]+'0'; + } + } + s[j]='\0'; + + return s; +} diff --git a/data/poi_geodownload/libmdb/options.c b/data/poi_geodownload/libmdb/options.c new file mode 100644 index 00000000..cdbbc662 --- /dev/null +++ b/data/poi_geodownload/libmdb/options.c @@ -0,0 +1,86 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define DEBUG 1 + +static unsigned long opts; +static int optset; + +static void load_options(); + +void +mdb_debug(int klass, char *fmt, ...) +{ +#ifdef DEBUG + va_list ap; + + if (!optset) load_options(); + if (klass & opts) { + va_start(ap, fmt); + vfprintf (stdout,fmt, ap); + va_end(ap); + fprintf(stdout,"\n"); + } +#endif +} + +static void +load_options() +{ + char *opt; + char *s; + + if (!optset && (s=getenv("MDBOPTS"))) { + opt = strtok(s, ":"); + do { + if (!strcmp(opt, "use_index")) opts |= MDB_USE_INDEX; + if (!strcmp(opt, "debug_like")) opts |= MDB_DEBUG_LIKE; + if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE; + if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE; + if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE; + if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW; + if (!strcmp(opt, "debug_all")) { + opts |= MDB_DEBUG_LIKE; + opts |= MDB_DEBUG_WRITE; + opts |= MDB_DEBUG_USAGE; + opts |= MDB_DEBUG_OLE; + opts |= MDB_DEBUG_ROW; + } + opt = strtok(NULL,":"); + } while (opt); + } + optset = 1; +} +int +mdb_get_option(unsigned long optnum) +{ + if (!optset) load_options(); + return ((opts & optnum) > 0); +} diff --git a/data/poi_geodownload/libmdb/props.c b/data/poi_geodownload/libmdb/props.c new file mode 100644 index 00000000..61db9f54 --- /dev/null +++ b/data/poi_geodownload/libmdb/props.c @@ -0,0 +1,127 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +GPtrArray * +mdb_read_props_list(gchar *kkd, int len) +{ + guint32 record_len; + int pos = 0; + gchar *name; + GPtrArray *names = NULL; + int i = 0; + + names = g_ptr_array_new(); +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + pos += 2; +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos - 2, pos + record_len - 1); +#endif + name = g_malloc(record_len + 1); + strncpy(name, &kkd[pos], record_len); + name[record_len] = '\0'; + pos += record_len; + g_ptr_array_add(names, name); +#ifdef MDB_DEBUG + printf("new len = %d\n", names->len); +#endif + } + return names; +} +void +mdb_free_props(MdbProperties *props) +{ + if (!props) return; + + if (props->name) g_free(props->name); + g_free(props); +} +MdbProperties * +mdb_alloc_props() +{ + MdbProperties *props; + + props = g_malloc0(sizeof(MdbProperties)); + + return props; +} +MdbProperties * +mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len) +{ + guint32 record_len, name_len; + int pos = 0; + int elem, dtype, dsize; + gchar *name, *value; + MdbProperties *props; + int i = 0; + +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + + /* skip the name record */ + record_len = mdb_get_int16(kkd, pos); + pos += 4; + name_len = mdb_get_int16(kkd, pos); + pos += 2; + props = mdb_alloc_props(); + if (name_len) { + props->name = g_malloc(name_len + 1); + strncpy(props->name, &kkd[pos], name_len); + props->name[name_len]='\0'; + } + pos += name_len; + + props->hash = g_hash_table_new(g_str_hash, g_str_equal); + + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + elem = mdb_get_int16(kkd, pos + 4); + dtype = kkd[pos + 3]; + dsize = mdb_get_int16(kkd, pos + 6); + value = g_malloc(dsize + 1); + strncpy(value, &kkd[pos + 8], dsize); + value[dsize] = '\0'; + name = g_ptr_array_index(names,elem); +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos, pos + record_len - 1); + printf("elem %d dsize %d dtype %d\n", elem, dsize, dtype); +#endif + if (dtype == MDB_MEMO) dtype = MDB_TEXT; + if (dtype == MDB_BOOL) { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(kkd[pos + 8] ? "yes" : "no")); + } else { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize))); + } + g_free(value); + pos += record_len; + } + return props; + +} diff --git a/data/poi_geodownload/libmdb/sargs.c b/data/poi_geodownload/libmdb/sargs.c new file mode 100644 index 00000000..b14aaa94 --- /dev/null +++ b/data/poi_geodownload/libmdb/sargs.c @@ -0,0 +1,273 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * code for handling searchable arguments (sargs) used primary by the sql + * engine to support where clause handling. The sargs are configured in + * a tree with AND/OR operators connecting the child nodes. NOT operations + * have only one child on the left side. Logical operators (=,<,>,etc..) + * have no children. + * + * datatype support is a bit weak at this point. To add more types create + * a mdb_test_[type]() function and invoke it from mdb_test_sarg() + */ +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void +mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data) +{ + if (func(node, data)) + return; + if (node->left) mdb_sql_walk_tree(node->left, func, data); + if (node->right) mdb_sql_walk_tree(node->right, func, data); +} +int +mdb_test_string(MdbSargNode *node, char *s) +{ +int rc; + + if (node->op == MDB_LIKE) { + return mdb_like_cmp(s,node->value.s); + } + rc = strncmp(node->value.s, s, 255); + switch (node->op) { + case MDB_EQUAL: + if (rc==0) return 1; + break; + case MDB_GT: + if (rc<0) return 1; + break; + case MDB_LT: + if (rc>0) return 1; + break; + case MDB_GTEQ: + if (rc<=0) return 1; + break; + case MDB_LTEQ: + if (rc>=0) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op); + break; + } + return 0; +} +int mdb_test_int(MdbSargNode *node, gint32 i) +{ + switch (node->op) { + case MDB_EQUAL: + printf("comparing %x and %x %d\n", i, node->value.i, node->value.i == i); + if (node->value.i == i) return 1; + break; + case MDB_GT: + if (node->value.i < i) return 1; + break; + case MDB_LT: + if (node->value.i > i) return 1; + break; + case MDB_GTEQ: + if (node->value.i <= i) return 1; + break; + case MDB_LTEQ: + if (node->value.i >= i) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op); + break; + } + return 0; +} +#if 0 +#endif +int +mdb_find_indexable_sargs(MdbSargNode *node, gpointer data) +{ + MdbSarg sarg; + + if (node->op == MDB_OR || node->op == MDB_NOT) return 1; + + /* + * right now all we do is look for sargs that are anded together from + * the root. Later we may put together OR ops into a range, and then + * range scan the leaf pages. That is col1 = 2 or col1 = 4 becomes + * col1 >= 2 and col1 <= 4 for the purpose of index scans, and then + * extra rows are thrown out when the row is tested against the main + * sarg tree. range scans are generally only a bit better than table + * scanning anyway. + * + * also, later we should support the NOT operator, but it's generally + * a pretty worthless test for indexes, ie NOT col1 = 3, we are + * probably better off table scanning. + */ + if (mdb_is_relational_op(node->op) && node->col) { + //printf("op = %d value = %s\n", node->op, node->value.s); + sarg.op = node->op; + sarg.value = node->value; + mdb_add_sarg(node->col, &sarg); + } + return 0; +} +int +mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field) +{ +char tmpbuf[256]; +int lastchar; + + if (node->op == MDB_ISNULL) { + if (field->is_null) return 0; + else return 1; + } else if (node->op == MDB_NOTNULL) { + if (field->is_null) return 1; + else return 0; + } + switch (col->col_type) { + case MDB_BOOL: + return mdb_test_int(node, !field->is_null); + break; + case MDB_BYTE: + return mdb_test_int(node, (gint32)((char *)field->value)[0]); + break; + case MDB_INT: + return mdb_test_int(node, (gint32)mdb_get_int16(field->value, 0)); + break; + case MDB_LONGINT: + return mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0)); + break; + case MDB_TEXT: + if (IS_JET4(mdb)) { + mdb_unicode2ascii(mdb, field->value, 0, field->siz, tmpbuf); + } else { + strncpy(tmpbuf, field->value, 255); + lastchar = field->siz > 255 ? 255 : field->siz; + tmpbuf[lastchar]='\0'; + } + return mdb_test_string(node, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +int +mdb_find_field(int col_num, MdbField *fields, int num_fields) +{ + int i; + + for (i=0;iop)) { + col = node->col; + /* for const = const expressions */ + if (!col) { + return (node->value.i); + } + elem = mdb_find_field(col->col_num, fields, num_fields); + if (!mdb_test_sarg(mdb, col, node, &fields[elem])) + return 0; + } else { /* logical op */ + switch (node->op) { + case MDB_NOT: + rc = mdb_test_sarg_node(mdb, node->left, fields, num_fields); + return !rc; + break; + case MDB_AND: + if (!mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 0; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + case MDB_OR: + if (mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 1; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + } + } + return 1; +} +int +mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields) +{ + MdbSargNode *node; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + node = table->sarg_tree; + + /* there may not be a sarg tree */ + if (!node) return 1; + + return mdb_test_sarg_node(mdb, node, fields, num_fields); +} +#if 0 +int mdb_test_sargs(MdbHandle *mdb, MdbColumn *col, int offset, int len) +{ +MdbSarg *sarg; +int i; + + for (i=0;inum_sargs;i++) { + sarg = g_ptr_array_index (col->sargs, i); + if (!mdb_test_sarg(mdb, col, sarg, offset, len)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + + return 1; +} +#endif +int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg) +{ +MdbSarg *sarg; + if (!col->sargs) { + col->sargs = g_ptr_array_new(); + } + sarg = g_memdup(in_sarg,sizeof(MdbSarg)); + g_ptr_array_add(col->sargs, sarg); + col->num_sargs++; + + return 1; +} +int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg) +{ + MdbColumn *col; + unsigned int i; + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + if (!strcasecmp(col->name,colname)) { + return mdb_add_sarg(col, in_sarg); + } + } + /* else didn't find the column return 0! */ + return 0; +} diff --git a/data/poi_geodownload/libmdb/stats.c b/data/poi_geodownload/libmdb/stats.c new file mode 100644 index 00000000..1abf2857 --- /dev/null +++ b/data/poi_geodownload/libmdb/stats.c @@ -0,0 +1,74 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_stats_on: + * @mdb: Handle to the (open) MDB file to collect stats on. + * + * Begins collection of statistics on an MDBHandle. + * + * Statistics in LibMDB will track the number of reads from the MDB file. The + * collection of statistics is started and stopped with the mdb_stats_on and + * mdb_stats_off functions. Collected statistics are accessed by reading the + * MdbStatistics structure or calling mdb_dump_stats. + * + */ +void +mdb_stats_on(MdbHandle *mdb) +{ + if (!mdb->stats) + mdb->stats = g_malloc0(sizeof(MdbStatistics)); + + mdb->stats->collect = TRUE; +} +/** + * mdb_stats_off: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Turns off statistics collection. + * + * If mdb_stats_off is not called, statistics will be turned off when handle + * is freed using mdb_close. + **/ +void +mdb_stats_off(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + mdb->stats->collect = FALSE; +} +/** + * mdb_dump_stats: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Dumps current statistics to stdout. + **/ +void +mdb_dump_stats(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + fprintf(stdout, "Physical Page Reads: %lu\n", mdb->stats->pg_reads); +} diff --git a/data/poi_geodownload/libmdb/table.c b/data/poi_geodownload/libmdb/table.c new file mode 100644 index 00000000..d3afca8c --- /dev/null +++ b/data/poi_geodownload/libmdb/table.c @@ -0,0 +1,368 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +static gint mdb_col_comparer(MdbColumn **a, MdbColumn **b) +{ + if ((*a)->col_num > (*b)->col_num) + return 1; + else if ((*a)->col_num < (*b)->col_num) + return -1; + else + return 0; +} + +unsigned char mdb_col_needs_size(int col_type) +{ + if (col_type == MDB_TEXT) { + return TRUE; + } else { + return FALSE; + } +} + +MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + + table = (MdbTableDef *) g_malloc0(sizeof(MdbTableDef)); + table->entry=entry; + strcpy(table->name, entry->object_name); + + return table; +} +void mdb_free_tabledef(MdbTableDef *table) +{ + if (!table) return; + if (table->is_temp_table) { + unsigned int i; + for (i=0; itemp_table_pages->len; i++) + g_free(g_ptr_array_index(table->temp_table_pages,i)); + g_ptr_array_free(table->temp_table_pages, TRUE); + } + mdb_free_columns(table->columns); + mdb_free_indices(table->indices); + g_free(table->usage_map); + g_free(table->free_usage_map); + g_free(table); +} +MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + int len, row_start, pg_row; + char *buf; + + table = mdb_alloc_tabledef(entry); + + mdb_read_pg(mdb, entry->table_pg); + if (mdb->pg_buf[0] != 0x02) return NULL; /* not a valid table def page */ + + len = mdb_pg_get_int16(mdb,8); + + table->num_rows = mdb_pg_get_int32(mdb, fmt->tab_num_rows_offset); + table->num_var_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset-2); + table->num_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset); + table->num_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_idxs_offset); + table->num_real_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_ridxs_offset); + /* grab a copy of the usage map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_usage_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz)); + table->usage_map = g_memdup(buf + row_start, table->map_sz); + if (mdb_get_option(MDB_DEBUG_USAGE)) + buffer_dump(buf, row_start, row_start+table->map_sz-1); + mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d", + pg_row >> 8, pg_row & 0xff, row_start, table->map_sz); + + /* grab a copy of the free space page map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_free_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz)); + table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz); + mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n", + pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz); + + table->first_data_pg = mdb_pg_get_int16(mdb, fmt->tab_first_dpg_offset); + + return table; +} +MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + + for (i=0; inum_catalog; i++) { + entry = g_ptr_array_index(mdb->catalog, i); + if (!strcasecmp(entry->object_name, table_name)) + return mdb_read_table(entry); + } + + return NULL; +} + +/* +** read the next page if offset is > pg_size +** return true if page was read +*/ +int +read_pg_if(MdbHandle *mdb, int *cur_pos, int offset) +{ + if (*cur_pos + offset >= mdb->fmt->pg_size) { + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + *cur_pos = 8 - (mdb->fmt->pg_size - (*cur_pos)); + return 1; + } + return 0; +} +guint32 +read_pg_if_32(MdbHandle *mdb, int *cur_pos) +{ + unsigned char c[4]; + int i, rc = 0; + + for (i=0;i<4;i++) { + rc += read_pg_if(mdb, cur_pos, i); + c[i] = mdb->pg_buf[(*cur_pos) + i]; + } + return mdb_get_int32(c, 0); +} +guint16 +read_pg_if_16(MdbHandle *mdb, int *cur_pos) +{ + unsigned char low_byte, high_byte; + int rc = 0; + + rc += read_pg_if(mdb, cur_pos, 0); + low_byte = mdb->pg_buf[*cur_pos]; + rc += read_pg_if(mdb, cur_pos, 1); + high_byte = mdb->pg_buf[(*cur_pos) + 1]; + + return (high_byte * 256 + low_byte); +} +guint16 +read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len) +{ + if (*cur_pos + len < mdb->fmt->pg_size) { + memcpy(buf, &mdb->pg_buf[*cur_pos], len); + return 0; + } else { + int half = mdb->fmt->pg_size - *cur_pos; + memcpy(buf, &mdb->pg_buf[*cur_pos], half); + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + memcpy(buf + half, &mdb->pg_buf[8], len - half); + *cur_pos = 8 - half; + return 1; + } +} + +void mdb_append_column(GPtrArray *columns, MdbColumn *in_col) +{ + g_ptr_array_add(columns, g_memdup(in_col,sizeof(MdbColumn))); +} +void mdb_free_columns(GPtrArray *columns) +{ + unsigned int i; + + if (!columns) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(columns, i)); + g_ptr_array_free(columns, TRUE); +} +GPtrArray *mdb_read_columns(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *pcol; + unsigned char *col; + unsigned int i; + int cur_pos, name_sz; + + table->columns = g_ptr_array_new(); + + col = (unsigned char *) g_malloc(fmt->tab_col_entry_size); + + cur_pos = fmt->tab_cols_start_offset + + (table->num_real_idxs * fmt->tab_ridx_entry_size); + + /* new code based on patch submitted by Tim Nelson 2000.09.27 */ + + /* + ** column attributes + */ + for (i=0;inum_cols;i++) { +#ifdef MDB_DEBUG + /* printf("column %d\n", i); + buffer_dump(mdb->pg_buf, cur_pos ,cur_pos + 18); */ +#endif + read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size); + cur_pos += fmt->tab_col_entry_size; + pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn)); + + pcol->col_type = col[0]; + + // col_num_offset == 1 or 5 + pcol->col_num = col[fmt->col_num_offset]; + + //fprintf(stdout,"----- column %d -----\n",pcol->col_num); + // col_var == 3 or 7 + pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var); + //fprintf(stdout,"var column pos %d\n",pcol->var_col_num); + + // col_var == 5 or 9 + pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset); + //fprintf(stdout,"row column num %d\n",pcol->row_col_num); + + /* FIXME: can this be right in Jet3 and Jet4? */ + if (pcol->col_type == MDB_NUMERIC) { + pcol->col_prec = col[11]; + pcol->col_scale = col[12]; + } + + // col_fixed_offset == 13 or 15 + pcol->is_fixed = col[fmt->col_fixed_offset] & 0x01 ? 1 : 0; + + // col_fixed_offset == 13 or 15 + pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed); + //fprintf(stdout,"fixed column offset %d\n",pcol->fixed_offset); + //fprintf(stdout,"col type %s\n",pcol->is_fixed ? "fixed" : "variable"); + + if (pcol->col_type != MDB_BOOL) { + // col_size_offset == 16 or 23 + pcol->col_size = mdb_get_int16(col, fmt->col_size_offset); + } else { + pcol->col_size=0; + } + + g_ptr_array_add(table->columns, pcol); + } + + g_free (col); + + /* + ** column names - ordered the same as the column attributes table + */ + for (i=0;inum_cols;i++) { + pcol = g_ptr_array_index(table->columns, i); + + if (IS_JET4(mdb)) { + char *tmp_buf; + name_sz = read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmp_buf = (char *) g_malloc(name_sz); + read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz); + mdb_unicode2ascii(mdb, tmp_buf, 0, name_sz, pcol->name); + g_free(tmp_buf); + cur_pos += name_sz; + } else if (IS_JET3(mdb)) { + read_pg_if(mdb, &cur_pos, 0); + name_sz = mdb->pg_buf[cur_pos]; + cur_pos++; + read_pg_if_n(mdb, pcol->name, &cur_pos, name_sz); + pcol->name[name_sz]='\0'; + cur_pos += name_sz; + } else { + fprintf(stderr,"Unknown MDB version\n"); + } + } + + /* Sort the columns by col_num */ + g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer); + + table->index_start = cur_pos; + return table->columns; +} + +void mdb_table_dump(MdbCatalogEntry *entry) +{ +MdbTableDef *table; +MdbColumn *col; +int coln; +MdbIndex *idx; +MdbHandle *mdb = entry->mdb; +unsigned int i, bitn; +guint32 pgnum; + + table = mdb_read_table(entry); + fprintf(stdout,"definition page = %lu\n",entry->table_pg); + fprintf(stdout,"number of datarows = %d\n",table->num_rows); + fprintf(stdout,"number of columns = %d\n",table->num_cols); + fprintf(stdout,"number of indices = %d\n",table->num_real_idxs); + + mdb_read_columns(table); + mdb_read_indices(table); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + + fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n", + i, col->name, + mdb_get_coltype_string(mdb->default_backend, col->col_type), + col->col_size); + } + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_index_dump(table, idx); + } + if (table->usage_map) { + printf("pages reserved by this object\n"); + printf("usage map pg %" G_GUINT32_FORMAT "\n", + table->map_base_pg); + printf("free map pg %" G_GUINT32_FORMAT "\n", + table->freemap_base_pg); + pgnum = mdb_get_int32(table->usage_map,1); + /* the first 5 bytes of the usage map mean something */ + coln = 0; + for (i=5;imap_sz;i++) { + for (bitn=0;bitn<8;bitn++) { + if (table->usage_map[i] & 1 << bitn) { + coln++; + printf("%6" G_GUINT32_FORMAT, pgnum); + if (coln==10) { + printf("\n"); + coln = 0; + } else { + printf(" "); + } + } + pgnum++; + } + } + printf("\n"); + } +} + +int mdb_is_user_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && !(entry->flags & 0x80000002)) ? 1 : 0; +} +int mdb_is_system_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && (entry->flags & 0x80000002)) ? 1 : 0; +} diff --git a/data/poi_geodownload/libmdb/worktable.c b/data/poi_geodownload/libmdb/worktable.c new file mode 100644 index 00000000..6f893dcf --- /dev/null +++ b/data/poi_geodownload/libmdb/worktable.c @@ -0,0 +1,99 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* + * Temp table routines. These are currently used to generate mock results for + * commands like "list tables" and "describe table" + */ + +void +mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed) +{ + memset(tcol,0,sizeof(MdbColumn)); + strcpy(tcol->name, col_name); + tcol->col_type = col_type; + if ((col_type == MDB_TEXT) || (col_type == MDB_MEMO)) { + tcol->col_size = col_size; + } else { + tcol->col_size = mdb_col_fixed_size(tcol); + } + tcol->is_fixed = is_fixed; +} +void +mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int colnum) +{ + field->value = value; + field->siz = siz; + field->is_fixed = is_fixed; + field->is_null = is_null; + field->start = start; + field->colnum = colnum; +} +MdbTableDef * +mdb_create_temp_table(MdbHandle *mdb, char *name) +{ + MdbCatalogEntry *entry; + MdbTableDef *table; + + /* dummy up a catalog entry */ + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + entry->object_type = MDB_TABLE; + entry->table_pg = 0; + strcpy(entry->object_name, name); + + table = mdb_alloc_tabledef(entry); + table->columns = g_ptr_array_new(); + table->is_temp_table = 1; + table->temp_table_pages = g_ptr_array_new(); + + return table; +} +void +mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col) +{ + col->col_num = table->num_cols; + if (!col->is_fixed) + col->var_col_num = table->num_var_cols++; + g_ptr_array_add(table->columns, g_memdup(col, sizeof(MdbColumn))); + table->num_cols++; +} +/* + * Should be called after setting up all temp table columns + */ +void mdb_temp_columns_end(MdbTableDef *table) +{ + MdbColumn *col; + unsigned int i; + unsigned int start = 0; + + for (i=0; inum_cols; i++) { + col = g_ptr_array_index(table->columns, i); + if (col->is_fixed) { + col->fixed_offset = start; + start += col->col_size; + } + } +} diff --git a/data/poi_geodownload/libmdb/write.c b/data/poi_geodownload/libmdb/write.c new file mode 100644 index 00000000..1cff96a4 --- /dev/null +++ b/data/poi_geodownload/libmdb/write.c @@ -0,0 +1,878 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +//static int mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg); +static int mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields); + +void +_mdb_put_int16(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; +} +void +_mdb_put_int32(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; + value /= 256; + buf[offset+2] = value % 256; + value /= 256; + buf[offset+3] = value % 256; +} +ssize_t +mdb_write_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + /* is page beyond current size + 1 ? */ + if (status.st_size < offset + mdb->fmt->pg_size) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + lseek(mdb->f->fd, offset, SEEK_SET); + len = write(mdb->f->fd,mdb->pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("write"); + return 0; + } else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->pg_size); */ + return 0; + } + mdb->cur_pos = 0; + return len; +} + +static int +mdb_is_col_indexed(MdbTableDef *table, int colnum) +{ + unsigned int i, j; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + for (j=0;jnum_keys;j++) { + if (idx->key_col_num[j]==colnum) return 1; + } + } + return 0; +} +static int +mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols=0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = mdb_pg_get_int16(mdb, row_start); + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = mdb_pg_get_int16(mdb, row_end - bitmask_sz - 1); + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + for (i=0; inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 2; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + /* Use col->var_col_num because a deleted column is still + * present in the variable column offsets table for the row */ + } else if ((!fields[i].is_fixed) + && (col->var_col_num < row_var_cols)) { + col_start = var_col_offsets[col->var_col_num]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[(col->var_col_num)+1] - + col_start; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +static int +mdb_crack_row3(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols = 0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found, var_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + unsigned int num_jumps = 0, jumps_used = 0; + unsigned int col_ptr, row_len; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = pg_buf[row_start]; + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = pg_buf[row_end - bitmask_sz]; + row_len = row_end - row_start + 1; + num_jumps = (row_len - 1) / 256; + col_ptr = row_end - bitmask_sz - num_jumps - 1; + /* If last jump is a dummy value, ignore it */ + if ((col_ptr-row_start-row_var_cols)/256 < num_jumps) + num_jumps--; + + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + jumps_used = 0; + for (i=0; inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 1; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + } else if ((!fields[i].is_fixed) + && (var_cols_found < row_var_cols)) { + col_start = var_col_offsets[var_cols_found]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[var_cols_found+1] - + col_start; + var_cols_found++; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +/** + * mdb_crack_row: + * @table: Table that the row belongs to + * @row_start: offset to start of row on current page + * @row_end: offset to end of row on current page + * @fields: pointer to MdbField array to be popluated by mdb_crack_row + * + * Cracks a row buffer apart into its component fields. + * + * A row buffer is that portion of a data page which contains the values for + * that row. Its beginning and end can be found in the row offset table. + * + * The resulting MdbField array contains pointers into the row for each field + * present. Be aware that by modifying field[]->value, you would be modifying + * the row buffer itself, not a copy. + * + * This routine is mostly used internally by mdb_fetch_row() but may have some + * applicability for advanced application programs. + * + * Return value: number of fields present. + */ +int +mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; + + if (IS_JET4(mdb)) { + return mdb_crack_row4(table, row_start, row_end, fields); + } else { + return mdb_crack_row3(table, row_start, row_end, fields); + } +} + +static int +mdb_pack_null_mask(unsigned char *buffer, int num_fields, MdbField *fields) +{ + int pos = 0, bit = 0, byte = 0; + int i; + + /* 'Not null' bitmap */ + for (i=0; i> 8) & 0xff; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i> 8) & 0xff; + pos += 2; + + /* Offsets of the variable-length columns */ + for (i=num_fields; i>0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + row_buffer[pos++] = (fields[i-1].offset >> 8) & 0xff; + } + } + /* Number of variable-length columns */ + row_buffer[pos++] = var_cols & 0xff; + row_buffer[pos++] = (var_cols >> 8) & 0xff; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} + +static int +mdb_pack_row3(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields) +{ + unsigned int pos = 0; + unsigned int var_cols = 0; + unsigned int i, j; + unsigned char *offset_high; + + row_buffer[pos++] = num_fields; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + offset_high[j++] = (fields[i-1].offset << 8) & 0xff; + } + } + + /* Dummy jump table entry */ + if (offset_high[0] < (pos+(num_fields+7)/8-1)/255) { + row_buffer[pos++] = 0xff; + } + /* Jump table */ + for (i=0; i offset_high[i+1]) { + row_buffer[pos++] = var_cols-i; + } + } + g_free(offset_high); + + row_buffer[pos++] = var_cols; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} +int +mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, int unsigned num_fields, MdbField *fields) +{ + if (table->is_temp_table) { + unsigned int i; + for (i=0; icolumns, i); + fields[i].is_null = (fields[i].value) ? 0 : 1; + fields[i].colnum = i; + fields[i].is_fixed = c->is_fixed; + if ((c->col_type != MDB_TEXT) + && (c->col_type != MDB_MEMO)) { + fields[i].siz = c->col_size; + } + } + } + if (IS_JET4(table->entry->mdb)) { + return mdb_pack_row4(table, row_buffer, num_fields, fields); + } else { + return mdb_pack_row3(table, row_buffer, num_fields, fields); + } +} +int +mdb_pg_get_freespace(MdbHandle *mdb) +{ + int rows, free_start, free_end; + int row_count_offset = mdb->fmt->row_count_offset; + + rows = mdb_pg_get_int16(mdb, row_count_offset); + free_start = row_count_offset + 2 + (rows * 2); + free_end = mdb_pg_get_int16(mdb, row_count_offset + (rows * 2)); + mdb_debug(MDB_DEBUG_WRITE,"free space left on page = %d", free_end - free_start); + return (free_end - free_start); +} +unsigned char * +mdb_new_leaf_pg(MdbCatalogEntry *entry) +{ + MdbHandle *mdb = entry->mdb; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(mdb->fmt->pg_size); + + new_pg[0]=0x04; + new_pg[1]=0x01; + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} +unsigned char * +mdb_new_data_pg(MdbCatalogEntry *entry) +{ + MdbFormatConstants *fmt = entry->mdb->fmt; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(fmt->pg_size); + + new_pg[0]=0x01; + new_pg[1]=0x01; + _mdb_put_int16(new_pg, 2, fmt->pg_size - fmt->row_count_offset - 2); + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} + +int +mdb_update_indexes(MdbTableDef *table, int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + unsigned int i; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_debug(MDB_DEBUG_WRITE,"Updating %s (%d).", idx->name, idx->index_type); + if (idx->index_type==1) { + mdb_update_index(table, idx, num_fields, fields, pgnum, rownum); + } + } + return 1; +} + +int +mdb_init_index_chain(MdbTableDef *table, MdbIndex *idx) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + table->scan_idx = idx; + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + + return 1; +} + +int +mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int idx_xref[16]; + unsigned int i, j; + MdbIndexChain *chain; + MdbField idx_fields[10]; + + for (i = 0; i < idx->num_keys; i++) { + for (j = 0; j < num_fields; j++) { + // key_col_num is 1 based, can't remember why though + if (fields[j].colnum == idx->key_col_num[i]-1) { + idx_xref[i] = j; + idx_fields[i] = fields[j]; + } + } + } + for (i = 0; i < idx->num_keys; i++) { + fprintf(stdout, "key col %d (%d) is mapped to field %d (%d %d)\n", + i, idx->key_col_num[i], idx_xref[i], fields[idx_xref[i]].colnum, + fields[idx_xref[i]].siz); + } + for (i = 0; i < num_fields; i++) { + fprintf(stdout, "%d (%d %d)\n", + i, fields[i].colnum, + fields[i].siz); + } + + chain = g_malloc0(sizeof(MdbIndexChain)); + + mdb_index_find_row(mdb, idx, chain, pgnum, rownum); + printf("chain depth = %d\n", chain->cur_depth); + printf("pg = %" G_GUINT32_FORMAT "\n", + chain->pages[chain->cur_depth-1].pg); + //mdb_copy_index_pg(table, idx, &chain->pages[chain->cur_depth-1]); + mdb_add_row_to_leaf_pg(table, idx, &chain->pages[chain->cur_depth-1], idx_fields); + + return 1; +} + +int +mdb_insert_row(MdbTableDef *table, int num_fields, MdbField *fields) +{ + int new_row_size; + unsigned char row_buffer[4096]; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + guint32 pgnum; + guint16 rownum; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(row_buffer, 0, new_row_size-1); + } + pgnum = mdb_map_find_next_freepage(table, new_row_size); + if (!pgnum) { + fprintf(stderr, "Unable to allocate new page.\n"); + return 0; + } + + rownum = mdb_add_row_to_pg(table, row_buffer, new_row_size); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE, "writing page %d", pgnum); + if (!mdb_write_pg(mdb, pgnum)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + + mdb_update_indexes(table, num_fields, fields, pgnum, rownum); + + return 1; +} +/* + * Assumes caller has verfied space is available on page and adds the new + * row to the current pg_buf. + */ +guint16 +mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size) +{ + unsigned char *new_pg; + int num_rows, i, pos, row_start, row_end, row_size; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + if (pages->len == 0) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } else { + new_pg = g_ptr_array_index(pages, pages->len - 1); + if (mdb_get_int16(new_pg, 2) < new_row_size + 2) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } + } + + num_rows = mdb_get_int16(new_pg, fmt->row_count_offset); + pos = (num_rows == 0) ? fmt->pg_size : + mdb_get_int16(new_pg, fmt->row_count_offset + (num_rows*2)); + } else { /* is not a temp table */ + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + pos = fmt->pg_size; + + /* copy existing rows */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + } + + /* add our new row */ + pos -= new_row_size; + memcpy(&new_pg[pos], row_buffer, new_row_size); + /* add row to the row offset table */ + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); + + /* update number rows on this page */ + num_rows++; + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + /* update the freespace */ + _mdb_put_int16(new_pg,2,pos - fmt->row_count_offset - 2 - (num_rows*2)); + + /* copy new page over old */ + if (!table->is_temp_table) { + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + g_free(new_pg); + } + + return num_rows; +} +int +mdb_update_row(MdbTableDef *table) +{ +int row_start, row_end; +unsigned int i; +MdbColumn *col; +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +MdbField fields[256]; +unsigned char row_buffer[4096]; +int old_row_size, new_row_size, delta; +unsigned int num_fields; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + ((table->cur_row-1)*2)); + row_end = mdb_find_end_of_row(mdb, table->cur_row-1); + old_row_size = row_end - row_start; + + row_start &= 0x0FFF; /* remove flags */ + + mdb_debug(MDB_DEBUG_WRITE,"page %lu row %d start %d end %d", (unsigned long) table->cur_phys_pg, table->cur_row-1, row_start, row_end); + if (mdb_get_option(MDB_DEBUG_LIKE)) + buffer_dump(mdb->pg_buf, row_start, row_end); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr && mdb_is_col_indexed(table,i)) { + fprintf(stderr, "Attempting to update column that is part of an index\n"); + return 0; + } + } + num_fields = mdb_crack_row(table, row_start, row_end, fields); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr) { + printf("yes\n"); + fields[i].value = col->bind_ptr; + fields[i].siz = *(col->len_ptr); + } + } + + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) + buffer_dump(row_buffer, 0, new_row_size-1); + delta = new_row_size - old_row_size; + if ((mdb_pg_get_freespace(mdb) - delta) < 0) { + fprintf(stderr, "No space left on this page, update will not occur\n"); + return 0; + } + /* do it! */ + mdb_replace_row(table, table->cur_row-1, row_buffer, new_row_size); + return 0; +} +int +mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +unsigned char *new_pg; +guint16 num_rows; +int row_start, row_end, row_size; +int i, pos; + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE,"updating row %d on page %lu", row, (unsigned long) table->cur_phys_pg); + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + pos = mdb->fmt->pg_size; + + /* rows before */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* our row */ + pos -= new_row_size; + memcpy(&new_pg[pos], new_row, new_row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (row*2), pos); + + /* rows after */ + for (i=row+1;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* almost done, copy page over current */ + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + + g_free(new_pg); + + _mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + /* drum roll, please */ + if (!mdb_write_pg(mdb, table->cur_phys_pg)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + return 0; +} +static int +mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields) +/*, guint32 pgnum, guint16 rownum) +static int +mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg) +*/ +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + guint32 pg; + guint16 row; + unsigned char *new_pg; + unsigned char key_hash[256]; + unsigned char iflag; + int keycol; + + new_pg = mdb_new_leaf_pg(entry); + + mdb_index_page_reset(ipg); + mdb_read_pg(mdb, ipg->pg); + + /* do we support this index type yet? */ + if (idx->num_keys > 1) { + fprintf(stderr,"multikey indexes not yet supported, aborting\n"); + return 0; + } + keycol = idx->key_col_num[0]; + col = g_ptr_array_index (table->columns, keycol - 1); + printf("keycol = %d (%s)\n", keycol, col->name); + if (!mdb_is_fixed_col(col)) { + fprintf(stderr,"variable length key columns not yet supported, aborting\n"); + return 0; + } + printf("col size = %d\n", col->col_size); + + while (mdb_index_find_next_on_page(mdb, ipg)) { + + /* check for compressed indexes. */ + if (ipg->len < col->col_size + 1) { + fprintf(stderr,"compressed indexes not yet supported, aborting\n"); + return 0; + } + + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + row = mdb->pg_buf[ipg->offset + ipg->len - 1]; + iflag = mdb->pg_buf[ipg->offset]; + mdb_index_swap_n(&mdb->pg_buf[ipg->offset + 1], col->col_size, key_hash); + key_hash[col->col_size - 1] &= 0x7f; + printf("length = %d\n", ipg->len); + printf("iflag = %d pg = %" G_GUINT32_FORMAT + " row = %" G_GUINT16_FORMAT "\n", iflag, pg, row); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset + ipg->len - 1); + buffer_dump(mdb->pg_buf, ipg->offset + 1, ipg->offset + col->col_size); + buffer_dump(key_hash, 0, col->col_size - 1); + ipg->offset += ipg->len; + ipg->len = 0; + row++; + } + g_free(new_pg); + + return ipg->len; +} diff --git a/data/poi_geodownload/poi_geodownload.c b/data/poi_geodownload/poi_geodownload.c new file mode 100644 index 00000000..8062ca50 --- /dev/null +++ b/data/poi_geodownload/poi_geodownload.c @@ -0,0 +1,661 @@ +#include +#include "debug.h" +#include "coord.h" +#include "map.h" +#include "item.h" +#include "projection.h" +#include "plugin.h" + + +#include +#include +#include + +struct map_priv +{ + char *filename; + MdbHandle *h; + MdbHandle *h_idx; + MdbTableDef *table; + GPtrArray *table_col; + MdbColumn **cols; + MdbIndex *idx; + int idx_size; + enum item_type type; +}; + +struct map_rect_priv +{ + struct item item; + struct map_priv *m; + int cidx; +}; + +#if 0 +struct index_data { + unsigned char data[15]; +}; +struct poi { + char filename[1024]; + char icon[1024]; + long pos; + MdbHandle *h; + MdbHandle *h_idx; + MdbTableDef *table; + GPtrArray *table_col; + MdbColumn **cols; + MdbIndex *idx; + int idx_size; + struct index_data index_data; + MdbIndexChain chain; + struct poi *next; +} *poi_list; + +struct poi_data { + struct poi *poi; + int page; + int row; +}; + + char poipath[256]; + char poibmp[256]; + + +static void +print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) +{ + switch (col->col_type) { + case MDB_BOOL: + strcpy(buffer, mdb_pg_get_byte(h, col->cur_value_start) ? "True" : "False"); + break; + case MDB_BYTE: + sprintf(buffer, "%d", mdb_pg_get_byte(h, col->cur_value_start)); + break; + case MDB_LONGINT: + if (hex) + sprintf(buffer, "0x%lx", mdb_pg_get_int32(h, col->cur_value_start)); + else + sprintf(buffer, "%ld", mdb_pg_get_int32(h, col->cur_value_start)); + break; + case MDB_DOUBLE: + sprintf(buffer, "%f", mdb_pg_get_double(h, col->cur_value_start)); + break; + case MDB_TEXT: + sprintf(buffer, "%s", mdb_col_to_string (h, h->pg_buf, col-> cur_value_start, + col->col_type, col->cur_value_len)); + break; + default: + sprintf(buffer, "unknown (%d)", col->col_type); + } +} + +static void +setup_idx_data(struct index_data *idx, struct coord *c, unsigned int geoflags, int size) +{ + /* 7f 80 1c 91 0a 7f 80 5c f5 41 7f 80 00 00 05 */ + idx->data[0]=0x7f; + idx->data[1]=(c->x >> 24) ^ 0x80; + idx->data[2]=c->x >> 16; + idx->data[3]=c->x >> 8; + idx->data[4]=c->x; + idx->data[5]=0x7f; + idx->data[6]=(c->y >> 24) ^ 0x80; + idx->data[7]=c->y >> 16; + idx->data[8]=c->y >> 8; + idx->data[9]=c->y; + idx->data[10]=0x7f; + if (size > 12) { + idx->data[11]=0x80 | (geoflags >> 24); + idx->data[12]=geoflags >> 16; + idx->data[13]=geoflags >> 8; + idx->data[14]=geoflags; + } else { + idx->data[11]=geoflags; + } +} + +static void +setup_idx_rect(struct coord *rect, struct index_data *idx, int size) +{ + struct coord r[2]; + r[0].x=rect[0].x; + r[0].y=rect[1].y; + r[1].x=rect[1].x; + r[1].y=rect[0].y; +#if 0 + printf("low 0x%x 0%x\n", r[0].x, r[0].y); + printf("high 0x%x 0%x\n", r[1].x, r[1].y); +#endif + setup_idx_data(idx, r, 0, size); + setup_idx_data(idx+1, r+1, 0xffffffff, size); +} + +static int +load_row(struct poi *poi, int pg, int row) +{ + int row_start, row_end, offset; + unsigned int num_fields, i; + MdbField fields[256]; + MdbFormatConstants *fmt; + int debug=0; + + fmt=poi->h->fmt; + mdb_read_pg(poi->h, pg); + if (debug) + printf("Page Type %d row_count_offset %d\n",poi->h->pg_buf[0], fmt->row_count_offset); + if (debug > 1) { + for (i = 0; i <= row; i++) { + offset=(fmt->row_count_offset + 2) + i * 2; + printf("row %d %d 0x%x\n", i, offset, mdb_pg_get_int16(poi->h, offset)); + } + } + row_start = mdb_pg_get_int16(poi->h, (fmt->row_count_offset + 2) + row * 2); + if (row_start & 0x4000) + return 1; + row_end = mdb_find_end_of_row(poi->h, row); + if (debug) { + printf("start=0x%x end=0x%x\n", row_start, row_end); + buffer_dump(poi->h->pg_buf, row_start, row_end); + } + + poi->h->cur_pos=row_start & 0x1fff; + poi->table->cur_row=row+1; + num_fields = mdb_crack_row(poi->table, row_start & 0x1fff, row_end, fields); + if (debug) + printf("num_fields=%d\n", num_fields); + for (i = 0; i < num_fields; i++) { + poi->cols[i]->cur_value_start=fields[i].start; + poi->cols[i]->cur_value_len=fields[i].siz; + } + return 0; +} + +static MdbIndexPage * +index_next_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no next\n"); +#endif + if (!chain->clean_up_mode) { +#if 0 + printf("no cleanup\n"); +#endif + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { +#if 0 + printf("cleanup\n"); +#endif + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) { + printf("no last_leaf_found\n"); + return NULL; + } + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = + mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no find_next_on_page\n"); +#endif + return NULL; + } + } + } + return ipg; +} + +static int +index_next(struct poi *poi, struct index_data *idx) +{ + MdbIndexPage *ipg; + MdbIndexChain *chain = &poi->chain; + int row; + int pg; + int offset; + char *cmp, *low, *high; + int debug=0; + + + for(;;) { + for(;;) { + ipg=index_next_row(poi->h_idx, poi->idx, chain); + if (! ipg) + return 0; + row = poi->h_idx->pg_buf[ipg->offset + ipg->len - 1]; + pg = mdb_pg_get_int24_msb(poi->h_idx, ipg->offset + ipg->len - 4); + + offset=poi->idx_size+4-ipg->len; + memcpy(poi->index_data.data+offset, poi->h_idx->pg_buf+ipg->offset, ipg->len - 4); + cmp=poi->index_data.data; + low=idx[0].data; + high=idx[1].data; + if (debug > 1) { + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } +#if 0 + buffer_dump(poi->h_idx->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + ipg->offset += ipg->len; + if (memcmp(cmp, low, poi->idx_size) >= 0) { + if (memcmp(cmp, high, poi->idx_size) <=0 ) { + if (debug) { + printf("match\n"); + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } + break; + } else { + return 0; + } + } + if (debug > 1) + printf("row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + } + if (debug) + printf("match: row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + if (!load_row(poi, pg, row)) + break; + } + return 1; +} + +#endif + +static int +load_poi_table(struct map_priv *m, MdbCatalogEntry *entry) +{ + int j; + MdbIndex *idx; + + m->h_idx=NULL; + m->table = mdb_read_table(entry); + m->table_col = mdb_read_columns(m->table); + mdb_read_indices(m->table); + m->cols = (MdbColumn **) (m->table_col->pdata); + if (m->table_col->len < 4 || strcasecmp(m->cols[0]->name, "X") || + strcasecmp(m->cols[1]->name, "Y") || strcasecmp(m->cols[3]->name, "GEOFLAGS")) + return 1; + for (j = 0; j < m->table->num_idxs; j++) { + idx = m->table->indices->pdata[j]; + if (idx->num_keys == 3 && idx->key_col_num[0] == 1 && + idx->key_col_num[1] == 2 && idx->key_col_num[2] == 4) { + m->idx = idx; + m->idx_size=3+m->cols[0]->col_size+m->cols[1]->col_size+m->cols[3]->col_size; + m->h_idx=mdb_clone_handle(m->h); + } + } + return 0; +} + +#if 0 + +static void +load_poi(char *filename, char *icon, int type) +{ + int i; + MdbCatalogEntry *entry; + GPtrArray *catalog; + struct poi *new = g_new0(struct poi, 1); + + FILE *fp = fopen(filename,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : POI file %s does not exists!\n",filename); + exit(0); + return -1; + } + + + fp = fopen(icon,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : WARNING INCORRECT PICTURE! %s!\n",icon); + exit(0); + return -1; + } + + strcpy(new->filename,filename); + strcpy(new->icon,icon); + new->type = type; + + + if (type == 0) { + new->h = mdb_open(filename, MDB_NOFLAGS); + catalog = mdb_read_catalog(new->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(new, entry)) { + printf("%s invalid\n", filename); + g_free(new); + new=NULL; + } + } + } + g_ptr_array_free(catalog, 1); + } + if (new) { + new->next = poi_list; + poi_list = new; + } +} + +static void +get_coord(struct poi *p, struct coord *c) +{ + c->x=mdb_pg_get_int32(p->h, p->cols[0]->cur_value_start); + c->y=mdb_pg_get_int32(p->h, p->cols[1]->cur_value_start); +} + +static void +poi_info(struct display_list *list, struct popup_item **popup) +{ + struct poi_data *data=list->data; + struct poi *poi=data->poi; + struct popup_item *popup_last, *popup_val_last; + char *text,buffer[4096]; + int j; + MdbColumn *col; + char *v; + + popup_last = *popup; + + popup_val_last = NULL; + sprintf(buffer,"File:%s", poi->filename); + popup_item_new_text(&popup_val_last, buffer, 1); + sprintf(buffer,"Icon:%s", poi->icon); + popup_item_new_text(&popup_val_last, buffer, 2); + if (poi->type == 0) { + printf("poi_info pg=%d row=%d\n", data->page, data->row); + load_row(poi, data->page, data->row); + sprintf(buffer,"Page:%d", data->page); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Row:%d", data->row); + popup_item_new_text(&popup_val_last, buffer, 4); + for (j = 0; j < poi->table_col->len; j++) { + col = poi->table_col->pdata[j]; + #if 0 + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); + #endif + sprintf(buffer, "%s:", col->name); + v = buffer + strlen(buffer); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(poi->h, col, v, 1); + else + print_col(poi->h, col, v, 0); + #if 0 + printf("%s\n", buffer); + #endif + text=g_convert(buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + popup_item_new_text(&popup_val_last, buffer, j+10); + g_free(text); + } + } + popup_item_new_text(&popup_last, "POI", 20)->submenu = popup_val_last; + *popup=popup_last; +} + +static void +draw_poi(struct poi *p, struct container *co, struct point *pnt) +{ + struct poi_data data; + data.poi=p; + if (p->type == 0) { + data.page=p->h->cur_pg; + data.row=p->table->cur_row-1; + } + if (p->type == 1) { + data.row=p->pos; + } + display_add(&co->disp[display_poi], 5, 0, p->icon, 1, pnt, poi_info, &data, sizeof(data)); +} + +static void +plugin_draw(struct container *co) +{ + struct coord c; + struct point pnt; + struct poi *p; + struct index_data idx[2]; + int use_index=0; + int debug=1; + + p = poi_list; + + if (co->trans->scale > 1024) + return; + if (debug) { + printf("scale=%ld\n", co->trans->scale); + printf("rect 0x%lx,0%lx-0x%lx,0x%lx\n", co->trans->rect[0].x, co->trans->rect[0].y, co->trans->rect[1].x, co->trans->rect[1].y); + } + while (p) { + if (p->type == 0) { + if (use_index) + setup_idx_rect(co->trans->rect, idx, p->idx_size); + if (! use_index) { + printf("rewind %s %p\n", p->filename, p->table); + mdb_rewind_table(p->table); + while (mdb_fetch_row(p->table)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } else { + memset(&p->chain, 0, sizeof(p->chain)); + while (index_next(p, idx)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } + } + if (p->type == 1) { + FILE *f; + char line[1024]; + struct text_poi tpoi; + if(!(f=fopen(p->filename, "r"))){ + printf("can't open poi file for drawing!\n"); + exit(0); + } +#if 0 + printf("opened poi file %s for drawing!\n",p->filename); +#endif + p->pos=ftell(f); + fgets(line, 1024, f); + while (!feof(f)) { + if (strlen(line)) { + line[strlen(line)-1]='\0'; + } + if (parse_text_poi(line, &tpoi)) { + transform_mercator(&tpoi.lat,&tpoi.lng,&c); +// printf("%ld %ld\n", c.x, c.y); + if (transform(co->trans, &c, &pnt)) { + draw_poi(p, co, &pnt); + } + } + p->pos=ftell(f); + fgets(line, 1024, f); + } + fclose(f); + } + p = p->next; + } + +} + +#endif + +static void +map_destroy_poi_geodownload(struct map_priv *m) +{ + dbg(1,"enter\n"); + g_free(m); +} + +static void +poi_geodownload_coord_rewind(void *priv_data) +{ + struct map_rect_priv *mr=priv_data; + mr->cidx=0; +} + + +static int +poi_geodownload_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + dbg(1,"enter\n"); + if (mr->cidx || !count) + return 0; + c->x=mdb_pg_get_int32(mr->m->h, mr->m->cols[0]->cur_value_start); + c->y=mdb_pg_get_int32(mr->m->h, mr->m->cols[1]->cur_value_start); + dbg(1,"x=0x%x y=0x%x\n", c->x, c->y); + return 1; +} + +static void +poi_geodownload_attr_rewind(void *priv_data) +{ +} + +static int +poi_geodownload_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + dbg(1,"enter\n"); + return 0; +} + +static struct item_methods methods_poi_geodownload = { + poi_geodownload_coord_rewind, + poi_geodownload_coord_get, + poi_geodownload_attr_rewind, + poi_geodownload_attr_get, +}; + + +static struct map_rect_priv * +map_rect_new_poi_geodownload(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + + dbg(1,"enter\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->item.meth=&methods_poi_geodownload; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.priv_data=mr; + mr->item.type=map->type; + mr->m=map; + mdb_rewind_table(map->table); + return mr; +} + + +static void +map_rect_destroy_poi_geodownload(struct map_rect_priv *mr) +{ + g_free(mr); +} + +static struct item * +map_rect_get_item_poi_geodownload(struct map_rect_priv *mr) +{ + dbg(1,"enter\n"); + if (mdb_fetch_row(mr->m->table)) + return &mr->item; + return NULL; +} + +static struct item * +map_rect_get_item_byid_poi_geodownload(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + return NULL; +} + + +static struct map_methods map_methods_poi_geodownload = { + map_destroy_poi_geodownload, + map_rect_new_poi_geodownload, + map_rect_destroy_poi_geodownload, + map_rect_get_item_poi_geodownload, + map_rect_get_item_byid_poi_geodownload, +}; + +static struct map_priv * +map_new_poi_geodownload(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) +{ + struct map_priv *m; + dbg(1,"filename %s\n",filename); + MdbCatalogEntry *entry; + GPtrArray *catalog; + int i; + struct attr *attr; + + *meth=map_methods_poi_geodownload; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->filename=g_strdup(filename); + m->h = mdb_open(m->filename, MDB_NOFLAGS); + m->type=type_none; + dbg(1,"attr_search\n"); + attr=attr_search(attrs, NULL, attr_item_type); + dbg(1,"attr_search result %p\n", attr); + if (attr) { + m->type=attr->u.item_type; + printf("type '%s'\n", item_to_name(m->type)); + } + + + catalog = mdb_read_catalog(m->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + dbg(1,"object name '%s'\n", entry->object_name); + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(m, entry)) { + printf("%s invalid\n", filename); + g_free(m); + m=NULL; + } + } + } + g_ptr_array_free(catalog, 1); + return m; +} + +void +plugin_init(void) +{ + dbg(1,"plugin_init\n"); + plugin_register_map_type("poi_geodownload", map_new_poi_geodownload); +} + diff --git a/data/textfile/textfile.c b/data/textfile/textfile.c index 908be5b2..17e62f8d 100644 --- a/data/textfile/textfile.c +++ b/data/textfile/textfile.c @@ -291,7 +291,7 @@ static struct map_methods map_methods_textfile = { }; static struct map_priv * -map_new_textfile(struct map_methods *meth, char *filename, char **charset, enum projection *pro) +map_new_textfile(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) { struct map_priv *m; dbg(1,"map_new_textfile %s\n",filename); diff --git a/graphics.c b/graphics.c index 593d7f3c..7a2f205a 100644 --- a/graphics.c +++ b/graphics.c @@ -466,8 +466,10 @@ do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapset while ((item=map_rect_get_item(mr))) { if (item->type < type_line) { item_coord_get(item, &c, 1); - if (!transform(t, pro, &c, &pnt[0])) + if (!transform(t, pro, &c, &pnt[0])) { + dbg(1,"not visible\n"); continue; + } count=1; } else { count=0; diff --git a/gui/gtk/destination.c b/gui/gtk/destination.c index 286da7ac..6af8b347 100644 --- a/gui/gtk/destination.c +++ b/gui/gtk/destination.c @@ -7,9 +7,8 @@ #include "debug.h" #include "destination.h" #include "navit.h" -#include "attr.h" -#include "coord.h" #include "item.h" +#include "coord.h" #include "search.h" #define COL_COUNT 8 diff --git a/item.c b/item.c index 89c5a2ec..81ec9b24 100644 --- a/item.c +++ b/item.c @@ -1,6 +1,5 @@ #include #include -#include "attr.h" #include "coord.h" #include "debug.h" #include "item.h" diff --git a/item.h b/item.h index 473d8f9e..d497f15f 100644 --- a/item.h +++ b/item.h @@ -1,4 +1,3 @@ -#include "attr.h" enum item_type { @@ -9,6 +8,8 @@ enum item_type { #undef ITEM }; +#include "attr.h" + #define item_is_equal_id(a,b) ((a).id_hi == (b).id_hi && (a).id_lo == (b).id_lo) #define item_is_equal(a,b) (item_is_equal_id(a,b) && (a).map == (b).map) diff --git a/item_def.h b/item_def.h index 0f771d2e..71d33113 100644 --- a/item_def.h +++ b/item_def.h @@ -89,6 +89,10 @@ ITEM(poi_picnic) ITEM(poi_hospital) ITEM(poi_camping) ITEM(poi_public_utilities) +ITEM(poi_burgerking) +ITEM(poi_kfc) +ITEM(poi_mcdonalds) +ITEM(poi_wienerwald) ITEM2(0x80000000,line) ITEM2(0x80000001,line_unspecified) /* Line */ diff --git a/map.c b/map.c index a209c14c..36bf329a 100644 --- a/map.c +++ b/map.c @@ -26,10 +26,10 @@ struct map_rect { }; struct map * -map_new(const char *type, const char *filename) +map_new(const char *type, const char *filename, struct attr **attrs) { struct map *m; - struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, char **charset, enum projection *pro); + struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, struct attr *attrs, char **charset, enum projection *pro); maptype_new=plugin_get_map_type(type); if (! maptype_new) @@ -39,7 +39,7 @@ map_new(const char *type, const char *filename) m->active=1; m->filename=g_strdup(filename); m->type=g_strdup(type); - m->priv=maptype_new(&m->meth, filename, &m->charset, &m->projection); + m->priv=maptype_new(&m->meth, filename, attrs, &m->charset, &m->projection); return m; } diff --git a/map.h b/map.h index c0b93614..91274943 100644 --- a/map.h +++ b/map.h @@ -28,7 +28,7 @@ struct map; struct map_rect; struct map_search; struct map_selection; -struct map *map_new(const char *type, const char *filename); +struct map *map_new(const char *type, const char *filename, struct attr **attrs); char * map_convert_string(struct map *this, char *str); void map_convert_free(char *str); char *map_get_filename(struct map *this); diff --git a/mapset.c b/mapset.c index 17fbecf3..39cb0d55 100644 --- a/mapset.c +++ b/mapset.c @@ -1,7 +1,7 @@ #include #include #include "debug.h" -#include "attr.h" +#include "item.h" #include "mapset.h" #include "map.h" diff --git a/navit.c b/navit.c index 9bb1dd25..652563d8 100644 --- a/navit.c +++ b/navit.c @@ -694,7 +694,7 @@ navit_window_items_open(struct menu *men, struct navit *this_, struct navit_wind if (item_coord_get(item, &c, 1)) { if (coord_rect_contains(&sel.rect, &c) && g_hash_table_lookup(nwi->hash, &item->type)) { if (! item_attr_get(item, attr_label, &attr)) - attr.u.str=NULL; + attr.u.str=""; idist=transform_distance(center, &c); if (idist < dist) { get_direction(dirbuf, transform_get_angle_delta(center, &c, 0), 1); diff --git a/plugin_def.h b/plugin_def.h index 075709ba..701598df 100644 --- a/plugin_def.h +++ b/plugin_def.h @@ -1,10 +1,11 @@ enum projection; +struct attr; PLUGIN_FUNC1(draw, struct container *, co) PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) struct navit; PLUGIN_TYPE(graphics, (struct graphics_methods *meth)) PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, int w, int h)) -PLUGIN_TYPE(map, (struct map_methods *meth, char *data, char **charset, enum projection *pro)) +PLUGIN_TYPE(map, (struct map_methods *meth, char *data, struct attr **attr, char **charset, enum projection *pro)) PLUGIN_TYPE(osd, (struct osd_methods *meth)) PLUGIN_TYPE(speech, (char *data, struct speech_methods *meth)) PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth)) diff --git a/search.c b/search.c index 8ac95183..3d7e3e0d 100644 --- a/search.c +++ b/search.c @@ -2,7 +2,6 @@ #include "debug.h" #include "map.h" #include "mapset.h" -#include "attr.h" #include "coord.h" #include "item.h" #include "search.h" diff --git a/xmlconfig.c b/xmlconfig.c index 0eff60ba..a2ff4626 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -28,6 +28,33 @@ struct xmlstate { } *xmlstate_root; +static struct attr ** convert_to_attr(struct xmlstate *state) +{ + const gchar **attribute_name=state->attribute_names; + const gchar **attribute_value=state->attribute_values; + int count=0; + struct attr **ret; + + while (*attribute_name) { + count++; + attribute_name++; + } + ret=g_new(struct attr, count+1); + attribute_name=state->attribute_names; + count=0; + while (*attribute_name) { + ret[count]=attr_new_from_text(*attribute_name,*attribute_value); + if (ret[count]) + count++; + attribute_name++; + attribute_value++; + } + ret[count]=NULL; + dbg(0,"ret=%p\n", ret); + return ret; +} + + static const char * find_attribute(struct xmlstate *state, const char *attribute, int required) { const gchar **attribute_name=state->attribute_names; @@ -342,11 +369,13 @@ xmlconfig_mapset(struct xmlstate *state) static int xmlconfig_map(struct xmlstate *state) { + struct attr **attr; const char *type=find_attribute(state, "type", 1); const char *data=find_attribute(state, "data", 1); if (! type || ! data) return 0; - state->element_object = map_new(type, data); + attr=convert_to_attr(state); + state->element_object = map_new(type, data, attr); if (! state->element_object) return 0; if (!find_boolean(state, "active", 1, 0)) -- cgit v1.2.1 From 9fb18ca2d332d03d999e5a4e1d3fb39b37c512f9 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 11 Aug 2007 10:30:00 +0000 Subject: Made it compile again git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@380 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- binding/python/binding_python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/python/binding_python.c b/binding/python/binding_python.c index fc841465..81c07e51 100644 --- a/binding/python/binding_python.c +++ b/binding/python/binding_python.c @@ -173,7 +173,7 @@ map_new_py(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ss:navit.map", &type, &filename)) return NULL; ret=PyObject_NEW(mapObject, &map_Type); - ret->m=map_new(type,filename); + ret->m=map_new(type,filename,NULL); return (PyObject *)ret; } -- cgit v1.2.1 From 8431e7674542c902f1818a076a1fec81d311434c Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 11 Aug 2007 12:06:02 +0000 Subject: Fixed include files git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@381 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/sdl/sdl_events.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/gui/sdl/sdl_events.cpp b/gui/sdl/sdl_events.cpp index cc8ad082..9f6ff548 100644 --- a/gui/sdl/sdl_events.cpp +++ b/gui/sdl/sdl_events.cpp @@ -10,7 +10,6 @@ #include "coord.h" // Theses are needed for searches -#include "attr.h" #include "item.h" #include "search.h" -- cgit v1.2.1 From 5730a2f8132d59495cbe1c0c210df3de4b49839b Mon Sep 17 00:00:00 2001 From: horwitz Date: Sat, 11 Aug 2007 13:23:45 +0000 Subject: Cleanup navit.c, remove navit_cb_cursor_offscreen git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@382 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- cursor.c | 16 +++++----------- cursor.h | 2 +- navit.c | 25 +++++++++++++------------ navit.h | 6 ++++++ 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cursor.c b/cursor.c index 3584cd95..ba7051a3 100644 --- a/cursor.c +++ b/cursor.c @@ -28,7 +28,6 @@ struct cursor { struct graphics_gc *cursor_gc; struct transformation *trans; struct point cursor_pnt; - struct callback_list *offscreen_cbl; struct callback_list *update_cbl; struct vehicle *v; struct callback *vehicle_cb; @@ -211,7 +210,6 @@ cursor_update(struct cursor *this, struct vehicle *v) double *dir; double *speed; enum projection pro; - int border=10; if (v) { pos=vehicle_pos_get(v); @@ -223,10 +221,7 @@ cursor_update(struct cursor *this, struct vehicle *v) this->pos=*pos; this->pro=pro; callback_list_call_1(this->update_cbl, this); - if (!transform(this->trans, pro, &this->pos, &pnt) || !transform_within_border(this->trans, &pnt, border)) { - callback_list_call_1(this->offscreen_cbl, this); - transform(this->trans, this->pro, &this->pos, &pnt); - } + transform(this->trans, pro, &this->pos, &pnt); cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5); } #if 0 @@ -239,7 +234,9 @@ cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct tran { dbg(2,"enter gra=%p v=%p c=%p t=%p\n", gra, v, c, t); struct cursor *this=g_new(struct cursor,1); +#if 0 this->offscreen_cbl=callback_list_new(); +#endif this->update_cbl=callback_list_new(); this->gra=gra; this->trans=t; @@ -254,10 +251,7 @@ cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct tran } void -cursor_add_callback(struct cursor *this, int offscreen, struct callback *cb) +cursor_add_callback(struct cursor *this, struct callback *cb) { - if (offscreen) - callback_list_add(this->offscreen_cbl, cb); - else - callback_list_add(this->update_cbl, cb); + callback_list_add(this->update_cbl, cb); } diff --git a/cursor.h b/cursor.h index 88b3b388..ff14f05c 100644 --- a/cursor.h +++ b/cursor.h @@ -12,5 +12,5 @@ void cursor_redraw(struct cursor *this); int cursor_get_dir(struct cursor *this); int cursor_get_speed(struct cursor *this); struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t); -void cursor_add_callback(struct cursor *this, int offscreen, struct callback *cb); +void cursor_add_callback(struct cursor *this, struct callback *cb); /* end of prototypes */ diff --git a/navit.c b/navit.c index 652563d8..aa2450fe 100644 --- a/navit.c +++ b/navit.c @@ -27,6 +27,7 @@ #include "navigation.h" #include "speech.h" #include "track.h" +#include "vehicle.h" #define _(STRING) gettext(STRING) @@ -39,7 +40,6 @@ struct navit_vehicle { struct menu *menu; struct cursor *cursor; struct vehicle *vehicle; - struct callback *offscreen_cb; struct callback *update_cb; }; @@ -855,20 +855,15 @@ navit_toggle_tracking(struct navit *this_) this_->tracking_flag=1-this_->tracking_flag; } -static void -navit_cursor_offscreen(struct navit *this_, struct cursor *cursor) -{ - if (!this_->cursor_flag || !this_->vehicle || this_->vehicle->cursor != cursor) - return; - navit_set_center(this_, cursor_pos_get(cursor)); -} - static void navit_cursor_update(struct navit *this_, struct cursor *cursor) { + struct point pnt; struct coord *cursor_c=cursor_pos_get(cursor); int dir=cursor_get_dir(cursor); int speed=cursor_get_speed(cursor); + enum projection pro; + int border=10; if (!this_->vehicle || this_->vehicle->cursor != cursor) return; @@ -876,6 +871,14 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) cursor_c=cursor_pos_get(cursor); dir=cursor_get_dir(cursor); speed=cursor_get_speed(cursor); + pro=vehicle_projection(this_->vehicle); + + if (!transform(this_->trans, pro, cursor_c, &pnt) || !transform_within_border(this_->trans, &pnt, border)) { + if (!this_->cursor_flag) + return; + navit_set_center(this_, cursor_c); + transform(this_->trans, pro, cursor_c, &pnt); + } if (this_->pid && speed > 2) kill(this_->pid, SIGWINCH); @@ -929,10 +932,8 @@ navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, stru nv->update_curr=nv->update=update; nv->follow_curr=nv->follow=follow; nv->cursor=cursor_new(this_->gra, v, c, this_->trans); - nv->offscreen_cb=callback_new_1(callback_cast(navit_cursor_offscreen), this_); - cursor_add_callback(nv->cursor, 1, nv->offscreen_cb); nv->update_cb=callback_new_1(callback_cast(navit_cursor_update), this_); - cursor_add_callback(nv->cursor, 0, nv->update_cb); + cursor_add_callback(nv->cursor, nv->update_cb); this_->vehicles=g_list_append(this_->vehicles, nv); return nv; diff --git a/navit.h b/navit.h index 7e79aa46..48399e68 100644 --- a/navit.h +++ b/navit.h @@ -4,6 +4,7 @@ extern "C" { extern struct gui *main_loop_gui; /* prototypes */ enum projection; +enum item_type; struct callback; struct color; struct coord; @@ -42,6 +43,11 @@ void navit_add_menu_vehicles(struct navit *this_, struct menu *men); void navit_add_menu_vehicle(struct navit *this_, struct menu *men); void navit_speak(struct navit *this_); void navit_window_roadbook_new(struct navit *this_); +void navit_window_roadbook_destroy(struct navit *this_); +struct navit_window_items * navit_window_items_new(char *name, int distance); +void navit_window_items_add_item(struct navit_window_items *nwi, enum item_type type); +void navit_add_window_items(struct navit *this_, struct navit_window_items *nwi); +void navit_add_menu_windows_items(struct navit *this_, struct menu *men); void navit_init(struct navit *this_); void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); -- cgit v1.2.1 From e444052a66183a3559b137ca4d31bd9cb8cf87eb Mon Sep 17 00:00:00 2001 From: horwitz Date: Sat, 11 Aug 2007 14:38:17 +0000 Subject: Reenable orient north button and improve placement map reposistioning git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@383 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/gtk/gui_gtk_action.c | 10 +--------- navit.c | 15 +++++++++++++-- navit.h | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c index 7932d400..b2684da9 100644 --- a/gui/gtk/gui_gtk_action.c +++ b/gui/gtk/gui_gtk_action.c @@ -55,26 +55,18 @@ static void cursor_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { navit_toggle_cursor(gui->nav); -#if 0 - ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); -#endif } static void tracking_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { navit_toggle_tracking(gui->nav); -#if 0 - ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); -#endif } static void orient_north_action(GtkWidget *w, struct gui_priv *gui, void *dummy) { -#if 0 - ac->gui->co->flags->orient_north=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); -#endif + navit_toggle_orient_north(gui->nav); } static void diff --git a/navit.c b/navit.c index aa2450fe..ed6b2b24 100644 --- a/navit.c +++ b/navit.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "debug.h" #include "navit.h" #include "callback.h" @@ -66,6 +67,7 @@ struct navit { struct displaylist *displaylist; int cursor_flag; int tracking_flag; + int orient_north_flag; GList *vehicles; GList *windows_items; struct navit_vehicle *vehicle; @@ -855,6 +857,12 @@ navit_toggle_tracking(struct navit *this_) this_->tracking_flag=1-this_->tracking_flag; } +void +navit_toggle_orient_north(struct navit *this_) +{ + this_->orient_north_flag=1-this_->orient_north_flag; +} + static void navit_cursor_update(struct navit *this_, struct cursor *cursor) { @@ -863,7 +871,7 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) int dir=cursor_get_dir(cursor); int speed=cursor_get_speed(cursor); enum projection pro; - int border=10; + int border=30; if (!this_->vehicle || this_->vehicle->cursor != cursor) return; @@ -876,7 +884,10 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) if (!transform(this_->trans, pro, cursor_c, &pnt) || !transform_within_border(this_->trans, &pnt, border)) { if (!this_->cursor_flag) return; - navit_set_center(this_, cursor_c); + if(this_->orient_north_flag) + navit_set_center_cursor(this_, cursor_c, 0, 50 - 30.*sin(M_PI*dir/180.), 50 + 30.*cos(M_PI*dir/180.)); + else + navit_set_center_cursor(this_, cursor_c, dir, 50, 80); transform(this_->trans, pro, cursor_c, &pnt); } diff --git a/navit.h b/navit.h index 48399e68..9a3094e9 100644 --- a/navit.h +++ b/navit.h @@ -53,6 +53,7 @@ void navit_set_center(struct navit *this_, struct coord *center); void navit_set_center_screen(struct navit *this_, struct point *p); void navit_toggle_cursor(struct navit *this_); void navit_toggle_tracking(struct navit *this_); +void navit_toggle_orient_north(struct navit *this_); void navit_set_position(struct navit *this_, struct coord *c); struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow); void navit_add_vehicle_cb(struct navit *this_, struct callback *cb); -- cgit v1.2.1 From ad2c02306c844c94a7dcbea707c9992dae8954e7 Mon Sep 17 00:00:00 2001 From: horwitz Date: Sat, 11 Aug 2007 14:39:13 +0000 Subject: Fix some attr related warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@384 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- attr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/attr.h b/attr.h index 356185c8..3c430346 100644 --- a/attr.h +++ b/attr.h @@ -23,5 +23,7 @@ struct attr { enum attr_type attr_from_name(char *name); char * attr_to_name(enum attr_type attr); +struct attr * attr_new_from_text(char *name, char *value); +struct attr * attr_search(struct attr **attrs, struct attr *last, enum attr_type attr); #endif -- cgit v1.2.1 From 810b1f0c1dd61fe4bb0a4f657cc346d5a8877bad Mon Sep 17 00:00:00 2001 From: horwitz Date: Sat, 11 Aug 2007 20:13:13 +0000 Subject: Cleanup. Fix some warnings git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@385 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- attr.c | 1 + attr.h | 1 + gui/gtk/datawindow.c | 1 + navit.c | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/attr.c b/attr.c index 91d3f5ab..01355691 100644 --- a/attr.c +++ b/attr.c @@ -1,3 +1,4 @@ +#include #include #include #include "debug.h" diff --git a/attr.h b/attr.h index 3c430346..823872d7 100644 --- a/attr.h +++ b/attr.h @@ -25,5 +25,6 @@ enum attr_type attr_from_name(char *name); char * attr_to_name(enum attr_type attr); struct attr * attr_new_from_text(char *name, char *value); struct attr * attr_search(struct attr **attrs, struct attr *last, enum attr_type attr); +void attr_free(struct attr *attr); #endif diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c index 7a6cce89..549de734 100644 --- a/gui/gtk/datawindow.c +++ b/gui/gtk/datawindow.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/navit.c b/navit.c index ed6b2b24..7227b826 100644 --- a/navit.c +++ b/navit.c @@ -884,7 +884,7 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) if (!transform(this_->trans, pro, cursor_c, &pnt) || !transform_within_border(this_->trans, &pnt, border)) { if (!this_->cursor_flag) return; - if(this_->orient_north_flag) + if (this_->orient_north_flag) navit_set_center_cursor(this_, cursor_c, 0, 50 - 30.*sin(M_PI*dir/180.), 50 + 30.*cos(M_PI*dir/180.)); else navit_set_center_cursor(this_, cursor_c, dir, 50, 80); -- cgit v1.2.1 From 46308ae891b489d51b281d28a2794a9961c7fc48 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 11 Aug 2007 21:58:18 +0000 Subject: Fixed some Bugs in poi_geodownload git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@386 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- attr.c | 9 ++- data/poi_geodownload/poi_geodownload.c | 126 ++++++++++++++++++++++++++++----- popup.c | 1 - xmlconfig.c | 2 +- 4 files changed, 113 insertions(+), 25 deletions(-) diff --git a/attr.c b/attr.c index 01355691..7a5faabb 100644 --- a/attr.c +++ b/attr.c @@ -50,7 +50,7 @@ attr_new_from_text(char *name, char *value) struct attr *ret; ret=g_new0(struct attr, 1); - dbg(0,"enter name='%s' value='%s'\n", name, value); + dbg(1,"enter name='%s' value='%s'\n", name, value); attr=attr_from_name(name); ret->type=attr; switch (attr) { @@ -58,7 +58,7 @@ attr_new_from_text(char *name, char *value) ret->u.item_type=item_from_name(value); break; default: - dbg(0,"default\n"); + dbg(1,"default\n"); g_free(ret); ret=NULL; } @@ -68,15 +68,14 @@ attr_new_from_text(char *name, char *value) struct attr * attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) { - dbg(0, "enter attrs=%p\n", attrs); + dbg(1, "enter attrs=%p\n", attrs); while (*attrs) { - dbg(0,"*attrs=%p\n", *attrs); + dbg(1,"*attrs=%p\n", *attrs); if ((*attrs)->type == attr) { return *attrs; } attrs++; } - exit(0); return NULL; } diff --git a/data/poi_geodownload/poi_geodownload.c b/data/poi_geodownload/poi_geodownload.c index 8062ca50..1c226d2d 100644 --- a/data/poi_geodownload/poi_geodownload.c +++ b/data/poi_geodownload/poi_geodownload.c @@ -22,13 +22,16 @@ struct map_priv MdbIndex *idx; int idx_size; enum item_type type; + int name_col; }; struct map_rect_priv { struct item item; struct map_priv *m; + enum attr_type attr_next; int cidx; + char buffer[4096]; }; #if 0 @@ -61,9 +64,13 @@ struct poi_data { char poibmp[256]; +#endif + static void print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) { + char *s; + dbg(1,"type=%d\n", col->col_type); switch (col->col_type) { case MDB_BOOL: strcpy(buffer, mdb_pg_get_byte(h, col->cur_value_start) ? "True" : "False"); @@ -81,14 +88,20 @@ print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) sprintf(buffer, "%f", mdb_pg_get_double(h, col->cur_value_start)); break; case MDB_TEXT: - sprintf(buffer, "%s", mdb_col_to_string (h, h->pg_buf, col-> cur_value_start, - col->col_type, col->cur_value_len)); + dbg(1,"pg_buf %p start %d len %d\n", h->pg_buf, col->cur_value_start, col->cur_value_len); + if (col->cur_value_len) { + s=mdb_col_to_string (h, h->pg_buf, col->cur_value_start, col->col_type, col->cur_value_len); + dbg(1,"s=%p\n", s); + sprintf(buffer, "%s", s); + } break; default: sprintf(buffer, "unknown (%d)", col->col_type); } } +#if 0 + static void setup_idx_data(struct index_data *idx, struct coord *c, unsigned int geoflags, int size) { @@ -130,8 +143,10 @@ setup_idx_rect(struct coord *rect, struct index_data *idx, int size) setup_idx_data(idx+1, r+1, 0xffffffff, size); } +#endif + static int -load_row(struct poi *poi, int pg, int row) +load_row(struct map_priv *poi, int pg, int row) { int row_start, row_end, offset; unsigned int num_fields, i; @@ -141,13 +156,11 @@ load_row(struct poi *poi, int pg, int row) fmt=poi->h->fmt; mdb_read_pg(poi->h, pg); - if (debug) - printf("Page Type %d row_count_offset %d\n",poi->h->pg_buf[0], fmt->row_count_offset); - if (debug > 1) { - for (i = 0; i <= row; i++) { - offset=(fmt->row_count_offset + 2) + i * 2; - printf("row %d %d 0x%x\n", i, offset, mdb_pg_get_int16(poi->h, offset)); - } + dbg(1, "enter poi=%p pg=%d row=%d\n", poi, pg, row); + dbg(1,"Page Type %d row_count_offset %d\n",poi->h->pg_buf[0], fmt->row_count_offset); + for (i = 0; i <= row; i++) { + offset=(fmt->row_count_offset + 2) + i * 2; + dbg(1,"row %d %d 0x%x\n", i, offset, mdb_pg_get_int16(poi->h, offset)); } row_start = mdb_pg_get_int16(poi->h, (fmt->row_count_offset + 2) + row * 2); if (row_start & 0x4000) @@ -159,17 +172,19 @@ load_row(struct poi *poi, int pg, int row) } poi->h->cur_pos=row_start & 0x1fff; - poi->table->cur_row=row+1; + poi->table->cur_row=row; num_fields = mdb_crack_row(poi->table, row_start & 0x1fff, row_end, fields); - if (debug) - printf("num_fields=%d\n", num_fields); + dbg(1,"num_fields=%d\n", num_fields); for (i = 0; i < num_fields; i++) { + dbg(1,"i=%d/%d\n", i, num_fields); poi->cols[i]->cur_value_start=fields[i].start; poi->cols[i]->cur_value_len=fields[i].siz; } return 0; } +#if 0 + static MdbIndexPage * index_next_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) { @@ -295,6 +310,11 @@ load_poi_table(struct map_priv *m, MdbCatalogEntry *entry) if (m->table_col->len < 4 || strcasecmp(m->cols[0]->name, "X") || strcasecmp(m->cols[1]->name, "Y") || strcasecmp(m->cols[3]->name, "GEOFLAGS")) return 1; + m->name_col=-1; + for (j = 0; j < m->table_col->len ; j++) { + if (!strcasecmp(m->cols[j]->name, "NAME")) + m->name_col=j; + } for (j = 0; j < m->table->num_idxs; j++) { idx = m->table->indices->pdata[j]; if (idx->num_keys == 3 && idx->key_col_num[0] == 1 && @@ -544,12 +564,60 @@ poi_geodownload_coord_get(void *priv_data, struct coord *c, int count) static void poi_geodownload_attr_rewind(void *priv_data) { + struct map_rect_priv *mr=priv_data; + mr->attr_next=attr_label; } static int poi_geodownload_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) { + struct map_rect_priv *mr=priv_data; + struct map_priv *m=mr->m; + MdbColumn *col; + char *v; + int j; + dbg(1,"enter\n"); + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (mr->attr_next != attr_none) { + if (poi_geodownload_attr_get(mr, mr->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + mr->attr_next=attr_debug; + if (m->name_col == -1) + return 0; + col=m->cols[m->name_col]; + if (col->cur_value_len) + attr->u.str=mdb_col_to_string (m->h, m->h->pg_buf, col->cur_value_start, col->col_type, col->cur_value_len); + else + attr->u.str=""; + return 1; + case attr_debug: + mr->attr_next=attr_none; + v=mr->buffer; + *v='\0'; + for (j = 0; j < mr->m->table_col->len; j++) { + col = mr->m->table_col->pdata[j]; + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); + sprintf(v, "%s:", col->name); + v += strlen(v); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(mr->m->h, col, v, 1); + else + print_col(mr->m->h, col, v, 0); + v += strlen(v); + *v++='\n'; + *v='\0'; + } + attr->u.str=mr->buffer; + return 1; + default: + break; + } return 0; } @@ -589,15 +657,38 @@ static struct item * map_rect_get_item_poi_geodownload(struct map_rect_priv *mr) { dbg(1,"enter\n"); - if (mdb_fetch_row(mr->m->table)) + if (mdb_fetch_row(mr->m->table)) { + mr->item.id_hi=mr->m->table->cur_phys_pg; + mr->item.id_lo=mr->m->table->cur_row-1; + poi_geodownload_attr_rewind(mr); return &mr->item; + } return NULL; } static struct item * map_rect_get_item_byid_poi_geodownload(struct map_rect_priv *mr, int id_hi, int id_lo) { - return NULL; + char *v, buffer[4096]; + int j; + MdbColumn *col; + + dbg(1,"enter\n"); + load_row(mr->m, id_hi, id_lo); + for (j = 0; j < mr->m->table_col->len; j++) { + col = mr->m->table_col->pdata[j]; + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); + sprintf(buffer, "%s:", col->name); + v = buffer + strlen(buffer); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(mr->m->h, col, v, 1); + else + print_col(mr->m->h, col, v, 0); + printf("%s\n", buffer); + } + dbg(1,"ret=%p\n", &mr->item); + poi_geodownload_attr_rewind(mr); + return &mr->item; } @@ -630,10 +721,8 @@ map_new_poi_geodownload(struct map_methods *meth, char *filename, struct attr ** dbg(1,"attr_search\n"); attr=attr_search(attrs, NULL, attr_item_type); dbg(1,"attr_search result %p\n", attr); - if (attr) { + if (attr) m->type=attr->u.item_type; - printf("type '%s'\n", item_to_name(m->type)); - } catalog = mdb_read_catalog(m->h, MDB_TABLE); @@ -657,5 +746,6 @@ plugin_init(void) { dbg(1,"plugin_init\n"); plugin_register_map_type("poi_geodownload", map_new_poi_geodownload); + mdb_init(); } diff --git a/popup.c b/popup.c index c549f23c..cc532b71 100644 --- a/popup.c +++ b/popup.c @@ -121,7 +121,6 @@ popup_show_attr_val(void *menu, struct attr *attr) { char *attr_name=attr_to_name(attr->type); - printf("attr\n"); if (attr->type == attr_limit) popup_printf(menu, menu_type_menu, "%s: %d", attr_name, attr->u.num); else diff --git a/xmlconfig.c b/xmlconfig.c index a2ff4626..0c645f6f 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -50,7 +50,7 @@ static struct attr ** convert_to_attr(struct xmlstate *state) attribute_value++; } ret[count]=NULL; - dbg(0,"ret=%p\n", ret); + dbg(1,"ret=%p\n", ret); return ret; } -- cgit v1.2.1 From 69635527c33d56d6b7e4c563c4d6efa797be3b00 Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 21 Aug 2007 19:53:47 +0000 Subject: Fixed a compile bug with sdl git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@387 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- gui/sdl/gui_sdl_window.cpp | 3 +-- gui/sdl/sdl_events.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gui/sdl/gui_sdl_window.cpp b/gui/sdl/gui_sdl_window.cpp index 68f88909..e999ec63 100644 --- a/gui/sdl/gui_sdl_window.cpp +++ b/gui/sdl/gui_sdl_window.cpp @@ -4,7 +4,7 @@ // FIXME temporary fix for enum #include "projection.h" - +#include "item.h" #include "navit.h" #include "profile.h" #include "transform.h" @@ -15,7 +15,6 @@ #include "point.h" #include "graphics.h" #include "gui_sdl.h" -#include "item.h" #include "navigation.h" #include "debug.h" diff --git a/gui/sdl/sdl_events.cpp b/gui/sdl/sdl_events.cpp index 9f6ff548..2a132cf5 100644 --- a/gui/sdl/sdl_events.cpp +++ b/gui/sdl/sdl_events.cpp @@ -5,12 +5,12 @@ // FIXME temporary fix for enum #include "projection.h" +#include "item.h" #include "navit.h" #include "coord.h" // Theses are needed for searches -#include "item.h" #include "search.h" -- cgit v1.2.1 From 4133eec252ae2c080980f1baa371bdd42d9e3c21 Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 23 Aug 2007 18:58:47 +0000 Subject: Fixed make distcheck git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@389 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/poi_geodownload/libmdb/Makefile.am | 1 + data/poi_geodownload/libmdb/include/Makefile.am | 1 + 2 files changed, 2 insertions(+) create mode 100644 data/poi_geodownload/libmdb/include/Makefile.am diff --git a/data/poi_geodownload/libmdb/Makefile.am b/data/poi_geodownload/libmdb/Makefile.am index 6ff3fd61..f5eb49eb 100644 --- a/data/poi_geodownload/libmdb/Makefile.am +++ b/data/poi_geodownload/libmdb/Makefile.am @@ -1,3 +1,4 @@ +SUBDIRS=include AUTOMAKE_OPTIONS = no-exeext AM_CPPFLAGS = @NAVIT_CFLAGS@ -Iinclude diff --git a/data/poi_geodownload/libmdb/include/Makefile.am b/data/poi_geodownload/libmdb/include/Makefile.am new file mode 100644 index 00000000..084a7542 --- /dev/null +++ b/data/poi_geodownload/libmdb/include/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = mdbtools.h -- cgit v1.2.1 From 9738081259407f439a4b5ee4fc58581adb870c40 Mon Sep 17 00:00:00 2001 From: martin-s Date: Thu, 23 Aug 2007 19:29:51 +0000 Subject: Fixed make distcheck git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@390 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/poi_geodownload/Makefile.am | 2 +- data/poi_geodownload/libmdb/Makefile.am | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/data/poi_geodownload/Makefile.am b/data/poi_geodownload/Makefile.am index d3412df3..f58a0f05 100644 --- a/data/poi_geodownload/Makefile.am +++ b/data/poi_geodownload/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS=libmdb include $(top_srcdir)/Makefile.inc -AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -Ilibmdb/include -DMODULE=\"data_poi_geodownload\" +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -I$(srcdir)/libmdb/include -DMODULE=\"data_poi_geodownload\" moduledata_LTLIBRARIES = libdata_poi_geodownload.la libdata_poi_geodownload_la_SOURCES = poi_geodownload.c libdata_poi_geodownload_la_LIBADD = -Llibmdb -lmdb diff --git a/data/poi_geodownload/libmdb/Makefile.am b/data/poi_geodownload/libmdb/Makefile.am index f5eb49eb..088cbad7 100644 --- a/data/poi_geodownload/libmdb/Makefile.am +++ b/data/poi_geodownload/libmdb/Makefile.am @@ -1,14 +1,5 @@ SUBDIRS=include -AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @NAVIT_CFLAGS@ -Iinclude - -objdir=$(prefix) -obj_PROGRAMS=libmdb.a -INSTALL_PROGRAM=/bin/true - -libmdb_a_SOURCES=backend.c catalog.c data.c dump.c file.c iconv.c index.c kkd.c like.c map.c mem.c money.c options.c props.c sargs.c stats.c table.c worktable.c write.c - -libmdb.a: $(libmdb_a_OBJECTS) - ar r $@ $(libmdb_a_OBJECTS) - - +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(srcdir)/include +noinst_LTLIBRARIES = libmdb.la +libmdb_la_LDFLAGS = -static +libmdb_la_SOURCES=backend.c catalog.c data.c dump.c file.c iconv.c index.c kkd.c like.c map.c mem.c money.c options.c props.c sargs.c stats.c table.c worktable.c write.c -- cgit v1.2.1 From 92fdb3c02c4568962db0ce0f68f2a612ec1e000b Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 28 Aug 2007 17:31:21 +0000 Subject: Changed api for gui and graphics git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@393 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- attr.c | 7 ++- attr.h | 13 +++-- attr_def.h | 3 + binding/python/binding_python.c | 3 +- data/garmin_img/garmin_img.c | 12 +++- data/mg/map.c | 24 ++++---- data/mg/mg.h | 1 + data/textfile/textfile.c | 15 +++-- graphics.c | 8 +-- graphics.h | 5 +- .../gtk_drawing_area/graphics_gtk_drawing_area.c | 2 +- graphics/null/graphics_null.c | 2 +- graphics/opengl/graphics_opengl.c | 2 +- gui.c | 6 +- gui.h | 3 +- gui/gtk/gui_gtk_window.c | 5 +- gui/sdl/gui_sdl_window.cpp | 2 +- item.c | 2 +- item.h | 2 +- map.c | 23 ++++---- map.h | 11 ++-- mapset.c | 1 + maptype.c | 1 + navigation.c | 1 + navit.c | 66 +++++++++++++--------- navit.h | 12 ++-- navit.xml | 9 ++- plugin_def.h | 6 +- route.c | 2 +- search.c | 1 + track.c | 1 + xmlconfig.c | 60 ++++++++++++++------ xpm/Makefile.am | 4 +- 33 files changed, 198 insertions(+), 117 deletions(-) diff --git a/attr.c b/attr.c index 7a5faabb..ceb74dc5 100644 --- a/attr.c +++ b/attr.c @@ -20,7 +20,7 @@ static struct attr_name attr_names[]={ }; enum attr_type -attr_from_name(char *name) +attr_from_name(const char *name) { int i; @@ -44,7 +44,7 @@ attr_to_name(enum attr_type attr) } struct attr * -attr_new_from_text(char *name, char *value) +attr_new_from_text(const char *name, const char *value) { enum attr_type attr; struct attr *ret; @@ -57,6 +57,9 @@ attr_new_from_text(char *name, char *value) case attr_item_type: ret->u.item_type=item_from_name(value); break; + case attr_data: + ret->u.str=value; + break; default: dbg(1,"default\n"); g_free(ret); diff --git a/attr.h b/attr.h index 823872d7..c4cc4013 100644 --- a/attr.h +++ b/attr.h @@ -21,10 +21,13 @@ struct attr { } u; }; -enum attr_type attr_from_name(char *name); -char * attr_to_name(enum attr_type attr); -struct attr * attr_new_from_text(char *name, char *value); -struct attr * attr_search(struct attr **attrs, struct attr *last, enum attr_type attr); +/* prototypes */ +enum attr_type; +struct attr; +enum attr_type attr_from_name(const char *name); +char *attr_to_name(enum attr_type attr); +struct attr *attr_new_from_text(const char *name, const char *value); +struct attr *attr_search(struct attr **attrs, struct attr *last, enum attr_type attr); void attr_free(struct attr *attr); - +/* end of prototypes */ #endif diff --git a/attr_def.h b/attr_def.h index 0f259764..ae8a0695 100644 --- a/attr_def.h +++ b/attr_def.h @@ -12,9 +12,12 @@ ATTR2(type_item_end,0x0001ffff) ATTR2(type_int_begin,0x00020000) ATTR(id) ATTR(limit) +ATTR(w) +ATTR(h) ATTR2(type_int_end,0x0002ffff) ATTR2(type_string_begin,0x00030000) ATTR(label) +ATTR(data) ATTR(country_all) ATTR(country_iso3) ATTR(country_iso2) diff --git a/binding/python/binding_python.c b/binding/python/binding_python.c index 81c07e51..f1931e54 100644 --- a/binding/python/binding_python.c +++ b/binding/python/binding_python.c @@ -2,6 +2,7 @@ #include #include #include "coord.h" +#include "projection.h" #include "map.h" #include "mapset.h" #include "plugin.h" @@ -173,7 +174,7 @@ map_new_py(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ss:navit.map", &type, &filename)) return NULL; ret=PyObject_NEW(mapObject, &map_Type); - ret->m=map_new(type,filename,NULL); + ret->m=map_new(type,NULL); return (PyObject *)ret; } diff --git a/data/garmin_img/garmin_img.c b/data/garmin_img/garmin_img.c index 86b03ca1..0ba74f85 100644 --- a/data/garmin_img/garmin_img.c +++ b/data/garmin_img/garmin_img.c @@ -5,13 +5,13 @@ #include #include "plugin.h" #include "data.h" +#include "projection.h" #include "map.h" #include "maptype.h" #include "item.h" #include "attr.h" #include "coord.h" #include "transform.h" -#include "projection.h" #include #include "attr.h" #include "coord.h" @@ -1458,6 +1458,8 @@ map_rect_get_item_byid_garmin_img(struct map_rect_priv *mr, int id_hi, int id_lo } static struct map_methods map_methods_garmin_img = { + projection_garmin, + "iso8859-1", map_destroy_garmin_img, map_charset_garmin_img, map_projection_garmin_img, @@ -1468,13 +1470,17 @@ static struct map_methods map_methods_garmin_img = { }; static struct map_priv * -map_new_garmin_img(struct map_methods *meth, char *filename) +map_new_garmin_img(struct map_methods *meth, struct attr **attrs) { struct map_priv *m; + struct attr *data=attr_search(attrs, NULL, attr_data); + if (! data) + return NULL; + *meth=map_methods_garmin_img; m=g_new(struct map_priv, 1); m->id=++map_id; - m->filename=g_strdup(filename); + m->filename=g_strdup(data->u.str); return m; } diff --git a/data/mg/map.c b/data/mg/map.c index 6122b98a..c951d9fd 100644 --- a/data/mg/map.c +++ b/data/mg/map.c @@ -3,11 +3,10 @@ #include "debug.h" #include "plugin.h" #include "maptype.h" -#include "projection.h" #include "mg.h" -struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro); +struct map_priv * map_new_mg(struct map_methods *meth, struct attr **attrs); static int map_id; @@ -248,6 +247,8 @@ map_search_get_item_mg(struct map_search_priv *ms) } static struct map_methods map_methods_mg = { + projection_mg, + "iso8859-1", map_destroy_mg, map_rect_new_mg, map_rect_destroy_mg, @@ -259,30 +260,31 @@ static struct map_methods map_methods_mg = { }; struct map_priv * -map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro) +map_new_mg(struct map_methods *meth, struct attr **attrs) { struct map_priv *m; - int i,maybe_missing,len=strlen(dirname); - char filename[len+16]; + int i,maybe_missing; + struct attr *data; + char *filename; *meth=map_methods_mg; - *charset="iso8859-1"; - *pro=projection_mg; + data=attr_search(attrs, NULL, attr_data); + if (! data) + return NULL; m=g_new(struct map_priv, 1); m->id=++map_id; - m->dirname=g_strdup(dirname); - strcpy(filename, dirname); - filename[len]='/'; + m->dirname=g_strdup(data->u.str); for (i = 0 ; i < file_end ; i++) { if (file[i]) { - strcpy(filename+len+1, file[i]); + filename=g_strdup_printf("%s/%s", data->u.str, file[i]); m->file[i]=file_create_caseinsensitive(filename); if (! m->file[i]) { maybe_missing=(i == file_border_ply || i == file_height_ply || i == file_sea_ply); if (! maybe_missing) g_warning("Failed to load %s", filename); } + g_free(filename); } } diff --git a/data/mg/mg.h b/data/mg/mg.h index 78f72c04..62433afc 100644 --- a/data/mg/mg.h +++ b/data/mg/mg.h @@ -3,6 +3,7 @@ #include "attr.h" #include "coord.h" #include "data.h" +#include "projection.h" #include "map.h" #include "file.h" diff --git a/data/textfile/textfile.c b/data/textfile/textfile.c index 17e62f8d..cfa89304 100644 --- a/data/textfile/textfile.c +++ b/data/textfile/textfile.c @@ -5,13 +5,13 @@ #include #include "debug.h" #include "plugin.h" +#include "projection.h" #include "map.h" #include "maptype.h" #include "item.h" #include "attr.h" #include "coord.h" #include "transform.h" -#include "projection.h" #include "textfile.h" @@ -283,6 +283,8 @@ map_rect_get_item_byid_textfile(struct map_rect_priv *mr, int id_hi, int id_lo) } static struct map_methods map_methods_textfile = { + projection_mg, + "iso8859-1", map_destroy_textfile, map_rect_new_textfile, map_rect_destroy_textfile, @@ -291,17 +293,18 @@ static struct map_methods map_methods_textfile = { }; static struct map_priv * -map_new_textfile(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) +map_new_textfile(struct map_methods *meth, struct attr **attrs) { struct map_priv *m; - dbg(1,"map_new_textfile %s\n",filename); + struct attr *data=attr_search(attrs, NULL, attr_data); + if (! data) + return NULL; + dbg(1,"map_new_textfile %s\n", data->u.str); *meth=map_methods_textfile; - *charset="iso8859-1"; - *pro=projection_mg; m=g_new(struct map_priv, 1); m->id=++map_id; - m->filename=g_strdup(filename); + m->filename=g_strdup(data->u.str); return m; } diff --git a/graphics.c b/graphics.c index 7a2f205a..5c7c0003 100644 --- a/graphics.c +++ b/graphics.c @@ -6,10 +6,10 @@ #include "draw_info.h" #include "point.h" #include "graphics.h" +#include "projection.h" #include "map.h" #include "coord.h" #include "transform.h" -#include "projection.h" #include "plugin.h" #include "profile.h" #include "mapset.h" @@ -31,16 +31,16 @@ struct displaylist { }; struct graphics * -graphics_new(const char *type) +graphics_new(const char *type, struct attr **attrs) { struct graphics *this_; - struct graphics_priv * (*new)(struct graphics_methods *meth); + struct graphics_priv * (*new)(struct graphics_methods *meth, struct attr **attrs); new=plugin_get_graphics_type(type); if (! new) return NULL; this_=g_new0(struct graphics, 1); - this_->priv=(*new)(&this_->meth); + this_->priv=(*new)(&this_->meth, attrs); return this_; } diff --git a/graphics.h b/graphics.h index 6218b34a..fbf2c4fb 100644 --- a/graphics.h +++ b/graphics.h @@ -82,6 +82,7 @@ struct graphics_image { /* prototypes */ enum draw_mode_num; +struct attr; struct color; struct displayitem; struct displaylist; @@ -94,7 +95,7 @@ struct item; struct point; struct route; struct transformation; -struct graphics *graphics_new(const char *type); +struct graphics *graphics_new(const char *type, struct attr **attrs); void graphics_init(struct graphics *this_); void *graphics_get_data(struct graphics *this_, char *type); void graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data); @@ -112,12 +113,12 @@ void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r); void display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label); int graphics_ready(struct graphics *this_); +void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route); void graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route); struct displaylist_handle *graphics_displaylist_open(struct displaylist *displaylist); struct displayitem *graphics_displaylist_next(struct displaylist_handle *dlh); void graphics_displaylist_close(struct displaylist_handle *dlh); struct displaylist *graphics_displaylist_new(void); -void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route); struct item *graphics_displayitem_get_item(struct displayitem *di); char *graphics_displayitem_get_label(struct displayitem *di); int graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist); diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index cd38b2ac..554f1203 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -758,7 +758,7 @@ graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth) } static struct graphics_priv * -graphics_gtk_drawing_area_new(struct graphics_methods *meth) +graphics_gtk_drawing_area_new(struct graphics_methods *meth, struct attr **attrs) { GtkWidget *draw; diff --git a/graphics/null/graphics_null.c b/graphics/null/graphics_null.c index 35ebd588..748a5bcb 100644 --- a/graphics/null/graphics_null.c +++ b/graphics/null/graphics_null.c @@ -194,7 +194,7 @@ overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct poin static struct graphics_priv * -graphics_null_new(struct graphics_methods *meth) +graphics_null_new(struct graphics_methods *meth, struct attr **attrs) { *meth=graphics_methods; return &graphics_priv; diff --git a/graphics/opengl/graphics_opengl.c b/graphics/opengl/graphics_opengl.c index 8e424351..4a5b5fa0 100644 --- a/graphics/opengl/graphics_opengl.c +++ b/graphics/opengl/graphics_opengl.c @@ -891,7 +891,7 @@ static struct graphics_methods graphics_methods = { }; static struct graphics_priv * -graphics_opengl_new(struct graphics_methods *meth) +graphics_opengl_new(struct graphics_methods *meth, struct attr **attrs) { struct graphics_priv *this=g_new0(struct graphics_priv,1); *meth=graphics_methods; diff --git a/gui.c b/gui.c index 63a68d65..bddc9162 100644 --- a/gui.c +++ b/gui.c @@ -7,17 +7,17 @@ #include "plugin.h" struct gui * -gui_new(struct navit *nav, const char *type, int w, int h) +gui_new(struct navit *nav, const char *type, struct attr **attrs) { struct gui *this_; - struct gui_priv *(*guitype_new)(struct navit *nav, struct gui_methods *meth, int w, int h); + struct gui_priv *(*guitype_new)(struct navit *nav, struct gui_methods *meth, struct attr **attrs); guitype_new=plugin_get_gui_type(type); if (! guitype_new) return NULL; this_=g_new0(struct gui, 1); - this_->priv=guitype_new(nav, &this_->meth, w, h); + this_->priv=guitype_new(nav, &this_->meth, attrs); return this_; } diff --git a/gui.h b/gui.h index f5238b7a..c477d4da 100644 --- a/gui.h +++ b/gui.h @@ -25,6 +25,7 @@ struct gui { }; /* prototypes */ +struct attr; struct callback; struct coord; struct datawindow; @@ -33,7 +34,7 @@ struct gui; struct menu; struct navit; struct statusbar; -struct gui *gui_new(struct navit *nav, const char *type, int w, int h); +struct gui *gui_new(struct navit *nav, const char *type, struct attr **attrs); struct statusbar *gui_statusbar_new(struct gui *gui); struct menu *gui_menubar_new(struct gui *gui); struct menu *gui_toolbar_new(struct gui *gui); diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c index 9d2f9ec6..89c4b9d0 100644 --- a/gui/gtk/gui_gtk_window.c +++ b/gui/gtk/gui_gtk_window.c @@ -149,12 +149,13 @@ gui_gtk_delete(GtkWidget *widget, GdkEvent *event, struct navit *nav) } static struct gui_priv * -gui_gtk_new(struct navit *nav, struct gui_methods *meth, int w, int h) +gui_gtk_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs) { struct gui_priv *this; + int w=792, h=547; *meth=gui_gtk_methods; - + this=g_new0(struct gui_priv, 1); this->nav=nav; this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); diff --git a/gui/sdl/gui_sdl_window.cpp b/gui/sdl/gui_sdl_window.cpp index e999ec63..c6b9a37e 100644 --- a/gui/sdl/gui_sdl_window.cpp +++ b/gui/sdl/gui_sdl_window.cpp @@ -680,7 +680,7 @@ static void init_sdlgui(void) } static struct gui_priv * -gui_sdl_new(struct navit *nav, struct gui_methods *meth, int w, int h) +gui_sdl_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs) { dbg(1,"Begin SDL init\n"); struct gui_priv *this_; diff --git a/item.c b/item.c index 81ec9b24..aa18904f 100644 --- a/item.c +++ b/item.c @@ -53,7 +53,7 @@ struct item * item_new(char *type, int zoom) } enum item_type -item_from_name(char *name) +item_from_name(const char *name) { int i; diff --git a/item.h b/item.h index d497f15f..fe24dd87 100644 --- a/item.h +++ b/item.h @@ -43,7 +43,7 @@ int item_coord_get(struct item *it, struct coord *c, int count); void item_attr_rewind(struct item *it); int item_attr_get(struct item *it, enum attr_type attr_type, struct attr *attr); struct item *item_new(char *type, int zoom); -enum item_type item_from_name(char *name); +enum item_type item_from_name(const char *name); char *item_to_name(enum item_type item); struct item_hash *item_hash_new(void); void item_hash_insert(struct item_hash *h, struct item *item, void *val); diff --git a/map.c b/map.c index 36bf329a..facf6daf 100644 --- a/map.c +++ b/map.c @@ -2,10 +2,10 @@ #include #include "debug.h" #include "coord.h" +#include "projection.h" #include "map.h" #include "maptype.h" #include "transform.h" -#include "projection.h" #include "item.h" #include "plugin.h" #include "country.h" @@ -13,11 +13,9 @@ struct map { struct map_methods meth; struct map_priv *priv; - char *filename; char *type; - char *charset; + char *filename; int active; - enum projection projection; }; struct map_rect { @@ -26,10 +24,12 @@ struct map_rect { }; struct map * -map_new(const char *type, const char *filename, struct attr **attrs) +map_new(const char *type, struct attr **attrs) { struct map *m; - struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, struct attr *attrs, char **charset, enum projection *pro); + struct map_priv *(*maptype_new)(struct map_methods *meth, struct attr **attrs); + struct attr *data=attr_search(attrs, NULL, attr_data); + maptype_new=plugin_get_map_type(type); if (! maptype_new) @@ -37,9 +37,10 @@ map_new(const char *type, const char *filename, struct attr **attrs) m=g_new0(struct map, 1); m->active=1; - m->filename=g_strdup(filename); m->type=g_strdup(type); - m->priv=maptype_new(&m->meth, filename, attrs, &m->charset, &m->projection); + if (data) + m->filename=g_strdup(data->u.str); + m->priv=maptype_new(&m->meth, attrs); return m; } @@ -70,13 +71,13 @@ map_set_active(struct map *this, int active) int map_requires_conversion(struct map *this) { - return (this->charset != NULL); + return (this->meth.charset != NULL); } char * map_convert_string(struct map *this, char *str) { - return g_convert(str, -1,"utf-8",this->charset,NULL,NULL,NULL); + return g_convert(str, -1,"utf-8",this->meth.charset,NULL,NULL,NULL); } void @@ -88,7 +89,7 @@ map_convert_free(char *str) enum projection map_projection(struct map *this) { - return this->projection; + return this->meth.pro; } void diff --git a/map.h b/map.h index 91274943..84e5b022 100644 --- a/map.h +++ b/map.h @@ -10,6 +10,8 @@ struct map_selection { }; struct map_methods { + enum projection pro; + char *charset; void (*map_destroy)(struct map_priv *priv); struct map_rect_priv * (*map_rect_new)(struct map_priv *map, struct map_selection *sel); void (*map_rect_destroy)(struct map_rect_priv *mr); @@ -28,13 +30,14 @@ struct map; struct map_rect; struct map_search; struct map_selection; -struct map *map_new(const char *type, const char *filename, struct attr **attrs); -char * map_convert_string(struct map *this, char *str); -void map_convert_free(char *str); +struct map *map_new(const char *type, struct attr **attrs); char *map_get_filename(struct map *this); char *map_get_type(struct map *this); int map_get_active(struct map *this); void map_set_active(struct map *this, int active); +int map_requires_conversion(struct map *this); +char *map_convert_string(struct map *this, char *str); +void map_convert_free(char *str); enum projection map_projection(struct map *this); void map_destroy(struct map *m); struct map_rect *map_rect_new(struct map *m, struct map_selection *sel); @@ -44,4 +47,4 @@ void map_rect_destroy(struct map_rect *mr); struct map_search *map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial); struct item *map_search_get_item(struct map_search *this); void map_search_destroy(struct map_search *this); -int map_requires_conversion(struct map *this); +/* end of prototypes */ diff --git a/mapset.c b/mapset.c index 39cb0d55..e118bb99 100644 --- a/mapset.c +++ b/mapset.c @@ -3,6 +3,7 @@ #include "debug.h" #include "item.h" #include "mapset.h" +#include "projection.h" #include "map.h" struct mapset { diff --git a/maptype.c b/maptype.c index 81039613..0c0a26bc 100644 --- a/maptype.c +++ b/maptype.c @@ -1,4 +1,5 @@ #include +#include "projection.h" #include "map.h" #include "maptype.h" diff --git a/navigation.c b/navigation.c index e23ce3f6..5348165f 100644 --- a/navigation.c +++ b/navigation.c @@ -12,6 +12,7 @@ #include "route.h" #include "transform.h" #include "mapset.h" +#include "projection.h" #include "map.h" #include "navit.h" #include "callback.h" diff --git a/navit.c b/navit.c index 7227b826..6aa995a3 100644 --- a/navit.c +++ b/navit.c @@ -11,13 +11,13 @@ #include "callback.h" #include "gui.h" #include "item.h" +#include "projection.h" #include "map.h" #include "mapset.h" #include "main.h" #include "coord.h" #include "point.h" #include "transform.h" -#include "projection.h" #include "param.h" #include "menu.h" #include "graphics.h" @@ -29,6 +29,7 @@ #include "speech.h" #include "track.h" #include "vehicle.h" +#include "color.h" #define _(STRING) gettext(STRING) @@ -38,6 +39,7 @@ struct navit_vehicle { int update_curr; int follow; int follow_curr; + struct color c; struct menu *menu; struct cursor *cursor; struct vehicle *vehicle; @@ -83,6 +85,7 @@ struct navit { struct gui *main_loop_gui; +static void navit_cursor_update(struct navit *this_, struct cursor *cursor); void navit_add_mapset(struct navit *this_, struct mapset *ms) @@ -175,7 +178,7 @@ navit_zoom_out(struct navit *this_, int factor) } struct navit * -navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom) +navit_new(struct coord *center, enum projection pro, int zoom) { struct navit *this_=g_new0(struct navit, 1); FILE *f; @@ -198,39 +201,32 @@ navit_new(const char *ui, const char *graphics, struct coord *center, enum proje transform_setup(this_->trans, center, zoom, 0); this_->displaylist=graphics_displaylist_new(); - this_->gui=gui_new(this_, ui, 792, 547); - if (! this_->gui) { - g_warning("failed to create gui '%s'", ui); - navit_destroy(this_); - return NULL; - } + return this_; +} + +void +navit_set_gui(struct navit *this_, struct gui *gui) +{ + this_->gui=gui; if (gui_has_main_loop(this_->gui)) { if (! main_loop_gui) { main_loop_gui=this_->gui; } else { g_warning("gui with main loop already active, ignoring this instance"); - navit_destroy(this_); - return NULL; + return; } } this_->menubar=gui_menubar_new(this_->gui); this_->toolbar=gui_toolbar_new(this_->gui); this_->statusbar=gui_statusbar_new(this_->gui); - this_->gra=graphics_new(graphics); - if (! this_->gra) { - g_warning("failed to create graphics '%s'", graphics); - navit_destroy(this_); - return NULL; - } +} + +void +navit_set_graphics(struct navit *this_, struct graphics *gra) +{ + this_->gra=gra; graphics_register_resize_callback(this_->gra, navit_resize, this_); graphics_register_button_callback(this_->gra, navit_button, this_); - if (gui_set_graphics(this_->gui, this_->gra)) { - g_warning("failed to connect graphics '%s' to gui '%s'\n", graphics, ui); - navit_destroy(this_); - return NULL; - } - graphics_init(this_->gra); - return this_; } static void @@ -721,7 +717,7 @@ navit_window_items_open(struct menu *men, struct navit *this_, struct navit_wind } struct navit_window_items * -navit_window_items_new(char *name, int distance) +navit_window_items_new(const char *name, int distance) { struct navit_window_items *nwi=g_new0(struct navit_window_items, 1); nwi->name=g_strdup(name); @@ -762,7 +758,23 @@ navit_init(struct navit *this_) { struct menu *men; struct mapset *ms; + GList *l; + struct navit_vehicle *nv; + if (!this_->gui || !this_->gra || gui_set_graphics(this_->gui, this_->gra)) { + g_warning("failed to connect graphics to gui\n"); + navit_destroy(this_); + return; + } + graphics_init(this_->gra); + l=this_->vehicles; + while (l) { + nv=l->data; + nv->cursor=cursor_new(this_->gra, nv->vehicle, &nv->c, this_->trans); + nv->update_cb=callback_new_1(callback_cast(navit_cursor_update), this_); + cursor_add_callback(nv->cursor, nv->update_cb); + l=g_list_next(l); + } if (this_->mapsets) { ms=this_->mapsets->data; if (this_->route) @@ -879,7 +891,7 @@ navit_cursor_update(struct navit *this_, struct cursor *cursor) cursor_c=cursor_pos_get(cursor); dir=cursor_get_dir(cursor); speed=cursor_get_speed(cursor); - pro=vehicle_projection(this_->vehicle); + pro=vehicle_projection(this_->vehicle->vehicle); if (!transform(this_->trans, pro, cursor_c, &pnt) || !transform_within_border(this_->trans, &pnt, border)) { if (!this_->cursor_flag) @@ -942,9 +954,7 @@ navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, stru nv->name=g_strdup(name); nv->update_curr=nv->update=update; nv->follow_curr=nv->follow=follow; - nv->cursor=cursor_new(this_->gra, v, c, this_->trans); - nv->update_cb=callback_new_1(callback_cast(navit_cursor_update), this_); - cursor_add_callback(nv->cursor, nv->update_cb); + nv->c=*c; this_->vehicles=g_list_append(this_->vehicles, nv); return nv; diff --git a/navit.h b/navit.h index 9a3094e9..fc22cdf2 100644 --- a/navit.h +++ b/navit.h @@ -3,12 +3,13 @@ extern "C" { #endif extern struct gui *main_loop_gui; /* prototypes */ -enum projection; enum item_type; +enum projection; struct callback; struct color; struct coord; struct displaylist; +struct graphics; struct gui; struct layout; struct mapset; @@ -16,6 +17,7 @@ struct menu; struct navigation; struct navit; struct navit_vehicle; +struct navit_window_items; struct point; struct route; struct speech; @@ -29,7 +31,9 @@ void navit_draw(struct navit *this_); void navit_draw_displaylist(struct navit *this_); void navit_zoom_in(struct navit *this_, int factor); void navit_zoom_out(struct navit *this_, int factor); -struct navit *navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom); +struct navit *navit_new(struct coord *center, enum projection pro, int zoom); +void navit_set_gui(struct navit *this_, struct gui *gui); +void navit_set_graphics(struct navit *this_, struct graphics *gra); void navit_set_destination(struct navit *this_, struct coord *c, char *description); void navit_add_bookmark(struct navit *this_, struct coord *c, char *description); void navit_add_menu_layouts(struct navit *this_, struct menu *men); @@ -42,9 +46,9 @@ void navit_add_menu_bookmarks(struct navit *this_, struct menu *men); void navit_add_menu_vehicles(struct navit *this_, struct menu *men); void navit_add_menu_vehicle(struct navit *this_, struct menu *men); void navit_speak(struct navit *this_); -void navit_window_roadbook_new(struct navit *this_); void navit_window_roadbook_destroy(struct navit *this_); -struct navit_window_items * navit_window_items_new(char *name, int distance); +void navit_window_roadbook_new(struct navit *this_); +struct navit_window_items *navit_window_items_new(const char *name, int distance); void navit_window_items_add_item(struct navit_window_items *nwi, enum item_type type); void navit_add_window_items(struct navit *this_, struct navit_window_items *nwi); void navit_add_menu_windows_items(struct navit *this_, struct menu *men); diff --git a/navit.xml b/navit.xml index 85e9b43e..d31275b0 100644 --- a/navit.xml +++ b/navit.xml @@ -5,9 +5,12 @@ - - diff --git a/plugin_def.h b/plugin_def.h index 701598df..c3e93939 100644 --- a/plugin_def.h +++ b/plugin_def.h @@ -3,9 +3,9 @@ struct attr; PLUGIN_FUNC1(draw, struct container *, co) PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) struct navit; -PLUGIN_TYPE(graphics, (struct graphics_methods *meth)) -PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, int w, int h)) -PLUGIN_TYPE(map, (struct map_methods *meth, char *data, struct attr **attr, char **charset, enum projection *pro)) +PLUGIN_TYPE(graphics, (struct graphics_methods *meth, struct attr **attr)) +PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, struct attr **attr)) +PLUGIN_TYPE(map, (struct map_methods *meth, struct attr **attr)) PLUGIN_TYPE(osd, (struct osd_methods *meth)) PLUGIN_TYPE(speech, (char *data, struct speech_methods *meth)) PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth)) diff --git a/route.c b/route.c index 65dd0c3a..345d2a7a 100644 --- a/route.c +++ b/route.c @@ -11,6 +11,7 @@ #include "debug.h" #include "profile.h" #include "coord.h" +#include "projection.h" #include "map.h" #include "mapset.h" #include "item.h" @@ -958,7 +959,6 @@ route_info_free(struct route_info *inf) #include "point.h" -#include "projection.h" struct street_data * route_info_street(struct route_info *rinf) diff --git a/search.c b/search.c index 3d7e3e0d..91f2cb31 100644 --- a/search.c +++ b/search.c @@ -1,5 +1,6 @@ #include #include "debug.h" +#include "projection.h" #include "map.h" #include "mapset.h" #include "coord.h" diff --git a/track.c b/track.c index 23ec5d3e..38f83c74 100644 --- a/track.c +++ b/track.c @@ -5,6 +5,7 @@ #include "coord.h" #include "item.h" #include "route.h" +#include "projection.h" #include "map.h" #include "mapset.h" diff --git a/xmlconfig.c b/xmlconfig.c index 0c645f6f..a36d3bd4 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -5,15 +5,18 @@ #include "coord.h" #include "layout.h" #include "mapset.h" +#include "projection.h" #include "map.h" #include "navigation.h" #include "navit.h" #include "plugin.h" -#include "projection.h" #include "route.h" #include "speech.h" #include "track.h" #include "vehicle.h" +#include "point.h" +#include "graphics.h" +#include "gui.h" #include "xmlconfig.h" @@ -28,7 +31,7 @@ struct xmlstate { } *xmlstate_root; -static struct attr ** convert_to_attr(struct xmlstate *state) +static struct attr ** convert_to_attrs(struct xmlstate *state) { const gchar **attribute_name=state->attribute_names; const gchar **attribute_value=state->attribute_values; @@ -39,7 +42,7 @@ static struct attr ** convert_to_attr(struct xmlstate *state) count++; attribute_name++; } - ret=g_new(struct attr, count+1); + ret=g_new(struct attr *, count+1); attribute_name=state->attribute_names; count=0; while (*attribute_name) { @@ -186,7 +189,7 @@ xmlconfig_debug(struct xmlstate *state) static int xmlconfig_navit(struct xmlstate *state) { - const char *value,*gui,*graphics; + const char *value; int zoom=0; struct coord c; enum projection pro=projection_mg; @@ -201,15 +204,39 @@ xmlconfig_navit(struct xmlstate *state) c.x=1300000; c.y=7000000; } - gui=find_attribute(state, "gui", 0); - if (! gui) - gui="gtk"; - graphics=find_attribute(state, "graphics", 0); - if (! graphics) - graphics="gtk_drawing_area"; - state->element_object = navit_new(gui, graphics, &c, pro, zoom); + state->element_object = navit_new(&c, pro, zoom); + if (! state->element_object) + return 0; + return 1; +} + +static int +xmlconfig_graphics(struct xmlstate *state) +{ + struct attr **attrs; + const char *type=find_attribute(state, "type", 1); + if (! type) + return 0; + attrs=convert_to_attrs(state); + state->element_object = graphics_new(type, attrs); + if (! state->element_object) + return 0; + navit_set_graphics(state->parent->element_object, state->element_object); + return 1; +} + +static int +xmlconfig_gui(struct xmlstate *state) +{ + struct attr **attrs; + const char *type=find_attribute(state, "type", 1); + if (! type) + return 0; + attrs=convert_to_attrs(state); + state->element_object = gui_new(state->parent->element_object, type, attrs); if (! state->element_object) return 0; + navit_set_gui(state->parent->element_object, state->element_object); return 1; } @@ -369,13 +396,12 @@ xmlconfig_mapset(struct xmlstate *state) static int xmlconfig_map(struct xmlstate *state) { - struct attr **attr; + struct attr **attrs; const char *type=find_attribute(state, "type", 1); - const char *data=find_attribute(state, "data", 1); - if (! type || ! data) + if (! type) return 0; - attr=convert_to_attr(state); - state->element_object = map_new(type, data, attr); + attrs=convert_to_attrs(state); + state->element_object = map_new(type, attrs); if (! state->element_object) return 0; if (!find_boolean(state, "active", 1, 0)) @@ -551,6 +577,8 @@ struct element_func { } elements[] = { { "debug", NULL, xmlconfig_debug}, { "navit", NULL, xmlconfig_navit}, + { "graphics", "navit", xmlconfig_graphics}, + { "gui", "navit", xmlconfig_gui}, { "layout", "navit", xmlconfig_layout}, { "layer", "layout", xmlconfig_layer}, { "item", "layer", xmlconfig_item}, diff --git a/xpm/Makefile.am b/xpm/Makefile.am index 1c4507ca..4117c9df 100644 --- a/xpm/Makefile.am +++ b/xpm/Makefile.am @@ -1,3 +1,5 @@ include $(top_srcdir)/Makefile.inc -xpm_DATA = camping.xpm car_dealer.xpm flag_bk_tr.xpm flag_bk_wh.xpm flag_bl_wh.xpm fuel.xpm hospital.xpm hotel.xpm parking.xpm restaurant.xpm unknown.xpm +xpm_DATA = camping.xpm car_dealer.xpm flag_bk_tr.xpm flag_bk_wh.xpm flag_bl_wh.xpm fuel.xpm hospital.xpm hotel.xpm parking.xpm restaurant.xpm unknown.xpm burgerking.ico EXTRA_DIST = $(xpm_DATA) +burgerking.ico: + wget http://www.burgerking.de/favicon.ico -O burgerking.ico -- cgit v1.2.1 From 639a1ae2789c3db64c539042efe68e731e636cbe Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 28 Aug 2007 17:38:09 +0000 Subject: Changed api for gui and graphics git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@394 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/poi_geodownload/poi_geodownload.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/data/poi_geodownload/poi_geodownload.c b/data/poi_geodownload/poi_geodownload.c index 1c226d2d..a1824245 100644 --- a/data/poi_geodownload/poi_geodownload.c +++ b/data/poi_geodownload/poi_geodownload.c @@ -1,9 +1,9 @@ #include #include "debug.h" #include "coord.h" +#include "projection.h" #include "map.h" #include "item.h" -#include "projection.h" #include "plugin.h" @@ -693,6 +693,8 @@ map_rect_get_item_byid_poi_geodownload(struct map_rect_priv *mr, int id_hi, int static struct map_methods map_methods_poi_geodownload = { + projection_mg, + "iso8859-1", map_destroy_poi_geodownload, map_rect_new_poi_geodownload, map_rect_destroy_poi_geodownload, @@ -701,18 +703,20 @@ static struct map_methods map_methods_poi_geodownload = { }; static struct map_priv * -map_new_poi_geodownload(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) +map_new_poi_geodownload(struct map_methods *meth, struct attr **attrs) { struct map_priv *m; - dbg(1,"filename %s\n",filename); MdbCatalogEntry *entry; GPtrArray *catalog; int i; struct attr *attr; - + struct attr *data=attr_search(attrs, NULL, attr_data); + char *filename; + if (! data) + return NULL; + filename=data->u.str; + dbg(1,"filename %s\n",filename); *meth=map_methods_poi_geodownload; - *charset="iso8859-1"; - *pro=projection_mg; m=g_new(struct map_priv, 1); m->filename=g_strdup(filename); -- cgit v1.2.1 From 3afb1cbacc25e6a93b5884d94dc5fd8aa6bd7d5d Mon Sep 17 00:00:00 2001 From: horwitz Date: Tue, 28 Aug 2007 20:09:29 +0000 Subject: Add some more polygon types git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@395 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- data/mg/poly.c | 15 +++++++++++++++ item_def.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/data/mg/poly.c b/data/mg/poly.c index 90f547ee..cc24e59b 100644 --- a/data/mg/poly.c +++ b/data/mg/poly.c @@ -142,15 +142,30 @@ poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) case 0x2d: item->type=type_hospital_poly; break; + case 0x2e: + item->type=type_hospital_poly; + break; + case 0x2f: + item->type=type_university; + break; case 0x32: item->type=type_park_poly; break; case 0x34: item->type=type_sport_poly; break; + case 0x35: + item->type=type_sport_poly; + break; case 0x37: item->type=type_golf_course; break; + case 0x38: + item->type=type_national_park; + break; + case 0x39: + item->type=type_nature_park; + break; case 0x3c: item->type=type_water_poly; break; diff --git a/item_def.h b/item_def.h index 71d33113..0dbc1799 100644 --- a/item_def.h +++ b/item_def.h @@ -133,7 +133,11 @@ ITEM(airport_poly) ITEM(hospital_poly) ITEM(park_poly) ITEM(sport_poly) +ITEM(museum_poly) ITEM(image) ITEM(image_path) ITEM(commercial_center) ITEM(golf_course) +ITEM(university) +ITEM(national_park) +ITEM(nature_park) -- cgit v1.2.1 From 237cfc43256913d892846b47076a7762433d9089 Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 29 Aug 2007 18:32:16 +0000 Subject: Reworked osd git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@396 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 2 +- attr.c | 11 +- attr_def.h | 7 +- graphics.c | 16 ++ .../gtk_drawing_area/graphics_gtk_drawing_area.c | 12 +- navit.c | 21 +++ osd.c | 39 +++-- osd.h | 12 +- osd/Makefile.am | 2 +- osd/core/Makefile.am | 4 + osd/core/osd_core.c | 163 +++++++++++++++++++++ plugin_def.h | 8 +- xmlconfig.c | 14 ++ 13 files changed, 285 insertions(+), 26 deletions(-) create mode 100644 osd/core/Makefile.am create mode 100644 osd/core/osd_core.c diff --git a/Makefile.am b/Makefile.am index f6eb1369..211ef304 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ EXTRA_DIST = navit.xml navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_window.c debug.c \ file.c graphics.c gui.c item.c layout.c log.c main.c map.c \ - mapset.c maptype.c menu.c navit.c navigation.c param.c phrase.c plugin.c popup.c \ + mapset.c maptype.c menu.c navit.c navigation.c osd.c param.c phrase.c plugin.c popup.c \ profile.c route.c search.c speech.c transform.c track.c \ util.c vehicle.c xmlconfig.c attr.h attr_def.h callback.h color.h compass.h coord.h country.h \ cursor.h data.h data_window.h data_window_int.h debug.h destination.h draw_info.h \ diff --git a/attr.c b/attr.c index ceb74dc5..52b408eb 100644 --- a/attr.c +++ b/attr.c @@ -57,10 +57,15 @@ attr_new_from_text(const char *name, const char *value) case attr_item_type: ret->u.item_type=item_from_name(value); break; - case attr_data: - ret->u.str=value; - break; default: + if (attr >= attr_type_string_begin && attr <= attr_type_string_end) { + ret->u.str=value; + break; + } + if (attr >= attr_type_int_begin && attr <= attr_type_int_end) { + ret->u.num=atoi(value); + break; + } dbg(1,"default\n"); g_free(ret); ret=NULL; diff --git a/attr_def.h b/attr_def.h index ae8a0695..ed32336b 100644 --- a/attr_def.h +++ b/attr_def.h @@ -1,6 +1,7 @@ /* common */ ATTR2(none,0x00000000) ATTR(any) + ATTR2(type_item_begin,0x00010000) ATTR(town_streets_item) ATTR(street_name_item) @@ -9,12 +10,16 @@ ATTR(street_item) ATTR(street_number_item) ATTR(item_type) ATTR2(type_item_end,0x0001ffff) + ATTR2(type_int_begin,0x00020000) +ATTR(h) ATTR(id) ATTR(limit) ATTR(w) -ATTR(h) +ATTR(x) +ATTR(y) ATTR2(type_int_end,0x0002ffff) + ATTR2(type_string_begin,0x00030000) ATTR(label) ATTR(data) diff --git a/graphics.c b/graphics.c index 5c7c0003..6dced9a6 100644 --- a/graphics.c +++ b/graphics.c @@ -44,6 +44,15 @@ graphics_new(const char *type, struct attr **attrs) return this_; } +struct graphics * +graphics_overlay_new(struct graphics *parent, struct point *p, int w, int h) +{ + struct graphics *this_; + this_=g_new0(struct graphics, 1); + this_->priv=parent->meth.overlay_new(parent->priv, &this_->meth, p, w, h); + return this_; +} + void graphics_init(struct graphics *this_) @@ -161,6 +170,13 @@ graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct poin } +void +graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h) +{ + this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h); +} + + #include "attr.h" #include "popup.h" #include diff --git a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index 554f1203..d0cd1cc4 100644 --- a/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -7,6 +7,7 @@ #include #endif #include +#include "debug.h" #include "point.h" #include "graphics.h" #include "color.h" @@ -18,6 +19,7 @@ struct graphics_priv { GtkWidget *widget; GdkDrawable *drawable; GdkDrawable *background; + int background_ready; GdkColormap *colormap; FT_Library library; struct point p; @@ -493,10 +495,14 @@ overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int wi p2[3]=127; } } - if (window) - gdk_draw_drawable(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], overlay->background, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height); - else + if (window) { + if (overlay->background_ready) + gdk_draw_drawable(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], overlay->background, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height); + } + else { gdk_draw_drawable(overlay->background, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, 0, 0, overlay->width, overlay->height); + overlay->background_ready=1; + } gdk_draw_pixbuf(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixbuf2, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height, GDK_RGB_DITHER_NONE, 0, 0); if (window) gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, overlay->p.x, overlay->p.y, overlay->width, overlay->height); diff --git a/navit.c b/navit.c index 6aa995a3..7af90cbb 100644 --- a/navit.c +++ b/navit.c @@ -74,6 +74,7 @@ struct navit { GList *windows_items; struct navit_vehicle *vehicle; struct callback_list *vehicle_cbl; + struct callback_list *init_cbl; int pid; struct callback *nav_speech_cb; struct callback *roadbook_callback; @@ -185,6 +186,7 @@ navit_new(struct coord *center, enum projection pro, int zoom) main_add_navit(this_); this_->vehicle_cbl=callback_list_new(); + this_->init_cbl=callback_list_new(); f=popen("pidof /usr/bin/ipaq-sleep","r"); if (f) { @@ -229,6 +231,12 @@ navit_set_graphics(struct navit *this_, struct graphics *gra) graphics_register_button_callback(this_->gra, navit_button, this_); } +struct graphics * +navit_get_graphics(struct navit *this_) +{ + return this_->gra; +} + static void navit_map_toggle(struct menu *menu, void *this__p, void *map_p) { @@ -817,6 +825,7 @@ navit_init(struct navit *this_) navit_window_items_new(this_); #endif navit_debug(this_); + callback_list_call_1(this_->init_cbl, this_); } void @@ -972,6 +981,18 @@ navit_remove_vehicle_cb(struct navit *this_, struct callback *cb) callback_list_remove(this_->vehicle_cbl, cb); } +void +navit_add_init_cb(struct navit *this_, struct callback *cb) +{ + callback_list_add(this_->init_cbl, cb); +} + +void +navit_remove_init_cb(struct navit *this_, struct callback *cb) +{ + callback_list_remove(this_->init_cbl, cb); +} + void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv) { diff --git a/osd.c b/osd.c index 40703d4c..d078ff27 100644 --- a/osd.c +++ b/osd.c @@ -1,3 +1,4 @@ +#if 0 //#include #include #include @@ -10,17 +11,6 @@ #include "container.h" #include "osd.h" -struct osd { - struct graphics *gr; - struct graphics_gc *bg; - struct graphics_gc *white; - struct graphics_gc *green; - struct graphics_font *font; - - char command[256]; - char road_name[256]; -}; - void osd_set_next_command(char *new_command,char *new_road){ extern struct container *co; @@ -81,3 +71,30 @@ osd_new(struct container *co) osd_draw(this, co); return this; } +#endif + +#include +#include "debug.h" +#include "plugin.h" +#include "osd.h" + + +struct osd { + struct osd_methods meth; + struct osd_priv *priv; +}; + +struct osd * +osd_new(struct navit *nav, const char *type, struct attr **attrs) +{ + struct osd *o; + struct osd_priv *(*new)(struct navit *nav, struct osd_methods *meth, struct attr **attrs); + + new=plugin_get_osd_type(type); + if (! new) + return NULL; + o=g_new0(struct osd, 1); + o->priv=new(nav, &o->meth, attrs); + return o; +} + diff --git a/osd.h b/osd.h index 815b7a4a..0f28d12d 100644 --- a/osd.h +++ b/osd.h @@ -1,2 +1,10 @@ -struct osd * osd_new(struct container *co); -void osd_draw(struct osd *comp, struct container *co); +struct osd_methods { + void (*osd_destroy)(struct osd_priv *osd); +}; + +/* prototypes */ +struct attr; +struct navit; +struct osd; +struct osd *osd_new(struct navit *nav, const char *type, struct attr **attrs); +/* end of prototypes */ diff --git a/osd/Makefile.am b/osd/Makefile.am index e2baa045..eabd6910 100644 --- a/osd/Makefile.am +++ b/osd/Makefile.am @@ -1 +1 @@ -SUBDIRS= +SUBDIRS=core diff --git a/osd/core/Makefile.am b/osd/core/Makefile.am new file mode 100644 index 00000000..de7f6291 --- /dev/null +++ b/osd/core/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"osd_core\" +moduleosd_LTLIBRARIES = libosd_core.la +libosd_core_la_SOURCES = osd_core.c diff --git a/osd/core/osd_core.c b/osd/core/osd_core.c new file mode 100644 index 00000000..7afa464b --- /dev/null +++ b/osd/core/osd_core.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include "item.h" +#include "point.h" +#include "coord.h" +#include "graphics.h" +#include "transform.h" +#include "route.h" +#include "navit.h" +#include "plugin.h" +#include "debug.h" +#include "callback.h" +#include "color.h" + +struct compass { + struct point p; + struct graphics *gr; + struct graphics_gc *bg; + struct graphics_gc *white; + struct graphics_gc *green; + struct graphics_font *font; +}; + + +static void +transform_rotate(struct point *center, int angle, struct point *p, int count) +{ + int i,x,y; + double dx,dy; + for (i = 0 ; i < count ; i++) + { + dx=sin(M_PI*angle/180.0); + dy=cos(M_PI*angle/180.0); + x=dy*p->x-dx*p->y; + y=dx*p->x+dy*p->y; + + p->x=center->x+x; + p->y=center->y+y; + p++; + } +} + +static void +handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r, int dir) +{ + struct point ph[3]; + int l=r*0.4; + + ph[0].x=0; + ph[0].y=r; + ph[1].x=0; + ph[1].y=-r; + transform_rotate(p, dir, ph, 2); + graphics_draw_lines(gr, gc, ph, 2); + ph[0].x=-l; + ph[0].y=-r+l; + ph[1].x=0; + ph[1].y=-r; + ph[2].x=l; + ph[2].y=-r+l; + transform_rotate(p, dir, ph, 3); + graphics_draw_lines(gr, gc, ph, 3); +} + +static void +osd_compass_draw(struct compass *this, struct vehicle *v) +{ + struct point p; + struct coord *pos, *dest; + double *vehicle_dir,dir,distance; + int dx,dy; + char buffer[16]; + + graphics_draw_mode(this->gr, draw_mode_begin); + p.x=0; + p.y=0; + graphics_draw_rectangle(this->gr, this->bg, &p, 60, 80); + p.x=30; + p.y=30; + graphics_draw_circle(this->gr, this->white, &p, 50); + if (v) { + vehicle_dir=vehicle_dir_get(v); + handle(this->gr, this->white, &p, 20, -*vehicle_dir); +#if 0 /* FIXME */ + dest=route_get_destination(co->route); + if (dest) { + pos=vehicle_pos_get(co->vehicle); + dx=dest->x-pos->x; + dy=dest->y-pos->y; + dir=atan2(dx,dy)*180.0/M_PI; +#if 0 + printf("dx %d dy %d dir=%f vehicle_dir=%f\n", dx, dy, dir, *vehicle_dir); +#endif + if (! co->flags->orient_north) + dir-=*vehicle_dir; + handle(comp->gr, comp->green, &p, 20, dir); + p.x=8; + p.y=72; + distance=transform_distance(pos, dest)/1000.0; + if (distance >= 100) + sprintf(buffer,"%.0f km", distance); + else if (distance >= 10) + sprintf(buffer,"%.1f km", distance); + else + sprintf(buffer,"%.2f km", distance); + + comp->gr->draw_text(comp->gr, comp->green, NULL, comp->font, buffer, &p, 0x10000, 0); + } +#endif + } + graphics_draw_mode(this->gr, draw_mode_end); +} + +static void +osd_compass_init(struct compass *this, struct navit *nav) +{ + struct point p; + struct graphics *navit_gr; + struct color c; + navit_gr=navit_get_graphics(nav); + this->gr=graphics_overlay_new(navit_gr, &this->p, 60, 80); + + this->bg=graphics_gc_new(this->gr); + c.r=0; c.g=0; c.b=0; + graphics_gc_set_foreground(this->bg, &c); + + this->white=graphics_gc_new(this->gr); + c.r=65535; c.g=65535; c.b=65535; + graphics_gc_set_foreground(this->white, &c); + graphics_gc_set_linewidth(this->white, 2); + + this->green=graphics_gc_new(this->gr); + c.r=0; c.g=65535; c.b=0; + graphics_gc_set_foreground(this->green, &c); + graphics_gc_set_linewidth(this->green, 2); + + osd_compass_draw(this, NULL); +} + +struct osd_priv * +osd_compass_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs) +{ + struct compass *this=g_new0(struct compass, 1); + struct attr *attr; + this->p.x=20; + this->p.y=20; + attr=attr_search(attrs, NULL, attr_x); + if (attr) + this->p.x=attr->u.num; + attr=attr_search(attrs, NULL, attr_y); + if (attr) + this->p.y=attr->u.num; + navit_add_init_cb(nav, callback_new_1(osd_compass_init, this)); + return (struct osd_priv *) this; +} + +void +plugin_init(void) +{ + plugin_register_osd_type("compass", osd_compass_new); +} + diff --git a/plugin_def.h b/plugin_def.h index c3e93939..831dfc97 100644 --- a/plugin_def.h +++ b/plugin_def.h @@ -3,9 +3,9 @@ struct attr; PLUGIN_FUNC1(draw, struct container *, co) PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) struct navit; -PLUGIN_TYPE(graphics, (struct graphics_methods *meth, struct attr **attr)) -PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, struct attr **attr)) -PLUGIN_TYPE(map, (struct map_methods *meth, struct attr **attr)) -PLUGIN_TYPE(osd, (struct osd_methods *meth)) +PLUGIN_TYPE(graphics, (struct graphics_methods *meth, struct attr **attrs)) +PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, struct attr **attrs)) +PLUGIN_TYPE(map, (struct map_methods *meth, struct attr **attrs)) +PLUGIN_TYPE(osd, (struct navit *nav, struct osd_methods *meth, struct attr **attrs)) PLUGIN_TYPE(speech, (char *data, struct speech_methods *meth)) PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth)) diff --git a/xmlconfig.c b/xmlconfig.c index a36d3bd4..6e1b79a5 100644 --- a/xmlconfig.c +++ b/xmlconfig.c @@ -18,6 +18,7 @@ #include "graphics.h" #include "gui.h" #include "xmlconfig.h" +#include "osd.h" struct xmlstate { @@ -350,6 +351,18 @@ xmlconfig_navigation(struct xmlstate *state) return 1; } +static int +xmlconfig_osd(struct xmlstate *state) +{ + struct attr **attrs; + const char *type=find_attribute(state, "type", 1); + if (! type) + return 0; + attrs=convert_to_attrs(state); + state->element_object = osd_new(state->parent->element_object, type, attrs); + return 1; +} + static int xmlconfig_announce(struct xmlstate *state) { @@ -591,6 +604,7 @@ struct element_func { { "mapset", "navit", xmlconfig_mapset}, { "map", "mapset", xmlconfig_map}, { "navigation", "navit", xmlconfig_navigation}, + { "osd", "navit", xmlconfig_osd}, { "announce", "navigation", xmlconfig_announce}, { "speech", "navit", xmlconfig_speech}, { "tracking", "navit", xmlconfig_tracking}, -- cgit v1.2.1 From a077e644c5bec6721048b8bc5a612a0469e5db8e Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 29 Aug 2007 18:41:04 +0000 Subject: Reworked osd git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@397 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 211ef304..66efd7e6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,7 +16,7 @@ navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_wind util.c vehicle.c xmlconfig.c attr.h attr_def.h callback.h color.h compass.h coord.h country.h \ cursor.h data.h data_window.h data_window_int.h debug.h destination.h draw_info.h \ file.h graphics.h gtkext.h gui.h item.h item_def.h log.h layer.h layout.h main.h map-share.h map.h\ - map_data.h mapset.h maptype.h menu.h navigation.h navit.h \ + map_data.h mapset.h maptype.h menu.h navigation.h navit.h osd.h \ param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h profile.h search.h speech.h statusbar.h \ transform.h track.h util.h vehicle.h xmlconfig.h -- cgit v1.2.1 From 0054b4c8ce103d2982e0ca4657881bba9ee8dd3b Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 29 Aug 2007 21:30:21 +0000 Subject: Improve map display git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@398 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit.xml | 94 ++++++++++++++++++--------------------------------------------- 1 file changed, 27 insertions(+), 67 deletions(-) diff --git a/navit.xml b/navit.xml index d31275b0..2eca6416 100644 --- a/navit.xml +++ b/navit.xml @@ -377,44 +377,44 @@ - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + @@ -459,47 +459,7 @@ - - - - + + + -- cgit v1.2.1 From 54996ac1d86fa079b724d56c3e9ac463604abeeb Mon Sep 17 00:00:00 2001 From: horwitz Date: Wed, 29 Aug 2007 21:56:05 +0000 Subject: Fix typo and increase inimal font size git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@399 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/navit.xml b/navit.xml index 2eca6416..31241df7 100644 --- a/navit.xml +++ b/navit.xml @@ -387,12 +387,12 @@