xref: /potrace-1.14/src/progress_bar.c (revision b3fce824)
1 /* Copyright (C) 2001-2017 Peter Selinger.
2    This file is part of Potrace. It is free software and it is covered
3    by the GNU General Public License. See the file COPYING for details. */
4 
5 /* functions to render a progress bar for main.c. We provide a
6    standard and a simplified progress bar. */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <stdio.h>
13 #include <math.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "potracelib.h"
18 #include "progress_bar.h"
19 
20 /* ---------------------------------------------------------------------- */
21 /* vt100 progress bar */
22 
23 #define COL0 "\033[G"  /* reset cursor to column 0 */
24 
25 struct vt100_progress_s {
26   char name[22];          /* filename for status bar */
27   double dnext;           /* threshold value for next tick */
28 };
29 typedef struct vt100_progress_s vt100_progress_t;
30 
31 /* print a progress bar using vt100 control characters. This is a
32    callback function that is potentially called often; thus, it has
33    been optimized for the typical case, which is when the progress bar
34    does not need updating. */
vt100_progress(double d,void * data)35 static void vt100_progress(double d, void *data) {
36   vt100_progress_t *p = (vt100_progress_t *)data;
37   static char b[] = "========================================";
38   int tick;    /* number of visible tickmarks, 0..40 */
39   int perc;    /* visible percentage, 0..100 */
40 
41   /* note: the 0.01 and 0.025 ensure that we always end on 40
42      tickmarks and 100%, despite any rounding errors. The 0.995
43      ensures that tick always increases when d >= p->dnext. */
44   if (d >= p->dnext) {
45     tick = (int) floor(d*40+0.01);
46     perc = (int) floor(d*100+0.025);
47     fprintf(stderr, "%-21s |%-40s| %d%% " COL0 "", p->name, b+40-tick, perc);
48     fflush(stderr);
49     p->dnext = (tick+0.995) / 40.0;
50   }
51 }
52 
53 /* Initialize progress bar. Return 0 on success or 1 on failure with
54    errno set. */
init_vt100_progress(potrace_progress_t * prog,const char * filename,int count)55 static int init_vt100_progress(potrace_progress_t *prog, const char *filename, int count) {
56   vt100_progress_t *p;
57   const char *q, *s;
58   int len;
59 
60   p = (vt100_progress_t *) malloc(sizeof(vt100_progress_t));
61   if (!p) {
62     return 1;
63   }
64 
65   /* initialize callback function's data */
66   p->dnext = 0;
67 
68   if (count != 0) {
69     sprintf(p->name, " (p.%d):", count+1);
70   } else {
71     s = filename;
72     if ((q = strrchr(s, '/')) != NULL) {
73       s = q+1;
74     }
75     len = strlen(s);
76     strncpy(p->name, s, 21);
77     p->name[20] = 0;
78     if (len > 20) {
79       p->name[17] = '.';
80       p->name[18] = '.';
81       p->name[19] = '.';
82     }
83     strcat(p->name, ":");
84   }
85 
86   /* initialize progress parameters */
87   prog->callback = &vt100_progress;
88   prog->data = (void *)p;
89   prog->min = 0.0;
90   prog->max = 1.0;
91   prog->epsilon = 0.0;
92 
93   /* draw first progress bar */
94   vt100_progress(0.0, prog->data);
95   return 0;
96 }
97 
98 /* Finalize the progress bar. */
term_vt100_progress(potrace_progress_t * prog)99 static void term_vt100_progress(potrace_progress_t *prog) {
100   fprintf(stderr, "\n");
101   fflush(stderr);
102   free(prog->data);
103   return;
104 }
105 
106 /* progress bar interface structure */
107 static progress_bar_t progress_bar_vt100_struct = {
108   init_vt100_progress,
109   term_vt100_progress,
110 };
111 progress_bar_t *progress_bar_vt100 = &progress_bar_vt100_struct;
112 
113 /* ---------------------------------------------------------------------- */
114 /* another progress bar for dumb terminals */
115 
116 struct simplified_progress_s {
117   int n;                  /* number of ticks displayed so far */
118   double dnext;           /* threshold value for next tick */
119 };
120 typedef struct simplified_progress_s simplified_progress_t;
121 
122 /* print a simplified progress bar, not using any special tty control
123    codes. Optimized for frequent calling. */
simplified_progress(double d,void * data)124 static void simplified_progress(double d, void *data) {
125   simplified_progress_t *p = (simplified_progress_t *)data;
126   int tick;    /* number of visible tickmarks, 0..40 */
127 
128   /* note: the 0.01 and 0.025 ensure that we always end on 40
129      tickmarks and 100%, despite any rounding errors. The 0.995
130      ensures that tick always increases when d >= p->dnext. */
131   if (d >= p->dnext) {
132     tick = (int) floor(d*40+0.01);
133     while (p->n < tick) {
134       fputc('=', stderr);
135       p->n++;
136     }
137     fflush(stderr);
138     p->dnext = (tick+0.995) / 40.0;
139   }
140 }
141 
142 /* Initialize parameters for simplified progress bar. Return 0 on
143    success or 1 on error with errno set. */
init_simplified_progress(potrace_progress_t * prog,const char * filename,int count)144 static int init_simplified_progress(potrace_progress_t *prog, const char *filename, int count) {
145   simplified_progress_t *p;
146   const char *q, *s;
147   int len;
148   char buf[22];
149 
150   p = (simplified_progress_t *) malloc(sizeof(simplified_progress_t));
151   if (!p) {
152     return 1;
153   }
154 
155   /* initialize callback function's data */
156   p->n = 0;
157   p->dnext = 0;
158 
159   if (count != 0) {
160     sprintf(buf, " (p.%d):", count+1);
161   } else {
162     s = filename;
163     if ((q = strrchr(s, '/')) != NULL) {
164       s = q+1;
165     }
166     len = strlen(s);
167     strncpy(buf, s, 21);
168     buf[20] = 0;
169     if (len > 20) {
170       buf[17] = '.';
171       buf[18] = '.';
172       buf[19] = '.';
173     }
174     strcat(buf, ":");
175   }
176 
177   fprintf(stderr, "%-21s |", buf);
178 
179   /* initialize progress parameters */
180   prog->callback = &simplified_progress;
181   prog->data = (void *)p;
182   prog->min = 0.0;
183   prog->max = 1.0;
184   prog->epsilon = 0.0;
185 
186   /* draw first progress bar */
187   simplified_progress(0.0, prog->data);
188   return 0;
189 }
190 
term_simplified_progress(potrace_progress_t * prog)191 static void term_simplified_progress(potrace_progress_t *prog) {
192   simplified_progress_t *p = (simplified_progress_t *)prog->data;
193 
194   simplified_progress(1.0, (void *)p);
195   fprintf(stderr, "| 100%%\n");
196   fflush(stderr);
197   free(p);
198   return;
199 }
200 
201 /* progress bar interface structure */
202 static progress_bar_t progress_bar_simplified_struct = {
203   init_simplified_progress,
204   term_simplified_progress,
205 };
206 progress_bar_t *progress_bar_simplified = &progress_bar_simplified_struct;
207 
208