Line data Source code
1 0 : /*
2 :
3 : OOCocoa.h
4 :
5 : Import OpenStep main headers and define some Macisms and other compatibility
6 : stuff.
7 :
8 : Oolite
9 : Copyright (C) 2004-2013 Giles C Williams and contributors
10 :
11 : This program is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU General Public License
13 : as published by the Free Software Foundation; either version 2
14 : of the License, or (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program; if not, write to the Free Software
23 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 : MA 02110-1301, USA.
25 :
26 : */
27 :
28 : /*
29 : Expressions like #define FOO (1 && !defined(NDEBUG)) are formally invalid,
30 : causing a warning in Clang. This lets us write #define FOO (1 && OOLITE_DEBUG)
31 : instead.
32 : */
33 : #ifdef NDEBUG
34 : #define OOLITE_DEBUG 0
35 : #else
36 0 : #define OOLITE_DEBUG 1
37 : #endif
38 :
39 : #if !OOLITE_DEBUG
40 : #define NS_BLOCK_ASSERTIONS 1
41 : #endif
42 :
43 :
44 : #include <math.h>
45 : #include <stdbool.h>
46 : #import <Foundation/Foundation.h>
47 :
48 : #ifdef GNUSTEP
49 : #define OOLITE_GNUSTEP 1
50 :
51 : #if (((GNUSTEP_BASE_MAJOR_VERSION == 1 && GNUSTEP_BASE_MINOR_VERSION >= 31) || (GNUSTEP_BASE_MAJOR_VERSION > 1)) && !OOLITE_MODERN_BUILD)
52 : #error Oolite legacy build cannot be generated using GNUstep 1.31 or higher.
53 : #endif
54 :
55 : #if ((GNUSTEP_BASE_MAJOR_VERSION == 1 && GNUSTEP_BASE_MINOR_VERSION < 28) && OOLITE_MODERN_BUILD)
56 : #error Oolite modern build cannot be generated using GNUstep earlier than 1.28.
57 : #endif
58 :
59 : #if (GNUSTEP_BASE_MAJOR_VERSION == 1 && GNUSTEP_BASE_MINOR_VERSION >= 20) || (GNUSTEP_BASE_MAJOR_VERSION > 1)
60 : #define OOLITE_GNUSTEP_1_20 1
61 : #else
62 : #error Oolite for non-Mac targets requires GNUstep 1.20.
63 : #endif
64 :
65 : #ifndef NSIntegerMax
66 : // Missing in GNUstep-base prior to 1.23.
67 : #define NSIntegerMax INTPTR_MAX
68 : #define NSIntegerMin INTPTR_MIN
69 : #define NSUIntegerMax UINTPTR_MAX
70 : #endif
71 :
72 : #else
73 : #import <AppKit/AppKit.h>
74 :
75 0 : #define OOLITE_MAC_OS_X 1
76 0 : #define OOLITE_SPEECH_SYNTH 1
77 :
78 : #if __LP64__
79 : #define OOLITE_64_BIT 1
80 : #endif
81 :
82 : /* Useful macro copied from GNUstep.
83 : */
84 : #ifndef DESTROY
85 0 : #define DESTROY(x) do { id x_ = x; x = nil; [x_ release]; } while (0)
86 : #endif
87 :
88 : #if defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
89 : #define OOLITE_MAC_OS_X_10_7 1
90 : #endif
91 :
92 : #if defined MAC_OS_X_VERSION_10_8 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8
93 : #define OOLITE_MAC_OS_X_10_8 1
94 : #endif
95 :
96 : #ifndef MAC_OS_X_VERSION_10_12
97 0 : typedef NSUInteger NSWindowStyleMask;
98 : #endif
99 : #endif
100 :
101 :
102 : #ifndef OOLITE_MAC_OS_X_10_7
103 0 : #define OOLITE_MAC_OS_X_10_7 0
104 : #endif
105 :
106 : #ifndef OOLITE_MAC_OS_X_10_8
107 0 : #define OOLITE_MAC_OS_X_10_8 0
108 : #endif
109 :
110 :
111 : #ifdef __clang__
112 : #define OOLITE_HAVE_CLANG 1
113 : #else
114 0 : #define OOLITE_HAVE_CLANG 0
115 : #endif
116 :
117 :
118 : #if defined(__GNUC__) && !OOLITE_HAVE_CLANG
119 : // GCC version; for instance, 40300 for 4.3.0. Deliberately undefined in Clang (which defines fake __GNUC__ macros for compatibility).
120 : #define OOLITE_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
121 : #endif
122 :
123 :
124 : #if OOLITE_GNUSTEP
125 : #include <stdint.h>
126 : #include <limits.h> // to get UINT_MAX
127 :
128 :
129 : #define OOLITE_SDL 1
130 :
131 : #ifdef WIN32
132 : #define OOLITE_WINDOWS 1
133 : #if defined(_WIN64)
134 : #define OOLITE_64_BIT 1
135 : #endif
136 : #endif
137 :
138 : #ifdef LINUX
139 : #define OOLITE_LINUX 1
140 : #endif
141 :
142 :
143 : #define true 1
144 : #define false 0
145 :
146 : #if !defined(MAX)
147 : #define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a > __b ? __a : __b; })
148 : #endif
149 :
150 : #if !defined(MIN)
151 : #define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
152 : #endif
153 :
154 : #ifdef HAVE_LIBESPEAK
155 : #define OOLITE_SPEECH_SYNTH 1
156 : #define OOLITE_ESPEAK 1
157 : #endif
158 :
159 :
160 : // Pseudo-keywords used for AppKit UI bindings.
161 : #ifndef IBOutlet
162 : #define IBOutlet /**/
163 : #endif
164 : #ifndef IBAction
165 : #define IBAction void
166 : #endif
167 :
168 :
169 : #import "Comparison.h"
170 :
171 : /* Define AppKit constants for events */
172 : enum {
173 : NSUpArrowFunctionKey = 0xF700,
174 : NSDownArrowFunctionKey = 0xF701,
175 : NSLeftArrowFunctionKey = 0xF702,
176 : NSRightArrowFunctionKey = 0xF703,
177 : NSF1FunctionKey = 0xF704,
178 : NSF2FunctionKey = 0xF705,
179 : NSF3FunctionKey = 0xF706,
180 : NSF4FunctionKey = 0xF707,
181 : NSF5FunctionKey = 0xF708,
182 : NSF6FunctionKey = 0xF709,
183 : NSF7FunctionKey = 0xF70A,
184 : NSF8FunctionKey = 0xF70B,
185 : NSF9FunctionKey = 0xF70C,
186 : NSF10FunctionKey = 0xF70D,
187 : NSF11FunctionKey = 0xF70E,
188 : NSF12FunctionKey = 0xF70F,
189 : NSF13FunctionKey = 0xF710,
190 : NSF14FunctionKey = 0xF711,
191 : NSF15FunctionKey = 0xF712,
192 : NSF16FunctionKey = 0xF713,
193 : NSF17FunctionKey = 0xF714,
194 : NSF18FunctionKey = 0xF715,
195 : NSF19FunctionKey = 0xF716,
196 : NSF20FunctionKey = 0xF717,
197 : NSF21FunctionKey = 0xF718,
198 : NSF22FunctionKey = 0xF719,
199 : NSF23FunctionKey = 0xF71A,
200 : NSF24FunctionKey = 0xF71B,
201 : NSF25FunctionKey = 0xF71C,
202 : NSF26FunctionKey = 0xF71D,
203 : NSF27FunctionKey = 0xF71E,
204 : NSF28FunctionKey = 0xF71F,
205 : NSF29FunctionKey = 0xF720,
206 : NSF30FunctionKey = 0xF721,
207 : NSF31FunctionKey = 0xF722,
208 : NSF32FunctionKey = 0xF723,
209 : NSF33FunctionKey = 0xF724,
210 : NSF34FunctionKey = 0xF725,
211 : NSF35FunctionKey = 0xF726,
212 : NSInsertFunctionKey = 0xF727,
213 : NSDeleteFunctionKey = 0xF728,
214 : NSHomeFunctionKey = 0xF729,
215 : NSBeginFunctionKey = 0xF72A,
216 : NSEndFunctionKey = 0xF72B,
217 : NSPageUpFunctionKey = 0xF72C,
218 : NSPageDownFunctionKey = 0xF72D,
219 : NSPrintScreenFunctionKey = 0xF72E,
220 : NSScrollLockFunctionKey = 0xF72F,
221 : NSPauseFunctionKey = 0xF730,
222 : NSSysReqFunctionKey = 0xF731,
223 : NSBreakFunctionKey = 0xF732,
224 : NSResetFunctionKey = 0xF733,
225 : NSStopFunctionKey = 0xF734,
226 : NSMenuFunctionKey = 0xF735,
227 : NSUserFunctionKey = 0xF736,
228 : NSSystemFunctionKey = 0xF737,
229 : NSPrintFunctionKey = 0xF738,
230 : NSClearLineFunctionKey = 0xF739,
231 : NSClearDisplayFunctionKey = 0xF73A,
232 : NSInsertLineFunctionKey = 0xF73B,
233 : NSDeleteLineFunctionKey = 0xF73C,
234 : NSInsertCharFunctionKey = 0xF73D,
235 : NSDeleteCharFunctionKey = 0xF73E,
236 : NSPrevFunctionKey = 0xF73F,
237 : NSNextFunctionKey = 0xF740,
238 : NSSelectFunctionKey = 0xF741,
239 : NSExecuteFunctionKey = 0xF742,
240 : NSUndoFunctionKey = 0xF743,
241 : NSRedoFunctionKey = 0xF744,
242 : NSFindFunctionKey = 0xF745,
243 : NSHelpFunctionKey = 0xF746,
244 : NSModeSwitchFunctionKey = 0xF747
245 : };
246 :
247 : #endif
248 :
249 :
250 : #ifndef OOLITE_GNUSTEP
251 0 : #define OOLITE_GNUSTEP 0
252 : #endif
253 :
254 : #ifndef OOLITE_MAC_OS_X
255 : #define OOLITE_MAC_OS_X 0
256 : #endif
257 :
258 : #ifndef OOLITE_WINDOWS
259 0 : #define OOLITE_WINDOWS 0
260 : #endif
261 :
262 : #ifndef OOLITE_LINUX
263 0 : #define OOLITE_LINUX 0
264 : #endif
265 :
266 : #ifndef OOLITE_SDL
267 0 : #define OOLITE_SDL 0
268 : #endif
269 :
270 : #ifndef OOLITE_SPEECH_SYNTH
271 : #define OOLITE_SPEECH_SYNTH 0
272 : #endif
273 :
274 : #ifndef OOLITE_ESPEAK
275 0 : #define OOLITE_ESPEAK 0
276 : #endif
277 :
278 : #ifndef OOLITE_64_BIT
279 0 : #define OOLITE_64_BIT 0
280 : #endif
281 :
282 :
283 0 : #define OOLITE_PROPERTY_SYNTAX (OOLITE_MAC_OS_X || OOLITE_HAVE_CLANG)
284 :
285 :
286 : #import "OOLogging.h"
287 :
288 :
289 : @interface NSObject (OODescriptionComponents)
290 :
291 : /* In order to allow implementations of -description to inherit description
292 : components from superclasses, and to allow implementations of -description
293 : and -oo_jsDescription to share code, both are implemented as wrappers
294 : around -descriptionComponents. -descriptionComponents should provide
295 : information about an object without a class name or surrounding
296 : punctuation. -description will wrap the components like this:
297 : <ClassName 0xnnnnnnnn>{descriptionComponents}
298 : and -oo_jsDescription will wrap them like this:
299 : [oo_jsClassName descriptionComponents]
300 : */
301 0 : - (NSString *)descriptionComponents;
302 :
303 :
304 : /* A lot of Oolite's -description implementations are rather long, and many
305 : embed other descriptions. -shortDescription provides a truncated
306 : alternative, while -shortDescriptionComponents provides a
307 : -descriptionComponents-like mechanism to simplify implementation.
308 : */
309 0 : - (NSString *) shortDescription;
310 0 : - (NSString *) shortDescriptionComponents;
311 :
312 : @end
313 :
314 :
315 : #if OOLITE_MAC_OS_X
316 0 : #define OOLITE_RELEASE_PLIST_ERROR_STRINGS 1
317 : #else
318 : #define OOLITE_RELEASE_PLIST_ERROR_STRINGS 0
319 : #endif
320 :
321 :
322 : /* For some reason, return types for some comparison callbacks are typed
323 : NSInteger/int under OS X but (more sensibly) NSComparisonResult under
324 : GNUstep.
325 : */
326 : #if OOLITE_MAC_OS_X
327 0 : typedef NSInteger OOComparisonResult;
328 : #else
329 : typedef NSComparisonResult OOComparisonResult;
330 : #endif
331 :
332 :
333 : /* Fast enumeration (for (x in y) syntax) is supported in all Mac compilers
334 : when targeting 10.5 or later, and in gcc 4.6 with the GNU libobjc runtime.
335 : At the time of writing, GNUstep stable does not support gcc 4.6, but it
336 : already has support for the fast enumeration protocol in its collection
337 : classes.
338 :
339 : All release versions of clang support fast enumeration, assuming libobjc2
340 : or ObjectiveC2.framework is being used. We shall make that assumption.
341 :
342 : References:
343 : http://lists.gnu.org/archive/html/discuss-gnustep/2011-02/msg00019.html
344 : http://wiki.gnustep.org/index.php/ObjC2_FAQ
345 : -- Ahruman 2011-02-04
346 : */
347 : #if OOLITE_MAC_OS_X
348 0 : #define OOLITE_FAST_ENUMERATION 1
349 : #else
350 : #if __clang__
351 : #define OOLITE_FAST_ENUMERATION 1
352 : #elif defined (OOLITE_GNUSTEP)
353 : #define OOLITE_FAST_ENUMERATION (OOLITE_GCC_VERSION >= 40600)
354 : #endif
355 : #endif
356 :
357 : #ifndef OOLITE_FAST_ENUMERATION
358 : #define OOLITE_FAST_ENUMERATION 0
359 : #endif
360 :
361 :
362 : /* Enumeration macros:
363 : foreach(VAR, COLLECTION) enumerates the members of an array or set, setting
364 : the variable VAR to a member on each pass.
365 : foreachkey(VAR, DICT) enumerates the keys of a dictionary the same way.
366 :
367 : Example:
368 : id element = nil;
369 : foreach (element, array)
370 : {
371 : OOLog(@"element", @"%@", element);
372 : }
373 :
374 : These are based on macros by Jens Alfke.
375 : */
376 : #if OOLITE_FAST_ENUMERATION
377 0 : #define foreach(VAR, COLLECTION) for(VAR in COLLECTION)
378 0 : #define foreachkey(VAR, DICT) for(VAR in DICT)
379 : #else
380 : #define foreach(VAR, COLLECTION) for (NSEnumerator *ooForEachEnum = [(COLLECTION) objectEnumerator]; ((VAR) = [ooForEachEnum nextObject]); )
381 : #define foreachkey(VAR, DICT) for (NSEnumerator *ooForEachEnum = [(DICT) keyEnumerator]; ((VAR) = [ooForEachEnum nextObject]); )
382 : #endif
383 :
384 :
385 : /* Support for foreach() with NSEnumerators in GCC.
386 : It works without this with for (x in y) support, but we leave it defined
387 : to reduce differences between different build environments.
388 : */
389 : @interface NSEnumerator (OOForEachSupport)
390 0 : - (NSEnumerator *) objectEnumerator;
391 : @end
392 :
393 :
394 : /* @optional directive for protocols: added in Objective-C 2.0.
395 :
396 : As a nasty, nasty hack, the OOLITE_OPTIONAL(foo) macro allows an optional
397 : section with or without @optional. If @optional is not available, it
398 : actually ends the protocol and starts an appropriately-named informal
399 : protocol, i.e. a category on NSObject. Since it ends the protocol, there
400 : can only be one and there's no way to switch back to @required.
401 : */
402 : #ifndef OOLITE_HAVE_PROTOCOL_OPTIONAL
403 : #define OOLITE_HAVE_PROTOCOL_OPTIONAL (OOLITE_MAC_OS_X || OOLITE_HAVE_CLANG || OOLITE_GCC_VERSION >= 40700)
404 : #endif
405 :
406 : #if OOLITE_HAVE_PROTOCOL_OPTIONAL
407 0 : #define OOLITE_OPTIONAL(protocolName) @optional
408 : #else
409 : #define OOLITE_OPTIONAL(protocolName) @end @interface NSObject (protocolName ## Optional)
410 : #endif
411 :
412 :
413 : /* instancetype contextual keyword; added in Clang 3.0ish.
414 :
415 : Pseudo-type indicating that the return value of an instance method is an
416 : instance of the same class as the receiver, or for a class mothod, is an
417 : instance of that class.
418 :
419 : For example, given:
420 : @interface Foo: NSObject
421 : + (instancetype) fooWithProperty:(id)property;
422 : @end
423 :
424 : @interface Bar: Foo
425 : @end
426 :
427 : the type of [Bar fooWithProperty] is inferred to be Bar *.
428 :
429 : Clang treats methods of type id as instancetype when their names begin with
430 : +alloc, +new, -init, -autorelease, -retain, or -self.
431 :
432 : For compilers without instancetype support, id is appropriate but less
433 : type-safe.
434 :
435 : NOTE: it is not appropriate to use instancetype for a factory method which
436 : chooses which publicly-visible subclass to instantiate based on parameters.
437 : For instance, calling one of the OOMaterial convenience factory methods on
438 : OOShaderMaterial might return an OOSingleTextureMaterial, so the correct
439 : return type is either OOMaterial or id.
440 : On the other hand, it is appropriate on factory methods which just wrap
441 : the corresponding -init and/or -init + configuration through properties.
442 : (Such factory methods should be implemented in terms of [[self alloc]
443 : init...].)
444 : */
445 : #if __OBJC__ && !__has_feature(objc_instancetype)
446 : typedef id instancetype;
447 : #endif
448 :
449 :
450 : #ifndef OO_DEBUG
451 : // Defined by makefile/Xcode in debug builds.
452 : #define OO_DEBUG 0
453 : #endif
|