1 /* 2 * Copyright (c) 2004-2015 Derelict Developers 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the names 'Derelict', 'DerelictSDL', nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /** 33 Dynamic bindings to the Foundation framework. 34 */ 35 module derelict.cocoa.foundation; 36 37 import std..string; 38 import std.utf; 39 40 import dplug.core.nogc; 41 42 import derelict.cocoa.runtime; 43 44 45 // NSZone 46 47 extern (C) nothrow @nogc 48 { 49 alias void* function(NSUInteger bytes) pfNSAllocateMemoryPages; 50 alias void function (void* ptr, NSUInteger bytes) pfNSDeallocateMemoryPages; 51 alias void function(id format, ...) pfNSLog; 52 } 53 54 __gshared 55 { 56 pfNSDeallocateMemoryPages NSDeallocateMemoryPages; 57 pfNSAllocateMemoryPages NSAllocateMemoryPages; 58 pfNSLog NSLog; 59 } 60 61 __gshared 62 { 63 //NSString NSDefaultRunLoopMode; 64 NSString NSRunLoopCommonModes; 65 } 66 67 alias NSTimeInterval = double; 68 69 70 // Mixin'd by all Cocoa objects 71 mixin template NSObjectTemplate(T, string className) 72 { 73 nothrow @nogc: 74 75 // create from an id 76 this (id id_) 77 { 78 this._id = id_; 79 } 80 81 /// Allocates, but do not init 82 static T alloc() 83 { 84 alias fun_t = extern(C) id function (id obj, SEL sel) nothrow @nogc; 85 return T( (cast(fun_t)objc_msgSend)(getClassID(), sel!"alloc") ); 86 } 87 88 static Class getClass() 89 { 90 return cast(Class)( lazyClass!className() ); 91 } 92 93 static id getClassID() 94 { 95 return lazyClass!className(); 96 } 97 } 98 99 struct NSObject 100 { 101 nothrow @nogc: 102 103 // The only field available in all NSObject hierarchy 104 // That makes all these destructs idempotent with an id, 105 // and the size of a pointer. 106 id _id = null; 107 108 // Subtype id 109 bool opCast() 110 { 111 return _id != null; 112 } 113 114 mixin NSObjectTemplate!(NSObject, "NSObject"); 115 116 ~this() 117 { 118 } 119 120 NSObject init_() 121 { 122 alias fun_t = extern(C) id function (id, const(SEL)) nothrow @nogc; 123 id result = (cast(fun_t)objc_msgSend)(_id, sel!"init"); 124 return NSObject(result); 125 } 126 127 void retain() 128 { 129 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 130 (cast(fun_t)objc_msgSend)(_id, sel!"retain"); 131 } 132 133 void release() 134 { 135 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 136 (cast(fun_t)objc_msgSend)(_id, sel!"release"); 137 } 138 } 139 140 struct NSData 141 { 142 nothrow @nogc: 143 144 NSObject parent; 145 alias parent this; 146 147 mixin NSObjectTemplate!(NSData, "NSData"); 148 149 static NSData data() 150 { 151 alias fun_t = extern(C) id function (id obj, const(SEL) sel) nothrow @nogc; 152 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"data"); 153 return NSData(result); 154 } 155 156 static NSData dataWithBytesNoCopy(void* bytes, NSUInteger length, bool freeWhenDone) 157 { 158 alias fun_t = extern(C) id function(id, const(SEL), void*, NSUInteger, BOOL) nothrow @nogc; 159 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"dataWithBytesNoCopy:length:freeWhenDone:", 160 bytes, length, freeWhenDone ? YES : NO); 161 return NSData(result); 162 } 163 } 164 165 struct NSString 166 { 167 nothrow @nogc: 168 169 NSObject parent; 170 alias parent this; 171 172 mixin NSObjectTemplate!(NSString, "NSString"); 173 174 static NSString stringWith (wstring str) nothrow @nogc 175 { 176 alias fun_t = extern(C) id function(id, SEL, const(wchar)*, NSUInteger) nothrow @nogc; 177 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"stringWithCharacters:length:", 178 CString16(str).storage, cast(NSUInteger)(str.length)); 179 return NSString(result); 180 } 181 182 size_t length () 183 { 184 alias fun_t = extern(C) NSUInteger function(id, SEL) nothrow @nogc; 185 return cast(size_t)( (cast(fun_t)objc_msgSend)(_id, sel!"length") ); 186 } 187 188 char* UTF8String () 189 { 190 alias fun_t = extern(C) char* function(id, SEL) nothrow @nogc; 191 return (cast(fun_t)objc_msgSend)(_id, sel!"UTF8String"); 192 } 193 194 void getCharacters (wchar* buffer, NSRange range) 195 { 196 alias fun_t = extern(C) void function(id, SEL, wchar*, NSRange) nothrow @nogc; 197 (cast(fun_t)objc_msgSend)(_id, sel!"getCharacters:range:", buffer, range); 198 } 199 200 NSString stringWithCharacters (wchar* chars, size_t length) 201 { 202 alias fun_t = extern(C) id function(id, SEL, wchar*, NSUInteger) nothrow @nogc; 203 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringWithCharacters:length:", chars, cast(NSUInteger)length); 204 return NSString(result); 205 } 206 207 NSRange rangeOfString (NSString aString) 208 { 209 alias fun_t = extern(C) NSRange function(id, SEL, id) nothrow @nogc; 210 return (cast(fun_t)objc_msgSend)(_id, sel!"rangeOfString", aString._id); 211 } 212 213 NSString stringByAppendingString (NSString aString) 214 { 215 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 216 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringByAppendingString:", aString._id); 217 return NSString(result); 218 } 219 220 /// Returns: The character at a given UTF-16 code unit index. 221 wchar characterAtIndex(int index) 222 { 223 alias fun_t = extern(C) wchar function(id, SEL, NSUInteger) nothrow @nogc; 224 return (cast(fun_t)objc_msgSend)(_id, sel!"characterAtIndex:", cast(NSUInteger)index); 225 } 226 } 227 228 struct NSURL 229 { 230 nothrow @nogc: 231 NSObject parent; 232 alias parent this; 233 234 mixin NSObjectTemplate!(NSURL, "NSURL"); 235 236 static NSURL URLWithString(NSString str) 237 { 238 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 239 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"URLWithString:", str._id); 240 return NSURL(result); 241 } 242 243 } 244 245 struct NSEnumerator 246 { 247 nothrow @nogc: 248 NSObject parent; 249 alias parent this; 250 251 mixin NSObjectTemplate!(NSEnumerator, "NSEnumerator"); 252 253 id nextObject () 254 { 255 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 256 return (cast(fun_t)objc_msgSend)(_id, sel!"nextObject"); 257 } 258 } 259 260 struct NSArray 261 { 262 nothrow @nogc: 263 264 NSObject parent; 265 alias parent this; 266 267 mixin NSObjectTemplate!(NSArray, "NSArray"); 268 269 NSEnumerator objectEnumerator () 270 { 271 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 272 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectEnumerator"); 273 return NSEnumerator(result); 274 } 275 } 276 277 278 struct NSProcessInfo 279 { 280 nothrow @nogc: 281 282 NSObject parent; 283 alias parent this; 284 285 mixin NSObjectTemplate!(NSProcessInfo, "NSProcessInfo"); 286 287 static NSProcessInfo processInfo () 288 { 289 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 290 id result = (cast(fun_t)objc_msgSend)(lazyClass!"NSProcessInfo", sel!"processInfo"); 291 return NSProcessInfo(result); 292 } 293 294 NSString processName () 295 { 296 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 297 id result = (cast(fun_t)objc_msgSend)(_id, sel!"processName"); 298 return NSString(result); 299 } 300 } 301 302 struct NSNotification 303 { 304 nothrow @nogc: 305 NSObject parent; 306 alias parent this; 307 308 mixin NSObjectTemplate!(NSNotification, "NSNotification"); 309 } 310 311 struct NSDictionary 312 { 313 nothrow @nogc: 314 NSObject parent; 315 alias parent this; 316 317 mixin NSObjectTemplate!(NSDictionary, "NSDictionary"); 318 319 static NSDictionary dictionaryWithObjectsAndKeys(Args...)(id firstObject, Args args) 320 { 321 alias fun_t = extern(C) id function(id, SEL, id, ...) nothrow @nogc; 322 auto result = (cast(fun_t) objc_msgSend)(getClassID(), sel!"dictionaryWithObjectsAndKeys:", firstObject, args); 323 324 return NSDictionary(result); 325 } 326 327 id objectForKey(id key) 328 { 329 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 330 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectForKey:", key); 331 return result; 332 } 333 } 334 335 struct NSAutoreleasePool 336 { 337 nothrow @nogc: 338 NSObject parent; 339 alias parent this; 340 341 mixin NSObjectTemplate!(NSAutoreleasePool, "NSAutoreleasePool"); 342 } 343 344 enum : int 345 { 346 NSFileErrorMaximum = 1023, 347 NSFileErrorMinimum = 0, 348 NSFileLockingError = 255, 349 NSFileNoSuchFileError = 4, 350 NSFileReadCorruptFileError = 259, 351 NSFileReadInapplicableStringEncodingError = 261, 352 NSFileReadInvalidFileNameError = 258, 353 NSFileReadNoPermissionError = 257, 354 NSFileReadNoSuchFileError = 260, 355 NSFileReadUnknownError = 256, 356 NSFileReadUnsupportedSchemeError = 262, 357 NSFileWriteInapplicableStringEncodingError = 517, 358 NSFileWriteInvalidFileNameError = 514, 359 NSFileWriteNoPermissionError = 513, 360 NSFileWriteOutOfSpaceError = 640, 361 NSFileWriteUnknownError = 512, 362 NSFileWriteUnsupportedSchemeError = 518, 363 NSFormattingError = 2048, 364 NSFormattingErrorMaximum = 2559, 365 NSFormattingErrorMinimum = 2048, 366 NSKeyValueValidationError = 1024, 367 NSUserCancelledError = 3072, 368 NSValidationErrorMaximum = 2047, 369 NSValidationErrorMinimum = 1024, 370 371 NSExecutableArchitectureMismatchError = 3585, 372 NSExecutableErrorMaximum = 3839, 373 NSExecutableErrorMinimum = 3584, 374 NSExecutableLinkError = 3588, 375 NSExecutableLoadError = 3587, 376 NSExecutableNotLoadableError = 3584, 377 NSExecutableRuntimeMismatchError = 3586, 378 NSFileReadTooLargeError = 263, 379 NSFileReadUnknownStringEncodingError = 264, 380 381 GSFoundationPlaceHolderError = 9999 382 } 383 384 struct NSError 385 { 386 nothrow @nogc: 387 NSObject parent; 388 alias parent this; 389 390 mixin NSObjectTemplate!(NSError, "NSError"); 391 392 NSString localizedDescription() 393 { 394 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 395 id res = (cast(fun_t)objc_msgSend)(_id, sel!"localizedDescription"); 396 return NSString(res); 397 } 398 } 399 400 struct NSBundle 401 { 402 nothrow @nogc: 403 NSObject parent; 404 alias parent this; 405 406 mixin NSObjectTemplate!(NSBundle, "NSBundle"); 407 408 void initWithPath(NSString path) 409 { 410 alias fun_t = extern(C) void function(id, SEL, id) nothrow @nogc; 411 (cast(fun_t)objc_msgSend)(_id, sel!"initWithPath:", path._id); 412 } 413 414 bool load() 415 { 416 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 417 return (cast(fun_t)objc_msgSend)(_id, sel!"load") != NO; 418 } 419 420 bool unload() 421 { 422 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 423 return (cast(fun_t)objc_msgSend)(_id, sel!"unload") != NO; 424 } 425 426 bool loadAndReturnError(NSError error) 427 { 428 alias fun_t = extern(C) BOOL function(id, SEL, id) nothrow @nogc; 429 return (cast(fun_t)objc_msgSend)(_id, sel!"loadAndReturnError:", error._id) != NO; 430 } 431 } 432 433 struct NSTimer 434 { 435 nothrow @nogc: 436 NSObject parent; 437 alias parent this; 438 439 mixin NSObjectTemplate!(NSTimer, "NSTimer"); 440 441 static NSTimer timerWithTimeInterval(double seconds, NSObject target, SEL selector, void* userInfo, bool repeats) 442 { 443 alias fun_t = extern(C) id function(id, SEL, double, id, SEL, id, BOOL) nothrow @nogc; 444 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"timerWithTimeInterval:target:selector:userInfo:repeats:", 445 seconds, target._id, selector, cast(id)userInfo, repeats ? YES : NO); 446 return NSTimer(result); 447 } 448 449 void invalidate() 450 { 451 alias fun_t = extern(C) void function(id, SEL) nothrow @nogc; 452 (cast(fun_t)objc_msgSend)(_id, sel!"invalidate"); 453 } 454 } 455 456 struct NSRunLoop 457 { 458 nothrow @nogc: 459 NSObject parent; 460 alias parent this; 461 462 mixin NSObjectTemplate!(NSRunLoop, "NSRunLoop"); 463 464 static NSRunLoop currentRunLoop() 465 { 466 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 467 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"currentRunLoop"); 468 return NSRunLoop(result); 469 } 470 471 static NSRunLoop mainRunLoop() 472 { 473 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 474 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"mainRunLoop"); 475 return NSRunLoop(result); 476 } 477 478 void runUntilDate(NSDate limitDate) 479 { 480 alias fun_t = extern(C) void function(id, SEL, id) nothrow @nogc; 481 (cast(fun_t)objc_msgSend)(_id, sel!"runUntilDate:", limitDate._id); 482 } 483 484 void addTimer(NSTimer aTimer, NSString forMode) 485 { 486 alias fun_t = extern(C) void function(id, SEL, id, id) nothrow @nogc; 487 (cast(fun_t)objc_msgSend)(_id, sel!"addTimer:forMode:", aTimer._id, forMode._id); 488 } 489 } 490 491 struct NSDate 492 { 493 nothrow @nogc: 494 NSObject parent; 495 alias parent this; 496 497 mixin NSObjectTemplate!(NSDate, "NSDate"); 498 499 static NSDate date() 500 { 501 return NSDate(objc_msgSend(getClassID(), sel!"date")); 502 } 503 504 static NSTimeInterval timeIntervalSinceReferenceDate() 505 { 506 alias fun_t = extern(C) NSTimeInterval function(id, SEL) nothrow @nogc; 507 508 version(X86) 509 return (cast(fun_t)objc_msgSend_fpret)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 510 else version(X86_64) 511 return (cast(fun_t)objc_msgSend)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 512 else 513 static assert(false); 514 } 515 516 static NSDate dateWithTimeIntervalSinceNow(double secs) 517 { 518 alias fun_t = extern(C) id function(id, SEL, double) nothrow @nogc; 519 id res = (cast(fun_t)objc_msgSend)(getClassID(), sel!"dateWithTimeIntervalSinceNow:", secs); 520 521 return NSDate(res); 522 } 523 524 NSString description() 525 { 526 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 527 id result = (cast(fun_t)objc_msgSend)(_id, sel!"description"); 528 529 return NSString(result); 530 } 531 532 NSString descriptionWithLocale() 533 { 534 alias fun_t = extern(C) id function(id, SEL, void*) nothrow @nogc; 535 id result = (cast(fun_t)objc_msgSend)(_id, sel!"descriptionWithLocale:", null); 536 return NSString(result); 537 } 538 } 539 540 struct NSNumber 541 { 542 nothrow @nogc: 543 NSObject parent; 544 alias parent this; 545 546 mixin NSObjectTemplate!(NSNumber, "NSNumber"); 547 548 static NSNumber numberWithUnsignedInt(uint value) 549 { 550 alias fun_t = extern(C) id function(id, SEL, uint) nothrow @nogc; 551 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"numberWithUnsignedInt:", value); 552 553 return NSNumber(result); 554 } 555 }