diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index b284cf4d83..5e1cd99fae 100755 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -3911,35 +3911,47 @@ static void xmb_list_free(file_list_t *list, size_t a, size_t b) xmb_list_clear(list); } -static void xmb_list_deep_copy(const file_list_t *src, file_list_t *dst) +static void xmb_list_deep_copy(const file_list_t *src, file_list_t *dst, + size_t first, size_t last) { - size_t i; + size_t i, j = 0; menu_animation_ctx_tag tag = (uintptr_t)dst; - size_t size = dst->size; menu_animation_ctl(MENU_ANIMATION_CTL_KILL_BY_TAG, &tag); /* use true here because file_list_copy() doesn't free actiondata */ xmb_free_list_nodes(dst, true); - file_list_copy(src, dst); - size = dst->size; + file_list_clear(dst); + file_list_reserve(dst, (last + 1) - first); - for (i = 0; i < size; ++i) + for (i = first; i <= last; ++i) { - void *src_udata = menu_entries_get_userdata_at_offset(src, i); - void *src_adata = (void*)menu_entries_get_actiondata_at_offset(src, i); + struct item_file *d = &dst->list[j]; + struct item_file *s = &src->list[i]; + + void *src_udata = s->userdata; + void *src_adata = s->actiondata; + + *d = *s; + d->alt = string_is_empty(d->alt) ? NULL : strdup(d->alt); + d->path = string_is_empty(d->path) ? NULL : strdup(d->path); + d->label = string_is_empty(d->label) ? NULL : strdup(d->label); if (src_udata) - file_list_set_userdata(dst, i, (xmb_node_t*)xmb_copy_node(src_udata)); + file_list_set_userdata(dst, j, (xmb_node_t*)xmb_copy_node(src_udata)); if (src_adata) { void *data = malloc(sizeof(menu_file_list_cbs_t)); memcpy(data, src_adata, sizeof(menu_file_list_cbs_t)); - file_list_set_actiondata(dst, i, data); + file_list_set_actiondata(dst, j, data); } + + ++j; } + + dst->size = j; } static void xmb_list_cache(void *data, enum menu_list_type type, unsigned action) @@ -3954,16 +3966,30 @@ static void xmb_list_cache(void *data, enum menu_list_type type, unsigned action if (!xmb) return; - /* Check whether to enable the horizontal animation. */ - if (settings->bools.menu_horizontal_animation) - xmb_list_deep_copy(selection_buf, xmb->selection_buf_old); - /* FIXME: this shouldn't be happening at all */ if (selection >= xmb->selection_buf_old->size) selection = xmb->selection_buf_old->size ? xmb->selection_buf_old->size - 1 : 0; xmb->selection_ptr_old = selection; + /* Check whether to enable the horizontal animation. */ + if (settings->bools.menu_horizontal_animation) + { + unsigned first = 0, last = 0; + unsigned height = 0; + video_driver_get_size(NULL, &height); + + xmb_calculate_visible_range(xmb, height, selection_buf->size, + xmb->selection_ptr_old, &first, &last); + + xmb_list_deep_copy(selection_buf, xmb->selection_buf_old, first, last); + + xmb->selection_ptr_old -= first; + last -= first; + first = 0; + } + + list_size = xmb_list_get_size(xmb, MENU_LIST_HORIZONTAL) + xmb->system_tab_end; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index fcd2a38541..d745f9028c 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1550,6 +1550,9 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info, menu_driver_set_thumbnail_system(lpl_basename, sizeof(lpl_basename)); } + /* prealocate the file list */ + file_list_reserve(info->list, list_size); + for (i = 0; i < list_size; i++) { char fill_buf[PATH_MAX_LENGTH];