(svn r11492) -Codechange: [OSX] Split the cocoa video driver into several files. The reason for this is that the fullscreen and windowed mode api are separate from each other in OS X and thus the driver actual is two drivers in one. This split is to make the code more readable and to prepare for replacing the Quickdraw windowed mode code which uses apis deprecated as of OS X 10.5 (and maybe earlier).
authoregladil
Thu, 22 Nov 2007 21:48:17 +0000
changeset 8435 38a1ab65d6e4
parent 8434 6cce8c248f24
child 8436 f52eebc3fc20
(svn r11492) -Codechange: [OSX] Split the cocoa video driver into several files. The reason for this is that the fullscreen and windowed mode api are separate from each other in OS X and thus the driver actual is two drivers in one. This split is to make the code more readable and to prepare for replacing the Quickdraw windowed mode code which uses apis deprecated as of OS X 10.5 (and maybe earlier).
source.list
src/video/cocoa/cocoa_keys.h
src/video/cocoa/cocoa_v.h
src/video/cocoa/cocoa_v.mm
src/video/cocoa/event.mm
src/video/cocoa/fullscreen.mm
src/video/cocoa/wnd_quickdraw.mm
src/video/cocoa_keys.h
src/video/cocoa_v.h
src/video/cocoa_v.mm
--- a/source.list	Thu Nov 22 19:55:54 2007 +0000
+++ b/source.list	Thu Nov 22 21:48:17 2007 +0000
@@ -479,7 +479,10 @@
 	#end
 
 	#if COCOA
-		video/cocoa_v.mm
+		video/cocoa/cocoa_v.mm
+		video/cocoa/event.mm
+		video/cocoa/fullscreen.mm
+		video/cocoa/wnd_quickdraw.mm
 		sound/cocoa_s.cpp
 		os/macosx/splash.cpp
 	#end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/cocoa_keys.h	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,127 @@
