home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-12 | 66.2 KB | 1,998 lines |
- head 1.4;
- branch ;
- access ;
- symbols beta10:1.3;
- locks death:1.4;
- comment @@;
-
-
- 1.4
- date 93.04.04.23.44.18; author death; state Exp;
- branches ;
- next 1.3;
-
- 1.3
- date 93.01.10.15.07.50; author death; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 92.07.26.13.57.36; author death; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 92.07.26.13.51.42; author death; state Exp;
- branches ;
- next ;
-
-
- desc
- @Basic and primitive convert controller object
- @
-
-
- 1.4
- log
- @Sun Apr 4 23:44:18 PDT 1993
- @
- text
- @#import "ConvertController.h"
- #import "File.h"
- #import "AbstractConverter.h" // mainly to stop annoying 'I don't know about this runtime method call'
-
- #import <stdio.h>
- #import <stdlib.h>
- #import <string.h>
- #import <appkit/Panel.h>
- #import <appkit/Window.h> // for manipulations of ProgressWindow
- #import <appkit/Matrix.h>
- #import <appkit/Cell.h>
- #import <appkit/SavePanel.h>
- #import <appkit/OpenPanel.h>
- #import <libc.h> //for getwd
- #import <sys/param.h>
- //
- // Include the following 2 for drag and drop facility, plus for IAC communications.
- //
- #import "ConvertListener.h"
- #import "ConvertSpeaker.h"
- #import <appkit/Application.h> // To get NXApp (I thought that is what defaults was...)
- #import <appkit/publicWraps.h> // for NXConvertWinNumToGlobal
- #import <appkit/graphics.h> // For NXPing
- #import <appkit/publicWraps.h> // For NXBeep
-
- @@implementation ConvertController
-
- /*============================================================*\
-
- The following routines are all for the application delegate responsibilities of this
- class. Basically dealing with starting up, shutting down, and with allowing the
- user to double click on a file in the workspace and have it open up, and setting up
- for providnig communications between applications
-
- \*============================================================*/
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: appWillInit:
- // Parameters: our caller
- // Returns: self
- // Stores: none
- // Description:
- // This is used to store a specialized speaker and listener in the application.
- // these specialized objects are subclasses of the normal speaker and listener
- // classes, and together implement a method to allow the caller to instruct this
- // class to convert a file.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - appWillInit: sender
- {
- Instance mySpeaker;
- Instance myListener;
- //
- // Set up the conversion-aware speaker
- //
- mySpeaker = [[ConvertSpeaker alloc] init];
- [mySpeaker setDelegate:NXApp];
- [NXApp setAppSpeaker:mySpeaker];
- //
- // Set up the conversion-aware listener
- //
- myListener = [[ConvertListener alloc] init];
- [myListener setDelegate:NXApp];
- [NXApp setAppListener:myListener];
-
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: appDidInit:
- // Parameters: our caller
- // Returns: self
- // Stores: none
- // Description:
- // This is for when this class acts as a delegate to the application. It allows it to
- // do some final initialization stuff. The big thins is to allow us to register out
- // window so the user will be able to drag icons over it, and thus serve as the
- // drag-and-drop facilities that we support. This later causes iconEntered: and
- // iconReleasedAt::ok: messages to be sent later.
- // The 2.x code for the drag-and-drop was mainly copied from DrawDocument.
- // The 3.x code is copied straight from NeXT's Window.rtf help doc. The window
- // registration for 3.0 is much more straight forward.
- // Bugs:
- // Perhaps I should be using appDidBecomeActive here some?
- // History
- // 93.01.24 djb Modified so will make use of NS 3.0 drag and drop
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - appDidInit: sender
- {
- #if ((NSmajor == 2) || (DoNS3DragNDrop == 0))
- //
- // Allocate a listener instance, and store as one of our instance variables.
- // Set it up as using our private port, and have the app's speaker register
- // the window and port.
- //
- listener = [[Listener allocFromZone:[self zone]] init]; // from MY zone?
- [listener setDelegate:self]; // We'll now get the messages from the workspace
- [listener usePrivatePort];
- [listener addPort];
- #endif
- [self allowDragAndDrop]; // do nothing special for NS 3.0 style
- //
- // Force the window the front, and give it's miniwindow an icon.
- //
- [ProgressWindow setMiniwindowIcon: "Application"];
- [ProgressWindow makeKeyAndOrderFront:self];
- //
- // 93.01.08 djb Whoops. Wasn't disabling parts of edit menu right off as needs to be
- //
- [cutCommand setEnabled: NO];
- [pasteCommand setEnabled: NO];
- [spellingCommand setEnabled: NO];
- [checkSpellingCommand setEnabled: NO];
-
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: appWillTerminate:
- // Parameters: our caller
- // Returns: self
- // Stores: none
- // Description:
- // This serves tobalance the init above!
- // Mainly, it unregisters our window information that was used to allow the
- // workspace to have the user drag folders over our window!
- // This code is basically copied directly from DrawDocument.m =)
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - appWillTerminate: sender
- {
- [self refuseDragAndDrop];
- if (listener != NullInstance)
- [listener free];
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: appAcceptsAnotherFile:
- // Parameters: our caller
- // Returns: self
- // Stores: none
- // Description:
- // If we can accept another file to be opened, we return YES. If we can't we respond
- // NO. For now, we always return that we'll accept another file. This just ends
- // up queueing files waiting to be converted.
- // Bugs:
- // To be honest, this makes me a bit uncomfortable. I feel as though I should be
- // keeping some kinda lock and returning NO if I'm presently converting
- // something. yet, if I'm converting something, nothing else should be able to
- // be doing any execution here, so I guess it doesn't matter.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - (BOOL)appAcceptsAnotherFile:sender
- {
- return YES;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: app:openFile:type:
- // Parameters: The name of the file to be converted
- // It's extension
- // Returns: a flag indicating whether we can deal with the file
- // Stores: none
- // Description:
- // The user double clicked on a file in the workspace, and now we are asked to open it.
- // All this does, though, is pass the file information on to the first level conversion
- // method and let it try to deal with it.
- // Bugs:
- // Might it be nicer to play a game, like below, where we do a 'perform' to do the
- // conversion after we return YES to the caller? That begins to seem a bit
- // dangerous to me. still.....
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - (int)app:sender openFile:(const char *)filename type:(const char *)aType
- {
- CString tempString;
- //
- // Ask the convert controlling object to convert this particular file
- //
- [self ConvertThisFile: filename];
- //
- // Check if the file was converted alright...
- //
- if ([self GetErrorCode] == ERR_OK)
- {
- [SourceTitle setStringValue: "Converted:"];
- [Status setStringValue: "The conversion is done."];
- [self StoreErrorCode: ERR_OK AndText: "Conversion process done"];
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- }
-
- return YES; // Always report that it was converted ok
- }
-
-
- /*============================================================*\
-
- The following routines are all for the drag-and-drop facilities which allow the
- user to drag files from the workspace, and drop them over the main window of
- the application. Fun with InterProcessCommuniction. =)
-
- \*============================================================*/
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: iconEntered:at:iconWindow:iconX:iconY:iconWidth:iconHeight:pathList:
- // Parameters: various, mostly not important at the moment
- // Returns: 0 if successfull, something else if not
- // Stores: none
- // Description:
- // When the user drags a clump of one of more files over our window, we get
- // this message. We store away the list of files, because we are not given it
- // later on. =( Note that we first free any pending set of file paths in the
- // extremely unlikely condition that there is one already there, and then
- // copy the list of paths for use in iconReleasedAt: below
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (int)iconEntered:(int)windowNum at:(double)x :(double)y
- iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
- iconWidth:(double)iconWidth iconHeight:(double)iconHeight
- pathList:(char *)pathList
- {
- if (filePaths != NullCString)
- FreeCString(filePaths);
- filePaths = NewCString(strlen(pathList));
- strcpy(filePaths, pathList);
- return 0;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: iconMovedTo::
- // Parameters: n/a
- // Returns: n/a
- // Stores: n/a
- // Description:
- // I'm NOT implimenting this, though it might still be nice if we wanted some
- // kinda graphical effect, or if we could enforce dropping in only a particular
- // area (I like this idea, rather than the generic droppoing we have now...
- // (heh. drop on the NeXT icon to convert it TO NeXt, drop it on the Mac
- // to convert TO mac. =) However, the below code demonstrates that one can
- // not change the little-copy-cursor-icon-thingie based on a return value
- // Bugs:
- // None, of course, since it is commented out, unless you count that I've grotesquely put it
- // all on one line so one doesn't mistake that it is in fact commented out for now.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /*- (int)iconMovedTo:(double)x :(double)y { if ((x > 100) || (y > 100)) {NXBeep(); return 0;} else return 1; } */
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: iconReleasedAt::ok:
- // Parameters: x and y coords of the dropping point
- // Returns: 0 if successfull, something else if not
- // a ptr to a boolean flag returned by reference
- // Stores: none
- // Description:
- // When the user droppes the files, we inform the workspace manager that we
- // can deal with them (always). We then ask ourselves to do something in
- // some fraction of a second.
- // The reason for all this is simple: processing the files is apt to take some time,
- // and we don't want that icon hanging on the window while we do so. So,
- // we gotta return soon. Fact is, we also want to be liberal about what kind
- // of files to accept, since in general many of these conversion programs may not
- // have files with 'proper' extensions (e.g. what isthe extension for a Mac font?).
- // So, we tell the workspace all is well, so the icon goes away. Soon, we get
- // reminded to ProcessDroppedFiles, which will go through and actually start
- // the processing.
- // Bugs:
- // As with some of the routines above, a bit of me is concerned that if this code is
- // executed while this instance is also doing some conversion, trouble will result.
- // but, then, of course, this isn't a multi-threaded thing, so I shouldn't need to
- // worry about that. Why does my mind keep trying to think in terms of a
- // processing architecture that doesn't exist yet?
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
- {
-
- [self perform: @@selector(ProcessDroppedFiles)
- with: self
- afterDelay: 100
- cancelPrevious: NO];
- *flag = YES;
- return 0;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: iconExitedAt::
- // Parameters: The x and y coordinates at which the icon left the window
- // Returns: 0 if successfull, something else if not
- // Stores: none
- // Description:
- // If the user drags the icon off the window, we just free the string of
- // paths and reutrn.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (int)iconExitedAt:(double)x :(double)y
- {
- if (filePaths != NullCString)
- {
- FreeCString(filePaths);
- filePaths = NullCString;
- }
- return 0;
- }
-
-
- #if (NSmajor == 3)
-
- /*============================================================*\
-
- The following routines are NeXTSTEP 3.0 routines that will allow for drag and drop
- of filenames. NOTE that these are equivalent to the routines above, and that both
- are being maintained so I can recompile easily under 2.1 if needed.
- NOTE! For this to work, the instance that this is must be designated the delagate
- of the progresswindow!
- It Might be more efficient, by the way, instead of registering and undregistering the
- accepted types all the time, to instead set a flag and return NX_DragOperationNone.
-
- \*============================================================*/
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: draggingEntered:
- // Parameters: the caller
- // Returns: NX_DragOperationCopy
- // Stores: none
- // Description:
- // Aside from telling the caller that we'll happily convert whatever files we're
- // being asked about, this also gets and stores the tab delimited list of file names
- // for potential later processing.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (NXDragOperation)draggingEntered:(id)sender
- {
- Instance filenamePasteboard;
- CString names;
- int thelength;
- filenamePasteboard = [sender draggingPasteboard];
-
- if (filePaths != NullCString)
- FreeCString(filePaths);
- [filenamePasteboard readType: NXFilenamePboardType data: &names
- length: &thelength];
- filePaths = NewCString(thelength);
- strcpy(filePaths, names);
- [filenamePasteboard deallocatePasteboardData: names length: thelength];
-
- return NX_DragOperationCopy;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: draggingUpdated:
- // Parameters: the caller
- // Returns: NX_DragOperationCopy
- // Stores: none
- // Description:
- // This merely indicates that we'll be happy to try to convert the specified
- // filenames. We aren't particular aboout what kinds of files they are. =)
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (NXDragOperation)draggingUpdated:(id)sender
- {
- return NX_DragOperationCopy;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: prepareForDragOperation:
- // Parameters: the caller
- // Returns: YES
- // Stores: none
- // Description:
- // We will always do the drag operation.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (BOOL)prepareForDragOperation:(id)sender
- {
- return YES;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: performDragOperation:
- // Parameters: the caller
- // Returns: YES
- // Stores: none
- // Description:
- // Convert the file(s). Indicate that we could.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (BOOL)performDragOperation:(id)sender
- {
- [self perform: @@selector(ProcessDroppedFiles)
- with: self
- afterDelay: 100
- cancelPrevious: NO];
- return YES;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: concludeDragOperation:
- // Parameters: the caller
- // Returns: self
- // Stores: none
- // Description:
- // Do nothing, as there's nothing to clean up, really (we could free the copy of
- // the pathnames, but there's no real urgent need).
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - concludeDragOperation:(id)sender
- {
- return self;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: draggingExited:
- // Parameters: the caller
- // Returns: returns self
- // Stores: none
- // Description:
- // If the user drags the icon off the window, we just free the string of
- // paths and reuturn
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - draggingExited:(id)sender
- {
- if (filePaths != NullCString)
- {
- FreeCString(filePaths);
- filePaths = NullCString;
- }
- return self;
- }
-
- #endif
-
-
- /*============================================================*\
-
- The following routines are various basic utility routines used by the above
- methods. In short: toggle drag-and-drop on and off, and process the file names
- when/if they are actually dropped.
-
- \*============================================================*/
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: refuseDragAndDrop
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This handy method is used to turn off our request to allow files to be dropped
- // over the application's window. Clearly, it has conditionally compiled sections
- // for NS 3.0 and 2.x style drag and drop
- // Bugs:
- // History:
- // 93.01.24 djb Added support for 3.0 style drag and drop
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - refuseDragAndDrop
- {
- #if ((NSmajor == 2) || (DoNS3DragNDrop == 0))
- unsigned int windowNum;
- Instance speaker = [NXApp appSpeaker];
-
- if (listener != NullInstance)
- {
- [speaker setSendPort: NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
- NXConvertWinNumToGlobal([ProgressWindow windowNum], &windowNum);
- [speaker unregisterWindow: windowNum];
- }
- #else
- [ProgressWindow unregisterDraggedTypes];
- #endif
-
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: allowDragAndDrop
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This turns on the ability to have files droped over our window so we can
- // process them. It has code fro both NS 2.x and 3.x style implementations
- // Bugs:
- // History:
- // 93.01.24 djb Added support for 3.0 style drag and drop
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - allowDragAndDrop
- {
- #if ((NSmajor == 2) || (DoNS3DragNDrop == 0))
- unsigned int windowNum;
- Instance speaker = [NXApp appSpeaker];
-
- NXConvertWinNumToGlobal([ProgressWindow windowNum], &windowNum);
- [speaker setSendPort: NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
- [speaker registerWindow:windowNum toPort:[listener listenPort]];
- #else
- //
- // We must tell the window to be ready for some dragged file names
- //
- const char *dataType[] = {NXFilenamePboardType};
- [ProgressWindow registerForDraggedTypes: dataType count:1];
- #endif
-
- return self;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: ProcessDroppedFiles
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // There is, presumably, string of file names waiting to be processed. We
- // should process them one at a time, then. We make a copy of the file name
- // list, and then repeatedly locate the and start and end of each file path name
- // in the list (they're tab delimited). For each that we find, we process it.
- // Bugs:
- // We could almost certainly munge the file path string directly, but I feel
- // safer treating it 'right'.
- // If any of the files have tabs in their names, I have no idea what will or will
- // have happened.
- // I chose not to nuke the filePaths at when done here. This might not be good?
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - ProcessDroppedFiles
- {
- CString allpaths,
- nextpath,
- location;
- CString tempString;
-
- allpaths = NewCString(strlen(filePaths));
- strcpy(allpaths, filePaths);
- nextpath = allpaths;
- do
- {
- //
- // Find the next tab. If we found it, put a null there. If we did not,
- // then this is the end of allpaths. We still have the last file name to
- // process, so we keep going. In all cases, convert the file, set up for
- // the next conversion (if any). Check whether we reached the end, and
- // if so quit.
- //
- location = strchr(nextpath, '\t');
- if (location != EndOfCString)
- location[0] = EndOfCString;
- [self ConvertThisFile: nextpath];
- //
- // Check if the file was converted alright...
- //
- if ([self GetErrorCode] == ERR_OK)
- {
- [SourceTitle setStringValue: "Converted:"];
- [Status setStringValue: "The conversion is done."];
- [self StoreErrorCode: ERR_OK AndText: "Conversion process done"];
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- }
- nextpath = location+1;
- }
- while (location != EndOfCString);
- FreeCString(allpaths);
- return self;
- }
-
-
-
- /*============================================================*\
-
- The following methods are intended to be used to allow a limited dialog as the
- 'slave' of another app that wants us to convert a file.
-
- \*============================================================*/
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: msgQuit
- // Parameters: An integer that we fill in YES if we work (we always work =)
- // Returns: self
- // Stores: none
- // Description:
- // This will set up a delayed message to the app to have it quit. We allow PLENTY
- // of time for us to quit and retun to the caller before that method gets invoked. If
- // we didn't provide enough time (as, for instance the Draw demo app does not), then
- // the caller will hang until time out because we would never return from the call.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (int)msgQuit:(int *)flag
- {
- [NXApp perform:@@selector(terminate) with: NXApp afterDelay: 300
- cancelPrevious: NO];
- *flag = YES;
- return 0;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: msgConvert:To:
- // Parameters: The name of the file to convert from, and the name of the file to convert to.
- // Returns: self
- // Stores: none
- // Description:
- // This provides a way for an other application to call us, and get into our
- // main conversion routines below. This takes the two files, opens them, and jumps
- // to the main conversio method. If either fails to open, we abort the process.
- // However, the caller never learns of this.
- // These file names, basically, should be complete pathnames
- // Bugs:
- // I still don't understand how we we can be sure that these strings haven't been
- // freed by the time we get to them...
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - msgConvert: (char *) sourceFile To: (char*) destFile
- {
- CString sourceName = NewCString(strlen(sourceFile));
- CString destName = NewCString(strlen(destFile));
- CString dirname;
- CString filename;
- CString tempString;
- Instance source;
- Instance destination;
-
- strcpy(sourceName, sourceFile);
- strcpy(destName, destFile);
- //
- // Get ourselves out of the way of the caller.
- // Bug: We still display our window briefly.
- //
- [NXApp hide: self];
-
- source = [self openSourceFile: sourceName];
- if ([self GetErrorCode] == ERR_OK)
- {
- [StatusTitle setStringValue: "Status:"];
- [Status setStringValue: "Converting"];
- [SourceTitle setStringValue: "Converting:"];
- [SourcePathTitle setStringValue: "In:"];
- filename = [source GetFilename];
- dirname = [source GetDirectory];
- [SourceFileName setStringValue: filename];
- [SourcePath setStringValue: dirname];
- FreeCString (filename);
- FreeCString (dirname);
-
- destination = [self openDestFile: destName];
- if ([self GetErrorCode] == ERR_OK)
- {
- [DestTitle setStringValue: "To:"];
- [DestPathTitle setStringValue: "In:"];
-
- filename = [destination GetFilename];
- dirname = [destination GetDirectory];
- [DestFileName setStringValue: filename];
- [DestPath setStringValue: dirname];
- FreeCString (filename);
- FreeCString (dirname);
- [self DoConversionFrom: source To: destination];
- if ([self GetErrorCode] == ERR_OK)
- {
- [SourceTitle setStringValue: "Converted:"];
- [Status setStringValue: "The conversion is done."];
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- }
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- [Status setStringValue: "Could not open the destination file."];
- [source free];
- }
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- [Status setStringValue: "Could not open the source file."];
- }
- FreeCString(sourceName);
- FreeCString(destName);
-
- return 0;
- }
-
-
-
- /*============================================================*\
-
- The rest of the methods here do the stuff that is the focus of the application.
- Specifically, we init, deal with user preference settings, set the indicator on the
- screen to indicate how far done the conversion is, open and close files and check
- that the file to be converted is OK.
-
- \*============================================================*/
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // 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:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - init
- {
- CString temppath,
- fullpath,
- tempPos;
-
- [super init];
- destIsDead = NO;
- //
- // Clear, if necessary, the string of file names
- //
- filePaths = NullCString;
- //
- // Provide silly defaul strings.
- //
- ConversionString = "Converting a file to another";
- SourcePrompt = "a file:";
- DestPrompt = "another file:";
- DestExtension = ".a";
- DefaultsOwner = "I have no defaults";
- //
- // Locate the path where the application exists (if the app is a foo.app type appwrapper,
- // this includes the foo.app directory).
- // (if NXArgv doesn't have a full path, build one using getwd)
- //
- AppHome = NewCString(MAXPATHLEN);
- strcpy(AppHome, NXArgv[0]);
- if (AppHome[0] != '/')
- {
- //
- // We musta been started up from the command line, so use our working
- // directory to constructe the rest of the path.
- //
- temppath = NewCString(MAXPATHLEN);
- getwd(temppath);
- fullpath = NewCString(strlen(temppath) + 1 + strlen(AppHome));
- sprintf(fullpath, "%s/%s", temppath, AppHome);
- FreeCString(AppHome);
- AppHome = fullpath;
- FreeCString(temppath);
- }
- //
- // Now, remove the application's name from the end of the path.
- //
- tempPos = strrchr(AppHome, '/');
- tempPos[0] = EndOfCString;
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: free
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This merely cleans up after ourselves.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - free
- {
- FreeCString(AppHome);
- return self;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: GetBoolPref
- // Parameters: The preference that we are to retrieve the value for
- // Returns: YES or NO, depending on the value of the preference
- // Stores: None
- // Description:
- // This is used to lookup the value for a preference in the defaults database,
- // and return a Boolean value to the caller. It's really just provided as a
- // shortcut to the several lines of code needed to retrieve the value, compare
- // it to a string value of YES or NO, and then return the appropriate result.
- // Bugs:
- // If anything goes wrong, the user will get a NO value, and not an error code.
- // Should I be disposing of the string that I get back?
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (Boolean) GetBoolPref: (ConstCString) thePreference
- {
- ConstCString theValue;
- Boolean result;
-
- theValue = NXGetDefaultValue(DefaultsOwner, thePreference);
- if (strcmp(theValue, "YES") == 0)
- result = YES;
- else
- result = NO;
-
- return result;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: SetBoolPref:To:
- // Parameters: The preference that we are to retrieve the value for
- // The Boolean value to assign it
- // Returns: self
- // Stores: None
- // Description:
- // This is used to store a boolean value for a preference in the defaults database.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - SetBoolPref: (ConstCString) thePreference To: (Boolean) value
- {
- if (value == YES)
- NXWriteDefault(DefaultsOwner, thePreference, "YES");
- else
- NXWriteDefault(DefaultsOwner, thePreference, "NO");
-
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: SetPref:To:
- // Parameters: The preference that we are to retrieve the value for
- // The string value to assign it
- // Returns: self
- // Stores: None
- // Description:
- // This is used to store a string value for a preference in the defaults database.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - SetPref: (ConstCString) thePreference To: (CString) value
- {
- NXWriteDefault(DefaultsOwner, thePreference, value);
- return self;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: GetPref:
- // Parameters: The preference that we are to retrieve the value for
- // Returns: A copy of the preference string.
- // Stores: None
- // Description:
- // This retrieves a string from the defaults database associated with the name
- // thePreference, makes a copy of it, and returns it.
- // Bugs:
- // History:
- // 93.02.15 djb Added for the rtf converter's new three option preference.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (CString) GetPref: (ConstCString) thePreference
- {
- ConstCString theValue;
- CString result;
-
- theValue = NXGetDefaultValue(DefaultsOwner, thePreference);
-
- result = NewCString(strlen(theValue));
- strcpy(result, theValue);
-
- return result;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: displayPreferences:
- // Parameters: the object that called us
- // Returns: self
- // Stores: none
- // Description:
- // This method is indended to be overridden. The subclass would just do whatever
- // it needs to do to display preferences for the user..
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- -displayPreferences: target
- {
- return self;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: SetPercentageDone:
- // Parameters: A new percentage to display
- // Returns: self
- // Stores: none
- // Description:
- // This allows a calling object to set the percentage of conversion done so far.
- // Note that we only actually ask the percentage meter to display itself in
- // in increments of 5%, simply because re-drawing after every percent, for
- // example, is EXTREMELY slow.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - SetPercentageDone: (Real) percentage
- {
- if (percentage > lastPercent+5)
- {
- [ProgressMeter SetTo: percentage];
- lastPercent = percentage;
- NXPing();
- }
- return self;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: openSource and Dest files
- // Parameters: the full path of the file to be converted.
- // Returns: the file object
- // Stores: errors
- // Description:
- // These tiny methods are provided so a subclass can override what kind of
- // file gets opened for the source or the dest, without overriding the whole
- // of the conversion methods. Note that they should always open a subclass
- // of File, though.
- // Bugs:
- // Modifications
- // 92.11.27 djb Changed CreateAndOpenFor: to ClearAnd.... Any time this method
- // is called within the framework of this class, the user has already
- // specified they definitely want to use this file, even if it already
- // exists, so we want to just clear the file if it exists already.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - openDestFile: (roCString) theFile
- {
- Instance fileInstance;
- [self ResetResults];
-
- fileInstance = [[File alloc] initAndUse: theFile];
- if ([fileInstance GetErrorCode] == ERR_OK)
- [fileInstance ClearAndOpenFor: FILE_WRITE];
- if ([fileInstance GetErrorCode] != ERR_OK)
- {
- [self StoreErrorCode: ERR_CREATEFAILED
- AndText: "We failed to create the file"];
- [fileInstance free];
- fileInstance = NullInstance;
- }
- return fileInstance;
- }
-
- - openSourceFile: (roCString) theFile
- {
- Instance fileInstance;
- [self ResetResults];
-
- fileInstance = [[File alloc] initAndUse: theFile];
- if ([fileInstance GetErrorCode] == ERR_OK)
- [fileInstance OpenExistingFor: FILE_READ];
- if ([fileInstance GetErrorCode] != ERR_OK)
- {
- [self StoreErrorCode: ERR_OPENFAILED
- AndText: "We failed to open the file"];
- [fileInstance free];
- fileInstance = NullInstance;
- }
- return fileInstance;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: closeSource and Dest files
- // Parameters: the file object to be closed
- // Returns: self
- // Stores: errors
- // Description:
- // These Little methods are used to undo the work of the above open methods.
- // they close the file objects, and free them. Like the above, they are pretty
- // simple and generic, and will probably be overridden by many converters.
- // Note that the dest file closing method has a boolean flag. If true, we also delete
- // the file (presumably something went wrong.
- // Bugs:
- // History
- // 93.01.01 djb Added tempString and freeing of it, so as not to leak memory.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - closeSourceFile: fileInstance
- {
- CString tempString = [fileInstance GetErrorText];
- [self ResetResults];
-
- [self StoreErrorCode: [fileInstance GetErrorCode]
- AndText: tempString];
- FreeCString(tempString);
- [fileInstance free];
-
- return self;
- }
-
-
- - closeDestFile: fileInstance andDelete: (Boolean) deleteit
- {
- CString tempString = [fileInstance GetErrorText];
- [self ResetResults];
-
- if (deleteit == NO)
- [fileInstance CloseAndSave];
- else
- [fileInstance CloseAndDelete];
- [self StoreErrorCode: [fileInstance GetErrorCode]
- AndText: tempString];
- FreeCString(tempString);
- [fileInstance free];
-
- return self;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: preConversion
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This method is called just before calling the conversion routine (i.e. after
- // files have been located and opened alright). It does any work needed
- // to finish up preparing for the conversion. At the moment, this means unregistering
- // the window, and setting the progress meter up. One is welcome to subclass
- // this method, but should probably [super preConversion] before proceeding there.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - preConversion
- {
- [self refuseDragAndDrop];
- lastPercent = 0;
- [ProgressMeter ActivateWithGoal: 100];
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: postConversion
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This method is called just after calling the conversion routine has finished.
- // It does some work needed to clean up aspects of this instance after the conversion.
- // At the moment, this means re-registering the window for file-icon-dropping,
- // and making sure the progress meter shows 100% done. One is welcome to subclass
- // this method, but should probably [super postConversion] before proceeding there.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- - postConversion
- {
- [self allowDragAndDrop];
- [ProgressMeter SetTo: 100];
- [ProgressMeter Deactivate];
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: CheckFileOK
- // Parameters: none
- // Returns: self
- // Stores: none
- // Description:
- // This asks the converter if this is an ok file to be converted. If no, then it
- // gets the reason why, displays it for the user, and goes into a modal loop to
- // force the user to decide whether to continue or not. If the user says continue,
- // we continue.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - (Boolean) CheckFileOK: fileInst
- {
- cancelResult = NO;
- if ( [converterInst respondsTo:@@selector(isThisAGoodFile:)] )
- {
- cancelResult = [converterInst isThisAGoodFile: fileInst];
- if (cancelResult != YES)
- {
- [decisionText setStringValue: [converterInst GetCStringFrom: SECOND_RESULT]];
- [decisionWindow center];
- [decisionWindow makeKeyAndOrderFront: self];
- [NXApp runModalFor: decisionWindow];
- }
- }
- else
- cancelResult = YES;
- return cancelResult;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: UserDecided
- // Parameters: the thing that called us
- // Returns: self
- // Stores: none
- // Description:
- // This method gets called when the user clicks on a button in a window during
- // the modal loop set up in CheckFileOK, above. It gets the result and stores it in
- // cancelResult, closes the window and shuts down the modal loop.
- // Bugs:
- // I dislike modality in general.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - UserDecided: sender
- {
- if ( [sender tag] == 0)
- cancelResult = NO;
- else
- cancelResult = YES;
- [decisionWindow close];
- [NXApp stopModal];
- return self;
- }
-
-
-
- /*============================================================*\
-
- At last, here are the true guts of the application. The following three methods
- deal with processing files. Briefly, PrepareForConversion: starts from scratch,
- and prompts the user for a file to convert from. ConvertThisFile: takes a file name
- and determines what file to put the conversion results into. ConvertFrom:To:
- then just converts between the two files (this last and init are things that
- subclasses MUST override.
-
- \*============================================================*/
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: PrepareForConversion:
- // Parameters: the object that send this message
- // Returns: self
- // Stores: error code
- // Description:
- // This merely creates the converstion necessary object, and sets its
- // preference for using curly quotes according to the value stored in this
- // object. Then, call the method to start getting information from the user to
- // do the conversion.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - PrepareForConversion: sender
- {
- Instance theOpenPanel = [OpenPanel new];
- CString const * openedFiles;
- roCString theDirectory;
- CString fullPath, theFile;
- CString tempString;
- Integer result, pathLength, index;
-
- [self ResetResults];
- //
- // Set up the display fields
- //
- [SourceFileName setStringValue: ""];
- [SourcePath setStringValue: ""];
- [SourceTitle setStringValue: "Converting:"];
- [SourcePathTitle setStringValue: "In:"];
-
- [DestFileName setStringValue: ""];
- [DestPath setStringValue: ""];
- [DestTitle setStringValue: "To:"];
- [DestPathTitle setStringValue: "In:"];
-
- [StatusTitle setStringValue: "Status:"];
- [Status setStringValue: ConversionString];
- //
- // Prepare the open dialog, and get info from the user.
- // @@@@ Bug: it doesn't let the user know what kind of conversion
- // @@@@ process is now underway in this dialog
- //
- [cutCommand setEnabled: YES];
- [pasteCommand setEnabled: YES];
- [spellingCommand setEnabled: YES];
- [checkSpellingCommand setEnabled: YES];
-
- [theOpenPanel allowMultipleFiles: YES];
- [theOpenPanel setPrompt: SourcePrompt]; // use instance variable for prompt
- [theOpenPanel setTitle: "Convert"];
- result = [theOpenPanel runModal];
-
- [cutCommand setEnabled: NO];
- [pasteCommand setEnabled: NO];
- [spellingCommand setEnabled: NO];
- [checkSpellingCommand setEnabled: NO];
-
- if (result != 1)
- {
- [self StoreErrorCode: ERR_USERABORTED
- AndText: "User canceled when opening a source file!"];
- [Status setStringValue: "Conversion process canceled at your request!"];
- }
- else
- {
- //
- // get the set of files, as well as the path to them (or it)
- //
- openedFiles = [theOpenPanel filenames];
- theDirectory = [theOpenPanel directory];
- pathLength = strlen(theDirectory);
- //
- // For each of the one or more files, allocate a space for the full path.
- // construct the path using the directory name and file name.
- // then, call the method to finish up, and dispose of the path we built.
- // Note: re: the if-then-else to fuse the file name and path
- // If the directory path is not empty, and it doesn't end in a slash, then
- // we build the full path from dir/file. Otherwise, do the same without a
- // slash. This last is usefull if someone has chosen a file at the root and we
- // don't want a double slash (i.e. //myfile). (the check for zero length is really
- // just for completeness...)
- //
- for (index=0; openedFiles[index] != NULL; index++)
- {
- theFile = openedFiles[index];
- fullPath = NewCString(strlen(theFile) + 1 + pathLength);
- if ((pathLength > 0) && (theDirectory[pathLength-1] != '/'))
- sprintf(fullPath, "%s/%s", theDirectory, theFile);
- else
- sprintf(fullPath, "%s%s", theDirectory, theFile);
- //
- // With a path in hand, do the next stage in the converstion.
- //
- [self ConvertThisFile: fullPath];
- FreeCString(fullPath);
- }
- //
- // Check if the file was converted alright...
- //
- if ([self GetErrorCode] == ERR_OK)
- {
- [SourceTitle setStringValue: "Converted:"];
- [Status setStringValue: "The conversion is done."];
- [self StoreErrorCode: ERR_OK AndText: "Conversion process done"];
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- }
- }
- return self;
- }
-
-
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: ConvertThisFile
- // Parameters: the full path of the file to be converted.
- // Returns: self
- // Stores: error code
- // Description:
- // Given a file, you want to convert it! First, you make sure you can open the file OK,
- // then, you ask the user for what the destination file should be called. Having done
- // this, you then assure that the destination file can be created without problems,
- // and then you ask the converting routine to convert between the two..
- // Bugs:
- // I find this routine a bit too confusing for my tastes... (long-winded)
- // We retrieve some strings below, but can't free them.
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - ConvertThisFile: (roCString) theFile
- {
- roCString destname;
- Instance sourceFile, destFile;
- Integer outcome;
- PositiveInteger extenLen, destLen;
- CString filename, directory, tempstring, basename;
- Instance theSavePanel;
- Boolean goodfile;
- CString tempString;
- //
- [self ResetResults];
- //
- // Set up the display fields (we don't always go through prepare for conversion, above.
- //
- [SourceFileName setStringValue: ""];
- [SourcePath setStringValue: ""];
- [SourceTitle setStringValue: "Converting:"];
- [SourcePathTitle setStringValue: "In:"];
-
- [DestFileName setStringValue: ""];
- [DestPath setStringValue: ""];
- [DestTitle setStringValue: "To:"];
- [DestPathTitle setStringValue: "In:"];
-
- [StatusTitle setStringValue: "Status:"];
- [Status setStringValue: ConversionString];
- //
- // If possible,, open the source file, and update the display.
- //
- sourceFile = [self openSourceFile: theFile];
- if ([self GetErrorCode] != ERR_OK)
- {
- [SourceFileName setStringValue: theFile];
- [SourcePath setStringValue: ""];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- }
- else
- {
- goodfile = [self CheckFileOK: sourceFile];
- if (goodfile == NO)
- {
- filename = [sourceFile GetFilename];
- directory = [sourceFile GetDirectory];
- [SourceFileName setStringValue: filename];
- [SourcePath setStringValue: directory];
- FreeCString (filename);
- FreeCString (directory);
- [Status setStringValue: "The conversion was canceled at your request"];
- [self StoreErrorCode: ERR_USERABORTED AndText: "The conversion was canceled at your request"];
- }
- else
- {
- ////
- // Get descriptions of the file's name, and use these to build a message
- // on the screen for the user, and a prompt in the save panel
- ////
- filename = [sourceFile GetFilename];
- directory = [sourceFile GetDirectory];
- basename = [sourceFile GetBasename];
- //
- // Update the user about current events.
- //
- [SourceFileName setStringValue: filename];
- [SourcePath setStringValue: directory];
- [Status setStringValue: "OK"];
- //
- // Then, build a name for the file we want to convert to
- //
- [cutCommand setEnabled: YES];
- [pasteCommand setEnabled: YES];
- [spellingCommand setEnabled: YES];
- [checkSpellingCommand setEnabled: YES];
-
- theSavePanel = [SavePanel new];
- [theSavePanel setPrompt: DestPrompt];
- [theSavePanel setTitle: "Convert to"];
- tempstring = NewCString(strlen(basename) + strlen(DestExtension));
- sprintf(tempstring, "%s%s", basename, DestExtension);
- // 93.01.01 djb Added this to free the leak with basename
- FreeCString(basename);
- outcome = [theSavePanel runModalForDirectory: directory file: tempstring];
-
- FreeCString (tempstring);
- FreeCString (filename);
- FreeCString (directory);
-
- [cutCommand setEnabled: NO];
- [pasteCommand setEnabled: NO];
- [spellingCommand setEnabled: NO];
- [checkSpellingCommand setEnabled: NO];
-
- ////
- // Now, check the output of the call to runModalForDirectory:file. If
- // the user canceled, tell the user this. Otherwise, continue processing.
- ////
- if (outcome != 1)
- {
- [self StoreErrorCode: ERR_USERABORTED
- AndText: "Conversion process canceled at your request"];
- [SourceTitle setStringValue: "Canceled:"];
- [Status setStringValue: "Conversion process canceled at your request!"];
- }
- else
- {
- ////
- // Open the destination file. If we can't, display why, otherwise show the
- // user what the destination file name and path is. Finally, CONVERT
- // the bloody file!
- ////
- //
- // See if the file ends with the proper extension. If so, copy it into a
- // temporary string. Otherwise, tack the extension onto it...
- //
- destname = [theSavePanel filename];
- extenLen = strlen(DestExtension);
- destLen = strlen(destname);
- if (strcmp(&destname[destLen - extenLen], DestExtension) == 0)
- {
- tempstring = NewCString(destLen);
- strcpy(tempstring, destname);
- }
- else
- {
- tempstring = NewCString(destLen+extenLen);
- sprintf(tempstring, "%s%s", destname, DestExtension);
- }
- //
- // Make sure that this ne name doesn't refer to the source file
- //
- if ([sourceFile SameFileAs: tempstring] == YES)
- {
- [SourceTitle setStringValue: "Error:"];
- [Status setStringValue: "These refer to the same file. This is not allowed!" ];
-
- [self StoreErrorCode: ERR_TRIEDTOOVERWRITE
- AndText: "Attempt to overwrite source file with destination file! Conversion NOT done."];
- [sourceFile Close];
- FreeCString(tempstring);
- }
- else
- {
- destFile = [self openDestFile: tempstring];
- FreeCString(tempstring);
- if ([self GetErrorCode] != ERR_OK)
- {
- [SourceTitle setStringValue: "Failed:"];
- tempString = [self GetErrorText];
- [Status setStringValue: tempString];
- FreeCString(tempString);
- [sourceFile Close];
- }
- else
- {
- //
- // we opened the dest file. So, tell the user, and continue.
- //
- filename = [destFile GetFilename];
- directory = [destFile GetDirectory];
- [DestFileName setStringValue: filename];
- [DestPath setStringValue: directory];
- FreeCString (filename);
- FreeCString (directory);
- [self DoConversionFrom: sourceFile To: destFile];
- }
- }
- }
- }
- }
-
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: DoConversionFrom:To:
- // Parameters: The file to be converted from, and the file to be converted to
- // Returns: self
- // Stores: none
- // Description:
- // This is called once we have a source and destination file object opened.
- // It does any preparation needed by the application, then calls the convertFrom:To:
- // method, and cleans up afterwards.
- // Note: tempInst is a kludge that was added for things like rtfConverter which
- // destroys the destination file and creates a new one. This allows us to deal with
- // this situation.
- // Bugs
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - DoConversionFrom: sourceFile To: destinationFile
- {
- Instance tempInst;
- Integer tempError;
- CString errorText;
- //
- // Do some preparing of the conversion window...
- //
- [self preConversion];
- //
- // Dim the menus during any conversion process
- //
- [quitCommand setEnabled: NO];
- [hideCommand setEnabled: NO];
- [infoCommands setEnabled: NO];
- [editCommands setEnabled: NO];
- [servicesCommands setEnabled: NO];
- [windowsCommands setEnabled: NO];
-
- [Status setStringValue: "Converting"];
- tempInst = [self ConvertFrom: sourceFile To: destinationFile];
- if (destIsDead == YES)
- destinationFile = tempInst;
- destIsDead = NO;
- [quitCommand setEnabled: YES];
- [hideCommand setEnabled: YES];
- [infoCommands setEnabled: YES];
- [editCommands setEnabled: YES];
- [servicesCommands setEnabled: YES];
- [windowsCommands setEnabled: YES];
- //
- // Close the files, now that we are done converting.
- //
- tempError = [self GetErrorCode];
- errorText = [self GetErrorText];
- if (tempError < ERR_OK)
- [self closeDestFile: destinationFile andDelete: YES];
- else
- [self closeDestFile: destinationFile andDelete: NO];
- [self closeSourceFile: sourceFile];
-
- [self postConversion];
-
- [self StoreErrorCode: tempError AndText: errorText];
- FreeCString(errorText);
- return self;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Routine: ConvertFrom:To:
- // Parameters: The file to be converted from, and the file to be converted to
- // Returns: self
- // Stores: none
- // Description:
- // This is a method indended to be subclassed. It would do the actual conversion
- // of the source to destination file.
- // Bugs
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - ConvertFrom: sourceFile To: destinationFile
- {
- //
- // If our converter instance has the ReportTo: method, then we tell it to report to it
- //
- if ( [converterInst respondsTo:@@selector(ReportTo:)] )
- [converterInst ReportTo: self];
- [Status setStringValue: "Converting"];
- return self;
- }
-
- @@end
- @
-
-
- 1.3
- log
- @Sun Jan 10 15:07:50 PST 1993
- @
- text
- @d81 3
- a83 1
- // This code for the drag-and-drop was mainly copied from DrawDocument.
- d86 2
- d91 1
- d101 2
- a102 1
- [self allowDragAndDrop];
- d111 2
- a112 2
- [cutCommand setEnabled: NO];
- [pasteCommand setEnabled: NO];
- d320 2
- d324 128
- d466 2
- a467 1
- // over the application's window.
- d469 2
- d475 1
- d485 4
- d500 1
- a500 1
- // process them.
- d502 2
- d508 1
- d515 7
- d866 26
- @
-
-
- 1.2
- log
- @Hopefully a pretty final version (it lived through the Font contrller...
- @
- text
- @d14 1
- a14 1
- #import <libc.h> //for getwd()
- d16 5
- a20 2
- #import <appkit/Listener.h> // for the drag-and-drop of files facility
- #import <appkit/Speaker.h> // ibid
- d23 2
- d32 2
- a33 1
- user to double click on a file in the workspace and have it open up.
- d37 31
- d69 1
- d102 8
- d175 1
- d180 16
- d197 1
- a197 1
- return YES; // Rashly assume that it got converted OK. =)
- d396 1
- d414 16
- a432 1
-
- d438 1
- d441 122
- d584 4
- d589 1
- d602 26
- a627 1
-
- d633 15
- d739 1
- a739 1
- // in increments of 15%, simply because re-drawing after every percent, for
- d745 1
- a745 1
- if (percentage > lastPercent+15)
- d749 1
- d767 5
- d780 1
- a780 1
- [fileInstance CreateAndOpenFor: FILE_WRITE];
- d823 2
- d829 1
- a831 1
- // [fileInstance Close];
- d833 2
- a834 1
- AndText: [fileInstance GetErrorText]];
- d843 1
- d851 2
- a852 1
- AndText: [fileInstance GetErrorText]];
- d993 1
- d1017 5
- d1026 6
- d1083 3
- a1085 1
- [Status setStringValue: [self GetErrorText]];
- d1118 1
- a1118 2
- Integer tempError;
- CString errorText;
- d1144 3
- a1146 1
- [Status setStringValue: [self GetErrorText]];
- d1153 6
- a1158 3
- //Bug: we are loosing these strings (cn't free them)
- [SourceFileName setStringValue: [sourceFile GetFilename]];
- [SourcePath setStringValue: [sourceFile GetDirectory]];
- d1180 5
- d1190 2
- a1191 1
-
- d1197 6
- d1258 3
- a1260 1
- [Status setStringValue: [self GetErrorText]];
- a1265 4
- // Do some preparing of the conversion window...
- //
- [self preConversion];
- //
- d1274 1
- a1274 19
-
- [Status setStringValue: "Converting"];
- [self ConvertFrom: sourceFile To: destFile];
- //
- // Close the files, now that we are done converting.
- //
- tempError = [self GetErrorCode];
- errorText = [self GetErrorText];
- if (tempError < ERR_OK)
- [self closeDestFile: destFile andDelete: YES];
- else
- [self closeDestFile: destFile andDelete: NO];
- [self closeSourceFile: sourceFile];
-
- [self postConversion];
-
- [self StoreErrorCode: tempError AndText: errorText];
- FreeCString(errorText);
-
- d1286 63
- d1365 1
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d2 2
- d9 1
- d14 1
- a14 3
- #import "File.h"
- #import <libc.h> //for getwd
- #import <appkit/defaults.h> // for NXApp to get path to app
- d16 4
- d21 1
- d23 1
- d25 3
- a27 1
- @@implementation ConvertController
- d29 1
- d31 1
- d33 1
- a33 1
- // Routine: appDidInit
- d39 5
- a43 1
- // do some final initialization stuff
- d45 1
- d49 13
- d63 1
- d69 301
- d376 2
- d383 13
- d473 1
- a473 1
- // This method is indended to be overridden. THe subclass would just do whatever
- d485 233
- d733 1
- a733 1
- ConstCString theDirectory;
- d806 1
- a819 25
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Method: ConvertOneFile:OfType:
- // Parameters: The name of a file, and its type
- // Returns: self
- // Stores: nothing
- // Description:
- // This method is indented mainly to be used for the applicaication delegate to contact
- // when the user has double clicked on a file in the workspace. This, in turn, does all
- // the work necessary to then proceed and call the routine below to get the name of
- // the file to convert to. By default this ignores the type.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - ConvertOneFile: (CString) filename OfType: (CString) type
- {
- [self ResetResults];
- //
- // Clear the display fields, and call the conversion routine
- //
- //
- // Set up the display fields
- //
- [SourceFileName setStringValue: ""];
- [SourcePath setStringValue: ""];
- [SourceTitle setStringValue: "Converting:"];
- [SourcePathTitle setStringValue: "In:"];
- a820 7
- [DestFileName setStringValue: ""];
- [DestPath setStringValue: ""];
- [DestTitle setStringValue: "To:"];
- [DestPathTitle setStringValue: "In:"];
-
- [Status setStringValue: ConversionString];
- [StatusTitle setStringValue: "Status:"];
- a821 16
- [self ConvertThisFile: filename];
- //
- // Check if the file was converted alright...
- //
- if ([self GetErrorCode] == ERR_OK)
- {
- [Status setStringValue: "The conversion is done."];
- [self StoreErrorCode: ERR_OK AndText: "Conversion process done"];
- }
- else
- {
- [SourceTitle setStringValue: "Failed:"];
- [Status setStringValue: [self GetErrorText]];
- }
- return self;
- }
- a822 2
-
-
- a823 26
- // Routine: openSource and Dest files
- // Parameters: the full path of the file to be converted.
- // Returns: the file object
- // Stores: none
- // Description:
- // These tiny methods are provided so a subclass can override what kind of
- // file gets opened for the source or the dest, without overriding the whole
- // of the conversion methods. Note that they should always open a subclass
- // of File, though.
- // Bugs:
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- - openDestFile: (CString) theFile
- {
- return [[File alloc] initAndUse: theFile];
- }
-
- - openSourceFile: (CString) theFile
- {
- return [[File alloc] initAndUse: theFile];
- }
-
-
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- d834 2
- a835 1
- // I find this routine a bit too confusing for my tastes...
- d837 1
- a837 1
- - ConvertThisFile: (CString) theFile
- d839 1
- a839 1
- ConstCString destname;
- d845 3
- d851 15
- d869 1
- a869 2
- [sourceFile OpenExistingFor: FILE_READ];
- if ([sourceFile GetErrorCode] != ERR_OK)
- d873 1
- a873 1
- [Status setStringValue: [sourceFile GetErrorText]];
- d877 2
- a878 32
- ////
- // Get descriptions of the file's name, and use these to build a message
- // on the screen for the user, and a prompt in the save panel
- ////
- filename = [sourceFile GetFilename];
- directory = [sourceFile GetDirectory];
- basename = [sourceFile GetBasename];
- //
- // Update the user about current events.
- //
- [SourceFileName setStringValue: filename];
- [SourcePath setStringValue: directory];
- [Status setStringValue: "OK"];
- //
- // Then, build a name for the file we want to convert to
- //
- theSavePanel = [SavePanel new];
- [theSavePanel setPrompt: DestPrompt];
- [theSavePanel setTitle: "Convert to"];
- tempstring = NewCString(strlen(basename) + strlen(DestExtension));
- sprintf(tempstring, "%s%s", basename, DestExtension);
-
- outcome = [theSavePanel runModalForDirectory: directory file: tempstring];
-
- FreeCString (tempstring);
- FreeCString (filename);
- FreeCString (directory);
- ////
- // Now, check the output of the call to runModalForDirectory:file. If
- // the user canceled, tell the user this. Otherwise, continue processing.
- ////
- if (outcome != 1)
- d880 5
- a884 4
- [self StoreErrorCode: ERR_OK
- AndText: "The user chose to abort the conversion at this point"];
- [SourceTitle setStringValue: "Canceled:"];
- [Status setStringValue: "Conversion process canceled at your request!"];
- d889 2
- a890 3
- // Open the destination file. If we can't, display why, otherwise show the
- // user what the destination file name and path is. Finally, CONVERT
- // the bloody file!
- d892 3
- d896 1
- a896 2
- // See if the file ends with the proper extension. If so, copy it into a
- // temporary string. Otherwise, tack the extension onto it...
- d898 3
- a900 13
- destname = [theSavePanel filename];
- extenLen = strlen(DestExtension);
- destLen = strlen(destname);
- if (strcmp(&destname[destLen - extenLen], DestExtension) == 0)
- {
- tempstring = NewCString(destLen);
- strcpy(tempstring, destname);
- }
- else
- {
- tempstring = NewCString(destLen+extenLen);
- sprintf(tempstring, "%s%s", destname, DestExtension);
- }
- d902 1
- a902 1
- // Make sure that this ne name doesn't refer to the source file
- d904 16
- a919 1
- if ([sourceFile SameFileAs: tempstring] == YES)
- d921 4
- a924 6
- [SourceTitle setStringValue: "Error:"];
- [Status setStringValue: "These refer to the same file. This is not allowed!" ];
-
- [self StoreErrorCode: ERR_TRIEDTOOVERWRITE
- AndText: "Attempt to overwrite source file with destination file! Conversion NOT done."];
- [sourceFile Close];
- d928 13
- a940 3
- destFile = [self openDestFile: tempstring];
- [destFile CreateAndOpenFor: FILE_WRITE];
- if ([destFile GetErrorCode] != ERR_OK)
- d942 18
- a959 2
- [SourceTitle setStringValue: "Failed:"];
- [Status setStringValue: [destFile GetErrorText]];
- d961 1
- d965 23
- a987 6
- free(tempstring); // not needed anymore.
- //
- // we opened the dest file. So, tell the user, and continue.
- //
- filename = [destFile GetFilename];
- directory = [destFile GetDirectory];
- d989 12
- a1000 2
- [DestFileName setStringValue: filename];
- [DestPath setStringValue: directory];
- d1002 6
- a1007 12
- [Status setStringValue: "Converting"];
-
- [self ConvertFrom: sourceFile To: destFile];
-
- FreeCString (filename);
- FreeCString (tempstring);
- FreeCString (directory);
- //
- // Convert the file and then clean up.
- //
- [destFile CloseAndSave];
- [sourceFile Close];
- d1029 5
- @
-