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

Contents of /navit/navit/bookmarks.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show annotations) (download)
Mon Apr 9 21:27:36 2012 UTC (10 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 19777 byte(s)
lots of new stuff, tranlsations, bug fixes ...
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 struct bookmarks *this_;
225
226 if (parent->type!=attr_navit) {
227 return NULL;
228 }
229
230 this_ = g_new0(struct bookmarks,1);
231 this_->attr_cbl=callback_list_new();
232 this_->parent=parent;
233 //this_->attrs=attr_list_dup(attrs);
234 this_->trans=trans;
235
236 this_->bookmark_file=g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/bookmark.txt", NULL);
237 this_->working_file=g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/bookmark.txt.tmp", NULL);
238
239 this_->clipboard=g_new0(struct bookmark_item_priv,1);
240
241 {
242 //Load map now
243 struct attr type={attr_type, {"textfile"}}, data={attr_data, {this_->bookmark_file}};
244 struct attr *attrs[]={&type, &data, NULL};
245 this_->bookmark=map_new(this_->parent, attrs);
246 if (!this_->bookmark)
247 return NULL;
248 bookmarks_load_hash(this_);
249 }
250
251 return this_;
252 }
253
254 void
255 bookmarks_destroy(struct bookmarks *this_) {
256
257 bookmarks_clear_hash(this_);
258
259 map_destroy(this_->bookmark);
260 callback_list_destroy(this_->attr_cbl);
261
262 g_free(this_->bookmark_file);
263 g_free(this_->working_file);
264
265 g_free(this_->clipboard);
266 g_free(this_);
267 }
268
269 struct map*
270 bookmarks_get_map(struct bookmarks *this_) {
271 return this_->bookmark;
272 }
273
274 enum projection bookmarks_get_projection(struct bookmarks *this_){
275 return map_projection(this_->bookmark);
276 }
277 void
278 bookmarks_add_callback(struct bookmarks *this_, struct callback *cb)
279 {
280 callback_list_add(this_->attr_cbl, cb);
281 }
282
283 static int
284 bookmarks_store_bookmarks_to_file(struct bookmarks *this_, int limit,int replace) {
285 FILE *f;
286 struct bookmark_item_priv *item,*parent_item;
287 char *fullname;
288 const char *prostr;
289 int result;
290 GHashTable *dedup=g_hash_table_new_full(g_str_hash,g_str_equal,g_free,NULL);
291
292 f=fopen(this_->working_file, replace ? "w+" : "a+");
293 if (f==NULL) {
294 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
295 return FALSE;
296 }
297
298 this_->bookmarks_list=g_list_first(this_->bookmarks_list);
299 while (this_->bookmarks_list) {
300 item=(struct bookmark_item_priv*)this_->bookmarks_list->data;
301
302 parent_item=item;
303 fullname=g_strdup(item->label);
304 while ((parent_item=parent_item->parent)) {
305 char *pathHelper;
306 if (parent_item->label) {
307 pathHelper=g_strconcat(parent_item->label,"/",fullname,NULL);
308 g_free(fullname);
309 fullname=g_strdup(pathHelper);
310 g_free(pathHelper);
311 dbg(1,"full name: %s\n",fullname);
312 }
313 }
314
315 if (!g_hash_table_lookup(dedup,fullname)) {
316 g_hash_table_insert(dedup,fullname,fullname);
317 if (item->type == type_bookmark) {
318 prostr = projection_to_name(projection_mg,NULL);
319 if (fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\" path=\"%s\"\n",
320 prostr, *prostr ? ":" : "",
321 item->c.x >= 0 ? "":"-", item->c.x >= 0 ? item->c.x : -item->c.x,
322 item->c.y >= 0 ? "":"-", item->c.y >= 0 ? item->c.y : -item->c.y,
323 "bookmark", item->label,fullname)<1) {
324 g_free(fullname);
325 break;
326 }
327 }
328 if (item->type == type_bookmark_folder) {
329 prostr = projection_to_name(projection_mg,NULL);
330 if (fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\" path=\"%s\"\n",
331 prostr, *prostr ? ":" : "",
332 "", 0,
333 "", 0,
334 "bookmark_folder", item->label,fullname)<1) {
335 g_free(fullname);
336 break;
337 }
338 }
339 }
340
341 /* Limit could be zero, so we start decrementing it from zero and never reach 1
342 or it was bigger and we decreased it earlier. So when this counter becomes 1, we know
343 that we have enough entries in bookmarks file */
344 if (limit==1) {
345 break;
346 }
347 limit--;
348
349 this_->bookmarks_list=g_list_next(this_->bookmarks_list);
350 }
351
352 fclose(f);
353
354 g_hash_table_destroy(dedup);
355
356 if (this_->mr) {
357 map_rect_destroy(this_->mr);
358 this_->mr = 0;
359 }
360
361 unlink(this_->bookmark_file);
362 result=(rename(this_->working_file,this_->bookmark_file)==0);
363 if (!result)
364 {
365 navit_add_message(this_->parent->u.navit,"Failed to write bookmarks file");
366 }
367 return result;
368 }
369
370 /*
371 * bookmarks_get_destination_file
372 *
373 * returns the name of the file used to store destinations with its
374 * full path
375 *
376 * arg: gboolean create: create the directory where the file is stored
377 * if it does not exist
378 */
379 char*
380 bookmarks_get_destination_file(gboolean create)
381 {
382 return g_strjoin(NULL, navit_get_user_data_directory(create), "/destination.txt", NULL);
383 }
384
385 /*
386 * bookmarks_get_center_file
387 *
388 * returns the name of the file used to store the center file with its
389 * full path
390 *
391 * arg: gboolean create: create the directory where the file is stored
392 * if it does not exist
393 */
394 char*
395 bookmarks_get_center_file(gboolean create)
396 {
397 return g_strjoin(NULL, navit_get_user_data_directory(create), "/center.txt", NULL);
398 }
399
400 void
401 bookmarks_set_center_from_file(struct bookmarks *this_, char *file)
402 {
403 FILE *f;
404 char *line = NULL;
405
406 dbg(0,"enter\n");
407
408 size_t line_size = 0;
409 enum projection pro;
410 struct coord *center;
411
412 f = fopen(file, "r");
413 if (! f)
414 return;
415 getline(&line, &line_size, f);
416 fclose(f);
417 if (line) {
418 center = transform_center(this_->trans);
419 pro = transform_get_projection(this_->trans);
420 coord_parse(g_strchomp(line), pro, center);
421 dbg(0,"******** load center from file *********\n");
422 free(line);
423 }
424 return;
425 }
426
427 void
428 bookmarks_write_center_to_file(struct bookmarks *this_, char *file)
429 {
430 dbg(0,"EEnter\n");
431
432 FILE *f;
433 enum projection pro;
434 struct coord *center;
435
436 f = fopen(file, "w+");
437 if (f)
438 {
439 // save (pixel-on-screen width/2 height/2) screen center
440 struct coord_geo g22;
441 struct coord c22;
442 struct point p;
443
444 int width, height;
445 transform_get_size(this_->trans, &width, &height);
446 p.x=width/2;
447 p.y=height/2;
448
449 transform_reverse(this_->trans, &p, &c22);
450 //dbg(0,"%f, %f\n",a, b);
451 //dbg(0,"%d, %d\n",p.x, p.y);
452 // * transform_to_geo(projection_mg, &c22, &g22);
453 //dbg(0,"%d, %d, %f, %f\n",c22.x, c22.y, g22.lat, g22.lng);
454 // * result=g_strdup_printf("%f:%f",g22.lat,g22.lng);
455
456 // + center = transform_center(this_->trans);
457 pro = transform_get_projection(this_->trans);
458 // + coord_print(pro, center, f);
459 coord_print(pro, &c22, f);
460 fclose(f);
461 dbg(0,"******** write center to file *********\n");
462 }
463 else
464 {
465 perror(file);
466 }
467
468 dbg(0,"ready\n");
469
470 return;
471 }
472
473 static void
474 bookmarks_emit_dbus_signal(struct bookmarks *this_, struct pcoord *c, const char *description,int create)
475 {
476 struct attr attr1,attr2,attr3,attr4,cb,*attr_list[5];
477 int valid=0;
478 attr1.type=attr_type;
479 attr1.u.str="bookmark";
480 attr2.type=attr_data;
481 attr2.u.str=create ? "create" : "delete";
482 attr3.type=attr_data;
483 attr3.u.str=(char *)description;
484 attr4.type=attr_coord;
485 attr4.u.pcoord=c;
486 attr_list[0]=&attr1;
487 attr_list[1]=&attr2;
488 attr_list[2]=&attr3;
489 attr_list[3]=&attr4;
490 attr_list[4]=NULL;
491 if (navit_get_attr(this_->parent->u.navit, attr_callback_list, &cb, NULL))
492 callback_list_call_attr_4(cb.u.callback_list, attr_command, "dbus_send_signal", attr_list, NULL, &valid);
493 }
494
495 /**
496 * Record the given set of coordinates as a bookmark
497 *
498 * @param navit The navit instance
499 * @param c The coordinate to store
500 * @param description A label which allows the user to later identify this bookmark
501 * @returns nothing
502 */
503 int
504 bookmarks_add_bookmark(struct bookmarks *this_, struct pcoord *pc, const char *description)
505 {
506 struct bookmark_item_priv *b_item=g_new0(struct bookmark_item_priv,1);
507 int result;
508
509 if (pc) {
510 b_item->c.x=pc->x;
511 b_item->c.y=pc->y;
512 b_item->type=type_bookmark;
513 } else {
514 b_item->type=type_bookmark_folder;
515 }
516 b_item->label=g_strdup(description);
517 b_item->parent=this_->current;
518 b_item->children=NULL;
519
520 this_->current->children=g_list_first(this_->current->children);
521 this_->current->children=g_list_append(this_->current->children,b_item);
522 this_->bookmarks_list=g_list_first(this_->bookmarks_list);
523 this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
524
525 result=bookmarks_store_bookmarks_to_file(this_,0,0);
526
527 callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
528 bookmarks_clear_hash(this_);
529 bookmarks_load_hash(this_);
530
531 bookmarks_emit_dbus_signal(this_,&(b_item->c),description,TRUE);
532
533 return result;
534 }
535
536 int
537 bookmarks_cut_bookmark(struct bookmarks *this_, const char *label) {
538 if (bookmarks_copy_bookmark(this_,label)) {
539 return bookmarks_delete_bookmark(this_,label);
540 }
541
542 return FALSE;
543 }
544 int
545 bookmarks_copy_bookmark(struct bookmarks *this_, const char *label) {
546 bookmarks_item_rewind(this_);
547 if (this_->current->children==NULL) {
548 return 0;
549 }
550 while (this_->current->iter!=NULL) {
551 struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
552 if (!strcmp(data->label,label)) {
553 this_->clipboard->c=data->c;
554 this_->clipboard->type=data->type;
555 this_->clipboard->item=data->item;
556 this_->clipboard->children=data->children;
557 if (!this_->clipboard->label) {
558 g_free(this_->clipboard->label);
559 }
560 this_->clipboard->label=g_strdup(data->label);
561 return TRUE;
562 }
563 this_->current->iter=g_list_next(this_->current->iter);
564 }
565 return FALSE;
566 }
567 int
568 bookmarks_paste_bookmark(struct bookmarks *this_) {
569 int result;
570 struct bookmark_item_priv* b_item;
571
572 if (!this_->clipboard->label) {
573 return FALSE;
574 }
575
576 b_item=g_new0(struct bookmark_item_priv,1);
577 b_item->c.x=this_->clipboard->c.x;
578 b_item->c.y=this_->clipboard->c.y;
579 b_item->label=g_strdup(this_->clipboard->label);
580 b_item->type=this_->clipboard->type;
581 b_item->item=this_->clipboard->item;
582 b_item->parent=this_->current;
583 b_item->children=this_->clipboard->children;
584
585 g_hash_table_insert(this_->bookmarks_hash,b_item->label,b_item);
586 this_->bookmarks_list=g_list_append(this_->bookmarks_list,b_item);
587 this_->current->children=g_list_append(this_->current->children,b_item);
588 this_->current->children=g_list_first(this_->current->children);
589
590 result=bookmarks_store_bookmarks_to_file(this_,0,0);
591
592 callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
593 bookmarks_clear_hash(this_);
594 bookmarks_load_hash(this_);
595
596 return result;
597 }
598
599
600 int
601 bookmarks_delete_bookmark(struct bookmarks *this_, const char *label) {
602 int result;
603
604 bookmarks_item_rewind(this_);
605 if (this_->current->children==NULL) {
606 return 0;
607 }
608 while (this_->current->iter!=NULL) {
609 struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
610 if (!strcmp(data->label,label)) {
611 this_->bookmarks_list=g_list_first(this_->bookmarks_list);
612 this_->bookmarks_list=g_list_remove(this_->bookmarks_list,data);
613
614 result=bookmarks_store_bookmarks_to_file(this_,0,0);
615
616 callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
617 bookmarks_clear_hash(this_);
618 bookmarks_load_hash(this_);
619
620 bookmarks_emit_dbus_signal(this_,&(data->c),label,FALSE);
621
622 return result;
623 }
624 this_->current->iter=g_list_next(this_->current->iter);
625 }
626
627 return FALSE;
628 }
629
630 int
631 bookmarks_rename_bookmark(struct bookmarks *this_, const char *oldName, const char* newName) {
632 int result;
633
634 bookmarks_item_rewind(this_);
635 if (this_->current->children==NULL) {
636 return 0;
637 }
638 while (this_->current->iter!=NULL) {
639 struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data;
640 if (!strcmp(data->label,oldName)) {
641 g_free(data->label);
642 data->label=g_strdup(newName);
643
644 result=bookmarks_store_bookmarks_to_file(this_,0,0);
645
646 callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
647 bookmarks_clear_hash(this_);
648 bookmarks_load_hash(this_);
649
650 return result;
651 }
652 this_->current->iter=g_list_next(this_->current->iter);
653 }
654
655 return FALSE;
656 }
657
658 static int
659 bookmarks_shrink(char *bookmarks, int offset)
660 {
661 char buffer[4096];
662 int count,ioffset=offset,ooffset=0;
663 FILE *f;
664 if (!offset)
665 return 1;
666 f = fopen(bookmarks, "r+");
667 if (!f)
668 return 0;
669 for (;;) {
670 fseek(f, ioffset, SEEK_SET);
671 count=fread(buffer, 1, sizeof(buffer), f);
672 if (!count)
673 break;
674 fseek(f, ooffset, SEEK_SET);
675 if (fwrite(buffer, count, 1, f) != 1)
676 return 0;
677 ioffset+=count;
678 ooffset+=count;
679 }
680 fflush(f);
681 ftruncate(fileno(f),ooffset);
682 #ifdef HAVE_FSYNC
683 fsync(fileno(f));
684 #endif
685 fclose(f);
686 return 1;
687 }
688
689 /**
690 * @param limit Limits the number of entries in the "backlog". Set to 0 for "infinite"
691 */
692 void
693 bookmarks_append_coord(struct bookmarks *this_, char *file, struct pcoord *c, int count, const char *type, const char *description, GHashTable *h, int limit)
694 {
695 FILE *f;
696 const char *prostr;
697
698 if (limit != 0 && (f=fopen(file, "r"))) {
699 int *offsets=g_alloca(sizeof(int)*limit);
700 int offset_pos=0;
701 int offset;
702 char buffer[4096];
703 memset(offsets, 0, sizeof(int)*limit);
704 for (;;) {
705 offset=ftell(f);
706 if (!fgets(buffer, sizeof(buffer), f))
707 break;
708 if (strstr(buffer,"type=")) {
709 offsets[offset_pos]=offset;
710 offset_pos=(offset_pos+1)%limit;
711 }
712 }
713 fclose(f);
714 bookmarks_shrink(file, offsets[offset_pos]);
715 }
716 f=fopen(file, "a");
717 if (f) {
718 if (c) {
719 int i;
720 if (description)
721 fprintf(f,"type=%s label=\"%s\"\n", type, description);
722 else
723 fprintf(f,"type=%s\n", type);
724 for (i = 0 ; i < count ; i++) {
725 prostr = projection_to_name(c[i].pro,NULL);
726 fprintf(f,"%s%s%s0x%x %s0x%x\n",
727 prostr, *prostr ? ":" : "",
728 c[i].x >= 0 ? "":"-", c[i].x >= 0 ? c[i].x : -c[i].x,
729 c[i].y >= 0 ? "":"-", c[i].y >= 0 ? c[i].y : -c[i].y);
730 }
731 } else
732 fprintf(f,"\n");
733 }
734 fclose(f);
735 }
736

   
Visit the ZANavi Wiki