Initial revision
[reactos.git] / freeldr / freeldr / tui.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "freeldr.h"
21 #include "stdlib.h"
22 #include "tui.h"
23
24 int nScreenWidth = 80; // Screen Width
25 int nScreenHeight = 25; // Screen Height
26
27 char cStatusBarFgColor = COLOR_BLACK; // Status bar foreground color
28 char cStatusBarBgColor = COLOR_CYAN; // Status bar background color
29 char cBackdropFgColor = COLOR_WHITE; // Backdrop foreground color
30 char cBackdropBgColor = COLOR_BLUE; // Backdrop background color
31 char cBackdropFillStyle = MEDIUM_FILL; // Backdrop fill style
32 char cTitleBoxFgColor = COLOR_WHITE; // Title box foreground color
33 char cTitleBoxBgColor = COLOR_RED; // Title box background color
34 char cMessageBoxFgColor = COLOR_WHITE; // Message box foreground color
35 char cMessageBoxBgColor = COLOR_BLUE; // Message box background color
36 char cMenuFgColor = COLOR_WHITE; // Menu foreground color
37 char cMenuBgColor = COLOR_BLUE; // Menu background color
38 char cTextColor = COLOR_YELLOW; // Normal text color
39 char cSelectedTextColor = COLOR_BLACK; // Selected text color
40 char cSelectedTextBgColor = COLOR_GRAY; // Selected text background color
41 char szTitleBoxTitleText[260] = "Boot Menu"; // Title box's title text
42
43 char szMessageBoxLineText[4000] = "";
44
45 void DrawBackdrop(void)
46 {
47 // Fill in the backdrop
48 FillArea(0, 0, nScreenWidth-1, nScreenHeight-1, cBackdropFillStyle, ATTR(cBackdropFgColor, cBackdropBgColor));
49
50 // Draw the title box
51 DrawBox(1, 1, nScreenWidth, 5, D_VERT, D_HORZ, TRUE, FALSE, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
52
53 // Draw version
54 DrawText(3, 2, VERSION, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
55 // Draw copyright
56 DrawText(3, 3, "by Brian Palmer", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
57 DrawText(3, 4, "<brianp@sginet.com>", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
58
59 // Draw help text
60 //DrawText(nScreenWidth-15, 4, /*"F1 for Help"*/"F8 for Options", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
61
62 // Draw title
63 DrawText((nScreenWidth/2)-(strlen(szTitleBoxTitleText)/2), 3, szTitleBoxTitleText, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
64
65 // Draw date
66 DrawText(nScreenWidth-9, 2, "01/02/03", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
67 // Draw time
68 DrawText(nScreenWidth-9, 3, "10:12:34", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
69
70 // Draw status bar
71 DrawStatusText("");
72
73 // Update the date & time
74 UpdateDateTime();
75 }
76
77 /*
78 * FillArea()
79 * This function assumes coordinates are zero-based
80 */
81 void FillArea(int nLeft, int nTop, int nRight, int nBottom, char cFillChar, char cAttr /* Color Attributes */)
82 {
83 char *screen = (char *)SCREEN_MEM;
84 int i, j;
85
86 for(i=nTop; i<=nBottom; i++)
87 {
88 for(j=nLeft; j<=nRight; j++)
89 {
90 screen[((i*2)*nScreenWidth)+(j*2)] = cFillChar;
91 screen[((i*2)*nScreenWidth)+(j*2)+1] = cAttr;
92 }
93 }
94 }
95
96 /*
97 * DrawShadow()
98 * This function assumes coordinates are zero-based
99 */
100 void DrawShadow(int nLeft, int nTop, int nRight, int nBottom)
101 {
102 char *screen = (char *)SCREEN_MEM;
103 int i;
104
105 // Shade the bottom of the area
106 if(nBottom < (nScreenHeight-1))
107 {
108 for(i=nLeft+2; i<=nRight; i++)
109 screen[(((nBottom+1)*2)*nScreenWidth)+(i*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
110 }
111
112 // Shade the right of the area
113 if(nRight < (nScreenWidth-1))
114 {
115 for(i=nTop+1; i<=nBottom; i++)
116 screen[((i*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
117 }
118 if(nRight+1 < (nScreenWidth-1))
119 {
120 for(i=nTop+1; i<=nBottom; i++)
121 screen[((i*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
122 }
123
124 // Shade the bottom right corner
125 if((nRight < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
126 screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
127 if((nRight+1 < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
128 screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
129 }
130
131 /*
132 * DrawBox()
133 * This function assumes coordinates are one-based
134 */
135 void DrawBox(int nLeft, int nTop, int nRight, int nBottom, int nVertStyle, int nHorzStyle, int bFill, int bShadow, char cAttr)
136 {
137 char cULCorner, cURCorner, cLLCorner, cLRCorner;
138 char cHorz, cVert;
139
140 nLeft--;
141 nTop--;
142 nRight--;
143 nBottom--;
144
145 cHorz = nHorzStyle;
146 cVert = nVertStyle;
147 if(nHorzStyle == HORZ)
148 {
149 if(nVertStyle == VERT)
150 {
151 cULCorner = UL;
152 cURCorner = UR;
153 cLLCorner = LL;
154 cLRCorner = LR;
155 }
156 else // nVertStyle == D_VERT
157 {
158 cULCorner = VD_UL;
159 cURCorner = VD_UR;
160 cLLCorner = VD_LL;
161 cLRCorner = VD_LR;
162 }
163 }
164 else // nHorzStyle == D_HORZ
165 {
166 if(nVertStyle == VERT)
167 {
168 cULCorner = HD_UL;
169 cURCorner = HD_UR;
170 cLLCorner = HD_LL;
171 cLRCorner = HD_LR;
172 }
173 else // nVertStyle == D_VERT
174 {
175 cULCorner = D_UL;
176 cURCorner = D_UR;
177 cLLCorner = D_LL;
178 cLRCorner = D_LR;
179 }
180 }
181
182 // Fill in box background
183 if(bFill)
184 FillArea(nLeft, nTop, nRight, nBottom, ' ', cAttr);
185
186 // Fill in corners
187 FillArea(nLeft, nTop, nLeft, nTop, cULCorner, cAttr);
188 FillArea(nRight, nTop, nRight, nTop, cURCorner, cAttr);
189 FillArea(nLeft, nBottom, nLeft, nBottom, cLLCorner, cAttr);
190 FillArea(nRight, nBottom, nRight, nBottom, cLRCorner, cAttr);
191
192 // Fill in left line
193 FillArea(nLeft, nTop+1, nLeft, nBottom-1, cVert, cAttr);
194 // Fill in top line
195 FillArea(nLeft+1, nTop, nRight-1, nTop, cHorz, cAttr);
196 // Fill in right line
197 FillArea(nRight, nTop+1, nRight, nBottom-1, cVert, cAttr);
198 // Fill in bottom line
199 FillArea(nLeft+1, nBottom, nRight-1, nBottom, cHorz, cAttr);
200
201 if(bShadow)
202 DrawShadow(nLeft, nTop, nRight, nBottom);
203 }
204
205 /*
206 * DrawText()
207 * This function assumes coordinates are one-based
208 */
209 void DrawText(int nX, int nY, char *text, char cAttr)
210 {
211 char *screen = (char *)SCREEN_MEM;
212 int i, j;
213
214 nX--;
215 nY--;
216
217 // Draw the text
218 for(i=nX, j=0; text[j]; i++,j++)
219 {
220 screen[((nY*2)*nScreenWidth)+(i*2)] = text[j];
221 screen[((nY*2)*nScreenWidth)+(i*2)+1] = cAttr;
222 }
223 }
224
225 void DrawStatusText(char *text)
226 {
227 int i;
228
229 DrawText(1, nScreenHeight, text, ATTR(cStatusBarFgColor, cStatusBarBgColor));
230
231 for(i=strlen(text)+1; i<=nScreenWidth; i++)
232 DrawText(i, nScreenHeight, " ", ATTR(cStatusBarFgColor, cStatusBarBgColor));
233 }
234
235 void UpdateDateTime(void)
236 {
237 char date[260];
238 char time[260];
239 char temp[20];
240 int hour, minute, second, bPM=FALSE;
241
242 switch(getmonth())
243 {
244 case 1:
245 strcpy(date, "January ");
246 break;
247 case 2:
248 strcpy(date, "February ");
249 break;
250 case 3:
251 strcpy(date, "March ");
252 break;
253 case 4:
254 strcpy(date, "April ");
255 break;
256 case 5:
257 strcpy(date, "May ");
258 break;
259 case 6:
260 strcpy(date, "June ");
261 break;
262 case 7:
263 strcpy(date, "July ");
264 break;
265 case 8:
266 strcpy(date, "August ");
267 break;
268 case 9:
269 strcpy(date, "September ");
270 break;
271 case 10:
272 strcpy(date, "October ");
273 break;
274 case 11:
275 strcpy(date, "November ");
276 break;
277 case 12:
278 strcpy(date, "December ");
279 break;
280 }
281 itoa(getday(), temp, 10);
282 if((getday() == 1) || (getday() == 21) || (getday() == 31))
283 strcat(temp, "st");
284 else if((getday() == 2) || (getday() == 22))
285 strcat(temp, "nd");
286 else if((getday() == 3) || (getday() == 23))
287 strcat(temp, "rd");
288 else
289 strcat(temp, "th");
290
291 strcat(date, temp);
292 strcat(date, " ");
293 itoa(getyear(), temp, 10);
294 strcat(date, temp);
295
296 // Draw the date
297 DrawText(nScreenWidth-strlen(date)-1, 2, date, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
298
299 hour = gethour();
300 if(hour > 12)
301 {
302 hour -= 12;
303 bPM = TRUE;
304 }
305 if (hour == 0)
306 hour = 12;
307 minute = getminute();
308 second = getsecond();
309 itoa(hour, temp, 10);
310 strcpy(time, " ");
311 strcat(time, temp);
312 strcat(time, ":");
313 itoa(minute, temp, 10);
314 if(minute < 10)
315 strcat(time, "0");
316 strcat(time, temp);
317 strcat(time, ":");
318 itoa(second, temp, 10);
319 if(second < 10)
320 strcat(time, "0");
321 strcat(time, temp);
322 if(bPM)
323 strcat(time, " PM");
324 else
325 strcat(time, " AM");
326
327 // Draw the time
328 DrawText(nScreenWidth-strlen(time)-1, 3, time, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
329 }
330
331 void SaveScreen(char *buffer)
332 {
333 char *screen = (char *)SCREEN_MEM;
334 int i;
335
336 for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++)
337 buffer[i] = screen[i];
338 }
339
340 void RestoreScreen(char *buffer)
341 {
342 char *screen = (char *)SCREEN_MEM;
343 int i;
344
345 for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++)
346 screen[i] = buffer[i];
347 }
348
349 void MessageBox(char *text)
350 {
351 int width = 8;
352 int height = 1;
353 int curline = 0;
354 int i , j, k;
355 int x1, x2, y1, y2;
356 char savebuffer[8000];
357 char temp[260];
358 char key;
359
360 SaveScreen(savebuffer);
361 strcat(szMessageBoxLineText, text);
362
363 // Find the height
364 for(i=0; i<strlen(szMessageBoxLineText); i++)
365 {
366 if(szMessageBoxLineText[i] == '\n')
367 height++;
368 }
369
370 // Find the width
371 for(i=0,j=0,k=0; i<height; i++)
372 {
373 while((szMessageBoxLineText[j] != '\n') && (szMessageBoxLineText[j] != 0))
374 {
375 j++;
376 k++;
377 }
378
379 if(k > width)
380 width = k;
381
382 k = 0;
383 j++;
384 }
385
386 // Calculate box area
387 x1 = (nScreenWidth - (width+2))/2;
388 x2 = x1 + width + 3;
389 y1 = ((nScreenHeight - height - 2)/2) + 1;
390 y2 = y1 + height + 4;
391
392 // Draw the box
393 DrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMessageBoxFgColor, cMessageBoxBgColor));
394
395 // Draw the text
396 for(i=0,j=0; i<strlen(szMessageBoxLineText)+1; i++)
397 {
398 if((szMessageBoxLineText[i] == '\n') || (szMessageBoxLineText[i] == 0))
399 {
400 temp[j] = 0;
401 j = 0;
402 DrawText(x1+2, y1+1+curline, temp, ATTR(cMessageBoxFgColor, cMessageBoxBgColor));
403 curline++;
404 }
405 else
406 temp[j++] = szMessageBoxLineText[i];
407 }
408
409 // Draw OK button
410 strcpy(temp, " OK ");
411 DrawText(x1+((x2-x1)/2)-3, y2-2, temp, ATTR(COLOR_BLACK, COLOR_GRAY));
412
413 for(;;)
414 {
415 if(kbhit())
416 {
417 key = getch();
418 if(key == KEY_EXTENDED)
419 key = getch();
420
421 if(key == KEY_ENTER)
422 break;
423 else if(key == KEY_SPACE)
424 break;
425 }
426
427 UpdateDateTime();
428 }
429
430 RestoreScreen(savebuffer);
431 UpdateDateTime();
432 strcpy(szMessageBoxLineText, "");
433 }
434
435 void MessageLine(char *text)
436 {
437 strcat(szMessageBoxLineText, text);
438 strcat(szMessageBoxLineText, "\n");
439 }
440
441 BOOL IsValidColor(char *color)
442 {
443 if(stricmp(color, "Black") == 0)
444 return TRUE;
445 else if(stricmp(color, "Blue") == 0)
446 return TRUE;
447 else if(stricmp(color, "Green") == 0)
448 return TRUE;
449 else if(stricmp(color, "Cyan") == 0)
450 return TRUE;
451 else if(stricmp(color, "Red") == 0)
452 return TRUE;
453 else if(stricmp(color, "Magenta") == 0)
454 return TRUE;
455 else if(stricmp(color, "Brown") == 0)
456 return TRUE;
457 else if(stricmp(color, "Gray") == 0)
458 return TRUE;
459 else if(stricmp(color, "DarkGray") == 0)
460 return TRUE;
461 else if(stricmp(color, "LightBlue") == 0)
462 return TRUE;
463 else if(stricmp(color, "LightGreen") == 0)
464 return TRUE;
465 else if(stricmp(color, "LightCyan") == 0)
466 return TRUE;
467 else if(stricmp(color, "LightRed") == 0)
468 return TRUE;
469 else if(stricmp(color, "LightMagenta") == 0)
470 return TRUE;
471 else if(stricmp(color, "Yellow") == 0)
472 return TRUE;
473 else if(stricmp(color, "White") == 0)
474 return TRUE;
475
476 return FALSE;
477 }
478
479 char TextToColor(char *color)
480 {
481 if(stricmp(color, "Black") == 0)
482 return COLOR_BLACK;
483 else if(stricmp(color, "Blue") == 0)
484 return COLOR_BLUE;
485 else if(stricmp(color, "Green") == 0)
486 return COLOR_GREEN;
487 else if(stricmp(color, "Cyan") == 0)
488 return COLOR_CYAN;
489 else if(stricmp(color, "Red") == 0)
490 return COLOR_RED;
491 else if(stricmp(color, "Magenta") == 0)
492 return COLOR_MAGENTA;
493 else if(stricmp(color, "Brown") == 0)
494 return COLOR_BROWN;
495 else if(stricmp(color, "Gray") == 0)
496 return COLOR_GRAY;
497 else if(stricmp(color, "DarkGray") == 0)
498 return COLOR_DARKGRAY;
499 else if(stricmp(color, "LightBlue") == 0)
500 return COLOR_LIGHTBLUE;
501 else if(stricmp(color, "LightGreen") == 0)
502 return COLOR_LIGHTGREEN;
503 else if(stricmp(color, "LightCyan") == 0)
504 return COLOR_LIGHTCYAN;
505 else if(stricmp(color, "LightRed") == 0)
506 return COLOR_LIGHTRED;
507 else if(stricmp(color, "LightMagenta") == 0)
508 return COLOR_LIGHTMAGENTA;
509 else if(stricmp(color, "Yellow") == 0)
510 return COLOR_YELLOW;
511 else if(stricmp(color, "White") == 0)
512 return COLOR_WHITE;
513
514 return COLOR_BLACK;
515 }
516
517 BOOL IsValidFillStyle(char *fill)
518 {
519 if(stricmp(fill, "Light") == 0)
520 return TRUE;
521 else if(stricmp(fill, "Medium") == 0)
522 return TRUE;
523 else if(stricmp(fill, "Dark") == 0)
524 return TRUE;
525
526 return FALSE;
527 }
528
529 char TextToFillStyle(char *fill)
530 {
531 if(stricmp(fill, "Light") == 0)
532 return LIGHT_FILL;
533 else if(stricmp(fill, "Medium") == 0)
534 return MEDIUM_FILL;
535 else if(stricmp(fill, "Dark") == 0)
536 return DARK_FILL;
537
538 return LIGHT_FILL;
539 }
540
541 void DrawProgressBar(int nPos)
542 {
543 int left, top, right, bottom;
544 int width = 50; // Allow for 50 "bars"
545 int height = 2;
546 int i;
547
548 if(nPos > 100)
549 nPos = 100;
550
551 left = (nScreenWidth - width - 4) / 2;
552 right = left + width + 3;
553 top = (nScreenHeight - height - 2) / 2;
554 top += 4;
555 bottom = top + height + 1;
556
557 // Draw the box
558 DrawBox(left, top, right, bottom, VERT, HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
559
560 // Draw the "Loading..." text
561 DrawText(70/2, top+1, "Loading...", ATTR(cTextColor, cMenuBgColor));
562
563 // Draw the percent complete
564 for(i=0; i<(nPos/2); i++)
565 DrawText(left+2+i, top+2, "\xDB", ATTR(cTextColor, cMenuBgColor));
566
567 // Draw the rest
568 for(; i<50; i++)
569 DrawText(left+2+i, top+2, "\xB2", ATTR(cTextColor, cMenuBgColor));
570
571 UpdateDateTime();
572 }