[SETUPLIB][USETUP][INPUT.CPL] MUI integration with setuplib.
[reactos.git] / base / setup / usetup / progress.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: base/setup/usetup/progress.c
5 * PURPOSE: Partition list functions
6 * PROGRAMMER:
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "usetup.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS ****************************************************************/
17
18 static
19 BOOLEAN NTAPI
20 UpdateProgressPercentage(
21 IN PPROGRESSBAR Bar,
22 IN BOOLEAN AlwaysUpdate,
23 OUT PSTR Buffer,
24 IN SIZE_T cchBufferSize)
25 {
26 // static PCSTR ProgressFormatText;
27 ULONG OldProgress = Bar->Progress;
28
29 /* Calculate the new percentage */
30 if (Bar->StepCount == 0)
31 Bar->Progress = 0;
32 else
33 Bar->Progress = ((100 * Bar->CurrentStep + (Bar->StepCount / 2)) / Bar->StepCount);
34
35 /* Build the progress string if it has changed */
36 if ( Bar->ProgressFormatText &&
37 (AlwaysUpdate || (Bar->Progress != OldProgress)) )
38 {
39 RtlStringCchPrintfA(Buffer, cchBufferSize,
40 Bar->ProgressFormatText, Bar->Progress);
41 return TRUE;
42 }
43 return FALSE;
44 }
45
46 static
47 VOID
48 DrawBorder(
49 IN PPROGRESSBAR Bar)
50 {
51 COORD coPos;
52 DWORD Written;
53 SHORT i;
54
55 /* draw upper left corner */
56 coPos.X = Bar->Left;
57 coPos.Y = Bar->Top + 1;
58 FillConsoleOutputCharacterA(StdOutput,
59 0xDA, // '+',
60 1,
61 coPos,
62 &Written);
63
64 /* draw upper edge */
65 coPos.X = Bar->Left + 1;
66 coPos.Y = Bar->Top + 1;
67 FillConsoleOutputCharacterA(StdOutput,
68 0xC4, // '-',
69 Bar->Right - Bar->Left - 1,
70 coPos,
71 &Written);
72
73 /* draw upper right corner */
74 coPos.X = Bar->Right;
75 coPos.Y = Bar->Top + 1;
76 FillConsoleOutputCharacterA(StdOutput,
77 0xBF, // '+',
78 1,
79 coPos,
80 &Written);
81
82 /* draw left and right edge */
83 for (i = Bar->Top + 2; i < Bar->Bottom; i++)
84 {
85 coPos.X = Bar->Left;
86 coPos.Y = i;
87 FillConsoleOutputCharacterA(StdOutput,
88 0xB3, // '|',
89 1,
90 coPos,
91 &Written);
92
93 coPos.X = Bar->Right;
94 FillConsoleOutputCharacterA(StdOutput,
95 0xB3, //'|',
96 1,
97 coPos,
98 &Written);
99 }
100
101 /* draw lower left corner */
102 coPos.X = Bar->Left;
103 coPos.Y = Bar->Bottom;
104 FillConsoleOutputCharacterA(StdOutput,
105 0xC0, // '+',
106 1,
107 coPos,
108 &Written);
109
110 /* draw lower edge */
111 coPos.X = Bar->Left + 1;
112 coPos.Y = Bar->Bottom;
113 FillConsoleOutputCharacterA(StdOutput,
114 0xC4, // '-',
115 Bar->Right - Bar->Left - 1,
116 coPos,
117 &Written);
118
119 /* draw lower right corner */
120 coPos.X = Bar->Right;
121 coPos.Y = Bar->Bottom;
122 FillConsoleOutputCharacterA(StdOutput,
123 0xD9, // '+',
124 1,
125 coPos,
126 &Written);
127 }
128
129 static
130 VOID
131 DrawThickBorder(
132 IN PPROGRESSBAR Bar)
133 {
134 COORD coPos;
135 DWORD Written;
136 SHORT i;
137
138 /* draw upper left corner */
139 coPos.X = Bar->Left;
140 coPos.Y = Bar->Top + 1;
141 FillConsoleOutputCharacterA(StdOutput,
142 0xC9, // '+',
143 1,
144 coPos,
145 &Written);
146
147 /* draw upper edge */
148 coPos.X = Bar->Left + 1;
149 coPos.Y = Bar->Top + 1;
150 FillConsoleOutputCharacterA(StdOutput,
151 0xCD, // '-',
152 Bar->Right - Bar->Left - 1,
153 coPos,
154 &Written);
155
156 /* draw upper right corner */
157 coPos.X = Bar->Right;
158 coPos.Y = Bar->Top + 1;
159 FillConsoleOutputCharacterA(StdOutput,
160 0xBB, // '+',
161 1,
162 coPos,
163 &Written);
164
165 /* draw left and right edge */
166 for (i = Bar->Top + 2; i < Bar->Bottom; i++)
167 {
168 coPos.X = Bar->Left;
169 coPos.Y = i;
170 FillConsoleOutputCharacterA(StdOutput,
171 0xBA, // '|',
172 1,
173 coPos,
174 &Written);
175
176 coPos.X = Bar->Right;
177 FillConsoleOutputCharacterA(StdOutput,
178 0xBA, //'|',
179 1,
180 coPos,
181 &Written);
182 }
183
184 /* draw lower left corner */
185 coPos.X = Bar->Left;
186 coPos.Y = Bar->Bottom;
187 FillConsoleOutputCharacterA(StdOutput,
188 0xC8, // '+',
189 1,
190 coPos,
191 &Written);
192
193 /* draw lower edge */
194 coPos.X = Bar->Left + 1;
195 coPos.Y = Bar->Bottom;
196 FillConsoleOutputCharacterA(StdOutput,
197 0xCD, // '-',
198 Bar->Right - Bar->Left - 1,
199 coPos,
200 &Written);
201
202 /* draw lower right corner */
203 coPos.X = Bar->Right;
204 coPos.Y = Bar->Bottom;
205 FillConsoleOutputCharacterA(StdOutput,
206 0xBC, // '+',
207 1,
208 coPos,
209 &Written);
210 }
211
212 static
213 VOID
214 DrawProgressBar(
215 IN PPROGRESSBAR Bar)
216 {
217 COORD coPos;
218 DWORD Written;
219 PROGRESSBAR BarBorder = *Bar;
220 CHAR TextBuffer[256];
221
222 /* Draw the progress bar "border" border */
223 if (Bar->DoubleEdge)
224 {
225 BarBorder.Top -= 5;
226 BarBorder.Bottom += 2;
227 BarBorder.Right += 5;
228 BarBorder.Left -= 5;
229 DrawThickBorder(&BarBorder);
230 }
231
232 /* Draw the progress bar border */
233 DrawBorder(Bar);
234
235 /* Display the description text */
236 if (Bar->DescriptionText)
237 CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->DescriptionText);
238
239 /* Always update and display the progress */
240 if (Bar->UpdateProgressProc &&
241 Bar->UpdateProgressProc(Bar, TRUE, TextBuffer, ARRAYSIZE(TextBuffer)))
242 {
243 coPos.X = Bar->Left + (Bar->Width - strlen(TextBuffer) + 1) / 2;
244 coPos.Y = Bar->Top;
245 WriteConsoleOutputCharacterA(StdOutput,
246 TextBuffer,
247 strlen(TextBuffer),
248 coPos,
249 &Written);
250 }
251
252 /* Draw the empty bar */
253 coPos.X = Bar->Left + 1;
254 for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
255 {
256 FillConsoleOutputAttribute(StdOutput,
257 Bar->ProgressColour,
258 Bar->Width - 2,
259 coPos,
260 &Written);
261
262 FillConsoleOutputCharacterA(StdOutput,
263 ' ',
264 Bar->Width - 2,
265 coPos,
266 &Written);
267 }
268 }
269
270
271 PPROGRESSBAR
272 CreateProgressBarEx(
273 IN SHORT Left,
274 IN SHORT Top,
275 IN SHORT Right,
276 IN SHORT Bottom,
277 IN SHORT TextTop,
278 IN SHORT TextRight,
279 IN BOOLEAN DoubleEdge,
280 IN SHORT ProgressColour,
281 IN ULONG StepCount,
282 IN PCSTR DescriptionText OPTIONAL,
283 IN PCSTR ProgressFormatText OPTIONAL,
284 IN PUPDATE_PROGRESS UpdateProgressProc OPTIONAL)
285 {
286 PPROGRESSBAR Bar;
287
288 Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap,
289 0,
290 sizeof(PROGRESSBAR));
291 if (Bar == NULL)
292 return NULL;
293
294 Bar->Left = Left;
295 Bar->Top = Top;
296 Bar->Right = Right;
297 Bar->Bottom = Bottom;
298 Bar->TextTop = TextTop;
299 Bar->TextRight = TextRight;
300
301 Bar->Width = Bar->Right - Bar->Left + 1;
302
303 Bar->DoubleEdge = DoubleEdge;
304 Bar->ProgressColour = ProgressColour;
305 Bar->DescriptionText = DescriptionText;
306 Bar->ProgressFormatText = ProgressFormatText;
307
308 Bar->UpdateProgressProc = UpdateProgressProc;
309
310 /* Reset the progress bar counts and initially draw it */
311 ProgressSetStepCount(Bar, StepCount);
312
313 return Bar;
314 }
315
316 PPROGRESSBAR
317 CreateProgressBar(
318 IN SHORT Left,
319 IN SHORT Top,
320 IN SHORT Right,
321 IN SHORT Bottom,
322 IN SHORT TextTop,
323 IN SHORT TextRight,
324 IN BOOLEAN DoubleEdge,
325 IN PCSTR DescriptionText OPTIONAL)
326 {
327 /* Call the Ex variant of the function */
328 return CreateProgressBarEx(Left, Top, Right, Bottom,
329 TextTop, TextRight,
330 DoubleEdge,
331 FOREGROUND_YELLOW | BACKGROUND_BLUE,
332 0,
333 DescriptionText,
334 "%-3lu%%",
335 UpdateProgressPercentage);
336 }
337
338 VOID
339 DestroyProgressBar(
340 IN OUT PPROGRESSBAR Bar)
341 {
342 RtlFreeHeap(ProcessHeap, 0, Bar);
343 }
344
345
346 VOID
347 ProgressSetStepCount(
348 IN PPROGRESSBAR Bar,
349 IN ULONG StepCount)
350 {
351 Bar->CurrentStep = 0;
352 Bar->StepCount = StepCount;
353
354 Bar->Progress = 0;
355 Bar->Pos = 0;
356
357 DrawProgressBar(Bar);
358 }
359
360 VOID
361 ProgressNextStep(
362 IN PPROGRESSBAR Bar)
363 {
364 ProgressSetStep(Bar, Bar->CurrentStep + 1);
365 }
366
367 VOID
368 ProgressSetStep(
369 IN PPROGRESSBAR Bar,
370 IN ULONG Step)
371 {
372 COORD coPos;
373 DWORD Written;
374 ULONG NewPos;
375 CHAR TextBuffer[256];
376
377 if (Step > Bar->StepCount)
378 return;
379
380 Bar->CurrentStep = Step;
381
382 /* Update the progress and redraw it if it has changed */
383 if (Bar->UpdateProgressProc &&
384 Bar->UpdateProgressProc(Bar, FALSE, TextBuffer, ARRAYSIZE(TextBuffer)))
385 {
386 coPos.X = Bar->Left + (Bar->Width - strlen(TextBuffer) + 1) / 2;
387 coPos.Y = Bar->Top;
388 WriteConsoleOutputCharacterA(StdOutput,
389 TextBuffer,
390 strlen(TextBuffer),
391 coPos,
392 &Written);
393 }
394
395 /* Calculate the bar position */
396 NewPos = (((Bar->Width - 2) * 2 * Bar->CurrentStep + (Bar->StepCount / 2)) / Bar->StepCount);
397
398 /* Redraw the bar if it has changed */
399 if (Bar->Pos != NewPos)
400 {
401 Bar->Pos = NewPos;
402
403 for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
404 {
405 coPos.X = Bar->Left + 1;
406 FillConsoleOutputCharacterA(StdOutput,
407 0xDB,
408 Bar->Pos / 2,
409 coPos,
410 &Written);
411 coPos.X += Bar->Pos / 2;
412
413 if (NewPos & 1)
414 {
415 FillConsoleOutputCharacterA(StdOutput,
416 0xDD,
417 1,
418 coPos,
419 &Written);
420 coPos.X++;
421 }
422
423 if (coPos.X <= Bar->Right - 1)
424 {
425 FillConsoleOutputCharacterA(StdOutput,
426 ' ',
427 Bar->Right - coPos.X,
428 coPos,
429 &Written);
430 }
431 }
432 }
433 }
434
435 /* EOF */