diff options
Diffstat (limited to 'apps/tree.c')
-rw-r--r-- | apps/tree.c | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/apps/tree.c b/apps/tree.c index 211ddb2f9b..c7484ff420 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -104,12 +104,18 @@ static int ft_play_dirname(char* name); | |||
104 | static void ft_play_filename(char *dir, char *file); | 104 | static void ft_play_filename(char *dir, char *file); |
105 | static void say_filetype(int attr); | 105 | static void say_filetype(int attr); |
106 | 106 | ||
107 | static struct entry* get_entry_at(struct tree_context *t, int index) | 107 | struct entry* tree_get_entries(struct tree_context *t) |
108 | { | 108 | { |
109 | struct entry* entries = t->cache.entries; | 109 | return core_get_data(t->cache.entries_handle); |
110 | } | ||
111 | |||
112 | struct entry* tree_get_entry_at(struct tree_context *t, int index) | ||
113 | { | ||
114 | struct entry* entries = tree_get_entries(t); | ||
110 | return &entries[index]; | 115 | return &entries[index]; |
111 | } | 116 | } |
112 | 117 | ||
118 | |||
113 | static const char* tree_get_filename(int selected_item, void *data, | 119 | static const char* tree_get_filename(int selected_item, void *data, |
114 | char *buffer, size_t buffer_len) | 120 | char *buffer, size_t buffer_len) |
115 | { | 121 | { |
@@ -122,12 +128,12 @@ static const char* tree_get_filename(int selected_item, void *data, | |||
122 | 128 | ||
123 | if (id3db) | 129 | if (id3db) |
124 | { | 130 | { |
125 | return tagtree_get_entry(&tc, selected_item)->name; | 131 | return tagtree_get_entry_name(&tc, selected_item, buffer, buffer_len); |
126 | } | 132 | } |
127 | else | 133 | else |
128 | #endif | 134 | #endif |
129 | { | 135 | { |
130 | struct entry* e = get_entry_at(local_tc, selected_item); | 136 | struct entry* e = tree_get_entry_at(local_tc, selected_item); |
131 | name = e->name; | 137 | name = e->name; |
132 | attr = e->attr; | 138 | attr = e->attr; |
133 | } | 139 | } |
@@ -169,7 +175,7 @@ static int tree_get_filecolor(int selected_item, void * data) | |||
169 | if (*tc.dirfilter == SHOW_ID3DB) | 175 | if (*tc.dirfilter == SHOW_ID3DB) |
170 | return -1; | 176 | return -1; |
171 | struct tree_context * local_tc=(struct tree_context *)data; | 177 | struct tree_context * local_tc=(struct tree_context *)data; |
172 | struct entry* e = get_entry_at(local_tc, selected_item); | 178 | struct entry* e = tree_get_entry_at(local_tc, selected_item); |
173 | return filetype_get_color(e->name, e->attr); | 179 | return filetype_get_color(e->name, e->attr); |
174 | } | 180 | } |
175 | #endif | 181 | #endif |
@@ -185,7 +191,7 @@ static enum themable_icons tree_get_fileicon(int selected_item, void * data) | |||
185 | else | 191 | else |
186 | #endif | 192 | #endif |
187 | { | 193 | { |
188 | struct entry* e = get_entry_at(local_tc, selected_item); | 194 | struct entry* e = tree_get_entry_at(local_tc, selected_item); |
189 | return filetype_get_icon(e->attr); | 195 | return filetype_get_icon(e->attr); |
190 | } | 196 | } |
191 | } | 197 | } |
@@ -197,16 +203,17 @@ static int tree_voice_cb(int selected_item, void * data) | |||
197 | int attr=0; | 203 | int attr=0; |
198 | #ifdef HAVE_TAGCACHE | 204 | #ifdef HAVE_TAGCACHE |
199 | bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB; | 205 | bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB; |
206 | char buf[AVERAGE_FILENAME_LENGTH*2]; | ||
200 | 207 | ||
201 | if (id3db) | 208 | if (id3db) |
202 | { | 209 | { |
203 | attr = tagtree_get_attr(local_tc); | 210 | attr = tagtree_get_attr(local_tc); |
204 | name = tagtree_get_entry(local_tc, selected_item)->name; | 211 | name = tagtree_get_entry_name(local_tc, selected_item, buf, sizeof(buf)); |
205 | } | 212 | } |
206 | else | 213 | else |
207 | #endif | 214 | #endif |
208 | { | 215 | { |
209 | struct entry* e = get_entry_at(local_tc, selected_item); | 216 | struct entry* e = tree_get_entry_at(local_tc, selected_item); |
210 | name = e->name; | 217 | name = e->name; |
211 | attr = e->attr; | 218 | attr = e->attr; |
212 | } | 219 | } |
@@ -329,7 +336,7 @@ static int tree_get_file_position(char * filename) | |||
329 | /* use lastfile to determine the selected item (default=0) */ | 336 | /* use lastfile to determine the selected item (default=0) */ |
330 | for (i=0; i < tc.filesindir; i++) | 337 | for (i=0; i < tc.filesindir; i++) |
331 | { | 338 | { |
332 | e = get_entry_at(&tc, i); | 339 | e = tree_get_entry_at(&tc, i); |
333 | if (!strcasecmp(e->name, filename)) | 340 | if (!strcasecmp(e->name, filename)) |
334 | return(i); | 341 | return(i); |
335 | } | 342 | } |
@@ -531,7 +538,7 @@ char* get_current_file(char* buffer, size_t buffer_len) | |||
531 | return NULL; | 538 | return NULL; |
532 | #endif | 539 | #endif |
533 | 540 | ||
534 | struct entry* e = get_entry_at(&tc, tc.selected_item); | 541 | struct entry* e = tree_get_entry_at(&tc, tc.selected_item); |
535 | if (getcwd(buffer, buffer_len)) | 542 | if (getcwd(buffer, buffer_len)) |
536 | { | 543 | { |
537 | if (tc.dirlength) | 544 | if (tc.dirlength) |
@@ -650,7 +657,6 @@ static int dirbrowse(void) | |||
650 | 657 | ||
651 | gui_synclist_draw(&tree_lists); | 658 | gui_synclist_draw(&tree_lists); |
652 | while(1) { | 659 | while(1) { |
653 | struct entry *entries = tc.cache.entries; | ||
654 | bool restore = false; | 660 | bool restore = false; |
655 | if (tc.dirlevel < 0) | 661 | if (tc.dirlevel < 0) |
656 | tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */ | 662 | tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */ |
@@ -666,8 +672,9 @@ static int dirbrowse(void) | |||
666 | if ( numentries == 0 ) | 672 | if ( numentries == 0 ) |
667 | break; | 673 | break; |
668 | 674 | ||
675 | short attr = tree_get_entry_at(&tc, tc.selected_item)->attr; | ||
669 | if ((tc.browse->flags & BROWSE_SELECTONLY) && | 676 | if ((tc.browse->flags & BROWSE_SELECTONLY) && |
670 | !(entries[tc.selected_item].attr & ATTR_DIRECTORY)) | 677 | !(attr & ATTR_DIRECTORY)) |
671 | { | 678 | { |
672 | tc.browse->flags |= BROWSE_SELECTED; | 679 | tc.browse->flags |= BROWSE_SELECTED; |
673 | get_current_file(tc.browse->buf, tc.browse->bufsize); | 680 | get_current_file(tc.browse->buf, tc.browse->bufsize); |
@@ -792,15 +799,14 @@ static int dirbrowse(void) | |||
792 | else | 799 | else |
793 | #endif | 800 | #endif |
794 | { | 801 | { |
795 | attr = entries[tc.selected_item].attr; | 802 | struct entry *entry = tree_get_entry_at(&tc, tc.selected_item); |
803 | attr = entry->attr; | ||
796 | 804 | ||
797 | if (currdir[1]) /* Not in / */ | 805 | if (currdir[1]) /* Not in / */ |
798 | snprintf(buf, sizeof buf, "%s/%s", | 806 | snprintf(buf, sizeof buf, "%s/%s", |
799 | currdir, | 807 | currdir, entry->name); |
800 | entries[tc.selected_item].name); | ||
801 | else /* In / */ | 808 | else /* In / */ |
802 | snprintf(buf, sizeof buf, "/%s", | 809 | snprintf(buf, sizeof buf, "/%s", entry->name); |
803 | entries[tc.selected_item].name); | ||
804 | } | 810 | } |
805 | onplay_result = onplay(buf, attr, curr_context, hotkey); | 811 | onplay_result = onplay(buf, attr, curr_context, hotkey); |
806 | } | 812 | } |
@@ -999,10 +1005,36 @@ int rockbox_browse(struct browse_context *browse) | |||
999 | return ret_val; | 1005 | return ret_val; |
1000 | } | 1006 | } |
1001 | 1007 | ||
1008 | static int move_callback(int handle, void* current, void* new) | ||
1009 | { | ||
1010 | struct tree_cache* cache = &tc.cache; | ||
1011 | if (cache->lock_count > 0) | ||
1012 | return BUFLIB_CB_CANNOT_MOVE; | ||
1013 | |||
1014 | size_t diff = new - current; | ||
1015 | /* FIX_PTR makes sure to not accidentally update static allocations */ | ||
1016 | #define FIX_PTR(x) \ | ||
1017 | { if ((void*)x > current && (void*)x < (current+cache->name_buffer_size)) x+= diff; } | ||
1018 | |||
1019 | if (handle == cache->name_buffer_handle) | ||
1020 | { /* update entry structs, *even if they are struct tagentry */ | ||
1021 | struct entry *this = core_get_data(cache->entries_handle); | ||
1022 | struct entry *last = this + cache->max_entries; | ||
1023 | for(; this < last; this++) | ||
1024 | FIX_PTR(this->name); | ||
1025 | } | ||
1026 | /* nothing to do if entries moved */ | ||
1027 | return BUFLIB_CB_OK; | ||
1028 | } | ||
1029 | |||
1030 | static struct buflib_callbacks ops = { | ||
1031 | .move_callback = move_callback, | ||
1032 | .shrink_callback = NULL, | ||
1033 | }; | ||
1034 | |||
1002 | void tree_mem_init(void) | 1035 | void tree_mem_init(void) |
1003 | { | 1036 | { |
1004 | /* initialize tree context struct */ | 1037 | /* initialize tree context struct */ |
1005 | int handle; | ||
1006 | struct tree_cache* cache = &tc.cache; | 1038 | struct tree_cache* cache = &tc.cache; |
1007 | memset(&tc, 0, sizeof(tc)); | 1039 | memset(&tc, 0, sizeof(tc)); |
1008 | tc.dirfilter = &global_settings.dirfilter; | 1040 | tc.dirfilter = &global_settings.dirfilter; |
@@ -1010,12 +1042,14 @@ void tree_mem_init(void) | |||
1010 | 1042 | ||
1011 | cache->name_buffer_size = AVERAGE_FILENAME_LENGTH * | 1043 | cache->name_buffer_size = AVERAGE_FILENAME_LENGTH * |
1012 | global_settings.max_files_in_dir; | 1044 | global_settings.max_files_in_dir; |
1013 | handle = core_alloc("tree names", cache->name_buffer_size); | 1045 | cache->name_buffer_handle = core_alloc_ex("tree names", |
1014 | cache->name_buffer = core_get_data(handle); | 1046 | cache->name_buffer_size, |
1047 | &ops); | ||
1015 | 1048 | ||
1016 | cache->max_entries = global_settings.max_files_in_dir; | 1049 | cache->max_entries = global_settings.max_files_in_dir; |
1017 | handle = core_alloc("tree entries", cache->max_entries*(sizeof(struct entry))); | 1050 | cache->entries_handle = core_alloc_ex("tree entries", |
1018 | cache->entries = core_get_data(handle); | 1051 | cache->max_entries*(sizeof(struct entry)), |
1052 | &ops); | ||
1019 | tree_get_filetypes(&filetypes, &filetypes_count); | 1053 | tree_get_filetypes(&filetypes, &filetypes_count); |
1020 | } | 1054 | } |
1021 | 1055 | ||