diff --git a/tests/testcpuinfo.pas b/tests/testcpuinfo.pas new file mode 100644 index 0000000..72cf8c2 --- /dev/null +++ b/tests/testcpuinfo.pas @@ -0,0 +1,38 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{ Test CPU Info routines } + +program testcpuinfo; + +uses + SDL3; + +begin + + SDL_Log('SDL_GetNumLogicalCPUCores: %d',[SDL_GetNumLogicalCPUCores]); + SDL_Log('SDL_GetCPUCacheLineSize: %d',[SDL_GetCPUCacheLineSize]); + SDL_Log('SDL_HasAltiVec: %d',[SDL_HasAltiVec]); + SDL_Log('SDL_HasMMX: %d',[SDL_HasMMX]); + SDL_Log('SDL_HasSSE: %d',[SDL_HasSSE]); + SDL_Log('SDL_HasSSE2: %d',[SDL_HasSSE2]); + SDL_Log('SDL_HasSSE3: %d',[SDL_HasSSE3]); + SDL_Log('SDL_HasSSE41: %d',[SDL_HasSSE41]); + SDL_Log('SDL_HasSSE42: %d',[SDL_HasSSE42]); + SDL_Log('SDL_HasAVX: %d',[SDL_HasAVX]); + SDL_Log('SDL_HasAVX2: %d',[SDL_HasAVX2]); + SDL_Log('SDL_HasAVX512F: %d',[SDL_HasAVX512F]); + SDL_Log('SDL_HasARMSIMD: %d',[SDL_HasARMSIMD]); + SDL_Log('SDL_HasNEON: %d',[SDL_HasNEON]); + SDL_Log('SDL_HasLSX: %d',[SDL_HasLSX]); + SDL_Log('SDL_HasLASX: %d',[SDL_HasLASX]); + SDL_Log('SDL_GetSystemRAM: %d',[SDL_GetSystemRAM]); + SDL_Log('SDL_GetSIMDAlignment: %d',[SDL_GetSIMDAlignment]); + +end. + diff --git a/units/SDL3.pas b/units/SDL3.pas index 0098a6d..8057ca9 100644 --- a/units/SDL3.pas +++ b/units/SDL3.pas @@ -103,6 +103,11 @@ interface {$I SDL_camera.inc} // 3.1.6-prev {$I SDL_events.inc} // 3.1.6-prev {$I SDL_render.inc} // 3.1.6-prev +{$I SDL_clipboard.inc} // 3.2.0 +{$I SDL_cpuinfo.inc} // 3.2.0 +{$I SDL_dialog.inc} // 3.2.0 +{$I SDL_time.inc} // 3.2.0 +{$I SDL_filesystem.inc} // 3.2.0 implementation diff --git a/units/SDL_clipboard.inc b/units/SDL_clipboard.inc new file mode 100644 index 0000000..2f96ac6 --- /dev/null +++ b/units/SDL_clipboard.inc @@ -0,0 +1,312 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{* + * # CategoryClipboard + * + * SDL provides access to the system clipboard, both for reading information + * from other processes and publishing information of its own. + * + * This is not just text! SDL apps can access and publish data by mimetype. + * + * ## Basic use (text) + * + * Obtaining and publishing simple text to the system clipboard is as easy as + * calling SDL_GetClipboardText() and SDL_SetClipboardText(), respectively. + * These deal with C strings in UTF-8 encoding. Data transmission and encoding + * conversion is completely managed by SDL. + * + * ## Clipboard callbacks (data other than text) + * + * Things get more complicated when the clipboard contains something other + * than text. Not only can the system clipboard contain data of any type, in + * some cases it can contain the same data in different formats! For example, + * an image painting app might let the user copy a graphic to the clipboard, + * and offers it in .BMP, .JPG, or .PNG format for other apps to consume. + * + * Obtaining clipboard data ("pasting") like this is a matter of calling + * SDL_GetClipboardData() and telling it the mimetype of the data you want. + * But how does one know if that format is available? SDL_HasClipboardData() + * can report if a specific mimetype is offered, and + * SDL_GetClipboardMimeTypes() can provide the entire list of mimetypes + * available, so the app can decide what to do with the data and what formats + * it can support. + * + * Setting the clipboard ("copying") to arbitrary data is done with + * SDL_SetClipboardData. The app does not provide the data in this call, but + * rather the mimetypes it is willing to provide and a callback function. + * During the callback, the app will generate the data. This allows massive + * data sets to be provided to the clipboard, without any data being copied + * before it is explicitly requested. More specifically, it allows an app to + * offer data in multiple formats without providing a copy of all of them + * upfront. If the app has an image that it could provide in PNG or JPG + * format, it doesn't have to encode it to either of those unless and until + * something tries to paste it. + * + * ## Primary Selection + * + * The X11 and Wayland video targets have a concept of the "primary selection" + * in addition to the usual clipboard. This is generally highlighted (but not + * explicitly copied) text from various apps. SDL offers APIs for this through + * SDL_GetPrimarySelectionText() and SDL_SetPrimarySelectionText(). SDL offers + * these APIs on platforms without this concept, too, but only so far that it + * will keep a copy of a string that the app sets for later retrieval; the + * operating system will not ever attempt to change the string externally if + * it doesn't support a primary selection. + } + +{ Function prototypes } + +{* + * Put UTF-8 text into the clipboard. + * + * \param text the text to store in the clipboard. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_GetClipboardText + * \sa SDL_HasClipboardText + } +function SDL_SetClipboardText(text: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_SetClipboardText' {$ENDIF} {$ENDIF}; + +{* + * Get UTF-8 text from the clipboard. + * + * This functions returns an empty string if there was not enough memory left + * for a copy of the clipboard's content. + * + * \returns the clipboard text on success or an empty string on failure; call + * SDL_GetError() for more information. This should be freed with + * SDL_free() when it is no longer needed. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasClipboardText + * \sa SDL_SetClipboardText + } +function SDL_GetClipboardText: PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetClipboardText' {$ENDIF} {$ENDIF}; + +{* + * Query whether the clipboard exists and contains a non-empty text string. + * + * \returns true if the clipboard has text, or false if it does not. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_GetClipboardText + * \sa SDL_SetClipboardText + } +function SDL_HasClipboardText: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasClipboardText' {$ENDIF} {$ENDIF}; + +{* + * Put UTF-8 text into the primary selection. + * + * \param text the text to store in the primary selection. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_GetPrimarySelectionText + * \sa SDL_HasPrimarySelectionText + } +function SDL_SetPrimarySelectionText(text: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_SetPrimarySelectionText' {$ENDIF} {$ENDIF}; + +{* + * Get UTF-8 text from the primary selection. + * + * This functions returns an empty string if there was not enough memory left + * for a copy of the primary selection's content. + * + * \returns the primary selection text on success or an empty string on + * failure; call SDL_GetError() for more information. This should be + * freed with SDL_free() when it is no longer needed. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasPrimarySelectionText + * \sa SDL_SetPrimarySelectionText + } +function SDL_GetPrimarySelectionText: PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetPrimarySelectionText' {$ENDIF} {$ENDIF}; + +{* + * Query whether the primary selection exists and contains a non-empty text + * string. + * + * \returns true if the primary selection has text, or false if it does not. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_GetPrimarySelectionText + * \sa SDL_SetPrimarySelectionText + } +function SDL_HasPrimarySelectionText: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasPrimarySelectionText' {$ENDIF} {$ENDIF}; + +{* + * Callback function that will be called when data for the specified mime-type + * is requested by the OS. + * + * The callback function is called with nil as the mime_type when the + * clipboard is cleared or new data is set. The clipboard is automatically + * cleared in SDL_Quit(). + * + * \param userdata a Pointer to provided user data. + * \param mime_type the requested mime-type. + * \param size a Pointer filled in with the length of the returned data. + * \returns a Pointer to the data for the provided mime-type. Returning nil + * or setting length to 0 will cause no data to be sent to the + * "receiver". It is up to the receiver to handle this. Essentially + * returning no data is more or less undefined behavior and may cause + * breakage in receiving applications. The returned data will not be + * freed so it needs to be retained and dealt with internally. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetClipboardData + } +type + TSDL_ClipboardDataCallback = function(userdata: Pointer; mime_type: PAnsiChar; size: pcsize_t): Pointer; cdecl; + +{* + * Callback function that will be called when the clipboard is cleared, or new + * data is set. + * + * \param userdata a Pointer to provided user data. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetClipboardData + } +type + TSDL_ClipboardCleanupCallback = procedure(userdata: Pointer); cdecl; + +{* + * Offer clipboard data to the OS. + * + * Tell the operating system that the application is offering clipboard data + * for each of the proivded mime-types. Once another application requests the + * data the callback function will be called allowing it to generate and + * respond with the data for the requested mime-type. + * + * The size of text data does not include any terminator, and the text does + * not need to be null terminated (e.g. you can directly copy a portion of a + * document) + * + * \param callback a function Pointer to the function that provides the + * clipboard data. + * \param cleanup a function Pointer to the function that cleans up the + * clipboard data. + * \param userdata an opaque Pointer that will be forwarded to the callbacks. + * \param mime_types a list of mime-types that are being offered. + * \param num_mime_types the number of mime-types in the mime_types list. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_ClearClipboardData + * \sa SDL_GetClipboardData + * \sa SDL_HasClipboardData + } +function SDL_SetClipboardData(callback: TSDL_ClipboardDataCallback; cleanup: TSDL_ClipboardCleanupCallback; userdata: Pointer; mime_types: PPAnsiChar; num_mime_types: csize_t): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_SetClipboardData' {$ENDIF} {$ENDIF}; + +{* + * Clear the clipboard data. + * + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetClipboardData + } +function SDL_ClearClipboardData: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_ClearClipboardData' {$ENDIF} {$ENDIF}; + +{* + * Get the data from clipboard for a given mime type. + * + * The size of text data does not include the terminator, but the text is + * guaranteed to be null terminated. + * + * \param mime_type the mime type to read from the clipboard. + * \param size a Pointer filled in with the length of the returned data. + * \returns the retrieved data buffer or nil on failure; call SDL_GetError() + * for more information. This should be freed with SDL_free() when it + * is no longer needed. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasClipboardData + * \sa SDL_SetClipboardData + } +function SDL_GetClipboardData(mime_type: PAnsiChar; size: pcsize_t): Pointer; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetClipboardData' {$ENDIF} {$ENDIF}; + +{* + * Query whether there is data in the clipboard for the provided mime type. + * + * \param mime_type the mime type to check for data for. + * \returns true if there exists data in clipboard for the provided mime type, + * false if it does not. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetClipboardData + * \sa SDL_GetClipboardData + } +function SDL_HasClipboardData(mime_type: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasClipboardData' {$ENDIF} {$ENDIF}; + +{* + * Retrieve the list of mime types available in the clipboard. + * + * \param num_mime_types a Pointer filled with the number of mime types, may + * be nil. + * \returns a null terminated array of strings with mime types, or nil on + * failure; call SDL_GetError() for more information. This should be + * freed with SDL_free() when it is no longer needed. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetClipboardData + } +function SDL_GetClipboardMimeTypes(num_mime_types: pcsize_t):PPAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetClipboardMimeTypes' {$ENDIF} {$ENDIF}; + diff --git a/units/SDL_cpuinfo.inc b/units/SDL_cpuinfo.inc new file mode 100644 index 0000000..6b18ba2 --- /dev/null +++ b/units/SDL_cpuinfo.inc @@ -0,0 +1,339 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{* + * # CategoryCPUInfo + * + * CPU feature detection for SDL. + * + * These functions are largely concerned with reporting if the system has + * access to various SIMD instruction sets, but also has other important info + * to share, such as system RAM size and number of logical CPU cores. + * + * CPU instruction set checks, like SDL_HasSSE() and SDL_HasNEON(), are + * available on all platforms, even if they don't make sense (an ARM processor + * will never have SSE and an x86 processor will never have NEON, for example, + * but these functions still exist and will simply return false in these + * cases). + } + +{* + * A guess for the cacheline size used for padding. + * + * Most x86 processors have a 64 byte cache line. The 64-bit PowerPC + * processors have a 128 byte cache line. We use the larger value to be + * generally safe. + * + * \since This macro is available since SDL 3.1.3. + } +const + SDL_CACHELINE_SIZE = 128; + +{* + * Get the number of logical CPU cores available. + * + * \returns the total number of logical CPU cores. On CPUs that include + * technologies such as hyperthreading, the number of logical cores + * may be more than the number of physical cores. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_GetNumLogicalCPUCores: cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetNumLogicalCPUCores' {$ENDIF} {$ENDIF}; + +{* + * Determine the L1 cache line size of the CPU. + * + * This is useful for determining multi-threaded structure padding or SIMD + * prefetch sizes. + * + * \returns the L1 cache line size of the CPU, in bytes. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_GetCPUCacheLineSize: cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetCPUCacheLineSize' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has AltiVec features. + * + * This always returns false on CPUs that aren't using PowerPC instruction + * sets. + * + * \returns true if the CPU has AltiVec features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_HasAltiVec: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasAltiVec' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has MMX features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has MMX features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_HasMMX: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasMMX' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has SSE features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has SSE features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 + } +function SDL_HasSSE: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasSSE' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has SSE2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has SSE2 features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasSSE + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 + } +function SDL_HasSSE2: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasSSE2' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has SSE3 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has SSE3 features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 + } +function SDL_HasSSE3: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasSSE3' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has SSE4.1 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has SSE4.1 features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE42 + } +function SDL_HasSSE41: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasSSE41' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has SSE4.2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has SSE4.2 features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + } +function SDL_HasSSE42: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasSSE42' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has AVX features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has AVX features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasAVX2 + * \sa SDL_HasAVX512F + } +function SDL_HasAVX: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasAVX' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has AVX2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has AVX2 features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasAVX + * \sa SDL_HasAVX512F + } +function SDL_HasAVX2: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasAVX2' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has AVX-512F (foundation) features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns true if the CPU has AVX-512F features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + } +function SDL_HasAVX512F: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasAVX512F' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has ARM SIMD (ARMv6) features. + * + * This is different from ARM NEON, which is a different instruction set. + * + * This always returns false on CPUs that aren't using ARM instruction sets. + * + * \returns true if the CPU has ARM SIMD features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_HasNEON + } +function SDL_HasARMSIMD: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasARMSIMD' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has NEON (ARM SIMD) features. + * + * This always returns false on CPUs that aren't using ARM instruction sets. + * + * \returns true if the CPU has ARM NEON features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_HasNEON: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasNEON' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has LSX (LOONGARCH SIMD) features. + * + * This always returns false on CPUs that aren't using LOONGARCH instruction + * sets. + * + * \returns true if the CPU has LOONGARCH LSX features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_HasLSX: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasLSX' {$ENDIF} {$ENDIF}; + +{* + * Determine whether the CPU has LASX (LOONGARCH SIMD) features. + * + * This always returns false on CPUs that aren't using LOONGARCH instruction + * sets. + * + * \returns true if the CPU has LOONGARCH LASX features or false if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_HasLASX: cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_HasLASX' {$ENDIF} {$ENDIF}; + +{* + * Get the amount of RAM configured in the system. + * + * \returns the amount of RAM configured in the system in MiB. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + } +function SDL_GetSystemRAM: cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetSystemRAM' {$ENDIF} {$ENDIF}; + +{* + * Report the alignment this system needs for SIMD allocations. + * + * This will return the minimum number of bytes to which a Pointer must be + * aligned to be compatible with SIMD instructions on the current machine. For + * example, if the machine supports SSE only, it will return 16, but if it + * supports AVX-512F, it'll return 64 (etc). This only reports values for + * instruction sets SDL knows about, so if your SDL build doesn't have + * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and + * not 64 for the AVX-512 instructions that exist but SDL doesn't know about. + * Plan accordingly. + * + * \returns the alignment in bytes needed for available, known SIMD + * instructions. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_aligned_alloc + * \sa SDL_aligned_free + } +function SDL_GetSIMDAlignment: csize_t; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetSIMDAlignment' {$ENDIF} {$ENDIF}; + diff --git a/units/SDL_dialog.inc b/units/SDL_dialog.inc new file mode 100644 index 0000000..58d7561 --- /dev/null +++ b/units/SDL_dialog.inc @@ -0,0 +1,317 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{* +* # CategoryDialog +* +* File dialog support. +* +* SDL offers file dialogs, to let users select files with native GUI +* interfaces. There are "open" dialogs, "save" dialogs, and folder selection +* dialogs. The app can control some details, such as filtering to specific +* files, or whether multiple files can be selected by the user. +* +* Note that launching a file dialog is a non-blocking operation; control +* returns to the app immediately, and a callback is called later (possibly in +* another thread) when the user makes a choice. + } + +{* + * An entry for filters for file dialogs. + * + * `name` is a user-readable label for the filter (for example, "Office + * document"). + * + * `pattern` is a semicolon-separated list of file extensions (for example, + * "doc;docx"). File extensions may only contain alphanumeric characters, + * hyphens, underscores and periods. Alternatively, the whole string can be a + * single asterisk ("*"), which serves as an "All files" filter. + * + * \since This struct is available since SDL 3.1.3. + * + * \sa SDL_DialogFileCallback + * \sa SDL_ShowOpenFileDialog + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + } +type + PPSDL_DialogFileFilter = ^PSDL_DialogFileFilter; + PSDL_DialogFileFilter = ^TSDL_DialogFileFilter; + TSDL_DialogFileFilter = record + name: PAnsiChar; + pattern: PAnsiChar; + end; + +{* + * Callback used by file dialog functions. + * + * The specific usage is described in each function. + * + * If `filelist` is: + * + * - nil, an error occurred. Details can be obtained with SDL_GetError(). + * - A Pointer to nil, the user either didn't choose any file or canceled the + * dialog. + * - A Pointer to non-`nil`, the user chose one or more files. The argument + * is a null-terminated list of pointers to C strings, each containing a + * path. + * + * The filelist argument does not need to be freed; it will automatically be + * freed when the callback returns. + * + * The filter argument is the index of the filter that was selected, or -1 if + * no filter was selected or if the platform or method doesn't support + * fetching the selected filter. + * + * \param userdata an app-provided Pointer, for the callback's use. + * \param filelist the file(s) chosen by the user. + * \param filter index of the selected filter. + * + * \since This datatype is available since SDL 3.1.3. + * + * \sa SDL_DialogFileFilter + * \sa SDL_ShowOpenFileDialog + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + } +type + TSDL_DialogFileCallback = procedure(userdata: Pointer; filelist: PPAnsiChar; filter: cint); cdecl; + + {* + * Displays a dialog that lets the user select a file on their filesystem. + * + * This function should only be invoked from the main thread. + * + * This is an asynchronous function; it will return immediately, and the + * result will be passed to the callback. + * + * The callback will be invoked with a null-terminated list of files the user + * chose. The list will be empty if the user canceled the dialog, and it will + * be nil if an error occurred. + * + * Note that the callback may be called from a different thread than the one + * the function was invoked on. + * + * Depending on the platform, the user may be allowed to input paths that + * don't yet exist. + * + * On Linux, dialogs may require XDG Portals, which requires DBus, which + * requires an event-handling loop. Apps that do not use SDL to handle events + * should add a call to SDL_PumpEvents in their main loop. + * + * \param callback an SDL_DialogFileCallback to be invoked when the user + * selects a file and accepts, or cancels the dialog, or an + * error occurs. The first argument is a null-terminated list + * of C strings, representing the paths chosen by the user. + * The list will be empty if the user canceled the dialog, and + * it will be nil if an error occurred. If an error occurred, + * it can be fetched with SDL_GetError(). The second argument + * is the userdata Pointer passed to the function. The third + * argument is the index of the filter selected by the user, + * or one past the index of the last filter (therefore the + * index of the terminating nil filter) if no filter was + * chosen, or -1 if the platform does not support detecting + * the selected filter. + * \param userdata an optional Pointer to pass extra data to the callback when + * it will be invoked. + * \param window the window that the dialog should be modal for, may be nil. + * Not all platforms support this option. + * \param filters a list of SDL_DialogFileFilter's, may be nil. Not all + * platforms support this option, and platforms that do support + * it may allow the user to ignore the filters. + * \param nfilters the number of filters. Ignored if filters is nil. + * \param default_location the default folder or file to start the dialog at, + * may be nil. Not all platforms support this option. + * \param allow_many if non-zero, the user will be allowed to select multiple + * entries. Not all platforms support this option. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_DialogFileCallback + * \sa SDL_DialogFileFilter + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + } +procedure SDL_ShowOpenFileDialog(callback: TSDL_DialogFileCallback; userdata: Pointer; window: PSDL_Window; filters: PSDL_DialogFileFilter; nfilters: cint; default_location: PAnsiChar; allow_many: cbool); cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_ShowOpenFileDialog' {$ENDIF} {$ENDIF}; + +{* +* Displays a dialog that lets the user choose a new or existing file on their +* filesystem. +* +* This is an asynchronous function; it will return immediately, and the +* result will be passed to the callback. +* +* The callback will be invoked with a null-terminated list of files the user +* chose. The list will be empty if the user canceled the dialog, and it will +* be NULL if an error occurred. +* +* Note that the callback may be called from a different thread than the one +* the function was invoked on. +* +* The chosen file may or may not already exist. +* +* On Linux, dialogs may require XDG Portals, which requires DBus, which +* requires an event-handling loop. Apps that do not use SDL to handle events +* should add a call to SDL_PumpEvents in their main loop. +* +* \param callback a function pointer to be invoked when the user selects a +* file and accepts, or cancels the dialog, or an error +* occurs. +* \param userdata an optional pointer to pass extra data to the callback when +* it will be invoked. +* \param window the window that the dialog should be modal for, may be NULL. +* Not all platforms support this option. +* \param filters a list of filters, may be NULL. Not all platforms support +* this option, and platforms that do support it may allow the +* user to ignore the filters. If non-NULL, it must remain +* valid at least until the callback is invoked. +* \param nfilters the number of filters. Ignored if filters is NULL. +* \param default_location the default folder or file to start the dialog at, +* may be NULL. Not all platforms support this option. +* +* \threadsafety This function should be called only from the main thread. The +* callback may be invoked from the same thread or from a +* different one, depending on the OS's constraints. +* +* \since This function is available since SDL 3.2.0. +* +* \sa SDL_DialogFileCallback +* \sa SDL_DialogFileFilter +* \sa SDL_ShowOpenFileDialog +* \sa SDL_ShowOpenFolderDialog +* \sa SDL_ShowFileDialogWithProperties + } +procedure SDL_ShowSaveFileDialog(callback: TSDL_DialogFileCallback; userdata: Pointer; window: PSDL_Window; filters: PSDL_DialogFileFilter; nfilters: cint; default_location: PAnsiChar); cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_ShowSaveFileDialog' {$ENDIF} {$ENDIF}; + +{* +* Displays a dialog that lets the user select a folder on their filesystem. +* +* This is an asynchronous function; it will return immediately, and the +* result will be passed to the callback. +* +* The callback will be invoked with a null-terminated list of files the user +* chose. The list will be empty if the user canceled the dialog, and it will +* be NULL if an error occurred. +* +* Note that the callback may be called from a different thread than the one +* the function was invoked on. +* +* Depending on the platform, the user may be allowed to input paths that +* don't yet exist. +* +* On Linux, dialogs may require XDG Portals, which requires DBus, which +* requires an event-handling loop. Apps that do not use SDL to handle events +* should add a call to SDL_PumpEvents in their main loop. +* +* \param callback a function pointer to be invoked when the user selects a +* file and accepts, or cancels the dialog, or an error +* occurs. +* \param userdata an optional pointer to pass extra data to the callback when +* it will be invoked. +* \param window the window that the dialog should be modal for, may be NULL. +* Not all platforms support this option. +* \param default_location the default folder or file to start the dialog at, +* may be NULL. Not all platforms support this option. +* \param allow_many if non-zero, the user will be allowed to select multiple +* entries. Not all platforms support this option. +* +* \threadsafety This function should be called only from the main thread. The +* callback may be invoked from the same thread or from a +* different one, depending on the OS's constraints. +* +* \since This function is available since SDL 3.2.0. +* +* \sa SDL_DialogFileCallback +* \sa SDL_ShowOpenFileDialog +* \sa SDL_ShowSaveFileDialog +* \sa SDL_ShowFileDialogWithProperties + } +procedure SDL_ShowOpenFolderDialog(callback: TSDL_DialogFileCallback; userdata: Pointer; window: PSDL_Window; default_location: PAnsiChar; allow_many: cbool); cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_ShowOpenFolderDialog' {$ENDIF} {$ENDIF}; + +{* + * Various types of file dialogs. + * + * This is used by SDL_ShowFileDialogWithProperties() to decide what kind of + * dialog to present to the user. + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_ShowFileDialogWithProperties + } +type + PPSDL_FileDialogType = ^PSDL_FileDialogType; + PSDL_FileDialogType = ^TSDL_FileDialogType; + TSDL_FileDialogType = type Integer; +const + SDL_FILEDIALOG_OPENFILE = TSDL_FileDialogType(0); + SDL_FILEDIALOG_SAVEFILE = TSDL_FileDialogType(1); + SDL_FILEDIALOG_OPENFOLDER = TSDL_FileDialogType(2); + +{* + * Create and launch a file dialog with the specified properties. + * + * These are the supported properties: + * + * - `SDL_PROP_FILE_DIALOG_FILTERS_POINTER`: a Pointer to a list of + * SDL_DialogFileFilter structs, which will be used as filters for + * file-based selections. Ignored if the dialog is an "Open Folder" dialog. + * If non-nil, the array of filters must remain valid at least until the + * callback is invoked. + * - `SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER`: the number of filters in the + * array of filters, if it exists. + * - `SDL_PROP_FILE_DIALOG_WINDOW_POINTER`: the window that the dialog should + * be modal for. + * - `SDL_PROP_FILE_DIALOG_LOCATION_STRING`: the default folder or file to + * start the dialog at. + * - `SDL_PROP_FILE_DIALOG_MANY_BOOLEAN`: true to allow the user to select + * more than one entry. + * - `SDL_PROP_FILE_DIALOG_TITLE_STRING`: the title for the dialog. + * - `SDL_PROP_FILE_DIALOG_ACCEPT_STRING`: the label that the accept button + * should have. + * - `SDL_PROP_FILE_DIALOG_CANCEL_STRING`: the label that the cancel button + * should have. + * + * Note that each platform may or may not support any of the properties. + * + * \param type the type of file dialog. + * \param callback a function Pointer to be invoked when the user selects a + * file and accepts, or cancels the dialog, or an error + * occurs. + * \param userdata an optional Pointer to pass extra data to the callback when + * it will be invoked. + * \param props the properties to use. + * + * \threadsafety This function should be called only from the main thread. The + * callback may be invoked from the same thread or from a + * different one, depending on the OS's constraints. + * + * \since This function is available since SDL 3.2.0. + * + * \sa SDL_FileDialogType + * \sa SDL_DialogFileCallback + * \sa SDL_DialogFileFilter + * \sa SDL_ShowOpenFileDialog + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + } +procedure SDL_ShowFileDialogWithProperties(type_: TSDL_FileDialogType; callback: TSDL_DialogFileCallback; userdata: Pointer; props: TSDL_PropertiesID); cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_ShowFileDialogWithProperties' {$ENDIF} {$ENDIF}; + +const + SDL_PROP_FILE_DIALOG_FILTERS_POINTER = 'SDL.filedialog.filters'; + SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER = 'SDL.filedialog.nfilters'; + SDL_PROP_FILE_DIALOG_WINDOW_POINTER = 'SDL.filedialog.window'; + SDL_PROP_FILE_DIALOG_LOCATION_STRING = 'SDL.filedialog.location'; + SDL_PROP_FILE_DIALOG_MANY_BOOLEAN = 'SDL.filedialog.many'; + SDL_PROP_FILE_DIALOG_TITLE_STRING = 'SDL.filedialog.title'; + SDL_PROP_FILE_DIALOG_ACCEPT_STRING = 'SDL.filedialog.accept'; + SDL_PROP_FILE_DIALOG_CANCEL_STRING = 'SDL.filedialog.cancel'; + diff --git a/units/SDL_filesystem.inc b/units/SDL_filesystem.inc new file mode 100644 index 0000000..137d880 --- /dev/null +++ b/units/SDL_filesystem.inc @@ -0,0 +1,492 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{ +* # CategoryFilesystem +* +* SDL offers an API for examining and manipulating the system's filesystem. +* This covers most things one would need to do with directories, except for +* actual file I/O (which is covered by [CategoryIOStream](CategoryIOStream) +* and [CategoryAsyncIO](CategoryAsyncIO) instead). +* +* There are functions to answer necessary path questions: +* +* - Where is my app's data? SDL_GetBasePath(). +* - Where can I safely write files? SDL_GetPrefPath(). +* - Where are paths like Downloads, Desktop, Music? SDL_GetUserFolder(). +* - What is this thing at this location? SDL_GetPathInfo(). +* - What items live in this folder? SDL_EnumerateDirectory(). +* - What items live in this folder by wildcard? SDL_GlobDirectory(). +* - What is my current working directory? SDL_GetCurrentDirectory(). +* +* SDL also offers functions to manipulate the directory tree: renaming, +* removing, copying files. +} + +{* + * Get the directory where the application was run from. + * + * SDL caches the result of this call internally, but the first call to this + * function is not necessarily fast, so plan accordingly. + * + * **macOS and iOS Specific Functionality**: If the application is in a ".app" + * bundle, this function returns the Resource directory (e.g. + * MyApp.app/Contents/Resources/). This behaviour can be overridden by adding + * a property to the Info.plist file. Adding a string key with the name + * SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the + * behaviour. + * + * Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an + * application in /Applications/SDLApp/MyApp.app): + * + * - `resource`: bundle resource directory (the default). For example: + * `/Applications/SDLApp/MyApp.app/Contents/Resources` + * - `bundle`: the Bundle directory. For example: + * `/Applications/SDLApp/MyApp.app/` + * - `parent`: the containing directory of the bundle. For example: + * `/Applications/SDLApp/` + * + * **Nintendo 3DS Specific Functionality**: This function returns "romfs" + * directory of the application as it is uncommon to store resources outside + * the executable. As such it is not a writable directory. + * + * The returned path is guaranteed to end with a path separator ('\\' on + * Windows, '/' on most other platforms). + * + * \returns an absolute path in UTF-8 encoding to the application data + * directory. nil will be returned on error or when the platform + * doesn't implement this functionality, call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + * + * \sa SDL_GetPrefPath + } +function SDL_GetBasePath: PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetBasePath' {$ENDIF} {$ENDIF}; + +{* + * Get the user-and-app-specific path where files can be written. + * + * Get the "pref dir". This is meant to be where users can write personal + * files (preferences and save games, etc) that are specific to your + * application. This directory is unique per user, per application. + * + * This function will decide the appropriate location in the native + * filesystem, create the directory if necessary, and return a string of the + * absolute path to the directory in UTF-8 encoding. + * + * On Windows, the string might look like: + * + * `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\` + * + * On Linux, the string might look like: + * + * `/home/bob/.local/share/My Program Name/` + * + * On macOS, the string might look like: + * + * `/Users/bob/Library/Application Support/My Program Name/` + * + * You should assume the path returned by this function is the only safe place + * to write files (and that SDL_GetBasePath(), while it might be writable, or + * even the parent of the returned path, isn't where you should be writing + * things). + * + * Both the org and app strings may become part of a directory name, so please + * follow these rules: + * + * - Try to use the same org string (_including case-sensitivity_) for all + * your applications that use this function. + * - Always use a unique app string for each one, and make sure it never + * changes for an app once you've decided on it. + * - Unicode characters are legal, as long as they are UTF-8 encoded, but... + * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game + * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. + * + * The returned path is guaranteed to end with a path separator ('\\' on + * Windows, '/' on most other platforms). + * + * \param org the name of your organization. + * \param app the name of your application. + * \returns a UTF-8 string of the user directory in platform-dependent + * notation. nil if there's a problem (creating directory failed, + * etc.). This should be freed with SDL_free() when it is no longer + * needed. + * + * \since This function is available since SDL 3.2.0. + * + * \sa SDL_GetBasePath + } +function SDL_GetPrefPath(org: PAnsiChar; app: PAnsiChar): PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetPrefPath' {$ENDIF} {$ENDIF}; + +{* + * The type of the OS-provided default folder for a specific purpose. + * + * Note that the Trash folder isn't included here, because trashing files + * usually involves extra OS-specific functionality to remember the file's + * original location. + * + * The folders supported per platform are: + * + * | | Windows | macOS/iOS | tvOS | Unix (XDG) | Haiku | Emscripten | + * | ----------- | ------- | --------- | ---- | ---------- | ----- | ---------- | + * | HOME | X | X | | X | X | X | + * | DESKTOP | X | X | | X | X | | + * | DOCUMENTS | X | X | | X | | | + * | DOWNLOADS | Vista+ | X | | X | | | + * | MUSIC | X | X | | X | | | + * | PICTURES | X | X | | X | | | + * | PUBLICSHARE | | X | | X | | | + * | SAVEDGAMES | Vista+ | | | | | | + * | SCREENSHOTS | Vista+ | | | | | | + * | TEMPLATES | X | X | | X | | | + * | VIDEOS | X | X* | | X | | | + * + * Note that on macOS/iOS, the Videos folder is called "Movies". + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_GetUserFolder + } +type + PPSDL_Folder = ^PSDL_Folder; + PSDL_Folder = ^TSDL_Folder; + TSDL_Folder = type Integer; +const + SDL_FOLDER_HOME = TSDL_Folder(0); {*< The folder which contains all of the current user's data, preferences, and documents. It usually contains most of the other folders. If a requested folder does not exist, the home folder can be considered a safe fallback to store a user's documents. } + SDL_FOLDER_DESKTOP = TSDL_Folder(1); {*< The folder of files that are displayed on the desktop. Note that the existence of a desktop folder does not guarantee that the system does show icons on its desktop; certain GNU/Linux distros with a graphical environment may not have desktop icons. } + SDL_FOLDER_DOCUMENTS = TSDL_Folder(2); {*< User document files, possibly application-specific. This is a good place to save a user's projects. } + SDL_FOLDER_DOWNLOADS = TSDL_Folder(3); {*< Standard folder for user files downloaded from the internet. } + SDL_FOLDER_MUSIC = TSDL_Folder(4); {*< Music files that can be played using a standard music player (mp3, ogg...). } + SDL_FOLDER_PICTURES = TSDL_Folder(5); {*< Image files that can be displayed using a standard viewer (png, jpg...). } + SDL_FOLDER_PUBLICSHARE = TSDL_Folder(6); {*< Files that are meant to be shared with other users on the same computer. } + SDL_FOLDER_SAVEDGAMES = TSDL_Folder(7); {*< Save files for games. } + SDL_FOLDER_SCREENSHOTS = TSDL_Folder(8); {*< Application screenshots. } + SDL_FOLDER_TEMPLATES = TSDL_Folder(9); {*< Template files to be used when the user requests the desktop environment to create a new file in a certain folder, such as "New Text File.txt". Any file in the Templates folder can be used as a starting point for a new file. } + SDL_FOLDER_VIDEOS = TSDL_Folder(10); {*< Video files that can be played using a standard video player (mp4, webm...). } + SDL_FOLDER_COUNT = TSDL_Folder(11); {*< Total number of types in this enum, not a folder type by itself. } + +{* + * Finds the most suitable user folder for a specific purpose. + * + * Many OSes provide certain standard folders for certain purposes, such as + * storing pictures, music or videos for a certain user. This function gives + * the path for many of those special locations. + * + * This function is specifically for _user_ folders, which are meant for the + * user to access and manage. For application-specific folders, meant to hold + * data for the application to manage, see SDL_GetBasePath() and + * SDL_GetPrefPath(). + * + * The returned path is guaranteed to end with a path separator ('\\' on + * Windows, '/' on most other platforms). + * + * If nil is returned, the error may be obtained with SDL_GetError(). + * + * \param folder the type of folder to find. + * \returns either a null-terminated C string containing the full path to the + * folder, or nil if an error happened. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetUserFolder(folder: TSDL_Folder): PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetUserFolder' {$ENDIF} {$ENDIF}; + +{ Abstract filesystem interface } +{* + * Types of filesystem entries. + * + * Note that there may be other sorts of items on a filesystem: devices, + * symlinks, named pipes, etc. They are currently reported as + * SDL_PATHTYPE_OTHER. + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_PathInfo + } +type + PPSDL_PathType = ^PSDL_PathType; + PSDL_PathType = ^TSDL_PathType; + TSDL_PathType = type Integer; +const + SDL_PATHTYPE_NONE = TSDL_PathType(0); {*< path does not exist } + SDL_PATHTYPE_FILE = TSDL_PathType(1); {*< a normal file } + SDL_PATHTYPE_DIRECTORY = TSDL_PathType(2); {*< a directory } + SDL_PATHTYPE_OTHER = TSDL_PathType(3); {*< something completely different like a device node (not a symlink, those are always followed) } + +{* + * Information about a path on the filesystem. + * + * \since This datatype is available since SDL 3.2.0. + * + * \sa SDL_GetPathInfo + * \sa SDL_GetStoragePathInfo + } +type + PPSDL_PathInfo = ^PSDL_PathInfo; + PSDL_PathInfo = ^TSDL_PathInfo; + TSDL_PathInfo = record + type_: TSDL_PathType; {*< the path type } + size: cuint64; {*< the file size in bytes } + create_time: TSDL_Time; {*< the time when the path was created } + modify_time: TSDL_Time; {*< the last time the path was modified } + access_time: TSDL_Time; {*< the last time the path was read } + end; + +{* + * Flags for path matching. + * + * \since This datatype is available since SDL 3.2.0. + * + * \sa SDL_GlobDirectory + * \sa SDL_GlobStorageDirectory + } +type + PPSDL_GlobFlags = ^PSDL_GlobFlags; + PSDL_GlobFlags = ^TSDL_GlobFlags; + TSDL_GlobFlags = type cuint32; + +const + SDL_GLOB_CASEINSENSITIVE = TSDL_GlobFlags(1 shl 0); + +{* + * Create a directory, and any missing parent directories. + * + * This reports success if `path` already exists as a directory. + * + * If parent directories are missing, it will also create them. Note that if + * this fails, it will not remove any parent directories it already made. + * + * \param path the path of the directory to create. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_CreateDirectory(path: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_CreateDirectory' {$ENDIF} {$ENDIF}; + +{* + * Possible results from an enumeration callback. + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_EnumerateDirectoryCallback + } +type + PPSDL_EnumerationResult = ^PSDL_EnumerationResult; + PSDL_EnumerationResult = ^TSDL_EnumerationResult; + TSDL_EnumerationResult = type Integer; +const + SDL_ENUM_CONTINUE = TSDL_EnumerationResult(0); {*< Value that requests that enumeration continue. } + SDL_ENUM_SUCCESS = TSDL_EnumerationResult(1); {*< Value that requests that enumeration stop, successfully. } + SDL_ENUM_FAILURE = TSDL_EnumerationResult(2); {*< Value that requests that enumeration stop, as a failure. } + +{* + * Callback for directory enumeration. + * + * Enumeration of directory entries will continue until either all entries + * have been provided to the callback, or the callback has requested a stop + * through its return value. + * + * Returning SDL_ENUM_CONTINUE will let enumeration proceed, calling the + * callback with further entries. SDL_ENUM_SUCCESS and SDL_ENUM_FAILURE will + * terminate the enumeration early, and dictate the return value of the + * enumeration function itself. + * + * `dirname` is guaranteed to end with a path separator ('\\' on Windows, '/' + * on most other platforms). + * + * \param userdata an app-controlled Pointer that is passed to the callback. + * \param dirname the directory that is being enumerated. + * \param fname the next entry in the enumeration. + * \returns how the enumeration should proceed. + * + * \since This datatype is available since SDL 3.2.0. + * + * \sa SDL_EnumerateDirectory + } +type + TSDL_EnumerateDirectoryCallback = function(userdata: Pointer; dirname: PAnsiChar; fname: PAnsiChar): TSDL_EnumerationResult; cdecl; + +{* + * Enumerate a directory through a callback function. + * + * This function provides every directory entry through an app-provided + * callback, called once for each directory entry, until all results have been + * provided or the callback returns either SDL_ENUM_SUCCESS or + * SDL_ENUM_FAILURE. + * + * This will return false if there was a system problem in general, or if a + * callback returns SDL_ENUM_FAILURE. A successful return means a callback + * returned SDL_ENUM_SUCCESS to halt enumeration, or all directory entries + * were enumerated. + * + * \param path the path of the directory to enumerate. + * \param callback a function that is called for each entry in the directory. + * \param userdata a Pointer that is passed to `callback`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_EnumerateDirectory(path: PAnsiChar; callback: TSDL_EnumerateDirectoryCallback; userdata: Pointer): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_EnumerateDirectory' {$ENDIF} {$ENDIF}; + +{* + * Remove a file or an empty directory. + * + * Directories that are not empty will fail; this function will not recursely + * delete directory trees. + * + * \param path the path to remove from the filesystem. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_RemovePath(path: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_RemovePath' {$ENDIF} {$ENDIF}; + +{* + * Rename a file or directory. + * + * If the file at `newpath` already exists, it will replaced. + * + * Note that this will not copy files across filesystems/drives/volumes, as + * that is a much more complicated (and possibly time-consuming) operation. + * + * Which is to say, if this function fails, SDL_CopyFile() to a temporary file + * in the same directory as `newpath`, then SDL_RenamePath() from the + * temporary file to `newpath` and SDL_RemovePath() on `oldpath` might work + * for files. Renaming a non-empty directory across filesystems is + * dramatically more complex, however. + * + * \param oldpath the old path. + * \param newpath the new path. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_RenamePath(oldpath: PAnsiChar; newpath: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_RenamePath' {$ENDIF} {$ENDIF}; + +{* + * Copy a file. + * + * If the file at `newpath` already exists, it will be overwritten with the + * contents of the file at `oldpath`. + * + * This function will block until the copy is complete, which might be a + * significant time for large files on slow disks. On some platforms, the copy + * can be handed off to the OS itself, but on others SDL might just open both + * paths, and read from one and write to the other. + * + * Note that this is not an atomic operation! If something tries to read from + * `newpath` while the copy is in progress, it will see an incomplete copy of + * the data, and if the calling thread terminates (or the power goes out) + * during the copy, `newpath`'s previous contents will be gone, replaced with + * an incomplete copy of the data. To avoid this risk, it is recommended that + * the app copy to a temporary file in the same directory as `newpath`, and if + * the copy is successful, use SDL_RenamePath() to replace `newpath` with the + * temporary file. This will ensure that reads of `newpath` will either see a + * complete copy of the data, or it will see the pre-copy state of `newpath`. + * + * This function attempts to synchronize the newly-copied data to disk before + * returning, if the platform allows it, so that the renaming trick will not + * have a problem in a system crash or power failure, where the file could be + * renamed but the contents never made it from the system file cache to the + * physical disk. + * + * If the copy fails for any reason, the state of `newpath` is undefined. It + * might be half a copy, it might be the untouched data of what was already + * there, or it might be a zero-byte file, etc. + * + * \param oldpath the old path. + * \param newpath the new path. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_CopyFile(oldpath: PAnsiChar; newpath: PAnsiChar): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_CopyFile' {$ENDIF} {$ENDIF}; + +{* + * Get information about a filesystem path. + * + * \param path the path to query. + * \param info a Pointer filled in with information about the path, or nil to + * check for the existence of a file. + * \returns true on success or false if the file doesn't exist, or another + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetPathInfo(path: PAnsiChar; info: PSDL_PathInfo): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetPathInfo' {$ENDIF} {$ENDIF}; + +{* + * Enumerate a directory tree, filtered by pattern, and return a list. + * + * Files are filtered out if they don't match the string in `pattern`, which + * may contain wildcard characters '\*' (match everything) and '?' (match one + * character). If pattern is nil, no filtering is done and all results are + * returned. Subdirectories are permitted, and are specified with a path + * separator of '/'. Wildcard characters '\*' and '?' never match a path + * separator. + * + * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching + * case-insensitive. + * + * The returned array is always nil-terminated, for your iterating + * convenience, but if `count` is non-nil, on return it will contain the + * number of items in the array, not counting the nil terminator. + * + * \param path the path of the directory to enumerate. + * \param pattern the pattern that files in the directory must match. Can be + * nil. + * \param flags `SDL_GLOB_*` bitflags that affect this search. + * \param count on return, will be set to the number of items in the returned + * array. Can be nil. + * \returns an array of strings on success or nil on failure; call + * SDL_GetError() for more information. This is a single allocation + * that should be freed with SDL_free() when it is no longer needed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GlobDirectory(path: PAnsiChar; pattern: PAnsiChar; flags: TSDL_GlobFlags; count: pcint):PPAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GlobDirectory' {$ENDIF} {$ENDIF}; + +{* + * Get what the system believes is the "current working directory." + * + * For systems without a concept of a current working directory, this will + * still attempt to provide something reasonable. + * + * SDL does not provide a means to _change_ the current working directory; for + * platforms without this concept, this would cause surprises with file access + * outside of SDL. + * + * The returned path is guaranteed to end with a path separator ('\\' on + * Windows, '/' on most other platforms). + * + * \returns a UTF-8 string of the current working directory in + * platform-dependent notation. nil if there's a problem. This + * should be freed with SDL_free() when it is no longer needed. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetCurrentDirectory: PAnsiChar; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetCurrentDirectory' {$ENDIF} {$ENDIF}; + diff --git a/units/SDL_stdinc.inc b/units/SDL_stdinc.inc index 7652e4c..89ee747 100644 --- a/units/SDL_stdinc.inc +++ b/units/SDL_stdinc.inc @@ -6,6 +6,142 @@ SPDX-License-Identifier: Zlib } +{* + * A signed 8-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcint8_t=^pcint8_t; + pcint8_t=^cint8_t; + cint8_t=cint8; +const + SDL_MAX_SINT8=cint8($7F); { 127 } + SDL_MIN_SINT8=cint8(not ($7F)); { -128 } + +{* + * An unsigned 8-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcuint8_t=^pcuint8_t; + pcuint8_t=^cuint8_t; + cuint8_t=cuint8; +const + SDL_MAX_UINT8=cuint8($FF); { 255 } + SDL_MIN_UINT8=cuint8($00); { 0 } + +{* + * A signed 16-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcint16_t=^pcint16_t; + pcint16_t=^cint16_t; + cint16_t=cint16; +const + SDL_MAX_SINT16=cint16($7FFF); { 32767 } + SDL_MIN_SINT16=cint16(not ($7FFF)); { -32768 } + +{* + * An unsigned 16-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcuint16_t=^pcuint16_t; + pcuint16_t=^cuint16_t; + cuint16_t=cuint16; +const + SDL_MAX_UINT16=cuint16($FFFF); { 65535 } + SDL_MIN_UINT16=cuint16($0000); { 0 } + +{* + * A signed 32-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcint32_t=^pcint32_t; + pcint32_t=^cint32_t; + cint32_t=cint32; +const + SDL_MAX_SINT32=cint32($7FFFFFFF); { 2147483647 } + SDL_MIN_SINT32=cint32(not ($7FFFFFFF)); { -2147483648 } + +{* + * An unsigned 32-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + } +type + ppcuint32_t=^pcuint32_t; + pcuint32_t=^cuint32_t; + cuint32_t=cuint32; +const + SDL_MAX_UINT32=cuint32($FFFFFFFF); { 4294967295 } + SDL_MIN_UINT32=cuint32($00000000); { 0 } + +{* + * A signed 64-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SINT64_C + } +type + ppcint64_t=^pcint64_t; + pcint64_t=^cint64_t; + cint64_t=cint64; +const + { #note : SDL3-for-Pascal: + The macro SDL_SINT64_C converts the values to guarantee their size. + We do this simply by converting to cint64 here. } + SDL_MAX_SINT64=cint64($7FFFFFFFFFFFFFFF); { 9223372036854775807 } + SDL_MIN_SINT64= not (cint64($7FFFFFFFFFFFFFFF)); { -9223372036854775808 } + +{* + * An unsigned 64-bit integer type. + * + * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_UINT64_C + } +type + ppcuint64_t=^pcuint64_t; + pcuint64_t=^cuint64_t; + cuint64_t=cuint64; +const + { #note : SDL3-for-Pascal: + The macro SDL_SUINT64_C converts the values to guarantee their size. + We do this simply by converting to cuint64 here. } + SDL_MAX_UINT64=cuint64($FFFFFFFFFFFFFFFF); { 18446744073709551615 } + SDL_MIN_UINT64=cuint64($0000000000000000); { 0 } + +{* + * SDL times are signed, 64-bit integers representing nanoseconds since the + * Unix epoch (Jan 1, 1970). + * + * They can be converted between POSIX time_t values with SDL_NS_TO_SECONDS() + * and SDL_SECONDS_TO_NS(), and between Windows FILETIME values with + * SDL_TimeToWindows() and SDL_TimeFromWindows(). + * + * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_MAX_SINT64 + * \sa SDL_MIN_SINT64 + } +type + PPSDL_Time = ^PSDL_Time; + PSDL_Time = ^TSDL_Time; + TSDL_Time = cint64; + +const + SDL_MAX_TIME = SDL_MAX_SINT64; + SDL_MIN_TIME = SDL_MIN_SINT64; + {* * Epsilon constant, used for comparing floating-point numbers. * diff --git a/units/SDL_time.inc b/units/SDL_time.inc new file mode 100644 index 0000000..415ffdc --- /dev/null +++ b/units/SDL_time.inc @@ -0,0 +1,213 @@ +{ + This file is part of: + + SDL3 for Pascal + (https://github.com/PascalGameDevelopment/SDL3-for-Pascal) + SPDX-License-Identifier: Zlib +} + +{* + * # CategoryTime + * + * SDL realtime clock and date/time routines. + * + * There are two data types that are used in this category: SDL_Time, which + * represents the nanoseconds since a specific moment (an "epoch"), and + * SDL_DateTime, which breaks time down into human-understandable components: + * years, months, days, hours, etc. + * + * Much of the functionality is involved in converting those two types to + * other useful forms. + } +{* + * A structure holding a calendar date and time broken down into its + * components. + * + * \since This struct is available since SDL 3.2.0. + } +type + PPSDL_DateTime = ^PSDL_DateTime; + PSDL_DateTime = ^TSDL_DateTime; + TSDL_DateTime = record + year: cint; {*< Year } + month: cint; {*< Month [01-12] } + day: cint; {*< Day of the month [01-31] } + hour: cint; {*< Hour [0-23] } + minute: cint; {*< Minute [0-59] } + second: cint; {*< Seconds [0-60] } + nanosecond: cint; {*< Nanoseconds [0-999999999] } + day_of_week: cint; {*< Day of the week [0-6] (0 being Sunday) } + utc_offset: cint; {*< Seconds east of UTC } + end; + +{* + * The preferred date format of the current system locale. + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_GetDateTimeLocalePreferences + } +type + PPSDL_DateFormat = ^PSDL_DateFormat; + PSDL_DateFormat = ^TSDL_DateFormat; + TSDL_DateFormat = type Integer; +const + SDL_DATE_FORMAT_YYYYMMDD = TSDL_DateFormat(0); {*< Year/Month/Day } + SDL_DATE_FORMAT_DDMMYYYY = TSDL_DateFormat(1); {*< Day/Month/Year } + SDL_DATE_FORMAT_MMDDYYYY = TSDL_DateFormat(2); {*< Month/Day/Year } + +{* + * The preferred time format of the current system locale. + * + * \since This enum is available since SDL 3.2.0. + * + * \sa SDL_GetDateTimeLocalePreferences + } +type + PPSDL_TimeFormat = ^PSDL_TimeFormat; + PSDL_TimeFormat = ^TSDL_TimeFormat; + TSDL_TimeFormat = type Integer; +const + SDL_TIME_FORMAT_24HR = TSDL_TimeFormat(0); {*< 24 hour time } + SDL_TIME_FORMAT_12HR = TSDL_TimeFormat(1); {*< 12 hour time } + +{* + * Gets the current preferred date and time format for the system locale. + * + * This might be a "slow" call that has to query the operating system. It's + * best to ask for this once and save the results. However, the preferred + * formats can change, usually because the user has changed a system + * preference outside of your program. + * + * \param dateFormat a Pointer to the SDL_DateFormat to hold the returned date + * format, may be nil. + * \param timeFormat a Pointer to the SDL_TimeFormat to hold the returned time + * format, may be nil. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetDateTimeLocalePreferences(dateFormat: PSDL_DateFormat; timeFormat: PSDL_TimeFormat): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetDateTimeLocalePreferences' {$ENDIF} {$ENDIF}; + +{* + * Gets the current value of the system realtime clock in nanoseconds since + * Jan 1, 1970 in Universal Coordinated Time (UTC). + * + * \param ticks the SDL_Time to hold the returned tick count. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetCurrentTime(ticks: PSDL_Time): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetCurrentTime' {$ENDIF} {$ENDIF}; + +{* + * Converts an SDL_Time in nanoseconds since the epoch to a calendar time in + * the SDL_DateTime format. + * + * \param ticks the SDL_Time to be converted. + * \param dt the resulting SDL_DateTime. + * \param localTime the resulting SDL_DateTime will be expressed in local time + * if true, otherwise it will be in Universal Coordinated + * Time (UTC). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_TimeToDateTime(ticks: TSDL_Time; dt: PSDL_DateTime; localTime: cbool): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_TimeToDateTime' {$ENDIF} {$ENDIF}; + +{* + * Converts a calendar time to an SDL_Time in nanoseconds since the epoch. + * + * This function ignores the day_of_week member of the SDL_DateTime struct, so + * it may remain unset. + * + * \param dt the source SDL_DateTime. + * \param ticks the resulting SDL_Time. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_DateTimeToTime(dt: PSDL_DateTime; ticks: PSDL_Time): cbool; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_DateTimeToTime' {$ENDIF} {$ENDIF}; + +{* + * Converts an SDL time into a Windows FILETIME (100-nanosecond intervals + * since January 1, 1601). + * + * This function fills in the two 32-bit values of the FILETIME structure. + * + * \param ticks the time to convert. + * \param dwLowDateTime a Pointer filled in with the low portion of the + * Windows FILETIME value. + * \param dwHighDateTime a Pointer filled in with the high portion of the + * Windows FILETIME value. + * + * \since This function is available since SDL 3.2.0. + } +procedure SDL_TimeToWindows(ticks: TSDL_Time; dwLowDateTime: pcuint32; dwHighDateTime: pcuint32); cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_TimeToWindows' {$ENDIF} {$ENDIF}; + +{* + * Converts a Windows FILETIME (100-nanosecond intervals since January 1, + * 1601) to an SDL time. + * + * This function takes the two 32-bit values of the FILETIME structure as + * parameters. + * + * \param dwLowDateTime the low portion of the Windows FILETIME value. + * \param dwHighDateTime the high portion of the Windows FILETIME value. + * \returns the converted SDL time. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_TimeFromWindows(dwLowDateTime: cuint32; dwHighDateTime: cuint32): TSDL_Time; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_TimeFromWindows' {$ENDIF} {$ENDIF}; + +{* + * Get the number of days in a month for a given year. + * + * \param year the year. + * \param month the month [1-12]. + * \returns the number of days in the requested month or -1 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetDaysInMonth(year: cint; month: cint): cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetDaysInMonth' {$ENDIF} {$ENDIF}; + +{* + * Get the day of year for a calendar date. + * + * \param year the year component of the date. + * \param month the month component of the date. + * \param day the day component of the date. + * \returns the day of year [0-365] if the date is valid or -1 on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetDayOfYear(year: cint; month: cint; day: cint): cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetDayOfYear' {$ENDIF} {$ENDIF}; + +{* + * Get the day of week for a calendar date. + * + * \param year the year component of the date. + * \param month the month component of the date. + * \param day the day component of the date. + * \returns a value between 0 and 6 (0 being Sunday) if the date is valid or + * -1 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.2.0. + } +function SDL_GetDayOfWeek(year: cint; month: cint; day: cint): cint; cdecl; + external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_GetDayOfWeek' {$ENDIF} {$ENDIF}; +