File indexing completed on 2024-12-22 04:04:14

0001 /* Copyright (C) 2001-2019 Peter Selinger.
0002    This file is part of Potrace. It is free software and it is covered
0003    by the GNU General Public License. See the file COPYING for details. */
0004 
0005 /* functions to render a progress bar for main.c. We provide a
0006    standard and a simplified progress bar. */
0007 
0008 #ifdef HAVE_CONFIG_H
0009 #include <config.h>
0010 #endif
0011 
0012 #include <stdio.h>
0013 #include <math.h>
0014 #include <stdlib.h>
0015 #include <string.h>
0016 
0017 #include "potracelib.h"
0018 #include "progress_bar.h"
0019 
0020 /* ---------------------------------------------------------------------- */
0021 /* vt100 progress bar */
0022 
0023 #define COL0 "\033[G"  /* reset cursor to column 0 */
0024 
0025 struct vt100_progress_s {
0026   char name[22];          /* filename for status bar */
0027   double dnext;           /* threshold value for next tick */
0028 };
0029 typedef struct vt100_progress_s vt100_progress_t;
0030 
0031 /* print a progress bar using vt100 control characters. This is a
0032    callback function that is potentially called often; thus, it has
0033    been optimized for the typical case, which is when the progress bar
0034    does not need updating. */
0035 static void vt100_progress(double d, void *data) {
0036   vt100_progress_t *p = (vt100_progress_t *)data;
0037   static char b[] = "========================================";
0038   int tick;    /* number of visible tickmarks, 0..40 */
0039   int perc;    /* visible percentage, 0..100 */
0040 
0041   /* note: the 0.01 and 0.025 ensure that we always end on 40
0042      tickmarks and 100%, despite any rounding errors. The 0.995
0043      ensures that tick always increases when d >= p->dnext. */
0044   if (d >= p->dnext) {
0045     tick = (int) floor(d*40+0.01);
0046     perc = (int) floor(d*100+0.025);
0047     fprintf(stderr, "%-21s |%-40s| %d%% " COL0 "", p->name, b+40-tick, perc);
0048     fflush(stderr);
0049     p->dnext = (tick+0.995) / 40.0;
0050   }
0051 }
0052 
0053 /* Initialize progress bar. Return 0 on success or 1 on failure with
0054    errno set. */
0055 static int init_vt100_progress(potrace_progress_t *prog, const char *filename, int count) {
0056   vt100_progress_t *p;
0057   const char *q, *s;
0058   int len;
0059 
0060   p = (vt100_progress_t *) malloc(sizeof(vt100_progress_t));
0061   if (!p) {
0062     return 1;
0063   }
0064 
0065   /* initialize callback function's data */
0066   p->dnext = 0;
0067 
0068   if (count != 0) {
0069     sprintf(p->name, " (p.%d):", count+1);
0070   } else {
0071     s = filename;
0072     if ((q = strrchr(s, '/')) != NULL) {
0073       s = q+1;
0074     }
0075     len = strlen(s);
0076     strncpy(p->name, s, 21);
0077     p->name[20] = 0;
0078     if (len > 20) {
0079       p->name[17] = '.';
0080       p->name[18] = '.';
0081       p->name[19] = '.';
0082     }
0083     strcat(p->name, ":");
0084   }
0085 
0086   /* initialize progress parameters */
0087   prog->callback = &vt100_progress;
0088   prog->data = (void *)p;
0089   prog->min = 0.0;
0090   prog->max = 1.0;
0091   prog->epsilon = 0.0;
0092   
0093   /* draw first progress bar */
0094   vt100_progress(0.0, prog->data);
0095   return 0;
0096 }
0097 
0098 /* Finalize the progress bar. */
0099 static void term_vt100_progress(potrace_progress_t *prog) {
0100   fprintf(stderr, "\n");
0101   fflush(stderr);
0102   free(prog->data);
0103   return;
0104 }
0105 
0106 /* progress bar interface structure */
0107 static progress_bar_t progress_bar_vt100_struct = {
0108   init_vt100_progress,
0109   term_vt100_progress,
0110 };
0111 progress_bar_t *progress_bar_vt100 = &progress_bar_vt100_struct;
0112 
0113 /* ---------------------------------------------------------------------- */
0114 /* another progress bar for dumb terminals */
0115 
0116 struct simplified_progress_s {
0117   int n;                  /* number of ticks displayed so far */
0118   double dnext;           /* threshold value for next tick */
0119 };
0120 typedef struct simplified_progress_s simplified_progress_t;
0121 
0122 /* print a simplified progress bar, not using any special tty control
0123    codes. Optimized for frequent calling. */
0124 static void simplified_progress(double d, void *data) {
0125   simplified_progress_t *p = (simplified_progress_t *)data;
0126   int tick;    /* number of visible tickmarks, 0..40 */
0127 
0128   /* note: the 0.01 and 0.025 ensure that we always end on 40
0129      tickmarks and 100%, despite any rounding errors. The 0.995
0130      ensures that tick always increases when d >= p->dnext. */
0131   if (d >= p->dnext) {
0132     tick = (int) floor(d*40+0.01);
0133     while (p->n < tick) {
0134       fputc('=', stderr);
0135       p->n++;
0136     }
0137     fflush(stderr);
0138     p->dnext = (tick+0.995) / 40.0;
0139   }
0140 }
0141 
0142 /* Initialize parameters for simplified progress bar. Return 0 on
0143    success or 1 on error with errno set. */
0144 static int init_simplified_progress(potrace_progress_t *prog, const char *filename, int count) {
0145   simplified_progress_t *p;
0146   const char *q, *s;
0147   int len;
0148   char buf[22];
0149 
0150   p = (simplified_progress_t *) malloc(sizeof(simplified_progress_t));
0151   if (!p) {
0152     return 1;
0153   }
0154 
0155   /* initialize callback function's data */
0156   p->n = 0;
0157   p->dnext = 0;
0158 
0159   if (count != 0) {
0160     sprintf(buf, " (p.%d):", count+1);
0161   } else {
0162     s = filename;
0163     if ((q = strrchr(s, '/')) != NULL) {
0164       s = q+1;
0165     }
0166     len = strlen(s);
0167     strncpy(buf, s, 21);
0168     buf[20] = 0;
0169     if (len > 20) {
0170       buf[17] = '.';
0171       buf[18] = '.';
0172       buf[19] = '.';
0173     }
0174     strcat(buf, ":");
0175   }
0176 
0177   fprintf(stderr, "%-21s |", buf);
0178 
0179   /* initialize progress parameters */
0180   prog->callback = &simplified_progress;
0181   prog->data = (void *)p;
0182   prog->min = 0.0;
0183   prog->max = 1.0;
0184   prog->epsilon = 0.0;
0185   
0186   /* draw first progress bar */
0187   simplified_progress(0.0, prog->data);
0188   return 0;
0189 }
0190 
0191 static void term_simplified_progress(potrace_progress_t *prog) {
0192   simplified_progress_t *p = (simplified_progress_t *)prog->data;
0193 
0194   simplified_progress(1.0, (void *)p);
0195   fprintf(stderr, "| 100%%\n");
0196   fflush(stderr);
0197   free(p);
0198   return;
0199 }
0200 
0201 /* progress bar interface structure */
0202 static progress_bar_t progress_bar_simplified_struct = {
0203   init_simplified_progress,
0204   term_simplified_progress,
0205 };
0206 progress_bar_t *progress_bar_simplified = &progress_bar_simplified_struct;
0207