00001
00038 #include <stream.h>
00039 #include <string.h>
00040 #include <workqueue.h>
00041
00042 #include <gfx/gfx.h>
00043 #include <gfx/win.h>
00044 #include <gfx/wtk.h>
00045 #include <gfx/sysfont.h>
00046
00047 #include <fs/tsfs.h>
00048
00049 #include "app_files.h"
00050 #include "app_desktop.h"
00051 #include "file_loader.h"
00052
00059
00060 #define FONT_HEADER_SIZE 16
00061
00063 #define FILE_NAMES_PER_PAGE 8
00064
00066 enum app_files_page_numbers {
00068 PAGE_NUM_BLANK = 1,
00070 PAGE_NUM_FIRST = 2,
00072 PAGE_NUM_INTRO_SCREEN = PAGE_NUM_FIRST,
00074 PAGE_NUM_INFO_SCREEN,
00076 PAGE_NUM_LAST = PAGE_NUM_INFO_SCREEN,
00077 };
00078
00080
00081
00082 #define COLOR_TEXT GFX_COLOR(250, 250, 250)
00083
00084 #define COLOR_TEXT_SHADED GFX_COLOR(150, 150, 150)
00085
00086 #define COLOR_BACKGROUND GFX_COLOR(0, 0, 0)
00087
00088 #define COLOR_LINE GFX_COLOR(48, 120, 158)
00089
00090
00092
00093
00094 #define TEXT_HEADER_HEIGHT 30
00095
00096 #define TEXT_INDENT 5
00097
00098 #define TEXT_PADDING 3
00099
00100 #define TEXT_PADDING_NEWLINE 2
00101
00102
00106 enum app_files_button_ids {
00108 BUTTON_NEXT_ID = 1,
00110 BUTTON_PREV_ID,
00112 BUTTON_QUIT_ID,
00113 };
00114
00116 struct app_files {
00118 struct wtk_basic_frame *frame;
00120 struct gfx_bitmap background;
00122 struct workqueue_task *task;
00124 struct font old_sysfont;
00126 uint_fast8_t page_number;
00127 };
00128
00130 extern struct tsfs myfs;
00131
00133 static struct app_files *the_app_files;
00134
00136 static struct font font_fixedrus = {
00137 .type = FONT_LOC_HUGEMEM,
00138 .scale = 1,
00139 };
00140
00152 static void string_file_size(char *file_size_str, uint32_t size,
00153 size_t str_size)
00154 {
00155 uint8_t order = 0;
00156
00157 while (size > (1024 * 5) && order <= 3) {
00158 size /= 1024;
00159 order++;
00160 }
00161
00162 switch (order) {
00163 case 0:
00164 snprintf(file_size_str, str_size, "%li B", size);
00165 break;
00166
00167 case 1:
00168 snprintf(file_size_str, str_size, "%li kB", size);
00169 break;
00170
00171 case 2:
00172 snprintf(file_size_str, str_size, "%li MB", size);
00173 break;
00174
00175 case 3:
00176 snprintf(file_size_str, str_size, "%li GB", size);
00177 break;
00178
00179 default:
00180 unhandled_case(order);
00181 break;
00182
00183 };
00184 }
00185
00192 static void screen_draw_introduction(void)
00193 {
00194 gfx_coord_t x = TEXT_INDENT;
00195 gfx_coord_t y = TEXT_HEADER_HEIGHT;
00196
00197
00198 gfx_draw_horizontal_line(TEXT_PADDING,
00199 gfx_font_get_height(&font_fixedrus) + TEXT_INDENT,
00200 gfx_get_width() - (2 * TEXT_PADDING), COLOR_LINE);
00201 gfx_draw_string("Tiny Simple File System", TEXT_INDENT, TEXT_INDENT,
00202 &font_fixedrus, COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00203
00204
00205 gfx_draw_string("The TSFS is a fast and simple", x, y, &font_fixedrus,
00206 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00207
00208 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00209 gfx_draw_string("read-only file system built for", x, y,
00210 &font_fixedrus, COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00211
00212 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00213 gfx_draw_string("speed in integrated systems.", x, y, &font_fixedrus,
00214 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00215
00216 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE +
00217 TEXT_INDENT;
00218 gfx_draw_string("TSFS makes it easy to load", x, y, &font_fixedrus,
00219 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00220
00221 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00222 gfx_draw_string("resources like pictures or data", x, y, &font_fixedrus,
00223 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00224
00225 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00226 gfx_draw_string("files from external storage to", x, y, &font_fixedrus,
00227 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00228
00229 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00230 gfx_draw_string("RAM or directly to the screen.", x, y, &font_fixedrus,
00231 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00232 }
00233
00240 static void screen_draw_file_system_info(void)
00241 {
00242 char string[30];
00243 char file_size_str[10];
00244 gfx_coord_t x = TEXT_INDENT;
00245 gfx_coord_t y = TEXT_HEADER_HEIGHT;
00246
00247
00248 gfx_draw_horizontal_line(TEXT_PADDING,
00249 gfx_font_get_height(&font_fixedrus) + TEXT_INDENT,
00250 gfx_get_width() - (2 * TEXT_PADDING), COLOR_LINE);
00251 gfx_draw_string("Tiny Simple File System", TEXT_INDENT, TEXT_INDENT,
00252 &font_fixedrus, COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00253
00254
00255 gfx_draw_string("File system details",
00256 x, y, &font_fixedrus, COLOR_TEXT,
00257 GFX_COLOR_TRANSPARENT);
00258
00259 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE +
00260 TEXT_INDENT;
00261 snprintf(string, sizeof(string), "TSFS version : v%i.0",
00262 myfs.header.version);
00263 gfx_draw_string(string, x, y, &font_fixedrus, COLOR_TEXT,
00264 GFX_COLOR_TRANSPARENT);
00265
00266 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00267 snprintf(string, sizeof(string), "Files in volume : %i",
00268 (int)myfs.header.nr_files);
00269 gfx_draw_string(string, x, y, &font_fixedrus, COLOR_TEXT,
00270 GFX_COLOR_TRANSPARENT);
00271
00272 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00273 string_file_size(file_size_str, myfs.header.volume_size,
00274 sizeof(file_size_str));
00275 snprintf(string, sizeof(string), "Volume size : %s", file_size_str);
00276 gfx_draw_string(string, x, y, &font_fixedrus, COLOR_TEXT,
00277 GFX_COLOR_TRANSPARENT);
00278
00279 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE +
00280 TEXT_INDENT;
00281 gfx_draw_string("The following pages will show", x, y, &font_fixedrus,
00282 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00283
00284 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00285 gfx_draw_string("the contents of the file", x, y, &font_fixedrus,
00286 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00287
00288 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00289 gfx_draw_string("system using the string", x, y, &font_fixedrus,
00290 COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00291
00292 y += gfx_font_get_height(&font_fixedrus) + TEXT_PADDING_NEWLINE;
00293 gfx_draw_string("formatting utils.", x, y, &font_fixedrus, COLOR_TEXT,
00294 GFX_COLOR_TRANSPARENT);
00295 }
00296
00305 static void screen_draw_file_list_from_index(uint_fast8_t index)
00306 {
00307 char string[30];
00308 char file_size_str[10];
00309 uint8_t file_name[TSFS_FILENAME_LEN + 1];
00310 uint8_t x = TEXT_INDENT;
00311 uint8_t y = TEXT_HEADER_HEIGHT;
00312 uint_fast8_t file_index;
00313 uint_fast8_t first_file;
00314 uint_fast8_t last_file;
00315
00316 first_file = index;
00317 last_file = min_u(first_file + FILE_NAMES_PER_PAGE - 1,
00318 myfs.header.nr_files - 1);
00319
00320
00321 memset(string, 0, sizeof(string));
00322 memset(file_name, 0, sizeof(file_name));
00323 memset(file_size_str, 0, sizeof(file_size_str));
00324
00325
00326 gfx_draw_horizontal_line(TEXT_PADDING,
00327 gfx_font_get_height(&font_fixedrus) + TEXT_INDENT,
00328 gfx_get_width() - (2 * TEXT_PADDING), COLOR_LINE);
00329 gfx_draw_string("String formatting TSFS contents", TEXT_INDENT, TEXT_INDENT,
00330 &font_fixedrus, COLOR_TEXT, GFX_COLOR_TRANSPARENT);
00331
00332
00333 snprintf(string, sizeof(string), "Displaying files %i to %i",
00334 (int)first_file, (int)last_file);
00335 gfx_draw_string(string, x, y, &font_fixedrus, COLOR_TEXT,
00336 GFX_COLOR_TRANSPARENT);
00337
00338 for (file_index = first_file; file_index <= last_file; file_index++) {
00339 struct tsfs_file file;
00340
00341 y += gfx_font_get_height(&font_fixedrus);
00342
00343 tsfs_get_filename(&myfs, file_index, file_name);
00344 tsfs_open(&myfs, (char *)file_name, &file);
00345
00346 string_file_size(file_size_str, tsfs_get_file_size(&file),
00347 sizeof(file_size_str));
00348 snprintf(string, sizeof(string), "%i) %s %s", (int)file_index,
00349 file_name, file_size_str);
00350 gfx_draw_string(string, x, y, &font_fixedrus, COLOR_TEXT,
00351 GFX_COLOR_TRANSPARENT);
00352 }
00353 }
00354
00360 static void app_files_frame_draw_handler(struct win_window *win,
00361 const struct win_clip_region *clip)
00362 {
00363 uint_fast8_t page_number = the_app_files->page_number;
00364
00365 if (page_number < PAGE_NUM_INTRO_SCREEN)
00366 return;
00367
00368 if (page_number == PAGE_NUM_INTRO_SCREEN) {
00369 screen_draw_introduction();
00370 }
00371 else if (page_number == PAGE_NUM_INFO_SCREEN) {
00372 screen_draw_file_system_info();
00373 } else {
00374 uint_fast8_t file_offset;
00375 file_offset = (page_number - (PAGE_NUM_LAST + 1)) *
00376 FILE_NAMES_PER_PAGE;
00377 screen_draw_file_list_from_index(file_offset);
00378 }
00379 }
00380
00391 static bool app_files_frame_command_handler(struct wtk_basic_frame *frame,
00392 win_command_t command_data)
00393 {
00394 uint8_t command = (uint8_t)(uintptr_t)command_data;
00395 uint_fast8_t nr_of_file_pages;
00396
00397 nr_of_file_pages = (myfs.header.nr_files / FILE_NAMES_PER_PAGE) + 1;
00398
00399 switch (command) {
00400 case BUTTON_NEXT_ID:
00401 the_app_files->page_number++;
00402 if (the_app_files->page_number >
00403 (PAGE_NUM_LAST + nr_of_file_pages)) {
00404 the_app_files->page_number = PAGE_NUM_FIRST;
00405 }
00406 win_redraw(wtk_basic_frame_as_child(the_app_files->frame));
00407 break;
00408
00409 case BUTTON_PREV_ID:
00410 the_app_files->page_number--;
00411 if (the_app_files->page_number < PAGE_NUM_FIRST) {
00412 the_app_files->page_number = PAGE_NUM_LAST +
00413 nr_of_file_pages;
00414 }
00415 win_redraw(wtk_basic_frame_as_child(the_app_files->frame));
00416 break;
00417
00418 case BUTTON_QUIT_ID:
00419 memcpy(&sysfont, &the_app_files->old_sysfont, sizeof(struct font));
00420 membag_free(the_app_files);
00421 app_desktop_restart();
00422 return true;
00423
00424 default:
00425 break;
00426 }
00427
00428 return false;
00429 }
00430
00440 static void app_files_load_worker(struct workqueue_task *task)
00441 {
00442 uint8_t buffer[FONT_HEADER_SIZE];
00443 struct font *font = &font_fixedrus;
00444
00445 hugemem_read_block(buffer, font->data.hugemem, FONT_HEADER_SIZE);
00446
00447 assert(buffer[0] == 'F' && buffer[1] == 'T');
00448
00449 font->width = buffer[2];
00450 font->height = buffer[3];
00451 font->first_char = buffer[4];
00452 font->last_char = buffer[5];
00453 font->data.hugemem = (hugemem_ptr_t)
00454 ((uint32_t)font->data.hugemem + FONT_HEADER_SIZE);
00455
00456 the_app_files->page_number = PAGE_NUM_INTRO_SCREEN;
00457 win_show(wtk_basic_frame_as_child(the_app_files->frame));
00458 }
00459
00465 void app_files_launch(struct workqueue_task *task)
00466 {
00467 struct win_window *win_root;
00468 struct win_window *parent;
00469 struct wtk_button *button;
00470 struct win_area area;
00471
00472 the_app_files = membag_alloc(sizeof(struct app_files));
00473 if (!the_app_files)
00474 goto error_membag_alloc;
00475
00476 the_app_files->page_number = PAGE_NUM_BLANK;
00477
00478
00479 memcpy(&the_app_files->old_sysfont, &sysfont, sizeof(struct font));
00480 sysfont.scale = 2;
00481
00482
00483
00484
00485
00486 the_app_files->task = task;
00487 workqueue_task_set_work_func(the_app_files->task,
00488 app_files_load_worker);
00489
00490
00491 the_app_files->background.type = BITMAP_SOLID;
00492 the_app_files->background.data.color = COLOR_BACKGROUND;
00493
00494 win_root = win_get_root();
00495
00496
00497
00498
00499
00500 area.pos.x = 0;
00501 area.pos.y = 0;
00502 area.size.x = gfx_get_width();
00503 area.size.y = gfx_get_height();
00504
00505 the_app_files->frame = wtk_basic_frame_create(win_root, &area,
00506 &the_app_files->background,
00507 app_files_frame_draw_handler,
00508 app_files_frame_command_handler, &the_app_files);
00509 if (!the_app_files->frame)
00510 goto error_text_frame;
00511
00512 parent = wtk_basic_frame_as_child(the_app_files->frame);
00513
00514
00515 area.size.x = APP_EXIT_BUTTON_SIZE_X;
00516 area.size.y = APP_EXIT_BUTTON_SIZE_Y;
00517 area.pos.x = APP_EXIT_BUTTON_POS_X;
00518 area.pos.y = APP_EXIT_BUTTON_POS_Y;
00519
00520 button = wtk_button_create(parent, &area, APP_EXIT_BUTTON_TEXT,
00521 (win_command_t)BUTTON_QUIT_ID);
00522 if (!button)
00523 goto error_widget;
00524
00525 win_show(wtk_button_as_child(button));
00526
00527
00528 area.pos.x -= APP_EXIT_BUTTON_SIZE_X;
00529
00530 button = wtk_button_create(parent, &area, ">>",
00531 (win_command_t)BUTTON_NEXT_ID);
00532 if (!button)
00533 goto error_widget;
00534
00535 win_show(wtk_button_as_child(button));
00536
00537
00538 area.pos.x -= APP_EXIT_BUTTON_SIZE_X;
00539
00540 button = wtk_button_create(parent, &area, "<<",
00541 (win_command_t)BUTTON_PREV_ID);
00542 if (!button)
00543 goto error_widget;
00544
00545 win_show(wtk_button_as_child(button));
00546
00547
00548
00549
00550
00551 if (!font_fixedrus.data.hugemem) {
00552 hugemem_ptr_t addr = load_file_to_hugemem("f_fixrus",
00553 the_app_files->task);
00554 if (addr == HUGEMEM_NULL)
00555 goto error_widget;
00556
00557 font_fixedrus.data.hugemem = addr;
00558 } else {
00559 the_app_files->page_number = PAGE_NUM_INTRO_SCREEN;
00560 win_show(wtk_basic_frame_as_child(the_app_files->frame));
00561 }
00562
00563 return;
00564
00565 error_widget:
00566 win_destroy(wtk_basic_frame_as_child(the_app_files->frame));
00567 error_text_frame:
00568 memcpy(&sysfont, &the_app_files->old_sysfont, sizeof(struct font));
00569 membag_free(the_app_files);
00570 error_membag_alloc:
00571 app_desktop_restart();
00572 }
00573