253 lines
8.2 KiB
Objective-C
253 lines
8.2 KiB
Objective-C
/*
|
|
* PDP-8/E Simulator
|
|
*
|
|
* Copyright © 1994-2015 Bernhard Baehr
|
|
*
|
|
* RK05Controller.m - Controller for RK05 view
|
|
*
|
|
* This file is part of PDP-8/E Simulator.
|
|
*
|
|
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#import "PluginFramework/PluginAPI.h"
|
|
#import "PluginFramework/Utilities.h"
|
|
#import "PluginFramework/Unicode.h"
|
|
#import "PluginFramework/NSControl+FileDrop.h"
|
|
#import "PluginFramework/FileDropControlTargetProtocol.h"
|
|
|
|
#import "RK05Controller.h"
|
|
#import "RK05.h"
|
|
|
|
|
|
#define DECPACK_HFS_TYPE_CODE 0x524b3845l // 'RK8E', for compatibility with the old simulator
|
|
#define DECPACK_EXTENSION_RK05 @"rk05"
|
|
#define DECPACK_EXTENSION_DECPACK @"decpack"
|
|
|
|
#define CODER_KEY_RK05_PATH_FMT @"rk05path%d"
|
|
#define CODER_KEY_RK05_LOCK_FMT @"rk05lock%d"
|
|
|
|
|
|
@implementation RK05Controller
|
|
|
|
|
|
- (IBAction) writeProtectClicked:(id)sender
|
|
{
|
|
[rk05 setWriteProtected:[sender intValue]];
|
|
}
|
|
|
|
|
|
- (void) notifyWriteProtectChanged:(NSNotification *)notification
|
|
{
|
|
// NSLog (@"RK05Controller notifyWriteProtectChanged");
|
|
[writeProtectCheckbox setIntValue:[rk05 isWriteProtected]];
|
|
}
|
|
|
|
|
|
- (void) updateMountButton:(NSString *)path
|
|
{
|
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
|
if (path) {
|
|
decpackPath = [path retain];
|
|
[filenameField setStringValue:[[NSFileManager defaultManager] displayNameAtPath:path]];
|
|
[filenameField setHidden:NO];
|
|
[mountUnmountButton setTitle:
|
|
NSLocalizedStringFromTableInBundle(@"Unmount", nil, bundle, @"")];
|
|
[mountUnmountButton unregisterAsFileDropTarget];
|
|
} else {
|
|
[mountUnmountButton setTitle:
|
|
NSLocalizedStringFromTableInBundle(@"Mount", nil, bundle, @"")];
|
|
[mountUnmountButton registerAsFileDropTarget];
|
|
[filenameField setHidden:YES];
|
|
[decpackPath release];
|
|
decpackPath = nil;
|
|
}
|
|
}
|
|
|
|
|
|
- (BOOL) mount:(NSString *)path create:(BOOL)create
|
|
{
|
|
int err = [rk05 mount:path create:create];
|
|
if (err) {
|
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
|
NSAlert *alert = [[NSAlert alloc] init];
|
|
[alert setMessageText:err == -1 ?
|
|
(create ?
|
|
NSLocalizedStringFromTableInBundle(
|
|
@"Cannot create this DECpack.", nil, bundle, @"") :
|
|
NSLocalizedStringFromTableInBundle(
|
|
@"Cannot mount this DECpack, maybe it is write protected.",
|
|
nil, bundle, @"")) :
|
|
NSLocalizedStringFromTableInBundle(
|
|
@"This DECpack is already mounted to another RK05 drive.", nil, bundle, @"")
|
|
];
|
|
[alert setInformativeText:path];
|
|
[alert beginSheetModalForWindow:[mountUnmountButton window]
|
|
modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
|
[alert release];
|
|
} else
|
|
[self updateMountButton:path];
|
|
return err == 0;
|
|
}
|
|
|
|
|
|
- (void) panelDidEnd:(NSSavePanel *)panel return:(int)ret context:(void *)context
|
|
{
|
|
if (ret == NSOKButton) {
|
|
[panel close];
|
|
[self mount:[panel filename] create:[panel isMemberOfClass:[NSSavePanel class]]];
|
|
}
|
|
[[NSUserDefaults standardUserDefaults] setObject:[panel directory] forKey:LAST_FILE_PANEL_DIR_KEY];
|
|
}
|
|
|
|
|
|
- (NSArray *) openFileTypes
|
|
{
|
|
return [NSArray arrayWithObjects:DECPACK_EXTENSION_RK05, DECPACK_EXTENSION_DECPACK,
|
|
NSFileTypeForHFSTypeCode(DECPACK_HFS_TYPE_CODE), nil];
|
|
}
|
|
|
|
|
|
- (IBAction) mountUnmountClicked:(id)sender
|
|
{
|
|
if ([rk05 isMounted]) {
|
|
if ([rk05 unmount]) {
|
|
NSAlert *alert = [[NSAlert alloc] init];
|
|
[alert setMessageText:NSLocalizedStringFromTableInBundle(
|
|
@"An error occured while closing the DECpack. "
|
|
"The data on that DECpack might be corrupt.", nil,
|
|
[NSBundle bundleForClass:[self class]], @"")];
|
|
[alert setInformativeText:[filenameField stringValue]];
|
|
[alert beginSheetModalForWindow:[mountUnmountButton window]
|
|
modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
|
[alert release];
|
|
}
|
|
[self updateMountButton:nil];
|
|
} else {
|
|
if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) {
|
|
NSSavePanel *savePanel = [NSSavePanel savePanel];
|
|
[savePanel setRequiredFileType:@"rk05"];
|
|
[savePanel beginSheetForDirectory:
|
|
[[NSUserDefaults standardUserDefaults] stringForKey:LAST_FILE_PANEL_DIR_KEY]
|
|
file:nil modalForWindow:[mountUnmountButton window] modalDelegate:self
|
|
didEndSelector:@selector(panelDidEnd:return:context:) contextInfo:nil];
|
|
} else
|
|
[[NSOpenPanel openPanel] beginSheetForDirectory:
|
|
[[NSUserDefaults standardUserDefaults] stringForKey:LAST_FILE_PANEL_DIR_KEY]
|
|
file:nil types:[self openFileTypes]
|
|
modalForWindow:[mountUnmountButton window] modalDelegate:self
|
|
didEndSelector:@selector(panelDidEnd:return:context:) contextInfo:nil];
|
|
}
|
|
}
|
|
|
|
|
|
- (void) setDecpackPathAndMountAtStartup:(NSString *)path
|
|
{
|
|
if (path == nil)
|
|
return;
|
|
if ([rk05 mount:path create:NO]) {
|
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
|
NSAlert *alert = [[NSAlert alloc] init];
|
|
[alert setMessageText:[NSString stringWithFormat:NSLocalizedStringFromTableInBundle(
|
|
@"The following DECpack could not be found. It was mounted on RK05 drive %d. "
|
|
"Do you want to locate it?", nil, bundle, @""), [rk05 driveNumber]]];
|
|
[alert setInformativeText:path];
|
|
[[alert addButtonWithTitle:NSLocalizedStringFromTableInBundle(@"Yes", nil, bundle, @"")]
|
|
setKeyEquivalent:@"\r"];
|
|
[[alert addButtonWithTitle:NSLocalizedStringFromTableInBundle(@"No", nil, bundle, @"")]
|
|
setKeyEquivalent:@"\e"];
|
|
if ([alert runModal] == NSAlertFirstButtonReturn) {
|
|
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
|
[openPanel setTitle:[NSString stringWithFormat:
|
|
NSLocalizedStringFromTableInBundle(@"Locate the DECpack %C%@%C",
|
|
nil, bundle, @""),
|
|
UNICODE_LEFT_DOUBLEQUOTE,
|
|
[[NSFileManager defaultManager] displayNameAtPath:path],
|
|
UNICODE_RIGHT_DOUBLEQUOTE]];
|
|
if ([openPanel runModalForDirectory:
|
|
[[NSUserDefaults standardUserDefaults] stringForKey:LAST_FILE_PANEL_DIR_KEY]
|
|
file:nil types:[self openFileTypes]] == NSOKButton)
|
|
[self mount:[openPanel filename] create:NO];
|
|
[[NSUserDefaults standardUserDefaults]
|
|
setObject:[openPanel directory] forKey:LAST_FILE_PANEL_DIR_KEY];
|
|
}
|
|
[alert release];
|
|
} else
|
|
[self updateMountButton:path];
|
|
}
|
|
|
|
|
|
#pragma mark FileDropControlTarget Protocol
|
|
|
|
|
|
- (BOOL) willAcceptFile:(NSString *)path
|
|
{
|
|
NSString *extension = [path pathExtension];
|
|
if ([extension isEqualToString:DECPACK_EXTENSION_RK05] ||
|
|
[extension isEqualToString:DECPACK_EXTENSION_DECPACK] ||
|
|
[NSHFSTypeOfFile(path) isEqualToString:NSFileTypeForHFSTypeCode(DECPACK_HFS_TYPE_CODE)]) {
|
|
return [rk05 canMount:path];
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
|
|
- (BOOL) acceptFile:(NSString *)path
|
|
{
|
|
return [self mount:path create:NO];
|
|
}
|
|
|
|
|
|
#pragma mark Initialization
|
|
|
|
|
|
- (id) initWithCoder:(NSCoder *)coder
|
|
{
|
|
self = [super init];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifyWriteProtectChanged:)
|
|
name:WRITEPROTECT_CHANGED_NOTIFICATION object:nil];
|
|
[mountUnmountButton registerAsFileDropTarget];
|
|
if (runningOnLionOrNewer()) {
|
|
// Make the textured button a normal push button of the same size, otherwise
|
|
// the label is not centered vertically and aligned with the "Write Proctect" label
|
|
NSRect rect = [mountUnmountButton frame];
|
|
[mountUnmountButton setBezelStyle:NSRoundedBezelStyle];
|
|
[mountUnmountButton setFrame:NSInsetRect(NSOffsetRect(rect, 0, -1), -5, -2)];
|
|
}
|
|
int drive = [mountUnmountButton tag];
|
|
[rk05 setDriveNumber:drive];
|
|
[self setDecpackPathAndMountAtStartup:
|
|
[coder decodeObjectForKey:[NSString stringWithFormat:CODER_KEY_RK05_PATH_FMT, drive]]];
|
|
[rk05 setWriteProtected:
|
|
[coder decodeBoolForKey:[NSString stringWithFormat:CODER_KEY_RK05_LOCK_FMT, drive]]];
|
|
return self;
|
|
}
|
|
|
|
|
|
- (void) encodeWithCoder:(NSCoder *)coder
|
|
{
|
|
int drive = [rk05 driveNumber];
|
|
[coder encodeObject:decpackPath forKey:
|
|
[NSString stringWithFormat:CODER_KEY_RK05_PATH_FMT, drive]];
|
|
[coder encodeBool:[rk05 isWriteProtected] forKey:
|
|
[NSString stringWithFormat:CODER_KEY_RK05_LOCK_FMT, drive]];
|
|
[rk05 flush];
|
|
}
|
|
|
|
|
|
@end
|