├── en.lproj ├── InfoPlist.strings ├── MoveApplication.strings └── MainMenu.xib ├── ca.lproj └── MoveApplication.strings ├── cs.lproj └── MoveApplication.strings ├── da.lproj └── MoveApplication.strings ├── de.lproj └── MoveApplication.strings ├── el.lproj └── MoveApplication.strings ├── es.lproj └── MoveApplication.strings ├── fr.lproj └── MoveApplication.strings ├── hu.lproj └── MoveApplication.strings ├── it.lproj └── MoveApplication.strings ├── ja.lproj └── MoveApplication.strings ├── ko.lproj └── MoveApplication.strings ├── mk.lproj └── MoveApplication.strings ├── nb.lproj └── MoveApplication.strings ├── nl.lproj └── MoveApplication.strings ├── pl.lproj └── MoveApplication.strings ├── pt.lproj └── MoveApplication.strings ├── ru.lproj └── MoveApplication.strings ├── sk.lproj └── MoveApplication.strings ├── sr.lproj └── MoveApplication.strings ├── sv.lproj └── MoveApplication.strings ├── tr.lproj └── MoveApplication.strings ├── pt_BR.lproj └── MoveApplication.strings ├── vi-VN.lproj └── MoveApplication.strings ├── zh_CN.lproj └── MoveApplication.strings ├── zh_TW.lproj └── MoveApplication.strings ├── LetsMove.modulemap ├── .gitignore ├── LetsMove_Prefix.pch ├── LetsMove.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── LetsMove.xcscheme └── project.pbxproj ├── LetsMove.h ├── main.m ├── LetsMoveAppDelegate.h ├── LetsMove.podspec ├── LetsMove-Info.plist ├── LetsMoveAppDelegate.m ├── LetsMove-Test-Info.plist ├── PFMoveApplication.h ├── README.md └── PFMoveApplication.m /en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ca.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/ca.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /cs.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/cs.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /da.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/da.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /de.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/de.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /el.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/el.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /en.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/en.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /es.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/es.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /fr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/fr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /hu.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/hu.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /it.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/it.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /ja.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/ja.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /ko.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/ko.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /mk.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/mk.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /nb.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/nb.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /nl.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/nl.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /pl.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/pl.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /pt.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/pt.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /ru.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/ru.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /sk.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/sk.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /sr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/sr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /sv.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/sv.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /tr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/tr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /pt_BR.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/pt_BR.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /vi-VN.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/vi-VN.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /zh_CN.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/zh_CN.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /zh_TW.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potionfactory/LetsMove/HEAD/zh_TW.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /LetsMove.modulemap: -------------------------------------------------------------------------------- 1 | framework module LetsMove { 2 | umbrella header "LetsMove.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | *.DS_Store 3 | 4 | # Xcode 5 | build 6 | *.mode* 7 | *.pbxuser 8 | xcuserdata/ 9 | project.xcworkspace/ 10 | -------------------------------------------------------------------------------- /LetsMove_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'LetsMove' target in the 'LetsMove' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /LetsMove.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LetsMove.h: -------------------------------------------------------------------------------- 1 | // 2 | // LetsMove.h 3 | // LetsMove 4 | // 5 | // Created by Matt Prowse on 14/05/2016. 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #import 10 | #import 11 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LetsMove 4 | // 5 | // Created by Andy Kim on 9/17/09. 6 | // Copyright 2009 Potion Factory LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char *argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /LetsMoveAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LetsMoveAppDelegate.h 3 | // LetsMove 4 | // 5 | // Created by Andy Kim on 9/17/09. 6 | // Copyright 2009 Potion Factory LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifdef MAC_OS_X_VERSION_10_6 12 | #define APPLICATION_DELEGATE 13 | #else 14 | #define APPLICATION_DELEGATE 15 | #endif 16 | 17 | @interface LetsMoveAppDelegate : NSObject APPLICATION_DELEGATE { 18 | IBOutlet NSWindow *window; 19 | } 20 | 21 | - (NSWindow *)window; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /LetsMove.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "LetsMove" 3 | s.version = "1.25" 4 | s.summary = "Moves a running Mac application to the /Applications directory." 5 | s.homepage = "https://github.com/potionfactory/LetsMove/" 6 | s.license = 'Public Domain' 7 | s.author = { "Andy Kim" => "andy@karelia.com" } 8 | 9 | s.platform = :osx, '10.6' 10 | 11 | s.source = { 12 | :git => "https://github.com/potionfactory/LetsMove.git", 13 | :tag => "v1.25" 14 | } 15 | 16 | s.source_files = '*.{h,m}' 17 | s.exclude_files = 'main.m', 'LetsMoveAppDelegate.{h,m}' 18 | s.public_header_files = 'PFMoveApplication.h' 19 | 20 | s.resources = '*.lproj' 21 | s.requires_arc = false 22 | end 23 | 24 | -------------------------------------------------------------------------------- /LetsMove-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.25 19 | CFBundleVersion 20 | 125 21 | NSHumanReadableCopyright 22 | Copyright © 2009–2020 Karelia Software LLC 23 | 24 | 25 | -------------------------------------------------------------------------------- /LetsMoveAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LetsMoveAppDelegate.m 3 | // LetsMove 4 | // 5 | // Created by Andy Kim on 9/17/09. 6 | // Copyright 2009 Potion Factory LLC. All rights reserved. 7 | // 8 | 9 | #import "LetsMoveAppDelegate.h" 10 | #import "PFMoveApplication.h" 11 | 12 | @implementation LetsMoveAppDelegate 13 | 14 | - (NSWindow *)window { 15 | return window; 16 | } 17 | 18 | - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { 19 | // Offer to the move the Application if necessary. 20 | // Note that if the user chooses to move the application, 21 | // this call will never return. Therefore you can suppress 22 | // any first run UI by putting it after this call. 23 | NSLog(@"applicationWillFinishlaunching: %@", aNotification); 24 | 25 | PFMoveToApplicationsFolderIfNecessary(); 26 | 27 | [window center]; 28 | [window makeKeyAndOrderFront:self]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /LetsMove-Test-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /PFMoveApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // PFMoveApplication.h, version 1.25 3 | // LetsMove 4 | // 5 | // Created by Andy Kim at Potion Factory LLC on 9/17/09 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #import 14 | 15 | /** 16 | Moves the running application to ~/Applications or /Applications if the former does not exist. 17 | After the move, it relaunches app from the new location. 18 | DOES NOT work for sandboxed applications. 19 | 20 | Call from \c NSApplication's delegate method \c -applicationWillFinishLaunching: method. */ 21 | void PFMoveToApplicationsFolderIfNecessary(void); 22 | 23 | /** 24 | Check whether an app move is currently in progress. 25 | Returns YES if LetsMove is currently in-progress trying to move the app to the Applications folder, or NO otherwise. 26 | This can be used to work around a crash with apps that terminate after last window is closed. 27 | See https://github.com/potionfactory/LetsMove/issues/64 for details. */ 28 | BOOL PFMoveIsInProgress(void); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /LetsMove.xcodeproj/xcshareddata/xcschemes/LetsMove.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LetsMove 2 | ======== 3 | 4 | A sample project that demonstrates how to move a running Mac OS X application to the Applications folder. 5 | 6 | ![Screenshot](http://i.imgur.com/euTRZiI.png) 7 | 8 | 9 | Requirements 10 | ------------ 11 | Builds and runs on Mac OS X 10.6 or higher. Does NOT support sandboxed applications. 12 | 13 | 14 | Usage 15 | ----- 16 | 17 | Option 1: 18 | 19 | Build then embed LetsMove.framework into your app. 20 | 21 | Option 2: 22 | 23 | Copy the following files into your project: 24 | 25 | - PFMoveApplication.h 26 | - PFMoveApplication.m 27 | 28 | If your project has ARC enabled, you'll want to disable ARC on the above files. You can do so by adding -fno-objc-arc compiler flag to your PFMoveApplication.m source file. See http://stackoverflow.com/questions/6646052/how-can-i-disable-arc-for-a-single-file-in-a-project/6658549#6658549 29 | 30 | If your application is localized, also copy the 'MoveApplication.string' files into your project. 31 | 32 | Link your application against Security.framework. 33 | 34 | In your app delegate's "-[applicationWillFinishLaunching:]" method, call the PFMoveToApplicationsFolderIfNecessary function at the very top. 35 | 36 | 37 | License 38 | ------- 39 | Public domain 40 | 41 | 42 | 43 | Version History 44 | --------------- 45 | 46 | * 1.25 47 | - Added Greek and Vietnamese localizations 48 | - Update project for Xcode 11.5 49 | 50 | * 1.24 51 | - Add PFMoveIsInProgress function 52 | - Update project for Xcode 9.1 53 | 54 | * 1.23 55 | - Fix localization not being used when built as a framework 56 | - Fix backwards compatibility with OS X 10.9 and earlier being broken 57 | - Make usable for Electron based apps or other apps that do not have access to the main thread dispatch queue 58 | - Update Russian localization 59 | 60 | * 1.22 61 | - Fix not deleting or trashing itself after copying to /Applications in macOS Sierra 62 | 63 | * 1.21 64 | - Support for [Carthage](https://github.com/Carthage/Carthage) added 65 | - Project now support OS X 10.6 and higher 66 | 67 | * 1.20 68 | - Support for applications bundled inside another application 69 | - Brazilian Portuguese localization slightly updated 70 | - Build warnings fixed 71 | 72 | * 1.19 73 | - Slovak localization added 74 | 75 | * 1.18 76 | - Catalan localization added 77 | 78 | * 1.17 79 | - Tranditional Chinese localization added. 80 | 81 | * 1.16 82 | - Deprecation warning that appears when minimum deployment target is set to OS X 10.10 taken care of 83 | 84 | * 1.15 85 | - Swedish localization added 86 | 87 | * 1.14 88 | - Hugarian, Serbian, and Turkish localizations added 89 | - Macedonian localization added 90 | 91 | * 1.13 92 | - Polish localization added 93 | 94 | * 1.12 95 | - Use country code based .lproj directories 96 | - Make it compile for projects that don't use precompiled headers to import AppKit.framework 97 | - Minor adjustment to Dutch localization 98 | - Warning fixes in example project 99 | 100 | * 1.11 101 | - Objective-C++ compatibility 102 | 103 | * 1.10 104 | - Fixed deprecation warnings that show up when building against the OS X 10.9 SDK. 105 | 106 | * 1.9 107 | - Removed OS X 10.4 support 108 | - Properly detect if the running app is in a disk image 109 | - Fixed a bug where if the app's name contained a quote, the app could not be moved 110 | - After a successful move, delete the application instead of moving it to the Trash. 111 | - Other fixes and improvements 112 | 113 | * 1.8 114 | - If the app is already there in the Applications folder but not writable, request authentication from user 115 | - Added Korean localization 116 | 117 | * 1.7.2 118 | - Fixed an exception that could happen. 119 | 120 | * 1.7.1 121 | - Refactoring 122 | 123 | * 1.7 124 | - Only move to ~/Appilcations directory if an app is already in there. 125 | 126 | * 1.6.3 127 | - Function calls deprecated in 10.7 no longer cause compile time warnings. 128 | - Added Simplified Chinese and European Portuguese localizations 129 | 130 | * 1.6.2 131 | - Garbage collection compatibility added 132 | - Use a new method to check if an application is already running on Mac OS X 10.6 systems or higher 133 | 134 | * 1.6.1 135 | - Use exit(0) to terminate the app before relaunching instead of [NSApp terminate:]. We don't want applicationShouldTerminate or applicationWillTerminate NSApplication delegate methods to be called, possibly introducing side effects. 136 | 137 | * 1.6 138 | - Resolve any aliases when finding the Applications directory 139 | 140 | * 1.5.2 141 | - Cleaned up the code a bit. Almost functionally equivalent to 1.5.1. 142 | 143 | * 1.5.1 144 | - Fixed a bug with clearing the quarantine file attribute on Mac OS X 10.5 145 | 146 | * 1.5 147 | - Don't prompt to move the application if it has "Applications" in its path somewhere 148 | 149 | * 1.4 150 | - Mac OS X 10.5 compatibility fixes 151 | 152 | * 1.3 153 | - Fixed a rare bug in the shell script that checks to see if the app is already running 154 | - Clear quarantine flag after copying 155 | - Compile time option to show normal sized alert supress checkbox button 156 | - German, Danish, and Norwegian localizations added 157 | 158 | * 1.2 159 | - Copy application from disk image then unmount disk image 160 | - Spanish, French, Dutch, and Russian localizations 161 | 162 | * 1.1 163 | - Prefers ~/Applications over /Applications if it exists 164 | - Escape key pushes the "Do Not Move" button 165 | 166 | * 1.0 167 | - First release 168 | 169 | 170 | Code Contributors: 171 | ------------- 172 | * Andy Kim 173 | * John Brayton 174 | * Chad Sellers 175 | * Kevin LaCoste 176 | * Rasmus Andersson 177 | * Timothy J. Wood 178 | * Matt Gallagher 179 | * Whitney Young 180 | * Nick Moore 181 | * Nicholas Riley 182 | * Matt Prowse 183 | * Maxim Ananov 184 | * Charlie Stigler 185 | 186 | 187 | Translators: 188 | ------------ 189 | * Eita Hayashi (Japanese) 190 | * Gleb M. Borisov, Maxim Ananov (Russian) 191 | * Wouter Broekhof (Dutch) 192 | * Rasmus Andersson / Spotify (French and Spanish) 193 | * Markus Kirschner (German) 194 | * Fredrik Nannestad (Danish) 195 | * Georg Alexander Bøe (Norwegian) 196 | * Marco Improda (Italian) 197 | * Venj Chu (Simplified Chinese) 198 | * Sérgio Miranda (European Portuguese) 199 | * Victor Figueiredo and BR Lingo (Brazilian Portuguese) 200 | * AppLingua (Korean) 201 | * Czech X Team (Czech) 202 | * Marek Telecki (Polish) 203 | * Petar Vlahu (Macedonian) 204 | * Václav Slavík (Hungarian, Serbian, and Turkish) 205 | * Erik Vikström (Swedish) 206 | * Inndy Lin (Traditional Chinese) 207 | * aONe (Catalan) 208 | * Marek Hrusovsky (Slovak) 209 | * Sotirios Papathanasiou (Greek) 210 | * Minh-Ton (Vietnamese) 211 | 212 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 213 | -------------------------------------------------------------------------------- /PFMoveApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // PFMoveApplication.m, version 1.25 3 | // LetsMove 4 | // 5 | // Created by Andy Kim at Potion Factory LLC on 9/17/09 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #import "PFMoveApplication.h" 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | @interface LetsMove : NSObject 17 | @end 18 | 19 | @implementation LetsMove 20 | + (NSBundle *)bundle { 21 | return [NSBundle bundleForClass:self]; 22 | } 23 | @end 24 | 25 | // Strings 26 | // These are macros to be able to use custom i18n tools 27 | #define _I10NS(nsstr) NSLocalizedStringFromTableInBundle(nsstr, @"MoveApplication", [LetsMove bundle], nil) 28 | #define kStrMoveApplicationCouldNotMove _I10NS(@"Could not move to Applications folder") 29 | #define kStrMoveApplicationQuestionTitle _I10NS(@"Move to Applications folder?") 30 | #define kStrMoveApplicationQuestionTitleHome _I10NS(@"Move to Applications folder in your Home folder?") 31 | #define kStrMoveApplicationQuestionMessage _I10NS(@"I can move myself to the Applications folder if you'd like.") 32 | #define kStrMoveApplicationButtonMove _I10NS(@"Move to Applications Folder") 33 | #define kStrMoveApplicationButtonDoNotMove _I10NS(@"Do Not Move") 34 | #define kStrMoveApplicationQuestionInfoWillRequirePasswd _I10NS(@"Note that this will require an administrator password.") 35 | #define kStrMoveApplicationQuestionInfoInDownloadsFolder _I10NS(@"This will keep your Downloads folder uncluttered.") 36 | 37 | // Needs to be defined for compiling under 10.5 SDK 38 | #ifndef NSAppKitVersionNumber10_5 39 | #define NSAppKitVersionNumber10_5 949 40 | #endif 41 | 42 | // By default, we use a small control/font for the suppression button. 43 | // If you prefer to use the system default (to match your other alerts), 44 | // set this to 0. 45 | #define PFUseSmallAlertSuppressCheckbox 1 46 | 47 | 48 | static NSString *AlertSuppressKey = @"moveToApplicationsFolderAlertSuppress"; 49 | static BOOL MoveInProgress = NO; 50 | 51 | // Helper functions 52 | static NSString *PreferredInstallLocation(BOOL *isUserDirectory); 53 | static BOOL IsInApplicationsFolder(NSString *path); 54 | static BOOL IsInDownloadsFolder(NSString *path); 55 | static BOOL IsApplicationAtPathRunning(NSString *path); 56 | static BOOL IsApplicationAtPathNested(NSString *path); 57 | static NSString *ContainingDiskImageDevice(NSString *path); 58 | static BOOL Trash(NSString *path); 59 | static BOOL DeleteOrTrash(NSString *path); 60 | static BOOL AuthorizedInstall(NSString *srcPath, NSString *dstPath, BOOL *canceled); 61 | static BOOL CopyBundle(NSString *srcPath, NSString *dstPath); 62 | static NSString *ShellQuotedString(NSString *string); 63 | static void Relaunch(NSString *destinationPath); 64 | 65 | // Main worker function 66 | void PFMoveToApplicationsFolderIfNecessary(void) { 67 | 68 | // Make sure to do our work on the main thread. 69 | // Apparently Electron apps need this for things to work properly. 70 | if (![NSThread isMainThread]) { 71 | dispatch_async(dispatch_get_main_queue(), ^{ 72 | PFMoveToApplicationsFolderIfNecessary(); 73 | }); 74 | return; 75 | } 76 | 77 | // Skip if user suppressed the alert before 78 | if ([[NSUserDefaults standardUserDefaults] boolForKey:AlertSuppressKey]) return; 79 | 80 | // Path of the bundle 81 | NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; 82 | 83 | // Check if the bundle is embedded in another application 84 | BOOL isNestedApplication = IsApplicationAtPathNested(bundlePath); 85 | 86 | // Skip if the application is already in some Applications folder, 87 | // unless it's inside another app's bundle. 88 | if (IsInApplicationsFolder(bundlePath) && !isNestedApplication) return; 89 | 90 | // OK, looks like we'll need to do a move - set the status variable appropriately 91 | MoveInProgress = YES; 92 | 93 | // File Manager 94 | NSFileManager *fm = [NSFileManager defaultManager]; 95 | 96 | // Are we on a disk image? 97 | NSString *diskImageDevice = ContainingDiskImageDevice(bundlePath); 98 | 99 | // Since we are good to go, get the preferred installation directory. 100 | BOOL installToUserApplications = NO; 101 | NSString *applicationsDirectory = PreferredInstallLocation(&installToUserApplications); 102 | NSString *bundleName = [bundlePath lastPathComponent]; 103 | NSString *destinationPath = [applicationsDirectory stringByAppendingPathComponent:bundleName]; 104 | 105 | // Check if we need admin password to write to the Applications directory 106 | BOOL needAuthorization = ([fm isWritableFileAtPath:applicationsDirectory] == NO); 107 | 108 | // Check if the destination bundle is already there but not writable 109 | needAuthorization |= ([fm fileExistsAtPath:destinationPath] && ![fm isWritableFileAtPath:destinationPath]); 110 | 111 | // Setup the alert 112 | NSAlert *alert = [[[NSAlert alloc] init] autorelease]; 113 | { 114 | NSString *informativeText = nil; 115 | 116 | [alert setMessageText:(installToUserApplications ? kStrMoveApplicationQuestionTitleHome : kStrMoveApplicationQuestionTitle)]; 117 | 118 | informativeText = kStrMoveApplicationQuestionMessage; 119 | 120 | if (needAuthorization) { 121 | informativeText = [informativeText stringByAppendingString:@" "]; 122 | informativeText = [informativeText stringByAppendingString:kStrMoveApplicationQuestionInfoWillRequirePasswd]; 123 | } 124 | else if (IsInDownloadsFolder(bundlePath)) { 125 | // Don't mention this stuff if we need authentication. The informative text is long enough as it is in that case. 126 | informativeText = [informativeText stringByAppendingString:@" "]; 127 | informativeText = [informativeText stringByAppendingString:kStrMoveApplicationQuestionInfoInDownloadsFolder]; 128 | } 129 | 130 | [alert setInformativeText:informativeText]; 131 | 132 | // Add accept button 133 | [alert addButtonWithTitle:kStrMoveApplicationButtonMove]; 134 | 135 | // Add deny button 136 | NSButton *cancelButton = [alert addButtonWithTitle:kStrMoveApplicationButtonDoNotMove]; 137 | [cancelButton setKeyEquivalent:[NSString stringWithFormat:@"%C", 0x1b]]; // Escape key 138 | 139 | // Setup suppression button 140 | [alert setShowsSuppressionButton:YES]; 141 | 142 | if (PFUseSmallAlertSuppressCheckbox) { 143 | NSCell *cell = [[alert suppressionButton] cell]; 144 | [cell setControlSize:NSSmallControlSize]; 145 | [cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; 146 | } 147 | } 148 | 149 | // Activate app -- work-around for focus issues related to "scary file from internet" OS dialog. 150 | if (![NSApp isActive]) { 151 | [NSApp activateIgnoringOtherApps:YES]; 152 | } 153 | 154 | if ([alert runModal] == NSAlertFirstButtonReturn) { 155 | NSLog(@"INFO -- Moving myself to the Applications folder"); 156 | 157 | // Move 158 | if (needAuthorization) { 159 | BOOL authorizationCanceled; 160 | 161 | if (!AuthorizedInstall(bundlePath, destinationPath, &authorizationCanceled)) { 162 | if (authorizationCanceled) { 163 | NSLog(@"INFO -- Not moving because user canceled authorization"); 164 | MoveInProgress = NO; 165 | return; 166 | } 167 | else { 168 | NSLog(@"ERROR -- Could not copy myself to /Applications with authorization"); 169 | goto fail; 170 | } 171 | } 172 | } 173 | else { 174 | // If a copy already exists in the Applications folder, put it in the Trash 175 | if ([fm fileExistsAtPath:destinationPath]) { 176 | // But first, make sure that it's not running 177 | if (IsApplicationAtPathRunning(destinationPath)) { 178 | // Give the running app focus and terminate myself 179 | NSLog(@"INFO -- Switching to an already running version"); 180 | [[NSTask launchedTaskWithLaunchPath:@"/usr/bin/open" arguments:[NSArray arrayWithObject:destinationPath]] waitUntilExit]; 181 | MoveInProgress = NO; 182 | exit(0); 183 | } 184 | else { 185 | if (!Trash([applicationsDirectory stringByAppendingPathComponent:bundleName])) 186 | goto fail; 187 | } 188 | } 189 | 190 | if (!CopyBundle(bundlePath, destinationPath)) { 191 | NSLog(@"ERROR -- Could not copy myself to %@", destinationPath); 192 | goto fail; 193 | } 194 | } 195 | 196 | // Trash the original app. It's okay if this fails. 197 | // NOTE: This final delete does not work if the source bundle is in a network mounted volume. 198 | // Calling rm or file manager's delete method doesn't work either. It's unlikely to happen 199 | // but it'd be great if someone could fix this. 200 | if (!isNestedApplication && diskImageDevice == nil && !DeleteOrTrash(bundlePath)) { 201 | NSLog(@"WARNING -- Could not delete application after moving it to Applications folder"); 202 | } 203 | 204 | // Relaunch. 205 | Relaunch(destinationPath); 206 | 207 | // Launched from within a disk image? -- unmount (if no files are open after 5 seconds, 208 | // otherwise leave it mounted). 209 | if (diskImageDevice && !isNestedApplication) { 210 | NSString *script = [NSString stringWithFormat:@"(/bin/sleep 5 && /usr/bin/hdiutil detach %@) &", ShellQuotedString(diskImageDevice)]; 211 | [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 212 | } 213 | 214 | MoveInProgress = NO; 215 | exit(0); 216 | } 217 | // Save the alert suppress preference if checked 218 | else if ([[alert suppressionButton] state] == NSOnState) { 219 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:AlertSuppressKey]; 220 | } 221 | 222 | MoveInProgress = NO; 223 | return; 224 | 225 | fail: 226 | { 227 | // Show failure message 228 | alert = [[[NSAlert alloc] init] autorelease]; 229 | [alert setMessageText:kStrMoveApplicationCouldNotMove]; 230 | [alert runModal]; 231 | MoveInProgress = NO; 232 | } 233 | } 234 | 235 | BOOL PFMoveIsInProgress() { 236 | return MoveInProgress; 237 | } 238 | 239 | #pragma mark - 240 | #pragma mark Helper Functions 241 | 242 | static NSString *PreferredInstallLocation(BOOL *isUserDirectory) { 243 | // Return the preferred install location. 244 | // Assume that if the user has a ~/Applications folder, they'd prefer their 245 | // applications to go there. 246 | 247 | NSFileManager *fm = [NSFileManager defaultManager]; 248 | 249 | NSArray *userApplicationsDirs = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES); 250 | 251 | if ([userApplicationsDirs count] > 0) { 252 | NSString *userApplicationsDir = [userApplicationsDirs objectAtIndex:0]; 253 | BOOL isDirectory; 254 | 255 | if ([fm fileExistsAtPath:userApplicationsDir isDirectory:&isDirectory] && isDirectory) { 256 | // User Applications directory exists. Get the directory contents. 257 | NSArray *contents = [fm contentsOfDirectoryAtPath:userApplicationsDir error:NULL]; 258 | 259 | // Check if there is at least one ".app" inside the directory. 260 | for (NSString *contentsPath in contents) { 261 | if ([[contentsPath pathExtension] isEqualToString:@"app"]) { 262 | if (isUserDirectory) *isUserDirectory = YES; 263 | return [userApplicationsDir stringByResolvingSymlinksInPath]; 264 | } 265 | } 266 | } 267 | } 268 | 269 | // No user Applications directory in use. Return the machine local Applications directory 270 | if (isUserDirectory) *isUserDirectory = NO; 271 | 272 | return [[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSLocalDomainMask, YES) lastObject] stringByResolvingSymlinksInPath]; 273 | } 274 | 275 | static BOOL IsInApplicationsFolder(NSString *path) { 276 | // Check all the normal Application directories 277 | NSArray *applicationDirs = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES); 278 | for (NSString *appDir in applicationDirs) { 279 | if ([path hasPrefix:appDir]) return YES; 280 | } 281 | 282 | // Also, handle the case that the user has some other Application directory (perhaps on a separate data partition). 283 | if ([[path pathComponents] containsObject:@"Applications"]) return YES; 284 | 285 | return NO; 286 | } 287 | 288 | static BOOL IsInDownloadsFolder(NSString *path) { 289 | NSArray *downloadDirs = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSAllDomainsMask, YES); 290 | for (NSString *downloadsDirPath in downloadDirs) { 291 | if ([path hasPrefix:downloadsDirPath]) return YES; 292 | } 293 | 294 | return NO; 295 | } 296 | 297 | static BOOL IsApplicationAtPathRunning(NSString *bundlePath) { 298 | bundlePath = [bundlePath stringByStandardizingPath]; 299 | 300 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 301 | // Use the new API on 10.6 or higher to determine if the app is already running 302 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 303 | for (NSRunningApplication *runningApplication in [[NSWorkspace sharedWorkspace] runningApplications]) { 304 | NSString *runningAppBundlePath = [[[runningApplication bundleURL] path] stringByStandardizingPath]; 305 | if ([runningAppBundlePath isEqualToString:bundlePath]) { 306 | return YES; 307 | } 308 | } 309 | return NO; 310 | } 311 | #endif 312 | // Use the shell to determine if the app is already running on systems 10.5 or lower 313 | NSString *script = [NSString stringWithFormat:@"/bin/ps ax -o comm | /usr/bin/grep %@/ | /usr/bin/grep -v grep >/dev/null", ShellQuotedString(bundlePath)]; 314 | NSTask *task = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 315 | [task waitUntilExit]; 316 | 317 | // If the task terminated with status 0, it means that the final grep produced 1 or more lines of output. 318 | // Which means that the app is already running 319 | return [task terminationStatus] == 0; 320 | } 321 | 322 | static BOOL IsApplicationAtPathNested(NSString *path) { 323 | NSString *containingPath = [path stringByDeletingLastPathComponent]; 324 | 325 | NSArray *components = [containingPath pathComponents]; 326 | for (NSString *component in components) { 327 | if ([[component pathExtension] isEqualToString:@"app"]) { 328 | return YES; 329 | } 330 | } 331 | 332 | return NO; 333 | } 334 | 335 | static NSString *ContainingDiskImageDevice(NSString *path) { 336 | NSString *containingPath = [path stringByDeletingLastPathComponent]; 337 | 338 | struct statfs fs; 339 | if (statfs([containingPath fileSystemRepresentation], &fs) || (fs.f_flags & MNT_ROOTFS)) 340 | return nil; 341 | 342 | NSString *device = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:fs.f_mntfromname length:strlen(fs.f_mntfromname)]; 343 | 344 | NSTask *hdiutil = [[[NSTask alloc] init] autorelease]; 345 | [hdiutil setLaunchPath:@"/usr/bin/hdiutil"]; 346 | [hdiutil setArguments:[NSArray arrayWithObjects:@"info", @"-plist", nil]]; 347 | [hdiutil setStandardOutput:[NSPipe pipe]]; 348 | [hdiutil launch]; 349 | [hdiutil waitUntilExit]; 350 | 351 | NSData *data = [[[hdiutil standardOutput] fileHandleForReading] readDataToEndOfFile]; 352 | NSDictionary *info = nil; 353 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 354 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 355 | info = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:NULL]; 356 | } 357 | else { 358 | #endif 359 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 360 | info = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL]; 361 | #endif 362 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 363 | } 364 | #endif 365 | 366 | if (![info isKindOfClass:[NSDictionary class]]) return nil; 367 | 368 | NSArray *images = (NSArray *)[info objectForKey:@"images"]; 369 | if (![images isKindOfClass:[NSArray class]]) return nil; 370 | 371 | for (NSDictionary *image in images) { 372 | if (![image isKindOfClass:[NSDictionary class]]) return nil; 373 | 374 | id systemEntities = [image objectForKey:@"system-entities"]; 375 | if (![systemEntities isKindOfClass:[NSArray class]]) return nil; 376 | 377 | for (NSDictionary *systemEntity in systemEntities) { 378 | if (![systemEntity isKindOfClass:[NSDictionary class]]) return nil; 379 | 380 | NSString *devEntry = [systemEntity objectForKey:@"dev-entry"]; 381 | if (![devEntry isKindOfClass:[NSString class]]) return nil; 382 | 383 | if ([devEntry isEqualToString:device]) 384 | return device; 385 | } 386 | } 387 | 388 | return nil; 389 | } 390 | 391 | static BOOL Trash(NSString *path) { 392 | BOOL result = NO; 393 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 394 | if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_8) { 395 | result = [[NSFileManager defaultManager] trashItemAtURL:[NSURL fileURLWithPath:path] resultingItemURL:NULL error:NULL]; 396 | } 397 | #endif 398 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 399 | if (!result) { 400 | result = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation 401 | source:[path stringByDeletingLastPathComponent] 402 | destination:@"" 403 | files:[NSArray arrayWithObject:[path lastPathComponent]] 404 | tag:NULL]; 405 | } 406 | #endif 407 | 408 | // As a last resort try trashing with AppleScript. 409 | // This allows us to trash the app in macOS Sierra even when the app is running inside 410 | // an app translocation image. 411 | if (!result) { 412 | NSAppleScript *appleScript = [[[NSAppleScript alloc] initWithSource: 413 | [NSString stringWithFormat:@"\ 414 | set theFile to POSIX file \"%@\" \n\ 415 | tell application \"Finder\" \n\ 416 | move theFile to trash \n\ 417 | end tell", path]] autorelease]; 418 | NSDictionary *errorDict = nil; 419 | NSAppleEventDescriptor *scriptResult = [appleScript executeAndReturnError:&errorDict]; 420 | if (scriptResult == nil) { 421 | NSLog(@"Trash AppleScript error: %@", errorDict); 422 | } 423 | result = (scriptResult != nil); 424 | } 425 | 426 | if (!result) { 427 | NSLog(@"ERROR -- Could not trash '%@'", path); 428 | } 429 | 430 | return result; 431 | } 432 | 433 | static BOOL DeleteOrTrash(NSString *path) { 434 | NSError *error; 435 | 436 | if ([[NSFileManager defaultManager] removeItemAtPath:path error:&error]) { 437 | return YES; 438 | } 439 | else { 440 | // Don't log warning if on Sierra and running inside App Translocation path 441 | if ([path rangeOfString:@"/AppTranslocation/"].location == NSNotFound) 442 | NSLog(@"WARNING -- Could not delete '%@': %@", path, [error localizedDescription]); 443 | 444 | return Trash(path); 445 | } 446 | } 447 | 448 | static BOOL AuthorizedInstall(NSString *srcPath, NSString *dstPath, BOOL *canceled) { 449 | if (canceled) *canceled = NO; 450 | 451 | // Make sure that the destination path is an app bundle. We're essentially running 'sudo rm -rf' 452 | // so we really don't want to fuck this up. 453 | if (![[dstPath pathExtension] isEqualToString:@"app"]) return NO; 454 | 455 | // Do some more checks 456 | if ([[dstPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return NO; 457 | if ([[srcPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return NO; 458 | 459 | int pid, status; 460 | AuthorizationRef myAuthorizationRef; 461 | 462 | // Get the authorization 463 | OSStatus err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &myAuthorizationRef); 464 | if (err != errAuthorizationSuccess) return NO; 465 | 466 | AuthorizationItem myItems = {kAuthorizationRightExecute, 0, NULL, 0}; 467 | AuthorizationRights myRights = {1, &myItems}; 468 | AuthorizationFlags myFlags = (AuthorizationFlags)(kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize); 469 | 470 | err = AuthorizationCopyRights(myAuthorizationRef, &myRights, NULL, myFlags, NULL); 471 | if (err != errAuthorizationSuccess) { 472 | if (err == errAuthorizationCanceled && canceled) 473 | *canceled = YES; 474 | goto fail; 475 | } 476 | 477 | static OSStatus (*security_AuthorizationExecuteWithPrivileges)(AuthorizationRef authorization, const char *pathToTool, 478 | AuthorizationFlags options, char * const *arguments, 479 | FILE **communicationsPipe) = NULL; 480 | if (!security_AuthorizationExecuteWithPrivileges) { 481 | // On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want to still use it since there's no 482 | // good alternative (without requiring code signing). We'll look up the function through dyld and fail 483 | // if it is no longer accessible. If Apple removes the function entirely this will fail gracefully. If 484 | // they keep the function and throw some sort of exception, this won't fail gracefully, but that's a 485 | // risk we'll have to take for now. 486 | security_AuthorizationExecuteWithPrivileges = (OSStatus (*)(AuthorizationRef, const char*, 487 | AuthorizationFlags, char* const*, 488 | FILE **)) dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges"); 489 | } 490 | if (!security_AuthorizationExecuteWithPrivileges) goto fail; 491 | 492 | // Delete the destination 493 | { 494 | char *args[] = {"-rf", (char *)[dstPath fileSystemRepresentation], NULL}; 495 | err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/rm", kAuthorizationFlagDefaults, args, NULL); 496 | if (err != errAuthorizationSuccess) goto fail; 497 | 498 | // Wait until it's done 499 | pid = wait(&status); 500 | if (pid == -1 || !WIFEXITED(status)) goto fail; // We don't care about exit status as the destination most likely does not exist 501 | } 502 | 503 | // Copy 504 | { 505 | char *args[] = {"-pR", (char *)[srcPath fileSystemRepresentation], (char *)[dstPath fileSystemRepresentation], NULL}; 506 | err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/cp", kAuthorizationFlagDefaults, args, NULL); 507 | if (err != errAuthorizationSuccess) goto fail; 508 | 509 | // Wait until it's done 510 | pid = wait(&status); 511 | if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) goto fail; 512 | } 513 | 514 | AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDefaults); 515 | return YES; 516 | 517 | fail: 518 | AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDefaults); 519 | return NO; 520 | } 521 | 522 | static BOOL CopyBundle(NSString *srcPath, NSString *dstPath) { 523 | NSFileManager *fm = [NSFileManager defaultManager]; 524 | NSError *error = nil; 525 | 526 | if ([fm copyItemAtPath:srcPath toPath:dstPath error:&error]) { 527 | return YES; 528 | } 529 | else { 530 | NSLog(@"ERROR -- Could not copy '%@' to '%@' (%@)", srcPath, dstPath, error); 531 | return NO; 532 | } 533 | } 534 | 535 | static NSString *ShellQuotedString(NSString *string) { 536 | return [NSString stringWithFormat:@"'%@'", [string stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]]; 537 | } 538 | 539 | static void Relaunch(NSString *destinationPath) { 540 | // The shell script waits until the original app process terminates. 541 | // This is done so that the relaunched app opens as the front-most app. 542 | int pid = [[NSProcessInfo processInfo] processIdentifier]; 543 | 544 | // Command run just before running open /final/path 545 | NSString *preOpenCmd = @""; 546 | 547 | NSString *quotedDestinationPath = ShellQuotedString(destinationPath); 548 | 549 | // OS X >=10.5: 550 | // Before we launch the new app, clear xattr:com.apple.quarantine to avoid 551 | // duplicate "scary file from the internet" dialog. 552 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 553 | // Add the -r flag on 10.6 554 | preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d -r com.apple.quarantine %@", quotedDestinationPath]; 555 | } 556 | else { 557 | preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d com.apple.quarantine %@", quotedDestinationPath]; 558 | } 559 | 560 | NSString *script = [NSString stringWithFormat:@"(while /bin/kill -0 %d >&/dev/null; do /bin/sleep 0.1; done; %@; /usr/bin/open %@) &", pid, preOpenCmd, quotedDestinationPath]; 561 | 562 | [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 563 | } 564 | -------------------------------------------------------------------------------- /LetsMove.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 256AC3DA0F4B6AC300CF3369 /* LetsMoveAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* LetsMoveAppDelegate.m */; }; 11 | 50223BEB1E1D90F800619DEA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F146F82F1CE7097500233A9B /* Cocoa.framework */; }; 12 | 50223BEC1E1D90FA00619DEA /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F146F8311CE7097800233A9B /* Security.framework */; }; 13 | 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 14 | A120E7F810630B160045BE3F /* PFMoveApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = A120E7F710630B160045BE3F /* PFMoveApplication.m */; }; 15 | A17CADEB192F7E14008A209F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A17CADE5192F7E14008A209F /* InfoPlist.strings */; }; 16 | A17CADEC192F7E14008A209F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A17CADE7192F7E14008A209F /* MainMenu.xib */; }; 17 | A17CADED192F7E14008A209F /* MoveApplication.strings in Resources */ = {isa = PBXBuildFile; fileRef = A17CADE9192F7E14008A209F /* MoveApplication.strings */; }; 18 | F146F8301CE7097500233A9B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F146F82F1CE7097500233A9B /* Cocoa.framework */; }; 19 | F146F8321CE7097800233A9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F146F8311CE7097800233A9B /* Security.framework */; }; 20 | F146F8331CE7124100233A9B /* MoveApplication.strings in Resources */ = {isa = PBXBuildFile; fileRef = A17CADE9192F7E14008A209F /* MoveApplication.strings */; }; 21 | F146F8341CE7125900233A9B /* PFMoveApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = A120E7F710630B160045BE3F /* PFMoveApplication.m */; }; 22 | F146F8391CE7167F00233A9B /* PFMoveApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = A120E7F610630B160045BE3F /* PFMoveApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23 | F146F83C1CE71DAF00233A9B /* LetsMove.h in Headers */ = {isa = PBXBuildFile; fileRef = F146F83B1CE71D9700233A9B /* LetsMove.h */; settings = {ATTRIBUTES = (Public, ); }; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 01F3187C242381EF007E0E18 /* vi-VN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "vi-VN"; path = "vi-VN.lproj/MoveApplication.strings"; sourceTree = ""; }; 28 | 256AC3D80F4B6AC300CF3369 /* LetsMoveAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LetsMoveAppDelegate.h; sourceTree = ""; }; 29 | 256AC3D90F4B6AC300CF3369 /* LetsMoveAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LetsMoveAppDelegate.m; sourceTree = ""; }; 30 | 256AC3F00F4B6AF500CF3369 /* LetsMove_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LetsMove_Prefix.pch; sourceTree = ""; }; 31 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | 8D1107310486CEB800E47090 /* LetsMove-Test-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "LetsMove-Test-Info.plist"; sourceTree = ""; }; 33 | 8D1107320486CEB800E47090 /* LetsMove Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LetsMove Test.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | A120E7F610630B160045BE3F /* PFMoveApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFMoveApplication.h; sourceTree = ""; }; 35 | A120E7F710630B160045BE3F /* PFMoveApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFMoveApplication.m; sourceTree = ""; }; 36 | A1339024192F8183009ABCE2 /* cs */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/MoveApplication.strings; sourceTree = ""; }; 37 | A178554A24B74D830036CB0A /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/MoveApplication.strings; sourceTree = ""; }; 38 | A17CADE6192F7E14008A209F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 39 | A17CADE8192F7E14008A209F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 40 | A17CADEA192F7E14008A209F /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MoveApplication.strings; sourceTree = ""; }; 41 | A17ED68F1A00BA8B0032BA5B /* sv */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/MoveApplication.strings; sourceTree = ""; }; 42 | A19B38C1192F81C200F1CCA3 /* da */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/MoveApplication.strings; sourceTree = ""; }; 43 | A19B38C2192F81D400F1CCA3 /* de */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/MoveApplication.strings; sourceTree = ""; }; 44 | A19B38C3192F81DD00F1CCA3 /* es */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MoveApplication.strings; sourceTree = ""; }; 45 | A19B38C4192F81E200F1CCA3 /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/MoveApplication.strings; sourceTree = ""; }; 46 | A19B38C5192F81E700F1CCA3 /* it */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/MoveApplication.strings; sourceTree = ""; }; 47 | A19B38C6192F81ED00F1CCA3 /* ja */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/MoveApplication.strings; sourceTree = ""; }; 48 | A19B38C7192F81F100F1CCA3 /* ko */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/MoveApplication.strings; sourceTree = ""; }; 49 | A19B38C8192F81F700F1CCA3 /* nb */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/MoveApplication.strings; sourceTree = ""; }; 50 | A19B38C9192F81FC00F1CCA3 /* nl */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/MoveApplication.strings; sourceTree = ""; }; 51 | A19B38CA192F820200F1CCA3 /* pt_BR */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = pt_BR; path = pt_BR.lproj/MoveApplication.strings; sourceTree = ""; }; 52 | A19B38CB192F820900F1CCA3 /* pt */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/MoveApplication.strings; sourceTree = ""; }; 53 | A19B38CC192F820E00F1CCA3 /* ru */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/MoveApplication.strings; sourceTree = ""; }; 54 | A19B38CD192F821300F1CCA3 /* zh_CN */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = zh_CN; path = zh_CN.lproj/MoveApplication.strings; sourceTree = ""; }; 55 | A19B38CD192F821800F1CCA3 /* zh_TW */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = zh_TW; path = zh_TW.lproj/MoveApplication.strings; sourceTree = ""; }; 56 | A1A4C5A8106760B100AF3142 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 57 | B2A84660197EAB71008A4ACA /* hu */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/MoveApplication.strings; sourceTree = ""; }; 58 | B2A84661197EAB79008A4ACA /* tr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/MoveApplication.strings; sourceTree = ""; }; 59 | B2A84662197EAB85008A4ACA /* sr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/MoveApplication.strings; sourceTree = ""; }; 60 | B5B5D108198940DF0074DBCE /* pl */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/MoveApplication.strings; sourceTree = ""; }; 61 | C3A14200EF754221ACE32119 /* mk */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = mk; path = mk.lproj/MoveApplication.strings; sourceTree = ""; }; 62 | D2CC8CA81B90F10700F763DF /* sk */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/MoveApplication.strings; sourceTree = ""; }; 63 | F146F8271CE7094400233A9B /* LetsMove.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LetsMove.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | F146F82F1CE7097500233A9B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 65 | F146F8311CE7097800233A9B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 66 | F146F8381CE7164D00233A9B /* LetsMove.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = LetsMove.modulemap; sourceTree = ""; }; 67 | F146F83A1CE71D8A00233A9B /* LetsMove-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LetsMove-Info.plist"; sourceTree = ""; }; 68 | F146F83B1CE71D9700233A9B /* LetsMove.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LetsMove.h; sourceTree = ""; }; 69 | F7846CE41A9F83E100BFAF88 /* ca */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/MoveApplication.strings; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 8D11072E0486CEB800E47090 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 50223BEC1E1D90FA00619DEA /* Security.framework in Frameworks */, 78 | 50223BEB1E1D90F800619DEA /* Cocoa.framework in Frameworks */, 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | F146F8231CE7094400233A9B /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | F146F8321CE7097800233A9B /* Security.framework in Frameworks */, 87 | F146F8301CE7097500233A9B /* Cocoa.framework in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 080E96DDFE201D6D7F000001 /* Classes */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | A120E7F610630B160045BE3F /* PFMoveApplication.h */, 98 | A120E7F710630B160045BE3F /* PFMoveApplication.m */, 99 | 256AC3D80F4B6AC300CF3369 /* LetsMoveAppDelegate.h */, 100 | 256AC3D90F4B6AC300CF3369 /* LetsMoveAppDelegate.m */, 101 | ); 102 | name = Classes; 103 | sourceTree = ""; 104 | }; 105 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 8D1107320486CEB800E47090 /* LetsMove Test.app */, 109 | F146F8271CE7094400233A9B /* LetsMove.framework */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | 29B97314FDCFA39411CA2CEA /* LetsMove */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | A1A4C5A8106760B100AF3142 /* README.md */, 118 | 080E96DDFE201D6D7F000001 /* Classes */, 119 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 120 | 29B97317FDCFA39411CA2CEA /* Resources */, 121 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 122 | 19C28FACFE9D520D11CA2CBB /* Products */, 123 | ); 124 | name = LetsMove; 125 | sourceTree = ""; 126 | usesTabs = 1; 127 | }; 128 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | F146F83B1CE71D9700233A9B /* LetsMove.h */, 132 | 256AC3F00F4B6AF500CF3369 /* LetsMove_Prefix.pch */, 133 | 29B97316FDCFA39411CA2CEA /* main.m */, 134 | ); 135 | name = "Other Sources"; 136 | sourceTree = ""; 137 | }; 138 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | F146F83A1CE71D8A00233A9B /* LetsMove-Info.plist */, 142 | 8D1107310486CEB800E47090 /* LetsMove-Test-Info.plist */, 143 | F146F8381CE7164D00233A9B /* LetsMove.modulemap */, 144 | A17CADE5192F7E14008A209F /* InfoPlist.strings */, 145 | A17CADE7192F7E14008A209F /* MainMenu.xib */, 146 | A17CADE9192F7E14008A209F /* MoveApplication.strings */, 147 | ); 148 | name = Resources; 149 | sourceTree = ""; 150 | }; 151 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | F146F8311CE7097800233A9B /* Security.framework */, 155 | F146F82F1CE7097500233A9B /* Cocoa.framework */, 156 | ); 157 | name = Frameworks; 158 | sourceTree = ""; 159 | }; 160 | /* End PBXGroup section */ 161 | 162 | /* Begin PBXHeadersBuildPhase section */ 163 | F146F8241CE7094400233A9B /* Headers */ = { 164 | isa = PBXHeadersBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | F146F83C1CE71DAF00233A9B /* LetsMove.h in Headers */, 168 | F146F8391CE7167F00233A9B /* PFMoveApplication.h in Headers */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXHeadersBuildPhase section */ 173 | 174 | /* Begin PBXNativeTarget section */ 175 | 8D1107260486CEB800E47090 /* LetsMove Test */ = { 176 | isa = PBXNativeTarget; 177 | buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "LetsMove Test" */; 178 | buildPhases = ( 179 | 8D11072C0486CEB800E47090 /* Sources */, 180 | 8D11072E0486CEB800E47090 /* Frameworks */, 181 | 8D1107290486CEB800E47090 /* Resources */, 182 | ); 183 | buildRules = ( 184 | ); 185 | dependencies = ( 186 | ); 187 | name = "LetsMove Test"; 188 | productInstallPath = "$(HOME)/Applications"; 189 | productName = LetsMove; 190 | productReference = 8D1107320486CEB800E47090 /* LetsMove Test.app */; 191 | productType = "com.apple.product-type.application"; 192 | }; 193 | F146F8261CE7094400233A9B /* LetsMove */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = F146F82C1CE7094400233A9B /* Build configuration list for PBXNativeTarget "LetsMove" */; 196 | buildPhases = ( 197 | F146F8221CE7094400233A9B /* Sources */, 198 | F146F8231CE7094400233A9B /* Frameworks */, 199 | F146F8241CE7094400233A9B /* Headers */, 200 | F146F8251CE7094400233A9B /* Resources */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | ); 206 | name = LetsMove; 207 | productName = LetsMove; 208 | productReference = F146F8271CE7094400233A9B /* LetsMove.framework */; 209 | productType = "com.apple.product-type.framework"; 210 | }; 211 | /* End PBXNativeTarget section */ 212 | 213 | /* Begin PBXProject section */ 214 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 215 | isa = PBXProject; 216 | attributes = { 217 | LastUpgradeCheck = 1150; 218 | TargetAttributes = { 219 | F146F8261CE7094400233A9B = { 220 | CreatedOnToolsVersion = 7.3.1; 221 | }; 222 | }; 223 | }; 224 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "LetsMove" */; 225 | compatibilityVersion = "Xcode 3.2"; 226 | developmentRegion = en; 227 | hasScannedForEncodings = 1; 228 | knownRegions = ( 229 | ko, 230 | nb, 231 | cs, 232 | en, 233 | da, 234 | de, 235 | es, 236 | fr, 237 | it, 238 | ja, 239 | nl, 240 | pt_BR, 241 | pt, 242 | ru, 243 | zh_CN, 244 | zh_TW, 245 | pl, 246 | hu, 247 | tr, 248 | sr, 249 | sv, 250 | ca, 251 | sk, 252 | mk, 253 | "vi-VN", 254 | el, 255 | ); 256 | mainGroup = 29B97314FDCFA39411CA2CEA /* LetsMove */; 257 | projectDirPath = ""; 258 | projectRoot = ""; 259 | targets = ( 260 | 8D1107260486CEB800E47090 /* LetsMove Test */, 261 | F146F8261CE7094400233A9B /* LetsMove */, 262 | ); 263 | }; 264 | /* End PBXProject section */ 265 | 266 | /* Begin PBXResourcesBuildPhase section */ 267 | 8D1107290486CEB800E47090 /* Resources */ = { 268 | isa = PBXResourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | A17CADED192F7E14008A209F /* MoveApplication.strings in Resources */, 272 | A17CADEB192F7E14008A209F /* InfoPlist.strings in Resources */, 273 | A17CADEC192F7E14008A209F /* MainMenu.xib in Resources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | F146F8251CE7094400233A9B /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | F146F8331CE7124100233A9B /* MoveApplication.strings in Resources */, 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | /* End PBXResourcesBuildPhase section */ 286 | 287 | /* Begin PBXSourcesBuildPhase section */ 288 | 8D11072C0486CEB800E47090 /* Sources */ = { 289 | isa = PBXSourcesBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | 8D11072D0486CEB800E47090 /* main.m in Sources */, 293 | 256AC3DA0F4B6AC300CF3369 /* LetsMoveAppDelegate.m in Sources */, 294 | A120E7F810630B160045BE3F /* PFMoveApplication.m in Sources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | F146F8221CE7094400233A9B /* Sources */ = { 299 | isa = PBXSourcesBuildPhase; 300 | buildActionMask = 2147483647; 301 | files = ( 302 | F146F8341CE7125900233A9B /* PFMoveApplication.m in Sources */, 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | /* End PBXSourcesBuildPhase section */ 307 | 308 | /* Begin PBXVariantGroup section */ 309 | A17CADE5192F7E14008A209F /* InfoPlist.strings */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | A17CADE6192F7E14008A209F /* en */, 313 | ); 314 | name = InfoPlist.strings; 315 | sourceTree = ""; 316 | }; 317 | A17CADE7192F7E14008A209F /* MainMenu.xib */ = { 318 | isa = PBXVariantGroup; 319 | children = ( 320 | A17CADE8192F7E14008A209F /* en */, 321 | ); 322 | name = MainMenu.xib; 323 | sourceTree = ""; 324 | }; 325 | A17CADE9192F7E14008A209F /* MoveApplication.strings */ = { 326 | isa = PBXVariantGroup; 327 | children = ( 328 | A17CADEA192F7E14008A209F /* en */, 329 | A19B38CD192F821300F1CCA3 /* zh_CN */, 330 | A19B38CD192F821800F1CCA3 /* zh_TW */, 331 | A1339024192F8183009ABCE2 /* cs */, 332 | A19B38C1192F81C200F1CCA3 /* da */, 333 | A19B38C9192F81FC00F1CCA3 /* nl */, 334 | A19B38C4192F81E200F1CCA3 /* fr */, 335 | A19B38C2192F81D400F1CCA3 /* de */, 336 | A19B38C5192F81E700F1CCA3 /* it */, 337 | A19B38C6192F81ED00F1CCA3 /* ja */, 338 | A19B38C7192F81F100F1CCA3 /* ko */, 339 | A19B38C8192F81F700F1CCA3 /* nb */, 340 | A19B38CB192F820900F1CCA3 /* pt */, 341 | A19B38CA192F820200F1CCA3 /* pt_BR */, 342 | A19B38CC192F820E00F1CCA3 /* ru */, 343 | A19B38C3192F81DD00F1CCA3 /* es */, 344 | B5B5D108198940DF0074DBCE /* pl */, 345 | B2A84660197EAB71008A4ACA /* hu */, 346 | B2A84661197EAB79008A4ACA /* tr */, 347 | B2A84662197EAB85008A4ACA /* sr */, 348 | C3A14200EF754221ACE32119 /* mk */, 349 | A17ED68F1A00BA8B0032BA5B /* sv */, 350 | F7846CE41A9F83E100BFAF88 /* ca */, 351 | D2CC8CA81B90F10700F763DF /* sk */, 352 | 01F3187C242381EF007E0E18 /* vi-VN */, 353 | A178554A24B74D830036CB0A /* el */, 354 | ); 355 | name = MoveApplication.strings; 356 | sourceTree = ""; 357 | }; 358 | /* End PBXVariantGroup section */ 359 | 360 | /* Begin XCBuildConfiguration section */ 361 | C01FCF4B08A954540054247B /* Debug */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | ALWAYS_SEARCH_USER_PATHS = NO; 365 | CODE_SIGN_IDENTITY = "-"; 366 | COMBINE_HIDPI_IMAGES = YES; 367 | COPY_PHASE_STRIP = NO; 368 | GCC_DYNAMIC_NO_PIC = NO; 369 | GCC_MODEL_TUNING = G5; 370 | GCC_OPTIMIZATION_LEVEL = 0; 371 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 372 | GCC_PREFIX_HEADER = LetsMove_Prefix.pch; 373 | INFOPLIST_FILE = "LetsMove-Test-Info.plist"; 374 | INSTALL_PATH = "$(HOME)/Applications"; 375 | PRODUCT_BUNDLE_IDENTIFIER = "com.potionfactory.LetsMove-Test"; 376 | PRODUCT_NAME = "LetsMove Test"; 377 | }; 378 | name = Debug; 379 | }; 380 | C01FCF4C08A954540054247B /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | ALWAYS_SEARCH_USER_PATHS = NO; 384 | CODE_SIGN_IDENTITY = "-"; 385 | COMBINE_HIDPI_IMAGES = YES; 386 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 387 | GCC_MODEL_TUNING = G5; 388 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 389 | GCC_PREFIX_HEADER = LetsMove_Prefix.pch; 390 | INFOPLIST_FILE = "LetsMove-Test-Info.plist"; 391 | INSTALL_PATH = "$(HOME)/Applications"; 392 | PRODUCT_BUNDLE_IDENTIFIER = "com.potionfactory.LetsMove-Test"; 393 | PRODUCT_NAME = "LetsMove Test"; 394 | }; 395 | name = Release; 396 | }; 397 | C01FCF4F08A954540054247B /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | "ARCHS[sdk=macosx10.4]" = "$(ARCHS_STANDARD_32_BIT)"; 401 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 402 | CLANG_WARN_ASSIGN_ENUM = YES; 403 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 404 | CLANG_WARN_BOOL_CONVERSION = YES; 405 | CLANG_WARN_COMMA = YES; 406 | CLANG_WARN_CONSTANT_CONVERSION = YES; 407 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 408 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 409 | CLANG_WARN_EMPTY_BODY = YES; 410 | CLANG_WARN_ENUM_CONVERSION = YES; 411 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 412 | CLANG_WARN_INFINITE_RECURSION = YES; 413 | CLANG_WARN_INT_CONVERSION = YES; 414 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; 415 | CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; 416 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 417 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 418 | CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; 419 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 420 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 421 | CLANG_WARN_STRICT_PROTOTYPES = YES; 422 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 423 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 424 | CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; 425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 426 | ENABLE_STRICT_OBJC_MSGSEND = YES; 427 | ENABLE_TESTABILITY = YES; 428 | GCC_C_LANGUAGE_STANDARD = gnu99; 429 | GCC_NO_COMMON_BLOCKS = YES; 430 | GCC_OPTIMIZATION_LEVEL = 0; 431 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 432 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 433 | "GCC_VERSION[sdk=macosx10.4][arch=*]" = 4.0; 434 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 435 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 436 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 437 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 438 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 439 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 440 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 441 | GCC_WARN_PEDANTIC = YES; 442 | GCC_WARN_SHADOW = YES; 443 | GCC_WARN_SIGN_COMPARE = YES; 444 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 445 | GCC_WARN_UNDECLARED_SELECTOR = YES; 446 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 447 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 448 | GCC_WARN_UNUSED_FUNCTION = YES; 449 | GCC_WARN_UNUSED_LABEL = YES; 450 | GCC_WARN_UNUSED_PARAMETER = YES; 451 | GCC_WARN_UNUSED_VARIABLE = YES; 452 | MACOSX_DEPLOYMENT_TARGET = 10.6; 453 | "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; 454 | ONLY_ACTIVE_ARCH = YES; 455 | }; 456 | name = Debug; 457 | }; 458 | C01FCF5008A954540054247B /* Release */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | "ARCHS[sdk=macosx10.4]" = "$(ARCHS_STANDARD_32_BIT)"; 462 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 463 | CLANG_WARN_ASSIGN_ENUM = YES; 464 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 465 | CLANG_WARN_BOOL_CONVERSION = YES; 466 | CLANG_WARN_COMMA = YES; 467 | CLANG_WARN_CONSTANT_CONVERSION = YES; 468 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 469 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 473 | CLANG_WARN_INFINITE_RECURSION = YES; 474 | CLANG_WARN_INT_CONVERSION = YES; 475 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; 476 | CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; 477 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 478 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 479 | CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; 480 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 481 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 482 | CLANG_WARN_STRICT_PROTOTYPES = YES; 483 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 484 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 485 | CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; 486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 487 | ENABLE_STRICT_OBJC_MSGSEND = YES; 488 | GCC_C_LANGUAGE_STANDARD = gnu99; 489 | GCC_NO_COMMON_BLOCKS = YES; 490 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 491 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 492 | "GCC_VERSION[sdk=macosx10.4][arch=*]" = 4.0; 493 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 494 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 495 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 496 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 497 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 498 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 499 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 500 | GCC_WARN_PEDANTIC = YES; 501 | GCC_WARN_SHADOW = YES; 502 | GCC_WARN_SIGN_COMPARE = YES; 503 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 504 | GCC_WARN_UNDECLARED_SELECTOR = YES; 505 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 506 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 507 | GCC_WARN_UNUSED_FUNCTION = YES; 508 | GCC_WARN_UNUSED_LABEL = YES; 509 | GCC_WARN_UNUSED_PARAMETER = YES; 510 | GCC_WARN_UNUSED_VARIABLE = YES; 511 | MACOSX_DEPLOYMENT_TARGET = 10.6; 512 | "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; 513 | }; 514 | name = Release; 515 | }; 516 | F146F82D1CE7094400233A9B /* Debug */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | ALWAYS_SEARCH_USER_PATHS = NO; 520 | CLANG_ANALYZER_NONNULL = YES; 521 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 522 | CLANG_CXX_LIBRARY = "libc++"; 523 | CLANG_ENABLE_MODULES = YES; 524 | CLANG_ENABLE_OBJC_ARC = NO; 525 | CLANG_MODULES_AUTOLINK = NO; 526 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 527 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 528 | CLANG_WARN_UNREACHABLE_CODE = YES; 529 | CODE_SIGN_IDENTITY = "-"; 530 | COMBINE_HIDPI_IMAGES = YES; 531 | COPY_PHASE_STRIP = NO; 532 | CURRENT_PROJECT_VERSION = 1.20; 533 | DEBUG_INFORMATION_FORMAT = dwarf; 534 | DEFINES_MODULE = YES; 535 | DYLIB_COMPATIBILITY_VERSION = 1.20; 536 | DYLIB_CURRENT_VERSION = 1.20; 537 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 538 | ENABLE_STRICT_OBJC_MSGSEND = YES; 539 | FRAMEWORK_VERSION = A; 540 | GCC_DYNAMIC_NO_PIC = NO; 541 | GCC_NO_COMMON_BLOCKS = YES; 542 | GCC_PREPROCESSOR_DEFINITIONS = ( 543 | "DEBUG=1", 544 | "$(inherited)", 545 | ); 546 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 547 | INFOPLIST_FILE = "LetsMove-Info.plist"; 548 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 549 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 550 | MODULEMAP_FILE = LetsMove.modulemap; 551 | MTL_ENABLE_DEBUG_INFO = YES; 552 | PRODUCT_BUNDLE_IDENTIFIER = com.potionfactory.LetsMove; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | SDKROOT = macosx; 555 | SKIP_INSTALL = YES; 556 | VERSIONING_SYSTEM = "apple-generic"; 557 | VERSION_INFO_PREFIX = ""; 558 | }; 559 | name = Debug; 560 | }; 561 | F146F82E1CE7094400233A9B /* Release */ = { 562 | isa = XCBuildConfiguration; 563 | buildSettings = { 564 | ALWAYS_SEARCH_USER_PATHS = NO; 565 | CLANG_ANALYZER_NONNULL = YES; 566 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 567 | CLANG_CXX_LIBRARY = "libc++"; 568 | CLANG_ENABLE_MODULES = YES; 569 | CLANG_ENABLE_OBJC_ARC = NO; 570 | CLANG_MODULES_AUTOLINK = NO; 571 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 572 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 573 | CLANG_WARN_UNREACHABLE_CODE = YES; 574 | CODE_SIGN_IDENTITY = "-"; 575 | COMBINE_HIDPI_IMAGES = YES; 576 | COPY_PHASE_STRIP = NO; 577 | CURRENT_PROJECT_VERSION = 1.20; 578 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 579 | DEFINES_MODULE = YES; 580 | DYLIB_COMPATIBILITY_VERSION = 1.20; 581 | DYLIB_CURRENT_VERSION = 1.20; 582 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 583 | ENABLE_NS_ASSERTIONS = NO; 584 | ENABLE_STRICT_OBJC_MSGSEND = YES; 585 | FRAMEWORK_VERSION = A; 586 | GCC_NO_COMMON_BLOCKS = YES; 587 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 588 | INFOPLIST_FILE = "LetsMove-Info.plist"; 589 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 590 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 591 | MODULEMAP_FILE = LetsMove.modulemap; 592 | MTL_ENABLE_DEBUG_INFO = NO; 593 | PRODUCT_BUNDLE_IDENTIFIER = com.potionfactory.LetsMove; 594 | PRODUCT_NAME = "$(TARGET_NAME)"; 595 | SDKROOT = macosx; 596 | SKIP_INSTALL = YES; 597 | VERSIONING_SYSTEM = "apple-generic"; 598 | VERSION_INFO_PREFIX = ""; 599 | }; 600 | name = Release; 601 | }; 602 | /* End XCBuildConfiguration section */ 603 | 604 | /* Begin XCConfigurationList section */ 605 | C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "LetsMove Test" */ = { 606 | isa = XCConfigurationList; 607 | buildConfigurations = ( 608 | C01FCF4B08A954540054247B /* Debug */, 609 | C01FCF4C08A954540054247B /* Release */, 610 | ); 611 | defaultConfigurationIsVisible = 0; 612 | defaultConfigurationName = Release; 613 | }; 614 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "LetsMove" */ = { 615 | isa = XCConfigurationList; 616 | buildConfigurations = ( 617 | C01FCF4F08A954540054247B /* Debug */, 618 | C01FCF5008A954540054247B /* Release */, 619 | ); 620 | defaultConfigurationIsVisible = 0; 621 | defaultConfigurationName = Release; 622 | }; 623 | F146F82C1CE7094400233A9B /* Build configuration list for PBXNativeTarget "LetsMove" */ = { 624 | isa = XCConfigurationList; 625 | buildConfigurations = ( 626 | F146F82D1CE7094400233A9B /* Debug */, 627 | F146F82E1CE7094400233A9B /* Release */, 628 | ); 629 | defaultConfigurationIsVisible = 0; 630 | defaultConfigurationName = Release; 631 | }; 632 | /* End XCConfigurationList section */ 633 | }; 634 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 635 | } 636 | -------------------------------------------------------------------------------- /en.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | Default 524 | 525 | 526 | 527 | 528 | 529 | 530 | Left to Right 531 | 532 | 533 | 534 | 535 | 536 | 537 | Right to Left 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | Default 549 | 550 | 551 | 552 | 553 | 554 | 555 | Left to Right 556 | 557 | 558 | 559 | 560 | 561 | 562 | Right to Left 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | --------------------------------------------------------------------------------