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