diff options
-rw-r--r-- | apps/gui/skin_engine/skin_buffer.c | 2 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_display.c | 196 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 137 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_tokens.c | 2 | ||||
-rw-r--r-- | apps/gui/skin_engine/wps_debug.c | 28 | ||||
-rw-r--r-- | apps/gui/skin_engine/wps_internals.h | 43 |
6 files changed, 188 insertions, 220 deletions
diff --git a/apps/gui/skin_engine/skin_buffer.c b/apps/gui/skin_engine/skin_buffer.c index c7e01ba5cd..1d18fb9431 100644 --- a/apps/gui/skin_engine/skin_buffer.c +++ b/apps/gui/skin_engine/skin_buffer.c | |||
@@ -118,6 +118,8 @@ void* skin_buffer_alloc(size_t size) | |||
118 | buffer_back -= size; | 118 | buffer_back -= size; |
119 | /* 32-bit aligned */ | 119 | /* 32-bit aligned */ |
120 | buffer_back = (void *)(((unsigned long)buffer_back) & ~3); | 120 | buffer_back = (void *)(((unsigned long)buffer_back) & ~3); |
121 | |||
122 | memset(buffer_back, 0, size); | ||
121 | return buffer_back; | 123 | return buffer_back; |
122 | } | 124 | } |
123 | 125 | ||
diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c index 409984494c..4aeafb595d 100644 --- a/apps/gui/skin_engine/skin_display.c +++ b/apps/gui/skin_engine/skin_display.c | |||
@@ -391,41 +391,6 @@ static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size) | |||
391 | 391 | ||
392 | #endif /* HAVE_LCD_CHARCELL */ | 392 | #endif /* HAVE_LCD_CHARCELL */ |
393 | 393 | ||
394 | /* Returns the index of the subline in the subline array | ||
395 | line - 0-based line number | ||
396 | subline - 0-based subline number within the line | ||
397 | */ | ||
398 | static int subline_index(struct wps_data *data, int line, int subline) | ||
399 | { | ||
400 | return data->lines[line].first_subline_idx + subline; | ||
401 | } | ||
402 | |||
403 | /* Returns the index of the first subline's token in the token array | ||
404 | line - 0-based line number | ||
405 | subline - 0-based subline number within the line | ||
406 | */ | ||
407 | static int first_token_index(struct wps_data *data, int line, int subline) | ||
408 | { | ||
409 | int first_subline_idx = data->lines[line].first_subline_idx; | ||
410 | return data->sublines[first_subline_idx + subline].first_token_idx; | ||
411 | } | ||
412 | |||
413 | int skin_last_token_index(struct wps_data *data, int line, int subline) | ||
414 | { | ||
415 | int first_subline_idx = data->lines[line].first_subline_idx; | ||
416 | int idx = first_subline_idx + subline; | ||
417 | if (idx < data->num_sublines - 1) | ||
418 | { | ||
419 | /* This subline ends where the next begins */ | ||
420 | return data->sublines[idx+1].first_token_idx - 1; | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | /* The last subline goes to the end */ | ||
425 | return data->num_tokens - 1; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* Return the index to the end token for the conditional token at index. | 394 | /* Return the index to the end token for the conditional token at index. |
430 | The conditional token can be either a start token or a separator | 395 | The conditional token can be either a start token or a separator |
431 | (i.e. option) token. | 396 | (i.e. option) token. |
@@ -541,7 +506,7 @@ struct skin_viewport* find_viewport(char label, struct wps_data *data) | |||
541 | The return value indicates whether the line needs to be updated. | 506 | The return value indicates whether the line needs to be updated. |
542 | */ | 507 | */ |
543 | static bool get_line(struct gui_wps *gwps, | 508 | static bool get_line(struct gui_wps *gwps, |
544 | int line, int subline, | 509 | struct wps_subline *subline, |
545 | struct align_pos *align, | 510 | struct align_pos *align, |
546 | char *linebuf, | 511 | char *linebuf, |
547 | int linebuf_size) | 512 | int linebuf_size) |
@@ -551,8 +516,8 @@ static bool get_line(struct gui_wps *gwps, | |||
551 | char temp_buf[128]; | 516 | char temp_buf[128]; |
552 | char *buf = linebuf; /* will always point to the writing position */ | 517 | char *buf = linebuf; /* will always point to the writing position */ |
553 | char *linebuf_end = linebuf + linebuf_size - 1; | 518 | char *linebuf_end = linebuf + linebuf_size - 1; |
554 | int i, last_token_idx; | ||
555 | bool update = false; | 519 | bool update = false; |
520 | int i; | ||
556 | 521 | ||
557 | /* alignment-related variables */ | 522 | /* alignment-related variables */ |
558 | int cur_align; | 523 | int cur_align; |
@@ -562,11 +527,9 @@ static bool get_line(struct gui_wps *gwps, | |||
562 | align->left = NULL; | 527 | align->left = NULL; |
563 | align->center = NULL; | 528 | align->center = NULL; |
564 | align->right = NULL; | 529 | align->right = NULL; |
565 | |||
566 | /* Process all tokens of the desired subline */ | 530 | /* Process all tokens of the desired subline */ |
567 | last_token_idx = skin_last_token_index(data, line, subline); | 531 | for (i = subline->first_token_idx; |
568 | for (i = first_token_index(data, line, subline); | 532 | i <= subline->last_token_idx; i++) |
569 | i <= last_token_idx; i++) | ||
570 | { | 533 | { |
571 | switch(data->tokens[i].type) | 534 | switch(data->tokens[i].type) |
572 | { | 535 | { |
@@ -685,18 +648,14 @@ static bool get_line(struct gui_wps *gwps, | |||
685 | 648 | ||
686 | return update; | 649 | return update; |
687 | } | 650 | } |
688 | 651 | static void get_subline_timeout(struct gui_wps *gwps, struct wps_subline *subline) | |
689 | static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) | ||
690 | { | 652 | { |
691 | struct wps_data *data = gwps->data; | 653 | struct wps_data *data = gwps->data; |
692 | int i; | 654 | int i; |
693 | int subline_idx = subline_index(data, line, subline); | 655 | subline->time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; |
694 | int last_token_idx = skin_last_token_index(data, line, subline); | ||
695 | 656 | ||
696 | data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; | 657 | for (i = subline->first_token_idx; |
697 | 658 | i <= subline->last_token_idx; i++) | |
698 | for (i = first_token_index(data, line, subline); | ||
699 | i <= last_token_idx; i++) | ||
700 | { | 659 | { |
701 | switch(data->tokens[i].type) | 660 | switch(data->tokens[i].type) |
702 | { | 661 | { |
@@ -712,7 +671,7 @@ static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) | |||
712 | break; | 671 | break; |
713 | 672 | ||
714 | case WPS_TOKEN_SUBLINE_TIMEOUT: | 673 | case WPS_TOKEN_SUBLINE_TIMEOUT: |
715 | data->sublines[subline_idx].time_mult = data->tokens[i].value.i; | 674 | subline->time_mult = data->tokens[i].value.i; |
716 | break; | 675 | break; |
717 | 676 | ||
718 | default: | 677 | default: |
@@ -723,77 +682,37 @@ static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) | |||
723 | 682 | ||
724 | /* Calculates which subline should be displayed for the specified line | 683 | /* Calculates which subline should be displayed for the specified line |
725 | Returns true iff the subline must be refreshed */ | 684 | Returns true iff the subline must be refreshed */ |
726 | static bool update_curr_subline(struct gui_wps *gwps, int line) | 685 | static bool update_curr_subline(struct gui_wps *gwps, struct wps_line *line) |
727 | { | 686 | { |
728 | struct wps_data *data = gwps->data; | 687 | /* shortcut this whole thing if we need to reset the line completly */ |
729 | 688 | if (line->curr_subline == NULL) | |
730 | int search, search_start, num_sublines; | 689 | { |
731 | bool reset_subline; | 690 | int next_refresh = current_tick; |
732 | bool new_subline_refresh; | 691 | line->curr_subline = &line->sublines; |
733 | bool only_one_subline; | 692 | if (!line->curr_subline->next) |
734 | 693 | next_refresh += 100*HZ; | |
735 | num_sublines = data->lines[line].num_sublines; | 694 | line->subline_expire_time = next_refresh; |
736 | reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET); | 695 | return true; |
737 | new_subline_refresh = false; | 696 | } |
738 | only_one_subline = false; | ||
739 | |||
740 | /* if time to advance to next sub-line */ | 697 | /* if time to advance to next sub-line */ |
741 | if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) || | 698 | if (TIME_AFTER(current_tick, line->subline_expire_time - 1)) |
742 | reset_subline) | ||
743 | { | 699 | { |
744 | /* search all sublines until the next subline with time > 0 | 700 | /* if there is only one subline, there is no need to search for a new one */ |
745 | is found or we get back to the subline we started with */ | 701 | if (&line->sublines == line->curr_subline && |
746 | if (reset_subline) | 702 | line->curr_subline->next == NULL) |
747 | search_start = 0; | ||
748 | else | ||
749 | search_start = data->lines[line].curr_subline; | ||
750 | |||
751 | for (search = 0; search < num_sublines; search++) | ||
752 | { | 703 | { |
753 | data->lines[line].curr_subline++; | 704 | line->subline_expire_time += 100 * HZ; |
754 | 705 | return true; | |
755 | /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */ | ||
756 | if (data->lines[line].curr_subline == num_sublines) | ||
757 | { | ||
758 | if (data->lines[line].curr_subline == 1) | ||
759 | only_one_subline = true; | ||
760 | data->lines[line].curr_subline = 0; | ||
761 | } | ||
762 | |||
763 | /* if back where we started after search or | ||
764 | only one subline is defined on the line */ | ||
765 | if (((search > 0) && | ||
766 | (data->lines[line].curr_subline == search_start)) || | ||
767 | only_one_subline) | ||
768 | { | ||
769 | /* no other subline with a time > 0 exists */ | ||
770 | data->lines[line].subline_expire_time = (reset_subline ? | ||
771 | current_tick : | ||
772 | data->lines[line].subline_expire_time) + 100 * HZ; | ||
773 | break; | ||
774 | } | ||
775 | else | ||
776 | { | ||
777 | /* get initial time multiplier for this subline */ | ||
778 | get_subline_timeout(gwps, line, data->lines[line].curr_subline); | ||
779 | |||
780 | int subline_idx = subline_index(data, line, | ||
781 | data->lines[line].curr_subline); | ||
782 | |||
783 | /* only use this subline if subline time > 0 */ | ||
784 | if (data->sublines[subline_idx].time_mult > 0) | ||
785 | { | ||
786 | new_subline_refresh = true; | ||
787 | data->lines[line].subline_expire_time = (reset_subline ? | ||
788 | current_tick : data->lines[line].subline_expire_time) + | ||
789 | TIMEOUT_UNIT*data->sublines[subline_idx].time_mult; | ||
790 | break; | ||
791 | } | ||
792 | } | ||
793 | } | 706 | } |
707 | if (line->curr_subline->next) | ||
708 | line->curr_subline = line->curr_subline->next; | ||
709 | else | ||
710 | line->curr_subline = &line->sublines; | ||
711 | get_subline_timeout(gwps, line->curr_subline); | ||
712 | line->subline_expire_time += TIMEOUT_UNIT*line->curr_subline->time_mult; | ||
713 | return true; | ||
794 | } | 714 | } |
795 | 715 | return false; | |
796 | return new_subline_refresh; | ||
797 | } | 716 | } |
798 | 717 | ||
799 | /* Display a line appropriately according to its alignment format. | 718 | /* Display a line appropriately according to its alignment format. |
@@ -971,8 +890,7 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
971 | 890 | ||
972 | if (!id3) | 891 | if (!id3) |
973 | return false; | 892 | return false; |
974 | 893 | ||
975 | int line, i, subline_idx; | ||
976 | unsigned flags; | 894 | unsigned flags; |
977 | char linebuf[MAX_PATH]; | 895 | char linebuf[MAX_PATH]; |
978 | 896 | ||
@@ -980,6 +898,9 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
980 | align.left = NULL; | 898 | align.left = NULL; |
981 | align.center = NULL; | 899 | align.center = NULL; |
982 | align.right = NULL; | 900 | align.right = NULL; |
901 | |||
902 | |||
903 | struct skin_token_list *viewport_list; | ||
983 | 904 | ||
984 | bool update_line, new_subline_refresh; | 905 | bool update_line, new_subline_refresh; |
985 | 906 | ||
@@ -999,12 +920,20 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
999 | /* reset to first subline if refresh all flag is set */ | 920 | /* reset to first subline if refresh all flag is set */ |
1000 | if (refresh_mode == WPS_REFRESH_ALL) | 921 | if (refresh_mode == WPS_REFRESH_ALL) |
1001 | { | 922 | { |
923 | struct wps_line *line; | ||
924 | |||
1002 | display->set_viewport(&find_viewport(VP_DEFAULT_LABEL, data)->vp); | 925 | display->set_viewport(&find_viewport(VP_DEFAULT_LABEL, data)->vp); |
1003 | display->clear_viewport(); | 926 | display->clear_viewport(); |
1004 | 927 | ||
1005 | for (i = 0; i <= data->num_lines; i++) | 928 | for (viewport_list = data->viewports; |
929 | viewport_list; viewport_list = viewport_list->next) | ||
1006 | { | 930 | { |
1007 | data->lines[i].curr_subline = SUBLINE_RESET; | 931 | struct skin_viewport *skin_viewport = |
932 | (struct skin_viewport *)viewport_list->token->value.data; | ||
933 | for(line = skin_viewport->lines; line; line = line->next) | ||
934 | { | ||
935 | line->curr_subline = NULL; | ||
936 | } | ||
1008 | } | 937 | } |
1009 | } | 938 | } |
1010 | 939 | ||
@@ -1017,7 +946,6 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
1017 | #endif | 946 | #endif |
1018 | 947 | ||
1019 | /* disable any viewports which are conditionally displayed */ | 948 | /* disable any viewports which are conditionally displayed */ |
1020 | struct skin_token_list *viewport_list; | ||
1021 | for (viewport_list = data->viewports; | 949 | for (viewport_list = data->viewports; |
1022 | viewport_list; viewport_list = viewport_list->next) | 950 | viewport_list; viewport_list = viewport_list->next) |
1023 | { | 951 | { |
@@ -1069,25 +997,27 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
1069 | { | 997 | { |
1070 | display->clear_viewport(); | 998 | display->clear_viewport(); |
1071 | } | 999 | } |
1000 | |||
1001 | /* loop over the lines for this viewport */ | ||
1002 | struct wps_line *line; | ||
1003 | int line_count = 0; | ||
1072 | 1004 | ||
1073 | for (line = skin_viewport->first_line; | 1005 | for (line = skin_viewport->lines; line; line = line->next, line_count++) |
1074 | line <= skin_viewport->last_line; line++) | ||
1075 | { | 1006 | { |
1007 | struct wps_subline *subline; | ||
1076 | memset(linebuf, 0, sizeof(linebuf)); | 1008 | memset(linebuf, 0, sizeof(linebuf)); |
1077 | update_line = false; | 1009 | update_line = false; |
1078 | 1010 | ||
1079 | /* get current subline for the line */ | 1011 | /* get current subline for the line */ |
1080 | new_subline_refresh = update_curr_subline(gwps, line); | 1012 | new_subline_refresh = update_curr_subline(gwps, line); |
1081 | 1013 | subline = line->curr_subline; | |
1082 | subline_idx = subline_index(data, line, | 1014 | flags = line->curr_subline->line_type; |
1083 | data->lines[line].curr_subline); | ||
1084 | flags = data->sublines[subline_idx].line_type; | ||
1085 | 1015 | ||
1086 | if (vp_refresh_mode == WPS_REFRESH_ALL || (flags & vp_refresh_mode) | 1016 | if (vp_refresh_mode == WPS_REFRESH_ALL || (flags & vp_refresh_mode) |
1087 | || new_subline_refresh) | 1017 | || new_subline_refresh) |
1088 | { | 1018 | { |
1089 | /* get_line tells us if we need to update the line */ | 1019 | /* get_line tells us if we need to update the line */ |
1090 | update_line = get_line(gwps, line, data->lines[line].curr_subline, | 1020 | update_line = get_line(gwps, subline, |
1091 | &align, linebuf, sizeof(linebuf)); | 1021 | &align, linebuf, sizeof(linebuf)); |
1092 | } | 1022 | } |
1093 | #ifdef HAVE_LCD_BITMAP | 1023 | #ifdef HAVE_LCD_BITMAP |
@@ -1098,19 +1028,19 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
1098 | update_line = false; | 1028 | update_line = false; |
1099 | 1029 | ||
1100 | int h = font_get(skin_viewport->vp.font)->height; | 1030 | int h = font_get(skin_viewport->vp.font)->height; |
1101 | int peak_meter_y = (line - skin_viewport->first_line)* h; | 1031 | int peak_meter_y = line_count* h; |
1102 | 1032 | ||
1103 | /* The user might decide to have the peak meter in the last | 1033 | /* The user might decide to have the peak meter in the last |
1104 | line so that it is only displayed if no status bar is | 1034 | line so that it is only displayed if no status bar is |
1105 | visible. If so we neither want do draw nor enable the | 1035 | visible. If so we neither want do draw nor enable the |
1106 | peak meter. */ | 1036 | peak meter. */ |
1107 | if (peak_meter_y + h <= display->getheight()) { | 1037 | if (peak_meter_y + h <= skin_viewport->vp.y+skin_viewport->vp.height) { |
1108 | /* found a line with a peak meter -> remember that we must | 1038 | /* found a line with a peak meter -> remember that we must |
1109 | enable it later */ | 1039 | enable it later */ |
1110 | enable_pm = true; | 1040 | enable_pm = true; |
1111 | peak_meter_enabled = true; | 1041 | peak_meter_enabled = true; |
1112 | peak_meter_screen(gwps->display, 0, peak_meter_y, | 1042 | peak_meter_screen(gwps->display, 0, peak_meter_y, |
1113 | MIN(h, display->getheight() - peak_meter_y)); | 1043 | MIN(h, skin_viewport->vp.y+skin_viewport->vp.height - peak_meter_y)); |
1114 | } | 1044 | } |
1115 | else | 1045 | else |
1116 | { | 1046 | { |
@@ -1143,10 +1073,10 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) | |||
1143 | /* if the line is a scrolling one we don't want to update | 1073 | /* if the line is a scrolling one we don't want to update |
1144 | too often, so that it has the time to scroll */ | 1074 | too often, so that it has the time to scroll */ |
1145 | if ((vp_refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) | 1075 | if ((vp_refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) |
1146 | write_line(display, &align, line - skin_viewport->first_line, true); | 1076 | write_line(display, &align, line_count, true); |
1147 | } | 1077 | } |
1148 | else | 1078 | else |
1149 | write_line(display, &align, line - skin_viewport->first_line, false); | 1079 | write_line(display, &align, line_count, false); |
1150 | } | 1080 | } |
1151 | } | 1081 | } |
1152 | 1082 | ||
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 68bddf6205..f8c9b75a87 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c | |||
@@ -72,11 +72,13 @@ static int condindex[WPS_MAX_COND_LEVEL]; | |||
72 | /* number of condtional options in current level */ | 72 | /* number of condtional options in current level */ |
73 | static int numoptions[WPS_MAX_COND_LEVEL]; | 73 | static int numoptions[WPS_MAX_COND_LEVEL]; |
74 | 74 | ||
75 | /* the current line in the file */ | 75 | /* line number, debug only */ |
76 | static int line; | 76 | static int line_number; |
77 | 77 | ||
78 | /* the current viewport */ | 78 | /* the current viewport */ |
79 | static struct skin_viewport *curr_vp; | 79 | static struct skin_viewport *curr_vp; |
80 | /* the current line, linked to the above viewport */ | ||
81 | static struct wps_line *curr_line; | ||
80 | 82 | ||
81 | #ifdef HAVE_LCD_BITMAP | 83 | #ifdef HAVE_LCD_BITMAP |
82 | 84 | ||
@@ -397,7 +399,7 @@ static struct skin_token_list *new_skin_token_list_item(struct wps_token *token, | |||
397 | immediately after the first eol, i.e. to the start of the next line */ | 399 | immediately after the first eol, i.e. to the start of the next line */ |
398 | static int skip_end_of_line(const char *wps_bufptr) | 400 | static int skip_end_of_line(const char *wps_bufptr) |
399 | { | 401 | { |
400 | line++; | 402 | line_number++; |
401 | int skip = 0; | 403 | int skip = 0; |
402 | while(*(wps_bufptr + skip) != '\n') | 404 | while(*(wps_bufptr + skip) != '\n') |
403 | skip++; | 405 | skip++; |
@@ -405,11 +407,59 @@ static int skip_end_of_line(const char *wps_bufptr) | |||
405 | } | 407 | } |
406 | 408 | ||
407 | /* Starts a new subline in the current line during parsing */ | 409 | /* Starts a new subline in the current line during parsing */ |
408 | static void wps_start_new_subline(struct wps_data *data) | 410 | static bool wps_start_new_subline(struct wps_line *line, int curr_token) |
409 | { | 411 | { |
410 | data->num_sublines++; | 412 | struct wps_subline *subline = skin_buffer_alloc(sizeof(struct wps_subline)); |
411 | data->sublines[data->num_sublines].first_token_idx = data->num_tokens; | 413 | if (!subline) |
412 | data->lines[data->num_lines].num_sublines++; | 414 | return false; |
415 | |||
416 | subline->first_token_idx = curr_token; | ||
417 | subline->next = NULL; | ||
418 | |||
419 | subline->line_type = 0; | ||
420 | subline->time_mult = 0; | ||
421 | |||
422 | line->curr_subline->last_token_idx = curr_token-1; | ||
423 | line->curr_subline->next = subline; | ||
424 | line->curr_subline = subline; | ||
425 | return true; | ||
426 | } | ||
427 | |||
428 | static bool wps_start_new_line(struct skin_viewport *vp, int curr_token) | ||
429 | { | ||
430 | struct wps_line *line = skin_buffer_alloc(sizeof(struct wps_line)); | ||
431 | struct wps_subline *subline = NULL; | ||
432 | if (!line) | ||
433 | return false; | ||
434 | |||
435 | /* init the subline */ | ||
436 | subline = &line->sublines; | ||
437 | subline->first_token_idx = curr_token; | ||
438 | subline->next = NULL; | ||
439 | subline->line_type = 0; | ||
440 | subline->time_mult = 0; | ||
441 | |||
442 | /* init the new line */ | ||
443 | line->curr_subline = &line->sublines; | ||
444 | line->next = NULL; | ||
445 | line->subline_expire_time = 0; | ||
446 | |||
447 | /* connect to curr_line and vp pointers. | ||
448 | * 1) close the previous lines subline | ||
449 | * 2) connect to vp pointer | ||
450 | * 3) connect to curr_line global pointer | ||
451 | */ | ||
452 | if (curr_line) | ||
453 | { | ||
454 | curr_line->curr_subline->last_token_idx = curr_token - 1; | ||
455 | curr_line->next = line; | ||
456 | curr_line->curr_subline = NULL; | ||
457 | } | ||
458 | curr_line = line; | ||
459 | if (!vp->lines) | ||
460 | vp->lines = line; | ||
461 | line_number++; | ||
462 | return true; | ||
413 | } | 463 | } |
414 | 464 | ||
415 | #ifdef HAVE_LCD_BITMAP | 465 | #ifdef HAVE_LCD_BITMAP |
@@ -617,6 +667,12 @@ static int parse_viewport(const char *wps_bufptr, | |||
617 | skin_vp->hidden_flags = 0; | 667 | skin_vp->hidden_flags = 0; |
618 | skin_vp->label = VP_NO_LABEL; | 668 | skin_vp->label = VP_NO_LABEL; |
619 | skin_vp->pb = NULL; | 669 | skin_vp->pb = NULL; |
670 | skin_vp->lines = NULL; | ||
671 | |||
672 | curr_line = NULL; | ||
673 | if (!wps_start_new_line(skin_vp, wps_data->num_tokens)) | ||
674 | return WPS_ERROR_INVALID_PARAM; | ||
675 | |||
620 | 676 | ||
621 | if (*ptr == 'l') | 677 | if (*ptr == 'l') |
622 | { | 678 | { |
@@ -647,18 +703,6 @@ static int parse_viewport(const char *wps_bufptr, | |||
647 | if (*ptr != '|') | 703 | if (*ptr != '|') |
648 | return WPS_ERROR_INVALID_PARAM; | 704 | return WPS_ERROR_INVALID_PARAM; |
649 | 705 | ||
650 | curr_vp->last_line = wps_data->num_lines - 1; | ||
651 | |||
652 | skin_vp->first_line = wps_data->num_lines; | ||
653 | |||
654 | if (wps_data->num_sublines < WPS_MAX_SUBLINES) | ||
655 | { | ||
656 | wps_data->lines[wps_data->num_lines].first_subline_idx = | ||
657 | wps_data->num_sublines; | ||
658 | |||
659 | wps_data->sublines[wps_data->num_sublines].first_token_idx = | ||
660 | wps_data->num_tokens; | ||
661 | } | ||
662 | 706 | ||
663 | struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp); | 707 | struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp); |
664 | if (!list) | 708 | if (!list) |
@@ -826,8 +870,15 @@ static int parse_progressbar(const char *wps_bufptr, | |||
826 | #else | 870 | #else |
827 | int font_height = 8; | 871 | int font_height = 8; |
828 | #endif | 872 | #endif |
829 | int line_num = wps_data->num_lines - curr_vp->first_line; | 873 | /* we need to know what line number (viewport relative) this pb is, |
830 | 874 | * so count them... */ | |
875 | int line_num = -1; | ||
876 | struct wps_line *line = curr_vp->lines; | ||
877 | while (line) | ||
878 | { | ||
879 | line_num++; | ||
880 | line = line->next; | ||
881 | } | ||
831 | pb->have_bitmap_pb = false; | 882 | pb->have_bitmap_pb = false; |
832 | pb->bm.data = NULL; /* no bitmap specified */ | 883 | pb->bm.data = NULL; /* no bitmap specified */ |
833 | 884 | ||
@@ -1241,8 +1292,7 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) | |||
1241 | 1292 | ||
1242 | taglen = (tag->type != WPS_TOKEN_UNKNOWN) ? strlen(tag->name) : 2; | 1293 | taglen = (tag->type != WPS_TOKEN_UNKNOWN) ? strlen(tag->name) : 2; |
1243 | token->type = tag->type; | 1294 | token->type = tag->type; |
1244 | wps_data->sublines[wps_data->num_sublines].line_type |= | 1295 | curr_line->curr_subline->line_type |= tag->refresh_type; |
1245 | tag->refresh_type; | ||
1246 | 1296 | ||
1247 | /* if the tag has a special parsing function, we call it */ | 1297 | /* if the tag has a special parsing function, we call it */ |
1248 | if (tag->parse_func) | 1298 | if (tag->parse_func) |
@@ -1282,7 +1332,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) | |||
1282 | int ret; | 1332 | int ret; |
1283 | int max_tokens = TOKEN_BLOCK_SIZE; | 1333 | int max_tokens = TOKEN_BLOCK_SIZE; |
1284 | size_t buf_free = 0; | 1334 | size_t buf_free = 0; |
1285 | line = 1; | 1335 | line_number = 1; |
1286 | level = -1; | 1336 | level = -1; |
1287 | 1337 | ||
1288 | /* allocate enough RAM for a reasonable skin, grow as needed. | 1338 | /* allocate enough RAM for a reasonable skin, grow as needed. |
@@ -1293,8 +1343,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) | |||
1293 | skin_buffer_increment(max_tokens * sizeof(struct wps_token), false); | 1343 | skin_buffer_increment(max_tokens * sizeof(struct wps_token), false); |
1294 | data->num_tokens = 0; | 1344 | data->num_tokens = 0; |
1295 | 1345 | ||
1296 | while(*wps_bufptr && !fail | 1346 | while (*wps_bufptr && !fail) |
1297 | && data->num_lines < WPS_MAX_LINES) | ||
1298 | { | 1347 | { |
1299 | /* first make sure there is enough room for tokens */ | 1348 | /* first make sure there is enough room for tokens */ |
1300 | if (max_tokens -1 == data->num_tokens) | 1349 | if (max_tokens -1 == data->num_tokens) |
@@ -1337,9 +1386,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) | |||
1337 | break; | 1386 | break; |
1338 | } | 1387 | } |
1339 | 1388 | ||
1340 | if (data->num_sublines+1 < WPS_MAX_SUBLINES) | 1389 | if (!wps_start_new_subline(curr_line, data->num_tokens)) |
1341 | wps_start_new_subline(data); | ||
1342 | else | ||
1343 | fail = PARSE_FAIL_LIMITS_EXCEEDED; | 1390 | fail = PARSE_FAIL_LIMITS_EXCEEDED; |
1344 | 1391 | ||
1345 | break; | 1392 | break; |
@@ -1419,19 +1466,16 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) | |||
1419 | fail = PARSE_FAIL_UNCLOSED_COND; | 1466 | fail = PARSE_FAIL_UNCLOSED_COND; |
1420 | break; | 1467 | break; |
1421 | } | 1468 | } |
1469 | /* add a new token for the \n so empty lines are correct */ | ||
1470 | data->tokens[data->num_tokens].type = WPS_TOKEN_CHARACTER; | ||
1471 | data->tokens[data->num_tokens].value.c = '\n'; | ||
1472 | data->tokens[data->num_tokens].next = false; | ||
1473 | data->num_tokens++; | ||
1422 | 1474 | ||
1423 | line++; | 1475 | if (!wps_start_new_line(curr_vp, data->num_tokens)) |
1424 | wps_start_new_subline(data); | 1476 | { |
1425 | data->num_lines++; /* Start a new line */ | 1477 | fail = PARSE_FAIL_LIMITS_EXCEEDED; |
1426 | 1478 | break; | |
1427 | if ((data->num_lines < WPS_MAX_LINES) && | ||
1428 | (data->num_sublines < WPS_MAX_SUBLINES)) | ||
1429 | { | ||
1430 | data->lines[data->num_lines].first_subline_idx = | ||
1431 | data->num_sublines; | ||
1432 | |||
1433 | data->sublines[data->num_sublines].first_token_idx = | ||
1434 | data->num_tokens; | ||
1435 | } | 1479 | } |
1436 | 1480 | ||
1437 | break; | 1481 | break; |
@@ -1511,11 +1555,12 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) | |||
1511 | /* freeup unused tokens */ | 1555 | /* freeup unused tokens */ |
1512 | skin_buffer_free_from_front(sizeof(struct wps_token) | 1556 | skin_buffer_free_from_front(sizeof(struct wps_token) |
1513 | * (max_tokens - data->num_tokens)); | 1557 | * (max_tokens - data->num_tokens)); |
1514 | curr_vp->last_line = data->num_lines - 1; | 1558 | /* close the last subline */ |
1559 | curr_line->curr_subline->last_token_idx = data->num_tokens; | ||
1515 | 1560 | ||
1516 | #if defined(DEBUG) || defined(SIMULATOR) | 1561 | #if defined(DEBUG) || defined(SIMULATOR) |
1517 | if (debug) | 1562 | if (debug) |
1518 | print_debug_info(data, fail, line); | 1563 | print_debug_info(data, fail, line_number); |
1519 | #else | 1564 | #else |
1520 | (void)debug; | 1565 | (void)debug; |
1521 | #endif | 1566 | #endif |
@@ -1658,6 +1703,12 @@ bool skin_data_load(struct wps_data *wps_data, | |||
1658 | curr_vp->vp.height = display->getheight(); | 1703 | curr_vp->vp.height = display->getheight(); |
1659 | curr_vp->pb = NULL; | 1704 | curr_vp->pb = NULL; |
1660 | curr_vp->hidden_flags = 0; | 1705 | curr_vp->hidden_flags = 0; |
1706 | curr_vp->lines = NULL; | ||
1707 | |||
1708 | curr_line = NULL; | ||
1709 | if (!wps_start_new_line(curr_vp, 0)) | ||
1710 | return false; | ||
1711 | |||
1661 | switch (statusbar_position(display->screen_type)) | 1712 | switch (statusbar_position(display->screen_type)) |
1662 | { | 1713 | { |
1663 | case STATUSBAR_OFF: | 1714 | case STATUSBAR_OFF: |
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index 386dc5ded8..1254900844 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c | |||
@@ -164,6 +164,8 @@ const char *get_token_value(struct gui_wps *gwps, | |||
164 | switch (token->type) | 164 | switch (token->type) |
165 | { | 165 | { |
166 | case WPS_TOKEN_CHARACTER: | 166 | case WPS_TOKEN_CHARACTER: |
167 | if (token->value.c == '\n') | ||
168 | return NULL; | ||
167 | return &(token->value.c); | 169 | return &(token->value.c); |
168 | 170 | ||
169 | case WPS_TOKEN_STRING: | 171 | case WPS_TOKEN_STRING: |
diff --git a/apps/gui/skin_engine/wps_debug.c b/apps/gui/skin_engine/wps_debug.c index 78f58c42b1..8e0727516a 100644 --- a/apps/gui/skin_engine/wps_debug.c +++ b/apps/gui/skin_engine/wps_debug.c | |||
@@ -60,8 +60,11 @@ static char *get_token_desc(struct wps_token *token, char *buf, int bufsize) | |||
60 | break; | 60 | break; |
61 | 61 | ||
62 | case WPS_TOKEN_CHARACTER: | 62 | case WPS_TOKEN_CHARACTER: |
63 | snprintf(buf, bufsize, "Character '%c'", | 63 | if (token->value.c == '\n') |
64 | token->value.c); | 64 | snprintf(buf, bufsize, "Character '\\n'"); |
65 | else | ||
66 | snprintf(buf, bufsize, "Character '%c'", | ||
67 | token->value.c); | ||
65 | break; | 68 | break; |
66 | 69 | ||
67 | case WPS_TOKEN_STRING: | 70 | case WPS_TOKEN_STRING: |
@@ -486,7 +489,6 @@ static void dump_wps_tokens(struct wps_data *data) | |||
486 | 489 | ||
487 | static void print_line_info(struct wps_data *data) | 490 | static void print_line_info(struct wps_data *data) |
488 | { | 491 | { |
489 | int i, j; | ||
490 | struct wps_line *line; | 492 | struct wps_line *line; |
491 | struct wps_subline *subline; | 493 | struct wps_subline *subline; |
492 | if (wps_verbose_level > 0) | 494 | if (wps_verbose_level > 0) |
@@ -498,16 +500,14 @@ static void print_line_info(struct wps_data *data) | |||
498 | struct skin_viewport *v = | 500 | struct skin_viewport *v = |
499 | (struct skin_viewport *)viewport_list->token->value.data; | 501 | (struct skin_viewport *)viewport_list->token->value.data; |
500 | DEBUGF("vp Label:'%c' Hidden flags:%x\n", v->label, v->hidden_flags); | 502 | DEBUGF("vp Label:'%c' Hidden flags:%x\n", v->label, v->hidden_flags); |
501 | DEBUGF(" First line: %d\n", v->first_line); | ||
502 | DEBUGF(" Last line: %d\n", v->last_line); | ||
503 | } | 503 | } |
504 | DEBUGF("Number of sublines : %d\n", data->num_sublines); | ||
505 | DEBUGF("Number of tokens : %d\n", data->num_tokens); | 504 | DEBUGF("Number of tokens : %d\n", data->num_tokens); |
506 | DEBUGF("\n"); | 505 | DEBUGF("\n"); |
507 | } | 506 | } |
508 | 507 | ||
509 | if (wps_verbose_level > 1) | 508 | if (wps_verbose_level > 1) |
510 | { | 509 | { |
510 | int line_number = 0; | ||
511 | struct skin_token_list *viewport_list; | 511 | struct skin_token_list *viewport_list; |
512 | for (viewport_list = data->viewports; | 512 | for (viewport_list = data->viewports; |
513 | viewport_list; viewport_list = viewport_list->next) | 513 | viewport_list; viewport_list = viewport_list->next) |
@@ -516,17 +516,15 @@ static void print_line_info(struct wps_data *data) | |||
516 | (struct skin_viewport *)viewport_list->token->value.data; | 516 | (struct skin_viewport *)viewport_list->token->value.data; |
517 | DEBUGF("Viewport '%c' - +%d+%d (%dx%d)\n",v->label, v->vp.x, v->vp.y, | 517 | DEBUGF("Viewport '%c' - +%d+%d (%dx%d)\n",v->label, v->vp.x, v->vp.y, |
518 | v->vp.width, v->vp.height); | 518 | v->vp.width, v->vp.height); |
519 | for (i = v->first_line, line = &data->lines[v->first_line]; i <= v->last_line; i++,line++) | 519 | for (line = v->lines; line; line = line->next, line_number++) |
520 | { | 520 | { |
521 | DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n", | 521 | DEBUGF("Line %2d\n", line_number); |
522 | i, line->num_sublines, line->first_subline_idx); | 522 | int subline_number = 0; |
523 | 523 | subline = &line->sublines; | |
524 | for (j = 0, subline = data->sublines + line->first_subline_idx; | 524 | while (subline) |
525 | j < line->num_sublines; j++, subline++) | ||
526 | { | 525 | { |
527 | DEBUGF(" Subline %d: first_token=%3d, last_token=%3d", | 526 | DEBUGF(" Subline %d: first_token=%3d, last_token=%3d", |
528 | j, subline->first_token_idx, | 527 | subline_number, subline->first_token_idx,subline->last_token_idx); |
529 | skin_last_token_index(data, i, j)); | ||
530 | 528 | ||
531 | if (subline->line_type & WPS_REFRESH_SCROLL) | 529 | if (subline->line_type & WPS_REFRESH_SCROLL) |
532 | DEBUGF(", scrolled"); | 530 | DEBUGF(", scrolled"); |
@@ -536,6 +534,8 @@ static void print_line_info(struct wps_data *data) | |||
536 | DEBUGF(", peakmeter"); | 534 | DEBUGF(", peakmeter"); |
537 | 535 | ||
538 | DEBUGF("\n"); | 536 | DEBUGF("\n"); |
537 | subline = subline->next; | ||
538 | subline_number++; | ||
539 | } | 539 | } |
540 | } | 540 | } |
541 | } | 541 | } |
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index fbd18b9f73..bcc68a88f0 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h | |||
@@ -160,12 +160,16 @@ struct wps_subline { | |||
160 | Tokens of this subline end where tokens for the next subline | 160 | Tokens of this subline end where tokens for the next subline |
161 | begin. */ | 161 | begin. */ |
162 | unsigned short first_token_idx; | 162 | unsigned short first_token_idx; |
163 | unsigned short last_token_idx; | ||
163 | 164 | ||
164 | /* Bit or'ed WPS_REFRESH_xxx */ | 165 | /* Bit or'ed WPS_REFRESH_xxx */ |
165 | unsigned char line_type; | 166 | unsigned char line_type; |
166 | 167 | ||
167 | /* How long the subline should be displayed, in 10ths of sec */ | 168 | /* How long the subline should be displayed, in 10ths of sec */ |
168 | unsigned char time_mult; | 169 | unsigned char time_mult; |
170 | |||
171 | /* pointer to the next subline in this line */ | ||
172 | struct wps_subline *next; | ||
169 | }; | 173 | }; |
170 | 174 | ||
171 | /* Description of a line on the WPS. A line is a set of sublines. | 175 | /* Description of a line on the WPS. A line is a set of sublines. |
@@ -173,19 +177,18 @@ struct wps_subline { | |||
173 | the next subline of the line is displayed. And so on. */ | 177 | the next subline of the line is displayed. And so on. */ |
174 | struct wps_line { | 178 | struct wps_line { |
175 | 179 | ||
176 | /* Number of sublines in this line */ | 180 | /* Linked list of all the sublines on this line, |
177 | signed char num_sublines; | 181 | * a line *must* have at least one subline so no need to add an extra pointer */ |
178 | 182 | struct wps_subline sublines; | |
179 | /* Number (0-based) of the subline within this line currently being displayed */ | 183 | /* pointer to the current subline */ |
180 | signed char curr_subline; | 184 | struct wps_subline *curr_subline; |
181 | |||
182 | /* Index of the first subline of this line in the subline array. | ||
183 | Sublines for this line end where sublines for the next line begin. */ | ||
184 | unsigned short first_subline_idx; | ||
185 | 185 | ||
186 | /* When the next subline of this line should be displayed | 186 | /* When the next subline of this line should be displayed |
187 | (absolute time value in ticks) */ | 187 | (absolute time value in ticks) */ |
188 | long subline_expire_time; | 188 | long subline_expire_time; |
189 | |||
190 | /* pointer to the next line */ | ||
191 | struct wps_line *next; | ||
189 | }; | 192 | }; |
190 | 193 | ||
191 | #define VP_DRAW_HIDEABLE 0x1 | 194 | #define VP_DRAW_HIDEABLE 0x1 |
@@ -196,9 +199,7 @@ struct wps_line { | |||
196 | struct skin_viewport { | 199 | struct skin_viewport { |
197 | struct viewport vp; /* The LCD viewport struct */ | 200 | struct viewport vp; /* The LCD viewport struct */ |
198 | struct progressbar *pb; | 201 | struct progressbar *pb; |
199 | /* Indexes of the first and last lines belonging to this viewport in the | 202 | struct wps_line *lines; |
200 | lines[] array */ | ||
201 | int first_line, last_line; | ||
202 | char hidden_flags; | 203 | char hidden_flags; |
203 | char label; | 204 | char label; |
204 | }; | 205 | }; |
@@ -259,20 +260,8 @@ struct wps_data | |||
259 | bool remote_wps; | 260 | bool remote_wps; |
260 | #endif | 261 | #endif |
261 | 262 | ||
262 | /* Number of lines in the WPS. During WPS parsing, this is | ||
263 | the index of the line being parsed. */ | ||
264 | int num_lines; | ||
265 | |||
266 | /* Number of viewports in the WPS */ | ||
267 | struct skin_token_list *viewports; | 263 | struct skin_token_list *viewports; |
268 | 264 | ||
269 | struct wps_line lines[WPS_MAX_LINES]; | ||
270 | |||
271 | /* Total number of sublines in the WPS. During WPS parsing, this is | ||
272 | the index of the subline where the parsed tokens are added to. */ | ||
273 | int num_sublines; | ||
274 | struct wps_subline sublines[WPS_MAX_SUBLINES]; | ||
275 | |||
276 | /* Total number of tokens in the WPS. During WPS parsing, this is | 265 | /* Total number of tokens in the WPS. During WPS parsing, this is |
277 | the index of the token being parsed. */ | 266 | the index of the token being parsed. */ |
278 | int num_tokens; | 267 | int num_tokens; |
@@ -286,12 +275,6 @@ struct wps_data | |||
286 | unsigned int button_time_volume; | 275 | unsigned int button_time_volume; |
287 | }; | 276 | }; |
288 | 277 | ||
289 | /* Returns the index of the last subline's token in the token array. | ||
290 | line - 0-based line number | ||
291 | subline - 0-based subline number within the line | ||
292 | */ | ||
293 | int skin_last_token_index(struct wps_data *data, int line, int subline); | ||
294 | |||
295 | /* wps_data end */ | 278 | /* wps_data end */ |
296 | 279 | ||
297 | /* wps_state | 280 | /* wps_state |