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