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

Archive Download this file

Revision: 1735