Annotation of embedaddon/pimd/libite/progress.c, revision 1.1.1.1

1.1       misho       1: /* Simple termios based progress bar
                      2:  *
                      3:  * Copyright (c) 2012-2015  Joachim Nilsson <troglobit@gmail.com>
                      4:  *
                      5:  * Permission to use, copy, modify, and/or distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: 
                     18: #include <limits.h>            /* INT_MAX */
                     19: #include <stdio.h>
                     20: #include <string.h>
                     21: 
                     22: #include "conio.h"
                     23: 
                     24: #define SPINNER_THROB   ".oOo"
                     25: #define SPINNER_PULSAR  ".oO°Oo."
                     26: #define SPINNER_ARROW   "v<^>"
                     27: #define SPINNER_STAR    ".oO@*"
                     28: #define SPINNER_DEFAULT "|/-\\"
                     29: 
                     30: static char spinner(char *style)
                     31: {
                     32:        size_t num;
                     33:        static unsigned int i = 0;
                     34: 
                     35:        if (!style)
                     36:                style = SPINNER_DEFAULT;
                     37:        num = strlen(style);
                     38: 
                     39:        return style[i++ % num]; /* % Number of states in style */
                     40: }
                     41: 
                     42: /**
                     43:  * progress - Advanced ASCII progress bar with spinner
                     44:  * @percent: Start first call with this set to 0, end with 100
                     45:  * @max_width: Max width of progress bar, in total characters.
                     46:  *
                     47:  * This function draws an advanced ASCII progressbar at the current
                     48:  * line.  It always start from the first column.
                     49:  *
                     50:  * The progress bar will hide the cursor if started with @percent 0 and
                     51:  * show it again at the end, when called with @percent 100.
                     52:  *
                     53:  * While being called with the same percentage the spinner will spin,
                     54:  * to show the user the process hasn't frozen.
                     55:  *
                     56:  * If the output TTY cannot interpret control characters, like \r, it is
                     57:  * advised to instead used the progress_simple() function.
                     58:  */
                     59: void progress(int percent, int max_width)
                     60: {
                     61:        int i, bar;
                     62: 
                     63:        /* Adjust for progress bar overhead */
                     64:        max_width -= 10;
                     65: 
                     66:        if (0 == percent)
                     67:                hidecursor();
                     68: 
                     69:        fprintf(stderr, "\r%3d%% %c [", percent, spinner(NULL));
                     70: 
                     71:        bar = percent * max_width / 100;
                     72:        for (i = 0; i < max_width; i++) {
                     73:                if (i > bar)
                     74:                        fputc(' ', stderr);
                     75:                else if (i == bar)
                     76:                        fputc('>', stderr);
                     77:                else
                     78:                        fputc('=', stderr);
                     79:        }
                     80: 
                     81:        fprintf(stderr, "]");
                     82:        if (100 == percent) {
                     83:                showcursor();
                     84:                fputc('\n', stderr);
                     85:        }
                     86: }
                     87: 
                     88: void progress_simple(int percent)
                     89: {
                     90:        static int last = 1;
                     91:        int ratio, numout;
                     92: 
                     93:        if (!percent && last) {
                     94:                last = 0;
                     95:                fputs("0%       25%       50%       75%       100%\n"
                     96:                      "|---------+---------+---------+---------|\n"
                     97:                      "|", stderr);
                     98:                return;
                     99:        }
                    100: 
                    101:        ratio = 40 * percent / 100;
                    102:        numout = ratio - last;
                    103: 
                    104:        if (ratio <= last)
                    105:                return;
                    106: 
                    107:        last = ratio;
                    108: 
                    109:        while (numout--) {
                    110:                if (ratio != 40 || numout)
                    111:                        putc('=', stderr);
                    112:                else
                    113:                        putc('|', stderr);
                    114:        }
                    115: }
                    116: 
                    117: #ifdef UNITTEST
                    118: #include <stdlib.h>            /* atexit() */
                    119: #include <unistd.h>            /* usleep() */
                    120: 
                    121: #define MAX_WIDTH    80
                    122: #define msleep(msec) usleep(msec * 1000)
                    123: 
                    124: static void bye(void)
                    125: {
                    126:        showcursor();
                    127: }
                    128: 
                    129: static void testit(int fn, int percent)
                    130: {
                    131:        if (fn)
                    132:                progress(percent, MAX_WIDTH);
                    133:        else
                    134:                progress_simple(percent);
                    135: }
                    136: 
                    137: static void test(int fn)
                    138: {
                    139:        int i, percent, block = 0, num = 85;
                    140: 
                    141:        while (block < num) {
                    142:                percent = block * 100 / num;
                    143:                for (i = 0; i < 10; i++) {
                    144:                        testit(fn, percent);
                    145:                        msleep(5);
                    146:                }
                    147:                block++;
                    148:                msleep(10);
                    149:        }
                    150:        testit(fn, 100);
                    151: }
                    152: 
                    153: int main(void)
                    154: {
                    155:        atexit(bye);
                    156:        hidecursor();
                    157: 
                    158:        printf("\nAdvanced:\n");
                    159:        test(1);
                    160:        printf("\nSimple:\n");
                    161:        test(0);
                    162:        printf("\n");
                    163: 
                    164:        return 0;
                    165: }
                    166: #endif /* UNITTEST */
                    167: 
                    168: /**
                    169:  * Local Variables:
                    170:  *  compile-command: "make V=1 -f progress.mk"
                    171:  *  version-control: t
                    172:  *  indent-tabs-mode: t
                    173:  *  c-file-style: "linux"
                    174:  * End:
                    175:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>