ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/PrefsEditor.mm
Revision: 1.9
Committed: 2003-03-25T01:47:37Z (21 years, 2 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-13
Changes since 1.8: +2 -2 lines
Log Message:
Minor UI error from removal of OpenGL button

File Contents

# Content
1 /*
2 * PrefsEditor.m - GUI stuff for Basilisk II preferences
3 * (which is a text file in the user's home directory)
4 *
5 * $Id: PrefsEditor.mm,v 1.8 2003/03/21 12:04:34 nigel Exp $
6 *
7 * Basilisk II (C) 1997-2003 Christian Bauer
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #import "PrefsEditor.h"
25
26 @implementation TableDS
27
28 - (TableDS *) init
29 {
30 self = [super init];
31
32 numItems = 0;
33 col1 = [NSMutableArray new];
34 col2 = [NSMutableArray new];
35
36 return self;
37 }
38
39 - (void) dealloc
40 {
41 [col1 dealloc];
42 [col2 dealloc];
43 [super dealloc];
44 }
45
46 - (void) addInt: (int)target
47 withPath: (NSString *)path
48 {
49 [col1 addObject: [NSNumber numberWithInt: target]];
50 [col2 addObject: path];
51 ++numItems;
52 }
53
54 - (void) addObject: (NSObject *)obj
55 withPath: (NSString *)path
56 {
57 [col1 addObject: obj];
58 [col2 addObject: path];
59 ++numItems;
60 }
61
62 - (void) deleteAll
63 {
64 numItems = 0;
65 [col1 removeAllObjects];
66 [col2 removeAllObjects];
67 }
68
69 - (BOOL) deleteRow: (int)row
70 {
71 if ( row > numItems )
72 return NO;
73
74 [col1 removeObjectAtIndex: row];
75 [col2 removeObjectAtIndex: row];
76 -- numItems;
77
78 return YES;
79 }
80
81 - (int)intAtRow: (int)row
82 {
83 return [[col1 objectAtIndex: row] intValue];
84 }
85
86 - (int) numberOfRowsInTableView: (NSTableView *)tView
87 {
88 return numItems;
89 }
90
91 - (NSString *)pathAtRow: (int)row
92 {
93 return (NSString *) [col2 objectAtIndex: row];
94 }
95
96 - (id) tableView: (NSTableView *)tView
97 objectValueForTableColumn: (NSTableColumn *)tColumn
98 row: (int)row
99 {
100 if ( [[tColumn identifier] isEqualToString:@"path"] )
101 return [col2 objectAtIndex: row];
102 else
103 return [col1 objectAtIndex: row];
104 }
105
106 @end
107
108 @implementation PrefsEditor
109
110 #import <AppKit/NSImage.h> // For [NSBundle pathForImageResource:] proto
111
112 #import "sysdeps.h" // Types used in Basilisk C++ code
113 #import "video_macosx.h" // some items that we edit here
114 #import "misc_macosx.h" // WarningSheet() prototype
115
116 #import <prefs.h>
117
118 #define DEBUG 0
119 #import <debug.h>
120
121 - (PrefsEditor *) init
122 {
123 self = [super init];
124
125 edited = NO;
126
127 devs = @"/dev";
128 home = NSHomeDirectory();
129 volsDS = [TableDS new];
130 SCSIds = [TableDS new];
131
132 lockCell = [NSImageCell new];
133 if ( lockCell == nil )
134 NSLog (@"%s - Can't create NSImageCell?", __PRETTY_FUNCTION__);
135
136 blank = [NSImage new];
137 locked = [NSImage alloc];
138 if ( [locked initWithContentsOfFile:
139 [[NSBundle mainBundle]
140 pathForImageResource: @"nowrite.icns"]] == nil )
141 NSLog(@"%s - Couldn't open write protection image", __PRETTY_FUNCTION__);
142
143 return self;
144 }
145
146 - (void) dealloc
147 {
148 [volsDS dealloc];
149 [SCSIds dealloc];
150 [lockCell dealloc];
151 [locked dealloc];
152 [blank dealloc];
153 [super dealloc];
154 }
155
156 - (void) awakeFromNib
157 {
158 emuFreq = [theEmulator speed];
159 #if DEBUG
160 [self ShowPrefs: self]; // For testing
161 #endif
162 }
163
164 - (BOOL) hasEdited
165 {
166 return edited;
167 }
168
169 - (NSWindow *) window
170 {
171 return panel;
172 }
173
174 - (IBAction) AddSCSI: (id)sender
175 {
176 NSOpenPanel *oP = [NSOpenPanel openPanel];
177
178 if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton )
179 {
180 [SCSIds addInt: -1
181 withPath: [oP filename] ];
182 [SCSIdisks reloadData];
183 edited = YES;
184 }
185 }
186
187 - (IBAction) AddVolume: (id)sender
188 {
189 NSOpenPanel *oP = [NSOpenPanel openPanel];
190
191 if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton )
192 {
193 [volsDS addObject: (NSObject *) locked
194 withPath: [oP filename] ];
195 PrefsAddString("disk", [[oP filename] cString]);
196 [diskImages reloadData];
197 edited = YES;
198 }
199 }
200
201 - (IBAction) BrowseExtFS: (id)sender
202 {
203 NSOpenPanel *oP = [NSOpenPanel openPanel];
204
205 [oP setCanChooseDirectories: YES];
206 [oP setCanChooseFiles: NO];
207 [oP setPrompt: @"Select"];
208 [oP setTitle: @"Select a directory to mount"];
209 D(NSLog(@"%s - home = %@, [extFS stringValue] = %@",
210 __PRETTY_FUNCTION__, home, [extFS stringValue]));
211 if ( [oP runModalForDirectory: ([extFS stringValue] ? [extFS stringValue] : home)
212 file:nil
213 types:nil] == NSOKButton )
214 {
215 [extFS setStringValue: [oP directory] ];
216 PrefsReplaceString("extfs", [[oP directory] cString]);
217 edited = YES;
218 }
219 }
220
221 - (IBAction) BrowseROM: (id)sender
222 {
223 NSOpenPanel *oP = [NSOpenPanel openPanel];
224
225 [oP setCanChooseFiles: YES];
226 [oP setTitle: @"Open a ROM file"];
227 D(NSLog(@"%s - home = %@", __PRETTY_FUNCTION__, home));
228 if ( [oP runModalForDirectory: ([ROMfile stringValue] ? [ROMfile stringValue] : home)
229 file:nil
230 types:nil] == NSOKButton )
231 {
232 [ROMfile setStringValue: [oP filename] ];
233 PrefsReplaceString("rom", [[oP filename] cString]);
234 edited = YES;
235 }
236 }
237
238 #include <cdrom.h> // for CDROMRefNum
239
240 - (IBAction) ChangeBootFrom: (NSMatrix *)sender
241 {
242 if ( [sender selectedCell] == bootFromCD )
243 PrefsReplaceInt32("bootdriver", CDROMRefNum);
244 else
245 PrefsReplaceInt32("bootdriver", 0);
246 edited = YES;
247 }
248
249 - (IBAction) ChangeCPU: (NSMatrix *)sender
250 {
251 PrefsReplaceInt32("cpu", [[sender selectedCell] tag]);
252 edited = YES;
253 }
254
255 - (IBAction) ChangeDisableCD: (NSButton *)sender
256 {
257 PrefsReplaceBool("nocdrom", [disableCD state]);
258 edited = YES;
259 }
260
261 - (IBAction) ChangeDisableSound: (NSButton *)sender
262 {
263 BOOL noSound = [disableSound state];
264
265 if ( ! noSound )
266 WarningSheet(@"Sound is currently unimplemented", panel);
267
268 PrefsReplaceBool("nosound", noSound);
269 edited = YES;
270 }
271
272 - (IBAction) ChangeFPU: (NSButton *)sender
273 {
274 PrefsReplaceBool("fpu", [FPU state]);
275 edited = YES;
276 }
277
278 - (IBAction) ChangeModel: (NSMatrix *)sender
279 {
280 PrefsReplaceInt32("modelid", [[sender selectedCell] tag]);
281 edited = YES;
282 }
283
284
285 // If we are not using the CGIMAGEREF drawing strategy,
286 // then source bitmaps must be 32bits deep.
287
288 - (short) testWinDepth: (int) newbpp
289 {
290 #ifdef CGIMAGEREF
291 return newbpp;
292 #else
293 if ( newbpp != 32 )
294 WarningSheet(@"Sorry - In windowed mode, depth must be 32", panel);
295 return 32
296 #endif
297 }
298
299 // This is called when the screen/window,
300 // width, height or depth is clicked.
301 //
302 // Note that sender may not actually be an NSMatrix.
303
304 - (IBAction) ChangeScreen: (NSMatrix *)sender
305 {
306 NSButton *cell = [sender selectedCell];
307
308 short newx = [width intValue];
309 short newy = [height intValue];
310 short newbpp = [depth intValue];
311 short newtype;
312 char str[20];
313
314 if ( cell == screen )
315 newtype = DISPLAY_SCREEN;
316 else if ( cell == window )
317 newtype = DISPLAY_WINDOW;
318 else
319 newtype = display_type;
320
321 // Check that a field actually changed
322 if ( newbpp == init_depth && newx == init_width &&
323 newy == init_height && newtype == display_type )
324 {
325 D(NSLog(@"No changed GUI items in ChangeScreen"));
326 return;
327 }
328
329 // If we are changing type, supply some sensible defaults
330
331 short screenx = CGDisplayPixelsWide(kCGDirectMainDisplay),
332 screeny = CGDisplayPixelsHigh(kCGDirectMainDisplay),
333 screenb = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
334
335 if ( newtype != display_type )
336 {
337 D(NSLog(@"Changing display type in ChangeScreen"));
338
339 // If changing to full screen, supply main screen dimensions as a default
340 if ( newtype == DISPLAY_SCREEN )
341 newx = screenx, newy = screeny, newbpp = screenb;
342
343 // If changing from full screen, use minimum screen resolutions
344 if ( display_type == DISPLAY_SCREEN )
345 {
346 newx = MIN_WIDTH, newy = MIN_HEIGHT;
347 newbpp = [self testWinDepth: newbpp];
348 }
349 }
350 else
351 {
352 newbpp = [self testWinDepth: newbpp];
353
354 // Check size is within ranges of MIN_WIDTH ... MAX_WIDTH
355 // and MIN_HEIGHT ... MAX_HEIGHT
356 // ???
357 }
358
359 [width setIntValue: newx];
360 [height setIntValue: newy];
361 [depth setIntValue: newbpp];
362
363
364 // Store new prefs
365 *str = '\0';
366 switch ( newtype )
367 {
368 case DISPLAY_WINDOW:
369 if ( newbpp )
370 sprintf(str, "win/%hd/%hd/%hd", newx, newy, newbpp);
371 else
372 sprintf(str, "win/%hd/%hd", newx, newy);
373 break;
374 case DISPLAY_SCREEN:
375 if ( newbpp )
376 sprintf(str, "full/%hd/%hd/%hd", newx, newy, newbpp);
377 else
378 sprintf(str, "full/%hd/%hd", newx, newy);
379 break;
380 };
381 PrefsReplaceString("screen", str);
382
383 parse_screen_prefs(str);
384
385 edited = YES;
386
387 if ( display_type != DISPLAY_SCREEN )
388 {
389 D(NSLog(@"Display type is not SCREEN (%d), resizing window",
390 display_type));
391 resizeWinTo(newx, newy);
392 }
393 }
394
395 - (IBAction) CreateVolume: (id)sender
396 {
397 NSSavePanel *sP = [NSSavePanel savePanel];
398
399 [sP setAccessoryView: newVolumeView];
400 [sP setPrompt: @"Create"];
401 [sP setTitle: @"Create new volume as"];
402
403 if ( [sP runModalForDirectory:NSHomeDirectory() file:@"basilisk-II.vol"] == NSOKButton )
404 {
405 char cmd[1024];
406 const char *filename = [[sP filename] cString];
407 int retVal,
408 size = [newVolumeSize intValue];
409
410 sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", filename, size);
411 retVal = system(cmd);
412 if (retVal != 0)
413 {
414 NSString *details = [NSString stringWithFormat:
415 @"The dd command failed.\nReturn status %d (%s)",
416 retVal, strerror(errno)];
417 WarningSheet(@"Unable to create volume", details, nil, panel);
418 }
419 else
420 {
421 [volsDS addObject: (NSObject *) blank
422 withPath: [sP filename] ];
423 PrefsAddString("disk", filename);
424 [diskImages reloadData];
425 }
426 }
427 }
428
429 - (BOOL) fileManager: (NSFileManager *) manager
430 shouldProceedAfterError: (NSDictionary *) errorDict
431 {
432 NSRunAlertPanel(@"File operation error",
433 @"%@ %@, toPath %@",
434 @"Bugger!", nil, nil,
435 [errorDict objectForKey:@"Error"],
436 [errorDict objectForKey:@"Path"],
437 [errorDict objectForKey:@"ToPath"]);
438 return NO;
439 }
440
441 - (IBAction) DeleteVolume: (id)sender
442 {
443 // const char *path = [self RemoveVolumeEntry];
444 // if ( unlink(path) == -1 )
445 NSString *Path = [self RemoveVolumeEntry];
446
447 if ( ! [[NSFileManager defaultManager] removeFileAtPath: Path
448 handler: self] )
449 {
450 WarningSheet(@"Unable to delete volume", panel);
451 // NSLog(@"%s unlink(%s) failed - %s", __PRETTY_FUNCTION__, path, strerror(errno));
452 }
453 }
454
455 - (IBAction) EditDelay: (NSTextField *)sender
456 {
457 int ticks = [delay intValue];
458 float freq;
459
460 if ( ticks )
461 freq = 60.0 / ticks;
462 else
463 freq = 60.0;
464
465 [frequency setFloatValue: freq];
466 [emuFreq setFloatValue: freq];
467 PrefsReplaceInt32("frameskip", ticks);
468 edited = YES;
469 }
470
471 - (IBAction) EditBytes: (NSTextField *)sender
472 {
473 int B = (int) [bytes floatValue];
474 float M = B / 1024 / 1024;
475
476 D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B));
477 PrefsReplaceInt32("ramsize", B);
478 [MB setFloatValue: M];
479 edited = YES;
480 }
481
482 - (IBAction) EditEtherNetDevice: (NSTextField *)sender
483 {
484 NSString *path = [etherNet stringValue];
485
486 PrefsReplaceString("ether", [path cString]);
487 edited = YES;
488 }
489
490 - (IBAction) EditExtFS: (NSTextField *)sender
491 {
492 NSString *path = [extFS stringValue];
493
494 PrefsReplaceString("extfs", [path cString]);
495 edited = YES;
496 }
497
498 - (IBAction) EditFrequency: (NSTextField *)sender
499 {
500 float freq = [frequency floatValue];
501
502 [delay setIntValue: frequencyToTickDelay(freq)];
503 [emuFreq setFloatValue: freq];
504 edited = YES;
505 }
506
507 - (IBAction) EditModemDevice: (NSTextField *)sender
508 {
509 NSString *path = [modem stringValue];
510
511 PrefsReplaceString("seriala", [path cString]);
512 edited = YES;
513 }
514
515 - (IBAction) EditMB: (NSTextField *)sender
516 {
517 float M = [MB floatValue];
518 int B = (int) (M * 1024 * 1024);
519
520 D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B));
521 PrefsReplaceInt32("ramsize", B);
522 [bytes setIntValue: B];
523 edited = YES;
524 }
525
526 - (IBAction) EditPrinterDevice: (NSTextField *)sender
527 {
528 NSString *path = [printer stringValue];
529
530 PrefsReplaceString("serialb", [path cString]);
531 edited = YES;
532 }
533
534 - (IBAction) EditROMpath: (NSTextField *)sender
535 {
536 NSString *path = [ROMfile stringValue];
537
538 PrefsReplaceString("rom", [path cString]);
539 }
540
541 - (IBAction) RemoveSCSI: (id)sender
542 {
543 char pref[6];
544 int row = [SCSIdisks selectedRow],
545 SCSIid = [SCSIds intAtRow: row];
546
547 if ( ! [SCSIds deleteRow: row] )
548 NSLog (@"%s - [SCSIds deleteRow: %d] failed", __PRETTY_FUNCTION__, row);
549 [SCSIdisks reloadData];
550 sprintf(pref, "scsi%d", SCSIid);
551 PrefsRemoveItem(pref,0);
552 }
553
554 //- (const char *) RemoveVolumeEntry
555 - (NSString *) RemoveVolumeEntry
556 {
557 int row = [diskImages selectedRow];
558
559 if ( row != -1 )
560 {
561 NSString *Path = [volsDS pathAtRow: row];
562 const char *path = [Path cString],
563 *str;
564 int tmp = 0;
565
566 while ( (str = PrefsFindString("disk", tmp) ) != NULL )
567 {
568 if ( strcmp(str, path) == 0 )
569 {
570 PrefsRemoveItem("disk", tmp);
571 D(NSLog(@"%s - Deleted prefs entry \"disk\", %d",
572 __PRETTY_FUNCTION__, tmp));
573 edited = YES;
574 break;
575 }
576 ++tmp;
577 }
578
579 if ( str == NULL )
580 {
581 NSLog(@"%s - Couldn't find any disk preference to match %s",
582 __PRETTY_FUNCTION__, path);
583 return NULL;
584 }
585
586 if ( ! [volsDS deleteRow: row] )
587 NSLog (@"%s - RemoveVolume %d failed", __PRETTY_FUNCTION__, tmp);
588 [diskImages reloadData];
589 // return path;
590 return Path;
591 }
592 else
593 {
594 WarningSheet(@"Please select a volume first", panel);
595 return NULL;
596 }
597 }
598
599 - (IBAction) RemoveVolume: (id)sender
600 {
601 [self RemoveVolumeEntry];
602 }
603
604 - (IBAction) ResetPrefs: (id)sender
605 {
606 int argc = 0;
607 char **argv = NULL;
608
609 [panel close]; // Temporarily hide preferences panel
610
611 PrefsExit(); // Purge all the old pref values
612
613 PrefsInit(argc, argv);
614 AddPrefsDefaults();
615 AddPlatformPrefsDefaults(); // and only create basic ones
616
617 [SCSIds deleteAll]; // Clear out datasources for the tables
618 [volsDS deleteAll];
619
620 [self ShowPrefs: self]; // Reset items in panel, and redisplay
621 edited = NO;
622 }
623
624 - (void) setStringOf: (NSTextField *) field
625 fromPref: (const char *) prefName
626 {
627 const char *value = PrefsFindString(prefName, 0);
628
629 if ( value )
630 [field setStringValue: [NSString stringWithCString: value] ];
631 }
632
633 - (IBAction) SavePrefs: (id)sender
634 {
635 SavePrefs();
636 edited = NO;
637 }
638
639 - (IBAction) ShowPrefs: (id)sender
640 {
641 NSTableColumn *locks;
642 const char *str;
643 int cpu, tmp;
644
645
646 // Set simple single field items
647
648 tmp = PrefsFindInt32("frameskip");
649 [delay setIntValue: tmp];
650 if ( tmp )
651 [frequency setFloatValue: 60.0 / tmp];
652 else
653 [frequency setFloatValue: 60.0];
654
655 tmp = PrefsFindInt32("ramsize");
656 [bytes setIntValue: tmp];
657 [MB setFloatValue: tmp / (1024.0 * 1024.0)];
658
659 [disableCD setState: PrefsFindBool("nocdrom")];
660 [disableSound setState: PrefsFindBool("nosound")];
661 [FPU setState: PrefsFindBool("fpu") ];
662
663 [self setStringOf: etherNet fromPref: "ether" ];
664 [self setStringOf: extFS fromPref: "extfs" ];
665 [self setStringOf: modem fromPref: "seriala"];
666 [self setStringOf: printer fromPref: "serialb"];
667 [self setStringOf: ROMfile fromPref: "rom" ];
668
669
670 parse_screen_prefs(PrefsFindString("screen"));
671
672 [width setIntValue: init_width];
673 [height setIntValue: init_height];
674 [depth setIntValue: init_depth];
675
676 [screen setState: NO];
677 switch ( display_type )
678 {
679 case DISPLAY_WINDOW: [window setState: YES]; break;
680 case DISPLAY_SCREEN: [screen setState: YES]; break;
681 }
682
683 [newVolumeSize setIntValue: 10];
684
685 // Radio button groups:
686
687 tmp = PrefsFindInt32("bootdriver");
688 [bootFromAny setState: tmp != CDROMRefNum];
689 [bootFromCD setState: tmp == CDROMRefNum];
690
691 cpu = PrefsFindInt32("cpu");
692 tmp = PrefsFindInt32("modelid");
693
694 #if REAL_ADDRESSING || DIRECT_ADDRESSING
695 puts("Current memory model does not support 24bit addressing");
696 if ( tmp == [classic tag] )
697 {
698 // Window already created by NIB file, just display
699 [panel makeKeyAndOrderFront:self];
700 WarningSheet(@"Compiled-in memory model does not support 24bit",
701 @"Disabling Mac Classic emulation", nil, panel);
702 cpu = [CPU68030 tag];
703 PrefsReplaceInt32("cpu", cpu);
704 tmp = [IIci tag];
705 PrefsReplaceInt32("modelid", tmp);
706 }
707
708 puts("Disabling 68000 & Mac Classic buttons");
709 [CPU68000 setEnabled:FALSE];
710 [classic setEnabled:FALSE];
711 #endif
712
713 [CPU68000 setState: [CPU68000 tag] == cpu];
714 [CPU68020 setState: [CPU68020 tag] == cpu];
715 [CPU68030 setState: [CPU68030 tag] == cpu];
716 [CPU68040 setState: [CPU68040 tag] == cpu];
717
718 [classic setState: [classic tag] == tmp];
719 [IIci setState: [IIci tag] == tmp];
720 [quadra900 setState: [quadra900 tag] == tmp];
721
722
723 // Lists of thingies:
724
725 for ( tmp = 0; tmp < 7; ++tmp)
726 {
727 char pref[6];
728
729 pref[0] = '\0';
730
731 sprintf (pref, "scsi%d", tmp);
732 if ( (str = PrefsFindString(pref, 0) ) )
733 [SCSIds addInt: tmp
734 withPath: [NSString stringWithCString: str] ];
735 }
736
737 [SCSIdisks setDataSource: SCSIds];
738
739 locks = [diskImages tableColumnWithIdentifier: @"locked"];
740 if ( locks == nil )
741 NSLog (@"%s - Can't find column for lock images", __PRETTY_FUNCTION__);
742 [locks setDataCell: lockCell];
743
744 tmp = 0;
745 while ( (str = PrefsFindString("disk", tmp++) ) != NULL )
746 {
747 if ( *str == '*' )
748 [volsDS addObject: (NSObject *) locked
749 withPath: [NSString stringWithCString: str+1]];
750 else
751 [volsDS addObject: (NSObject *) blank
752 withPath: [NSString stringWithCString: str]];
753 }
754
755 [diskImages setDataSource: volsDS];
756
757
758 [panel makeKeyAndOrderFront:self]; // Window already created by NIB file, just display
759 }
760
761 @end