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

Contents of /navit/navit/bookmarks.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (6 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 19948 byte(s)
new map version, lots of fixes and experimental new features
1 /**
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 bookmarks_new(struct attr *parent, struct attr **attrs, struct transformation *trans)
224 {
225 struct bookmarks *this_;
226
227 if (parent->type!=attr_navit)
228 {
229 return NULL;
230 }
231
232 dbg(0,"bb 001\n");
233
234 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
241 return this_;
242
243 #if 0
244 dbg(0,"bb 002\n");
245
246 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 dbg(0,"bb 003\n");
250
251 this_->clipboard=g_new0(struct bookmark_item_priv,1);
252
253 dbg(0,"bb 004\n");
254
255 {
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 {
262 return NULL;
263 }
264 dbg(0,"bb 005\n");
265 bookmarks_load_hash(this_);
266 }
267
268 dbg(0,"bb 006\n");
269
270 return this_;
271 #endif
272 }
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 GHashTable *dedup=g_hash_table_new_full(g_str_hash,g_str_equal,g_free_func,NULL);
311
312 f=fopen(this_->working_file, replace ? "w+" : "a+");
313 if (f==NULL) {
314 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
315 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 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
386 }
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 if (line)
438 {
439 center = transform_center(this_->trans);
440 pro = transform_get_projection(this_->trans);
441 coord_parse(g_strchomp(line), pro, center);
442 dbg(0,"******** load center from file *********\n");
443 free(line);
444 }
445 return;
446 }
447
448 void
449 bookmarks_write_center_to_file(struct bookmarks *this_, char *file)
450 {
451 dbg(0,"EEnter\n");
452
453 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 dbg(0,"******** write center to file *********\n");
483 }
484 else
485 {
486 perror(file);
487 }
488
489 dbg(0,"ready\n");
490
491 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