xref: /reactos/base/setup/usetup/progress.c (revision c2c66aff)
1 
2 /* INCLUDES *****************************************************************/
3 
4 #include "usetup.h"
5 
6 #define NDEBUG
7 #include <debug.h>
8 
9 /* FUNCTIONS ****************************************************************/
10 
11 
12 static
13 VOID
14 DrawBorder(
15     PPROGRESSBAR Bar)
16 {
17     COORD coPos;
18     DWORD Written;
19     SHORT i;
20 
21     /* draw upper left corner */
22     coPos.X = Bar->Left;
23     coPos.Y = Bar->Top + 1;
24     FillConsoleOutputCharacterA(StdOutput,
25                                 0xDA, // '+',
26                                 1,
27                                 coPos,
28                                 &Written);
29 
30     /* draw upper edge */
31     coPos.X = Bar->Left + 1;
32     coPos.Y = Bar->Top + 1;
33     FillConsoleOutputCharacterA(StdOutput,
34                                 0xC4, // '-',
35                                 Bar->Right - Bar->Left - 1,
36                                 coPos,
37                                 &Written);
38 
39     /* draw upper right corner */
40     coPos.X = Bar->Right;
41     coPos.Y = Bar->Top + 1;
42     FillConsoleOutputCharacterA(StdOutput,
43                                 0xBF, // '+',
44                                 1,
45                                 coPos,
46                                 &Written);
47 
48     /* draw left and right edge */
49     for (i = Bar->Top + 2; i < Bar->Bottom; i++)
50     {
51         coPos.X = Bar->Left;
52         coPos.Y = i;
53         FillConsoleOutputCharacterA(StdOutput,
54                                     0xB3, // '|',
55                                     1,
56                                     coPos,
57                                     &Written);
58 
59         coPos.X = Bar->Right;
60         FillConsoleOutputCharacterA(StdOutput,
61                                     0xB3, //'|',
62                                     1,
63                                     coPos,
64                                     &Written);
65     }
66 
67     /* draw lower left corner */
68     coPos.X = Bar->Left;
69     coPos.Y = Bar->Bottom;
70     FillConsoleOutputCharacterA(StdOutput,
71                                 0xC0, // '+',
72                                 1,
73                                 coPos,
74                                 &Written);
75 
76     /* draw lower edge */
77     coPos.X = Bar->Left + 1;
78     coPos.Y = Bar->Bottom;
79     FillConsoleOutputCharacterA(StdOutput,
80                                 0xC4, // '-',
81                                 Bar->Right - Bar->Left - 1,
82                                 coPos,
83                                 &Written);
84 
85     /* draw lower right corner */
86     coPos.X = Bar->Right;
87     coPos.Y = Bar->Bottom;
88     FillConsoleOutputCharacterA(StdOutput,
89                                 0xD9, // '+',
90                                 1,
91                                 coPos,
92                                 &Written);
93 }
94 
95 
96 static
97 VOID
98 DrawThickBorder(
99     PPROGRESSBAR Bar)
100 {
101     COORD coPos;
102     DWORD Written;
103     SHORT i;
104 
105     /* draw upper left corner */
106     coPos.X = Bar->Left;
107     coPos.Y = Bar->Top + 1;
108     FillConsoleOutputCharacterA(StdOutput,
109                                 0xC9, // '+',
110                                 1,
111                                 coPos,
112                                 &Written);
113 
114     /* draw upper edge */
115     coPos.X = Bar->Left + 1;
116     coPos.Y = Bar->Top + 1;
117     FillConsoleOutputCharacterA(StdOutput,
118                                 0xCD, // '-',
119                                 Bar->Right - Bar->Left - 1,
120                                 coPos,
121                                 &Written);
122 
123     /* draw upper right corner */
124     coPos.X = Bar->Right;
125     coPos.Y = Bar->Top + 1;
126     FillConsoleOutputCharacterA(StdOutput,
127                                 0xBB, // '+',
128                                 1,
129                                 coPos,
130                                 &Written);
131 
132     /* draw left and right edge */
133     for (i = Bar->Top + 2; i < Bar->Bottom; i++)
134     {
135         coPos.X = Bar->Left;
136         coPos.Y = i;
137         FillConsoleOutputCharacterA(StdOutput,
138                                     0xBA, // '|',
139                                     1,
140                                     coPos,
141                                     &Written);
142 
143         coPos.X = Bar->Right;
144         FillConsoleOutputCharacterA(StdOutput,
145                                     0xBA, //'|',
146                                     1,
147                                     coPos,
148                                     &Written);
149     }
150 
151     /* draw lower left corner */
152     coPos.X = Bar->Left;
153     coPos.Y = Bar->Bottom;
154     FillConsoleOutputCharacterA(StdOutput,
155                                 0xC8, // '+',
156                                 1,
157                                 coPos,
158                                 &Written);
159 
160     /* draw lower edge */
161     coPos.X = Bar->Left + 1;
162     coPos.Y = Bar->Bottom;
163     FillConsoleOutputCharacterA(StdOutput,
164                                 0xCD, // '-',
165                                 Bar->Right - Bar->Left - 1,
166                                 coPos,
167                                 &Written);
168 
169     /* draw lower right corner */
170     coPos.X = Bar->Right;
171     coPos.Y = Bar->Bottom;
172     FillConsoleOutputCharacterA(StdOutput,
173                                 0xBC, // '+',
174                                 1,
175                                 coPos,
176                                 &Written);
177 }
178 
179 
180 static
181 VOID
182 DrawProgressBar(
183     PPROGRESSBAR Bar)
184 {
185     CHAR TextBuffer[8];
186     COORD coPos;
187     DWORD Written;
188     PROGRESSBAR BarBorder = *Bar;
189 
190     /* Print percentage */
191     sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
192 
193     coPos.X = Bar->Left + (Bar->Width - 2) / 2;
194     coPos.Y = Bar->Top;
195     WriteConsoleOutputCharacterA(StdOutput,
196                                  TextBuffer,
197                                  4,
198                                  coPos,
199                                  &Written);
200 
201     /* Draw the progress bar border */
202     DrawBorder(Bar);
203 
204     /* Write Text Associated with Bar */
205     CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text);
206 
207     /* Draw the progress bar "border" border */
208     if (Bar->Double)
209     {
210         BarBorder.Top -= 5;
211         BarBorder.Bottom += 2;
212         BarBorder.Right += 5;
213         BarBorder.Left -= 5;
214         DrawThickBorder(&BarBorder);
215     }
216 
217     /* Draw the bar */
218     coPos.X = Bar->Left + 1;
219     for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
220     {
221         FillConsoleOutputAttribute(StdOutput,
222                                    FOREGROUND_YELLOW | BACKGROUND_BLUE,
223                                    Bar->Width - 2,
224                                    coPos,
225                                    &Written);
226 
227         FillConsoleOutputCharacterA(StdOutput,
228                                     ' ',
229                                     Bar->Width - 2,
230                                     coPos,
231                                     &Written);
232     }
233 }
234 
235 
236 PPROGRESSBAR
237 CreateProgressBar(
238     SHORT Left,
239     SHORT Top,
240     SHORT Right,
241     SHORT Bottom,
242     SHORT TextTop,
243     SHORT TextRight,
244     IN BOOLEAN DoubleEdge,
245     CHAR *Text)
246 {
247     PPROGRESSBAR Bar;
248 
249     Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap,
250                                         0,
251                                         sizeof(PROGRESSBAR));
252     if (Bar == NULL)
253         return NULL;
254 
255     Bar->Left = Left;
256     Bar->Top = Top;
257     Bar->Right = Right;
258     Bar->Bottom = Bottom;
259     Bar->TextTop = TextTop;
260     Bar->TextRight = TextRight;
261     Bar->Double = DoubleEdge;
262     Bar->Text = Text;
263 
264     Bar->Width = Bar->Right - Bar->Left + 1;
265 
266     Bar->Percent = 0;
267     Bar->Pos = 0;
268 
269     Bar->StepCount = 0;
270     Bar->CurrentStep = 0;
271 
272     DrawProgressBar(Bar);
273 
274     return Bar;
275 }
276 
277 
278 VOID
279 DestroyProgressBar(
280     PPROGRESSBAR Bar)
281 {
282     RtlFreeHeap(ProcessHeap, 0, Bar);
283 }
284 
285 
286 VOID
287 ProgressSetStepCount(
288     PPROGRESSBAR Bar,
289     ULONG StepCount)
290 {
291     Bar->CurrentStep = 0;
292     Bar->StepCount = StepCount;
293 
294     DrawProgressBar(Bar);
295 }
296 
297 
298 VOID
299 ProgressNextStep(
300     PPROGRESSBAR Bar)
301 {
302     ProgressSetStep(Bar, Bar->CurrentStep + 1);
303 }
304 
305 
306 VOID
307 ProgressSetStep(
308     PPROGRESSBAR Bar,
309     ULONG Step)
310 {
311     CHAR TextBuffer[8];
312     COORD coPos;
313     DWORD Written;
314     ULONG NewPercent;
315     ULONG NewPos;
316 
317     if (Step > Bar->StepCount)
318         return;
319 
320     Bar->CurrentStep = Step;
321 
322     /* Calculate new percentage */
323     NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
324 
325     /* Redraw percentage if changed */
326     if (Bar->Percent != NewPercent)
327     {
328         Bar->Percent = NewPercent;
329 
330         sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
331 
332         coPos.X = Bar->Left + (Bar->Width - 2) / 2;
333         coPos.Y = Bar->Top;
334         WriteConsoleOutputCharacterA(StdOutput,
335                                      TextBuffer,
336                                      4,
337                                      coPos,
338                                      &Written);
339     }
340 
341     /* Calculate bar position */
342     NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
343 
344     /* Redraw bar if changed */
345     if (Bar->Pos != NewPos)
346     {
347         Bar->Pos = NewPos;
348 
349         for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
350         {
351             coPos.X = Bar->Left + 1;
352             FillConsoleOutputCharacterA(StdOutput,
353                                         0xDB,
354                                         Bar->Pos / 2,
355                                         coPos,
356                                         &Written);
357             coPos.X += Bar->Pos/2;
358 
359             if (NewPos & 1)
360             {
361                 FillConsoleOutputCharacterA(StdOutput,
362                                             0xDD,
363                                             1,
364                                             coPos,
365                                             &Written);
366                 coPos.X++;
367             }
368 
369             if (coPos.X <= Bar->Right - 1)
370             {
371                 FillConsoleOutputCharacterA(StdOutput,
372                                             ' ',
373                                             Bar->Right - coPos.X,
374                                             coPos,
375                                             &Written);
376             }
377         }
378     }
379 }
380 
381 /* EOF */
382