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

Contents of /navit/navit/bookmarks.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 19948 byte(s)
new map version, lots of fixes and experimental new features
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     this_->attr_cbl=callback_list_new();
236     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     bookmarks_write_center_to_file(struct bookmarks *this_, char *file)
450     {
451 zoff99 27 dbg(0,"EEnter\n");
452    
453 zoff99 2 FILE *f;
454     enum projection pro;
455     struct coord *center;
456    
457     f = fopen(file, "w+");
458     if (f)
459     {
460     // save (pixel-on-screen width/2 height/2) screen center
461     struct coord_geo g22;
462     struct coord c22;
463     struct point p;
464    
465     int width, height;
466     transform_get_size(this_->trans, &width, &height);
467     p.x=width/2;
468     p.y=height/2;
469    
470     transform_reverse(this_->trans, &p, &c22);
471     //dbg(0,"%f, %f\n",a, b);
472     //dbg(0,"%d, %d\n",p.x, p.y);
473     // * transform_to_geo(projection_mg, &c22, &g22);
474     //dbg(0,"%d, %d, %f, %f\n",c22.x, c22.y, g22.lat, g22.lng);
475     // * result=g_strdup_printf("%f:%f",g22.lat,g22.lng);
476    
477     // + center = transform_center(this_->trans);
478     pro = transform_get_projection(this_->trans);
479     // + coord_print(pro, center, f);
480     coord_print(pro, &c22, f);
481     fclose(f);
482 zoff99 27 dbg(0,"******** write center to file *********\n");
483 zoff99 2 }
484     else
485     {
486     perror(file);
487     }
488 zoff99 27
489     dbg(0,"ready\n");
490    
491 zoff99 2 return;
492     }
493    
494     static void
495     bookmarks_emit_dbus_signal(struct bookmarks *this_, struct pcoord *c, const char *description,int create)
496     {
497     struct attr attr1,attr2,attr3,attr4,cb,*attr_list[5];
498     int valid=0;
499     attr1.type=attr_type;
500     attr1.u.str="bookmark";
501     attr2.type=attr_data;
502     attr2.u.str=create ? "create" : "delete";
503     attr3.type=attr_data;
504     attr3.u.str=(char *)description;
505     attr4.type=attr_coord;
506     attr4.u.pcoord=c;
507     attr_list[0]=&attr1;
508     attr_list[1]=&attr2;
509     attr_list[2]=&attr3;
510     attr_list[3]=&attr4;
511     attr_list[4]=NULL;
512     if (navit_get_attr(this_->parent->u.navit, attr_callback_list, &cb, NULL))
513     callback_list_call_attr_4(cb.u.callback_list, attr_command, "dbus_send_signal", attr_list, NULL, &valid);
514     }
515    
516     /**
517     * Record the given set of coordinates as a bookmark
518     *
519     * @param navit The navit instance
520     * @param c The coordinate to store
521     * @param description A label which allows the user to later identify this bookmark
522     * @returns nothing
523     */
524     int
525     bookmarks_add_bookmark(struct bookmarks *this_, struct pcoord *pc, const char *description)
526     {
527     struct bookmark_item_priv *b_item=g_new0(struct bookmark_item_priv,1);
528     int result;
529    
530     if (pc) {
531     b_item->c.x=pc->x;
532     b_item->c.y=pc->y;
533     b_item->type=type_bookmark;
534     } else {
535     b_item->type=type_bookmark_folder;
536     }
537     b_item->label=g_strdup(description);
538     b_item->parent=this_->current;
539     b_item->children=NULL;
540    
541     this_->current->children=g_list_first(this_->current->children);
542     this_->current->children=g_list_append(this_->current->children,b_item);
543     this_->bookmarks_list=g_list_first(this_->bookmarks_list);
544     this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
545    
546     result=bookmarks_store_bookmarks_to_file(this_,0,0);
547    
548     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
549     bookmarks_clear_hash(this_);
550     bookmarks_load_hash(this_);
551    
552     bookmarks_emit_dbus_signal(this_,&(b_item->c),description,TRUE);
553    
554     return result;
555     }
556    
557     int
558     bookmarks_cut_bookmark(struct bookmarks *this_, const char *label) {
559     if (bookmarks_copy_bookmark(this_,label)) {
560     return bookmarks_delete_bookmark(this_,label);
561     }
562    
563     return FALSE;
564     }
565     int
566     bookmarks_copy_bookmark(struct bookmarks *this_, const char *label) {
567     bookmarks_item_rewind(this_);
568     if (this_->current->children==NULL) {
569     return 0;
570     }
571     while (this_->current->iter!=NULL) {
572     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
573     if (!strcmp(data->label,label)) {
574     this_->clipboard->c=data->c;
575     this_->clipboard->type=data->type;
576     this_->clipboard->item=data->item;
577     this_->clipboard->children=data->children;
578     if (!this_->clipboard->label) {
579     g_free(this_->clipboard->label);
580     }
581     this_->clipboard->label=g_strdup(data->label);
582     return TRUE;
583     }
584     this_->current->iter=g_list_next(this_->current->iter);
585     }
586     return FALSE;
587     }
588     int
589     bookmarks_paste_bookmark(struct bookmarks *this_) {
590     int result;
591     struct bookmark_item_priv* b_item;
592    
593     if (!this_->clipboard->label) {
594     return FALSE;
595     }
596    
597     b_item=g_new0(struct bookmark_item_priv,1);
598     b_item->c.x=this_->clipboard->c.x;
599     b_item->c.y=this_->clipboard->c.y;
600     b_item->label=g_strdup(this_->clipboard->label);
601     b_item->type=this_->clipboard->type;
602     b_item->item=this_->clipboard->item;
603     b_item->parent=this_->current;
604     b_item->children=this_->clipboard->children;
605    
606     g_hash_table_insert(this_->bookmarks_hash,b_item->label,b_item);
607     this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
608     this_->current->children=g_list_append(this_->current->children,b_item);
609     this_->current->children=g_list_first(this_->current->children);
610    
611     result=bookmarks_store_bookmarks_to_file(this_,0,0);
612    
613     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
614     bookmarks_clear_hash(this_);
615     bookmarks_load_hash(this_);
616    
617     return result;
618     }
619    
620    
621     int
622     bookmarks_delete_bookmark(struct bookmarks *this_, const char *label) {
623     int result;
624    
625     bookmarks_item_rewind(this_);
626     if (this_->current->children==NULL) {
627     return 0;
628     }
629     while (this_->current->iter!=NULL) {
630     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
631     if (!strcmp(data->label,label)) {
632     this_->bookmarks_list=g_list_first(this_->bookmarks_list);
633     this_->bookmarks_list=g_list_remove(this_->bookmarks_list,data);
634    
635     result=bookmarks_store_bookmarks_to_file(this_,0,0);
636    
637     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
638     bookmarks_clear_hash(this_);
639     bookmarks_load_hash(this_);
640    
641     bookmarks_emit_dbus_signal(this_,&(data->c),label,FALSE);
642    
643     return result;
644     }
645     this_->current->iter=g_list_next(this_->current->iter);
646     }
647    
648     return FALSE;
649     }
650    
651     int
652     bookmarks_rename_bookmark(struct bookmarks *this_, const char *oldName, const char* newName) {
653     int result;
654    
655     bookmarks_item_rewind(this_);
656     if (this_->current->children==NULL) {
657     return 0;
658     }
659     while (this_->current->iter!=NULL) {
660     struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
661     if (!strcmp(data->label,oldName)) {
662     g_free(data->label);
663     data->label=g_strdup(newName);
664    
665     result=bookmarks_store_bookmarks_to_file(this_,0,0);
666    
667     callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
668     bookmarks_clear_hash(this_);
669     bookmarks_load_hash(this_);
670    
671     return result;
672     }
673     this_->current->iter=g_list_next(this_->current->iter);
674     }
675    
676     return FALSE;
677     }
678    
679     static int
680     bookmarks_shrink(char *bookmarks, int offset)
681     {
682     char buffer[4096];
683     int count,ioffset=offset,ooffset=0;
684     FILE *f;
685     if (!offset)
686     return 1;
687     f = fopen(bookmarks, "r+");
688     if (!f)
689     return 0;
690     for (;;) {
691     fseek(f, ioffset, SEEK_SET);
692     count=fread(buffer, 1, sizeof(buffer), f);
693     if (!count)
694     break;
695     fseek(f, ooffset, SEEK_SET);
696     if (fwrite(buffer, count, 1, f) != 1)
697     return 0;
698     ioffset+=count;
699     ooffset+=count;
700     }
701     fflush(f);
702     ftruncate(fileno(f),ooffset);
703     #ifdef HAVE_FSYNC
704     fsync(fileno(f));
705     #endif
706     fclose(f);
707     return 1;
708     }
709    
710     /**
711     * @param limit Limits the number of entries in the "backlog". Set to 0 for "infinite"
712     */
713     void
714     bookmarks_append_coord(struct bookmarks *this_, char *file, struct pcoord *c, int count, const char *type, const char *description, GHashTable *h, int limit)
715     {
716     FILE *f;
717     const char *prostr;
718    
719     if (limit != 0 && (f=fopen(file, "r"))) {
720     int *offsets=g_alloca(sizeof(int)*limit);
721     int offset_pos=0;
722     int offset;
723     char buffer[4096];
724     memset(offsets, 0, sizeof(int)*limit);
725     for (;;) {
726     offset=ftell(f);
727     if (!fgets(buffer, sizeof(buffer), f))
728     break;
729     if (strstr(buffer,"type=")) {
730     offsets[offset_pos]=offset;
731     offset_pos=(offset_pos+1)%limit;
732     }
733     }
734     fclose(f);
735     bookmarks_shrink(file, offsets[offset_pos]);
736     }
737     f=fopen(file, "a");
738     if (f) {
739     if (c) {
740     int i;
741     if (description)
742     fprintf(f,"type=%s label=\"%s\"\n", type, description);
743     else
744     fprintf(f,"type=%s\n", type);
745     for (i = 0 ; i < count ; i++) {
746     prostr = projection_to_name(c[i].pro,NULL);
747     fprintf(f,"%s%s%s0x%x %s0x%x\n",
748     prostr, *prostr ? ":" : "",
749     c[i].x >= 0 ? "":"-", c[i].x >= 0 ? c[i].x : -c[i].x,
750     c[i].y >= 0 ? "":"-", c[i].y >= 0 ? c[i].y : -c[i].y);
751     }
752     } else
753     fprintf(f,"\n");
754     }
755     fclose(f);
756     }
757    

   
Visit the ZANavi Wiki