Final Platform Layer  0.9.6-beta
final_platform_layer.h
Go to the documentation of this file.
1 /*
2 final_platform_layer.h
3 
4 -------------------------------------------------------------------------------
5  About
6 -------------------------------------------------------------------------------
7 
8 Final Platform Layer is a Single-Header-File cross-platform C development library designed to abstract the underlying platform to a simple and easy-to-use API - providing low-level access to (Window, Video, Audio, Input, File/Path IO, Threads, Memory, Hardware, etc.).
9 
10 The main focus is game/media/simulation development, so the default settings will create a window, set up an OpenGL rendering context, and initialize audio playback on any platform.
11 
12 It is written in C99 for simplicity and best portability but is C++ compatible as well.
13 
14 FPL supports the platforms Windows/Linux/Unix for the architectures x86/x64/arm.
15 
16 The only dependencies are built-in operating system libraries and a C99 compliant compiler.
17 
18 It is licensed under the MIT-License. This license allows you to use FPL freely in any software.
19 
20 -------------------------------------------------------------------------------
21  Getting started
22 -------------------------------------------------------------------------------
23 
24 - Drop this file into any C/C++ projects you want and include it in any place you want
25 - In your main translation unit provide the typical main() entry point
26 - Define FPL_IMPLEMENTATION in at least one translation unit before including this header file
27 - Init the platform using fplPlatformInit()
28 - Use the features you want
29 - Release the platform when you are done using fplPlatformRelease()
30 
31 -------------------------------------------------------------------------------
32  Usage: Hello world console application
33 -------------------------------------------------------------------------------
34 
35 #define FPL_IMPLEMENTATION
36 #include <final_platform_layer.h>
37 
38 int main(int argc, char **args){
39  if (fplPlatformInit(fplInitFlags_None, fpl_null)) {
40  fplConsoleOut("Hello World!");
41  fplPlatformRelease();
42  return 0;
43  } else {
44  return -1;
45  }
46 }
47 
48 -------------------------------------------------------------------------------
49  Usage: OpenGL legacy or modern application
50 -------------------------------------------------------------------------------
51 
52 #define FPL_IMPLEMENTATION
53 #include <final_platform_layer.h>
54 
55 int main(int argc, char **args){
56  // Create default settings
57  fplSettings settings = fplMakeDefaultSettings();
58 
59  // Overwrite the video backend
60  settings.video.backend = fplVideoBackendType_OpenGL;
61 
62  // Legacy OpenGL
63  settings.video.graphics.opengl.compabilityFlags = fplOpenGLCompabilityFlags_Legacy;
64 
65  // or
66 
67  // Modern OpenGL
68  settings.video.graphics.opengl.compabilityFlags = fplOpenGLCompabilityFlags_Core;
69  settings.video.graphics.opengl.majorVersion = 3;
70  settings.video.graphics.opengl.minorVersion = 3;
71 
72  if (fplPlatformInit(fplInitFlags_Video, &settings)) {
73  // Event/Main loop
74  while (fplWindowUpdate()) {
75  // Poll events
76  fplEvent ev;
77  while (fplPollEvent(&ev)) {
79  }
80 
81  // your code goes here
82 
83  fplVideoFlip();
84  }
85  fplPlatformRelease();
86  return 0;
87  } else {
88  return -1;
89  }
90 }
91 
92 -------------------------------------------------------------------------------
93  License
94 -------------------------------------------------------------------------------
95 
96 Final Platform Layer is released under the following license:
97 
98 MIT License
99 
100 Copyright (c) 2017-2021 Torsten Spaete
101 
102 Permission is hereby granted, free of charge, to any person obtaining a copy
103 of this software and associated documentation files (the "Software"), to deal
104 in the Software without restriction, including without limitation the rights
105 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106 copies of the Software, and to permit persons to whom the Software is
107 furnished to do so, subject to the following conditions:
108 
109 The above copyright notice and this permission notice shall be included in all
110 copies or substantial portions of the Software.
111 
112 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
113 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
114 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
115 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
116 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
117 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
118 SOFTWARE.
119 */
120 
128 // ----------------------------------------------------------------------------
129 // > CHANGELOG
130 // ----------------------------------------------------------------------------
1448 // ****************************************************************************
1449 //
1450 // > HEADER
1451 //
1452 // ****************************************************************************
1453 #ifndef FPL_HEADER_H
1454 #define FPL_HEADER_H
1455 
1456 //
1457 // C99 detection
1458 //
1459 // https://en.wikipedia.org/wiki/C99#Version_detection
1460 // C99 is partially supported since MSVC 2015
1461 #if !defined(__cplusplus) && ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(_MSC_VER) && (_MSC_VER >= 1900)))
1462 # define FPL_IS_C99
1464 #elif defined(__cplusplus)
1465 # define FPL_IS_CPP
1467 # if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
1468 # define FPL_IS_CPP11
1470 # endif
1471 #else
1472 # error "This C/C++ compiler is not supported!"
1473 #endif
1474 
1475 //
1476 // Architecture detection (x86, x64)
1477 // https://sourceforge.net/p/predef/wiki/Architectures/
1478 //
1479 #if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__)
1480 # define FPL_ARCH_X64
1481 #elif defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_)
1482 # define FPL_ARCH_X86
1483 #elif defined(__aarch64__) || defined(_M_ARM64)
1484 # define FPL_ARCH_ARM64
1485 #elif defined(__arm__) || defined(_M_ARM)
1486 # define FPL_ARCH_ARM32
1487 #elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(_ARCH_PPC64)
1488 # define FPL_ARCH_POWERPC64
1489 #elif defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
1490 # define FPL_ARCH_POWERPC32
1491 #else
1492 # error "This architecture is not supported!"
1493 #endif // FPL_ARCH
1494 
1495 //
1496 // 32-bit or 64-bit
1497 //
1498 #if defined(_WIN32)
1499 # if defined(_WIN64)
1500 # define FPL__M_CPU_64BIT
1501 # else
1502 # define FPL__M_CPU_32BIT
1503 # endif
1504 #elif defined(__GNUC__)
1505 # if defined(__LP64__)
1506 # define FPL__M_CPU_64BIT
1507 # else
1508 # define FPL__M_CPU_32BIT
1509 # endif
1510 #else
1511 # if (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8) || (sizeof(void *) == 8)
1512 # define FPL__M_CPU_64BIT
1513 # else
1514 # define FPL__M_CPU_32BIT
1515 # endif
1516 #endif
1517 
1518 #if defined(FPL__M_CPU_64BIT)
1519 # define FPL_CPU_64BIT
1521 #elif defined(FPL__M_CPU_32BIT)
1522 # define FPL_CPU_32BIT
1524 #endif
1525 
1526 //
1527 // Compiler detection
1528 // http://beefchunk.com/documentation/lang/c/pre-defined-c/precomp.html
1529 // http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros
1530 //
1531 #if defined(__clang__)
1532 # define FPL_COMPILER_CLANG
1534 #elif defined(__INTEL_COMPILER)
1535 # define FPL_COMPILER_INTEL
1537 #elif defined(__MINGW32__)
1538 # define FPL_COMPILER_MINGW
1540 #elif defined(__CC_ARM)
1541 # define FPL_COMPILER_ARM
1543 #elif defined(__GNUC__)
1544 # define FPL_COMPILER_GCC
1546 #elif defined(_MSC_VER)
1547 # define FPL_COMPILER_MSVC
1549 #else
1550 #error "This compiler is not supported!"
1552 #endif // FPL_COMPILER
1553 
1554 //
1555 // Platform detection
1556 // https://sourceforge.net/p/predef/wiki/OperatingSystems/
1557 //
1558 #if defined(_WIN32) || defined(_WIN64)
1559 # define FPL_PLATFORM_WINDOWS
1560 # define FPL_PLATFORM_NAME "Windows"
1561 #elif defined(__ANDROID__)
1562 # define FPL_PLATFORM_ANDROID
1563 # define FPL_PLATFORM_NAME "Android"
1564 # define FPL_SUBPLATFORM_POSIX
1565 # define FPL_SUBPLATFORM_STD_STRINGS
1566 # define FPL_SUBPLATFORM_STD_CONSOLE
1567 #elif defined(__linux__) || defined(__gnu_linux__)
1568 # define FPL_PLATFORM_LINUX
1569 # define FPL_PLATFORM_NAME "Linux"
1570 # define FPL_SUBPLATFORM_POSIX
1571 # define FPL_SUBPLATFORM_X11
1572 # define FPL_SUBPLATFORM_STD_STRINGS
1573 # define FPL_SUBPLATFORM_STD_CONSOLE
1574 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__bsdi__)
1575  // @NOTE(final): BSD is treated as a subplatform for now
1576 # define FPL_PLATFORM_UNIX
1577 # define FPL_PLATFORM_NAME "BSD"
1578 # define FPL_SUBPLATFORM_BSD
1579 # define FPL_SUBPLATFORM_POSIX
1580 # define FPL_SUBPLATFORM_X11
1581 # define FPL_SUBPLATFORM_STD_STRINGS
1582 # define FPL_SUBPLATFORM_STD_CONSOLE
1583 #elif defined(unix) || defined(__unix) || defined(__unix__)
1584 # define FPL_PLATFORM_UNIX
1585 # define FPL_PLATFORM_NAME "Unix"
1586 # define FPL_SUBPLATFORM_POSIX
1587 # define FPL_SUBPLATFORM_X11
1588 # define FPL_SUBPLATFORM_STD_STRINGS
1589 # define FPL_SUBPLATFORM_STD_CONSOLE
1590 #else
1591 # error "This platform is not supported!"
1592 #endif // FPL_PLATFORM
1593 
1594 // Assembler keyword is compiler specific
1595 #if defined(FPL_COMPILER_CLANG) || defined(FPL_COMPILER_GCC)
1596 #define fpl__m_Asm __asm__
1597 #elif defined(FPL_COMPILER_MSVC)
1598 #define fpl__m_Asm __asm
1599 #else
1600 #define fpl__m_Asm asm
1601 #endif
1602 
1604 #define fplAsm fpl__m_Asm
1605 
1606 // Minimum alignment
1607 #if defined(FPL_COMPILER_MSVC)
1608 # define fpl__MinAlignment 8
1609 #elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1610 # if defined(FPL_CPU_64BIT)
1611 # define fpl__MinAlignment 8
1612 # else
1613 # define fpl__MinAlignment 4
1614 # endif
1615 #else
1616 # define fpl__MinAlignment 8
1617 #endif
1618 #define fplMinAlignment fpl__MinAlignment
1620 
1621 // Alignment keyword
1622 #if defined(FPL_IS_CPP11)
1623 #define fpl__m_AlignAs(N) alignas(N)
1624 #elif defined(FPL_COMPILER_MSVC)
1625 #define fpl__m_AlignAs(N) __declspec(align(N))
1626 #elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1627 #define fpl__m_AlignAs(N) __attribute__((aligned(N)))
1628 #else
1629 #define fpl__m_AlignAs(N)
1630 #endif
1631 #define fpl__m_AlignAsAuto(N) fpl__m_AlignAs(((N) < fplMinAlignment ? fplMinAlignment : (N)))
1632 
1634 #define fplAlignAs(N) fpl__m_AlignAsAuto(N)
1635 
1636 //
1637 // Defines required for POSIX (mmap, 64-bit file io, etc.)
1638 //
1639 #if defined(FPL_SUBPLATFORM_POSIX)
1640 # if !defined(_XOPEN_SOURCE)
1641 # define _XOPEN_SOURCE 600
1642 # endif
1643 # if !defined(_DEFAULT_SOURCE)
1644 # define _DEFAULT_SOURCE 1
1645 # endif
1646 # if !defined(__STDC_FORMAT_MACROS)
1647 # define __STDC_FORMAT_MACROS
1648 # endif
1649 # if !defined(__STDC_LIMIT_MACROS)
1650 # define __STDC_LIMIT_MACROS
1651 # endif
1652 # if !defined(_LARGEFILE_SOURCE)
1653 # define _LARGEFILE_SOURCE
1654 # endif
1655 # if !defined(_LARGEFILE64_SOURCE)
1656 # define _LARGEFILE64_SOURCE
1657 # endif
1658 # if !defined(_FILE_OFFSET_BITS)
1659 # define _FILE_OFFSET_BITS 64
1660 # endif
1661 #endif
1662 
1663 #if defined(FPL_PLATFORM_LINUX)
1664 # define FPL__INCLUDE_ALLOCA
1665 #else
1666 # define FPL__INCLUDE_MALLOC
1667 #endif
1668 
1669 // MingW compiler hack
1670 #if defined(FPL_PLATFORM_WINDOWS) && defined(FPL_COMPILER_MINGW)
1671 # if !defined(_WIN32_WINNT)
1672 # define _WIN32_WINNT 0x0600
1673 # endif
1674 #endif // FPL_COMPILER_MINGW
1675 
1676 //
1677 // Storage class identifiers
1678 //
1679 
1686 #define fpl_globalvar static
1688 #define fpl_localvar static
1690 #define fpl_internal static
1692 #define fpl_inline inline
1694 #define fpl_internal_inline inline
1696 #if defined(FPL_IS_CPP)
1698 # define fpl_extern
1699 #else
1700 # define fpl_extern extern
1701 #endif
1702 
1703 //
1704 // DLL Export/Import definition
1705 //
1706 #if defined(_WIN32) || defined(__CYGWIN__)
1707 # ifdef __GNUC__
1708 # define fpl__m_dllexport __attribute__ ((dllexport))
1709 # define fpl__m_dllimport __attribute__ ((dllimport))
1710 # else
1711 # define fpl__m_dllexport __declspec(dllexport)
1712 # define fpl__m_dllimport __declspec(dllimport)
1713 # endif
1714 # define fpl__m_dlllocal
1715 #else
1716 # if __GNUC__ >= 4
1717 # define fpl__m_dllimport __attribute__((visibility("default")))
1718 # define fpl__m_dllexport __attribute__((visibility("default")))
1719 # define fpl__m_dlllocal __attribute__((visibility("hidden")))
1720 # else
1721 # define fpl__m_dllimport
1722 # define fpl__m_dllexport
1723 # define fpl__m_dlllocal
1724 # endif
1725 #endif
1726 
1728 #define fpl_dllimport fpl__m_dllimport
1729 #define fpl_dllexport fpl__m_dllexport
1731 #define fpl_dlllocal fpl__m_dlllocal
1733 
1734 //
1735 // API Call
1736 //
1737 #if defined(FPL_API_AS_PRIVATE)
1738 # define fpl__m_api static
1739 #elif defined(FPL_DLLEXPORT)
1740 # define fpl__m_api fpl_dllexport
1741 #elif defined(FPL_DLLIMPORT)
1742 # define fpl__m_api fpl_dllimport
1743 #else
1744 # define fpl__m_api fpl_extern
1745 #endif // FPL_API_AS_PRIVATE
1746 
1748 #define fpl_api fpl__m_api
1749 
1751 #define fpl_main
1752 
1753 #if defined(FPL_IS_CPP)
1754 # define fpl__m_platform_api extern "C" fpl_api
1755 # define fpl__m_common_api extern "C" fpl_api
1756 #else
1757 # define fpl__m_platform_api fpl_api
1758 # define fpl__m_common_api fpl_api
1759 #endif
1760 
1762 #define fpl_platform_api fpl__m_platform_api
1763 #define fpl_common_api fpl__m_common_api
1765 
1766 //
1767 // Inlining
1768 //
1769 #if defined(FPL_COMPILER_MSVC)
1770 # define fpl__m_force_inline __forceinline
1771 # define fpl__m_no_inline __declspec(noinline)
1772 #elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1773 # define fpl__m_force_inline __attribute__((__always_inline__)) inline
1774 # define fpl__m_no_inline __attribute__((noinline))
1775 #else
1776 # define fpl__m_force_inline inline
1777 # define fpl__m_no_inline
1778 #endif
1779 
1781 #define fpl_force_inline fpl__m_force_inline
1782 #define fpl_no_inline fpl__m_no_inline
1784 
1787 //
1788 // When C-Runtime is disabled we cannot use any function from the C-Standard Library <stdio.h> or <stdlib.h>
1789 //
1790 #if defined(FPL_NO_CRT)
1791 # if defined(FPL_SUBPLATFORM_STD_CONSOLE)
1792 # undef FPL_SUBPLATFORM_STD_CONSOLE
1793 # endif
1794 # if defined(FPL_SUBPLATFORM_STD_STRINGS)
1795 # undef FPL_SUBPLATFORM_STD_STRINGS
1796 # endif
1797 # if !defined(FPL_USERFUNC_vsnprintf)
1798 # error "You need to provide a replacement for vsnprintf() by defining FPL_USERFUNC_vsnprintf!"
1799 # endif
1800 #endif
1801 
1802 //
1803 // Application type detection
1804 // - Can be disabled by FPL_NO_APPTYPE
1805 // - Must be explicitly set for No-CRT on Win32
1806 //
1807 #if defined(FPL_APPTYPE_CONSOLE) && defined(FPL_APPTYPE_WINDOW)
1808 # error "Its now allowed to define both FPL_APPTYPE_CONSOLE and FPL_APPTYPE_WINDOW!"
1809 #endif
1810 #if defined(FPL_NO_CRT)
1811 # if !defined(FPL_APPTYPE_CONSOLE) && !defined(FPL_APPTYPE_WINDOW)
1812 # error "In 'No-CRT' mode you need to define either FPL_APPTYPE_CONSOLE or FPL_APPTYPE_WINDOW manually!"
1813 # endif
1814 #elif !defined(FPL_NO_APPTYPE) && !(defined(FPL_APPTYPE_CONSOLE) || defined(FPL_APPTYPE_WINDOW))
1815 # if !defined(FPL_NO_WINDOW)
1816 # define FPL_APPTYPE_WINDOW
1818 # else
1819 # define FPL_APPTYPE_CONSOLE
1821 # endif
1822 #endif
1823 
1824 //
1825 // Include entry points always when its not disabled and implementation block is compiled in
1826 //
1827 #if defined(FPL_IMPLEMENTATION) && !defined(FPL_NO_ENTRYPOINT)
1828 # define FPL_ENTRYPOINT
1829 #endif
1830 
1831 //
1832 // Debug/Release detection
1833 //
1834 #if defined(FPL_DEBUG)
1835 # define FPL__ENABLE_DEBUG
1836 #elif defined(FPL_RELEASE)
1837 # define FPL__ENABLE_RELEASE
1838 #endif
1839 
1840 //
1841 // Compiler settings
1842 //
1843 #if defined(FPL_COMPILER_MSVC)
1844  // Debug/Release detection
1845 # if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
1846 # if defined(_DEBUG) || (!defined(NDEBUG))
1847 # define FPL__ENABLE_DEBUG
1848 # else
1849 # define FPL__ENABLE_RELEASE
1850 # endif
1851 # endif
1852 
1853  // Function name macro (Win32)
1854 # define FPL__M_FUNCTION_NAME __FUNCTION__
1855 
1856  // Setup MSVC subsystem hints
1857 # if defined(FPL_APPTYPE_WINDOW)
1858 # pragma comment(linker, "/SUBSYSTEM:WINDOWS")
1859 # elif defined(FPL_APPTYPE_CONSOLE)
1860 # pragma comment(linker, "/SUBSYSTEM:CONSOLE")
1861 # endif
1862 
1863  // Setup MSVC linker hints
1864 # pragma comment(lib, "kernel32.lib")
1865 #else
1866  // Function name macro (Other compilers)
1867 # define FPL__M_FUNCTION_NAME __FUNCTION__
1868 #endif // FPL_COMPILER
1869 
1870 // Debug Release fallback
1871 #if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
1872 # define FPL__ENABLE_DEBUG
1873 #endif
1874 
1876 #if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
1877 # define FPL_IS_IDE 1
1878 #else
1879 # define FPL_IS_IDE 0
1880 #endif
1881 
1883 #define FPL_FUNCTION_NAME FPL__M_FUNCTION_NAME
1884 
1885 //
1886 // Options & Feature detection
1887 //
1888 
1889 //
1890 // CPU Instruction Set Detection based on compiler settings
1891 //
1892 #if defined(__AVX512F__)
1893 # define FPL__COMPILED_X86_CPU_INSTR_SET 9
1894 #elif defined(__AVX2__)
1895 # define FPL__COMPILED_X86_CPU_INSTR_SET 8
1896 #elif defined(__AVX__)
1897 # define FPL__COMPILED_X86_CPU_INSTR_SET 7
1898 #elif defined(__SSE4_2__)
1899 # define FPL__COMPILED_X86_CPU_INSTR_SET 6
1900 #elif defined(__SSE4_1__)
1901 # define FPL__COMPILED_X86_CPU_INSTR_SET 5
1902 #elif defined(__SSSE3__)
1903 # define FPL__COMPILED_X86_CPU_INSTR_SET 4
1904 #elif defined(__SSE3__)
1905 # define FPL__COMPILED_X86_CPU_INSTR_SET 3
1906 #elif defined(__SSE2__) || (_M_IX86_FP >= 2)
1907 # define FPL__COMPILED_X86_CPU_INSTR_SET 2
1908 #elif defined(__SSE__) || (_M_IX86_FP >= 1)
1909 # define FPL__COMPILED_X86_CPU_INSTR_SET 1
1910 #elif defined(_M_IX86_FP)
1911 # define FPL__COMPILED_X86_CPU_INSTR_SET _M_IX86_FP
1912 #else
1913 # define FPL__COMPILED_X86_CPU_INSTR_SET 0
1914 #endif
1915 
1916 //
1917 // Assertions
1918 //
1919 #if !defined(FPL_NO_ASSERTIONS)
1920 # if !defined(FPL_FORCE_ASSERTIONS)
1921 # if defined(FPL__ENABLE_DEBUG)
1922 # define FPL__ENABLE_ASSERTIONS
1923 # endif
1924 # else
1925 # define FPL__ENABLE_ASSERTIONS
1926 # endif
1927 #endif // !FPL_NO_ASSERTIONS
1928 #if defined(FPL__ENABLE_ASSERTIONS)
1929 # if !defined(FPL_NO_C_ASSERT) && !defined(FPL_NO_CRT)
1930 # define FPL__ENABLE_C_ASSERT
1931 # endif
1932 #endif // FPL__ENABLE_ASSERTIONS
1933 
1934 //
1935 // HasInclude
1936 //
1937 #if defined(__has_include)
1938 # define fpl__m_HasInclude(inc) __has_include(inc)
1939 #else
1940 # define fpl__m_HasInclude(inc) (1)
1941 #endif
1942 #define fplHasInclude(inc) fpl__m_HasInclude(inc)
1944 
1945 //
1946 // Window
1947 //
1948 #if !defined(FPL_NO_WINDOW) && !defined(FPL_APPTYPE_CONSOLE)
1949 # define FPL__SUPPORT_WINDOW
1950 #endif
1951 
1952 //
1953 // Video
1954 //
1955 #if !defined(FPL_NO_VIDEO)
1956 # define FPL__SUPPORT_VIDEO
1957 #endif
1958 #if defined(FPL__SUPPORT_VIDEO)
1959 # if !defined(FPL_NO_VIDEO_OPENGL)
1960 # define FPL__SUPPORT_VIDEO_OPENGL
1961 # endif
1962 # if !defined(FPL_NO_VIDEO_VULKAN)
1963 # define FPL__SUPPORT_VIDEO_VULKAN
1964 # endif
1965 # if !defined(FPL_NO_VIDEO_SOFTWARE)
1966 # define FPL__SUPPORT_VIDEO_SOFTWARE
1967 # endif
1968 #endif // FPL__SUPPORT_VIDEO
1969 
1970 //
1971 // Audio
1972 //
1973 #if !defined(FPL_NO_AUDIO)
1974  // Audio support
1975 # define FPL__SUPPORT_AUDIO
1976 #endif
1977 #if defined(FPL__SUPPORT_AUDIO)
1978 # if !defined(FPL_NO_AUDIO_DIRECTSOUND) && defined(FPL_PLATFORM_WINDOWS)
1979 # define FPL__SUPPORT_AUDIO_DIRECTSOUND // <dsound.h> is always present on windows
1980 # endif
1981 # if !defined(FPL_NO_AUDIO_ALSA) && defined(FPL_PLATFORM_LINUX)
1982 # if fplHasInclude(<alsa/asoundlib.h>)
1983 # define FPL__SUPPORT_AUDIO_ALSA
1984 # else
1985 # warning "FPL-Warning: ALSA audio development library is missing. Please install 'libasound2-dev' and try again!"
1986 # endif
1987 # endif
1988 #endif // FPL__SUPPORT_AUDIO
1989 
1990 //
1991 // Remove video support when the window is disabled
1992 //
1993 #if !defined(FPL__SUPPORT_WINDOW)
1994 # if defined(FPL_SUBPLATFORM_X11)
1995 # undef FPL_SUBPLATFORM_X11
1996 # endif
1997 
1998 # if defined(FPL__SUPPORT_VIDEO)
1999 # undef FPL__SUPPORT_VIDEO
2000 # endif
2001 # if defined(FPL__SUPPORT_VIDEO_OPENGL)
2002 # undef FPL__SUPPORT_VIDEO_OPENGL
2003 # endif
2004 # if defined(FPL__SUPPORT_VIDEO_VULKAN)
2005 # undef FPL__SUPPORT_VIDEO_VULKAN
2006 # endif
2007 # if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2008 # undef FPL__SUPPORT_VIDEO_SOFTWARE
2009 # endif
2010 #endif // !FPL__SUPPORT_WINDOW
2011 
2012 //
2013 // Enable supports (FPL uses _ENABLE_ internally only)
2014 //
2015 #if defined(FPL__SUPPORT_WINDOW)
2016 # define FPL__ENABLE_WINDOW
2017 #endif
2018 
2019 #if defined(FPL__SUPPORT_VIDEO)
2020 # define FPL__ENABLE_VIDEO
2021 # if defined(FPL__SUPPORT_VIDEO_OPENGL)
2022 # define FPL__ENABLE_VIDEO_OPENGL
2023 # endif
2024 # if defined(FPL__SUPPORT_VIDEO_VULKAN)
2025 # define FPL__ENABLE_VIDEO_VULKAN
2026 # endif
2027 # if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2028 # define FPL__ENABLE_VIDEO_SOFTWARE
2029 # endif
2030 #endif // FPL__SUPPORT_VIDEO
2031 
2032 #if defined(FPL__SUPPORT_AUDIO)
2033 # define FPL__ENABLE_AUDIO
2034 # if defined(FPL__SUPPORT_AUDIO_DIRECTSOUND)
2035 # define FPL__ENABLE_AUDIO_DIRECTSOUND
2036 # endif
2037 # if defined(FPL__SUPPORT_AUDIO_ALSA)
2038 # define FPL__ENABLE_AUDIO_ALSA
2039 # endif
2040 #endif // FPL__SUPPORT_AUDIO
2041 
2042 #if defined(FPL_LOGGING)
2043 # define FPL__ENABLE_LOGGING
2044 # if defined(FPL_LOG_MULTIPLE_WRITERS)
2045 # define FPL__ENABLE_LOG_MULTIPLE_WRITERS
2046 # endif
2047 #endif
2048 
2049 //
2050 // Assertions & Debug
2051 //
2052 
2059 #if defined(FPL__ENABLE_ASSERTIONS)
2060 # if defined(FPL__ENABLE_C_ASSERT) && !defined(FPL_FORCE_ASSERTIONS)
2061 # define FPL__INCLUDE_ASSERT
2062 # define fpl__m_Assert(exp) assert(exp)
2063 # if defined(__cplusplus)
2064 # define fpl__m_StaticAssert(exp) static_assert(exp, "fpl_static_assert")
2065 # endif
2066 # else
2067 # define fpl__m_Assert(exp) if(!(exp)) {*(int *)0 = 0;}
2068 # endif // FPL__ENABLE_C_ASSERT
2069 # if !defined(fpl__m_StaticAssert)
2070 # define FPL__M_STATICASSERT_0(exp, line, counter) \
2071  int fpl__ct_assert_##line_##counter(int ct_assert_failed[(exp)?1:-1])
2072 # define fpl__m_StaticAssert(exp) \
2073  FPL__M_STATICASSERT_0(exp, __LINE__, __COUNTER__)
2074 # endif
2075 #else
2076 # define fpl__m_Assert(exp)
2077 # define fpl__m_StaticAssert(exp)
2078 #endif // FPL__ENABLE_ASSERTIONS
2079 
2081 #define fplAssert(exp) fpl__m_Assert(exp)
2082 #define fplStaticAssert(exp) fpl__m_StaticAssert(exp)
2084 #define fplAlwaysAssert(exp) if(!(exp)) {*(int *)0 = 0;}
2086 #define fplAssertPtr(ptr) fpl__m_Assert((ptr) != fpl_null)
2088 
2089 //
2090 // Debug-Break
2091 // Based on: https://stackoverflow.com/questions/173618/is-there-a-portable-equivalent-to-debugbreak-debugbreak
2092 //
2093 #if defined(__has_builtin)
2094 # if __has_builtin(__builtin_debugtrap)
2095 # define fpl__m_DebugBreak() __builtin_debugtrap()
2096 # elif __has_builtin(__debugbreak)
2097 # define fpl__m_DebugBreak() __debugbreak()
2098 # endif
2099 #endif
2100 #if !defined(fpl__m_DebugBreak)
2101 # if defined(FPL_COMPILER_MSVC) || defined(FPL_COMPILER_INTEL)
2102 # define fpl__m_DebugBreak() __debugbreak()
2103 # elif defined(FPL_COMPILER_ARM)
2104 # define fpl__m_DebugBreak() __breakpoint(42)
2105 # elif defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
2106 fpl_internal fpl_force_inline void fpl__m_DebugBreak() { __asm__ __volatile__("int $03"); }
2107 # elif defined(__thumb__)
2108 fpl_internal fpl_force_inline void fpl__m_DebugBreak() { __asm__ __volatile__(".inst 0xde01"); }
2109 # elif defined(FPL_ARCH_ARM64)
2110 fpl_internal fpl_force_inline void fpl__m_DebugBreak() { __asm__ __volatile__(".inst 0xd4200000"); }
2111 # elif defined(FPL_ARCH_ARM32)
2112 fpl_internal fpl_force_inline void fpl__m_DebugBreak() { __asm__ __volatile__(".inst 0xe7f001f0"); }
2113 # elif defined(FPL_COMPILER_GCC)
2114 # define fpl__m_DebugBreak() __builtin_trap()
2115 # else
2116 # define FPL__INCLUDE_SIGNAL
2117 # if defined(SIGTRAP)
2118 # define fpl__m_DebugBreak() raise(SIGTRAP)
2119 # else
2120 # define fpl__m_DebugBreak() raise(SIGABRT)
2121 # endif
2122 # endif
2123 #endif
2124 
2126 #define fplDebugBreak() fpl__m_DebugBreak()
2127 
2130 //
2131 // Types & Limits
2132 //
2133 #include <stdint.h> // uint32_t, ...
2134 #include <stddef.h> // size_t
2135 #include <stdbool.h> // bool
2136 #include <stdarg.h> // va_start, va_end, va_list, va_arg
2137 #include <limits.h> // UINT32_MAX, ...
2138 #if defined(FPL__INCLUDE_ASSERT)
2139 # include <assert.h>
2140 #endif
2141 #if defined(FPL__INCLUDE_SIGNAL)
2142 # include <signal.h>
2143 #endif
2144 #if defined(FPL__INCLUDE_MALLOC)
2145 # include <malloc.h>
2146 #endif
2147 #if defined(FPL__INCLUDE_ALLOCA)
2148 # include <alloca.h>
2149 #endif
2150 
2152 #if !defined(UINT32_MAX)
2153  // On android or older posix versions there is no UINT32_MAX
2154 # define UINT32_MAX ((uint32_t)-1)
2155 #endif
2156 
2158 #if defined(FPL_IS_CPP11)
2159 # define fpl__m_null nullptr
2160 #elif defined(NULL)
2161 # define fpl__m_null NULL
2162 #else
2163 # define fpl__m_null 0
2164 #endif
2165 #define fpl_null fpl__m_null
2167 
2169 typedef int32_t fpl_b32;
2170 
2171 //
2172 // Test sizes
2173 //
2175 #if defined(FPL_CPU_64BIT)
2176 fplStaticAssert(sizeof(uintptr_t) >= sizeof(uint64_t));
2177 fplStaticAssert(sizeof(size_t) >= sizeof(uint64_t));
2178 #elif defined(FPL_CPU_32BIT)
2179 fplStaticAssert(sizeof(uintptr_t) >= sizeof(uint32_t));
2180 fplStaticAssert(sizeof(size_t) >= sizeof(uint32_t));
2181 #endif
2182 
2184 //
2185 // Macro functions
2186 //
2187 
2194 #define FPL_NOT_IMPLEMENTED {*(int *)0 = 0xBAD;}
2196 
2197 #if defined(FPL_IS_C99)
2198 # define fpl__m_ZeroInit {0}
2199 # define fpl__m_StructSet(ptr, type, value) *(ptr) = (type)value
2200 # define fpl__m_StructInit(type, ...) (type){__VA_ARGS__}
2201 #else
2202 # define fpl__m_ZeroInit {}
2203 # define fpl__m_StructSet(ptr, type, value) *(ptr) = value
2204 # define fpl__m_StructInit(type, ...) {__VA_ARGS__}
2205 #endif
2206 
2208 #define fplZeroInit fpl__m_ZeroInit
2209 #define fplStructSet fpl__m_StructSet
2211 #define fplStructInit fpl__m_StructInit
2213 
2215 #define fplGetAlignmentOffset(value, alignment) ( (((alignment) > 1) && (((value) & ((alignment) - 1)) != 0)) ? ((alignment) - ((value) & (alignment - 1))) : 0)
2216 #define fplGetAlignedSize(size, alignment) (((size) > 0 && (alignment) > 0) ? ((size) + fplGetAlignmentOffset(size, alignment)) : (size))
2218 #define fplIsAligned(ptr, alignment) (((uintptr_t)(const void *)(ptr)) % (alignment) == 0)
2220 #define fplIsPowerOfTwo(value) (((value) != 0) && (((value) & (~(value) + 1)) == (value)))
2222 #define fplIsBigEndian() (*(uint16_t *)"\0\xff" < 0x100)
2224 #define fplIsLittleEndian() (!fplIsBigEndian())
2226 #define fplIsBitSet(value, bit) (((value) >> (bit)) & 0x1)
2228 
2230 #define fplKiloBytes(value) (((value) * 1024ull))
2231 #define fplMegaBytes(value) ((fplKiloBytes(value) * 1024ull))
2233 #define fplGigaBytes(value) ((fplMegaBytes(value) * 1024ull))
2235 #define fplTeraBytes(value) ((fplGigaBytes(value) * 1024ull))
2237 
2239 #define fplClearStruct(ptr) fplMemoryClear((void *)(ptr), sizeof(*(ptr)))
2240 #define fplCopyStruct(src, dst) fplMemoryCopy(src, sizeof(*(src)), dst);
2242 
2243 // Array count
2244 #if defined(FPL_COMPILER_MSVC) && !defined(FPL_NO_CRT) // @TODO(final): Find a better way to detect no-crt inclusion!
2245 # define fpl__m_ArrayCount(arr) _countof(arr)
2246 #elif defined(ARRAY_SIZE)
2247 # define fpl__m_ArrayCount(arr) ARRAY_SIZE(arr)
2248 #else
2249 # define FPL__NO_ARRAYCOUNT_VALIDATION
2251 # define fpl__m_ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
2252 #endif
2253 #define fplArrayCount(arr) fpl__m_ArrayCount(arr)
2255 
2257 #define fplOffsetOf(type, field) ((size_t)(&(((type*)(0))->field)))
2258 
2260 #define fplMin(a, b) ((a) < (b) ? (a) : (b))
2261 
2263 #define fplMax(a, b) ((a) > (b) ? (a) : (b))
2264 
2265 #if defined(FPL_PLATFORM_WINDOWS)
2266 # define fpl__m_StackAllocate(size) _alloca(size)
2267 #else
2268 # define fpl__m_StackAllocate(size) alloca(size)
2269 #endif
2270 
2272 #define fplStackAllocate(size) fpl__m_StackAllocate(size)
2273 
2276 #if defined(FPL_IS_CPP)
2277 # define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype) \
2278  inline etype operator | (etype a, etype b) { \
2279  return static_cast<etype>(static_cast<int>(a) | static_cast<int>(b)); \
2280  } \
2281  inline etype& operator |= (etype &a, etype b) { \
2282  return a = a | b; \
2283  } \
2284  inline etype operator & (etype a, etype b) { \
2285  return static_cast<etype>(static_cast<int>(a) & static_cast<int>(b)); \
2286  } \
2287  inline etype& operator &= (etype &a, etype b) { \
2288  return a = a & b; \
2289  } \
2290  inline etype operator ~ (etype a) { \
2291  return static_cast<etype>(~static_cast<int>(a)); \
2292  } \
2293  inline etype operator ^ (etype a, etype b) { \
2294  return static_cast<etype>(static_cast<int>(a) ^ static_cast<int>(b)); \
2295  } \
2296  inline etype& operator ^= (etype &a, etype b) { \
2297  return a = a ^ b; \
2298  }
2299 #else
2300 # define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype)
2301 #endif
2302 
2304 #define FPL_ENUM_AS_FLAGS_OPERATORS(type) FPL__M_ENUM_AS_FLAGS_OPERATORS(type)
2305 
2306 // ****************************************************************************
2307 //
2308 // Platform Includes
2309 //
2310 // ****************************************************************************
2311 #if !defined(FPL_NO_PLATFORM_INCLUDES) && !defined(FPL__HAS_PLATFORM_INCLUDES)
2312 # define FPL__HAS_PLATFORM_INCLUDES
2313 
2314 # if defined(FPL_PLATFORM_WINDOWS)
2315  // @NOTE(final): windef.h defines min/max macros in lowerspace, this will break for example std::min/max, so we have to tell the header we dont want this!
2316 # if !defined(NOMINMAX)
2317 # define NOMINMAX
2318 # endif
2319  // @NOTE(final): For now we dont want any network, com or gdi stuff at all, maybe later who knows.
2320 # if !defined(WIN32_LEAN_AND_MEAN)
2321 # define WIN32_LEAN_AND_MEAN 1
2322 # endif
2323  // @STUPID(final): Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here"
2324 struct IUnknown;
2325 # include <windows.h> // Win32 api
2326 # if _WIN32_WINNT < 0x0600
2327 # error "Windows Vista or higher required!"
2328 # endif
2329 # endif // FPL_PLATFORM_WINDOWS
2330 
2331 # if defined(FPL_SUBPLATFORM_POSIX)
2332 # include <pthread.h> // pthread_t, pthread_mutex_, pthread_cond_, pthread_barrier_
2333 # include <sched.h> // sched_param, sched_get_priority_max, SCHED_FIFO
2334 # include <semaphore.h> // sem_t
2335 # include <dirent.h> // DIR, dirent
2336 # endif // FPL_SUBPLATFORM_POSIX
2337 
2338 # if defined(FPL_SUBPLATFORM_X11)
2339 # include <X11/X.h> // Window
2340 # include <X11/Xlib.h> // Display
2341 # include <X11/Xutil.h> // XVisualInfo
2342 # include <X11/Xatom.h> // XA_CARDINAL
2343 # endif // FPL_SUBPLATFORM_X11
2344 
2345 #endif // !FPL_NO_PLATFORM_INCLUDES
2346 
2347 //
2348 // Platform handles
2349 //
2350 #if !defined(FPL__HAS_PLATFORM_INCLUDES) || defined(FPL_OPAQUE_HANDLES)
2351 
2352 # if defined(FPL_PLATFORM_WINDOWS)
2353 
2355 typedef uint64_t fpl__Win32Guid[4];
2357 typedef void *fpl__Win32Handle;
2359 typedef fpl__Win32Handle fpl__Win32InstanceHandle;
2361 typedef fpl__Win32Handle fpl__Win32LibraryHandle;
2363 typedef fpl__Win32Handle fpl__Win32FileHandle;
2365 typedef fpl__Win32Handle fpl__Win32ThreadHandle;
2367 typedef uint64_t fpl__Win32MutexHandle[16];
2369 typedef fpl__Win32Handle fpl__Win32SignalHandle;
2371 typedef void *fpl__Win32ConditionVariable;
2373 typedef fpl__Win32Handle fpl__Win32SemaphoreHandle;
2375 typedef fpl__Win32Handle fpl__Win32WindowHandle;
2377 typedef fpl__Win32Handle fpl__Win32DeviceContext;
2379 typedef fpl__Win32Handle fpl__Win32RenderingContext;
2380 
2381 # endif // FPL_PLATFORM_WINDOWS
2382 
2383 # if defined(FPL_SUBPLATFORM_POSIX)
2384 
2386 typedef void *fpl__POSIXLibraryHandle;
2388 typedef int fpl__POSIXFileHandle;
2390 typedef void *fpl__POSIXDirHandle;
2392 typedef uint64_t fpl__POSIXThreadHandle;
2394 typedef uint64_t fpl__POSIXMutexHandle[16];
2396 typedef uint64_t fpl__POSIXSemaphoreHandle[8];
2398 typedef uint64_t fpl__POSIXConditionVariable[16];
2399 
2400 # endif // FPL_SUBPLATFORM_POSIX
2401 
2402 # if defined(FPL_SUBPLATFORM_X11)
2403 
2405 typedef void *fpl__X11Display;
2407 typedef int fpl__X11Window;
2409 typedef void *fpl__X11Visual;
2411 typedef void *fpl__X11GC;
2413 typedef void *fpl__X11Image;
2415 typedef void *fpl__GLXContext;
2416 
2417 # endif // FPL_SUBPLATFORM_X11
2418 
2419 # if defined(FPL_PLATFORM_LINUX)
2420 
2422 typedef int fpl__LinuxSignalHandle;
2423 
2424 # endif // FPL_PLATFORM_LINUX
2425 
2426 #else
2427 
2428 # if defined(FPL_PLATFORM_WINDOWS)
2429 
2431 typedef GUID fpl__Win32Guid;
2433 typedef HANDLE fpl__Win32Handle;
2435 typedef HINSTANCE fpl__Win32InstanceHandle;
2437 typedef HMODULE fpl__Win32LibraryHandle;
2439 typedef HANDLE fpl__Win32ThreadHandle;
2441 typedef HANDLE fpl__Win32FileHandle;
2443 typedef CRITICAL_SECTION fpl__Win32MutexHandle;
2445 typedef HANDLE fpl__Win32SignalHandle;
2447 typedef CONDITION_VARIABLE fpl__Win32ConditionVariable;
2449 typedef HANDLE fpl__Win32SemaphoreHandle;
2451 typedef HWND fpl__Win32WindowHandle;
2453 typedef HDC fpl__Win32DeviceContext;
2455 typedef HGLRC fpl__Win32RenderingContext;
2456 
2457 # endif // FPL_PLATFORM_WINDOWS
2458 
2459 # if defined(FPL_SUBPLATFORM_POSIX)
2460 
2462 typedef void *fpl__POSIXLibraryHandle;
2464 typedef int fpl__POSIXFileHandle;
2466 typedef DIR *fpl__POSIXDirHandle;
2468 typedef pthread_t fpl__POSIXThreadHandle;
2470 typedef pthread_mutex_t fpl__POSIXMutexHandle;
2472 typedef sem_t fpl__POSIXSemaphoreHandle;
2474 typedef pthread_cond_t fpl__POSIXConditionVariable;
2475 
2476 # endif // FPL_SUBPLATFORM_POSIX
2477 
2478 # if defined(FPL_SUBPLATFORM_X11)
2479 
2481 typedef Display *fpl__X11Display;
2483 typedef Window fpl__X11Window;
2485 typedef Visual *fpl__X11Visual;
2487 typedef GC fpl__X11GC;
2489 typedef XImage *fpl__X11Image;
2491 typedef void *fpl__GLXContext;
2492 
2493 # endif // FPL_SUBPLATFORM_X11
2494 
2495 
2496 # if defined(FPL_PLATFORM_LINUX)
2497 
2499 typedef int fpl__LinuxSignalHandle;
2500 
2501 # endif // FPL_PLATFORM_LINUX
2502 
2503 
2504 #endif
2505 
2506 //
2507 // Constants
2508 //
2509 
2515 #if defined(FPL_PLATFORM_WINDOWS)
2516 # if defined(MAX_PATH)
2517 # define FPL__M_MAX_FILENAME_LENGTH (MAX_PATH)
2518 # define FPL__M_MAX_PATH_LENGTH (MAX_PATH * 2)
2519 # else
2520 # define FPL__M_MAX_FILENAME_LENGTH (260)
2521 # define FPL__M_MAX_PATH_LENGTH (260 * 2)
2522 # endif
2523 # define FPL__M_PATH_SEPARATOR '\\'
2524 # define FPL__M_FILE_EXT_SEPARATOR '.'
2525 #else
2526 # define FPL__M_MAX_FILENAME_LENGTH (512)
2527 # define FPL__M_MAX_PATH_LENGTH (2048)
2528 # define FPL__M_PATH_SEPARATOR '/'
2529 # define FPL__M_FILE_EXT_SEPARATOR '.'
2530 #endif
2531 
2533 #define FPL_MAX_FILENAME_LENGTH FPL__M_MAX_FILENAME_LENGTH
2534 #define FPL_MAX_PATH_LENGTH FPL__M_MAX_PATH_LENGTH
2536 #define FPL_PATH_SEPARATOR FPL__M_PATH_SEPARATOR
2538 #define FPL_FILE_EXT_SEPARATOR FPL__M_FILE_EXT_SEPARATOR
2540 #define FPL_MAX_NAME_LENGTH (256)
2542 #define FPL_MAX_BUFFER_LENGTH (2048)
2544 
2547 // ****************************************************************************
2548 //
2549 // > API
2550 //
2551 // ****************************************************************************
2552 
2553 // ----------------------------------------------------------------------------
2560 // ----------------------------------------------------------------------------
2561 
2562 //
2563 // Barrier/Fence
2564 //
2565 
2584 
2585 //
2586 // Exchange
2587 //
2588 
2597 fpl_platform_api uint32_t fplAtomicExchangeU32(volatile uint32_t *target, const uint32_t value);
2606 fpl_platform_api uint64_t fplAtomicExchangeU64(volatile uint64_t *target, const uint64_t value);
2615 fpl_platform_api int32_t fplAtomicExchangeS32(volatile int32_t *target, const int32_t value);
2624 fpl_platform_api int64_t fplAtomicExchangeS64(volatile int64_t *target, const int64_t value);
2633 fpl_common_api void *fplAtomicExchangePtr(volatile void **target, const void *value);
2642 fpl_common_api size_t fplAtomicExchangeSize(volatile size_t *target, const size_t value);
2643 
2644 //
2645 // Fetch and Add
2646 //
2647 
2656 fpl_platform_api uint32_t fplAtomicFetchAndAddU32(volatile uint32_t *value, const uint32_t addend);
2665 fpl_platform_api uint64_t fplAtomicFetchAndAddU64(volatile uint64_t *value, const uint64_t addend);
2674 fpl_platform_api int32_t fplAtomicFetchAndAddS32(volatile int32_t *value, const int32_t addend);
2683 fpl_platform_api int64_t fplAtomicFetchAndAddS64(volatile int64_t *value, const int64_t addend);
2692 fpl_common_api size_t fplAtomicFetchAndAddSize(volatile size_t *dest, const size_t addend);
2701 fpl_common_api void *fplAtomicFetchAndAddPtr(volatile void **dest, const intptr_t addend);
2702 
2703 //
2704 // Add and Fetch
2705 //
2706 
2715 fpl_platform_api uint32_t fplAtomicAddAndFetchU32(volatile uint32_t *dest, const uint32_t addend);
2724 fpl_platform_api uint64_t fplAtomicAddAndFetchU64(volatile uint64_t *dest, const uint64_t addend);
2733 fpl_platform_api int32_t fplAtomicAddAndFetchS32(volatile int32_t *dest, const int32_t addend);
2742 fpl_platform_api int64_t fplAtomicAddAndFetchS64(volatile int64_t *dest, const int64_t addend);
2751 fpl_common_api size_t fplAtomicAddAndFetchSize(volatile size_t *dest, const size_t addend);
2760 fpl_common_api void *fplAtomicAddAndFetchPtr(volatile void **dest, const intptr_t addend);
2761 
2762 //
2763 // Increment
2764 //
2765 
2773 fpl_platform_api uint32_t fplAtomicIncrementU32(volatile uint32_t *dest);
2781 fpl_platform_api uint64_t fplAtomicIncrementU64(volatile uint64_t *dest);
2789 fpl_platform_api int32_t fplAtomicIncrementS32(volatile int32_t *dest);
2797 fpl_platform_api int64_t fplAtomicIncrementS64(volatile int64_t *dest);
2805 fpl_common_api size_t fplAtomicIncrementSize(volatile size_t *dest);
2813 fpl_common_api void *fplAtomicIncrementPtr(volatile void **dest);
2814 
2815 //
2816 // CAS
2817 //
2818 
2829 fpl_platform_api uint32_t fplAtomicCompareAndSwapU32(volatile uint32_t *dest, const uint32_t comparand, const uint32_t exchange);
2840 fpl_platform_api uint64_t fplAtomicCompareAndSwapU64(volatile uint64_t *dest, const uint64_t comparand, const uint64_t exchange);
2851 fpl_platform_api int32_t fplAtomicCompareAndSwapS32(volatile int32_t *dest, const int32_t comparand, const int32_t exchange);
2862 fpl_platform_api int64_t fplAtomicCompareAndSwapS64(volatile int64_t *dest, const int64_t comparand, const int64_t exchange);
2873 fpl_common_api size_t fplAtomicCompareAndSwapSize(volatile size_t *dest, const size_t comparand, const size_t exchange);
2884 fpl_common_api void *fplAtomicCompareAndSwapPtr(volatile void **dest, const void *comparand, const void *exchange);
2885 
2895 fpl_platform_api bool fplAtomicIsCompareAndSwapU32(volatile uint32_t *dest, const uint32_t comparand, const uint32_t exchange);
2905 fpl_platform_api bool fplAtomicIsCompareAndSwapU64(volatile uint64_t *dest, const uint64_t comparand, const uint64_t exchange);
2915 fpl_platform_api bool fplAtomicIsCompareAndSwapS32(volatile int32_t *dest, const int32_t comparand, const int32_t exchange);
2925 fpl_platform_api bool fplAtomicIsCompareAndSwapS64(volatile int64_t *dest, const int64_t comparand, const int64_t exchange);
2935 fpl_common_api bool fplAtomicIsCompareAndSwapSize(volatile size_t *dest, const size_t comparand, const size_t exchange);
2945 fpl_common_api bool fplAtomicIsCompareAndSwapPtr(volatile void **dest, const void *comparand, const void *exchange);
2946 
2947 //
2948 // Load
2949 //
2950 
2959 fpl_platform_api uint32_t fplAtomicLoadU32(volatile uint32_t *source);
2968 fpl_platform_api uint64_t fplAtomicLoadU64(volatile uint64_t *source);
2977 fpl_platform_api int32_t fplAtomicLoadS32(volatile int32_t *source);
2986 fpl_platform_api int64_t fplAtomicLoadS64(volatile int64_t *source);
2995 fpl_common_api size_t fplAtomicLoadSize(volatile size_t *source);
3004 fpl_common_api void *fplAtomicLoadPtr(volatile void **source);
3005 
3006 //
3007 // Store
3008 //
3009 
3017 fpl_platform_api void fplAtomicStoreU32(volatile uint32_t *dest, const uint32_t value);
3025 fpl_platform_api void fplAtomicStoreU64(volatile uint64_t *dest, const uint64_t value);
3033 fpl_platform_api void fplAtomicStoreS32(volatile int32_t *dest, const int32_t value);
3041 fpl_platform_api void fplAtomicStoreS64(volatile int64_t *dest, const int64_t value);
3049 fpl_common_api void fplAtomicStoreSize(volatile size_t *dest, const size_t value);
3057 fpl_common_api void fplAtomicStorePtr(volatile void **dest, const void *value);
3058 
3061 // ----------------------------------------------------------------------------
3067 // ----------------------------------------------------------------------------
3068 
3070 typedef struct fplMemoryBlock {
3072  void *base;
3074  size_t size;
3075 } fplMemoryBlock;
3076 
3078 typedef struct fplMemoryInfos {
3086  uint64_t totalCacheSize;
3088  uint64_t freeCacheSize;
3090  uint64_t totalPageCount;
3092  uint64_t freePageCount;
3094  uint64_t pageSize;
3095 } fplMemoryInfos;
3096 
3103 fpl_common_api void fplMemoryClear(void *mem, const size_t size);
3111 fpl_common_api void fplMemorySet(void *mem, const uint8_t value, const size_t size);
3119 fpl_common_api void fplMemoryCopy(const void *sourceMem, const size_t sourceSize, void *targetMem);
3129 fpl_platform_api void *fplMemoryAllocate(const size_t size);
3137 fpl_platform_api void fplMemoryFree(void *ptr);
3147 fpl_common_api void *fplMemoryAlignedAllocate(const size_t size, const size_t alignment);
3155 fpl_common_api void fplMemoryAlignedFree(void *ptr);
3163 
3166 // ----------------------------------------------------------------------------
3172 // ----------------------------------------------------------------------------
3173 
3175 typedef char fplVersionNumberPart[4 + 1];
3176 
3178 typedef struct fplVersionInfo {
3181  union {
3184  struct {
3193  };
3194  };
3195 } fplVersionInfo;
3196 
3198 typedef struct fplOSVersionInfos {
3208 
3217 
3220 // ----------------------------------------------------------------------------
3226 // ----------------------------------------------------------------------------
3227 
3235 fpl_platform_api size_t fplSessionGetUsername(char *nameBuffer, const size_t maxNameBufferLen);
3236 
3239 // ----------------------------------------------------------------------------
3246 // ----------------------------------------------------------------------------
3247 
3249 typedef enum fplCPUArchType {
3262 
3267 } fplCPUArchType;
3268 
3270 typedef struct fplCPUCapabilities {
3294 
3296 typedef union fplCPUIDLeaf {
3297  struct {
3299  uint32_t eax;
3301  uint32_t ebx;
3303  uint32_t ecx;
3305  uint32_t edx;
3306  };
3308  uint32_t raw[4];
3309 } fplCPUIDLeaf;
3310 
3317 fpl_common_api void fplCPUID(fplCPUIDLeaf *outLeaf, const uint32_t functionId);
3323 fpl_common_api uint64_t fplCPUXCR0();
3329 fpl_common_api uint64_t fplCPURDTSC();
3336 fpl_common_api const char *fplCPUGetArchName(const fplCPUArchType type);
3350 fpl_common_api size_t fplCPUGetName(char *destBuffer, const size_t maxDestBufferLen);
3364 
3367 // ----------------------------------------------------------------------------
3373 // ----------------------------------------------------------------------------
3374 
3376 typedef enum fplInitFlags {
3391 } fplInitFlags;
3394 
3396 typedef enum fplPlatformType {
3405 
3410 } fplPlatformType;
3411 
3430 
3436 
3444 
3446 typedef enum fplVideoBackendType {
3455 
3461 
3462 #if defined(FPL__ENABLE_VIDEO_OPENGL)
3463 typedef enum fplOpenGLCompabilityFlags {
3474 
3476 typedef struct fplOpenGLSettings {
3480  uint32_t majorVersion;
3482  uint32_t minorVersion;
3486 #endif // FPL__ENABLE_VIDEO_OPENGL
3487 
3488 #if defined(FPL__ENABLE_VIDEO_VULKAN)
3489 
3491 typedef void (fplVulkanValidationLayerCallback)(void *userData, const char *message, const uint32_t messageSeverity, const uint32_t messageType, const void *debugUtilsMessengerCallbackData);
3492 
3502 
3518 
3520 typedef struct fplVulkanSettings {
3528  const char *appName;
3530  const char *engineName;
3534  const void *allocator;
3538  void *userData;
3544 #endif // FPL__ENABLE_VIDEO_VULKAN
3545 
3547 typedef union fplGraphicsApiSettings {
3548 #if defined(FPL__ENABLE_VIDEO_OPENGL)
3551 #endif
3552 #if defined(FPL__ENABLE_VIDEO_VULKAN)
3555 #endif
3556  int dummy;
3559 
3561 typedef struct fplVideoSettings {
3571 
3579 
3581 typedef enum fplAudioBackendType {
3590 
3596 
3598 typedef enum fplAudioFormatType {
3615 
3621 
3639 
3641 typedef enum fplAudioLatencyMode {
3647 
3649 typedef struct fplAudioDeviceFormat {
3653  uint32_t sampleRate;
3655  uint32_t channels;
3657  uint32_t periods;
3667 
3669 typedef struct fplAudioTargetFormat {
3671  uint32_t sampleRate;
3673  uint32_t channels;
3679  uint32_t periods;
3687 
3689 typedef union fplAudioDeviceID {
3690 #if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
3691  fpl__Win32Guid dshow;
3693 #endif
3694 #if defined(FPL__ENABLE_AUDIO_ALSA)
3695  char alsa[256];
3697 #endif
3698  int dummy;
3701 
3703 typedef struct fplAudioDeviceInfo {
3709 
3710 #if defined(FPL__ENABLE_AUDIO_ALSA)
3711 typedef struct fplAlsaAudioSettings {
3714  fpl_b32 noMMap;
3715 } fplAlsaAudioSettings;
3716 #endif
3717 
3720 #if defined(FPL__ENABLE_AUDIO_ALSA)
3721  fplAlsaAudioSettings alsa;
3723 #endif
3724  int dummy;
3727 
3737 typedef uint32_t(fpl_audio_client_read_callback)(const fplAudioDeviceFormat *deviceFormat, const uint32_t frameCount, void *outputSamples, void *userData);
3738 
3740 typedef struct fplAudioSettings {
3750  void *userData;
3758 
3766 
3768 typedef enum fplImageType {
3773 } fplImageType;
3774 
3776 typedef struct fplImageSource {
3778  const uint8_t *data;
3780  uint32_t width;
3782  uint32_t height;
3785 } fplImageSource;
3786 
3795 typedef bool (fpl_window_event_callback)(const fplPlatformType platformType, void *windowState, void *rawEventData, void *userData);
3796 
3806 
3808 typedef struct fplWindowCallbacks {
3818 
3820 typedef struct fplWindowSize {
3822  uint32_t width;
3824  uint32_t height;
3825 } fplWindowSize;
3826 
3828 typedef struct fplWindowPosition {
3830  int32_t left;
3832  int32_t top;
3834 
3836 typedef struct fplWindowSettings {
3858 
3866 
3868 typedef struct fplConsoleSettings {
3872 
3879 
3881 typedef struct fplInputSettings {
3887 
3895 
3897 typedef void *(fpl_memory_allocate_callback)(void *userData, const size_t size, const size_t alignment);
3899 typedef void (fpl_memory_release_callback)(void *userData, void *ptr);
3900 
3908 
3918  void *userData;
3920 
3922 typedef struct fplMemorySettings {
3928 
3930 typedef struct fplSettings {
3943 } fplSettings;
3944 
3964 
3967 // ----------------------------------------------------------------------------
3973 // ----------------------------------------------------------------------------
3974 
3987 fpl_common_api const char *fplGetPlatformName(const fplPlatformType type);
3996 fpl_common_api bool fplPlatformInit(const fplInitFlags initFlags, const fplSettings *initSettings);
4013 
4016 // ----------------------------------------------------------------------------
4022 // ----------------------------------------------------------------------------
4023 
4025 typedef enum fplLogLevel {
4042 
4047 } fplLogLevel;
4048 
4049 #if defined(FPL__ENABLE_LOGGING)
4050 
4058 typedef void (fpl_log_func_callback)(const char *funcName, const int lineNumber, const fplLogLevel level, const char *message);
4059 
4061 typedef enum fplLogWriterFlags {
4075 
4077 typedef struct fplLogWriterConsole {
4079  int dummy;
4081 
4083 typedef struct fplLogWriterCustom {
4087 
4089 typedef struct fplLogWriter {
4096 } fplLogWriter;
4097 
4099 typedef struct fplLogSettings {
4100 #if defined(FPL__ENABLE_LOG_MULTIPLE_WRITERS)
4101  union {
4103  fplLogWriter writers[6];
4104  struct {
4106  fplLogWriter criticalWriter;
4108  fplLogWriter errorWriter;
4110  fplLogWriter warningWriter;
4112  fplLogWriter infoWriter;
4114  fplLogWriter verboseWriter;
4116  fplLogWriter debugWriter;
4117  };
4118  };
4119 #else
4120  fplLogWriter writers[1];
4122 #endif // FPL_USE_LOG_SIMPLE
4127 } fplLogSettings;
4128 
4135 fpl_common_api void fplSetLogSettings(const fplLogSettings *params);
4149 fpl_common_api void fplSetMaxLogLevel(const fplLogLevel maxLevel);
4157 #endif // FPL__ENABLE_LOGGING
4158 
4161 // ----------------------------------------------------------------------------
4167 // ----------------------------------------------------------------------------
4168 
4175 fpl_common_api const char *fplGetLastError();
4183 fpl_common_api const char *fplGetErrorByIndex(const size_t index);
4197 
4200 // ----------------------------------------------------------------------------
4206 // ----------------------------------------------------------------------------
4207 
4210 #if defined(FPL_PLATFORM_WINDOWS)
4211  fpl__Win32LibraryHandle win32LibraryHandle;
4213 #elif defined(FPL_SUBPLATFORM_POSIX)
4214  fpl__POSIXLibraryHandle posixLibraryHandle;
4216 #endif
4218 
4220 typedef struct fplDynamicLibraryHandle {
4226 
4234 fpl_platform_api bool fplDynamicLibraryLoad(const char *libraryFilePath, fplDynamicLibraryHandle *outHandle);
4242 fpl_platform_api void *fplGetDynamicLibraryProc(const fplDynamicLibraryHandle *handle, const char *name);
4249 
4252 // ----------------------------------------------------------------------------
4257 // ----------------------------------------------------------------------------
4258 
4265 fpl_platform_api void fplDebugOut(const char *text);
4273 fpl_common_api void fplDebugFormatOut(const char *format, ...);
4274 
4277 // ----------------------------------------------------------------------------
4283 // ----------------------------------------------------------------------------
4284 
4290 fpl_platform_api void fplConsoleOut(const char *text);
4296 fpl_platform_api void fplConsoleError(const char *text);
4303 
4310 fpl_common_api void fplConsoleFormatOut(const char *format, ...);
4317 fpl_common_api void fplConsoleFormatError(const char *format, ...);
4318 
4321 // ----------------------------------------------------------------------------
4327 // ----------------------------------------------------------------------------
4328 
4330 typedef union fplWallClock {
4331 #if defined(FPL_PLATFORM_WINDOWS)
4332  struct {
4335  uint64_t qpc;
4336  } win32;
4337 #endif
4338 #if defined(FPL_SUBPLATFORM_POSIX)
4339  struct {
4342  uint64_t seconds;
4344  int64_t nanoSeconds;
4345  } posix;
4346 #endif
4347  uint64_t unused;
4349 } fplWallClock;
4350 
4361 fpl_platform_api double fplGetWallDelta(const fplWallClock start, const fplWallClock finish);
4398 
4401 // ----------------------------------------------------------------------------
4407 // ----------------------------------------------------------------------------
4408 
4410 typedef uint32_t fplTimeoutValue;
4412 #define FPL_TIMEOUT_INFINITE UINT32_MAX
4413 
4415 typedef enum fplThreadStates {
4424 } fplThreadStates;
4425 
4427 typedef uint32_t fplThreadState;
4428 
4430 typedef enum fplThreadPriority {
4433 
4444 
4449 
4455 
4458 
4464 typedef void (fpl_run_thread_callback)(const fplThreadHandle *thread, void *data);
4465 
4468 #if defined(FPL_PLATFORM_WINDOWS)
4469  fpl__Win32ThreadHandle win32ThreadHandle;
4471 #elif defined(FPL_SUBPLATFORM_POSIX)
4472  fpl__POSIXThreadHandle posixThread;
4474 #endif
4476 
4478 typedef struct fplThreadParameters {
4480  void *userData;
4484  size_t stackSize;
4488 
4490 typedef struct fplThreadHandle {
4498  uint32_t id;
4500  volatile fpl_b32 isValid;
4503 } fplThreadHandle;
4504 
4505 #if defined(FPL_PLATFORM_WINDOWS)
4506 typedef struct fpl__Win32InternalSemaphore {
4508  fpl__Win32SemaphoreHandle handle;
4510  volatile int32_t value;
4511 } fpl__Win32InternalSemaphore;
4512 #endif
4513 
4516 #if defined(FPL_PLATFORM_WINDOWS)
4517  fpl__Win32InternalSemaphore win32;
4519 #elif defined(FPL_SUBPLATFORM_POSIX)
4520  fpl__POSIXSemaphoreHandle posixHandle;
4522 #endif
4524 
4526 typedef struct fplSemaphoreHandle {
4532 
4534 typedef union fplInternalMutexHandle {
4535 #if defined(FPL_PLATFORM_WINDOWS)
4536  fpl__Win32MutexHandle win32CriticalSection;
4538 #elif defined(FPL_SUBPLATFORM_POSIX)
4539  fpl__POSIXMutexHandle posixMutex;
4541 #endif
4543 
4545 typedef struct fplMutexHandle {
4550 } fplMutexHandle;
4551 
4554 #if defined(FPL_PLATFORM_WINDOWS)
4555  fpl__Win32SignalHandle win32EventHandle;
4557 #elif defined(FPL_PLATFORM_LINUX)
4558  fpl__LinuxSignalHandle linuxEventHandle;
4560 #endif
4562 
4564 typedef struct fplSignalHandle {
4569 } fplSignalHandle;
4570 
4572 typedef enum fplSignalValue {
4577 } fplSignalValue;
4578 
4581 #if defined(FPL_PLATFORM_WINDOWS)
4582  fpl__Win32ConditionVariable win32Condition;
4584 #elif defined(FPL_SUBPLATFORM_POSIX)
4585  fpl__POSIXConditionVariable posixCondition;
4587 #endif
4588  int dummy;
4591 
4593 typedef struct fplConditionVariable {
4599 
4653 fpl_platform_api void fplThreadSleep(const uint32_t milliseconds);
4686 fpl_platform_api bool fplThreadWaitForAll(fplThreadHandle **threads, const size_t count, const size_t stride, const fplTimeoutValue timeout);
4696 fpl_platform_api bool fplThreadWaitForAny(fplThreadHandle **threads, const size_t count, const size_t stride, const fplTimeoutValue timeout);
4697 
4733 
4742 fpl_platform_api bool fplSignalInit(fplSignalHandle *signal, const fplSignalValue initialValue);
4766 fpl_platform_api bool fplSignalWaitForAll(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout);
4776 fpl_platform_api bool fplSignalWaitForAny(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout);
4791 
4830 
4838 fpl_platform_api bool fplSemaphoreInit(fplSemaphoreHandle *semaphore, const uint32_t initialValue);
4877 
4880 // ----------------------------------------------------------------------------
4886 // ----------------------------------------------------------------------------
4887 
4894 fpl_common_api bool fplIsStringMatchWildcard(const char *source, const char *wildcard);
4904 fpl_common_api bool fplIsStringEqualLen(const char *a, const size_t aLen, const char *b, const size_t bLen);
4911 fpl_common_api bool fplIsStringEqual(const char *a, const char *b);
4918 fpl_common_api char *fplEnforcePathSeparatorLen(char *path, size_t maxPathLen);
4925 fpl_common_api char *fplEnforcePathSeparator(char *path);
4934 fpl_common_api char *fplStringAppendLen(const char *appended, const size_t appendedLen, char *buffer, size_t maxBufferLen);
4942 fpl_common_api char *fplStringAppend(const char *appended, char *buffer, size_t maxBufferLen);
4948 fpl_common_api size_t fplGetStringLength(const char *str);
4958 fpl_common_api char *fplCopyStringLen(const char *source, const size_t sourceLen, char *dest, const size_t maxDestLen);
4967 fpl_common_api char *fplCopyString(const char *source, char *dest, const size_t maxDestLen);
4977 fpl_platform_api size_t fplWideStringToUTF8String(const wchar_t *wideSource, const size_t wideSourceLen, char *utf8Dest, const size_t maxUtf8DestLen);
4987 fpl_platform_api size_t fplUTF8StringToWideString(const char *utf8Source, const size_t utf8SourceLen, wchar_t *wideDest, const size_t maxWideDestLen);
4997 fpl_common_api size_t fplFormatString(char *destBuffer, const size_t maxDestBufferLen, const char *format, ...);
5007 fpl_common_api size_t fplFormatStringArgs(char *destBuffer, const size_t maxDestBufferLen, const char *format, va_list argList);
5008 
5015 fpl_common_api int32_t fplStringToS32Len(const char *str, const size_t len);
5016 
5022 fpl_common_api int32_t fplStringToS32(const char *str);
5023 
5031 fpl_common_api size_t fplS32ToString(const int32_t value, char *buffer, const size_t maxBufferLen);
5032 
5035 // ----------------------------------------------------------------------------
5041 // ----------------------------------------------------------------------------
5042 
5044 typedef union fplInternalFileHandle {
5045 #if defined(FPL_PLATFORM_WINDOWS)
5046  fpl__Win32FileHandle win32FileHandle;
5048 #elif defined(FPL_SUBPLATFORM_POSIX)
5049  fpl__POSIXFileHandle posixFileHandle;
5051 #endif
5053 
5055 typedef struct fplFileHandle {
5060 } fplFileHandle;
5061 
5063 typedef enum fplFilePositionMode {
5071 
5073 typedef enum fplFileEntryType {
5081 
5095 
5109 
5111 typedef union fplFilePermissions {
5112  struct {
5114  uint8_t user;
5116  uint8_t group;
5118  uint8_t owner;
5120  uint8_t unused;
5121  };
5123  uint32_t umask;
5125 
5141 
5144 #if defined(FPL_PLATFORM_WINDOWS)
5145  fpl__Win32FileHandle win32FileHandle;
5147 #elif defined(FPL_SUBPLATFORM_POSIX)
5148  fpl__POSIXDirHandle posixDirHandle;
5150 #endif
5152 
5154 typedef struct fplInternalFileRootInfo {
5156  const char *rootPath;
5158  const char *filter;
5160 
5162 typedef uint64_t fplFileTimeStamp;
5163 
5165 typedef struct fplFileTimeStamps {
5173 
5175 typedef struct fplFileEntry {
5191  size_t size;
5192 } fplFileEntry;
5193 
5201 fpl_platform_api bool fplOpenBinaryFile(const char *filePath, fplFileHandle *outHandle);
5209 fpl_platform_api bool fplCreateBinaryFile(const char *filePath, fplFileHandle *outHandle);
5220 fpl_platform_api uint32_t fplReadFileBlock32(const fplFileHandle *fileHandle, const uint32_t sizeToRead, void *targetBuffer, const uint32_t maxTargetBufferSize);
5231 fpl_platform_api uint64_t fplReadFileBlock64(const fplFileHandle *fileHandle, const uint64_t sizeToRead, void *targetBuffer, const uint64_t maxTargetBufferSize);
5242 fpl_platform_api size_t fplReadFileBlock(const fplFileHandle *fileHandle, const size_t sizeToRead, void *targetBuffer, const size_t maxTargetBufferSize);
5252 fpl_platform_api uint32_t fplWriteFileBlock32(const fplFileHandle *fileHandle, void *sourceBuffer, const uint32_t sourceSize);
5262 fpl_platform_api uint64_t fplWriteFileBlock64(const fplFileHandle *fileHandle, void *sourceBuffer, const uint64_t sourceSize);
5272 fpl_common_api size_t fplWriteFileBlock(const fplFileHandle *fileHandle, void *sourceBuffer, const size_t sourceSize);
5281 fpl_platform_api uint32_t fplSetFilePosition32(const fplFileHandle *fileHandle, const int32_t position, const fplFilePositionMode mode);
5290 fpl_platform_api uint64_t fplSetFilePosition64(const fplFileHandle *fileHandle, const int64_t position, const fplFilePositionMode mode);
5299 fpl_common_api size_t fplSetFilePosition(const fplFileHandle *fileHandle, const intptr_t position, const fplFilePositionMode mode);
5307 fpl_platform_api uint32_t fplGetFilePosition32(const fplFileHandle *fileHandle);
5315 fpl_platform_api uint64_t fplGetFilePosition64(const fplFileHandle *fileHandle);
5323 fpl_common_api size_t fplGetFilePosition(const fplFileHandle *fileHandle);
5329 fpl_platform_api bool fplFlushFile(fplFileHandle *fileHandle);
5335 fpl_platform_api void fplCloseFile(fplFileHandle *fileHandle);
5336 
5343 fpl_platform_api uint32_t fplGetFileSizeFromPath32(const char *filePath);
5350 fpl_platform_api uint64_t fplGetFileSizeFromPath64(const char *filePath);
5357 fpl_platform_api size_t fplGetFileSizeFromPath(const char *filePath);
5364 fpl_platform_api uint32_t fplGetFileSizeFromHandle32(const fplFileHandle *fileHandle);
5371 fpl_platform_api uint64_t fplGetFileSizeFromHandle64(const fplFileHandle *fileHandle);
5378 fpl_common_api size_t fplGetFileSizeFromHandle(const fplFileHandle *fileHandle);
5385 fpl_platform_api bool fplGetFileTimestampsFromPath(const char *filePath, fplFileTimeStamps *outStamps);
5399 fpl_platform_api bool fplSetFileTimestamps(const char *filePath, const fplFileTimeStamps *timeStamps);
5405 fpl_platform_api bool fplFileExists(const char *filePath);
5413 fpl_platform_api bool fplFileCopy(const char *sourceFilePath, const char *targetFilePath, const bool overwrite);
5420 fpl_platform_api bool fplFileMove(const char *sourceFilePath, const char *targetFilePath);
5426 fpl_platform_api bool fplFileDelete(const char *filePath);
5427 
5433 fpl_platform_api bool fplDirectoriesCreate(const char *path);
5439 fpl_platform_api bool fplDirectoryExists(const char *path);
5445 fpl_platform_api bool fplDirectoryRemove(const char *path);
5456 fpl_platform_api bool fplListDirBegin(const char *path, const char *filter, fplFileEntry *entry);
5473 
5476 // ----------------------------------------------------------------------------
5482 // ----------------------------------------------------------------------------
5483 
5491 fpl_platform_api size_t fplGetExecutableFilePath(char *destPath, const size_t maxDestLen);
5499 fpl_platform_api size_t fplGetHomePath(char *destPath, const size_t maxDestLen);
5508 fpl_common_api size_t fplExtractFilePath(const char *sourcePath, char *destPath, const size_t maxDestLen);
5515 fpl_common_api const char *fplExtractFileExtension(const char *sourcePath);
5522 fpl_common_api const char *fplExtractFileName(const char *sourcePath);
5532 fpl_common_api size_t fplChangeFileExtension(const char *filePath, const char *newFileExtension, char *destPath, const size_t maxDestLen);
5542 fpl_common_api size_t fplPathCombine(char *destPath, const size_t maxDestPathLen, const size_t pathCount, ...);
5543 
5546 #if defined(FPL__ENABLE_WINDOW)
5547 // ----------------------------------------------------------------------------
5553 // ----------------------------------------------------------------------------
5554 
5556 typedef enum fplKey {
5557  fplKey_None = 0,
5558 
5559  // 0x0-0x07: Undefined
5560 
5561  fplKey_Backspace = 0x08,
5562  fplKey_Tab = 0x09,
5563 
5564  // 0x0A-0x0B: Reserved
5565 
5566  fplKey_Clear = 0x0C,
5567  fplKey_Return = 0x0D,
5568 
5569  // 0x0E-0x0F: Undefined
5570 
5571  fplKey_Shift = 0x10,
5572  fplKey_Control = 0x11,
5573  fplKey_Alt = 0x12,
5574  fplKey_Pause = 0x13,
5575  fplKey_CapsLock = 0x14,
5576 
5577  // 0x15: IME-Keys
5578  // 0x16: Undefined
5579  // 0x17-0x19 IME-Keys
5580  // 0x1A: Undefined
5581 
5582  fplKey_Escape = 0x1B,
5583 
5584  // 0x1C-0x1F: IME-Keys
5585 
5586  fplKey_Space = 0x20,
5587  fplKey_PageUp = 0x21,
5588  fplKey_PageDown = 0x22,
5589  fplKey_End = 0x23,
5590  fplKey_Home = 0x24,
5591  fplKey_Left = 0x25,
5592  fplKey_Up = 0x26,
5593  fplKey_Right = 0x27,
5594  fplKey_Down = 0x28,
5595  fplKey_Select = 0x29,
5596  fplKey_Print = 0x2A,
5597  fplKey_Execute = 0x2B,
5598  fplKey_Snapshot = 0x2C,
5599  fplKey_Insert = 0x2D,
5600  fplKey_Delete = 0x2E,
5601  fplKey_Help = 0x2F,
5602 
5603  fplKey_0 = 0x30,
5604  fplKey_1 = 0x31,
5605  fplKey_2 = 0x32,
5606  fplKey_3 = 0x33,
5607  fplKey_4 = 0x34,
5608  fplKey_5 = 0x35,
5609  fplKey_6 = 0x36,
5610  fplKey_7 = 0x37,
5611  fplKey_8 = 0x38,
5612  fplKey_9 = 0x39,
5613 
5614  // 0x3A-0x40: Undefined
5615 
5616  fplKey_A = 0x41,
5617  fplKey_B = 0x42,
5618  fplKey_C = 0x43,
5619  fplKey_D = 0x44,
5620  fplKey_E = 0x45,
5621  fplKey_F = 0x46,
5622  fplKey_G = 0x47,
5623  fplKey_H = 0x48,
5624  fplKey_I = 0x49,
5625  fplKey_J = 0x4A,
5626  fplKey_K = 0x4B,
5627  fplKey_L = 0x4C,
5628  fplKey_M = 0x4D,
5629  fplKey_N = 0x4E,
5630  fplKey_O = 0x4F,
5631  fplKey_P = 0x50,
5632  fplKey_Q = 0x51,
5633  fplKey_R = 0x52,
5634  fplKey_S = 0x53,
5635  fplKey_T = 0x54,
5636  fplKey_U = 0x55,
5637  fplKey_V = 0x56,
5638  fplKey_W = 0x57,
5639  fplKey_X = 0x58,
5640  fplKey_Y = 0x59,
5641  fplKey_Z = 0x5A,
5642 
5643  fplKey_LeftSuper = 0x5B,
5644  fplKey_RightSuper = 0x5C,
5645  fplKey_Apps = 0x5D,
5646 
5647  // 0x5E: Reserved
5648 
5649  fplKey_Sleep = 0x5F,
5650  fplKey_NumPad0 = 0x60,
5651  fplKey_NumPad1 = 0x61,
5652  fplKey_NumPad2 = 0x62,
5653  fplKey_NumPad3 = 0x63,
5654  fplKey_NumPad4 = 0x64,
5655  fplKey_NumPad5 = 0x65,
5656  fplKey_NumPad6 = 0x66,
5657  fplKey_NumPad7 = 0x67,
5658  fplKey_NumPad8 = 0x68,
5659  fplKey_NumPad9 = 0x69,
5660  fplKey_Multiply = 0x6A,
5661  fplKey_Add = 0x6B,
5662  fplKey_Separator = 0x6C,
5663  fplKey_Substract = 0x6D,
5664  fplKey_Decimal = 0x6E,
5665  fplKey_Divide = 0x6F,
5666  fplKey_F1 = 0x70,
5667  fplKey_F2 = 0x71,
5668  fplKey_F3 = 0x72,
5669  fplKey_F4 = 0x73,
5670  fplKey_F5 = 0x74,
5671  fplKey_F6 = 0x75,
5672  fplKey_F7 = 0x76,
5673  fplKey_F8 = 0x77,
5674  fplKey_F9 = 0x78,
5675  fplKey_F10 = 0x79,
5676  fplKey_F11 = 0x7A,
5677  fplKey_F12 = 0x7B,
5678  fplKey_F13 = 0x7C,
5679  fplKey_F14 = 0x7D,
5680  fplKey_F15 = 0x7E,
5681  fplKey_F16 = 0x7F,
5682  fplKey_F17 = 0x80,
5683  fplKey_F18 = 0x81,
5684  fplKey_F19 = 0x82,
5685  fplKey_F20 = 0x83,
5686  fplKey_F21 = 0x84,
5687  fplKey_F22 = 0x85,
5688  fplKey_F23 = 0x86,
5689  fplKey_F24 = 0x87,
5690 
5691  // 0x88-8F: Unassigned
5692 
5693  fplKey_NumLock = 0x90,
5694  fplKey_Scroll = 0x91,
5695 
5696  // 0x92-9x96: OEM specific
5697  // 0x97-0x9F: Unassigned
5698 
5699  fplKey_LeftShift = 0xA0,
5700  fplKey_RightShift = 0xA1,
5701  fplKey_LeftControl = 0xA2,
5702  fplKey_RightControl = 0xA3,
5703  fplKey_LeftAlt = 0xA4,
5704  fplKey_RightAlt = 0xA5,
5705 
5706  // 0xA6-0xAC: Dont care
5707 
5708  fplKey_VolumeMute = 0xAD,
5709  fplKey_VolumeDown = 0xAE,
5710  fplKey_VolumeUp = 0xAF,
5711  fplKey_MediaNextTrack = 0xB0,
5712  fplKey_MediaPrevTrack = 0xB1,
5713  fplKey_MediaStop = 0xB2,
5714  fplKey_MediaPlayPause = 0xB3,
5715 
5716  // 0xB4-0xB9 Dont care
5717 
5719  fplKey_Oem1 = 0xBA,
5729  fplKey_Oem2 = 0xBF,
5731  fplKey_Oem3 = 0xC0,
5732 
5733  // 0xC1-0xD7 Reserved
5734  // 0xD8-0xDA Unassigned
5735 
5737  fplKey_Oem4 = 0xDB,
5739  fplKey_Oem5 = 0xDC,
5741  fplKey_Oem6 = 0xDD,
5743  fplKey_Oem7 = 0xDE,
5744  fplKey_Oem8 = 0xDF,
5745 
5746  // 0xE0-0xFE Dont care
5747 } fplKey;
5748 
5750 typedef enum fplWindowEventType {
5778 
5780 typedef struct fplWindowDropFiles {
5784  const char **files;
5786  size_t fileCount;
5788 
5790 typedef struct fplWindowEvent {
5793  union {
5800  };
5801 } fplWindowEvent;
5802 
5804 typedef enum fplButtonState {
5811 } fplButtonState;
5812 
5814 typedef enum fplKeyboardEventType {
5822 
5852 
5854 typedef struct fplKeyboardEvent {
5856  uint64_t keyCode;
5866 
5868 typedef enum fplMouseEventType {
5878 
5880 typedef enum fplMouseButtonType {
5892 
5894 typedef struct fplMouseEvent {
5902  int32_t mouseX;
5904  int32_t mouseY;
5906  float wheelDelta;
5907 } fplMouseEvent;
5908 
5910 typedef enum fplGamepadEventType {
5920 
5922 typedef struct fplGamepadButton {
5926 
5928 typedef enum fplGamepadButtonType {
5937 
5946 
5951 
5956 
5962 
5964 typedef struct fplGamepadState {
5965  union {
5966  struct {
5975 
5984 
5989 
5994 
5999  };
6002  };
6003 
6005  const char *deviceName;
6006 
6008  float leftStickX;
6010  float leftStickY;
6015 
6020 
6025 } fplGamepadState;
6026 
6028 typedef struct fplGamepadEvent {
6032  const char *deviceName;
6036  uint32_t deviceIndex;
6037 } fplGamepadEvent;
6038 
6040 typedef enum fplEventType {
6051 } fplEventType;
6052 
6054 typedef struct fplEvent {
6057  union {
6066  };
6067 } fplEvent;
6068 
6076 
6083 
6086 // ----------------------------------------------------------------------------
6092 // ----------------------------------------------------------------------------
6093 
6095 #define FPL_MAX_KEYBOARD_STATE_COUNT 256
6096 
6098 typedef struct fplKeyboardState {
6106 
6108 #define FPL_MAX_GAMEPAD_STATE_COUNT 4
6109 
6111 typedef struct fplGamepadStates {
6115 
6117 typedef struct fplMouseState {
6121  int32_t x;
6123  int32_t y;
6124 } fplMouseState;
6125 
6144 
6150 fpl_platform_api bool fplQueryCursorPosition(int32_t *outX, int32_t *outY);
6151 
6154 // ----------------------------------------------------------------------------
6160 // ----------------------------------------------------------------------------
6161 
6163 typedef enum fplWindowState {
6174 } fplWindowState;
6175 
6185 
6204 fpl_platform_api void fplSetWindowCursorEnabled(const bool value);
6216 fpl_platform_api void fplSetWindowSize(const uint32_t width, const uint32_t height);
6226 fpl_platform_api void fplSetWindowResizeable(const bool value);
6236 fpl_platform_api void fplSetWindowDecorated(const bool value);
6246 fpl_platform_api void fplSetWindowFloating(const bool value);
6256 fpl_platform_api bool fplSetWindowFullscreenSize(const bool value, const uint32_t fullscreenWidth, const uint32_t fullscreenHeight, const uint32_t refreshRate);
6267 fpl_platform_api bool fplSetWindowFullscreenRect(const bool value, const int32_t x, const int32_t y, const int32_t width, const int32_t height);
6296 fpl_platform_api void fplSetWindowPosition(const int32_t left, const int32_t top);
6301 fpl_platform_api void fplSetWindowTitle(const char *title);
6308 fpl_common_api char *fplGetWindowTitle(char *outTitle, const size_t maxOutTitleLength);
6325 fpl_common_api void fplSetWindowInputEvents(const bool enabled);
6326 
6329 // ----------------------------------------------------------------------------
6335 // ----------------------------------------------------------------------------
6336 
6338 typedef struct fplDisplayInfo {
6349 } fplDisplayInfo;
6350 
6352 typedef struct fplDisplayMode {
6354  uint32_t width;
6356  uint32_t height;
6358  uint32_t colorBits;
6360  uint32_t refreshRate;
6361 } fplDisplayMode;
6362 
6374 fpl_platform_api size_t fplGetDisplays(fplDisplayInfo *outDisplays, const size_t maxDisplayCount);
6394 fpl_platform_api bool fplGetDisplayFromPosition(const int32_t x, const int32_t y, fplDisplayInfo *outInfo);
6402 fpl_platform_api size_t fplGetDisplayModes(const char *id, fplDisplayMode *outModes, const size_t maxDisplayModeCount);
6403 
6406 // ----------------------------------------------------------------------------
6412 // ----------------------------------------------------------------------------
6413 
6420 fpl_platform_api bool fplGetClipboardText(char *dest, const uint32_t maxDestLen);
6426 fpl_platform_api bool fplSetClipboardText(const char *text);
6427 
6429 #endif // FPL__ENABLE_WINDOW
6430 
6431 #if defined(FPL__ENABLE_VIDEO)
6432 // ----------------------------------------------------------------------------
6438 // ----------------------------------------------------------------------------
6439 
6441 typedef struct fplVideoRect {
6443  int32_t x;
6445  int32_t y;
6447  int32_t width;
6449  int32_t height;
6450 } fplVideoRect;
6451 
6460 fpl_inline fplVideoRect fplCreateVideoRectFromLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
6461  fplVideoRect result = { left, top, (right - left) + 1, (bottom - top) + 1 };
6462  return(result);
6463 }
6464 
6466 typedef struct fplVideoBackBuffer {
6468  uint32_t *pixels;
6470  uint32_t width;
6472  uint32_t height;
6474  size_t pixelStride;
6476  size_t lineWidth;
6482 
6483 #if defined(FPL__ENABLE_VIDEO_VULKAN)
6484 typedef struct fplVideoSurfaceVulkan {
6487  void *instance;
6489  void *surfaceKHR;
6491 #endif
6492 
6493 #if defined(FPL__ENABLE_VIDEO_OPENGL)
6494 typedef struct fplVideoSurfaceOpenGL {
6499 #endif
6500 
6501 #if defined(FPL_PLATFORM_WINDOWS)
6502 typedef struct fplVideoWindowWin32 {
6505  fpl__Win32WindowHandle windowHandle;
6507  fpl__Win32DeviceContext deviceContext;
6508 } fplVideoWindowWin32;
6509 #endif
6510 
6511 #if defined(FPL_SUBPLATFORM_X11)
6512 typedef struct fplVideoWindowX11 {
6515  fpl__X11Window window;
6517  fpl__X11Display display;
6519  fpl__X11Visual visual;
6521  int screen;
6522 } fplVideoWindowX11;
6523 #endif // FPL_SUBPLATFORM_X11
6524 
6526 typedef union fplVideoWindow {
6527 #if defined(FPL_PLATFORM_WINDOWS)
6528  fplVideoWindowWin32 win32;
6529 #elif defined(FPL_SUBPLATFORM_X11)
6530  fplVideoWindowX11 x11;
6531 #endif
6532  int dummy;
6534 } fplVideoWindow;
6535 
6537 typedef struct fplVideoSurface {
6540 
6541 #if defined(FPL__ENABLE_VIDEO_VULKAN)
6544 #endif
6545 
6546 #if defined(FPL__ENABLE_VIDEO_OPENGL)
6549 #endif
6550 
6552  int dummy;
6553 } fplVideoSurface;
6554 
6555 #if defined(FPL__ENABLE_VIDEO_VULKAN)
6556 typedef struct fplVideoRequirementsVulkan {
6559  const char *instanceExtensions[2];
6563 #endif // FPL__ENABLE_VIDEO_VULKAN
6564 
6565 
6567 typedef union fplVideoRequirements {
6568 #if defined(FPL__ENABLE_VIDEO_VULKAN)
6571 #endif // FPL__ENABLE_VIDEO_VULKAN
6572  int dummy;
6575 
6599 fpl_common_api bool fplResizeVideoBackBuffer(const uint32_t width, const uint32_t height);
6600 
6605 
6611 fpl_common_api const void *fplGetVideoProcedure(const char *procName);
6612 
6618 
6626 
6628 #endif // FPL__ENABLE_VIDEO
6629 
6630 #if defined(FPL__ENABLE_AUDIO)
6631 // ----------------------------------------------------------------------------
6637 // ----------------------------------------------------------------------------
6638 
6640 typedef enum fplAudioResultType {
6671 
6677 
6713 fpl_common_api uint32_t fplGetAudioDevices(fplAudioDeviceInfo *devices, uint32_t maxDeviceCount);
6725 fpl_common_api const char *fplGetAudioFormatName(const fplAudioFormatType format);
6738 fpl_common_api uint32_t fplGetAudioBufferSizeInFrames(uint32_t sampleRate, uint32_t bufferSizeInMilliSeconds);
6745 fpl_common_api uint32_t fplGetAudioBufferSizeInMilliseconds(uint32_t sampleRate, uint32_t frameCount);
6752 fpl_common_api uint32_t fplGetAudioFrameSizeInBytes(const fplAudioFormatType format, const uint32_t channelCount);
6760 fpl_common_api uint32_t fplGetAudioBufferSizeInBytes(const fplAudioFormatType format, const uint32_t channelCount, const uint32_t frameCount);
6767 
6769 #endif // FPL__ENABLE_AUDIO
6770 
6771 // ----------------------------------------------------------------------------
6777 // ----------------------------------------------------------------------------
6778 
6780 typedef enum fplLocaleFormat {
6785 } fplLocaleFormat;
6786 
6794 fpl_platform_api size_t fplGetUserLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen);
6795 
6803 fpl_platform_api size_t fplGetSystemLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen);
6804 
6812 fpl_platform_api size_t fplGetInputLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen);
6813 
6816 // Ignore any doxygen documentation from here
6818 
6819 // ****************************************************************************
6820 //
6821 // > EXPORT
6822 //
6823 // Internal functions for static library
6824 // Entry-Point forward declaration
6825 //
6826 // ****************************************************************************
6827 #if defined(FPL_PLATFORM_WINDOWS)
6828 # if defined(FPL_ENTRYPOINT)
6829 // @NOTE(final): Required for access "main" from the actual win32 entry point
6830 fpl_main int main(int argc, char **args);
6831 # endif
6832 #endif // FPL_PLATFORM_WINDOWS
6833 
6834 #endif // FPL_HEADER_H
6835 
6836 // ****************************************************************************
6837 //
6838 // > IMPLEMENTATION
6839 //
6840 // FPL uses several implementation blocks to structure things in categories.
6841 // Each block has its own ifdef definition to collapse it down if needed.
6842 // But the baseline structure is the following:
6843 //
6844 // - Compiler settings (Disable warnings, etc.)
6845 // - Platform Constants & Types (All required structs, Constants, Global variables, etc.)
6846 // - Common implementations
6847 // - Actual platform implementations (Win32, Linux)
6848 // - Sub platform implementations (X11, POSIX, STD)
6849 // - Backend implementations (Video: OpenGL/Software/Vulkan, Audio: DirectSound/Alsa)
6850 // - Systems (Audio, Video, Window systems)
6851 // - Core (Init & Release of the specific platform by selection)
6852 //
6853 // You can use the following strings to search for implementation blocks - including the > prefix:
6854 //
6855 // > COMPILER_CONFIG
6856 // > PLATFORM_INCLUDES
6857 //
6858 // > INTERNAL_TOP
6859 // > INTERNAL_LOGGING
6860 //
6861 // > PLATFORM_CONSTANTS
6862 // > UTILITY_FUNCTIONS
6863 //
6864 // > TYPES
6865 // > TYPES_WIN32
6866 // > TYPES_POSIX
6867 // > TYPES_LINUX
6868 // > TYPES_X11
6869 //
6870 // > PLATFORM_STATES
6871 //
6872 // > COMMON
6873 //
6874 // > WIN32_PLATFORM
6875 // > POSIX_SUBPLATFORM (Linux, Unix)
6876 // > STD_STRINGS_SUBPLATFORM
6877 // > STD_CONSOLE_SUBPLATFORM
6878 // > X11_SUBPLATFORM
6879 // > LINUX_PLATFORM
6880 // > UNIX_PLATFORM
6881 //
6882 // > VIDEO_BACKENDS
6883 // > VIDEO_BACKEND_OPENGL_WIN32
6884 // > VIDEO_BACKEND_OPENGL_X11
6885 // > VIDEO_BACKEND_SOFTWARE_WIN32
6886 // > VIDEO_BACKEND_SOFTWARE_X11
6887 // > VIDEO_BACKEND_VULKAN
6888 //
6889 // > AUDIO_BACKENDS
6890 // > AUDIO_BACKEND_DIRECTSOUND
6891 // > AUDIO_BACKEND_ALSA
6892 //
6893 // > SYSTEM_AUDIO_L1
6894 // > SYSTEM_VIDEO_L1
6895 // > SYSTEM_WINDOW
6896 // > SYSTEM_AUDIO_L2
6897 // > SYSTEM_VIDEO_L2 (Video backbuffer access and present of the frame)
6898 // > SYSTEM_INIT (Init & Release of the Platform)
6899 //
6900 // ****************************************************************************
6901 #if (defined(FPL_IMPLEMENTATION) || FPL_IS_IDE) && !defined(FPL__IMPLEMENTED)
6902 #define FPL__IMPLEMENTED
6903 
6904 // ############################################################################
6905 //
6906 // > COMPILER_CONFIG
6907 //
6908 // ############################################################################
6909 #if !defined(FPL__COMPILER_CONFIG_DEFINED)
6910 #define FPL__COMPILER_CONFIG_DEFINED
6911 
6912 //
6913 // Compiler warnings
6914 //
6915 #if defined(FPL_COMPILER_MSVC)
6916 
6917  // Start to overwrite warning settings (MSVC)
6918 # pragma warning( push )
6919 
6920  // Disable noexcept compiler warning for C++
6921 # pragma warning( disable : 4577 )
6922  // Disable "switch statement contains 'default' but no 'case' labels" compiler warning for C++
6923 # pragma warning( disable : 4065 )
6924  // Disable "conditional expression is constant" warning
6925 # pragma warning( disable : 4127 )
6926  // Disable "unreferenced formal parameter" warning
6927 # pragma warning( disable : 4100 )
6928  // Disable "nonstandard extension used: nameless struct/union" warning
6929 # pragma warning( disable : 4201 )
6930  // Disable "local variable is initialized but not referenced" warning
6931 # pragma warning( disable : 4189 )
6932  // Disable "nonstandard extension used: non-constant aggregate initializer" warning
6933 # pragma warning( disable : 4204 )
6934 
6935 #elif defined(FPL_COMPILER_GCC)
6936 
6937  // Start to overwrite warning settings (GCC)
6938 # pragma GCC diagnostic push
6939 // Disable warning -Wunused-variable
6940 # pragma GCC diagnostic ignored "-Wunused-variable"
6941 // Disable warning -Wunused-function
6942 # pragma GCC diagnostic ignored "-Wunused-function"
6943 
6944 #elif defined(FPL_COMPILER_CLANG)
6945 
6946  // Start to overwrite warning settings (Clang)
6947 # pragma clang diagnostic push
6948 
6949 // Disable warning -Wunused-variable
6950 # pragma clang diagnostic ignored "-Wunused-variable"
6951 // Disable warning -Wunused-function
6952 # pragma clang diagnostic ignored "-Wunused-function"
6953 
6954 #endif // FPL_COMPILER
6955 
6956 #endif // FPL__COMPILER_CONFIG_DEFINED
6957 
6958 // ############################################################################
6959 //
6960 // > PLATFORM_INCLUDES
6961 //
6962 // ############################################################################
6963 #if !defined(FPL__PLATFORM_INCLUDES_DEFINED)
6964 #define FPL__PLATFORM_INCLUDES_DEFINED
6965 
6966 #if !defined(FPL__HAS_PLATFORM_INCLUDES)
6967 # define FPL__HAS_PLATFORM_INCLUDES
6968 
6969 # if defined(FPL_PLATFORM_WINDOWS)
6970  // @NOTE(final): windef.h defines min/max macros in lowerspace, this will break for example std::min/max so we have to tell the header we dont want this!
6971 # if !defined(NOMINMAX)
6972 # define NOMINMAX
6973 # endif
6974  // @NOTE(final): For now we dont want any network, com or gdi stuff at all, maybe later who knows.
6975 # if !defined(WIN32_LEAN_AND_MEAN)
6976 # define WIN32_LEAN_AND_MEAN 1
6977 # endif
6978  // @STUPID(final): Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here"
6979 struct IUnknown;
6980 # include <windows.h> // Win32 api
6981 # if _WIN32_WINNT < 0x0600
6982 # error "Windows Vista or higher required!"
6983 # endif
6984 # endif // FPL_PLATFORM_WINDOWS
6985 
6986 # if defined(FPL_SUBPLATFORM_POSIX)
6987 # include <pthread.h> // pthread_t, pthread_mutex_, pthread_cond_, pthread_barrier_
6988 # include <sched.h> // sched_param, sched_get_priority_max, SCHED_FIFO
6989 # include <semaphore.h> // sem_t
6990 # include <dirent.h> // DIR, dirent
6991 # endif // FPL_SUBPLATFORM_POSIX
6992 
6993 # if defined(FPL_SUBPLATFORM_X11)
6994 # include <X11/X.h> // Window
6995 # include <X11/Xlib.h> // Display
6996 # include <X11/Xutil.h> // XVisualInfo
6997 # include <X11/Xatom.h> // XA_CARDINAL
6998 # endif // FPL_SUBPLATFORM_X11
6999 
7000 #endif // !FPL__HAS_PLATFORM_INCLUDES
7001 
7002 //
7003 // Test OS handles
7004 //
7005 #if defined(FPL_PLATFORM_WINDOWS)
7006 fplStaticAssert(sizeof(fpl__Win32Handle) >= sizeof(HANDLE));
7007 fplStaticAssert(sizeof(fpl__Win32LibraryHandle) >= sizeof(HANDLE));
7008 fplStaticAssert(sizeof(fpl__Win32FileHandle) >= sizeof(HANDLE));
7009 fplStaticAssert(sizeof(fpl__Win32ThreadHandle) >= sizeof(HANDLE));
7010 fplStaticAssert(sizeof(fpl__Win32MutexHandle) >= sizeof(CRITICAL_SECTION));
7011 fplStaticAssert(sizeof(fpl__Win32SemaphoreHandle) >= sizeof(HANDLE));
7012 fplStaticAssert(sizeof(fpl__Win32ConditionVariable) >= sizeof(CONDITION_VARIABLE));
7013 #elif defined(FPL_SUBPLATFORM_POSIX)
7014 fplStaticAssert(sizeof(fpl__POSIXLibraryHandle) >= sizeof(void *));
7015 fplStaticAssert(sizeof(fpl__POSIXFileHandle) >= sizeof(int));
7016 fplStaticAssert(sizeof(fpl__POSIXDirHandle) >= sizeof(DIR *));
7017 fplStaticAssert(sizeof(fpl__POSIXThreadHandle) >= sizeof(pthread_t));
7018 fplStaticAssert(sizeof(fpl__POSIXMutexHandle) >= sizeof(pthread_mutex_t));
7019 fplStaticAssert(sizeof(fpl__POSIXSemaphoreHandle) >= sizeof(sem_t));
7020 fplStaticAssert(sizeof(fpl__POSIXConditionVariable) >= sizeof(pthread_cond_t));
7021 #endif // FPL_PLATFORM_WINDOWS / FPL_SUBPLATFORM_POSIX
7022 #if defined(FPL_PLATFORM_LINUX)
7023 fplStaticAssert(sizeof(fpl__LinuxSignalHandle) >= sizeof(int));
7024 #endif // FPL_PLATFORM_LINUX
7025 
7026 //
7027 // Compiler Includes
7028 //
7029 #if defined(FPL_COMPILER_MSVC)
7030 # include <intrin.h> // __cpuid, _Interlocked*
7031 #elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
7032 # if defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
7033 # include <cpuid.h> // __cpuid_count
7034 # endif // X86 or X64
7035 #endif
7036 
7037 // Only include C-Runtime functions when CRT is enabled
7038 #if !defined(FPL_NO_CRT)
7039 # include <stdio.h> // stdin, stdout, stderr, fprintf, vfprintf, vsnprintf, getchar
7040 # include <stdlib.h> // wcstombs, mbstowcs, getenv
7041 # include <locale.h> // setlocale, struct lconv, localeconv
7042 #endif
7043 
7044 #endif // FPL__PLATFORM_INCLUDES_DEFINED
7045 
7046 // ############################################################################
7047 //
7048 // > INTERNAL_TOP
7049 //
7050 // ############################################################################
7051 #if !defined(FPL__INTERNAL_TOP_DEFINED)
7052 #define FPL__INTERNAL_TOP_DEFINED
7053 
7054 // Module constants used for logging
7055 #define FPL__MODULE_CORE "Core"
7056 #define FPL__MODULE_FILES "Files"
7057 #define FPL__MODULE_THREADING "Threading"
7058 #define FPL__MODULE_MEMORY "Memory"
7059 #define FPL__MODULE_WINDOW "Window"
7060 #define FPL__MODULE_LIBRARIES "Libraries"
7061 #define FPL__MODULE_OS "OS"
7062 #define FPL__MODULE_HARDWARE "Hardware"
7063 #define FPL__MODULE_STRINGS "Strings"
7064 #define FPL__MODULE_PATHS "Paths"
7065 #define FPL__MODULE_ARGS "Arguments"
7066 
7067 #define FPL__MODULE_AUDIO "Audio"
7068 #define FPL__MODULE_AUDIO_DIRECTSOUND "DirectSound"
7069 #define FPL__MODULE_AUDIO_ALSA "ALSA"
7070 
7071 #define FPL__MODULE_VIDEO "Video"
7072 #define FPL__MODULE_VIDEO_OPENGL "OpenGL"
7073 #define FPL__MODULE_VIDEO_VULKAN "Vulkan"
7074 #define FPL__MODULE_VIDEO_SOFTWARE "Software"
7075 
7076 #define FPL__MODULE_WIN32 "Win32"
7077 #define FPL__MODULE_XINPUT "XInput"
7078 
7079 #define FPL__MODULE_LINUX "Linux"
7080 #define FPL__MODULE_UNIX "Unix"
7081 #define FPL__MODULE_POSIX "POSIX"
7082 #define FPL__MODULE_PTHREAD "pthread"
7083 #define FPL__MODULE_X11 "X11"
7084 #define FPL__MODULE_GLX "GLX"
7085 
7086 //
7087 // Enum macros
7088 //
7089 #define FPL__ENUM_COUNT(first, last) ((last) - (first) + 1)
7090 #define FPL__ENUM_VALUE_TO_ARRAY_INDEX(value, first, last) (((value) >= (first) && (value) <= (last)) ? ((value) - (first)) : 0)
7091 
7092 //
7093 // Internal memory
7094 //
7095 fpl_internal void *fpl__AllocateMemory(const fplMemoryAllocationSettings *allocSettings, const size_t size, const size_t alignment);
7096 fpl_internal void fpl__ReleaseMemory(const fplMemoryAllocationSettings *allocSettings, void *ptr);
7097 
7098 #endif // FPL__INTERNAL_TOP_DEFINED
7099 
7100 // ############################################################################
7101 //
7102 // > INTERNAL_LOGGING
7103 //
7104 // ############################################################################
7105 #if !defined(FPL__INTERNAL_LOGGING_DEFINED)
7106 #define FPL__INTERNAL_LOGGING_DEFINED
7107 
7108 #define FPL__MODULE_CONCAT(mod, format) "[" mod "] " format
7109 
7110 #if defined(FPL__ENABLE_LOGGING)
7111 fpl_globalvar fplLogSettings fpl__global__LogSettings = fplZeroInit;
7112 
7113 #define FPL__LOGLEVEL_COUNT FPL__ENUM_COUNT(fplLogLevel_First, fplLogLevel_Last)
7114 fpl_globalvar const char *fpl__LogLevelNameTable[] = {
7115  "All", // fplLogLevel_All (-1)
7116  "Critical", // fplLogLevel_Critical (0)
7117  "Error", // fplLogLevel_Error (1)
7118  "Warning", // fplLogLevel_Warning (2)
7119  "Info", // fplLogLevel_Info (3)
7120  "Verbose", // fplLogLevel_Verbose (4)
7121  "Debug", // fplLogLevel_Debug (5)
7122  "Trace", // fplLogLevel_Trace (6)
7123 };
7124 fplStaticAssert(fplArrayCount(fpl__LogLevelNameTable) == FPL__LOGLEVEL_COUNT);
7125 
7126 fpl_internal const char *fpl__LogLevelToString(const fplLogLevel level) {
7127  uint32_t index = FPL__ENUM_VALUE_TO_ARRAY_INDEX(level, fplLogLevel_First, fplLogLevel_Last);
7128  const char *result = fpl__LogLevelNameTable[index];
7129  return(result);
7130 }
7131 
7132 fpl_internal void fpl__LogWrite(const char *funcName, const int lineNumber, const fplLogLevel level, const char *message) {
7133  fplLogSettings *settings = &fpl__global__LogSettings;
7134  if(!settings->isInitialized) {
7135 #if defined(FPL_LOG_MULTIPLE_WRITERS)
7136  settings->criticalWriter.console.logToError = true;
7137  settings->criticalWriter.flags = fplLogWriterFlags_ErrorConsole | fplLogWriterFlags_DebugOut;
7138  settings->errorWriter = settings->criticalWriter;
7139  settings->warningWriter = settings->criticalWriter;
7140  settings->infoWriter.flags = fplLogWriterFlags_StandardConsole | fplLogWriterFlags_DebugOut;
7141  settings->verboseWriter = settings->infoWriter;
7142  settings->debugWriter.flags = fplLogWriterFlags_DebugOut;
7143 #else
7145 #endif
7146  settings->maxLevel = fplLogLevel_Warning;
7147  settings->isInitialized = true;
7148  }
7149 
7150  if((settings->maxLevel == -1) || (level <= settings->maxLevel)) {
7151 #if defined(FPL_LOG_MULTIPLE_WRITERS)
7152  fplAssert(level < fplArrayCount(settings->writers));
7153  const fplLogWriter *writer = &settings->writers[(int)level];
7154 #else
7155  const fplLogWriter *writer = &settings->writers[0];
7156 #endif
7157  const char *levelStr = fpl__LogLevelToString(level);
7158 
7160  fplConsoleFormatOut("[%s:%d][%s] %s\n", funcName, lineNumber, levelStr, message);
7161  }
7162  if(writer->flags & fplLogWriterFlags_ErrorConsole) {
7163  fplConsoleFormatError("[%s:%d][%s] %s\n", funcName, lineNumber, levelStr, message);
7164  }
7165  if(writer->flags & fplLogWriterFlags_DebugOut) {
7166  fplDebugFormatOut("[%s:%d][%s] %s\n", funcName, lineNumber, levelStr, message);
7167  }
7168  if(writer->flags & fplLogWriterFlags_Custom && writer->custom.callback != fpl_null) {
7169  writer->custom.callback(funcName, lineNumber, level, message);
7170  }
7171  }
7172 }
7173 fpl_internal void fpl__LogWriteArgs(const char *funcName, const int lineNumber, const fplLogLevel level, const char *format, va_list argList) {
7174  va_list listCopy;
7175  va_copy(listCopy, argList);
7176  char buffer[FPL_MAX_BUFFER_LENGTH];
7177  fplFormatStringArgs(buffer, fplArrayCount(buffer), format, listCopy);
7178  fpl__LogWrite(funcName, lineNumber, level, buffer);
7179  va_end(listCopy);
7180 }
7181 
7182 fpl_internal void fpl__LogWriteVarArgs(const char *funcName, const int lineNumber, const fplLogLevel level, const char *format, ...) {
7183  va_list argList;
7184  va_start(argList, format);
7185  fpl__LogWriteArgs(funcName, lineNumber, level, format, argList);
7186  va_end(argList);
7187 }
7188 
7189 # define FPL_LOG(lvl, mod, format, ...) fpl__LogWriteVarArgs(FPL_FUNCTION_NAME, __LINE__, lvl, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7190 # define FPL_LOG_CRITICAL(mod, format, ...) FPL_LOG(fplLogLevel_Critical, mod, format, ## __VA_ARGS__)
7191 # define FPL_LOG_ERROR(mod, format, ...) FPL_LOG(fplLogLevel_Error, mod, format, ## __VA_ARGS__)
7192 # define FPL_LOG_WARN(mod, format, ...) FPL_LOG(fplLogLevel_Warning, mod, format, ## __VA_ARGS__)
7193 # define FPL_LOG_INFO(mod, format, ...) FPL_LOG(fplLogLevel_Info, mod, format, ## __VA_ARGS__)
7194 # define FPL_LOG_VERBOSE(mod, format, ...) FPL_LOG(fplLogLevel_Verbose, mod, format, ## __VA_ARGS__)
7195 # define FPL_LOG_DEBUG(mod, format, ...) FPL_LOG(fplLogLevel_Debug, mod, format, ## __VA_ARGS__)
7196 # define FPL_LOG_TRACE(mod, format, ...) FPL_LOG(fplLogLevel_Trace, mod, format, ## __VA_ARGS__)
7197 
7198 # define FPL__LOG_FUNCTION_N(mod, name) FPL_LOG(fplLogLevel_Debug, mod, "-> %s()", name)
7199 # define FPL_LOG_FUNCTION(mod) FPL__LOG_FUNCTION_N(mod, FPL_FUNCTION_NAME)
7200 
7201 #else
7202 
7203 # define FPL_LOG(lvl, mod, format, ...)
7204 # define FPL_LOG_CRITICAL(mod, format, ...)
7205 # define FPL_LOG_ERROR(mod, format, ...)
7206 # define FPL_LOG_WARN(mod, format, ...)
7207 # define FPL_LOG_INFO(mod, format, ...)
7208 # define FPL_LOG_VERBOSE(mod, format, ...)
7209 # define FPL_LOG_DEBUG(mod, format, ...)
7210 # define FPL_LOG_FUNCTION(mod)
7211 
7212 #endif
7213 
7214 //
7215 // Error handling
7216 //
7217 
7218 #define FPL__M_CRITICAL(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Critical, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7219 #define FPL__M_ERROR(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Error, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7220 #define FPL__M_WARNING(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Warning, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7221 
7222 #define FPL__CRITICAL(mod, format, ...) FPL__M_CRITICAL(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7223 #define FPL__ERROR(mod, format, ...) FPL__M_ERROR(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7224 #define FPL__WARNING(mod, format, ...) FPL__M_WARNING(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7225 
7226 #endif // FPL__INTERNAL_LOGGING_DEFINED
7227 
7228 // ############################################################################
7229 //
7230 // > PLATFORM_CONSTANTS
7231 //
7232 // ############################################################################
7233 #if !defined(FPL__PLATFORM_CONSTANTS_DEFINED)
7234 #define FPL__PLATFORM_CONSTANTS_DEFINED
7235 
7236 // One cacheline worth of padding
7237 #define FPL__ARBITARY_PADDING 64
7238 // Small padding to split sections in memory blocks
7239 #define FPL__MEMORY_PADDING sizeof(uintptr_t)
7240 
7241 fpl_globalvar struct fpl__PlatformAppState *fpl__global__AppState = fpl_null;
7242 
7243 fpl_internal void fpl__HandleError(const char *funcName, const int lineNumber, const fplLogLevel level, const char *format, ...);
7244 #endif // FPL__PLATFORM_CONSTANTS_DEFINED
7245 
7246 // ############################################################################
7247 //
7248 // > UTILITY_FUNCTIONS
7249 //
7250 // ############################################################################
7251 fpl_internal void *fpl__AllocateMemory(const fplMemoryAllocationSettings *allocSettings, const size_t size, const size_t alignment) {
7252  if(allocSettings->mode == fplMemoryAllocationMode_Custom) {
7253  if(allocSettings->allocateCallback != fpl_null && allocSettings->releaseCallback != fpl_null) {
7254  return allocSettings->allocateCallback(allocSettings->userData, size, alignment);
7255  }
7256  }
7257  return fplMemoryAlignedAllocate(size, alignment);
7258 }
7259 
7260 fpl_internal void fpl__ReleaseMemory(const fplMemoryAllocationSettings *allocSettings, void *ptr) {
7261  if(allocSettings->mode == fplMemoryAllocationMode_Custom) {
7262  if(allocSettings->allocateCallback != fpl_null && allocSettings->releaseCallback != fpl_null) {
7263  allocSettings->releaseCallback(allocSettings->userData, ptr);
7264  return;
7265  }
7266  }
7267  fplMemoryAlignedFree(ptr);
7268 }
7269 
7270 // Forward declarations of internal memory
7271 fpl_internal void *fpl__AllocateDynamicMemory(const size_t size, const size_t alignment);
7272 fpl_internal void fpl__ReleaseDynamicMemory(void *ptr);
7273 fpl_internal void *fpl__AllocateTemporaryMemory(const size_t size, const size_t alignment);
7274 fpl_internal void fpl__ReleaseTemporaryMemory(void *ptr);
7275 
7276 fpl_internal uint32_t fpl__NextPowerOfTwo(const uint32_t input) {
7277  uint32_t x = input;
7278  x--;
7279  x |= x >> 1;
7280  x |= x >> 2;
7281  x |= x >> 4;
7282  x |= x >> 8;
7283  x |= x >> 16;
7284  x++;
7285  return(x);
7286 }
7287 fpl_internal uint32_t fpl__PrevPowerOfTwo(const uint32_t input) {
7288  uint32_t result = fpl__NextPowerOfTwo(input) >> 1;
7289  return(result);
7290 }
7291 
7292 fpl_internal uint32_t fpl__RoundToPowerOfTwo(const uint32_t input) {
7293  uint32_t prev = fpl__PrevPowerOfTwo(input);
7294  uint32_t next = fpl__NextPowerOfTwo(input);
7295  if((next - input) < (input - prev)) {
7296  return prev;
7297  } else {
7298  return next;
7299  }
7300 }
7301 
7302 fpl_internal bool fpl__AddLineWhenAnyMatches(const char *line, const char **wildcards, const size_t maxWildcardCount, const size_t maxLineSize, const size_t maxLineCount, char **outLines, size_t *outCount) {
7303  for(size_t i = 0; i < maxWildcardCount; ++i) {
7304  const char *wildcard = wildcards[i];
7305  if(fplIsStringMatchWildcard(line, wildcard)) {
7306  size_t index = *outCount;
7307  char *target = outLines[index];
7308  fplCopyString(line, target, maxLineSize);
7309  *outCount = index + 1;
7310  break;
7311  }
7312  }
7313  bool result = *outCount < maxLineCount;
7314  return(result);
7315 }
7316 
7317 fpl_internal size_t fpl__ParseTextFile(const char *filePath, const char **wildcards, const size_t maxWildcardCount, const size_t maxLineSize, const size_t maxLineCount, char **outLines) {
7318  if(filePath == fpl_null || wildcards == fpl_null || maxWildcardCount == 0 || maxLineSize == 0 || maxLineCount == 0 || outLines == fpl_null) {
7319  return(0);
7320  }
7321  // @NOTE(final): Forced Zero-Terminator is not nessecary here, but we do it here to debug it better
7322  // This function supports maxLineSize < fplArrayCount(buffer)
7323  // We allocate the line buffer on the stack because we do not know how large the line will be on compile time
7324  size_t result = 0;
7325  fplFileHandle fileHandle = fplZeroInit;
7326  if(fplOpenBinaryFile(filePath, &fileHandle)) {
7327  char *line = (char *)fpl__AllocateTemporaryMemory(maxLineSize, 8);
7328  char buffer[FPL_MAX_BUFFER_LENGTH];
7329  const size_t maxBufferSize = fplArrayCount(buffer) - 1;
7330  size_t bytesRead = 0;
7331  size_t posLineBytes = 0;
7332  bool done = false;
7333  while(!done && ((bytesRead = fplReadFileBlock(&fileHandle, maxBufferSize, &buffer[0], maxBufferSize)) > 0)) {
7334  buffer[bytesRead] = 0;
7335  char *start = &buffer[0];
7336  char *p = start;
7337  size_t readPos = 0;
7338  size_t lineSizeToRead = 0;
7339  while(readPos < bytesRead) {
7340  if(*p == '\n') {
7341  size_t remainingLineBytes = maxLineSize - posLineBytes;
7342  char *lineTargetP = line + posLineBytes;
7343  if(lineSizeToRead < remainingLineBytes) {
7344  fplCopyStringLen(start, lineSizeToRead, lineTargetP, remainingLineBytes);
7345  } else {
7346  fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
7347  }
7348  if(!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7349  done = true;
7350  break;
7351  }
7352  start = p + 1;
7353  line[0] = 0;
7354  lineSizeToRead = 0;
7355  posLineBytes = 0;
7356  } else {
7357  ++lineSizeToRead;
7358  }
7359  ++p;
7360  ++readPos;
7361  }
7362  if(done) {
7363  break;
7364  }
7365  if(lineSizeToRead > 0) {
7366  size_t remainingLineBytes = maxLineSize - posLineBytes;
7367  char *lineTargetP = line + posLineBytes;
7368  if(lineSizeToRead < remainingLineBytes) {
7369  fplCopyStringLen(start, lineSizeToRead, lineTargetP, remainingLineBytes);
7370  posLineBytes += lineSizeToRead;
7371  if(bytesRead <= maxBufferSize) {
7372  if(!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7373  done = true;
7374  }
7375  }
7376  } else {
7377  fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
7378  line[0] = 0;
7379  lineSizeToRead = 0;
7380  posLineBytes = 0;
7381  if(!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7382  done = true;
7383  }
7384  }
7385  }
7386  }
7387  fpl__ReleaseTemporaryMemory(line);
7388  fplCloseFile(&fileHandle);
7389  }
7390  return(result);
7391 }
7392 
7393 fpl_internal void fpl__ParseVersionString(const char *versionStr, fplVersionInfo *versionInfo) {
7394  fplCopyString(versionStr, versionInfo->fullName, fplArrayCount(versionInfo->fullName));
7395  if(versionStr != fpl_null) {
7396  const char *p = versionStr;
7397  for(int i = 0; i < 4; ++i) {
7398  const char *digitStart = p;
7399  while(*p >= '0' && *p <= '9') {
7400  ++p;
7401  }
7402  size_t len = p - digitStart;
7403  if(len <= fplArrayCount(versionInfo->values[i])) {
7404  fplCopyStringLen(digitStart, len, versionInfo->values[i], fplArrayCount(versionInfo->values[i]));
7405  } else {
7406  versionInfo->values[i][0] = 0;
7407  }
7408  if(*p != '.' && *p != '-') break;
7409  ++p;
7410  }
7411  }
7412 }
7413 
7414 // ****************************************************************************
7415 //
7416 // > TYPES
7417 //
7418 // This implementation block includes all the required platform-specific
7419 // header files and defines all the constants, structures and types.
7420 //
7421 // ****************************************************************************
7422 
7423 // ############################################################################
7424 //
7425 // > TYPES_WIN32
7426 //
7427 // ############################################################################
7428 #if defined(FPL_PLATFORM_WINDOWS)
7429 # include <windowsx.h> // Macros for window messages
7430 # include <shlobj.h> // SHGetFolderPath
7431 # include <xinput.h> // XInputGetState
7432 # include <shellapi.h> // HDROP
7433 
7434 # if defined(FPL_IS_CPP)
7435 # define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(a, b)
7436 # else
7437 # define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(&a, &b)
7438 # endif
7439 
7440 fpl_internal const char *fpl__Win32FormatGuidString(char *buffer, const size_t maxBufferLen, const GUID *guid) {
7441  fplFormatString(buffer, maxBufferLen, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
7442  guid->Data1, guid->Data2, guid->Data3,
7443  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
7444  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
7445  return(buffer);
7446 }
7447 
7448 // Little macro to not write 5 lines of code all the time
7449 #define FPL__WIN32_LOAD_LIBRARY_BREAK(mod, target, libName) \
7450  (target) = LoadLibraryA(libName); \
7451  if((target) == fpl_null) { \
7452  FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
7453  break; \
7454  }
7455 #define FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
7456  (target)->name = (type *)GetProcAddress(libHandle, #name); \
7457  if ((target)->name == fpl_null) { \
7458  FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
7459  break; \
7460  }
7461 #if !defined(FPL_NO_RUNTIME_LINKING)
7462 # define FPL__WIN32_LOAD_LIBRARY FPL__WIN32_LOAD_LIBRARY_BREAK
7463 # define FPL__WIN32_GET_FUNCTION_ADDRESS FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK
7464 #else
7465 # define FPL__WIN32_LOAD_LIBRARY(mod, target, libName)
7466 # define FPL__WIN32_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
7467  (target)->name = name
7468 #endif
7469 
7470 //
7471 // XInput
7472 //
7473 #define FPL__FUNC_XINPUT_XInputGetState(name) DWORD WINAPI name(DWORD dwUserIndex, XINPUT_STATE *pState)
7474 typedef FPL__FUNC_XINPUT_XInputGetState(fpl__win32_func_XInputGetState);
7475 FPL__FUNC_XINPUT_XInputGetState(fpl__Win32XInputGetStateStub) {
7476  return(ERROR_DEVICE_NOT_CONNECTED);
7477 }
7478 #define FPL__FUNC_XINPUT_XInputGetCapabilities(name) DWORD WINAPI name(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
7479 typedef FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__win32_func_XInputGetCapabilities);
7480 FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__Win32XInputGetCapabilitiesStub) {
7481  return(ERROR_DEVICE_NOT_CONNECTED);
7482 }
7483 typedef struct fpl__Win32XInputApi {
7484  HMODULE xinputLibrary;
7485  fpl__win32_func_XInputGetState *XInputGetState;
7486  fpl__win32_func_XInputGetCapabilities *XInputGetCapabilities;
7487 } fpl__Win32XInputApi;
7488 
7489 fpl_internal void fpl__Win32UnloadXInputApi(fpl__Win32XInputApi *xinputApi) {
7490  fplAssert(xinputApi != fpl_null);
7491  if(xinputApi->xinputLibrary) {
7492  FPL_LOG_DEBUG("XInput", "Unload XInput Library");
7493  FreeLibrary(xinputApi->xinputLibrary);
7494  xinputApi->xinputLibrary = fpl_null;
7495  xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
7496  xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
7497  }
7498 }
7499 
7500 fpl_internal void fpl__Win32LoadXInputApi(fpl__Win32XInputApi *xinputApi) {
7501  fplAssert(xinputApi != fpl_null);
7502  const char *xinputFileNames[] = {
7503  "xinput1_4.dll",
7504  "xinput1_3.dll",
7505  "xinput9_1_0.dll",
7506  };
7507  bool result = false;
7508  for(uint32_t index = 0; index < fplArrayCount(xinputFileNames); ++index) {
7509  const char *libName = xinputFileNames[index];
7510  fplClearStruct(xinputApi);
7511  do {
7512  HMODULE libHandle = fpl_null;
7513  FPL__WIN32_LOAD_LIBRARY_BREAK(FPL__MODULE_XINPUT, libHandle, libName);
7514  xinputApi->xinputLibrary = libHandle;
7515  FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetState, XInputGetState);
7516  FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetCapabilities, XInputGetCapabilities);
7517  result = true;
7518  } while(0);
7519  if(result) {
7520  break;
7521  }
7522  fpl__Win32UnloadXInputApi(xinputApi);
7523  }
7524 
7525  if(!result) {
7526  xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
7527  xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
7528  }
7529 }
7530 
7531 //
7532 // WINAPI functions
7533 //
7534 
7535 // GDI32
7536 #define FPL__FUNC_WIN32_ChoosePixelFormat(name) int WINAPI name(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
7537 typedef FPL__FUNC_WIN32_ChoosePixelFormat(fpl__win32_func_ChoosePixelFormat);
7538 #define FPL__FUNC_WIN32_SetPixelFormat(name) BOOL WINAPI name(HDC hdc, int format, CONST PIXELFORMATDESCRIPTOR *ppfd)
7539 typedef FPL__FUNC_WIN32_SetPixelFormat(fpl__win32_func_SetPixelFormat);
7540 #define FPL__FUNC_WIN32_DescribePixelFormat(name) int WINAPI name(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
7541 typedef FPL__FUNC_WIN32_DescribePixelFormat(fpl__win32_func_DescribePixelFormat);
7542 #define FPL__FUNC_WIN32_GetDeviceCaps(name) int WINAPI name(HDC hdc, int index)
7543 typedef FPL__FUNC_WIN32_GetDeviceCaps(fpl__win32_func_GetDeviceCaps);
7544 #define FPL__FUNC_WIN32_StretchDIBits(name) int WINAPI name(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, CONST VOID *lpBits, CONST BITMAPINFO *lpbmi, UINT iUsage, DWORD rop)
7545 typedef FPL__FUNC_WIN32_StretchDIBits(fpl__win32_func_StretchDIBits);
7546 #define FPL__FUNC_WIN32_DeleteObject(name) BOOL WINAPI name( _In_ HGDIOBJ ho)
7547 typedef FPL__FUNC_WIN32_DeleteObject(fpl__win32_func_DeleteObject);
7548 #define FPL__FUNC_WIN32_SwapBuffers(name) BOOL WINAPI name(HDC)
7549 typedef FPL__FUNC_WIN32_SwapBuffers(fpl__win32_func_SwapBuffers);
7550 #define FPL__FUNC_WIN32_CreateDIBSection(name) HBITMAP WINAPI name(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset)
7551 typedef FPL__FUNC_WIN32_CreateDIBSection(fpl__win32_func_CreateDIBSection);
7552 #define FPL__FUNC_WIN32_CreateBitmap(name) HBITMAP WINAPI name(int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits)
7553 typedef FPL__FUNC_WIN32_CreateBitmap(fpl__win32_func_CreateBitmap);
7554 
7555 // ShellAPI
7556 #define FPL__FUNC_WIN32_SHGetFolderPathW(name) HRESULT WINAPI name(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath)
7557 typedef FPL__FUNC_WIN32_SHGetFolderPathW(fpl__win32_func_SHGetFolderPathW);
7558 #define FPL__FUNC_WIN32_DragQueryFileW(name) UINT WINAPI name(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch)
7559 typedef FPL__FUNC_WIN32_DragQueryFileW(fpl__win32_func_DragQueryFileW);
7560 #define FPL__FUNC_WIN32_DragAcceptFiles(name) void WINAPI name(HWND hWnd, BOOL fAccept)
7561 typedef FPL__FUNC_WIN32_DragAcceptFiles(fpl__win32_func_DragAcceptFiles);
7562 
7563 // User32
7564 #define FPL__FUNC_WIN32_RegisterClassExW(name) ATOM WINAPI name(CONST WNDCLASSEXW *)
7565 typedef FPL__FUNC_WIN32_RegisterClassExW(fpl__win32_func_RegisterClassExW);
7566 #define FPL__FUNC_WIN32_UnregisterClassW(name) BOOL WINAPI name(LPCWSTR lpClassName, HINSTANCE hInstance)
7567 typedef FPL__FUNC_WIN32_UnregisterClassW(fpl__win32_func_UnregisterClassW);
7568 #define FPL__FUNC_WIN32_ShowWindow(name) BOOL WINAPI name(HWND hWnd, int nCmdShow)
7569 typedef FPL__FUNC_WIN32_ShowWindow(fpl__win32_func_ShowWindow);
7570 #define FPL__FUNC_WIN32_DestroyWindow(name) BOOL WINAPI name(HWND hWnd)
7571 typedef FPL__FUNC_WIN32_DestroyWindow(fpl__win32_func_DestroyWindow);
7572 #define FPL__FUNC_WIN32_UpdateWindow(name) BOOL WINAPI name(HWND hWnd)
7573 typedef FPL__FUNC_WIN32_UpdateWindow(fpl__win32_func_UpdateWindow);
7574 #define FPL__FUNC_WIN32_TranslateMessage(name) BOOL WINAPI name(CONST MSG *lpMsg)
7575 typedef FPL__FUNC_WIN32_TranslateMessage(fpl__win32_func_TranslateMessage);
7576 #define FPL__FUNC_WIN32_DispatchMessageW(name) LRESULT WINAPI name(CONST MSG *lpMsg)
7577 typedef FPL__FUNC_WIN32_DispatchMessageW(fpl__win32_func_DispatchMessageW);
7578 #define FPL__FUNC_WIN32_PeekMessageW(name) BOOL WINAPI name(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
7579 typedef FPL__FUNC_WIN32_PeekMessageW(fpl__win32_func_PeekMessageW);
7580 #define FPL__FUNC_WIN32_DefWindowProcW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
7581 typedef FPL__FUNC_WIN32_DefWindowProcW(fpl__win32_func_DefWindowProcW);
7582 #define FPL__FUNC_WIN32_CreateWindowExW(name) HWND WINAPI name(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
7583 typedef FPL__FUNC_WIN32_CreateWindowExW(fpl__win32_func_CreateWindowExW);
7584 #define FPL__FUNC_WIN32_SetWindowPos(name) BOOL WINAPI name(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
7585 typedef FPL__FUNC_WIN32_SetWindowPos(fpl__win32_func_SetWindowPos);
7586 #define FPL__FUNC_WIN32_GetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, WINDOWPLACEMENT *lpwndpl)
7587 typedef FPL__FUNC_WIN32_GetWindowPlacement(fpl__win32_func_GetWindowPlacement);
7588 #define FPL__FUNC_WIN32_SetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl)
7589 typedef FPL__FUNC_WIN32_SetWindowPlacement(fpl__win32_func_SetWindowPlacement);
7590 #define FPL__FUNC_WIN32_GetClientRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
7591 typedef FPL__FUNC_WIN32_GetClientRect(fpl__win32_func_GetClientRect);
7592 #define FPL__FUNC_WIN32_GetWindowRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
7593 typedef FPL__FUNC_WIN32_GetWindowRect(fpl__win32_func_GetWindowRect);
7594 #define FPL__FUNC_WIN32_AdjustWindowRect(name) BOOL WINAPI name(LPRECT lpRect, DWORD dwStyle, BOOL bMenu)
7595 typedef FPL__FUNC_WIN32_AdjustWindowRect(fpl__win32_func_AdjustWindowRect);
7596 #define FPL__FUNC_WIN32_ClientToScreen(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
7597 typedef FPL__FUNC_WIN32_ClientToScreen(fpl__win32_func_ClientToScreen);
7598 #define FPL__FUNC_WIN32_GetAsyncKeyState(name) SHORT WINAPI name(int vKey)
7599 typedef FPL__FUNC_WIN32_GetAsyncKeyState(fpl__win32_func_GetAsyncKeyState);
7600 #define FPL__FUNC_WIN32_GetKeyState(name) SHORT WINAPI name(int vKey)
7601 typedef FPL__FUNC_WIN32_GetKeyState(fpl__win32_func_GetKeyState);
7602 #define FPL__FUNC_WIN32_MapVirtualKeyW(name) UINT WINAPI name(UINT uCode, UINT uMapType)
7603 typedef FPL__FUNC_WIN32_MapVirtualKeyW(fpl__win32_func_MapVirtualKeyW);
7604 #define FPL__FUNC_WIN32_SetCursor(name) HCURSOR WINAPI name(HCURSOR hCursor)
7605 typedef FPL__FUNC_WIN32_SetCursor(fpl__win32_func_SetCursor);
7606 #define FPL__FUNC_WIN32_GetCursor(name) HCURSOR WINAPI name(VOID)
7607 typedef FPL__FUNC_WIN32_GetCursor(fpl__win32_func_GetCursor);
7608 #define FPL__FUNC_WIN32_GetCursorPos(name) BOOL WINAPI name(LPPOINT lpPoint)
7609 typedef FPL__FUNC_WIN32_GetCursorPos(fpl__win32_func_GetCursorPos);
7610 #define FPL__FUNC_WIN32_WindowFromPoint(name) HWND WINAPI name(POINT Point)
7611 typedef FPL__FUNC_WIN32_WindowFromPoint(fpl__win32_func_WindowFromPoint);
7612 #define FPL__FUNC_WIN32_PtInRect(name) BOOL WINAPI name(CONST RECT *lprc, POINT pt)
7613 typedef FPL__FUNC_WIN32_PtInRect(fpl__win32_func_PtInRect);
7614 #define FPL__FUNC_WIN32_LoadCursorA(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCSTR lpCursorName)
7615 typedef FPL__FUNC_WIN32_LoadCursorA(fpl__win32_func_LoadCursorA);
7616 #define FPL__FUNC_WIN32_LoadCursorW(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCWSTR lpCursorName)
7617 typedef FPL__FUNC_WIN32_LoadCursorW(fpl__win32_func_LoadCursorW);
7618 #define FPL__FUNC_WIN32_LoadIconA(name) HICON WINAPI name(HINSTANCE hInstance, LPCSTR lpIconName)
7619 typedef FPL__FUNC_WIN32_LoadIconA(fpl__win32_func_LoadIconA);
7620 #define FPL__FUNC_WIN32_LoadIconW(name) HICON WINAPI name(HINSTANCE hInstance, LPCWSTR lpIconName)
7621 typedef FPL__FUNC_WIN32_LoadIconW(fpl__win32_func_LoadIconW);
7622 #define FPL__FUNC_WIN32_SetWindowTextW(name) BOOL WINAPI name(HWND hWnd, LPCWSTR lpString)
7623 typedef FPL__FUNC_WIN32_SetWindowTextW(fpl__win32_func_SetWindowTextW);
7624 #define FPL__FUNC_WIN32_GetWindowTextW(name) int WINAPI name(HWND hWnd, LPWSTR lpString, int nMaxCount)
7625 typedef FPL__FUNC_WIN32_GetWindowTextW(fpl__win32_func_GetWindowTextW);
7626 #define FPL__FUNC_WIN32_SetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex, LONG dwNewLong)
7627 typedef FPL__FUNC_WIN32_SetWindowLongW(fpl__win32_func_SetWindowLongW);
7628 #define FPL__FUNC_WIN32_GetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex)
7629 typedef FPL__FUNC_WIN32_GetWindowLongW(fpl__win32_func_GetWindowLongW);
7630 
7631 #if defined(FPL_ARCH_X64)
7632 #define FPL__FUNC_WIN32_SetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
7633 typedef FPL__FUNC_WIN32_SetWindowLongPtrW(fpl__win32_func_SetWindowLongPtrW);
7634 #define FPL__FUNC_WIN32_GetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex)
7635 typedef FPL__FUNC_WIN32_GetWindowLongPtrW(fpl__win32_func_GetWindowLongPtrW);
7636 #endif
7637 
7638 #define FPL__FUNC_WIN32_ReleaseDC(name) int WINAPI name(HWND hWnd, HDC hDC)
7639 typedef FPL__FUNC_WIN32_ReleaseDC(fpl__win32_func_ReleaseDC);
7640 #define FPL__FUNC_WIN32_GetDC(name) HDC WINAPI name(HWND hWnd)
7641 typedef FPL__FUNC_WIN32_GetDC(fpl__win32_func_GetDC);
7642 #define FPL__FUNC_WIN32_ChangeDisplaySettingsW(name) LONG WINAPI name(DEVMODEW* lpDevMode, DWORD dwFlags)
7643 typedef FPL__FUNC_WIN32_ChangeDisplaySettingsW(fpl__win32_func_ChangeDisplaySettingsW);
7644 #define FPL__FUNC_WIN32_EnumDisplaySettingsW(name) BOOL WINAPI name(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode)
7645 typedef FPL__FUNC_WIN32_EnumDisplaySettingsW(fpl__win32_func_EnumDisplaySettingsW);
7646 #define FPL__FUNC_WIN32_OpenClipboard(name) BOOL WINAPI name(HWND hWndNewOwner)
7647 typedef FPL__FUNC_WIN32_OpenClipboard(fpl__win32_func_OpenClipboard);
7648 #define FPL__FUNC_WIN32_CloseClipboard(name) BOOL WINAPI name(VOID)
7649 typedef FPL__FUNC_WIN32_CloseClipboard(fpl__win32_func_CloseClipboard);
7650 #define FPL__FUNC_WIN32_EmptyClipboard(name) BOOL WINAPI name(VOID)
7651 typedef FPL__FUNC_WIN32_EmptyClipboard(fpl__win32_func_EmptyClipboard);
7652 #define FPL__FUNC_WIN32_IsClipboardFormatAvailable(name) BOOL WINAPI name(UINT format)
7653 typedef FPL__FUNC_WIN32_IsClipboardFormatAvailable(fpl__win32_func_IsClipboardFormatAvailable);
7654 #define FPL__FUNC_WIN32_SetClipboardData(name) HANDLE WINAPI name(UINT uFormat, HANDLE hMem)
7655 typedef FPL__FUNC_WIN32_SetClipboardData(fpl__win32_func_SetClipboardData);
7656 #define FPL__FUNC_WIN32_GetClipboardData(name) HANDLE WINAPI name(UINT uFormat)
7657 typedef FPL__FUNC_WIN32_GetClipboardData(fpl__win32_func_GetClipboardData);
7658 #define FPL__FUNC_WIN32_GetDesktopWindow(name) HWND WINAPI name(VOID)
7659 typedef FPL__FUNC_WIN32_GetDesktopWindow(fpl__win32_func_GetDesktopWindow);
7660 #define FPL__FUNC_WIN32_GetForegroundWindow(name) HWND WINAPI name(VOID)
7661 typedef FPL__FUNC_WIN32_GetForegroundWindow(fpl__win32_func_GetForegroundWindow);
7662 #define FPL__FUNC_WIN32_IsZoomed(name) BOOL WINAPI name(HWND hWnd)
7663 typedef FPL__FUNC_WIN32_IsZoomed(fpl__win32_func_IsZoomed);
7664 #define FPL__FUNC_WIN32_IsIconic(name) BOOL WINAPI name(HWND hWnd)
7665 typedef FPL__FUNC_WIN32_IsIconic(fpl__win32_func_IsIconic);
7666 #define FPL__FUNC_WIN32_SendMessageW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
7667 typedef FPL__FUNC_WIN32_SendMessageW(fpl__win32_func_SendMessageW);
7668 #define FPL__FUNC_WIN32_GetMonitorInfoW(name) BOOL WINAPI name(HMONITOR hMonitor, LPMONITORINFO lpmi)
7669 typedef FPL__FUNC_WIN32_GetMonitorInfoW(fpl__win32_func_GetMonitorInfoW);
7670 #define FPL__FUNC_WIN32_EnumDisplayMonitors(name) BOOL WINAPI name(HDC hdc, LPCRECT lprcClip, MONITORENUMPROC lpfnEnum,LPARAM dwData)
7671 typedef FPL__FUNC_WIN32_EnumDisplayMonitors(fpl__win32_func_EnumDisplayMonitors);
7672 #define FPL__FUNC_WIN32_MonitorFromRect(name) HMONITOR WINAPI name(LPCRECT lprc, DWORD dwFlags)
7673 typedef FPL__FUNC_WIN32_MonitorFromRect(fpl__win32_func_MonitorFromRect);
7674 #define FPL__FUNC_WIN32_MonitorFromPoint(name) HMONITOR WINAPI name(POINT pt, DWORD dwFlags)
7675 typedef FPL__FUNC_WIN32_MonitorFromPoint(fpl__win32_func_MonitorFromPoint);
7676 #define FPL__FUNC_WIN32_MonitorFromWindow(name) HMONITOR WINAPI name(HWND hwnd, DWORD dwFlags)
7677 typedef FPL__FUNC_WIN32_MonitorFromWindow(fpl__win32_func_MonitorFromWindow);
7678 #define FPL__FUNC_WIN32_RegisterRawInputDevices(name) BOOL WINAPI name(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
7679 typedef FPL__FUNC_WIN32_RegisterRawInputDevices(fpl__win32_func_RegisterRawInputDevices);
7680 #define FPL__FUNC_WIN32_ClipCursor(name) BOOL WINAPI name(CONST RECT *lpRect)
7681 typedef FPL__FUNC_WIN32_ClipCursor(fpl__win32_func_ClipCursor);
7682 #define FPL__FUNC_WIN32_PostQuitMessage(name) VOID WINAPI name(int nExitCode)
7683 typedef FPL__FUNC_WIN32_PostQuitMessage(fpl__win32_func_PostQuitMessage);
7684 #define FPL__FUNC_WIN32_CreateIconIndirect(name) HICON WINAPI name(PICONINFO piconinfo)
7685 typedef FPL__FUNC_WIN32_CreateIconIndirect(fpl__win32_func_CreateIconIndirect);
7686 #define FPL__FUNC_WIN32_GetKeyboardLayout(name) HKL WINAPI name(DWORD idThread)
7687 typedef FPL__FUNC_WIN32_GetKeyboardLayout(fpl__win32_func_GetKeyboardLayout);
7688 #define FPL__FUNC_WIN32_SetCapture(name) HWND WINAPI name(HWND hWnd)
7689 typedef FPL__FUNC_WIN32_SetCapture(fpl__win32_func_SetCapture);
7690 #define FPL__FUNC_WIN32_ReleaseCapture(name) BOOL WINAPI name(VOID)
7691 typedef FPL__FUNC_WIN32_ReleaseCapture(fpl__win32_func_ReleaseCapture);
7692 #define FPL__FUNC_WIN32_ScreenToClient(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
7693 typedef FPL__FUNC_WIN32_ScreenToClient(fpl__win32_func_ScreenToClient);
7694 #define FPL__FUNC_WIN32_BeginPaint(name) HDC WINAPI name(_In_ HWND hWnd, _Out_ LPPAINTSTRUCT lpPaint)
7695 typedef FPL__FUNC_WIN32_BeginPaint(fpl__win32_func_BeginPaint);
7696 #define FPL__FUNC_WIN32_EndPaint(name) BOOL WINAPI name(_In_ HWND hWnd, _In_ CONST PAINTSTRUCT *lpPaint)
7697 typedef FPL__FUNC_WIN32_EndPaint(fpl__win32_func_EndPaint);
7698 #define FPL__FUNC_WIN32_SetForegroundWindow(name) BOOL WINAPI name(_In_ HWND hWnd)
7699 typedef FPL__FUNC_WIN32_SetForegroundWindow(fpl__win32_func_SetForegroundWindow);
7700 #define FPL__FUNC_WIN32_SetFocus(name) HWND WINAPI name(_In_opt_ HWND hWnd)
7701 typedef FPL__FUNC_WIN32_SetFocus(fpl__win32_func_SetFocus);
7702 #define FPL__FUNC_WIN32_SetTimer(name) UINT_PTR WINAPI name(_In_opt_ HWND hWnd, _In_ UINT_PTR nIDEvent, _In_ UINT uElapse, _In_opt_ TIMERPROC lpTimerFunc)
7703 typedef FPL__FUNC_WIN32_SetTimer(fpl__win32_func_SetTimer);
7704 
7705 // OLE32
7706 #define FPL__FUNC_WIN32_CoInitializeEx(name) HRESULT WINAPI name(LPVOID pvReserved, DWORD dwCoInit)
7707 typedef FPL__FUNC_WIN32_CoInitializeEx(fpl__win32_func_CoInitializeEx);
7708 #define FPL__FUNC_WIN32_CoUninitialize(name) void WINAPI name(void)
7709 typedef FPL__FUNC_WIN32_CoUninitialize(fpl__win32_func_CoUninitialize);
7710 #define FPL__FUNC_WIN32_CoCreateInstance(name) HRESULT WINAPI name(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
7711 typedef FPL__FUNC_WIN32_CoCreateInstance(fpl__win32_func_CoCreateInstance);
7712 #define FPL__FUNC_WIN32_CoTaskMemFree(name) void WINAPI name(LPVOID pv)
7713 typedef FPL__FUNC_WIN32_CoTaskMemFree(fpl__win32_func_CoTaskMemFree);
7714 #define FPL__FUNC_WIN32_PropVariantClear(name) HRESULT WINAPI name(PROPVARIANT *pvar)
7715 typedef FPL__FUNC_WIN32_PropVariantClear(fpl__win32_func_PropVariantClear);
7716 
7717 typedef struct fpl__Win32GdiApi {
7718  HMODULE gdiLibrary;
7719  fpl__win32_func_ChoosePixelFormat *ChoosePixelFormat;
7720  fpl__win32_func_SetPixelFormat *SetPixelFormat;
7721  fpl__win32_func_DescribePixelFormat *DescribePixelFormat;
7722  fpl__win32_func_GetDeviceCaps *GetDeviceCaps;
7723  fpl__win32_func_StretchDIBits *StretchDIBits;
7724  fpl__win32_func_DeleteObject *DeleteObject;
7725  fpl__win32_func_SwapBuffers *SwapBuffers;
7726  fpl__win32_func_CreateDIBSection *CreateDIBSection;
7727  fpl__win32_func_CreateBitmap *CreateBitmap;
7728 } fpl__Win32GdiApi;
7729 
7730 typedef struct fpl__Win32ShellApi {
7731  HMODULE shellLibrary;
7732  fpl__win32_func_SHGetFolderPathW *SHGetFolderPathW;
7733  fpl__win32_func_DragQueryFileW *DragQueryFileW;
7734  fpl__win32_func_DragAcceptFiles *DragAcceptFiles;
7735 } fpl__Win32ShellApi;
7736 
7737 typedef struct fpl__Win32UserApi {
7738  HMODULE userLibrary;
7739  fpl__win32_func_RegisterClassExW *RegisterClassExW;
7740  fpl__win32_func_UnregisterClassW *UnregisterClassW;
7741  fpl__win32_func_ShowWindow *ShowWindow;
7742  fpl__win32_func_DestroyWindow *DestroyWindow;
7743  fpl__win32_func_UpdateWindow *UpdateWindow;
7744  fpl__win32_func_TranslateMessage *TranslateMessage;
7745  fpl__win32_func_DispatchMessageW *DispatchMessageW;
7746  fpl__win32_func_PeekMessageW *PeekMessageW;
7747  fpl__win32_func_DefWindowProcW *DefWindowProcW;
7748  fpl__win32_func_CreateWindowExW *CreateWindowExW;
7749  fpl__win32_func_SetWindowPos *SetWindowPos;
7750  fpl__win32_func_GetWindowPlacement *GetWindowPlacement;
7751  fpl__win32_func_SetWindowPlacement *SetWindowPlacement;
7752  fpl__win32_func_GetClientRect *GetClientRect;
7753  fpl__win32_func_GetWindowRect *GetWindowRect;
7754  fpl__win32_func_AdjustWindowRect *AdjustWindowRect;
7755  fpl__win32_func_GetAsyncKeyState *GetAsyncKeyState;
7756  fpl__win32_func_MapVirtualKeyW *MapVirtualKeyW;
7757  fpl__win32_func_SetCursor *SetCursor;
7758  fpl__win32_func_GetCursor *GetCursor;
7759  fpl__win32_func_LoadCursorA *LoadCursorA;
7760  fpl__win32_func_LoadCursorW *LoadCursorW;
7761  fpl__win32_func_LoadIconA *LoadIconA;
7762  fpl__win32_func_LoadIconW *LoadIconW;
7763  fpl__win32_func_SetWindowTextW *SetWindowTextW;
7764  fpl__win32_func_GetWindowTextW *GetWindowTextW;
7765  fpl__win32_func_SetWindowLongW *SetWindowLongW;
7766  fpl__win32_func_GetWindowLongW *GetWindowLongW;
7767 #if defined(FPL_ARCH_X64)
7768  fpl__win32_func_SetWindowLongPtrW *SetWindowLongPtrW;
7769  fpl__win32_func_GetWindowLongPtrW *GetWindowLongPtrW;
7770 #endif
7771  fpl__win32_func_ReleaseDC *ReleaseDC;
7772  fpl__win32_func_GetDC *GetDC;
7773  fpl__win32_func_ChangeDisplaySettingsW *ChangeDisplaySettingsW;
7774  fpl__win32_func_EnumDisplaySettingsW *EnumDisplaySettingsW;
7775  fpl__win32_func_OpenClipboard *OpenClipboard;
7776  fpl__win32_func_CloseClipboard *CloseClipboard;
7777  fpl__win32_func_EmptyClipboard *EmptyClipboard;
7778  fpl__win32_func_IsClipboardFormatAvailable *IsClipboardFormatAvailable;
7779  fpl__win32_func_SetClipboardData *SetClipboardData;
7780  fpl__win32_func_GetClipboardData *GetClipboardData;
7781  fpl__win32_func_GetDesktopWindow *GetDesktopWindow;
7782  fpl__win32_func_GetForegroundWindow *GetForegroundWindow;
7783  fpl__win32_func_IsZoomed *IsZoomed;
7784  fpl__win32_func_IsIconic *IsIconic;
7785  fpl__win32_func_SendMessageW *SendMessageW;
7786  fpl__win32_func_GetMonitorInfoW *GetMonitorInfoW;
7787  fpl__win32_func_EnumDisplayMonitors *EnumDisplayMonitors;
7788  fpl__win32_func_MonitorFromRect *MonitorFromRect;
7789  fpl__win32_func_MonitorFromPoint *MonitorFromPoint;
7790  fpl__win32_func_MonitorFromWindow *MonitorFromWindow;
7791  fpl__win32_func_GetCursorPos *GetCursorPos;
7792  fpl__win32_func_WindowFromPoint *WindowFromPoint;
7793  fpl__win32_func_ClientToScreen *ClientToScreen;
7794  fpl__win32_func_PtInRect *PtInRect;
7795  fpl__win32_func_RegisterRawInputDevices *RegisterRawInputDevices;
7796  fpl__win32_func_ClipCursor *ClipCursor;
7797  fpl__win32_func_PostQuitMessage *PostQuitMessage;
7798  fpl__win32_func_CreateIconIndirect *CreateIconIndirect;
7799  fpl__win32_func_GetKeyboardLayout *GetKeyboardLayout;
7800  fpl__win32_func_GetKeyState *GetKeyState;
7801  fpl__win32_func_SetCapture *SetCapture;
7802  fpl__win32_func_ReleaseCapture *ReleaseCapture;
7803  fpl__win32_func_ScreenToClient *ScreenToClient;
7804  fpl__win32_func_BeginPaint *BeginPaint;
7805  fpl__win32_func_EndPaint *EndPaint;
7806  fpl__win32_func_SetForegroundWindow *SetForegroundWindow;
7807  fpl__win32_func_SetFocus *SetFocus;
7808  fpl__win32_func_SetTimer *SetTimer;
7809 } fpl__Win32UserApi;
7810 
7811 typedef struct fpl__Win32OleApi {
7812  HMODULE oleLibrary;
7813  fpl__win32_func_CoInitializeEx *CoInitializeEx;
7814  fpl__win32_func_CoUninitialize *CoUninitialize;
7815  fpl__win32_func_CoCreateInstance *CoCreateInstance;
7816  fpl__win32_func_CoTaskMemFree *CoTaskMemFree;
7817  fpl__win32_func_PropVariantClear *PropVariantClear;
7818 } fpl__Win32OleApi;
7819 
7820 typedef struct fpl__Win32Api {
7821  fpl__Win32GdiApi gdi;
7822  fpl__Win32ShellApi shell;
7823  fpl__Win32UserApi user;
7824  fpl__Win32OleApi ole;
7825  fpl_b32 isValid;
7826 } fpl__Win32Api;
7827 
7828 fpl_internal void fpl__Win32UnloadApi(fpl__Win32Api *wapi) {
7829  fplAssert(wapi != fpl_null);
7830  if(wapi->ole.oleLibrary != fpl_null) {
7831  FreeLibrary(wapi->ole.oleLibrary);
7832  }
7833  fplClearStruct(&wapi->ole);
7834  if(wapi->gdi.gdiLibrary != fpl_null) {
7835  FreeLibrary(wapi->gdi.gdiLibrary);
7836  }
7837  fplClearStruct(&wapi->gdi);
7838  if(wapi->user.userLibrary != fpl_null) {
7839  FreeLibrary(wapi->user.userLibrary);
7840  }
7841  fplClearStruct(&wapi->user);
7842  if(wapi->shell.shellLibrary != fpl_null) {
7843  FreeLibrary(wapi->shell.shellLibrary);
7844  }
7845  fplClearStruct(&wapi->shell);
7846  wapi->isValid = false;
7847 }
7848 
7849 fpl_internal bool fpl__Win32LoadApi(fpl__Win32Api *wapi) {
7850  fplAssert(wapi != fpl_null);
7851  bool result = false;
7852  fplClearStruct(wapi);
7853  do {
7854  // Shell32
7855  const char *shellLibraryName = "shell32.dll";
7856  HMODULE shellLibrary = fpl_null;
7857  FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, shellLibrary, shellLibraryName);
7858  wapi->shell.shellLibrary = shellLibrary;
7859  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_SHGetFolderPathW, SHGetFolderPathW);
7860  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragQueryFileW, DragQueryFileW);
7861  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragAcceptFiles, DragAcceptFiles);
7862 
7863  // User32
7864  const char *userLibraryName = "user32.dll";
7865  HMODULE userLibrary = fpl_null;
7866  FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, userLibrary, userLibraryName);
7867  wapi->user.userLibrary = userLibrary;
7868  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterClassExW, RegisterClassExW);
7869  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UnregisterClassW, UnregisterClassW);
7870  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ShowWindow, ShowWindow);
7871  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DestroyWindow, DestroyWindow);
7872  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UpdateWindow, UpdateWindow);
7873  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_TranslateMessage, TranslateMessage);
7874  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DispatchMessageW, DispatchMessageW);
7875  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PeekMessageW, PeekMessageW);
7876  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DefWindowProcW, DefWindowProcW);
7877  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateWindowExW, CreateWindowExW);
7878  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPos, SetWindowPos);
7879  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowPlacement, GetWindowPlacement);
7880  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPlacement, SetWindowPlacement);
7881  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClientRect, GetClientRect);
7882  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowRect, GetWindowRect);
7883  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_AdjustWindowRect, AdjustWindowRect);
7884  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetAsyncKeyState, GetAsyncKeyState);
7885  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MapVirtualKeyW, MapVirtualKeyW);
7886  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCursor, SetCursor);
7887  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursor, GetCursor);
7888  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorA, LoadCursorA);
7889  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorW, LoadCursorW);
7890  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursorPos, GetCursorPos);
7891  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_WindowFromPoint, WindowFromPoint);
7892  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconA, LoadIconA);
7893  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconW, LoadIconW);
7894  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowTextW, SetWindowTextW);
7895  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongW, SetWindowLongW);
7896  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongW, GetWindowLongW);
7897 
7898 # if defined(FPL_ARCH_X64)
7899  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongPtrW, SetWindowLongPtrW);
7900  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongPtrW, GetWindowLongPtrW);
7901 # endif
7902 
7903  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseDC, ReleaseDC);
7904  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDC, GetDC);
7905  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ChangeDisplaySettingsW, ChangeDisplaySettingsW);
7906  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplaySettingsW, EnumDisplaySettingsW);
7907  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsClipboardFormatAvailable, IsClipboardFormatAvailable);
7908  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_OpenClipboard, OpenClipboard);
7909  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CloseClipboard, CloseClipboard);
7910  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EmptyClipboard, EmptyClipboard);
7911  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetClipboardData, SetClipboardData);
7912  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClipboardData, GetClipboardData);
7913  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDesktopWindow, GetDesktopWindow);
7914  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetForegroundWindow, GetForegroundWindow);
7915  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsZoomed, IsZoomed);
7916  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsIconic, IsIconic);
7917  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SendMessageW, SendMessageW);
7918  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetMonitorInfoW, GetMonitorInfoW);
7919  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplayMonitors, EnumDisplayMonitors);
7920  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromRect, MonitorFromRect);
7921  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromPoint, MonitorFromPoint);
7922  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromWindow, MonitorFromWindow);
7923  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClientToScreen, ClientToScreen);
7924  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PtInRect, PtInRect);
7925  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterRawInputDevices, RegisterRawInputDevices);
7926  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClipCursor, ClipCursor);
7927  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PostQuitMessage, PostQuitMessage);
7928  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateIconIndirect, CreateIconIndirect);
7929  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyboardLayout, GetKeyboardLayout);
7930  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyState, GetKeyState);
7931  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCapture, SetCapture);
7932  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseCapture, ReleaseCapture);
7933  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ScreenToClient, ScreenToClient);
7934  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_BeginPaint, BeginPaint);
7935  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EndPaint, EndPaint);
7936  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetForegroundWindow, SetForegroundWindow);
7937  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetFocus, SetFocus);
7938  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetTimer, SetTimer);
7939 
7940  // GDI32
7941  const char *gdiLibraryName = "gdi32.dll";
7942  HMODULE gdiLibrary = fpl_null;
7943  FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName);
7944  wapi->gdi.gdiLibrary = gdiLibrary;
7945  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_ChoosePixelFormat, ChoosePixelFormat);
7946  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SetPixelFormat, SetPixelFormat);
7947  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DescribePixelFormat, DescribePixelFormat);
7948  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_StretchDIBits, StretchDIBits);
7949  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DeleteObject, DeleteObject);
7950  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SwapBuffers, SwapBuffers);
7951  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_GetDeviceCaps, GetDeviceCaps);
7952  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateDIBSection, CreateDIBSection);
7953  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateBitmap, CreateBitmap);
7954 
7955  // OLE32
7956  const char *oleLibraryName = "ole32.dll";
7957  HMODULE oleLibrary = fpl_null;
7958  FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, oleLibrary, oleLibraryName);
7959  wapi->ole.oleLibrary = oleLibrary;
7960  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoInitializeEx, CoInitializeEx);
7961  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoUninitialize, CoUninitialize);
7962  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoCreateInstance, CoCreateInstance);
7963  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoTaskMemFree, CoTaskMemFree);
7964  FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_PropVariantClear, PropVariantClear);
7965 
7966  result = true;
7967  } while(0);
7968  if(!result) {
7969  fpl__Win32UnloadApi(wapi);
7970  }
7971  wapi->isValid = result;
7972  return(result);
7973 }
7974 
7975 // Win32 unicode dependend stuff
7976 #define FPL__WIN32_CLASSNAME L"FPLWindowClassW"
7977 #define FPL__WIN32_UNNAMED_WINDOW L"Unnamed FPL Unicode Window"
7978 #define FPL__WIN32_UNNAMED_CONSOLE L"Unnamed FPL Unicode Console"
7979 #if defined(FPL_ARCH_X64)
7980 # define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongPtrW
7981 #else
7982 # define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongW
7983 #endif
7984 #define fpl__win32_SetWindowLong fpl__global__AppState->win32.winApi.user.SetWindowLongW
7985 #define fpl__win32_GetWindowLong fpl__global__AppState->win32.winApi.user.GetWindowLongW
7986 #if UNICODE
7987 # define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconW
7988 # define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorW
7989 #else
7990 # define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconA
7991 # define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorA
7992 #endif
7993 
7994 typedef char fpl__GameControllerName[FPL_MAX_NAME_LENGTH];
7995 
7996 typedef struct fpl__Win32XInputState {
7997  fpl__GameControllerName deviceNames[XUSER_MAX_COUNT];
7998  fpl_b32 isConnected[XUSER_MAX_COUNT];
7999  fpl__Win32XInputApi xinputApi;
8000  LARGE_INTEGER lastDeviceSearchTime;
8001 } fpl__Win32XInputState;
8002 
8003 typedef struct fpl__Win32InitState {
8004  HINSTANCE appInstance;
8005 } fpl__Win32InitState;
8006 
8007 typedef struct fpl__Win32AppState {
8008  fpl__Win32XInputState xinput;
8009  fpl__Win32Api winApi;
8010 } fpl__Win32AppState;
8011 
8012 #if defined(FPL__ENABLE_WINDOW)
8013 typedef struct fpl__Win32LastWindowInfo {
8014  WINDOWPLACEMENT placement;
8015  DWORD style;
8016  DWORD exStyle;
8017  fpl_b32 isMaximized;
8018  fpl_b32 isMinimized;
8019  fpl_b32 wasResolutionChanged;
8020 } fpl__Win32LastWindowInfo;
8021 
8022 typedef struct fpl__Win32WindowState {
8023  wchar_t windowClass[256];
8024  fpl__Win32LastWindowInfo lastFullscreenInfo;
8025  void *mainFiber;
8026  void *messageFiber;
8027  HWND windowHandle;
8028  HDC deviceContext;
8029  HCURSOR defaultCursor;
8030  int pixelFormat;
8031  fpl_b32 isCursorActive;
8032  fpl_b32 isFrameInteraction;
8033 } fpl__Win32WindowState;
8034 #endif // FPL__ENABLE_WINDOW
8035 
8036 #endif // FPL_PLATFORM_WINDOWS
8037 
8038 // ############################################################################
8039 //
8040 // > TYPES_POSIX
8041 //
8042 // ############################################################################
8043 #if defined(FPL_SUBPLATFORM_POSIX)
8044 # include <sys/types.h> // data types
8045 # include <sys/mman.h> // mmap, munmap
8046 # include <sys/stat.h> // mkdir
8047 # include <sys/errno.h> // errno
8048 # include <sys/time.h> // gettimeofday
8049 # include <sys/utsname.h> // uname
8050 # include <signal.h> // pthread_kill
8051 # include <time.h> // clock_gettime, nanosleep
8052 # include <dlfcn.h> // dlopen, dlclose
8053 # include <fcntl.h> // open
8054 # include <unistd.h> // read, write, close, access, rmdir, getpid, sysconf, geteuid
8055 # include <ctype.h> // isspace
8056 # include <pwd.h> // getpwuid
8057 
8058 // @TODO(final): Detect the case of (Older POSIX versions where st_atim != st_atime)
8059 #if !defined(FPL_PLATFORM_ANDROID)
8060 # define st_atime st_atim.tv_sec
8061 # define st_mtime st_mtim.tv_sec
8062 # define st_ctime st_ctim.tv_sec
8063 #endif
8064 
8065 #if defined(FPL_PLATFORM_LINUX)
8066 # define fpl__lseek64 lseek64
8067 # define fpl__off64_t off64_t
8068 #else
8069 # define fpl__lseek64 lseek
8070 # define fpl__off64_t off_t
8071 #endif
8072 
8073 // Little macros for loading a library and getting proc address for POSIX
8074 #define FPL__POSIX_LOAD_LIBRARY_BREAK(mod, target, libName) \
8075  (target) = dlopen(libName, FPL__POSIX_DL_LOADTYPE); \
8076  if((target) == fpl_null) { \
8077  FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
8078  break; \
8079  }
8080 
8081 #define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
8082  (target)->name = (type *)dlsym(libHandle, #name)
8083 
8084 #define FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
8085  (target)->name = (type *)dlsym(libHandle, #name); \
8086  if ((target)->name == fpl_null) { \
8087  FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
8088  break; \
8089  }
8090 #if !defined(FPL_NO_RUNTIME_LINKING)
8091 # define FPL__POSIX_LOAD_LIBRARY FPL__POSIX_LOAD_LIBRARY_BREAK
8092 # define FPL__POSIX_GET_FUNCTION_ADDRESS FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK
8093 #else
8094 # define FPL__POSIX_LOAD_LIBRARY(mod, target, libName)
8095 # define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
8096  (target)->name = name
8097 # define FPL__POSIX_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
8098  (target)->name = name
8099 #endif
8100 
8101 #define FPL__FUNC_PTHREAD_pthread_self(name) pthread_t name(void)
8102 typedef FPL__FUNC_PTHREAD_pthread_self(fpl__pthread_func_pthread_self);
8103 #define FPL__FUNC_PTHREAD_pthread_setschedparam(name) int name(pthread_t thread, int policy, const struct sched_param *param)
8104 typedef FPL__FUNC_PTHREAD_pthread_setschedparam(fpl__pthread_func_pthread_setschedparam);
8105 #define FPL__FUNC_PTHREAD_pthread_getschedparam(name) int name(pthread_t thread, int *policy, struct sched_param *param)
8106 typedef FPL__FUNC_PTHREAD_pthread_getschedparam(fpl__pthread_func_pthread_getschedparam);
8107 #define FPL__FUNC_PTHREAD_pthread_setschedprio(name) int name(pthread_t thread, int prio)
8108 typedef FPL__FUNC_PTHREAD_pthread_setschedprio(fpl__pthread_func_pthread_setschedprio);
8109 
8110 #define FPL__FUNC_PTHREAD_pthread_attr_init(name) int name(pthread_attr_t *attr)
8111 typedef FPL__FUNC_PTHREAD_pthread_attr_init(fpl__pthread_func_pthread_attr_init);
8112 #define FPL__FUNC_PTHREAD_pthread_attr_getschedparam(name) int name(const pthread_attr_t *__restrict__ attr, struct sched_param *__restrict__ param)
8113 typedef FPL__FUNC_PTHREAD_pthread_attr_getschedparam(fpl__pthread_func_pthread_attr_getschedparam);
8114 #define FPL__FUNC_PTHREAD_pthread_attr_setschedparam(name) int name(pthread_attr_t *__restrict__ attr, const struct sched_param *__restrict__ param)
8115 typedef FPL__FUNC_PTHREAD_pthread_attr_setschedparam(fpl__pthread_func_pthread_attr_setschedparam);
8116 #define FPL__FUNC_PTHREAD_pthread_attr_setstacksize(name) int name(pthread_attr_t *attr, size_t stacksize)
8117 typedef FPL__FUNC_PTHREAD_pthread_attr_setstacksize(fpl__pthread_func_pthread_attr_setstacksize);
8118 #define FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(name) int name(pthread_attr_t *attr, int detachstate);
8119 typedef FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(fpl__pthread_func_pthread_attr_setdetachstate);
8120 #define FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(name) int name(pthread_attr_t *__attr, int __policy)
8121 typedef FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(fpl__pthread_func_pthread_attr_setschedpolicy);
8122 
8123 #define FPL__FUNC_PTHREAD_pthread_create(name) int name(pthread_t *, const pthread_attr_t *, void *(*__start_routine) (void *), void *)
8124 typedef FPL__FUNC_PTHREAD_pthread_create(fpl__pthread_func_pthread_create);
8125 #define FPL__FUNC_PTHREAD_pthread_kill(name) int name(pthread_t thread, int sig)
8126 typedef FPL__FUNC_PTHREAD_pthread_kill(fpl__pthread_func_pthread_kill);
8127 #define FPL__FUNC_PTHREAD_pthread_join(name) int name(pthread_t __th, void **retval)
8128 typedef FPL__FUNC_PTHREAD_pthread_join(fpl__pthread_func_pthread_join);
8129 #define FPL__FUNC_PTHREAD_pthread_exit(name) void name(void *__retval)
8130 typedef FPL__FUNC_PTHREAD_pthread_exit(fpl__pthread_func_pthread_exit);
8131 #define FPL__FUNC_PTHREAD_pthread_yield(name) int name(void)
8132 typedef FPL__FUNC_PTHREAD_pthread_yield(fpl__pthread_func_pthread_yield);
8133 #define FPL__FUNC_PTHREAD_pthread_timedjoin_np(name) int name(pthread_t thread, void **retval, const struct timespec *abstime)
8134 typedef FPL__FUNC_PTHREAD_pthread_timedjoin_np(fpl__pthread_func_pthread_timedjoin_np);
8135 
8136 #define FPL__FUNC_PTHREAD_pthread_mutex_init(name) int name(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
8137 typedef FPL__FUNC_PTHREAD_pthread_mutex_init(fpl__pthread_func_pthread_mutex_init);
8138 #define FPL__FUNC_PTHREAD_pthread_mutex_destroy(name) int name(pthread_mutex_t *mutex)
8139 typedef FPL__FUNC_PTHREAD_pthread_mutex_destroy(fpl__pthread_func_pthread_mutex_destroy);
8140 #define FPL__FUNC_PTHREAD_pthread_mutex_lock(name) int name(pthread_mutex_t *mutex)
8141 typedef FPL__FUNC_PTHREAD_pthread_mutex_lock(fpl__pthread_func_pthread_mutex_lock);
8142 #define FPL__FUNC_PTHREAD_pthread_mutex_trylock(name) int name(pthread_mutex_t *mutex)
8143 typedef FPL__FUNC_PTHREAD_pthread_mutex_trylock(fpl__pthread_func_pthread_mutex_trylock);
8144 #define FPL__FUNC_PTHREAD_pthread_mutex_unlock(name) int name(pthread_mutex_t *mutex)
8145 typedef FPL__FUNC_PTHREAD_pthread_mutex_unlock(fpl__pthread_func_pthread_mutex_unlock);
8146 
8147 #define FPL__FUNC_PTHREAD_pthread_cond_init(name) int name(pthread_cond_t *cond, const pthread_condattr_t *attr)
8148 typedef FPL__FUNC_PTHREAD_pthread_cond_init(fpl__pthread_func_pthread_cond_init);
8149 #define FPL__FUNC_PTHREAD_pthread_cond_destroy(name) int name(pthread_cond_t *cond)
8150 typedef FPL__FUNC_PTHREAD_pthread_cond_destroy(fpl__pthread_func_pthread_cond_destroy);
8151 #define FPL__FUNC_PTHREAD_pthread_cond_timedwait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
8152 typedef FPL__FUNC_PTHREAD_pthread_cond_timedwait(fpl__pthread_func_pthread_cond_timedwait);
8153 #define FPL__FUNC_PTHREAD_pthread_cond_wait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex)
8154 typedef FPL__FUNC_PTHREAD_pthread_cond_wait(fpl__pthread_func_pthread_cond_wait);
8155 #define FPL__FUNC_PTHREAD_pthread_cond_broadcast(name) int name(pthread_cond_t *cond)
8156 typedef FPL__FUNC_PTHREAD_pthread_cond_broadcast(fpl__pthread_func_pthread_cond_broadcast);
8157 #define FPL__FUNC_PTHREAD_pthread_cond_signal(name) int name(pthread_cond_t *cond)
8158 typedef FPL__FUNC_PTHREAD_pthread_cond_signal(fpl__pthread_func_pthread_cond_signal);
8159 
8160 #define FPL__FUNC_PTHREAD_sem_init(name) int name(sem_t *__sem, int __pshared, unsigned int __value)
8161 typedef FPL__FUNC_PTHREAD_sem_init(fpl__pthread_func_sem_init);
8162 #define FPL__FUNC_PTHREAD_sem_destroy(name) int name(sem_t *__sem)
8163 typedef FPL__FUNC_PTHREAD_sem_destroy(fpl__pthread_func_sem_destroy);
8164 #define FPL__FUNC_PTHREAD_sem_wait(name) int name(sem_t *__sem)
8165 typedef FPL__FUNC_PTHREAD_sem_wait(fpl__pthread_func_sem_wait);
8166 #define FPL__FUNC_PTHREAD_sem_timedwait(name) int name(sem_t *__restrict __sem, const struct timespec *__restrict __abstime)
8167 typedef FPL__FUNC_PTHREAD_sem_timedwait(fpl__pthread_func_sem_timedwait);
8168 #define FPL__FUNC_PTHREAD_sem_trywait(name) int name(sem_t *__sem)
8169 typedef FPL__FUNC_PTHREAD_sem_trywait(fpl__pthread_func_sem_trywait);
8170 #define FPL__FUNC_PTHREAD_sem_post(name) int name(sem_t *__sem)
8171 typedef FPL__FUNC_PTHREAD_sem_post(fpl__pthread_func_sem_post);
8172 #define FPL__FUNC_PTHREAD_sem_getvalue(name) int name(sem_t *__restrict __sem, int *__restrict __sval)
8173 typedef FPL__FUNC_PTHREAD_sem_getvalue(fpl__pthread_func_sem_getvalue);
8174 
8175 typedef struct fpl__PThreadApi {
8176  void *libHandle;
8177 
8178  // pthread_t
8179  fpl__pthread_func_pthread_self *pthread_self;
8180  fpl__pthread_func_pthread_setschedparam *pthread_setschedparam;
8181  fpl__pthread_func_pthread_getschedparam *pthread_getschedparam;
8182  fpl__pthread_func_pthread_setschedprio *pthread_setschedprio;
8183 
8184  fpl__pthread_func_pthread_create *pthread_create;
8185  fpl__pthread_func_pthread_kill *pthread_kill;
8186  fpl__pthread_func_pthread_join *pthread_join;
8187  fpl__pthread_func_pthread_exit *pthread_exit;
8188  fpl__pthread_func_pthread_yield *pthread_yield;
8189  fpl__pthread_func_pthread_timedjoin_np *pthread_timedjoin_np;
8190 
8191  // pthread_attr_t
8192  fpl__pthread_func_pthread_attr_init *pthread_attr_init;
8193  fpl__pthread_func_pthread_attr_getschedparam *pthread_attr_getschedparam;
8194  fpl__pthread_func_pthread_attr_setschedparam *pthread_attr_setschedparam;
8195  fpl__pthread_func_pthread_attr_setstacksize *pthread_attr_setstacksize;
8196  fpl__pthread_func_pthread_attr_setdetachstate *pthread_attr_setdetachstate;
8197  fpl__pthread_func_pthread_attr_setschedpolicy *pthread_attr_setschedpolicy;
8198 
8199  // pthread_mutex_t
8200  fpl__pthread_func_pthread_mutex_init *pthread_mutex_init;
8201  fpl__pthread_func_pthread_mutex_destroy *pthread_mutex_destroy;
8202  fpl__pthread_func_pthread_mutex_lock *pthread_mutex_lock;
8203  fpl__pthread_func_pthread_mutex_trylock *pthread_mutex_trylock;
8204  fpl__pthread_func_pthread_mutex_unlock *pthread_mutex_unlock;
8205 
8206  // pthread_cond_t
8207  fpl__pthread_func_pthread_cond_init *pthread_cond_init;
8208  fpl__pthread_func_pthread_cond_destroy *pthread_cond_destroy;
8209  fpl__pthread_func_pthread_cond_timedwait *pthread_cond_timedwait;
8210  fpl__pthread_func_pthread_cond_wait *pthread_cond_wait;
8211  fpl__pthread_func_pthread_cond_broadcast *pthread_cond_broadcast;
8212  fpl__pthread_func_pthread_cond_signal *pthread_cond_signal;
8213 
8214  // sem_t
8215  fpl__pthread_func_sem_init *sem_init;
8216  fpl__pthread_func_sem_destroy *sem_destroy;
8217  fpl__pthread_func_sem_wait *sem_wait;
8218  fpl__pthread_func_sem_timedwait *sem_timedwait;
8219  fpl__pthread_func_sem_trywait *sem_trywait;
8220  fpl__pthread_func_sem_post *sem_post;
8221  fpl__pthread_func_sem_getvalue *sem_getvalue;
8222 } fpl__PThreadApi;
8223 
8224 #define FPL__POSIX_DL_LOADTYPE RTLD_NOW
8225 
8226 fpl_internal void fpl__PThreadUnloadApi(fpl__PThreadApi *pthreadApi) {
8227  fplAssert(pthreadApi != fpl_null);
8228  if(pthreadApi->libHandle != fpl_null) {
8229  dlclose(pthreadApi->libHandle);
8230  }
8231  fplClearStruct(pthreadApi);
8232 }
8233 
8234 fpl_internal bool fpl__PThreadLoadApi(fpl__PThreadApi *pthreadApi) {
8235  const char *libpthreadFileNames[] = {
8236  "libpthread.so",
8237  "libpthread.so.0",
8238  };
8239  bool result = false;
8240  for(uint32_t index = 0; index < fplArrayCount(libpthreadFileNames); ++index) {
8241  const char *libName = libpthreadFileNames[index];
8242  fplClearStruct(pthreadApi);
8243  do {
8244  void *libHandle = fpl_null;
8245  FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_PTHREAD, libHandle, libName);
8246 
8247  // pthread_t
8248  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_self, pthread_self);
8249  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedparam, pthread_setschedparam);
8250  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_getschedparam, pthread_getschedparam);
8251  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedprio, pthread_setschedprio);
8252 
8253  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_create, pthread_create);
8254  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_kill, pthread_kill);
8255  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_join, pthread_join);
8256  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_exit, pthread_exit);
8257  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_yield, pthread_yield);
8258  FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_timedjoin_np, pthread_timedjoin_np);
8259 
8260  // pthread_attr_t
8261  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_init, pthread_attr_init);
8262  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_getschedparam, pthread_attr_getschedparam);
8263  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedparam, pthread_attr_setschedparam);
8264  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setstacksize, pthread_attr_setstacksize);
8265  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
8266  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
8267 
8268  // pthread_mutex_t
8269  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_init, pthread_mutex_init);
8270  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_destroy, pthread_mutex_destroy);
8271  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_lock, pthread_mutex_lock);
8272  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_trylock, pthread_mutex_trylock);
8273  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_unlock, pthread_mutex_unlock);
8274 
8275  // pthread_cond_t
8276  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_init, pthread_cond_init);
8277  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_destroy, pthread_cond_destroy);
8278  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_timedwait, pthread_cond_timedwait);
8279  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_wait, pthread_cond_wait);
8280  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_broadcast, pthread_cond_broadcast);
8281  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_signal, pthread_cond_signal);
8282 
8283  // sem_t
8284  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_init, sem_init);
8285  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_destroy, sem_destroy);
8286  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_wait, sem_wait);
8287  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_timedwait, sem_timedwait);
8288  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_trywait, sem_trywait);
8289  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_post, sem_post);
8290  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_getvalue, sem_getvalue);
8291 
8292  pthreadApi->libHandle = libHandle;
8293  result = true;
8294  } while(0);
8295  if(result) {
8296  break;
8297  }
8298  fpl__PThreadUnloadApi(pthreadApi);
8299  }
8300  return(result);
8301 }
8302 
8303 typedef struct fpl__PosixInitState {
8304  int dummy;
8305 } fpl__PosixInitState;
8306 
8307 typedef struct fpl__PosixAppState {
8308  fpl__PThreadApi pthreadApi;
8309 } fpl__PosixAppState;
8310 #endif // FPL_SUBPLATFORM_POSIX
8311 
8312 // ############################################################################
8313 //
8314 // > TYPES_LINUX
8315 //
8316 // ############################################################################
8317 #if defined(FPL_PLATFORM_LINUX)
8318 typedef struct fpl__LinuxInitState {
8319  int dummy;
8320 } fpl__LinuxInitState;
8321 
8322 #if defined(FPL__ENABLE_WINDOW)
8323 #define FPL__LINUX_MAX_GAME_CONTROLLER_COUNT 4
8324 typedef struct fpl__LinuxGameController {
8325  char deviceName[512 + 1];
8326  char displayName[FPL_MAX_NAME_LENGTH];
8327  int fd;
8328  uint8_t axisCount;
8329  uint8_t buttonCount;
8330  fplGamepadState state;
8331 } fpl__LinuxGameController;
8332 
8333 typedef struct fpl__LinuxGameControllersState {
8334  fpl__LinuxGameController controllers[FPL__LINUX_MAX_GAME_CONTROLLER_COUNT];
8335  uint64_t lastCheckTime;
8336 } fpl__LinuxGameControllersState;
8337 #endif
8338 
8339 typedef struct fpl__LinuxAppState {
8340 #if defined(FPL__ENABLE_WINDOW)
8341  fpl__LinuxGameControllersState controllersState;
8342 #endif
8343  int dummy;
8344 } fpl__LinuxAppState;
8345 
8346 // Forward declarations
8347 #if defined(FPL__ENABLE_WINDOW)
8348 fpl_internal void fpl__LinuxFreeGameControllers(fpl__LinuxGameControllersState *controllersState);
8349 fpl_internal void fpl__LinuxPollGameControllers(const fplSettings *settings, fpl__LinuxGameControllersState *controllersState, const bool useEvents);
8350 #endif
8351 
8352 #endif // FPL_PLATFORM_LINUX
8353 
8354 // ############################################################################
8355 //
8356 // > TYPES_UNIX
8357 //
8358 // ############################################################################
8359 #if defined(FPL_PLATFORM_UNIX)
8360 typedef struct fpl__UnixInitState {
8361  int dummy;
8362 } fpl__UnixInitState;
8363 
8364 typedef struct fpl__UnixAppState {
8365  int dummy;
8366 } fpl__UnixAppState;
8367 #endif // FPL_PLATFORM_UNIX
8368 
8369 // ############################################################################
8370 //
8371 // > TYPES_X11
8372 //
8373 // ############################################################################
8374 #if defined(FPL_SUBPLATFORM_X11)
8375 
8376 #include <X11/keysym.h> // Keyboard symbols (XK_Escape, etc.)
8377 
8378 //
8379 // X11 Api
8380 //
8381 #define FPL__FUNC_X11_XFree(name) int name(void *data)
8382 typedef FPL__FUNC_X11_XFree(fpl__func_x11_XFree);
8383 #define FPL__FUNC_X11_XFlush(name) int name(Display *display)
8384 typedef FPL__FUNC_X11_XFlush(fpl__func_x11_XFlush);
8385 #define FPL__FUNC_X11_XOpenDisplay(name) Display *name(char *display_name)
8386 typedef FPL__FUNC_X11_XOpenDisplay(fpl__func_x11_XOpenDisplay);
8387 #define FPL__FUNC_X11_XCloseDisplay(name) int name(Display *display)
8388 typedef FPL__FUNC_X11_XCloseDisplay(fpl__func_x11_XCloseDisplay);
8389 #define FPL__FUNC_X11_XDefaultScreen(name) int name(Display *display)
8390 typedef FPL__FUNC_X11_XDefaultScreen(fpl__func_x11_XDefaultScreen);
8391 #define FPL__FUNC_X11_XRootWindow(name) Window name(Display *display, int screen_number)
8392 typedef FPL__FUNC_X11_XRootWindow(fpl__func_x11_XRootWindow);
8393 #define FPL__FUNC_X11_XCreateWindow(name) Window name(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long valuemask, XSetWindowAttributes *attributes)
8394 typedef FPL__FUNC_X11_XCreateWindow(fpl__func_x11_XCreateWindow);
8395 #define FPL__FUNC_X11_XDestroyWindow(name) int name(Display *display, Window w)
8396 typedef FPL__FUNC_X11_XDestroyWindow(fpl__func_x11_XDestroyWindow);
8397 #define FPL__FUNC_X11_XCreateColormap(name) Colormap name(Display *display, Window w, Visual *visual, int alloc)
8398 typedef FPL__FUNC_X11_XCreateColormap(fpl__func_x11_XCreateColormap);
8399 #define FPL__FUNC_X11_XDefaultColormap(name) Colormap name(Display *display, int screen_number)
8400 typedef FPL__FUNC_X11_XDefaultColormap(fpl__func_x11_XDefaultColormap);
8401 #define FPL__FUNC_X11_XFreeColormap(name) int name(Display *display, Colormap colormap)
8402 typedef FPL__FUNC_X11_XFreeColormap(fpl__func_x11_XFreeColormap);
8403 #define FPL__FUNC_X11_XMapWindow(name) int name(Display *display, Window w)
8404 typedef FPL__FUNC_X11_XMapWindow(fpl__func_x11_XMapWindow);
8405 #define FPL__FUNC_X11_XUnmapWindow(name) int name(Display *display, Window w)
8406 typedef FPL__FUNC_X11_XUnmapWindow(fpl__func_x11_XUnmapWindow);
8407 #define FPL__FUNC_X11_XStoreName(name) int name(Display *display, Window w, _Xconst char *window_name)
8408 typedef FPL__FUNC_X11_XStoreName(fpl__func_x11_XStoreName);
8409 #define FPL__FUNC_X11_XDefaultVisual(name) Visual *name(Display *display, int screen_number)
8410 typedef FPL__FUNC_X11_XDefaultVisual(fpl__func_x11_XDefaultVisual);
8411 #define FPL__FUNC_X11_XDefaultDepth(name) int name(Display *display, int screen_number)
8412 typedef FPL__FUNC_X11_XDefaultDepth(fpl__func_x11_XDefaultDepth);
8413 #define FPL__FUNC_X11_XInternAtom(name) Atom name(Display *display, const char *atom_name, Bool only_if_exists)
8414 typedef FPL__FUNC_X11_XInternAtom(fpl__func_x11_XInternAtom);
8415 #define FPL__FUNC_X11_XSetWMProtocols(name) Status name(Display *display, Window w, Atom *protocols, int count)
8416 typedef FPL__FUNC_X11_XSetWMProtocols(fpl__func_x11_XSetWMProtocols);
8417 #define FPL__FUNC_X11_XPending(name) int name(Display *display)
8418 typedef FPL__FUNC_X11_XPending(fpl__func_x11_XPending);
8419 #define FPL__FUNC_X11_XSync(name) int name(Display *display, Bool discard)
8420 typedef FPL__FUNC_X11_XSync(fpl__func_x11_XSync);
8421 #define FPL__FUNC_X11_XNextEvent(name) int name(Display *display, XEvent *event_return)
8422 typedef FPL__FUNC_X11_XNextEvent(fpl__func_x11_XNextEvent);
8423 #define FPL__FUNC_X11_XPeekEvent(name) int name(Display *display, XEvent *event_return)
8424 typedef FPL__FUNC_X11_XPeekEvent(fpl__func_x11_XPeekEvent);
8425 #define FPL__FUNC_X11_XEventsQueued(name) int name(Display *display, int mode)
8426 typedef FPL__FUNC_X11_XEventsQueued(fpl__func_x11_XEventsQueued);
8427 #define FPL__FUNC_X11_XGetWindowAttributes(name) Status name(Display *display, Window w, XWindowAttributes *window_attributes_return)
8428 typedef FPL__FUNC_X11_XGetWindowAttributes(fpl__func_x11_XGetWindowAttributes);
8429 #define FPL__FUNC_X11_XResizeWindow(name) int name(Display *display, Window w, unsigned int width, unsigned int height)
8430 typedef FPL__FUNC_X11_XResizeWindow(fpl__func_x11_XResizeWindow);
8431 #define FPL__FUNC_X11_XMoveWindow(name) int name(Display *display, Window w, int x, int y)
8432 typedef FPL__FUNC_X11_XMoveWindow(fpl__func_x11_XMoveWindow);
8433 #define FPL__FUNC_X11_XGetKeyboardMapping(name) KeySym *name(Display *display, KeyCode first_keycode, int keycode_count, int *keysyms_per_keycode_return)
8434 typedef FPL__FUNC_X11_XGetKeyboardMapping(fpl__func_x11_XGetKeyboardMapping);
8435 #define FPL__FUNC_X11_XLookupString(name) int name(XKeyEvent* event_struct, char* buffer_return, int bytes_buffer, KeySym* keysym_return, XComposeStatus* status_in_out)
8436 typedef FPL__FUNC_X11_XLookupString(fpl__func_x11_XLookupString);
8437 #define FPL__FUNC_X11_XSendEvent(name) Status name(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
8438 typedef FPL__FUNC_X11_XSendEvent(fpl__func_x11_XSendEvent);
8439 #define FPL__FUNC_X11_XMatchVisualInfo(name) Status name(Display* display, int screen, int depth, int clazz, XVisualInfo* vinfo_return)
8440 typedef FPL__FUNC_X11_XMatchVisualInfo(fpl__func_x11_XMatchVisualInfo);
8441 #define FPL__FUNC_X11_XCreateGC(name) GC name(Display* display, Drawable d, unsigned long valuemask, XGCValues* values)
8442 typedef FPL__FUNC_X11_XCreateGC(fpl__func_x11_XCreateGC);
8443 #define FPL__FUNC_X11_XGetImage(name) XImage *name(Display* display, Drawable d, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format)
8444 typedef FPL__FUNC_X11_XGetImage(fpl__func_x11_XGetImage);
8445 #define FPL__FUNC_X11_XCreateImage(name) XImage *name(Display *display, Visual *visual, unsigned int depth, int format, int offset, char *data, unsigned int width, unsigned int height, int bitmap_pad, int bytes_per_line)
8446 typedef FPL__FUNC_X11_XCreateImage(fpl__func_x11_XCreateImage);
8447 #define FPL__FUNC_X11_XPutImage(name) int name(Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
8448 typedef FPL__FUNC_X11_XPutImage(fpl__func_x11_XPutImage);
8449 #define FPL__FUNC_X11_XMapRaised(name) int name(Display *display, Window w)
8450 typedef FPL__FUNC_X11_XMapRaised(fpl__func_x11_XMapRaised);
8451 #define FPL__FUNC_X11_XCreatePixmap(name) Pixmap name(Display * display, Drawable d, unsigned int width, unsigned int height, unsigned int depth)
8452 typedef FPL__FUNC_X11_XCreatePixmap(fpl__func_x11_XCreatePixmap);
8453 #define FPL__FUNC_X11_XSelectInput(name) int name(Display * display, Window w, long eventMask)
8454 typedef FPL__FUNC_X11_XSelectInput(fpl__func_x11_XSelectInput);
8455 #define FPL__FUNC_X11_XGetWindowProperty(name) int name(Display* display, Window w, Atom prop, long long_offset, long long_length, Bool del, Atom req_type, Atom* actual_type_return, int* actual_format_return, unsigned long* nitems_return, unsigned long* bytes_after_return, unsigned char** prop_return)
8456 typedef FPL__FUNC_X11_XGetWindowProperty(fpl__func_x11_XGetWindowProperty);
8457 #define FPL__FUNC_X11_XChangeProperty(name) int name(Display* display, Window w, Atom property, Atom type, int format, int mode, _Xconst unsigned char* data, int nelements)
8458 typedef FPL__FUNC_X11_XChangeProperty(fpl__func_x11_XChangeProperty);
8459 #define FPL__FUNC_X11_XDeleteProperty(name) int name(Display* display, Window w,Atom prop)
8460 typedef FPL__FUNC_X11_XDeleteProperty(fpl__func_x11_XDeleteProperty);
8461 #define FPL__FUNC_X11_XStringListToTextProperty(name) Status name(char** list, int count, XTextProperty* text_prop_return)
8462 typedef FPL__FUNC_X11_XStringListToTextProperty(fpl__func_x11_XStringListToTextProperty);
8463 #define FPL__FUNC_X11_XSetWMIconName(name) void name(Display* display, Window w, XTextProperty *text_prop)
8464 typedef FPL__FUNC_X11_XSetWMIconName(fpl__func_x11_XSetWMIconName);
8465 #define FPL__FUNC_X11_XSetWMName(name) void name(Display* display, Window w, XTextProperty *text_prop)
8466 typedef FPL__FUNC_X11_XSetWMName(fpl__func_x11_XSetWMName);
8467 #define FPL__FUNC_X11_XQueryKeymap(name) int name(Display* display, char [32])
8468 typedef FPL__FUNC_X11_XQueryKeymap(fpl__func_x11_XQueryKeymap);
8469 #define FPL__FUNC_X11_XQueryPointer(name) Bool name(Display* display, Window w, Window* root_return, Window* child_return, int* root_x_return, int* root_y_return, int* win_x_return, int* win_y_return, unsigned int* mask_return)
8470 typedef FPL__FUNC_X11_XQueryPointer(fpl__func_x11_XQueryPointer);
8471 #define FPL__FUNC_X11_XConvertSelection(name) int name(Display *display, Atom selection, Atom target, Atom property, Window requestor, Time time)
8472 typedef FPL__FUNC_X11_XConvertSelection(fpl__func_x11_XConvertSelection);
8473 #define FPL__FUNC_X11_XInitThreads(name) Status name(void)
8474 typedef FPL__FUNC_X11_XInitThreads(fpl__func_x11_XInitThreads);
8475 #define FPL__FUNC_X11_XSetErrorHandler(name) XErrorHandler name(XErrorHandler *handler)
8476 typedef FPL__FUNC_X11_XSetErrorHandler(fpl__func_x11_XSetErrorHandler);
8477 
8478 typedef struct fpl__X11Api {
8479  void *libHandle;
8480  fpl__func_x11_XFlush *XFlush;
8481  fpl__func_x11_XFree *XFree;
8482  fpl__func_x11_XOpenDisplay *XOpenDisplay;
8483  fpl__func_x11_XCloseDisplay *XCloseDisplay;
8484  fpl__func_x11_XDefaultScreen *XDefaultScreen;
8485  fpl__func_x11_XRootWindow *XRootWindow;
8486  fpl__func_x11_XCreateWindow *XCreateWindow;
8487  fpl__func_x11_XDestroyWindow *XDestroyWindow;
8488  fpl__func_x11_XCreateColormap *XCreateColormap;
8489  fpl__func_x11_XFreeColormap *XFreeColormap;
8490  fpl__func_x11_XDefaultColormap *XDefaultColormap;
8491  fpl__func_x11_XMapWindow *XMapWindow;
8492  fpl__func_x11_XUnmapWindow *XUnmapWindow;
8493  fpl__func_x11_XStoreName *XStoreName;
8494  fpl__func_x11_XDefaultVisual *XDefaultVisual;
8495  fpl__func_x11_XDefaultDepth *XDefaultDepth;
8496  fpl__func_x11_XInternAtom *XInternAtom;
8497  fpl__func_x11_XSetWMProtocols *XSetWMProtocols;
8498  fpl__func_x11_XPending *XPending;
8499  fpl__func_x11_XSync *XSync;
8500  fpl__func_x11_XNextEvent *XNextEvent;
8501  fpl__func_x11_XPeekEvent *XPeekEvent;
8502  fpl__func_x11_XEventsQueued *XEventsQueued;
8503  fpl__func_x11_XGetWindowAttributes *XGetWindowAttributes;
8504  fpl__func_x11_XResizeWindow *XResizeWindow;
8505  fpl__func_x11_XMoveWindow *XMoveWindow;
8506  fpl__func_x11_XGetKeyboardMapping *XGetKeyboardMapping;
8507  fpl__func_x11_XLookupString *XLookupString;
8508  fpl__func_x11_XSendEvent *XSendEvent;
8509  fpl__func_x11_XMatchVisualInfo *XMatchVisualInfo;
8510  fpl__func_x11_XCreateGC *XCreateGC;
8511  fpl__func_x11_XGetImage *XGetImage;
8512  fpl__func_x11_XPutImage *XPutImage;
8513  fpl__func_x11_XMapRaised *XMapRaised;
8514  fpl__func_x11_XCreateImage *XCreateImage;
8515  fpl__func_x11_XCreatePixmap *XCreatePixmap;
8516  fpl__func_x11_XSelectInput *XSelectInput;
8517  fpl__func_x11_XGetWindowProperty *XGetWindowProperty;
8518  fpl__func_x11_XChangeProperty *XChangeProperty;
8519  fpl__func_x11_XDeleteProperty *XDeleteProperty;
8520  fpl__func_x11_XStringListToTextProperty *XStringListToTextProperty;
8521  fpl__func_x11_XSetWMIconName *XSetWMIconName;
8522  fpl__func_x11_XSetWMName *XSetWMName;
8523  fpl__func_x11_XQueryKeymap *XQueryKeymap;
8524  fpl__func_x11_XQueryPointer *XQueryPointer;
8525  fpl__func_x11_XConvertSelection *XConvertSelection;
8526  fpl__func_x11_XInitThreads *XInitThreads;
8527  fpl__func_x11_XSetErrorHandler *XSetErrorHandler;
8528 } fpl__X11Api;
8529 
8530 fpl_internal void fpl__UnloadX11Api(fpl__X11Api *x11Api) {
8531  fplAssert(x11Api != fpl_null);
8532  if(x11Api->libHandle != fpl_null) {
8533  dlclose(x11Api->libHandle);
8534  }
8535  fplClearStruct(x11Api);
8536 }
8537 
8538 fpl_internal bool fpl__LoadX11Api(fpl__X11Api *x11Api) {
8539  fplAssert(x11Api != fpl_null);
8540  const char *libFileNames[] = {
8541  "libX11.so",
8542  "libX11.so.7",
8543  "libX11.so.6",
8544  "libX11.so.5",
8545  };
8546  bool result = false;
8547  for(uint32_t index = 0; index < fplArrayCount(libFileNames); ++index) {
8548  const char *libName = libFileNames[index];
8549  fplClearStruct(x11Api);
8550  do {
8551  void *libHandle = fpl_null;
8552  FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_X11, libHandle, libName);
8553  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFlush, XFlush);
8554  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFree, XFree);
8555  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XOpenDisplay, XOpenDisplay);
8556  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCloseDisplay, XCloseDisplay);
8557  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultScreen, XDefaultScreen);
8558  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XRootWindow, XRootWindow);
8559  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateWindow, XCreateWindow);
8560  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDestroyWindow, XDestroyWindow);
8561  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateColormap, XCreateColormap);
8562  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFreeColormap, XFreeColormap);
8563  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultColormap, XDefaultColormap);
8564  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapWindow, XMapWindow);
8565  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XUnmapWindow, XUnmapWindow);
8566  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStoreName, XStoreName);
8567  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultVisual, XDefaultVisual);
8568  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultDepth, XDefaultDepth);
8569  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInternAtom, XInternAtom);
8570  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMProtocols, XSetWMProtocols);
8571  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPending, XPending);
8572  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSync, XSync);
8573  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XNextEvent, XNextEvent);
8574  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPeekEvent, XPeekEvent);
8575  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XEventsQueued, XEventsQueued);
8576  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowAttributes, XGetWindowAttributes);
8577  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XResizeWindow, XResizeWindow);
8578  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMoveWindow, XMoveWindow);
8579  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetKeyboardMapping, XGetKeyboardMapping);
8580  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XLookupString, XLookupString);
8581  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSendEvent, XSendEvent);
8582  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMatchVisualInfo, XMatchVisualInfo);
8583  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateGC, XCreateGC);
8584  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetImage, XGetImage);
8585  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPutImage, XPutImage);
8586  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapRaised, XMapRaised);
8587  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateImage, XCreateImage);
8588  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreatePixmap, XCreatePixmap);
8589  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSelectInput, XSelectInput);
8590  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowProperty, XGetWindowProperty);
8591  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XChangeProperty, XChangeProperty);
8592  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDeleteProperty, XDeleteProperty);
8593  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStringListToTextProperty, XStringListToTextProperty);
8594  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMIconName, XSetWMIconName);
8595  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMName, XSetWMName);
8596  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryKeymap, XQueryKeymap);
8597  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryPointer, XQueryPointer);
8598  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XConvertSelection, XConvertSelection);
8599  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInitThreads, XInitThreads);
8600  FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetErrorHandler, XSetErrorHandler);
8601  x11Api->libHandle = libHandle;
8602  result = true;
8603  } while(0);
8604  if(result) {
8605  break;
8606  }
8607  fpl__UnloadX11Api(x11Api);
8608  }
8609  return(result);
8610 }
8611 
8612 typedef struct fpl__X11SubplatformState {
8613  fpl__X11Api api;
8614 } fpl__X11SubplatformState;
8615 
8616 typedef struct fpl__X11WindowStateInfo {
8617  fplWindowState state;
8618  fplWindowVisibilityState visibility;
8619  fplWindowPosition position;
8620  fplWindowSize size;
8621 } fpl__X11WindowStateInfo;
8622 
8623 typedef struct fpl__X11Xdnd {
8624  int version;
8625  Window source;
8626  Atom format;
8627 } fpl__X11Xdnd;
8628 
8629 #define FPL__FUNC_X11_ErrorHandlerCallback(name) int name(Display *display, XErrorEvent *ev)
8630 typedef FPL__FUNC_X11_ErrorHandlerCallback(fpl__func_X11ErrorHandlerCallback);
8631 
8632 typedef struct fpl__X11WindowState {
8633  fpl__X11WindowStateInfo lastWindowStateInfo;
8634  Colormap colorMap;
8635  Display *display;
8636  fpl__func_X11ErrorHandlerCallback *lastErrorHandler;
8637  fpl__X11Xdnd xdnd;
8638  Window root;
8639  Window window;
8640  Visual *visual;
8641  Atom wmProtocols;
8642  Atom wmDeleteWindow;
8643  Atom wmState;
8644  Atom netWMPing;
8645  Atom netWMState;
8646  Atom netWMStateFocused;
8647  Atom netWMStateFullscreen;
8648  Atom netWMStateHidden;
8649  Atom netWMStateMaximizedVert;
8650  Atom netWMStateMaximizedHorz;
8651  Atom netWMPid;
8652  Atom netWMIcon;
8653  Atom netWMName;
8654  Atom netWMIconName;
8655  Atom utf8String;
8656  Atom motifWMHints;
8657  // drag and drop
8658  Atom xdndAware;
8659  Atom xdndEnter;
8660  Atom xdndPosition;
8661  Atom xdndStatus;
8662  Atom xdndActionCopy;
8663  Atom xdndDrop;
8664  Atom xdndFinished;
8665  Atom xdndSelection;
8666  Atom xdndTypeList;
8667  Atom textUriList;
8668  int screen;
8669  int colorDepth;
8670 } fpl__X11WindowState;
8671 
8672 #define FPL__XDND_VERSION 5
8673 
8674 #endif // FPL_SUBPLATFORM_X11
8675 
8676 // ****************************************************************************
8677 //
8678 // > PLATFORM_STATES
8679 //
8680 // - Defines the final PlatformInitState and PlatformAppState
8681 // - Declares all required global variables
8682 //
8683 // ****************************************************************************
8684 #if !defined(FPL__PLATFORM_STATES_DEFINED)
8685 #define FPL__PLATFORM_STATES_DEFINED
8686 //
8687 // Platform initialization state
8688 //
8689 typedef struct fpl__PlatformInitSettings {
8690  fplMemorySettings memorySettings;
8691 } fpl__PlatformInitSettings;
8692 
8693 typedef struct fpl__PlatformInitState {
8694 #if defined(FPL_SUBPLATFORM_POSIX)
8695  fpl__PosixInitState posix;
8696 #endif
8697 
8698  fpl__PlatformInitSettings initSettings;
8699  fplPlatformResultType initResult;
8700  fpl_b32 isInitialized;
8701 
8702  union {
8703 # if defined(FPL_PLATFORM_WINDOWS)
8704  fpl__Win32InitState win32;
8705 # elif defined(FPL_PLATFORM_LINUX)
8706  fpl__LinuxInitState plinux;
8707 # elif defined(FPL_PLATFORM_UNIX)
8708  fpl__UnixInitState punix;
8709 # endif
8710  };
8711 } fpl__PlatformInitState;
8712 fpl_globalvar fpl__PlatformInitState fpl__global__InitState = fplZeroInit;
8713 
8714 #if defined(FPL__ENABLE_WINDOW)
8715 #define FPL__MAX_EVENT_COUNT 32768
8716 typedef struct fpl__EventQueue {
8717  // @FIXME(final): Internal events are not Thread-Safe!
8718  fplEvent events[FPL__MAX_EVENT_COUNT];
8719  uint32_t pollIndex;
8720  uint32_t pushCount;
8721 } fpl__EventQueue;
8722 
8723 typedef struct fpl__PlatformWindowState {
8724  fpl__EventQueue eventQueue;
8725  fplKey keyMap[256];
8726  fplButtonState keyStates[256];
8727  uint64_t keyPressTimes[256];
8728  fplButtonState mouseStates[5];
8729  fpl_b32 isRunning;
8730 
8731 #if defined(FPL_PLATFORM_WINDOWS)
8732  fpl__Win32WindowState win32;
8733 #endif
8734 #if defined(FPL_SUBPLATFORM_X11)
8735  fpl__X11WindowState x11;
8736 #endif
8737 } fpl__PlatformWindowState;
8738 #endif // FPL__ENABLE_WINDOW
8739 
8740 #if defined(FPL__ENABLE_VIDEO)
8741 typedef struct fpl__PlatformVideoState {
8742  void *mem; // Points to fpl__VideoState
8743  size_t memSize;
8744 } fpl__PlatformVideoState;
8745 #endif // FPL__ENABLE_VIDEO
8746 
8747 #if defined(FPL__ENABLE_AUDIO)
8748 typedef struct fpl__PlatformAudioState {
8749  void *mem; // Points to fpl__AudioState
8750  size_t memSize;
8751 } fpl__PlatformAudioState;
8752 #endif
8753 
8754 //
8755 // Platform application state
8756 //
8757 typedef struct fpl__PlatformAppState fpl__PlatformAppState;
8758 struct fpl__PlatformAppState {
8759  // Subplatforms
8760 #if defined(FPL_SUBPLATFORM_POSIX)
8761  fpl__PosixAppState posix;
8762 #endif
8763 #if defined(FPL_SUBPLATFORM_X11)
8764  fpl__X11SubplatformState x11;
8765 #endif
8766 
8767  // Window/video/audio
8768 #if defined(FPL__ENABLE_WINDOW)
8769  fpl__PlatformWindowState window;
8770 #endif
8771 #if defined(FPL__ENABLE_VIDEO)
8772  fpl__PlatformVideoState video;
8773 #endif
8774 #if defined(FPL__ENABLE_AUDIO)
8775  fpl__PlatformAudioState audio;
8776 #endif
8777 
8778  // Settings
8779  fplSettings initSettings;
8780  fplSettings currentSettings;
8781  fplInitFlags initFlags;
8782 
8783  // Platforms
8784  union {
8785 # if defined(FPL_PLATFORM_WINDOWS)
8786  fpl__Win32AppState win32;
8787 # elif defined(FPL_PLATFORM_LINUX)
8788  fpl__LinuxAppState plinux;
8789 # elif defined(FPL_PLATFORM_UNIX)
8790  fpl__UnixAppState plinux;
8791 # endif
8792  };
8793 };
8794 
8795 //
8796 // Internal window
8797 //
8798 #if defined(FPL__ENABLE_WINDOW)
8799 fpl_internal fplKey fpl__GetMappedKey(const fpl__PlatformWindowState *windowState, const uint64_t keyCode) {
8800  fplKey result;
8801  if(keyCode < fplArrayCount(windowState->keyMap))
8802  result = windowState->keyMap[keyCode];
8803  else
8804  result = fplKey_None;
8805  return(result);
8806 }
8807 
8808 fpl_internal void fpl__ClearInternalEvents() {
8809  fpl__PlatformAppState *appState = fpl__global__AppState;
8810  fplAssert(appState != fpl_null);
8811  fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8812  // @FIXME(final): Internal events are not thread-safe, introduce a proper thread-safe queue here!
8813  uint32_t eventCount = eventQueue->pollIndex;
8814  eventQueue->pollIndex = 0;
8815  for(size_t eventIndex = 0; eventIndex < eventCount; ++eventIndex) {
8816  fplEvent *ev = &eventQueue->events[eventIndex];
8818  fpl__ReleaseDynamicMemory(ev->window.dropFiles.internalMemory.base);
8820  }
8821  }
8822  eventQueue->pushCount = 0;
8823 }
8824 
8825 fpl_internal bool fpl__PollInternalEvent(fplEvent *ev) {
8826  fpl__PlatformAppState *appState = fpl__global__AppState;
8827  bool result = false;
8828  if(appState != fpl_null) {
8829  fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8830  // @FIXME(final): Internal events are not thread-safe, introduce a proper thread-safe queue here!
8831  if(eventQueue->pollIndex < eventQueue->pushCount) {
8832  uint32_t eventIndex = eventQueue->pollIndex++;
8833  *ev = eventQueue->events[eventIndex];
8834  result = true;
8835  } else if(eventQueue->pushCount > 0) {
8836  eventQueue->pollIndex = 0;
8837  eventQueue->pushCount = 0;
8838  }
8839  }
8840  return(result);
8841 }
8842 
8843 fpl_internal void fpl__PushInternalEvent(const fplEvent *event) {
8844  fpl__PlatformAppState *appState = fpl__global__AppState;
8845  fplAssert(appState != fpl_null);
8846  fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8847  // @FIXME(final): Internal events are not thread-safe, introduce a proper thread-safe queue here!
8848  if(eventQueue->pushCount < FPL__MAX_EVENT_COUNT) {
8849  uint32_t eventIndex = eventQueue->pushCount++;
8850  eventQueue->events[eventIndex] = *event;
8851  }
8852 }
8853 
8854 fpl_internal void fpl__PushWindowStateEvent(const fplWindowEventType windowType) {
8855  fplEvent newEvent = fplZeroInit;
8856  newEvent.type = fplEventType_Window;
8857  newEvent.window.type = windowType;
8858  fpl__PushInternalEvent(&newEvent);
8859 }
8860 
8861 fpl_internal void fpl__PushWindowSizeEvent(const fplWindowEventType windowType, uint32_t w, uint32_t h) {
8862  fplEvent newEvent = fplZeroInit;
8863  newEvent.type = fplEventType_Window;
8864  newEvent.window.type = windowType;
8865  newEvent.window.size.width = w;
8866  newEvent.window.size.height = h;
8867  fpl__PushInternalEvent(&newEvent);
8868 }
8869 
8870 fpl_internal void fpl__PushWindowPositionEvent(const fplWindowEventType windowType, int32_t x, int32_t y) {
8871  fplEvent newEvent = fplZeroInit;
8872  newEvent.type = fplEventType_Window;
8873  newEvent.window.type = windowType;
8874  newEvent.window.position.left = x;
8875  newEvent.window.position.top = y;
8876  fpl__PushInternalEvent(&newEvent);
8877 }
8878 
8879 fpl_internal void fpl__PushWindowDropFilesEvent(const char *filePath, const size_t fileCount, const char **files, const fplMemoryBlock *memory) {
8880  fplEvent newEvent = fplZeroInit;
8881  newEvent.type = fplEventType_Window;
8883  newEvent.window.dropFiles.fileCount = fileCount;
8884  newEvent.window.dropFiles.files = files;
8885  newEvent.window.dropFiles.internalMemory = *memory;
8886  fpl__PushInternalEvent(&newEvent);
8887 }
8888 
8889 fpl_internal void fpl__PushKeyboardButtonEvent(const uint64_t keyCode, const fplKey mappedKey, const fplKeyboardModifierFlags modifiers, const fplButtonState buttonState) {
8890  fplEvent newEvent = fplZeroInit;
8891  newEvent.type = fplEventType_Keyboard;
8893  newEvent.keyboard.keyCode = keyCode;
8894  newEvent.keyboard.modifiers = modifiers;
8895  newEvent.keyboard.buttonState = buttonState;
8896  newEvent.keyboard.mappedKey = mappedKey;
8897  fpl__PushInternalEvent(&newEvent);
8898 }
8899 
8900 fpl_internal void fpl__PushKeyboardInputEvent(const uint32_t textCode, const fplKey mappedKey) {
8901  fplEvent newEvent = fplZeroInit;
8902  newEvent.type = fplEventType_Keyboard;
8904  newEvent.keyboard.keyCode = (uint64_t)textCode;
8905  newEvent.keyboard.mappedKey = mappedKey;
8906  fpl__PushInternalEvent(&newEvent);
8907 }
8908 
8909 fpl_internal void fpl__PushMouseButtonEvent(const int32_t x, const int32_t y, const fplMouseButtonType mouseButton, const fplButtonState buttonState) {
8910  fplEvent newEvent = fplZeroInit;
8911  newEvent.type = fplEventType_Mouse;
8912  newEvent.mouse.type = fplMouseEventType_Button;
8913  newEvent.mouse.mouseX = x;
8914  newEvent.mouse.mouseY = y;
8915  newEvent.mouse.mouseButton = mouseButton;
8916  newEvent.mouse.buttonState = buttonState;
8917  fpl__PushInternalEvent(&newEvent);
8918 }
8919 
8920 fpl_internal void fpl__PushMouseWheelEvent(const int32_t x, const int32_t y, const float wheelDelta) {
8921  fplEvent newEvent = fplZeroInit;
8922  newEvent.type = fplEventType_Mouse;
8923  newEvent.mouse.type = fplMouseEventType_Wheel;
8925  newEvent.mouse.mouseX = x;
8926  newEvent.mouse.mouseY = y;
8927  newEvent.mouse.wheelDelta = wheelDelta;
8928  fpl__PushInternalEvent(&newEvent);
8929 }
8930 
8931 fpl_internal void fpl__PushMouseMoveEvent(const int32_t x, const int32_t y) {
8932  fplEvent newEvent = fplZeroInit;
8933  newEvent.type = fplEventType_Mouse;
8934  newEvent.mouse.type = fplMouseEventType_Move;
8936  newEvent.mouse.mouseX = x;
8937  newEvent.mouse.mouseY = y;
8938  fpl__PushInternalEvent(&newEvent);
8939 }
8940 
8941 fpl_internal void fpl__HandleKeyboardButtonEvent(fpl__PlatformWindowState *windowState, const uint64_t time, const uint64_t keyCode, const fplKeyboardModifierFlags modifiers, const fplButtonState buttonState, const bool force) {
8942 #if defined(FPL_LOG_KEY_EVENTS)
8943  const char *buttonStateName = "";
8944  if(buttonState == fplButtonState_Press)
8945  buttonStateName = "Press";
8946  else if(buttonState == fplButtonState_Repeat)
8947  buttonStateName = "Repeat";
8948  else
8949  buttonStateName = "Released";
8950  FPL_LOG_INFO(FPL__MODULE_OS, "[%llu] Keyboard button event with keycode: '%llu', state: '%s'", time, keyCode, buttonStateName);
8951 #endif
8952 
8953  fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
8954  bool repeat = false;
8955  if(force) {
8956  repeat = (buttonState == fplButtonState_Repeat);
8957  windowState->keyStates[keyCode] = buttonState;
8958  } else {
8959  if(keyCode < fplArrayCount(windowState->keyStates)) {
8960  if((buttonState == fplButtonState_Release) && (windowState->keyStates[keyCode] == fplButtonState_Release)) {
8961  return;
8962  }
8963  if((buttonState == fplButtonState_Press) && (windowState->keyStates[keyCode] >= fplButtonState_Press)) {
8964  repeat = true;
8965  }
8966  windowState->keyStates[keyCode] = buttonState;
8967  }
8968  }
8969  fpl__PushKeyboardButtonEvent(keyCode, mappedKey, modifiers, repeat ? fplButtonState_Repeat : buttonState);
8970 }
8971 
8972 fpl_internal void fpl__HandleKeyboardInputEvent(fpl__PlatformWindowState *windowState, const uint64_t keyCode, const uint32_t textCode) {
8973  fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
8974  fpl__PushKeyboardInputEvent(textCode, mappedKey);
8975 }
8976 
8977 fpl_internal void fpl__HandleMouseButtonEvent(fpl__PlatformWindowState *windowState, const int32_t x, const int32_t y, const fplMouseButtonType mouseButton, const fplButtonState buttonState) {
8978  if(mouseButton < fplArrayCount(windowState->mouseStates)) {
8979  windowState->mouseStates[(int)mouseButton] = buttonState;
8980  }
8981  fpl__PushMouseButtonEvent(x, y, mouseButton, buttonState);
8982 }
8983 
8984 fpl_internal void fpl__HandleMouseMoveEvent(fpl__PlatformWindowState *windowState, const int32_t x, const int32_t y) {
8985  fpl__PushMouseMoveEvent(x, y);
8986 }
8987 
8988 fpl_internal void fpl__HandleMouseWheelEvent(fpl__PlatformWindowState *windowState, const int32_t x, const int32_t y, const float wheelDelta) {
8989  fpl__PushMouseWheelEvent(x, y, wheelDelta);
8990 }
8991 
8992 // @NOTE(final): Callback used for setup a window before it is created
8993 #define FPL__FUNC_PREPARE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
8994 typedef FPL__FUNC_PREPARE_VIDEO_WINDOW(callback_PreSetupWindow);
8995 
8996 // @NOTE(final): Callback used for setup a window after it was created
8997 #define FPL__FUNC_FINALIZE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
8998 typedef FPL__FUNC_FINALIZE_VIDEO_WINDOW(callback_PostSetupWindow);
8999 
9000 typedef struct fpl__SetupWindowCallbacks {
9001  callback_PreSetupWindow *preSetup;
9002  callback_PostSetupWindow *postSetup;
9003 } fpl__SetupWindowCallbacks;
9004 #endif // FPL__ENABLE_WINDOW
9005 
9006 #endif // FPL__PLATFORM_STATES_DEFINED
9007 
9008 // ****************************************************************************
9009 //
9010 // > COMMON (Common Implementations)
9011 //
9012 // - Standard C library includes
9013 // - Internal macros
9014 // - Error state handling
9015 // - Threading state handling
9016 // - CommonAudioState
9017 // - Common Implementations (Strings, Memory, Atomics, Path, etc.)
9018 //
9019 // ****************************************************************************
9020 #if !defined(FPL__COMMON_DEFINED)
9021 #define FPL__COMMON_DEFINED
9022 
9023 //
9024 // Internal memory
9025 //
9026 fpl_internal void *fpl__AllocateDynamicMemory(const size_t size, const size_t alignment) {
9027  void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, size, alignment);
9028  return(result);
9029 }
9030 
9031 fpl_internal void fpl__ReleaseDynamicMemory(void *ptr) {
9032  fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, ptr);
9033 }
9034 
9035 fpl_internal void *fpl__AllocateTemporaryMemory(const size_t size, const size_t alignment) {
9036  void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, size, alignment);
9037  return(result);
9038 }
9039 
9040 fpl_internal void fpl__ReleaseTemporaryMemory(void *ptr) {
9041  fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, ptr);
9042 }
9043 
9044 //
9045 // Audio constants
9046 //
9047 static const uint32_t FPL__DEFAULT_AUDIO_SAMPLERATE = 44100;
9048 static const fplAudioFormatType FPL__DEFAULT_AUDIO_FORMAT = fplAudioFormatType_S16;
9049 static const uint32_t FPL__DEFAULT_AUDIO_CHANNELS = 2;
9050 static const uint32_t FPL__DEFAULT_AUDIO_PERIODS = 3;
9051 static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_LOWLATENCY_IN_MSECS = 10;
9052 static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_CONSERVATIVE_IN_MSECS = 25;
9053 
9054 //
9055 // Internal types and functions
9056 //
9057 #define FPL__MAX_LAST_ERROR_STRING_LENGTH 256
9058 #define FPL__MAX_ERRORSTATE_COUNT 256
9059 
9060 typedef struct fpl__ErrorState {
9061  char errors[FPL__MAX_ERRORSTATE_COUNT][FPL__MAX_LAST_ERROR_STRING_LENGTH];
9062  uint32_t count;
9063 } fpl__ErrorState;
9064 
9065 fpl_globalvar fpl__ErrorState fpl__global__LastErrorState = fplZeroInit;
9066 
9067 fpl_internal void fpl__PushError_Formatted(const char *funcName, const int lineNumber, const fplLogLevel level, const char *format, va_list argList) {
9068  fplAssert(format != fpl_null);
9069 
9070  if(level <= fplLogLevel_Error) {
9071  fpl__ErrorState *state = &fpl__global__LastErrorState;
9072  char buffer[FPL__MAX_LAST_ERROR_STRING_LENGTH] = fplZeroInit;
9073  fplFormatStringArgs(buffer, fplArrayCount(buffer), format, argList);
9074  size_t messageLen = fplGetStringLength(buffer);
9075  fplAssert(state->count < FPL__MAX_ERRORSTATE_COUNT);
9076  size_t errorIndex = state->count;
9077  state->count = (state->count + 1) % FPL__MAX_ERRORSTATE_COUNT;
9078  fplCopyStringLen(buffer, messageLen, state->errors[errorIndex], FPL__MAX_LAST_ERROR_STRING_LENGTH);
9079  }
9080 
9081 #if defined(FPL__ENABLE_LOGGING)
9082  va_list listCopy;
9083  va_copy(listCopy, argList);
9084  fpl__LogWriteArgs(funcName, lineNumber, level, format, listCopy);
9085  va_end(listCopy);
9086 #endif
9087 }
9088 
9089 fpl_internal void fpl__HandleError(const char *funcName, const int lineNumber, const fplLogLevel level, const char *format, ...) {
9090  va_list valist;
9091  va_start(valist, format);
9092  fpl__PushError_Formatted(funcName, lineNumber, level, format, valist);
9093  va_end(valist);
9094 
9095 #if defined(FPL_CRASH_ON_ERROR) || defined(FPL_CRASH_ON_WARNING)
9096  fplLogLevel minErrorLevel = fplLogLevel_Error;
9097 # if defined(FPL_CRASH_ON_WARNING)
9098  minErrorLevel = fplLogLevel_Warning;
9099 # endif
9100  if(level >= minErrorLevel) {
9101  // @NOTE(final): Force a null pointer assignment crash here
9102  *(int *)0 = 0;
9103  }
9104 #endif
9105 }
9106 
9107 //
9108 // Argument Errors
9109 //
9110 
9111 //
9112 
9113 
9114 fpl_internal void fpl__ArgumentInvalidError(const char *funcName, const int line, const char *paramName) {
9115  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter are not valid", paramName);
9116 }
9117 fpl_internal void fpl__ArgumentNullError(const char *funcName, const int line, const char *paramName) {
9118  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter are not allowed to be null", paramName);
9119 }
9120 fpl_internal void fpl__ArgumentZeroError(const char *funcName, const int line, const char *paramName) {
9121  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter must be greater than zero", paramName);
9122 }
9123 fpl_internal void fpl__ArgumentMinError(const char *funcName, const int line, const char *paramName, const size_t value, const size_t minValue) {
9124  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter '%zu' must be greater or equal than '%zu'", paramName, value, minValue);
9125 }
9126 fpl_internal void fpl__ArgumentMaxError(const char *funcName, const int line, const char *paramName, const size_t value, const size_t maxValue) {
9127  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter '%zu' must be less or equal than '%zu'", paramName, value, maxValue);
9128 }
9129 fpl_internal void fpl__ArgumentRangeError(const char *funcName, const int line, const char *paramName, const size_t value, const size_t minValue, const size_t maxValue) {
9130  FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS, "%s parameter '%zu' must be in range of '%zu' to '%zu'", paramName, value, minValue, maxValue);
9131 }
9132 
9133 #define FPL__CheckArgumentInvalid(arg, cond, ret) \
9134  if((cond)) { \
9135  fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9136  return (ret); \
9137  }
9138 
9139 #define FPL__CheckArgumentInvalidNoRet(arg, cond) \
9140  if((cond)) { \
9141  fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9142  return; \
9143  }
9144 #define FPL__CheckArgumentNull(arg, ret) \
9145  if((arg) == fpl_null) { \
9146  fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9147  return (ret); \
9148  }
9149 #define FPL__CheckArgumentNullNoRet(arg) \
9150  if((arg) == fpl_null) { \
9151  fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9152  return; \
9153  }
9154 #define FPL__CheckArgumentZero(arg, ret) \
9155  if((arg) == 0) { \
9156  fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9157  return (ret); \
9158  }
9159 #define FPL__CheckArgumentZeroNoRet(arg) \
9160  if((arg) == 0) { \
9161  fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9162  return; \
9163  }
9164 #define FPL__CheckArgumentMin(arg, minValue, ret) \
9165  if((arg) < (minValue)) { \
9166  fpl__ArgumentMinError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, minValue); \
9167  return (ret); \
9168  }
9169 #define FPL__CheckArgumentMax(arg, maxValue, ret) \
9170  if((arg) > (maxValue)) { \
9171  fpl__ArgumentMaxError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, maxValue); \
9172  return (ret); \
9173  }
9174 #define FPL__CheckPlatform(ret) \
9175  if(fpl__global__AppState == fpl_null) { \
9176  FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
9177  return (ret); \
9178  }
9179 #define FPL__CheckPlatformNoRet() \
9180  if(fpl__global__AppState == fpl_null) { \
9181  FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
9182  return; \
9183  }
9184 
9185 #define FPL__CheckApi(cond, name, ret) \
9186  if(!(cond)) { \
9187  FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
9188  return (ret); \
9189  }
9190 #define FPL__CheckApiNoRet(cond, name) \
9191  if(!(cond)) { \
9192  FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
9193  return; \
9194  }
9195 
9196 #if !defined(FPL_MAX_THREAD_COUNT)
9197  // Maximum number of active threads you can have in your process
9198 # define FPL_MAX_THREAD_COUNT 64
9199 #endif
9200 
9201 #if !defined(FPL_MAX_SIGNAL_COUNT)
9202  // Maximum number of active signals you can wait for
9203 # define FPL_MAX_SIGNAL_COUNT 256
9204 #endif
9205 
9206 typedef struct fpl__ThreadState {
9207  fplThreadHandle mainThread;
9208  fplThreadHandle threads[FPL_MAX_THREAD_COUNT];
9209 } fpl__ThreadState;
9210 
9211 fpl_globalvar fpl__ThreadState fpl__global__ThreadState = fplZeroInit;
9212 
9213 fpl_internal fplThreadHandle *fpl__GetFreeThread() {
9214  fplThreadHandle *result = fpl_null;
9215  for(uint32_t index = 0; index < FPL_MAX_THREAD_COUNT; ++index) {
9216  fplThreadHandle *thread = fpl__global__ThreadState.threads + index;
9217  fplThreadState state = fplGetThreadState(thread);
9218  if(state == fplThreadState_Stopped) {
9219  result = thread;
9220  break;
9221  }
9222  }
9223  return(result);
9224 }
9225 
9226 fpl_internal bool fpl__IsEqualsMemory(const void *a, const void *b, const size_t size) {
9227  const uint8_t *ptrA = (const uint8_t *)a;
9228  const uint8_t *ptrB = (const uint8_t *)b;
9229  size_t s = size;
9230  // @SPEED(final): This may be very slow, so we should use a faster function for comparing memory.
9231  bool result = true;
9232 #if 1
9233  while(s-- > 0) {
9234  if(*ptrA != *ptrB) {
9235  result = false;
9236  break;
9237  }
9238  ptrA++;
9239  ptrB++;
9240  }
9241 #else
9242  result = memcmp(a, b, size) == 0;
9243 #endif
9244  return(result);
9245 }
9246 
9247 fpl_internal bool fpl__IsZeroMemory(const void *memory, const size_t size) {
9248  const uint8_t *ptr = (const uint8_t *)memory;
9249  // @SPEED(final): This may be very slow, so we should use a faster function for comparing memory.
9250  bool result = true;
9251 #if 1
9252  size_t s = size;
9253  while(s-- > 0) {
9254  if(*ptr) {
9255  result = false;
9256  break;
9257  }
9258  ptr++;
9259  }
9260 #else
9261  result = memcmp(a, b, size) == 0;
9262 #endif
9263  return(result);
9264 }
9265 
9266 //
9267 // Common Strings
9268 //
9269 #if !defined(FPL__COMMON_STRINGS_DEFINED)
9270 #define FPL__COMMON_STRINGS_DEFINED
9271 
9272 fpl_common_api bool fplIsStringMatchWildcard(const char *source, const char *wildcard) {
9273  // Supported patterns:
9274  // * = Match zero or more characters
9275  // ? = Match one character
9276  if(source == fpl_null || wildcard == fpl_null) {
9277  return false;
9278  }
9279  const char *s = source;
9280  const char *w = wildcard;
9281  while(*w) {
9282  if(*w == '?') {
9283  if(!*s) {
9284  return false;
9285  }
9286  ++s;
9287  } else if(*w == '*') {
9288  while(*s) {
9289  char nw = w[1];
9290  if(nw != 0) {
9291  if((*s == nw) || (nw == '?') || (nw == '*')) {
9292  break;
9293  }
9294  }
9295  ++s;
9296  }
9297  } else {
9298  if(*s != *w) {
9299  return false;
9300  }
9301  ++s;
9302  }
9303  ++w;
9304  }
9305  return true;
9306 }
9307 
9308 fpl_common_api bool fplIsStringEqualLen(const char *a, const size_t aLen, const char *b, const size_t bLen) {
9309  if((a == fpl_null) || (b == fpl_null)) {
9310  return false;
9311  }
9312  if(aLen != bLen) {
9313  return false;
9314  }
9315  bool result = true;
9316  for(size_t index = 0; index < aLen; ++index) {
9317  char aChar = a[index];
9318  char bChar = b[index];
9319  if(aChar != bChar) {
9320  result = false;
9321  break;
9322  }
9323  }
9324  return(result);
9325 }
9326 
9327 fpl_common_api bool fplIsStringEqual(const char *a, const char *b) {
9328  if((a == fpl_null) || (b == fpl_null)) {
9329  return (a == b);
9330  }
9331  bool result = true;
9332  for(;;) {
9333  const char aChar = *(a++);
9334  const char bChar = *(b++);
9335  if(aChar == 0 || bChar == 0) {
9336  result = (aChar == bChar);
9337  break;
9338  }
9339  if(aChar != bChar) {
9340  result = false;
9341  break;
9342  }
9343  }
9344  return(result);
9345 }
9346 
9347 fpl_common_api char *fplEnforcePathSeparatorLen(char *path, size_t maxPathLen) {
9348  FPL__CheckArgumentNull(path, fpl_null);
9349  FPL__CheckArgumentZero(maxPathLen, fpl_null);
9350  char *end = path;
9351  while(*end) {
9352  end++;
9353  }
9354  size_t len = end - path;
9355  char *result = fpl_null;
9356  if(len > 0) {
9357  if(path[len - 1] != FPL_PATH_SEPARATOR) {
9358  if(len + 1 <= maxPathLen) {
9359  path[len] = FPL_PATH_SEPARATOR;
9360  path[len + 1] = 0;
9361  result = &path[len + 1];
9362  } else {
9363  FPL__ERROR(FPL__MODULE_PATHS, "Cannot append path separator: Max length '%zu' of path '%s' is exceeded", maxPathLen, path);
9364  }
9365  } else {
9366  result = &path[len];
9367  }
9368  }
9369  return(result);
9370 }
9371 
9372 fpl_common_api char *fplEnforcePathSeparator(char *path) {
9373  FPL__CheckArgumentNull(path, fpl_null);
9374  char *end = path;
9375  while(*end) {
9376  end++;
9377  }
9378  size_t len = end - path;
9379  char *result = fpl_null;
9380  if(len > 0) {
9381  if(path[l