Annotation of embedaddon/pimd/libite/progress.c, revision 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>