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

Archive Download this file

Revision: 1931