no error message if changing directory fails (PhysicsFS uses search paths, not a...
[btb/d2x.git] / ui / file.c
1 /* $Id: file.c,v 1.10 2005-03-05 09:18:46 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 #ifdef RCS
16 static char rcsid[] = "$Id: file.c,v 1.10 2005-03-05 09:18:46 chris Exp $";
17 #endif
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <direct.h>
23 #include <dos.h>
24 #include <ctype.h>
25 #include <conio.h>
26 #include <fcntl.h>
27 #include <io.h>
28 #include <sys\types.h>
29 #include <sys\stat.h>
30
31 #include "fix.h"
32 #include "pstypes.h"
33 #include "gr.h"
34 #include "key.h"
35 #include "strutil.h"
36
37 #include "ui.h"
38 #include "mono.h"
39
40 #include "u_mem.h"
41
42 char filename_list[300][13];
43 char directory_list[100][13];
44
45 int file_sort_func(char *e0, char *e1)
46 {
47         return stricmp(e0, e1);
48 }
49
50
51 int SingleDrive()
52 {
53         int FloppyPresent, FloppyNumber;
54         unsigned char b;
55
56         b = *((unsigned char *)0x410);
57
58         FloppyPresent = b & 1;
59         FloppyNumber = ((b&0xC0)>>6)+1;
60         if (FloppyPresent && (FloppyNumber==1) )
61                 return 1;
62         else
63                 return 0;
64 }
65
66 void SetFloppy(int d)
67 {
68         if (SingleDrive())
69         {
70         if (d==1)
71                 *((unsigned char *)0x504) = 0;
72         else if (d==2)
73                 *((unsigned char *)0x504) = 1;
74         }
75 }
76
77
78 void file_capitalize( char * s )
79 {
80         while( *s++ = toupper(*s) );
81 }
82
83
84 // Changes to a drive if valid.. 1=A, 2=B, etc
85 // If flag, then changes to it.
86 // Returns 0 if not-valid, 1 if valid.
87 int file_chdrive( int DriveNum, int flag )
88 {
89         unsigned NumDrives, n, org;
90         int Valid = 0;
91
92         if (!flag)
93                 _dos_getdrive( &org );
94
95         _dos_setdrive( DriveNum, &NumDrives );
96         _dos_getdrive( &n );
97
98         if (n == DriveNum )
99                 Valid = 1;
100
101         if ( (!flag) && (n != org) )
102                 _dos_setdrive( org, &NumDrives );
103
104         return Valid;
105 }
106
107
108 // Changes to directory in dir.  Even drive is changed.
109 // Returns 1 if failed.
110 //  0 = Changed ok.
111 //  1 = Invalid disk drive.
112 //  2 = Invalid directory.
113
114 int file_chdir( char * dir )
115 {
116         int e;
117         char OriginalDirectory[100];
118         char * Drive, * Path;
119         char NoDir[] = "\.";
120
121         getcwd( OriginalDirectory, 100 );
122
123         file_capitalize( dir );
124
125         Drive = strchr(dir, ':');
126
127         if (Drive)
128         {
129                 if (!file_chdrive( *(Drive - 1) - 'A' + 1, 1))
130                         return 1;
131
132                 Path = Drive+1;
133
134                 SetFloppy(*(Drive - 1) - 'A' + 1);
135         }
136         else
137         {
138                 Path = dir;
139
140         }
141
142         if (!(*Path))
143         {
144                 Path = NoDir;
145         }
146
147         // This chdir might get a critical error!
148         e = chdir( Path );
149         if (e)
150         {
151                 file_chdrive( OriginalDirectory[0] - 'A'+1, 1 );
152                 return 2;
153         }
154
155         return 0;
156
157 }
158
159
160 int file_getdirlist( int MaxNum, char list[][13] )
161 {
162         struct find_t find;
163         int NumDirs = 0, i, CurDrive;
164         char cwd[129];
165         MaxNum = MaxNum;
166
167         getcwd(cwd, 128 );
168
169         if (strlen(cwd) >= 4)
170         {
171                 sprintf( list[NumDirs++], ".." );
172         }
173
174         CurDrive = cwd[0] - 'A' + 1;
175
176         if( !_dos_findfirst( "*.", _A_SUBDIR, &find ) )
177         {
178                 if ( find.attrib & _A_SUBDIR )  {
179                         if (strcmp( "..", find.name) && strcmp( ".", find.name))
180                                 strncpy(list[NumDirs++], find.name, 13 );
181                 }
182
183                 while( !_dos_findnext( &find ) )
184                 {
185                         if ( find.attrib & _A_SUBDIR )  {
186                                 if (strcmp( "..", find.name) && strcmp( ".", find.name))
187                                 {
188                                         if (NumDirs==74)
189                                         {
190                                                 MessageBox( -2,-2, 1, "Only the first 74 directories will be displayed.", "Ok" );
191                                                 break;
192                                         } else {
193                                                 strncpy(list[NumDirs++], find.name, 13 );
194                                         }
195                                 }
196                         }
197                 }
198         }
199
200         qsort(list, NumDirs, 13, (int (*)( const void *, const void * ))file_sort_func);
201
202         for (i=1; i<=26; i++ )
203         {
204                 if (file_chdrive(i,0) && (i!=CurDrive))
205                 {
206                         if (!((i==2) && SingleDrive()))
207                                 sprintf( list[NumDirs++], "%c:", i+'A'-1 );
208                 }
209         }
210
211         return NumDirs;
212 }
213
214 int file_getfilelist( int MaxNum, char list[][13], char * filespec )
215 {
216         struct find_t find;
217         int NumFiles = 0;
218
219         MaxNum = MaxNum;
220
221         if( !_dos_findfirst( filespec, 0, &find ) )
222         {
223                 //if ( !(find.attrib & _A_SUBDIR) )
224                         strncpy(list[NumFiles++], find.name, 13 );
225
226                 while( !_dos_findnext( &find ) )
227                 {
228                         //if ( !(find.attrib & _A_SUBDIR) )
229                         //{
230                                 if (NumFiles==300)
231                                 {
232                                         MessageBox( -2,-2, 1, "Only the first 300 files will be displayed.", "Ok" );
233                                         break;
234                                 } else {
235                                         strncpy(list[NumFiles++], find.name, 13 );
236                                 }
237                         //}
238
239                 }
240         }
241
242         qsort(list, NumFiles, 13, (int (*)( const void *, const void * ))file_sort_func);
243
244         return NumFiles;
245 }
246
247 static int FirstTime = 1;
248 static char CurDir[128];
249
250 int ui_get_filename( char * filename, char * Filespec, char * message  )
251 {
252         FILE * TempFile;
253         int NumFiles, NumDirs,i;
254         char InputText[100];
255         char Spaces[35];
256         UI_WINDOW * wnd;
257         UI_GADGET_BUTTON * Button1, * Button2, * HelpButton;
258         UI_GADGET_LISTBOX * ListBox1;
259         UI_GADGET_LISTBOX * ListBox2;
260         UI_GADGET_INPUTBOX * UserFile;
261         int new_listboxes;
262
263         char drive[ _MAX_DRIVE ];
264         char dir[ _MAX_DIR ];
265         char fname[ _MAX_FNAME ];
266         char ext[ _MAX_EXT ];
267         char fulldir[ _MAX_DIR + _MAX_DRIVE ];
268         char fullfname[ _MAX_FNAME + _MAX_EXT ];
269
270
271         char OrgDir[128];
272
273         getcwd( OrgDir, 128 );
274
275         if (FirstTime)
276                 getcwd( CurDir, 128 );
277         FirstTime=0;
278
279         file_chdir( CurDir );
280         
281         //MessageBox( -2,-2, 1,"DEBUG:0", "Ok" );
282         for (i=0; i<35; i++)
283                 Spaces[i] = ' ';
284         Spaces[34] = 0;
285
286         NumFiles = file_getfilelist( 300, filename_list, Filespec );
287
288         NumDirs = file_getdirlist( 100, directory_list );
289
290         wnd = ui_open_window( 200, 100, 400, 370, WIN_DIALOG );
291
292         ui_wprintf_at( wnd, 10, 5, message );
293
294         _splitpath( filename, drive, dir, fname, ext );
295
296         sprintf( InputText, "%s%s", fname, ext );
297
298         ui_wprintf_at( wnd, 20, 32,"N&ame" );
299         UserFile  = ui_add_gadget_inputbox( wnd, 60, 30, 40, 40, InputText );
300
301         ui_wprintf_at( wnd, 20, 86,"&Files" );
302         ui_wprintf_at( wnd, 210, 86,"&Dirs" );
303
304         ListBox1 = ui_add_gadget_listbox( wnd,  20, 110, 125, 200, NumFiles, filename_list, 13 );
305         ListBox2 = ui_add_gadget_listbox( wnd, 210, 110, 100, 200, NumDirs, directory_list, 13 );
306
307         Button1 = ui_add_gadget_button( wnd,     20, 330, 60, 25, "Ok", NULL );
308         Button2 = ui_add_gadget_button( wnd,    100, 330, 60, 25, "Cancel", NULL );
309         HelpButton = ui_add_gadget_button( wnd, 180, 330, 60, 25, "Help", NULL );
310
311         wnd->keyboard_focus_gadget = (UI_GADGET *)UserFile;
312
313         Button1->hotkey = KEY_CTRLED + KEY_ENTER;
314         Button2->hotkey = KEY_ESC;
315         HelpButton->hotkey = KEY_F1;
316         ListBox1->hotkey = KEY_ALTED + KEY_F;
317         ListBox2->hotkey = KEY_ALTED + KEY_D;
318         UserFile->hotkey = KEY_ALTED + KEY_A;
319
320         ui_gadget_calc_keys(wnd);
321
322         ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
323         ui_wprintf_at( wnd, 20, 60, "%s", CurDir );
324
325         new_listboxes = 0;
326
327         while( 1 )
328         {
329                 ui_mega_process();
330                 ui_window_do_gadgets(wnd);
331
332                 if ( Button2->pressed )
333                 {
334                         file_chdir( OrgDir );
335                         ui_close_window(wnd);
336                         return 0;
337                 }
338
339                 if ( HelpButton->pressed )
340                         MessageBox( -1, -1, 1, "Sorry, no help is available!", "Ok" );
341
342                 if (ListBox1->moved || new_listboxes)
343                 {
344                         if (ListBox1->current_item >= 0 )
345                         {
346                                 strcpy(UserFile->text, filename_list[ListBox1->current_item] );
347                                 UserFile->position = strlen(UserFile->text);
348                                 UserFile->oldposition = UserFile->position;
349                                 UserFile->status=1;
350                                 UserFile->first_time = 1;
351                         }
352                 }
353
354                 if (ListBox2->moved || new_listboxes)
355                 {
356                         if (ListBox2->current_item >= 0 )
357                         {
358                                 if (strrchr( directory_list[ListBox2->current_item], ':' ))
359                                         sprintf( UserFile->text, "%s%s", directory_list[ListBox2->current_item], Filespec );
360                                 else
361                                         sprintf( UserFile->text, "%s\\%s", directory_list[ListBox2->current_item], Filespec );
362                                 UserFile->position = strlen(UserFile->text);
363                                 UserFile->oldposition = UserFile->position;
364                                 UserFile->status=1;
365                                 UserFile->first_time = 1;
366                         }
367                 }
368                 new_listboxes = 0;
369
370                 if (Button1->pressed || UserFile->pressed || (ListBox1->selected_item > -1 ) || (ListBox2->selected_item > -1 ))
371                 {
372                         ui_mouse_hide();
373
374                         if (ListBox2->selected_item > -1 )      {
375                                 if (strrchr( directory_list[ListBox2->selected_item], ':' ))
376                                         sprintf( UserFile->text, "%s%s", directory_list[ListBox2->selected_item], Filespec );
377                                 else
378                                         sprintf( UserFile->text, "%s\\%s", directory_list[ListBox2->selected_item], Filespec );
379                         }
380
381                         TempFile = fopen( UserFile->text, "r" );
382                         if (TempFile)
383                         {
384                                 // Looks like a valid filename that already exists!
385                                 fclose( TempFile );
386                                 break;
387                         }
388
389                         // File doesn't exist, but can we create it?
390                         TempFile = fopen( UserFile->text, "w" );
391                         if (TempFile)
392                         {
393                                 // Looks like a valid filename!
394                                 fclose( TempFile );
395                                 remove( UserFile->text );
396                                 break;
397                         }
398
399                         _splitpath( UserFile->text, drive, dir, fname, ext );
400                         sprintf( fullfname, "%s%s", fname, ext );
401
402                         //mprintf( 0, "----------------------------\n" );
403                         //mprintf( 0, "Full text: '%s'\n", UserFile->text );
404                         //mprintf( 0, "Drive: '%s'\n", drive );
405                         //mprintf( 0, "Dir: '%s'\n", dir );
406                         //mprintf( 0, "Filename: '%s'\n", fname );
407                         //mprintf( 0, "Extension: '%s'\n", ext );
408                         //mprintf( 0, "Full dir: '%s'\n", fulldir );
409                         //mprintf( 0, "Full fname: '%s'\n", fname );
410
411                         if (strrchr( fullfname, '?' ) || strrchr( fullfname, '*' ) )    
412                         {
413                                 sprintf( fulldir, "%s%s.", drive, dir );
414                         } else {
415                                 sprintf( fullfname, "%s", Filespec );
416                                 sprintf( fulldir, "%s", UserFile->text );
417                         }
418
419                         //mprintf( 0, "----------------------------\n" );
420                         //mprintf( 0, "Full dir: '%s'\n", fulldir );
421                         //mprintf( 0, "Full fname: '%s'\n", fullfname );
422
423                         if (file_chdir( fulldir )==0)
424                         {
425                                 NumFiles = file_getfilelist( 300, filename_list, fullfname );
426
427                                 strcpy(UserFile->text, fullfname );
428                                 UserFile->position = strlen(UserFile->text);
429                                 UserFile->oldposition = UserFile->position;
430                                 UserFile->status=1;
431                                 UserFile->first_time = 1;
432
433                                 NumDirs = file_getdirlist( 100, directory_list );
434
435                                 ui_listbox_change( wnd, ListBox1, NumFiles, filename_list, 13 );
436                                 ui_listbox_change( wnd, ListBox2, NumDirs, directory_list, 13 );
437                                 new_listboxes = 0;
438
439                                 getcwd( CurDir, 35 );
440                                 ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
441                                 ui_wprintf_at( wnd, 20, 60, "%s", CurDir );
442
443                                 //i = TICKER;
444                                 //while ( TICKER < i+2 );
445
446                         }
447
448                         ui_mouse_show();
449
450                 }
451
452                 gr_update();
453         }
454
455         //key_flush();
456
457         _splitpath( UserFile->text, drive, dir, fname, ext );
458         sprintf( fulldir, "%s%s.", drive, dir );
459         sprintf( fullfname, "%s%s", fname, ext );
460         
461         if ( strlen(fulldir) > 1 )
462                 file_chdir( fulldir );
463         
464         getcwd( CurDir, 35 );
465                 
466         if ( strlen(CurDir) > 0 )
467         {
468                         if ( CurDir[strlen(CurDir)-1] == '\\' )
469                                 CurDir[strlen(CurDir)-1] = 0;
470         }
471                 
472         sprintf( filename, "%s\\%s", CurDir, fullfname );
473         //MessageBox( -2, -2, 1, filename, "Ok" );
474         
475         file_chdir( OrgDir );
476                 
477         ui_close_window(wnd);
478
479         return 1;
480 }
481
482
483
484 int ui_get_file( char * filename, char * Filespec  )
485 {
486         int x, i, NumFiles;
487         char * text[200];
488
489         NumFiles = file_getfilelist( 200, filename_list, Filespec );
490
491         for (i=0; i< NumFiles; i++ )
492         {
493                 MALLOC( text[i], char, 15 );
494                 strcpy(text[i], filename_list[i] );
495         }
496
497         x = MenuX( -1, -1, NumFiles, text );
498
499         if ( x > 0 )
500                 strcpy(filename, filename_list[x-1] );
501
502         for (i=0; i< NumFiles; i++ )
503         {
504                 d_free( text[i] );
505         }
506
507         if ( x>0 )
508                 return 1;
509         else
510                 return 0;
511
512 }
513