File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimd / libite / progress.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 09:12:58 2017 UTC (7 years, 4 months ago) by misho
Branches: pimd, MAIN
CVS tags: v2_3_2, HEAD
libite

    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>