iOSPlatform.mm 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include <unistd.h>
  23. #include "platform/platform.h"
  24. #include "console/console.h"
  25. #include "string/stringTable.h"
  26. #include "platform/platformInput.h"
  27. #include "platform/threads/thread.h"
  28. #pragma mark ---- Various Directories ----
  29. //-----------------------------------------------------------------------------
  30. const char* Platform::getUserDataDirectory()
  31. {
  32. // application support directory is most in line with the current usages of this function.
  33. // this may change with later usage
  34. // perhaps the user data directory should be pref-controlled?
  35. //NSString *nsDataDir = [@"~/Library/Application Support/" stringByStandardizingPath];
  36. //-Mat using Documents directory in same folder as .app
  37. NSString *nsDataDir = [@"~/Documents/" stringByStandardizingPath];
  38. return StringTable->insert([nsDataDir UTF8String]);
  39. }
  40. //-----------------------------------------------------------------------------
  41. const char* Platform::getUserHomeDirectory()
  42. {
  43. return StringTable->insert([[@"~/" stringByStandardizingPath] UTF8String]);
  44. }
  45. //-----------------------------------------------------------------------------
  46. StringTableEntry Platform::osGetTemporaryDirectory()
  47. {
  48. NSString *tdir = NSTemporaryDirectory();
  49. const char *path = [tdir UTF8String];
  50. return StringTable->insert(path);
  51. }
  52. #pragma mark ---- Administrator ----
  53. //-----------------------------------------------------------------------------
  54. /* <Mat> may need these for buttons later
  55. #pragma mark ---- MessageBox ----
  56. struct _NSStringMap
  57. {
  58. S32 num;
  59. NSString* ok;
  60. NSString* cancel;
  61. NSString* third;
  62. };
  63. static _NSStringMap sgButtonTextMap[] =
  64. {
  65. { MBOk, @"Ok", nil, nil },
  66. { MBOkCancel, @"Ok", @"Cancel", nil },
  67. { MBRetryCancel, @"Retry", @"Cancel", nil },
  68. { MBSaveDontSave, @"Save", @"Discard", nil },
  69. { MBSaveDontSaveCancel, @"Save", @"Cancel", @"Don't Save" },
  70. { -1, nil, nil, nil }
  71. };
  72. struct _NSAlertResultMap
  73. {
  74. S32 num;
  75. S32 ok;
  76. S32 cancel;
  77. S32 third;
  78. };
  79. static _NSAlertResultMap sgAlertResultMap[] =
  80. {
  81. { MBOk, MROk, 0, 0 },
  82. { MBOkCancel, MROk, MRCancel, 0 },
  83. { MBRetryCancel, MRRetry, MRCancel, 0 },
  84. { MBSaveDontSave, MROk, MRDontSave, 0 },
  85. { MBSaveDontSaveCancel, MROk, MRCancel, MRDontSave },
  86. { -1, nil, nil, nil }
  87. };
  88. */
  89. //-----------------------------------------------------------------------------
  90. S32 Platform::messageBox(const UTF8 *title, const UTF8 *message, MBButtons buttons, MBIcons icon)
  91. {
  92. Platform::AlertOK( title, message );//<Mat> maybe add in a a way to do other buttons
  93. return 1;
  94. }
  95. #pragma mark ---- File IO ----
  96. //-----------------------------------------------------------------------------
  97. bool Platform::pathCopy(const char* source, const char* dest, bool nooverwrite)
  98. {
  99. NSFileManager *manager = [NSFileManager defaultManager];
  100. @autoreleasepool {
  101. NSString *nsource = [@(source) stringByStandardizingPath];
  102. NSString *ndest = [@(dest) stringByStandardizingPath];
  103. NSString *ndestFolder = [ndest stringByDeletingLastPathComponent];
  104. if(! [manager fileExistsAtPath:nsource])
  105. {
  106. Con::errorf("Platform::pathCopy: no file exists at %s",source);
  107. return false;
  108. }
  109. //Catcher for the errors.
  110. NSError* returnValue = nil;
  111. if( [manager fileExistsAtPath:ndest] )
  112. {
  113. if(nooverwrite)
  114. {
  115. Con::errorf("Platform::pathCopy file already exists at %s",dest);
  116. return false;
  117. }
  118. Con::warnf("Deleting files at path: %s", dest);
  119. bool deleted = [manager removeItemAtPath:ndest error:&returnValue];
  120. if(!deleted)
  121. {
  122. Con::errorf("Copy failed! Could not delete files at path: %s", dest);
  123. return false;
  124. }
  125. }
  126. if([manager fileExistsAtPath:ndestFolder] == NO)
  127. {
  128. ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash
  129. Platform::createPath([ndestFolder UTF8String]);
  130. }
  131. bool ret = [manager copyItemAtPath:nsource toPath:ndest error:&returnValue];
  132. return ret;
  133. }
  134. }
  135. //-----------------------------------------------------------------------------
  136. bool Platform::fileRename(const char *source, const char *dest)
  137. {
  138. if(source == NULL || dest == NULL)
  139. return false;
  140. NSFileManager *manager = [NSFileManager defaultManager];
  141. NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)];
  142. NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)];
  143. if(! [manager fileExistsAtPath:nsource])
  144. {
  145. Con::errorf("Platform::fileRename: no file exists at %s",source);
  146. return false;
  147. }
  148. if( [manager fileExistsAtPath:ndest] )
  149. {
  150. Con::warnf("Platform::fileRename: Deleting files at path: %s", dest);
  151. }
  152. NSError* returnValue = NULL;
  153. bool ret = [manager moveItemAtPath:nsource toPath:ndest error:&returnValue];
  154. return ret;
  155. }
  156. #pragma mark ---- ShellExecute ----
  157. class ExecuteThread : public Thread
  158. {
  159. const char* zargs;
  160. const char* directory;
  161. const char* executable;
  162. public:
  163. ExecuteThread(const char *_executable, const char *_args /* = NULL */, const char *_directory /* = NULL */) : Thread(0, NULL, false, true)
  164. {
  165. zargs = dStrdup(_args);
  166. directory = dStrdup(_directory);
  167. executable = dStrdup(_executable);
  168. start();
  169. }
  170. virtual void run(void* arg);
  171. };
  172. static char* _unDoubleQuote(char* arg)
  173. {
  174. U32 len = dStrlen(arg);
  175. if(!len)
  176. return arg;
  177. if(arg[0] == '"' && arg[len-1] == '"')
  178. {
  179. arg[len - 1] = '\0';
  180. return arg + 1;
  181. }
  182. return arg;
  183. }
  184. void ExecuteThread::run(void* arg)
  185. {
  186. #if 0 // FIXME: HACK PUAP -Mat Threads
  187. // 2k should be enough. if it's not, bail.
  188. // char buf[2048];
  189. // U32 len = dSprintf(buf, sizeof(buf), "%s %s -workingDir %s", executable, args, directory);
  190. // if( len >= sizeof(buf))
  191. // {
  192. // Con::errorf("shellExecute(): the command was too long, and won't be run.");
  193. // return;
  194. // }
  195. // // calls sh with the string and blocks until the command returns.
  196. // system(buf);
  197. // FIXME: there is absolutely no error checking in here.
  198. printf("creating nstask\n");
  199. NSTask *aTask = [[NSTask alloc] init];
  200. NSMutableArray *array = [NSMutableArray array];
  201. // scan the args list, breaking it up, space delimited, backslash escaped.
  202. U32 len = dStrlen(zargs);
  203. char args[len+1];
  204. dStrncpy(args, zargs, len+1);
  205. char *lastarg = args;
  206. bool escaping = false;
  207. for(int i = 0; i< len; i++)
  208. {
  209. char c = args[i];
  210. // a backslash escapes the next character
  211. if(escaping)
  212. continue;
  213. if(c == '\\')
  214. escaping = true;
  215. if(c == ' ')
  216. {
  217. args[i] = '\0';
  218. if(*lastarg)
  219. [array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
  220. lastarg = args + i + 1;
  221. }
  222. }
  223. if(*lastarg)
  224. [array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
  225. [aTask setArguments: array];
  226. [aTask setCurrentDirectoryPath:[NSString stringWithUTF8String: this->directory]];
  227. [aTask setLaunchPath:[NSString stringWithUTF8String:executable]];
  228. [aTask launch];
  229. [aTask waitUntilExit];
  230. U32 ret = [aTask terminationStatus];
  231. Con::executef(2, "onExecuteDone", Con::getIntArg(ret));
  232. printf("done nstask\n");
  233. #endif
  234. }
  235. ConsoleFunction(shellExecute, bool, 2, 4, "(executable, [args], [directory])")
  236. {
  237. return true; // Bug: BPNC error: need feedback on whether the command was sucessful
  238. }
  239. void Input::setCursorShape(U32 cursorID)
  240. {
  241. //no cursors on iOS except Torque cursors
  242. }
  243. void Input::setCursorState(bool on)
  244. {
  245. }