Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/GUI/gui.c

1/*
2 * gui.c
3 *
4 *
5 * Created by Jasmin Fazlic on 18.12.08.
6 * Copyright 2008/09 Jasmin Fazlic All rights reserved.
7 * Copyright 2008/09 iNDi All rights reserved.
8 *
9 */
10
11/*
12 * cparm : cleaned
13 */
14
15#include "gui.h"
16#include "appleboot.h"
17#include "vers.h"
18#include "modules.h"
19#include "rand.h"
20#include "sl.h"
21
22
23gui_t gui;// gui structure
24font_t font_small;
25font_t font_console;
26
27
28#define IMG_REQUIRED -1
29#define THEME_NAME_DEFAULT"Default"
30const char* theme_name = THEME_NAME_DEFAULT;
31
32char dirsrc[22];
33
34#ifdef EMBED_THEME
35#include "art.h"
36#endif
37
38struct putc_info {
39 char * str;
40 char * last_str;
41};
42
43static int loadThemeImage(char *src, const char *image, int alt_image);
44static void loadBootGraphics(char *src);
45static void drawInfoMenuItems();
46static void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress);
47static void animateProgressBar();
48static void makeRoundedCorners(pixmap_t *p);
49static void colorFont(font_t *font, uint32_t color);
50static int initFont(font_t *font, image_t *data);
51static void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p);
52static void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p);
53#if DEBUG
54static int dprintf( window_t * window, const char * fmt, ...);
55#endif
56static void sputc(int c, struct putc_info * pi);
57#if UNUSED
58static inline
59void vramwrite (void *data, int width, int height);
60#else
61static inline
62void vramwrite (void *data, int width);
63#endif
64static void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected);
65static int startGUI(void);
66static int randomTheme(char *dirspec, const char **theme);
67static void loadThemeValues(config_file_t *theme);
68static void setupDeviceList(config_file_t *theme);
69static void fillPixmapWithColor(pixmap_t *pm, uint32_t color);
70static int freeWindowBuffer( window_t *window );
71static int createWindowBuffer( window_t *window );
72static int createBackBuffer( window_t *window );
73static int loadGraphics(char *src);
74#ifdef EMBED_THEME
75static int getEmbeddedImageIndexByName(const char *name);
76#endif
77static int getImageIndexByName(const char *name);
78
79#define LOADPNG(src, img, alt_img) if (loadThemeImage(src, #img, alt_img) != 0) { return 1; }
80
81#ifndef MIN
82#define MIN(x, y) ((x) < (y) ? (x) : (y))
83#endif
84
85#ifndef MAX
86#define MAX(x, y) ((x) > (y) ? (x) : (y))
87#endif
88
89#define VIDEO(x) (bootArgs->Video.v_ ## x)
90
91#define vram VIDEO(baseAddr)
92
93int lasttime = 0; // we need this for animating maybe
94
95extern int gDeviceCount;
96
97/*
98 * ATTENTION: the enum and the following array images[] MUST match !!!
99 */
100enum {
101 iBackground = 0,
102 iLogo,
103
104 iDeviceGeneric,
105 iDeviceGeneric_o,
106 iDeviceHFS,
107 iDeviceHFS_o,
108 iDeviceHFSRAID,
109 iDeviceHFSRAID_o,
110 iDeviceEXT3,
111 iDeviceEXT3_o,
112iDeviceFreeBSD,
113 iDeviceFreeBSD_o,
114 iDeviceOpenBSD,
115 iDeviceOpenBSD_o,
116 iDeviceFAT,
117 iDeviceFAT_o,
118 iDeviceFAT16,
119 iDeviceFAT16_o,
120 iDeviceFAT32,
121 iDeviceFAT32_o,
122 iDeviceNTFS,
123 iDeviceNTFS_o,
124 iDeviceCDROM,
125 iDeviceCDROM_o,
126
127 iSelection,
128 iDeviceScrollPrev,
129 iDeviceScrollNext,
130
131 iMenuBoot,
132 iMenuVerbose,
133 iMenuIgnoreCaches,
134 iMenuSingleUser,
135 iMenuMemoryInfo,
136 iMenuVideoInfo,
137 iMenuHelp,
138 iMenuVerboseDisabled,
139 iMenuIgnoreCachesDisabled,
140 iMenuSingleUserDisabled,
141 iMenuSelection,
142
143 iProgressBar,
144 iProgressBarBackground,
145
146 iTextScrollPrev,
147 iTextScrollNext,
148
149 iFontConsole,
150 iFontSmall,
151};
152
153image_t images[] = {
154 {.name = "background", .image = NULL},
155 {.name = "logo", .image = NULL},
156
157 {.name = "device_generic", .image = NULL},
158 {.name = "device_generic_o", .image = NULL},
159 {.name = "device_hfsplus", .image = NULL},
160 {.name = "device_hfsplus_o", .image = NULL},
161 {.name = "device_hfsraid", .image = NULL},
162 {.name = "device_hfsraid_o", .image = NULL},
163 {.name = "device_ext3", .image = NULL},
164 {.name = "device_ext3_o", .image = NULL},
165{.name = "device_freebsd", .image = NULL},
166 {.name = "device_freebsd_o", .image = NULL},
167 {.name = "device_openbsd", .image = NULL},
168 {.name = "device_openbsd_o", .image = NULL},
169 {.name = "device_fat", .image = NULL},
170 {.name = "device_fat_o", .image = NULL},
171 {.name = "device_fat16", .image = NULL},
172 {.name = "device_fat16_o", .image = NULL},
173 {.name = "device_fat32", .image = NULL},
174 {.name = "device_fat32_o", .image = NULL},
175 {.name = "device_ntfs", .image = NULL},
176 {.name = "device_ntfs_o", .image = NULL},
177 {.name = "device_cdrom", .image = NULL},
178 {.name = "device_cdrom_o", .image = NULL},
179
180 {.name = "device_selection", .image = NULL},
181 {.name = "device_scroll_prev", .image = NULL},
182 {.name = "device_scroll_next", .image = NULL},
183
184 {.name = "menu_boot", .image = NULL},
185 {.name = "menu_verbose", .image = NULL},
186 {.name = "menu_ignore_caches", .image = NULL},
187 {.name = "menu_single_user", .image = NULL},
188 {.name = "menu_memory_info", .image = NULL},
189 {.name = "menu_video_info", .image = NULL},
190 {.name = "menu_help", .image = NULL},
191 {.name = "menu_verbose_disabled", .image = NULL},
192 {.name = "menu_ignore_caches_disabled", .image = NULL},
193 {.name = "menu_single_user_disabled", .image = NULL},
194 {.name = "menu_selection", .image = NULL},
195
196 {.name = "progress_bar", .image = NULL},
197 {.name = "progress_bar_background", .image = NULL},
198
199 {.name = "text_scroll_prev", .image = NULL},
200 {.name = "text_scroll_next", .image = NULL},
201
202 {.name = "font_console", .image = NULL},
203 {.name = "font_small", .image = NULL},
204};
205
206int imageCnt = 0;
207
208extern intgDeviceCount;
209extern intselectIndex;
210
211char prompt[BOOT_STRING_LEN];
212
213int prompt_pos=0;
214
215char prompt_text[] = "boot: ";
216
217menuitem_t infoMenuItems[] =
218{
219{ .text = "Boot" },
220{ .text = "Boot Verbose" },
221{ .text = "Boot Ignore Caches" },
222{ .text = "Boot Single User" },
223{ .text = "Memory Info" },
224{ .text = "Video Info" },
225{ .text = "Help" }
226};
227
228int infoMenuSelection = 0;
229int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);
230
231bool infoMenuNativeBoot = false;
232
233unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0};// here we store the used screen resolution
234
235static int getImageIndexByName(const char *name)
236{
237 int i;
238for (i = 0; (unsigned)i < sizeof(images) / sizeof(images[0]); i++)
239{
240 if (strcmp(name, images[i].name) == 0)
241 return i; // found the name
242}
243return -1;
244}
245
246#ifdef EMBED_THEME
247static int getEmbeddedImageIndexByName(const char *name)
248{
249int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1;
250int lowerLimit = 0;
251int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint
252int result;
253
254// NOTE: This algorithm assumes that the embeddedImages is sorted.
255// This is currently done using the make file. If the array is every
256// manualy generated, this *will* fail to work properly.
257while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)
258{
259if(result > 0)// We need to search a HIGHER index
260{
261if(compareIndex != lowerLimit)
262{
263lowerLimit = compareIndex;
264}
265else
266{
267return -1;
268}
269compareIndex = (upperLimit + lowerLimit + 1) >> 1;// Midpoint, round up
270}
271else // We Need to search a LOWER index
272{
273if(compareIndex != upperLimit)
274{
275upperLimit = compareIndex;
276}
277else
278{
279return -1;
280}
281compareIndex = (upperLimit + lowerLimit) >> 1;// Midpoint, round down
282}
283}
284return compareIndex;
285}
286#endif
287
288static int loadThemeImage(char* src, const char *image, int alt_image)
289{
290chardirspec[256];
291int i;
292#ifdef EMBED_THEME
293int e;
294#endif
295uint16_twidth;
296uint16_theight;
297uint8_t*imagedata;
298if ((unsigned)(strlen(image) + strlen(theme_name) + 30 ) > sizeof(dirspec)) {
299return 1;
300}
301
302 if ((i = getImageIndexByName(image)) >= 0)
303 {
304 if (images[i].image == NULL) {
305 images[i].image = malloc(sizeof(pixmap_t));
306 }
307 sprintf(dirspec, "%s/%s/%s.png", src, theme_name, image);
308
309 width = 0;
310 height = 0;
311 imagedata = NULL;
312 if ( strlen(theme_name) > 0 && (loadPngImage(dirspec, &width, &height, &imagedata)) == 0)
313 {
314 images[i].image->width = width;
315 images[i].image->height = height;
316 images[i].image->pixels = (pixel_t *)imagedata;
317 flipRB(images[i].image);
318 return 0;
319 }
320#ifdef EMBED_THEME
321 else if ((e = getEmbeddedImageIndexByName(image)) >= 0)
322 {
323 unsigned char *embed_data;
324 unsigned int embed_size;
325 embed_data = embeddedImages[e].pngdata;
326 embed_size = *embeddedImages[e].length;
327
328 if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0)
329 {
330 images[i].image->width = width;
331 images[i].image->height = height;
332 images[i].image->pixels = (pixel_t *)imagedata;
333 flipRB(images[i].image);
334 return 0;
335 }
336
337 return 0;
338 }
339#endif
340 else if (alt_image != IMG_REQUIRED && images[alt_image].image->pixels != NULL)
341 {
342 // Using the passed alternate image for non-mandatory images.
343 // We don't clone the already existing pixmap, but using its properties instead!
344 images[i].image->width = images[alt_image].image->width;
345 images[i].image->height = images[alt_image].image->height;
346 images[i].image->pixels = images[alt_image].image->pixels;
347 return 0;
348 }
349 else
350 {
351#ifndef EMBED_THEME
352 printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);
353sleep(2);
354#endif
355 return 1;
356 }
357 }
358
359return 1;
360}
361
362static int loadGraphics(char *src)
363{
364LOADPNG(src, background, IMG_REQUIRED);
365
366LOADPNG(src, logo, IMG_REQUIRED);
367
368LOADPNG(src, device_generic, IMG_REQUIRED);
369LOADPNG(src, device_generic_o, iDeviceGeneric);
370LOADPNG(src, device_hfsplus, iDeviceGeneric);
371LOADPNG(src, device_hfsplus_o, iDeviceHFS);
372LOADPNG(src, device_hfsraid, iDeviceGeneric);
373LOADPNG(src, device_hfsraid_o, iDeviceHFSRAID);
374LOADPNG(src, device_ext3, iDeviceGeneric);
375LOADPNG(src, device_ext3_o, iDeviceEXT3);
376LOADPNG(src, device_freebsd, iDeviceGeneric);
377LOADPNG(src, device_freebsd_o, iDeviceFreeBSD);
378LOADPNG(src, device_openbsd, iDeviceGeneric);
379LOADPNG(src, device_openbsd_o, iDeviceOpenBSD);
380LOADPNG(src, device_fat, iDeviceGeneric);
381LOADPNG(src, device_fat_o, iDeviceFAT);
382LOADPNG(src, device_fat16, iDeviceFAT);
383LOADPNG(src, device_fat16_o, iDeviceFAT_o);
384LOADPNG(src, device_fat32, iDeviceFAT);
385LOADPNG(src, device_fat32_o, iDeviceFAT_o);
386LOADPNG(src, device_ntfs, iDeviceGeneric);
387LOADPNG(src, device_ntfs_o, iDeviceNTFS);
388LOADPNG(src, device_cdrom, iDeviceGeneric);
389LOADPNG(src, device_cdrom_o, iDeviceCDROM);
390
391LOADPNG(src, device_selection, IMG_REQUIRED);
392LOADPNG(src, device_scroll_prev, IMG_REQUIRED);
393LOADPNG(src, device_scroll_next, IMG_REQUIRED);
394
395LOADPNG(src, menu_boot, IMG_REQUIRED);
396LOADPNG(src, menu_verbose, IMG_REQUIRED);
397LOADPNG(src, menu_ignore_caches, IMG_REQUIRED);
398LOADPNG(src, menu_single_user, IMG_REQUIRED);
399LOADPNG(src, menu_memory_info, IMG_REQUIRED);
400LOADPNG(src, menu_video_info, IMG_REQUIRED);
401LOADPNG(src, menu_help, IMG_REQUIRED);
402LOADPNG(src, menu_verbose_disabled, IMG_REQUIRED);
403LOADPNG(src, menu_ignore_caches_disabled, IMG_REQUIRED);
404LOADPNG(src, menu_single_user_disabled, IMG_REQUIRED);
405LOADPNG(src, menu_selection, IMG_REQUIRED);
406
407LOADPNG(src, progress_bar, IMG_REQUIRED);
408LOADPNG(src, progress_bar_background, IMG_REQUIRED);
409
410LOADPNG(src, text_scroll_prev, IMG_REQUIRED);
411LOADPNG(src, text_scroll_next, IMG_REQUIRED);
412
413LOADPNG(src, font_console, IMG_REQUIRED);
414LOADPNG(src, font_small, IMG_REQUIRED);
415
416initFont( &font_console, &images[iFontConsole]);
417initFont( &font_small, &images[iFontSmall]);
418
419return 0;
420}
421#if UNUSED
422pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )
423{
424
425pixmap_t *cropped = malloc( sizeof( pixmap_t ) );
426if( !cropped )
427return 0;
428cropped->pixels = malloc( width * height * 4 );
429if ( !cropped->pixels )
430return 0;
431
432cropped->width = width;
433cropped->height = height;
434
435int destx = 0, desty = 0;
436int srcx = pos.x, srcy = pos.y;
437
438for( ; desty < height; desty++, srcy++)
439{
440for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )
441{
442pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;
443}
444}
445return cropped;
446}
447#endif
448
449static int createBackBuffer( window_t *window )
450{
451gui.backbuffer = malloc(sizeof(pixmap_t));
452if(!gui.backbuffer)
453return 1;
454
455gui.backbuffer->pixels = malloc( window->width * window->height * 4 );
456if(!gui.backbuffer->pixels)
457{
458free(gui.backbuffer);
459gui.backbuffer = 0;
460return 1;
461}
462
463gui.backbuffer->width = gui.screen.width;
464gui.backbuffer->height = gui.screen.height;
465
466return 0;
467}
468
469static int createWindowBuffer( window_t *window )
470{
471window->pixmap = malloc(sizeof(pixmap_t));
472if(!window->pixmap)
473return 1;
474
475window->pixmap->pixels = malloc( window->width * window->height * 4 );
476if(!window->pixmap->pixels)
477{
478free(window->pixmap);
479window->pixmap = 0;
480return 1;
481}
482
483window->pixmap->width = window->width;
484window->pixmap->height = window->height;
485
486return 0;
487}
488
489static int freeWindowBuffer( window_t *window )
490{
491if (window->pixmap && window->pixmap->pixels)
492 {
493free(window->pixmap->pixels);
494free(window->pixmap);
495return 0;
496}
497
498return 1;
499}
500
501static void fillPixmapWithColor(pixmap_t *pm, uint32_t color)
502{
503int x,y;
504
505// fill with given color AARRGGBB
506for( x=0; x < pm->width; x++ )
507for( y=0; y< pm->height; y++)
508pixel(pm,x,y).value = color;
509}
510
511void drawBackground()
512{
513// reset text cursor
514gui.screen.cursor.x = gui.screen.hborder;
515gui.screen.cursor.y = gui.screen.vborder;
516
517fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);
518
519// draw background.png into background buffer
520blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );
521
522// draw logo.png into background buffer
523if (gui.logo.draw)
524{
525 blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);
526}
527
528memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
529}
530
531static void setupDeviceList(config_file_t *theme)
532{
533unsigned int pixel;
534intalpha;// transparency level 0 (obligue) - 255 (transparent)
535uint32_t color;// color value formatted RRGGBB
536int val, len;
537const char *string;
538
539if(getIntForKey("devices_max_visible", &val, theme ))
540gui.maxdevices = MIN( val, gDeviceCount );
541
542if(getIntForKey("devices_iconspacing", &val, theme ))
543gui.devicelist.iconspacing = val;
544
545// check layout for horizontal or vertical
546gui.layout = HorizontalLayout;
547if(getValueForKey( "devices_layout", &string, &len, theme)) {
548if (!strcmp (string, "vertical")) {
549gui.layout = VerticalLayout;
550}
551}
552
553switch (gui.layout) {
554case VerticalLayout:
555gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing);
556gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);
557
558if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
559gui.devicelist.pos.x = pixel;
560
561if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
562gui.devicelist.pos.y = pixel;
563break;
564
565case HorizontalLayout:
566default:
567gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
568gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);
569
570if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
571gui.devicelist.pos.x = pixel;
572else
573gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
574
575if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
576gui.devicelist.pos.y = pixel;
577else
578gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
579break;
580}
581
582if(getColorForKey("devices_bgcolor", &color, theme))
583gui.devicelist.bgcolor = (color & 0x00FFFFFF);
584
585if(getIntForKey("devices_transparency", &alpha, theme))
586gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
587
588if (gui.devicelist.pixmap)
589{
590 freeWindowBuffer(&gui.devicelist);
591 createWindowBuffer(&gui.devicelist);
592 }
593}
594
595static void loadThemeValues(config_file_t *theme)
596{
597unsigned int screen_width = gui.screen.width;
598unsigned int screen_height = gui.screen.height;
599unsigned int pixel;
600intalpha;// transparency level 0 (obligue) - 255 (transparent)
601uint32_t color;// color value formatted RRGGBB
602int val;
603
604/*
605 * Parse screen parameters
606 */
607if(getColorForKey("screen_bgcolor", &color, theme ))
608gui.screen.bgcolor = (color & 0x00FFFFFF);
609
610if(getIntForKey("screen_textmargin_h", &val, theme))
611gui.screen.hborder = MIN( gui.screen.width , val );
612
613if(getIntForKey("screen_textmargin_v", &val, theme))
614gui.screen.vborder = MIN( gui.screen.height , val );
615
616/*
617 * Parse background parameters
618 */
619if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
620gui.background.pos.x = pixel;
621
622if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
623gui.background.pos.y = pixel;
624
625/*
626 * Parse logo parameters
627 */
628if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
629gui.logo.pos.x = pixel;
630
631if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
632gui.logo.pos.y = pixel;
633
634/*
635 * Parse progress bar parameters
636 */
637if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
638gui.progressbar.pos.x = pixel;
639
640if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
641gui.progressbar.pos.y = pixel;
642
643/*
644 * Parse countdown text parameters
645 */
646if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
647gui.countdown.pos.x = pixel;
648
649if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
650gui.countdown.pos.y = pixel;
651
652 /*
653 * Parse devicelist parameters
654 */
655setupDeviceList(theme);
656
657/*
658 * Parse infobox parameters
659 */
660if(getIntForKey("infobox_width", &val, theme) && val >= 0)
661gui.infobox.width = MIN( screen_width ,(unsigned) val );
662
663if(getIntForKey("infobox_height", &val, theme) && val >= 0)
664gui.infobox.height = MIN( screen_height , (unsigned)val );
665
666if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
667gui.infobox.pos.x = pixel;
668
669if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
670gui.infobox.pos.y = pixel;
671
672if(getIntForKey("infobox_textmargin_h", &val, theme))
673gui.infobox.hborder = MIN( gui.infobox.width , val );
674
675if(getIntForKey("infobox_textmargin_v", &val, theme))
676gui.infobox.vborder = MIN( gui.infobox.height , val );
677
678if(getColorForKey("infobox_bgcolor", &color, theme))
679gui.infobox.bgcolor = (color & 0x00FFFFFF);
680
681if(getIntForKey("infobox_transparency", &alpha, theme))
682gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
683
684/*
685 * Parse menu parameters
686 */
687if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
688gui.menu.width = pixel;
689else
690gui.menu.width = images[iMenuSelection].image->width;
691
692if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
693gui.menu.height = pixel;
694else
695gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;
696
697if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
698gui.menu.pos.x = pixel;
699
700if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
701gui.menu.pos.y = pixel;
702
703if(getIntForKey("menu_textmargin_h", &val, theme))
704gui.menu.hborder = MIN( gui.menu.width , val );
705
706if(getIntForKey("menu_textmargin_v", &val, theme))
707gui.menu.vborder = MIN( gui.menu.height , val );
708
709if(getColorForKey("menu_bgcolor", &color, theme))
710gui.menu.bgcolor = (color & 0x00FFFFFF);
711
712if(getIntForKey("menu_transparency", &alpha, theme))
713gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
714
715/*
716 * Parse bootprompt parameters
717 */
718if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
719gui.bootprompt.width = pixel;
720
721if(getIntForKey("bootprompt_height", &val, theme) && val >= 0)
722gui.bootprompt.height = MIN( screen_height , (unsigned)val );
723
724if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
725gui.bootprompt.pos.x = pixel;
726
727if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
728gui.bootprompt.pos.y = pixel;
729
730if(getIntForKey("bootprompt_textmargin_h", &val, theme) && val >= 0)
731gui.bootprompt.hborder = MIN( gui.bootprompt.width , (unsigned)val );
732
733if(getIntForKey("bootprompt_textmargin_v", &val, theme) && val >= 0)
734gui.bootprompt.vborder = MIN( gui.bootprompt.height , (unsigned)val );
735
736if(getColorForKey("bootprompt_bgcolor", &color, theme))
737gui.bootprompt.bgcolor = (color & 0x00FFFFFF);
738
739if(getIntForKey("bootprompt_transparency", &alpha, theme))
740gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
741
742if(getColorForKey("font_small_color", &color, theme))
743gui.screen.font_small_color = (color & 0x00FFFFFF);
744
745if(getColorForKey("font_console_color", &color, theme))
746gui.screen.font_console_color = (color & 0x00FFFFFF);
747}
748
749#define MAX_tHEME 255
750
751static int randomTheme(char *dirspec, const char **theme) {
752
753long ret, flags, time;
754long long index;
755
756const char * name;
757index = 0;
758uint8_t i=0;
759
760char *list[MAX_tHEME];
761#ifdef EMBED_THEME
762list[i] = "";
763i++;
764#endif
765
766while (i < MAX_tHEME) {
767ret = GetDirEntry(dirspec, &index, &name, &flags, &time);
768if (ret == -1) break;
769
770// Make sure this is a directory.
771if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
772
773if ((unsigned)(strlen(name) + 34) > 256) continue;
774
775if ((list[i] = (char *)malloc(strlen(name))) == NULL) continue;
776
777strcpy(list[i], name);
778
779i++;
780
781}
782
783if (i) {
784
785srand (time18());
786
787*theme = list[(rand() % i)];
788
789
790int ret = startGUI();
791
792uint8_t l=0;
793#ifdef EMBED_THEME
794l++;
795#endif
796while (l<i) {
797free(list[l]);
798l++;
799}
800
801return ret;
802}
803
804return 1;
805
806
807}
808
809int initGUI(void)
810{
811bool dummybool = true;
812getBoolForKey(kGUIKey, &dummybool, &bootInfo->bootConfig);
813if (!dummybool) {
814return 1;
815}
816
817{
818long flags;
819long time;
820long ret = -1;
821
822ret = GetFileInfo("rd(0,0)/Extra/", "Themes", &flags, &time);
823if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
824sprintf(dirsrc, "rd(0,0)/Extra/Themes");
825
826} else {
827ret = GetFileInfo("/Extra/", "Themes", &flags, &time);
828if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
829sprintf(dirsrc, "/Extra/Themes");
830
831} else {
832ret = GetFileInfo("bt(0,0)/Extra/", "Themes", &flags, &time);
833if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
834sprintf(dirsrc, "bt(0,0)/Extra/Themes");
835
836} else {
837printf("Failed to find the /extra/Themes folder\n");
838return 1;
839}
840}
841
842}
843}
844
845int len;
846bool theme_ran= false;
847getBoolForKey("RandomTheme", &theme_ran, &bootInfo->bootConfig);
848int ret = 1;
849
850if (theme_ran) {
851
852ret = randomTheme(dirsrc, &theme_name);
853
854if (ret) printf("randomTheme Failed !! \n");
855
856}
857
858
859if (ret)
860{
861if (getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig ) == true)
862{
863ret = startGUI();
864
865if (ret) printf("Failed to load Theme : %s !! \n", theme_name);
866
867}
868#ifdef EMBED_THEME
869if (ret) {
870theme_name = "";
871ret = startGUI();
872
873if (ret) printf("Failed to load Embed Theme !! \n");
874
875}
876#endif
877if (ret) {
878theme_name = THEME_NAME_DEFAULT;
879ret = startGUI();
880
881if (ret) printf("Failed to load Default Theme : %s !! \n", THEME_NAME_DEFAULT);
882}
883}
884return ret;
885}
886
887static int startGUI(void)
888{
889int val;
890char dirspec[256];
891
892
893if ((unsigned)(strlen(theme_name) + 34) > sizeof(dirspec)) {
894return 1;
895}
896
897sprintf(dirspec, "%s/%s/theme.plist", dirsrc ,theme_name);
898
899if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
900
901#ifdef EMBED_THEME
902if (strlen(theme_name) == 0) {
903config_file_t *config;
904
905config = &bootInfo->themeConfig;
906if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
907return 1;
908}
909}
910#else
911return 1;
912#endif
913 }
914
915if (execute_hook("getResolution_hook", &screen_params[0], &screen_params[1], &screen_params[2], NULL, NULL, NULL) != EFI_SUCCESS)
916{
917// parse display size parameters
918if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) {
919screen_params[0] = val;
920}
921if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) {
922screen_params[1] = val;
923}
924}
925
926
927// Initalizing GUI strucutre.
928bzero(&gui, sizeof(gui_t));
929
930// find best matching vesa mode for our requested width & height
931getGraphicModeParams(screen_params);
932
933// set our screen structure with the mode width & height
934gui.screen.width = screen_params[0];
935gui.screen.height = screen_params[1];
936
937// load graphics otherwise fail and return
938if (loadGraphics(dirsrc) == 0) {
939loadThemeValues(&bootInfo->themeConfig);
940colorFont(&font_small, gui.screen.font_small_color);
941colorFont(&font_console, gui.screen.font_console_color);
942
943// create the screen & window buffers
944if (createBackBuffer(&gui.screen) == 0)
945{
946if (createWindowBuffer(&gui.screen) == 0)
947{
948if (createWindowBuffer(&gui.devicelist) == 0)
949{
950if (createWindowBuffer(&gui.bootprompt) == 0)
951{
952if (createWindowBuffer(&gui.infobox) == 0)
953{
954if (createWindowBuffer(&gui.menu) == 0)
955{
956 gui.logo.draw = true;
957drawBackground();
958// lets copy the screen into the back buffer
959#if UNUSED
960setVideoMode( GRAPHICS_MODE, 0 );
961#else
962setVideoMode( GRAPHICS_MODE );
963#endif
964gui.initialised = true;
965return 0;
966}
967}
968}
969}
970}
971}
972}
973return 1;
974}
975
976static void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected)
977{
978int devicetype;
979
980if( diskIsCDROM(device) )
981devicetype = iDeviceCDROM;// Use CDROM icon
982else
983{
984switch (device->part_type)
985{
986case kPartitionTypeHFS:
987#ifdef BOOT_HELPER_SUPPORT
988// Use HFS or HFSRAID icon depending on bvr flags.
989devicetype = (device->flags & kBVFlagBooter) ? iDeviceHFSRAID : iDeviceHFS;
990#else
991devicetype = iDeviceHFS;
992#endif
993break;
994
995case kPartitionTypeHPFS:
996devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
997break;
998
999case kPartitionTypeFAT16:
1000devicetype = iDeviceFAT16;// Use FAT16 icon
1001break;
1002
1003case kPartitionTypeFAT32:
1004devicetype = iDeviceFAT32;// Use FAT32 icon
1005break;
1006
1007case kPartitionTypeEXT3:
1008devicetype = iDeviceEXT3;// Use EXT2/3 icon
1009break;
1010
1011case kPartitionTypeFreeBSD:
1012devicetype = iDeviceFreeBSD;// Use FreeBSD icon
1013break;
1014
1015case kPartitionTypeOpenBSD:
1016devicetype = iDeviceOpenBSD;// Use OpenBSD icon
1017break;
1018
1019default:
1020devicetype = iDeviceGeneric;// Use Generic icon
1021break;
1022}
1023}
1024
1025// Draw the selection image and use the next (device_*_o) image for the selected item.
1026 if (isSelected)
1027{
1028blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p));
1029devicetype++; // selec override image
1030}
1031
1032// draw icon
1033blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
1034
1035p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
1036
1037// draw volume label
1038drawStrCenteredAt( device->label, &font_small, buffer, p);
1039
1040}
1041
1042void drawDeviceList (int start, int end, int selection)
1043{
1044int i;
1045position_t p, p_prev, p_next;
1046
1047//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
1048
1049fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
1050
1051makeRoundedCorners( gui.devicelist.pixmap);
1052
1053switch (gui.layout)
1054{
1055
1056case VerticalLayout:
1057p.x = (gui.devicelist.width /2);
1058p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
1059
1060// place scroll indicators at top & bottom edges
1061p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
1062p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
1063
1064break;
1065
1066default:// use Horizontal layout as the default
1067
1068case HorizontalLayout:
1069p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
1070p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
1071
1072// place scroll indicators at left & right edges
1073p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
1074p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
1075
1076break;
1077
1078}
1079
1080// draw visible device icons
1081for (i = 0; i < gui.maxdevices; i++)
1082{
1083BVRef param = menuItems[start + i].param;
1084
1085 bool isSelected = ((start + i) == selection) ? true : false;
1086if (isSelected)
1087{
1088 if (param->flags & kBVFlagNativeBoot)
1089 {
1090 infoMenuNativeBoot = true;
1091 }
1092 else
1093 {
1094 infoMenuNativeBoot = false;
1095 if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
1096infoMenuSelection = 0;
1097 }
1098
1099if(gui.menu.draw)
1100drawInfoMenuItems();
1101
1102#if DEBUG
1103 gui.debug.cursor = pos( 10, 100);
1104 dprintf( &gui.screen, "label %s\n", param->label );
1105 dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev );
1106 dprintf( &gui.screen, "width %d\n", gui.screen.width);
1107 dprintf( &gui.screen, "height %d\n", gui.screen.height);
1108 dprintf( &gui.screen, "type 0x%x\n", param->type );
1109 dprintf( &gui.screen, "flags 0x%x\n", param->flags );
1110 dprintf( &gui.screen, "part_no %d\n", param->part_no );
1111 dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff );
1112 dprintf( &gui.screen, "part_type 0x%x\n", param->part_type );
1113 dprintf( &gui.screen, "bps 0x%x\n", param->bps );
1114 dprintf( &gui.screen, "name %s\n", param->name );
1115 dprintf( &gui.screen, "type_name %s\n", param->type_name );
1116 dprintf( &gui.screen, "modtime %d\n", param->modTime );
1117#endif
1118}
1119
1120drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected);
1121
1122if (gui.layout == HorizontalLayout)
1123{
1124p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
1125}
1126if (gui.layout == VerticalLayout)
1127{
1128p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
1129}
1130}
1131
1132// draw prev indicator
1133if(start)
1134blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
1135
1136// draw next indicator
1137if( end < gDeviceCount - 1 )
1138blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
1139
1140gui.redraw = true;
1141
1142updateVRAM();
1143
1144}
1145
1146void clearGraphicBootPrompt()
1147{
1148// clear text buffer
1149prompt[0] = '\0';
1150prompt_pos=0;
1151
1152
1153if(gui.bootprompt.draw == true )
1154{
1155gui.bootprompt.draw = false;
1156gui.redraw = true;
1157// this causes extra frames to be drawn
1158//updateVRAM();
1159}
1160
1161return;
1162}
1163
1164void updateGraphicBootPrompt(int key)
1165{
1166if ( key == kBackspaceKey )
1167prompt[--prompt_pos] = '\0';
1168else
1169{
1170prompt[prompt_pos] = key;
1171prompt_pos++;
1172prompt[prompt_pos] = '\0';
1173}
1174
1175fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
1176
1177makeRoundedCorners( gui.bootprompt.pixmap);
1178
1179position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
1180
1181// print the boot prompt text
1182drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
1183
1184// get the position of the end of the boot prompt text to display user input
1185position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
1186
1187// calculate the position of the cursor
1188intoffset = ( prompt_pos - ( ( gui.bootprompt.width / font_console.chars[0]->width ) - strlen(prompt_text) - 2 ) );
1189
1190if ( offset < 0)
1191offset = 0;
1192
1193drawStr( prompt+offset, &font_console, gui.bootprompt.pixmap, p_prompt);
1194
1195gui.menu.draw = false;
1196gui.bootprompt.draw = true;
1197gui.redraw = true;
1198
1199updateVRAM();
1200
1201return;
1202}
1203
1204#if UNUSED
1205static inline
1206void vramwrite (void *data, int width, int height)
1207#else
1208static inline
1209 void vramwrite (void *data, int width)
1210#endif
1211{
1212if (VIDEO (depth) == 0x20 /*32*/ && VIDEO (rowBytes) == (unsigned long)gui.backbuffer->width * 4)
1213memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
1214else
1215{
1216uint32_t r, g, b;
1217uint32_t i, j;
1218for (i = 0; i < VIDEO (height); i++)
1219for (j = 0; j < VIDEO (width); j++)
1220{
1221b = ((uint8_t *) data)[4*i*width + 4*j];
1222g = ((uint8_t *) data)[4*i*width + 4*j + 1];
1223r = ((uint8_t *) data)[4*i*width + 4*j + 2];
1224switch (VIDEO (depth))
1225{
1226case 32:
1227*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
1228break;
1229case 24:
1230*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
1231| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
1232break;
1233case 16:
1234// Somehow 16-bit is always 15-bits really
1235//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
1236//break;
1237case 15:
1238*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
1239break;
1240default:
1241break;
1242}
1243}
1244}
1245}
1246
1247void updateVRAM()
1248{
1249if (gui.redraw)
1250{
1251if (gui.devicelist.draw)
1252blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
1253
1254if (gui.bootprompt.draw)
1255blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
1256
1257if (gui.menu.draw)
1258blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
1259
1260if (gui.infobox.draw)
1261blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
1262}
1263#if UNUSED
1264vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
1265#else
1266vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width );
1267#endif
1268if (gui.redraw)
1269{
1270memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
1271gui.redraw = false;
1272}
1273}
1274
1275static void
1276sputc(int c, struct putc_info * pi)
1277{
1278 if (pi->last_str)
1279 if (pi->str == pi->last_str) {
1280 *(pi->str) = '\0';
1281 return;
1282 }
1283 *(pi->str)++ = c;
1284}
1285
1286int gprintf( window_t * window, const char * fmt, ...)
1287{
1288char *formattedtext;
1289
1290va_list ap;
1291
1292struct putc_info pi;
1293
1294if ((formattedtext = malloc(1024)) != NULL) {
1295// format the text
1296va_start(ap, fmt);
1297pi.str = formattedtext;
1298pi.last_str = 0;
1299prf(fmt, ap, sputc, &pi);
1300*pi.str = '\0';
1301va_end(ap);
1302
1303position_torigin, cursor, bounds;
1304
1305int i;
1306int character;
1307
1308origin.x = MAX( window->cursor.x, window->hborder );
1309origin.y = MAX( window->cursor.y, window->vborder );
1310
1311bounds.x = ( window->width - window->hborder );
1312bounds.y = ( window->height - window->vborder );
1313
1314cursor = origin;
1315
1316font_t *font = &font_console;
1317
1318for( i=0; i< strlen(formattedtext); i++ )
1319{
1320character = formattedtext[i];
1321
1322character -= 32;
1323
1324// newline ?
1325if( formattedtext[i] == '\n' )
1326{
1327cursor.x = window->hborder;
1328cursor.y += font->height;
1329
1330if ( cursor.y > bounds.y )
1331cursor.y = origin.y;
1332
1333continue;
1334}
1335
1336// tab ?
1337if( formattedtext[i] == '\t' )
1338cursor.x += ( font->chars[0]->width * 5 );
1339
1340// draw the character
1341if( font->chars[character])
1342blend(font->chars[character], window->pixmap, cursor);
1343
1344cursor.x += font->chars[character]->width;
1345
1346// check x pos and do newline
1347if ( cursor.x > bounds.x )
1348{
1349cursor.x = origin.x;
1350cursor.y += font->height;
1351}
1352
1353// check y pos and reset to origin.y
1354if ( cursor.y > bounds.y )
1355cursor.y = origin.y;
1356}
1357
1358// update cursor postition
1359window->cursor = cursor;
1360
1361free(formattedtext);
1362
1363return 0;
1364
1365}
1366return 1;
1367}
1368#if DEBUG
1369static int dprintf( window_t * window, const char * fmt, ...)
1370{
1371char *formattedtext;
1372
1373va_list ap;
1374
1375//window = &gui.debug;
1376
1377struct putc_info pi;
1378
1379if ((formattedtext = malloc(1024)) != NULL) {
1380// format the text
1381va_start(ap, fmt);
1382pi.str = formattedtext;
1383pi.last_str = 0;
1384prf(fmt, ap, sputc, &pi);
1385*pi.str = '\0';
1386va_end(ap);
1387
1388position_torigin, cursor, bounds;
1389
1390int i;
1391int character;
1392
1393origin.x = MAX( gui.debug.cursor.x, window->hborder );
1394origin.y = MAX( gui.debug.cursor.y, window->vborder );
1395
1396bounds.x = ( window->width - window->hborder );
1397bounds.y = ( window->height - window->vborder );
1398
1399cursor = origin;
1400
1401font_t *font = &font_console;
1402
1403for( i=0; i< strlen(formattedtext); i++ )
1404{
1405character = formattedtext[i];
1406
1407character -= 32;
1408
1409// newline ?
1410if( formattedtext[i] == '\n' )
1411{
1412cursor.x = window->hborder;
1413cursor.y += font->height;
1414
1415if ( cursor.y > bounds.y )
1416cursor.y = origin.y;
1417
1418continue;
1419}
1420
1421// tab ?
1422if( formattedtext[i] == '\t' )
1423cursor.x += ( font->chars[0]->width * 5 );
1424
1425// draw the character
1426if( font->chars[character])
1427blend(font->chars[character], gui.backbuffer, cursor);
1428
1429cursor.x += font->chars[character]->width;
1430
1431// check x pos and do newline
1432if ( cursor.x > bounds.x )
1433{
1434cursor.x = origin.x;
1435cursor.y += font->height;
1436}
1437
1438// check y pos and reset to origin.y
1439if ( cursor.y > bounds.y )
1440cursor.y = origin.y;
1441}
1442
1443// update cursor postition
1444gui.debug.cursor = cursor;
1445
1446free(formattedtext);
1447
1448return 0;
1449
1450}
1451return 1;
1452}
1453#endif
1454int vprf(const char * fmt, va_list ap)
1455{
1456int i;
1457int character;
1458
1459char *formattedtext;
1460window_t *window = &gui.screen;
1461struct putc_info pi;
1462
1463position_torigin, cursor, bounds;
1464font_t *font = &font_console;
1465
1466if ((formattedtext = malloc(1024)) != NULL) {
1467// format the text
1468pi.str = formattedtext;
1469pi.last_str = 0;
1470prf(fmt, ap, sputc, &pi);
1471*pi.str = '\0';
1472
1473origin.x = MAX( window->cursor.x, window->hborder );
1474origin.y = MAX( window->cursor.y, window->vborder );
1475bounds.x = ( window->width - ( window->hborder * 2 ) );
1476bounds.y = ( window->height - ( window->vborder * 2 ) );
1477cursor = origin;
1478
1479for( i=0; i< strlen(formattedtext); i++ )
1480{
1481character = formattedtext[i];
1482character -= 32;
1483
1484// newline ?
1485if( formattedtext[i] == '\n' )
1486{
1487cursor.x = window->hborder;
1488cursor.y += font->height;
1489if ( cursor.y > bounds.y )
1490{
1491gui.redraw = true;
1492updateVRAM();
1493cursor.y = window->vborder;
1494}
1495window->cursor.y = cursor.y;
1496continue;
1497}
1498
1499// tab ?
1500if( formattedtext[i] == '\t' )
1501{
1502cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
1503continue;
1504}
1505cursor.x += font->chars[character]->width;
1506
1507// check x pos and do newline
1508if ( cursor.x > bounds.x )
1509{
1510cursor.x = origin.x;
1511cursor.y += font->height;
1512}
1513
1514// check y pos and reset to origin.y
1515if ( cursor.y > ( bounds.y + font->chars[0]->height) )
1516{
1517gui.redraw = true;
1518updateVRAM();
1519cursor.y = window->vborder;
1520}
1521// draw the character
1522if( font->chars[character])
1523blend(font->chars[character], gui.backbuffer, cursor);
1524}
1525// save cursor postition
1526window->cursor.x = cursor.x;
1527updateVRAM();
1528free(formattedtext);
1529return 0;
1530}
1531return 1;
1532}
1533
1534static void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
1535{
1536int i=0;
1537int y=0; // we need this to support multilines '\n'
1538int x=0;
1539
1540for(i=0;i<strlen(ch);i++)
1541{
1542int cha=(int)ch[i];
1543
1544cha-=32;
1545
1546// newline ?
1547if( ch[i] == '\n' )
1548{
1549x = 0;
1550y += font->height;
1551continue;
1552}
1553
1554// tab ?
1555if( ch[i] == '\t' )
1556x+=(font->chars[0]->width*5);
1557
1558if(font->chars[cha])
1559blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
1560
1561x += font->chars[cha]->width;
1562}
1563}
1564
1565static void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
1566{
1567int i = 0;
1568int width = 0;
1569
1570// calculate the width in pixels
1571for(i=0;i<strlen(text);i++)
1572width += font->chars[text[i]-32]->width;
1573
1574p.x = ( p.x - ( width / 2 ) );
1575p.y = ( p.y - ( font->height / 2 ) );
1576
1577if ( p.x == -6 )
1578{
1579p.x = 0;
1580}
1581
1582for(i=0;i<strlen(text);i++)
1583{
1584int cha=(int)text[i];
1585
1586cha-=32;
1587
1588if(font->chars[cha])
1589{
1590blend(font->chars[cha], blendInto, p);
1591p.x += font->chars[cha]->width;
1592}
1593}
1594
1595}
1596
1597static int initFont(font_t *font, image_t *data)
1598{
1599unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
1600
1601int start = 0, end = 0, count = 0, space = 0;
1602
1603bool monospaced = false;
1604
1605font->height = data->image->height;
1606
1607for( x = 0; x < data->image->width; x++)
1608{
1609start = end;
1610
1611// if the pixel is red we've reached the end of the char
1612if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
1613{
1614end = x + 1;
1615
1616if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
1617{
1618font->chars[count]->width = ( end - start) - 1;
1619font->chars[count]->height = font->height;
1620
1621if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
1622{
1623space += ( font->chars[count]->width * data->image->height * 4 );
1624// we skip the first line because there are just the red pixels for the char width
1625for( y = 1; y< (font->height); y++)
1626{
1627for( x2 = (unsigned)start, x3 = 0; x2 < (unsigned)end; x2++, x3++)
1628{
1629pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
1630}
1631}
1632
1633// check if font is monospaced
1634if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
1635monospaced = true;
1636
1637font->width = font->chars[count]->width;
1638
1639count++;
1640}
1641}
1642}
1643}
1644
1645if(monospaced)
1646font->width = 0;
1647
1648return 0;
1649}
1650
1651static void colorFont(font_t *font, uint32_t color)
1652{
1653if( !color )
1654return;
1655
1656int x, y, width, height;
1657int count = 0;
1658pixel_t *buff;
1659
1660while( font->chars[count++] )
1661{
1662width = font->chars[count-1]->width;
1663height = font->chars[count-1]->height;
1664for( y = 0; y < height; y++ )
1665{
1666for( x = 0; x < width; x++ )
1667{
1668buff = &(pixel( font->chars[count-1], x, y ));
1669if( buff->ch.a )
1670{
1671buff->ch.r = (color & 0xFFFF0000) >> 16;
1672buff->ch.g = (color & 0xFF00FF00) >> 8;
1673buff->ch.b = (color & 0xFF0000FF);
1674}
1675}
1676}
1677}
1678}
1679
1680static void makeRoundedCorners(pixmap_t *p)
1681{
1682int x,y;
1683int width=p->width-1;
1684int height=p->height-1;
1685
1686// 10px rounded corner alpha values
1687uint8_t roundedCorner[10][10] =
1688{
1689{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
1690{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
1691{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1692{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1693{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1694{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1695{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1696{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1697{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1698{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
1699};
1700
1701uint8_t alpha=0;
1702
1703for( y=0; y<10; y++)
1704{
1705for( x=0; x<10; x++)
1706{
1707// skip if the pixel should be visible
1708if(roundedCorner[y][x] != 0xFF)
1709{
1710alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
1711// Upper left corner
1712pixel(p, x, y).ch.a = alpha;
1713
1714// upper right corner
1715pixel(p, width-x,y).ch.a = alpha;
1716
1717// lower left corner
1718pixel(p, x, height-y).ch.a = alpha;
1719
1720// lower right corner
1721pixel(p, width-x, height-y).ch.a = alpha;
1722}
1723}
1724}
1725}
1726
1727void showInfoBox(char *title, char *text)
1728{
1729int i, key, lines, visiblelines;
1730
1731int currentline=0;
1732int cnt=0;
1733int offset=0;
1734
1735if( !title || !text )
1736return;
1737
1738position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
1739
1740// calculate number of lines in the title
1741for ( i = 0, lines = 1; i<strlen(title); i++ )
1742if( title[i] == '\n')
1743lines++;
1744
1745// y position of text is lines in title * height of font
1746position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
1747
1748// calculate number of lines in the text
1749for ( i=0, lines = 1; i<strlen(text); i++ )
1750if( text[i] == '\n')
1751lines++;
1752
1753// if text ends with \n strip off
1754if( text[i] == '\n' || text[i] == '\0')
1755lines--;
1756
1757visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
1758
1759// lets display the text and allow scroll thru using up down / arrows
1760while(1)
1761{
1762// move to current line in text
1763for( offset = 0, i = 0; offset < strlen(text); offset++ )
1764{
1765if( currentline == i)
1766break;
1767if( text[offset] =='\n')
1768i++;
1769}
1770
1771// find last visible line in text and place \0
1772for( i = offset, cnt = 0; i < strlen(text); i++)
1773{
1774if(text[i]=='\n')
1775cnt++;
1776if ( cnt == visiblelines )
1777{
1778text[i]='\0';
1779break;
1780}
1781}
1782
1783fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
1784
1785makeRoundedCorners( gui.infobox.pixmap);
1786
1787// print the title if present
1788if( title )
1789drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
1790
1791// print the text
1792drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
1793
1794// restore \n in text
1795if ( cnt == visiblelines )
1796text[i] = '\n';
1797
1798position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
1799
1800// draw prev indicator
1801if(offset)
1802{
1803blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
1804}
1805
1806// draw next indicator
1807if( lines > ( currentline + visiblelines ) )
1808{
1809pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
1810blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
1811}
1812
1813gui.bootprompt.draw = false;
1814gui.infobox.draw = true;
1815gui.redraw = true;
1816
1817updateVRAM();
1818
1819key = getc();
1820
1821if( key == kUpArrowkey )
1822if( currentline > 0 )
1823currentline--;
1824
1825if( key == kDownArrowkey )
1826if( lines > ( currentline + visiblelines ) )
1827currentline++;
1828
1829if( key == kEscapeKey || key == 'q' || key == 'Q')
1830{
1831gui.infobox.draw = false;
1832gui.redraw = true;
1833updateVRAM();
1834break;
1835}
1836}
1837}
1838
1839static void animateProgressBar()
1840{
1841int y;
1842
1843if( time18() > (unsigned) lasttime)
1844{
1845lasttime = time18();
1846
1847pixmap_t *buffBar = images[iProgressBar].image;
1848
1849uint32_t buff = buffBar->pixels[0].value;
1850
1851memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
1852
1853for( y = buffBar->height - 1; y > 0; y--)
1854pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
1855
1856pixel(buffBar, buffBar->width-1, 0).value = buff;
1857}
1858}
1859
1860static void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
1861{
1862if(progress>100)
1863return;
1864
1865p.x = ( p.x - ( width / 2 ) );
1866
1867int todraw = (width * progress) / 100;
1868
1869pixmap_t *buff = images[iProgressBar].image;
1870pixmap_t *buffBG = images[iProgressBarBackground].image;
1871if(!buff || !buffBG)
1872return;
1873
1874pixmap_t progressbar;
1875progressbar.pixels=malloc(width * 4 * buff->height);
1876if(!progressbar.pixels)
1877return;
1878
1879progressbar.width = width;
1880progressbar.height = buff->height;
1881
1882int x=0,x2=0,y=0;
1883
1884for(y=0; y<buff->height; y++)
1885{
1886for(x=0; x<todraw; x++, x2++)
1887{
1888if(x2 == (buff->width-1)) x2=0;
1889pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
1890}
1891x2=0;
1892}
1893
1894for(y=0; y<buff->height; y++)
1895{
1896for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
1897{
1898if(x2 == (buffBG->width -2 )) x2 = 0;
1899pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
1900}
1901if(progress < 100)
1902pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1903if(progress == 0)
1904pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1905x2=0;
1906}
1907
1908blend(&progressbar, blendInto, p);
1909animateProgressBar();
1910free(progressbar.pixels);
1911}
1912
1913static void drawInfoMenuItems()
1914{
1915int i,n;
1916
1917position_t position;
1918
1919pixmap_t *selection = images[iMenuSelection].image;
1920
1921pixmap_t *pbuff;
1922
1923fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
1924
1925makeRoundedCorners(gui.menu.pixmap);
1926
1927uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
1928
1929position = pos(0,0);
1930
1931for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
1932{
1933if (i == infoMenuSelection)
1934{
1935blend(selection, gui.menu.pixmap, position);
1936}
1937
1938pbuff = images[n].image;
1939if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
1940{
1941blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
1942 pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1943}
1944else
1945{
1946blend( pbuff, gui.menu.pixmap,
1947 pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1948}
1949
1950drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
1951pos(position.x + (pbuff->width + gui.menu.hborder),
1952position.y + ((selection->height - font_console.height) / 2)));
1953position.y += images[iMenuSelection].image->height;
1954
1955}
1956
1957gui.redraw = true;
1958}
1959
1960int drawInfoMenu()
1961{
1962drawInfoMenuItems();
1963
1964gui.menu.draw = true;
1965
1966updateVRAM();
1967
1968return 1;
1969}
1970
1971int updateInfoMenu(int key)
1972{
1973switch (key)
1974{
1975
1976case kUpArrowkey:// up arrow
1977if (infoMenuSelection > 0)
1978{
1979if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
1980{
1981infoMenuSelection -= 4;
1982}
1983else
1984{
1985infoMenuSelection--;
1986}
1987drawInfoMenuItems();
1988updateVRAM();
1989
1990}
1991else
1992{
1993
1994gui.menu.draw = false;
1995gui.redraw = true;
1996
1997updateVRAM();
1998
1999return CLOSE_INFO_MENU;
2000}
2001break;
2002
2003case kDownArrowkey:// down arrow
2004if (infoMenuSelection < infoMenuItemsCount - 1)
2005{
2006if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
2007infoMenuSelection += 4;
2008else
2009infoMenuSelection++;
2010drawInfoMenuItems();
2011updateVRAM();
2012}
2013break;
2014
2015case kReturnKey:
2016key = 0;
2017if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
2018showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
2019
2020else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
2021showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
2022
2023else if( infoMenuSelection == MENU_SHOW_HELP )
2024showHelp();
2025
2026else
2027{
2028int buff = infoMenuSelection;
2029infoMenuSelection = 0;
2030return buff;
2031}
2032break;
2033default:
2034break;
2035}
2036return DO_NOT_BOOT;
2037}
2038
2039uint16_t bootImageWidth = 0;
2040uint16_t bootImageHeight = 0;
2041uint8_t *bootImageData = NULL;
2042static bool usePngImage = false;
2043
2044//==========================================================================
2045// loadBootGraphics
2046static void loadBootGraphics(char *src)
2047{
2048if (bootImageData != NULL) {
2049return;
2050}
2051
2052char dirspec[256];
2053
2054if ((unsigned)(strlen(theme_name) + 34) > sizeof(dirspec)) {
2055usePngImage = false;
2056return;
2057}
2058sprintf(dirspec, "%s/%s/boot.png", src, theme_name);
2059if (strlen(theme_name) == 0 || loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
2060#ifdef EMBED_THEME
2061if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
2062#endif
2063usePngImage = false;
2064}
2065}
2066
2067//==========================================================================
2068// drawBootGraphics
2069void drawBootGraphics(void)
2070{
2071int pos;
2072int length;
2073const char *dummyVal;
2074int oldScreenWidth, oldScreenHeight;
2075uint16_t x, y;
2076bool legacy_logo = false;
2077getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig);
2078if (legacy_logo == false) {
2079usePngImage = true;
2080
2081if (bootImageData == NULL)
2082loadBootGraphics(dirsrc);
2083
2084}
2085
2086
2087if (execute_hook("getResolution_hook", &screen_params[0], &screen_params[1], &screen_params[2], NULL, NULL, NULL) != EFI_SUCCESS)
2088{
2089// parse screen size parameters
2090if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) {
2091screen_params[0] = pos;
2092} else {
2093screen_params[0] = DEFAULT_SCREEN_WIDTH;
2094}
2095if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) {
2096screen_params[1] = pos;
2097} else {
2098screen_params[1] = DEFAULT_SCREEN_HEIGHT;
2099}
2100}
2101
2102 // Save current screen resolution.
2103oldScreenWidth = gui.screen.width;
2104oldScreenHeight = gui.screen.height;
2105
2106gui.screen.width = screen_params[0];
2107gui.screen.height = screen_params[1];
2108
2109// find best matching vesa mode for our requested width & height
2110getGraphicModeParams(screen_params);
2111
2112 // Set graphics mode if the booter was in text mode or the screen resolution has changed.
2113if (bootArgs->Video.v_display == VGA_TEXT_MODE
2114|| (screen_params[0] != (uint32_t)oldScreenWidth && screen_params[1] != (uint32_t)oldScreenHeight) )
2115{
2116#if UNUSED
2117setVideoMode(GRAPHICS_MODE, 0);
2118#else
2119setVideoMode(GRAPHICS_MODE);
2120#endif
2121}
2122
2123if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) {
2124drawCheckerBoard();
2125} else {
2126// Fill the background to 75% grey (same as BootX).
2127drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
2128}
2129if ((bootImageData) && (usePngImage)) {
2130x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
2131y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
2132
2133// Draw the image in the center of the display.
2134blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
2135} else {
2136uint8_t *appleBootPict;
2137bootImageData = NULL;
2138bootImageWidth = kAppleBootWidth;
2139bootImageHeight = kAppleBootHeight;
2140
2141// Prepare the data for the default Apple boot image.
2142appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
2143if (appleBootPict) {
2144convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
2145if (bootImageData) {
2146x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
2147y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
2148drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
2149free(bootImageData);
2150}
2151free(appleBootPict);
2152}
2153}
2154}
2155
2156int GUI_initGraphicsMode ()
2157{
2158unsigned long params[4];
2159int count;
2160
2161params[3] = 0;
2162count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
2163
2164// Try to find a resolution if "Graphics Mode" setting is not available.
2165if ( count < 3 )
2166{
2167// Use the default resolution if we don't have an initialized GUI.
2168if (gui.screen.width == 0 || gui.screen.height == 0)
2169{
2170gui.screen.width = DEFAULT_SCREEN_WIDTH;
2171gui.screen.height = DEFAULT_SCREEN_HEIGHT;
2172}
2173
2174params[0] = gui.screen.width;
2175params[1] = gui.screen.height;
2176params[2] = 32;
2177}
2178
2179// Map from pixel format to bits per pixel.
2180
2181if ( params[2] == 256 ) params[2] = 8;
2182if ( params[2] == 555 ) params[2] = 16;
2183if ( params[2] == 888 ) params[2] = 32;
2184
2185#if UNUSED
2186return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
2187#else
2188return setVESAGraphicsMode( params[0], params[1], params[2] );
2189#endif
2190}
2191
2192
2193int GUI_countdown( const char * msg, int row, int timeout )
2194{
2195 unsigned long time;
2196 register int ch = 0;
2197 int col = strlen(msg) + 1;
2198
2199 flushKeyboardBuffer();
2200
2201if( bootArgs->Video.v_display == VGA_TEXT_MODE )
2202{
2203moveCursor( 0, row );
2204printf(msg);
2205
2206} else {
2207
2208position_t p = pos( gui.screen.width / 2 + 1 , ( gui.devicelist.pos.y + 3 ) + ( ( gui.devicelist.height - gui.devicelist.iconspacing ) / 2 ) );
2209
2210char dummy[80];
2211getBootVolumeDescription( gBootVolume, dummy, sizeof(dummy) - 1, true );
2212drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true );
2213drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos );
2214
2215// make this screen the new background
2216memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
2217
2218}
2219
2220int multi_buff = 18 * (timeout);
2221 int multi = ++multi_buff;
2222
2223 int lasttime=0;
2224
2225 for ( time = time18(), timeout++; timeout > 0; )
2226 {
2227if( time18() > (unsigned)lasttime)
2228{
2229multi--;
2230lasttime=time18();
2231}
2232
2233 if ((ch = readKeyboardStatus()))
2234 break;
2235
2236 // Count can be interrupted by holding down shift,
2237 // control or alt key
2238 if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 )
2239{
2240 ch = 1;
2241 break;
2242 }
2243
2244 if ( time18() >= time )
2245 {
2246 time += 18;
2247 timeout--;
2248
2249if( bootArgs->Video.v_display == VGA_TEXT_MODE )
2250{
2251moveCursor( col, row );
2252printf("(%d) ", timeout);
2253}
2254 }
2255
2256if( bootArgs->Video.v_display == GRAPHICS_MODE )
2257{
2258drawProgressBar( gui.screen.pixmap, 100, gui.progressbar.pos , ( multi * 100 / multi_buff ) );
2259gui.redraw = true;
2260updateVRAM();
2261}
2262
2263 }
2264
2265 flushKeyboardBuffer();
2266
2267 return ch;
2268}
2269
2270

Archive Download this file

Revision: 1468