added a utility that warns the user to install hedgewars when it's run from the diskimage
authorkoda
Fri, 02 Oct 2009 16:49:31 +0000
changeset 2400 2422ea85d100
parent 2399 ddde0ac1472b
child 2401 2a694ea2a437
added a utility that warns the user to install hedgewars when it's run from the diskimage
QTfrontend/CMakeLists.txt
QTfrontend/CocoaInitializer.h
QTfrontend/CocoaInitializer.mm
QTfrontend/InstallController.cpp
QTfrontend/InstallController.h
QTfrontend/M3InstallController.h
QTfrontend/M3InstallController.m
QTfrontend/M3Panel.h
QTfrontend/M3Panel.mm
QTfrontend/NSWorkspace_RBAdditions.h
QTfrontend/NSWorkspace_RBAdditions.m
QTfrontend/hwform.cpp
QTfrontend/hwform.h
cmake_modules/FindOggVorbis.cmake
--- a/QTfrontend/CMakeLists.txt	Sun Sep 27 22:25:27 2009 +0000
+++ b/QTfrontend/CMakeLists.txt	Fri Oct 02 16:49:31 2009 +0000
@@ -138,9 +138,11 @@
 	bgwidget.h
 	)
 
-if(APPLE AND SPARKLE_FOUND)
-set(hwfr_src ${hwfr_src} AutoUpdater.cpp CocoaInitializer.mm SparkleAutoUpdater.mm)
-#set(hwfr_moc_hdrs ${hwfr_moc_hdrs} AutoUpdater.h CocoaInitializer.h SparkleAutoUpdater.h)
+if(APPLE)
+set(hwfr_src ${hwfr_src} InstallController.cpp CocoaInitializer.mm M3Panel.mm M3InstallController.m NSWorkspace_RBAdditions.m)
+if(SPARKLE_FOUND)
+set(hwfr_src ${hwfr_src} AutoUpdater.cpp SparkleAutoUpdater.mm)
+endif()
 endif()
 
 set(hwfr_hdrs
@@ -188,6 +190,7 @@
 		${OGG_LIBRARY}
 		${VORBIS_LIBRARY}
 		${HW_LINK_LIBS}
+		IOKit
 		)
         if (SPARKLE_FOUND)
                 set(HW_LINK_LIBS ${HW_LINK_LIBS} ${SPARKLE_LIBRARY})
--- a/QTfrontend/CocoaInitializer.h	Sun Sep 27 22:25:27 2009 +0000
+++ b/QTfrontend/CocoaInitializer.h	Fri Oct 02 16:49:31 2009 +0000
@@ -14,6 +14,7 @@
 	private:
 		class Private;
 		Private* d;
+                Private* c;
 };
 
 #endif
