This is CharController.m in view mode; [Download] [Up]
/*********************************************************************** Controller class for Convert TEXT which converts between Mac and NeXT text. Copyright (C) 1993 David John Burrowes This program 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 1, 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author, David John Burrowes, can be reached at: davidjohn@kira.net.netcom.com David John Burrowes 1926 Ivy #10 San Mateo, CA 94403-1367 ***********************************************************************/ #import "CharController.h" #import "NeXTToMacText.h" #import "MacToNeXTText.h" #import "CRLFToNeXTText.h" #import "NeXTToCRLFText.h" #import "File.h" #import <appkit/Cell.h> #import <appkit/Matrix.h> @implementation CharController ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: init // Parameters: none // Returns: self // Stores: none // Description: // This overrides the defalut init method. But it does little else. // Other initializations done in AppDidInit, above... // Note that subclasses should OVERRIDE this // Bugs: // History: // 93.07.05 djb Reworked conversion preferences. Used tobe a boolean for yes or no // to indicate mac vs. next source conversion. Now use a string to // indicate what kinda conversion should be default. Non-intuitively, // I've decided to leave the default name the same (DoMacConversio) // and let it keep the old yes/no, as well as newer MacToNeXT, etc // options. Icky, but provides some upward compat.. HOWEVER. // This has taught me, I think, the lesson that: defaults names should // be a bit general, and it's better if their options are meaningful rather // than booleans. Both allow later changes without breaking things like // this. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - init { // // Get all the default values from the database // static NXDefaultsVector theDefaults = { {"UseCurlyQuotes", "NO"}, {"UseIMv1", "NO"}, {"DoMacConversion", "MacToNeXT"}, {NULL, NULL} }; CString tempPreference; [super init]; // // Set up strings for the interface. // ConversionString = "Converting text files"; SourcePrompt = "Source file:"; DestPrompt = "Dest file:"; DestExtension = ""; DefaultsOwner = "MacToNeXTText"; NXRegisterDefaults(DefaultsOwner, theDefaults); // // Note that we completely ignore the old DoMacConversion preference. // We neither read nor remove it. // UseCurlyQuotes = [self GetBoolPref: "UseCurlyQuotes"]; UseIMv1 = [self GetBoolPref: "UseIMv1"]; tempPreference = [self GetPref: "DoMacConversion"]; // // New for 1.1. Get a more detailed conversion type from the defaults database, // and set our new ConversionType flag appropriately. // if ((strcmp(tempPreference, "MacToNeXT") == 0) || (strcmp(tempPreference, "YES") == 0) ) DefaultConversion = MacToNeXT; else if ((strcmp(tempPreference, "NeXTToMac") == 0) || (strcmp(tempPreference, "NO") == 0) ) DefaultConversion = NeXTToMac; else if (strcmp(tempPreference, "CRLFToNeXT") == 0) DefaultConversion = CRLFToNeXT; else if (strcmp(tempPreference, "NeXTToCRLF") == 0) DefaultConversion = NeXTToCRLF; // // Since we are pretending to be a converter as well as controller, define our manager // And, then set ourselves up to recieve the messages we sent to a converter! // myManager = NullInstance; converterInst = self; // // Set up default converter. // theConverter = NullInstance; CurrentConversion = DefaultConversion; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: displayPreferences: // Parameters: the object that called us // Returns: self // Stores: none // Description: // This is called whenever we need to bring the preferences panel onto the screen. // Using the value in our internal preference variables, then we set the buttons // in the preference panel to reflect these, and then we show the panel. // History: // 93.07.05 djb Modified for 1.1's more complex default conversion choices. // Bugs: // Well, strictly speaking, this is only needed the first time this is called, // because thereafter the buttons maintain their own highlite properly. // Oh well. This whole scheme is a bit awkward, given my trivial use, and the fact // that it really seems to be designed for bigger things. // This doesn't set any ResultObject fields. =( ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -displayPreferences: sender { // // Get the default preference values, and compare judge what buttons to // highlight for the user. // if (UseIMv1 == YES) [UseIMv1Button setIntValue: 1]; else [UseIMv1Button setIntValue: 0]; if (UseCurlyQuotes == YES) [UseCurlyQuotesButton setIntValue: 1]; else [UseCurlyQuotesButton setIntValue: 0]; switch (DefaultConversion) { case MacToNeXT: [DefaultConversionButton selectCellWithTag: MacToNeXT]; break; case NeXTToMac: [DefaultConversionButton selectCellWithTag: NeXTToMac]; break; case CRLFToNeXT: [DefaultConversionButton selectCellWithTag: CRLFToNeXT]; break; case NeXTToCRLF: [DefaultConversionButton selectCellWithTag: NeXTToCRLF]; break; } [prefPanel makeKeyAndOrderFront:self]; // return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: SetIMV1: // Parameters: the object that called us // Returns: self // Stores: nothing! // Description: // This method gets called whenever the user clicks on a button to change // the setting of whether we should use IMv1 when converting Mac files. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - SetIMV1: sender { if ( [sender intValue] == 1) UseIMv1 = YES; else UseIMv1 = NO; [self SetBoolPref: "UseIMv1" To: UseIMv1]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: SetUseCurlyQuotes: // Parameters: the object that called us // Returns: self // Stores: nothing! // Description: // This method gets called whenever the user clicks on a button to change // the setting of whether we should convert to curly quotes when converting NeXT files. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SetUseCurlyQuotes: sender { if ( [sender intValue] == 1) UseCurlyQuotes = YES; else UseCurlyQuotes = NO; [self SetBoolPref: "UseCurlyQuotes" To: UseCurlyQuotes]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: SetDefaultConversion: // Parameters: the object that called us // Returns: self // Stores: nothing! // Description: // This method gets called whenever the user clicks on a button to change // the setting of whether we should assume files to be converted are Mac ones or not. // History: // 93.07.05 djb Modified for 1.1's richer conversion options. NOTE: This // makes some assumptions that the sender's value will always be // one of it's conversionvalues. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SetDefaultConversion: sender { DefaultConversion = [[sender selectedCell] tag] ; switch ( DefaultConversion ) { case MacToNeXT: [self SetPref: "DoMacConversion" To: "MacToNeXT"]; break; case NeXTToMac: [self SetPref: "DoMacConversion" To: "NeXTToMac"]; break; case CRLFToNeXT: [self SetPref: "DoMacConversion" To: "CRLFToNeXT"]; break; case NeXTToCRLF: [self SetPref: "DoMacConversion" To: "NeXTToCRLF"]; break; } CurrentConversion = DefaultConversion; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: PrepareToConvertMac // Parameters: the object that send this message // Returns: self // Stores: nothing // Description: // Sets the flag for the kind of conversion to do (not a mac one), and convert a file. // Bugs: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - PrepareToConvertMac:sender { CurrentConversion = MacToNeXT; [self PrepareForConversion: self]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: PrepareToConvertNeXT // Parameters: the object that send this message // Returns: self // Stores: nothing // Description: // Sets the flag for the kind of conversion to do (not a mac one), and convert a file. // Bugs: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - PrepareToConvertNeXT:sender { CurrentConversion = NeXTToMac; [self PrepareForConversion: self]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: PrepareToConvertCRLF // Parameters: the object that send this message // Returns: self // Stores: nothing // Description: // Sets the flag for the kind of conversion to do (CRLF to NeXT) and does the // conversion. We set the CurrentConversion flag here to override the default // value it would have.. // Bugs: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - PrepareToConvertCRLF:sender { CurrentConversion = CRLFToNeXT; [self PrepareForConversion: self]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: PrepareToConvertNeXTToCRLF // Parameters: the object that send this message // Returns: self // Stores: nothing // Description: // Sets the flag for the kind of conversion to do (NeXT to CRLF) and does the // conversion. We set the CurrentConversion flag here to override the default // value it would have.. // Bugs: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - PrepareToConvertNeXTToCRLF:sender { CurrentConversion = CRLFToNeXT; [self PrepareForConversion: self]; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: ReportTo: // Parameters: The caller // Returns: none // Stores: none // Description: // ConvertController's use this to tell the converter what object to report status // to. That is, we must tell sender when we are, for example, 50% of the way // done so it can let the user know what's going on. Subclasses should have no // need of subclassing this. It will always be set up before a call to the main // conversion routine. // Bugs: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ReportTo: sender { myManager = sender; return self; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Method: isThisAGoodFile: // Parameters: A File instance // Returns: YES if it is, NO if it isn't. // Stores: none // Description: // A converter, in addition to converting a file X to a file Y, should be able to // identify when a source file is a legitimate file for conversion. In the case of // this abstract class, this method does nothing. A subclass, however, will // subclass this method and have it examine the specified file, and determine // if it's a legit file or not. It returns YES if the file is good, or NO if the file is // questionable or bad. // Bugs: // We need to use the proposed Fact datatype here, instead of Boolean. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (Boolean) isThisAGoodFile: Instance { return YES; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Routine: ConvertFrom:To: // Parameters: The file to be converted from, and the file to be converted to // Returns: self // Stores: error code // Description: // This uses the object stored in this object's instance variable theConverter // to convert the contents of the source file to a new form, and writes them out // into the destination file. Note that this assumes that the converter is a subclass // of textConverter. Basiclally, loop until we find the eof, readin 512 byte chunks, // converting, and writing out. In the last time through, we find Eof, and // write out what we read in that was just before this eof, then quit when we // loop around. // History: // 93.07.05 djb Modified for the now 4 types of conversions, rather than the older 2. // Bugs // We ignore errors that the file access might generate. // (if we don't read 512 bytes, and we don't find eof, then we have an error. // but we don't check for it either ) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ConvertFrom: sourceFile To: destinationFile { Pointer sourceBuffer = NewPointer(512); Pointer destinationBuffer; PositiveInteger numWritten, bytesRead = 512; Boolean eofFound = NO; Real modifier = 100.0 / [sourceFile FileSize]; [super ConvertFrom: sourceFile To: destinationFile]; [MacConvertCommand setEnabled: NO]; [NextConvertCommand setEnabled: NO]; [CRLFConvertCommand setEnabled: NO]; [NeXT2CRLFConvertCommand setEnabled: NO]; [ConvertCommands setEnabled: NO]; // // Kill any converter waiting around, then set up the proper one for this conversion. // if (theConverter != NullInstance) [theConverter free]; switch ( CurrentConversion ) { case MacToNeXT: theConverter = [ [MacToNeXTText alloc] init ]; [theConverter UseIM1: UseIMv1]; ConversionString = "Converting Macintosh text to NeXT text"; break; case NeXTToMac: theConverter = [[NeXTToMacText alloc] init]; [theConverter ConvertSingleQuotes: UseCurlyQuotes]; ConversionString = "Converting NeXT text to Macintosh text"; break; case CRLFToNeXT: theConverter = [ [CRLFToNeXTText alloc] init ]; ConversionString = "Converting CRLF text to NeXT text"; break; case NeXTToCRLF: theConverter = [ [NeXTToCRLFText alloc] init ]; ConversionString = "Converting NeXT text to CRLF text"; break; } // // With the converter set up, set the flag so it will do the default conversion // (stored in DoMacConversion) next time if none other is specified. // (that is, if someone drags a file onto our window, do the default conversion, // and not the one we are actually about to do). // CurrentConversion = DefaultConversion; [super ConvertFrom: sourceFile To: destinationFile]; while ((eofFound != YES) && (bytesRead == 512)) { [sourceFile Read: 512 BytesInto: sourceBuffer]; bytesRead = [sourceFile GetPositiveInteger]; eofFound = [sourceFile GetBooleanFrom: SECOND_RESULT]; // // If eof was found, then this is our last pass through the converter. // [theConverter ConvertString: sourceBuffer WithLength: bytesRead]; destinationBuffer = [theConverter GetPointer]; numWritten = [theConverter GetPositiveIntegerFrom: SECOND_RESULT]; [destinationFile Write: numWritten BytesFrom: destinationBuffer]; [myManager SetPercentageDone: modifier * [sourceFile GetCurrentPosition]]; } [MacConvertCommand setEnabled: YES]; [NextConvertCommand setEnabled: YES]; [CRLFConvertCommand setEnabled: YES]; [NeXT2CRLFConvertCommand setEnabled: YES]; [ConvertCommands setEnabled: YES]; // return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.