1 /*
2  * readvmf.c
3  * Jean-Pierre Demailly
4  * July 2001
5  *
6  * Copyright (C) 2001 by Jean-Pierre Demailly <demailly@ujf-grenoble.fr>
7  *
8  * Permission to use, copy, modify and freely distribute these data for
9  * non-commercial and not-for-profit purposes is hereby granted
10  * without fee, provided that both the above copyright notice and this
11  * permission notice appear in all copies and in supporting
12  * documentation.
13  *
14  * The author makes no representations about the suitability of this
15  * software for any purpose. It is provided "as is" without express or
16  * implied warranty.
17  *
18  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
21  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  */
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <math.h>
30 #ifdef ZLIB
31 #include <zlib.h>
32 #include <errno.h>
33 #endif
34 
35 #include "sunclock.h"
36 
37 #define LINELENGTH 256
38 
39 extern char *ProgName;
40 extern char *vmfcolors;
41 extern char *vmfrange;
42 extern char *vmfcoordformat;
43 
44 extern Display *	dpy;
45 extern Colormap         tmp_cmap;
46 
47 extern int		scr;
48 extern int		bigendian;
49 extern int              color_depth;
50 extern int              color_pad;
51 extern int              bytes_per_pixel;
52 extern int              color_alloc_failed;
53 extern int              verbose;
54 extern int              reformat;
55 extern int		min_zoomwidth;
56 extern int		min_zoomheight;
57 
58 static struct Sundata *map;
59 #define pixels map->vmfpixels   /* Pointer to list of colors */
60 
61 static int mapwidth;
62 static int mapheight;
63 static int fillmode;
64 
65 static char *buffer;  /* Buffer to hold input lines */
66 static int *grid;     /* Pointer to grid data */
67 static int *palette;  /* Pointer to list of color codes */
68 
69 static int uu, cc, vv, vv1, vv2, full;
70 static int num_palette;
71 static int default_color;
72 
73 static double txmin=1E27, txmax=-1E27, tymin=1E27, tymax=-1E27;
74 
75 char *
salloc(nbytes)76 salloc(nbytes)
77 register int			nbytes;
78 {
79 	register char *		p;
80 
81 	p = malloc((unsigned)nbytes);
82 	if (p == (char *)NULL) {
83 		fprintf(stderr, "%s: %d bytes required; out of memory\n",
84                       ProgName, nbytes);
85 		exit(1);
86 	}
87 	return (p);
88 }
89 
90 void
plotdata(u,v,s)91 plotdata(u, v, s)
92 int u, v, s;
93 {
94   int v1=0, v2=0, c, w, ind;
95 
96   c = u;
97   if (c<0) c+=map->zoom.width;
98   if (c>=map->zoom.width) c-=map->zoom.width;
99   c -= map->zoom.dx-1;
100   v -= map->zoom.dy;
101 
102   if (fillmode==0) {
103      if (c>=0 && c<=mapwidth && v>=0 && v<mapheight) {
104         ind = c*mapheight+v;
105         if (s>0) grid[ind] = s * 65536;
106         if (s<0) grid[ind] = -s * 65536;
107      }
108      return;
109   }
110 
111   if (c>=0 && c<=mapwidth) {
112      ind = c*mapheight;
113 
114      if (v>=0 && v<mapheight) {
115         if (s>0) grid[ind+v] |= s;
116         if (s<0) grid[ind+v] |= -s;
117      }
118 
119      s *= 65536;
120 
121      if (v<0) v1=0; else v1=v+1;
122      if (v>=mapheight) v2=mapheight-1; else v2=v;
123 
124      if (u==uu) {
125         if (v>vv)
126            for (w=vv1; w<=v2; w++) grid[ind+w] += s;
127         if (v<vv)
128            for (w=v1; w<=vv2; w++) grid[ind+w] -= s;
129      }
130      if (u>uu)
131         for (w=0; w<=v2; w++) grid[ind+w] += s;
132   }
133 
134   if (u<uu && cc>=0 && cc<=mapwidth) {
135      ind = cc*mapheight;
136      for (w=0; w<=vv2; w++) grid[ind+w] -= s;
137   }
138 
139   uu = u;
140   cc = c;
141   vv = v;
142   vv1 = v1;
143   vv2 = v2;
144 }
145 
check(i,j,which)146 int check(i, j, which)
147 int i, j, which;
148 {
149 #define MASK -65536
150    int ind, indp, inds;
151 
152    which *= 65536;
153 
154    ind = i*mapheight+j;
155    if (j>0 && (grid[ind-1]&MASK)!=which) return 1;
156    if (j<mapheight-1 && (grid[ind+1]&MASK)!=which) return 1;
157 
158    indp = (i-1)*mapheight+j;
159    if (i>0 && (grid[indp]&MASK)!=which) return 1;
160 
161    inds = (i+1)*mapheight+j;
162    if (i<mapwidth && (grid[inds]&MASK)!=which) return 1;
163 
164    if (full) {
165      if (j>0) {
166         if (i>0 && (grid[indp-1]&MASK)!=which) return 1;
167         if (i<mapwidth && (grid[inds-1]&MASK)!=which) return 1;
168      }
169      if (j<mapheight-1) {
170         if (i>0 && (grid[indp+1]&MASK)!=which) return 1;
171         if (i<mapwidth && (grid[inds+1]&MASK)!=which) return 1;
172      }
173    }
174    return 0;
175 }
176 
177 void
filterdata()178 filterdata()
179 {
180 int i, j, t, ind;
181 
182     if (fillmode==0) return;
183 
184     if (fillmode==1) {
185 
186       for (j=0; j<mapheight; j++)
187         for (i=0; i<=mapwidth; i++) {
188             ind = i*mapheight+j;
189 	    t = grid[ind];
190 	    full = 1;
191 	    if ( (t & 16383) && !check(i,j,0) ) {
192 	       grid[ind] |= 16384;
193 	       continue;
194 	    }
195 	    full = 0;
196 	    t = t/65536;
197 	    if ((t>0) && !check(i,j,t)) grid[ind] |= 32768;
198         }
199 
200       for (j=0; j<mapheight; j++)
201         for (i=0; i<=mapwidth; i++) {
202             ind = i*mapheight+j;
203 	    t = grid[ind];
204 	    if (t&16384)
205 	      grid[ind] = (t&16383) * 65536;
206 	    else
207 	    if (t&32768)
208               grid[ind] = 0;
209 	    else
210 	      grid[ind] = t&MASK;
211         }
212       goto correct;
213     }
214 
215     /* only remains fillmode = 2 */
216     full = 1;
217 
218     for (j=0; j<mapheight; j++)
219       for (i=0; i<=mapwidth; i++)
220 	  if (check(i,j,0)) grid[i*mapheight+j] &= MASK;
221 
222     for (j=0; j<mapheight; j++)
223       for (i=0; i<=mapwidth; i++) {
224           ind = i*mapheight+j;
225 	  t = (grid[ind] & 32767) * 65536;
226 	  grid[ind] |= t;
227       }
228 
229  correct:
230     if (map->zoom.width > map->geom.width && map->zoom.dx == 0) {
231       for (j=0; j<mapheight; j++) grid[j+mapheight] = grid[j+2*mapheight];
232     }
233 }
234 
235 char *
blacknwhite_image()236 blacknwhite_image()
237 {
238   int i, j, k, l, u;
239   char *bits;
240 
241   bits = (char *)
242         salloc(((mapwidth+7)/8)*mapheight*sizeof(char));
243 
244   k = 0;
245   for (j=0; j<mapheight; j++) {
246     l = 1;
247     u = 0;
248     for (i=0; i<mapwidth; i++) {
249       if (grid[(i+1)*mapheight+j]<65536) u = u+l;
250       l = l+l;
251       if (l==256 || i==mapwidth-1) {
252         bits[k] = u;
253 	u = 0;
254 	l = 1;
255         ++k;
256       }
257     }
258   }
259   return bits;
260 }
261 
262 XImage *
pixmap_image()263 pixmap_image()
264 {
265   int i, j, k, l, w, h;
266   char *c;
267   XImage *image;
268   Visual visual;
269 
270   visual = *DefaultVisual(dpy, scr);
271 
272   w = mapwidth;
273   h = mapheight;
274 
275   image = XCreateImage(dpy,&visual,
276       DefaultDepth(dpy, scr), ZPixmap, 0, NULL, w, h, color_pad, 0);
277   if (!image) return NULL;
278 
279   bytes_per_pixel = (image->bits_per_pixel/8);
280   image->data = (char *) salloc(image->bytes_per_line * h);
281 
282   if (color_depth>16)
283   for (j=0; j<mapheight; j++) {
284     c = image->data + j * image->bytes_per_line;
285     for (i=0; i<mapwidth; i++) {
286        k = bytes_per_pixel * i;
287        l = grid[(i+1)*mapheight+j]/65536;
288        if (l>=0 && l<num_palette)
289            l = palette[l];
290        else
291 	   l = default_color;
292        if (bigendian) {
293           c[k+1] = (pixels[l] >> 16) & 255;
294           c[k+2] = (pixels[l] >> 8) & 255;
295           c[k+3] = pixels[l];
296        } else {
297           c[k] = pixels[l];
298           c[k+1] = (pixels[l] >> 8) & 255;
299           c[k+2] = (pixels[l] >> 16) & 255;
300        }
301     }
302   }
303   else
304   if (color_depth>8)
305   for (j=0; j<mapheight; j++) {
306     c = image->data + j * mapwidth * bytes_per_pixel;
307     for (i=0; i<mapwidth; i++) {
308        k = bytes_per_pixel * i;
309        l = grid[(i+1)*mapheight+j]/65536;
310        if (l>=0 && l<num_palette)
311            l = palette[l];
312        else
313 	 l = default_color;
314        if (bigendian) {
315           c[k] = pixels[l] / 256;
316           c[k+1] = pixels[l] & 255;
317        } else {
318           c[k] = pixels[l] & 255;
319           c[k+1] = pixels[l] / 256;
320        }
321     }
322   }
323   else
324   for (j=0; j<mapheight; j++) {
325     c = image->data + j * mapwidth * bytes_per_pixel;
326     for (i=0; i<mapwidth; i++) {
327        k = bytes_per_pixel * i;
328        l = grid[(i+1)*mapheight+j]/65536;
329        if (l>=0 && l<num_palette)
330            l = palette[l];
331        else
332 	   l = default_color;
333        c[k] = pixels[l] & 255;
334     }
335   }
336 
337   return image;
338 }
339 
340 char *
getdata(fd)341 getdata(fd)
342 #ifdef ZLIB
343 gzFile fd;
344 #else
345 FILE *fd;
346 #endif
347 {
348   int i, j;
349   char c;
350 
351  repeat:
352 #ifdef ZLIB
353   i = gzgetc(fd);
354 #else
355   i = fgetc(fd);
356 #endif
357   if (i==EOF) return NULL;
358 
359   c = (char) i;
360 
361   if (c=='%') {
362      if (reformat) printf("%c", i);
363      while (i!=EOF && (char) i!= '\n') {
364 #ifdef ZLIB
365         i = gzgetc(fd);
366 #else
367         i = fgetc(fd);
368 #endif
369 	if (reformat) printf("%c", i);
370      }
371      if (i==EOF) return NULL;
372      goto repeat;
373   }
374 
375   while(isspace(c)) goto repeat;
376 
377   j = 0;
378   while(!isspace(c) && j<LINELENGTH) {
379     buffer[j] = c;
380     ++j;
381 #ifdef ZLIB
382     i = gzgetc(fd);
383 #else
384     i = fgetc(fd);
385 #endif
386     if (i==EOF) break;
387     c = (char) i;
388   }
389 
390   buffer[j] = '\0';
391   return buffer;
392 }
393 
394 Pixel
getPixel(cmap,str)395 getPixel(cmap, str)
396 Colormap cmap;
397 char *str;
398 {
399 Status s;
400 XColor c, e;
401 
402       if (!str) {
403 	 color_alloc_failed += 2;;
404 	 return 0;
405       }
406 
407       s = XAllocNamedColor(dpy, cmap, str, &c, &e);
408       if (s != (Status)1) {
409 	 fprintf(stderr, "%s: warning: can't allocate color `%s'\n",
410 		 ProgName, buffer);
411 	 color_alloc_failed += 2;
412 	 return 0;
413       }
414       return c.pixel;
415 }
416 
417 int
readVMF(path,Context)418 readVMF(path, Context)
419 char * path;
420 struct Sundata * Context;
421 {
422   char coordformat[32] = "%7.3f %8.3f";
423   int num_colors, correct, maxgrid, run_flag = -1, opencurves = 0,
424       ret_value = -1;
425   int color=0, i, j, k, l, num=0, count=0, u=0, v=0, up, vp, flag;
426   int position=0;
427   int m, min, max, addumin, addvmin, addumax, addvmax, diffu, diffv, sum;
428   double fx=0.0, fy=0.0, fx0=0.0, fy0=0.0;
429   double fxmin=-180.0, fxmax=180.0, fymin=-90.0, fymax=90.0,
430          fdx=360.0, fdy=180.0;
431   double rxmin=-180.0, rxmax, rymin=-90.0, rymax;
432   double cx=1.0, cy=1.0, cdx=0.0, cdy=0.0;
433   double theta, phi;
434   char *str, *ptr;
435 #ifdef ZLIB
436   gzFile fd;
437   int plen;
438   char *zpath;
439 #else
440   FILE *fd;
441 #endif
442 
443   fd = NULL;
444   buffer = NULL;
445   palette = NULL;
446   grid = NULL;
447   min_zoomwidth = 0;
448   min_zoomheight = 0;
449 
450   if (!path) {
451      ret_value = 1;
452      goto abort;
453   }
454 
455   map = Context;
456   fillmode = Context->flags.fillmode;
457   mapwidth = Context->geom.width;
458   if (mapwidth <=10) return 4;
459   mapheight = Context->geom.height;
460   if (mapheight<= 5) return 4;
461 
462   if (verbose)
463     fprintf(stderr, "Loading vector map %s\n", path);
464 #ifdef ZLIB
465   fd = gzopen(path, "r");
466   #define	Z_PATH_EXT	".gz"
467   #define	Z_PATH_LEN	( sizeof( Z_PATH_EXT)- 1)
468   if ( fd == NULL && errno == ENOENT
469        && ( ( plen= strlen( path)) < Z_PATH_LEN
470             || strcmp( &path[ plen- Z_PATH_LEN], Z_PATH_EXT) != 0))
471     {	/* try to open gzip'd file... (ThMO) */
472   #if	__GNUC__ >= 2
473       zpath= alloca( plen+ Z_PATH_LEN+ 1);
474   #else
475       zpath= salloc( plen+ Z_PATH_LEN+ 1);
476   #endif
477       memcpy( zpath, path, plen);
478       memcpy( zpath+ plen, Z_PATH_EXT, Z_PATH_LEN+ 1);
479       if ( verbose)
480         fprintf( stderr, "Try loading vector map %s\n", zpath);
481       fd= gzopen( zpath, "r");
482   #if	!( __GNUC__ >= 2)
483       free( zpath);
484   #endif
485     }
486   #undef	Z_PATH_EXT
487   #undef	Z_PATH_LEN
488 #else
489   fd = fopen(path, "r");
490 #endif
491   if (fd == NULL) {
492      ret_value = 1;
493      goto abort;
494   }
495 
496   buffer = (char *) salloc(LINELENGTH+2);
497   if (!buffer) goto abort;
498 
499 #ifdef ZLIB
500   str = gzgets(fd, buffer, LINELENGTH);
501 #else
502   str = fgets(buffer, LINELENGTH, fd);
503 #endif
504   if (!str || strncmp(buffer, "%!VMF", 5)) {
505      ret_value = 5;
506      goto abort;
507   }
508   if (reformat) printf(str);
509 
510   k = 0;
511   num_colors = 0;
512   while (1) {
513     if (map->flags.colorlevel==FULLCOLORS) {
514        count = color_alloc_failed;
515        if (vmfcolors) {
516           if (vmfcolors[k]) {
517 	     strcpy(buffer, vmfcolors+k);
518              str = buffer;
519 	     l = 0;
520              while (str[l]!='|' && str[l] != '\0') ++l;
521 	     if (str[l]=='|')
522 	        k=k+l+1;
523 	     else
524 	        k=k+l;
525 	     str[l] = '\0';
526              if (*str) {
527 	        ++num_colors;
528                 pixels =
529                   (Pixel *)realloc((void *)pixels, num_colors*sizeof(Pixel));
530 	        if (!pixels) goto abort;
531                 pixels[num_colors-1] = getPixel(tmp_cmap, str);
532 	     } else
533 	        --count;
534           } else
535 	     --count;
536        }
537        str = getdata(fd);
538        if (!strcmp(str, ";")) break;
539        if (!vmfcolors || color_alloc_failed>count) {
540 	  count = color_alloc_failed;
541 	  ++num_colors;
542           pixels = (Pixel *)realloc((void *)pixels, num_colors*sizeof(Pixel));
543 	  if (!pixels) goto abort;
544 	  pixels[num_colors-1] = getPixel(tmp_cmap, str);
545        }
546        if (color_alloc_failed>count) {
547 	  color_alloc_failed = 1;
548 	  ret_value = 6;
549 	  goto abort;
550        } else
551 	  color_alloc_failed &= 1;
552        if (color_depth<=8)
553           Context->daypixel[num_colors-1] =
554              (unsigned char) pixels[num_colors-1];
555     } else {
556        str = getdata(fd);
557        ++num_colors;
558        if (!strcmp(str, ";")) break;
559     }
560     if (reformat) printf("%s\t", str);
561   }
562   if (reformat) printf(";\n\n");
563   Context->ncolors = num_colors;
564 
565   str = getdata(fd);
566   if (!str) goto abort;
567   default_color = atoi(str);
568   if (default_color<0 || default_color>=num_colors) goto abort;
569   if (reformat) printf("%d\n\n", default_color);
570 
571   j = 0;
572   num_palette = 0;
573   while (1) {
574     str = getdata(fd);
575     if (!str) goto abort;
576     if (*str==';') {
577        if (reformat) printf("\n;\n\n");
578        break;
579     }
580     if (*str=='c') {
581        v = atoi(str+1);
582        if (v<0 || v>=num_colors) goto abort;
583        if (reformat) {
584 	  if (j) printf("\n");
585 	  printf("c%d", v);
586        }
587     }
588     else {
589        u = atoi(str);
590        if (u<0) goto abort;
591        if (u>=num_palette) {
592 	  palette = (int *) realloc(palette, (u+1)*sizeof(int));
593 	  if (!palette) goto abort;
594 	  for (k=num_palette; k<u; ++k) palette[k] = default_color;
595 	  num_palette = u+1;
596        }
597        palette[u] = v;
598        if (reformat) printf(" %d", u);
599     }
600     ++j;
601   }
602 
603   str = getdata(fd);
604   if (!str) goto abort;
605   if (fillmode)
606      correct = atoi(str);
607   else
608      correct = 0;
609   if (reformat) printf("%d\n\n", correct);
610   correct *= 65536;
611 
612   maxgrid = (mapwidth+1)*mapheight;
613   grid = (int *) salloc(maxgrid*sizeof(int));
614   for (i=0; i<maxgrid; i++) grid[i] = correct;
615 
616   count = 0;
617 
618   if (reformat) {
619      if (vmfrange) {
620         if (vmfcoordformat)
621 	   strncpy(coordformat, vmfcoordformat, 30);
622 	else
623            strcpy(coordformat, "%g %g");
624         for (i=0; i<strlen(vmfrange); i++)
625             if (vmfrange[i]=='|') vmfrange[i] = ' ';
626         if (sscanf(vmfrange, "%lg %lg %lg %lg",
627             &rymin, &rymax, &rxmin, &rxmax)<4)
628             goto abort;
629      } else {
630         rxmin = fxmin;
631         rxmax = fxmax;
632         rymin = fymin;
633         rymax = fymax;
634      }
635      cx =  (rxmax-rxmin)/fdx;
636      cy =  (rymax-rymin)/fdy;
637      cdx = -fxmin*cx+rxmin;
638      cdy = -fymin*cy+rymin;
639   }
640 
641  iter:
642   str = getdata(fd);
643   if (!str) goto abort;
644   if (*str >= 'A') {
645      if (!strcmp(str, "end")) {
646         if (reformat)
647            printf("\n%s\n", str);
648         goto endcurves;
649      } else
650      if (!strcmp(str, "flag")) {
651         str = getdata(fd);
652         if (!str) goto abort;
653 	run_flag = atoi(str);
654         if (reformat)
655            printf("flag %d\n", run_flag);
656      } else
657      if (!strcmp(str, "opencurves")) {
658         if (reformat)
659            printf("%s\n", str);
660         opencurves = 1;
661      } else
662      if (!strcmp(str, "closedcurves")) {
663         if (reformat)
664            printf("%s\n", str);
665         opencurves = 0;
666      } else
667      if (!strcmp(str, "zoomwidth")) {
668         str = getdata(fd);
669 	min_zoomwidth = atoi(str);
670      } else
671      if (!strcmp(str, "zoomheight")) {
672         str = getdata(fd);
673 	min_zoomheight = atoi(str);
674      } else
675      if (!strcmp(str, "fillmode")) {
676         str = getdata(fd);
677         if (!str) goto abort;
678 	i = atoi(str);
679         if (reformat)
680            printf("fillmode %d\n", i);
681 	if (i>map->flags.fillmode)
682            i = map->flags.fillmode;
683 	if (i<fillmode) filterdata();
684 	fillmode = i;
685      } else
686      if (!strcmp(str, "range")) {
687         str = getdata(fd);
688         if (!str) goto abort;
689         fymin = atof(str);
690         str = getdata(fd);
691         if (!str) goto abort;
692         fymax = atof(str);
693         str = getdata(fd);
694         if (!str) goto abort;
695         fxmin = atof(str);
696         str = getdata(fd);
697         if (!str) goto abort;
698         fxmax = atof(str);
699         fdx = fxmax - fxmin;
700         fdy = fymax - fymin;
701 	if (reformat) {
702 	   if (!vmfrange){
703 	      rxmin = fxmin;
704 	      rxmax = fxmax;
705 	      rymin = fymin;
706 	      rymax = fymax;
707 	   }
708 	   cx = (rxmax-rxmin)/fdx;
709 	   cy = (rymax-rymin)/fdy;
710            cdx = -fxmin*cx+rxmin;
711            cdy = -fymin*cy+rymin;
712            printf("range %g %g %g %g\n\n", rymin, rymax, rxmin, rxmax);
713         }
714      } else
715      if (!strcmp(str, "label")) {
716         /* get rid of count number */
717         str = getdata(fd);
718         str = getdata(fd);
719         if (!str) goto abort;
720         color = atoi(str);
721         str = getdata(fd);
722         if (!str) goto abort;
723         position = atoi(str);
724         str = getdata(fd);
725         if (!str) goto abort;
726         fy = atof(str);
727         str = getdata(fd);
728         if (!str) goto abort;
729         fx = atof(str);
730         if (reformat) {
731            printf("\nlabel %d %d %d ", count, color, position);
732            printf(coordformat, fy, fx);
733            printf("\n");
734         }
735         ++count;
736         ptr = NULL;
737         l = 0;
738 #ifdef ZLIB
739         while (!gzeof(fd)) {
740            str = gzgets(fd, buffer, LINELENGTH);
741 #else
742         while (!feof(fd)) {
743            str = fgets(buffer, LINELENGTH, fd);
744 #endif
745 	   if (!str) break;
746            if (reformat) {
747 	      printf("%s", str);
748 	   }
749 	   if (*str == ';') break;
750            if (*str == ' ') ++str; /* remove any initial blank space */
751            k = strlen(str);
752    	   if (k>=2 && str[k-1]=='\n' && str[k-2]=='\\' &&
753                (k==2 || (k>=3 && str[k-3]!='\\'))) {
754 	      k -=2;
755               str[k] = '\0';
756 	   }
757            ptr = realloc(ptr, l+k+2);
758            strcpy(ptr + l, str);
759            l += k;
760 	}
761 	if (ptr && *ptr) {
762 	   l -= 1;
763 	   if (l>=0 && ptr[l]=='\n') ptr[l] = '\0';
764            if (Context->zoom.width<min_zoomwidth) goto iter;
765            if (Context->zoom.height<min_zoomheight) goto iter;
766            str = (char *)Context->label;
767            Context->label = (struct TextLabel *)salloc(sizeof(TextLabel));
768            Context->label->text = ptr;
769            Context->label->lon = fx;
770            Context->label->lat = fy;
771            Context->label->color = color;
772            Context->label->position = position;
773            Context->label->next = (struct TextLabel *)str;
774 	}
775      }
776   goto iter;
777   } else
778   if (*str == '#') {
779      num = 0;
780      str = getdata(fd);
781      if (!str) goto abort;
782      color = atoi(str);
783      if (reformat)
784         printf("\n#%d %d", count, color);
785      ++count;
786   } else
787   if (*str == ';') {
788      fx = fx0;
789      fy = fy0;
790      if (reformat) printf("\n;\n");
791      if (opencurves) goto iter;
792   } else {
793      fy = atof(str);
794      str = getdata(fd);
795      if (!str) goto abort;
796      fx = atof(str);
797      if (verbose) {
798         if (fx<txmin) txmin = fx;
799         if (fx>txmax) txmax = fx;
800         if (fy<tymin) tymin = fy;
801         if (fy>tymax) tymax = fy;
802      }
803      if (num == 0) {
804 	fx0 = fx;
805 	fy0 = fy;
806      }
807      if (reformat) {
808         if (num%4 == 0) printf("\n"); else printf("  ");
809         printf(coordformat, fy*cy+cdy, fx*cx+cdx);
810      }
811      ++num;
812   }
813 
814   flag = run_flag & map->flags.vmfflags;
815   if (!flag) goto iter;
816   if ((flag&1) && !map->wintype) goto iter;
817   if (map->zoom.width<min_zoomwidth) goto iter;
818 
819   theta = (fx - fxmin) / fdx;
820   phi = (fymax - fy) / fdy;
821   cc = uu = up = u;
822   if (cc<0) cc+=map->zoom.width;
823   if (cc>=map->zoom.width) cc-=map->zoom.width;
824   cc -= map->zoom.dx-1;
825 
826   vp = v;
827   vv = v - map->zoom.dy;
828   vv1 = vv + 1;
829   if (vv1<0) vv1 = 0;
830   vv2 = vv;
831   if (vv2>=mapheight) vv2 = mapheight-1;
832 
833   u = (int) (theta * (double) map->zoom.width);
834   v = (int) (phi * (double) map->zoom.height);
835   if (num>=2) {
836      diffu = abs(u-up);
837      if (diffu>map->zoom.width/2) {
838         if (u>up)
839            u -= map->zoom.width;
840 	else
841 	   u += map->zoom.width;
842         diffu = abs(u-up);
843      }
844      diffv = abs(v-vp);
845      addumin = (u>up)? 1:-1;
846      addvmin = (v>vp)? 1:-1;
847      if (diffu>diffv) {
848 	max = diffu ;
849         min = diffv;
850         addumax = addumin;
851 	addvmax = 0;
852      } else {
853         max = diffv ;
854         min = diffu;
855 	addumax = 0;
856 	addvmax = addvmin;
857      }
858      sum = max/2-max;
859      for (m=0; m<max; m++) {
860         sum = sum + min;
861         if (sum>=max/2) {
862 	   sum -= max;
863 	   up += addumin;
864            vp += addvmin;
865         } else {
866 	   up += addumax;
867            vp += addvmax;
868 	}
869         plotdata(up, vp, color);
870      }
871   }
872   goto iter;
873 
874  endcurves:
875   filterdata();
876 
877   if (map->flags.colorlevel==FULLCOLORS)
878      Context->xim = pixmap_image();
879   else
880      Context->bits = blacknwhite_image();
881   if ((map->flags.colorlevel<FULLCOLORS && Context->bits==NULL) ||
882       (map->flags.colorlevel==FULLCOLORS && Context->xim==NULL))
883      ret_value = 2;
884   if (ret_value < 0) ret_value = 0;
885 
886  abort:
887   if (ret_value < 0) ret_value = 2;
888 #ifdef ZLIB
889   if (fd) gzclose(fd);
890 #else
891   if (fd) fclose(fd);
892 #endif
893   if (buffer) free(buffer);
894   if (grid) free(grid);
895   if (palette) free(palette);
896   if (verbose)
897      fprintf(stderr, "ymin = %9.3f ymax = %9.3f   xmin = %9.3f xmax = %9.3f\n", tymin, tymax, txmin, txmax);
898   return ret_value;
899 }
900