This is rtfController.m in view mode; [Download] [Up]
/***********************************************************************\
controller class for Convert RTF which converts between Mac and NeXT rtf formats.
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
\***********************************************************************/
/*
====================================================================
This is $Revision: 1.8 $ of this file
It was last modified by $Author: death $ on $Date: 93/04/04 23:28:27 $
Note that this file was created while using the New Century Schoolbook Roman typeface. You may find that some things line up strangely if you don't use that family.
$Log: rtfController.m,v $
Revision 1.8 93/04/04 23:28:27 death
Sun Apr 4 23:28:27 PDT 1993
Revision 1.7 93/02/21 12:00:05 death
Sun Feb 21 12:00:05 PST 1993
Revision 1.6 93/01/10 08:27:28 death
Sun Jan 10 08:27:28 PST 1993
Revision 1.5 93/01/02 23:41:36 death
Sat Jan 2 23:41:36 PST 1993
Revision 1.4 93/01/02 13:39:06 death
Sat Jan 2 13:39:06 PST 1993
Revision 1.3 92/12/25 16:26:51 death
Fri Dec 25 16:26:51 PST 1992
Revision 1.2 92/12/21 07:01:18 death
Mon Dec 21 07:01:18 PST 1992
Revision 1.1 92/12/19 08:19:11 death
Sat Dec 19 08:19:10 PST 1992
====================================================================
*/
#import "rtfController.h"
#import "rtfFile.h"
#import "rtfConverter.h"
#import <appkit/Matrix.h> // For matrix stuff for preferences setting
#import <libc.h> // for mkdir and rmdir
#import <string.h> // for strrchr
#import <appkit/Listener.h> // for the drag-and-drop of files facility
#import <appkit/Speaker.h> // ibid
#import <appkit/Application.h> // To get NXApp (I thought that is what defaults was...)
#import <errno.h> // for errno.
#import "djbflag.h"
@implementation rtfController
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: init
// Parameters: none
// Returns: self
// Stores: none
// Description:
// This overrides the defalut init method. and sets up some strings used during
// some of the user interaction. time. We also create the pict converter instance
// needed later.
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- init
{
static NXDefaultsVector theDefaults =
{
{CONVERTTYPE, "YES"},
{REMOVEUNDERLINE, "NO"},
{CONVERTTEXT, "ALL"},
{CONVERTQUOTES, "NO"},
{CONVERTPICTS, "YES"},
{DELETEPICTS, "YES"},
{NULL, NULL}
};
CString tempPref;
[super init];
DefaultsOwner = "RTFConverter";
NXRegisterDefaults(DefaultsOwner, theDefaults);
convertMacRTF = [self GetBoolPref: CONVERTTYPE];
StripFirstUL0 = [self GetBoolPref: REMOVEUNDERLINE];
//
// 93.02.15 djb Changed from a boolean(yes/no) to a string parameter to support
// doing no conversion whatsoever. Checks for yes and no for
// backward compatability. =)
//
tempPref = [self GetPref: CONVERTTEXT];
if ((strcmp(tempPref, "ALL") == 0) || (strcmp(tempPref,"YES") == 0))
ConvertAllFonts = ConvertAll;
else if ((strcmp(tempPref, "STANDARD") == 0)|| (strcmp(tempPref,"NO") == 0))
ConvertAllFonts = ConvertStandard;
else if (strcmp(tempPref, "NONE") == 0)
ConvertAllFonts = ConvertNone;
FreeCString(tempPref);
ConvertSingleQuotes = [self GetBoolPref: CONVERTQUOTES];
ConvertPictData = [self GetBoolPref: CONVERTPICTS];
DeletePictData = [self GetBoolPref: DELETEPICTS];
if (convertMacRTF == YES)
{
ConversionString = "Converting Mac rtf to NeXT rtf";
SourcePrompt = "Mac file:";
DestPrompt = "NeXT file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".mac.rtf";
else
DestExtension = ".next.rtf";
}
else
{
ConversionString = "Converting NeXT rtf to Mac rtf";
SourcePrompt = "NeXT file:";
DestPrompt = "Mac file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".next.rtf";
else
DestExtension = ".mac.rtf";
}
MenuOpen = NO;
converterInst = [[rtfConverter alloc] init];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: free
// Parameters: none
// Returns: ?
// Stores: none
// Description:
// This cleans up before being deallocated. (derezed, in tron terms, I suppose).
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- free
{
if (converterInst != NullInstance)
[converterInst free];
return [super free];
}
//
// Added this because the free method is apparently not being called, and we
// need to kill the converter instance so it can kill the pict converter (so much for
// modularity, eh? thank you NeXT/Interface Builder (or maybe my stupidity)
//
- appWillTerminate: sender
{
if (converterInst != NullInstance)
[converterInst free];
converterInst = NullInstance;
return [super appWillTerminate: sender];
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: displayPreferences:
// Parameters: the object that called us
// Returns: self
// Stores: none
// This is called whenever we need to bring the preferences panel onto the screen.
// Using the value in our several preferences variables, we set the buttons in
// the preferences panel to reflect the current values, and then shows the panel.
// Bugs:
// As pointed out elsewhere, we don't really need to do this after the first time,
// since the buttons keep their own state. So my frakework needs revising!!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-displayPreferences: target
{
//
// Get the default preference values, and compare judge what buttons to
// highlight for the user.
//
if (convertMacRTF == YES)
[MacSourceButton selectCellWithTag: 1];
else
[MacSourceButton selectCellWithTag: 0];
if (StripFirstUL0 == YES)
[RemoveUnderlineButton setIntValue: 1];
else
[RemoveUnderlineButton setIntValue: 0];
//
// 93.02.15 djb Added support for three types of conversion, rather than 2
//
if (ConvertAllFonts == ConvertAll)
[ConvertAllFontsButton selectCellWithTag: 0];
else if (ConvertAllFonts == ConvertStandard)
[ConvertAllFontsButton selectCellWithTag: 1];
else
[ConvertAllFontsButton selectCellWithTag: 2];
if (ConvertSingleQuotes == YES)
[ConvertSingleQuotesButton selectCellWithTag: 1];
else
[ConvertSingleQuotesButton selectCellWithTag: 0];
if (ConvertPictData == YES)
[ConvertPictButton selectCellWithTag: 0];
else
[ConvertPictButton selectCellWithTag: 1];
if (DeletePictData == YES)
[DeletePictDataButton selectCellWithTag: 0];
else
[DeletePictDataButton selectCellWithTag: 1];
[prefPanel makeKeyAndOrderFront:self];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: ChangeConvertSource:
// Parameters: the object that called us
// Returns: self;
// Description:
// Specifies whether the source is a Mac or a NeXT rtf file. This is relevant when
// dealing with drag-and-drop or double clicked files where it is otherwise ambiguous.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-ChangeConvertSource: sender
{
if ( [[sender selectedCell] tag] == 1)
{
convertMacRTF = YES;
ConversionString = "Converting Mac rtf to NeXT rtf";
SourcePrompt = "Mac file:";
DestPrompt = "NeXT file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".mac.rtf";
else
DestExtension = ".next.rtf";
}
else
{
convertMacRTF = NO;
ConversionString = "Converting NeXT rtf to Mac rtf";
SourcePrompt = "NeXT file:";
DestPrompt = "Mac file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".next.rtf";
else
DestExtension = ".mac.rtf";
}
[self SetBoolPref: CONVERTTYPE To: convertMacRTF];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: SetUnderlineRemoval:
// Parameters: the object that called us
// Returns: self
// Description:
// Sets the boolean preference that indicates whether or not we should remove
// the first \ul0 in a NeXT rtf file.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetUnderlineRemoval: sender
{
if ( [sender intValue] == 1)
StripFirstUL0 = YES;
else
StripFirstUL0 = NO;
[self SetBoolPref: REMOVEUNDERLINE To: StripFirstUL0];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: SetFontConversion:
// Parameters: the object that called us
// Returns: self
// Description:
// Sets the preference that indicates whether or not we should convert
// text in all fonts, or in the standard fonts, or in none at all.
// History
// 93.02.15 djb Added suport for three types of conversion, rather than two.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetFontConversion: sender
{
if ( [[sender selectedCell] tag] == 0)
{
ConvertAllFonts = ConvertAll;
[self SetPref: CONVERTTEXT To: "ALL"];
}
else if ( [[sender selectedCell] tag] == 1)
{
ConvertAllFonts = ConvertStandard;
[self SetPref: CONVERTTEXT To: "STANDARD"];
}
else
{
ConvertAllFonts = ConvertNone;
[self SetPref: CONVERTTEXT To: "NONE"];
}
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: SetSingleQuoteChange:
// Parameters: the object that called us
// Returns: self
// Description:
// Sets the boolean preference that indicates whether or not we should produce
// MacStyle single quotes
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetSingleQuoteChange: sender
{
if ( [[sender selectedCell] tag] == 1)
ConvertSingleQuotes = YES;
else
ConvertSingleQuotes = NO;
[self SetBoolPref: CONVERTQUOTES To: ConvertSingleQuotes];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: SetPictDataDeletion:
// Parameters: the object that called us
// Returns: self
// Description:
// Sets the boolean preference that indicates what we should do with PICT data
// found in the rtf file. If the value is YES, then we wish to delete the data entirely
// If it is NO, then we store the pict data in another file
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetPictDataDeletion: sender
{
if ( [[sender selectedCell] tag] == 0)
DeletePictData = YES;
else
DeletePictData = NO;
[self SetBoolPref: DELETEPICTS To: DeletePictData];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: SetPictConversion:
// Parameters: the object that called us
// Returns: self
// Description:
// Sets the boolean preference that indicates whether we should try to do a
// conversion of any pictures we find in the rtf file. If the value is YES, then
// we will convert the pictures, otherwise we won't.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetPictConversion: sender
{
if ( [[sender selectedCell] tag] == 0)
ConvertPictData = YES;
else
ConvertPictData = NO;
[self SetBoolPref: CONVERTPICTS To: ConvertPictData];
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: PrepareForNeXTConversion:
// Parameters: the object that called us
// Returns: self
// Description:
// If the user chooses to convert a NeXT file via the menus, this routine is
// called first, so we can set up the right conversion options.
// Note that we store ptrs to all the strings used by the user interface stuff,
// and substitute ones for this routine, and then restore later. This is because
// the default strings are all about what happens when one drags and drops
// files, wheras this is when someone chooses a menu item.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- PrepareForNeXTConversion: sender
{
CString tempString = ConversionString;
CString sourceString = SourcePrompt;
CString destString = DestPrompt;
CString extenString = DestExtension;
ConversionString = "Converting NeXT rtf to Mac rtf";
SourcePrompt = "NeXT file:";
DestPrompt = "Mac file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".next.rtf";
else
DestExtension = ".mac.rtf";
[converterInst SetConversionDirection: NO];
MenuOpen = YES;
[self PrepareForConversion: self];
ConversionString = tempString;
SourcePrompt = sourceString;
DestPrompt = destString;
DestExtension = extenString;
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: PrepareForMacConversion:
// Parameters: the object that called us
// Returns: self
// Description:
// If the user chooses to convert a Mac file via the menus, this routine is
// called first, so we can set up the right conversion options.
// Note that we store ptrs to all the strings used by the user interface stuff,
// and substitute ones for this routine, and then restore later. This is because
// the default strings are all about what happens when one drags and drops
// files, wheras this is when someone chooses a menu item.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- PrepareForMacConversion: sender
{
CString tempString = ConversionString;
CString sourceString = SourcePrompt;
CString destString = DestPrompt;
CString extenString = DestExtension;
ConversionString = "Converting Mac rtf to NeXT rtf";
SourcePrompt = "Mac file:";
DestPrompt = "NeXT file:";
if (ForDavidJohnBurrowesOnly == 1)
DestExtension = ".mac.rtf";
else
DestExtension = ".next.rtf";
[converterInst SetConversionDirection: YES];
MenuOpen = YES;
[self PrepareForConversion: self];
ConversionString = tempString;
SourcePrompt = sourceString;
DestPrompt = destString;
DestExtension = extenString;
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: openSourceFile:
// Parameters: the name of the file we are to open
// Returns: the new file object
// Stores: error
// Description:
// This simply attempts to open the source file. If we are successfull, we
// return it to the caller, otherwise we return an error.
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- openSourceFile: (roCString) theFile
{
Instance fileInstance;
[self ResetResults];
fileInstance = [[rtfFile alloc] initAndUse: theFile];
if ([fileInstance GetErrorCode] == ERR_OK)
[fileInstance OpenExistingFor: FILE_READ];
if ([fileInstance GetErrorCode] != ERR_OK)
{
[self StoreErrorCode: ERR_CANTOPEN
AndText: "Unable to open that file."];
[fileInstance free];
fileInstance = NullInstance;
}
return fileInstance;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: openDestFile:
// Parameters: the name of the file we are to open
// Returns: the new file object
// Stores: error
// Description:
// This simply attempts to open the destination file. If we are successfull, we
// return it to the caller, otherwise we return an error.
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- openDestFile: (roCString) theFile
{
Instance fileInstance;
[self ResetResults];
fileInstance = [[rtfFile alloc] initAndUse: theFile];
if ([fileInstance GetErrorCode] == ERR_OK)
[fileInstance ClearAndOpenFor: FILE_WRITE];
if ([fileInstance GetErrorCode] != ERR_OK)
{
[self StoreErrorCode: ERR_CREATEFAILED
AndText: "We were not able to create and/or open that file"];
[fileInstance free];
fileInstance = NullInstance;
}
return fileInstance;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: ConvertFrom:To:
// Parameters:
// The file to be converted from
// the file to be converted to
// Returns: self
// Stores: error
// Description:
// This asks the super class to do any initalizing it needs to, and then goes
// ahead and asks the converter object to go at it.
// Bugs
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ConvertFrom: sourceFile To: destinationFile
{
[self ResetResults];
[super ConvertFrom: sourceFile To: destinationFile];
//
// If we were started via a menu selection, then the convert
// direction has already been set. Otherwise, we need to set it based on
// the default stored in convertMacRTF
//
if (MenuOpen == NO)
[converterInst SetConversionDirection: convertMacRTF];
[converterInst RemoveFirstNeXTUnderline: StripFirstUL0];
[converterInst SetTextConversion: ConvertAllFonts];
[converterInst ConvertTheSingleQuotes: ConvertSingleQuotes];
[converterInst SetPictConversion: ConvertPictData
AndDataRemoval: DeletePictData];
[MacConvertCommand setEnabled: NO];
[NeXTConvertCommand setEnabled: NO];
destFileHolder = destinationFile;
[converterInst ConvertFrom: sourceFile To: destinationFile];
[MacConvertCommand setEnabled: YES];
[NeXTConvertCommand setEnabled: YES];
MenuOpen = NO;
if ( [converterInst GetErrorCode] < ERR_OK)
[self StoreErrorCode: [converterInst GetErrorCode]
AndText: [converterInst GetErrorText] ];
else
[self StoreErrorCode: ERR_OK
AndText: "Converted Successfully" ];
return destFileHolder;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: MakeDestAnRTFD
// Parameters: none
// Returns: self
// Stores: error
// Description:
// This semi-hack routine allows the converter to call us and ask that the destination
// file be converted into being an rtfd instead of an rtf file. This involves closeing
// the rtf file earlier allocated, and creating a directory and subfile for the rtfd.
// It also involves using a definite hack by way of destFileHolder, which allows
// us to implicitly change the value that the above routine will return.
// Bugs
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- MakeDestAnRTFD
{
id newFile;
CString buffer = NewCString(1024);
CString oldPathName;
CString rtfdName;
CString pathname;
Integer result;
oldPathName = [destFileHolder GetPathname];
[destFileHolder CloseAndDelete];
//
// Create an RTFD folder and file by
// 1) getting the name for the rtfd folder (the rtf name + d)
// 2) Creating a directory with this name
// 3) Create a TXT.rtf file in said directory
//
rtfdName = NewCString(strlen(oldPathName) + 1);
strcat(rtfdName, oldPathName);
strcat(rtfdName, "d");
//
// 2) Creating a directory with the name of the requested font
//
errno = 0;
result = mkdir(rtfdName, 0700 | 0070 | 0007); // strange perms
if (result != 0)
{
sprintf(buffer, "The rtfd folder could not be created. (mkdir error: %d)", errno);
[self StoreErrorCode: ERR_CREATEFAILED AndText:buffer];
rmdir(rtfdName);
newFile = NullInstance;
}
else
{
//
// Allocate space for path to font folder, plus font or font.afm name
//
pathname = NewCString(strlen(rtfdName) + 1 +7);
strcpy(pathname, rtfdName);
strcat(pathname, "/TXT.rtf");
//
// 3) Create a font file in said directory
//
newFile = [[rtfFile alloc] initAndUse: pathname];
if ([newFile GetErrorCode] == ERR_OK)
[newFile CreateAndOpenFor: FILE_WRITE];
if ([newFile GetErrorCode] != ERR_OK)
{
[self StoreErrorCode: ERR_CREATEFAILED
AndText: "We failed to create the rtf file"];
newFile = NullInstance;
rmdir(rtfdName);
}
FreeCString(pathname);
}
FreeCString(oldPathName);
FreeCString(rtfdName);
FreeCString(buffer);
destFileHolder = newFile;
destIsDead = YES;
return newFile;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.