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 */ 436