/[zanavi_public1]/navit/navit/bookmarks.c
ZANavi

Contents of /navit/navit/bookmarks.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (hide annotations) (download)
Wed Mar 4 14:00:54 2015 UTC (7 years, 11 months ago) by zoff99
File MIME type: text/plain
File size: 20452 byte(s)
new market version, lots of fixes
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2010 Navit Team
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     #include <stdlib.h>
21     #include <glib.h>
22     #include <stdio.h>
23     #include "config.h"
24     #ifdef HAVE_UNISTD_H
25     #include <unistd.h>
26     #endif
27     #include "file.h"
28     #include "debug.h"
29     #include "projection.h"
30     #include "coord.h"
31     #include "transform.h"
32     #include "callback.h"
33     #include "map.h"
34     #include "command.h"
35     #include "bookmarks.h"
36     #include "navit.h"
37     #include "navit_nls.h"
38     #include "util.h"
39    
40     /* FIXME: Move this to support directory */
41     #ifdef _MSC_VER
42     #include <windows.h>
43     static int ftruncate(int fd, __int64 length)
44     {
45     HANDLE fh = (HANDLE)_get_osfhandle(fd);
46     if (!fh || _lseeki64(fd, length, SEEK_SET)) {
47     return -1;
48     }
49     return SetEndOfFile(fh) ? 0 : -1;
50     }
51     #endif /* _MSC_VER */
52    
53     struct bookmarks {
54     //data storage
55     struct map *bookmark;
56     struct map_rect *mr;
57     GHashTable *bookmarks_hash;
58     GList *bookmarks_list;
59     char* bookmark_file;
60     char *working_file;
61     struct bookmark_item_priv* clipboard;
62     struct bookmark_item_priv* root;
63     struct bookmark_item_priv* current;
64    
65     //Refs to other objects
66     struct transformation *trans;
67     struct attr **attrs;
68     struct callback_list *attr_cbl;
69     struct attr *parent;
70     };
71    
72     struct bookmark_item_priv {
73     char *label;
74     enum item_type type;
75     struct pcoord c;
76     GList *children;
77     GList *iter;
78     struct bookmark_item_priv *parent;
79     struct item item;
80     };
81    
82     void bookmarks_move_root(struct bookmarks *this_) {
83     this_->current=this_->root;
84     this_->current->iter=g_list_first(this_->current->children);
85     dbg(2,"Root list have %u entries\n",g_list_length(this_->current->children));
86     return;
87     }
88     void bookmarks_move_up(struct bookmarks *this_) {
89     if (this_->current->parent) {
90     this_->current=this_->current->parent;
91     this_->current->iter=this_->current->children;
92     }
93     return;
94     }
95     int bookmarks_move_down(struct bookmarks *this_,const char* name) {
96     bookmarks_item_rewind(this_);
97     if (this_->current->children==NULL) {
98     return 0;
99     }
100     while (this_->current->iter!=NULL) {
101     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
102     if (!strcmp(data->label,name)) {
103     this_->current=(struct bookmark_item_priv*)this_->current->iter->data;
104     this_->current->iter=g_list_first(this_->current->children);
105     dbg(2,"%s list have %u entries\n",this_->current->label,g_list_length(this_->current->children));
106     return 1;
107     }
108     this_->current->iter=g_list_next(this_->current->iter);
109     }
110     return 0;
111     }
112    
113     void bookmarks_item_rewind(struct bookmarks* this_) {
114     this_->current->children=g_list_first(this_->current->children);
115     this_->current->iter=this_->current->children;
116     this_->current->iter=this_->current->children;
117     }
118     struct item* bookmarks_get_item(struct bookmarks* this_) {
119     struct item item,*ret;
120     if (this_->current->iter==NULL) {
121     return NULL;
122     }
123    
124     item=((struct bookmark_item_priv*)this_->current->iter->data)->item;
125     this_->current->iter=g_list_next(this_->current->iter);
126    
127     ret = map_rect_get_item_byid(this_->mr, item.id_hi, item.id_lo);
128    
129     return ret;
130     }
131    
132     const char* bookmarks_item_cwd(struct bookmarks* this_) {
133     return this_->current->label;
134     }
135    
136     static void bookmarks_clear_item(struct bookmark_item_priv *b_item) {
137     b_item->children=g_list_first(b_item->children);
138     while(b_item->children) {
139     bookmarks_clear_item((struct bookmark_item_priv*)b_item->children->data);
140     b_item->children=g_list_next(b_item->children);
141     }
142     g_free(b_item->label);
143     g_free(b_item);
144     }
145    
146     static void
147     bookmarks_clear_hash(struct bookmarks *this_) {
148     bookmarks_clear_item(this_->root);
149     g_hash_table_destroy(this_->bookmarks_hash);
150     g_list_free(this_->bookmarks_list);
151     }
152    
153     static void
154     bookmarks_load_hash(struct bookmarks *this_) {
155     struct bookmark_item_priv *b_item;
156     struct item *item;
157     struct attr attr;
158     struct coord c;
159     char *pos,*finder;
160     char *copy_helper;
161    
162     if (this_->mr) {
163     map_rect_destroy(this_->mr);
164     }
165     this_->mr=map_rect_new(this_->bookmark, NULL);
166    
167     this_->bookmarks_hash=g_hash_table_new(g_str_hash, g_str_equal);
168     this_->root=g_new0(struct bookmark_item_priv,1);
169     this_->root->type=type_none;
170     this_->root->parent=NULL;
171     this_->root->children=NULL;
172     bookmarks_move_root(this_);
173    
174     while ((item=map_rect_get_item(this_->mr))) {
175     if (item->type != type_bookmark && item->type != type_bookmark_folder ) continue;
176     if (!item_attr_get(item, attr_path, &attr)) {
177     item_attr_get(item, attr_label, &attr);
178     }
179     item_coord_get(item, &c, 1);
180    
181     b_item=g_new0(struct bookmark_item_priv,1);
182     b_item->c.x=c.x;
183     b_item->c.y=c.y;
184     b_item->label=g_strdup(attr.u.str);
185     b_item->type=item->type;
186     b_item->item=*item;
187    
188     //Prepare position
189     bookmarks_move_root(this_);
190     finder=b_item->label;
191     while ((pos=strchr(finder,'/'))) {
192     *pos=0x00;
193     dbg(1,"Found path entry: %s\n",finder);
194     if (!bookmarks_move_down(this_,finder)) {
195     struct bookmark_item_priv *path_item=g_new0(struct bookmark_item_priv,1);
196     path_item->type=type_bookmark_folder;
197     path_item->parent=this_->current;
198     path_item->children=NULL;
199     path_item->label=g_strdup(finder);
200    
201     this_->current->children=g_list_append(this_->current->children,path_item);
202     this_->current=path_item;
203     g_hash_table_insert(this_->bookmarks_hash,b_item->label,path_item);
204     this_->bookmarks_list=g_list_append(this_->bookmarks_list,path_item);
205     }
206     finder+=strlen(finder)+1;
207     }
208     copy_helper=g_strdup(finder);
209     free(b_item->label);
210     b_item->label=copy_helper;
211     b_item->parent=this_->current;
212    
213     g_hash_table_insert(this_->bookmarks_hash,b_item->label,b_item);
214     this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
215     this_->current->children=g_list_append(this_->current->children,b_item);
216     this_->current->children=g_list_first(this_->current->children);
217     dbg(1,"Added %s to %s and current list now %u long\n",b_item->label,this_->current->label,g_list_length(this_->current->children));
218     }
219     bookmarks_move_root(this_);
220     }
221    
222     struct bookmarks *
223 zoff99 31 bookmarks_new(struct attr *parent, struct attr **attrs, struct transformation *trans)
224     {
225 zoff99 2 struct bookmarks *this_;
226    
227 zoff99 31 if (parent->type!=attr_navit)
228     {
229 zoff99 2 return NULL;
230     }
231    
232 zoff99 31 dbg(0,"bb 001\n");
233    
234 zoff99 2 this_ = g_new0(struct bookmarks,1);
235 zoff99 40 this_->attr_cbl=callback_list_new("bookmarks_new:this_->attr_cbl");
236 zoff99 2 this_->parent=parent;
237     //this_->attrs=attr_list_dup(attrs);
238     this_->trans=trans;
239    
240 zoff99 31
241     return this_;
242    
243     #if 0
244     dbg(0,"bb 002\n");
245    
246 zoff99 2 this_->bookmark_file=g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/bookmark.txt", NULL);
247     this_->working_file=g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/bookmark.txt.tmp", NULL);
248    
249 zoff99 31 dbg(0,"bb 003\n");
250    
251 zoff99 2 this_->clipboard=g_new0(struct bookmark_item_priv,1);
252    
253 zoff99 31 dbg(0,"bb 004\n");
254    
255 zoff99 2 {
256     //Load map now
257     struct attr type={attr_type, {"textfile"}}, data={attr_data, {this_->bookmark_file}};
258     struct attr *attrs[]={&type, &data, NULL};
259     this_->bookmark=map_new(this_->parent, attrs);
260     if (!this_->bookmark)
261 zoff99 31 {
262 zoff99 2 return NULL;
263 zoff99 31 }
264     dbg(0,"bb 005\n");
265 zoff99 2 bookmarks_load_hash(this_);
266     }
267    
268 zoff99 31 dbg(0,"bb 006\n");
269    
270 zoff99 2 return this_;
271 zoff99 31 #endif
272 zoff99 2 }
273    
274     void
275     bookmarks_destroy(struct bookmarks *this_) {
276    
277     bookmarks_clear_hash(this_);
278    
279     map_destroy(this_->bookmark);
280     callback_list_destroy(this_->attr_cbl);
281    
282     g_free(this_->bookmark_file);
283     g_free(this_->working_file);
284    
285     g_free(this_->clipboard);
286     g_free(this_);
287     }
288    
289     struct map*
290     bookmarks_get_map(struct bookmarks *this_) {
291     return this_->bookmark;
292     }
293    
294     enum projection bookmarks_get_projection(struct bookmarks *this_){
295     return map_projection(this_->bookmark);
296     }
297     void
298     bookmarks_add_callback(struct bookmarks *this_, struct callback *cb)
299     {
300     callback_list_add(this_->attr_cbl, cb);
301     }
302    
303     static int
304     bookmarks_store_bookmarks_to_file(struct bookmarks *this_, int limit,int replace) {
305     FILE *f;
306     struct bookmark_item_priv *item,*parent_item;
307     char *fullname;
308     const char *prostr;
309     int result;
310 zoff99 31 GHashTable *dedup=g_hash_table_new_full(g_str_hash,g_str_equal,g_free_func,NULL);
311 zoff99 2
312     f=fopen(this_->working_file, replace ? "w+" : "a+");
313     if (f==NULL) {
314 zoff99 27 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
315 zoff99 2 return FALSE;
316     }
317    
318     this_->bookmarks_list=g_list_first(this_->bookmarks_list);
319     while (this_->bookmarks_list) {
320     item=(struct bookmark_item_priv*)this_->bookmarks_list->data;
321    
322     parent_item=item;
323     fullname=g_strdup(item->label);
324     while ((parent_item=parent_item->parent)) {
325     char *pathHelper;
326     if (parent_item->label) {
327     pathHelper=g_strconcat(parent_item->label,"/",fullname,NULL);
328     g_free(fullname);
329     fullname=g_strdup(pathHelper);
330     g_free(pathHelper);
331     dbg(1,"full name: %s\n",fullname);
332     }
333     }
334    
335     if (!g_hash_table_lookup(dedup,fullname)) {
336     g_hash_table_insert(dedup,fullname,fullname);
337     if (item->type == type_bookmark) {
338     prostr = projection_to_name(projection_mg,NULL);
339     if (fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\" path=\"%s\"\n",
340     prostr, *prostr ? ":" : "",
341     item->c.x >= 0 ? "":"-", item->c.x >= 0 ? item->c.x : -item->c.x,
342     item->c.y >= 0 ? "":"-", item->c.y >= 0 ? item->c.y : -item->c.y,
343     "bookmark", item->label,fullname)<1) {
344     g_free(fullname);
345     break;
346     }
347     }
348     if (item->type == type_bookmark_folder) {
349     prostr = projection_to_name(projection_mg,NULL);
350     if (fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\" path=\"%s\"\n",
351     prostr, *prostr ? ":" : "",
352     "", 0,
353     "", 0,
354     "bookmark_folder", item->label,fullname)<1) {
355     g_free(fullname);
356     break;
357     }
358     }
359     }
360    
361     /* Limit could be zero, so we start decrementing it from zero and never reach 1
362     or it was bigger and we decreased it earlier. So when this counter becomes 1, we know
363     that we have enough entries in bookmarks file */
364     if (limit==1) {
365     break;
366     }
367     limit--;
368    
369     this_->bookmarks_list=g_list_next(this_->bookmarks_list);
370     }
371    
372     fclose(f);
373    
374     g_hash_table_destroy(dedup);
375    
376     if (this_->mr) {
377     map_rect_destroy(this_->mr);
378     this_->mr = 0;
379     }
380    
381     unlink(this_->bookmark_file);
382     result=(rename(this_->working_file,this_->bookmark_file)==0);
383     if (!result)
384     {
385 zoff99 27 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
386 zoff99 2 }
387     return result;
388     }
389    
390     /*
391     * bookmarks_get_destination_file
392     *
393     * returns the name of the file used to store destinations with its
394     * full path
395     *
396     * arg: gboolean create: create the directory where the file is stored
397     * if it does not exist
398     */
399     char*
400     bookmarks_get_destination_file(gboolean create)
401     {
402     return g_strjoin(NULL, navit_get_user_data_directory(create), "/destination.txt", NULL);
403     }
404    
405     /*
406     * bookmarks_get_center_file
407     *
408     * returns the name of the file used to store the center file with its
409     * full path
410     *
411     * arg: gboolean create: create the directory where the file is stored
412     * if it does not exist
413     */
414     char*
415     bookmarks_get_center_file(gboolean create)
416     {
417     return g_strjoin(NULL, navit_get_user_data_directory(create), "/center.txt", NULL);
418     }
419    
420     void
421     bookmarks_set_center_from_file(struct bookmarks *this_, char *file)
422     {
423     FILE *f;
424     char *line = NULL;
425    
426     dbg(0,"enter\n");
427    
428     size_t line_size = 0;
429     enum projection pro;
430     struct coord *center;
431    
432     f = fopen(file, "r");
433     if (! f)
434     return;
435     getline(&line, &line_size, f);
436     fclose(f);
437 zoff99 31 if (line)
438     {
439 zoff99 2 center = transform_center(this_->trans);
440     pro = transform_get_projection(this_->trans);
441     coord_parse(g_strchomp(line), pro, center);
442 zoff99 27 dbg(0,"******** load center from file *********\n");
443 zoff99 2 free(line);
444     }
445     return;
446     }
447    
448     void
449 zoff99 40 bookmarks_get_center_from_file(struct bookmarks *this_, char *file, struct coord *center)
450     {
451     FILE *f;
452     char *line = NULL;
453    
454     dbg(0,"enter\n");
455    
456     size_t line_size = 0;
457     enum projection pro;
458    
459     f = fopen(file, "r");
460     if (! f)
461     return;
462     getline(&line, &line_size, f);
463     fclose(f);
464     if (line)
465     {
466     pro = transform_get_projection(this_->trans);
467     coord_parse(g_strchomp(line), pro, center);
468     dbg(0,"******** get center from file *********\n");
469     free(line);
470     }
471     return;
472     }
473    
474    
475     void
476 zoff99 2 bookmarks_write_center_to_file(struct bookmarks *this_, char *file)
477     {
478 zoff99 27 dbg(0,"EEnter\n");
479    
480 zoff99 2 FILE *f;
481     enum projection pro;
482     struct coord *center;
483    
484     f = fopen(file, "w+");
485     if (f)
486     {
487     // save (pixel-on-screen width/2 height/2) screen center
488     struct coord_geo g22;
489     struct coord c22;
490     struct point p;
491    
492     int width, height;
493     transform_get_size(this_->trans, &width, &height);
494     p.x=width/2;
495     p.y=height/2;
496    
497     transform_reverse(this_->trans, &p, &c22);
498     //dbg(0,"%f, %f\n",a, b);
499     //dbg(0,"%d, %d\n",p.x, p.y);
500     // * transform_to_geo(projection_mg, &c22, &g22);
501     //dbg(0,"%d, %d, %f, %f\n",c22.x, c22.y, g22.lat, g22.lng);
502     // * result=g_strdup_printf("%f:%f",g22.lat,g22.lng);
503    
504     // + center = transform_center(this_->trans);
505     pro = transform_get_projection(this_->trans);
506     // + coord_print(pro, center, f);
507     coord_print(pro, &c22, f);
508     fclose(f);
509 zoff99 27 dbg(0,"******** write center to file *********\n");
510 zoff99 2 }
511     else
512     {
513     perror(file);
514     }
515 zoff99 27
516     dbg(0,"ready\n");
517    
518 zoff99 2 return;
519     }
520    
521     static void
522     bookmarks_emit_dbus_signal(struct bookmarks *this_, struct pcoord *c, const char *description,int create)
523     {
524     struct attr attr1,attr2,attr3,attr4,cb,*attr_list[5];
525     int valid=0;
526     attr1.type=attr_type;
527     attr1.u.str="bookmark";
528     attr2.type=attr_data;
529     attr2.u.str=create ? "create" : "delete";
530     attr3.type=attr_data;
531     attr3.u.str=(char *)description;
532     attr4.type=attr_coord;
533     attr4.u.pcoord=c;
534     attr_list[0]=&attr1;
535     attr_list[1]=&attr2;
536     attr_list[2]=&attr3;
537     attr_list[3]=&attr4;
538     attr_list[4]=NULL;
539     if (navit_get_attr(this_->parent->u.navit, attr_callback_list, &cb, NULL))
540     callback_list_call_attr_4(cb.u.callback_list, attr_command, "dbus_send_signal", attr_list, NULL, &valid);
541     }
542    
543     /**
544     * Record the given set of coordinates as a bookmark
545     *
546     * @param navit The navit instance
547     * @param c The coordinate to store
548     * @param description A label which allows the user to later identify this bookmark
549     * @returns nothing
550     */
551     int
552     bookmarks_add_bookmark(struct bookmarks *this_, struct pcoord *pc, const char *description)
553     {
554     struct bookmark_item_priv *b_item=g_new0(struct bookmark_item_priv,1);
555     int result;
556    
557     if (pc) {
558     b_item->c.x=pc->x;
559     b_item->c.y=pc->y;
560     b_item->type=type_bookmark;
561     } else {
562     b_item->type=type_bookmark_folder;
563     }
564     b_item->label=g_strdup(description);
565     b_item->parent=this_->current;
566     b_item->children=NULL;
567    
568     this_->current->children=g_list_first(this_->current->children);
569     this_->current->children=g_list_append(this_->current->children,b_item);
570     this_->bookmarks_list=g_list_first(this_->bookmarks_list);
571     this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
572    
573     result=bookmarks_store_bookmarks_to_file(this_,0,0);
574    
575     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
576     bookmarks_clear_hash(this_);
577     bookmarks_load_hash(this_);
578    
579     bookmarks_emit_dbus_signal(this_,&(b_item->c),description,TRUE);
580    
581     return result;
582     }
583    
584     int
585     bookmarks_cut_bookmark(struct bookmarks *this_, const char *label) {
586     if (bookmarks_copy_bookmark(this_,label)) {
587     return bookmarks_delete_bookmark(this_,label);
588     }
589    
590     return FALSE;
591     }
592     int
593     bookmarks_copy_bookmark(struct bookmarks *this_, const char *label) {
594     bookmarks_item_rewind(this_);
595     if (this_->current->children==NULL) {
596     return 0;
597     }
598     while (this_->current->iter!=NULL) {
599     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
600     if (!strcmp(data->label,label)) {
601     this_->clipboard->c=data->c;
602     this_->clipboard->type=data->type;
603     this_->clipboard->item=data->item;
604     this_->clipboard->children=data->children;
605     if (!this_->clipboard->label) {
606     g_free(this_->clipboard->label);
607     }
608     this_->clipboard->label=g_strdup(data->label);
609     return TRUE;
610     }
611     this_->current->iter=g_list_next(this_->current->iter);
612     }
613     return FALSE;
614     }
615     int
616     bookmarks_paste_bookmark(struct bookmarks *this_) {
617     int result;
618     struct bookmark_item_priv* b_item;
619    
620     if (!this_->clipboard->label) {
621     return FALSE;
622     }
623    
624     b_item=g_new0(struct bookmark_item_priv,1);
625     b_item->c.x=this_->clipboard->c.x;
626     b_item->c.y=this_->clipboard->c.y;
627     b_item->label=g_strdup(this_->clipboard->label);
628     b_item->type=this_->clipboard->type;
629     b_item->item=this_->clipboard->item;
630     b_item->parent=this_->current;
631     b_item->children=this_->clipboard->children;
632    
633     g_hash_table_insert(this_->bookmarks_hash,b_item->label,b_item);
634     this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
635     this_->current->children=g_list_append(this_->current->children,b_item);
636     this_->current->children=g_list_first(this_->current->children);
637    
638     result=bookmarks_store_bookmarks_to_file(this_,0,0);
639    
640     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
641     bookmarks_clear_hash(this_);
642     bookmarks_load_hash(this_);
643    
644     return result;
645     }
646    
647    
648     int
649     bookmarks_delete_bookmark(struct bookmarks *this_, const char *label) {
650     int result;
651    
652     bookmarks_item_rewind(this_);
653     if (this_->current->children==NULL) {
654     return 0;
655     }
656     while (this_->current->iter!=NULL) {
657     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
658     if (!strcmp(data->label,label)) {
659     this_->bookmarks_list=g_list_first(this_->bookmarks_list);
660     this_->bookmarks_list=g_list_remove(this_->bookmarks_list,data);
661    
662     result=bookmarks_store_bookmarks_to_file(this_,0,0);
663    
664     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
665     bookmarks_clear_hash(this_);
666     bookmarks_load_hash(this_);
667    
668     bookmarks_emit_dbus_signal(this_,&(data->c),label,FALSE);
669    
670     return result;
671     }
672     this_->current->iter=g_list_next(this_->current->iter);
673     }
674    
675     return FALSE;
676     }
677    
678     int
679     bookmarks_rename_bookmark(struct bookmarks *this_, const char *oldName, const char* newName) {
680     int result;
681    
682     bookmarks_item_rewind(this_);
683     if (this_->current->children==NULL) {
684     return 0;
685     }
686     while (this_->current->iter!=NULL) {
687     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
688     if (!strcmp(data->label,oldName)) {
689     g_free(data->label);
690     data->label=g_strdup(newName);
691    
692     result=bookmarks_store_bookmarks_to_file(this_,0,0);
693    
694     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
695     bookmarks_clear_hash(this_);
696     bookmarks_load_hash(this_);
697    
698     return result;
699     }
700     this_->current->iter=g_list_next(this_->current->iter);
701     }
702    
703     return FALSE;
704     }
705    
706     static int
707     bookmarks_shrink(char *bookmarks, int offset)
708     {
709     char buffer[4096];
710     int count,ioffset=offset,ooffset=0;
711     FILE *f;
712     if (!offset)
713     return 1;
714     f = fopen(bookmarks, "r+");
715     if (!f)
716     return 0;
717     for (;;) {
718     fseek(f, ioffset, SEEK_SET);
719     count=fread(buffer, 1, sizeof(buffer), f);
720     if (!count)
721     break;
722     fseek(f, ooffset, SEEK_SET);
723     if (fwrite(buffer, count, 1, f) != 1)
724     return 0;
725     ioffset+=count;
726     ooffset+=count;
727     }
728     fflush(f);
729     ftruncate(fileno(f),ooffset);
730     #ifdef HAVE_FSYNC
731     fsync(fileno(f));
732     #endif
733     fclose(f);
734     return 1;
735     }
736    
737     /**
738     * @param limit Limits the number of entries in the "backlog". Set to 0 for "infinite"
739     */
740     void
741     bookmarks_append_coord(struct bookmarks *this_, char *file, struct pcoord *c, int count, const char *type, const char *description, GHashTable *h, int limit)
742     {
743     FILE *f;
744     const char *prostr;
745    
746     if (limit != 0 && (f=fopen(file, "r"))) {
747     int *offsets=g_alloca(sizeof(int)*limit);
748     int offset_pos=0;
749     int offset;
750     char buffer[4096];
751     memset(offsets, 0, sizeof(int)*limit);
752     for (;;) {
753     offset=ftell(f);
754     if (!fgets(buffer, sizeof(buffer), f))
755     break;
756     if (strstr(buffer,"type=")) {
757     offsets[offset_pos]=offset;
758     offset_pos=(offset_pos+1)%limit;
759     }
760     }
761     fclose(f);
762     bookmarks_shrink(file, offsets[offset_pos]);
763     }
764     f=fopen(file, "a");
765     if (f) {
766     if (c) {
767     int i;
768     if (description)
769     fprintf(f,"type=%s label=\"%s\"\n", type, description);
770     else
771     fprintf(f,"type=%s\n", type);
772     for (i = 0 ; i < count ; i++) {
773     prostr = projection_to_name(c[i].pro,NULL);
774     fprintf(f,"%s%s%s0x%x %s0x%x\n",
775     prostr, *prostr ? ":" : "",
776     c[i].x >= 0 ? "":"-", c[i].x >= 0 ? c[i].x : -c[i].x,
777     c[i].y >= 0 ? "":"-", c[i].y >= 0 ? c[i].y : -c[i].y);
778     }
779     } else
780     fprintf(f,"\n");
781     }
782     fclose(f);
783     }
784    

   
Visit the ZANavi Wiki