use qsort and file_sort_func instead of file_sort
[btb/d2x.git] / ui / file.c
1 /* $Id: file.c,v 1.9 2005-03-05 09:14:59 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.9 2005-03-05 09:14:59 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         char ErrorMessage[100];
257         UI_WINDOW * wnd;
258         UI_GADGET_BUTTON * Button1, * Button2, * HelpButton;
259         UI_GADGET_LISTBOX * ListBox1;
260         UI_GADGET_LISTBOX * ListBox2;
261         UI_GADGET_INPUTBOX * UserFile;
262         int new_listboxes;
263
264         char drive[ _MAX_DRIVE ];
265         char dir[ _MAX_DIR ];
266         char fname[ _MAX_FNAME ];
267         char ext[ _MAX_EXT ];
268         char fulldir[ _MAX_DIR + _MAX_DRIVE ];
269         char fullfname[ _MAX_FNAME + _MAX_EXT ];
270
271
272         char OrgDir[128];
273
274         getcwd( OrgDir, 128 );
275
276         if (FirstTime)
277                 getcwd( CurDir, 128 );
278         FirstTime=0;
279
280         file_chdir( CurDir );
281         
282         //MessageBox( -2,-2, 1,"DEBUG:0", "Ok" );
283         for (i=0; i<35; i++)
284                 Spaces[i] = ' ';
285         Spaces[34] = 0;
286
287         NumFiles = file_getfilelist( 300, filename_list, Filespec );
288
289         NumDirs = file_getdirlist( 100, directory_list );
290
291         wnd = ui_open_window( 200, 100, 400, 370, WIN_DIALOG );
292
293         ui_wprintf_at( wnd, 10, 5, message );
294
295         _splitpath( filename, drive, dir, fname, ext );
296
297         sprintf( InputText, "%s%s", fname, ext );
298
299         ui_wprintf_at( wnd, 20, 32,"N&ame" );
300         UserFile  = ui_add_gadget_inputbox( wnd, 60, 30, 40, 40, InputText );
301
302         ui_wprintf_at( wnd, 20, 86,"&Files" );
303         ui_wprintf_at( wnd, 210, 86,"&Dirs" );
304
305         ListBox1 = ui_add_gadget_listbox( wnd,  20, 110, 125, 200, NumFiles, filename_list, 13 );
306         ListBox2 = ui_add_gadget_listbox( wnd, 210, 110, 100, 200, NumDirs, directory_list, 13 );
307
308         Button1 = ui_add_gadget_button( wnd,     20, 330, 60, 25, "Ok", NULL );
309         Button2 = ui_add_gadget_button( wnd,    100, 330, 60, 25, "Cancel", NULL );
310         HelpButton = ui_add_gadget_button( wnd, 180, 330, 60, 25, "Help", NULL );
311
312         wnd->keyboard_focus_gadget = (UI_GADGET *)UserFile;
313
314         Button1->hotkey = KEY_CTRLED + KEY_ENTER;
315         Button2->hotkey = KEY_ESC;
316         HelpButton->hotkey = KEY_F1;
317         ListBox1->hotkey = KEY_ALTED + KEY_F;
318         ListBox2->hotkey = KEY_ALTED + KEY_D;
319         UserFile->hotkey = KEY_ALTED + KEY_A;
320
321         ui_gadget_calc_keys(wnd);
322
323         ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
324         ui_wprintf_at( wnd, 20, 60, "%s", CurDir );
325
326         new_listboxes = 0;
327
328         while( 1 )
329         {
330                 ui_mega_process();
331                 ui_window_do_gadgets(wnd);
332
333                 if ( Button2->pressed )
334                 {
335                         file_chdir( OrgDir );
336                         ui_close_window(wnd);
337                         return 0;
338                 }
339
340                 if ( HelpButton->pressed )
341                         MessageBox( -1, -1, 1, "Sorry, no help is available!", "Ok" );
342
343                 if (ListBox1->moved || new_listboxes)
344                 {
345                         if (ListBox1->current_item >= 0 )
346                         {
347                                 strcpy(UserFile->text, filename_list[ListBox1->current_item] );
348                                 UserFile->position = strlen(UserFile->text);
349                                 UserFile->oldposition = UserFile->position;
350                                 UserFile->status=1;
351                                 UserFile->first_time = 1;
352                         }
353                 }
354
355                 if (ListBox2->moved || new_listboxes)
356                 {
357                         if (ListBox2->current_item >= 0 )
358                         {
359                                 if (strrchr( directory_list[ListBox2->current_item], ':' ))
360                                         sprintf( UserFile->text, "%s%s", directory_list[ListBox2->current_item], Filespec );
361                                 else
362                                         sprintf( UserFile->text, "%s\\%s", directory_list[ListBox2->current_item], Filespec );
363                                 UserFile->position = strlen(UserFile->text);
364                                 UserFile->oldposition = UserFile->position;
365                                 UserFile->status=1;
366                                 UserFile->first_time = 1;
367                         }
368                 }
369                 new_listboxes = 0;
370
371                 if (Button1->pressed || UserFile->pressed || (ListBox1->selected_item > -1 ) || (ListBox2->selected_item > -1 ))
372                 {
373                         ui_mouse_hide();
374
375                         if (ListBox2->selected_item > -1 )      {
376                                 if (strrchr( directory_list[ListBox2->selected_item], ':' ))
377                                         sprintf( UserFile->text, "%s%s", directory_list[ListBox2->selected_item], Filespec );
378                                 else
379                                         sprintf( UserFile->text, "%s\\%s", directory_list[ListBox2->selected_item], Filespec );
380                         }
381
382                         TempFile = fopen( UserFile->text, "r" );
383                         if (TempFile)
384                         {
385                                 // Looks like a valid filename that already exists!
386                                 fclose( TempFile );
387                                 break;
388                         }
389
390                         // File doesn't exist, but can we create it?
391                         TempFile = fopen( UserFile->text, "w" );
392                         if (TempFile)
393                         {
394                                 // Looks like a valid filename!
395                                 fclose( TempFile );
396                                 remove( UserFile->text );
397                                 break;
398                         }
399
400                         _splitpath( UserFile->text, drive, dir, fname, ext );
401                         sprintf( fullfname, "%s%s", fname, ext );
402
403                         //mprintf( 0, "----------------------------\n" );
404                         //mprintf( 0, "Full text: '%s'\n", UserFile->text );
405                         //mprintf( 0, "Drive: '%s'\n", drive );
406                         //mprintf( 0, "Dir: '%s'\n", dir );
407                         //mprintf( 0, "Filename: '%s'\n", fname );
408                         //mprintf( 0, "Extension: '%s'\n", ext );
409                         //mprintf( 0, "Full dir: '%s'\n", fulldir );
410                         //mprintf( 0, "Full fname: '%s'\n", fname );
411
412                         if (strrchr( fullfname, '?' ) || strrchr( fullfname, '*' ) )    
413                         {
414                                 sprintf( fulldir, "%s%s.", drive, dir );
415                         } else {
416                                 sprintf( fullfname, "%s", Filespec );
417                                 sprintf( fulldir, "%s", UserFile->text );
418                         }
419
420                         //mprintf( 0, "----------------------------\n" );
421                         //mprintf( 0, "Full dir: '%s'\n", fulldir );
422                         //mprintf( 0, "Full fname: '%s'\n", fullfname );
423
424                         if (file_chdir( fulldir )==0)
425                         {
426                                 NumFiles = file_getfilelist( 300, filename_list, fullfname );
427
428                                 strcpy(UserFile->text, fullfname );
429                                 UserFile->position = strlen(UserFile->text);
430                                 UserFile->oldposition = UserFile->position;
431                                 UserFile->status=1;
432                                 UserFile->first_time = 1;
433
434                                 NumDirs = file_getdirlist( 100, directory_list );
435
436                                 ui_listbox_change( wnd, ListBox1, NumFiles, filename_list, 13 );
437                                 ui_listbox_change( wnd, ListBox2, NumDirs, directory_list, 13 );
438                                 new_listboxes = 0;
439
440                                 getcwd( CurDir, 35 );
441                                 ui_wprintf_at( wnd, 20, 60, "%s", Spaces );
442                                 ui_wprintf_at( wnd, 20, 60, "%s", CurDir );
443
444                                 //i = TICKER;
445                                 //while ( TICKER < i+2 );
446
447                         }else {
448                                 sprintf(ErrorMessage, "Error changing to directory '%s'", fulldir );
449                                 MessageBox( -2, -2, 1, ErrorMessage, "Ok" );
450                                 UserFile->first_time = 1;
451
452                         }
453
454                         ui_mouse_show();
455
456                 }
457
458                 gr_update();
459         }
460
461         //key_flush();
462
463         _splitpath( UserFile->text, drive, dir, fname, ext );
464         sprintf( fulldir, "%s%s.", drive, dir );
465         sprintf( fullfname, "%s%s", fname, ext );
466         
467         if ( strlen(fulldir) > 1 )
468                 file_chdir( fulldir );
469         
470         getcwd( CurDir, 35 );
471                 
472         if ( strlen(CurDir) > 0 )
473         {
474                         if ( CurDir[strlen(CurDir)-1] == '\\' )
475                                 CurDir[strlen(CurDir)-1] = 0;
476         }
477                 
478         sprintf( filename, "%s\\%s", CurDir, fullfname );
479         //MessageBox( -2, -2, 1, filename, "Ok" );
480         
481         file_chdir( OrgDir );
482                 
483         ui_close_window(wnd);
484
485         return 1;
486 }
487
488
489
490 int ui_get_file( char * filename, char * Filespec  )
491 {
492         int x, i, NumFiles;
493         char * text[200];
494
495         NumFiles = file_getfilelist( 200, filename_list, Filespec );
496
497         for (i=0; i< NumFiles; i++ )
498         {
499                 MALLOC( text[i], char, 15 );
500                 strcpy(text[i], filename_list[i] );
501         }
502
503         x = MenuX( -1, -1, NumFiles, text );
504
505         if ( x > 0 )
506                 strcpy(filename, filename_list[x-1] );
507
508         for (i=0; i< NumFiles; i++ )
509         {
510                 d_free( text[i] );
511         }
512
513         if ( x>0 )
514                 return 1;
515         else
516                 return 0;
517
518 }
519