--- a/QTfrontend/CocoaInitializer.mm	Sun Sep 27 22:25:27 2009 +0000
+++ b/QTfrontend/CocoaInitializer.mm	Fri Oct 02 16:49:31 2009 +0000
@@ -17,12 +17,16 @@
 CocoaInitializer::CocoaInitializer()
 {
 	d = new CocoaInitializer::Private();
+        c = new CocoaInitializer::Private();
 	NSApplicationLoad();
+        c->autoReleasePool_ = [[NSAutoreleasePool alloc] init];
 	d->autoReleasePool_ = [[NSAutoreleasePool alloc] init];
 }
 
 CocoaInitializer::~CocoaInitializer()
 {
 	[d->autoReleasePool_ release];
+        [c->autoReleasePool_ release];
+	delete c;
 	delete d;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/InstallController.cpp	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,14 @@
+/*
+ *  InstallController.cpp
+ *  
+ *
+ *  Created by Vittorio on 28/09/09.
+ *  Copyright 2009 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "InstallController.h"
+
+InstallController::~InstallController()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/InstallController.h	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,21 @@
+/*
+ *  InstallController.h
+ *  
+ *
+ *  Created by Vittorio on 28/09/09.
+ *  Copyright 2009 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef INSTALLCONTROLLER_H
+#define INSTALLCONTROLLER_H
+
+class InstallController
+        {
+	public:
+		virtual ~InstallController();
+                
+		virtual void showInstallController() = 0;
+        };
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/M3InstallController.h	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,51 @@
+/*****************************************************************
+ M3InstallController.m
+ 
+ Created by Martin Pilkington on 02/06/2007.
+ 
+ Copyright (c) 2006-2009 M Cubed Software
+ 
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+ 
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ 
+ *****************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+#if __LP64__ || NS_BUILD_32_LIKE_64
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+#else
+typedef int NSInteger;
+typedef unsigned int NSUInteger;
+#endif
+#endif
+
+
+@interface M3InstallController : NSObject {
+	NSAlert *alert;
+}
+
+- (void)displayInstaller;
+- (void)installApp;
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/M3InstallController.m	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,98 @@
+/*****************************************************************
+ M3InstallController.m
+ 
+ Created by Martin Pilkington on 02/06/2007.
+ 
+ Copyright (c) 2006-2009 M Cubed Software
+ 
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+ 
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ 
+ *****************************************************************/
+
+#import "M3InstallController.h"
+#import "NSWorkspace_RBAdditions.h"
+
+#import <Foundation/Foundation.h>
+#import <Foundation/NSObjCRuntime.h>
+
+@implementation M3InstallController
+
+- (id) init {
+	if (self = [super init]) {
+		NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
+		NSString *title = [NSString stringWithFormat:NSLocalizedString(@"%@ is currently running from a disk image", @"AppName is currently running from a disk image"), appName];
+		NSString *body = [NSString stringWithFormat:NSLocalizedString(@"Would you like to install %@ in your applications folder before quitting?", @"Would you like to install App Name in your applications folder before quitting?"), appName];
+		alert = [[NSAlert alertWithMessageText:title 
+								 defaultButton:NSLocalizedString(@"Install", @"Install")
+							   alternateButton:NSLocalizedString(@"Don't Install", @"Don't Install")
+								   otherButton:nil
+					 informativeTextWithFormat:body] retain];
+		[alert setShowsSuppressionButton:YES];
+	}
+	return self;
+}
+
+- (void)displayInstaller {
+	NSString *imageFilePath = [[[NSWorkspace sharedWorkspace] propertiesForPath:[[NSBundle mainBundle] bundlePath]] objectForKey:NSWorkspace_RBimagefilepath];
+	if (imageFilePath && ![imageFilePath isEqualToString:[NSString stringWithFormat:@"/Users/.%@/%@.sparseimage", NSUserName(), NSUserName()]] && ![[NSUserDefaults standardUserDefaults] boolForKey:@"M3DontAskInstallAgain"]) {
+		NSInteger returnValue = [alert runModal];
+		if (returnValue == NSAlertDefaultReturn) {
+			[self installApp];
+		}
+		if ([[alert suppressionButton] state] == NSOnState) {
+			[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"M3DontAskInstallAgain"];
+		}
+	}
+}
+
+- (void)installApp {
+	NSString *appsPath = [[NSString stringWithString:@"/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]];
+	NSString *userAppsPath = [[[NSString stringWithString:@"~/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] stringByExpandingTildeInPath];
+	NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
+	
+	//Delete the app that is installed
+	if ([[NSFileManager defaultManager] fileExistsAtPath:appsPath]) {
+		[[NSFileManager defaultManager] removeFileAtPath:appsPath handler:nil];
+	}
+	//Delete the app that is installed
+	if ([[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath] toPath:appsPath 
+										  handler:nil]) {
+		NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"App Name installed successfully"), appName], 
+						[NSString stringWithFormat:NSLocalizedString(@"%@ was installed in /Applications", @"App Name was installed in /Applications"), appName], 
+						NSLocalizedString(@"Quit", @"Quit"), nil, nil);
+	} else {
+		if ([[NSFileManager defaultManager] fileExistsAtPath:userAppsPath]) {
+			[[NSFileManager defaultManager] removeFileAtPath:userAppsPath handler:nil];
+		}
+		if ([[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath] toPath:userAppsPath
+												handler:nil]) {
+		NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"AppName installed successfully"), appName], 
+				[NSString stringWithFormat:NSLocalizedString(@"%@ was installed in %@", @"App Name was installed in %@"), appName, [[NSString stringWithString:@"~/Applications"] stringByExpandingTildeInPath]], 
+						NSLocalizedString(@"Quit", @"Quit"), nil, nil);
+		} else {
+			NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"Could not install %@", @"Could not install App Name"), appName], 
+							NSLocalizedString(@"An error occurred when installing", @"An error occurred when installing"), NSLocalizedString(@"Quit", @"Quit"), nil, nil);
+		}
+	}
+}
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/M3Panel.h	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,28 @@
+/*
+ *  M3Panel.h
+ *  
+ *
+ *  Created by Vittorio on 28/09/09.
+ *  Copyright 2009 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef M3PANEL_H
+#define M3PANEL_H
+
+#include "InstallController.h"
+
+class M3Panel : public InstallController
+        {
+	public:
+		M3Panel(void);
+		~M3Panel();
+                
+		void showInstallController();
+                
+	private:
+		class Private;
+		Private* c;
+        };
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/M3Panel.mm	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,39 @@
+/*
+ *  M3Panel.cpp
+ *  
+ *
+ *  Created by Vittorio on 28/09/09.
+ *  Copyright 2009 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "M3Panel.h"
+#include "M3InstallController.h"
+
+#include <Cocoa/Cocoa.h>
+
+class M3Panel::Private
+{
+public:
+        M3InstallController *install;
+};
+
+M3Panel::M3Panel(void)
+{
+	c = new Private;
+        
+	c->install = [[M3InstallController alloc] init];
+	[c->install retain];
+        
+}
+
+M3Panel::~M3Panel()
+{
+	[c->install release];
+	delete c;
+}
+
+void M3Panel::showInstallController()
+{
+        [c->install displayInstaller];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/NSWorkspace_RBAdditions.h	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,37 @@
+//
+//  NSWorkspace_RBAdditions.h
+//  PathProps
+//
+//  Created by Rainer Brockerhoff on 10/04/2007.
+//  Copyright 2007 Rainer Brockerhoff. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+extern NSString* NSWorkspace_RBfstypename;
+extern NSString* NSWorkspace_RBmntonname;
+extern NSString* NSWorkspace_RBmntfromname;
+extern NSString* NSWorkspace_RBdeviceinfo;
+extern NSString* NSWorkspace_RBimagefilepath;
+extern NSString* NSWorkspace_RBconnectiontype;
+extern NSString* NSWorkspace_RBpartitionscheme;
+extern NSString* NSWorkspace_RBserverURL;
+
+@interface NSWorkspace (NSWorkspace_RBAdditions)
+
+// This method will return nil if the input path is invalid. Otherwise, the returned NSDictionary may contain
+// the following keys:
+//- NSWorkspace_RBfstypename: will always be present.Shows the filesystem type (usually "hfs"), from statfs.
+//- NSWorkspace_RBmntonname: will always be present. Shows the volume mount point.
+//- NSWorkspace_RBmntfromname: will always be present. Shows the BSD device path for local volumes; info for
+//		remote volumes depends on the filesystem type.
+//- NSWorkspace_RBconnectiontype: should always be present for local volumes. Shows the connection type ("SATA", "USB", etc.).
+//- NSWorkspace_RBpartitionscheme: should always be present for local volumes. Shows the partition scheme.
+//- NSWorkspace_RBdeviceinfo: should always be present for local volumes. Shows some information about the
+//		physical device; varies widely.
+//- NSWorkspace_RBimagefilepath: should be present for disk images only. Shows the path of the disk image file.
+//- NSWorkspace_RBserverURL: should be present for remote volumes only. Shows the server URL.
+
+- (NSDictionary*)propertiesForPath:(NSString*)path;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/NSWorkspace_RBAdditions.m	Fri Oct 02 16:49:31 2009 +0000
@@ -0,0 +1,260 @@
+//
+//  NSWorkspace_RBAdditions.m
+//  PathProps
+//
+//  Created by Rainer Brockerhoff on 10/04/2007.
+//  Copyright 2007 Rainer Brockerhoff. All rights reserved.
+//
+
+#import "NSWorkspace_RBAdditions.h"
+#include <IOKit/IOKitLib.h>
+#include <sys/mount.h>
+
+NSString* NSWorkspace_RBfstypename = @"NSWorkspace_RBfstypename";
+NSString* NSWorkspace_RBmntonname = @"NSWorkspace_RBmntonname";
+NSString* NSWorkspace_RBmntfromname = @"NSWorkspace_RBmntfromname";
+NSString* NSWorkspace_RBdeviceinfo = @"NSWorkspace_RBdeviceinfo";
+NSString* NSWorkspace_RBimagefilepath = @"NSWorkspace_RBimagefilepath";
+NSString* NSWorkspace_RBconnectiontype = @"NSWorkspace_RBconnectiontype";
+NSString* NSWorkspace_RBpartitionscheme = @"NSWorkspace_RBpartitionscheme";
+NSString* NSWorkspace_RBserverURL = @"NSWorkspace_RBserverURL";
+
+// This static funtion concatenates two strings, but first checks several possibilities...
+// like one or the other nil, or one containing the other already.
+
+static NSString* AddPart(NSString* first,NSString* second) {
+	if (!second) {
+		return first;
+	}
+	second = [second stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+	if (first) {
+		if ([first rangeOfString:second options:NSCaseInsensitiveSearch].location==NSNotFound) {
+			if ([second rangeOfString:first options:NSCaseInsensitiveSearch].location==NSNotFound) {
+				return [NSString stringWithFormat:@"%@; %@",first,second];
+			}
+			return second;
+		}
+		return first;
+	}
+	return second;
+}
+
+// This static functions recurses "upwards" over the IO registry. Returns strings that are concatenated
+// and ultimately end up under the NSWorkspace_RBdeviceinfo key.
+// This isn't too robust in that it assumes that objects returned by the objectForKey methods are
+// either strings or dictionaries. A "standard" implementations would use either only CoreFoundation and
+// IOKit calls for this, or do more robust type checking on the returned objects.
+//
+// Also notice that this works as determined experimentally in 10.4.9, there's no official docs I could find.
+// YMMV, and it may stop working in any new version of Mac OS X.
+
+static NSString* CheckParents(io_object_t thing,NSString* part,NSMutableDictionary* dict) {
+	NSString* result = part;
+    io_iterator_t parentsIterator = 0;
+    kern_return_t kernResult = IORegistryEntryGetParentIterator(thing,kIOServicePlane,&parentsIterator);
+    if ((kernResult==KERN_SUCCESS)&&parentsIterator) {
+		io_object_t nextParent = 0;
+		while ((nextParent = IOIteratorNext(parentsIterator))) {
+			NSDictionary* props = nil;
+			NSString* image = nil;
+			NSString* partition = nil;
+			NSString* connection = nil;
+			kernResult = IORegistryEntryCreateCFProperties(nextParent,(CFMutableDictionaryRef*)&props,kCFAllocatorDefault,0);
+			if (IOObjectConformsTo(nextParent,"IOApplePartitionScheme")) {
+				partition = [props objectForKey:@"Content Mask"];
+			} else if (IOObjectConformsTo(nextParent,"IOMedia")) {
+				partition = [props objectForKey:@"Content"];
+			} else if (IOObjectConformsTo(nextParent,"IODiskImageBlockStorageDeviceOutKernel")) {
+				NSData* data = nil;
+				if (data = [[props objectForKey:@"Protocol Characteristics"] objectForKey:@"Virtual Interface Location Path"]) {
+					image = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease];
+				}
+			} else if (IOObjectConformsTo(nextParent,"IOHDIXHDDriveInKernel")) {
+				image = [props objectForKey:@"KDIURLPath"];
+			}
+			NSDictionary* subdict;
+			if (subdict = [props objectForKey:@"Protocol Characteristics"]) {
+				connection = [subdict objectForKey:@"Physical Interconnect"];
+			} else {
+				connection = [props objectForKey:@"Physical Interconnect"];
+			}
+			if (connection) {
+				[dict setObject:AddPart([dict objectForKey:NSWorkspace_RBconnectiontype],connection) forKey:NSWorkspace_RBconnectiontype];
+			}
+			if (partition) {
+				[dict setObject:partition forKey:NSWorkspace_RBpartitionscheme];
+			}
+			if (image) {
+				[dict setObject:image forKey:NSWorkspace_RBimagefilepath];
+			}
+			NSString* value;
+			if (subdict = [props objectForKey:@"Device Characteristics"]) {
+				if (value = [subdict objectForKey:@"Product Name"]) {
+					result = AddPart(result,value);
+				}
+				if (value = [subdict objectForKey:@"Product Revision Level"]) {
+					result = AddPart(result,value);
+				}
+				if (value = [subdict objectForKey:@"Vendor Name"]) {
+					result = AddPart(result,value);
+				}
+			}
+			if (value = [props objectForKey:@"USB Serial Number"]) {
+				result = AddPart(result,value);
+			}
+			if (value = [props objectForKey:@"USB Vendor Name"]) {
+				result = AddPart(result,value);
+			}
+			NSString* cls = [(NSString*)IOObjectCopyClass(nextParent) autorelease];
+			if (![cls isEqualToString:@"IOPCIDevice"]) {
+			
+// Uncomment the following line to have the device tree dumped to the console.
+//				NSLog(@"=================================> %@:%@\n",cls,props);
+
+				result = CheckParents(nextParent,result,dict);
+			}
+			IOObjectRelease(nextParent);
+		}
+    }
+    if (parentsIterator) {
+		IOObjectRelease(parentsIterator);
+    }
+	return result;
+}
+
+// This formats the (partially undocumented) AFPXMountInfo info into a string.
+
+static NSString* FormatAFPURL(AFPXVolMountInfoPtr mountInfo,NSString** devdesc) {
+	UInt8* work = ((UInt8*)mountInfo)+mountInfo->serverNameOffset;
+	if (devdesc) {
+		*devdesc = [[[NSString alloc] initWithBytes:&work[1] length:work[0] encoding:NSUTF8StringEncoding] autorelease];
+	}
+	work = ((UInt8*)mountInfo)+mountInfo->volNameOffset;
+	NSString* volname = [[[NSString alloc] initWithBytes:&work[1] length:work[0] encoding:NSUTF8StringEncoding] autorelease];
+	work = ((UInt8*)mountInfo)+mountInfo->alternateAddressOffset;
+	AFPAlternateAddress* afpa = (AFPAlternateAddress*)work;
+	AFPTagData* afpta = (AFPTagData*)(&afpa->fAddressList);
+	NSString* ip = nil;
+	NSString* dns = nil;
+	int i = afpa->fAddressCount;
+	while ((i-->0)) {
+		switch (afpta->fType) {
+			case kAFPTagTypeIP:
+				if (!ip) {
+					ip = [[[NSString alloc] initWithBytes:&afpta->fData[0] length:afpta->fLength-2 encoding:NSUTF8StringEncoding] autorelease];
+				}
+				break;
+			case kAFPTagTypeIPPort:
+				ip = [NSString stringWithFormat:@"%u.%u.%u.%u:%u",afpta->fData[0],afpta->fData[1],afpta->fData[2],afpta->fData[3],OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[4])];
+				break;
+			case kAFPTagTypeDNS:
+				dns = [[[NSString alloc] initWithBytes:&afpta->fData[0] length:afpta->fLength-2 encoding:NSUTF8StringEncoding] autorelease];
+				break;
+			case 0x07:
+				ip = [NSString stringWithFormat:@"[%x:%x:%x:%x:%x:%x:%x:%x]",OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[0]),
+					OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[2]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[4]),
+					OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[6]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[8]),
+					OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[10]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[12]),
+					OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[14])];
+				break;
+		}
+		afpta = (AFPTagData*)((char*)afpta+afpta->fLength);
+	}
+	return [NSString stringWithFormat:@"afp://%@/%@",dns?:(ip?:@""),volname];
+}
+
+@implementation NSWorkspace (NSWorkspace_RBAdditions)
+
+// Returns a NSDictionary with properties for the path. See details in the .h file.
+// This assumes that the length of path is less than PATH_MAX (currently 1024 characters).
+
+- (NSDictionary*)propertiesForPath:(NSString*)path {
+	const char* ccpath = (const char*)[path fileSystemRepresentation];
+	NSMutableDictionary* result = nil;
+	struct statfs fs;
+	if (!statfs(ccpath,&fs)) {
+		NSString* from = [NSString stringWithUTF8String:fs.f_mntfromname];
+		result = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+			[NSString stringWithUTF8String:fs.f_fstypename],NSWorkspace_RBfstypename,
+			[NSString stringWithUTF8String:fs.f_mntonname],NSWorkspace_RBmntonname,
+			nil];
+		if (strncmp(fs.f_mntfromname,"/dev/",5)==0) {
+// For a local volume,get the IO registry tree and search it for further info.
+			mach_port_t masterPort = 0;
+			io_iterator_t mediaIterator = 0;
+			kern_return_t kernResult = IOMasterPort(bootstrap_port,&masterPort);
+			if (kernResult==KERN_SUCCESS) {
+				CFMutableDictionaryRef classesToMatch = IOBSDNameMatching(masterPort,0,&fs.f_mntfromname[5]);
+				if (classesToMatch) {
+					kernResult = IOServiceGetMatchingServices(masterPort,classesToMatch,&mediaIterator);
+					if ((kernResult==KERN_SUCCESS)&&mediaIterator) {
+						io_object_t firstMedia = 0;
+						while ((firstMedia = IOIteratorNext(mediaIterator))) {
+							NSString* stuff = CheckParents(firstMedia,nil,result);
+							if (stuff) {
+								[result setObject:stuff forKey:NSWorkspace_RBdeviceinfo];
+							}
+							IOObjectRelease(firstMedia);
+						}
+					}
+				}
+			}
+			if (mediaIterator) {
+				IOObjectRelease(mediaIterator);
+			}
+			if (masterPort) {
+				mach_port_deallocate(mach_task_self(),masterPort);
+			}
+		}
+		//Don't need this for disk images, gets around warnings for some deprecated functions
+		
+		/* else {
+// For a network volume, get the volume reference number and use to get the server URL.
+			FSRef ref;
+			if (FSPathMakeRef((const UInt8*)ccpath,&ref,NULL)==noErr) {
+				FSCatalogInfo info;
+				if (FSGetCatalogInfo(&ref,kFSCatInfoVolume,&info,NULL,NULL,NULL)==noErr) {
+					ParamBlockRec pb;
+					UInt16 vmisize = 0;
+					VolumeMountInfoHeaderPtr mountInfo = NULL;
+					pb.ioParam.ioCompletion = NULL;
+					pb.ioParam.ioNamePtr = NULL;
+					pb.ioParam.ioVRefNum = info.volume;
+					pb.ioParam.ioBuffer = (Ptr)&vmisize;
+					pb.ioParam.ioReqCount = sizeof(vmisize);
+					if ((PBGetVolMountInfoSize(&pb)==noErr)&&vmisize) {
+						mountInfo = (VolumeMountInfoHeaderPtr)malloc(vmisize);
+						if (mountInfo) {
+							pb.ioParam.ioBuffer = (Ptr)mountInfo;
+							pb.ioParam.ioReqCount = vmisize;
+							if (PBGetVolMountInfo(&pb)==noErr) {
+								NSString* url = nil;
+								switch (mountInfo->media) {
+								case AppleShareMediaType:
+									url = FormatAFPURL((AFPXVolMountInfoPtr)mountInfo,&from);
+									break;
+								case 'http':
+									url = from;
+									break;
+								case 'crbm':
+								case 'nfs_':
+								case 'cifs':
+									url = [NSString stringWithUTF8String:(char*)mountInfo+sizeof(VolumeMountInfoHeader)+sizeof(OSType)];
+									break;
+								}
+								if (url) {
+									[result setObject:url forKey:NSWorkspace_RBserverURL];
+								}
+							}
+						}
+						free(mountInfo);
+					}
+				}
+			}
+		}*/
+		[result setObject:from forKey:NSWorkspace_RBmntfromname];
+	}
+	return result;
+}
+
+@end
--- a/QTfrontend/hwform.cpp	Sun Sep 27 22:25:27 2009 +0000
+++ b/QTfrontend/hwform.cpp	Fri Oct 02 16:49:31 2009 +0000
@@ -55,10 +55,13 @@
 #include "ammoSchemeModel.h"
 #include "bgwidget.h"
 
