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

Archive Download this file

Revision: 1762