mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
491 lines
18 KiB
C
491 lines
18 KiB
C
//
|
|
// GrowlDefinesInternal.h
|
|
// Growl
|
|
//
|
|
// Created by Karl Adam on Mon May 17 2004.
|
|
// Copyright (c) 2004 the Growl Project. All rights reserved.
|
|
//
|
|
|
|
#ifndef _GROWL_GROWLDEFINESINTERNAL_H
|
|
#define _GROWL_GROWLDEFINESINTERNAL_H
|
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef __OBJC__
|
|
#define XSTR(x) (@x)
|
|
#else /* !__OBJC__ */
|
|
#define XSTR CFSTR
|
|
#endif /* __OBJC__ */
|
|
|
|
/*! @header GrowlDefinesInternal.h
|
|
* @abstract Defines internal Growl macros and types.
|
|
* @ignore ATTRIBUTE_PACKED
|
|
* @discussion These constants are used both by GrowlHelperApp and by plug-ins.
|
|
*
|
|
* Notification keys (used in GrowlHelperApp, in GrowlApplicationBridge, and
|
|
* by applications that don't use GrowlApplicationBridge) are defined in
|
|
* GrowlDefines.h.
|
|
*/
|
|
|
|
/*!
|
|
* @defined NSInteger
|
|
* @abstract Typedef to int so Growl will compile on pre-10.5 SDKs.
|
|
*/
|
|
#ifndef NSINTEGER_DEFINED
|
|
typedef int NSInteger;
|
|
typedef unsigned int NSUInteger;
|
|
#define NSINTEGER_DEFINED
|
|
#endif
|
|
|
|
/*!
|
|
* @defined CGFloat
|
|
* @abstract Typedef to float so Growl will compile on pre-10.5 SDKs.
|
|
*/
|
|
#ifndef CGFLOAT_DEFINED
|
|
typedef float CGFloat;
|
|
#define CGFLOAT_IS_DOUBLE 0
|
|
#define CGFLOAT_DEFINED
|
|
#endif
|
|
|
|
/*!
|
|
* @defined GrowlCGFloatCeiling()
|
|
* @abstract Macro for the ceil() function that uses a different precision depending on the CPU architecture.
|
|
*/
|
|
/*!
|
|
* @defined GrowlCGFloatAbsoluteValue()
|
|
* @abstract Macro for the fabs() function that uses a different precision depending on the CPU architecture.
|
|
*/
|
|
/*!
|
|
* @defined GrowlCGFloatFloor()
|
|
* @abstract Macro for the floor() function that uses a different precision depending on the CPU architecture.
|
|
*/
|
|
#if CGFLOAT_IS_DOUBLE
|
|
#define GrowlCGFloatCeiling(x) ceil(x)
|
|
#define GrowlCGFloatAbsoluteValue(x) fabs(x)
|
|
#define GrowlCGFloatFloor(x) floor(x)
|
|
#else
|
|
#define GrowlCGFloatCeiling(x) ceilf(x)
|
|
#define GrowlCGFloatAbsoluteValue(x) fabsf(x)
|
|
#define GrowlCGFloatFloor(x) floorf(x)
|
|
#endif
|
|
|
|
/*! @defined GROWL_TCP_PORT
|
|
* @abstract The TCP listen port for Growl notification servers.
|
|
*/
|
|
#define GROWL_TCP_PORT 23052
|
|
|
|
/*! @defined GROWL_UDP_PORT
|
|
* @abstract The UDP listen port for Growl notification servers.
|
|
*/
|
|
#define GROWL_UDP_PORT 9887
|
|
|
|
/*! @defined GROWL_PROTOCOL_VERSION
|
|
* @abstract The current version of the Growl network-notifications protocol (without encryption).
|
|
*/
|
|
#define GROWL_PROTOCOL_VERSION 1
|
|
|
|
/*! @defined GROWL_PROTOCOL_VERSION_AES128
|
|
* @abstract The current version of the Growl network-notifications protocol (with AES-128 encryption).
|
|
*/
|
|
#define GROWL_PROTOCOL_VERSION_AES128 2
|
|
|
|
/*! @defined GROWL_TYPE_REGISTRATION
|
|
* @abstract The packet type of registration packets with MD5 authentication.
|
|
*/
|
|
#define GROWL_TYPE_REGISTRATION 0
|
|
/*! @defined GROWL_TYPE_NOTIFICATION
|
|
* @abstract The packet type of notification packets with MD5 authentication.
|
|
*/
|
|
#define GROWL_TYPE_NOTIFICATION 1
|
|
/*! @defined GROWL_TYPE_REGISTRATION_SHA256
|
|
* @abstract The packet type of registration packets with SHA-256 authentication.
|
|
*/
|
|
#define GROWL_TYPE_REGISTRATION_SHA256 2
|
|
/*! @defined GROWL_TYPE_NOTIFICATION_SHA256
|
|
* @abstract The packet type of notification packets with SHA-256 authentication.
|
|
*/
|
|
#define GROWL_TYPE_NOTIFICATION_SHA256 3
|
|
/*! @defined GROWL_TYPE_REGISTRATION_NOAUTH
|
|
* @abstract The packet type of registration packets without authentication.
|
|
*/
|
|
#define GROWL_TYPE_REGISTRATION_NOAUTH 4
|
|
/*! @defined GROWL_TYPE_NOTIFICATION_NOAUTH
|
|
* @abstract The packet type of notification packets without authentication.
|
|
*/
|
|
#define GROWL_TYPE_NOTIFICATION_NOAUTH 5
|
|
|
|
#define ATTRIBUTE_PACKED __attribute((packed))
|
|
|
|
/*! @struct GrowlNetworkPacket
|
|
* @abstract This struct is a header common to all incoming Growl network
|
|
* packets which identifies the type and version of the packet.
|
|
*/
|
|
struct GrowlNetworkPacket {
|
|
unsigned char version;
|
|
unsigned char type;
|
|
} ATTRIBUTE_PACKED;
|
|
|
|
/*!
|
|
* @struct GrowlNetworkRegistration
|
|
* @abstract The format of a registration packet.
|
|
* @discussion A Growl client that wants to register with a Growl server sends
|
|
* a packet in this format.
|
|
* @field common The Growl packet header.
|
|
* @field appNameLen The name of the application that is registering.
|
|
* @field numAllNotifications The number of notifications in the list.
|
|
* @field numDefaultNotifications The number of notifications in the list that are enabled by default.
|
|
* @field data Variable-sized data.
|
|
*/
|
|
struct GrowlNetworkRegistration {
|
|
struct GrowlNetworkPacket common;
|
|
/* This name is used both internally and in the Growl
|
|
* preferences.
|
|
*
|
|
* The application name should remain stable between different versions
|
|
* and incarnations of your application.
|
|
* For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0"
|
|
* and "SurfWriter Lite" are not.
|
|
*
|
|
* In addition to being unsigned, the application name length is in
|
|
* network byte order.
|
|
*/
|
|
unsigned short appNameLen;
|
|
/* These names are used both internally and in the Growl
|
|
* preferences. For this reason, they should be human-readable.
|
|
*/
|
|
unsigned char numAllNotifications;
|
|
|
|
unsigned char numDefaultNotifications;
|
|
/* The variable-sized data of a registration is:
|
|
* - The application name, in UTF-8 encoding, for appNameLen bytes.
|
|
* - The list of all notification names.
|
|
* - The list of default notifications, as 8-bit unsigned indices into the list of all notifications.
|
|
* - The MD5/SHA256 checksum of all the data preceding the checksum.
|
|
*
|
|
* Each notification name is encoded as:
|
|
* - Length: two bytes, unsigned, network byte order.
|
|
* - Name: As many bytes of UTF-8-encoded text as the length says.
|
|
* And there are numAllNotifications of these.
|
|
*/
|
|
unsigned char data[];
|
|
} ATTRIBUTE_PACKED;
|
|
|
|
/*!
|
|
* @struct GrowlNetworkNotification
|
|
* @abstract The format of a notification packet.
|
|
* @discussion A Growl client that wants to post a notification to a Growl
|
|
* server sends a packet in this format.
|
|
* @field common The Growl packet header.
|
|
* @field flags The priority number and the sticky bit.
|
|
* @field nameLen The length of the notification name.
|
|
* @field titleLen The length of the notification title.
|
|
* @field descriptionLen The length of the notification description.
|
|
* @field appNameLen The length of the application name.
|
|
* @field data Variable-sized data.
|
|
*/
|
|
struct GrowlNetworkNotification {
|
|
struct GrowlNetworkPacket common;
|
|
/*!
|
|
* @struct GrowlNetworkNotificationFlags
|
|
* @abstract Various flags.
|
|
* @discussion This 16-bit packed structure contains the priority as a
|
|
* signed 3-bit integer from -2 to +2, and the sticky flag as a single bit.
|
|
* The high 12 bits of the structure are reserved for future use.
|
|
* @field reserved reserved for future use.
|
|
* @field priority the priority as a signed 3-bit integer from -2 to +2.
|
|
* @field sticky the sticky flag.
|
|
*/
|
|
struct GrowlNetworkNotificationFlags {
|
|
#ifdef __BIG_ENDIAN__
|
|
unsigned reserved: 12;
|
|
signed priority: 3;
|
|
unsigned sticky: 1;
|
|
#else
|
|
unsigned sticky: 1;
|
|
signed priority: 3;
|
|
unsigned reserved: 12;
|
|
#endif
|
|
} ATTRIBUTE_PACKED flags; //size = 16 (12 + 3 + 1)
|
|
|
|
/* In addition to being unsigned, the notification name length
|
|
* is in network byte order.
|
|
*/
|
|
unsigned short nameLen;
|
|
/* @discussion In addition to being unsigned, the title length is in
|
|
* network byte order.
|
|
*/
|
|
unsigned short titleLen;
|
|
/* In addition to being unsigned, the description length is in
|
|
* network byte order.
|
|
*/
|
|
unsigned short descriptionLen;
|
|
/* In addition to being unsigned, the application name length
|
|
* is in network byte order.
|
|
*/
|
|
unsigned short appNameLen;
|
|
/* The variable-sized data of a notification is:
|
|
* - Notification name, in UTF-8 encoding, for nameLen bytes.
|
|
* - Title, in UTF-8 encoding, for titleLen bytes.
|
|
* - Description, in UTF-8 encoding, for descriptionLen bytes.
|
|
* - Application name, in UTF-8 encoding, for appNameLen bytes.
|
|
* - The MD5/SHA256 checksum of all the data preceding the checksum.
|
|
*/
|
|
unsigned char data[];
|
|
} ATTRIBUTE_PACKED;
|
|
|
|
/*! @defined GrowlEnabledKey
|
|
* @abstract Preference key controlling whether Growl is enabled.
|
|
* @discussion If this is false, then when GrowlHelperApp is launched to open
|
|
* a Growl registration dictionary file, GrowlHelperApp will quit when it has
|
|
* finished processing the file instead of listening for notifications.
|
|
*/
|
|
#define GrowlEnabledKey XSTR("GrowlEnabled")
|
|
|
|
/*! @defined GROWL_SCREENSHOT_MODE
|
|
* @abstract Preference and notification key controlling whether to save a screenshot of the notification.
|
|
* @discussion This is for GHA's private usage. If your application puts this
|
|
* key into a notification dictionary, GHA will clobber it. This key is only
|
|
* allowed in the notification dictionaries GHA passes to displays.
|
|
*
|
|
* If this key contains an object whose boolValue is not NO, the display is
|
|
* asked to save a screenshot of the notification to
|
|
* ~/Library/Application\ Support/Growl/Screenshots.
|
|
*/
|
|
#define GROWL_SCREENSHOT_MODE XSTR("ScreenshotMode")
|
|
|
|
/*! @defined GROWL_APP_LOCATION
|
|
* @abstract The location of this application.
|
|
* @discussion Contains either the POSIX path to the application, or a file-data dictionary (as used by the Dock).
|
|
* contains the file's alias record and its pathname.
|
|
*/
|
|
#define GROWL_APP_LOCATION XSTR("AppLocation")
|
|
|
|
/*! @defined GROWL_REMOTE_ADDRESS
|
|
* @abstract The address of the host who sent this notification/registration.
|
|
* @discussion Contains an NSData with the address of the remote host who
|
|
* sent this notification/registration.
|
|
*/
|
|
#define GROWL_REMOTE_ADDRESS XSTR("RemoteAddress")
|
|
|
|
/*!
|
|
* @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER
|
|
* @discussion The bundle identifier for the Growl preference pane.
|
|
*/
|
|
#define GROWL_PREFPANE_BUNDLE_IDENTIFIER XSTR("com.growl.prefpanel")
|
|
/*!
|
|
* @defined GROWL_HELPERAPP_BUNDLE_IDENTIFIER
|
|
* @discussion The bundle identifier for the Growl background application (GrowlHelperApp).
|
|
*/
|
|
#define GROWL_HELPERAPP_BUNDLE_IDENTIFIER XSTR("com.Growl.GrowlHelperApp")
|
|
|
|
/*!
|
|
* @defined GROWL_PREFPANE_NAME
|
|
* @discussion The file name of the Growl preference pane.
|
|
*/
|
|
#define GROWL_PREFPANE_NAME XSTR("Growl.prefPane")
|
|
#define PREFERENCE_PANES_SUBFOLDER_OF_LIBRARY XSTR("PreferencePanes")
|
|
#define PREFERENCE_PANE_EXTENSION XSTR("prefPane")
|
|
|
|
//plug-in bundle filename extensions
|
|
#define GROWL_PLUGIN_EXTENSION XSTR("growlPlugin")
|
|
#define GROWL_PATHWAY_EXTENSION XSTR("growlPathway")
|
|
#define GROWL_VIEW_EXTENSION XSTR("growlView")
|
|
#define GROWL_STYLE_EXTENSION XSTR("growlStyle")
|
|
#define GROWL_PATHEXTENSION_TICKET XSTR("growlTicket")
|
|
|
|
/* --- These following macros are intended for plug-ins --- */
|
|
|
|
/*! @function SYNCHRONIZE_GROWL_PREFS
|
|
* @abstract Synchronizes Growl prefs so they're up-to-date.
|
|
* @discussion This macro is intended for use by GrowlHelperApp and by
|
|
* plug-ins (when the prefpane is selected).
|
|
*/
|
|
#define SYNCHRONIZE_GROWL_PREFS() CFPreferencesAppSynchronize(CFSTR("com.Growl.GrowlHelperApp"))
|
|
|
|
/*! @function UPDATE_GROWL_PREFS
|
|
* @abstract Tells GrowlHelperApp to update its prefs.
|
|
* @discussion This macro is intended for use by plug-ins.
|
|
* It sends a notification to tell GrowlHelperApp to update its preferences.
|
|
*/
|
|
#define UPDATE_GROWL_PREFS() do { \
|
|
SYNCHRONIZE_GROWL_PREFS(); \
|
|
CFStringRef _key = CFSTR("pid"); \
|
|
int pid = getpid(); \
|
|
CFNumberRef _value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); \
|
|
CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&_key, (const void **)&_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); \
|
|
CFRelease(_value); \
|
|
CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), \
|
|
CFSTR("GrowlPreferencesChanged"), \
|
|
CFSTR("GrowlUserDefaults"), \
|
|
userInfo, false); \
|
|
CFRelease(userInfo); \
|
|
} while(0)
|
|
|
|
/*! @function READ_GROWL_PREF_VALUE
|
|
* @abstract Reads the given pref value from the plug-in's preferences.
|
|
* @discussion This macro is intended for use by plug-ins. It reads the value for the
|
|
* given key from the plug-in's preferences (which are stored in a dictionary inside of
|
|
* GrowlHelperApp's prefs).
|
|
* @param key The preference key to read the value of.
|
|
* @param domain The bundle ID of the plug-in.
|
|
* @param type The type of the result expected.
|
|
* @param result A pointer to an id. Set to the value if exists, left unchanged if not.
|
|
*
|
|
* If the value is set, you are responsible for releasing it.
|
|
*/
|
|
#define READ_GROWL_PREF_VALUE(key, domain, type, result) do {\
|
|
CFDictionaryRef prefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
|
|
CFSTR("com.Growl.GrowlHelperApp")); \
|
|
if (prefs) {\
|
|
if (CFDictionaryContainsKey(prefs, key)) {\
|
|
*result = (type)CFDictionaryGetValue(prefs, key); \
|
|
CFRetain(*result); \
|
|
} \
|
|
CFRelease(prefs); } \
|
|
} while(0)
|
|
|
|
/*! @function WRITE_GROWL_PREF_VALUE
|
|
* @abstract Writes the given pref value to the plug-in's preferences.
|
|
* @discussion This macro is intended for use by plug-ins. It writes the given
|
|
* value to the plug-in's preferences.
|
|
* @param key The preference key to write the value of.
|
|
* @param value The value to write to the preferences. It should be either a
|
|
* CoreFoundation type or toll-free bridged with one.
|
|
* @param domain The bundle ID of the plug-in.
|
|
*/
|
|
#define WRITE_GROWL_PREF_VALUE(key, value, domain) do {\
|
|
CFDictionaryRef staticPrefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
|
|
CFSTR("com.Growl.GrowlHelperApp")); \
|
|
CFMutableDictionaryRef prefs; \
|
|
if (staticPrefs == NULL) {\
|
|
prefs = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); \
|
|
} else {\
|
|
prefs = CFDictionaryCreateMutableCopy(NULL, 0, staticPrefs); \
|
|
CFRelease(staticPrefs); \
|
|
}\
|
|
CFDictionarySetValue(prefs, key, value); \
|
|
CFPreferencesSetAppValue((CFStringRef)domain, prefs, CFSTR("com.Growl.GrowlHelperApp")); \
|
|
CFRelease(prefs); } while(0)
|
|
|
|
/*! @function READ_GROWL_PREF_BOOL
|
|
* @abstract Reads the given Boolean from the plug-in's preferences.
|
|
* @discussion This is a wrapper around READ_GROWL_PREF_VALUE() intended for
|
|
* use with Booleans.
|
|
* @param key The preference key to read the Boolean from.
|
|
* @param domain The bundle ID of the plug-in.
|
|
* @param result A pointer to a Boolean type. Left unchanged if the value doesn't exist.
|
|
*/
|
|
#define READ_GROWL_PREF_BOOL(key, domain, result) do {\
|
|
CFBooleanRef boolValue = NULL; \
|
|
READ_GROWL_PREF_VALUE(key, domain, CFBooleanRef, &boolValue); \
|
|
if (boolValue) {\
|
|
*result = CFBooleanGetValue(boolValue); \
|
|
CFRelease(boolValue); \
|
|
} } while(0)
|
|
|
|
/*! @function WRITE_GROWL_PREF_BOOL
|
|
* @abstract Writes the given Boolean to the plug-in's preferences.
|
|
* @discussion This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
|
|
* use with Booleans.
|
|
* @param key The preference key to write the Boolean for.
|
|
* @param value The Boolean value to write to the preferences.
|
|
* @param domain The bundle ID of the plug-in.
|
|
*/
|
|
#define WRITE_GROWL_PREF_BOOL(key, value, domain) do {\
|
|
WRITE_GROWL_PREF_VALUE(key, value ? kCFBooleanTrue : kCFBooleanFalse, domain); } while(0)
|
|
|
|
/*! @function READ_GROWL_PREF_INT
|
|
* @abstract Reads the given integer from the plug-in's preferences.
|
|
* @discussion This is a wrapper around READ_GROWL_PREF_VALUE() intended for
|
|
* use with integers.
|
|
* @param key The preference key to read the integer from.
|
|
* @param domain The bundle ID of the plug-in.
|
|
* @param result A pointer to an integer. Leaves unchanged if the value doesn't exist.
|
|
*/
|
|
#define READ_GROWL_PREF_INT(key, domain, result) do {\
|
|
CFNumberRef intValue = NULL; \
|
|
READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &intValue); \
|
|
if (intValue) {\
|
|
CFNumberGetValue(intValue, kCFNumberIntType, result); \
|
|
CFRelease(intValue); \
|
|
} } while(0)
|
|
|
|
/*! @function WRITE_GROWL_PREF_INT
|
|
* @abstract Writes the given integer to the plug-in's preferences.
|
|
* @discussion This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
|
|
* use with integers.
|
|
* @param key The preference key to write the integer for.
|
|
* @param value The integer value to write to the preferences.
|
|
* @param domain The bundle ID of the plug-in.
|
|
*/
|
|
#define WRITE_GROWL_PREF_INT(key, value, domain) do {\
|
|
CFNumberRef intValue = CFNumberCreate(NULL, kCFNumberIntType, &value); \
|
|
WRITE_GROWL_PREF_VALUE(key, intValue, domain); \
|
|
CFRelease(intValue); } while(0)
|
|
|
|
/*! @function READ_GROWL_PREF_FLOAT
|
|
* @abstract Reads the given float from the plug-in's preferences.
|
|
* @discussion This is a wrapper around READ_GROWL_PREF_VALUE() intended for
|
|
* use with floats.
|
|
* @param key The preference key to read the float from.
|
|
* @param domain The bundle ID of the plug-in.
|
|
* @param result A pointer to a float. Leaves unchanged if the value doesn't exist.
|
|
*/
|
|
#ifdef __LP64__
|
|
#define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
|
|
CFNumberRef floatValue = NULL; \
|
|
READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
|
|
if (floatValue) {\
|
|
CFNumberGetValue(floatValue, kCFNumberCGFloatType, result); \
|
|
CFRelease(floatValue); \
|
|
} } while(0)
|
|
#else
|
|
#define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
|
|
CFNumberRef floatValue = NULL; \
|
|
READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
|
|
if (floatValue) {\
|
|
CFNumberGetValue(floatValue, kCFNumberFloatType, result); \
|
|
CFRelease(floatValue); \
|
|
} } while(0)
|
|
#endif
|
|
|
|
/*! @function WRITE_GROWL_PREF_FLOAT
|
|
* @abstract Writes the given float to the plug-in's preferences.
|
|
* @discussion This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
|
|
* use with floats.
|
|
* @param key The preference key to write the float for.
|
|
* @param value The float value to write to the preferences.
|
|
* @param domain The bundle ID of the plug-in.
|
|
*/
|
|
#ifdef __LP64__
|
|
#define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
|
|
CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberCGFloatType, &value); \
|
|
WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
|
|
CFRelease(floatValue); } while(0)
|
|
#else
|
|
#define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
|
|
CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberFloatType, &value); \
|
|
WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
|
|
CFRelease(floatValue); } while(0)
|
|
#endif
|
|
|
|
|
|
/*! @defined GROWL_CLOSE_ALL_NOTIFICATIONS
|
|
* @abstract Notification to close all Growl notifications
|
|
* @discussion Should be posted to the default notification center when a close widget is option+clicked.
|
|
* All notifications should close in response.
|
|
*/
|
|
#define GROWL_CLOSE_ALL_NOTIFICATIONS XSTR("GrowlCloseAllNotifications")
|
|
|
|
#pragma mark Small utilities
|
|
|
|
/*!
|
|
* @defined FLOAT_EQ(x,y)
|
|
* @abstract Compares two floats.
|
|
*/
|
|
#define FLOAT_EQ(x,y) (((y - FLT_EPSILON) < x) && (x < (y + FLT_EPSILON)))
|
|
|
|
#endif //ndef _GROWL_GROWLDEFINESINTERNAL_H
|