1 /*
2  * uiimagefilereq.c - Functions to select a file inside a D64/T64 Image
3  *
4  * Written by
5  *  groepaz <groepaz@gmx.net>
6  *
7  * This file is part of VICE, the Versatile Commodore Emulator.
8  * See README for copyright notice.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23  *  02111-1307  USA.
24  *
25  */
26 
27 #include "vice.h"
28 #include "types.h"
29 
30 #include "vice_sdl.h"
31 #include <string.h>
32 
33 #include "archdep.h"
34 #include "diskcontents.h"
35 #include "tapecontents.h"
36 #include "imagecontents.h"
37 #include "ioutil.h"
38 #include "lib.h"
39 #include "ui.h"
40 #include "uimenu.h"
41 #include "uifilereq.h"
42 #include "util.h"
43 #include "menu_common.h"
44 
45 #define SDL_FILEREQ_META_NUM 0
46 
47 #define IMAGE_FIRST_Y 1
48 
49 static menu_draw_t *menu_draw;
50 
sdl_ui_image_file_selector_redraw(image_contents_t * contents,const char * title,int offset,int num_items,int more,ui_menu_filereq_mode_t mode,int cur_offset)51 static void sdl_ui_image_file_selector_redraw(image_contents_t *contents, const char *title, int offset, int num_items, int more, ui_menu_filereq_mode_t mode, int cur_offset)
52 {
53     int i, j;
54     char* title_string;
55     char* name;
56     uint8_t oldbg;
57     image_contents_file_list_t *entry;
58 
59     title_string = image_contents_to_string(contents, 0);
60 
61     sdl_ui_clear();
62     sdl_ui_display_title(title_string);
63     lib_free(title_string);
64 
65     entry = contents->file_list;
66     for (i = 0; i < offset; ++i) {
67         entry = entry->next;
68     }
69     for (i = 0; i < num_items; ++i) {
70         if (i == cur_offset) {
71             oldbg = sdl_ui_set_cursor_colors();
72         }
73 
74         j = MENU_FIRST_X;
75         name = image_contents_file_to_string(entry, IMAGE_CONTENTS_STRING_PETSCII);
76         j += sdl_ui_print(name, j, i + IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
77 
78         if (i == cur_offset) {
79             sdl_ui_print_eol(j, i + IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
80             sdl_ui_reset_cursor_colors(oldbg);
81         }
82         entry = entry->next;
83     }
84     name = lib_msprintf("%d BLOCKS FREE.", contents->blocks_free);
85     sdl_ui_print(name, MENU_FIRST_X, i + IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
86     lib_free(name);
87 }
88 
sdl_ui_image_file_selector_redraw_cursor(image_contents_t * contents,int offset,int num_items,ui_menu_filereq_mode_t mode,int cur_offset,int old_offset)89 static void sdl_ui_image_file_selector_redraw_cursor(image_contents_t *contents, int offset, int num_items, ui_menu_filereq_mode_t mode, int cur_offset, int old_offset)
90 {
91     int i, j;
92     char* name;
93     uint8_t oldbg = 0;
94     image_contents_file_list_t *entry;
95 
96     entry = contents->file_list;
97     for (i = 0; i < offset; ++i) {
98         entry = entry->next;
99     }
100     for (i = 0; i < num_items; ++i) {
101         if ((i == cur_offset) || (i == old_offset)){
102             if (i == cur_offset) {
103                 oldbg = sdl_ui_set_cursor_colors();
104             }
105             j = MENU_FIRST_X;
106             name = image_contents_file_to_string(entry, IMAGE_CONTENTS_STRING_PETSCII);
107             j += sdl_ui_print(name, j, i + IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
108 
109             sdl_ui_print_eol(j, i + IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
110             if (i == cur_offset) {
111                 sdl_ui_reset_cursor_colors(oldbg);
112             }
113         }
114         entry = entry->next;
115     }
116 }
117 
118 /* ------------------------------------------------------------------ */
119 /* External UI interface */
120 
sdl_ui_image_file_selection_dialog(const char * filename,ui_menu_filereq_mode_t mode)121 int sdl_ui_image_file_selection_dialog(const char* filename, ui_menu_filereq_mode_t mode)
122 {
123     int total, dirs = 0, files, menu_max;
124     int active = 1;
125     int offset = 0;
126     int redraw = 1;
127     int cur = 0, cur_old = -1;
128 
129     image_contents_t *contents = NULL;
130     image_contents_file_list_t *entry;
131     int retval = -1;
132 
133     menu_draw = sdl_ui_get_menu_param();
134 
135     /* FIXME: it might be a good idea to wrap this into a common imagecontents_read */
136     contents = tapecontents_read(filename);
137     if (contents == NULL) {
138         contents = diskcontents_read(filename, 0 /* FIXME: unit */, 0 /* FIXME: drive */);
139         if (contents == NULL) {
140             return 0;
141         }
142     }
143 
144     /* count files in the list */
145     files = 0;
146     for (entry = contents->file_list; entry != NULL; entry = entry->next) {
147         files++;
148     }
149 
150     total = dirs + files + SDL_FILEREQ_META_NUM;
151     menu_max = menu_draw->max_text_y - (IMAGE_FIRST_Y + SDL_FILEREQ_META_NUM);
152     if (menu_max > 0) { menu_max--; } /* make room for BLOCKS FREE */
153 
154     while (active) {
155 
156         sdl_ui_set_active_font(MENU_FONT_IMAGES);
157 
158         if (redraw) {
159             sdl_ui_image_file_selector_redraw(contents, filename, offset,
160                 (total - offset > menu_max) ? menu_max : total - offset,
161                 (total - offset > menu_max) ? 1 : 0, mode, cur);
162             redraw = 0;
163         } else {
164             sdl_ui_image_file_selector_redraw_cursor(contents, offset,
165                     (total - offset > menu_max) ? menu_max : total - offset,
166                     mode, cur, cur_old);
167         }
168 
169         sdl_ui_set_active_font(MENU_FONT_ASCII);
170 
171         sdl_ui_refresh();
172 
173         switch (sdl_ui_menu_poll_input()) {
174             case MENU_ACTION_HOME:
175                 cur_old = cur;
176                 cur = 0;
177                 offset = 0;
178                 redraw = 1;
179                 break;
180 
181             case MENU_ACTION_END:
182                 cur_old = cur;
183                 if (total < (menu_max - 1)) {
184                     cur = total - 1;
185                     offset = 0;
186                 } else {
187                     cur = menu_max - 1;
188                     offset = total - menu_max;
189                 }
190                 redraw = 1;
191                 break;
192 
193             case MENU_ACTION_UP:
194                 if (cur > 0) {
195                     cur_old = cur;
196                     --cur;
197                 } else {
198                     if (offset > 0) {
199                         offset--;
200                         redraw = 1;
201                     }
202                 }
203                 break;
204 
205             case MENU_ACTION_PAGEUP:
206             case MENU_ACTION_LEFT:
207                 offset -= menu_max;
208                 if (offset < 0) {
209                     offset = 0;
210                     cur_old = -1;
211                     cur = 0;
212                 }
213                 redraw = 1;
214                 break;
215 
216             case MENU_ACTION_DOWN:
217                 if (cur < (menu_max - 1)) {
218                     if ((cur + offset) < total - 1) {
219                         cur_old = cur;
220                         ++cur;
221                     }
222                 } else {
223                     if (offset < (total - menu_max)) {
224                         offset++;
225                         redraw = 1;
226                     }
227                 }
228                 break;
229 
230             case MENU_ACTION_PAGEDOWN:
231             case MENU_ACTION_RIGHT:
232                 offset += menu_max;
233                 if (offset >= total) {
234                     offset = total - 1;
235                     cur_old = -1;
236                     cur = 0;
237                 } else if ((cur + offset) >= total) {
238                     cur_old = -1;
239                     cur = total - offset - 1;
240                 }
241                 redraw = 1;
242                 break;
243 
244             case MENU_ACTION_SELECT:
245                 active = 0;
246                 retval = offset + cur - dirs - SDL_FILEREQ_META_NUM + 1;
247                 break;
248 
249             case MENU_ACTION_CANCEL:
250             case MENU_ACTION_EXIT:
251                 active = 0;
252                 break;
253 
254             default:
255                 SDL_Delay(10);
256                 break;
257         }
258     }
259     lib_free(contents);
260     return retval;
261 }
262