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{
1978int cha=(int)ch[i];
1979
1980cha-=32;
1981
1982// newline ?
1983if ( ch[i] == '\n' )
1984{
1985current_pos.x = p.x;
1986current_pos.y += font->height;
1987continue;
1988}
1989
1990// tab ?
1991if ( ch[i] == '\t' )
1992{
1993current_pos.x += TAB_PIXELS_WIDTH;
1994continue;
1995}
1996
1997current_pos = drawChar(ch[i], font, blendInto, current_pos);
1998}
1999}
2000
2001static void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
2002{
2003int i = 0;
2004int width = 0;
2005int max_width = 0;
2006int height = font->height;
2007
2008// calculate the width in pixels
2009for (i=0; i < strlen(text); i++) {
2010if (text[i] == '\n')
2011{
2012width = 0;
2013height += font->height;
2014}
2015else if (text[i] == '\t')
2016width += TAB_PIXELS_WIDTH;
2017else
2018{
2019pixmap_t* pm = charToPixmap(text[i], font);
2020if (pm)
2021width += pm->width;
2022}
2023if (width > max_width)
2024max_width = width;
2025}
2026
2027p.x = ( p.x - ( max_width / 2 ) );
2028p.y = ( p.y - ( height / 2 ) );
2029
2030drawStr(text, font, blendInto, p);
2031}
2032
2033static int destroyFont(font_t *font)
2034{
2035int i;
2036 for (i = 0; i < CHARACTERS_COUNT; i++)
2037 {
2038if (font->chars[i])
2039{
2040if (font->chars[i]->pixels) free (font->chars[i]->pixels);
2041free (font->chars[i]);
2042font->chars[i] = 0;
2043}
2044 }
2045 return 0;
2046}
2047
2048static int initFont(font_t *font, image_t *data)
2049{
2050unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
2051
2052int start = 0, end = 0, count = 0, space = 0;
2053
2054bool monospaced = false;
2055
2056font->height = data->image->height;
2057
2058for( x = 0; x < data->image->width && count < CHARACTERS_COUNT; x++)
2059{
2060start = end;
2061
2062// if the pixel is red we've reached the end of the char
2063if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
2064{
2065end = x + 1;
2066
2067if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
2068{
2069font->chars[count]->width = ( end - start) - 1;
2070font->chars[count]->height = font->height;
2071
2072if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
2073{
2074space += ( font->chars[count]->width * data->image->height * 4 );
2075// we skip the first line because there are just the red pixels for the char width
2076for( y = 1; y< (font->height); y++)
2077{
2078for( x2 = (unsigned)start, x3 = 0; x2 < (unsigned)end; x2++, x3++)
2079{
2080pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
2081}
2082}
2083
2084// check if font is monospaced
2085if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
2086monospaced = true;
2087
2088font->width = font->chars[count]->width;
2089
2090count++;
2091}
2092}
2093}
2094}
2095
2096for (x = count; x < CHARACTERS_COUNT; x++)
2097font->chars[x] = NULL;
2098
2099if(monospaced)
2100font->width = 0;
2101
2102font->count = count;
2103
2104return 0;
2105}
2106
2107static void colorFont(font_t *font, uint32_t color)
2108{
2109if( !color )
2110return;
2111
2112int x, y, width, height;
2113int count = 0;
2114pixel_t *buff;
2115
2116while( font->chars[count++] )
2117{
2118width = font->chars[count-1]->width;
2119height = font->chars[count-1]->height;
2120for( y = 0; y < height; y++ )
2121{
2122for( x = 0; x < width; x++ )
2123{
2124buff = &(pixel( font->chars[count-1], x, y ));
2125if( buff->ch.a )
2126{
2127buff->ch.r = (color & 0xFFFF0000) >> 16;
2128buff->ch.g = (color & 0xFF00FF00) >> 8;
2129buff->ch.b = (color & 0xFF0000FF);
2130}
2131}
2132}
2133}
2134}
2135
2136static void makeRoundedCorners(pixmap_t *p)
2137{
2138int x,y;
2139int width=p->width-1;
2140int height=p->height-1;
2141
2142// 10px rounded corner alpha values
2143uint8_t roundedCorner[10][10] =
2144{
2145{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
2146{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
2147{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2148{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2149{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2150{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2151{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2152{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2153{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
2154{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
2155};
2156
2157uint8_t alpha=0;
2158
2159for( y=0; y<10; y++)
2160{
2161for( x=0; x<10; x++)
2162{
2163// skip if the pixel should be visible
2164if(roundedCorner[y][x] != 0xFF)
2165{
2166alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
2167// Upper left corner
2168pixel(p, x, y).ch.a = alpha;
2169
2170// upper right corner
2171pixel(p, width-x,y).ch.a = alpha;
2172
2173// lower left corner
2174pixel(p, x, height-y).ch.a = alpha;
2175
2176// lower right corner
2177pixel(p, width-x, height-y).ch.a = alpha;
2178}
2179}
2180}
2181}
2182
2183void showInfoBox(char *title, char *text)
2184{
2185int i, key, lines, visiblelines;
2186
2187int currentline=0;
2188int cnt=0;
2189int offset=0;
2190
2191if( !title || !text )
2192return;
2193
2194position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
2195
2196// calculate number of lines in the title
2197for ( i = 0, lines = 1; i<strlen(title); i++ )
2198if( title[i] == '\n')
2199lines++;
2200
2201// y position of text is lines in title * height of font
2202position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
2203
2204// calculate number of lines in the text
2205for ( i=0, lines = 1; i<strlen(text); i++ )
2206if( text[i] == '\n')
2207lines++;
2208
2209// if text ends with \n strip off
2210if( text[i] == '\n' || text[i] == '\0')
2211lines--;
2212
2213visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
2214
2215// lets display the text and allow scroll thru using up down / arrows
2216while(1)
2217{
2218// move to current line in text
2219for( offset = 0, i = 0; offset < strlen(text); offset++ )
2220{
2221if( currentline == i)
2222break;
2223if( text[offset] =='\n')
2224i++;
2225}
2226
2227// find last visible line in text and place \0
2228for( i = offset, cnt = 0; i < strlen(text); i++)
2229{
2230if(text[i]=='\n')
2231cnt++;
2232if ( cnt == visiblelines )
2233{
2234text[i]='\0';
2235break;
2236}
2237}
2238
2239fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
2240
2241makeRoundedCorners( gui.infobox.pixmap);
2242
2243// print the title if present
2244if( title )
2245drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
2246
2247// print the text
2248drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
2249
2250// restore \n in text
2251if ( cnt == visiblelines )
2252text[i] = '\n';
2253
2254position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
2255
2256// draw prev indicator
2257if(offset)
2258{
2259blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
2260}
2261
2262// draw next indicator
2263if( lines > ( currentline + visiblelines ) )
2264{
2265pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
2266blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
2267}
2268
2269gui.bootprompt.draw = false;
2270gui.infobox.draw = true;
2271gui.redraw = true;
2272
2273updateVRAM();
2274
2275key = getc();
2276
2277if( key == kUpArrowkey )
2278if( currentline > 0 )
2279currentline--;
2280
2281if( key == kDownArrowkey )
2282if( lines > ( currentline + visiblelines ) )
2283currentline++;
2284
2285if( key == kEscapeKey || key == 'q' || key == 'Q')
2286{
2287gui.infobox.draw = false;
2288gui.redraw = true;
2289updateVRAM();
2290break;
2291}
2292}
2293}
2294
2295static void animateProgressBar()
2296{
2297int y;
2298
2299if( time18() > (unsigned) lasttime)
2300{
2301lasttime = time18();
2302
2303pixmap_t *buffBar = images[iProgressBar].image;
2304
2305uint32_t buff = buffBar->pixels[0].value;
2306
2307memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
2308
2309for( y = buffBar->height - 1; y > 0; y--)
2310pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
2311
2312pixel(buffBar, buffBar->width-1, 0).value = buff;
2313}
2314}
2315
2316static void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
2317{
2318if(progress>100)
2319return;
2320
2321p.x = ( p.x - ( width / 2 ) );
2322
2323int todraw = (width * progress) / 100;
2324
2325pixmap_t *buff = images[iProgressBar].image;
2326pixmap_t *buffBG = images[iProgressBarBackground].image;
2327if(!buff || !buffBG)
2328return;
2329
2330pixmap_t progressbar;
2331progressbar.pixels=malloc(width * 4 * buff->height);
2332if(!progressbar.pixels)
2333return;
2334
2335progressbar.width = width;
2336progressbar.height = buff->height;
2337
2338int x=0,x2=0,y=0;
2339
2340for(y=0; y<buff->height; y++)
2341{
2342for(x=0; x<todraw; x++, x2++)
2343{
2344if(x2 == (buff->width-1)) x2=0;
2345pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
2346}
2347x2=0;
2348}
2349
2350for(y=0; y<buff->height; y++)
2351{
2352for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
2353{
2354if(x2 == (buffBG->width -2 )) x2 = 0;
2355pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
2356}
2357if(progress < 100)
2358pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
2359if(progress == 0)
2360pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
2361x2=0;
2362}
2363
2364blend(&progressbar, blendInto, p);
2365animateProgressBar();
2366free(progressbar.pixels);
2367}
2368
2369static void drawInfoMenuItems()
2370{
2371int i,n;
2372
2373position_t position;
2374
2375pixmap_t *selection = images[iMenuSelection].image;
2376
2377pixmap_t *pbuff;
2378
2379fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
2380
2381makeRoundedCorners(gui.menu.pixmap);
2382
2383uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
2384
2385position = pos(0,0);
2386
2387for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
2388{
2389if (i == infoMenuSelection)
2390{
2391blend(selection, gui.menu.pixmap, position);
2392}
2393
2394pbuff = images[n].image;
2395if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
2396{
2397blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
2398 pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
2399}
2400else
2401{
2402blend( pbuff, gui.menu.pixmap,
2403 pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
2404}
2405
2406drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
2407pos(position.x + (pbuff->width + gui.menu.hborder),
2408position.y + ((selection->height - font_console.height) / 2)));
2409position.y += images[iMenuSelection].image->height;
2410
2411}
2412
2413gui.redraw = true;
2414}
2415
2416int drawInfoMenu()
2417{
2418drawInfoMenuItems();
2419
2420gui.menu.draw = true;
2421
2422updateVRAM();
2423
2424return 1;
2425}
2426
2427int updateInfoMenu(int key)
2428{
2429switch (key)
2430{
2431
2432case kUpArrowkey:// up arrow
2433if (infoMenuSelection > 0)
2434{
2435if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
2436{
2437infoMenuSelection -= 4;
2438}
2439else
2440{
2441infoMenuSelection--;
2442}
2443drawInfoMenuItems();
2444updateVRAM();
2445
2446}
2447else
2448{
2449
2450gui.menu.draw = false;
2451gui.redraw = true;
2452
2453updateVRAM();
2454
2455return CLOSE_INFO_MENU;
2456}
2457break;
2458
2459case kDownArrowkey:// down arrow
2460if (infoMenuSelection < infoMenuItemsCount - 1)
2461{
2462if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
2463infoMenuSelection += 4;
2464else
2465infoMenuSelection++;
2466drawInfoMenuItems();
2467updateVRAM();
2468}
2469break;
2470
2471case kReturnKey:
2472key = 0;
2473if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
2474showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
2475
2476else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
2477showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
2478
2479else if( infoMenuSelection == MENU_SHOW_HELP )
2480showHelp();
2481
2482else
2483{
2484int buff = infoMenuSelection;
2485infoMenuSelection = 0;
2486return buff;
2487}
2488break;
2489default:
2490break;
2491}
2492return DO_NOT_BOOT;
2493}
2494
2495uint16_t bootImageWidth = 0;
2496uint16_t bootImageHeight = 0;
2497uint8_t *bootImageData = NULL;
2498static bool usePngImage = false;
2499
2500//==========================================================================
2501// loadBootGraphics
2502static void loadBootGraphics(char *src)
2503{
2504if (bootImageData != NULL) {
2505return;
2506}
2507
2508char dirspec[256];
2509
2510if ((unsigned)(strlen(theme_name) + 34) > sizeof(dirspec)) {
2511usePngImage = false;
2512return;
2513}
2514sprintf(dirspec, "%s/%s/boot.png", src, theme_name);
2515if (strlen(theme_name) == 0 || loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
2516#ifdef EMBED_THEME
2517if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
2518#endif
2519usePngImage = false;
2520}
2521}
2522
2523//==========================================================================
2524// drawBootGraphics
2525void drawBootGraphics(void)
2526{
2527int pos;
2528int length;
2529const char *dummyVal;
2530int oldScreenWidth, oldScreenHeight;
2531uint16_t x, y;
2532bool legacy_logo = false;
2533getBoolForKey("Legacy Logo", &legacy_logo, DEFAULT_BOOT_CONFIG);
2534if (legacy_logo == false) {
2535usePngImage = true;
2536
2537if (bootImageData == NULL)
2538loadBootGraphics(dirsrc);
2539
2540}
2541
2542
2543if (execute_hook("getResolution_hook", &screen_params[0], &screen_params[1], &screen_params[2], NULL, NULL, NULL) != EFI_SUCCESS)
2544{
2545// parse screen size parameters
2546if (getIntForKey("boot_width", &pos, &themeConfig) && pos > 0) {
2547screen_params[0] = pos;
2548} else {
2549screen_params[0] = DEFAULT_SCREEN_WIDTH;
2550}
2551if (getIntForKey("boot_height", &pos, &themeConfig) && pos > 0) {
2552screen_params[1] = pos;
2553} else {
2554screen_params[1] = DEFAULT_SCREEN_HEIGHT;
2555}
2556}
2557
2558 // Save current screen resolution.
2559oldScreenWidth = gui.screen.width;
2560oldScreenHeight = gui.screen.height;
2561
2562gui.screen.width = screen_params[0];
2563gui.screen.height = screen_params[1];
2564
2565// find best matching vesa mode for our requested width & height
2566getGraphicModeParams(screen_params);
2567
2568 // Set graphics mode if the booter was in text mode or the screen resolution has changed.
2569if (getVideoMode() == VGA_TEXT_MODE
2570|| (screen_params[0] != (uint32_t)oldScreenWidth && screen_params[1] != (uint32_t)oldScreenHeight) )
2571{
2572#if UNUSED
2573setVideoMode(GRAPHICS_MODE, 0);
2574#else
2575setVideoMode(GRAPHICS_MODE);
2576#endif
2577}
2578
2579if (getValueForKey("-checkers", &dummyVal, &length, DEFAULT_BOOT_CONFIG)) {
2580drawCheckerBoard();
2581} else {
2582// Fill the background to 75% grey (same as BootX).
2583drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
2584}
2585if ((bootImageData) && (usePngImage)) {
2586x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
2587y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
2588
2589// Draw the image in the center of the display.
2590blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
2591} else {
2592uint8_t *appleBootPict;
2593bootImageData = NULL;
2594bootImageWidth = kAppleBootWidth;
2595bootImageHeight = kAppleBootHeight;
2596
2597// Prepare the data for the default Apple boot image.
2598appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
2599if (appleBootPict) {
2600convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
2601if (bootImageData) {
2602x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
2603y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
2604drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
2605free(bootImageData);
2606}
2607free(appleBootPict);
2608}
2609}
2610}
2611
2612int GUI_initGraphicsMode (void)
2613{
2614unsigned long params[4];
2615int count;
2616
2617params[3] = 0;
2618count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
2619
2620// Try to find a resolution if "Graphics Mode" setting is not available.
2621if ( count < 3 )
2622{
2623// Use the default resolution if we don't have an initialized GUI.
2624if (gui.screen.width == 0 || gui.screen.height == 0)
2625{
2626gui.screen.width = DEFAULT_SCREEN_WIDTH;
2627gui.screen.height = DEFAULT_SCREEN_HEIGHT;
2628}
2629
2630params[0] = gui.screen.width;
2631params[1] = gui.screen.height;
2632params[2] = 32;
2633}
2634
2635// Map from pixel format to bits per pixel.
2636
2637if ( params[2] == 256 ) params[2] = 8;
2638if ( params[2] == 555 ) params[2] = 16;
2639if ( params[2] == 888 ) params[2] = 32;
2640
2641#if UNUSED
2642return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
2643#else
2644return setVESAGraphicsMode( params[0], params[1], params[2] );
2645#endif
2646}
2647
2648
2649int GUI_countdown( const char * msg, int row, int timeout , int *optionKey)
2650{
2651 unsigned long time;
2652 register int ch = 0;
2653 int col = strlen(msg) + 1;
2654
2655 flushKeyboardBuffer();
2656
2657if( getVideoMode() == VGA_TEXT_MODE )
2658{
2659moveCursor( 0, row );
2660printf(msg);
2661
2662} else {
2663
2664position_t p = pos( gui.screen.width / 2 + 1 , ( gui.devicelist.pos.y + 3 ) + ( ( gui.devicelist.height - gui.devicelist.iconspacing ) / 2 ) );
2665
2666char dummy[80];
2667getBootVolumeDescription( gBootVolume, dummy, sizeof(dummy) - 1, true );
2668drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true );
2669drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos );
2670
2671// make this screen the new background
2672memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
2673
2674}
2675
2676int multi_buff = 18 * (timeout);
2677 int multi = ++multi_buff;
2678
2679 int lasttime=0;
2680
2681 for ( time = time18(), timeout++; timeout > 0; )
2682 {
2683
2684if( time18() > (unsigned)lasttime)
2685{
2686multi--;
2687lasttime=time18();
2688}
2689
2690 if ((ch = readKeyboardStatus())){
2691 *optionKey = ch;
2692 break;
2693}
2694
2695 // Count can be interrupted by holding down shift,
2696 // control or alt key
2697 if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 )
2698{
2699 ch = 1;
2700 break;
2701 }
2702
2703 if ( time18() >= time )
2704 {
2705 time += 18;
2706 timeout--;
2707
2708if( getVideoMode() == VGA_TEXT_MODE )
2709{
2710moveCursor( col, row );
2711printf("(%d) ", timeout);
2712}
2713 }
2714
2715if( getVideoMode() == GRAPHICS_MODE )
2716{
2717drawProgressBar( gui.screen.pixmap, 100, gui.progressbar.pos , ( multi * 100 / multi_buff ) );
2718gui.redraw = true;
2719updateVRAM();
2720}
2721
2722 }
2723
2724 flushKeyboardBuffer();
2725
2726 return ch;
2727}
2728
2729
2730

Archive Download this file

Revision: 1899