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

Contents of /navit/navit/bookmarks.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki