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