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