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

Archive Download this file

Revision: 1810