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