* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/progress.c
* PURPOSE: Partition list functions
* PROGRAMMER:
*/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
static
BOOLEAN NTAPI
UpdateProgressPercentage(
IN PPROGRESSBAR Bar,
IN BOOLEAN AlwaysUpdate,
OUT PSTR Buffer,
IN SIZE_T cchBufferSize)
{
ULONG OldProgress = Bar->Progress;
if (Bar->StepCount == 0)
Bar->Progress = 0;
else
Bar->Progress = ((100 * Bar->CurrentStep + (Bar->StepCount / 2)) / Bar->StepCount);
if ( Bar->ProgressFormatText &&
(AlwaysUpdate || (Bar->Progress != OldProgress)) )
{
RtlStringCchPrintfA(Buffer, cchBufferSize,
Bar->ProgressFormatText, Bar->Progress);
return TRUE;
}
return FALSE;
}
static
VOID
DrawBorder(
IN PPROGRESSBAR Bar)
{
COORD coPos;
DWORD Written;
SHORT i;
coPos.X = Bar->Left;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharUpperLeftCorner,
1,
coPos,
&Written);
coPos.X = Bar->Left + 1;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharHorizontalLine,
Bar->Right - Bar->Left - 1,
coPos,
&Written);
coPos.X = Bar->Right;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharUpperRightCorner,
1,
coPos,
&Written);
for (i = Bar->Top + 2; i < Bar->Bottom; i++)
{
coPos.X = Bar->Left;
coPos.Y = i;
FillConsoleOutputCharacterA(StdOutput,
CharVerticalLine,
1,
coPos,
&Written);
coPos.X = Bar->Right;
FillConsoleOutputCharacterA(StdOutput,
CharVerticalLine,
1,
coPos,
&Written);
}
coPos.X = Bar->Left;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharLowerLeftCorner,
1,
coPos,
&Written);
coPos.X = Bar->Left + 1;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharHorizontalLine,
Bar->Right - Bar->Left - 1,
coPos,
&Written);
coPos.X = Bar->Right;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharLowerRightCorner,
1,
coPos,
&Written);
}
static
VOID
DrawThickBorder(
IN PPROGRESSBAR Bar)
{
COORD coPos;
DWORD Written;
SHORT i;
coPos.X = Bar->Left;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleUpperLeftCorner,
1,
coPos,
&Written);
coPos.X = Bar->Left + 1;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleHorizontalLine,
Bar->Right - Bar->Left - 1,
coPos,
&Written);
coPos.X = Bar->Right;
coPos.Y = Bar->Top + 1;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleUpperRightCorner,
1,
coPos,
&Written);
for (i = Bar->Top + 2; i < Bar->Bottom; i++)
{
coPos.X = Bar->Left;
coPos.Y = i;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleVerticalLine,
1,
coPos,
&Written);
coPos.X = Bar->Right;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleVerticalLine,
1,
coPos,
&Written);
}
coPos.X = Bar->Left;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleLowerLeftCorner,
1,
coPos,
&Written);
coPos.X = Bar->Left + 1;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleHorizontalLine,
Bar->Right - Bar->Left - 1,
coPos,
&Written);
coPos.X = Bar->Right;
coPos.Y = Bar->Bottom;
FillConsoleOutputCharacterA(StdOutput,
CharDoubleLowerRightCorner,
1,
coPos,
&Written);
}
static
VOID
DrawProgressBar(
IN PPROGRESSBAR Bar)
{
COORD coPos;
DWORD Written;
PROGRESSBAR BarBorder = *Bar;
CHAR TextBuffer[256];
if (Bar->DoubleEdge)
{
BarBorder.Top -= 5;
BarBorder.Bottom += 2;
BarBorder.Right += 5;
BarBorder.Left -= 5;
DrawThickBorder(&BarBorder);
}
DrawBorder(Bar);
if (Bar->DescriptionText)
CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->DescriptionText);
if (Bar->UpdateProgressProc &&
Bar->UpdateProgressProc(Bar, TRUE, TextBuffer, ARRAYSIZE(TextBuffer)))
{
coPos.X = Bar->Left + (Bar->Width - (USHORT)strlen(TextBuffer) + 1) / 2;
coPos.Y = Bar->Top;
WriteConsoleOutputCharacterA(StdOutput,
TextBuffer,
strlen(TextBuffer),
coPos,
&Written);
}
coPos.X = Bar->Left + 1;
for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
{
FillConsoleOutputAttribute(StdOutput,
Bar->ProgressColour,
Bar->Width - 2,
coPos,
&Written);
FillConsoleOutputCharacterA(StdOutput,
' ',
Bar->Width - 2,
coPos,
&Written);
}
}
PPROGRESSBAR
CreateProgressBarEx(
IN SHORT Left,
IN SHORT Top,
IN SHORT Right,
IN SHORT Bottom,
IN SHORT TextTop,
IN SHORT TextRight,
IN BOOLEAN DoubleEdge,
IN SHORT ProgressColour,
IN ULONG StepCount,
IN PCSTR DescriptionText OPTIONAL,
IN PCSTR ProgressFormatText OPTIONAL,
IN PUPDATE_PROGRESS UpdateProgressProc OPTIONAL)
{
PPROGRESSBAR Bar;
Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap,
0,
sizeof(PROGRESSBAR));
if (Bar == NULL)
return NULL;
Bar->Left = Left;
Bar->Top = Top;
Bar->Right = Right;
Bar->Bottom = Bottom;
Bar->TextTop = TextTop;
Bar->TextRight = TextRight;
Bar->Width = Bar->Right - Bar->Left + 1;
Bar->DoubleEdge = DoubleEdge;
Bar->ProgressColour = ProgressColour;
Bar->DescriptionText = DescriptionText;
Bar->ProgressFormatText = ProgressFormatText;
Bar->UpdateProgressProc = UpdateProgressProc;
ProgressSetStepCount(Bar, StepCount);
return Bar;
}
PPROGRESSBAR
CreateProgressBar(
IN SHORT Left,
IN SHORT Top,
IN SHORT Right,
IN SHORT Bottom,
IN SHORT TextTop,
IN SHORT TextRight,
IN BOOLEAN DoubleEdge,
IN PCSTR DescriptionText OPTIONAL)
{
return CreateProgressBarEx(Left, Top, Right, Bottom,
TextTop, TextRight,
DoubleEdge,
FOREGROUND_YELLOW | BACKGROUND_BLUE,
0,
DescriptionText,
"%-3lu%%",
UpdateProgressPercentage);
}
VOID
DestroyProgressBar(
IN OUT PPROGRESSBAR Bar)
{
RtlFreeHeap(ProcessHeap, 0, Bar);
}
VOID
ProgressSetStepCount(
IN PPROGRESSBAR Bar,
IN ULONG StepCount)
{
Bar->CurrentStep = 0;
Bar->StepCount = StepCount;
Bar->Progress = 0;
Bar->Pos = 0;
DrawProgressBar(Bar);
}
VOID
ProgressNextStep(
IN PPROGRESSBAR Bar)
{
ProgressSetStep(Bar, Bar->CurrentStep + 1);
}
VOID
ProgressSetStep(
IN PPROGRESSBAR Bar,
IN ULONG Step)
{
COORD coPos;
DWORD Written;
ULONG NewPos;
CHAR TextBuffer[256];
if (Step > Bar->StepCount)
return;
Bar->CurrentStep = Step;
if (Bar->UpdateProgressProc &&
Bar->UpdateProgressProc(Bar, FALSE, TextBuffer, ARRAYSIZE(TextBuffer)))
{
coPos.X = Bar->Left + (Bar->Width - (USHORT)strlen(TextBuffer) + 1) / 2;
coPos.Y = Bar->Top;
WriteConsoleOutputCharacterA(StdOutput,
TextBuffer,
strlen(TextBuffer),
coPos,
&Written);
}
NewPos = (((Bar->Width - 2) * 2 * Bar->CurrentStep + (Bar->StepCount / 2)) / Bar->StepCount);
if (Bar->Pos != NewPos)
{
Bar->Pos = NewPos;
for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
{
coPos.X = Bar->Left + 1;
FillConsoleOutputCharacterA(StdOutput,
CharBlock,
Bar->Pos / 2,
coPos,
&Written);
coPos.X += Bar->Pos / 2;
if (NewPos & 1)
{
FillConsoleOutputCharacterA(StdOutput,
CharHalfBlock,
1,
coPos,
&Written);
coPos.X++;
}
if (coPos.X <= Bar->Right - 1)
{
FillConsoleOutputCharacterA(StdOutput,
' ',
Bar->Right - coPos.X,
coPos,
&Written);
}
}
}
}