mirror of
https://github.com/DerekK19/PDP-8-E-Simulator.git
synced 2024-10-31 14:08:29 +00:00
267 lines
8.2 KiB
Mathematica
267 lines
8.2 KiB
Mathematica
|
/*
|
||
|
* PDP-8/E Simulator
|
||
|
*
|
||
|
* Copyright © 1994-2015 Bernhard Baehr
|
||
|
*
|
||
|
* PaperTapeController.m - Controller for a paper tape reader and punch
|
||
|
*
|
||
|
* 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 "FileDropControlTargetProtocol.h"
|
||
|
#import "PaperTapeController.h"
|
||
|
#import "NSControl+FileDrop.h"
|
||
|
#import "NSThread+MainThread.h"
|
||
|
#import "Utilities.h"
|
||
|
#import "EnableDisableTextField.h"
|
||
|
#import "Unicode.h"
|
||
|
#import "InputConsumerProtocol.h"
|
||
|
#import "PaperTapeProgressIndicator.h"
|
||
|
|
||
|
|
||
|
@implementation PaperTapeController
|
||
|
|
||
|
|
||
|
#define PAPER_TAPE_ON_TAG 0
|
||
|
#define PAPER_TAPE_OFF_TAG 1
|
||
|
|
||
|
#define PAPER_TAPE_READER 0
|
||
|
#define PAPER_TAPE_PUNCH 1
|
||
|
|
||
|
|
||
|
- (void) setEnabled:(BOOL)flag
|
||
|
{
|
||
|
[loadUnloadButton setEnabled:flag];
|
||
|
[filenameField setEnabled:flag];
|
||
|
if (onOffButton)
|
||
|
[onOffButton setEnabled:flag && fileHandle != nil];
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
- (int) getChar
|
||
|
{
|
||
|
NSAssert (kind == PAPER_TAPE_READER, @"Cannot read from paper tape punch");
|
||
|
int c = EOF;
|
||
|
if (fileHandle) {
|
||
|
if (onOffButton == nil || [onOffButton selectedSegment] == PAPER_TAPE_ON_TAG) {
|
||
|
NSData *data = [fileHandle readDataOfLength:1];
|
||
|
if ([data length] == 1) {
|
||
|
c = * (unsigned char *) [data bytes];
|
||
|
if ([NSThread isMainThread])
|
||
|
[progressIndicator incrementAndAnimate];
|
||
|
else
|
||
|
[progressIndicator
|
||
|
performSelectorOnMainThread:@selector(incrementAndAnimate)
|
||
|
withObject:self waitUntilDone:NO];
|
||
|
} else {
|
||
|
if ([NSThread isMainThread])
|
||
|
[self loadUnloadClicked:self];
|
||
|
else
|
||
|
[self performSelectorOnMainThread:@selector(loadUnloadClicked:)
|
||
|
withObject:self waitUntilDone:NO];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
- (BOOL) putChar:(unsigned char)c handleBackspace:(BOOL)handleBackspace
|
||
|
{
|
||
|
NSAssert (kind == PAPER_TAPE_PUNCH, @"Cannot punch to paper tape reader");
|
||
|
BOOL done = NO;
|
||
|
if (fileHandle && (onOffButton == nil || [onOffButton selectedSegment] == PAPER_TAPE_ON_TAG)) {
|
||
|
if (c == '\b' && handleBackspace) {
|
||
|
long size = (long) [fileHandle offsetInFile];
|
||
|
if (size > 0)
|
||
|
[fileHandle truncateFileAtOffset:size - 1];
|
||
|
} else
|
||
|
[fileHandle writeData:[NSData dataWithBytes:&c length:1]];
|
||
|
if ([NSThread isMainThread])
|
||
|
[progressIndicator incrementAndAnimate];
|
||
|
else
|
||
|
[progressIndicator
|
||
|
performSelectorOnMainThread:@selector(incrementAndAnimate)
|
||
|
withObject:self waitUntilDone:NO];
|
||
|
done = YES;
|
||
|
}
|
||
|
return done;
|
||
|
}
|
||
|
|
||
|
|
||
|
- (void) mountFile:(NSFileHandle *)handle withPath:(NSString *)path
|
||
|
{
|
||
|
fileHandle = handle;
|
||
|
[fileHandle retain];
|
||
|
[fileHandle seekToEndOfFile];
|
||
|
unsigned long long offset = [fileHandle offsetInFile];
|
||
|
[fileHandle seekToFileOffset:0];
|
||
|
[progressIndicator setMaxValue:offset];
|
||
|
[progressIndicator setDoubleValue:0];
|
||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||
|
NSString *title = NSLocalizedStringFromTableInBundle(@"Unload", nil, bundle, @"");
|
||
|
if ([loadUnloadButton class] == [NSSegmentedControl class])
|
||
|
[(NSSegmentedControl *) loadUnloadButton setLabel:title forSegment:0];
|
||
|
else
|
||
|
[(NSButton *) loadUnloadButton setTitle:title];
|
||
|
[loadUnloadButton unregisterAsFileDropTarget];
|
||
|
if (onOffButton)
|
||
|
[onOffButton setEnabled:YES];
|
||
|
[filenameField setStringValue:[[NSFileManager defaultManager] displayNameAtPath:path]];
|
||
|
[filenameField setHidden:NO];
|
||
|
[progressIndicator setHidden:NO];
|
||
|
}
|
||
|
|
||
|
|
||
|
- (void) panelDidEnd:(NSSavePanel *)panel return:(int)ret context:(void *)context
|
||
|
{
|
||
|
NSFileHandle *handle;
|
||
|
|
||
|
if (ret == NSOKButton) {
|
||
|
NSString *path = [panel filename];
|
||
|
if (kind == PAPER_TAPE_READER)
|
||
|
handle = [NSFileHandle fileHandleForReadingAtPath:path];
|
||
|
else {
|
||
|
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
|
||
|
handle = [NSFileHandle fileHandleForWritingAtPath:path];
|
||
|
}
|
||
|
if (handle)
|
||
|
[self mountFile:handle withPath:path];
|
||
|
else {
|
||
|
[panel close];
|
||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||
|
NSAlert *alert = [[NSAlert alloc] init];
|
||
|
[alert setMessageText:(kind == PAPER_TAPE_READER) ?
|
||
|
NSLocalizedStringFromTableInBundle(
|
||
|
@"Cannot open this paper tape file.", nil, bundle, @"") :
|
||
|
NSLocalizedStringFromTableInBundle(
|
||
|
@"Cannot create this paper tape file.", nil, bundle, @"")];
|
||
|
[alert setInformativeText:path];
|
||
|
[alert beginSheetModalForWindow:[loadUnloadButton window]
|
||
|
modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
||
|
[alert release];
|
||
|
}
|
||
|
}
|
||
|
[[NSUserDefaults standardUserDefaults] setObject:[panel directory] forKey:LAST_FILE_PANEL_DIR_KEY];
|
||
|
}
|
||
|
|
||
|
|
||
|
- (IBAction) loadUnloadClicked:(id)sender
|
||
|
{
|
||
|
if (fileHandle) {
|
||
|
[fileHandle closeFile];
|
||
|
[fileHandle release];
|
||
|
fileHandle = nil;
|
||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||
|
NSString *title = NSLocalizedStringFromTableInBundle(@"Load", nil, bundle, @"");
|
||
|
if ([loadUnloadButton class] == [NSSegmentedControl class])
|
||
|
[(NSSegmentedControl *) loadUnloadButton setLabel:title forSegment:0];
|
||
|
else
|
||
|
[(NSButton *) loadUnloadButton setTitle:title];
|
||
|
[loadUnloadButton setEnabled:onOffButton == nil ||[onOffButton isEnabled]];
|
||
|
[loadUnloadButton registerAsFileDropTarget];
|
||
|
if (onOffButton) {
|
||
|
[onOffButton setEnabled:NO];
|
||
|
[onOffButton selectSegmentWithTag:PAPER_TAPE_OFF_TAG];
|
||
|
}
|
||
|
[filenameField setHidden:YES];
|
||
|
[progressIndicator setHidden:YES];
|
||
|
} else {
|
||
|
NSSavePanel *panel = (kind == PAPER_TAPE_READER) ?
|
||
|
[NSOpenPanel openPanel] : [NSSavePanel savePanel];
|
||
|
[panel beginSheetForDirectory:
|
||
|
[[NSUserDefaults standardUserDefaults] stringForKey:LAST_FILE_PANEL_DIR_KEY]
|
||
|
file:nil modalForWindow:[loadUnloadButton window] modalDelegate:self
|
||
|
didEndSelector:@selector(panelDidEnd:return:context:) contextInfo:nil];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
- (IBAction) onOffClicked:(id)sender
|
||
|
{
|
||
|
if ([onOffButton selectedSegment] == PAPER_TAPE_ON_TAG) {
|
||
|
[loadUnloadButton setEnabled:NO];
|
||
|
if (kind == PAPER_TAPE_READER)
|
||
|
[inputConsumer canContinueInput];
|
||
|
} else {
|
||
|
[loadUnloadButton setEnabled:YES];
|
||
|
[progressIndicator stopAnimation:sender];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
- (void) awakeFromNib
|
||
|
{
|
||
|
kind = [loadUnloadButton tag];
|
||
|
adjustToolbarControlForTiger (filenameField);
|
||
|
adjustToolbarControlForTiger (progressIndicator);
|
||
|
[loadUnloadButton registerAsFileDropTarget];
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark FileDropControlTarget Protocol
|
||
|
|
||
|
|
||
|
- (BOOL) willAcceptFile:(NSString *)path
|
||
|
{
|
||
|
NSFileHandle *handle = (kind == PAPER_TAPE_READER) ?
|
||
|
[NSFileHandle fileHandleForReadingAtPath:path] :
|
||
|
[NSFileHandle fileHandleForWritingAtPath:path];
|
||
|
if (handle) {
|
||
|
[handle closeFile];
|
||
|
// [handle release]; // dont'd release, it crashs
|
||
|
}
|
||
|
return handle != nil;
|
||
|
}
|
||
|
|
||
|
|
||
|
- (BOOL) acceptFile:(NSString *)path
|
||
|
{
|
||
|
NSFileHandle *handle = nil;
|
||
|
if (kind == PAPER_TAPE_PUNCH) {
|
||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||
|
NSAlert *alert = [[NSAlert alloc] init];
|
||
|
[alert setMessageText:[NSString stringWithFormat:NSLocalizedStringFromTableInBundle(
|
||
|
@"Do you really want to overwrite %C%@%C with the paper tape output?",
|
||
|
nil, bundle, @""),
|
||
|
UNICODE_LEFT_DOUBLEQUOTE,
|
||
|
[[NSFileManager defaultManager] displayNameAtPath:path],
|
||
|
UNICODE_RIGHT_DOUBLEQUOTE]];
|
||
|
[alert setInformativeText:NSLocalizedStringFromTableInBundle(
|
||
|
@"The current content of the file will be lost.", nil, bundle, @"")];
|
||
|
[[alert addButtonWithTitle:NSLocalizedStringFromTableInBundle(
|
||
|
@"Yes", nil, bundle, @"")] setKeyEquivalent:@"\r"];
|
||
|
[[alert addButtonWithTitle:NSLocalizedStringFromTableInBundle(
|
||
|
@"No", nil, bundle, @"")] setKeyEquivalent:@"\e"];
|
||
|
[alert setAlertStyle:NSCriticalAlertStyle];
|
||
|
if ([alert runModal] == NSAlertFirstButtonReturn &&
|
||
|
(handle = [NSFileHandle fileHandleForWritingAtPath:path]))
|
||
|
[handle truncateFileAtOffset:0];
|
||
|
[alert release];
|
||
|
} else
|
||
|
handle = [NSFileHandle fileHandleForReadingAtPath:path];
|
||
|
if (handle)
|
||
|
[self mountFile:handle withPath:path];
|
||
|
return handle != nil;
|
||
|
}
|
||
|
|
||
|
|
||
|
@end
|