-#ifdef SPARKLE_ENABLED
+#ifdef __APPLE__
 #include "CocoaInitializer.h"
+#include "M3Panel.h"
+#ifdef SPARKLE_ENABLED
 #include "SparkleAutoUpdater.h"
 #endif
+#endif
 
 // I started handing this down to each place it touches, but it was getting ridiculous
 // and this one flag does not warrant a static class
@@ -82,12 +85,15 @@
 
 	namegen = new HWNamegen();
 
+#ifdef __APPLE__
+        panel = new M3Panel;
 #ifdef SPARKLE_ENABLED
         AutoUpdater* updater;
         CocoaInitializer initializer;
         updater = new SparkleAutoUpdater("http://files.getdropbox.com/u/24468/appcast.xml"); //this has to change before release!!!
         if(updater && config->isAutoUpdateEnabled())
             updater->checkForUpdates();
+#endif        
 #endif
 
 	UpdateTeamsLists();
@@ -427,9 +433,13 @@
 
 void HWForm::btnExitClicked()
 {
-	if (eggTimer.elapsed() < 3000)
+	if (eggTimer.elapsed() < 3000){
+#ifdef __APPLE__
+                panel->showInstallController();
+#endif
 		close();
-	else
+	}
+        else
 	{
 		QPushButton * btn = findChild<QPushButton *>("imageButt");
 		if (btn)
--- a/QTfrontend/hwform.h	Sun Sep 27 22:25:27 2009 +0000
+++ b/QTfrontend/hwform.h	Fri Oct 02 16:49:31 2009 +0000
@@ -29,6 +29,10 @@
 #include "SDLs.h"
 #include "bgwidget.h"
 
+#ifdef __APPLE
+#include "InstallController.h"
+#endif
+
 class HWGame;
 class HWTeam;
 class HWNamegen;
@@ -146,6 +150,11 @@
 	QTime eggTimer;
 	SDLInteraction * sdli;
 	BGWidget * wBackground;
+        
+#ifdef __APPLE__
+        InstallController * panel;
+#endif
+        
 	void OnPageShown(quint8 id, quint8 lastid=0);
 };
 
--- a/cmake_modules/FindOggVorbis.cmake	Sun Sep 27 22:25:27 2009 +0000
+++ b/cmake_modules/FindOggVorbis.cmake	Fri Oct 02 16:49:31 2009 +0000
@@ -18,9 +18,10 @@
 
 include (CheckLibraryExists)
 find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
-find_library(OGG_LIBRARY NAMES ogg)
-find_library(VORBIS_LIBRARY NAMES vorbis)
-find_library(VORBISFILE_LIBRARY NAMES vorbisfile)
+#  [koda] (for Hedgewars) added libraries with capital names for compatibility with Mac frameworks
+find_library(OGG_LIBRARY NAMES ogg Ogg)
+find_library(VORBIS_LIBRARY NAMES vorbis Vorbis)
+find_library(VORBISFILE_LIBRARY NAMES vorbisfile Vorbis)
 if (OGG_LIBRARY AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY)
    set(OGGVORBIS_FOUND TRUE)
 #  [sommer] (for SuperTux) reversed order of libraries, so that cmake 2.4.5 for Windows generates an MSYS Makefile that will link correctly