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

Archive Download this file

Revision: 1724