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