]> icculus.org git repositories - btb/d2x.git/blob - ui/file.c
more header cleanup
[btb/d2x.git] / ui / file.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <physfs.h>
17
18 #include "fix.h"
19 #include "gr.h"
20 #include "key.h"
21 #include "vid.h"
22 #include "strutil.h"
23 #include "ui.h"
24 #include "mono.h"
25 #include "u_mem.h"
26
27
28 int file_sort_func(char **e0, char **e1)
29 {
30         return stricmp(*e0, *e1);
31 }
32
33
34 char **file_getdirlist(int *NumDirs, char *dir)
35 {
36         char    path[PATH_MAX];
37         char    **list = PHYSFS_enumerateFiles(dir);
38         char    **i, **j = list;
39         char    *test_filename;
40         int             test_max;
41
42         if (!list)
43                 return NULL;
44
45         strcpy(path, dir);
46         if (*path)
47                 strncat(path, "/", PATH_MAX - strlen(dir));
48
49         test_filename = path + strlen(path);
50         test_max = PATH_MAX - (test_filename - path);
51
52         for (i = list; *i; i++)
53         {
54                 if (strlen(*i) >= test_max)
55                         continue;
56
57                 strcpy(test_filename, *i);
58                 if (PHYSFS_isDirectory(path))
59                         *j++ = *i;
60                 else
61                         free(*i);
62         }
63         *j = NULL;
64
65         *NumDirs = j - list;
66         qsort(list, *NumDirs, sizeof(char *), (int (*)( const void *, const void * ))file_sort_func);
67
68         if (*dir)
69         {
70                 // Put the 'go to parent directory' sequence '..' first
71                 (*NumDirs)++;
72                 list = realloc(list, sizeof(char *)*(*NumDirs + 1));
73                 list[*NumDirs] = NULL;  // terminate
74                 for (i = list + *NumDirs - 1; i != list; i--)
75                         *i = i[-1];
76                 list[0] = strdup("..");
77         }
78
79         return list;
80 }
81
82 char **file_getfilelist(int *NumFiles, char *filespec, char *dir)
83 {
84         char **list = PHYSFS_enumerateFiles(dir);
85         char **i, **j = list, *ext;
86
87         if (!list)
88                 return NULL;
89
90         if (*filespec == '*')
91                 filespec++;
92
93         for (i = list; *i; i++)
94         {
95                 ext = strrchr(*i, '.');
96                 if (ext && (!stricmp(ext, filespec)))
97                         *j++ = *i;
98                 else
99                         free(*i);
100         }
101         *j = NULL;
102
103
104         *NumFiles = j - list;
105         qsort(list, *NumFiles, sizeof(char *), (int (*)( const void *, const void * ))file_sort_func);
106
107         return list;
108 }
109
110 int ui_get_filename( char * filename, char * Filespec, char * message  )
111 {
112         char            ViewDir[PATH_MAX];
113         char            InputText[PATH_MAX];
114         char            *p;
115         PHYSFS_file     *TempFile;
116         int                     NumFiles, NumDirs,i;
117         char            **filename_list;
118         char            **directory_list;
119         char            Spaces[35];
120         UI_WINDOW                       *wnd;
121         UI_GADGET_BUTTON        *Button1, *Button2, *HelpButton;
122         UI_GADGET_LISTBOX       *ListBox1;
123         UI_GADGET_LISTBOX       *ListBox2;
124         UI_GADGET_INPUTBOX      *UserFile;
125         int                             new_listboxes;
126
127         if ((p = strrchr(filename, '/')))
128         {
129                 *p++ = 0;
130                 strcpy(ViewDir, filename);
131                 strcpy(InputText, p);
132         }
133         else
134         {
135                 strcpy(ViewDir, "");
136                 strcpy(InputText, filename);
137         }
138
139         filename_list = file_getfilelist(&NumFiles, Filespec, ViewDir);
140         directory_list = file_getdirlist(&NumDirs, ViewDir);
141
142         // Running out of memory may become likely in the future
143         if (!filename_list && !directory_list)
144                 return 0;
145
146         if (!filename_list)
147         {
148                 PHYSFS_freeList(directory_list);
149                 return 0;
150         }
151
152         if (!directory_list)
153         {
154                 PHYSFS_freeList(filename_list);
155                 return 0;
156         }
157
158         //MessageBox( -2,-2, 1,"DEBUG:0", "Ok" );
159         for (i=0; i<35; i++)
160                 Spaces[i] = ' ';
161         Spaces[34] = 0;
162
163         wnd = ui_open_window( 200, 100, 400, 370, WIN_DIALOG );
164
165         ui_wprintf_at( wnd, 10, 5, message );
166
167         ui_wprintf_at( wnd, 20, 32,"N&ame" );
168         UserFile  = ui_add_gadget_inputbox( wnd, 60, 30, PATH_MAX, 40, InputText );
169
170         ui_wprintf_at( wnd, 20, 86,"&Files" );
171         ui_wprintf_at( wnd, 210, 86,"&Dirs" );
172
173         ListBox1 = ui_add_gadget_listbox(wnd,  20, 110, 125, 200, NumFiles, filename_list);
174         ListBox2 = ui_add_gadget_listbox(wnd, 210, 110, 100, 200, NumDirs, directory_list);
175
176         Button1 = ui_add_gadget_button( wnd,     20, 330, 60, 25, "Ok", NULL );
177         Button2 = ui_add_gadget_button( wnd,    100, 330, 60, 25, "Cancel", NULL );
178         HelpButton = ui_add_gadget_button( wnd, 180, 330, 60, 25, "Help", NULL );
179
180         wnd->keyboard_focus_gadget = (UI_GADGET *)UserFile;
181
182         Button1->hotkey = KEY_CTRLED + KEY_ENTER;
183         Button2->hotkey = KEY_ESC;
184         HelpButton->hotkey = KEY_F1;
185         ListBox1->hotkey = KEY_ALTED + KEY_F;
186         ListBox2->hotkey = KEY_ALTED + KEY_D;
187         UserFile->hotkey = KEY_ALTED + KEY_A;
188
189         ui_gadget_calc_keys(wnd);
190
191         ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
192         ui_wprintf_at( wnd, 20, 60, "%s", ViewDir );
193
194         new_listboxes = 0;
195
196         while( 1 )
197         {
198                 ui_mega_process();
199                 ui_window_do_gadgets(wnd);
200
201                 if ( Button2->pressed )
202                 {
203                         PHYSFS_freeList(filename_list);
204                         PHYSFS_freeList(directory_list);
205                         ui_close_window(wnd);
206                         return 0;
207                 }
208
209                 if ( HelpButton->pressed )
210                         MessageBox( -1, -1, 1, "Sorry, no help is available!", "Ok" );
211
212                 if (ListBox1->moved || new_listboxes)
213                 {
214                         if (ListBox1->current_item >= 0 )
215                                 ui_inputbox_set_text(UserFile, filename_list[ListBox1->current_item]);
216                 }
217
218                 if (ListBox2->moved || new_listboxes)
219                 {
220                         if (ListBox2->current_item >= 0 )
221                                 ui_inputbox_set_text(UserFile, directory_list[ListBox2->current_item]);
222                 }
223                 new_listboxes = 0;
224
225                 if (Button1->pressed || UserFile->pressed || (ListBox1->selected_item > -1 ) || (ListBox2->selected_item > -1 ))
226                 {
227                         ui_mouse_hide();
228
229                         if (ListBox2->selected_item > -1 )
230                                 strcpy(UserFile->text, directory_list[ListBox2->selected_item]);
231
232                         strncpy(filename, ViewDir, PATH_MAX);
233
234                         p = UserFile->text;
235                         while (!strncmp(p, "..", 2))    // shorten the path manually
236                         {
237                                 char *sep = strrchr(filename, '/');
238                                 if (sep)
239                                         *sep = 0;
240                                 else
241                                         *filename = 0;  // look directly in search paths
242
243                                 p += 2;
244                                 if (*p == '/')
245                                         p++;
246                         }
247
248                         if (*filename && *p)
249                                 strncat(filename, "/", PATH_MAX - strlen(filename));
250                         strncat(filename, p, PATH_MAX - strlen(filename));
251
252                         if (!PHYSFS_isDirectory(filename))
253                         {
254                                 TempFile = PHYSFS_openRead(filename);
255                                 if (TempFile)
256                                 {
257                                         // Looks like a valid filename that already exists!
258                                         PHYSFS_close(TempFile);
259                                         break;
260                                 }
261         
262                                 // File doesn't exist, but can we create it?
263                                 TempFile = PHYSFS_openWrite(filename);
264                                 if (TempFile)
265                                 {
266                                         // Looks like a valid filename!
267                                         PHYSFS_close(TempFile);
268                                         PHYSFS_delete(filename);
269                                         break;
270                                 }
271                         }
272                         else
273                         {
274                                 if (filename[strlen(filename) - 1] == '/')      // user typed a separator on the end
275                                         filename[strlen(filename) - 1] = 0;
276         
277                                 strcpy(ViewDir, filename);
278         
279                                 //mprintf( 0, "----------------------------\n" );
280                                 //mprintf( 0, "Full dir: '%s'\n", ViewDir );
281         
282                                 PHYSFS_freeList(filename_list);
283                                 filename_list = file_getfilelist(&NumFiles, Filespec, ViewDir);
284                                 if (!filename_list)
285                                 {
286                                         PHYSFS_freeList(directory_list);
287                                         return 0;
288                                 }
289
290                                 ui_inputbox_set_text(UserFile, Filespec);
291
292                                 PHYSFS_freeList(directory_list);
293                                 directory_list = file_getdirlist(&NumDirs, ViewDir);
294                                 if (!directory_list)
295                                 {
296                                         PHYSFS_freeList(filename_list);
297                                         return 0;
298                                 }
299
300                                 ui_listbox_change(wnd, ListBox1, NumFiles, filename_list);
301                                 ui_listbox_change(wnd, ListBox2, NumDirs, directory_list);
302                                 new_listboxes = 0;
303
304                                 ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
305                                 ui_wprintf_at( wnd, 20, 60, "%s", ViewDir );
306
307                                 //i = TICKER;
308                                 //while ( TICKER < i+2 );
309
310                         }
311
312                         ui_mouse_show();
313
314                 }
315
316                 vid_update();
317         }
318
319         //key_flush();
320
321         ui_close_window(wnd);
322         if (filename_list)
323                 PHYSFS_freeList(filename_list);
324         if (directory_list)
325                 PHYSFS_freeList(directory_list);
326
327         return 1;
328 }
329
330
331
332 int ui_get_file( char * filename, char * Filespec  )
333 {
334         int x, NumFiles;
335         char **list = file_getfilelist(&NumFiles, Filespec, "");
336
337         if (!list) return 0;
338
339         x = MenuX(-1, -1, NumFiles, list);
340
341         if (x > 0)
342                 strcpy(filename, list[x - 1]);
343
344         PHYSFS_freeList(list);
345
346         return (x > 0);
347 }
348