/*
Copyright (C) 2002-2003, Jeffrey D. Argast.
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
Permission is hereby granted to use, copy, modify, and distribute this
software or portions thereof for any purpose, without fee, subject to these
conditions:
(1) If any part of the source code is distributed, then this
statement must be included, with this copyright and no-warranty notice
unaltered.
(2) Permission for use of this software is granted only if the user accepts
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
*/
#import <Cocoa/Cocoa.h>
//#import "MoreFilesX.h"
#import "AppUtils.h"
#import "AppDefaults.h"
#import "MessageDefs.h"
#import "EditSheetController.h"
#import "AppEnvironment.h"
static void SendConsoleMessage (const char* msg, NSString* whichMsg);
static NSString* GetExecPath(NSString* appName, BOOL showAlert);
void CreateAppTempDir()
{
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* tempDir = NSTemporaryDirectory();
NSMutableString* tempPath = [NSMutableString stringWithString:tempDir];
[tempPath appendString:@"/P4Cocoa"];
[fileManager createDirectoryAtPath:tempPath attributes:nil];
}
void RemoveAppTempDir()
{
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* tempDir = NSTemporaryDirectory();
NSMutableString* tempPath = [NSMutableString stringWithString:tempDir];
// Poke my eyes out and call me paranoid, but I don't want to accidentally
// delete the hard drive.
if ( [tempPath length] > 0 )
{
[tempPath appendString:@"/P4Cocoa"];
[fileManager removeFileAtPath:tempPath handler:nil];
/*
FSSpec dirSpec;
Boolean isDir = 0;
FSPathMakeFSSpec ([tempPath cString], &dirSpec, &isDir);
// this should be true, otherwise something bad happend
if ( isDir )
{
char outName[1024];
FSMakePath (dirSpec.vRefNum, dirSpec.parID, dirSpec.name, outName, 1024);
int strLen = strlen (outName);
BOOL namesMatch = NO;
if ( strLen > 0 )
{
char* matchTo = outName + strLen - 8;
if ( strncmp (matchTo, "/P4Cocoa", 8) == 0 )
{
namesMatch = YES;
}
}
if ( namesMatch == YES )
{
FSRef dirRef;
OSErr err = 0;
err = FSMakeFSRef (dirSpec.vRefNum, dirSpec.parID, dirSpec.name, &dirRef);
if ( err == 0 )
{
// Ok at this point we're fairly confident that this really is the temp directory
FSDeleteContainer (&dirRef);
}
}
*/
}
}
NSString* ExtractLastPathComponent (NSString* fullPath)
{
int n;
NSString* fileName;
int pathLen = [fullPath cStringLength];
char* cPathName = (char*) [fullPath cString];
n = pathLen - 1;
while ( (n >= 0) && (cPathName[n] != '/'))
{
n--;
}
fileName = [[[NSString alloc] initWithCString:(cPathName + n + 1)] autorelease];
return fileName;
}
NSString* GetAppTempPath()
{
NSString* tempDir = NSTemporaryDirectory();
NSMutableString* tempPath = [NSMutableString stringWithString:tempDir];
[tempPath appendString:@"/P4Cocoa/"];
return tempPath;
}
void SendExecutingMessage (const char* msg)
{
SendConsoleMessage (msg, kExecutingMessage);
}
void SendOutputMessage (const char* msg)
{
SendConsoleMessage (msg, kOutputMessage);
}
void SendInfoMessage (const char* msg)
{
SendConsoleMessage (msg, kInfoMessage);
}
void SendWarnMessage (const char* msg)
{
SendConsoleMessage (msg, kWarnMessage);
}
void SendErrorMessage (const char* msg)
{
SendConsoleMessage (msg, kErrorMessage);
}
static void SendConsoleMessage (const char* msg, NSString* whichMsg)
{
if ( msg )
{
NSString* outString = [NSString stringWithCString:msg];
NSNotificationCenter* nCenter = [NSNotificationCenter defaultCenter];
NSNotification* notifier = [NSNotification notificationWithName:whichMsg object:outString];
[nCenter postNotification:notifier];
}
}
void CenterWindowInScreen (NSWindow* nsWindow)
{
NSRect innerFrame = [nsWindow frame];
NSRect outerFrame = [[NSScreen mainScreen] frame];
float centerX = outerFrame.origin.x + outerFrame.size.width / 2.0;
float centerY = outerFrame.origin.y + outerFrame.size.height * 2.0 / 3.0;
centerX -= (innerFrame.size.width / 2.0);
centerY -= (innerFrame.size.height / 2.0);
[nsWindow setFrameOrigin:NSMakePoint(centerX, centerY)];
}
void DiffFiles (NSString* fileOne, NSString* fileTwo)
{
/*
NSString* diffProg = [[AppDefaults defaultAppDefaults] getDiffApp];
NSMutableString* systemCall = [NSMutableString stringWithString:diffProg];
[systemCall appendString:@" "];
[systemCall appendString:fileOne];
[systemCall appendString:@" "];
[systemCall appendString:fileTwo];
system ([systemCall cString]);
*/
NSString* diffProg = GetDiffExecPath();
if ( [diffProg length] > 0 )
{
NSArray* args = [NSArray arrayWithObjects:fileOne, fileTwo, nil];
[NSTask launchedTaskWithLaunchPath:diffProg arguments:args];
}
}
void ViewFileInEditor (NSString* file)
{
// first try to use nstask
NSString* editProg = GetEditExecPath();
if ( [editProg length] > 0 )
{
NSArray* args = [NSArray arrayWithObject:file];
[NSTask launchedTaskWithLaunchPath:editProg arguments:args];
}
else
{
NSString* editApp = [[AppDefaults defaultAppDefaults] getEditApp];
NSWorkspace* nsWorkspace = [NSWorkspace sharedWorkspace];
if ( ![nsWorkspace openFile:file withApplication:editApp andDeactivate:YES] )
{
NSString* unableString = [NSString stringWithString:@"Unable to view file."];
NSString* msgString = nil;
if ( !editApp || ([editApp length] == 0) )
{
msgString = [NSString stringWithString:@"The editor app preference setting is empty."];
}
/*
NSWindow* mainWindow = [[NSApplication sharedApplication] mainWindow];
NSBeginAlertSheet(
unableString,
@"OK", // default button label
nil, // alternate button label
nil, // no third button
mainWindow, // window sheet is attached to
nil, // no delegate
nil, // no did-end selector
nil, // no need for did-dismiss selector
nil, // context info
msgString, // additional text
nil); // no parameters in message
*/
NSRunAlertPanel (unableString, msgString, @"OK", nil, nil);
}
}
}
NSString* GetUserAtClientString()
{
AppDefaults* appDefaults = [AppDefaults defaultAppDefaults];
NSMutableString* userClient = [NSMutableString stringWithString:[appDefaults getPerforceUser]];
[userClient appendString:@"@"];
[userClient appendString:[appDefaults getPerforceClient]];
return userClient;
}
static NSString* slashString = @"/";
static NSString* p4CmdName = @"p4";
NSString* GetPerforceExecPath()
{
return GetExecPath (p4CmdName, YES);
}
NSString* GetDiffExecPath()
{
NSString* diffProg = [[AppDefaults defaultAppDefaults] getDiffApp];
if ( [diffProg length] > 0 )
{
return GetExecPath (diffProg, YES);
}
return nil;
}
NSString* GetEditExecPath()
{
NSString* editProg = [[AppDefaults defaultAppDefaults] getEditApp];
if ( [editProg length] > 0 )
{
return GetExecPath (editProg, NO);
}
return nil;
}
NSString* GetExecPath(NSString* appName, BOOL showAlert)
{
NSString* execPath = nil;
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray* pathArray = [AppEnvironment path];
int num = [pathArray count];
int n;
for ( n = 0; n < num; n++ )
{
NSString* onePath = [pathArray objectAtIndex:n];
NSMutableString* exeString = [NSMutableString stringWithString:onePath];
[exeString appendString:slashString];
[exeString appendString:appName];
if ( [fileManager isExecutableFileAtPath:exeString] )
{
execPath = exeString;
break;
}
}
// try the appname as it may be fully qualified
if ( !execPath )
{
if ( [fileManager isExecutableFileAtPath:appName] )
{
execPath = appName;
}
}
if ( !execPath && showAlert )
{
NSMutableString* msgString = [NSMutableString stringWithCString:"Your PATH variable contains:\n\n"];
//NSWindow* mainWindow = [[NSApplication sharedApplication] mainWindow];
int n;
for ( n = 0; n < [pathArray count]; n++ )
{
[msgString appendString:[pathArray objectAtIndex:n]];
[msgString appendString:@"\n"];
}
// The following line of code gave the dialog 3 times. Must be deprecated. Using sheets instead.
//NSRunCriticalAlertPanel (@"Unable to find the p4 client in your path", msgString, @"OK", nil, nil);
NSMutableString* unableString = [NSMutableString stringWithString:@"Unable to find "];
[unableString appendString:appName];
[unableString appendString:@" in your path"];
/*
NSBeginAlertSheet(
unableString,
@"OK", // default button label
nil, // alternate button label
nil, // no third button
mainWindow, // window sheet is attached to
nil, // no delegate
nil, // no did-end selector
nil, // no need for did-dismiss selector
nil, // context info
msgString, // additional text
nil); // no parameters in message
*/
NSRunAlertPanel (unableString, msgString, @"OK", nil, nil);
}
return execPath;
}
void SendNotificationWithObject (NSString* message, id withObject)
{
if ( !withObject )
{
SendNotification (message);
}
else
{
NSNotification* nsNotification = [NSNotification notificationWithName:message object:withObject];
NSNotificationQueue* nsQueue = [NSNotificationQueue defaultQueue];
[nsQueue enqueueNotification:nsNotification
postingStyle:NSPostASAP];
}
}
void SendNotification (NSString* message)
{
NSNotification* nsNotification = [NSNotification notificationWithName:message object:nil];
NSNotificationQueue* nsQueue = [NSNotificationQueue defaultQueue];
[nsQueue enqueueNotification:nsNotification
postingStyle:NSPostASAP
coalesceMask:NSNotificationCoalescingOnName
forModes:nil];
}
void WriteStringToPasteboard (NSString* dataString, NSPasteboard* pb)
{
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
[pb setString:dataString forType:NSStringPboardType];
}
NSString* ReadStringFromPasteboard (NSPasteboard* pb)
{
NSString* value = nil;
NSString* type;
type = [pb availableTypeFromArray: [NSArray arrayWithObject:NSStringPboardType]];
if ( type )
{
value = [pb stringForType:NSStringPboardType];
}
return value;
}
NSString* GetTempFileName (NSString* clientFilePath, NSString* fileRev)
{
NSMutableString* fileName = [NSMutableString stringWithString:GetAppTempPath()];
[fileName appendString:ExtractLastPathComponent(clientFilePath)];
[fileName appendString:@"#"];
[fileName appendString:fileRev];
return fileName;
}