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

Archive Download this file

Revision: 1913