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