Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/Chameleon/i386/boot2/gui.c

Source at commit 307 created 12 years 11 months ago.
By ifabio, merge changes from trunk (929). Also merge the module changes from Azimutz branche (fix compile error) Also edited the info.plist into AHCIPortInjector.kext: http://forum.voodooprojects.org/index.php/topic,1170.0.html
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#include "gui.h"
12#include "appleboot.h"
13#include "vers.h"
14
15#define IMG_REQUIRED -1
16#define THEME_NAME_DEFAULT"Default"
17static const char *theme_name = THEME_NAME_DEFAULT;
18
19#ifdef CONFIG_EMBED_THEME
20#include "art.h"
21#endif
22
23#define LOADPNG(img, alt_img) if (loadThemeImage(#img, alt_img) != 0) { return 1; }
24
25#define MIN(x, y) ((x) < (y) ? (x) : (y))
26#define MAX(x, y) ((x) > (y) ? (x) : (y))
27
28#define VIDEO(x) (bootArgs->Video.v_ ## x)
29
30#define vram VIDEO(baseAddr)
31
32int lasttime = 0; // we need this for animating maybe
33
34extern int gDeviceCount;
35
36
37/*
38 * ATTENTION: the enum and the following array images[] MUST match !!!
39 */
40enum {
41 iBackground = 0,
42 iLogo,
43
44 iDeviceGeneric,
45 iDeviceGeneric_o,
46 iDeviceHFS,
47 iDeviceHFS_o,
48 iDeviceHFSRAID,
49 iDeviceHFSRAID_o,
50 iDeviceEXT3,
51 iDeviceEXT3_o,
52 iDeviceFreeBSD,/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
53 iDeviceFreeBSD_o,/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
54 iDeviceOpenBSD,/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
55 iDeviceOpenBSD_o,/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
56 iDeviceFAT,
57 iDeviceFAT_o,
58 iDeviceFAT16,
59 iDeviceFAT16_o,
60 iDeviceFAT32,
61 iDeviceFAT32_o,
62 iDeviceNTFS,
63 iDeviceNTFS_o,
64 iDeviceBEFS,/* Haiku detection and Icon credits to scorpius */
65 iDeviceBEFS_o,/* Haiku detection and Icon credits to scorpius */
66 iDeviceCDROM,
67 iDeviceCDROM_o,
68
69 iSelection,
70 iDeviceScrollPrev,
71 iDeviceScrollNext,
72
73 iMenuBoot,
74 iMenuVerbose,
75 iMenuIgnoreCaches,
76 iMenuSingleUser,
77 iMenuMemoryInfo,
78 iMenuVideoInfo,
79 iMenuHelp,
80 iMenuVerboseDisabled,
81 iMenuIgnoreCachesDisabled,
82 iMenuSingleUserDisabled,
83 iMenuSelection,
84
85 iProgressBar,
86 iProgressBarBackground,
87
88 iTextScrollPrev,
89 iTextScrollNext,
90
91 iFontConsole,
92 iFontSmall,
93};
94
95image_t images[] = {
96 {.name = "background", .image = NULL},
97 {.name = "logo", .image = NULL},
98
99 {.name = "device_generic", .image = NULL},
100 {.name = "device_generic_o", .image = NULL},
101 {.name = "device_hfsplus", .image = NULL},
102 {.name = "device_hfsplus_o", .image = NULL},
103 {.name = "device_hfsraid", .image = NULL},
104 {.name = "device_hfsraid_o", .image = NULL},
105 {.name = "device_ext3", .image = NULL},
106 {.name = "device_ext3_o", .image = NULL},
107 {.name = "device_freebsd", .image = NULL},/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
108 {.name = "device_freebsd_o", .image = NULL},/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
109 {.name = "device_openbsd", .image = NULL},/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
110 {.name = "device_openbsd_o", .image = NULL},/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
111 {.name = "device_fat", .image = NULL},
112 {.name = "device_fat_o", .image = NULL},
113 {.name = "device_fat16", .image = NULL},
114 {.name = "device_fat16_o", .image = NULL},
115 {.name = "device_fat32", .image = NULL},
116 {.name = "device_fat32_o", .image = NULL},
117 {.name = "device_ntfs", .image = NULL},
118 {.name = "device_ntfs_o", .image = NULL},
119 {.name = "device_befs", .image = NULL},/* Haiku detection and Icon credits to scorpius */
120 {.name = "device_befs_o", .image = NULL},/* Haiku detection and Icon credits to scorpius */
121 {.name = "device_cdrom", .image = NULL},
122 {.name = "device_cdrom_o", .image = NULL},
123
124 {.name = "device_selection", .image = NULL},
125 {.name = "device_scroll_prev", .image = NULL},
126 {.name = "device_scroll_next", .image = NULL},
127
128 {.name = "menu_boot", .image = NULL},
129 {.name = "menu_verbose", .image = NULL},
130 {.name = "menu_ignore_caches", .image = NULL},
131 {.name = "menu_single_user", .image = NULL},
132 {.name = "menu_memory_info", .image = NULL},
133 {.name = "menu_video_info", .image = NULL},
134 {.name = "menu_help", .image = NULL},
135 {.name = "menu_verbose_disabled", .image = NULL},
136 {.name = "menu_ignore_caches_disabled", .image = NULL},
137 {.name = "menu_single_user_disabled", .image = NULL},
138 {.name = "menu_selection", .image = NULL},
139
140 {.name = "progress_bar", .image = NULL},
141 {.name = "progress_bar_background", .image = NULL},
142
143 {.name = "text_scroll_prev", .image = NULL},
144 {.name = "text_scroll_next", .image = NULL},
145
146 {.name = "font_console", .image = NULL},
147 {.name = "font_small", .image = NULL},
148};
149
150int imageCnt = 0;
151
152extern intgDeviceCount;
153extern intselectIndex;
154
155extern MenuItem *menuItems;
156
157char prompt[BOOT_STRING_LEN];
158
159int prompt_pos=0;
160
161char prompt_text[] = "boot: ";
162
163menuitem_t infoMenuItems[] =
164{
165{ .text = "Boot" },
166{ .text = "Boot Verbose" },
167{ .text = "Boot Ignore Caches" },
168{ .text = "Boot Single User" },
169{ .text = "Memory Info" },
170{ .text = "Video Info" },
171{ .text = "Help" }
172};
173
174int initFont(font_t *font, image_t *image);
175void colorFont(font_t *font, uint32_t color);
176void makeRoundedCorners(pixmap_t *p);
177
178static int infoMenuSelection = 0;
179static int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);
180
181static bool infoMenuNativeBoot = false;
182
183// here we store the used screen resolution
184static unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0};
185
186static int getImageIndexByName(const char *name)
187{
188 int i;
189for (i = 0; i < sizeof(images) / sizeof(images[0]); i++)
190{
191 if (strcmp(name, images[i].name) == 0)
192 return i; // found the name
193}
194return -1;
195}
196
197#ifdef CONFIG_EMBED_THEME
198static int getEmbeddedImageIndexByName(const char *name)
199{
200int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1;
201int lowerLimit = 0;
202int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint
203int result;
204
205// NOTE: This algorithm assumes that the embedded images are sorted.
206// This is currently done using the make file. If the array is
207// generated manualy, this *will* fail to work properly.
208while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)
209{
210if (result > 0)// We need to search a HIGHER index
211{
212if (compareIndex != lowerLimit)
213{
214lowerLimit = compareIndex;
215}
216else
217{
218return -1;
219}
220compareIndex = (upperLimit + lowerLimit + 1) >> 1;// Midpoint, round up
221}
222else // We Need to search a LOWER index
223{
224if (compareIndex != upperLimit)
225{
226upperLimit = compareIndex;
227}
228else
229{
230return -1;
231}
232compareIndex = (upperLimit + lowerLimit) >> 1;// Midpoint, round down
233}
234}
235return compareIndex;
236}
237#endif
238
239static int loadThemeImage(const char *image, int alt_image)
240{
241chardirspec[256];
242int i;
243#ifdef CONFIG_EMBED_THEME
244int e;
245#endif
246uint16_twidth;
247uint16_theight;
248uint8_t*imagedata;
249
250if ((strlen(image) + strlen(theme_name) + 20 ) > sizeof(dirspec)) {
251return 1;
252}
253
254 if ((i = getImageIndexByName(image)) >= 0)
255 {
256 if (images[i].image == NULL) {
257 images[i].image = malloc(sizeof(pixmap_t));
258 }
259 sprintf(dirspec, "/Extra/Themes/%s/%s.png", theme_name, image);
260 width = 0;
261 height = 0;
262 imagedata = NULL;
263 if ((loadPngImage(dirspec, &width, &height, &imagedata)) == 0)
264 {
265 images[i].image->width = width;
266 images[i].image->height = height;
267 images[i].image->pixels = (pixel_t *)imagedata;
268 flipRB(images[i].image);
269 return 0;
270 }
271#ifdef CONFIG_EMBED_THEME
272 else if ((e = getEmbeddedImageIndexByName(image)) >= 0)
273 {
274 unsigned char *embed_data;
275 unsigned int embed_size;
276 embed_data = embeddedImages[e].pngdata;
277 embed_size = *embeddedImages[e].length;
278
279 if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0)
280 {
281 images[i].image->width = width;
282 images[i].image->height = height;
283 images[i].image->pixels = (pixel_t *)imagedata;
284 flipRB(images[i].image);
285 return 0;
286 }
287
288 return 0;
289 }
290#endif
291 else if (alt_image != IMG_REQUIRED && images[alt_image].image->pixels != NULL)
292 {
293 // Using the passed alternate image for non-mandatory images.
294 // We don't clone the already existing pixmap, but using its properties instead!
295 images[i].image->width = images[alt_image].image->width;
296 images[i].image->height = images[alt_image].image->height;
297 images[i].image->pixels = images[alt_image].image->pixels;
298 return 0;
299 }
300 else
301 {
302#ifndef CONFIG_EMBED_THEME
303 printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);
304sleep(2);
305#endif
306 return 1;
307 }
308 }
309return 1;
310}
311
312static int loadGraphics(void)
313{
314LOADPNG(background, IMG_REQUIRED);
315LOADPNG(logo, IMG_REQUIRED);
316
317LOADPNG(device_generic, IMG_REQUIRED);
318LOADPNG(device_generic_o, iDeviceGeneric);
319LOADPNG(device_hfsplus, iDeviceGeneric);
320LOADPNG(device_hfsplus_o, iDeviceHFS);
321LOADPNG(device_hfsraid, iDeviceGeneric);
322LOADPNG(device_hfsraid_o, iDeviceHFSRAID);
323LOADPNG(device_ext3, iDeviceGeneric);
324LOADPNG(device_ext3_o, iDeviceEXT3);
325LOADPNG(device_freebsd, iDeviceGeneric);/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
326LOADPNG(device_freebsd_o, iDeviceFreeBSD);/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
327LOADPNG(device_openbsd, iDeviceGeneric);/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
328LOADPNG(device_openbsd_o, iDeviceOpenBSD);/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
329LOADPNG(device_fat, iDeviceGeneric);
330LOADPNG(device_fat_o, iDeviceFAT);
331LOADPNG(device_fat16, iDeviceFAT);
332LOADPNG(device_fat16_o, iDeviceFAT_o);
333LOADPNG(device_fat32, iDeviceFAT);
334LOADPNG(device_fat32_o, iDeviceFAT_o);
335LOADPNG(device_ntfs, iDeviceGeneric);
336LOADPNG(device_ntfs_o, iDeviceNTFS);
337LOADPNG(device_befs, iDeviceGeneric);/* Haiku detection and Icon credits to scorpius */
338LOADPNG(device_befs_o, iDeviceBEFS);/* Haiku detection and Icon credits to scorpius */
339LOADPNG(device_cdrom, iDeviceGeneric);
340LOADPNG(device_cdrom_o, iDeviceCDROM);
341
342LOADPNG(device_selection, IMG_REQUIRED);
343LOADPNG(device_scroll_prev, IMG_REQUIRED);
344LOADPNG(device_scroll_next, IMG_REQUIRED);
345
346LOADPNG(menu_boot, IMG_REQUIRED);
347LOADPNG(menu_verbose, IMG_REQUIRED);
348LOADPNG(menu_ignore_caches, IMG_REQUIRED);
349LOADPNG(menu_single_user, IMG_REQUIRED);
350LOADPNG(menu_memory_info, IMG_REQUIRED);
351LOADPNG(menu_video_info, IMG_REQUIRED);
352LOADPNG(menu_help, IMG_REQUIRED);
353LOADPNG(menu_verbose_disabled, IMG_REQUIRED);
354LOADPNG(menu_ignore_caches_disabled, IMG_REQUIRED);
355LOADPNG(menu_single_user_disabled, IMG_REQUIRED);
356LOADPNG(menu_selection, IMG_REQUIRED);
357
358LOADPNG(progress_bar, IMG_REQUIRED);
359LOADPNG(progress_bar_background, IMG_REQUIRED);
360
361LOADPNG(text_scroll_prev, IMG_REQUIRED);
362LOADPNG(text_scroll_next, IMG_REQUIRED);
363
364LOADPNG(font_console, IMG_REQUIRED);
365LOADPNG(font_small, IMG_REQUIRED);
366
367initFont( &font_console, &images[iFontConsole]);
368initFont( &font_small, &images[iFontSmall]);
369
370return 0;
371}
372
373pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )
374{
375
376pixmap_t *cropped = malloc( sizeof( pixmap_t ) );
377if( !cropped )
378return 0;
379cropped->pixels = malloc( width * height * 4 );
380if ( !cropped->pixels )
381return 0;
382
383cropped->width = width;
384cropped->height = height;
385
386int destx = 0, desty = 0;
387int srcx = pos.x, srcy = pos.y;
388
389for( ; desty < height; desty++, srcy++)
390{
391for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )
392{
393pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;
394}
395}
396return cropped;
397}
398
399int createBackBuffer( window_t *window )
400{
401gui.backbuffer = malloc(sizeof(pixmap_t));
402if(!gui.backbuffer)
403return 1;
404
405gui.backbuffer->pixels = malloc( window->width * window->height * 4 );
406if(!gui.backbuffer->pixels)
407{
408free(gui.backbuffer);
409gui.backbuffer = 0;
410return 1;
411}
412
413gui.backbuffer->width = gui.screen.width;
414gui.backbuffer->height = gui.screen.height;
415
416return 0;
417}
418
419int createWindowBuffer( window_t *window )
420{
421window->pixmap = malloc(sizeof(pixmap_t));
422if(!window->pixmap)
423return 1;
424
425window->pixmap->pixels = malloc( window->width * window->height * 4 );
426if(!window->pixmap->pixels)
427{
428free(window->pixmap);
429window->pixmap = 0;
430return 1;
431}
432
433window->pixmap->width = window->width;
434window->pixmap->height = window->height;
435
436return 0;
437}
438
439int freeWindowBuffer( window_t *window )
440{
441if (window->pixmap && window->pixmap->pixels)
442 {
443free(window->pixmap->pixels);
444free(window->pixmap);
445return 0;
446}
447
448return 1;
449}
450
451void fillPixmapWithColor(pixmap_t *pm, uint32_t color)
452{
453int x,y;
454
455// fill with given color AARRGGBB
456for( x=0; x < pm->width; x++ )
457for( y=0; y< pm->height; y++)
458pixel(pm,x,y).value = color;
459}
460
461void drawBackground()
462{
463// reset text cursor
464gui.screen.cursor.x = gui.screen.hborder;
465gui.screen.cursor.y = gui.screen.vborder;
466
467fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);
468
469// draw background.png into background buffer
470blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );
471
472// draw logo.png into background buffer
473if (gui.logo.draw)
474{
475 blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);
476}
477
478memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
479}
480
481void setupDeviceList(config_file_t *theme)
482{
483unsigned int pixel;
484intalpha;// transparency level 0 (obligue) - 255 (transparent)
485uint32_t color;// color value formatted RRGGBB
486int val, len;
487const char *string;
488
489if(getIntForKey("devices_max_visible", &val, theme ))
490gui.maxdevices = MIN( val, gDeviceCount );
491
492if(getIntForKey("devices_iconspacing", &val, theme ))
493gui.devicelist.iconspacing = val;
494
495// check layout for horizontal or vertical
496gui.layout = HorizontalLayout;
497if(getValueForKey( "devices_layout", &string, &len, theme)) {
498if (!strcmp (string, "vertical")) {
499gui.layout = VerticalLayout;
500}
501}
502
503switch (gui.layout) {
504case VerticalLayout:
505gui.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);
506gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);
507
508if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
509gui.devicelist.pos.x = pixel;
510
511if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
512gui.devicelist.pos.y = pixel;
513break;
514
515case HorizontalLayout:
516default:
517gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
518gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);
519
520if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
521gui.devicelist.pos.x = pixel;
522else
523gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
524
525if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
526gui.devicelist.pos.y = pixel;
527else
528gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
529break;
530}
531
532if(getColorForKey("devices_bgcolor", &color, theme))
533gui.devicelist.bgcolor = (color & 0x00FFFFFF);
534
535if(getIntForKey("devices_transparency", &alpha, theme))
536gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
537
538if (gui.devicelist.pixmap)
539{
540 freeWindowBuffer(&gui.devicelist);
541 createWindowBuffer(&gui.devicelist);
542 }
543}
544
545void loadThemeValues(config_file_t *theme)
546{
547unsigned int screen_width = gui.screen.width;
548unsigned int screen_height = gui.screen.height;
549unsigned int pixel;
550intalpha;// transparency level 0 (obligue) - 255 (transparent)
551uint32_t color;// color value formatted RRGGBB
552int val;
553
554/*
555 * Parse screen parameters
556 */
557if(getColorForKey("screen_bgcolor", &color, theme ))
558gui.screen.bgcolor = (color & 0x00FFFFFF);
559
560if(getIntForKey("screen_textmargin_h", &val, theme))
561gui.screen.hborder = MIN( gui.screen.width , val );
562
563if(getIntForKey("screen_textmargin_v", &val, theme))
564gui.screen.vborder = MIN( gui.screen.height , val );
565
566/*
567 * Parse background parameters
568 */
569if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
570gui.background.pos.x = pixel;
571
572if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
573gui.background.pos.y = pixel;
574
575/*
576 * Parse logo parameters
577 */
578if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
579gui.logo.pos.x = pixel;
580
581if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
582gui.logo.pos.y = pixel;
583
584/*
585 * Parse progress bar parameters
586 */
587if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
588gui.progressbar.pos.x = pixel;
589
590if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
591gui.progressbar.pos.y = pixel;
592
593/*
594 * Parse countdown text parameters
595 */
596if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
597gui.countdown.pos.x = pixel;
598
599if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
600gui.countdown.pos.y = pixel;
601
602 /*
603 * Parse devicelist parameters
604 */
605setupDeviceList(theme);
606
607/*
608 * Parse infobox parameters
609 */
610if(getIntForKey("infobox_width", &val, theme))
611gui.infobox.width = MIN( screen_width , val );
612
613if(getIntForKey("infobox_height", &val, theme))
614gui.infobox.height = MIN( screen_height , val );
615
616if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
617gui.infobox.pos.x = pixel;
618
619if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
620gui.infobox.pos.y = pixel;
621
622if(getIntForKey("infobox_textmargin_h", &val, theme))
623gui.infobox.hborder = MIN( gui.infobox.width , val );
624
625if(getIntForKey("infobox_textmargin_v", &val, theme))
626gui.infobox.vborder = MIN( gui.infobox.height , val );
627
628if(getColorForKey("infobox_bgcolor", &color, theme))
629gui.infobox.bgcolor = (color & 0x00FFFFFF);
630
631if(getIntForKey("infobox_transparency", &alpha, theme))
632gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
633
634/*
635 * Parse menu parameters
636 */
637if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
638gui.menu.width = pixel;
639else
640gui.menu.width = images[iMenuSelection].image->width;
641
642if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
643gui.menu.height = pixel;
644else
645gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;
646
647if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
648gui.menu.pos.x = pixel;
649
650if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
651gui.menu.pos.y = pixel;
652
653if(getIntForKey("menu_textmargin_h", &val, theme))
654gui.menu.hborder = MIN( gui.menu.width , val );
655
656if(getIntForKey("menu_textmargin_v", &val, theme))
657gui.menu.vborder = MIN( gui.menu.height , val );
658
659if(getColorForKey("menu_bgcolor", &color, theme))
660gui.menu.bgcolor = (color & 0x00FFFFFF);
661
662if(getIntForKey("menu_transparency", &alpha, theme))
663gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
664
665/*
666 * Parse bootprompt parameters
667 */
668if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
669gui.bootprompt.width = pixel;
670
671if(getIntForKey("bootprompt_height", &val, theme))
672gui.bootprompt.height = MIN( screen_height , val );
673
674if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
675gui.bootprompt.pos.x = pixel;
676
677if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
678gui.bootprompt.pos.y = pixel;
679
680if(getIntForKey("bootprompt_textmargin_h", &val, theme))
681gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );
682
683if(getIntForKey("bootprompt_textmargin_v", &val, theme))
684gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );
685
686if(getColorForKey("bootprompt_bgcolor", &color, theme))
687gui.bootprompt.bgcolor = (color & 0x00FFFFFF);
688
689if(getIntForKey("bootprompt_transparency", &alpha, theme))
690gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
691
692if(getColorForKey("font_small_color", &color, theme))
693gui.screen.font_small_color = (color & 0x00FFFFFF);
694
695if(getColorForKey("font_console_color", &color, theme))
696gui.screen.font_console_color = (color & 0x00FFFFFF);
697}
698
699int initGUI(void)
700{
701intval;
702intlen;
703chardirspec[256];
704
705getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig );
706if ((strlen(theme_name) + 27) > sizeof(dirspec)) {
707return 1;
708}
709sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);
710if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
711#ifdef CONFIG_EMBED_THEME
712 config_file_t*config;
713
714 config = &bootInfo->themeConfig;
715 if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
716 return 1;
717 }
718#else
719return 1;
720#endif
721}
722// parse display size parameters
723if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) {
724screen_params[0] = val;
725}
726if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) {
727screen_params[1] = val;
728}
729
730// Initalizing GUI strucutre.
731bzero(&gui, sizeof(gui_t));
732
733// find best matching vesa mode for our requested width & height
734getGraphicModeParams(screen_params);
735
736// set our screen structure with the mode width & height
737gui.screen.width = screen_params[0];
738gui.screen.height = screen_params[1];
739
740// load graphics otherwise fail and return
741if (loadGraphics() == 0) {
742loadThemeValues(&bootInfo->themeConfig);
743colorFont(&font_small, gui.screen.font_small_color);
744colorFont(&font_console, gui.screen.font_console_color);
745
746// create the screen & window buffers
747if (createBackBuffer(&gui.screen) == 0) {
748if (createWindowBuffer(&gui.screen) == 0) {
749if (createWindowBuffer(&gui.devicelist) == 0) {
750if (createWindowBuffer(&gui.bootprompt) == 0) {
751if (createWindowBuffer(&gui.infobox) == 0) {
752if (createWindowBuffer(&gui.menu) == 0) {
753 gui.logo.draw = true;
754drawBackground();
755// lets copy the screen into the back buffer
756memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
757setVideoMode( GRAPHICS_MODE, 0 );
758gui.initialised = true;
759return 0;
760}
761}
762}
763}
764}
765}
766}
767return 1;
768}
769
770void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected)
771{
772int devicetype;
773
774if( diskIsCDROM(device) )
775devicetype = iDeviceCDROM;// Use CDROM icon
776else
777{
778switch (device->part_type)
779{
780case kPartitionTypeHFS:
781
782// Use HFS or HFSRAID icon depending on bvr flags.
783devicetype = (device->flags & kBVFlagBooter) ? iDeviceHFSRAID : iDeviceHFS;
784break;
785
786case kPartitionTypeHPFS:
787devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
788break;
789
790case kPartitionTypeBEFS:/* Haiku detection and Icon credits to scorpius */
791devicetype = iDeviceBEFS;// Use BEFS / Haiku icon
792break;
793
794case kPartitionTypeFAT16:
795devicetype = iDeviceFAT16;// Use FAT16 icon
796break;
797
798case kPartitionTypeFAT32:
799devicetype = iDeviceFAT32;// Use FAT32 icon
800break;
801
802case kPartitionTypeEXT3:
803devicetype = iDeviceEXT3;// Use EXT2/3 icon
804break;
805
806case kPartitionTypeFreeBSD:/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
807devicetype = iDeviceFreeBSD;// Use FreeBSD icon
808break;
809
810case kPartitionTypeOpenBSD:/* FreeBSD/OpenBSD detection,nawcom's code by valv, Icon credits to blackosx */
811devicetype = iDeviceOpenBSD;// Use OpenBSD icon
812break;
813
814default:
815devicetype = iDeviceGeneric;// Use Generic icon
816break;
817}
818}
819
820// Draw the selection image and use the next (device_*_o) image for the selected item.
821 if (isSelected)
822{
823blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p));
824devicetype++;
825}
826
827// draw icon
828blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
829
830p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
831
832// draw volume label
833drawStrCenteredAt( device->label, &font_small, buffer, p);
834
835}
836
837void drawDeviceList (int start, int end, int selection)
838{
839int i;
840position_t p, p_prev, p_next;
841
842//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
843
844fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
845
846makeRoundedCorners( gui.devicelist.pixmap);
847
848switch (gui.layout)
849{
850
851case VerticalLayout:
852p.x = (gui.devicelist.width /2);
853p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
854
855// place scroll indicators at top & bottom edges
856p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
857p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
858
859break;
860
861default:// use Horizontal layout as the default
862
863case HorizontalLayout:
864p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
865p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
866
867// place scroll indicators at left & right edges
868p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
869p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
870
871break;
872
873}
874
875// draw visible device icons
876for (i = 0; i < gui.maxdevices; i++)
877{
878BVRef param = menuItems[start + i].param;
879
880 bool isSelected = ((start + i) == selection) ? true : false;
881if (isSelected)
882{
883 if (param->flags & kBVFlagNativeBoot)
884 {
885 infoMenuNativeBoot = true;
886 }
887 else
888 {
889 infoMenuNativeBoot = false;
890 if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
891 infoMenuSelection = 0;
892 }
893
894if(gui.menu.draw)
895drawInfoMenuItems();
896
897#if DEBUG
898 gui.debug.cursor = pos( 10, 100);
899 dprintf( &gui.screen, "label %s\n", param->label );
900 dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev );
901 dprintf(&gui.screen, "width %d\n", gui.screen.width);
902 dprintf(&gui.screen, "height %d\n", gui.screen.height);
903 dprintf( &gui.screen, "type 0x%x\n", param->type );
904 dprintf( &gui.screen, "flags 0x%x\n", param->flags );
905 dprintf( &gui.screen, "part_no %d\n", param->part_no );
906 dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff );
907 dprintf( &gui.screen, "part_type 0x%x\n", param->part_type );
908 dprintf( &gui.screen, "bps 0x%x\n", param->bps );
909 dprintf( &gui.screen, "name %s\n", param->name );
910 dprintf( &gui.screen, "type_name %s\n", param->type_name );
911 dprintf( &gui.screen, "modtime %d\n", param->modTime );
912#endif
913}
914
915drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected);
916
917if (gui.layout == HorizontalLayout)
918{
919p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
920}
921if (gui.layout == VerticalLayout)
922{
923p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
924}
925}
926
927// draw prev indicator
928if(start)
929blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
930
931// draw next indicator
932if( end < gDeviceCount - 1 )
933blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
934
935gui.redraw = true;
936
937updateVRAM();
938
939}
940
941void clearGraphicBootPrompt()
942{
943// clear text buffer
944prompt[0] = '\0';
945prompt_pos=0;
946
947
948if(gui.bootprompt.draw == true )
949{
950gui.bootprompt.draw = false;
951gui.redraw = true;
952// this causes extra frames to be drawn
953//updateVRAM();
954}
955
956return;
957}
958
959void updateGraphicBootPrompt(int key)
960{
961if ( key == kBackspaceKey )
962prompt[--prompt_pos] = '\0';
963else
964{
965prompt[prompt_pos] = key;
966prompt_pos++;
967prompt[prompt_pos] = '\0';
968}
969
970fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
971
972makeRoundedCorners( gui.bootprompt.pixmap);
973
974position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
975
976// print the boot prompt text
977drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
978
979// get the position of the end of the boot prompt text to display user input
980position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
981
982// calculate the position of the cursor
983intoffset = ( prompt_pos - ( ( gui.bootprompt.width / font_console.chars[0]->width ) - strlen(prompt_text) - 2 ) );
984
985if ( offset < 0)
986offset = 0;
987
988drawStr( prompt+offset, &font_console, gui.bootprompt.pixmap, p_prompt);
989
990gui.menu.draw = false;
991gui.bootprompt.draw = true;
992gui.redraw = true;
993
994updateVRAM();
995
996return;
997}
998
999inline
1000void vramwrite (void *data, int width, int height)
1001{
1002if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
1003memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
1004else
1005{
1006uint32_t r, g, b;
1007int i, j;
1008for (i = 0; i < VIDEO (height); i++)
1009for (j = 0; j < VIDEO (width); j++)
1010{
1011b = ((uint8_t *) data)[4*i*width + 4*j];
1012g = ((uint8_t *) data)[4*i*width + 4*j + 1];
1013r = ((uint8_t *) data)[4*i*width + 4*j + 2];
1014switch (VIDEO (depth))
1015{
1016case 32:
1017*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
1018break;
1019case 24:
1020*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
1021| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
1022break;
1023case 16:
1024// Somehow 16-bit is always 15-bits really
1025//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
1026//break;
1027case 15:
1028*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
1029break;
1030}
1031}
1032}
1033}
1034
1035void updateVRAM()
1036{
1037if (gui.redraw)
1038{
1039if (gui.devicelist.draw)
1040blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
1041
1042if (gui.bootprompt.draw)
1043blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
1044
1045if (gui.menu.draw)
1046blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
1047
1048if (gui.infobox.draw)
1049blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
1050}
1051
1052vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
1053
1054if (gui.redraw)
1055{
1056memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
1057gui.redraw = false;
1058}
1059}
1060
1061struct putc_info //Azi: same as below
1062{
1063 char * str;
1064 char * last_str;
1065};
1066
1067static int
1068sputc(int c, struct putc_info * pi) //Azi: exists on console.c & printf.c
1069{
1070 if (pi->last_str)
1071 if (pi->str == pi->last_str) {
1072 *(pi->str) = '\0';
1073 return 0;
1074 }
1075 *(pi->str)++ = c;
1076 return c;
1077}
1078
1079int gprintf( window_t * window, const char * fmt, ...)
1080{
1081char *formattedtext;
1082
1083va_list ap;
1084
1085struct putc_info pi;
1086
1087if ((formattedtext = malloc(1024)) != NULL) {
1088// format the text
1089va_start(ap, fmt);
1090pi.str = formattedtext;
1091pi.last_str = 0;
1092prf(fmt, ap, sputc, &pi);
1093*pi.str = '\0';
1094va_end(ap);
1095
1096position_torigin, cursor, bounds;
1097
1098int i;
1099int character;
1100
1101origin.x = MAX( window->cursor.x, window->hborder );
1102origin.y = MAX( window->cursor.y, window->vborder );
1103
1104bounds.x = ( window->width - window->hborder );
1105bounds.y = ( window->height - window->vborder );
1106
1107cursor = origin;
1108
1109font_t *font = &font_console;
1110
1111for( i=0; i< strlen(formattedtext); i++ )
1112{
1113character = formattedtext[i];
1114
1115character -= 32;
1116
1117// newline ?
1118if( formattedtext[i] == '\n' )
1119{
1120cursor.x = window->hborder;
1121cursor.y += font->height;
1122
1123if ( cursor.y > bounds.y )
1124cursor.y = origin.y;
1125
1126continue;
1127}
1128
1129// tab ?
1130if( formattedtext[i] == '\t' )
1131cursor.x += ( font->chars[0]->width * 5 );
1132
1133// draw the character
1134if( font->chars[character])
1135blend(font->chars[character], window->pixmap, cursor);
1136
1137cursor.x += font->chars[character]->width;
1138
1139// check x pos and do newline
1140if ( cursor.x > bounds.x )
1141{
1142cursor.x = origin.x;
1143cursor.y += font->height;
1144}
1145
1146// check y pos and reset to origin.y
1147if ( cursor.y > bounds.y )
1148cursor.y = origin.y;
1149}
1150
1151// update cursor postition
1152window->cursor = cursor;
1153
1154free(formattedtext);
1155
1156return 0;
1157
1158}
1159return 1;
1160}
1161
1162int dprintf( window_t * window, const char * fmt, ...)
1163{
1164char *formattedtext;
1165
1166va_list ap;
1167
1168//window = &gui.debug;
1169
1170struct putc_info pi;
1171
1172if ((formattedtext = malloc(1024)) != NULL) {
1173// format the text
1174va_start(ap, fmt);
1175pi.str = formattedtext;
1176pi.last_str = 0;
1177prf(fmt, ap, sputc, &pi);
1178*pi.str = '\0';
1179va_end(ap);
1180
1181position_torigin, cursor, bounds;
1182
1183int i;
1184int character;
1185
1186origin.x = MAX( gui.debug.cursor.x, window->hborder );
1187origin.y = MAX( gui.debug.cursor.y, window->vborder );
1188
1189bounds.x = ( window->width - window->hborder );
1190bounds.y = ( window->height - window->vborder );
1191
1192cursor = origin;
1193
1194font_t *font = &font_console;
1195
1196for( i=0; i< strlen(formattedtext); i++ )
1197{
1198character = formattedtext[i];
1199
1200character -= 32;
1201
1202// newline ?
1203if( formattedtext[i] == '\n' )
1204{
1205cursor.x = window->hborder;
1206cursor.y += font->height;
1207
1208if ( cursor.y > bounds.y )
1209cursor.y = origin.y;
1210
1211continue;
1212}
1213
1214// tab ?
1215if( formattedtext[i] == '\t' )
1216cursor.x += ( font->chars[0]->width * 5 );
1217
1218// draw the character
1219if( font->chars[character])
1220blend(font->chars[character], gui.backbuffer, cursor);
1221
1222cursor.x += font->chars[character]->width;
1223
1224// check x pos and do newline
1225if ( cursor.x > bounds.x )
1226{
1227cursor.x = origin.x;
1228cursor.y += font->height;
1229}
1230
1231// check y pos and reset to origin.y
1232if ( cursor.y > bounds.y )
1233cursor.y = origin.y;
1234}
1235
1236// update cursor postition
1237gui.debug.cursor = cursor;
1238
1239free(formattedtext);
1240
1241return 0;
1242
1243}
1244return 1;
1245}
1246
1247int vprf(const char * fmt, va_list ap)
1248{
1249int i;
1250int character;
1251
1252char *formattedtext;
1253window_t *window = &gui.screen;
1254struct putc_info pi;
1255
1256position_torigin, cursor, bounds;
1257font_t *font = &font_console;
1258
1259if ((formattedtext = malloc(1024)) != NULL) {
1260// format the text
1261pi.str = formattedtext;
1262pi.last_str = 0;
1263prf(fmt, ap, sputc, &pi);
1264*pi.str = '\0';
1265
1266origin.x = MAX( window->cursor.x, window->hborder );
1267origin.y = MAX( window->cursor.y, window->vborder );
1268bounds.x = ( window->width - ( window->hborder * 2 ) );
1269bounds.y = ( window->height - ( window->vborder * 2 ) );
1270cursor = origin;
1271
1272for( i=0; i< strlen(formattedtext); i++ )
1273{
1274character = formattedtext[i];
1275character -= 32;
1276
1277// newline ?
1278if( formattedtext[i] == '\n' )
1279{
1280cursor.x = window->hborder;
1281cursor.y += font->height;
1282if ( cursor.y > bounds.y )
1283{
1284gui.redraw = true;
1285updateVRAM();
1286cursor.y = window->vborder;
1287}
1288window->cursor.y = cursor.y;
1289continue;
1290}
1291
1292// tab ?
1293if( formattedtext[i] == '\t' )
1294{
1295cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
1296continue;
1297}
1298cursor.x += font->chars[character]->width;
1299
1300// check x pos and do newline
1301if ( cursor.x > bounds.x )
1302{
1303cursor.x = origin.x;
1304cursor.y += font->height;
1305}
1306
1307// check y pos and reset to origin.y
1308if ( cursor.y > ( bounds.y + font->chars[0]->height) )
1309{
1310gui.redraw = true;
1311updateVRAM();
1312cursor.y = window->vborder;
1313}
1314// draw the character
1315if( font->chars[character])
1316blend(font->chars[character], gui.backbuffer, cursor);
1317}
1318// save cursor postition
1319window->cursor.x = cursor.x;
1320updateVRAM();
1321free(formattedtext);
1322return 0;
1323}
1324return 1;
1325}
1326
1327void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
1328{
1329int i=0;
1330int y=0; // we need this to support multilines '\n'
1331int x=0;
1332
1333for(i=0;i<strlen(ch);i++)
1334{
1335int cha=(int)ch[i];
1336
1337cha-=32;
1338
1339// newline ?
1340if( ch[i] == '\n' )
1341{
1342x = 0;
1343y += font->height;
1344continue;
1345}
1346
1347// tab ?
1348if( ch[i] == '\t' )
1349x+=(font->chars[0]->width*5);
1350
1351if(font->chars[cha])
1352blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
1353
1354x += font->chars[cha]->width;
1355}
1356}
1357
1358void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
1359{
1360int i = 0;
1361int width = 0;
1362
1363// calculate the width in pixels
1364for(i=0;i<strlen(text);i++)
1365width += font->chars[text[i]-32]->width;
1366
1367p.x = ( p.x - ( width / 2 ) );
1368p.y = ( p.y - ( font->height / 2 ) );
1369
1370if ( p.x == -6 )
1371{
1372p.x = 0;
1373}
1374
1375for(i=0;i<strlen(text);i++)
1376{
1377int cha=(int)text[i];
1378
1379cha-=32;
1380
1381if(font->chars[cha])
1382{
1383blend(font->chars[cha], blendInto, p);
1384p.x += font->chars[cha]->width;
1385}
1386}
1387
1388}
1389
1390int initFont(font_t *font, image_t *data)
1391{
1392unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
1393
1394int start = 0, end = 0, count = 0, space = 0;
1395
1396bool monospaced = false;
1397
1398font->height = data->image->height;
1399
1400for( x = 0; x < data->image->width; x++)
1401{
1402start = end;
1403
1404// if the pixel is red we've reached the end of the char
1405if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
1406{
1407end = x + 1;
1408
1409if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
1410{
1411font->chars[count]->width = ( end - start) - 1;
1412font->chars[count]->height = font->height;
1413
1414if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
1415{
1416space += ( font->chars[count]->width * data->image->height * 4 );
1417// we skip the first line because there are just the red pixels for the char width
1418for( y = 1; y< (font->height); y++)
1419{
1420for( x2 = start, x3 = 0; x2 < end; x2++, x3++)
1421{
1422pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
1423}
1424}
1425
1426// check if font is monospaced
1427if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
1428monospaced = true;
1429
1430font->width = font->chars[count]->width;
1431
1432count++;
1433}
1434}
1435}
1436}
1437
1438if(monospaced)
1439font->width = 0;
1440
1441return 0;
1442}
1443
1444void colorFont(font_t *font, uint32_t color)
1445{
1446if( !color )
1447return;
1448
1449int x, y, width, height;
1450int count = 0;
1451pixel_t *buff;
1452
1453while( font->chars[count++] )
1454{
1455width = font->chars[count-1]->width;
1456height = font->chars[count-1]->height;
1457for( y = 0; y < height; y++ )
1458{
1459for( x = 0; x < width; x++ )
1460{
1461buff = &(pixel( font->chars[count-1], x, y ));
1462if( buff->ch.a )
1463{
1464buff->ch.r = (color & 0xFFFF0000) >> 16;
1465buff->ch.g = (color & 0xFF00FF00) >> 8;
1466buff->ch.b = (color & 0xFF0000FF);
1467}
1468}
1469}
1470}
1471}
1472
1473void makeRoundedCorners(pixmap_t *p)
1474{
1475int x,y;
1476int width=p->width-1;
1477int height=p->height-1;
1478
1479// 10px rounded corner alpha values
1480uint8_t roundedCorner[10][10] =
1481{
1482{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
1483{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
1484{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1485{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1486{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1487{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1488{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1489{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1490{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1491{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
1492};
1493
1494uint8_t alpha=0;
1495
1496for( y=0; y<10; y++)
1497{
1498for( x=0; x<10; x++)
1499{
1500// skip if the pixel should be visible
1501if(roundedCorner[y][x] != 0xFF)
1502{
1503alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
1504// Upper left corner
1505pixel(p, x, y).ch.a = alpha;
1506
1507// upper right corner
1508pixel(p, width-x,y).ch.a = alpha;
1509
1510// lower left corner
1511pixel(p, x, height-y).ch.a = alpha;
1512
1513// lower right corner
1514pixel(p, width-x, height-y).ch.a = alpha;
1515}
1516}
1517}
1518}
1519
1520void showInfoBox(char *title, char *text)
1521{
1522int i, key, lines, visiblelines;
1523
1524int currentline=0;
1525int cnt=0;
1526int offset=0;
1527
1528if( !title || !text )
1529return;
1530
1531position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
1532
1533// calculate number of lines in the title
1534for ( i = 0, lines = 1; i<strlen(title); i++ )
1535if( title[i] == '\n')
1536lines++;
1537
1538// y position of text is lines in title * height of font
1539position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
1540
1541// calculate number of lines in the text
1542for ( i=0, lines = 1; i<strlen(text); i++ )
1543if( text[i] == '\n')
1544lines++;
1545
1546// if text ends with \n strip off
1547if( text[i] == '\n' || text[i] == '\0')
1548lines--;
1549
1550visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
1551
1552// lets display the text and allow scroll thru using up down / arrows
1553while(1)
1554{
1555// move to current line in text
1556for( offset = 0, i = 0; offset < strlen(text); offset++ )
1557{
1558if( currentline == i)
1559break;
1560if( text[offset] =='\n')
1561i++;
1562}
1563
1564// find last visible line in text and place \0
1565for( i = offset, cnt = 0; i < strlen(text); i++)
1566{
1567if(text[i]=='\n')
1568cnt++;
1569if ( cnt == visiblelines )
1570{
1571text[i]='\0';
1572break;
1573}
1574}
1575
1576fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
1577
1578makeRoundedCorners( gui.infobox.pixmap);
1579
1580// print the title if present
1581if( title )
1582drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
1583
1584// print the text
1585drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
1586
1587// restore \n in text
1588if ( cnt == visiblelines )
1589text[i] = '\n';
1590
1591position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
1592
1593// draw prev indicator
1594if(offset)
1595{
1596blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
1597}
1598
1599// draw next indicator
1600if( lines > ( currentline + visiblelines ) )
1601{
1602pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
1603blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
1604}
1605
1606gui.bootprompt.draw = false;
1607gui.infobox.draw = true;
1608gui.redraw = true;
1609
1610updateVRAM();
1611
1612key = getchar();
1613
1614if( key == kUpArrowkey )
1615if( currentline > 0 )
1616currentline--;
1617
1618if( key == kDownArrowkey )
1619if( lines > ( currentline + visiblelines ) )
1620currentline++;
1621
1622if( key == kEscapeKey || key == 'q' || key == 'Q')
1623{
1624gui.infobox.draw = false;
1625gui.redraw = true;
1626updateVRAM();
1627break;
1628}
1629}
1630}
1631
1632void animateProgressBar()
1633{
1634int y;
1635
1636if( time18() > lasttime)
1637{
1638lasttime = time18();
1639
1640pixmap_t *buffBar = images[iProgressBar].image;
1641
1642uint32_t buff = buffBar->pixels[0].value;
1643
1644memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
1645
1646for( y = buffBar->height - 1; y > 0; y--)
1647pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
1648
1649pixel(buffBar, buffBar->width-1, 0).value = buff;
1650}
1651}
1652
1653void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
1654{
1655if(progress>100)
1656return;
1657
1658p.x = ( p.x - ( width / 2 ) );
1659
1660int todraw = (width * progress) / 100;
1661
1662pixmap_t *buff = images[iProgressBar].image;
1663pixmap_t *buffBG = images[iProgressBarBackground].image;
1664if(!buff || !buffBG)
1665return;
1666
1667pixmap_t progressbar;
1668progressbar.pixels=malloc(width * 4 * buff->height);
1669if(!progressbar.pixels)
1670return;
1671
1672progressbar.width = width;
1673progressbar.height = buff->height;
1674
1675int x=0,x2=0,y=0;
1676
1677for(y=0; y<buff->height; y++)
1678{
1679for(x=0; x<todraw; x++, x2++)
1680{
1681if(x2 == (buff->width-1)) x2=0;
1682pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
1683}
1684x2=0;
1685}
1686
1687for(y=0; y<buff->height; y++)
1688{
1689for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
1690{
1691if(x2 == (buffBG->width -2 )) x2 = 0;
1692pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
1693}
1694if(progress < 100)
1695pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1696if(progress == 0)
1697pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1698x2=0;
1699}
1700
1701blend(&progressbar, blendInto, p);
1702animateProgressBar();
1703free(progressbar.pixels);
1704}
1705
1706void drawInfoMenuItems()
1707{
1708int i,n;
1709
1710position_t position;
1711
1712pixmap_t *selection = images[iMenuSelection].image;
1713
1714pixmap_t *pbuff;
1715
1716fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
1717
1718makeRoundedCorners(gui.menu.pixmap);
1719
1720uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
1721
1722position = pos(0,0);
1723
1724for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
1725{
1726if (i == infoMenuSelection)
1727blend(selection, gui.menu.pixmap, position);
1728
1729pbuff = images[n].image;
1730if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
1731blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
1732pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1733else
1734blend( pbuff, gui.menu.pixmap,
1735pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1736
1737drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
1738pos(position.x + (pbuff->width + gui.menu.hborder),
1739position.y + ((selection->height - font_console.height) / 2)));
1740position.y += images[iMenuSelection].image->height;
1741
1742}
1743
1744gui.redraw = true;
1745}
1746
1747int drawInfoMenu()
1748{
1749drawInfoMenuItems();
1750
1751gui.menu.draw = true;
1752
1753updateVRAM();
1754
1755return 1;
1756}
1757
1758int updateInfoMenu(int key)
1759{
1760switch (key)
1761{
1762
1763case kUpArrowkey:// up arrow
1764if (infoMenuSelection > 0)
1765{
1766if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
1767infoMenuSelection -= 4;
1768
1769else
1770infoMenuSelection--;
1771drawInfoMenuItems();
1772updateVRAM();
1773
1774} else {
1775
1776gui.menu.draw = false;
1777gui.redraw = true;
1778
1779updateVRAM();
1780
1781return CLOSE_INFO_MENU;
1782}
1783break;
1784
1785case kDownArrowkey:// down arrow
1786if (infoMenuSelection < infoMenuItemsCount - 1)
1787{
1788if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
1789infoMenuSelection += 4;
1790else
1791infoMenuSelection++;
1792drawInfoMenuItems();
1793updateVRAM();
1794}
1795break;
1796
1797case kReturnKey:
1798key = 0;
1799if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
1800showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
1801
1802else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
1803showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
1804
1805else if( infoMenuSelection == MENU_SHOW_HELP )
1806showHelp();
1807
1808else
1809{
1810int buff = infoMenuSelection;
1811infoMenuSelection = 0;
1812return buff;
1813}
1814break;
1815}
1816return DO_NOT_BOOT;
1817}
1818
1819uint16_t bootImageWidth = 0;
1820uint16_t bootImageHeight = 0;
1821uint8_t *bootImageData = NULL;
1822static bool usePngImage = true;
1823
1824//==========================================================================
1825// loadBootGraphics
1826static void loadBootGraphics(void)
1827{
1828if (bootImageData != NULL) {
1829return;
1830}
1831
1832char dirspec[256];
1833
1834if ((strlen(theme_name) + 24) > sizeof(dirspec)) {
1835usePngImage = false;
1836return;
1837}
1838sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);
1839if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
1840#ifdef CONFIG_EMBED_THEME
1841 if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
1842#endif
1843usePngImage = false;
1844}
1845}
1846
1847//==========================================================================
1848// drawBootGraphics
1849void drawBootGraphics(void)
1850{
1851int pos;
1852int length;
1853const char *dummyVal;
1854int oldScreenWidth, oldScreenHeight;
1855bool legacy_logo;
1856uint16_t x, y;
1857
1858if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig) && legacy_logo) {
1859usePngImage = false;
1860} else if (bootImageData == NULL) {
1861loadBootGraphics();
1862}
1863
1864// parse screen size parameters
1865if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) {
1866screen_params[0] = pos;
1867} else {
1868screen_params[0] = DEFAULT_SCREEN_WIDTH;
1869}
1870if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) {
1871screen_params[1] = pos;
1872} else {
1873screen_params[1] = DEFAULT_SCREEN_HEIGHT;
1874}
1875
1876 // Save current screen resolution.
1877oldScreenWidth = gui.screen.width;
1878oldScreenHeight = gui.screen.height;
1879
1880gui.screen.width = screen_params[0];
1881gui.screen.height = screen_params[1];
1882
1883// find best matching vesa mode for our requested width & height
1884getGraphicModeParams(screen_params);
1885
1886 // Set graphics mode if the booter was in text mode or the screen resolution has changed.
1887if (bootArgs->Video.v_display == VGA_TEXT_MODE
1888|| (screen_params[0] != oldScreenWidth && screen_params[1] != oldScreenHeight) )
1889{
1890setVideoMode(GRAPHICS_MODE, 0);
1891}
1892
1893if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) {
1894drawCheckerBoard();
1895} else {
1896// Fill the background to 75% grey (same as BootX).
1897drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
1898}
1899if ((bootImageData) && (usePngImage)) {
1900x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
1901y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
1902
1903// Draw the image in the center of the display.
1904blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
1905} else {
1906uint8_t *appleBootPict;
1907bootImageData = NULL;
1908bootImageWidth = kAppleBootWidth;
1909bootImageHeight = kAppleBootHeight;
1910
1911// Prepare the data for the default Apple boot image.
1912appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
1913if (appleBootPict) {
1914convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
1915if (bootImageData) {
1916x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
1917y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
1918drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
1919free(bootImageData);
1920}
1921free(appleBootPict);
1922}
1923}
1924}
1925

Archive Download this file

Revision: 307