+/* $Id$ */
+
+#ifndef COCOA_KEYS_H
+#define COCOA_KEYS_H
+
+/* From SDL_QuartzKeys.h */
+/* These are the Macintosh key scancode constants -- from Inside Macintosh */
+
+#define QZ_ESCAPE       0x35
+#define QZ_F1           0x7A
+#define QZ_F2           0x78
+#define QZ_F3           0x63
+#define QZ_F4           0x76
+#define QZ_F5           0x60
+#define QZ_F6           0x61
+#define QZ_F7           0x62
+#define QZ_F8           0x64
+#define QZ_F9           0x65
+#define QZ_F10          0x6D
+#define QZ_F11          0x67
+#define QZ_F12          0x6F
+#define QZ_PRINT        0x69
+#define QZ_SCROLLOCK    0x6B
+#define QZ_PAUSE        0x71
+#define QZ_POWER        0x7F
+#define QZ_BACKQUOTE    0x0A
+#define QZ_BACKQUOTE2   0x32
+#define QZ_1            0x12
+#define QZ_2            0x13
+#define QZ_3            0x14
+#define QZ_4            0x15
+#define QZ_5            0x17
+#define QZ_6            0x16
+#define QZ_7            0x1A
+#define QZ_8            0x1C
+#define QZ_9            0x19
+#define QZ_0            0x1D
+#define QZ_MINUS        0x1B
+#define QZ_EQUALS       0x18
+#define QZ_BACKSPACE    0x33
+#define QZ_INSERT       0x72
+#define QZ_HOME         0x73
+#define QZ_PAGEUP       0x74
+#define QZ_NUMLOCK      0x47
+#define QZ_KP_EQUALS    0x51
+#define QZ_KP_DIVIDE    0x4B
+#define QZ_KP_MULTIPLY  0x43
+#define QZ_TAB          0x30
+#define QZ_q            0x0C
+#define QZ_w            0x0D
+#define QZ_e            0x0E
+#define QZ_r            0x0F
+#define QZ_t            0x11
+#define QZ_y            0x10
+#define QZ_u            0x20
+#define QZ_i            0x22
+#define QZ_o            0x1F
+#define QZ_p            0x23
+#define QZ_LEFTBRACKET  0x21
+#define QZ_RIGHTBRACKET 0x1E
+#define QZ_BACKSLASH    0x2A
+#define QZ_DELETE       0x75
+#define QZ_END          0x77
+#define QZ_PAGEDOWN     0x79
+#define QZ_KP7          0x59
+#define QZ_KP8          0x5B
+#define QZ_KP9          0x5C
+#define QZ_KP_MINUS     0x4E
+#define QZ_CAPSLOCK     0x39
+#define QZ_a            0x00
+#define QZ_s            0x01
+#define QZ_d            0x02
+#define QZ_f            0x03
+#define QZ_g            0x05
+#define QZ_h            0x04
+#define QZ_j            0x26
+#define QZ_k            0x28
+#define QZ_l            0x25
+#define QZ_SEMICOLON    0x29
+#define QZ_QUOTE        0x27
+#define QZ_RETURN       0x24
+#define QZ_KP4          0x56
+#define QZ_KP5          0x57
+#define QZ_KP6          0x58
+#define QZ_KP_PLUS      0x45
+#define QZ_LSHIFT       0x38
+#define QZ_z            0x06
+#define QZ_x            0x07
+#define QZ_c            0x08
+#define QZ_v            0x09
+#define QZ_b            0x0B
+#define QZ_n            0x2D
+#define QZ_m            0x2E
+#define QZ_COMMA        0x2B
+#define QZ_PERIOD       0x2F
+#define QZ_SLASH        0x2C
+#if 1        /* Panther now defines right side keys */
+#define QZ_RSHIFT       0x3C
+#endif
+#define QZ_UP           0x7E
+#define QZ_KP1          0x53
+#define QZ_KP2          0x54
+#define QZ_KP3          0x55
+#define QZ_KP_ENTER     0x4C
+#define QZ_LCTRL        0x3B
+#define QZ_LALT         0x3A
+#define QZ_LMETA        0x37
+#define QZ_SPACE        0x31
+#if 1        /* Panther now defines right side keys */
+#define QZ_RMETA        0x36
+#define QZ_RALT         0x3D
+#define QZ_RCTRL        0x3E
+#endif
+#define QZ_LEFT         0x7B
+#define QZ_DOWN         0x7D
+#define QZ_RIGHT        0x7C
+#define QZ_KP0          0x52
+#define QZ_KP_PERIOD    0x41
+
+/* Wierd, these keys are on my iBook under MacOS X */
+#define QZ_IBOOK_ENTER  0x34
+#define QZ_IBOOK_LEFT   0x3B
+#define QZ_IBOOK_RIGHT  0x3C
+#define QZ_IBOOK_DOWN   0x3D
+#define QZ_IBOOK_UP     0x3E
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/cocoa_v.h	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,71 @@
+/* $Id$ */
+
+#ifndef VIDEO_COCOA_H
+#define VIDEO_COCOA_H
+
+#include "../video_driver.hpp"
+
+class VideoDriver_Cocoa: public VideoDriver {
+public:
+	/* virtual */ const char *Start(const char * const *param);
+
+	/* virtual */ void Stop();
+
+	/* virtual */ void MakeDirty(int left, int top, int width, int height);
+
+	/* virtual */ void MainLoop();
+
+	/* virtual */ bool ChangeResolution(int w, int h);
+
+	/* virtual */ void ToggleFullscreen(bool fullscreen);
+};
+
+class FVideoDriver_Cocoa: public VideoDriverFactory<FVideoDriver_Cocoa> {
+public:
+	static const int priority = 10;
+	/* virtual */ const char *GetName() { return "cocoa"; }
+	/* virtual */ const char *GetDescription() { return "Cocoa Video Driver"; }
+	/* virtual */ Driver *CreateInstance() { return new VideoDriver_Cocoa(); }
+};
+
+
+
+class CocoaSubdriver {
+public:
+	virtual ~CocoaSubdriver() {}
+
+	virtual void Draw() = 0;
+	virtual void MakeDirty(int left, int top, int width, int height) = 0;
+	virtual void UpdatePalette(uint first_color, uint num_colors) = 0;
+
+	virtual uint ListModes(OTTDPoint* modes, uint max_modes) = 0;
+
+	virtual bool ChangeResolution(int w, int h) = 0;
+
+	virtual bool IsFullscreen() = 0;
+	virtual int GetWidth() = 0;
+	virtual int GetHeight() = 0;
+	virtual void *GetPixelBuffer() = 0;
+
+	/* Convert local coordinate to window server (CoreGraphics) coordinate */
+	virtual CGPoint PrivateLocalToCG(NSPoint* p) = 0;
+
+	virtual NSPoint GetMouseLocation(NSEvent *event) = 0;
+	virtual bool MouseIsInsideView(NSPoint *pt) = 0;
+
+	virtual bool IsActive() = 0;
+};
+
+extern CocoaSubdriver* _cocoa_subdriver;
+
+CocoaSubdriver *QZ_CreateFullscreenSubdriver(int width, int height, int bpp);
+CocoaSubdriver *QZ_CreateWindowQuickdrawSubdriver(int width, int height, int bpp);
+
+void QZ_GameSizeChanged();
+
+void QZ_GameLoop();
+
+void QZ_ShowMouse();
+void QZ_HideMouse();
+
+#endif /* VIDEO_COCOA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/cocoa_v.mm	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,416 @@
+/* $Id$ */
+
+/******************************************************************************
+ *                             Cocoa video driver                             *
+ * Known things left to do:                                                   *
+ *  Nothing at the moment.                                                    *
+ ******************************************************************************/
+
+#ifdef WITH_COCOA
+
+#include <AvailabilityMacros.h>
+
+#import <Cocoa/Cocoa.h>
+#import <sys/time.h> /* gettimeofday */
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/**
+ * Important notice regarding all modifications!!!!!!!
+ * There are certain limitations because the file is objective C++.
+ * gdb has limitations.
+ * C++ and objective C code can't be joined in all cases (classes stuff).
+ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
+ */
+
+
+/* Portions of CPS.h */
+struct CPSProcessSerNum {
+	UInt32 lo;
+	UInt32 hi;
+};
+
+extern "C" OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn);
+extern "C" OSErr CPSEnableForegroundOperation(CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+extern "C" OSErr CPSSetFrontProcess(CPSProcessSerNum* psn);
+
+/* Disables a warning. This is needed since the method exists but has been dropped from the header, supposedly as of 10.4. */
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
+@interface NSApplication(NSAppleMenu)
+- (void)setAppleMenu:(NSMenu *)menu;
+@end
+#endif
+
+
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+#  undef bool
+#  undef false
+#  undef true
+# endif
+#endif
+
+
+#include "../../stdafx.h"
+#include "../../openttd.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../os/macosx/splash.h"
+#include "../../variables.h"
+#include "../../gfx.h"
+#include "cocoa_v.h"
+#include "cocoa_keys.h"
+#include "../../blitter/factory.hpp"
+#include "../../fileio.h"
+
+#undef Point
+#undef Rect
+
+
+@interface OTTDMain : NSObject
+@end
+
+
+static NSAutoreleasePool *_ottd_autorelease_pool;
+static OTTDMain *_ottd_main;
+static bool _cocoa_video_started = false;
+static bool _cocoa_video_dialog = false;
+
+CocoaSubdriver* _cocoa_subdriver = NULL;
+
+
+
+/* The main class of the application, the application's delegate */
+@implementation OTTDMain
+/* Called when the internal event loop has just started running */
+- (void) applicationDidFinishLaunching: (NSNotification*) note
+{
+	/* Hand off to main application code */
+	QZ_GameLoop();
+
+	/* We're done, thank you for playing */
+	[ NSApp stop:_ottd_main ];
+}
+
+/* Display the in game quit confirmation dialog */
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*) sender
+{
+
+	HandleExitGameRequest();
+
+	return NSTerminateCancel; // NSTerminateLater ?
+}
+@end
+
+static void setApplicationMenu()
+{
+	/* warning: this code is very odd */
+	NSMenu *appleMenu;
+	NSMenuItem *menuItem;
+	NSString *title;
+	NSString *appName;
+
+	appName = @"OTTD";
+	appleMenu = [[NSMenu alloc] initWithTitle:appName];
+
+	/* Add menu items */
+	title = [@"About " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+
+	[appleMenu addItem:[NSMenuItem separatorItem]];
+
+	title = [@"Hide " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+
+	menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+	[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
+
+	[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+	[appleMenu addItem:[NSMenuItem separatorItem]];
+
+	title = [@"Quit " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
+
+	/* Put menu into the menubar */
+	menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+	[menuItem setSubmenu:appleMenu];
+	[[NSApp mainMenu] addItem:menuItem];
+
+	/* Tell the application object that this is now the application menu */
+	[NSApp setAppleMenu:appleMenu];
+
+	/* Finally give up our references to the objects */
+	[appleMenu release];
+	[menuItem release];
+}
+
+/* Create a window menu */
+static void setupWindowMenu()
+{
+	NSMenu* windowMenu;
+	NSMenuItem* windowMenuItem;
+	NSMenuItem* menuItem;
+
+	windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+
+	/* "Minimize" item */
+	menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+	[windowMenu addItem:menuItem];
+	[menuItem release];
+
+	/* Put menu into the menubar */
+	windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+	[windowMenuItem setSubmenu:windowMenu];
+	[[NSApp mainMenu] addItem:windowMenuItem];
+
+	/* Tell the application object that this is now the window menu */
+	[NSApp setWindowsMenu:windowMenu];
+
+	/* Finally give up our references to the objects */
+	[windowMenu release];
+	[windowMenuItem release];
+}
+
+static void setupApplication()
+{
+	CPSProcessSerNum PSN;
+
+	/* Ensure the application object is initialised */
+	[NSApplication sharedApplication];
+
+	/* Tell the dock about us */
+	if (!CPSGetCurrentProcess(&PSN) &&
+			!CPSEnableForegroundOperation(&PSN, 0x03, 0x3C, 0x2C, 0x1103) &&
+			!CPSSetFrontProcess(&PSN)) {
+		[NSApplication sharedApplication];
+	}
+
+	/* Set up the menubar */
+	[NSApp setMainMenu:[[NSMenu alloc] init]];
+	setApplicationMenu();
+	setupWindowMenu();
+
+	/* Create OTTDMain and make it the app delegate */
+	_ottd_main = [[OTTDMain alloc] init];
+	[NSApp setDelegate:_ottd_main];
+}
+
+
+static void QZ_UpdateVideoModes()
+{
+	uint i, count;
+	OTTDPoint modes[32];
+
+	assert(_cocoa_subdriver != NULL);
+
+	count = _cocoa_subdriver->ListModes(modes, lengthof(modes));
+
+	for (i = 0; i < count; i++) {
+		_resolutions[i][0] = modes[i].x;
+		_resolutions[i][1] = modes[i].y;
+	}
+
+	_num_resolutions = count;
+}
+
+
+void QZ_GameSizeChanged()
+{
+	if (_cocoa_subdriver == NULL) return;
+
+	/* Tell the game that the resolution has changed */
+	_screen.width = _cocoa_subdriver->GetWidth();
+	_screen.height = _cocoa_subdriver->GetHeight();
+	_screen.pitch = _cocoa_subdriver->GetWidth();
+	_fullscreen = _cocoa_subdriver->IsFullscreen();
+
+	GameSizeChanged();
+}
+
+
+static CocoaSubdriver *QZ_CreateWindowSubdriver(int width, int height, int bpp)
+{
+	// For now there is only the quickdraw window mode subdriver, but a pure quartz one should be added.
+	return QZ_CreateWindowQuickdrawSubdriver(width, height, bpp);
+}
+
+
+static CocoaSubdriver *QZ_CreateSubdriver(int width, int height, int bpp, bool fullscreen, bool fallback)
+{
+	CocoaSubdriver *ret;
+
+	ret = fullscreen ? QZ_CreateFullscreenSubdriver(width, height, bpp) : QZ_CreateWindowSubdriver(width, height, bpp);
+	if (ret != NULL) return ret;
+
+	if (!fallback) return NULL;
+
+	/* Try again in 640x480 windowed */
+	DEBUG(driver, 0, "Setting video mode failed, falling back to 640x480 windowed mode.");
+	ret = QZ_CreateWindowSubdriver(640, 480, bpp);
+	if (ret != NULL) return ret;
+
+#ifdef _DEBUG
+	/* Try fullscreen too when in debug mode */
+	DEBUG(driver, 0, "Setting video mode failed, falling back to 640x480 fullscreen mode.");
+	ret = QZ_CreateFullscreenSubdriver(640, 480, bpp);
+	if (ret != NULL) return ret;
+#endif
+
+	return NULL;
+}
+
+
+static FVideoDriver_Cocoa iFVideoDriver_Cocoa;
+
+void VideoDriver_Cocoa::Stop()
+{
+	if (!_cocoa_video_started) return;
+
+	delete _cocoa_subdriver;
+	_cocoa_subdriver = NULL;
+
+	[_ottd_main release];
+
+	_cocoa_video_started = false;
+}
+
+const char *VideoDriver_Cocoa::Start(const char * const *parm)
+{
+	int width, height, bpp;
+
+	if (_cocoa_video_started) return "Already started";
+	_cocoa_video_started = true;
+
+	setupApplication();
+
+	/* Don't create a window or enter fullscreen if we're just going to show a dialog. */
+	if (_cocoa_video_dialog) return NULL;
+
+	width = _cur_resolution[0];
+	height = _cur_resolution[1];
+	bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
+
+	_cocoa_subdriver = QZ_CreateSubdriver(width, height, bpp, _fullscreen, true);
+	if (_cocoa_subdriver == NULL) {
+		Stop();
+		return "Could not create subdriver";
+	}
+
+	QZ_GameSizeChanged();
+
+	QZ_UpdateVideoModes();
+
+	return NULL;
+}
+
+void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
+{
+	assert(_cocoa_subdriver != NULL);
+
+	_cocoa_subdriver->MakeDirty(left, top, width, height);
+}
+
+void VideoDriver_Cocoa::MainLoop()
+{
+	/* Start the main event loop */
+	[NSApp run];
+}
+
+bool VideoDriver_Cocoa::ChangeResolution(int w, int h)
+{
+	bool ret;
+
+	assert(_cocoa_subdriver != NULL);
+
+	ret = _cocoa_subdriver->ChangeResolution(w, h);
+
+	QZ_GameSizeChanged();
+
+	QZ_UpdateVideoModes();
+
+	return ret;
+}
+
+void VideoDriver_Cocoa::ToggleFullscreen(bool full_screen)
+{
+	bool oldfs;
+
+	assert(_cocoa_subdriver != NULL);
+
+	oldfs = _cocoa_subdriver->IsFullscreen();
+	if (full_screen != oldfs) {
+		int width  = _cocoa_subdriver->GetWidth();
+		int height = _cocoa_subdriver->GetHeight();
+		int bpp    = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
+
+		delete _cocoa_subdriver;
+		_cocoa_subdriver = NULL;
+
+		_cocoa_subdriver = QZ_CreateSubdriver(width, height, bpp, full_screen, false);
+		if (_cocoa_subdriver == NULL) {
+			_cocoa_subdriver = QZ_CreateSubdriver(width, height, bpp, oldfs, true);
+			if (_cocoa_subdriver == NULL) error("Cocoa: Failed to create subdriver");
+		}
+	}
+
+	QZ_GameSizeChanged();
+
+	QZ_UpdateVideoModes();
+}
+
+
+/* This is needed since sometimes assert is called before the videodriver is initialized */
+void CocoaDialog(const char* title, const char* message, const char* buttonLabel)
+{
+	bool wasstarted;
+
+	_cocoa_video_dialog = true;
+
+	wasstarted = _cocoa_video_started;
+	if (_video_driver == NULL) {
+		setupApplication(); // Setup application before showing dialog
+	} else if (!_cocoa_video_started && _video_driver->Start(NULL) != NULL) {
+		fprintf(stderr, "%s: %s\n", title, message);
+		return;
+	}
+
+	NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil);
+
+	if (!wasstarted && _video_driver != NULL) _video_driver->Stop();
+
+	_cocoa_video_dialog = false;
+}
+
+/* This is needed since OS X application bundles do not have a
+ * current directory and the data files are 'somewhere' in the bundle */
+void cocoaSetApplicationBundleDir()
+{
+	char tmp[MAXPATHLEN];
+	CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+	if (CFURLGetFileSystemRepresentation(url, true, (unsigned char*)tmp, MAXPATHLEN)) {
+		AppendPathSeparator(tmp, lengthof(tmp));
+		_searchpaths[SP_APPLICATION_BUNDLE_DIR] = strdup(tmp);
+	} else {
+		_searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
+	}
+
+	CFRelease(url);
+}
+
+/* These are called from main() to prevent a _NSAutoreleaseNoPool error when
+ * exiting before the cocoa video driver has been loaded
+ */
+void cocoaSetupAutoreleasePool()
+{
+	_ottd_autorelease_pool = [[NSAutoreleasePool alloc] init];
+}
+
+void cocoaReleaseAutoreleasePool()
+{
+	[_ottd_autorelease_pool release];
+}
+
+#endif /* WITH_COCOA */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/event.mm	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,700 @@
+/* $Id$ */
+
+/******************************************************************************
+ *                             Cocoa video driver                             *
+ * Known things left to do:                                                   *
+ *  Nothing at the moment.                                                    *
+ ******************************************************************************/
+
+#ifdef WITH_COCOA
+
+#import <Cocoa/Cocoa.h>
+#import <sys/time.h> /* gettimeofday */
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/**
+ * Important notice regarding all modifications!!!!!!!
+ * There are certain limitations because the file is objective C++.
+ * gdb has limitations.
+ * C++ and objective C code can't be joined in all cases (classes stuff).
+ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
+ */
+
+
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+#  undef bool
+#  undef false
+#  undef true
+# endif
+#endif
+
+
+#include "../../stdafx.h"
+#include "../../openttd.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../os/macosx/splash.h"
+#include "../../variables.h"
+#include "../../gfx.h"
+#include "cocoa_v.h"
+#include "cocoa_keys.h"
+#include "../../blitter/factory.hpp"
+#include "../../fileio.h"
+
+#undef Point
+#undef Rect
+
+/* Right Mouse Button Emulation enum */
+enum {
+	RMBE_COMMAND,
+	RMBE_CONTROL,
+	RMBE_OFF,
+};
+
+
+static bool _show_mouse = true;
+static unsigned int _current_mods;
+static bool _tab_is_down;
+static bool _emulating_right_button;
+#ifdef _DEBUG
+static uint32 _tEvent;
+#endif
+
+
+static uint32 GetTick()
+{
+	struct timeval tim;
+
+	gettimeofday(&tim, NULL);
+	return tim.tv_usec / 1000 + tim.tv_sec * 1000;
+}
+
+
+void QZ_ShowMouse()
+{
+	if (!_show_mouse) {
+		[ NSCursor unhide ];
+		_show_mouse = true;
+
+		// Hide the openttd cursor when leaving the window
+		if (_cocoa_subdriver != NULL)
+			UndrawMouseCursor();
+		_cursor.in_window = false;
+	}
+}
+
+void QZ_HideMouse()
+{
+	if (_show_mouse) {
+		/*
+		 * Don't hide the cursor when compiling in debug mode.
+		 * Note: Not hiding the cursor will cause artefacts around it in 8bpp fullscreen mode.
+		 */
+#ifndef _DEBUG
+		[ NSCursor hide ];
+#endif
+		_show_mouse = false;
+
+		// Show the openttd cursor again
+		_cursor.in_window = true;
+	}
+}
+
+static void QZ_WarpCursor(int x, int y)
+{
+	NSPoint p;
+	CGPoint cgp;
+
+	assert(_cocoa_subdriver);
+
+	/* Only allow warping when in foreground */
+	if (![ NSApp isActive ]) return;
+
+	p = NSMakePoint(x, y);
+	cgp = _cocoa_subdriver->PrivateLocalToCG(&p);
+
+	/* this is the magic call that fixes cursor "freezing" after warp */
+	CGSetLocalEventsSuppressionInterval(0.0);
+	/* Do the actual warp */
+	CGWarpMouseCursorPosition(cgp);
+
+	/* Generate the mouse moved event */
+}
+
+
+static void QZ_CheckPaletteAnim()
+{
+	if (_pal_count_dirty != 0) {
+		Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
+
+		switch (blitter->UsePaletteAnimation()) {
+			case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
+				_cocoa_subdriver->UpdatePalette(_pal_first_dirty, _pal_count_dirty);
+				break;
+
+			case Blitter::PALETTE_ANIMATION_BLITTER:
+				blitter->PaletteAnimate(_pal_first_dirty, _pal_count_dirty);
+				break;
+
+			case Blitter::PALETTE_ANIMATION_NONE:
+				break;
+
+			default:
+				NOT_REACHED();
+		}
+		_pal_count_dirty = 0;
+	}
+}
+
+
+
+struct VkMapping {
+	unsigned short vk_from;
+	byte map_to;
+};
+
+#define AS(x, z) {x, z}
+
+static const VkMapping _vk_mapping[] = {
+	AS(QZ_BACKQUOTE,  WKC_BACKQUOTE), // key left of '1'
+	AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode
+
+	/* Pageup stuff + up/down */
+	AS(QZ_PAGEUP,   WKC_PAGEUP),
+	AS(QZ_PAGEDOWN, WKC_PAGEDOWN),
+
+	AS(QZ_UP,    WKC_UP),
+	AS(QZ_DOWN,  WKC_DOWN),
+	AS(QZ_LEFT,  WKC_LEFT),
+	AS(QZ_RIGHT, WKC_RIGHT),
+
+	AS(QZ_HOME, WKC_HOME),
+	AS(QZ_END,  WKC_END),
+
+	AS(QZ_INSERT, WKC_INSERT),
+	AS(QZ_DELETE, WKC_DELETE),
+
+	/* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */
+	AS(QZ_a, 'A'),
+	AS(QZ_b, 'B'),
+	AS(QZ_c, 'C'),
+	AS(QZ_d, 'D'),
+	AS(QZ_e, 'E'),
+	AS(QZ_f, 'F'),
+	AS(QZ_g, 'G'),
+	AS(QZ_h, 'H'),
+	AS(QZ_i, 'I'),
+	AS(QZ_j, 'J'),
+	AS(QZ_k, 'K'),
+	AS(QZ_l, 'L'),
+	AS(QZ_m, 'M'),
+	AS(QZ_n, 'N'),
+	AS(QZ_o, 'O'),
+	AS(QZ_p, 'P'),
+	AS(QZ_q, 'Q'),
+	AS(QZ_r, 'R'),
+	AS(QZ_s, 'S'),
+	AS(QZ_t, 'T'),
+	AS(QZ_u, 'U'),
+	AS(QZ_v, 'V'),
+	AS(QZ_w, 'W'),
+	AS(QZ_x, 'X'),
+	AS(QZ_y, 'Y'),
+	AS(QZ_z, 'Z'),
+	/* Same thing for digits */
+	AS(QZ_0, '0'),
+	AS(QZ_1, '1'),
+	AS(QZ_2, '2'),
+	AS(QZ_3, '3'),
+	AS(QZ_4, '4'),
+	AS(QZ_5, '5'),
+	AS(QZ_6, '6'),
+	AS(QZ_7, '7'),
+	AS(QZ_8, '8'),
+	AS(QZ_9, '9'),
+
+	AS(QZ_ESCAPE,    WKC_ESC),
+	AS(QZ_PAUSE,     WKC_PAUSE),
+	AS(QZ_BACKSPACE, WKC_BACKSPACE),
+
+	AS(QZ_SPACE,  WKC_SPACE),
+	AS(QZ_RETURN, WKC_RETURN),
+	AS(QZ_TAB,    WKC_TAB),
+
+	/* Function keys */
+	AS(QZ_F1,  WKC_F1),
+	AS(QZ_F2,  WKC_F2),
+	AS(QZ_F3,  WKC_F3),
+	AS(QZ_F4,  WKC_F4),
+	AS(QZ_F5,  WKC_F5),
+	AS(QZ_F6,  WKC_F6),
+	AS(QZ_F7,  WKC_F7),
+	AS(QZ_F8,  WKC_F8),
+	AS(QZ_F9,  WKC_F9),
+	AS(QZ_F10, WKC_F10),
+	AS(QZ_F11, WKC_F11),
+	AS(QZ_F12, WKC_F12),
+
+	/* Numeric part */
+	AS(QZ_KP0,         WKC_NUM_0),
+	AS(QZ_KP1,         WKC_NUM_1),
+	AS(QZ_KP2,         WKC_NUM_2),
+	AS(QZ_KP3,         WKC_NUM_3),
+	AS(QZ_KP4,         WKC_NUM_4),
+	AS(QZ_KP5,         WKC_NUM_5),
+	AS(QZ_KP6,         WKC_NUM_6),
+	AS(QZ_KP7,         WKC_NUM_7),
+	AS(QZ_KP8,         WKC_NUM_8),
+	AS(QZ_KP9,         WKC_NUM_9),
+	AS(QZ_KP_DIVIDE,   WKC_NUM_DIV),
+	AS(QZ_KP_MULTIPLY, WKC_NUM_MUL),
+	AS(QZ_KP_MINUS,    WKC_NUM_MINUS),
+	AS(QZ_KP_PLUS,     WKC_NUM_PLUS),
+	AS(QZ_KP_ENTER,    WKC_NUM_ENTER),
+	AS(QZ_KP_PERIOD,   WKC_NUM_DECIMAL),
+
+	/* Other non-letter keys */
+	AS(QZ_SLASH,        WKC_SLASH),
+	AS(QZ_SEMICOLON,    WKC_SEMICOLON),
+	AS(QZ_EQUALS,       WKC_EQUALS),
+	AS(QZ_LEFTBRACKET,  WKC_L_BRACKET),
+	AS(QZ_BACKSLASH,    WKC_BACKSLASH),
+	AS(QZ_RIGHTBRACKET, WKC_R_BRACKET),
+
+	AS(QZ_QUOTE,   WKC_SINGLEQUOTE),
+	AS(QZ_COMMA,   WKC_COMMA),
+	AS(QZ_MINUS,   WKC_MINUS),
+	AS(QZ_PERIOD,  WKC_PERIOD)
+};
+
+
+static uint32 QZ_MapKey(unsigned short sym)
+{
+	const VkMapping *map;
+	uint32 key = 0;
+
+	for (map = _vk_mapping; map != endof(_vk_mapping); ++map) {
+		if (sym == map->vk_from) {
+			key = map->map_to;
+			break;
+		}
+	}
+
+	if (_current_mods & NSShiftKeyMask)     key |= WKC_SHIFT;
+	if (_current_mods & NSControlKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
+	if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT;
+	if (_current_mods & NSCommandKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
+
+	return key << 16;
+}
+
+static void QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down)
+{
+	switch (keycode) {
+		case QZ_UP:    SB(_dirkeys, 1, 1, down); break;
+		case QZ_DOWN:  SB(_dirkeys, 3, 1, down); break;
+		case QZ_LEFT:  SB(_dirkeys, 0, 1, down); break;
+		case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break;
+
+		case QZ_TAB: _tab_is_down = down; break;
+
+		case QZ_RETURN:
+		case QZ_f:
+			if (down && (_current_mods & NSCommandKeyMask)) {
+				_video_driver->ToggleFullscreen(!_fullscreen);
+			}
+			break;
+	}
+
+	if (down) {
+		uint32 pressed_key = QZ_MapKey(keycode) | unicode;
+		HandleKeypress(pressed_key);
+		DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key);
+	} else {
+		DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode);
+	}
+}
+
+static void QZ_DoUnsidedModifiers(unsigned int newMods)
+{
+	const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA };
+
+	int i;
+	unsigned int bit;
+
+	if (_current_mods == newMods) return;
+
+	/* Iterate through the bits, testing each against the current modifiers */
+	for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
+		unsigned int currentMask, newMask;
+
+		currentMask = _current_mods & bit;
+		newMask     = newMods & bit;
+
+		if (currentMask && currentMask != newMask) { /* modifier up event */
+			/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
+			if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES);
+			QZ_KeyEvent(mapping[i], 0, NO);
+		} else if (newMask && currentMask != newMask) { /* modifier down event */
+			QZ_KeyEvent(mapping[i], 0, YES);
+			/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
+			if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO);
+		}
+	}
+
+	_current_mods = newMods;
+}
+
+static void QZ_MouseMovedEvent(int x, int y)
+{
+	if (_cursor.fix_at) {
+		int dx = x - _cursor.pos.x;
+		int dy = y - _cursor.pos.y;
+
+		if (dx != 0 || dy != 0) {
+			_cursor.delta.x += dx;
+			_cursor.delta.y += dy;
+
+			QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
+		}
+	} else {
+		_cursor.delta.x = x - _cursor.pos.x;
+		_cursor.delta.y = y - _cursor.pos.y;
+		_cursor.pos.x = x;
+		_cursor.pos.y = y;
+		_cursor.dirty = true;
+	}
+	HandleMouseEvents();
+}
+
+
+static void QZ_MouseButtonEvent(int button, BOOL down)
+{
+	switch (button) {
+		case 0:
+			if (down) {
+				_left_button_down = true;
+			} else {
+				_left_button_down = false;
+				_left_button_clicked = false;
+			}
+			HandleMouseEvents();
+			break;
+
+		case 1:
+			if (down) {
+				_right_button_down = true;
+				_right_button_clicked = true;
+			} else {
+				_right_button_down = false;
+			}
+			HandleMouseEvents();
+			break;
+	}
+}
+
+
+
+
+static bool QZ_PollEvent()
+{
+	NSEvent *event;
+	NSPoint pt;
+	NSString *chars;
+#ifdef _DEBUG
+	uint32 et0, et;
+#endif
+
+	assert(_cocoa_subdriver != NULL);
+
+#ifdef _DEBUG
+	et0 = GetTick();
+#endif
+	event = [ NSApp nextEventMatchingMask:NSAnyEventMask
+			untilDate: [ NSDate distantPast ]
+			inMode: NSDefaultRunLoopMode dequeue:YES ];
+#ifdef _DEBUG
+	et = GetTick();
+	_tEvent+= et - et0;
+#endif
+
+	if (event == nil) return false;
+	if (!_cocoa_subdriver->IsActive()) {
+		QZ_ShowMouse();
+		[NSApp sendEvent:event];
+		return true;
+	}
+
+	QZ_DoUnsidedModifiers( [ event modifierFlags ] );
+
+	switch ([event type]) {
+		case NSMouseMoved:
+		case NSOtherMouseDragged:
+		case NSRightMouseDragged:
+		case NSLeftMouseDragged:
+			pt = _cocoa_subdriver->GetMouseLocation(event);
+			if (!_cocoa_subdriver->MouseIsInsideView(&pt) &&
+					!_emulating_right_button) {
+				QZ_ShowMouse();
+				[NSApp sendEvent:event];
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+			break;
+
+		case NSLeftMouseDown:
+		{
+			uint32 keymask = 0;
+			if (_patches.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
+			if (_patches.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
+
+			pt = _cocoa_subdriver->GetMouseLocation(event);
+
+			if (!([ event modifierFlags ] & keymask) ||
+					!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+				[NSApp sendEvent:event];
+			}
+
+			if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+
+			/* Right mouse button emulation */
+			if ([ event modifierFlags ] & keymask) {
+				_emulating_right_button = true;
+				QZ_MouseButtonEvent(1, YES);
+			} else {
+				QZ_MouseButtonEvent(0, YES);
+			}
+			break;
+		}
+		case NSLeftMouseUp:
+			[NSApp sendEvent:event];
+
+			pt = _cocoa_subdriver->GetMouseLocation(event);
+			if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+
+			/* Right mouse button emulation */
+			if (_emulating_right_button) {
+				_emulating_right_button = false;
+				QZ_MouseButtonEvent(1, NO);
+			} else {
+				QZ_MouseButtonEvent(0, NO);
+			}
+			break;
+
+		case NSRightMouseDown:
+			pt = _cocoa_subdriver->GetMouseLocation(event);
+			if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				[NSApp sendEvent:event];
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+			QZ_MouseButtonEvent(1, YES);
+			break;
+
+		case NSRightMouseUp:
+			pt = _cocoa_subdriver->GetMouseLocation(event);
+			if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				[NSApp sendEvent:event];
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+			QZ_MouseButtonEvent(1, NO);
+			break;
+
+#if 0
+		/* This is not needed since openttd currently only use two buttons */
+		case NSOtherMouseDown:
+			pt = QZ_GetMouseLocation(event);
+			if (!QZ_MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				[NSApp sendEvent:event];
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+			QZ_MouseButtonEvent([ event buttonNumber ], YES);
+			break;
+
+		case NSOtherMouseUp:
+			pt = QZ_GetMouseLocation(event);
+			if (!QZ_MouseIsInsideView(&pt)) {
+				QZ_ShowMouse();
+				[NSApp sendEvent:event];
+				break;
+			}
+
+			QZ_HideMouse();
+			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+			QZ_MouseButtonEvent([ event buttonNumber ], NO);
+			break;
+#endif
+
+		case NSKeyDown:
+			/* Quit, hide and minimize */
+			switch ([event keyCode]) {
+				case QZ_q:
+				case QZ_h:
+				case QZ_m:
+					if ([ event modifierFlags ] & NSCommandKeyMask) {
+						[NSApp sendEvent:event];
+					}
+					break;
+			}
+
+			chars = [ event characters ];
+			QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, YES);
+			break;
+
+		case NSKeyUp:
+			/* Quit, hide and minimize */
+			switch ([event keyCode]) {
+				case QZ_q:
+				case QZ_h:
+				case QZ_m:
+					if ([ event modifierFlags ] & NSCommandKeyMask) {
+						[NSApp sendEvent:event];
+					}
+					break;
+			}
+
+			chars = [ event characters ];
+			QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO);
+			break;
+
+		case NSScrollWheel:
+			if ([ event deltaY ] > 0.0) { /* Scroll up */
+				_cursor.wheel--;
+			} else if ([ event deltaY ] < 0.0) { /* Scroll down */
+				_cursor.wheel++;
+			} /* else: deltaY was 0.0 and we don't want to do anything */
+
+			/* Set the scroll count for scrollwheel scrolling */
+			_cursor.h_wheel -= (int)([ event deltaX ]* 5 * _patches.scrollwheel_multiplier);
+			_cursor.v_wheel -= (int)([ event deltaY ]* 5 * _patches.scrollwheel_multiplier);
+			break;
+
+		default:
+			[NSApp sendEvent:event];
+	}
+
+	return true;
+}
+
+
+void QZ_GameLoop()
+{
+	uint32 cur_ticks = GetTick();
+	uint32 last_cur_ticks = cur_ticks;
+	uint32 next_tick = cur_ticks + 30;
+	uint32 pal_tick = 0;
+#ifdef _DEBUG
+	uint32 et0, et, st0, st;
+#endif
+	int i;
+
+#ifdef _DEBUG
+	et0 = GetTick();
+	st = 0;
+#endif
+
+	_screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+	DisplaySplashImage();
+	QZ_CheckPaletteAnim();
+	_cocoa_subdriver->Draw();
+	CSleep(1);
+
+	for (i = 0; i < 2; i++) GameLoop();
+
+	_screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+	UpdateWindows();
+	QZ_CheckPaletteAnim();
+	_cocoa_subdriver->Draw();
+	CSleep(1);
+
+	for (;;) {
+		uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
+		InteractiveRandom(); // randomness
+
+		while (QZ_PollEvent()) {}
+
+		if (_exit_game) break;
+
+#if defined(_DEBUG)
+		if (_current_mods & NSShiftKeyMask)
+#else
+		if (_tab_is_down)
+#endif
+		{
+			if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
+		} else if (_fast_forward & 2) {
+			_fast_forward = 0;
+		}
+
+		cur_ticks = GetTick();
+		if (cur_ticks >= next_tick || (_fast_forward && !_pause_game) || cur_ticks < prev_cur_ticks) {
+			_realtime_tick += cur_ticks - last_cur_ticks;
+			last_cur_ticks = cur_ticks;
+			next_tick = cur_ticks + 30;
+
+			_ctrl_pressed = !!(_current_mods & ( _patches.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
+			_shift_pressed = !!(_current_mods & NSShiftKeyMask);
+
+			GameLoop();
+
+			_screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+			UpdateWindows();
+			if (++pal_tick > 4) {
+				QZ_CheckPaletteAnim();
+				pal_tick = 1;
+			}
+			_cocoa_subdriver->Draw();
+		} else {
+#ifdef _DEBUG
+			st0 = GetTick();
+#endif
+			CSleep(1);
+#ifdef _DEBUG
+			st += GetTick() - st0;
+#endif
+			_screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+			DrawChatMessage();
+			DrawMouseCursor();
+			_cocoa_subdriver->Draw();
+		}
+	}
+
+#ifdef _DEBUG
+	et = GetTick();
+
+	DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _tEvent);
+	DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st);
+	DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_tEvent / (double)(et - et0) * 100);
+	DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_tEvent / (double)(et - et0 - st) * 100);
+#endif
+}
+
+#endif /* WITH_COCOA */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/fullscreen.mm	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,617 @@
+/* $Id$ */
+
+/******************************************************************************
+ *                             Cocoa video driver                             *
+ * Known things left to do:                                                   *
+ *  Scale&copy the old pixel buffer to the new one when switching resolution. *
+ ******************************************************************************/
+
+#ifdef WITH_COCOA
+
+#include <AvailabilityMacros.h>
+
+#import <Cocoa/Cocoa.h>
+#import <sys/time.h> /* gettimeofday */
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/**
+ * Important notice regarding all modifications!!!!!!!
+ * There are certain limitations because the file is objective C++.
+ * gdb has limitations.
+ * C++ and objective C code can't be joined in all cases (classes stuff).
+ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
+ */
+
+
+/* From Menus.h (according to Xcode Developer Documentation) */
+extern "C" void ShowMenuBar();
+extern "C" void HideMenuBar();
+
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+#  undef bool
+#  undef false
+#  undef true
+# endif
+#endif
+
+
+#include "../../stdafx.h"
+#include "../../openttd.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../os/macosx/splash.h"
+#include "../../variables.h"
+#include "../../gfx.h"
+#include "cocoa_v.h"
+#include "cocoa_keys.h"
+#include "../../blitter/factory.hpp"
+#include "../../fileio.h"
+
+#undef Point
+#undef Rect
+
+
+/* Structure for rez switch gamma fades
+ * We can hide the monitor flicker by setting the gamma tables to 0
+ */
+#define QZ_GAMMA_TABLE_SIZE 256
+
+struct OTTD_QuartzGammaTable {
+	CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
+	CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
+	CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];
+};
+
+/* Add methods to get at private members of NSScreen.
+ * Since there is a bug in Apple's screen switching code that does not update
+ * this variable when switching to fullscreen, we'll set it manually (but only
+ * for the main screen).
+ */
+@interface NSScreen (NSScreenAccess)
+	- (void) setFrame:(NSRect)frame;
+@end
+
+@implementation NSScreen (NSScreenAccess)
+- (void) setFrame:(NSRect)frame;
+{
+	_frame = frame;
+}
+@end
+
+
+class FullscreenSubdriver: public CocoaSubdriver {
+	int                display_width;
+	int                display_height;
+	int                display_depth;
+	int                screen_pitch;
+	void*              screen_buffer;
+	void*              pixel_buffer;
+
+	CGDirectDisplayID  display_id;         /* 0 == main display (only support single display) */
+	CFDictionaryRef    cur_mode;           /* current mode of the display */
+	CFDictionaryRef    save_mode;          /* original mode of the display */
+	CGDirectPaletteRef palette;            /* palette of an 8-bit display */
+
+	#define MAX_DIRTY_RECTS 100
+	Rect dirty_rects[MAX_DIRTY_RECTS];
+	int num_dirty_rects;
+
+
+	/* Gamma functions to try to hide the flash from a rez switch
+	 * Fade the display from normal to black
+	 * Save gamma tables for fade back to normal
+	 */
+	uint32 FadeGammaOut(OTTD_QuartzGammaTable* table)
+	{
+		CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE];
+		CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE];
+		CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE];
+		float percent;
+		int j;
+		unsigned int actual;
+
+		if (CGGetDisplayTransferByTable(
+					display_id, QZ_GAMMA_TABLE_SIZE,
+					table->red, table->green, table->blue, &actual
+				) != CGDisplayNoErr ||
+				actual != QZ_GAMMA_TABLE_SIZE) {
+			return 1;
+		}
+
+		memcpy(redTable,   table->red,   sizeof(redTable));
+		memcpy(greenTable, table->green, sizeof(greenTable));
+		memcpy(blueTable,  table->blue,  sizeof(greenTable));
+
+		for (percent = 1.0; percent >= 0.0; percent -= 0.01) {
+			for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
+				redTable[j]   = redTable[j]   * percent;
+				greenTable[j] = greenTable[j] * percent;
+				blueTable[j]  = blueTable[j]  * percent;
+			}
+
+			if (CGSetDisplayTransferByTable(
+						display_id, QZ_GAMMA_TABLE_SIZE,
+						redTable, greenTable, blueTable
+					) != CGDisplayNoErr) {
+				CGDisplayRestoreColorSyncSettings();
+				return 1;
+			}
+
+			CSleep(10);
+		}
+
+		return 0;
+	}
+
+	/* Fade the display from black to normal
+	 * Restore previously saved gamma values
+	 */
+	uint32 FadeGammaIn(const OTTD_QuartzGammaTable* table)
+	{
+		CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE];
+		CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE];
+		CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE];
+		float percent;
+		int j;
+
+		memset(redTable, 0, sizeof(redTable));
+		memset(greenTable, 0, sizeof(greenTable));
+		memset(blueTable, 0, sizeof(greenTable));
+
+		for (percent = 0.0; percent <= 1.0; percent += 0.01) {
+			for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
+				redTable[j]   = table->red[j]   * percent;
+				greenTable[j] = table->green[j] * percent;
+				blueTable[j]  = table->blue[j]  * percent;
+			}
+
+			if (CGSetDisplayTransferByTable(
+						display_id, QZ_GAMMA_TABLE_SIZE,
+						redTable, greenTable, blueTable
+					) != CGDisplayNoErr) {
+				CGDisplayRestoreColorSyncSettings();
+				return 1;
+			}
+
+			CSleep(10);
+		}
+
+		return 0;
+	}
+
+	/* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
+	void WaitForVerticalBlank()
+	{
+		/* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
+		double refreshRate;
+		double linesPerSecond;
+		double target;
+		double position;
+		double adjustment;
+		CFNumberRef refreshRateCFNumber;
+
+		refreshRateCFNumber = (const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayRefreshRate);
+		if (refreshRateCFNumber == NULL) return;
+
+		if (CFNumberGetValue(refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) == 0)
+			return;
+
+		if (refreshRate == 0) return;
+
+		linesPerSecond = refreshRate * display_height;
+		target = display_height;
+
+		/* Figure out the first delay so we start off about right */
+		position = CGDisplayBeamPosition(display_id);
+		if (position > target) position = 0;
+
+		adjustment = (target - position) / linesPerSecond;
+
+		CSleep((uint32)(adjustment * 1000));
+	}
+
+
+	bool SetVideoMode(int w, int h)
+	{
+		int exact_match;
+		CFNumberRef number;
+		int bpp;
+		int gamma_error;
+		OTTD_QuartzGammaTable gamma_table;
+		NSRect screen_rect;
+		CGError error;
+		NSPoint pt;
+
+		/* Destroy any previous mode */
+		if (pixel_buffer != NULL) {
+			free(pixel_buffer);
+			pixel_buffer = NULL;
+		}
+
+		/* See if requested mode exists */
+		cur_mode = CGDisplayBestModeForParameters(display_id, display_depth, w, h, &exact_match);
+
+		/* If the mode wasn't an exact match, check if it has the right bpp, and update width and height */
+		if (!exact_match) {
+			number = (const __CFNumber*) CFDictionaryGetValue(cur_mode, kCGDisplayBitsPerPixel);
+			CFNumberGetValue(number, kCFNumberSInt32Type, &bpp);
+			if (bpp != display_depth) {
+				DEBUG(driver, 0, "Failed to find display resolution");
+				goto ERR_NO_MATCH;
+			}
+
+			number = (const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayWidth);
+			CFNumberGetValue(number, kCFNumberSInt32Type, &w);
+
+			number = (const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayHeight);
+			CFNumberGetValue(number, kCFNumberSInt32Type, &h);
+		}
+
+		/* Fade display to zero gamma */
+		gamma_error = FadeGammaOut(&gamma_table);
+
+		/* Put up the blanking window (a window above all other windows) */
+		error = CGDisplayCapture(display_id);
+
+		if (CGDisplayNoErr != error) {
+			DEBUG(driver, 0, "Failed capturing display");
+			goto ERR_NO_CAPTURE;
+		}
+
+		/* Do the physical switch */
+		if (CGDisplaySwitchToMode(display_id, cur_mode) != CGDisplayNoErr) {
+			DEBUG(driver, 0, "Failed switching display resolution");
+			goto ERR_NO_SWITCH;
+		}
+
+		screen_buffer = CGDisplayBaseAddress(display_id);
+		screen_pitch  = CGDisplayBytesPerRow(display_id);
+
+		display_width = CGDisplayPixelsWide(display_id);
+		display_height = CGDisplayPixelsHigh(display_id);
+
+		/* Setup double-buffer emulation */
+		pixel_buffer = malloc(display_width * display_height * display_depth / 8);
+		if (pixel_buffer == NULL) {
+			DEBUG(driver, 0, "Failed to allocate memory for double buffering");
+			goto ERR_DOUBLEBUF;
+		}
+
+		if (display_depth == 8 && !CGDisplayCanSetPalette(display_id)) {
+			DEBUG(driver, 0, "Not an indexed display mode.");
+			goto ERR_NOT_INDEXED;
+		}
+
+		/* If we don't hide menu bar, it will get events and interrupt the program */
+		HideMenuBar();
+
+		/* Fade the display to original gamma */
+		if (!gamma_error) FadeGammaIn(&gamma_table);
+
+		/* There is a bug in Cocoa where NSScreen doesn't synchronize
+		 * with CGDirectDisplay, so the main screen's frame is wrong.
+		 * As a result, coordinate translation produces incorrect results.
+		 * We can hack around this bug by setting the screen rect ourselves.
+		 * This hack should be removed if/when the bug is fixed.
+		*/
+		screen_rect = NSMakeRect(0, 0, display_width, display_height);
+		[ [ NSScreen mainScreen ] setFrame:screen_rect ];
+
+
+		pt = [ NSEvent mouseLocation ];
+		pt.y = display_height - pt.y;
+		if (MouseIsInsideView(&pt)) QZ_HideMouse();
+
+		UpdatePalette(0, 256);
+
+		return true;
+
+		/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
+ERR_NOT_INDEXED:
+		free(pixel_buffer);
+		pixel_buffer = NULL;
+ERR_DOUBLEBUF:
+		CGDisplaySwitchToMode(display_id, save_mode);
+ERR_NO_SWITCH:
+		CGReleaseAllDisplays();
+ERR_NO_CAPTURE:
+		if (!gamma_error) FadeGammaIn(&gamma_table);
+ERR_NO_MATCH:
+		display_width = 0;
+		display_height = 0;
+
+		return false;
+	}
+
+	void RestoreVideoMode()
+	{
+		/* Release fullscreen resources */
+		OTTD_QuartzGammaTable gamma_table;
+		int gamma_error;
+		NSRect screen_rect;
+
+		gamma_error = FadeGammaOut(&gamma_table);
+
+		/* Restore original screen resolution/bpp */
+		CGDisplaySwitchToMode(display_id, save_mode);
+		CGReleaseAllDisplays();
+		ShowMenuBar();
+		/* Reset the main screen's rectangle
+		 * See comment in SetVideoMode for why we do this
+		 */
+		screen_rect = NSMakeRect(0, 0, CGDisplayPixelsWide(display_id), CGDisplayPixelsHigh(display_id));
+		[ [ NSScreen mainScreen ] setFrame:screen_rect ];
+
+		QZ_ShowMouse();
+
+		/* Destroy the pixel buffer */
+		if (pixel_buffer != NULL) {
+			free(pixel_buffer);
+			pixel_buffer = NULL;
+		}
+
+		if (!gamma_error) FadeGammaIn(&gamma_table);
+
+		display_width = 0;
+		display_height = 0;
+	}
+
+public:
+	FullscreenSubdriver(int bpp)
+	{
+		if (bpp != 8 && bpp != 32) {
+			error("Cocoa: This video driver only supports 8 and 32 bpp blitters.");
+		}
+
+		/* Initialize the video settings; this data persists between mode switches */
+		display_id = kCGDirectMainDisplay;
+		save_mode  = CGDisplayCurrentMode(display_id);
+
+		if (bpp == 8) palette = CGPaletteCreateDefaultColorPalette();
+
+		display_width  = 0;
+		display_height = 0;
+		display_depth  = bpp;
+		pixel_buffer   = NULL;
+
+		num_dirty_rects = MAX_DIRTY_RECTS;
+	}
+
+	virtual ~FullscreenSubdriver()
+	{
+		RestoreVideoMode();
+	}
+
+	virtual void Draw()
+	{
+		const uint8* src   = (uint8*) pixel_buffer;
+		uint8* dst         = (uint8*) screen_buffer;
+		uint pitch         = screen_pitch;
+		uint width         = display_width;
+		uint num_dirty     = num_dirty_rects;
+		uint bytesperpixel = display_depth / 8;
+		uint i;
+
+		/* Check if we need to do anything */
+		if (num_dirty == 0) return;
+
+		if (num_dirty >= MAX_DIRTY_RECTS) {
+			num_dirty = 1;
+			dirty_rects[0].left   = 0;
+			dirty_rects[0].top    = 0;
+			dirty_rects[0].right  = display_width;
+			dirty_rects[0].bottom = display_height;
+		}
+
+		WaitForVerticalBlank();
+		/* Build the region of dirty rectangles */
+		for (i = 0; i < num_dirty; i++) {
+			uint y      = dirty_rects[i].top;
+			uint left   = dirty_rects[i].left;
+			uint length = dirty_rects[i].right - left;
+			uint bottom = dirty_rects[i].bottom;
+
+			for (; y < bottom; y++) {
+				memcpy(dst + y * pitch + left * bytesperpixel, src + y * width * bytesperpixel + left * bytesperpixel, length * bytesperpixel);
+			}
+		}
+
+		num_dirty_rects = 0;
+	}
+
+	virtual void MakeDirty(int left, int top, int width, int height)
+	{
+		if (num_dirty_rects < MAX_DIRTY_RECTS) {
+			dirty_rects[num_dirty_rects].left = left;
+			dirty_rects[num_dirty_rects].top = top;
+			dirty_rects[num_dirty_rects].right = left + width;
+			dirty_rects[num_dirty_rects].bottom = top + height;
+		}
+		num_dirty_rects++;
+	}
+
+	virtual void UpdatePalette(uint first_color, uint num_colors)
+	{
+		CGTableCount  index;
+		CGDeviceColor color;
+
+		if (display_depth != 8)
+			return;
+
+		for (index = first_color; index < first_color+num_colors; index++) {
+			/* Clamp colors between 0.0 and 1.0 */
+			color.red   = _cur_palette[index].r / 255.0;
+			color.blue  = _cur_palette[index].b / 255.0;
+			color.green = _cur_palette[index].g / 255.0;
+
+			CGPaletteSetColorAtIndex(palette, color, index);
+		}
+
+		CGDisplaySetPalette(display_id, palette);
+	}
+
+	virtual uint ListModes(OTTDPoint* modes, uint max_modes)
+	{
+		CFArrayRef mode_list;
+		CFIndex num_modes;
+		CFIndex i;
+		uint count = 0;
+
+		mode_list  = CGDisplayAvailableModes(display_id);
+		num_modes = CFArrayGetCount(mode_list);
+
+		/* Build list of modes with the requested bpp */
+		for (i = 0; i < num_modes && count < max_modes; i++) {
+			CFDictionaryRef onemode;
+			CFNumberRef     number;
+			int bpp;
+			int intvalue;
+			bool hasMode;
+			uint16 width, height;
+
+			onemode = (const __CFDictionary*)CFArrayGetValueAtIndex(mode_list, i);
+			number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayBitsPerPixel);
+			CFNumberGetValue (number, kCFNumberSInt32Type, &bpp);
+
+			if (bpp != display_depth) continue;
+
+			number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayWidth);
+			CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue);
+			width = (uint16)intvalue;
+
+			number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayHeight);
+			CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue);
+			height = (uint16)intvalue;
+
+			/* Check if mode is already in the list */
+			{
+				uint i;
+				hasMode = false;
+				for (i = 0; i < count; i++) {
+					if (modes[i].x == width &&  modes[i].y == height) {
+						hasMode = true;
+						break;
+					}
+				}
+			}
+
+			if (hasMode) continue;
+
+			/* Add mode to the list */
+			modes[count].x = width;
+			modes[count].y = height;
+			count++;
+		}
+
+		/* Sort list smallest to largest */
+		{
+			uint i, j;
+			for (i = 0; i < count; i++) {
+				for (j = 0; j < count-1; j++) {
+					if (modes[j].x > modes[j + 1].x || (
+						modes[j].x == modes[j + 1].x &&
+						modes[j].y >  modes[j + 1].y
+						)) {
+						uint tmpw = modes[j].x;
+						uint tmph = modes[j].y;
+
+						modes[j].x = modes[j + 1].x;
+						modes[j].y = modes[j + 1].y;
+
+						modes[j + 1].x = tmpw;
+						modes[j + 1].y = tmph;
+					}
+				}
+			}
+		}
+
+		return count;
+	}
+
+	virtual bool ChangeResolution(int w, int h)
+	{
+		int old_width  = display_width;
+		int old_height = display_height;
+
+		if (SetVideoMode(w, h))
+			return true;
+
+		if (old_width != 0 && old_height != 0)
+			SetVideoMode(old_width, old_height);
+
+		return false;
+	}
+
+	virtual bool IsFullscreen()
+	{
+		return true;
+	}
+
+	virtual int GetWidth()
+	{
+		return display_width;
+	}
+
+	virtual int GetHeight()
+	{
+		return display_height;
+	}
+
+	virtual void *GetPixelBuffer()
+	{
+		return pixel_buffer;
+	}
+
+	/*
+		Convert local coordinate to window server (CoreGraphics) coordinate.
+		In fullscreen mode this just means copying the coords.
+	*/
+	virtual CGPoint PrivateLocalToCG(NSPoint* p)
+	{
+		CGPoint cgp;
+
+		cgp.x = p->x;
+		cgp.y = p->y;
+
+		return cgp;
+	}
+
+	virtual NSPoint GetMouseLocation(NSEvent *event)
+	{
+		NSPoint pt;
+
+		pt = [ NSEvent mouseLocation ];
+		pt.y = display_height - pt.y;
+
+		return pt;
+	}
+
+	virtual bool MouseIsInsideView(NSPoint *pt)
+	{
+		return pt->x >= 0 && pt->y >= 0 && pt->x < display_width && pt->y < display_height;
+	}
+
+	virtual bool IsActive()
+	{
+		return true;
+	}
+};
+
+CocoaSubdriver *QZ_CreateFullscreenSubdriver(int width, int height, int bpp)
+{
+	FullscreenSubdriver *ret;
+
+	ret = new FullscreenSubdriver(bpp);
+
+	if (!ret->ChangeResolution(width, height)) {
+		delete ret;
+		return NULL;
+	}
+
+	return ret;
+}
+
+#endif /* WITH_COCOA */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/cocoa/wnd_quickdraw.mm	Thu Nov 22 21:48:17 2007 +0000
@@ -0,0 +1,816 @@
+/* $Id$ */
+
+/******************************************************************************
+ *                             Cocoa video driver                             *
+ * Known things left to do:                                                   *
+ *  List available resolutions.                                               *
+ ******************************************************************************/
+
+#ifdef WITH_COCOA
+
+#include <AvailabilityMacros.h>
+
+#import <Cocoa/Cocoa.h>
+#import <sys/time.h> /* gettimeofday */
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/**
+ * Important notice regarding all modifications!!!!!!!
+ * There are certain limitations because the file is objective C++.
+ * gdb has limitations.
+ * C++ and objective C code can't be joined in all cases (classes stuff).
+ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
+ */
+
+
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+#  undef bool
+#  undef false
+#  undef true
+# endif
+#endif
+
+
+#include "../../stdafx.h"
+#include "../../openttd.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../os/macosx/splash.h"
+#include "../../variables.h"
+#include "../../gfx.h"
+#include "cocoa_v.h"
+#include "cocoa_keys.h"
+#include "../../blitter/factory.hpp"
+#include "../../fileio.h"
+
+#undef Point
+#undef Rect
+
+
+class WindowQuickdrawSubdriver;
+
+
+/* Subclass of NSWindow to fix genie effect and support resize events  */
+@interface OTTD_QuartzWindow : NSWindow {
+	WindowQuickdrawSubdriver *driver;
+}
+
+- (void)setDriver:(WindowQuickdrawSubdriver*)drv;
+
+- (void)miniaturize:(id)sender;
+- (void)display;
+- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
+- (void)appDidHide:(NSNotification*)note;
+- (void)appWillUnhide:(NSNotification*)note;
+- (void)appDidUnhide:(NSNotification*)note;
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
+@end
+
+/* Delegate for our NSWindow to send ask for quit on close */
+@interface OTTD_QuartzWindowDelegate : NSObject{
+	WindowQuickdrawSubdriver *driver;
+}
+
+- (void)setDriver:(WindowQuickdrawSubdriver*)drv;
+
+- (BOOL)windowShouldClose:(id)sender;
+@end
+
+class WindowQuickdrawSubdriver: public CocoaSubdriver {
+	int device_width;
+	int device_height;
+	int device_depth;
+
+	int window_width;
+	int window_height;
+	int window_pitch;
+
+	int buffer_depth;
+
+	void *pixel_buffer;
+	void *window_buffer;
+
+	OTTD_QuartzWindow *window;
+
+	#define MAX_DIRTY_RECTS 100
+	Rect dirty_rects[MAX_DIRTY_RECTS];
+	int num_dirty_rects;
+
+	uint16 palette16[256];
+	uint32 palette32[256];
+
+public:
+	bool active;
+	bool setup;
+
+	NSQuickDrawView *qdview;
+
+private:
+	void GetDeviceInfo();
+
+	bool SetVideoMode(int width, int height);
+
+	/**
+	 * This function copies 32bpp pixels from the screen buffer in 16bpp windowed mode.
+	 *
+	 * @param left The x coord for the left edge of the box to blit.
+	 * @param top The y coord for the top edge of the box to blit.
+	 * @param right The x coord for the right edge of the box to blit.
+	 * @param bottom The y coord for the bottom edge of the box to blit.
+	 */
+	void Blit32ToView32(int left, int top, int right, int bottom);
+
+	/**
+	 * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode.
+	 *
+	 * @param left The x coord for the left edge of the box to blit.
+	 * @param top The y coord for the top edge of the box to blit.
+	 * @param right The x coord for the right edge of the box to blit.
+	 * @param bottom The y coord for the bottom edge of the box to blit.
+	 */
+	void BlitIndexedToView32(int left, int top, int right, int bottom);
+
+	/**
+	 * This function copies 8bpp pixels from the screen buffer in 16bpp windowed mode.
+	 *
+	 * @param left The x coord for the left edge of the box to blit.
+	 * @param top The y coord for the top edge of the box to blit.
+	 * @param right The x coord for the right edge of the box to blit.
+	 * @param bottom The y coord for the bottom edge of the box to blit.
+	 */
+	void BlitIndexedToView16(int left, int top, int right, int bottom);
+
+	inline void BlitToView(int left, int top, int right, int bottom);
+	void DrawResizeIcon();
+
+
+public:
+	WindowQuickdrawSubdriver(int bpp);
+	virtual ~WindowQuickdrawSubdriver();
+
+	virtual void Draw();
+	virtual void MakeDirty(int left, int top, int width, int height);
+	virtual void UpdatePalette(uint first_color, uint num_colors);
+
+	virtual uint ListModes(OTTDPoint* modes, uint max_modes);
+
+	virtual bool ChangeResolution(int w, int h);
+
+	virtual bool IsFullscreen() { return false; }
+
+	virtual int GetWidth() { return window_width; }
+	virtual int GetHeight() { return window_height; }
+	virtual void *GetPixelBuffer() { return pixel_buffer; }
+
+	/* Convert local coordinate to window server (CoreGraphics) coordinate */
+	virtual CGPoint PrivateLocalToCG(NSPoint* p);
+
+	virtual NSPoint GetMouseLocation(NSEvent *event);
+	virtual bool MouseIsInsideView(NSPoint *pt);
+
+	virtual bool IsActive() { return active; }
+
+
+	void SetPortAlphaOpaque();
+	bool WindowResized();
+};
+
+
+@implementation OTTD_QuartzWindow
+
+- (void)setDriver:(WindowQuickdrawSubdriver*)drv
+{
+	driver = drv;
+}
+
+
+/* we override these methods to fix the miniaturize animation/dock icon bug */
+- (void)miniaturize:(id)sender
+{
+	/* make the alpha channel opaque so anim won't have holes in it */
+	driver->SetPortAlphaOpaque ();
+
+	/* window is hidden now */
+	driver->active = false;
+
+	QZ_ShowMouse();
+
+	[ super miniaturize:sender ];
+}
+
+- (void)display
+{
+	/* This method fires just before the window deminaturizes from the Dock.
+	 * We'll save the current visible surface, let the window manager redraw any
+	 * UI elements, and restore the surface. This way, no expose event
+	 * is required, and the deminiaturize works perfectly.
+	 */
+
+	driver->SetPortAlphaOpaque();
+
+	/* save current visible surface */
+	[ self cacheImageInRect:[ driver->qdview frame ] ];
+
+	/* let the window manager redraw controls, border, etc */
+	[ super display ];
+
+	/* restore visible surface */
+	[ self restoreCachedImage ];
+
+	/* window is visible again */
+	driver->active = true;
+}
+
+- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
+{
+	[ super setFrame:frameRect display:flag ];
+
+	/* Don't do anything if the window is currently being created */
+	if (driver->setup) return;
+
+	if (!driver->WindowResized())
+		error("Cocoa: Failed to resize window.");
+}
+
+- (void)appDidHide:(NSNotification*)note
+{
+	driver->active = false;
+}
+
+
+- (void)appWillUnhide:(NSNotification*)note
+{
+	driver->SetPortAlphaOpaque ();
+
+	/* save current visible surface */
+	[ self cacheImageInRect:[ driver->qdview frame ] ];
+}
+
+- (void)appDidUnhide:(NSNotification*)note
+{
+	/* restore cached image, since it may not be current, post expose event too */
+	[ self restoreCachedImage ];
+
+	driver->active = true;
+}
+
+
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
+{
+	/* Make our window subclass receive these application notifications */
+	[ [ NSNotificationCenter defaultCenter ] addObserver:self
+	selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ];
+
+	[ [ NSNotificationCenter defaultCenter ] addObserver:self
+	selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
+
+	[ [ NSNotificationCenter defaultCenter ] addObserver:self
+	selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
+
+	return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
+}
+
+@end
+
+@implementation OTTD_QuartzWindowDelegate
+- (void)setDriver:(WindowQuickdrawSubdriver*)drv
+{
+	driver = drv;
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+	HandleExitGameRequest();
+
+	return NO;
+}
+
+- (void)windowDidBecomeKey:(NSNotification*)aNotification
+{
+	driver->active = true;
+}
+
+- (void)windowDidResignKey:(NSNotification*)aNotification
+{
+	driver->active = false;
+}
+
+- (void)windowDidBecomeMain:(NSNotification*)aNotification
+{
+	driver->active = true;
+}
+
+- (void)windowDidResignMain:(NSNotification*)aNotification
+{
+	driver->active = false;
+}
+
+@end
+
+
+static const int _resize_icon_width  = 16;
+static const int _resize_icon_height = 16;
+
+static bool _resize_icon[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+	0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+	0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
+	0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
+	0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+	0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+	0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
+	1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0
+};
+
+
+
+extern const char _openttd_revision[];
+
+
+void WindowQuickdrawSubdriver::GetDeviceInfo()
+{
+	CFDictionaryRef    cur_mode;
+
+	/* Initialize the video settings; this data persists between mode switches */
+	cur_mode = CGDisplayCurrentMode(kCGDirectMainDisplay);
+
+	/* Gather some information that is useful to know about the display */
+	CFNumberGetValue(
+		(const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayBitsPerPixel),
+		kCFNumberSInt32Type, &device_depth
+	);
+
+	CFNumberGetValue(
+		(const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayWidth),
+		kCFNumberSInt32Type, &device_width
+	);
+
+	CFNumberGetValue(
+		(const __CFNumber*)CFDictionaryGetValue(cur_mode, kCGDisplayHeight),
+		kCFNumberSInt32Type, &device_height
+	);
+}
+
+bool WindowQuickdrawSubdriver::SetVideoMode(int width, int height)
+{
+	char caption[50];
+	NSString *nsscaption;
+	unsigned int style;
+	NSRect contentRect;
+	BOOL isCustom = NO;
+	bool ret;
+
+	setup = true;
+
+	GetDeviceInfo();
+
+	if (buffer_depth > device_depth) {
+		DEBUG(driver, 0, "Cannot use a blitter with a higer screen depth than the display when running in windowed mode.");
+		setup = false;
+		return false;
+	}
+
+	if (width > device_width)
+		width = device_width;
+	if (height > device_height)
+		height = device_height;
+
+	contentRect = NSMakeRect(0, 0, width, height);
+
+	/* Check if we should recreate the window */
+	if (window == nil) {
+		OTTD_QuartzWindowDelegate *delegate;
+
+		/* Set the window style */
+		style = NSTitledWindowMask;
+		style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
+		style |= NSResizableWindowMask;
+
+		/* Manually create a window, avoids having a nib file resource */
+		window = [ [ OTTD_QuartzWindow alloc ]
+						initWithContentRect:contentRect
+						styleMask:style
+						backing:NSBackingStoreBuffered
+						defer:NO ];
+
+		if (window == nil) {
+			DEBUG(driver, 0, "Could not create the Cocoa window.");
+			setup = false;
+			return false;
+		}
+
+		[ window setDriver:this ];
+
+		snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision);
+		nsscaption = [ [ NSString alloc ] initWithCString:caption ];
+		[ window setTitle:nsscaption ];
+		[ window setMiniwindowTitle:nsscaption ];
+		[ nsscaption release ];
+
+		[ window setAcceptsMouseMovedEvents:YES ];
+		[ window setViewsNeedDisplay:NO ];
+
+		delegate = [ [ OTTD_QuartzWindowDelegate alloc ] init ];
+		[ delegate setDriver:this ];
+		[ window setDelegate: [ delegate autorelease ] ];
+	} else {
+		/* We already have a window, just change its size */
+		if (!isCustom) {
+			[ window setContentSize:contentRect.size ];
+			// Ensure frame height - title bar height >= view height
+			contentRect.size.height = Clamp(height, 0, [ window frame ].size.height - 22 /* 22 is the height of title bar of window*/);
+			height = contentRect.size.height;
+			[ qdview setFrameSize:contentRect.size ];
+		}
+	}
+
+	// Update again
+	window_width = width;
+	window_height = height;
+
+	[ window center ];
+
+	/* Only recreate the view if it doesn't already exist */
+	if (qdview == nil) {
+		qdview = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
+		if (qdview == nil) {
+			DEBUG(driver, 0, "Could not create the Quickdraw view.");
+			setup = false;
+			return false;
+		}
+
+		[ qdview setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
+		[ [ window contentView ] addSubview:qdview ];
+		[ qdview release ];
+		[ window makeKeyAndOrderFront:nil ];
+	}
+
+	ret = WindowResized();
+
+	UpdatePalette(0, 256);
+
+	setup = false;
+
+	return ret;
+}
+
+void WindowQuickdrawSubdriver::Blit32ToView32(int left, int top, int right, int bottom)
+{
+	const uint32* src   = (uint32*)pixel_buffer;
+	uint32*       dst   = (uint32*)window_buffer;
+	uint          width = window_width;
+	uint          pitch = window_pitch / 4;
+	int y;
+
+
+	dst += top * pitch + left;
+	src += top * width + left;
+
+	for (y = top; y < bottom; y++, dst+= pitch, src+= width) {
+		memcpy(dst, src, (right - left) * 4);
+	}
+}
+
+void WindowQuickdrawSubdriver::BlitIndexedToView32(int left, int top, int right, int bottom)
+{
+	const uint32* pal   = palette32;
+	const uint8*  src   = (uint8*)pixel_buffer;
+	uint32*       dst   = (uint32*)window_buffer;
+	uint          width = window_width;
+	uint          pitch = window_pitch / 4;
+	int x;
+	int y;
+
+	for (y = top; y < bottom; y++) {
+		for (x = left; x < right; x++) {
+			dst[y * pitch + x] = pal[src[y * width + x]];
+		}
+	}
+}
+
+void WindowQuickdrawSubdriver::BlitIndexedToView16(int left, int top, int right, int bottom)
+{
+	const uint16* pal   = palette16;
+	const uint8*  src   = (uint8*)pixel_buffer;
+	uint16*       dst   = (uint16*)window_buffer;
+	uint          width = window_width;
+	uint          pitch = window_pitch / 2;
+	int x;
+	int y;
+
+	for (y = top; y < bottom; y++) {
+		for (x = left; x < right; x++) {
+			dst[y * pitch + x] = pal[src[y * width + x]];
+		}
+	}
+}
+
+
+inline void WindowQuickdrawSubdriver::BlitToView(int left, int top, int right, int bottom)
+{
+	switch (device_depth) {
+		case 32:
+			switch(buffer_depth) {
+				case 32:
+					Blit32ToView32(left, top, right, bottom);
+					break;
+				case 8:
+					BlitIndexedToView32(left, top, right, bottom);
+					break;
+			}
+			break;
+		case 16:
+			BlitIndexedToView16(left, top, right, bottom);
+			break;
+	}
+}
+
+void WindowQuickdrawSubdriver::DrawResizeIcon()
+{
+	int xoff = window_width - _resize_icon_width;
+	int yoff = window_height - _resize_icon_height;
+	int x;
+	int y;
+
+	switch (device_depth) {
+		case 32:
+			for (y = 0; y < _resize_icon_height; y++) {
+				uint32* trg = (uint32*)window_buffer + (yoff + y) * window_pitch / 4 + xoff;
+
+				for (x = 0; x < _resize_icon_width; x++, trg++) {
+					if (_resize_icon[y * _resize_icon_width + x]) *trg = 0xff000000;
+				}
+			}
+			break;
+		case 16:
+			for (y = 0; y < _resize_icon_height; y++) {
+				uint16* trg = (uint16*)window_buffer + (yoff + y) * window_pitch / 2 + xoff;
+
+				for (x = 0; x < _resize_icon_width; x++, trg++) {
+					if (_resize_icon[y * _resize_icon_width + x]) *trg = 0x0000;
+				}
+			}
+			break;
+	}
+}
+
+
+WindowQuickdrawSubdriver::WindowQuickdrawSubdriver(int bpp)
+{
+	window_width  = 0;
+	window_height = 0;
+	buffer_depth  = bpp;
+	pixel_buffer  = NULL;
+	active        = false;
+	setup         = false;
+
+	window = nil;
+	qdview = nil;
+
+	num_dirty_rects = MAX_DIRTY_RECTS;
+}
+
+WindowQuickdrawSubdriver::~WindowQuickdrawSubdriver()
+{
+	QZ_ShowMouse();
+
+	/* Release window mode resources */
+	if (window != nil) [ window close ];
+
+	free(pixel_buffer);
+}
+
+void WindowQuickdrawSubdriver::Draw()
+{
+	int i;
+	RgnHandle dirty, temp;
+
+	/* Check if we need to do anything */
+	if (num_dirty_rects == 0 ||
+		[ window isMiniaturized ]) {
+		return;
+	}
+
+	if (num_dirty_rects >= MAX_DIRTY_RECTS) {
+		num_dirty_rects = 1;
+		dirty_rects[0].left = 0;
+		dirty_rects[0].top = 0;
+		dirty_rects[0].right = window_width;
+		dirty_rects[0].bottom = window_height;
+	}
+
+	dirty = NewRgn();
+	temp  = NewRgn();
+
+	SetEmptyRgn(dirty);
+
+	/* Build the region of dirty rectangles */
+	for (i = 0; i < num_dirty_rects; i++) {
+		BlitToView(
+			dirty_rects[i].left,
+			dirty_rects[i].top,
+			dirty_rects[i].right,
+			dirty_rects[i].bottom
+		);
+
+		MacSetRectRgn(
+			temp,
+			dirty_rects[i].left,
+			dirty_rects[i].top,
+			dirty_rects[i].right,
+			dirty_rects[i].bottom
+		);
+		MacUnionRgn(dirty, temp, dirty);
+	}
+
+	DrawResizeIcon();
+
+	/* Flush the dirty region */
+	QDFlushPortBuffer( (OpaqueGrafPtr*) [ qdview qdPort ], dirty);
+	DisposeRgn(dirty);
+	DisposeRgn(temp);
+
+	num_dirty_rects = 0;
+}
+
+void WindowQuickdrawSubdriver::MakeDirty(int left, int top, int width, int height)
+{
+	if (num_dirty_rects < MAX_DIRTY_RECTS) {
+		dirty_rects[num_dirty_rects].left = left;
+		dirty_rects[num_dirty_rects].top = top;
+		dirty_rects[num_dirty_rects].right = left + width;
+		dirty_rects[num_dirty_rects].bottom = top + height;
+	}
+	num_dirty_rects++;
+}
+
+void WindowQuickdrawSubdriver::UpdatePalette(uint first_color, uint num_colors)
+{
+	uint i;
+
+	if (buffer_depth != 8)
+		return;
+
+	switch (device_depth) {
+		case 32:
+			for (i = first_color; i < first_color + num_colors; i++) {
+				uint32 clr32 = 0xff000000;
+				clr32 |= (uint32)_cur_palette[i].r << 16;
+				clr32 |= (uint32)_cur_palette[i].g << 8;
+				clr32 |= (uint32)_cur_palette[i].b;
+				palette32[i] = clr32;
+			}
+			break;
+		case 16:
+			for (i = first_color; i < first_color + num_colors; i++) {
+				uint16 clr16 = 0x0000;
+				clr16 |= (uint16)((_cur_palette[i].r >> 3) & 0x1f) << 10;
+				clr16 |= (uint16)((_cur_palette[i].g >> 3) & 0x1f) << 5;
+				clr16 |= (uint16)((_cur_palette[i].b >> 3) & 0x1f);
+				palette16[i] = clr16;
+			}
+			break;
+	}
+
+	num_dirty_rects = MAX_DIRTY_RECTS;
+}
+
+uint WindowQuickdrawSubdriver::ListModes(OTTDPoint* modes, uint max_modes)
+{
+	if (max_modes == 0) return 0;
+
+	modes[0].x = window_width;
+	modes[0].y = window_height;
+
+	return 1;
+}
+
+bool WindowQuickdrawSubdriver::ChangeResolution(int w, int h)
+{
+	int old_width  = window_width;
+	int old_height = window_height;
+
+	if (SetVideoMode(w, h))
+		return true;
+
+	if (old_width != 0 && old_height != 0)
+		SetVideoMode(old_width, old_height);
+
+	return false;
+}
+
+/* Convert local coordinate to window server (CoreGraphics) coordinate */
+CGPoint WindowQuickdrawSubdriver::PrivateLocalToCG(NSPoint* p)
+{
+	CGPoint cgp;
+
+	*p = [ qdview convertPoint:*p toView: nil ];
+	*p = [ window convertBaseToScreen:*p ];
+	p->y = window_height - p->y;
+
+	cgp.x = p->x;
+	cgp.y = p->y;
+
+	return cgp;
+}
+
+NSPoint WindowQuickdrawSubdriver::GetMouseLocation(NSEvent *event)
+{
+	NSPoint pt;
+
+	pt = [ event locationInWindow ];
+	pt = [ qdview convertPoint:pt fromView:nil ];
+
+	return pt;
+}
+
+bool WindowQuickdrawSubdriver::MouseIsInsideView(NSPoint *pt)
+{
+	return [ qdview mouse:*pt inRect:[ qdview bounds ] ];
+}
+
+
+/* This function makes the *game region* of the window 100% opaque.
+ * The genie effect uses the alpha component. Otherwise,
+ * it doesn't seem to matter what value it has.
+ */
+void WindowQuickdrawSubdriver::SetPortAlphaOpaque()
+{
+	if (device_depth != 32)
+		return;
+
+	uint32* pixels = (uint32*)window_buffer;
+	uint32  pitch  = window_pitch / 4;
+	int x, y;
+
+	for (y = 0; y < window_height; y++)
+		for (x = 0; x < window_width; x++) {
+		pixels[y * pitch + x] |= 0xFF000000;
+	}
+}
+
+bool WindowQuickdrawSubdriver::WindowResized()
+{
+	if (window == nil || qdview == nil) return true;
+
+	NSRect   newframe = [ qdview frame ];
+	CGrafPtr thePort  = (OpaqueGrafPtr*) [ qdview qdPort ];
+	int voff, hoff;
+
+	LockPortBits(thePort);
+	window_buffer = GetPixBaseAddr(GetPortPixMap(thePort));
+	window_pitch = GetPixRowBytes(GetPortPixMap(thePort));
+	UnlockPortBits(thePort);
+
+	/* _cocoa_video_data.realpixels now points to the window's pixels
+	 * We want it to point to the *view's* pixels
+	 */
+	voff = [ window frame ].size.height - newframe.size.height - newframe.origin.y;
+	hoff = [ qdview frame ].origin.x;
+	window_buffer = (uint8*)window_buffer + (voff * window_pitch) + hoff * (device_depth / 8);
+
+	window_width = newframe.size.width;
+	window_height = newframe.size.height;
+
+	free(pixel_buffer);
+	pixel_buffer = malloc(window_width * window_height * buffer_depth / 8);
+	if (pixel_buffer == NULL) {
+		DEBUG(driver, 0, "Failed to allocate pixel buffer");
+		return false;
+	}
+
+	QZ_GameSizeChanged();
+
+	/* Redraw screen */
+	num_dirty_rects = MAX_DIRTY_RECTS;
+
+	return true;
+}
+
+
+CocoaSubdriver *QZ_CreateWindowQuickdrawSubdriver(int width, int height, int bpp)
+{
+	WindowQuickdrawSubdriver *ret;
+
+	ret = new WindowQuickdrawSubdriver(bpp);
+
+	if (!ret->ChangeResolution(width, height)) {
+		delete ret;
+		return NULL;
+	}
+
+	return ret;
+}
+
+#endif /* WITH_COCOA */
--- a/src/video/cocoa_keys.h	Thu Nov 22 19:55:54 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/* $Id$ */
-
-#ifndef COCOA_KEYS_H
-#define COCOA_KEYS_H
-
-/* From SDL_QuartzKeys.h */
-/* These are the Macintosh key scancode constants -- from Inside Macintosh */
-
-#define QZ_ESCAPE       0x35
-#define QZ_F1           0x7A
-#define QZ_F2           0x78
-#define QZ_F3           0x63
-#define QZ_F4           0x76
-#define QZ_F5           0x60
-#define QZ_F6           0x61
-#define QZ_F7           0x62
-#define QZ_F8           0x64
-#define QZ_F9           0x65
-#define QZ_F10          0x6D
-#define QZ_F11          0x67
-#define QZ_F12          0x6F
-#define QZ_PRINT        0x69
-#define QZ_SCROLLOCK    0x6B
-#define QZ_PAUSE        0x71
-#define QZ_POWER        0x7F
-#define QZ_BACKQUOTE    0x0A
-#define QZ_BACKQUOTE2   0x32
-#define QZ_1            0x12
-#define QZ_2            0x13
-#define QZ_3            0x14
-#define QZ_4            0x15
-#define QZ_5            0x17
-#define QZ_6            0x16
-#define QZ_7            0x1A
-#define QZ_8            0x1C
-#define QZ_9            0x19
-#define QZ_0            0x1D
-#define QZ_MINUS        0x1B
-#define QZ_EQUALS       0x18
-#define QZ_BACKSPACE    0x33
-#define QZ_INSERT       0x72
-#define QZ_HOME         0x73
-#define QZ_PAGEUP       0x74
-#define QZ_NUMLOCK      0x47
-#define QZ_KP_EQUALS    0x51
-#define QZ_KP_DIVIDE    0x4B
-#define QZ_KP_MULTIPLY  0x43
-#define QZ_TAB          0x30
-#define QZ_q            0x0C
-#define QZ_w            0x0D
-#define QZ_e            0x0E
-#define QZ_r            0x0F
-#define QZ_t            0x11
-#define QZ_y            0x10
-#define QZ_u            0x20
-#define QZ_i            0x22
-#define QZ_o            0x1F
-#define QZ_p            0x23
-#define QZ_LEFTBRACKET  0x21
-#define QZ_RIGHTBRACKET 0x1E
-#define QZ_BACKSLASH    0x2A
-#define QZ_DELETE       0x75
-#define QZ_END          0x77
-#define QZ_PAGEDOWN     0x79
-#define QZ_KP7          0x59
-#define QZ_KP8          0x5B
-#define QZ_KP9          0x5C
-#define QZ_KP_MINUS     0x4E
-#define QZ_CAPSLOCK     0x39
-#define QZ_a            0x00
-#define QZ_s            0x01
-#define QZ_d            0x02
-#define QZ_f            0x03
-#define QZ_g            0x05
-#define QZ_h            0x04
-#define QZ_j            0x26
-#define QZ_k            0x28
-#define QZ_l            0x25
-#define QZ_SEMICOLON    0x29
-#define QZ_QUOTE        0x27
-#define QZ_RETURN       0x24
-#define QZ_KP4          0x56
-#define QZ_KP5          0x57
-#define QZ_KP6          0x58
-#define QZ_KP_PLUS      0x45
-#define QZ_LSHIFT       0x38
-#define QZ_z            0x06
-#define QZ_x            0x07
-#define QZ_c            0x08
-#define QZ_v            0x09
-#define QZ_b            0x0B
-#define QZ_n            0x2D
-#define QZ_m            0x2E
-#define QZ_COMMA        0x2B
-#define QZ_PERIOD       0x2F
-#define QZ_SLASH        0x2C
-#if 1        /* Panther now defines right side keys */
-#define QZ_RSHIFT       0x3C
-#endif
-#define QZ_UP           0x7E
-#define QZ_KP1          0x53
-#define QZ_KP2          0x54
-#define QZ_KP3          0x55
-#define QZ_KP_ENTER     0x4C
-#define QZ_LCTRL        0x3B
-#define QZ_LALT         0x3A
-#define QZ_LMETA        0x37
-#define QZ_SPACE        0x31
-#if 1        /* Panther now defines right side keys */
-#define QZ_RMETA        0x36
-#define QZ_RALT         0x3D
-#define QZ_RCTRL        0x3E
-#endif
-#define QZ_LEFT         0x7B
-#define QZ_DOWN         0x7D
-#define QZ_RIGHT        0x7C
-#define QZ_KP0          0x52
-#define QZ_KP_PERIOD    0x41
-
-/* Wierd, these keys are on my iBook under MacOS X */
-#define QZ_IBOOK_ENTER  0x34
-#define QZ_IBOOK_LEFT   0x3B
-#define QZ_IBOOK_RIGHT  0x3C
-#define QZ_IBOOK_DOWN   0x3D
-#define QZ_IBOOK_UP     0x3E
-
-#endif
--- a/src/video/cocoa_v.h	Thu Nov 22 19:55:54 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/* $Id$ */
-
-#ifndef VIDEO_COCOA_H
-#define VIDEO_COCOA_H
-
-#include "video_driver.hpp"
-
-class VideoDriver_Cocoa: public VideoDriver {
-public:
-	/* virtual */ const char *Start(const char * const *param);
-
-	/* virtual */ void Stop();
-
-	/* virtual */ void MakeDirty(int left, int top, int width, int height);
-
-	/* virtual */ void MainLoop();
-
-	/* virtual */ bool ChangeResolution(int w, int h);
-
-	/* virtual */ void ToggleFullscreen(bool fullscreen);
-};
-
-class FVideoDriver_Cocoa: public VideoDriverFactory<FVideoDriver_Cocoa> {
-public:
-	static const int priority = 10;
-	/* virtual */ const char *GetName() { return "cocoa"; }
-	/* virtual */ const char *GetDescription() { return "Cocoa Video Driver"; }
-	/* virtual */ Driver *CreateInstance() { return new VideoDriver_Cocoa(); }
-};
-
-#endif /* VIDEO_COCOA_H */
--- a/src/video/cocoa_v.mm	Thu Nov 22 19:55:54 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2164 +0,0 @@
-/* $Id$ */
-
-/******************************************************************************
- *                             Cocoa video driver                             *
- * Known things left to do:                                                   *
- *  Nothing at the moment.                                                    *
- ******************************************************************************/
-
-#ifdef WITH_COCOA
-
-#include <AvailabilityMacros.h>
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
-/* On 10.4, we get tons of warnings that the QuickDraw functions are deprecated.
- *  We know that. Don't keep bugging us about that. */
-#	undef AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4
-#	define AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4 AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER
-#endif
-
-#import <Cocoa/Cocoa.h>
-#import <sys/time.h> /* gettimeofday */
-#import <sys/param.h> /* for MAXPATHLEN */
-#import <unistd.h>
-
-/**
- * Important notice regarding all modifications!!!!!!!
- * There are certain limitations because the file is objective C++.
- * gdb has limitations.
- * C++ and objective C code can't be joined in all cases (classes stuff).
- * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
- */
-
-
-/* Portions of CPS.h */
-struct CPSProcessSerNum {
-	UInt32 lo;
-	UInt32 hi;
-};
-
-extern "C" OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn);
-extern "C" OSErr CPSEnableForegroundOperation(CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
-extern "C" OSErr CPSSetFrontProcess(CPSProcessSerNum* psn);
-
-/* From Menus.h (according to Xcode Developer Documentation) */
-extern "C" void ShowMenuBar();
-extern "C" void HideMenuBar();
-
-/* Disables a warning. This is needed since the method exists but has been dropped from the header, supposedly as of 10.4. */
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
-@interface NSApplication(NSAppleMenu)
-- (void)setAppleMenu:(NSMenu *)menu;
-@end
-#endif
-
-
-/* Defined in stdbool.h */
-#ifndef __cplusplus
-# ifndef __BEOS__
-#  undef bool
-#  undef false
-#  undef true
-# endif
-#endif
-
-
-#include "../stdafx.h"
-#include "../openttd.h"
-#include "../debug.h"
-#include "../macros.h"
-#include "../os/macosx/splash.h"
-#include "../variables.h"
-#include "../gfx.h"
-#include "cocoa_v.h"
-#include "cocoa_keys.h"
-#include "../blitter/factory.hpp"
-#include "../fileio.h"
-
-#undef Point
-#undef Rect
-
-/* Right Mouse Button Emulation enum */
-enum {
-	RMBE_COMMAND,
-	RMBE_CONTROL,
-	RMBE_OFF,
-};
-
-
-/* Subclass of NSWindow to fix genie effect and support resize events  */
-@interface OTTD_QuartzWindow : NSWindow
-- (void)miniaturize:(id)sender;
-- (void)display;
-- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
-- (void)appDidHide:(NSNotification*)note;
-- (void)appWillUnhide:(NSNotification*)note;
-- (void)appDidUnhide:(NSNotification*)note;
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
-@end
-
-/* Delegate for our NSWindow to send ask for quit on close */
-@interface OTTD_QuartzWindowDelegate : NSObject
-- (BOOL)windowShouldClose:(id)sender;
-@end
-
-@interface OTTDMain : NSObject
-@end
-
-
-/* Structure for rez switch gamma fades
- * We can hide the monitor flicker by setting the gamma tables to 0
- */
-#define QZ_GAMMA_TABLE_SIZE 256
-
-struct OTTD_QuartzGammaTable {
-	CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];
-};
-
-/* Add methods to get at private members of NSScreen.
- * Since there is a bug in Apple's screen switching code that does not update
- * this variable when switching to fullscreen, we'll set it manually (but only
- * for the main screen).
- */
-@interface NSScreen (NSScreenAccess)
-	- (void) setFrame:(NSRect)frame;
-@end
-
-@implementation NSScreen (NSScreenAccess)
-- (void) setFrame:(NSRect)frame;
-{
-	_frame = frame;
-}
-@end
-
-
-static void QZ_Draw();
-static void QZ_UnsetVideoMode();
-static void QZ_UpdatePalette(uint start, uint count);
-static void QZ_WarpCursor(int x, int y);
-static void QZ_ShowMouse();
-static void QZ_HideMouse();
-
-
-static NSAutoreleasePool *_ottd_autorelease_pool;
-static OTTDMain *_ottd_main;
-
-
-static struct CocoaVideoData {
-	bool isset;
-	bool issetting;
-
-	CGDirectDisplayID  display_id;         /* 0 == main display (only support single display) */
-	CFDictionaryRef    mode;               /* current mode of the display */
-	CFDictionaryRef    save_mode;          /* original mode of the display */
-	CFArrayRef         mode_list;          /* list of available fullscreen modes */
-	CGDirectPaletteRef palette;            /* palette of an 8-bit display */
-
-	uint32 blitter_bpp;
-
-	uint32 device_width;
-	uint32 device_height;
-	uint32 device_bpp;
-
-	void *realpixels;
-	void *pixels;
-	uint32 width;
-	uint32 height;
-	uint32 pitch;
-	bool fullscreen;
-
-	unsigned int current_mods;
-	bool tab_is_down;
-	bool emulating_right_button;
-
-	bool cursor_visible;
-	bool active;
-
-#ifdef _DEBUG
-	uint32 tEvent;
-#endif
-
-	OTTD_QuartzWindow *window;
-	NSQuickDrawView *qdview;
-
-#define MAX_DIRTY_RECTS 100
-	Rect dirty_rects[MAX_DIRTY_RECTS];
-	int num_dirty_rects;
-
-	uint16 palette16[256];
-	uint32 palette32[256];
-} _cocoa_video_data;
-
-static bool _cocoa_video_started = false;
-static bool _cocoa_video_dialog = false;
-
-
-
-
-/******************************************************************************
- *                             Game loop and accessories                      *
- ******************************************************************************/
-
-static uint32 GetTick()
-{
-	struct timeval tim;
-
-	gettimeofday(&tim, NULL);
-	return tim.tv_usec / 1000 + tim.tv_sec * 1000;
-}
-
-static void QZ_CheckPaletteAnim()
-{
-	if (_pal_count_dirty != 0) {
-		Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
-
-		switch (blitter->UsePaletteAnimation()) {
-			case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
-				QZ_UpdatePalette(_pal_first_dirty, _pal_count_dirty);
-				break;
-
-			case Blitter::PALETTE_ANIMATION_BLITTER:
-				blitter->PaletteAnimate(_pal_first_dirty, _pal_count_dirty);
-				break;
-
-			case Blitter::PALETTE_ANIMATION_NONE:
-				break;
-
-			default:
-				NOT_REACHED();
-		}
-		_pal_count_dirty = 0;
-	}
-}
-
-
-
-struct VkMapping {
-	unsigned short vk_from;
-	byte map_to;
-};
-
-#define AS(x, z) {x, z}
-
-static const VkMapping _vk_mapping[] = {
-	AS(QZ_BACKQUOTE,  WKC_BACKQUOTE), // key left of '1'
-	AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode
-
-	/* Pageup stuff + up/down */
-	AS(QZ_PAGEUP,   WKC_PAGEUP),
-	AS(QZ_PAGEDOWN, WKC_PAGEDOWN),
-
-	AS(QZ_UP,    WKC_UP),
-	AS(QZ_DOWN,  WKC_DOWN),
-	AS(QZ_LEFT,  WKC_LEFT),
-	AS(QZ_RIGHT, WKC_RIGHT),
-
-	AS(QZ_HOME, WKC_HOME),
-	AS(QZ_END,  WKC_END),
-
-	AS(QZ_INSERT, WKC_INSERT),
-	AS(QZ_DELETE, WKC_DELETE),
-
-	/* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */
-	AS(QZ_a, 'A'),
-	AS(QZ_b, 'B'),
-	AS(QZ_c, 'C'),
-	AS(QZ_d, 'D'),
-	AS(QZ_e, 'E'),
-	AS(QZ_f, 'F'),
-	AS(QZ_g, 'G'),
-	AS(QZ_h, 'H'),
-	AS(QZ_i, 'I'),
-	AS(QZ_j, 'J'),
-	AS(QZ_k, 'K'),
-	AS(QZ_l, 'L'),
-	AS(QZ_m, 'M'),
-	AS(QZ_n, 'N'),
-	AS(QZ_o, 'O'),
-	AS(QZ_p, 'P'),
-	AS(QZ_q, 'Q'),
-	AS(QZ_r, 'R'),
-	AS(QZ_s, 'S'),
-	AS(QZ_t, 'T'),
-	AS(QZ_u, 'U'),
-	AS(QZ_v, 'V'),
-	AS(QZ_w, 'W'),
-	AS(QZ_x, 'X'),
-	AS(QZ_y, 'Y'),
-	AS(QZ_z, 'Z'),
-	/* Same thing for digits */
-	AS(QZ_0, '0'),
-	AS(QZ_1, '1'),
-	AS(QZ_2, '2'),
-	AS(QZ_3, '3'),
-	AS(QZ_4, '4'),
-	AS(QZ_5, '5'),
-	AS(QZ_6, '6'),
-	AS(QZ_7, '7'),
-	AS(QZ_8, '8'),
-	AS(QZ_9, '9'),
-
-	AS(QZ_ESCAPE,    WKC_ESC),
-	AS(QZ_PAUSE,     WKC_PAUSE),
-	AS(QZ_BACKSPACE, WKC_BACKSPACE),
-
-	AS(QZ_SPACE,  WKC_SPACE),
-	AS(QZ_RETURN, WKC_RETURN),
-	AS(QZ_TAB,    WKC_TAB),
-
-	/* Function keys */
-	AS(QZ_F1,  WKC_F1),
-	AS(QZ_F2,  WKC_F2),
-	AS(QZ_F3,  WKC_F3),
-	AS(QZ_F4,  WKC_F4),
-	AS(QZ_F5,  WKC_F5),
-	AS(QZ_F6,  WKC_F6),
-	AS(QZ_F7,  WKC_F7),
-	AS(QZ_F8,  WKC_F8),
-	AS(QZ_F9,  WKC_F9),
-	AS(QZ_F10, WKC_F10),
-	AS(QZ_F11, WKC_F11),
-	AS(QZ_F12, WKC_F12),
-
-	/* Numeric part */
-	AS(QZ_KP0,         WKC_NUM_0),
-	AS(QZ_KP1,         WKC_NUM_1),
-	AS(QZ_KP2,         WKC_NUM_2),
-	AS(QZ_KP3,         WKC_NUM_3),
-	AS(QZ_KP4,         WKC_NUM_4),
-	AS(QZ_KP5,         WKC_NUM_5),
-	AS(QZ_KP6,         WKC_NUM_6),
-	AS(QZ_KP7,         WKC_NUM_7),
-	AS(QZ_KP8,         WKC_NUM_8),
-	AS(QZ_KP9,         WKC_NUM_9),
-	AS(QZ_KP_DIVIDE,   WKC_NUM_DIV),
-	AS(QZ_KP_MULTIPLY, WKC_NUM_MUL),
-	AS(QZ_KP_MINUS,    WKC_NUM_MINUS),
-	AS(QZ_KP_PLUS,     WKC_NUM_PLUS),
-	AS(QZ_KP_ENTER,    WKC_NUM_ENTER),
-	AS(QZ_KP_PERIOD,   WKC_NUM_DECIMAL),
-
-	/* Other non-letter keys */
-	AS(QZ_SLASH,        WKC_SLASH),
-	AS(QZ_SEMICOLON,    WKC_SEMICOLON),
-	AS(QZ_EQUALS,       WKC_EQUALS),
-	AS(QZ_LEFTBRACKET,  WKC_L_BRACKET),
-	AS(QZ_BACKSLASH,    WKC_BACKSLASH),
-	AS(QZ_RIGHTBRACKET, WKC_R_BRACKET),
-
-	AS(QZ_QUOTE,   WKC_SINGLEQUOTE),
-	AS(QZ_COMMA,   WKC_COMMA),
-	AS(QZ_MINUS,   WKC_MINUS),
-	AS(QZ_PERIOD,  WKC_PERIOD)
-};
-
-
-static uint32 QZ_MapKey(unsigned short sym)
-{
-	const VkMapping *map;
-	uint32 key = 0;
-
-	for (map = _vk_mapping; map != endof(_vk_mapping); ++map) {
-		if (sym == map->vk_from) {
-			key = map->map_to;
-			break;
-		}
-	}
-
-	if (_cocoa_video_data.current_mods & NSShiftKeyMask)     key |= WKC_SHIFT;
-	if (_cocoa_video_data.current_mods & NSControlKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
-	if (_cocoa_video_data.current_mods & NSAlternateKeyMask) key |= WKC_ALT;
-	if (_cocoa_video_data.current_mods & NSCommandKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
-
-	return key << 16;
-}
-
-static void QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down)
-{
-	switch (keycode) {
-		case QZ_UP:    SB(_dirkeys, 1, 1, down); break;
-		case QZ_DOWN:  SB(_dirkeys, 3, 1, down); break;
-		case QZ_LEFT:  SB(_dirkeys, 0, 1, down); break;
-		case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break;
-
-		case QZ_TAB: _cocoa_video_data.tab_is_down = down; break;
-
-		case QZ_RETURN:
-		case QZ_f:
-			if (down && (_cocoa_video_data.current_mods & NSCommandKeyMask)) {
-				_video_driver->ToggleFullscreen(!_fullscreen);
-			}
-			break;
-	}
-
-	if (down) {
-		uint32 pressed_key = QZ_MapKey(keycode) | unicode;
-		HandleKeypress(pressed_key);
-		DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key);
-	} else {
-		DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode);
-	}
-}
-
-static void QZ_DoUnsidedModifiers(unsigned int newMods)
-{
-	const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA };
-
-	int i;
-	unsigned int bit;
-
-	if (_cocoa_video_data.current_mods == newMods) return;
-
-	/* Iterate through the bits, testing each against the current modifiers */
-	for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
-		unsigned int currentMask, newMask;
-
-		currentMask = _cocoa_video_data.current_mods & bit;
-		newMask     = newMods & bit;
-
-		if (currentMask && currentMask != newMask) { /* modifier up event */
-			/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
-			if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES);
-			QZ_KeyEvent(mapping[i], 0, NO);
-		} else if (newMask && currentMask != newMask) { /* modifier down event */
-			QZ_KeyEvent(mapping[i], 0, YES);
-			/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
-			if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO);
-		}
-	}
-
-	_cocoa_video_data.current_mods = newMods;
-}
-
-static void QZ_MouseMovedEvent(int x, int y)
-{
-	if (_cursor.fix_at) {
-		int dx = x - _cursor.pos.x;
-		int dy = y - _cursor.pos.y;
-
-		if (dx != 0 || dy != 0) {
-			_cursor.delta.x += dx;
-			_cursor.delta.y += dy;
-
-			QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
-		}
-	} else {
-		_cursor.delta.x = x - _cursor.pos.x;
-		_cursor.delta.y = y - _cursor.pos.y;
-		_cursor.pos.x = x;
-		_cursor.pos.y = y;
-		_cursor.dirty = true;
-	}
-	HandleMouseEvents();
-}
-
-
-static void QZ_MouseButtonEvent(int button, BOOL down)
-{
-	switch (button) {
-		case 0:
-			if (down) {
-				_left_button_down = true;
-			} else {
-				_left_button_down = false;
-				_left_button_clicked = false;
-			}
-			HandleMouseEvents();
-			break;
-
-		case 1:
-			if (down) {
-				_right_button_down = true;
-				_right_button_clicked = true;
-			} else {
-				_right_button_down = false;
-			}
-			HandleMouseEvents();
-			break;
-	}
-}
-
-
-static inline NSPoint QZ_GetMouseLocation(NSEvent *event)
-{
-	NSPoint pt;
-
-	if (_cocoa_video_data.fullscreen) {
-		pt = [ NSEvent mouseLocation ];
-		pt.y = _cocoa_video_data.height - pt.y;
-	} else {
-		pt = [event locationInWindow];
-		pt = [_cocoa_video_data.qdview convertPoint:pt fromView:nil];
-	}
-
-	return pt;
-}
-
-static bool QZ_MouseIsInsideView(NSPoint *pt)
-{
-	if (_cocoa_video_data.fullscreen) {
-		return pt->x >= 0 && pt->y >= 0 && pt->x < _cocoa_video_data.width && pt->y < _cocoa_video_data.height;
-	} else {
-		return [ _cocoa_video_data.qdview mouse:*pt inRect:[ _cocoa_video_data.qdview bounds ] ];
-	}
-}
-
-
-static bool QZ_PollEvent()
-{
-	NSEvent *event;
-	NSPoint pt;
-	NSString *chars;
-#ifdef _DEBUG
-	uint32 et0, et;
-#endif
-
-#ifdef _DEBUG
-	et0 = GetTick();
-#endif
-	event = [ NSApp nextEventMatchingMask:NSAnyEventMask
-			untilDate: [ NSDate distantPast ]
-			inMode: NSDefaultRunLoopMode dequeue:YES ];
-#ifdef _DEBUG
-	et = GetTick();
-	_cocoa_video_data.tEvent+= et - et0;
-#endif
-
-	if (event == nil) return false;
-	if (!_cocoa_video_data.active) {
-		QZ_ShowMouse();
-		[NSApp sendEvent:event];
-		return true;
-	}
-
-	QZ_DoUnsidedModifiers( [ event modifierFlags ] );
-
-	switch ([event type]) {
-		case NSMouseMoved:
-		case NSOtherMouseDragged:
-		case NSRightMouseDragged:
-		case NSLeftMouseDragged:
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt) &&
-					!_cocoa_video_data.emulating_right_button) {
-				QZ_ShowMouse();
-				[NSApp sendEvent:event];
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-			break;
-
-		case NSLeftMouseDown:
-		{
-			uint32 keymask = 0;
-			if (_patches.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
-			if (_patches.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
-
-			pt = QZ_GetMouseLocation(event);
-
-			if (!([ event modifierFlags ] & keymask) ||
-					!QZ_MouseIsInsideView(&pt)) {
-				[NSApp sendEvent:event];
-			}
-
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-
-			/* Right mouse button emulation */
-			if ([ event modifierFlags ] & keymask) {
-				_cocoa_video_data.emulating_right_button = true;
-				QZ_MouseButtonEvent(1, YES);
-			} else {
-				QZ_MouseButtonEvent(0, YES);
-			}
-			break;
-		}
-		case NSLeftMouseUp:
-			[NSApp sendEvent:event];
-
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-
-			/* Right mouse button emulation */
-			if (_cocoa_video_data.emulating_right_button) {
-				_cocoa_video_data.emulating_right_button = false;
-				QZ_MouseButtonEvent(1, NO);
-			} else {
-				QZ_MouseButtonEvent(0, NO);
-			}
-			break;
-
-		case NSRightMouseDown:
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				[NSApp sendEvent:event];
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-			QZ_MouseButtonEvent(1, YES);
-			break;
-
-		case NSRightMouseUp:
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				[NSApp sendEvent:event];
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-			QZ_MouseButtonEvent(1, NO);
-			break;
-
-#if 0
-		/* This is not needed since openttd currently only use two buttons */
-		case NSOtherMouseDown:
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				[NSApp sendEvent:event];
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-			QZ_MouseButtonEvent([ event buttonNumber ], YES);
-			break;
-
-		case NSOtherMouseUp:
-			pt = QZ_GetMouseLocation(event);
-			if (!QZ_MouseIsInsideView(&pt)) {
-				QZ_ShowMouse();
-				[NSApp sendEvent:event];
-				break;
-			}
-
-			QZ_HideMouse();
-			QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
-			QZ_MouseButtonEvent([ event buttonNumber ], NO);
-			break;
-#endif
-
-		case NSKeyDown:
-			/* Quit, hide and minimize */
-			switch ([event keyCode]) {
-				case QZ_q:
-				case QZ_h:
-				case QZ_m:
-					if ([ event modifierFlags ] & NSCommandKeyMask) {
-						[NSApp sendEvent:event];
-					}
-					break;
-			}
-
-			chars = [ event characters ];
-			QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, YES);
-			break;
-
-		case NSKeyUp:
-			/* Quit, hide and minimize */
-			switch ([event keyCode]) {
-				case QZ_q:
-				case QZ_h:
-				case QZ_m:
-					if ([ event modifierFlags ] & NSCommandKeyMask) {
-						[NSApp sendEvent:event];
-					}
-					break;
-			}
-
-			chars = [ event characters ];
-			QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO);
-			break;
-
-		case NSScrollWheel:
-			if ([ event deltaY ] > 0.0) { /* Scroll up */
-				_cursor.wheel--;
-			} else if ([ event deltaY ] < 0.0) { /* Scroll down */
-				_cursor.wheel++;
-			} /* else: deltaY was 0.0 and we don't want to do anything */
-
-			/* Set the scroll count for scrollwheel scrolling */
-			_cursor.h_wheel -= (int)([ event deltaX ]* 5 * _patches.scrollwheel_multiplier);
-			_cursor.v_wheel -= (int)([ event deltaY ]* 5 * _patches.scrollwheel_multiplier);
-			break;
-
-		default:
-			[NSApp sendEvent:event];
-	}
-
-	return true;
-}
-
-
-static void QZ_GameLoop()
-{
-	uint32 cur_ticks = GetTick();
-	uint32 last_cur_ticks = cur_ticks;
-	uint32 next_tick = cur_ticks + 30;
-	uint32 pal_tick = 0;
-#ifdef _DEBUG
-	uint32 et0, et, st0, st;
-#endif
-	int i;
-
-#ifdef _DEBUG
-	et0 = GetTick();
-	st = 0;
-#endif
-
-	_screen.dst_ptr = _cocoa_video_data.pixels;
-	DisplaySplashImage();
-	QZ_CheckPaletteAnim();
-	QZ_Draw();
-	CSleep(1);
-
-	for (i = 0; i < 2; i++) GameLoop();
-
-	_screen.dst_ptr = _cocoa_video_data.pixels;
-	UpdateWindows();
-	QZ_CheckPaletteAnim();
-	QZ_Draw();
-	CSleep(1);
-
-	for (;;) {
-		uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
-		InteractiveRandom(); // randomness
-
-		while (QZ_PollEvent()) {}
-
-		if (_exit_game) break;
-
-#if defined(_DEBUG)
-		if (_cocoa_video_data.current_mods & NSShiftKeyMask)
-#else
-		if (_cocoa_video_data.tab_is_down)
-#endif
-		{
-			if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
-		} else if (_fast_forward & 2) {
-			_fast_forward = 0;
-		}
-
-		cur_ticks = GetTick();
-		if (cur_ticks >= next_tick || (_fast_forward && !_pause_game) || cur_ticks < prev_cur_ticks) {
-			_realtime_tick += cur_ticks - last_cur_ticks;
-			last_cur_ticks = cur_ticks;
-			next_tick = cur_ticks + 30;
-
-			_ctrl_pressed = !!(_cocoa_video_data.current_mods & ( _patches.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
-			_shift_pressed = !!(_cocoa_video_data.current_mods & NSShiftKeyMask);
-
-			GameLoop();
-
-			_screen.dst_ptr = _cocoa_video_data.pixels;
-			UpdateWindows();
-			if (++pal_tick > 4) {
-				QZ_CheckPaletteAnim();
-				pal_tick = 1;
-			}
-			QZ_Draw();
-		} else {
-#ifdef _DEBUG
-			st0 = GetTick();
-#endif
-			CSleep(1);
-#ifdef _DEBUG
-			st += GetTick() - st0;
-#endif
-			_screen.dst_ptr = _cocoa_video_data.pixels;
-			DrawChatMessage();
-			DrawMouseCursor();
-			QZ_Draw();
-		}
-	}
-
-#ifdef _DEBUG
-	et = GetTick();
-
-	DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _cocoa_video_data.tEvent);
-	DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st);
-	DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_cocoa_video_data.tEvent / (double)(et - et0) * 100);
-	DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_cocoa_video_data.tEvent / (double)(et - et0 - st) * 100);
-#endif
-}
-
-
-/******************************************************************************
- *                             Windowed mode                                  *
- ******************************************************************************/
-
-/* This function makes the *game region* of the window 100% opaque.
- * The genie effect uses the alpha component. Otherwise,
- * it doesn't seem to matter what value it has.
- */
-static void QZ_SetPortAlphaOpaque()
-{
-	if (_cocoa_video_data.device_bpp == 32) {
-		uint32* pixels = (uint32*)_cocoa_video_data.realpixels;
-		uint32 rowPixels = _cocoa_video_data.pitch / 4;
-		uint32 i;
-		uint32 j;
-
-		for (i = 0; i < _cocoa_video_data.height; i++)
-			for (j = 0; j < _cocoa_video_data.width; j++) {
-			pixels[i * rowPixels + j] |= 0xFF000000;
-		}
-	}
-}
-
-
-@implementation OTTD_QuartzWindow
-
-/* we override these methods to fix the miniaturize animation/dock icon bug */
-- (void)miniaturize:(id)sender
-{
-	/* make the alpha channel opaque so anim won't have holes in it */
-	QZ_SetPortAlphaOpaque ();
-
-	/* window is hidden now */
-	_cocoa_video_data.active = false;
-
-	QZ_ShowMouse();
-
-	[ super miniaturize:sender ];
-}
-
-- (void)display
-{
-	/* This method fires just before the window deminaturizes from the Dock.
-	 * We'll save the current visible surface, let the window manager redraw any
-	 * UI elements, and restore the surface. This way, no expose event
-	 * is required, and the deminiaturize works perfectly.
-	 */
-
-	QZ_SetPortAlphaOpaque();
-
-	/* save current visible surface */
-	[ self cacheImageInRect:[ _cocoa_video_data.qdview frame ] ];
-
-	/* let the window manager redraw controls, border, etc */
-	[ super display ];
-
-	/* restore visible surface */
-	[ self restoreCachedImage ];
-
-	/* window is visible again */
-	_cocoa_video_data.active = true;
-}
-
-- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
-{
-	NSRect newViewFrame;
-	CGrafPtr thePort;
-
-	[ super setFrame:frameRect display:flag ];
-
-	/* Don't do anything if the window is currently beign created */
-	if (_cocoa_video_data.issetting) return;
-
-	if (_cocoa_video_data.window == nil) return;
-
-	newViewFrame = [ _cocoa_video_data.qdview frame ];
-
-	/* Update the pixels and pitch */
-	thePort = (OpaqueGrafPtr*) [ _cocoa_video_data.qdview qdPort ];
-	LockPortBits(thePort);
-
-	_cocoa_video_data.realpixels = GetPixBaseAddr(GetPortPixMap(thePort));
-	_cocoa_video_data.pitch      = GetPixRowBytes(GetPortPixMap(thePort));
-
-	/* _cocoa_video_data.realpixels now points to the window's pixels
-	 * We want it to point to the *view's* pixels
-	 */
-	{
-		int vOffset = [ _cocoa_video_data.window frame ].size.height - newViewFrame.size.height - newViewFrame.origin.y;
-		int hOffset = newViewFrame.origin.x;
-
-		_cocoa_video_data.realpixels = (uint8*)_cocoa_video_data.realpixels + (vOffset * _cocoa_video_data.pitch) + hOffset * (_cocoa_video_data.device_bpp / 8);
-	}
-
-	UnlockPortBits(thePort);
-
-	/* Allocate new buffer */
-	free(_cocoa_video_data.pixels);
-	_cocoa_video_data.pixels = malloc(newViewFrame.size.width * newViewFrame.size.height * _cocoa_video_data.blitter_bpp / 8);
-	assert(_cocoa_video_data.pixels != NULL);
-
-
-	/* Tell the game that the resolution changed */
-	_cocoa_video_data.width = newViewFrame.size.width;
-	_cocoa_video_data.height = newViewFrame.size.height;
-
-	_screen.width = _cocoa_video_data.width;
-	_screen.height = _cocoa_video_data.height;
-	_screen.pitch = _cocoa_video_data.width;
-
-	GameSizeChanged();
-
-	/* Redraw screen */
-	_cocoa_video_data.num_dirty_rects = MAX_DIRTY_RECTS;
-}
-
-- (void)appDidHide:(NSNotification*)note
-{
-	_cocoa_video_data.active = false;
-}
-
-
-- (void)appWillUnhide:(NSNotification*)note
-{
-	QZ_SetPortAlphaOpaque ();
-
-	/* save current visible surface */
-	[ self cacheImageInRect:[ _cocoa_video_data.qdview frame ] ];
-}
-
-- (void)appDidUnhide:(NSNotification*)note
-{
-	/* restore cached image, since it may not be current, post expose event too */
-	[ self restoreCachedImage ];
-
-	_cocoa_video_data.active = true;
-}
-
-
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
-{
-	/* Make our window subclass receive these application notifications */
-	[ [ NSNotificationCenter defaultCenter ] addObserver:self
-	selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ];
-
-	[ [ NSNotificationCenter defaultCenter ] addObserver:self
-	selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
-
-	[ [ NSNotificationCenter defaultCenter ] addObserver:self
-	selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
-
-	return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
-}
-
-@end
-
-@implementation OTTD_QuartzWindowDelegate
-- (BOOL)windowShouldClose:(id)sender
-{
-	HandleExitGameRequest();
-
-	return NO;
-}
-
-- (void)windowDidBecomeKey:(NSNotification*)aNotification
-{
-	_cocoa_video_data.active = true;
-}
-
-- (void)windowDidResignKey:(NSNotification*)aNotification
-{
-	_cocoa_video_data.active = false;
-}
-
-- (void)windowDidBecomeMain:(NSNotification*)aNotification
-{
-	_cocoa_video_data.active = true;
-}
-
-- (void)windowDidResignMain:(NSNotification*)aNotification
-{
-	_cocoa_video_data.active = false;
-}
-
-@end
-
-
-static void QZ_UpdateWindowPalette(uint start, uint count)
-{
-	uint i;
-
-	switch (_cocoa_video_data.device_bpp) {
-		case 32:
-			for (i = start; i < start + count; i++) {
-				uint32 clr32 = 0xff000000;
-				clr32 |= (uint32)_cur_palette[i].r << 16;
-				clr32 |= (uint32)_cur_palette[i].g << 8;
-				clr32 |= (uint32)_cur_palette[i].b;
-				_cocoa_video_data.palette32[i] = clr32;
-			}
-			break;
-		case 16:
-			for (i = start; i < start + count; i++) {
-				uint16 clr16 = 0x0000;
-				clr16 |= (uint16)((_cur_palette[i].r >> 3) & 0x1f) << 10;
-				clr16 |= (uint16)((_cur_palette[i].g >> 3) & 0x1f) << 5;
-				clr16 |= (uint16)((_cur_palette[i].b >> 3) & 0x1f);
-				_cocoa_video_data.palette16[i] = clr16;
-			}
-			break;
-	}
-
-	_cocoa_video_data.num_dirty_rects = MAX_DIRTY_RECTS;
-}
-
-static inline void QZ_WindowBlitIndexedPixelsToView32(uint left, uint top, uint right, uint bottom)
-{
-	uint32* dst = (uint32*)_cocoa_video_data.realpixels;
-	uint width = _cocoa_video_data.width;
-	uint pitch = _cocoa_video_data.pitch / 4;
-	uint x;
-	uint y;
-
-	switch (_cocoa_video_data.blitter_bpp) {
-		case 8: {
-				const uint32* pal = _cocoa_video_data.palette32;
-				const uint8*  src = (uint8*) _cocoa_video_data.pixels;
-
-				for (y = top; y < bottom; y++) {
-					for (x = left; x < right; x++) {
-						dst[y * pitch + x] = pal[src[y * width + x]];
-					}
-				}
-			}
-			break;
-		case 32: {
-				const uint32* src = (uint32*) _cocoa_video_data.pixels;
-
-				dst += top * pitch + left;
-				src += top * width + left;
-
-				for (y = top; y < bottom; y++, dst+= pitch, src+= width)
-					memcpy(dst, src, (right - left) * 4);
-			}
-			break;
-	}
-}
-
-/**
- * This function copies pixels from the screen buffer in 16bpp windowed mode. It assumes
- * that the blitter is 8bpp since the driver only supports 8 and 32 bpp blitters, and we
- * don't allow a blitter with a higer bpp than the display in windowed mode.
- *
- * @param left The x coord for the left edge of the box to blit.
- * @param top The y coord for the top edge of the box to blit.
- * @param right The x coord for the right edge of the box to blit.
- * @param bottom The y coord for the bottom edge of the box to blit.
- */
-static inline void QZ_WindowBlitIndexedPixelsToView16(uint left, uint top, uint right, uint bottom)
-{
-	const uint16* pal   = _cocoa_video_data.palette16;
-	const uint8*  src   = (uint8*) _cocoa_video_data.pixels;
-	uint16*       dst   = (uint16*)_cocoa_video_data.realpixels;
-	uint          width = _cocoa_video_data.width;
-	uint          pitch = _cocoa_video_data.pitch / 2;
-	uint x;
-	uint y;
-
-	for (y = top; y < bottom; y++) {
-		for (x = left; x < right; x++) {
-			dst[y * pitch + x] = pal[src[y * width + x]];
-		}
-	}
-}
-
-static inline void QZ_WindowBlitIndexedPixelsToView(int left, int top, int right, int bottom)
-{
-	switch (_cocoa_video_data.device_bpp) {
-		case 32: QZ_WindowBlitIndexedPixelsToView32(left, top, right, bottom); break;
-		case 16: QZ_WindowBlitIndexedPixelsToView16(left, top, right, bottom); break;
-	}
-}
-
-static bool _resize_icon[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
-	0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
-	0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
-	0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
-	0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
-	0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
-	0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
-	1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0
-};
-
-static void QZ_DrawResizeIcon()
-{
-	int xoff = _cocoa_video_data.width - 16;
-	int yoff = _cocoa_video_data.height - 16;
-	int x;
-	int y;
-
-	for (y = 0; y < 16; y++) {
-		uint16* trg16 = (uint16*)_cocoa_video_data.realpixels + (yoff + y) * _cocoa_video_data.pitch / 2 + xoff;
-		uint32* trg32 = (uint32*)_cocoa_video_data.realpixels + (yoff + y) * _cocoa_video_data.pitch / 4 + xoff;
-
-		for (x = 0; x < 16; x++, trg16++, trg32++) {
-			if (!_resize_icon[y * 16 + x]) continue;
-
-			switch (_cocoa_video_data.device_bpp) {
-				case 32: *trg32 = 0xff000000; break;
-				case 16: *trg16 = 0x0000;     break;
-			}
-		}
-	}
-}
-
-static void QZ_DrawWindow()
-{
-	int i;
-	RgnHandle dirty, temp;
-
-	/* Check if we need to do anything */
-	if (_cocoa_video_data.num_dirty_rects == 0 ||
-			[ _cocoa_video_data.window isMiniaturized ]) {
-		return;
-	}
-
-	if (_cocoa_video_data.num_dirty_rects >= MAX_DIRTY_RECTS) {
-		_cocoa_video_data.num_dirty_rects = 1;
-		_cocoa_video_data.dirty_rects[0].left = 0;
-		_cocoa_video_data.dirty_rects[0].top = 0;
-		_cocoa_video_data.dirty_rects[0].right = _cocoa_video_data.width;
-		_cocoa_video_data.dirty_rects[0].bottom = _cocoa_video_data.height;
-	}
-
-	dirty = NewRgn();
-	temp  = NewRgn();
-
-	SetEmptyRgn(dirty);
-
-	/* Build the region of dirty rectangles */
-	for (i = 0; i < _cocoa_video_data.num_dirty_rects; i++) {
-		QZ_WindowBlitIndexedPixelsToView(
-			_cocoa_video_data.dirty_rects[i].left,
-			_cocoa_video_data.dirty_rects[i].top,
-			_cocoa_video_data.dirty_rects[i].right,
-			_cocoa_video_data.dirty_rects[i].bottom
-		);
-
-		MacSetRectRgn(
-			temp,
-			_cocoa_video_data.dirty_rects[i].left,
-			_cocoa_video_data.dirty_rects[i].top,
-			_cocoa_video_data.dirty_rects[i].right,
-			_cocoa_video_data.dirty_rects[i].bottom
-		);
-		MacUnionRgn(dirty, temp, dirty);
-	}
-
-	QZ_DrawResizeIcon();
-
-	/* Flush the dirty region */
-	QDFlushPortBuffer( (OpaqueGrafPtr*) [ _cocoa_video_data.qdview qdPort ], dirty);
-	DisposeRgn(dirty);
-	DisposeRgn(temp);
-
-	_cocoa_video_data.num_dirty_rects = 0;
-}
-
-
-extern const char _openttd_revision[];
-
-static const char* QZ_SetVideoWindowed(uint width, uint height)
-{
-	char caption[50];
-	NSString *nsscaption;
-	unsigned int style;
-	NSRect contentRect;
-	BOOL isCustom = NO;
-
-	if (_cocoa_video_data.blitter_bpp > _cocoa_video_data.device_bpp) {
-		error("Cocoa: Cannot use a blitter with a higer screen depth than the display when running in windowed mode.");
-	}
-
-	if (width > _cocoa_video_data.device_width)
-		width = _cocoa_video_data.device_width;
-	if (height > _cocoa_video_data.device_height)
-		height = _cocoa_video_data.device_height;
-
-	_cocoa_video_data.width = width;
-	_cocoa_video_data.height = height;
-
-	contentRect = NSMakeRect(0, 0, width, height);
-
-	/* Check if we should completely destroy the previous mode
-	 * - If it is fullscreen
-	 */
-	if (_cocoa_video_data.isset && _cocoa_video_data.fullscreen)
-		QZ_UnsetVideoMode();
-
-	/* Check if we should recreate the window */
-	if (_cocoa_video_data.window == nil) {
-		/* Set the window style */
-		style = NSTitledWindowMask;
-		style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
-		style |= NSResizableWindowMask;
-
-		/* Manually create a window, avoids having a nib file resource */
-		_cocoa_video_data.window = [ [ OTTD_QuartzWindow alloc ]
-										initWithContentRect:contentRect
-										styleMask:style
-										backing:NSBackingStoreBuffered
-										defer:NO ];
-
-		if (_cocoa_video_data.window == nil)
-			return "Could not create the Cocoa window";
-
-		snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision);
-		nsscaption = [ [ NSString alloc ] initWithCString:caption ];
-		[ _cocoa_video_data.window setTitle:nsscaption ];
-		[ _cocoa_video_data.window setMiniwindowTitle:nsscaption ];
-		[ nsscaption release ];
-
-		[ _cocoa_video_data.window setAcceptsMouseMovedEvents:YES ];
-		[ _cocoa_video_data.window setViewsNeedDisplay:NO ];
-
-		[ _cocoa_video_data.window setDelegate: [ [ [ OTTD_QuartzWindowDelegate alloc ] init ] autorelease ] ];
-	} else {
-		/* We already have a window, just change its size */
-		if (!isCustom) {
-			[ _cocoa_video_data.window setContentSize:contentRect.size ];
-			// Ensure frame height - title bar height >= view height
-			contentRect.size.height = Clamp(height, 0, [ _cocoa_video_data.window frame ].size.height - 22 /* 22 is the height of title bar of window*/);
-			height = contentRect.size.height;
-			[ _cocoa_video_data.qdview setFrameSize:contentRect.size ];
-		}
-	}
-
-	// Update again
-	_cocoa_video_data.width = width;
-	_cocoa_video_data.height = height;
-
-	[ _cocoa_video_data.window center ];
-
-	/* Only recreate the view if it doesn't already exist */
-	if (_cocoa_video_data.qdview == nil) {
-		_cocoa_video_data.qdview = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
-		[ _cocoa_video_data.qdview setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
-		[ [ _cocoa_video_data.window contentView ] addSubview:_cocoa_video_data.qdview ];
-		[ _cocoa_video_data.qdview release ];
-		[ _cocoa_video_data.window makeKeyAndOrderFront:nil ];
-	}
-
-	CGrafPtr thePort = (OpaqueGrafPtr*) [ _cocoa_video_data.qdview qdPort ];
-
-	LockPortBits(thePort);
-	_cocoa_video_data.realpixels = GetPixBaseAddr(GetPortPixMap(thePort));
-	_cocoa_video_data.pitch = GetPixRowBytes(GetPortPixMap(thePort));
-	UnlockPortBits(thePort);
-
-	/* _cocoa_video_data.realpixels now points to the window's pixels
-	 * We want it to point to the *view's* pixels
-	 */
-	{
-		int vOffset = [ _cocoa_video_data.window frame ].size.height - [ _cocoa_video_data.qdview frame ].size.height - [ _cocoa_video_data.qdview frame ].origin.y;
-		int hOffset = [ _cocoa_video_data.qdview frame ].origin.x;
-
-		_cocoa_video_data.realpixels = (uint8*)_cocoa_video_data.realpixels + (vOffset * _cocoa_video_data.pitch) + hOffset * (_cocoa_video_data.device_bpp / 8);
-	}
-
-	free(_cocoa_video_data.pixels);
-	_cocoa_video_data.pixels = malloc(width * height * _cocoa_video_data.blitter_bpp / 8);
-	if (_cocoa_video_data.pixels == NULL) return "Failed to allocate 8-bit buffer";
-
-	_cocoa_video_data.fullscreen = false;
-
-	return NULL;
-}
-
-
-/******************************************************************************
- *                             Fullscreen mode                                *
- ******************************************************************************/
-
-/* Gamma functions to try to hide the flash from a rez switch
- * Fade the display from normal to black
- * Save gamma tables for fade back to normal
- */
-static uint32 QZ_FadeGammaOut(OTTD_QuartzGammaTable* table)
-{
-	CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE];
-	float percent;
-	int j;
-	unsigned int actual;
-
-	if (CGGetDisplayTransferByTable(
-				_cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE,
-				table->red, table->green, table->blue, &actual
-			) != CGDisplayNoErr ||
-			actual != QZ_GAMMA_TABLE_SIZE) {
-		return 1;
-	}
-
-	memcpy(redTable,   table->red,   sizeof(redTable));
-	memcpy(greenTable, table->green, sizeof(greenTable));
-	memcpy(blueTable,  table->blue,  sizeof(greenTable));
-
-	for (percent = 1.0; percent >= 0.0; percent -= 0.01) {
-		for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
-			redTable[j]   = redTable[j]   * percent;
-			greenTable[j] = greenTable[j] * percent;
-			blueTable[j]  = blueTable[j]  * percent;
-		}
-
-		if (CGSetDisplayTransferByTable(
-					_cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE,
-					redTable, greenTable, blueTable
-				) != CGDisplayNoErr) {
-			CGDisplayRestoreColorSyncSettings();
-			return 1;
-		}
-
-		CSleep(10);
-	}
-
-	return 0;
-}
-
-/* Fade the display from black to normal
- * Restore previously saved gamma values
- */
-static uint32 QZ_FadeGammaIn(const OTTD_QuartzGammaTable* table)
-{
-	CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE];
-	CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE];
-	float percent;
-	int j;
-
-	memset(redTable, 0, sizeof(redTable));
-	memset(greenTable, 0, sizeof(greenTable));
-	memset(blueTable, 0, sizeof(greenTable));
-
-	for (percent = 0.0; percent <= 1.0; percent += 0.01) {
-		for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
-			redTable[j]   = table->red[j]   * percent;
-			greenTable[j] = table->green[j] * percent;
-			blueTable[j]  = table->blue[j]  * percent;
-		}
-
-		if (CGSetDisplayTransferByTable(
-					_cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE,
-					redTable, greenTable, blueTable
-				) != CGDisplayNoErr) {
-			CGDisplayRestoreColorSyncSettings();
-			return 1;
-		}
-
-		CSleep(10);
-	}
-
-	return 0;
-}
-
-static const char* QZ_SetVideoFullScreen(int width, int height)
-{
-	const char* errstr = "QZ_SetVideoFullScreen error";
-	int exact_match;
-	CFNumberRef number;
-	int bpp;
-	int gamma_error;
-	OTTD_QuartzGammaTable gamma_table;
-	NSRect screen_rect;
-	CGError error;
-	NSPoint pt;
-
-	/* Destroy any previous mode */
-	if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
-
-	/* See if requested mode exists */
-	_cocoa_video_data.mode = CGDisplayBestModeForParameters(_cocoa_video_data.display_id, _cocoa_video_data.blitter_bpp, width, height, &exact_match);
-
-	/* If the mode wasn't an exact match, check if it has the right bpp, and update width and height */
-	if (!exact_match) {
-		number = (const __CFNumber*) CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayBitsPerPixel);
-		CFNumberGetValue(number, kCFNumberSInt32Type, &bpp);
-		if ((uint) bpp != _cocoa_video_data.blitter_bpp) {
-			errstr = "Failed to find display resolution";
-			goto ERR_NO_MATCH;
-		}
-
-		number = (const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayWidth);
-		CFNumberGetValue(number, kCFNumberSInt32Type, &width);
-
-		number = (const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayHeight);
-		CFNumberGetValue(number, kCFNumberSInt32Type, &height);
-	}
-
-	/* Fade display to zero gamma */
-	gamma_error = QZ_FadeGammaOut(&gamma_table);
-
-	/* Put up the blanking window (a window above all other windows) */
-	error = CGDisplayCapture(_cocoa_video_data.display_id);
-
-	if (CGDisplayNoErr != error) {
-		errstr = "Failed capturing display";
-		goto ERR_NO_CAPTURE;
-	}
-
-	/* Do the physical switch */
-	if (CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.mode) != CGDisplayNoErr) {
-		errstr = "Failed switching display resolution";
-		goto ERR_NO_SWITCH;
-	}
-
-	_cocoa_video_data.realpixels = CGDisplayBaseAddress(_cocoa_video_data.display_id);
-	_cocoa_video_data.pitch  = CGDisplayBytesPerRow(_cocoa_video_data.display_id);
-
-	_cocoa_video_data.width = CGDisplayPixelsWide(_cocoa_video_data.display_id);
-	_cocoa_video_data.height = CGDisplayPixelsHigh(_cocoa_video_data.display_id);
-	_cocoa_video_data.fullscreen = true;
-
-	/* Setup double-buffer emulation */
-	_cocoa_video_data.pixels = malloc(width * height * _cocoa_video_data.blitter_bpp / 8);
-	if (_cocoa_video_data.pixels == NULL) {
-		errstr = "Failed to allocate memory for double buffering";
-		goto ERR_DOUBLEBUF;
-	}
-
-	if (_cocoa_video_data.blitter_bpp == 8 && !CGDisplayCanSetPalette(_cocoa_video_data.display_id)) {
-		errstr = "Not an indexed display mode.";
-		goto ERR_NOT_INDEXED;
-	}
-
-	/* If we don't hide menu bar, it will get events and interrupt the program */
-	HideMenuBar();
-
-	/* Fade the display to original gamma */
-	if (!gamma_error) QZ_FadeGammaIn(&gamma_table);
-
-	/* There is a bug in Cocoa where NSScreen doesn't synchronize
-	 * with CGDirectDisplay, so the main screen's frame is wrong.
-	 * As a result, coordinate translation produces incorrect results.
-	 * We can hack around this bug by setting the screen rect ourselves.
-	 * This hack should be removed if/when the bug is fixed.
-	 */
-	screen_rect = NSMakeRect(0, 0, width, height);
-	[ [ NSScreen mainScreen ] setFrame:screen_rect ];
-
-	/* we're fullscreen, so flag all input states... */
-	_cocoa_video_data.active = true;
-
-
-	pt = [ NSEvent mouseLocation ];
-	pt.y = CGDisplayPixelsHigh(_cocoa_video_data.display_id) - pt.y;
-	if (QZ_MouseIsInsideView(&pt)) QZ_HideMouse();
-
-	return NULL;
-
-/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
-ERR_NOT_INDEXED:
-	free(_cocoa_video_data.pixels);
-	_cocoa_video_data.pixels = NULL;
-ERR_DOUBLEBUF:
-	CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.save_mode);
-ERR_NO_SWITCH:
-	CGReleaseAllDisplays();
-ERR_NO_CAPTURE:
-	if (!gamma_error) QZ_FadeGammaIn(&gamma_table);
-ERR_NO_MATCH:
-	return errstr;
-}
-
-
-static void QZ_UpdateFullscreenPalette(uint first_color, uint num_colors)
-{
-	CGTableCount  index;
-	CGDeviceColor color;
-
-	for (index = first_color; index < first_color+num_colors; index++) {
-		/* Clamp colors between 0.0 and 1.0 */
-		color.red   = _cur_palette[index].r / 255.0;
-		color.blue  = _cur_palette[index].b / 255.0;
-		color.green = _cur_palette[index].g / 255.0;
-
-		CGPaletteSetColorAtIndex(_cocoa_video_data.palette, color, index);
-	}
-
-	CGDisplaySetPalette(_cocoa_video_data.display_id, _cocoa_video_data.palette);
-}
-
-/* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
-static void QZ_WaitForVerticalBlank()
-{
-	/* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
-	double refreshRate;
-	double linesPerSecond;
-	double target;
-	double position;
-	double adjustment;
-	CFNumberRef refreshRateCFNumber;
-
-	refreshRateCFNumber = (const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayRefreshRate);
-	if (refreshRateCFNumber == NULL) return;
-
-	if (CFNumberGetValue(refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) == 0)
-		return;
-
-	if (refreshRate == 0) return;
-
-	linesPerSecond = refreshRate * _cocoa_video_data.height;
-	target = _cocoa_video_data.height;
-
-	/* Figure out the first delay so we start off about right */
-	position = CGDisplayBeamPosition(_cocoa_video_data.display_id);
-	if (position > target) position = 0;
-
-	adjustment = (target - position) / linesPerSecond;
-
-	CSleep((uint32)(adjustment * 1000));
-}
-
-
-static void QZ_DrawScreen()
-{
-	const uint8* src   = (uint8*) _cocoa_video_data.pixels;
-	uint8* dst         = (uint8*)_cocoa_video_data.realpixels;
-	uint pitch         = _cocoa_video_data.pitch;
-	uint width         = _cocoa_video_data.width;
-	uint num_dirty     = _cocoa_video_data.num_dirty_rects;
-	uint bytesperpixel = _cocoa_video_data.blitter_bpp / 8;
-	uint i;
-
-	/* Check if we need to do anything */
-	if (num_dirty == 0) return;
-
-	if (num_dirty >= MAX_DIRTY_RECTS) {
-		num_dirty = 1;
-		_cocoa_video_data.dirty_rects[0].left   = 0;
-		_cocoa_video_data.dirty_rects[0].top    = 0;
-		_cocoa_video_data.dirty_rects[0].right  = _cocoa_video_data.width;
-		_cocoa_video_data.dirty_rects[0].bottom = _cocoa_video_data.height;
-	}
-
-	QZ_WaitForVerticalBlank();
-	/* Build the region of dirty rectangles */
-	for (i = 0; i < num_dirty; i++) {
-		uint y      = _cocoa_video_data.dirty_rects[i].top;
-		uint left   = _cocoa_video_data.dirty_rects[i].left;
-		uint length = _cocoa_video_data.dirty_rects[i].right - left;
-		uint bottom = _cocoa_video_data.dirty_rects[i].bottom;
-
-		for (; y < bottom; y++) {
-			memcpy(dst + y * pitch + left * bytesperpixel, src + y * width * bytesperpixel + left * bytesperpixel, length * bytesperpixel);
-		}
-	}
-
-	_cocoa_video_data.num_dirty_rects = 0;
-}
-
-
-static int QZ_ListFullscreenModes(OTTDPoint* mode_list, int max_modes)
-{
-	CFIndex num_modes;
-	CFIndex i;
-	int list_size = 0;
-
-	num_modes = CFArrayGetCount(_cocoa_video_data.mode_list);
-
-	/* Build list of modes with the requested bpp */
-	for (i = 0; i < num_modes && list_size < max_modes; i++) {
-		CFDictionaryRef onemode;
-		CFNumberRef     number;
-		int bpp;
-		int intvalue;
-		bool hasMode;
-		uint16 width, height;
-
-		onemode = (const __CFDictionary*)CFArrayGetValueAtIndex(_cocoa_video_data.mode_list, i);
-		number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayBitsPerPixel);
-		CFNumberGetValue (number, kCFNumberSInt32Type, &bpp);
-
-		if ((uint) bpp != _cocoa_video_data.blitter_bpp) continue;
-
-		number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayWidth);
-		CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue);
-		width = (uint16)intvalue;
-
-		number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayHeight);
-		CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue);
-		height = (uint16)intvalue;
-
-		/* Check if mode is already in the list */
-		{
-			int i;
-			hasMode = false;
-			for (i = 0; i < list_size; i++) {
-				if (mode_list[i].x == width &&  mode_list[i].y == height) {
-					hasMode = true;
-					break;
-				}
-			}
-		}
-
-		if (hasMode) continue;
-
-		/* Add mode to the list */
-		mode_list[list_size].x = width;
-		mode_list[list_size].y = height;
-		list_size++;
-	}
-
-	/* Sort list smallest to largest */
-	{
-		int i, j;
-		for (i = 0; i < list_size; i++) {
-			for (j = 0; j < list_size-1; j++) {
-				if (mode_list[j].x > mode_list[j + 1].x || (
-							mode_list[j].x == mode_list[j + 1].x &&
-							mode_list[j].y >  mode_list[j + 1].y
-						)) {
-					uint tmpw = mode_list[j].x;
-					uint tmph = mode_list[j].y;
-
-					mode_list[j].x = mode_list[j + 1].x;
-					mode_list[j].y = mode_list[j + 1].y;
-
-					mode_list[j + 1].x = tmpw;
-					mode_list[j + 1].y = tmph;
-				}
-			}
-		}
-	}
-
-	return list_size;
-}
-
-
-/******************************************************************************
- *                             Windowed and fullscreen common code            *
- ******************************************************************************/
-
-static void QZ_UpdatePalette(uint start, uint count)
-{
-	if (_cocoa_video_data.fullscreen) {
-		QZ_UpdateFullscreenPalette(start, count);
-	} else {
-		QZ_UpdateWindowPalette(start, count);
-	}
-}
-
-static void QZ_InitPalette()
-{
-	QZ_UpdatePalette(0, 256);
-}
-
-static void QZ_Draw()
-{
-	if (_cocoa_video_data.fullscreen) {
-		QZ_DrawScreen();
-	} else {
-		QZ_DrawWindow();
-	}
-}
-
-
-static const OTTDPoint _default_resolutions[] = {
-	{ 640,  480},
-	{ 800,  600},
-	{1024,  768},
-	{1152,  864},
-	{1280,  800},
-	{1280,  960},
-	{1280, 1024},
-	{1400, 1050},
-	{1600, 1200},
-	{1680, 1050},
-	{1920, 1200}
-};
-
-static void QZ_UpdateVideoModes()
-{
-	uint i, j, count;
-	OTTDPoint modes[32];
-	const OTTDPoint *current_modes;
-
-	if (_cocoa_video_data.fullscreen) {
-		count = QZ_ListFullscreenModes(modes, 32);
-		current_modes = modes;
-	} else {
-		count = lengthof(_default_resolutions);
-		current_modes = _default_resolutions;
-	}
-
-	for (i = 0, j = 0; j < lengthof(_resolutions) && i < count; i++) {
-		if (_cocoa_video_data.fullscreen || (
-					(uint)current_modes[i].x < _cocoa_video_data.device_width &&
-					(uint)current_modes[i].y < _cocoa_video_data.device_height)
-				) {
-			_resolutions[j][0] = current_modes[i].x;
-			_resolutions[j][1] = current_modes[i].y;
-			j++;
-		}
-	}
-
-	_num_resolutions = j;
-}
-
-static void QZ_UnsetVideoMode()
-{
-	if (_cocoa_video_data.fullscreen) {
-		/* Release fullscreen resources */
-		OTTD_QuartzGammaTable gamma_table;
-		int gamma_error;
-		NSRect screen_rect;
-
-		gamma_error = QZ_FadeGammaOut(&gamma_table);
-
-		/* Restore original screen resolution/bpp */
-		CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.save_mode);
-		CGReleaseAllDisplays();
-		ShowMenuBar();
-		/* Reset the main screen's rectangle
-		 * See comment in QZ_SetVideoFullscreen for why we do this
-		 */
-		screen_rect = NSMakeRect(0,0,_cocoa_video_data.device_width,_cocoa_video_data.device_height);
-		[ [ NSScreen mainScreen ] setFrame:screen_rect ];
-
-		if (!gamma_error) QZ_FadeGammaIn(&gamma_table);
-	} else {
-		/* Release window mode resources */
-		[ _cocoa_video_data.window close ];
-		_cocoa_video_data.window = nil;
-		_cocoa_video_data.qdview = nil;
-	}
-
-	free(_cocoa_video_data.pixels);
-	_cocoa_video_data.pixels = NULL;
-
-	/* Signal successful teardown */
-	_cocoa_video_data.isset = false;
-
-	QZ_ShowMouse();
-}
-
-
-static const char* QZ_SetVideoMode(uint width, uint height, bool fullscreen)
-{
-	const char *ret;
-
-	_cocoa_video_data.issetting = true;
-	if (fullscreen) {
-		/* Setup full screen video */
-		ret = QZ_SetVideoFullScreen(width, height);
-	} else {
-		/* Setup windowed video */
-		ret = QZ_SetVideoWindowed(width, height);
-	}
-	_cocoa_video_data.issetting = false;
-	if (ret != NULL) return ret;
-
-	/* Signal successful completion (used internally) */
-	_cocoa_video_data.isset = true;
-
-	/* Tell the game that the resolution has changed */
-	_screen.width = _cocoa_video_data.width;
-	_screen.height = _cocoa_video_data.height;
-	_screen.pitch = _cocoa_video_data.width;
-
-	QZ_UpdateVideoModes();
-	GameSizeChanged();
-
-	QZ_InitPalette();
-
-	return NULL;
-}
-
-static const char* QZ_SetVideoModeAndRestoreOnFailure(uint width, uint height, bool fullscreen)
-{
-	bool wasset = _cocoa_video_data.isset;
-	uint32 oldwidth = _cocoa_video_data.width;
-	uint32 oldheight = _cocoa_video_data.height;
-	bool oldfullscreen = _cocoa_video_data.fullscreen;
-	const char *ret;
-
-	ret = QZ_SetVideoMode(width, height, fullscreen);
-	if (ret != NULL && wasset) QZ_SetVideoMode(oldwidth, oldheight, oldfullscreen);
-
-	return ret;
-}
-
-static void QZ_VideoInit()
-{
-
-	memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data));
-
-	_cocoa_video_data.blitter_bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
-	DEBUG(driver, 1, "Cocoa: Blitter bpp %d", _cocoa_video_data.blitter_bpp);
-
-	if (_cocoa_video_data.blitter_bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
-
-
-	if (_cocoa_video_data.blitter_bpp != 8 && _cocoa_video_data.blitter_bpp != 32) {
-		error("Cocoa: This video driver only supports 8 and 32 bpp blitters.");
-	}
-
-	/* Initialize the video settings; this data persists between mode switches */
-	_cocoa_video_data.display_id = kCGDirectMainDisplay;
-	_cocoa_video_data.save_mode  = CGDisplayCurrentMode(_cocoa_video_data.display_id);
-	_cocoa_video_data.mode_list  = CGDisplayAvailableModes(_cocoa_video_data.display_id);
-	_cocoa_video_data.palette    = CGPaletteCreateDefaultColorPalette();
-
-	/* Gather some information that is useful to know about the display */
-	/* Maybe this should be moved to QZ_SetVideoMode, in case this is changed after startup */
-	CFNumberGetValue(
-		(const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayBitsPerPixel),
-		kCFNumberSInt32Type, &_cocoa_video_data.device_bpp
-	);
-
-	CFNumberGetValue(
-		(const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayWidth),
-		kCFNumberSInt32Type, &_cocoa_video_data.device_width
-	);
-
-	CFNumberGetValue(
-		(const __CFNumber*)CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayHeight),
-		kCFNumberSInt32Type, &_cocoa_video_data.device_height
-	);
-
-	_cocoa_video_data.cursor_visible = true;
-
-	/* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */
-//	QZ_RegisterForSleepNotifications();
-}
-
-
-/* Convert local coordinate to window server (CoreGraphics) coordinate */
-static CGPoint QZ_PrivateLocalToCG(NSPoint* p)
-{
-	CGPoint cgp;
-
-	if (!_cocoa_video_data.fullscreen) {
-		*p = [ _cocoa_video_data.qdview convertPoint:*p toView: nil ];
-		*p = [ _cocoa_video_data.window convertBaseToScreen:*p ];
-		p->y = _cocoa_video_data.device_height - p->y;
-	}
-
-	cgp.x = p->x;
-	cgp.y = p->y;
-
-	return cgp;
-}
-
-static void QZ_WarpCursor(int x, int y)
-{
-	NSPoint p;
-	CGPoint cgp;
-
-	/* Only allow warping when in foreground */
-	if (![ NSApp isActive ]) return;
-
-	p = NSMakePoint(x, y);
-	cgp = QZ_PrivateLocalToCG(&p);
-
-	/* this is the magic call that fixes cursor "freezing" after warp */
-	CGSetLocalEventsSuppressionInterval(0.0);
-	/* Do the actual warp */
-	CGWarpMouseCursorPosition(cgp);
-
-	/* Generate the mouse moved event */
-}
-
-static void QZ_ShowMouse()
-{
-	if (!_cocoa_video_data.cursor_visible) {
-		[ NSCursor unhide ];
-		_cocoa_video_data.cursor_visible = true;
-
-		// Hide the openttd cursor when leaving the window
-		if (_cocoa_video_data.isset)
-			UndrawMouseCursor();
-		_cursor.in_window = false;
-	}
-}
-
-static void QZ_HideMouse()
-{
-	if (_cocoa_video_data.cursor_visible) {
-#ifndef _DEBUG
-		[ NSCursor hide ];
-#endif
-		_cocoa_video_data.cursor_visible = false;
-
-		// Show the openttd cursor again
-		_cursor.in_window = true;
-	}
-}
-
-
-/******************************************************************************
- *                             OS X application creation                      *
- ******************************************************************************/
-
-/* The main class of the application, the application's delegate */
-@implementation OTTDMain
-/* Called when the internal event loop has just started running */
-- (void) applicationDidFinishLaunching: (NSNotification*) note
-{
-	/* Hand off to main application code */
-	QZ_GameLoop();
-
-	/* We're done, thank you for playing */
-	[ NSApp stop:_ottd_main ];
-}
-
-/* Display the in game quit confirmation dialog */
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*) sender
-{
-
-	HandleExitGameRequest();
-
-	return NSTerminateCancel; // NSTerminateLater ?
-}
-@end
-
-static void setApplicationMenu()
-{
-	/* warning: this code is very odd */
-	NSMenu *appleMenu;
-	NSMenuItem *menuItem;
-	NSString *title;
-	NSString *appName;
-
-	appName = @"OTTD";
-	appleMenu = [[NSMenu alloc] initWithTitle:appName];
-
-	/* Add menu items */
-	title = [@"About " stringByAppendingString:appName];
-	[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
-
-	[appleMenu addItem:[NSMenuItem separatorItem]];
-
-	title = [@"Hide " stringByAppendingString:appName];
-	[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
-
-	menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
-	[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
-
-	[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
-
-	[appleMenu addItem:[NSMenuItem separatorItem]];
-
-	title = [@"Quit " stringByAppendingString:appName];
-	[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
-
-
-	/* Put menu into the menubar */
-	menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
-	[menuItem setSubmenu:appleMenu];
-	[[NSApp mainMenu] addItem:menuItem];
-
-	/* Tell the application object that this is now the application menu */
-	[NSApp setAppleMenu:appleMenu];
-
-	/* Finally give up our references to the objects */
-	[appleMenu release];
-	[menuItem release];
-}
-
-/* Create a window menu */
-static void setupWindowMenu()
-{
-	NSMenu* windowMenu;
-	NSMenuItem* windowMenuItem;
-	NSMenuItem* menuItem;
-
-	windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-
-	/* "Minimize" item */
-	menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
-	[windowMenu addItem:menuItem];
-	[menuItem release];
-
-	/* Put menu into the menubar */
-	windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
-	[windowMenuItem setSubmenu:windowMenu];
-	[[NSApp mainMenu] addItem:windowMenuItem];
-
-	/* Tell the application object that this is now the window menu */
-	[NSApp setWindowsMenu:windowMenu];
-
-	/* Finally give up our references to the objects */
-	[windowMenu release];
-	[windowMenuItem release];
-}
-
-static void setupApplication()
-{
-	CPSProcessSerNum PSN;
-
-	/* Ensure the application object is initialised */
-	[NSApplication sharedApplication];
-
-	/* Tell the dock about us */
-	if (!CPSGetCurrentProcess(&PSN) &&
-			!CPSEnableForegroundOperation(&PSN, 0x03, 0x3C, 0x2C, 0x1103) &&
-			!CPSSetFrontProcess(&PSN)) {
-		[NSApplication sharedApplication];
-	}
-
-	/* Set up the menubar */
-	[NSApp setMainMenu:[[NSMenu alloc] init]];
-	setApplicationMenu();
-	setupWindowMenu();
-
-	/* Create OTTDMain and make it the app delegate */
-	_ottd_main = [[OTTDMain alloc] init];
-	[NSApp setDelegate:_ottd_main];
-}
-
-
-/******************************************************************************
- *                             Video driver interface                         *
- ******************************************************************************/
-
-static FVideoDriver_Cocoa iFVideoDriver_Cocoa;
-
-void VideoDriver_Cocoa::Stop()
-{
-	if (!_cocoa_video_started) return;
-
-	if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
-
-	[_ottd_main release];
-
-	_cocoa_video_started = false;
-}
-
-const char *VideoDriver_Cocoa::Start(const char * const *parm)
-{
-	const char *ret;
-
-	if (_cocoa_video_started) return "Already started";
-	_cocoa_video_started = true;
-
-	memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data));
-
-	setupApplication();
-
-	/* Don't create a window or enter fullscreen if we're just going to show a dialog. */
-	if (_cocoa_video_dialog) return NULL;
-
-	QZ_VideoInit();
-
-	ret = QZ_SetVideoMode(_cur_resolution[0], _cur_resolution[1], _fullscreen);
-	if (ret != NULL) _video_driver->Stop();
-
-	return ret;
-}
-
-void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
-{
-	if (_cocoa_video_data.num_dirty_rects < MAX_DIRTY_RECTS) {
-		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].left = left;
-		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].top = top;
-		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].right = left + width;
-		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].bottom = top + height;
-	}
-	_cocoa_video_data.num_dirty_rects++;
-}
-
-void VideoDriver_Cocoa::MainLoop()
-{
-	/* Start the main event loop */
-	[NSApp run];
-}
-
-bool VideoDriver_Cocoa::ChangeResolution(int w, int h)
-{
-	const char *ret = QZ_SetVideoModeAndRestoreOnFailure((uint)w, (uint)h, _cocoa_video_data.fullscreen);
-	if (ret != NULL) {
-		DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ChangeResolution failed with message: %s", ret);
-	}
-
-	return ret == NULL;
-}
-
-void VideoDriver_Cocoa::ToggleFullscreen(bool full_screen)
-{
-	const char *ret = QZ_SetVideoModeAndRestoreOnFailure(_cocoa_video_data.width, _cocoa_video_data.height, full_screen);
-	if (ret != NULL) {
-		DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ToggleFullscreen failed with message: %s", ret);
-	}
-
-	_fullscreen = _cocoa_video_data.fullscreen;
-}
-
-
-/* This is needed since sometimes assert is called before the videodriver is initialized */
-void CocoaDialog(const char* title, const char* message, const char* buttonLabel)
-{
-	bool wasstarted;
-
-	_cocoa_video_dialog = true;
-
-	wasstarted = _cocoa_video_started;
-	if (_video_driver == NULL) {
-		setupApplication(); // Setup application before showing dialog
-	} else if (!_cocoa_video_started && _video_driver->Start(NULL) != NULL) {
-		fprintf(stderr, "%s: %s\n", title, message);
-		return;
-	}
-
-	NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil);
-
-	if (!wasstarted && _video_driver != NULL) _video_driver->Stop();
-
-	_cocoa_video_dialog = false;
-}
-
-/* This is needed since OS X application bundles do not have a
- * current directory and the data files are 'somewhere' in the bundle */
-void cocoaSetApplicationBundleDir()
-{
-	char tmp[MAXPATHLEN];
-	CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
-	if (CFURLGetFileSystemRepresentation(url, true, (unsigned char*)tmp, MAXPATHLEN)) {
-		AppendPathSeparator(tmp, lengthof(tmp));
-		_searchpaths[SP_APPLICATION_BUNDLE_DIR] = strdup(tmp);
-	} else {
-		_searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
-	}
-
-	CFRelease(url);
-}
-
-/* These are called from main() to prevent a _NSAutoreleaseNoPool error when
- * exiting before the cocoa video driver has been loaded
- */
-void cocoaSetupAutoreleasePool()
-{
-	_ottd_autorelease_pool = [[NSAutoreleasePool alloc] init];
-}
-
-void cocoaReleaseAutoreleasePool()
-{
-	[_ottd_autorelease_pool release];
-}
-
-#endif /* WITH_COCOA */