windows-nt/Source/XPSP1/NT/base/ntsetup/textmode/kernel/spgauge.c
2020-09-26 16:20:57 +08:00

299 lines
5.8 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
spgauge.c
Abstract:
Code implementing a gas gauge for file copies for text mode NT setup.
Author:
Ted Miller (tedm) 14-April-1992
Revision History:
--*/
#include "spprecmp.h"
#pragma hdrstop
PWSTR PctFmtStr = L"%u%% ";
VOID
pSpDrawVariableParts(
IN PGAS_GAUGE Gauge
);
PVOID
SpCreateAndDisplayGauge(
IN ULONG ItemCount,
IN ULONG GaugeWidth, OPTIONAL
IN ULONG Y,
IN PWCHAR Caption,
IN PWCHAR ProgressFmtStr, OPTIONAL
IN ULONG Flags, OPTIONAL
IN UCHAR Attribute OPTIONAL
)
{
PGAS_GAUGE Gauge;
ULONG X;
//
// Allocate a gauge structure.
//
Gauge = SpMemAlloc(sizeof(GAS_GAUGE));
if(!Gauge) {
return(NULL);
}
Gauge->Buffer = SpMemAlloc(VideoVars.ScreenWidth*sizeof(WCHAR));
if(!Gauge->Buffer) {
SpMemFree(Gauge);
return(NULL);
}
Gauge->Caption = SpMemAlloc((wcslen(Caption)+1)*sizeof(WCHAR));
if(!Gauge->Caption) {
SpMemFree(Gauge->Buffer);
SpMemFree(Gauge);
return(NULL);
}
wcscpy(Gauge->Caption,Caption);
if (ProgressFmtStr) {
Gauge->ProgressFmtStr = SpMemAlloc((wcslen(ProgressFmtStr)+1)*sizeof(WCHAR));
if(!Gauge->ProgressFmtStr) {
SpMemFree(Gauge->Buffer);
SpMemFree(Gauge->Caption);
SpMemFree(Gauge);
return(NULL);
}
wcscpy(Gauge->ProgressFmtStr,ProgressFmtStr);
Gauge->ProgressFmtWidth = SplangGetColumnCount(ProgressFmtStr);
} else {
Gauge->ProgressFmtStr = PctFmtStr;
Gauge->ProgressFmtWidth = 3;
}
Gauge->Flags = Flags;
if (Attribute) {
Gauge->Attribute = Attribute;
} else {
Gauge->Attribute = GAUGE_ATTRIBUTE;
}
//
// If the caller did not specify a width, calculate one.
// Originally, a gauge was 66 chars wide on an 80 character vga screen.
// To preserve that ratio, make the width 66/80ths of the screen.
//
if(!GaugeWidth) {
GaugeWidth = VideoVars.ScreenWidth * 66 / 80;
if(GaugeWidth & 1) {
GaugeWidth++; // make sure it's even.
}
}
//
// Center the gauge horizontally.
//
X = (VideoVars.ScreenWidth - GaugeWidth) / 2;
Gauge->GaugeX = X;
Gauge->GaugeY = Y;
Gauge->GaugeW = GaugeWidth;
//
// Calculate the size of the thermometer box.
// The box is always offset by 6 characters from the gauge itself.
//
Gauge->ThermX = X+6;
Gauge->ThermY = Y+3;
Gauge->ThermW = GaugeWidth-12;
//
// Save away additional info about the gauge.
//
Gauge->ItemCount = max (ItemCount, 1); // ensure no divide-by-zero bug checks
Gauge->ItemsElapsed = 0;
Gauge->CurrentPercentage = 0;
SpDrawGauge(Gauge);
return(Gauge);
}
VOID
SpDestroyGauge(
IN PVOID GaugeHandle
)
{
PGAS_GAUGE Gauge = (PGAS_GAUGE)GaugeHandle;
if (Gauge == NULL)
return;
if (Gauge->ProgressFmtStr != PctFmtStr) {
SpMemFree(Gauge->ProgressFmtStr);
}
SpMemFree(Gauge->Caption);
SpMemFree(Gauge->Buffer);
SpMemFree(Gauge);
}
VOID
SpDrawGauge(
IN PVOID GaugeHandle
)
{
PGAS_GAUGE Gauge = (PGAS_GAUGE)GaugeHandle;
//
// Draw the outer box.
//
SpDrawFrame(
Gauge->GaugeX,
Gauge->GaugeW,
Gauge->GaugeY,
GAUGE_HEIGHT,
DEFAULT_ATTRIBUTE,
TRUE
);
//
// Draw the thermometer box.
//
SpDrawFrame(
Gauge->ThermX,
Gauge->ThermW,
Gauge->ThermY,
3,
DEFAULT_ATTRIBUTE,
FALSE
);
//
// Percent complete, etc.
//
pSpDrawVariableParts(Gauge);
//
// Caption text
//
SpvidDisplayString(Gauge->Caption,DEFAULT_ATTRIBUTE,Gauge->GaugeX+2,Gauge->GaugeY+1);
}
VOID
SpTickGauge(
IN PVOID GaugeHandle
)
{
PGAS_GAUGE Gauge = (PGAS_GAUGE)GaugeHandle;
ULONG NewPercentage;
if(Gauge->ItemsElapsed < Gauge->ItemCount) {
Gauge->ItemsElapsed++;
NewPercentage = 100 * Gauge->ItemsElapsed / Gauge->ItemCount;
if(NewPercentage != Gauge->CurrentPercentage) {
Gauge->CurrentPercentage = NewPercentage;
pSpDrawVariableParts(Gauge);
}
}
}
VOID
pSpDrawVariableParts(
IN PGAS_GAUGE Gauge
)
{
ULONG Spaces;
ULONG i;
WCHAR Percent[128];
//
// Figure out how many spaces this is.
//
Spaces = Gauge->ItemsElapsed * (Gauge->ThermW-2) / Gauge->ItemCount;
for(i=0; i<Spaces; i++) {
Gauge->Buffer[i] = L' ';
}
Gauge->Buffer[Spaces] = 0;
SpvidDisplayString(Gauge->Buffer,Gauge->Attribute,Gauge->ThermX+1,Gauge->ThermY+1);
//
// Now put the percentage text up.
//
switch (Gauge->Flags) {
case GF_PERCENTAGE:
swprintf( Percent, Gauge->ProgressFmtStr, Gauge->CurrentPercentage );
break;
case GF_ITEMS_REMAINING:
swprintf( Percent, Gauge->ProgressFmtStr, Gauge->ItemCount - Gauge->ItemsElapsed );
break;
case GF_ITEMS_USED:
swprintf( Percent, Gauge->ProgressFmtStr, Gauge->ItemsElapsed );
break;
}
SpvidDisplayString(
Percent,
DEFAULT_ATTRIBUTE,
Gauge->GaugeX + ((Gauge->GaugeW-Gauge->ProgressFmtWidth)/2),
Gauge->GaugeY+2
);
}
VOID
SpFillGauge(
IN PVOID GaugeHandle,
IN ULONG Amount
)
{
PGAS_GAUGE Gauge = (PGAS_GAUGE)GaugeHandle;
ULONG NewPercentage;
if(Amount <= Gauge->ItemCount) {
Gauge->ItemsElapsed = Amount;
NewPercentage = 100 * Gauge->ItemsElapsed / Gauge->ItemCount;
if(NewPercentage != Gauge->CurrentPercentage) {
Gauge->CurrentPercentage = NewPercentage;
pSpDrawVariableParts(Gauge);
}
}
}