#include #include /* Only for the sleep, the progress bar code itself is standard C */ #include typedef enum { false=0, true=!false } bool; typedef struct { /* Start delimiter (e.g. [ )*/ char StartDelimiter; /* End Delimiter (e.g. ] )*/ char EndDelimiter; /* Central block (e.g. = )*/ char Block; /* Last blocks, rotated at each refresh (typical value: - | / - \ | / ) */ char LastBlocks[10]; /* Used positions of LastBlocks */ size_t LastBlocksSize; /* LastBlocks index to be used next time */ size_t LastBlockIndex; /* Width of the progress bar (in characters) */ unsigned int Width; /* Maximum value of the progress bar */ double Max; /* True if we have to print also the percentage of the operation */ bool PrintPercentage; /* True if the bar must be redrawn; note that this must be just set to false before the first call, the function then will change it by itself. */ bool Update; } ProgressBarSettings; /* Prints/updates the progress bar */ void PrintProgressBar(double Pos, ProgressBarSettings * Settings); /* Inits the settings of the progress bar to the default values */ void DefaultProgressBar(ProgressBarSettings * Settings); int main() { int i; /* Init the bar settings */ ProgressBarSettings pbs; DefaultProgressBar(&pbs); pbs.Max=400; pbs.Width=60; printf("Progress: "); /* Show the empty bar */ PrintProgressBar(0,&pbs); for(i=0;i<=pbs.Max;i++) { /* Wait 25 msec */ usleep(25000); /* Update the progress bar */ PrintProgressBar(i,&pbs); } puts(" Done"); return 0; } /* Inits the settings of the progress bar to the default values */ void DefaultProgressBar(ProgressBarSettings * Settings) { const char * defaultLastBlocks="-\\|/-\\|/"; Settings->StartDelimiter='['; Settings->EndDelimiter=']'; Settings->Block='='; strncpy(Settings->LastBlocks, defaultLastBlocks, sizeof(Settings->LastBlocks)); Settings->LastBlocksSize=strlen(defaultLastBlocks); if(Settings->LastBlocksSize>sizeof(Settings->LastBlocks)) Settings->LastBlocksSize=sizeof(Settings->LastBlocks); Settings->LastBlockIndex=0; Settings->PrintPercentage=true; Settings->Update=false; Settings->Max=100; Settings->Width=40; } /* Prints/updates the progress bar */ void PrintProgressBar(double Pos, ProgressBarSettings * Settings) { /* Blocks to print */ unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max); /* Counter */ unsigned int counter; /* If we are updating an existing bar...*/ if(Settings->Update) { /* ... we get back to its first character to rewrite it... */ for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--) putchar('\b'); } else Settings->Update=true; /* next time we'll be updating it */ /* Print the first delimiter */ putchar(Settings->StartDelimiter); /* Reset the counter */ counter=Settings->Width; /* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have the number of spaces to fill the bar */ for(;printBlocks>1;printBlocks--,counter--) putchar(Settings->Block); /* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */ putchar((Settings->Max==Pos)?Settings->Block:Settings->LastBlocks[Settings->LastBlockIndex]); /* At the next update we'll use the next last block */ Settings->LastBlockIndex=(Settings->LastBlockIndex+1)%Settings->LastBlocksSize; /* Another block was printed, decrement the counter */ counter--; /* Fill the rest of the bar with spaces */ for(;counter;counter--) putchar(' '); /* Print the end delimiter */ putchar(Settings->EndDelimiter); /* If asked, print also the percentage */ if(Settings->PrintPercentage) printf(" %3d%%",(int)(100*Pos/Settings->Max)); /* Flush the output buffer */ fflush(stdout); };