update for HEAD-2003021201
[reactos.git] / subsys / system / usetup / progress.c
1
2 /* INCLUDES *****************************************************************/
3
4 #include <ddk/ntddk.h>
5 #include <ntdll/rtl.h>
6
7 #include "usetup.h"
8 #include "progress.h"
9
10 /* FUNCTIONS ****************************************************************/
11
12
13 static VOID
14 DrawBorder(PPROGRESS Bar)
15 {
16   COORD coPos;
17   ULONG Written;
18   SHORT i;
19
20   /* draw upper left corner */
21   coPos.X = Bar->Left;
22   coPos.Y = Bar->Top + 1;
23   FillConsoleOutputCharacter(0xDA, // '+',
24                              1,
25                              coPos,
26                              &Written);
27
28   /* draw upper edge */
29   coPos.X = Bar->Left + 1;
30   coPos.Y = Bar->Top + 1;
31   FillConsoleOutputCharacter(0xC4, // '-',
32                              Bar->Right - Bar->Left - 1,
33                              coPos,
34                              &Written);
35
36   /* draw upper right corner */
37   coPos.X = Bar->Right;
38   coPos.Y = Bar->Top + 1;
39   FillConsoleOutputCharacter(0xBF, // '+',
40                              1,
41                              coPos,
42                              &Written);
43
44   /* draw left and right edge */
45   for (i = Bar->Top + 2; i < Bar->Bottom; i++)
46     {
47       coPos.X = Bar->Left;
48       coPos.Y = i;
49       FillConsoleOutputCharacter(0xB3, // '|',
50                                  1,
51                                  coPos,
52                                  &Written);
53
54       coPos.X = Bar->Right;
55       FillConsoleOutputCharacter(0xB3, //'|',
56                                  1,
57                                  coPos,
58                                  &Written);
59     }
60
61   /* draw lower left corner */
62   coPos.X = Bar->Left;
63   coPos.Y = Bar->Bottom;
64   FillConsoleOutputCharacter(0xC0, // '+',
65                              1,
66                              coPos,
67                              &Written);
68
69   /* draw lower edge */
70   coPos.X = Bar->Left + 1;
71   coPos.Y = Bar->Bottom;
72   FillConsoleOutputCharacter(0xC4, // '-',
73                              Bar->Right - Bar->Left - 1,
74                              coPos,
75                              &Written);
76
77   /* draw lower right corner */
78   coPos.X = Bar->Right;
79   coPos.Y = Bar->Bottom;
80   FillConsoleOutputCharacter(0xD9, // '+',
81                              1,
82                              coPos,
83                              &Written);
84 }
85
86
87 static VOID
88 DrawProgressBar(PPROGRESS Bar)
89 {
90   CHAR TextBuffer[8];
91   COORD coPos;
92   ULONG Written;
93   SHORT i;
94
95   /* Print percentage */
96   sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
97
98   coPos.X = Bar->Left + (Bar->Width - 2) / 2;
99   coPos.Y = Bar->Top;
100   WriteConsoleOutputCharacters(TextBuffer,
101                                4,
102                                coPos);
103
104   DrawBorder(Bar);
105
106   /* Draw the bar */
107   coPos.X = Bar->Left + 1;
108   for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
109     {
110       FillConsoleOutputAttribute(0x1E, /* Yellow on blue */
111                                  Bar->Width - 2,
112                                  coPos,
113                                  &Written);
114
115       FillConsoleOutputCharacter(' ',
116                                  Bar->Width - 2,
117                                  coPos,
118                                  &Written);
119     }
120
121 }
122
123
124
125 PPROGRESS
126 CreateProgressBar(SHORT Left,
127                   SHORT Top,
128                   SHORT Right,
129                   SHORT Bottom)
130 {
131   PPROGRESS Bar;
132
133   Bar = (PPROGRESS)RtlAllocateHeap(ProcessHeap,
134                                    0,
135                                    sizeof(PROGRESS));
136   if (Bar == NULL)
137     return(NULL);
138
139   Bar->Left = Left;
140   Bar->Top = Top;
141   Bar->Right = Right;
142   Bar->Bottom = Bottom;
143
144   Bar->Width = Bar->Right - Bar->Left + 1;
145
146   Bar->Percent = 0;
147   Bar->Pos = 0;
148
149   Bar->StepCount = 0;
150   Bar->CurrentStep = 0;
151
152   DrawProgressBar(Bar);
153
154   return(Bar);
155 }
156
157
158 VOID
159 DestroyProgressBar(PPROGRESS Bar)
160 {
161   RtlFreeHeap(ProcessHeap,
162               0,
163               Bar);
164 }
165
166 VOID
167 ProgressSetStepCount(PPROGRESS Bar,
168                      ULONG StepCount)
169 {
170   Bar->CurrentStep = 0;
171   Bar->StepCount = StepCount;
172
173   DrawProgressBar(Bar);
174 }
175
176
177 VOID
178 ProgressNextStep(PPROGRESS Bar)
179 {
180   CHAR TextBuffer[8];
181   COORD coPos;
182   ULONG Written;
183   ULONG NewPercent;
184   ULONG NewPos;
185
186   if ((Bar->StepCount == 0) ||
187       (Bar->CurrentStep == Bar->StepCount))
188     return;
189
190   Bar->CurrentStep++;
191
192   /* Calculate new percentage */
193   NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
194
195   /* Redraw precentage if changed */
196   if (Bar->Percent != NewPercent)
197     {
198       Bar->Percent = NewPercent;
199
200       sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
201
202       coPos.X = Bar->Left + (Bar->Width - 2) / 2;
203       coPos.Y = Bar->Top;
204       WriteConsoleOutputCharacters(TextBuffer,
205                                    4,
206                                    coPos);
207     }
208
209   /* Calculate bar position */
210   NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
211
212   /* Redraw bar if changed */
213   if (Bar->Pos != NewPos)
214     {
215       Bar->Pos = NewPos;
216
217       for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
218         {
219           coPos.X = Bar->Left + 1;
220           FillConsoleOutputCharacter(0xDB,
221                                      Bar->Pos / 2,
222                                      coPos,
223                                      &Written);
224           coPos.X += Bar->Pos/2;
225
226           if (Pos & 1)
227             {
228               FillConsoleOutputCharacter(0xDD,
229                                          1,
230                                          coPos,
231                                          &Written);
232               coPos.X++;
233             }
234
235           if (coPos.X <= Bar->Right - 1)
236             {
237               FillConsoleOutputCharacter(' ',
238                                          Bar->Right - coPos.X,
239                                          coPos,
240                                          &Written);
241             }
242         }
243     }
244 }
245
246 /* EOF */